[sundials] 42/76: New upstream version 2.5.0
Andreas Tille
tille at debian.org
Sun Feb 5 18:44:54 UTC 2017
This is an automated email from the git hooks/post-receive script.
tille pushed a commit to branch master
in repository sundials.
commit dfe09aadf5f71e9878efde9e167c66e3f3302a44
Author: Andreas Tille <tille at debian.org>
Date: Sun Feb 5 08:48:49 2017 +0100
New upstream version 2.5.0
---
CMakeLists.txt | 713 +
INSTALL_NOTES | 559 +
debian/copyright => LICENSE | 29 +-
Makefile.in | 139 +
README | 57 +
acinclude.m4 | 3213 +++
bin/fortran-update.in | 490 +
bin/makefile-update.in | 32 +
bin/sundials-config.in | 136 +
config.hin | 97 +
config/CheckFortranFunctionExists.cmake | 49 +
config/FindBLAS.cmake | 186 +
config/FindLAPACK.cmake | 96 +
config/FindMPI.cmake | 36 +
config/SundialsFortran.cmake | 176 +
config/SundialsLapack.cmake | 85 +
config/SundialsMPIC.cmake | 181 +
config/SundialsMPIF.cmake | 108 +
config/config.guess | 1471 +
config/config.sub | 1599 ++
config/cust_general.m4 | 94 +
config/install-sh | 251 +
config/ltmain.sh | 6868 +++++
config/mkinstalldirs | 137 +
config/mod_c.m4 | 62 +
config/mod_fortran.m4 | 117 +
config/rminstalldirs | 20 +
configure | 28297 +++++++++++++++++++
configure.ac | 157 +
debian/README.Debian | 23 -
debian/README.source | 9 -
debian/changelog | 301 -
debian/check.sh | 45 -
debian/clean | 3 -
debian/compat | 1 -
debian/control | 193 -
debian/docs | 1 -
debian/libsundials-cvode1.install | 1 -
debian/libsundials-cvode1.symbols | 189 -
debian/libsundials-cvodes2.install | 1 -
debian/libsundials-cvodes2.symbols | 300 -
debian/libsundials-doc.install | 1 -
debian/libsundials-ida2.install | 1 -
debian/libsundials-ida2.symbols | 192 -
debian/libsundials-idas0.install | 1 -
debian/libsundials-idas0.symbols | 302 -
debian/libsundials-kinsol1.install | 1 -
debian/libsundials-kinsol1.symbols | 164 -
debian/libsundials-nvecparallel-dev.install | 6 -
debian/libsundials-nvecparallel0.install | 2 -
debian/libsundials-nvecparallel0.symbols | 55 -
debian/libsundials-nvecserial0.install | 2 -
debian/libsundials-nvecserial0.symbols | 55 -
debian/libsundials-parallel.lintian-overrides | 2 -
debian/libsundials-serial-dev.install | 21 -
debian/libsundials-serial-doc.docs | 11 -
debian/libsundials-serial.lintian-overrides | 2 -
debian/octave-sundials.install | 2 -
debian/orig-tar.exclude | 2 -
debian/orig-tarball.sh | 17 -
debian/patches/bashim.diff | 19 -
debian/patches/cmake.patch | 111 -
debian/patches/fix-format-error.patch | 65 -
debian/patches/link-blas-lapack.patch | 104 -
debian/patches/makefile.patch | 465 -
debian/patches/modern-ltmain.sh.patch | 5878 ----
debian/patches/octave-sundialstb.patch | 193 -
debian/patches/series | 7 -
debian/patches/sh4.patch | 13 -
debian/patches/sundials-config.patch | 34 -
debian/rules | 114 -
debian/source.lintian-overrides | 5 -
debian/source/format | 1 -
debian/sundials-config.1 | 57 -
debian/watch | 4 -
examples/cvode/fcmix_parallel/CMakeLists.txt | 120 +
examples/cvode/fcmix_parallel/Makefile.in | 116 +
examples/cvode/fcmix_parallel/README | 17 +
examples/cvode/fcmix_parallel/fcvDiag_kry_bbd_p.f | 307 +
.../cvode/fcmix_parallel/fcvDiag_kry_bbd_p.out | 76 +
examples/cvode/fcmix_parallel/fcvDiag_kry_p.f | 346 +
examples/cvode/fcmix_parallel/fcvDiag_kry_p.out | 65 +
examples/cvode/fcmix_parallel/fcvDiag_non_p.f | 191 +
examples/cvode/fcmix_parallel/fcvDiag_non_p.out | 31 +
examples/cvode/fcmix_serial/CMakeLists.txt | 130 +
examples/cvode/fcmix_serial/Makefile.in | 137 +
examples/cvode/fcmix_serial/README | 18 +
examples/cvode/fcmix_serial/fcvAdvDiff_bnd.f | 281 +
examples/cvode/fcmix_serial/fcvAdvDiff_bnd.out | 24 +
examples/cvode/fcmix_serial/fcvDiurnal_kry.f | 993 +
examples/cvode/fcmix_serial/fcvDiurnal_kry.out | 63 +
examples/cvode/fcmix_serial/fcvDiurnal_kry_bp.f | 343 +
examples/cvode/fcmix_serial/fcvDiurnal_kry_bp.out | 68 +
examples/cvode/fcmix_serial/fcvRoberts_dns.f | 227 +
examples/cvode/fcmix_serial/fcvRoberts_dns.out | 32 +
examples/cvode/fcmix_serial/fcvRoberts_dnsL.f | 231 +
examples/cvode/fcmix_serial/fcvRoberts_dnsL.out | 32 +
examples/cvode/parallel/CMakeLists.txt | 113 +
examples/cvode/parallel/Makefile.in | 113 +
examples/cvode/parallel/README | 17 +
examples/cvode/parallel/cvAdvDiff_non_p.c | 362 +
examples/cvode/parallel/cvAdvDiff_non_p.out | 21 +
examples/cvode/parallel/cvDiurnal_kry_bbd_p.c | 891 +
examples/cvode/parallel/cvDiurnal_kry_bbd_p.out | 140 +
examples/cvode/parallel/cvDiurnal_kry_p.c | 975 +
examples/cvode/parallel/cvDiurnal_kry_p.out | 63 +
examples/cvode/serial/CMakeLists.txt | 127 +
examples/cvode/serial/Makefile.in | 139 +
examples/cvode/serial/README | 25 +
examples/cvode/serial/cvAdvDiff_bnd.c | 426 +
examples/cvode/serial/cvAdvDiff_bnd.out | 22 +
examples/cvode/serial/cvAdvDiff_bndL.c | 421 +
examples/cvode/serial/cvAdvDiff_bndL.out | 22 +
examples/cvode/serial/cvDirectDemo_ls.c | 789 +
examples/cvode/serial/cvDirectDemo_ls.out | 502 +
examples/cvode/serial/cvDiurnal_kry.c | 801 +
examples/cvode/serial/cvDiurnal_kry.out | 63 +
examples/cvode/serial/cvDiurnal_kry_bp.c | 530 +
examples/cvode/serial/cvDiurnal_kry_bp.out | 138 +
examples/cvode/serial/cvKrylovDemo_ls.c | 736 +
examples/cvode/serial/cvKrylovDemo_ls.out | 202 +
examples/cvode/serial/cvKrylovDemo_prec.c | 1142 +
examples/cvode/serial/cvKrylovDemo_prec.out | 645 +
examples/cvode/serial/cvRoberts_dns.c | 360 +
examples/cvode/serial/cvRoberts_dns.out | 24 +
examples/cvode/serial/cvRoberts_dnsL.c | 363 +
examples/cvode/serial/cvRoberts_dnsL.out | 24 +
examples/cvode/serial/cvRoberts_dns_uw.c | 377 +
examples/cvode/serial/cvRoberts_dns_uw.out | 24 +
examples/cvodes/parallel/CMakeLists.txt | 118 +
examples/cvodes/parallel/Makefile.in | 116 +
examples/cvodes/parallel/README | 34 +
examples/cvodes/parallel/cvsAdvDiff_ASAp_non_p.c | 696 +
examples/cvodes/parallel/cvsAdvDiff_ASAp_non_p.out | 27 +
examples/cvodes/parallel/cvsAdvDiff_FSA_non_p.c | 612 +
examples/cvodes/parallel/cvsAdvDiff_FSA_non_p.out | 71 +
examples/cvodes/parallel/cvsAdvDiff_non_p.c | 362 +
examples/cvodes/parallel/cvsAdvDiff_non_p.out | 21 +
.../cvodes/parallel/cvsAtmDisp_ASAi_kry_bbd_p.c | 1196 +
.../cvodes/parallel/cvsAtmDisp_ASAi_kry_bbd_p.out | 37 +
examples/cvodes/parallel/cvsDiurnal_FSA_kry_p.c | 1286 +
examples/cvodes/parallel/cvsDiurnal_FSA_kry_p.out | 139 +
examples/cvodes/parallel/cvsDiurnal_kry_bbd_p.c | 891 +
examples/cvodes/parallel/cvsDiurnal_kry_bbd_p.out | 140 +
examples/cvodes/parallel/cvsDiurnal_kry_p.c | 975 +
examples/cvodes/parallel/cvsDiurnal_kry_p.out | 63 +
examples/cvodes/serial/CMakeLists.txt | 139 +
examples/cvodes/serial/Makefile.in | 146 +
examples/cvodes/serial/README | 44 +
examples/cvodes/serial/cvsAdvDiff_ASAi_bnd.c | 559 +
examples/cvodes/serial/cvsAdvDiff_ASAi_bnd.out | 18 +
examples/cvodes/serial/cvsAdvDiff_FSA_non.c | 523 +
examples/cvodes/serial/cvsAdvDiff_FSA_non.out | 69 +
examples/cvodes/serial/cvsAdvDiff_bnd.c | 424 +
examples/cvodes/serial/cvsAdvDiff_bnd.out | 22 +
examples/cvodes/serial/cvsAdvDiff_bndL.c | 421 +
examples/cvodes/serial/cvsAdvDiff_bndL.out | 22 +
examples/cvodes/serial/cvsDirectDemo_ls.c | 789 +
examples/cvodes/serial/cvsDirectDemo_ls.out | 502 +
examples/cvodes/serial/cvsDiurnal_FSA_kry.c | 928 +
examples/cvodes/serial/cvsDiurnal_FSA_kry.out | 142 +
examples/cvodes/serial/cvsDiurnal_kry.c | 801 +
examples/cvodes/serial/cvsDiurnal_kry.out | 63 +
examples/cvodes/serial/cvsDiurnal_kry_bp.c | 530 +
examples/cvodes/serial/cvsDiurnal_kry_bp.out | 138 +
examples/cvodes/serial/cvsFoodWeb_ASAi_kry.c | 1363 +
examples/cvodes/serial/cvsFoodWeb_ASAi_kry.out | 51 +
examples/cvodes/serial/cvsFoodWeb_ASAp_kry.c | 1359 +
examples/cvodes/serial/cvsFoodWeb_ASAp_kry.out | 51 +
examples/cvodes/serial/cvsHessian_ASA_FSA.c | 779 +
examples/cvodes/serial/cvsHessian_ASA_FSA.out | 100 +
examples/cvodes/serial/cvsKrylovDemo_ls.c | 736 +
examples/cvodes/serial/cvsKrylovDemo_ls.out | 202 +
examples/cvodes/serial/cvsKrylovDemo_prec.c | 1141 +
examples/cvodes/serial/cvsKrylovDemo_prec.out | 645 +
examples/cvodes/serial/cvsRoberts_ASAi_dns.c | 655 +
examples/cvodes/serial/cvsRoberts_ASAi_dns.out | 39 +
examples/cvodes/serial/cvsRoberts_FSA_dns.c | 626 +
examples/cvodes/serial/cvsRoberts_FSA_dns.out | 93 +
examples/cvodes/serial/cvsRoberts_dns.c | 359 +
examples/cvodes/serial/cvsRoberts_dns.out | 24 +
examples/cvodes/serial/cvsRoberts_dnsL.c | 363 +
examples/cvodes/serial/cvsRoberts_dnsL.out | 24 +
examples/cvodes/serial/cvsRoberts_dns_uw.c | 377 +
examples/cvodes/serial/cvsRoberts_dns_uw.out | 24 +
examples/ida/fcmix_parallel/CMakeLists.txt | 118 +
examples/ida/fcmix_parallel/Makefile.in | 114 +
examples/ida/fcmix_parallel/README | 15 +
examples/ida/fcmix_parallel/fidaHeat2D_kry_bbd_p.f | 830 +
.../ida/fcmix_parallel/fidaHeat2D_kry_bbd_p.out | 65 +
examples/ida/fcmix_serial/CMakeLists.txt | 127 +
examples/ida/fcmix_serial/Makefile.in | 134 +
examples/ida/fcmix_serial/README | 14 +
examples/ida/fcmix_serial/fidaRoberts_dns.f | 264 +
examples/ida/fcmix_serial/fidaRoberts_dns.out | 34 +
examples/ida/parallel/CMakeLists.txt | 114 +
examples/ida/parallel/Makefile.in | 113 +
examples/ida/parallel/README | 18 +
examples/ida/parallel/idaFoodWeb_kry_bbd_p.c | 1091 +
examples/ida/parallel/idaFoodWeb_kry_bbd_p.out | 58 +
examples/ida/parallel/idaFoodWeb_kry_p.c | 1231 +
examples/ida/parallel/idaFoodWeb_kry_p.out | 50 +
examples/ida/parallel/idaHeat2D_kry_bbd_p.c | 840 +
examples/ida/parallel/idaHeat2D_kry_bbd_p.out | 58 +
examples/ida/parallel/idaHeat2D_kry_p.c | 892 +
examples/ida/parallel/idaHeat2D_kry_p.out | 32 +
examples/ida/serial/CMakeLists.txt | 125 +
examples/ida/serial/Makefile.in | 134 +
examples/ida/serial/README | 19 +
examples/ida/serial/idaFoodWeb_bnd.c | 674 +
examples/ida/serial/idaFoodWeb_bnd.out | 42 +
examples/ida/serial/idaHeat2D_bnd.c | 407 +
examples/ida/serial/idaHeat2D_bnd.out | 30 +
examples/ida/serial/idaHeat2D_kry.c | 550 +
examples/ida/serial/idaHeat2D_kry.out | 55 +
examples/ida/serial/idaKrylovDemo_ls.c | 582 +
examples/ida/serial/idaKrylovDemo_ls.out | 102 +
examples/ida/serial/idaRoberts_dns.c | 404 +
examples/ida/serial/idaRoberts_dns.out | 38 +
examples/ida/serial/idaSlCrank_dns.c | 349 +
examples/ida/serial/idaSlCrank_dns.out | 57 +
examples/idas/parallel/CMakeLists.txt | 118 +
examples/idas/parallel/Makefile.in | 117 +
examples/idas/parallel/README | 22 +
examples/idas/parallel/idasBruss_ASAp_kry_bbd_p.c | 1484 +
.../idas/parallel/idasBruss_ASAp_kry_bbd_p.out | 50 +
examples/idas/parallel/idasBruss_FSA_kry_bbd_p.c | 1169 +
examples/idas/parallel/idasBruss_FSA_kry_bbd_p.out | 60 +
examples/idas/parallel/idasBruss_kry_bbd_p.c | 1081 +
examples/idas/parallel/idasBruss_kry_bbd_p.out | 51 +
examples/idas/parallel/idasFoodWeb_kry_bbd_p.c | 1090 +
examples/idas/parallel/idasFoodWeb_kry_bbd_p.out | 51 +
examples/idas/parallel/idasFoodWeb_kry_p.c | 1231 +
examples/idas/parallel/idasFoodWeb_kry_p.out | 49 +
examples/idas/parallel/idasHeat2D_FSA_kry_bbd_p.c | 969 +
.../idas/parallel/idasHeat2D_FSA_kry_bbd_p.out | 57 +
examples/idas/parallel/idasHeat2D_kry_bbd_p.c | 840 +
examples/idas/parallel/idasHeat2D_kry_bbd_p.out | 58 +
examples/idas/parallel/idasHeat2D_kry_p.c | 892 +
examples/idas/parallel/idasHeat2D_kry_p.out | 32 +
examples/idas/serial/CMakeLists.txt | 131 +
examples/idas/serial/Makefile.in | 142 +
examples/idas/serial/README | 26 +
examples/idas/serial/idasAkzoNob_ASAi_dns.c | 441 +
examples/idas/serial/idasAkzoNob_ASAi_dns.out | 19 +
examples/idas/serial/idasAkzoNob_dns.c | 371 +
examples/idas/serial/idasAkzoNob_dns.out | 48 +
examples/idas/serial/idasFoodWeb_bnd.c | 674 +
examples/idas/serial/idasFoodWeb_bnd.out | 42 +
examples/idas/serial/idasHeat2D_bnd.c | 407 +
examples/idas/serial/idasHeat2D_bnd.out | 30 +
examples/idas/serial/idasHeat2D_kry.c | 550 +
examples/idas/serial/idasHeat2D_kry.out | 55 +
examples/idas/serial/idasHessian_ASA_FSA.c | 734 +
examples/idas/serial/idasHessian_ASA_FSA.out | 42 +
examples/idas/serial/idasKrylovDemo_ls.c | 581 +
examples/idas/serial/idasKrylovDemo_ls.out | 102 +
examples/idas/serial/idasRoberts_ASAi_dns.c | 757 +
examples/idas/serial/idasRoberts_ASAi_dns.out | 37 +
examples/idas/serial/idasRoberts_FSA_dns.c | 788 +
examples/idas/serial/idasRoberts_FSA_dns.out | 115 +
examples/idas/serial/idasRoberts_dns.c | 402 +
examples/idas/serial/idasRoberts_dns.out | 38 +
examples/idas/serial/idasSlCrank_FSA_dns.c | 550 +
examples/idas/serial/idasSlCrank_FSA_dns.out | 37 +
examples/idas/serial/idasSlCrank_dns.c | 433 +
examples/idas/serial/idasSlCrank_dns.out | 46 +
examples/kinsol/fcmix_parallel/CMakeLists.txt | 119 +
examples/kinsol/fcmix_parallel/Makefile.in | 114 +
examples/kinsol/fcmix_parallel/README | 15 +
examples/kinsol/fcmix_parallel/fkinDiagon_kry_p.f | 246 +
.../kinsol/fcmix_parallel/fkinDiagon_kry_p.out | 24 +
examples/kinsol/fcmix_serial/CMakeLists.txt | 128 +
examples/kinsol/fcmix_serial/Makefile.in | 134 +
examples/kinsol/fcmix_serial/README | 14 +
examples/kinsol/fcmix_serial/fkinDiagon_kry.f | 197 +
examples/kinsol/fcmix_serial/fkinDiagon_kry.out | 53 +
examples/kinsol/parallel/CMakeLists.txt | 112 +
examples/kinsol/parallel/Makefile.in | 111 +
examples/kinsol/parallel/README | 16 +
examples/kinsol/parallel/kinFoodWeb_kry_bbd_p.c | 1009 +
examples/kinsol/parallel/kinFoodWeb_kry_bbd_p.out | 33 +
examples/kinsol/parallel/kinFoodWeb_kry_p.c | 1112 +
examples/kinsol/parallel/kinFoodWeb_kry_p.out | 31 +
examples/kinsol/serial/CMakeLists.txt | 125 +
examples/kinsol/serial/Makefile.in | 133 +
examples/kinsol/serial/README | 18 +
examples/kinsol/serial/kinFerTron_dns.c | 494 +
examples/kinsol/serial/kinFerTron_dns.out | 71 +
examples/kinsol/serial/kinFoodWeb_kry.c | 789 +
examples/kinsol/serial/kinFoodWeb_kry.out | 29 +
examples/kinsol/serial/kinKrylovDemo_ls.c | 879 +
examples/kinsol/serial/kinKrylovDemo_ls.out | 102 +
examples/kinsol/serial/kinLaplace_bnd.c | 394 +
examples/kinsol/serial/kinLaplace_bnd.out | 32 +
examples/kinsol/serial/kinRoboKin_dns.c | 437 +
examples/kinsol/serial/kinRoboKin_dns.out | 32 +
examples/templates/cmakelists_parallel_C_ex.in | 83 +
examples/templates/cmakelists_parallel_F77_ex.in | 85 +
examples/templates/cmakelists_serial_C_ex.in | 80 +
examples/templates/cmakelists_serial_F77_ex.in | 82 +
examples/templates/makefile_parallel_C_ex.in | 78 +
examples/templates/makefile_parallel_F77_ex.in | 77 +
examples/templates/makefile_serial_C_ex.in | 73 +
examples/templates/makefile_serial_F77_ex.in | 71 +
include/cvode/cvode.h | 790 +
include/cvode/cvode_band.h | 61 +
include/cvode/cvode_bandpre.h | 141 +
include/cvode/cvode_bbdpre.h | 268 +
include/cvode/cvode_dense.h | 54 +
include/cvode/cvode_diag.h | 106 +
include/cvode/cvode_direct.h | 285 +
include/cvode/cvode_lapack.h | 86 +
include/cvode/cvode_spbcgs.h | 67 +
include/cvode/cvode_spgmr.h | 69 +
include/cvode/cvode_spils.h | 365 +
include/cvode/cvode_sptfqmr.h | 67 +
include/cvodes/cvodes.h | 1968 ++
include/cvodes/cvodes_band.h | 72 +
include/cvodes/cvodes_bandpre.h | 179 +
include/cvodes/cvodes_bbdpre.h | 331 +
include/cvodes/cvodes_dense.h | 64 +
include/cvodes/cvodes_diag.h | 140 +
include/cvodes/cvodes_direct.h | 365 +
include/cvodes/cvodes_lapack.h | 103 +
include/cvodes/cvodes_spbcgs.h | 87 +
include/cvodes/cvodes_spgmr.h | 88 +
include/cvodes/cvodes_spils.h | 450 +
include/cvodes/cvodes_sptfqmr.h | 88 +
include/ida/ida.h | 938 +
include/ida/ida_band.h | 59 +
include/ida/ida_bbdpre.h | 275 +
include/ida/ida_dense.h | 58 +
include/ida/ida_direct.h | 300 +
include/ida/ida_lapack.h | 80 +
include/ida/ida_spbcgs.h | 59 +
include/ida/ida_spgmr.h | 60 +
include/ida/ida_spils.h | 321 +
include/ida/ida_sptfqmr.h | 59 +
include/idas/idas.h | 2099 ++
include/idas/idas_band.h | 80 +
include/idas/idas_bbdpre.h | 327 +
include/idas/idas_dense.h | 69 +
include/idas/idas_direct.h | 374 +
include/idas/idas_lapack.h | 103 +
include/idas/idas_spbcgs.h | 79 +
include/idas/idas_spgmr.h | 80 +
include/idas/idas_spils.h | 413 +
include/idas/idas_sptfqmr.h | 78 +
include/kinsol/kinsol.h | 765 +
include/kinsol/kinsol_band.h | 57 +
include/kinsol/kinsol_bbdpre.h | 233 +
include/kinsol/kinsol_dense.h | 54 +
include/kinsol/kinsol_direct.h | 262 +
include/kinsol/kinsol_lapack.h | 84 +
include/kinsol/kinsol_spbcgs.h | 89 +
include/kinsol/kinsol_spgmr.h | 86 +
include/kinsol/kinsol_spils.h | 319 +
include/kinsol/kinsol_sptfqmr.h | 90 +
include/nvector/nvector_parallel.h | 314 +
include/nvector/nvector_serial.h | 265 +
include/sundials/sundials_band.h | 154 +
include/sundials/sundials_config.in | 76 +
include/sundials/sundials_dense.h | 187 +
include/sundials/sundials_direct.h | 336 +
include/sundials/sundials_fnvector.h | 41 +
include/sundials/sundials_iterative.h | 242 +
include/sundials/sundials_lapack.h | 126 +
include/sundials/sundials_math.h | 139 +
include/sundials/sundials_nvector.h | 373 +
include/sundials/sundials_spbcgs.h | 199 +
include/sundials/sundials_spgmr.h | 296 +
include/sundials/sundials_sptfqmr.h | 254 +
include/sundials/sundials_types.h | 122 +
src/cvode/CMakeLists.txt | 128 +
debian/copyright => src/cvode/LICENSE | 24 +-
src/cvode/Makefile.in | 175 +
src/cvode/README | 462 +
src/cvode/cvode.c | 4191 +++
src/cvode/cvode_band.c | 361 +
src/cvode/cvode_bandpre.c | 478 +
src/cvode/cvode_bandpre_impl.h | 76 +
src/cvode/cvode_bbdpre.c | 550 +
src/cvode/cvode_bbdpre_impl.h | 82 +
src/cvode/cvode_dense.c | 341 +
src/cvode/cvode_diag.c | 437 +
src/cvode/cvode_diag_impl.h | 66 +
src/cvode/cvode_direct.c | 463 +
src/cvode/cvode_direct_impl.h | 111 +
src/cvode/cvode_impl.h | 515 +
src/cvode/cvode_io.c | 1129 +
src/cvode/cvode_lapack.c | 653 +
src/cvode/cvode_spbcgs.c | 459 +
src/cvode/cvode_spgmr.c | 463 +
src/cvode/cvode_spils.c | 697 +
src/cvode/cvode_spils_impl.h | 142 +
src/cvode/cvode_sptfqmr.c | 459 +
src/cvode/fcmix/CMakeLists.txt | 45 +
src/cvode/fcmix/Makefile.in | 125 +
src/cvode/fcmix/fcvband.c | 97 +
src/cvode/fcmix/fcvbbd.c | 141 +
src/cvode/fcmix/fcvbbd.h | 331 +
src/cvode/fcmix/fcvbp.c | 54 +
src/cvode/fcmix/fcvbp.h | 256 +
src/cvode/fcmix/fcvdense.c | 93 +
src/cvode/fcmix/fcvewt.c | 74 +
src/cvode/fcmix/fcvjtimes.c | 95 +
src/cvode/fcmix/fcvlapack.c | 52 +
src/cvode/fcmix/fcvlapband.c | 106 +
src/cvode/fcmix/fcvlapdense.c | 95 +
src/cvode/fcmix/fcvode.c | 603 +
src/cvode/fcmix/fcvode.h | 758 +
src/cvode/fcmix/fcvpreco.c | 136 +
src/cvode/fcmix/fcvroot.c | 86 +
src/cvode/fcmix/fcvroot.h | 140 +
src/cvodes/CMakeLists.txt | 131 +
debian/copyright => src/cvodes/LICENSE | 18 +-
src/cvodes/Makefile.in | 180 +
src/cvodes/README | 468 +
src/cvodes/cvodea.c | 2980 ++
src/cvodes/cvodea_io.c | 716 +
src/cvodes/cvodes.c | 9011 ++++++
src/cvodes/cvodes_band.c | 461 +
src/cvodes/cvodes_bandpre.c | 545 +
src/cvodes/cvodes_bandpre_impl.h | 77 +
src/cvodes/cvodes_bbdpre.c | 785 +
src/cvodes/cvodes_bbdpre_impl.h | 102 +
src/cvodes/cvodes_dense.c | 440 +
src/cvodes/cvodes_diag.c | 508 +
src/cvodes/cvodes_diag_impl.h | 67 +
src/cvodes/cvodes_direct.c | 711 +
src/cvodes/cvodes_direct_impl.h | 154 +
src/cvodes/cvodes_impl.h | 1088 +
src/cvodes/cvodes_io.c | 1877 ++
src/cvodes/cvodes_lapack.c | 828 +
src/cvodes/cvodes_spbcgs.c | 573 +
src/cvodes/cvodes_spgmr.c | 579 +
src/cvodes/cvodes_spils.c | 1183 +
src/cvodes/cvodes_spils_impl.h | 183 +
src/cvodes/cvodes_sptfqmr.c | 570 +
src/ida/CMakeLists.txt | 125 +
debian/copyright => src/ida/LICENSE | 24 +-
src/ida/Makefile.in | 169 +
src/ida/README | 395 +
src/ida/fcmix/CMakeLists.txt | 43 +
src/ida/fcmix/Makefile.in | 123 +
src/ida/fcmix/fida.c | 752 +
src/ida/fcmix/fida.h | 727 +
src/ida/fcmix/fidaband.c | 117 +
src/ida/fcmix/fidabbd.c | 150 +
src/ida/fcmix/fidabbd.h | 338 +
src/ida/fcmix/fidadense.c | 115 +
src/ida/fcmix/fidaewt.c | 87 +
src/ida/fcmix/fidajtimes.c | 116 +
src/ida/fcmix/fidalapack.c | 53 +
src/ida/fcmix/fidalapband.c | 112 +
src/ida/fcmix/fidalapdense.c | 111 +
src/ida/fcmix/fidapreco.c | 159 +
src/ida/fcmix/fidaroot.c | 88 +
src/ida/fcmix/fidaroot.h | 142 +
src/ida/ida.c | 3433 +++
src/ida/ida_band.c | 319 +
src/ida/ida_bbdpre.c | 584 +
src/ida/ida_bbdpre_impl.h | 88 +
src/ida/ida_dense.c | 300 +
src/ida/ida_direct.c | 544 +
src/ida/ida_direct_impl.h | 102 +
src/ida/ida_ic.c | 728 +
src/ida/ida_impl.h | 485 +
src/ida/ida_io.c | 1152 +
src/ida/ida_lapack.c | 558 +
src/ida/ida_spbcgs.c | 477 +
src/ida/ida_spgmr.c | 476 +
src/ida/ida_spils.c | 637 +
src/ida/ida_spils_impl.h | 188 +
src/ida/ida_sptfqmr.c | 477 +
src/idas/CMakeLists.txt | 127 +
debian/copyright => src/idas/LICENSE | 24 +-
src/idas/Makefile.in | 173 +
src/idas/README | 112 +
src/idas/idaa.c | 3315 +++
src/idas/idaa_io.c | 727 +
src/idas/idas.c | 7231 +++++
src/idas/idas_band.c | 424 +
src/idas/idas_bbdpre.c | 828 +
src/idas/idas_bbdpre_impl.h | 110 +
src/idas/idas_dense.c | 404 +
src/idas/idas_direct.c | 799 +
src/idas/idas_direct_impl.h | 139 +
src/idas/idas_ic.c | 1350 +
src/idas/idas_impl.h | 1055 +
src/idas/idas_io.c | 1895 ++
src/idas/idas_lapack.c | 562 +
src/idas/idas_spbcgs.c | 590 +
src/idas/idas_spgmr.c | 582 +
src/idas/idas_spils.c | 1129 +
src/idas/idas_spils_impl.h | 224 +
src/idas/idas_sptfqmr.c | 583 +
src/kinsol/CMakeLists.txt | 124 +
debian/copyright => src/kinsol/LICENSE | 24 +-
src/kinsol/Makefile.in | 167 +
src/kinsol/README | 397 +
src/kinsol/fcmix/CMakeLists.txt | 42 +
src/kinsol/fcmix/Makefile.in | 119 +
src/kinsol/fcmix/fkinband.c | 111 +
src/kinsol/fcmix/fkinbbd.c | 138 +
src/kinsol/fcmix/fkinbbd.h | 303 +
src/kinsol/fcmix/fkindense.c | 100 +
src/kinsol/fcmix/fkinjtimes.c | 82 +
src/kinsol/fcmix/fkinlapack.c | 42 +
src/kinsol/fcmix/fkinlapband.c | 112 +
src/kinsol/fcmix/fkinlapdense.c | 100 +
src/kinsol/fcmix/fkinpreco.c | 134 +
src/kinsol/fcmix/fkinsol.c | 395 +
src/kinsol/fcmix/fkinsol.h | 586 +
src/kinsol/kinsol.c | 1936 ++
src/kinsol/kinsol_band.c | 346 +
src/kinsol/kinsol_bbdpre.c | 538 +
src/kinsol/kinsol_bbdpre_impl.h | 89 +
src/kinsol/kinsol_dense.c | 329 +
src/kinsol/kinsol_direct.c | 491 +
src/kinsol/kinsol_direct_impl.h | 98 +
src/kinsol/kinsol_impl.h | 459 +
src/kinsol/kinsol_io.c | 1000 +
src/kinsol/kinsol_lapack.c | 611 +
src/kinsol/kinsol_spbcgs.c | 426 +
src/kinsol/kinsol_spgmr.c | 427 +
src/kinsol/kinsol_spils.c | 623 +
src/kinsol/kinsol_spils_impl.h | 180 +
src/kinsol/kinsol_sptfqmr.c | 428 +
src/nvec_par/CMakeLists.txt | 89 +
src/nvec_par/Makefile.in | 128 +
src/nvec_par/README | 143 +
src/nvec_par/fnvector_parallel.c | 182 +
src/nvec_par/fnvector_parallel.h | 92 +
src/nvec_par/nvector_parallel.c | 1152 +
src/nvec_ser/CMakeLists.txt | 82 +
src/nvec_ser/Makefile.in | 125 +
src/nvec_ser/README | 139 +
src/nvec_ser/fnvector_serial.c | 147 +
src/nvec_ser/fnvector_serial.h | 88 +
src/nvec_ser/nvector_serial.c | 1034 +
src/sundials/CMakeLists.txt | 45 +
src/sundials/Makefile.in | 137 +
src/sundials/README | 215 +
src/sundials/sundials_band.c | 235 +
src/sundials/sundials_dense.c | 373 +
src/sundials/sundials_direct.c | 355 +
src/sundials/sundials_iterative.c | 288 +
src/sundials/sundials_math.c | 94 +
src/sundials/sundials_nvector.c | 233 +
src/sundials/sundials_spbcgs.c | 379 +
src/sundials/sundials_spgmr.c | 458 +
src/sundials/sundials_sptfqmr.c | 516 +
sundialsTB/Contents.m | 6 +
debian/copyright => sundialsTB/LICENSE | 27 +-
sundialsTB/README | 219 +
sundialsTB/cvodes/CVode.m | 55 +
sundialsTB/cvodes/CVodeAdjInit.m | 23 +
sundialsTB/cvodes/CVodeAdjReInit.m | 13 +
sundialsTB/cvodes/CVodeB.m | 49 +
sundialsTB/cvodes/CVodeFree.m | 11 +
sundialsTB/cvodes/CVodeGet.m | 36 +
sundialsTB/cvodes/CVodeGetStats.m | 86 +
sundialsTB/cvodes/CVodeGetStatsB.m | 76 +
sundialsTB/cvodes/CVodeInit.m | 42 +
sundialsTB/cvodes/CVodeInitB.m | 37 +
sundialsTB/cvodes/CVodeMonitor.m | 796 +
sundialsTB/cvodes/CVodeMonitorB.m | 697 +
sundialsTB/cvodes/CVodeMonitorB_octave.m | 545 +
sundialsTB/cvodes/CVodeMonitor_octave.m | 637 +
sundialsTB/cvodes/CVodeQuadInit.m | 28 +
sundialsTB/cvodes/CVodeQuadInitB.m | 32 +
sundialsTB/cvodes/CVodeQuadReInit.m | 28 +
sundialsTB/cvodes/CVodeQuadReInitB.m | 30 +
sundialsTB/cvodes/CVodeQuadSetOptions.m | 64 +
sundialsTB/cvodes/CVodeReInit.m | 32 +
sundialsTB/cvodes/CVodeReInitB.m | 36 +
sundialsTB/cvodes/CVodeSensInit.m | 33 +
sundialsTB/cvodes/CVodeSensReInit.m | 32 +
sundialsTB/cvodes/CVodeSensSetOptions.m | 112 +
sundialsTB/cvodes/CVodeSensToggleOff.m | 16 +
sundialsTB/cvodes/CVodeSet.m | 52 +
sundialsTB/cvodes/CVodeSetB.m | 48 +
sundialsTB/cvodes/CVodeSetOptions.m | 300 +
sundialsTB/cvodes/Contents.m | 115 +
sundialsTB/cvodes/cvm/Contents.m | 3 +
sundialsTB/cvodes/cvm/cvm_bjac.m | 12 +
sundialsTB/cvodes/cvm/cvm_bjacB.m | 12 +
sundialsTB/cvodes/cvm/cvm_djac.m | 13 +
sundialsTB/cvodes/cvm/cvm_djacB.m | 12 +
sundialsTB/cvodes/cvm/cvm_gcom.m | 12 +
sundialsTB/cvodes/cvm/cvm_gcomB.m | 12 +
sundialsTB/cvodes/cvm/cvm_gloc.m | 12 +
sundialsTB/cvodes/cvm/cvm_glocB.m | 12 +
sundialsTB/cvodes/cvm/cvm_jtv.m | 12 +
sundialsTB/cvodes/cvm/cvm_jtvB.m | 12 +
sundialsTB/cvodes/cvm/cvm_monitor.m | 17 +
sundialsTB/cvodes/cvm/cvm_monitorB.m | 15 +
sundialsTB/cvodes/cvm/cvm_options.m | 66 +
sundialsTB/cvodes/cvm/cvm_pset.m | 12 +
sundialsTB/cvodes/cvm/cvm_psetB.m | 12 +
sundialsTB/cvodes/cvm/cvm_psol.m | 12 +
sundialsTB/cvodes/cvm/cvm_psolB.m | 12 +
sundialsTB/cvodes/cvm/cvm_rhs.m | 13 +
sundialsTB/cvodes/cvm/cvm_rhsB.m | 48 +
sundialsTB/cvodes/cvm/cvm_rhsQ.m | 13 +
sundialsTB/cvodes/cvm/cvm_rhsQB.m | 49 +
sundialsTB/cvodes/cvm/cvm_rhsS.m | 17 +
sundialsTB/cvodes/cvm/cvm_root.m | 13 +
sundialsTB/cvodes/cvm/src/cvm.c | 3662 +++
sundialsTB/cvodes/cvm/src/cvm.h | 281 +
sundialsTB/cvodes/cvm/src/cvmOpts.c | 850 +
sundialsTB/cvodes/cvm/src/cvmWrap.c | 1225 +
.../cvodes/examples_par/mcvsAdvDiff_FSA_non_p.m | 206 +
.../cvodes/examples_par/mcvsAtmDisp_kry_bbd_p.m | 521 +
sundialsTB/cvodes/examples_par/mcvsDecoupl_non_p.m | 91 +
sundialsTB/cvodes/examples_ser/mcvsAdvDiff_bnd.m | 243 +
sundialsTB/cvodes/examples_ser/mcvsDiscRHS_dns.m | 150 +
sundialsTB/cvodes/examples_ser/mcvsDiscSOL_dns.m | 77 +
sundialsTB/cvodes/examples_ser/mcvsDiurnal_kry.m | 388 +
.../cvodes/examples_ser/mcvsHessian_FSA_ASA.m | 349 +
sundialsTB/cvodes/examples_ser/mcvsOzone_FSA_dns.m | 143 +
sundialsTB/cvodes/examples_ser/mcvsPleiades_non.m | 149 +
.../cvodes/examples_ser/mcvsPollut_FSA_dns.m | 417 +
.../cvodes/examples_ser/mcvsRoberts_ASAi_dns.m | 286 +
.../cvodes/examples_ser/mcvsRoberts_FSA_dns.m | 197 +
sundialsTB/cvodes/examples_ser/mcvsRoberts_dns.m | 132 +
sundialsTB/cvodes/examples_ser/mcvsVanDPol_dns.m | 64 +
sundialsTB/cvodes/function_types/CVBandJacFn.m | 31 +
sundialsTB/cvodes/function_types/CVBandJacFnB.m | 27 +
sundialsTB/cvodes/function_types/CVDenseJacFn.m | 27 +
sundialsTB/cvodes/function_types/CVDenseJacFnB.m | 24 +
sundialsTB/cvodes/function_types/CVGcommFn.m | 34 +
sundialsTB/cvodes/function_types/CVGcommFnB.m | 28 +
sundialsTB/cvodes/function_types/CVGlocalFn.m | 28 +
sundialsTB/cvodes/function_types/CVGlocalFnB.m | 22 +
sundialsTB/cvodes/function_types/CVJacTimesVecFn.m | 28 +
.../cvodes/function_types/CVJacTimesVecFnB.m | 23 +
sundialsTB/cvodes/function_types/CVMonitorFn.m | 37 +
sundialsTB/cvodes/function_types/CVMonitorFnB.m | 37 +
sundialsTB/cvodes/function_types/CVPrecSetupFn.m | 68 +
sundialsTB/cvodes/function_types/CVPrecSetupFnB.m | 53 +
sundialsTB/cvodes/function_types/CVPrecSolveFn.m | 35 +
sundialsTB/cvodes/function_types/CVPrecSolveFnB.m | 25 +
sundialsTB/cvodes/function_types/CVQuadRhsFn.m | 24 +
sundialsTB/cvodes/function_types/CVQuadRhsFnB.m | 20 +
sundialsTB/cvodes/function_types/CVRhsFn.m | 24 +
sundialsTB/cvodes/function_types/CVRhsFnB.m | 20 +
sundialsTB/cvodes/function_types/CVRootFn.m | 26 +
sundialsTB/cvodes/function_types/CVSensRhsFn.m | 26 +
sundialsTB/idas/Contents.m | 113 +
sundialsTB/idas/IDAAdjInit.m | 23 +
sundialsTB/idas/IDAAdjReInit.m | 13 +
sundialsTB/idas/IDACalcIC.m | 73 +
sundialsTB/idas/IDACalcICB.m | 23 +
sundialsTB/idas/IDAFree.m | 11 +
sundialsTB/idas/IDAGet.m | 36 +
sundialsTB/idas/IDAGetStats.m | 80 +
sundialsTB/idas/IDAGetStatsB.m | 66 +
sundialsTB/idas/IDAInit.m | 31 +
sundialsTB/idas/IDAInitB.m | 37 +
sundialsTB/idas/IDAMonitor.m | 796 +
sundialsTB/idas/IDAMonitorB.m | 697 +
sundialsTB/idas/IDAMonitorB_octave.m | 545 +
sundialsTB/idas/IDAMonitor_octave.m | 637 +
sundialsTB/idas/IDAQuadInit.m | 28 +
sundialsTB/idas/IDAQuadInitB.m | 32 +
sundialsTB/idas/IDAQuadReInit.m | 28 +
sundialsTB/idas/IDAQuadReInitB.m | 30 +
sundialsTB/idas/IDAQuadSetOptions.m | 63 +
sundialsTB/idas/IDAReInit.m | 33 +
sundialsTB/idas/IDAReInitB.m | 37 +
sundialsTB/idas/IDASensInit.m | 32 +
sundialsTB/idas/IDASensReInit.m | 32 +
sundialsTB/idas/IDASensSetOptions.m | 112 +
sundialsTB/idas/IDASensToggleOff.m | 16 +
sundialsTB/idas/IDASet.m | 52 +
sundialsTB/idas/IDASetB.m | 48 +
sundialsTB/idas/IDASetOptions.m | 263 +
sundialsTB/idas/IDASolve.m | 56 +
sundialsTB/idas/IDASolveB.m | 50 +
sundialsTB/idas/examples_ser/midasBruss_ASA_dns.m | 446 +
sundialsTB/idas/examples_ser/midasBruss_dns.m | 301 +
sundialsTB/idas/examples_ser/midasHeat2D_bnd.m | 175 +
sundialsTB/idas/examples_ser/midasPendI1_dns.m | 183 +
sundialsTB/idas/examples_ser/midasPendI2_dns.m | 158 +
sundialsTB/idas/examples_ser/midasReInit_dns.m | 108 +
.../idas/examples_ser/midasRoberts_ASAi_dns.m | 209 +
sundialsTB/idas/examples_ser/midasRoberts_dns.m | 120 +
.../idas/examples_ser/midasSlCrank_FSA_dns.m | 238 +
sundialsTB/idas/examples_ser/midasSlCrank_dns.m | 481 +
sundialsTB/idas/function_types/IDABandJacFn.m | 32 +
sundialsTB/idas/function_types/IDABandJacFnB.m | 27 +
sundialsTB/idas/function_types/IDADenseJacFn.m | 29 +
sundialsTB/idas/function_types/IDADenseJacFnB.m | 24 +
sundialsTB/idas/function_types/IDAGcommFn.m | 34 +
sundialsTB/idas/function_types/IDAGcommFnB.m | 28 +
sundialsTB/idas/function_types/IDAGlocalFn.m | 29 +
sundialsTB/idas/function_types/IDAGlocalFnB.m | 23 +
sundialsTB/idas/function_types/IDAJacTimesVecFn.m | 28 +
sundialsTB/idas/function_types/IDAJacTimesVecFnB.m | 23 +
sundialsTB/idas/function_types/IDAMonitorFn.m | 67 +
sundialsTB/idas/function_types/IDAMonitorFnB.m | 37 +
sundialsTB/idas/function_types/IDAPrecSetupFn.m | 53 +
sundialsTB/idas/function_types/IDAPrecSetupFnB.m | 18 +
sundialsTB/idas/function_types/IDAPrecSolveFn.m | 33 +
sundialsTB/idas/function_types/IDAPrecSolveFnB.m | 23 +
sundialsTB/idas/function_types/IDAQuadRhsFn.m | 24 +
sundialsTB/idas/function_types/IDAQuadRhsFnB.m | 20 +
sundialsTB/idas/function_types/IDAResFn.m | 23 +
sundialsTB/idas/function_types/IDAResFnB.m | 19 +
sundialsTB/idas/function_types/IDARootFn.m | 26 +
sundialsTB/idas/function_types/IDASensResFn.m | 26 +
sundialsTB/idas/idm/Contents.m | 3 +
sundialsTB/idas/idm/idm_bjac.m | 13 +
sundialsTB/idas/idm/idm_bjacB.m | 13 +
sundialsTB/idas/idm/idm_djac.m | 13 +
sundialsTB/idas/idm/idm_djacB.m | 12 +
sundialsTB/idas/idm/idm_gcom.m | 12 +
sundialsTB/idas/idm/idm_gcomB.m | 12 +
sundialsTB/idas/idm/idm_gloc.m | 13 +
sundialsTB/idas/idm/idm_glocB.m | 13 +
sundialsTB/idas/idm/idm_jtv.m | 12 +
sundialsTB/idas/idm/idm_jtvB.m | 12 +
sundialsTB/idas/idm/idm_monitor.m | 16 +
sundialsTB/idas/idm/idm_monitorB.m | 15 +
sundialsTB/idas/idm/idm_options.m | 66 +
sundialsTB/idas/idm/idm_pset.m | 12 +
sundialsTB/idas/idm/idm_psetB.m | 13 +
sundialsTB/idas/idm/idm_psol.m | 13 +
sundialsTB/idas/idm/idm_psolB.m | 13 +
sundialsTB/idas/idm/idm_res.m | 12 +
sundialsTB/idas/idm/idm_resB.m | 54 +
sundialsTB/idas/idm/idm_resS.m | 18 +
sundialsTB/idas/idm/idm_rhsQ.m | 12 +
sundialsTB/idas/idm/idm_rhsQB.m | 55 +
sundialsTB/idas/idm/idm_root.m | 13 +
sundialsTB/idas/idm/src/idm.c | 3513 +++
sundialsTB/idas/idm/src/idm.h | 319 +
sundialsTB/idas/idm/src/idmOpts.c | 875 +
sundialsTB/idas/idm/src/idmWrap.c | 1378 +
sundialsTB/install_STB.m | 1025 +
sundialsTB/kinsol/Contents.m | 28 +
sundialsTB/kinsol/KINFree.m | 11 +
sundialsTB/kinsol/KINGetStats.m | 44 +
sundialsTB/kinsol/KINInit.m | 29 +
sundialsTB/kinsol/KINSetOptions.m | 336 +
sundialsTB/kinsol/KINSol.m | 47 +
sundialsTB/kinsol/examples_par/mkinDiagon_kry_p.m | 128 +
sundialsTB/kinsol/examples_ser/mkinDiagon_kry.m | 104 +
sundialsTB/kinsol/examples_ser/mkinFerTron_dns.m | 182 +
sundialsTB/kinsol/examples_ser/mkinRoboKin_dns.m | 248 +
sundialsTB/kinsol/examples_ser/mkinTest_dns.m | 59 +
sundialsTB/kinsol/function_types/KINBandJacFn.m | 27 +
sundialsTB/kinsol/function_types/KINDenseJacFn.m | 27 +
sundialsTB/kinsol/function_types/KINGcommFn.m | 33 +
sundialsTB/kinsol/function_types/KINGlocalFn.m | 28 +
.../kinsol/function_types/KINJacTimesVecFn.m | 29 +
sundialsTB/kinsol/function_types/KINPrecSetupFn.m | 48 +
sundialsTB/kinsol/function_types/KINPrecSolveFn.m | 35 +
sundialsTB/kinsol/function_types/KINSysFn.m | 25 +
sundialsTB/kinsol/kim/Contents.m | 3 +
sundialsTB/kinsol/kim/kim_bjac.m | 12 +
sundialsTB/kinsol/kim/kim_djac.m | 12 +
sundialsTB/kinsol/kim/kim_gcom.m | 13 +
sundialsTB/kinsol/kim/kim_gloc.m | 12 +
sundialsTB/kinsol/kim/kim_info.m | 81 +
sundialsTB/kinsol/kim/kim_jtv.m | 12 +
sundialsTB/kinsol/kim/kim_pset.m | 12 +
sundialsTB/kinsol/kim/kim_psol.m | 11 +
sundialsTB/kinsol/kim/kim_sys.m | 13 +
sundialsTB/kinsol/kim/src/kim.c | 811 +
sundialsTB/kinsol/kim/src/kim.h | 166 +
sundialsTB/kinsol/kim/src/kimOpts.c | 431 +
sundialsTB/kinsol/kim/src/kimWrap.c | 388 +
sundialsTB/nvector/Contents.m | 17 +
sundialsTB/nvector/N_VDotProd.m | 26 +
sundialsTB/nvector/N_VL1Norm.m | 25 +
sundialsTB/nvector/N_VMax.m | 25 +
sundialsTB/nvector/N_VMaxNorm.m | 25 +
sundialsTB/nvector/N_VMin.m | 24 +
sundialsTB/nvector/N_VWL2Norm.m | 29 +
sundialsTB/nvector/N_VWrmsNorm.m | 34 +
sundialsTB/nvector/src/nvm.h | 43 +
sundialsTB/nvector/src/nvm_ops.c | 43 +
sundialsTB/nvector/src/nvm_parallel.c | 79 +
sundialsTB/nvector/src/nvm_serial.c | 29 +
sundialsTB/putils/Contents.m | 9 +
sundialsTB/putils/mpirun.m | 67 +
sundialsTB/putils/mpiruns.m | 50 +
sundialsTB/putils/mpistart.m | 324 +
sundialsTB/startup_STB.in | 65 +
793 files changed, 262098 insertions(+), 9100 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000..a0491b5
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,713 @@
+# ---------------------------------------------------------------
+# $Revision: 1.10 $
+# $Date: 2010/12/15 22:28:16 $
+# ---------------------------------------------------------------
+# Programmer: Radu Serban @ LLNL
+# ---------------------------------------------------------------
+# Copyright (c) 2007, The Regents of the University of California.
+# Produced at the Lawrence Livermore National Laboratory.
+# All rights reserved.
+# For details, see the LICENSE file.
+# ---------------------------------------------------------------
+# Top level CMakeLists.txt for SUNDIALS (for cmake build system)
+
+
+# -------------------------------------------------------------
+# Initial commands
+# -------------------------------------------------------------
+
+# Require a fairly recent cmake version
+
+CMAKE_MINIMUM_REQUIRED(VERSION 2.2)
+
+# Project SUNDIALS (initially only C supported)
+
+PROJECT(sundials C)
+
+# Set some variables with info on the SUNDIALS project
+
+SET(PACKAGE_BUGREPORT "radu at llnl.gov")
+SET(PACKAGE_NAME "SUNDIALS")
+SET(PACKAGE_STRING "SUNDIALS 2.4.0")
+SET(PACKAGE_TARNAME "sundials")
+SET(PACKAGE_VERSION "2.4.0")
+
+# 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
+
+MARK_AS_ADVANCED(EXECUTABLE_OUTPUT_PATH LIBRARY_OUTPUT_PATH)
+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)
+
+# Specify the VERSION and SOVERSION for shared libraries
+
+SET(cvodelib_VERSION "1.0.0")
+SET(cvodelib_SOVERSION "1")
+
+SET(cvodeslib_VERSION "2.0.0")
+SET(cvodeslib_SOVERSION "2")
+
+SET(idalib_VERSION "2.0.0")
+SET(idalib_SOVERSION "2")
+
+SET(idaslib_VERSION "0.0.0")
+SET(idaslib_SOVERSION "0")
+
+SET(kinsollib_VERSION "1.0.0")
+SET(kinsollib_SOVERSION "1")
+
+SET(cpodeslib_VERSION "0.0.0")
+SET(cpodeslib_SOVERSION "0")
+
+SET(nveclib_VERSION "0.0.2")
+SET(nveclib_SOVERSION "0")
+
+# Specify the location of additional CMAKE modules
+
+SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/config)
+
+# -------------------------------------------------------------
+# MACRO definitions
+# -------------------------------------------------------------
+
+# 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)
+
+# -------------------------------------------------------------
+# 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/cvode")
+ OPTION(BUILD_CVODE "Build the CVODE library" ON)
+ELSE(IS_DIRECTORY "${sundials_SOURCE_DIR}/src/cvode")
+ SET(BUILD_CVODE OFF)
+ENDIF(IS_DIRECTORY "${sundials_SOURCE_DIR}/src/cvode")
+
+IF(IS_DIRECTORY "${sundials_SOURCE_DIR}/src/cvodes")
+ OPTION(BUILD_CVODES "Build the CVODES library" ON)
+ELSE(IS_DIRECTORY "${sundials_SOURCE_DIR}/src/cvodes")
+ SET(BUILD_CVODES OFF)
+ENDIF(IS_DIRECTORY "${sundials_SOURCE_DIR}/src/cvodes")
+
+IF(IS_DIRECTORY "${sundials_SOURCE_DIR}/src/ida")
+ OPTION(BUILD_IDA "Build the IDA library" ON)
+ELSE(IS_DIRECTORY "${sundials_SOURCE_DIR}/src/ida")
+ SET(BUILD_IDA OFF)
+ENDIF(IS_DIRECTORY "${sundials_SOURCE_DIR}/src/ida")
+
+IF(IS_DIRECTORY "${sundials_SOURCE_DIR}/src/idas")
+ OPTION(BUILD_IDAS "Build the IDAS library" ON)
+ELSE(IS_DIRECTORY "${sundials_SOURCE_DIR}/src/idas")
+ SET(BUILD_IDAS OFF)
+ENDIF(IS_DIRECTORY "${sundials_SOURCE_DIR}/src/idas")
+
+IF(IS_DIRECTORY "${sundials_SOURCE_DIR}/src/kinsol")
+ OPTION(BUILD_KINSOL "Build the KINSOL library" ON)
+ELSE(IS_DIRECTORY "${sundials_SOURCE_DIR}/src/kinsol")
+ SET(BUILD_KINSOL OFF)
+ENDIF(IS_DIRECTORY "${sundials_SOURCE_DIR}/src/kinsol")
+
+IF(IS_DIRECTORY "${sundials_SOURCE_DIR}/src/cpodes")
+ OPTION(BUILD_CPODES "Build the CPODES library" ON)
+ELSE(IS_DIRECTORY "${sundials_SOURCE_DIR}/src/cpodes")
+ SET(BUILD_CPODES OFF)
+ENDIF(IS_DIRECTORY "${sundials_SOURCE_DIR}/src/cpodes")
+
+# -------------------------------------------------------------
+# Other configuration options
+# -------------------------------------------------------------
+
+# Option that allows users to build static and/or shared libraries
+# ----------------------------------------------------------------
+
+OPTION(BUILD_STATIC_LIBS "Build static libraries" ON)
+OPTION(BUILD_SHARED_LIBS "Build shared libraries" OFF)
+
+# Prepare substitution variable SUNDIALS_EXPORT for sundials_config.h
+# When building shared SUNDIALS libraries under Windows, use
+# #define SUNDIALS_EXPORT __declspec(dllexport)
+# When linking to shared SUNDIALS libraries under Windows, use
+# #define SUNDIALS_EXPORT __declspec(dllimport)
+# In all other cases (other platforms or static libraries
+# under Windows), the SUNDIALS_EXPORT macro is empty
+
+IF(BUILD_SHARED_LIBS AND WIN32)
+ SET(SUNDIALS_EXPORT
+ "#ifdef BUILD_SUNDIALS_LIBRARY
+#define SUNDIALS_EXPORT __declspec(dllexport)
+#else
+#define SUNDIALS_EXPORT __declspec(dllimport)
+#endif")
+ELSE(BUILD_SHARED_LIBS AND WIN32)
+ SET(SUNDIALS_EXPORT "#define SUNDIALS_EXPORT")
+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)
+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
+ SET(EXTRA_LINK_LIBS -lm)
+ # prepare substitution variable GENERIC_MATH_LIB for sundials_config.h
+ SET(GENERIC_MATH_LIB "#define SUNDIALS_USE_GENERIC_MATH")
+ ENDIF(USE_GENERIC_MATH)
+ENDIF(UNIX)
+
+# -------------------------------------------------------------
+# Enable Fortran support?
+# -------------------------------------------------------------
+
+# FCMIX support is an option only if at least one solver that
+# provides such an interface is built.
+
+IF(BUILD_CVODE OR BUILD_IDA OR BUILD_KINSOL)
+ SHOW_VARIABLE(FCMIX_ENABLE BOOL "Enable Fortran-C support" OFF)
+ELSE(BUILD_CVODE OR BUILD_IDA OR BUILD_KINSOL)
+ HIDE_VARIABLE(FCMIX_ENABLE)
+ENDIF(BUILD_CVODE OR BUILD_IDA OR BUILD_KINSOL)
+
+# -------------------------------------------------------------
+# Enable BLAS/LAPACK 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)
+
+# -------------------------------------------------------------
+# 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_MPIF77)
+ENDIF(NOT MPI_ENABLE)
+
+# -------------------------------------------------------------
+# Enable examples?
+# -------------------------------------------------------------
+
+OPTION(EXAMPLES_ENABLE "Build the SUNDIALS examples" OFF)
+
+IF(EXAMPLES_ENABLE)
+
+ # If examples are enabled, set different options
+
+ # The examples will be linked with the library corresponding to the build type.
+ # Whenever building shared libraries, use them to link the examples.
+ IF(BUILD_SHARED_LIBS)
+ SET(LINK_LIBRARY_TYPE "shared")
+ ELSE(BUILD_SHARED_LIBS)
+ SET(LINK_LIBRARY_TYPE "static")
+ ENDIF(BUILD_SHARED_LIBS)
+
+ # Check if example files are to be exported
+ SHOW_VARIABLE(EXAMPLES_INSTALL BOOL "Install example files" ON)
+
+ # If examples are to be exported, check where we should install them.
+ IF(EXAMPLES_INSTALL)
+
+ SHOW_VARIABLE(EXAMPLES_INSTALL_PATH STRING
+ "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")
+ SET(EXAMPLES_INSTALL_PATH "${CMAKE_INSTALL_PREFIX}/examples" CACHE STRING
+ "Output directory for installing example files" FORCE)
+ ENDIF(NOT EXAMPLES_INSTALL_PATH)
+
+ ELSE(EXAMPLES_INSTALL)
+
+ HIDE_VARIABLE(EXAMPLES_INSTALL_PATH)
+
+ ENDIF(EXAMPLES_INSTALL)
+
+ELSE(EXAMPLES_ENABLE)
+
+ # If examples are disabled, hide all options related to
+ # building and installing the SUNDIALS examples
+
+ HIDE_VARIABLE(EXAMPLES_INSTALL)
+ HIDE_VARIABLE(EXAMPLES_INSTALL_PATH)
+
+ENDIF(EXAMPLES_ENABLE)
+
+# -------------------------------------------------------------
+# Add any other necessary compiler flags & definitions
+# -------------------------------------------------------------
+
+# Under Windows, add compiler directive to inhibit warnings
+# about use of unsecure functions
+
+IF(WIN32)
+ ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS)
+ENDIF(WIN32)
+
+# -------------------------------------------------------------
+# A Fortran compiler is needed if:
+# (a) FCMIX is enabled
+# (b) LAPACK is enabled (for the name-mangling scheme)
+# -------------------------------------------------------------
+
+IF(FCMIX_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)
+
+# -------------------------------------------------------------
+# Check if we need an alternate way of specifying the Fortran
+# name-mangling scheme if we were unable to infer it using a
+# compiler.
+# Ask the user to specify the case and number of appended underscores
+# 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)
+ # 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
+ "number of underscores appended to Fortran function names"
+ "one")
+ # Based on the given case and number of underscores,
+ # set the C preprocessor macro definition
+ IF(${SUNDIALS_F77_FUNC_CASE} MATCHES "lower")
+ IF(${SUNDIALS_F77_FUNC_UNDERSCORES} MATCHES "none")
+ SET(CMAKE_Fortran_SCHEME_NO_UNDERSCORES "mysub")
+ ENDIF(${SUNDIALS_F77_FUNC_UNDERSCORES} MATCHES "none")
+ IF(${SUNDIALS_F77_FUNC_UNDERSCORES} MATCHES "one")
+ SET(CMAKE_Fortran_SCHEME_NO_UNDERSCORES "mysub_")
+ ENDIF(${SUNDIALS_F77_FUNC_UNDERSCORES} MATCHES "one")
+ IF(${SUNDIALS_F77_FUNC_UNDERSCORES} MATCHES "two")
+ SET(CMAKE_Fortran_SCHEME_NO_UNDERSCORES "mysub__")
+ ENDIF(${SUNDIALS_F77_FUNC_UNDERSCORES} MATCHES "two")
+ ELSE(${SUNDIALS_F77_FUNC_CASE} MATCHES "lower")
+ IF(${SUNDIALS_F77_FUNC_UNDERSCORES} MATCHES "none")
+ SET(CMAKE_Fortran_SCHEME_NO_UNDERSCORES "MYSUB")
+ ENDIF(${SUNDIALS_F77_FUNC_UNDERSCORES} MATCHES "none")
+ IF(${SUNDIALS_F77_FUNC_UNDERSCORES} MATCHES "one")
+ SET(CMAKE_Fortran_SCHEME_NO_UNDERSCORES "MYSUB_")
+ ENDIF(${SUNDIALS_F77_FUNC_UNDERSCORES} MATCHES "one")
+ IF(${SUNDIALS_F77_FUNC_UNDERSCORES} MATCHES "two")
+ SET(CMAKE_Fortran_SCHEME_NO_UNDERSCORES "MYSUB__")
+ ENDIF(${SUNDIALS_F77_FUNC_UNDERSCORES} MATCHES "two")
+ ENDIF(${SUNDIALS_F77_FUNC_CASE} MATCHES "lower")
+ # Since the SUNDIALS codes never use symbol names containing
+ # underscores, set a default scheme (probably wrong) for symbols
+ # with underscores.
+ SET(CMAKE_Fortran_SCHEME_WITH_UNDERSCORES "my_sub_")
+ # We now "have" a scheme.
+ SET(F77SCHEME_FOUND TRUE)
+ENDIF(LAPACK_ENABLE AND NOT F77SCHEME_FOUND)
+
+# -------------------------------------------------------------
+# If we have a name-mangling scheme (either automatically
+# inferred or provided by the user), set the SUNDIALS
+# compiler preprocessor macro definitions.
+# -------------------------------------------------------------
+
+SET(F77_MANGLE_MACRO1 "")
+SET(F77_MANGLE_MACRO2 "")
+
+IF(F77SCHEME_FOUND)
+ # Symbols WITHOUT underscores
+ 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")
+ 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_")
+ 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__")
+ 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")
+ 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_")
+ 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
+ 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")
+ 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_")
+ 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__")
+ 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")
+ 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_")
+ 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__")
+ENDIF(F77SCHEME_FOUND)
+
+# -------------------------------------------------------------
+# 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.
+
+# Macro to be inserted in sundials_config.h
+SET(BLAS_LAPACK_MACRO "#define SUNDIALS_BLAS_LAPACK 0")
+
+IF(LAPACK_ENABLE)
+
+ INCLUDE(SundialsLapack)
+
+ IF(LAPACK_FOUND)
+ SET(BLAS_LAPACK_MACRO "#define SUNDIALS_BLAS_LAPACK 1")
+ ELSE(LAPACK_FOUND)
+ SHOW_VARIABLE(LAPACK_LIBRARIES STRING "Lapack libraries" "${LAPACK_LIBRARIES}")
+ SHOW_VARIABLE(LAPACK_LINKER_FLAGS STRING "Lapack required linker flags" "${LAPACK_LINKER_FLAGS}")
+ ENDIF(LAPACK_FOUND)
+
+ IF(LAPACK_LIBRARIES AND NOT LAPACK_FOUND)
+ PRINT_WARNING("LAPACK not functional"
+ "Blas/Lapack support will not be provided")
+ ENDIF(LAPACK_LIBRARIES AND NOT LAPACK_FOUND)
+
+ELSE(LAPACK_ENABLE)
+
+ HIDE_VARIABLE(LAPACK_LIBRARIES)
+ HIDE_VARIABLE(LAPACK_LINKER_FLAGS)
+
+ENDIF(LAPACK_ENABLE)
+
+# -------------------------------------------------------------
+# Decide how to compile MPI codes.
+# -------------------------------------------------------------
+
+IF(MPI_ENABLE)
+ 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)
+ENDIF(MPI_ENABLE)
+
+# -------------------------------------------------------------
+# 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.
+CONFIGURE_FILE(
+ ${PROJECT_SOURCE_DIR}/include/sundials/sundials_config.in
+ ${PROJECT_BINARY_DIR}/include/sundials/sundials_config.h
+ )
+
+# Add the include directory in the source tree and the one in
+# the binary tree (for the header file sundials_config.h)
+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)
+IF(MPIC_FOUND)
+ ADD_SUBDIRECTORY(src/nvec_par)
+ENDIF(MPIC_FOUND)
+
+# CVODE library
+
+IF(BUILD_CVODE)
+ ADD_SUBDIRECTORY(src/cvode)
+ IF(FCMIX_ENABLE AND F77_FOUND)
+ ADD_SUBDIRECTORY(src/cvode/fcmix)
+ ENDIF(FCMIX_ENABLE AND F77_FOUND)
+ENDIF(BUILD_CVODE)
+
+# CVODES library
+
+IF(BUILD_CVODES)
+ ADD_SUBDIRECTORY(src/cvodes)
+ENDIF(BUILD_CVODES)
+
+# IDA library
+
+IF(BUILD_IDA)
+ ADD_SUBDIRECTORY(src/ida)
+ IF(FCMIX_ENABLE AND F77_FOUND)
+ ADD_SUBDIRECTORY(src/ida/fcmix)
+ ENDIF(FCMIX_ENABLE AND F77_FOUND)
+ENDIF(BUILD_IDA)
+
+# IDAS library
+
+IF(BUILD_IDAS)
+ ADD_SUBDIRECTORY(src/idas)
+ENDIF(BUILD_IDAS)
+
+# KINSOL library
+
+IF(BUILD_KINSOL)
+ ADD_SUBDIRECTORY(src/kinsol)
+ IF(FCMIX_ENABLE AND F77_FOUND)
+ ADD_SUBDIRECTORY(src/kinsol/fcmix)
+ ENDIF(FCMIX_ENABLE AND F77_FOUND)
+ENDIF(BUILD_KINSOL)
+
+# CPODES library
+
+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
+# variables needed in generating them from templates.
+
+IF(EXAMPLES_ENABLE)
+
+ 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(CFLAGS "${CMAKE_C_FLAGS_RELEASE}")
+ SET(LDFLAGS "${CMAKE_EXE_LINKER_FLAGS_RELEASE}")
+ LIST2STRING(EXTRA_LINK_LIBS LIBS)
+ IF(F77_FOUND)
+ SET(F77 "${CMAKE_Fortran_COMPILER}")
+ SET(F77_LNKR "${CMAKE_Fortran_COMPILER}")
+ SET(FFLAGS "${CMAKE_Fortran_FLAGS_RELEASE}")
+ SET(F77_LDFLAGS "${CMAKE_Fortran_FLAGS_RELEASE}")
+ LIST2STRING(EXTRA_LINK_LIBS F77_LIBS)
+ ENDIF(F77_FOUND)
+ IF(LAPACK_FOUND)
+ LIST2STRING(LAPACK_LIBRARIES BLAS_LAPACK_LIBS)
+ SET(BLAS_LAPACK_LIBS "${LAPACK_LINKER_FLAGS} ${BLAS_LAPACK_LIBS}")
+ ENDIF(LAPACK_FOUND)
+ IF(MPIC_FOUND)
+ IF(MPI_MPICC)
+ SET(MPICC "${MPI_MPICC}")
+ SET(MPI_INC_DIR ".")
+ SET(MPI_LIB_DIR ".")
+ SET(MPI_LIBS "")
+ SET(MPI_FLAGS "")
+ ELSE(MPI_MPICC)
+ SET(MPICC "${CMAKE_C_COMPILER}")
+ SET(MPI_INC_DIR "${MPI_INCLUDE_PATH}")
+ SET(MPI_LIB_DIR ".")
+ LIST2STRING(MPI_LIBRARIES MPI_LIBS)
+ ENDIF(MPI_MPICC)
+ ENDIF(MPIC_FOUND)
+ IF(MPIF_FOUND)
+ IF(MPI_MPIF77)
+ SET(MPIF77 "${MPI_MPIF77}")
+ SET(MPIF77_LNKR "${MPI_MPIF77}")
+ ELSE(MPI_MPIF77)
+ SET(MPIF77 "${CMAKE_Fortran_COMPILER}")
+ SET(MPIF77_LNKR "${CMAKE_Fortran_COMPILER}")
+ SET(MPI_INC_DIR "${MPI_INCLUDE_PATH}")
+ SET(MPI_LIB_DIR ".")
+ LIST2STRING(MPI_LIBRARIES MPI_LIBS)
+ ENDIF(MPI_MPIF77)
+ ENDIF(MPIF_FOUND)
+ ENDIF(EXAMPLES_INSTALL)
+
+ 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)
+ ENDIF(BUILD_CVODE)
+
+ IF(BUILD_CVODES)
+ ADD_SUBDIRECTORY(examples/cvodes/serial)
+ IF(MPIC_FOUND)
+ ADD_SUBDIRECTORY(examples/cvodes/parallel)
+ ENDIF(MPIC_FOUND)
+ ENDIF(BUILD_CVODES)
+
+ IF(BUILD_IDA)
+ ADD_SUBDIRECTORY(examples/ida/serial)
+ IF(FCMIX_ENABLE AND F77_FOUND)
+ ADD_SUBDIRECTORY(examples/ida/fcmix_serial)
+ ENDIF(FCMIX_ENABLE AND F77_FOUND)
+ IF(MPIC_FOUND)
+ ADD_SUBDIRECTORY(examples/ida/parallel)
+ ENDIF(MPIC_FOUND)
+ IF(MPIF_FOUND)
+ ADD_SUBDIRECTORY(examples/ida/fcmix_parallel)
+ ENDIF(MPIF_FOUND)
+ ENDIF(BUILD_IDA)
+
+ IF(BUILD_IDAS)
+ ADD_SUBDIRECTORY(examples/idas/serial)
+ IF(MPIC_FOUND)
+ ADD_SUBDIRECTORY(examples/idas/parallel)
+ ENDIF(MPIC_FOUND)
+ ENDIF(BUILD_IDAS)
+
+ IF(BUILD_KINSOL)
+ ADD_SUBDIRECTORY(examples/kinsol/serial)
+ 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)
+ ENDIF(BUILD_KINSOL)
+
+ IF(BUILD_CPODES)
+ ADD_SUBDIRECTORY(examples/cpodes/serial)
+ IF(MPIC_FOUND)
+ ADD_SUBDIRECTORY(examples/cpodes/parallel)
+ ENDIF(MPIC_FOUND)
+ ENDIF(BUILD_CPODES)
+
+ENDIF(EXAMPLES_ENABLE)
+
+#----------------------------------
+# Install configuration header file
+#----------------------------------
+
+# install configured header file
+INSTALL(
+ FILES ${PROJECT_BINARY_DIR}/include/sundials/sundials_config.h
+ DESTINATION include/sundials
+ )
+
diff --git a/INSTALL_NOTES b/INSTALL_NOTES
new file mode 100644
index 0000000..3d9870a
--- /dev/null
+++ b/INSTALL_NOTES
@@ -0,0 +1,559 @@
+ SUNDIALS Installation Instructions
+ Release 2.7.0, March 2011
+
+
+These are generic installation instructions. For complete installation instructions,
+consult the user guide for any of the SUNDIALS solvers.
+
+Contents:
+
+[A] Preliminaries
+ A.1. Libraries and exported headers
+[B] autotools-based installation
+ B.1. Basic Installation
+ B.2. Installation names
+ B.3. Compilers and Options
+ B.3.1. General options
+ B.3.2. Options for Fortran support
+ B.3.3. Options for Blas/Lapack support
+ B.3.4. Options for MPI support
+ B.3.5. Options for library support
+ B.3.6. Environment variables
+ B.4. Configuration examples
+[C] CMake-based installation
+ C.1. Prerequisites
+ C.2. Configuration and build
+
+================
+A. Preliminaries
+================
+
+The SUNDIALS suite (or an individual solver) is distributed as a compressed archive
+(.tar.gz). The name of the distribution archive is of the form 'solver'-x.y.z.tar.gz,
+where 'solver' is one of: 'sundials', 'cvode', 'cvodes', 'ida', 'idas', or 'kinsol',
+and x.y.z represents the version number (of the SUNDIALS suite or of the individual
+solver).
+
+To begin the installation, first uncompress and expand the sources, by issuing
+
+ % tar xzf solver-x.y.z.tar.gz
+
+This will extract source files under a directory 'solver'-x.y.z.
+
+In the remainder of this chapter, we make the following distinctions:
+
+'srcdir'
+
+ is the directory 'solver'-x.y.z created above; i.e., the
+ directory containing the SUNDIALS sources.
+
+'builddir'
+
+ is the directory under which SUNDIALS is built; i.e., the directory from within
+ which the configure or ccmake command is issued.
+
+ NOTE: When using the autoconf configure script, this directory can be the same
+ as 'srcdir'. However, when using ccmake, insource builds are prohibited.
+
+'instdir'
+
+ is the directory under which the SUNDIALS exported header files and libraries will
+ be installed. Typically, header files are exported under a directory 'instdir'/include
+ while libraries are installed under 'instdir'/lib, with 'instdir' specified with the
+ --prefix flag to configure. See below for more details on the installation directories,
+ including the special cases of the SUNDIALS examples.
+
+ NOTE: The installation directory 'instdir' should NOT be the same as the source
+ directory 'srcdir'.
+
+
+SUNDIALS provides two build alternatives:
+1) autotools-based build system. This options, suitable for *nix systems
+ (Linux, Unix, Mac OS X, cygwin, mingw, etc.) is based on running a 'configure'
+ shell script which generates all required makefiles.
+2) CMake-based build system. This option is available on a variety of platforms
+ (*nix, Windows, Mac OS, etc) but relies on additional software (freely
+ available CMake).
+
+
+-----------------------------------
+A.1. Libraries and exported headers
+-----------------------------------
+
+By default, 'make install' will install the SUNDIALS libraries under 'libdir' and the public
+header files under 'includedir'. The default values for these directories are 'instdir'/lib
+and 'instdir'/include, respectively, but can be changed at the configuration stage.
+
+The SUNDIALS libraries and header files are summarized below (names are relative to 'libdir'
+for libraries and to 'includedir' for header files)
+
+SHARED module
+ header files: sundials/sundials_types.h sundials/sundials_math.h
+ sundials/sundials_config.h sundias/sundials_nvector.h
+ sundials/sundials_smalldense.h sundials/sundials_dense.h
+ sundials/sundials_iterative.h sundials/sundials_band.h
+ sundials/sundials_spbcgs.h sundials/sundials_sptfqmr.h
+ sundials/sundials_spgmr.h sundials/sundials_lapack.h
+ sundials/sundials_fnvector.h
+
+
+NVECTOR_SERIAL module
+ libraries: libsundials_nvecserial.{a,so} libsundials_fnvecserial.a
+ header files: nvector/nvector_serial.h
+
+
+NVECTOR_PARALLEL module
+ libraries: libsundials_nvecparallel.{a,so} libsundials_fnvecparallel.a
+ header files: nvector/nvector_parallel.h
+
+
+CVODE module
+ libraries: libsundials_cvode.{a,so} libsundials_fcvode.a
+ header files: cvode/cvode.h cvode/cvode_direct.h
+ cvode/cvode_dense.h cvode/cvode_band.h
+ cvode/cvode_diag.h cvode/cvode_spils.h
+ cvode/cvode_bandpre.h cvode/cvode_bbdpre.h
+ cvode/cvode_spgmr.h cvode/cvode_spbcgs.h
+ cvode/cvode_sptfqmr.h cvode/cvode_impl.h
+ cvode/cvode_lapack.h
+
+
+CVODES module
+ library: libsundials_cvodes.{a,so}
+ header files: cvodes/cvodes.h cvodes/cvodes_direct.h
+ cvodes/cvodes_dense.h cvodes/cvodes_band.h
+ cvodes/cvodes_diag.h cvodes/cvodes_spils.h
+ cvodes/cvodes_bandpre.h cvodes/cvodes_bbdpre.h
+ cvodes/cvodes_spgmr.h cvodes/cvodes_spbcgs.h
+ cvodes/cvodes_sptfqmr.h cvodes/cvodes_impl.h
+ cvodes/cvodes_lapack.h
+
+
+IDA module
+ library: libsundials_ida.{a,so}
+ header files: ida/ida.h ida/ida_direct.h
+ ida/ida_dense.h ida/ida_band.h
+ ida/ida_spils.h ida/ida_spgmr.h
+ ida/ida_spbcgs.h ida/ida_sptfqmr.h
+ ida/ida_bbdpre.h ida/ida_impl.h
+ ida/dia_lapack.h
+
+
+IDAS module
+ library: libsundials_idas.{a,so}
+ header files: idas/idas.h idas/idas_direct.h
+ idas/idas_dense.h idas/idas_band.h
+ idas/idas_spils.h idas/idas_spgmr.h
+ idas/idas_spbcgs.h idas/idas_sptfqmr.h
+ idas/idas_bbdpre.h idas/idas_impl.h
+ idas/dia_lapack.h
+
+
+KINSOL module
+ libraries: libsundials_kinsol.{a,so} libsundials_fkinsol.a
+ header files: kinsol/kinsol.h
+ kinsol/kinsol_dense.h kinsol/kinsol_band.h
+ kinsol/kinsol_spils.h kinsol/kinsol_spgmr.h
+ kinsol/kinsol_spbcgs.h kinsol/kinsol_sptfqmr.h
+ kinsol/kinsol_bbdpre.h kinsol/kinsol_impl.h
+
+
+
+===============================
+B. autotools-based installation
+===============================
+
+-----------------------
+B.1. Basic Installation
+-----------------------
+
+The installation procedure outlined below will work on commodity Linux/Unix
+systems without modification. However, users are still encouraged to carefully read
+the entire chapter before attempting to install the SUNDIALS suite, in case
+non-default choices are desired for compilers, compilation options, or the like.
+Instead of reading the option list below, the user may invoke the configuration
+script with the help flag to view a complete listing of available options, which
+may be done by issuing
+
+ % ./configure --help
+
+from within the 'srcdir' directory created above.
+
+
+The installation steps for SUNDIALS can be as simple as
+
+ % tar xzf solver-x.y.z.tar.gz
+ % cd solver-x.y.z
+ % ./configure
+ % make
+ % make install
+
+in which case the SUNDIALS header files and libraries are installed under /usr/local/include
+and /usr/local/lib, respectively. Note that, by default, the example programs are not built
+and installed.
+
+If disk space is a priority, then to delete all temporary files created by building SUNDIALS, issue
+
+ % make clean
+
+To prepare the SUNDIALS distribution for a new install (using, for example, different options and/or
+installation destinations), issue
+
+ % make distclean
+
+
+-----------------------
+B.2. Installation names
+-----------------------
+
+By default, 'make install' will install the SUNDIALS libraries under 'libdir' and the public
+header files under 'includedir'. The default values for these directories are 'instdir'/lib
+and 'instdir'/include, respectively, but can be changed using the configure script options
+--prefix, --exec-prefix, --includedir, and --libdir (see below). For example, a global
+installation of SUNDIALS on a *NIX system could be accomplished using
+
+ % ./configure --prefix=/opt/sundials-2.3.0
+
+Although all installed libraries reside under 'libdir', the public header files are further
+organized into subdirectories under 'includedir'.
+
+The installed libraries and exported header files are listed for reference in Section A.1.
+
+A typical user program need not explicitly include any of the shared SUNDIALS header files
+from under the 'includedir'/sundials directory since they are explicitly included by the
+appropriate solver header files (e.g., cvode_dense.h includes sundials_dense.h).
+However, it is both legal and safe to do so (e.g., the functions declared in
+sundials_smalldense.h could be used in building a preconditioner.
+
+
+--------------------------
+B.3. Compilers and Options
+--------------------------
+
+Some systems require unusual options for compilation or linking that the `configure'
+script does not know about. Run `./configure --help' for details on some of the
+pertinent environment variables.
+
+You can give `configure' initial values for these variables by setting them in the
+environment. You can do that on the command line like this:
+
+ % ./configure CC=gcc CFLAGS=-O2 F77=g77 FFLAGS=-O
+
+Here is a detailed description of the configure options that are pertinent to SUNDIALS.
+In what follows, 'build_tree' is the directory from where 'configure' was invoked.
+
+
+----------------------
+B.3.1. General options
+----------------------
+
+--help
+-h
+
+ print a summary of the options to `configure', and exit.
+
+--quiet
+--silent
+-q
+
+ do not print messages saying which checks are being made. To
+ suppress all normal output, redirect it to `/dev/null' (any error
+ messages will still be shown).
+
+
+--prefix=PREFIX
+
+ Location for architecture-independent files.
+ Default: PREFIX=/usr/local
+
+--exec-prefix=EPREFIX
+
+ Location for architecture-dependent files.
+ Default: EPREFIX=/usr/local
+
+--includedir=DIR
+
+ Alternate location for header files.
+ Default: DIR=PREFIX/include
+
+--libdir=DIR
+
+ Alternate location for libraries.
+ Default: DIR=EPREFIX/lib
+
+--disable-solver
+
+ Although each existing solver module is built by default, support for a
+ given solver can be explicitly disabled using this option.
+ The valid values for solver are: cvode, cvodes,
+ ida, and kinsol.
+
+--enable-examples
+
+ Available example programs are not built by default. Use this option
+ to enable compilation of all pertinent example programs. Upon completion of
+ the 'make' command, the example executables will be created under solver-specific
+ subdirectories of 'builddir'/examples:
+
+ 'builddir'/examples/'solver'/serial : serial C examples
+ 'builddir'/examples/'solver'/parallel : parallel C examples
+ 'builddir'/examples/'solver'/fcmix_serial : serial Fortran examples
+ 'builddir'/examples/'solver'/fcmix_parallel : parallel Fortran examples
+
+ Note: Some of these subdirectories may not exist depending upon the
+ solver and/or the configuration options given.
+
+--with-exinstdir=DIR
+
+ Alternate location for example sources and sample output files (valid only if
+ examples are enabled). Note that installtion of example files can be completely
+ disabled by issuing DIR=no (in case building the examples is desired only as a
+ test of the SUNDIALS libraries).
+
+ Default: DIR=EPREFIX/examples
+
+--with-cppflags=ARG
+
+ Specify C preprocessor flags (overrides the environment variable CPPFLAGS)
+ (e.g., ARG=-I<include_dir> if necessary header files are located in nonstandard locations).
+
+--with-cflags=ARG
+
+ Specify C compilation flags (overrides the environment variable CFLAGS)
+
+--with-ldflags=ARG
+
+ Specify linker flags (overrides the environment variable LDFLAGS)
+ (e.g., ARG=-L<lib_dir> if required libraries are located in nonstandard locations).
+
+--with-libs=ARG
+
+ Specify additional libraries to be used
+ (e.g., ARG=-l<foo> to link with the library named libfoo.a or libfoo.so).
+
+--with-precision=ARG
+
+ By default, sundials will define a real number (internally referred to as
+ realtype) to be a double-precision floating-point numeric data type (double
+ C-type); however, this option may be used to build sundials with realtype
+ alternatively defined as a single-precision floating-point numeric data type
+ (float C-type) if ARG=single, or as a long double C-type if ARG=extended.
+
+ Default: ARG=double
+
+----------------------------------
+B.3.2. Options for Fortran support
+----------------------------------
+
+--disable-fcmix
+
+ Using this option will disable all F77 support. The fcvode, fida, fkinsol and
+ fnvector modules will not be built regardless of availability.
+
+--with-fflags=ARG
+
+ Specify F77 compilation flags (overrides the environment variable FFLAGS)
+
+--------------------------------------
+B.3.3. Options for Blas/Lapack support
+--------------------------------------
+
+--disable-lapack
+
+ Disable support for the linear solver module based on Blas/Lapack.
+
+--with-blas=ARG
+
+ Specifies the BLAS library to be used
+
+--with-lapack=ARG
+
+ Specifies the LAPACK library to be used
+
+------------------------------
+B.3.4. Options for MPI support
+------------------------------
+
+The following configuration options are only applicable to the parallel sundials packages:
+
+
+--disable-mpi
+
+ Using this option will completely disable MPI support.
+
+--with-mpicc=ARG
+--with-mpif77=ARG
+
+ By default, the configuration utility script will use the MPI compiler
+ scripts named mpicc and mpif77 to compile the parallelized
+ sundials subroutines; however, for reasons of compatibility, different
+ executable names may be specified via the above options. Also, ARG=no
+ can be used to disable the use of MPI compiler scripts, thus causing
+ the serial C and F compilers to be used to compile the parallelized
+ sundials functions and examples.
+
+--with-mpi-root=MPIDIR
+
+ This option may be used to specify which MPI implementation should be used.
+ The sundials configuration script will automatically check under the
+ subdirectories MPIDIR/include and MPIDIR/lib for the necessary
+ header files and libraries. The subdirectory MPIDIR/bin will also be
+ searched for the C and F MPI compiler scripts, unless the user uses
+ --with-mpicc=no or --with-mpif77=no.
+
+--with-mpi-incdir=INCDIR
+--with-mpi-libdir=LIBDIR
+--with-mpi-libs=LIBS
+
+ These options may be used if the user would prefer not to use a preexisting
+ MPI compiler script, but instead would rather use a serial complier and
+ provide the flags necessary to compile the MPI-aware subroutines in
+ sundials.
+
+ Often an MPI implementation will have unique library names and so it may
+ be necessary to specify the appropriate libraries to use (e.g., LIBS=-lmpich).
+
+ Default: INCDIR=MPIDIR/include, LIBDIR=MPIDIR/lib and LIBS=-lmpi
+
+--with-mpi-flags=ARG
+
+ Specify additional MPI-specific flags.
+
+----------------------------------
+B.3.5. Options for library support
+----------------------------------
+
+By default, only static libraries are built, but the following option
+may be used to build shared libraries on supported platforms.
+
+--enable-shared
+
+ Using this particular option will result in both static and shared versions
+ of the available sundials libraries being built if the systsupports
+ shared libraries. To build only shared libraries also specify --disable-static.
+
+ Note: The fcvode and fkinsol libraries can only be built as static
+ libraries because they contain references to externally defined symbols, namely
+ user-supplied F77 subroutines. Although the F77 interfaces to the serial and
+ parallel implementations of the supplied nvector module do not contain any
+ unresolvable external symbols, the libraries are still built as static libraries
+ for the purpose of consistency.
+
+----------------------------
+B.3.6. Environment variables
+----------------------------
+
+The following environment variables can be locally (re)defined for use during the
+configuration of sundials. See the next section for illustrations of these.
+
+CC
+
+F77
+
+ Since the configuration script uses the first C and F77 compilers found in
+ the current executable search path, then each relevant shell variable (CC
+ and F77) must be locally (re)defined in order to use a different compiler.
+ For example, to use xcc (executable name of chosen compiler) as the C
+ language compiler, use CC=xcc in the configure step.
+
+CFLAGS
+
+FFLAGS
+
+ Use these environment variables to override the default C and F77 compilation flags.
+
+
+---------------------------
+B.4. Configuration examples
+---------------------------
+
+The following examples are meant to help demonstrate proper usage of the configure options.
+
+To build SUNDIALS using the default C and Fortran compilers, and default mpicc and mpif77
+parallel compilers, enable compilation of examples, and install them under the default
+directory /home/myname/sundials/examples, use
+
+ % ./configure --prefix=/home/myname/sundials --enable-examples
+
+To disable installation of the examples, use:
+ % ./configure --prefix=/home/myname/sundials \
+ --enable-examples --with-examples-instdir=no
+
+The following example builds SUNDIALS using gcc as the serial C compiler, g77 as the serial
+Fortran compiler, mpicc as the parallel C compiler, mpif77 as the parallel Fortran compiler,
+and uses the -g3 C compilation flag:
+
+ % ./configure CC=gcc F77=g77 --with-cflags=-g3 --with-fflags=-g3 \
+ --with-mpicc=/usr/apps/mpich/1.2.4/bin/mpicc \
+ --with-mpif77=/usr/apps/mpich/1.2.4/bin/mpif77
+
+The next example again builds SUNDIALS using gcc as the serial C compiler, but the
+--with-mpicc=no option explicitly disables the use of the corresponding MPI compiler
+script. In addition, since the --with-mpi-root option is given, the compilation flags
+-I/usr/apps/mpich/1.2.4/include and -L/usr/apps/mpich/1.2.4/lib are passed to gcc when
+compiling the MPI-enabled functions.
+The --disable-examples option explicitly disables the examples.
+The --with-mpi-libs option is required so that the configure script can check if gcc
+can link with the appropriate MPI library.
+
+ % ./configure CC=gcc --disable-examples --with-mpicc=no \
+ --with-mpi-root=/usr/apps/mpich/1.2.4 \
+ --with-mpi-libs=-lmpich
+
+
+
+===========================
+C. CMake-based installation
+===========================
+
+Using CMake as a build system for the SUNDIALS libraries has the advantage
+that GUI based build configuration is possible. Also build files for Windows
+development environments can be easily generated. On the Windows platform
+compilers such as the Borland C++ compiler or Visual C++ compiler are natively
+supported.
+
+The installation options are very similar to the options mentioned above.
+Note, however, that CMake may not support all features and plattforms that
+are supported by the autotools build system.
+
+------------------
+C.1. Prerequisites
+------------------
+
+You may need to get CMake if it isn't available on your system already.
+In order to use the CMake build system, you need a fairly recent CMake version.
+You can download it from http://www.cmake.org www.cmake.org.
+
+----------------------------
+C.2. Configuration and build
+----------------------------
+
+We assume here a *nix system. For other systems, the required steps are very
+similar and are explained in more detail in the SUNDIALS user guides.
+The installation steps are as follows:
+
+- uncompress solver-x.y.z.tar.gz to obtain 'srcdir'
+- create the directories 'builddir' and 'instdir'
+- change directory to 'builddir'
+- run ccmake with 'srcdir' as an argument
+
+You should now see the ccmake curses interface. Press 'c' to configure your build
+with the default options. (If you don't have curses on your system and cannot use
+ccmake, you can configure cmake with command line options very similar to ./configure
+of the autotools. You can read about this on the cmake webpage.)
+
+In the dialog you can adjust the build options. For details see the options above
+in the autotools section. To adjust advanced options press 't' to show all the options
+and settings CMake offers.
+
+After adjusting some options, for instance enabling the examples by turning
+ENABLE_EXAMPLES to ON, you need to press 'c' again. Depending on the options,
+you will see new options at the top of the list, marked with a star. After
+adjusting the new options, press 'c' again. Once all options have been set,
+you can press 'g' to generate the make files.
+
+Now you can build and install the sundials library:
+ % make
+ % make install
+
+
diff --git a/debian/copyright b/LICENSE
similarity index 83%
copy from debian/copyright
copy to LICENSE
index 98cde97..73faf96 100644
--- a/debian/copyright
+++ b/LICENSE
@@ -1,22 +1,15 @@
-This package was debianized by Andrey Romanenko <andrey at enginum.com> on
-Wed, 20 Apr 2005 12:01:42 +0100.
+Copyright (c) 2002, The Regents of the University of California.
+Produced at the Lawrence Livermore National Laboratory.
+Written by S.D. Cohen, A.C. Hindmarsh, R. Serban,
+ D. Shumaker, and A.G. Taylor.
+UCRL-CODE-155951 (CVODE)
+UCRL-CODE-155950 (CVODES)
+UCRL-CODE-155952 (IDA)
+UCRL-CODE-237203 (IDAS)
+UCRL-CODE-155953 (KINSOL)
+All rights reserved.
-It was downloaded from http://www.llnl.gov/CASC/sundials/
-
-Authors: Peter Brown, Aaron Collier, Keith Grant, Alan Hindmarsh,
- Steve Lee, Radu Serban, Dan Shumaker, Carol Woodward
-
-Copyright Holder: The Regents of the University of California.
-
-License:
-
-Copyright (c) 2002, The Regents of the University of California.
-Produced at the Lawrence Livermore National Laboratory
-Written by A.C. Hindmarsh and R. Serban.
-UCRL-CODE-155950
-All rights reserved.
-
-This file is part of CVODES v2.1.0.
+This file is part of SUNDIALS.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
diff --git a/Makefile.in b/Makefile.in
new file mode 100644
index 0000000..c520e8e
--- /dev/null
+++ b/Makefile.in
@@ -0,0 +1,139 @@
+# -----------------------------------------------------------------
+# $Revision: 1.17 $
+# $Date: 2012/04/06 22:24:37 $
+# -----------------------------------------------------------------
+# Programmer(s): Radu Serban and Aaron Collier @ LLNL
+# -----------------------------------------------------------------
+# Copyright (c) 2002, The Regents of the University of California.
+# Produced at the Lawrence Livermore National Laboratory.
+# All rights reserved.
+# For details, see the LICENSE file.
+# -----------------------------------------------------------------
+# Main Makefile for SUNDIALS suite
+#
+# @configure_input@
+# -----------------------------------------------------------------
+
+SHELL = @SHELL@
+
+ at SET_MAKE@
+
+srcdir = @srcdir@
+builddir = @builddir@
+abs_builddir = @abs_builddir@
+top_builddir = @builddir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+includedir = @includedir@
+libdir = @libdir@
+bindir = @bindir@
+
+INSTALL = @INSTALL@
+INSTALL_PROG = @INSTALL_PROGRAM@
+
+SLV_MODULES = @SLV_MODULES@
+EXS_MODULES = @EXS_MODULES@
+
+ALL_MODULES = @SLV_MODULES@ @EXS_MODULES@
+
+EXS_INSTDIR = @EXS_INSTDIR@
+
+top_srcdir = $(srcdir)
+
+mkinstalldirs = $(SHELL) $(top_srcdir)/config/mkinstalldirs
+
+# -----------------------------------------------------------------
+
+all:
+ @for i in ${ALL_MODULES} ; do \
+ if test -d $${i} ; then \
+ echo "----------------------"; \
+ echo "Make $${i}..." ; \
+ echo "----------------------"; \
+ cd $${i} ; \
+ ${MAKE} ; \
+ cd ${abs_builddir} ; \
+ echo "" ; \
+ fi ; \
+ done
+
+install:
+ $(mkinstalldirs) $(bindir)
+ $(INSTALL_PROG) $(top_builddir)/bin/sundials-config $(bindir)/
+ @if test -f $(top_builddir)/bin/fortran-update.sh ; then \
+ $(INSTALL_PROG) $(top_builddir)/bin/fortran-update.sh $(bindir)/ ;\
+ fi
+ @for i in ${SLV_MODULES} ; do \
+ if test -d $${i} ; then \
+ echo "----------------------"; \
+ echo "Install $${i}..." ; \
+ echo "----------------------"; \
+ cd $${i} ; \
+ ${MAKE} install ; \
+ cd ${abs_builddir} ; \
+ echo "" ; \
+ fi ; \
+ done
+ @if test "X${EXS_MODULES}" = "X" ; then \
+ : ; \
+ else \
+ if test "X${EXS_INSTDIR}" = "Xno"; then \
+ echo "" ; \
+ echo "" ; \
+ echo "Examples were built but installation was disabled." ; \
+ echo "" ; \
+ echo "" ; \
+ else \
+ for i in ${EXS_MODULES} ; do \
+ echo "----------------------"; \
+ echo "Install $${i}..." ; \
+ echo "----------------------"; \
+ cd $${i} ; \
+ ${MAKE} install ; \
+ cd ${abs_builddir} ; \
+ echo "" ; \
+ done ; \
+ fi ; \
+ fi
+
+clean:
+ @for i in ${ALL_MODULES} ; do \
+ if test -d $${i} ; then \
+ cd $${i} ; \
+ ${MAKE} clean ; \
+ cd ${abs_builddir} ; \
+ fi ; \
+ done
+
+uninstall:
+ rm -f $(bindir)/sundials-config
+ rm -f $(bindir)/fortran-update.sh
+ @for i in ${ALL_MODULES} ; do \
+ if test -d $${i} ; then \
+ echo "----------------------"; \
+ echo "Uninstall $${i}..." ; \
+ echo "----------------------"; \
+ cd $${i} ; \
+ ${MAKE} uninstall ; \
+ cd ${abs_builddir} ; \
+ fi ; \
+ done
+
+# ---------------------------------------------------------------------
+
+distclean:
+ @for i in ${ALL_MODULES} ; do \
+ if test -d $${i} ; then \
+ cd $${i}; \
+ ${MAKE} distclean; \
+ cd ${abs_builddir} ; \
+ fi ; \
+ done
+ rm -f $(top_builddir)/config.log
+ rm -f $(top_builddir)/config.status
+ rm -f $(top_builddir)/config.cache
+ rm -f $(top_builddir)/config.h
+ rm -f $(top_builddir)/libtool
+ rm -f $(top_builddir)/bin/sundials-config
+ rm -f $(top_builddir)/bin/fortran-update.sh
+ rm -f Makefile
diff --git a/README b/README
new file mode 100644
index 0000000..2e4d7e8
--- /dev/null
+++ b/README
@@ -0,0 +1,57 @@
+ SUNDIALS
+ SUite of Nonlinear and DIfferential/ALgebraic equation Solvers
+ Release 2.5.0, March 2012
+ Alan Hindmarsh, Radu Serban, Carol Woodward
+ Center for Applied Scientific Computing, LLNL
+
+
+The family of solvers referred to as SUNDIALS consists of the following solvers:
+ CVODE - for integration of ordinary differential equation systems (ODEs)
+ CVODE treats stiff and nonstiff ODE systems of the form
+ y' = f(t,y), y(t0) = y0
+ CVODES - for integration and sensitivity analysis of ODEs
+ CVODES treats stiff and nonstiff ODE systems of the form
+ y' = f(t,y,p), y(t0) = y0(p)
+ IDA - for integration of differential-algebraic equation systems (DAEs)
+ IDA treats DAE systems of the form
+ F(t,y,y') = 0, y(t0) = y0, y'(t0) = y0'
+ IDAS - for integration and sensitivity analysis of DAEs
+ IDAS treats DAE systems of the form
+ F(t,y,y',p) = 0, y(t0) = y0(p), y'(t0) = y0'(p)
+ KINSOL - for solution of nonlinear algebraic systems
+ KINSOL treats nonlinear systems of the form
+ F(u) = 0
+
+The various solvers of this family share many subordinate modules.
+For this reason, it is organized as a family, with a directory structure
+that exploits that sharing. Each individual solver includes documentation
+on installation, along with full usage documentation.
+
+Warning to users who receive more than one of these individual solvers
+at different times: The mixing of old and new versions SUNDIALS may fail.
+To avoid such failures, obtain all desired solvers at the same time.
+
+For installation directions see the file INSTALL_NOTES.
+
+For additional information on a particular solver, see the README file
+in the solver directory (e.g. src/cvode/README).
+
+
+Release history
+
++----------+-----------------------------------------------------------------+
+| | SUNDIALS | Solver version |
+| Date | +----------+----------+----------+---------------------+
+| | release | CVODE | CVODES | IDA | IDAS | KINSOL |
++----------+----------+----------+----------+----------+---------------------+
+| Jul 2002 | 1.0 | 2.0 | 1.0 | 2.0 | | 2.0 |
+| Dec 2004 | 2.0 | 2.2.0 | 2.1.0 | 2.2.0 | | 2.2.0 |
+| Jan 2005 | 2.0.1 | 2.2.1 | 2.1.1 | 2.2.1 | | 2.2.1 |
+| Mar 2005 | 2.0.2 | 2.2.2 | 2.1.2 | 2.2.2 | | 2.2.2 |
+| Apr 2005 | 2.1.0 | 2.3.0 | 2.2.0 | 2.3.0 | | 2.3.0 |
+| May 2005 | 2.1.1 | 2.3.0 | 2.3.0 | 2.3.0 | | 2.3.0 |
+| Mar 2006 | 2.2.0 | 2.4.0 | 2.4.0 | 2.4.0 | | 2.4.0 |
+| Nov 2006 | 2.3.0 | 2.5.0 | 2.5.0 | 2.5.0 | | 2.5.0 |
+| May 2009 | 2.4.0 | 2.6.0 | 2.6.0 | 2.6.0 | 1.0.0 | 2.6.0 |
+| Mar 2012 | 2.5.0 | 2.7.0 | 2.7.0 | 2.7.0 | 1.1.0 | 2.7.0 |
++----------+----------+----------+----------+----------+---------------------+
diff --git a/acinclude.m4 b/acinclude.m4
new file mode 100644
index 0000000..7825698
--- /dev/null
+++ b/acinclude.m4
@@ -0,0 +1,3213 @@
+# -----------------------------------------------------------------
+# $Revision: 1.58 $
+# $Date: 2010/12/15 22:28:17 $
+# -----------------------------------------------------------------
+# Programmer(s): Radu Serban and Aaron Collier @ LLNL
+# -----------------------------------------------------------------
+# Copyright (c) 2002, The Regents of the University of California.
+# Produced at the Lawrence Livermore National Laboratory.
+# All rights reserved.
+# For details, see the LICENSE file.
+# -----------------------------------------------------------------
+#
+# SUNDIALS autoconf macros
+#
+# The functions defined here fall into the following categories:
+#
+# (1) Initializations:
+# SUNDIALS_GREETING
+# SUNDIALS_INITIALIZE
+# SUNDIALS_ENABLES
+#
+# (2) C compiler tests
+# SUNDIALS_SET_CC
+# SUNDIALS_CC_CHECK
+# SUNDIALS_CPLUSPLUS_CHECK
+#
+# (3) Fortran support
+# SUNDIALS_F77_SUPPORT
+# SUNDIALS_F77_CHECK
+# SUNDIALS_F77_LNKR_CHECK
+# SUNDIALS_F77_NAME_MANGLING
+# SUNDIALS_F77_LAPACK_SET
+#
+# (4) Parallel support
+# SUNDIALS_SET_MPICC
+# SUNDIALS_CHECK_MPICC
+# SUNDIALS_CC_WITH_MPI_CHECK
+# SUNDIALS_SET_MPIF77
+# SUNDIALS_CHECK_MPIF77
+# SUNDIALS_MPIF77_LNKR_CHECK
+# SUNDIALS_F77_WITH_MPI_CHECK
+# SUNDIALS_CHECK_MPI2
+#
+# (5) Finalizations:
+# SUNDIALS_MORE_HELP
+# SUNDIALS_SET_EXAMPLES
+# SUNDIALS_BUILD_MODULES_LIST
+# SUNDIALS_POST_PROCESSING
+# SUNDIALS_REPORT
+#
+# -----------------------------------------------------------------
+
+
+#=================================================================#
+# #
+# #
+# I N I T I A L I Z A T I O N S #
+# #
+# #
+#==================================================================
+
+#------------------------------------------------------------------
+# GREETING
+#------------------------------------------------------------------
+
+AC_DEFUN([SUNDIALS_GREETING],
+[
+
+# Say Hi!
+echo "
+---------------------------------
+Running SUNDIALS Configure Script
+---------------------------------
+"
+
+]) dnl END SUNDIALS_GREETING
+
+#------------------------------------------------------------------
+# PERFORM INITIALIZATIONS
+#------------------------------------------------------------------
+
+AC_DEFUN([SUNDIALS_INITIALIZE],
+[
+
+# Reference custom macros
+m4_include([config/mod_fortran.m4])
+m4_include([config/mod_c.m4])
+m4_include([config/cust_general.m4])
+
+# Make input filename DOS compatible (change config.h.in to config.hin)
+AC_CONFIG_HEADERS([config.h:config.hin])
+
+# Make user aware of copyright notice (input COPYRIGHT information)
+AC_COPYRIGHT(
+[
+Copyright (c) 2002, The Regents of the University of California.
+Produced at the Lawrence Livermore National Laboratory.
+All rights reserved.
+For details, see the LICENSE file.
+])
+
+# Specify root of source tree
+# Given file is guaranteed to exist in all SUNDIALS packages
+AC_CONFIG_SRCDIR([/src/sundials/sundials_nvector.c])
+
+# Get host information
+# AC_CANONICAL_BUILD defines the following variables: build, build_cpu,
+# build_vendor, and build_os
+AC_CANONICAL_BUILD
+# AC_CANONICAL_HOST defines the following variables: host, host_cpu,
+# host_vendor, and host_os
+AC_CANONICAL_HOST
+
+# Set MAKE if necessary
+# Must include @SET_MAKE@ in each Makefile.in file
+# AC_SUBST is called automatically for SET_MAKE
+AC_PROG_MAKE_SET
+
+# Defines INSTALL (sets to path of "install" program)
+# Also sets INSTALL_PROGRAM and INSTALL_SCRIPT
+AC_PROG_INSTALL
+
+# Set defaults for config/sundials_config.in file
+F77_MANGLE_MACRO1=""
+F77_MANGLE_MACRO2=""
+PRECISION_LEVEL=""
+GENERIC_MATH_LIB=""
+BLAS_LAPACK_MACRO=""
+F77_MPI_COMM_F2C=""
+SUNDIALS_EXPORT="#define SUNDIALS_EXPORT"
+
+# Initialize enable status of various modules, options, and features
+# to their default values
+#
+# NOTE: when CPODES is released, change its default to enabled.
+#
+CVODE_ENABLED="yes"
+CVODES_ENABLED="yes"
+IDA_ENABLED="yes"
+IDAS_ENABLED="yes"
+KINSOL_ENABLED="yes"
+LAPACK_ENABLED="yes"
+FCMIX_ENABLED="yes"
+MPI_ENABLED="yes"
+#
+CPODES_ENABLED="no"
+#
+EXAMPLES_ENABLED="no"
+F77_EXAMPLES_ENABLED="no"
+
+# Initialize variables that may NOT necessarily be initialized
+# during normal execution. Should NOT use uninitialized variables
+F77_OK="no"
+LAPACK_OK="no"
+MPI_C_COMP_OK="no"
+MPI_F77_COMP_OK="no"
+
+# This variable is set to "yes" if an AC_MSG_WARN statement
+# was executed
+SUNDIALS_WARN_FLAG="no"
+
+]) dnl END SUNDIALS_INITIALIZE
+
+#------------------------------------------------------------------
+# TEST ENABLES
+#
+# The following variables may be changed here (default value in []):
+#
+# CVODE_ENABLED - enable CVODE module [yes]
+# CVODES_ENABLED - enable CVODES module [yes]
+# IDA_ENABLED - enable IDA module [yes]
+# IDAS_ENABLED - enable IDAS module [yes]
+# KINSOL_ENABLED - enable KINSOL module [yes]
+# FCMIX_ENABLED - enable Fortran-C interfaces [yes]
+# LAPACK_ENABLED - enable Lapack support [yes]
+# MPI_ENABLED - enable parallel support [yes]
+# EXAMPLES_ENABLED - enable example programs [no]
+# F77_EXAMPLES_ENABLED - enable Fortran example programs [no]
+#
+#------------------------------------------------------------------
+
+AC_DEFUN([SUNDIALS_ENABLES],
+[
+
+# Check if user wants to disable CVODE module
+# If not, then make certain source directory actually exists
+AC_ARG_ENABLE(cvode,
+[AC_HELP_STRING([--disable-cvode],[disable configuration of CVODE])],
+[
+if test "X${enableval}" = "Xno"; then
+ CVODE_ENABLED="no"
+fi
+],
+[
+if test -d ${srcdir}/src/cvode ; then
+ CVODE_ENABLED="yes"
+else
+ CVODE_ENABLED="no"
+fi
+])
+
+# Check if user wants to disable CVODES module
+# If not, then make certain source directory actually exists
+AC_ARG_ENABLE(cvodes,
+[AC_HELP_STRING([--disable-cvodes],[disable configuration of CVODES])],
+[
+if test "X${enableval}" = "Xno"; then
+ CVODES_ENABLED="no"
+fi
+],
+[
+if test -d ${srcdir}/src/cvodes ; then
+ CVODES_ENABLED="yes"
+else
+ CVODES_ENABLED="no"
+fi
+])
+
+# Check if user wants to disable IDA module
+# If not, then make certain source directory actually exists
+AC_ARG_ENABLE(ida,
+[AC_HELP_STRING([--disable-ida],[disable configuration of IDA])],
+[
+if test "X${enableval}" = "Xno"; then
+ IDA_ENABLED="no"
+fi
+],
+[
+if test -d ${srcdir}/src/ida ; then
+ IDA_ENABLED="yes"
+else
+ IDA_ENABLED="no"
+fi
+])
+
+# Check if user wants to disable IDAS module
+# If not, then make certain source directory actually exists
+AC_ARG_ENABLE(idas,
+[AC_HELP_STRING([--disable-idas],[disable configuration of IDAS])],
+[
+if test "X${enableval}" = "Xno"; then
+ IDAS_ENABLED="no"
+fi
+],
+[
+if test -d ${srcdir}/src/idas ; then
+ IDAS_ENABLED="yes"
+else
+ IDAS_ENABLED="no"
+fi
+])
+
+# Check if user wants to disable KINSOL MODULE
+# If not, then make certain source directory actually exists
+AC_ARG_ENABLE(kinsol,
+[AC_HELP_STRING([--disable-kinsol],[disable configuration of KINSOL])],
+[
+if test "X${enableval}" = "Xno"; then
+ KINSOL_ENABLED="no"
+fi
+],
+[
+if test -d ${srcdir}/src/kinsol ; then
+ KINSOL_ENABLED="yes"
+else
+ KINSOL_ENABLED="no"
+fi
+])
+
+# Check if user wants to disable CPODES module
+# If not, then make certain source directory actually exists
+AC_ARG_ENABLE(cpodes,
+[AC_HELP_STRING([--disable-cpodes],[disable configuration of CPODES])],
+[
+if test "X${enableval}" = "Xno"; then
+ CPODES_ENABLED="no"
+fi
+],
+[
+if test -d ${srcdir}/src/cpodes ; then
+ CPODES_ENABLED="yes"
+else
+ CPODES_ENABLED="no"
+fi
+])
+
+# Check if user wants to disable Fortran support (FCMIX components).
+AC_ARG_ENABLE([fcmix],
+[AC_HELP_STRING([--disable-fcmix], [disable Fortran-C support])],
+[
+if test "X${enableval}" = "Xno"; then
+ FCMIX_ENABLED="no"
+fi
+],
+[
+if test "X${CVODE_ENABLED}" = "Xno" && test "X${KINSOL_ENABLED}" = "Xno" && test "X${IDA_ENABLED}" = "Xno"; then
+ FCMIX_ENABLED="no"
+fi
+])
+
+# Check if user wants to disable Lapack support.
+AC_ARG_ENABLE([lapack],
+[AC_HELP_STRING([--disable-lapack], [disable Lapack support])],
+[
+if test "X${enableval}" = "Xno"; then
+ LAPACK_ENABLED="no"
+fi
+])
+
+# Check if user wants to disable support for MPI.
+# If not, set the default based on whetehr certain source directories exist
+AC_ARG_ENABLE([mpi],
+[AC_HELP_STRING([--disable-mpi],[disable MPI support])],
+[
+if test "X${enableval}" = "Xno"; then
+ MPI_ENABLED="no"
+fi
+],
+[
+if test -d ${srcdir}/src/nvec_par || test -d ${srcdir}/src/nvec_spcpar; then
+ MPI_ENABLED="yes"
+else
+ MPI_ENABLED="no"
+fi
+])
+
+# Check if user wants to enable all examples.
+# Examples are NOT built by default
+AC_ARG_ENABLE(examples,
+[AC_HELP_STRING([--enable-examples],[enable configuration of examples])],
+[
+if test "X${enableval}" = "Xno"; then
+ EXAMPLES_ENABLED="no"
+else
+ EXAMPLES_ENABLED="yes"
+fi
+])
+
+# Fortran examples are enabled only if both FCMIX and EXAMPLES are enabled
+if test "X${FCMIX_ENABLED}" = "Xyes" && test "X${EXAMPLES_ENABLED}" = "Xyes"; then
+ F77_EXAMPLES_ENABLED="yes"
+fi
+
+]) dnl END SUNDIALS_ENABLES
+
+
+#=================================================================#
+# #
+# #
+# C C O M P I L E R T E S T S #
+# #
+# #
+#==================================================================
+
+
+#------------------------------------------------------------------
+# CHECK C COMPILER
+#------------------------------------------------------------------
+
+AC_DEFUN([SUNDIALS_SET_CC],
+[
+
+
+if test "X${CC}" = "X"; then
+
+ echo ""
+ echo " Unable to find a working C compiler"
+ echo ""
+ echo " Try using CC to explicitly specify a C compiler"
+ echo ""
+
+ AC_MSG_ERROR([cannot find a C compiler])
+
+else
+
+ SUNDIALS_CC_CHECK
+
+fi
+
+]) dnl END SUNDIALS_SET_CC
+
+
+AC_DEFUN([SUNDIALS_CC_CHECK],
+[
+
+# Default is C programming language (initialize language stack)
+AC_LANG([C])
+
+AC_ARG_WITH([],[],[])
+
+# Set floating-point precision: single [C type 'float']
+# double [C type 'double'] (default)
+# extended [C type 'long double']
+# Provide variable description templates for config.hin and config.h files
+# Required by autoheader utility
+AH_TEMPLATE([SUNDIALS_SINGLE_PRECISION],
+ [Define SUNDIALS data type 'realtype' as 'float'])
+AH_TEMPLATE([SUNDIALS_DOUBLE_PRECISION],
+ [Define SUNDIALS data type 'realtype' as 'double'])
+AH_TEMPLATE([SUNDIALS_EXTENDED_PRECISION],
+ [Define SUNDIALS data type 'realtype' as 'long double'])
+
+AC_MSG_CHECKING([floating-point data type to use])
+AC_ARG_WITH(precision,
+[AC_HELP_STRING([--with-precision=ARG],
+[specify floating-point precision (single/double/extended) [double]])],
+[
+if test "X${withval}" = "Xsingle"; then
+ AC_MSG_RESULT([float])
+ AC_DEFINE([SUNDIALS_SINGLE_PRECISION],[1],[])
+ FLOAT_TYPE="single"
+ PRECISION_LEVEL="#define SUNDIALS_SINGLE_PRECISION 1"
+elif test "X${withval}" = "Xdouble"; then
+ AC_MSG_RESULT([double])
+ AC_DEFINE([SUNDIALS_DOUBLE_PRECISION],[1],[])
+ FLOAT_TYPE="double"
+ PRECISION_LEVEL="#define SUNDIALS_DOUBLE_PRECISION 1"
+elif test "X${withval}" = "Xextended"; then
+ AC_MSG_RESULT([long double])
+ AC_DEFINE([SUNDIALS_EXTENDED_PRECISION],[1],[])
+ FLOAT_TYPE="extended"
+ PRECISION_LEVEL="#define SUNDIALS_EXTENDED_PRECISION 1"
+else
+ AC_MSG_ERROR([invalid input])
+fi
+],
+[
+# Use 'double' by default
+AC_MSG_RESULT([double])
+AC_DEFINE([SUNDIALS_DOUBLE_PRECISION],[1],[])
+FLOAT_TYPE="double"
+PRECISION_LEVEL="#define SUNDIALS_DOUBLE_PRECISION 1"
+])
+
+AC_ARG_WITH([],[ ],[])
+
+# Overwrite CFLAGS
+AC_MSG_CHECKING([for C compiler flags])
+AC_ARG_WITH(cflags,
+[AC_HELP_STRING([--with-cflags=ARG],[specify C compiler flags (CFLAGS will be overridden)])],
+[
+AC_MSG_RESULT([${withval}])
+CFLAGS="${withval}"
+],
+[
+AC_MSG_RESULT([none])
+])
+
+# Set CPP to command that runs C preprocessor
+AC_PROG_CPP
+
+# Overwrite CPPFLAGS
+AC_MSG_CHECKING([for C/C++ preprocessor flags])
+AC_ARG_WITH(cppflags,
+[AC_HELP_STRING([--with-cppflags=ARG],[specify C/C++ preprocessor flags (CPPFLAGS will be overridden)])],
+[
+AC_MSG_RESULT([${withval}])
+CPPFLAGS="${withval}"
+],
+[
+AC_MSG_RESULT([none])
+])
+
+# Overwrite LDFLAGS
+AC_MSG_CHECKING([for linker flags])
+AC_ARG_WITH(ldflags,
+[AC_HELP_STRING([--with-ldflags=ARG],[specify linker flags (LDFLAGS will be overridden)])],
+[
+AC_MSG_RESULT([${withval}])
+LDFLAGS="${withval}"
+],
+[
+AC_MSG_RESULT([none])
+])
+
+# Add any additional libraries
+AC_MSG_CHECKING([for extra libraries])
+AC_ARG_WITH(libs,
+[AC_HELP_STRING([--with-libs=ARG],[add extra libraries])],
+[
+AC_MSG_RESULT([${withval}])
+if test "X${LIBS}" = "X"; then
+ LIBS="${withval}"
+else
+ LIBS="${LIBS} ${withval}"
+fi
+],
+[
+AC_MSG_RESULT([none])
+])
+
+# Defines STDC_HEADERS if the following header files are found: stdlib.h,
+# stdarg.h, string.h, and float.h
+# We really only need stdlib.h and float.h
+AC_HEADER_STDC
+AC_CHECK_HEADERS([stdlib.h float.h math.h])
+
+# Set flag indicating if generic function names should be used
+# Provide variable description template for config.hin and config.h files
+# Required by autoheader utility
+AH_TEMPLATE([SUNDIALS_USE_GENERIC_MATH],
+ [Use generic math functions])
+
+# Check if math library contains abs(), fabs(), pow(), and sqrt() functions (required)
+# May update LIBS (meaning add additional library, namely libm)
+MATH_FABS_OK="yes"
+MATH_POW_OK="yes"
+MATH_SQRT_OK="yes"
+# Save copy of LIBS variable and unset LIBS
+SAVED_LIBS="${LIBS}"
+LIBS=""
+# The abs routine is defined for an integer argument, so check for it regardless of
+# the level of precision chosen
+AC_CHECK_LIB([m],abs,[],[AC_MSG_ERROR([cannot find abs function])])
+TEMP_MATH_LIB="${LIBS}"
+LIBS=""
+# Check for single-precision math routines
+if test "X${FLOAT_TYPE}" = "Xsingle"; then
+ AC_CHECK_LIB([m],fabsf,[],[MATH_FABS_OK="no"])
+ AC_CHECK_LIB([m],powf,[],[MATH_POW_OK="no"])
+ AC_CHECK_LIB([m],sqrtf,[],[MATH_SQRT_OK="no"])
+# Check for extended-precision math routines
+elif test "X${FLOAT_TYPE}" = "Xextended"; then
+ AC_CHECK_LIB([m],fabsl,[],[MATH_FABS_OK="no"])
+ AC_CHECK_LIB([m],powl,[],[MATH_POW_OK="no"])
+ AC_CHECK_LIB([m],sqrtl,[],[MATH_SQRT_OK="no"])
+# Check for (generic) double-precision math routines
+elif test "X${FLOAT_TYPE}" = "Xdouble"; then
+ AC_CHECK_LIB([m],fabs,[],[AC_MSG_ERROR([cannot find fabs function])])
+ AC_CHECK_LIB([m],pow,[],[AC_MSG_ERROR([cannot find pow function])])
+ AC_CHECK_LIB([m],sqrt,[],[AC_MSG_ERROR([cannot find sqrt function])])
+fi
+# If cannot find precision-specific implementations, then check for generic versions
+if test "X${MATH_FABS_OK}" = "Xno" || test "X${MATH_POW_OK}" = "Xno" || test "X${MATH_SQRT_OK}" = "Xno"; then
+ AC_CHECK_LIB([m],fabs,[],[AC_MSG_ERROR([cannot find fabs function])])
+ AC_CHECK_LIB([m],pow,[],[AC_MSG_ERROR([cannot find pow function])])
+ AC_CHECK_LIB([m],sqrt,[],[AC_MSG_ERROR([cannot find sqrt function])])
+ # If all generic math routines are available, then set SUNDIALS_USE_GENERIC_MATH flag
+ # for use by sundials_math.c file (preprocessor macros)
+ AC_DEFINE([SUNDIALS_USE_GENERIC_MATH],[1],[])
+ GENERIC_MATH_LIB="#define SUNDIALS_USE_GENERIC_MATH"
+# If found all precision-specific routines, then set SUNDIALS_USE_GENERIC_MATH only if
+# building SUNDIALS libraries with double-precision
+else
+ if test "X${FLOAT_TYPE}" = "Xdouble"; then
+ AC_DEFINE([SUNDIALS_USE_GENERIC_MATH],[1],[])
+ GENERIC_MATH_LIB="#define SUNDIALS_USE_GENERIC_MATH"
+ else
+ AC_DEFINE([SUNDIALS_USE_GENERIC_MATH],[0],[])
+ fi
+fi
+
+# Add math library to LIBS environment variable
+LIBS="${TEMP_MATH_LIB}"
+AC_MSG_CHECKING([for additional required C libraries])
+if test "X${LIBS}" = "X"; then
+ if test "X${SAVED_LIBS}" = "X"; then
+ LIBS=""
+ else
+ LIBS="${SAVED_LIBS}"
+ fi
+ AC_MSG_RESULT([none])
+else
+ AC_MSG_RESULT([${LIBS}])
+ if test "X${SAVED_LIBS}" = "X"; then
+ LIBS="${LIBS}"
+ else
+ LIBS="${LIBS} ${SAVED_LIBS}"
+ fi
+fi
+
+# Check sizeof(int) - used to modify Fortran examples
+AC_CHECK_SIZEOF(int)
+
+# Check sizeof(long int) - used to modify Fortran examples
+AC_CHECK_SIZEOF(long int)
+
+# Check sizeof(realtype), where realtype is either float, double
+# or long double - used to modify Fortran examples
+if test "X${FLOAT_TYPE}" = "Xsingle"; then
+ AC_CHECK_SIZEOF(float)
+elif test "X${FLOAT_TYPE}" = "Xdouble"; then
+ AC_CHECK_SIZEOF(double)
+elif test "X${FLOAT_TYPE}" = "Xextended"; then
+ AC_CHECK_SIZEOF(long double)
+fi
+
+# Defines EGREP and exports via AC_SUBST - used by FCMIX Makefile's
+AC_PROG_EGREP
+
+# Defines FGREP and exports via AC_SUBST - used by FCMIX Makefile's
+AC_PROG_FGREP
+
+# Check if CC is a C++ compiler
+# Note: If CC is a C++ compiler and MPI is enabled, then we will
+# check for "mpiCC" instead of "mpicc" if an MPI compiler was NOT specified
+SUNDIALS_CPLUSPLUS_CHECK([${CC}])
+
+]) dnl END SUNDIALS_SET_CC
+
+#------------------------------------------------------------------
+# CHECK IF COMPILER IS A C++ COMPILER
+#------------------------------------------------------------------
+
+AC_DEFUN([SUNDIALS_CPLUSPLUS_CHECK],
+[
+
+# Rename argument
+COMP_NAME="$1"
+
+# Update the language stack
+AC_LANG_PUSH([C])
+
+# Check if using a C++ compiler
+AC_MSG_CHECKING([if ${COMP_NAME} is a C++ compiler])
+AC_RUN_IFELSE(
+[AC_LANG_PROGRAM([[]],
+[[
+#ifdef __cplusplus
+ return(0);
+#else
+ return(1);
+#endif
+]])],
+[
+AC_MSG_RESULT([yes])
+# COMP_NAME is a C++ compiler
+USING_CPLUSPLUS_COMP="yes"
+],
+[
+AC_MSG_RESULT([no])
+# COMP_NAMPE is NOT a C++ compiler
+USING_CPLUSPLUS_COMP="no"
+])
+
+# Revert back to previous language
+AC_LANG_POP([C])
+
+]) dnl END SUNDIALS_CPLUSPLUS_CHECK
+
+
+
+
+#=================================================================#
+# #
+# #
+# F O R T R A N S U P P O R T #
+# #
+# #
+#==================================================================
+
+
+
+#------------------------------------------------------------------
+# FORTRAN SUPPORT
+#
+# Fortran support is required if FCMIX is enabled OR if LAPACK
+# is enabled. In either case, we need a working F77 compiler in
+# order to determine the Fortran name-mangling scheme.
+#
+# If we do need Fortran support, we first find and test a F77
+# compiler, determine the mangling scheme, then we find the
+# libraries required to link C and Fortran.
+#
+# Throughout this function we use the control variable F77_OK
+# which was initialized to "no".
+#------------------------------------------------------------------
+
+AC_DEFUN([SUNDIALS_F77_SUPPORT],
+[
+
+F77_OK="yes"
+
+# Look for a F77 compiler
+# If unsuccessful, disable all Fortran support
+
+AC_PROG_F77(f77 g77)
+
+if test "X${F77}" = "X"; then
+
+ F77_OK="no"
+ SUNDIALS_WARN_FLAG="yes"
+
+ echo ""
+ echo " Unable to find a working Fortran compiler"
+ echo ""
+ echo " Try using F77 to explicitly specify a C compiler"
+ echo ""
+ if test "X${FCMIX_ENABLED}" = "Xyes"; then
+ echo " Disabling compilation of Fortran-C interfaces..."
+ fi
+ if test "X${LAPACK_ENABLED}" = "Xyes"; then
+ echo " Disabling compilation of Blas/Lapack interfaces..."
+ fi
+ echo ""
+
+ FCMIX_ENABLED="no"
+ LAPACK_ENABLED="no"
+ F77_EXAMPLES_ENABLED="no"
+
+fi
+
+# Check Fortran compiler
+# If unsuccessful, disable all Fortran support
+
+if test "X${F77_OK}" = "Xyes"; then
+
+ SUNDIALS_F77_CHECK
+
+ if test "X${F77_OK}" = "Xno"; then
+
+ SUNDIALS_WARN_FLAG="yes"
+
+ echo ""
+ echo " Unable to compile test program using given Fortran compiler."
+ echo ""
+ if test "X${FCMIX_ENABLED}" = "Xyes"; then
+ echo " Disabling compilation of Fortran-C interfaces..."
+ fi
+ if test "X${LAPACK_ENABLED}" = "Xyes"; then
+ echo " Disabling compilation of Blas/Lapack interfaces..."
+ fi
+ echo ""
+
+ FCMIX_ENABLED="no"
+ LAPACK_ENABLED="no"
+ F77_EXAMPLES_ENABLED="no"
+
+ fi
+
+fi
+
+
+# Determine the Fortran name-mangling scheme
+# If successfull, provide variable description templates for config.hin
+# and config.h files required by autoheader utility
+# Otherwise, disable all Fortran support.
+
+if test "X${F77_OK}" = "Xyes"; then
+
+ SUNDIALS_F77_NAME_MANGLING
+
+ AH_TEMPLATE([SUNDIALS_F77_FUNC], [FCMIX: Define name-mangling macro for C identifiers])
+ AH_TEMPLATE([SUNDIALS_F77_FUNC_], [FCMIX: Define name-mangling macro for C identifiers with underscores])
+
+ if test "X${F77_OK}" = "Xno"; then
+
+ SUNDIALS_WARN_FLAG="yes"
+
+ echo ""
+ echo " Unable to determine Fortran name-mangling scheme."
+ echo ""
+ if test "X${FCMIX_ENABLED}" = "Xyes"; then
+ echo " Disabling compilation of Fortran-C interfaces..."
+ fi
+ if test "X${LAPACK_ENABLED}" = "Xyes"; then
+ echo " Disabling compilation of Blas/Lapack interfaces..."
+ fi
+ echo ""
+
+ F77_EXAMPLES_ENABLED="no"
+ FCMIX_ENABLED="no"
+ LAPACK_ENABLED="no"
+
+ fi
+
+fi
+
+
+# If LAPACK is enabled, determine the proper library linkage
+# If successful, set the libaries
+# Otherwise, disable all Blas/Lapack support.
+
+if test "X${LAPACK_ENABLED}" = "Xyes" && test "X${F77_OK}" = "Xyes"; then
+
+
+ SUNDIALS_F77_LAPACK_SET
+
+ if test "X${LAPACK_OK}" = "Xyes"; then
+
+ AC_MSG_CHECKING([for Blas/Lapack library linkage])
+ BLAS_LAPACK_LIBS="${LAPACK_LIBS} ${BLAS_LIBS} ${LIBS} ${FLIBS}"
+ AC_MSG_RESULT([${LAPACK_LIBS} ${BLAS_LIBS}])
+
+ else
+
+ SUNDIALS_WARN_FLAG="yes"
+ AC_MSG_CHECKING([for Blas/Lapack library linkage])
+ AC_MSG_RESULT("no")
+ echo ""
+ echo " Unable to determine Blas/Lapack library linkage."
+ echo ""
+ echo " Try using --with-blas and --with-lapack."
+ echo ""
+ echo " Disabling compilation of Blas/Lapack interfaces..."
+
+ LAPACK_ENABLED="no"
+
+ fi
+
+fi
+
+
+# Set the macro BLAS_LAPACK_MACRO for expansion in sundials_config.h
+
+AH_TEMPLATE([SUNDIALS_BLAS_LAPACK], [Availability of Blas/Lapack libraries])
+
+if test "X${LAPACK_ENABLED}" = "Xyes"; then
+ AC_DEFINE([SUNDIALS_BLAS_LAPACK],[1],[])
+ BLAS_LAPACK_MACRO="#define SUNDIALS_BLAS_LAPACK 1"
+else
+ AC_DEFINE([SUNDIALS_BLAS_LAPACK],[0],[])
+ BLAS_LAPACK_MACRO="#define SUNDIALS_BLAS_LAPACK 0"
+fi
+
+]) dnl SUNDIALS_F77_SUPPORT
+
+#------------------------------------------------------------------
+# CHECK FORTRAN COMPILER
+#
+# Test the Fortran compiler by attempting to compile and link a
+# simple Fortran program. If the test succeeds, set F77_OK=yes.
+# If the test fails, set F77_OK="no"
+#
+# Finally, check if we must use a Fortran compiler to link the
+# Fortran codes (default is to use CC).
+#------------------------------------------------------------------
+
+AC_DEFUN([SUNDIALS_F77_CHECK],
+[
+
+AC_LANG_PUSH([Fortran 77])
+
+# Add any additional FFLAGS
+AC_MSG_CHECKING([for extra Fortran compiler flags])
+AC_ARG_WITH(fflags,
+[AC_HELP_STRING([--with-fflags=ARG],[add extra Fortran compiler flags])],
+[
+AC_MSG_RESULT([${withval}])
+FFLAGS="${FFLAGS} ${withval}"
+],
+[
+AC_MSG_RESULT([none])
+])
+
+# Add any required linker flags to FLIBS
+# Note: if FLIBS is defined, it is left unchanged
+AC_F77_LIBRARY_LDFLAGS
+
+# Try to compile a simple Fortran program (no linking)
+AC_COMPILE_IFELSE(
+[AC_LANG_SOURCE(
+[[
+ SUBROUTINE SUNDIALS()
+ RETURN
+ END
+]])],
+[F77_OK="yes"],
+[F77_OK="no"])
+
+# If CC is a C++ compiler (decided in SUNDIALS_CPLUSPLUS_CHECK), we must use
+# it to link the Fortran examples. In this case, test if that is successful.
+# Otherwise, simply use F77 as the linker
+
+if test "X${F77_OK}" = "Xyes"; then
+ AC_MSG_CHECKING([which linker to use])
+ if test "X${USING_CPLUSPLUS_COMP}" = "Xyes"; then
+ SUNDIALS_F77_LNKR_CHECK
+ else
+ F77_LNKR="${F77}"
+ fi
+ AC_MSG_RESULT([${F77_LNKR}])
+fi
+
+# Reset language (remove 'Fortran 77' from stack)
+AC_LANG_POP([Fortran 77])
+
+]) dnl END SUNDIALS_SET_F77
+
+
+#------------------------------------------------------------------
+# F77 LINKER CHECK
+# Check if the C++ compiler CC can be used to link a Fortran program.
+#------------------------------------------------------------------
+
+AC_DEFUN([SUNDIALS_F77_LNKR_CHECK],
+[
+
+F77_LNKR_CHECK_OK="no"
+
+# Compile simple Fortran example, but do NOT link
+# Note: result stored as conftest.${ac_objext}
+AC_COMPILE_IFELSE(
+[AC_LANG_SOURCE(
+[[
+ PROGRAM SUNDIALS
+ WRITE(*,*)'TEST'
+ END
+]])],
+[
+
+# Temporarily reset LIBS environment variable to perform test
+SAVED_LIBS="${LIBS}"
+LIBS="${LIBS} ${FLIBS}"
+
+# Switch working language to C for next test
+AC_LANG_PUSH([C])
+
+# Check if CC can link Fortran example
+# Note: AC_LINKONLY_IFELSE is a custom macro (modifications made to
+# general.m4 and c.m4) (see config/cust_general.m4 and config/mod_c.m4)
+AC_LINKONLY_IFELSE([],[F77_LNKR_CHECK_OK="yes"],[F77_LNKR_CHECK_OK="no"])
+
+# Revert back to previous language (Fortran 77)
+AC_LANG_POP([C])
+
+# Set LIBS environment variable back to original value
+LIBS="${SAVED_LIBS}"
+
+])
+
+# If either the compilation or the linking failed, we should
+# disable building the Fortran examples
+# For now, use F77 as the linker...
+if test "X${F77_LNKR_CHECK_OK}" = "Xyes"; then
+ F77_LNKR="${CC}"
+else
+ F77_LNKR="${F77}"
+fi
+
+]) dnl SUNDIALS_F77_LNKR_CHECK
+
+
+#------------------------------------------------------------------
+# DETERMINE FORTRAN NAME-MANGLING SCHEME
+#
+# Compiling a simple Fortran example and link it using a C compiler.
+# Interpret results to infer name-mangling scheme.
+#------------------------------------------------------------------
+
+
+AC_DEFUN([SUNDIALS_F77_NAME_MANGLING],
+[
+
+AC_LANG_PUSH([Fortran 77])
+
+# (1) Compile a dummy Fortran subroutine named SUNDIALS
+
+FNAME_STATUS="none"
+
+AC_COMPILE_IFELSE(
+ [AC_LANG_SOURCE(
+ [[
+ SUBROUTINE SUNDIALS()
+ RETURN
+ END
+ ]])],
+ [
+
+ mv conftest.${ac_objext} f77_wrapper_check.${ac_objext}
+
+ # Temporarily reset LIBS environment variable to perform test
+ SAVED_LIBS="${LIBS}"
+ LIBS="f77_wrapper_check.${ac_objext} ${LIBS} ${FLIBS}"
+
+ AC_LANG_PUSH([C])
+
+ for i in "sundials" "SUNDIALS"
+ do
+ for j in "" "_" "__"
+ do
+ F77_MANGLED_NAME="${i}${j}"
+ AC_LINK_IFELSE([AC_LANG_CALL([],[${F77_MANGLED_NAME}])],[FNAME_STATUS="set" ; break 2])
+ done
+ done
+
+ AC_LANG_POP([C])
+
+ # If test succeeded, then set the F77_MANGLE_MACRO1 macro
+
+ if test "X${FNAME_STATUS}" = "Xset"; then
+
+ if test "X${i}" = "Xsundials"; then
+
+ FNAME_MSG="lower case "
+
+ if test "X${j}" = "X"; then
+ FNAME_MSG="${FNAME_MSG} + no underscore"
+ AC_DEFINE([SUNDIALS_F77_FUNC(name,NAME)],[name],[])
+ F77_MANGLE_MACRO1="#define SUNDIALS_F77_FUNC(name,NAME) name"
+ dgemm="dgemm"
+ dgetrf="dgetrf"
+ elif test "X${j}" = "X_"; then
+ FNAME_MSG="${FNAME_MSG} + one underscore"
+ AC_DEFINE([SUNDIALS_F77_FUNC(name,NAME)],[name ## _],[])
+ F77_MANGLE_MACRO1="#define SUNDIALS_F77_FUNC(name,NAME) name ## _"
+ dgemm="dgemm_"
+ dgetrf="dgetrf_"
+ else
+ FNAME_MSG="${FNAME_MSG} + two underscores"
+ AC_DEFINE([SUNDIALS_F77_FUNC(name,NAME)],[name ## __],[])
+ F77_MANGLE_MACRO1="#define SUNDIALS_F77_FUNC(name,NAME) name ## __"
+ dgemm="dgemm__"
+ dgetrf="dgetrf__"
+ fi
+
+ else
+
+ FNAME_MSG="upper case "
+
+ if test "X${j}" = "X"; then
+ FNAME_MSG="${FNAME_MSG} + no underscore"
+ AC_DEFINE([SUNDIALS_F77_FUNC(name,NAME)],[name],[])
+ F77_MANGLE_MACRO1="#define SUNDIALS_F77_FUNC(name,NAME) NAME"
+ dgemm="DGEMM"
+ dgetrf="DGETRF"
+ elif test "X${j}" = "X_"; then
+ FNAME_MSG="${FNAME_MSG} + one underscore"
+ AC_DEFINE([SUNDIALS_F77_FUNC(name,NAME)],[name ## _],[])
+ F77_MANGLE_MACRO1="#define SUNDIALS_F77_FUNC(name,NAME) NAME ## _"
+ dgemm="DGEMM_"
+ dgetrf="DGETRF_"
+ else
+ FNAME_MSG="${FNAME_MSG} + two underscores"
+ AC_DEFINE([SUNDIALS_F77_FUNC(name,NAME)],[name ## __],[])
+ F77_MANGLE_MACRO1="#define SUNDIALS_F77_FUNC(name,NAME) NAME ## __"
+ dgemm="DGEMM__"
+ dgetrf="DGETRF__"
+ fi
+
+ fi
+
+ AC_MSG_CHECKING([for Fortran name-mangling scheme of C identifiers])
+ AC_MSG_RESULT([${FNAME_MSG}])
+
+ else
+
+ F77_OK="no"
+
+ fi
+
+ # Set LIBS environment variable back to original value
+ LIBS="${SAVED_LIBS}"
+
+ ])
+
+# Remove temporary file
+rm -f f77_wrapper_check.${ac_objext}
+
+
+# (2) Compile a dummy Fortran subroutine named SUN_DIALS
+
+FNAME_STATUS="none"
+
+AC_COMPILE_IFELSE(
+ [AC_LANG_SOURCE(
+ [[
+ SUBROUTINE SUN_DIALS()
+ RETURN
+ END
+ ]])],
+ [
+
+ mv conftest.${ac_objext} f77_wrapper_check.${ac_objext}
+
+ # Temporarily reset LIBS environment variable to perform test
+ SAVED_LIBS="${LIBS}"
+ LIBS="f77_wrapper_check.${ac_objext} ${LIBS} ${FLIBS}"
+
+ AC_LANG_PUSH([C])
+
+ for i in "sun_dials" "SUN_DIALS"
+ do
+ for j in "" "_" "__"
+ do
+ F77_MANGLED_NAME="${i}${j}"
+ AC_LINK_IFELSE([AC_LANG_CALL([],[${F77_MANGLED_NAME}])],[FNAME_STATUS="set" ; break 2])
+ done
+ done
+
+ AC_LANG_POP([C])
+
+ # If test succeeded, then set the F77_MANGLE_MACRO2 macro
+
+ if test "X${FNAME_STATUS}" = "Xset"; then
+
+ if test "X${i}" = "Xsun_dials"; then
+
+ FNAME_MSG="lower case "
+
+ if test "X${j}" = "X"; then
+ FNAME_MSG="${FNAME_MSG} + no underscore"
+ AC_DEFINE([SUNDIALS_F77_FUNC_(name,NAME)],[name],[])
+ F77_MANGLE_MACRO2="#define SUNDIALS_F77_FUNC_(name,NAME) name"
+ elif test "X${j}" = "X_"; then
+ FNAME_MSG="${FNAME_MSG} + one underscore"
+ AC_DEFINE([SUNDIALS_F77_FUNC_(name,NAME)],[name ## _],[])
+ F77_MANGLE_MACRO2="#define SUNDIALS_F77_FUNC_(name,NAME) name ## _"
+ else
+ FNAME_MSG="${FNAME_MSG} + two underscores"
+ AC_DEFINE([SUNDIALS_F77_FUNC_(name,NAME)],[name ## __],[])
+ F77_MANGLE_MACRO2="#define SUNDIALS_F77_FUNC_(name,NAME) name ## __"
+ fi
+
+ else
+
+ FNAME_MSG="upper case "
+
+ if test "X${j}" = "X"; then
+ FNAME_MSG="${FNAME_MSG} + no underscore"
+ AC_DEFINE([SUNDIALS_F77_FUNC_(name,NAME)],[name],[])
+ F77_MANGLE_MACRO2="#define SUNDIALS_F77_FUNC_(name,NAME) NAME"
+ elif test "X${j}" = "X_"; then
+ FNAME_MSG="${FNAME_MSG} + one underscore"
+ AC_DEFINE([SUNDIALS_F77_FUNC_(name,NAME)],[name ## _],[])
+ F77_MANGLE_MACRO2="#define SUNDIALS_F77_FUNC_(name,NAME) NAME ## _"
+ else
+ FNAME_MSG="${FNAME_MSG} + two underscores"
+ AC_DEFINE([SUNDIALS_F77_FUNC_(name,NAME)],[name ## __],[])
+ F77_MANGLE_MACRO2="#define SUNDIALS_F77_FUNC_(name,NAME) NAME ## __"
+ fi
+
+ fi
+
+ AC_MSG_CHECKING([for Fortran name-mangling scheme of C identifiers with underscores])
+ AC_MSG_RESULT([${FNAME_MSG}])
+
+ else
+
+ F77_OK="no"
+
+ fi
+
+ # Set LIBS environment variable back to original value
+ LIBS="${SAVED_LIBS}"
+
+ ])
+
+# Remove temporary file
+rm -f f77_wrapper_check.${ac_objext}
+
+
+AC_LANG_POP([Fortran 77])
+
+]) dnl END SUNDIALS_SET_FNAME
+
+
+#------------------------------------------------------------------
+# DETERMINE BLAS/LAPACK LIBRARY LINKAGE SCHEME
+#
+# If successful, this function sets LAPACK_OK="yes".
+# Otherwise, it sets LAPACK_OK="no"
+#------------------------------------------------------------------
+
+AC_DEFUN([SUNDIALS_F77_LAPACK_SET],
+[
+
+# Check if the user specifies Blas libraries
+AC_ARG_WITH(blas,
+[AC_HELP_STRING([--with-blas=ARG],[specify Blas library])],
+[
+ case $withval in
+ -* | */* | *.a | *.so | *.so.* | *.o)
+ BLAS_LIBS="$withval"
+ ;;
+ *)
+ BLAS_LIBS="-l$withval"
+ ;;
+ esac
+])
+
+# Check if the user specifies Lapack libraries
+AC_ARG_WITH(lapack,
+[AC_HELP_STRING([--with-lapack=ARG],[specify Lapack library])],
+[
+ case $withval in
+ -* | */* | *.a | *.so | *.so.* | *.o)
+ LAPACK_LIBS="$withval"
+ ;;
+ *)
+ LAPACK_LIBS="-l$withval"
+ ;;
+ esac
+])
+
+acx_blas_ok=no
+acx_lapack_ok=no
+
+# BLAS_LIBS
+# ---------
+
+acx_blas_save_LIBS="$LIBS"
+LIBS="$LIBS $FLIBS"
+
+# First, check BLAS_LIBS environment variable
+if test "x$BLAS_LIBS" != x; then
+ save_LIBS="$LIBS"
+ LIBS="$BLAS_LIBS $LIBS"
+ AC_MSG_CHECKING([aha for $dgemm in $BLAS_LIBS])
+ AC_TRY_LINK_FUNC($dgemm, [acx_blas_ok=yes], [BLAS_LIBS=""])
+ AC_MSG_RESULT($acx_blas_ok)
+ LIBS="$save_LIBS"
+fi
+
+# BLAS linked to by default? (happens on some supercomputers)
+if test $acx_blas_ok = no; then
+ save_LIBS="$LIBS"; LIBS="$LIBS"
+ AC_CHECK_FUNC($dgemm, [acx_blas_ok=yes])
+ LIBS="$save_LIBS"
+fi
+
+# BLAS in Alpha CXML library?
+if test $acx_blas_ok = no; then
+ AC_CHECK_LIB(cxml, $dgemm, [acx_blas_ok=yes;BLAS_LIBS="-lcxml"])
+fi
+
+# BLAS in Alpha DXML library? (now called CXML, see above)
+if test $acx_blas_ok = no; then
+ AC_CHECK_LIB(dxml, $dgemm, [acx_blas_ok=yes;BLAS_LIBS="-ldxml"])
+fi
+
+# BLAS in Sun Performance library?
+if test $acx_blas_ok = no; then
+ if test "x$GCC" != xyes; then # only works with Sun CC
+ AC_CHECK_LIB(sunmath, acosp,
+ [AC_CHECK_LIB(sunperf, $dgemm,
+ [BLAS_LIBS="-xlic_lib=sunperf -lsunmath"
+ acx_blas_ok=yes],[],[-lsunmath])])
+ fi
+fi
+
+# BLAS in SCSL library? (SGI/Cray Scientific Library)
+if test $acx_blas_ok = no; then
+ AC_CHECK_LIB(scs, $dgemm, [acx_blas_ok=yes; BLAS_LIBS="-lscs"])
+fi
+
+# BLAS in SGIMATH library?
+if test $acx_blas_ok = no; then
+ AC_CHECK_LIB(complib.sgimath, $dgemm,
+ [acx_blas_ok=yes; BLAS_LIBS="-lcomplib.sgimath"])
+fi
+
+# BLAS in IBM ESSL library? (requires generic BLAS lib, too)
+if test $acx_blas_ok = no; then
+ AC_CHECK_LIB(blas, $dgemm,
+ [AC_CHECK_LIB(essl, $dgemm,
+ [acx_blas_ok=yes; BLAS_LIBS="-lessl -lblas"],
+ [], [-lblas $FLIBS])])
+fi
+
+# Generic BLAS library?
+if test $acx_blas_ok = no; then
+ AC_CHECK_LIB(blas, $dgemm, [acx_blas_ok=yes; BLAS_LIBS="-lblas"])
+fi
+
+LIBS="$acx_blas_save_LIBS"
+
+# LAPACK
+# ------
+
+# If we didn't find a Blas implementation, disable tests for Lapack
+if test $acx_blas_ok = no; then
+ acx_lapack_ok=disabled
+fi
+
+# Check LAPACK_LIBS environment variable
+if test $acx_lapack_ok = no; then
+if test "x$LAPACK_LIBS" != x; then
+ save_LIBS="$LIBS";
+ LIBS="$LAPACK_LIBS $BLAS_LIBS $LIBS $FLIBS"
+ AC_MSG_CHECKING([for $dgetrf in $LAPACK_LIBS])
+ AC_TRY_LINK_FUNC($dgetrf, [acx_lapack_ok=yes], [LAPACK_LIBS=""])
+ AC_MSG_RESULT($acx_lapack_ok)
+ LIBS="$save_LIBS"
+ if test acx_lapack_ok = no; then
+ LAPACK_LIBS=""
+ fi
+fi
+fi
+
+# LAPACK linked to by default? (is sometimes included in BLAS lib)
+if test $acx_lapack_ok = no; then
+ save_LIBS="$LIBS"
+ LIBS="$LIBS $BLAS_LIBS $FLIBS"
+ AC_CHECK_FUNC($dgetrf, [acx_lapack_ok=yes])
+ LIBS="$save_LIBS"
+fi
+
+# Generic LAPACK library?
+for lapack in lapack lapack_rs6k; do
+ if test $acx_lapack_ok = no; then
+ save_LIBS="$LIBS"
+ LIBS="$BLAS_LIBS $LIBS"
+ AC_CHECK_LIB($lapack, $dgetrf,
+ [acx_lapack_ok=yes; LAPACK_LIBS="-l$lapack"], [], [$FLIBS])
+ LIBS="$save_LIBS"
+ fi
+done
+
+# If we have both libraries, set LAPACK_OK to yes
+# -----------------------------------------------------
+
+if test $acx_blas_ok = yes && test $acx_lapack_ok = yes; then
+ LAPACK_OK="yes"
+else
+ LAPACK_OK="no"
+fi
+
+]) dnl SUNDIALS_F77_LAPACK_SET
+
+
+
+
+
+#=================================================================#
+# #
+# #
+# P A R A L L E L S U P P O R T #
+# #
+# #
+#==================================================================
+
+
+#------------------------------------------------------------------
+# CHECK MPI-C COMPILER
+#------------------------------------------------------------------
+
+AC_DEFUN([SUNDIALS_SET_MPICC],
+[
+
+AC_ARG_WITH([],[ ],[])
+
+# MPI root directory
+AC_ARG_WITH(mpi-root,
+[AC_HELP_STRING([--with-mpi-root=MPIROOT],[use MPI root directory])],
+[
+MPI_ROOT_DIR="${withval}"
+],
+[
+MPI_ROOT_DIR=""
+])
+
+# MPI include directory
+AC_ARG_WITH(mpi-incdir,
+[AC_HELP_STRING([--with-mpi-incdir=DIR],[MPI include directory @<:@MPIROOT/include@:>@])],
+[
+MPI_INC_DIR="${withval}"
+],
+[
+MPI_INC_DIR=""
+])
+
+# MPI library directory
+AC_ARG_WITH(mpi-libdir,
+[AC_HELP_STRING([--with-mpi-libdir=DIR],[MPI library directory @<:@MPIROOT/lib@:>@])],
+[
+MPI_LIB_DIR="${withval}"
+],
+[
+MPI_LIB_DIR=""
+])
+
+# MPI libraries
+AC_ARG_WITH(mpi-libs,
+[AC_HELP_STRING([--with-mpi-libs=ARG],[MPI libraries])],
+[
+MPI_LIBS="${withval}"
+],
+[
+MPI_LIBS=""
+])
+
+# MPI flags
+AC_ARG_WITH(mpi-flags,
+[AC_HELP_STRING([--with-mpi-flags=ARG],[MPI-specific flags])],
+[
+MPI_FLAGS="${withval}"
+MPI_FLAGS_OK="yes"
+],
+[
+MPI_FLAGS=""
+MPI_FLAGS_OK="no"
+])
+
+# MPI-C compiler
+MPICC_COMP_GIVEN="yes"
+AC_MSG_CHECKING([if using MPI-C script])
+AC_ARG_WITH(mpicc,
+[AC_HELP_STRING([--with-mpicc[[[[=ARG]]]]],[specify MPI-C compiler to use @<:@mpicc@:>@])],
+[
+if test "X${withval}" = "Xno"; then
+ USE_MPICC_SCRIPT="no"
+else
+ USE_MPICC_SCRIPT="yes"
+ MPICC_COMP="${withval}"
+fi
+],
+[
+ USE_MPICC_SCRIPT="yes"
+ MPICC_COMP="mpicc"
+ MPICC_COMP_GIVEN="no"
+])
+AC_MSG_RESULT([${USE_MPICC_SCRIPT}])
+
+# If CC is a C++ compiler, then we certainly do NOT want to use an MPI-C script
+# Note: USING_CPLUSPLUS_COMP was defined by a call to SUNDIALS_CPLUSPLUS_CHECK
+# in SUNDIALS_SET_CC
+# Note: If the user specified an MPI-C script, then we will NOT do anything for now
+if test "X${MPICC_COMP_GIVEN}" = "Xno" && test "X${USING_CPLUSPLUS_COMP}" = "Xyes"; then
+ MPICC_COMP="mpiCC"
+fi
+
+# Check MPI-C compiler (either MPI compiler script or regular C compiler)
+if test "X${USE_MPICC_SCRIPT}" = "Xyes"; then
+ SUNDIALS_CHECK_MPICC
+else
+ MPICC_COMP="${CC}"
+ MPICC="${CC}"
+ SUNDIALS_CC_WITH_MPI_CHECK
+fi
+
+]) dnl END SUNDIALS_SET_MPICC
+
+#------------------------------------------------------------------
+# TEST MPI-C COMPILER
+#------------------------------------------------------------------
+
+AC_DEFUN([SUNDIALS_CHECK_MPICC],
+[
+
+# Test MPI-C compiler (meaning test MPICC_COMP)
+# Check if MPI-C compiler can be found
+
+AC_MSG_CHECKING([if absolute path to ${MPICC_COMP} was given])
+
+# CASE 1: MPICC_COMP was found (cannot check if executable because the
+# "-x" flag is NOT portable)
+if test -f ${MPICC_COMP} ; then
+
+ AC_MSG_RESULT([yes])
+ MPICC_COMP_EXISTS="yes"
+ # Determine MPI_INC_DIR and MPI_LIB_DIR for use by Makefile
+ MPI_BASE_DIR=`AS_DIRNAME(["${MPICC_COMP}"])`
+ TMP_MPI_INC_DIR="${MPI_BASE_DIR}/../include"
+ TMP_MPI_LIB_DIR="${MPI_BASE_DIR}/../lib"
+
+# CASE 2: MPICC_COMP could NOT be found and MPI_ROOT_DIR was NOT specified,
+# so search in PATH
+else
+
+ AC_MSG_RESULT([no])
+
+ if test "X${MPI_ROOT_DIR}" = "X"; then
+ # Try to find location of executable (perhaps directory was entered
+ # incorrectly)
+ TEMP_MPICC_COMP=`basename "${MPICC_COMP}"`
+ AC_PATH_PROG([MPICC_COMP],[${TEMP_MPICC_COMP}],[none])
+ # Cannot find executable in PATH
+ if test "X${MPICC_COMP}" = "Xnone"; then
+ MPICC_COMP_EXISTS="no"
+ MPICC_COMP=""
+ # Found executable and set MPICC_COMP to absolute pathname
+ else
+ MPICC_COMP_EXISTS="yes"
+ MPI_BASE_DIR=`AS_DIRNAME(["${MPICC_COMP}"])`
+ TMP_MPI_INC_DIR="${MPI_BASE_DIR}/../include"
+ TMP_MPI_LIB_DIR="${MPI_BASE_DIR}/../lib"
+ fi
+
+ # CASE 3: MPICC_COMP could NOT be found, but MPI_ROOT_DIR was specified
+ else
+
+ AC_MSG_CHECKING([if ${MPICC_COMP} exists in ${MPI_ROOT_DIR}/bin])
+ # MPICC_COMP should really only contain an executable name
+ # Found location of MPICC_COMP
+ if test -f ${MPI_ROOT_DIR}/bin/${MPICC_COMP} ; then
+ AC_MSG_RESULT([yes])
+ MPICC_COMP_EXISTS="yes"
+ MPICC_COMP="${MPI_ROOT_DIR}/bin/${MPICC_COMP}"
+ TMP_MPI_INC_DIR="${MPI_ROOT_DIR}/include"
+ TMP_MPI_LIB_DIR="${MPI_ROOT_DIR}/lib"
+ # Could NOT find MPICC_COMP anywhere
+ else
+ AC_MSG_RESULT([no])
+ MPICC_COMP_EXISTS="no"
+ MPICC_COMP=""
+ fi
+
+ fi
+
+fi
+
+# If MPICC_COMP exists, set MPICC and (conditionally) set MPI_INC_DIR
+# and MPI_LIB_DIR so that we do not end up with empty -I options.
+# Otherwise, issue warning message
+if test "X${MPICC_COMP_EXISTS}" = "Xyes"; then
+
+ MPICC="${MPICC_COMP}"
+ MPI_C_COMP_OK="yes"
+
+ # If MPI_INC_DIR is empty, set it to TMP_MPI_INC_DIR
+ if test "X${MPI_INC_DIR}" = "X"; then
+ MPI_INC_DIR="$TMP_MPI_INC_DIR"
+ fi
+
+ # If MPI_LIB_DIR is empty, set it to TMP_MPI_LIB_DIR
+ if test "X${MPI_LIB_DIR}" = "X"; then
+ MPI_LIB_DIR="$TMP_MPI_LIB_DIR"
+ fi
+
+else
+
+ AC_MSG_WARN([cannot find MPI-C compiler])
+ echo ""
+ echo " Unable to find a functional MPI-C compiler."
+ echo ""
+ echo " Try using --with-mpicc to specify a MPI-C compiler script,"
+ echo " --with-mpi-incdir, --with-mpi-libdir and --with-mpi-libs"
+ echo " to specify the locations of all relevant MPI files, or"
+ echo " --with-mpi-root to specify the base installation directory"
+ echo " of the MPI implementation to be used."
+ echo ""
+ echo " Disabling the parallel NVECTOR module and all parallel examples..."
+ echo ""
+ MPICC=""
+ MPI_C_COMP_OK="no"
+ SUNDIALS_WARN_FLAG="yes"
+
+fi
+
+]) dnl END SUNDIALS_CHECK_MPICC
+
+#------------------------------------------------------------------
+# TEST C COMPILER WITH MPI
+#------------------------------------------------------------------
+
+AC_DEFUN([SUNDIALS_CC_WITH_MPI_CHECK],
+[
+
+# Test if we can compile MPI programs using the CC compiler
+# and current MPI settings
+
+AC_MSG_NOTICE([Testing CC with MPI settings])
+
+# Save copies of CPPFLAGS, LDFLAGS and LIBS (preserve information)
+# Temporarily overwritten so we can test MPI implementation
+SAVED_CPPFLAGS="${CPPFLAGS}"
+SAVED_LDFLAGS="${LDFLAGS}"
+SAVED_LIBS="${LIBS}"
+
+# Determine location of MPI header files (find MPI include directory)
+MPI_EXISTS="yes"
+
+AC_MSG_CHECKING([for location of MPI implementation])
+
+# If MPI include directory was NOT explicitly specified, check if MPI root
+# directory was given by user
+if test "X${MPI_INC_DIR}" = "X"; then
+ # If MPI root directory was NOT given so issue a warning message
+ if test "X${MPI_ROOT_DIR}" = "X"; then
+ AC_MSG_RESULT([not found])
+ MPI_EXISTS="no"
+ AC_MSG_WARN([cannot find MPI implementation files])
+ echo ""
+ echo " Unable to find MPI implementation files."
+ echo ""
+ echo " Try using --with-mpicc to specify a MPI-C compiler script,"
+ echo " --with-mpi-incdir, --with-mpi-libdir and --with-mpi-libs"
+ echo " to specify the locations of all relevant MPI files, or"
+ echo " --with-mpi-root to specify the base installation directory"
+ echo " of the MPI implementation to be used."
+ echo ""
+ echo " Disabling the parallel NVECTOR module and all parallel examples..."
+ echo ""
+ SUNDIALS_WARN_FLAG="yes"
+ # MPI root directory was given so set MPI_INC_DIR accordingly
+ # Update CPPFLAGS
+ else
+ MPI_INC_DIR="${MPI_ROOT_DIR}/include"
+ AC_MSG_RESULT([${MPI_INC_DIR}])
+ if test "X${CPPFLAGS}" = "X"; then
+ CPPFLAGS="-I${MPI_INC_DIR}"
+ else
+ CPPFLAGS="${CPPFLAGS} -I${MPI_INC_DIR}"
+ fi
+ # Add MPI_FLAGS if non-empty
+ if test "X${MPI_FLAGS}" = "X"; then
+ CPPFLAGS="${CPPFLAGS}"
+ else
+ CPPFLAGS="${CPPFLAGS} ${MPI_FLAGS}"
+ fi
+ fi
+# MPI include directory was specified so update CPPFLAGS
+else
+ AC_MSG_RESULT([${MPI_INC_DIR}])
+ if test "X${CPPFLAGS}" = "X"; then
+ CPPFLAGS="-I${MPI_INC_DIR}"
+ else
+ CPPFLAGS="${CPPFLAGS} -I${MPI_INC_DIR}"
+ fi
+ # Add MPI_FLAGS if non-empty
+ if test "X${MPI_FLAGS}" = "X"; then
+ CPPFLAGS="${CPPFLAGS}"
+ else
+ CPPFLAGS="${CPPFLAGS} ${MPI_FLAGS}"
+ fi
+fi
+
+# Only continue if found an MPI implementation
+if test "X${MPI_EXISTS}" = "Xyes"; then
+
+ AC_MSG_CHECKING([for location of MPI libraries])
+
+ # Determine location of MPI libraries
+ # MPI library directory was NOT specified by user so set based upon MPI_ROOT_DIR
+ # Update LDFLAGS
+ if test "X${MPI_LIB_DIR}" = "X"; then
+ MPI_LIB_DIR="${MPI_ROOT_DIR}/lib"
+ AC_MSG_RESULT([${MPI_LIB_DIR}])
+ if test "X${LDFLAGS}" = "X"; then
+ LDFLAGS="-L${MPI_LIB_DIR}"
+ else
+ LDFLAGS="${LDFLAGS} -L${MPI_LIB_DIR}"
+ fi
+ # MPI library directory was specified so update LDFLAGS
+ else
+ AC_MSG_RESULT([${MPI_LIB_DIR}])
+ if test "X${LDFLAGS}" = "X"; then
+ LDFLAGS="-L${MPI_LIB_DIR}"
+ else
+ LDFLAGS="${LDFLAGS} -L${MPI_LIB_DIR}"
+ fi
+ fi
+
+ # Check if user specified which MPI libraries must be included
+ # If no libraries are given, then issue a warning message
+ AC_MSG_CHECKING([for MPI libraries])
+ if test "X${MPI_LIBS}" = "X"; then
+ AC_MSG_RESULT([none])
+ AC_MSG_WARN([no MPI libraries were given])
+ echo ""
+ echo " Unable to compile MPI program using C compiler because"
+ echo " MPI libraries were not specified."
+ echo ""
+ echo " Try using --with-mpi-libdir and --with-mpi-libs to"
+ echo " specify the location and names of the MPI libraries."
+ echo ""
+ echo " Disabling the parallel NVECTOR module and all parallel examples..."
+ echo ""
+ MPI_C_COMP_OK="no"
+ SUNDIALS_WARN_FLAG="yes"
+ # MPI libraries were specified so update LIBS
+ else
+ AC_MSG_RESULT([${MPI_LIBS}])
+ if test "X${LIBS}" = "X"; then
+ LIBS="${MPI_LIBS}"
+ else
+ LIBS="${LIBS} ${MPI_LIBS}"
+ fi
+ # Set the MPI_C_COMP_OK variable to NULL so we can conditionally execute
+ # the next test
+ MPI_C_COMP_OK=""
+ fi
+
+ if test "X${MPI_C_COMP_OK}" = "X"; then
+ AC_MSG_CHECKING([if C compiler can compile MPI programs])
+ AC_LINK_IFELSE(
+ [AC_LANG_PROGRAM([[#include "mpi.h"]],[[int c; char **v; MPI_Init(&c,&v);]])],
+ [AC_MSG_RESULT([yes])
+ MPI_C_COMP_OK="yes"],
+ [AC_MSG_RESULT([no])
+ AC_MSG_WARN([C compiler cannot compile MPI programs])
+ echo ""
+ echo " Unable to compile MPI program using C compiler."
+ echo ""
+ echo " Try using --with-mpicc to specify a MPI-C compiler script,"
+ echo " --with-mpi-incdir, --with-mpi-libdir and --with-mpi-libs"
+ echo " to specify the locations of all relevant MPI files, or"
+ echo " --with-mpi-root to specify the base installation directory"
+ echo " of the MPI implementation to be used."
+ echo ""
+ echo " Disabling the parallel NVECTOR module and all parallel examples..."
+ echo ""
+ MPI_C_COMP_OK="no"
+ SUNDIALS_WARN_FLAG="yes"])
+ fi
+else
+ MPI_C_COMP_OK="no"
+fi
+
+# Restore CPPFLAGS, LDFLAGS and LIBS
+CPPFLAGS="${SAVED_CPPFLAGS}"
+LDFLAGS="${SAVED_LDFLAGS}"
+LIBS="${SAVED_LIBS}"
+
+]) dnl END SUNDIALS_CC_WITH_MPI_CHECK
+
+#------------------------------------------------------------------
+# SET MPI-F77 COMPILER
+#
+# These tests are done only if all of the following are still true:
+# - MPI is enabled
+# - F77 examples are enabled
+# - F77 works
+#------------------------------------------------------------------
+
+AC_DEFUN([SUNDIALS_SET_MPIF77],
+[
+
+AC_MSG_CHECKING([if using MPI-Fortran script])
+AC_ARG_WITH(mpif77,
+[AC_HELP_STRING([--with-mpif77[[[[=ARG]]]]],[specify MPI-Fortran compiler to use @<:@mpif77@:>@])],
+[
+if test "X${withval}" = "Xno"; then
+ USE_MPIF77_SCRIPT="no"
+else
+ USE_MPIF77_SCRIPT="yes"
+ MPIF77_COMP="${withval}"
+fi
+],
+[
+USE_MPIF77_SCRIPT="yes"
+MPIF77_COMP="mpif77"
+])
+AC_MSG_RESULT([${USE_MPIF77_SCRIPT}])
+
+# Check MPI-Fortran compiler (either MPI compiler script or regular Fortran compiler)
+if test "X${USE_MPIF77_SCRIPT}" = "Xyes"; then
+ SUNDIALS_CHECK_MPIF77
+else
+ MPIF77_COMP="${F77}"
+ MPIF77="${F77}"
+ SUNDIALS_F77_WITH_MPI_CHECK
+fi
+
+]) dnl END SUNDIALS_SET_MPIF77
+
+#------------------------------------------------------------------
+# TEST MPIF77 COMPILER SCRIPT
+#------------------------------------------------------------------
+
+AC_DEFUN([SUNDIALS_CHECK_MPIF77],
+[
+
+# Test the MPI-Fortran compiler (meaning test MPIF77_COMP)
+# Check if MPI-Fortran compiler can be found
+
+AC_MSG_CHECKING([if absolute path to ${MPIF77_COMP} was given])
+
+# CASE 1: MPIF77_COMP was found (cannot check if executable because the
+# "-x" flag is NOT portable)
+if test -f ${MPIF77_COMP} ; then
+
+ AC_MSG_RESULT([yes])
+ MPIF77_COMP_EXISTS="yes"
+ # Determine MPI_INC_DIR and MPI_LIB_DIR for use by Makefile
+ MPI_BASE_DIR=`AS_DIRNAME(["${MPIF77_COMP}"])`
+
+# CASE 2: MPIF77_COMP could NOT be found and MPI_ROOT_DIR was NOT specified,
+# so search in PATH
+else
+
+ AC_MSG_RESULT([no])
+
+ if test "X${MPI_ROOT_DIR}" = "X"; then
+
+ # Try to find location of executable (perhaps directory was entered incorrectly)
+ TEMP_MPIF77_COMP=`basename "${MPIF77_COMP}"`
+ AC_PATH_PROG([MPIF77_COMP],[${TEMP_MPIF77_COMP}],[none])
+ # Cannot find executable in PATH
+ if test "X${MPIF77_COMP}" = "Xnone"; then
+ MPIF77_COMP_EXISTS="no"
+ MPIF77_COMP=""
+ # Found executable and set MPIF77_COMP to absolute pathname
+ else
+ MPIF77_COMP_EXISTS="yes"
+ MPI_BASE_DIR=`AS_DIRNAME(["${MPIF77_COMP}"])`
+ fi
+
+ # CASE 3: MPIF77_COMP could NOT be found, but MPI_ROOT_DIR was specified
+ else
+
+ AC_MSG_CHECKING([if ${MPIF77_COMP} exists in ${MPI_ROOT_DIR}/bin])
+ # MPIF77_COMP should really only contain an executable name
+ # Found location of MPIF77_COMP
+ if test -f ${MPI_ROOT_DIR}/bin/${MPIF77_COMP} ; then
+ AC_MSG_RESULT([yes])
+ MPIF77_COMP_EXISTS="yes"
+ MPIF77_COMP="${MPI_ROOT_DIR}/bin/${MPIF77_COMP}"
+ # Could NOT find MPIF77_COMP anywhere
+ else
+ AC_MSG_RESULT([no])
+ MPIF77_COMP_EXISTS="no"
+ MPIF77_COMP=""
+ fi
+
+ fi
+
+fi
+
+# Issue warning message if MPIF77_COMP does NOT exist, else set MPIF77
+if test "X${MPIF77_COMP_EXISTS}" = "Xyes"; then
+
+ MPIF77="${MPIF77_COMP}"
+ MPI_F77_COMP_OK="yes"
+
+ # Note that we do not have to worry about empty MPI_INC_DIR and MPI_LIB_DIR
+ # here as they were set in SUNDIALS_CHECK_MPICC
+
+ # Check if we must use the MPI-Fortran compiler script (MPIF77) to link
+ # the Fortran examples (default is to use MPICC)
+ SUNDIALS_MPIF77_LNKR_CHECK
+
+else
+
+ AC_MSG_WARN([cannot find MPI-Fortran compiler])
+ echo ""
+ echo " Unable to find a functional MPI-Fortran compiler."
+ echo ""
+ echo " Try using --with-mpif77 to specify a MPI-Fortran compiler script,"
+ echo " --with-mpi-incdir, --with-mpi-libdir and --with-mpi-libs"
+ echo " to specify the locations of all relevant MPI files, or"
+ echo " --with-mpi-root to specify the base installation directory"
+ echo " of the MPI implementation to be used."
+ echo ""
+ echo " Disabling parallel Fortran examples...."
+ echo ""
+ MPIF77=""
+ MPI_F77_COMP_OK="no"
+ SUNDIALS_WARN_FLAG="yes"
+
+fi
+
+]) dnl END SUNDIALS_CHECK_MPIF77
+
+#------------------------------------------------------------------
+# DETERMINE MPI-FORTRAN LINKER IF USING MPIF77 SCRIPT
+#------------------------------------------------------------------
+
+AC_DEFUN([SUNDIALS_MPIF77_LNKR_CHECK],
+[
+
+# If we are NOT using an MPI script, then MPICC_COMP == CC and we do NOT need
+# to check again if CC is a C++ compiler as we already know the answer
+if test "X${USE_MPICC_SCRIPT}" = "Xyes"; then
+
+ # Check if using a C++ compiler (meaning MPI-C++ script)
+ # Save result from CC check
+ SAVED_USING_CPLUSPLUS_COMP="${USING_CPLUSPLUS_COMP}"
+ SUNDIALS_CPLUSPLUS_CHECK([${MPICC_COMP}])
+ # MPICC uses a C++ compiler so run the next test
+ if test "X${USING_CPLUSPLUS_COMP}" = "Xyes" && test "X${SAVED_USING_CPLUSPLUS_COMP}" = "Xyes"; then
+ RUN_MPIF77_LNKR_CHECK="yes"
+ # ERROR
+ elif test "X${USING_CPLUSPLUS_COMP}" = "Xyes" && test "X${SAVED_USING_CPLUSPLUS_COMP}" = "Xno"; then
+ AC_MSG_ERROR([${MPICC_COMP} is a C++ compiler but ${CC} is a C compiler])
+ # MPICC uses a C compiler so skip the next test
+ elif test "X${USING_CPLUSPLUS_COMP}" = "Xno" && test "X${SAVED_USING_CPLUSPLUS_COMP}" = "Xno" ; then
+ RUN_MPIF77_LNKR_CHECK="no"
+ # ERROR
+ elif test "X${USING_CPLUSPLUS_COMP}" = "Xno" && test "X${SAVED_USING_CPLUSPLUS_COMP}" = "Xyes" ; then
+ AC_MSG_ERROR([${MPICC_COMP} is a C compiler but ${CC} is a C++ compiler])
+ fi
+ # Restore result from CC check
+ USING_CPLUSPLUS_COMP="${SAVED_USING_CPLUSPLUS_COMP}"
+
+else
+
+ AC_MSG_CHECKING([if ${MPICC_COMP} is a C++ compiler])
+ if test "X${USING_CPLUSPLUS_COMP}" = "Xyes"; then
+ AC_MSG_RESULT([yes])
+ else
+ AC_MSG_RESULT([no])
+ fi
+
+fi
+
+AC_MSG_CHECKING([which linker to use])
+# Perform the next test only if using a C++ compiler to build NVECTOR_PARALLEL
+if test "X${RUN_MPIF77_LNKR_CHECK}" = "Xyes"; then
+
+ MPIF77_LNKR_CHECK_OK="no"
+
+ # Switch language to "Fortran 77"
+ AC_LANG_PUSH([Fortran 77])
+
+ # Temporarily reset F77 environment variable to perform test
+ SAVED_F77="${F77}"
+ F77="${MPIF77_COMP}"
+
+ # Compile simple Fortran example, but do NOT link
+ # Note: result stored as conftest.${ac_objext}
+ AC_COMPILE_IFELSE(
+ [AC_LANG_SOURCE(
+ [[
+ PROGRAM SUNDIALS
+ INTEGER IER
+ CALL MPI_INIT(IER)
+ END
+ ]])],
+ [
+
+ # Reset F77 to original value
+ F77="${SAVED_F77}"
+
+ # Revert to previous language
+ AC_LANG_POP([Fortran 77])
+
+ # Temporarily reset LIBS environment variable to perform test
+ SAVED_LIBS="${LIBS}"
+ LIBS="${LIBS} ${FLIBS}"
+
+ # Switch working language to C for next test
+ AC_LANG_PUSH([C])
+
+ # Temporarily reset CC environment variable to perform next test
+ SAVED_CC="${CC}"
+ CC="${MPICC_COMP}"
+
+ # Check if MPICC_COMP can link Fortran example
+ # Note: AC_LINKONLY_IFELSE is a custom macro (modifications made to
+ # general.m4 and c.m4)
+ AC_LINKONLY_IFELSE([],[MPIF77_LNKR_CHECK_OK="yes"],[MPIF77_LNKR_CHECK_OK="no"])
+
+ # Reset CC to original value
+ CC="${SAVED_CC}"
+
+ # Revert back to previous language (Fortran 77)
+ AC_LANG_POP([C])
+
+ # Set LIBS environment variable back to original value
+ LIBS="${SAVED_LIBS}"
+
+ ])
+
+ # If either the compilation or the linking failed, we should
+ # disable building the parallel Fortran examples
+ # For now, use MPIF77 as the linker...
+
+ if test "X${MPIF77_LNKR_CHECK_OK}" = "Xyes"; then
+ MPIF77_LNKR="${MPICC}"
+ else
+ MPIF77_LNKR="${MPIF77}"
+ fi
+
+else
+
+ # Using a C compiler so use MPIF77 to link parallel Fortran examples
+ MPIF77_LNKR="${MPIF77}"
+
+fi
+AC_MSG_RESULT([${MPIF77_LNKR}])
+
+
+]) dnl SUNDIALS_MPIF77_LNKR_CHECK
+
+#------------------------------------------------------------------
+# TEST FORTRAN COMPILER WITH MPI
+#------------------------------------------------------------------
+
+AC_DEFUN([SUNDIALS_F77_WITH_MPI_CHECK],
+[
+
+# Test if we can compile MPI programs using the F77 compiler
+# and current MPI settings
+
+AC_MSG_NOTICE([Testing F77 with MPI settings])
+
+AC_LANG_PUSH([Fortran 77])
+
+# Save copies of FFLAGS, LDFLAGS and LIBS (preserve information)
+# Temporarily overwritten so we can test MPI implementation
+SAVED_FFLAGS="${FFLAGS}"
+SAVED_LDFLAGS="${LDFLAGS}"
+SAVED_LIBS="${LIBS}"
+
+# This may seem redundant, but we are not guaranteed that
+# SUNDIALS_CC_WITH_MPI_CHECK has been executed
+# Determine location of MPI header files (find MPI include directory)
+MPI_EXISTS="yes"
+
+AC_MSG_CHECKING([for location of MPI implementation])
+
+# If MPI include directory was NOT explicitly specified so check if MPI root
+# directory was given by user
+if test "X${MPI_INC_DIR}" = "X"; then
+ # If MPI root directory was NOT given so issue a warning message
+ if test "X${MPI_ROOT_DIR}" = "X"; then
+ AC_MSG_RESULT([not found])
+ MPI_EXISTS="no"
+ AC_MSG_WARN([cannot find MPI implementation files])
+ echo ""
+ echo " Unable to find MPI implementation files."
+ echo ""
+ echo " Try using --with-mpif77 to specify a MPI-Fortran compiler script,"
+ echo " --with-mpi-incdir, --with-mpi-libdir and --with-mpi-libs"
+ echo " to specify the locations of all relevant MPI files, or"
+ echo " --with-mpi-root to specify the base installation directory"
+ echo " of the MPI implementation to be used."
+ echo ""
+ echo " Disabling all parallel Fortran examples..."
+ echo ""
+ SUNDIALS_WARN_FLAG="yes"
+ # MPI root directory was given so set MPI_INC_DIR accordingly
+ # Update FFLAGS
+ else
+ MPI_INC_DIR="${MPI_ROOT_DIR}/include"
+ AC_MSG_RESULT([${MPI_INC_DIR}])
+ if test "X${FFLAGS}" = "X"; then
+ FFLAGS="-I${MPI_INC_DIR}"
+ else
+ FFLAGS="${FFLAGS} -I${MPI_INC_DIR}"
+ fi
+ fi
+# MPI include directory was specified so update FFLAGS
+else
+ AC_MSG_RESULT([${MPI_INC_DIR}])
+ if test "X${FFLAGS}" = "X"; then
+ FFLAGS="-I${MPI_INC_DIR}"
+ else
+ FFLAGS="${FFLAGS} -I${MPI_INC_DIR}"
+ fi
+fi
+
+# Only continue if found an MPI implementation
+if test "X${MPI_EXISTS}" = "Xyes"; then
+
+ AC_MSG_CHECKING([for location of MPI libraries])
+
+ # Determine location of MPI libraries
+ # MPI library directory was NOT specified by user so set based upon MPI_ROOT_DIR
+ # Update LDFLAGS
+ if test "X${MPI_LIB_DIR}" = "X"; then
+ MPI_LIB_DIR="${MPI_ROOT_DIR}/lib"
+ AC_MSG_RESULT([${MPI_LIB_DIR}])
+ if test "X${LDFLAGS}" = "X"; then
+ LDFLAGS="-L${MPI_LIB_DIR}"
+ else
+ LDFLAGS="${LDFLAGS} -L${MPI_LIB_DIR}"
+ fi
+ # MPI library directory was specified so update LDFLAGS
+ else
+ AC_MSG_RESULT([${MPI_LIB_DIR}])
+ if test "X${LDFLAGS}" = "X"; then
+ LDFLAGS="-L${MPI_LIB_DIR}"
+ else
+ LDFLAGS="${LDFLAGS} -L${MPI_LIB_DIR}"
+ fi
+ fi
+
+ # Check if user specified which MPI libraries must be included
+ # If no libraries are given, then issue a warning message
+ AC_MSG_CHECKING([for MPI libraries])
+ if test "X${MPI_LIBS}" = "X"; then
+ AC_MSG_RESULT([none])
+ echo ""
+ echo " Unable to compile MPI program using Fortran compiler because"
+ echo " MPI libraries were not specified."
+ echo ""
+ echo " Try using --with-mpi-libdir and --with-mpi-libs to"
+ echo " specify the location and names of the MPI libraries."
+ echo ""
+ echo " Disabling all parallel Fortran examples..."
+ echo ""
+ MPI_F77_COMP_OK="no"
+ # MPI libraries were specified so update LIBS
+ else
+ AC_MSG_RESULT([${MPI_LIBS}])
+ if test "X${LIBS}" = "X"; then
+ LIBS="${MPI_LIBS}"
+ else
+ LIBS="${LIBS} ${MPI_LIBS}"
+ fi
+ # Set the MPI_F77_COMP_OK variable to NULL so we can conditionally execute
+ # the next test
+ MPI_F77_COMP_OK=""
+ fi
+
+ if test "X${MPI_F77_COMP_OK}" = "X"; then
+ AC_MSG_CHECKING([if Fortran compiler can compile MPI programs])
+ AC_LINK_IFELSE(
+ [AC_LANG_PROGRAM([],
+ [
+ INCLUDE "mpif.h"
+ CALL MPI_INIT(IER)
+ ])],
+ [AC_MSG_RESULT([yes])
+ MPI_F77_COMP_OK="yes"],
+ [AC_MSG_RESULT([no])
+ AC_MSG_WARN([Fortran compiler cannot compile MPI programs])
+ echo ""
+ echo " Unable to compile MPI program using Fortran compiler."
+ echo ""
+ echo " Try using --with-mpif77 to specify a MPI-Fortran compiler script,"
+ echo " --with-mpi-incdir, --with-mpi-libdir and --with-mpi-libs"
+ echo " to specify the locations of all relevant MPI files, or"
+ echo " --with-mpi-root to specify the base installation directory"
+ echo " of the MPI implementation to be used."
+ echo ""
+ echo " Disabling all parallel Fortran examples..."
+ echo ""
+ MPI_F77_COMP_OK="no"
+ SUNDIALS_WARN_FLAG="yes"])
+
+ # Set MPIF77_LNKR based on value of F77_LNKR
+ # Note: setting MPIF77_LNKR is trivial if NOT using the MPI compiler script
+ # since the SUNDIALS_F77_LNKR_CHECK macro already checked if CC or F77
+ # should be used
+ AC_MSG_CHECKING([which linker to use])
+ if test "X${F77_LNKR}" = "X${CC}"; then
+ MPIF77_LNKR="${MPICC}"
+ elif test "X${F77_LNKR}" = "X${F77}"; then
+ MPIF77_LNKR="${MPIF77}"
+ fi
+ AC_MSG_RESULT([${MPIF77_LNKR}])
+ fi
+
+else
+ MPI_F77_COMP_OK="no"
+fi
+
+# Restore FFLAGS, LDFLAGS and LIBS
+FFLAGS="${SAVED_FFLAGS}"
+LDFLAGS="${SAVED_LDFLAGS}"
+LIBS="${SAVED_LIBS}"
+
+AC_LANG_POP([Fortran 77])
+
+]) dnl END SUNDIALS_F77_WITH_MPI_CHECK
+
+#------------------------------------------------------------------
+# TEST MPI-2 FUNCTIONALITY
+#------------------------------------------------------------------
+
+AC_DEFUN([SUNDIALS_CHECK_MPI2],
+[
+
+# Determine if MPI implementation used to build SUNDIALS provides
+# MPI-2 functionality.
+#
+# Test for MPI_Comm_f2c() function:
+# (1) NO : FNVECTOR_PARALLEL module will NOT allow user to specify
+# an MPI communicator and MPI_COMM_WORLD will be used
+# (2) YES : FNVECTOR_PARALLEL module will allow user to specify
+# an MPI communicator
+#
+
+# Provide variable description templates for config.hin and config.h files
+# Required by autoheader utility
+AH_TEMPLATE([SUNDIALS_MPI_COMM_F2C],
+ [FNVECTOR: Allow user to specify different MPI communicator])
+
+# Save copies of CPPFLAGS, LDFLAGS and LIBS (preserve information)
+# Temporarily overwritten so we can test MPI implementation
+SAVED_CPPFLAGS="${CPPFLAGS}"
+SAVED_LDFLAGS="${LDFLAGS}"
+SAVED_LIBS="${LIBS}"
+
+# Determine location of MPI header files (find MPI include directory)
+MPI_EXISTS="yes"
+
+# MPI include directory was NOT explicitly specified so check if MPI root
+# directory was given by user
+if test "X${MPI_INC_DIR}" = "X"; then
+ # MPI root directory was NOT given so issue a warning message
+ if test "X${MPI_ROOT_DIR}" = "X"; then
+ MPI_EXISTS="no"
+ AC_MSG_WARN([cannot find MPI implementation files])
+ echo ""
+ echo " Unable to find MPI implementation files."
+ echo ""
+ echo " Try using --with-mpicc to specify a MPI-C compiler script,"
+ echo " --with-mpi-incdir, --with-mpi-libdir and --with-mpi-libs"
+ echo " to specify the locations of all relevant MPI files, or"
+ echo " --with-mpi-root to specify the base installation directory"
+ echo " of the MPI implementation to be used."
+ echo ""
+ echo " Disabling FNVECTOR_PARALLEL support for user-specified"
+ echo " MPI communicator..."
+ echo ""
+ SUNDIALS_WARN_FLAG="yes"
+ # MPI root directory was given so set MPI_INC_DIR accordingly
+ # Update CPPFLAGS
+ else
+ MPI_INC_DIR="${MPI_ROOT_DIR}/include"
+ if test "X${CPPFLAGS}" = "X"; then
+ CPPFLAGS="-I${MPI_INC_DIR}"
+ else
+ CPPFLAGS="${CPPFLAGS} -I${MPI_INC_DIR}"
+ fi
+ # Add MPI_FLAGS if non-empty
+ if test "X${MPI_FLAGS}" = "X"; then
+ CPPFLAGS="${CPPFLAGS}"
+ else
+ CPPFLAGS="${CPPFLAGS} ${MPI_FLAGS}"
+ fi
+ fi
+# MPI include directory was specified so update CPPFLAGS
+else
+ if test "X${CPPFLAGS}" = "X"; then
+ CPPFLAGS="-I${MPI_INC_DIR}"
+ else
+ CPPFLAGS="${CPPFLAGS} -I${MPI_INC_DIR}"
+ fi
+ # Add MPI_FLAGS if non-empty
+ if test "X${MPI_FLAGS}" = "X"; then
+ CPPFLAGS="${CPPFLAGS}"
+ else
+ CPPFLAGS="${CPPFLAGS} ${MPI_FLAGS}"
+ fi
+fi
+
+# Only continue if found an MPI implementation
+if test "X${MPI_EXISTS}" = "Xyes"; then
+
+ # Determine location of MPI libraries
+ # MPI library directory was NOT specified by user so set based upon MPI_ROOT_DIR
+ # Update LDFLAGS
+ if test "X${MPI_LIB_DIR}" = "X"; then
+ MPI_LIB_DIR="${MPI_ROOT_DIR}/lib"
+ if test "X${LDFLAGS}" = "X"; then
+ LDFLAGS="-L${MPI_LIB_DIR}"
+ else
+ LDFLAGS="${LDFLAGS} -L${MPI_LIB_DIR}"
+ fi
+ # MPI library directory was specified so update LDFLAGS
+ else
+ if test "X${LDFLAGS}" = "X"; then
+ LDFLAGS="-L${MPI_LIB_DIR}"
+ else
+ LDFLAGS="${LDFLAGS} -L${MPI_LIB_DIR}"
+ fi
+ fi
+
+ # Check if user specified which MPI libraries linker should be use
+ if test "X${MPI_LIBS}" = "X"; then
+ :
+ # MPI libraries were specified so update LIBS
+ else
+ if test "X${LIBS}" = "X"; then
+ LIBS="${MPI_LIBS}"
+ else
+ LIBS="${LIBS} ${MPI_LIBS}"
+ fi
+ fi
+
+ # Since AC_LINK_IFELSE uses CC, set CC = MPICC if using
+ # an MPI compiler script
+ if test "X${USE_MPICC_SCRIPT}" = "Xyes"; then
+ SAVED_CC="${CC}"
+ CC="${MPICC_COMP}"
+ fi
+
+ # Check if MPI implementation supports MPI_Comm_f2c() from
+ # MPI-2 specification
+ if test "X${FCMIX_ENABLED}" = "Xyes"; then
+ AC_MSG_CHECKING([for MPI_Comm_f2c() from MPI-2 specification])
+ AC_LINK_IFELSE(
+ [AC_LANG_PROGRAM([[#include "mpi.h"]],
+ [[
+ int c;
+ char **v;
+ MPI_Comm C_comm;
+ MPI_Init(&c, &v);
+ C_comm = MPI_Comm_f2c((MPI_Fint) 1);
+ MPI_Finalize();
+ ]])],
+ [AC_MSG_RESULT([yes])
+ AC_DEFINE([SUNDIALS_MPI_COMM_F2C],[1],[])
+ F77_MPI_COMM_F2C="#define SUNDIALS_MPI_COMM_F2C 1"],
+ [AC_MSG_RESULT([no])
+ AC_DEFINE([SUNDIALS_MPI_COMM_F2C],[0],[])
+ F77_MPI_COMM_F2C="#define SUNDIALS_MPI_COMM_F2C 0"])
+ fi
+
+ # Reset CC if necessary
+ if test "X${USE_MPICC_SCRIPT}" = "Xyes"; then
+ CC="${SAVED_CC}"
+ fi
+
+else
+ AC_DEFINE([SUNDIALS_MPI_COMM_F2C],[0],[])
+ F77_MPI_COMM_F2C="#define SUNDIALS_MPI_COMM_F2C 0"
+fi
+
+# Restore CPPFLAGS, LDFLAGS and LIBS
+CPPFLAGS="${SAVED_CPPFLAGS}"
+LDFLAGS="${SAVED_LDFLAGS}"
+LIBS="${SAVED_LIBS}"
+
+]) dnl END SUNDIALS_CHECK_MPI2
+
+
+
+
+#=================================================================#
+# #
+# #
+# F I N A L I Z A T I O N S #
+# #
+# #
+#==================================================================
+
+
+#------------------------------------------------------------------
+# ADD SOME MORE STUFF TO configure --help
+#------------------------------------------------------------------
+
+AC_DEFUN([SUNDIALS_MORE_HELP],
+[
+
+AC_ARG_WITH([],[ ],[])
+AC_ARG_WITH([],[NOTES],[])
+AC_ARG_WITH([],[ It is legal to set --with-exinstdir to "no", in which case the examples],[])
+AC_ARG_WITH([],[ are built but not installed.],[])
+AC_ARG_WITH([],[ Enabling the compilation of the examples (--enable-examples) but disabling their],[])
+AC_ARG_WITH([],[ installation (--with-exinstdir=no) can be used to test the SUNDIALS libraries.],[])
+
+]) dnl END SUNDIALS_MORE_HELP
+
+#------------------------------------------------------------------
+# SET EXAMPLES
+#
+# Decide which examples can be built
+#
+#------------------------------------------------------------------
+
+AC_DEFUN([SUNDIALS_SET_EXAMPLES],
+[
+
+# Set proper object file extension
+# Must export OBJ_EXT via AC_SUBST
+OBJEXT=".lo"
+
+# Check if serial C examples can actually be built
+SERIAL_C_EXAMPLES="yes"
+
+# Check if parallel C examples can actually be built
+if test "X${MPI_ENABLED}" = "Xyes"; then
+ if test "X${MPI_C_COMP_OK}" = "Xyes"; then
+ PARALLEL_C_EXAMPLES="yes"
+ else
+ PARALLEL_C_EXAMPLES="no"
+ fi
+else
+ PARALLEL_C_EXAMPLES="disabled"
+fi
+
+# Check if serial F77 examples can actually be built
+if test "X${FCMIX_ENABLED}" = "Xyes"; then
+ if test "X${F77_OK}" = "Xyes"; then
+ SERIAL_F77_EXAMPLES="yes"
+ else
+ SERIAL_F77_EXAMPLES="no"
+ fi
+else
+ SERIAL_F77_EXAMPLES="disabled"
+fi
+
+# Check if parallel F77 examples can actually be built
+if test "X${FCMIX_ENABLED}" = "Xyes" && test "X${MPI_ENABLED}" = "Xyes"; then
+ if test "X${MPI_F77_COMP_OK}" = "Xyes"; then
+ PARALLEL_F77_EXAMPLES="yes"
+ else
+ PARALLEL_F77_EXAMPLES="no"
+ fi
+else
+ PARALLEL_F77_EXAMPLES="disabled"
+fi
+
+# Notify user
+AC_MSG_CHECKING([if we can build serial C examples])
+AC_MSG_RESULT([${SERIAL_C_EXAMPLES}])
+AC_MSG_CHECKING([if we can build parallel C examples])
+AC_MSG_RESULT([${PARALLEL_C_EXAMPLES}])
+AC_MSG_CHECKING([if we can build serial Fortran examples])
+AC_MSG_RESULT([${SERIAL_F77_EXAMPLES}])
+AC_MSG_CHECKING([if we can build parallel Fortran examples])
+AC_MSG_RESULT([${PARALLEL_F77_EXAMPLES}])
+
+# Check if the Fortran update script (bin/fortran-update.in) is needed
+if test "X${SERIAL_F77_EXAMPLES}" = "Xyes" || test "X${PARALLEL_F77_EXAMPLES}" = "Xyes"; then
+ BUILD_F77_UPDATE_SCRIPT="yes";
+else
+ BUILD_F77_UPDATE_SCRIPT="no"
+fi
+
+# Where should we install the examples?
+# Note: setting this to "no" will disable example installation!
+AC_MSG_CHECKING([where to install the SUNDIALS examples])
+AC_ARG_WITH([],[ ],[])
+AC_ARG_WITH([exinstdir],
+[AC_HELP_STRING([--with-exinstdir=DIR], [install SUNDIALS examples in DIR @<:@EPREFIX/examples@:>@])],
+[
+ EXS_INSTDIR="${withval}"
+],
+[
+ if test "X${exec_prefix}" = "XNONE"; then
+ if test "X${prefix}" = "XNONE"; then
+ EXS_INSTDIR="\${exec_prefix}/examples"
+ else
+ EXS_INSTDIR="${prefix}/examples"
+ fi
+ else
+ EXS_INSTDIR="${exec_prefix}/examples"
+ fi
+])
+AC_MSG_RESULT([${EXS_INSTDIR}])
+
+# Prepare substitution variables to create the exported example Makefiles
+
+F77_LIBS="${FLIBS} ${LIBS}"
+if test "X${F77_LNKR}" = "X${F77}"; then
+ F77_LDFLAGS="${FFLAGS} ${LDFLAGS}"
+else
+ F77_LDFLAGS="${CFLAGS} ${LDFLAGS}"
+fi
+
+]) dnl END SUNDIALS_SET_EXAMPLES
+
+#------------------------------------------------------------------
+# BUILD MODULES LIST
+#------------------------------------------------------------------
+
+AC_DEFUN([SUNDIALS_BUILD_MODULES_LIST],
+[
+
+# Initialize the list of Makefiles to be created
+SUNDIALS_MAKEFILES="Makefile"
+
+# Initialize list of additional configure files to be created
+SUNDIALS_CONFIGFILES="include/sundials/sundials_config.h:include/sundials/sundials_config.in"
+SUNDIALS_CONFIGFILES="${SUNDIALS_CONFIGFILES} bin/sundials-config:bin/sundials-config.in"
+
+# Initialize lists of solver modules and example modules
+SLV_MODULES="src/sundials"
+SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} src/sundials/Makefile"
+
+EXS_MODULES=""
+
+# NVECTOR modules
+if test -d ${srcdir}/src/nvec_ser ; then
+ SLV_MODULES="${SLV_MODULES} src/nvec_ser"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} src/nvec_ser/Makefile"
+fi
+
+if test -d ${srcdir}/src/nvec_par && test "X${MPI_C_COMP_OK}" = "Xyes"; then
+ SLV_MODULES="${SLV_MODULES} src/nvec_par"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} src/nvec_par/Makefile"
+fi
+
+if test -d ${srcdir}/src/nvec_spcpar && test "X${MPI_C_COMP_OK}" = "Xyes"; then
+ SLV_MODULES="${SLV_MODULES} src/nvec_spcpar"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} src/nvec_spcpar/Makefile"
+fi
+
+# CVODE module
+if test "X${CVODE_ENABLED}" = "Xyes"; then
+
+ SLV_MODULES="${SLV_MODULES} src/cvode"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} src/cvode/Makefile"
+
+ if test "X${FCMIX_ENABLED}" = "Xyes" && test -d ${srcdir}/src/cvode/fcmix ; then
+ SLV_MODULES="${SLV_MODULES} src/cvode/fcmix"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} src/cvode/fcmix/Makefile"
+ fi
+
+ if test "X${SERIAL_C_EXAMPLES}" = "Xyes" && test -d ${srcdir}/examples/cvode/serial ; then
+ EXS_MODULES="${EXS_MODULES} examples/cvode/serial"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} examples/cvode/serial/Makefile"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} examples/cvode/serial/Makefile_ex:examples/templates/makefile_serial_C_ex.in"
+ fi
+
+ if test "X${SERIAL_F77_EXAMPLES}" = "Xyes" && test -d ${srcdir}/examples/cvode/fcmix_serial ; then
+ EXS_MODULES="${EXS_MODULES} examples/cvode/fcmix_serial"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} examples/cvode/fcmix_serial/Makefile"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} examples/cvode/fcmix_serial/Makefile_ex:examples/templates/makefile_serial_F77_ex.in"
+ fi
+
+ if test "X${PARALLEL_C_EXAMPLES}" = "Xyes" && test -d ${srcdir}/examples/cvode/parallel ; then
+ EXS_MODULES="${EXS_MODULES} examples/cvode/parallel"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} examples/cvode/parallel/Makefile"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} examples/cvode/parallel/Makefile_ex:examples/templates/makefile_parallel_C_ex.in"
+ fi
+
+ if test "X${PARALLEL_F77_EXAMPLES}" = "Xyes" && test -d ${srcdir}/examples/cvode/fcmix_parallel ; then
+ EXS_MODULES="${EXS_MODULES} examples/cvode/fcmix_parallel"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} examples/cvode/fcmix_parallel/Makefile"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} examples/cvode/fcmix_parallel/Makefile_ex:examples/templates/makefile_parallel_F77_ex.in"
+ fi
+
+fi
+
+# CVODES module
+if test "X${CVODES_ENABLED}" = "Xyes"; then
+
+ SLV_MODULES="${SLV_MODULES} src/cvodes"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} src/cvodes/Makefile"
+
+ if test "X${SERIAL_C_EXAMPLES}" = "Xyes" && test -d ${srcdir}/examples/cvodes/serial ; then
+ EXS_MODULES="${EXS_MODULES} examples/cvodes/serial"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} examples/cvodes/serial/Makefile"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} examples/cvodes/serial/Makefile_ex:examples/templates/makefile_serial_C_ex.in"
+ fi
+
+ if test "X${PARALLEL_C_EXAMPLES}" = "Xyes" && test -d ${srcdir}/examples/cvodes/parallel ; then
+ EXS_MODULES="${EXS_MODULES} examples/cvodes/parallel"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} examples/cvodes/parallel/Makefile"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} examples/cvodes/parallel/Makefile_ex:examples/templates/makefile_parallel_C_ex.in"
+ fi
+
+fi
+
+# IDA module
+if test "X${IDA_ENABLED}" = "Xyes"; then
+
+ SLV_MODULES="${SLV_MODULES} src/ida"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} src/ida/Makefile"
+
+ if test "X${FCMIX_ENABLED}" = "Xyes" && test -d ${srcdir}/src/ida/fcmix ; then
+ SLV_MODULES="${SLV_MODULES} src/ida/fcmix"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} src/ida/fcmix/Makefile"
+ fi
+
+ if test "X${SERIAL_C_EXAMPLES}" = "Xyes" && test -d ${srcdir}/examples/ida/serial ; then
+ EXS_MODULES="${EXS_MODULES} examples/ida/serial"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} examples/ida/serial/Makefile"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} examples/ida/serial/Makefile_ex:examples/templates/makefile_serial_C_ex.in"
+ fi
+
+ if test "X${SERIAL_F77_EXAMPLES}" = "Xyes" && test -d ${srcdir}/examples/ida/fcmix_serial ; then
+ EXS_MODULES="${EXS_MODULES} examples/ida/fcmix_serial"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} examples/ida/fcmix_serial/Makefile"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} examples/ida/fcmix_serial/Makefile_ex:examples/templates/makefile_serial_F77_ex.in"
+ fi
+
+ if test "X${PARALLEL_C_EXAMPLES}" = "Xyes" && test -d ${srcdir}/examples/ida/parallel ; then
+ EXS_MODULES="${EXS_MODULES} examples/ida/parallel"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} examples/ida/parallel/Makefile"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} examples/ida/parallel/Makefile_ex:examples/templates/makefile_parallel_C_ex.in"
+ fi
+
+ if test "X${PARALLEL_F77_EXAMPLES}" = "Xyes" && test -d ${srcdir}/examples/ida/fcmix_parallel ; then
+ EXS_MODULES="${EXS_MODULES} examples/ida/fcmix_parallel"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} examples/ida/fcmix_parallel/Makefile"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} examples/ida/fcmix_parallel/Makefile_ex:examples/templates/makefile_parallel_F77_ex.in"
+ fi
+
+fi
+
+# IDAS module
+if test "X${IDAS_ENABLED}" = "Xyes"; then
+
+ SLV_MODULES="${SLV_MODULES} src/idas"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} src/idas/Makefile"
+
+ if test "X${SERIAL_C_EXAMPLES}" = "Xyes" && test -d ${srcdir}/examples/idas/serial ; then
+ EXS_MODULES="${EXS_MODULES} examples/idas/serial"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} examples/idas/serial/Makefile"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} examples/idas/serial/Makefile_ex:examples/templates/makefile_serial_C_ex.in"
+ fi
+
+ if test "X${PARALLEL_C_EXAMPLES}" = "Xyes" && test -d ${srcdir}/examples/idas/parallel ; then
+ EXS_MODULES="${EXS_MODULES} examples/idas/parallel"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} examples/idas/parallel/Makefile"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} examples/idas/parallel/Makefile_ex:examples/templates/makefile_parallel_C_ex.in"
+ fi
+
+fi
+
+# KINSOL module
+if test "X${KINSOL_ENABLED}" = "Xyes"; then
+
+ SLV_MODULES="${SLV_MODULES} src/kinsol"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} src/kinsol/Makefile"
+
+ if test "X${FCMIX_ENABLED}" = "Xyes" && test -d ${srcdir}/src/kinsol/fcmix ; then
+ SLV_MODULES="${SLV_MODULES} src/kinsol/fcmix"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} src/kinsol/fcmix/Makefile"
+ fi
+
+ if test "X${SERIAL_C_EXAMPLES}" = "Xyes" && test -d ${srcdir}/examples/kinsol/serial ; then
+ EXS_MODULES="${EXS_MODULES} examples/kinsol/serial"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} examples/kinsol/serial/Makefile"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} examples/kinsol/serial/Makefile_ex:examples/templates/makefile_serial_C_ex.in"
+ fi
+
+ if test "X${SERIAL_F77_EXAMPLES}" = "Xyes" && test -d ${srcdir}/examples/kinsol/fcmix_serial ; then
+ EXS_MODULES="${EXS_MODULES} examples/kinsol/fcmix_serial"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} examples/kinsol/fcmix_serial/Makefile"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} examples/kinsol/fcmix_serial/Makefile_ex:examples/templates/makefile_serial_F77_ex.in"
+ fi
+
+ if test "X${PARALLEL_C_EXAMPLES}" = "Xyes" && test -d ${srcdir}/examples/kinsol/parallel ; then
+ EXS_MODULES="${EXS_MODULES} examples/kinsol/parallel"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} examples/kinsol/parallel/Makefile"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} examples/kinsol/parallel/Makefile_ex:examples/templates/makefile_parallel_C_ex.in"
+ fi
+
+ if test "X${PARALLEL_F77_EXAMPLES}" = "Xyes" && test -d ${srcdir}/examples/kinsol/fcmix_parallel ; then
+ EXS_MODULES="${EXS_MODULES} examples/kinsol/fcmix_parallel"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} examples/kinsol/fcmix_parallel/Makefile"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} examples/kinsol/fcmix_parallel/Makefile_ex:examples/templates/makefile_parallel_F77_ex.in"
+ fi
+
+fi
+
+# CPODES module
+if test "X${CPODES_ENABLED}" = "Xyes"; then
+
+ SLV_MODULES="${SLV_MODULES} src/cpodes"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} src/cpodes/Makefile"
+
+ if test "X${SERIAL_C_EXAMPLES}" = "Xyes" && test -d ${srcdir}/examples/cpodes/serial ; then
+ EXS_MODULES="${EXS_MODULES} examples/cpodes/serial"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} examples/cpodes/serial/Makefile"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} examples/cpodes/serial/Makefile_ex:examples/templates/makefile_serial_C_ex.in"
+ fi
+
+ if test "X${PARALLEL_C_EXAMPLES}" = "Xyes" && test -d ${srcdir}/examples/cpodes/parallel ; then
+ EXS_MODULES="${EXS_MODULES} examples/cpodes/parallel"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} examples/cpodes/parallel/Makefile"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} examples/cpodes/parallel/Makefile_ex:examples/templates/makefile_parallel_C_ex.in"
+ fi
+
+fi
+
+# Add Fortran update script to the list of additional files to be generated
+if test "X${BUILD_F77_UPDATE_SCRIPT}" = "Xyes"; then
+ SUNDIALS_CONFIGFILES="${SUNDIALS_CONFIGFILES} bin/fortran-update.sh:bin/fortran-update.in"
+fi
+
+# If needed, add Makefile update script to the list of additional files to be generated
+if test "X${EXAMPLES_ENABLED}" = "Xyes" && test "X${EXS_INSTDIR}" != "Xno"; then
+ SUNDIALS_CONFIGFILES="${SUNDIALS_CONFIGFILES} bin/makefile-update.sh:bin/makefile-update.in"
+fi
+
+]) dnl END SUNDIALS_BUILD_MODULES_LIST
+
+#------------------------------------------------------------------
+# POST PROCESSING OF EXAMPLE Makefiles for export
+#------------------------------------------------------------------
+
+AC_DEFUN([SUNDIALS_POST_PROCESSING],
+[
+
+# If installing examples, the Makefiles that will be exported must
+# be post-processed to complete the substitution of all variables.
+# After config.status runs, each example subdirectory contains an
+# export makefile, named Makefile_ex, which was created from the
+# common template in examples/templates.
+#
+# The following variables are still to be substituted at this point:
+# SOLVER
+# EXAMPLES
+# EXAMPLES_BL
+# SOLVER_LIB SOLVER_FLIB
+# NVEC_LIB NVEC_FLIB
+#
+# This function is called ONLY if examples are enabled AND examples will
+# be installed. If so, it sets up commands to be called after config.status
+# has generated a first version of the Makefiles for export:
+#
+# (1) For each solver, proceed ONLY if the solver is enabled.
+# (2) For each type of examples, proceed ONLY if they can be compiled AND
+# the example directory exists.
+
+# CVODE module
+if test "X${CVODE_ENABLED}" = "Xyes"; then
+
+ if test "X${SERIAL_C_EXAMPLES}" = "Xyes" && test -d ${srcdir}/examples/cvode/serial ; then
+ if test "X${LAPACK_ENABLED}" = "Xyes"; then
+ AC_CONFIG_COMMANDS([cvode_ser_ex_bl],
+ [
+ IN_FILE="examples/cvode/serial/Makefile_ex"
+ SOLVER="CVODE"
+ SOLVER_LIB="sundials_cvode"
+ SOLVER_FLIB=""
+ EXAMPLES="cvAdvDiff_bnd cvDirectDemo_ls cvDiurnal_kry_bp cvDiurnal_kry cvKrylovDemo_ls cvKrylovDemo_prec cvRoberts_dns cvRoberts_dns_uw"
+ EXAMPLES_BL="cvAdvDiff_bndL cvRoberts_dnsL"
+ ${SHELL} bin/makefile-update.sh "${IN_FILE}" "${SOLVER}" "${EXAMPLES}" "${EXAMPLES_BL}" "${SOLVER_LIB}" "${SOLVER_FLIB}"
+ ])
+ else
+ AC_CONFIG_COMMANDS([cvode_ser_ex],
+ [
+ IN_FILE="examples/cvode/serial/Makefile_ex"
+ SOLVER="CVODE"
+ SOLVER_LIB="sundials_cvode"
+ SOLVER_FLIB=""
+ EXAMPLES="cvAdvDiff_bnd cvDirectDemo_ls cvDiurnal_kry_bp cvDiurnal_kry cvKrylovDemo_ls cvKrylovDemo_prec cvRoberts_dns cvRoberts_dns_uw"
+ EXAMPLES_BL=""
+ ${SHELL} bin/makefile-update.sh "${IN_FILE}" "${SOLVER}" "${EXAMPLES}" "${EXAMPLES_BL}" "${SOLVER_LIB}" "${SOLVER_FLIB}"
+ ])
+ fi
+ fi
+
+ if test "X${SERIAL_F77_EXAMPLES}" = "Xyes" && test -d ${srcdir}/examples/cvode/fcmix_serial ; then
+ if test "X${LAPACK_ENABLED}" = "Xyes"; then
+ AC_CONFIG_COMMANDS([cvode_fser_ex_bl],
+ [
+ IN_FILE="examples/cvode/fcmix_serial/Makefile_ex"
+ SOLVER="CVODE"
+ SOLVER_LIB="sundials_cvode"
+ SOLVER_FLIB="sundials_fcvode"
+ EXAMPLES="fcvAdvDiff_bnd fcvDiurnal_kry_bp fcvDiurnal_kry fcvRoberts_dns"
+ EXAMPLES_BL="fcvRoberts_dnsL"
+ ${SHELL} bin/makefile-update.sh "${IN_FILE}" "${SOLVER}" "${EXAMPLES}" "${EXAMPLES_BL}" "${SOLVER_LIB}" "${SOLVER_FLIB}"
+ ])
+ else
+ AC_CONFIG_COMMANDS([cvode_fser_ex],
+ [
+ IN_FILE="examples/cvode/fcmix_serial/Makefile_ex"
+ SOLVER="CVODE"
+ SOLVER_LIB="sundials_cvode"
+ SOLVER_FLIB="sundials_fcvode"
+ EXAMPLES="fcvAdvDiff_bnd fcvDiurnal_kry_bp fcvDiurnal_kry fcvRoberts_dns"
+ EXAMPLES_BL=""
+ ${SHELL} bin/makefile-update.sh "${IN_FILE}" "${SOLVER}" "${EXAMPLES}" "${EXAMPLES_BL}" "${SOLVER_LIB}" "${SOLVER_FLIB}"
+ ])
+ fi
+ fi
+
+ if test "X${PARALLEL_C_EXAMPLES}" = "Xyes" && test -d ${srcdir}/examples/cvode/parallel ; then
+ AC_CONFIG_COMMANDS([cvode_par_ex],
+ [
+ IN_FILE="examples/cvode/parallel/Makefile_ex"
+ SOLVER="CVODE"
+ SOLVER_LIB="sundials_cvode"
+ SOLVER_FLIB=""
+ EXAMPLES="cvAdvDiff_non_p cvDiurnal_kry_bbd_p cvDiurnal_kry_p"
+ EXAMPLES_BL=""
+ ${SHELL} bin/makefile-update.sh "${IN_FILE}" "${SOLVER}" "${EXAMPLES}" "${EXAMPLES_BL}" "${SOLVER_LIB}" "${SOLVER_FLIB}"
+ ])
+ fi
+
+ if test "X${PARALLEL_F77_EXAMPLES}" = "Xyes" && test -d ${srcdir}/examples/cvode/fcmix_parallel ; then
+ AC_CONFIG_COMMANDS([cvode_fpar_ex],
+ [
+ IN_FILE="examples/cvode/fcmix_parallel/Makefile_ex"
+ SOLVER="CVODE"
+ SOLVER_LIB="sundials_cvode"
+ SOLVER_FLIB="sundials_fcvode"
+ EXAMPLES="fcvDiag_non_p fcvDiag_kry_bbd_p fcvDiag_kry_p"
+ EXAMPLES_BL=""
+ ${SHELL} bin/makefile-update.sh "${IN_FILE}" "${SOLVER}" "${EXAMPLES}" "${EXAMPLES_BL}" "${SOLVER_LIB}" "${SOLVER_FLIB}"
+ ])
+ fi
+
+fi
+
+
+# CVODES module
+if test "X${CVODES_ENABLED}" = "Xyes"; then
+
+ if test "X${SERIAL_C_EXAMPLES}" = "Xyes" && test -d ${srcdir}/examples/cvodes/serial ; then
+ if test "X${LAPACK_ENABLED}" = "Xyes"; then
+ AC_CONFIG_COMMANDS([cvodes_ser_ex_bl],
+ [
+ IN_FILE="examples/cvodes/serial/Makefile_ex"
+ SOLVER="CVODES"
+ SOLVER_LIB="sundials_cvodes"
+ SOLVER_FLIB=""
+ EXAMPLES="cvsAdvDiff_ASAi_bnd cvsAdvDiff_FSA_non cvsDiurnal_kry_bp cvsFoodWeb_ASAp_kry cvsKrylovDemo_prec cvsAdvDiff_bnd cvsDirectDemo_ls cvsDiurnal_kry cvsHessian_ASA_FSA cvsRoberts_ASAi_dns cvsRoberts_dns_uw cvsDiurnal_FSA_kry cvsFoodWeb_ASAi_kry cvsKrylovDemo_ls cvsRoberts_dns cvsRoberts_FSA_dns"
+ EXAMPLES_BL="cvsRoberts_dnsL cvsAdvDiff_bndL"
+ ${SHELL} bin/makefile-update.sh "${IN_FILE}" "${SOLVER}" "${EXAMPLES}" "${EXAMPLES_BL}" "${SOLVER_LIB}" "${SOLVER_FLIB}"
+ ])
+ else
+ AC_CONFIG_COMMANDS([cvodes_ser_ex],
+ [
+ IN_FILE="examples/cvodes/serial/Makefile_ex"
+ SOLVER="CVODES"
+ SOLVER_LIB="sundials_cvodes"
+ SOLVER_FLIB=""
+ EXAMPLES="cvsAdvDiff_ASAi_bnd cvsAdvDiff_FSA_non cvsDiurnal_kry_bp cvsFoodWeb_ASAp_kry cvsKrylovDemo_prec cvsAdvDiff_bnd cvsDirectDemo_ls cvsDiurnal_kry cvsHessian_ASA_FSA cvsRoberts_ASAi_dns cvsRoberts_dns_uw cvsDiurnal_FSA_kry cvsFoodWeb_ASAi_kry cvsKrylovDemo_ls cvsRoberts_dns cvsRoberts_FSA_dns"
+ EXAMPLES_BL=""
+ ${SHELL} bin/makefile-update.sh "${IN_FILE}" "${SOLVER}" "${EXAMPLES}" "${EXAMPLES_BL}" "${SOLVER_LIB}" "${SOLVER_FLIB}"
+ ])
+ fi
+ fi
+
+ if test "X${PARALLEL_C_EXAMPLES}" = "Xyes" && test -d ${srcdir}/examples/cvodes/parallel ; then
+ AC_CONFIG_COMMANDS([cvodes_par_ex],
+ [
+ IN_FILE="examples/cvodes/parallel/Makefile_ex"
+ SOLVER="CVODES"
+ SOLVER_LIB="sundials_cvodes"
+ SOLVER_FLIB=""
+ EXAMPLES="cvsAdvDiff_ASAp_non_p cvsAdvDiff_non_p cvsDiurnal_FSA_kry_p cvsDiurnal_kry_p cvsAdvDiff_FSA_non_p cvsAtmDisp_ASAi_kry_bbd_p cvsDiurnal_kry_bbd_p"
+ EXAMPLES_BL=""
+ ${SHELL} bin/makefile-update.sh "${IN_FILE}" "${SOLVER}" "${EXAMPLES}" "${EXAMPLES_BL}" "${SOLVER_LIB}" "${SOLVER_FLIB}"
+ ])
+ fi
+
+fi
+
+
+# IDA module
+if test "X${IDA_ENABLED}" = "Xyes"; then
+
+ if test "X${SERIAL_C_EXAMPLES}" = "Xyes" && test -d ${srcdir}/examples/ida/serial ; then
+ if test "X${LAPACK_ENABLED}" = "Xyes"; then
+ AC_CONFIG_COMMANDS([ida_ser_ex_bl],
+ [
+ IN_FILE="examples/ida/serial/Makefile_ex"
+ SOLVER="IDA"
+ SOLVER_LIB="sundials_ida"
+ SOLVER_FLIB=""
+ EXAMPLES="idaFoodWeb_bnd idaHeat2D_bnd idaHeat2D_kry idaKrylovDemo_ls idaRoberts_dns idaSlCrank_dns"
+ EXAMPLES_BL=""
+ ${SHELL} bin/makefile-update.sh "${IN_FILE}" "${SOLVER}" "${EXAMPLES}" "${EXAMPLES_BL}" "${SOLVER_LIB}" "${SOLVER_FLIB}"
+ ])
+ else
+ AC_CONFIG_COMMANDS([ida_ser_ex],
+ [
+ IN_FILE="examples/ida/serial/Makefile_ex"
+ SOLVER="IDA"
+ SOLVER_LIB="sundials_ida"
+ SOLVER_FLIB=""
+ EXAMPLES="idaFoodWeb_bnd idaHeat2D_bnd idaHeat2D_kry idaKrylovDemo_ls idaRoberts_dns idaSlCrank_dns"
+ EXAMPLES_BL=""
+ ${SHELL} bin/makefile-update.sh "${IN_FILE}" "${SOLVER}" "${EXAMPLES}" "${EXAMPLES_BL}" "${SOLVER_LIB}" "${SOLVER_FLIB}"
+ ])
+ fi
+ fi
+
+ if test "X${SERIAL_F77_EXAMPLES}" = "Xyes" && test -d ${srcdir}/examples/ida/fcmix_serial ; then
+ if test "X${LAPACK_ENABLED}" = "Xyes"; then
+ AC_CONFIG_COMMANDS([ida_fser_ex_bl],
+ [
+ IN_FILE="examples/ida/fcmix_serial/Makefile_ex"
+ SOLVER="IDA"
+ SOLVER_LIB="sundials_ida"
+ SOLVER_FLIB="sundials_fida"
+ EXAMPLES="fidaRoberts_dns"
+ EXAMPLES_BL=""
+ ${SHELL} bin/makefile-update.sh "${IN_FILE}" "${SOLVER}" "${EXAMPLES}" "${EXAMPLES_BL}" "${SOLVER_LIB}" "${SOLVER_FLIB}"
+ ])
+ else
+ AC_CONFIG_COMMANDS([ida_fser_ex],
+ [
+ IN_FILE="examples/ida/fcmix_serial/Makefile_ex"
+ SOLVER="IDA"
+ SOLVER_LIB="sundials_ida"
+ SOLVER_FLIB="sundials_fida"
+ EXAMPLES="fidaRoberts_dns"
+ EXAMPLES_BL=""
+ ${SHELL} bin/makefile-update.sh "${IN_FILE}" "${SOLVER}" "${EXAMPLES}" "${EXAMPLES_BL}" "${SOLVER_LIB}" "${SOLVER_FLIB}"
+ ])
+ fi
+ fi
+
+ if test "X${PARALLEL_C_EXAMPLES}" = "Xyes" && test -d ${srcdir}/examples/ida/parallel ; then
+ AC_CONFIG_COMMANDS([ida_par_ex],
+ [
+ IN_FILE="examples/ida/parallel/Makefile_ex"
+ SOLVER="IDA"
+ SOLVER_LIB="sundials_ida"
+ SOLVER_FLIB=""
+ EXAMPLES="idaFoodWeb_kry_bbd_p idaFoodWeb_kry_p idaHeat2D_kry_bbd_p idaHeat2D_kry_p"
+ EXAMPLES_BL=""
+ ${SHELL} bin/makefile-update.sh "${IN_FILE}" "${SOLVER}" "${EXAMPLES}" "${EXAMPLES_BL}" "${SOLVER_LIB}" "${SOLVER_FLIB}"
+ ])
+ fi
+
+ if test "X${PARALLEL_F77_EXAMPLES}" = "Xyes" && test -d ${srcdir}/examples/ida/fcmix_parallel ; then
+ AC_CONFIG_COMMANDS([ida_fpar_ex],
+ [
+ IN_FILE="examples/ida/fcmix_parallel/Makefile_ex"
+ SOLVER="IDA"
+ SOLVER_LIB="sundials_ida"
+ SOLVER_FLIB="sundials_fida"
+ EXAMPLES="fidaHeat2D_kry_bbd_p"
+ EXAMPLES_BL=""
+ ${SHELL} bin/makefile-update.sh "${IN_FILE}" "${SOLVER}" "${EXAMPLES}" "${EXAMPLES_BL}" "${SOLVER_LIB}" "${SOLVER_FLIB}"
+ ])
+ fi
+
+fi
+
+
+# IDAS module
+if test "X${IDAS_ENABLED}" = "Xyes"; then
+
+ if test "X${SERIAL_C_EXAMPLES}" = "Xyes" && test -d ${srcdir}/examples/idas/serial ; then
+ if test "X${LAPACK_ENABLED}" = "Xyes"; then
+ AC_CONFIG_COMMANDS([idas_ser_ex_bl],
+ [
+ IN_FILE="examples/idas/serial/Makefile_ex"
+ SOLVER="IDAS"
+ SOLVER_LIB="sundials_idas"
+ SOLVER_FLIB=""
+ EXAMPLES="idasAkzoNob_ASAi_dns idasFoodWeb_bnd idasHeat2D_kry idasKrylovDemo_ls idasRoberts_dns idasSlCrank_dns idasAkzoNob_dns idasHeat2D_bnd idasHessian_ASA_FSA idasRoberts_ASAi_dns idasRoberts_FSA_dns idasSlCrank_FSA_dns"
+ EXAMPLES_BL=""
+ ${SHELL} bin/makefile-update.sh "${IN_FILE}" "${SOLVER}" "${EXAMPLES}" "${EXAMPLES_BL}" "${SOLVER_LIB}" "${SOLVER_FLIB}"
+ ])
+ else
+ AC_CONFIG_COMMANDS([idas_ser_ex],
+ [
+ IN_FILE="examples/idas/serial/Makefile_ex"
+ SOLVER="IDAS"
+ SOLVER_LIB="sundials_idas"
+ SOLVER_FLIB=""
+ EXAMPLES="idasAkzoNob_ASAi_dns idasFoodWeb_bnd idasHeat2D_kry idasKrylovDemo_ls idasRoberts_dns idasSlCrank_dns idasAkzoNob_dns idasHeat2D_bnd idasHessian_ASA_FSA idasRoberts_ASAi_dns idasRoberts_FSA_dns idasSlCrank_FSA_dns"
+ EXAMPLES_BL=""
+ ${SHELL} bin/makefile-update.sh "${IN_FILE}" "${SOLVER}" "${EXAMPLES}" "${EXAMPLES_BL}" "${SOLVER_LIB}" "${SOLVER_FLIB}"
+ ])
+ fi
+ fi
+
+ if test "X${PARALLEL_C_EXAMPLES}" = "Xyes" && test -d ${srcdir}/examples/idas/parallel ; then
+ AC_CONFIG_COMMANDS([idas_par_ex],
+ [
+ IN_FILE="examples/idas/parallel/Makefile_ex"
+ SOLVER="IDAS"
+ SOLVER_LIB="sundials_idas"
+ SOLVER_FLIB=""
+ EXAMPLES="idasBruss_ASAp_kry_bbd_p idasBruss_kry_bbd_p idasFoodWeb_kry_p idasHeat2D_kry_bbd_p idasBruss_FSA_kry_bbd_p idasFoodWeb_kry_bbd_p idasHeat2D_FSA_kry_bbd_p idasHeat2D_kry_p"
+ EXAMPLES_BL=""
+ ${SHELL} bin/makefile-update.sh "${IN_FILE}" "${SOLVER}" "${EXAMPLES}" "${EXAMPLES_BL}" "${SOLVER_LIB}" "${SOLVER_FLIB}"
+ ])
+ fi
+
+fi
+
+
+# KINSOL module
+if test "X${KINSOL_ENABLED}" = "Xyes"; then
+
+ if test "X${SERIAL_C_EXAMPLES}" = "Xyes" && test -d ${srcdir}/examples/kinsol/serial ; then
+ if test "X${LAPACK_ENABLED}" = "Xyes"; then
+ AC_CONFIG_COMMANDS([kinsol_ser_ex_bl],
+ [
+ IN_FILE="examples/kinsol/serial/Makefile_ex"
+ SOLVER="KINSOL"
+ SOLVER_LIB="sundials_kinsol"
+ SOLVER_FLIB=""
+ EXAMPLES="kinFerTron_dns kinFoodWeb_kry kinKrylovDemo_ls kinLaplace_bnd kinRoboKin_dns"
+ EXAMPLES_BL=""
+ ${SHELL} bin/makefile-update.sh "${IN_FILE}" "${SOLVER}" "${EXAMPLES}" "${EXAMPLES_BL}" "${SOLVER_LIB}" "${SOLVER_FLIB}"
+ ])
+ else
+ AC_CONFIG_COMMANDS([kinsol_ser_ex],
+ [
+ IN_FILE="examples/kinsol/serial/Makefile_ex"
+ SOLVER="KINSOL"
+ SOLVER_LIB="sundials_kinsol"
+ SOLVER_FLIB=""
+ EXAMPLES="kinFerTron_dns kinFoodWeb_kry kinKrylovDemo_ls kinLaplace_bnd kinRoboKin_dns"
+ EXAMPLES_BL=""
+ ${SHELL} bin/makefile-update.sh "${IN_FILE}" "${SOLVER}" "${EXAMPLES}" "${EXAMPLES_BL}" "${SOLVER_LIB}" "${SOLVER_FLIB}"
+ ])
+ fi
+ fi
+
+ if test "X${SERIAL_F77_EXAMPLES}" = "Xyes" && test -d ${srcdir}/examples/kinsol/fcmix_serial ; then
+ if test "X${LAPACK_ENABLED}" = "Xyes"; then
+ AC_CONFIG_COMMANDS([kinsol_fser_ex_bl],
+ [
+ IN_FILE="examples/kinsol/fcmix_serial/Makefile_ex"
+ SOLVER="KINSOL"
+ SOLVER_LIB="sundials_kinsol"
+ SOLVER_FLIB="sundials_fkinsol"
+ EXAMPLES="fkinDiagon_kry"
+ EXAMPLES_BL=""
+ ${SHELL} bin/makefile-update.sh "${IN_FILE}" "${SOLVER}" "${EXAMPLES}" "${EXAMPLES_BL}" "${SOLVER_LIB}" "${SOLVER_FLIB}"
+ ])
+ else
+ AC_CONFIG_COMMANDS([kinsol_fser_ex],
+ [
+ IN_FILE="examples/kinsol/fcmix_serial/Makefile_ex"
+ SOLVER="KINSOL"
+ SOLVER_LIB="sundials_kinsol"
+ SOLVER_FLIB="sundials_fkinsol"
+ EXAMPLES="fkinDiagon_kry"
+ EXAMPLES_BL=""
+ ${SHELL} bin/makefile-update.sh "${IN_FILE}" "${SOLVER}" "${EXAMPLES}" "${EXAMPLES_BL}" "${SOLVER_LIB}" "${SOLVER_FLIB}"
+ ])
+ fi
+ fi
+
+ if test "X${PARALLEL_C_EXAMPLES}" = "Xyes" && test -d ${srcdir}/examples/kinsol/parallel ; then
+ AC_CONFIG_COMMANDS([kinsol_par_ex],
+ [
+ IN_FILE="examples/kinsol/parallel/Makefile_ex"
+ SOLVER="KINSOL"
+ SOLVER_LIB="sundials_kinsol"
+ SOLVER_FLIB=""
+ EXAMPLES="kinFoodWeb_kry_bbd_p kinFoodWeb_kry_p"
+ EXAMPLES_BL=""
+ ${SHELL} bin/makefile-update.sh "${IN_FILE}" "${SOLVER}" "${EXAMPLES}" "${EXAMPLES_BL}" "${SOLVER_LIB}" "${SOLVER_FLIB}"
+ ])
+ fi
+
+ if test "X${PARALLEL_F77_EXAMPLES}" = "Xyes" && test -d ${srcdir}/examples/kinsol/fcmix_parallel ; then
+ AC_CONFIG_COMMANDS([kinsol_fpar_ex],
+ [
+ IN_FILE="examples/kinsol/fcmix_parallel/Makefile_ex"
+ SOLVER="KINSOL"
+ SOLVER_LIB="sundials_kinsol"
+ SOLVER_FLIB="sundials_fkinsol"
+ EXAMPLES="fkinDiagon_kry_p"
+ EXAMPLES_BL=""
+ ${SHELL} bin/makefile-update.sh "${IN_FILE}" "${SOLVER}" "${EXAMPLES}" "${EXAMPLES_BL}" "${SOLVER_LIB}" "${SOLVER_FLIB}"
+ ])
+ fi
+
+fi
+
+
+# CPODES module
+if test "X${CPODES_ENABLED}" = "Xyes"; then
+
+ if test "X${SERIAL_C_EXAMPLES}" = "Xyes" && test -d ${srcdir}/examples/cpodes/serial ; then
+ if test "X${LAPACK_ENABLED}" = "Xyes"; then
+ AC_CONFIG_COMMANDS([cpodes_ser_ex_bl],
+ [
+ IN_FILE="examples/cpodes/serial/Makefile_ex"
+ SOLVER="CPODES"
+ SOLVER_LIB="sundials_cpodes"
+ SOLVER_FLIB=""
+ EXAMPLES="cpsAdvDiff_bnd cpsAdvDiff_non cpsNewtCrd_dns cpsPend_dns cpsRoberts_dns cpsVanDPol_non"
+ EXAMPLES_BL="cpsAdvDiff_bndL cpsPend_dnsL cpsRoberts_dnsL"
+ ${SHELL} bin/makefile-update.sh "${IN_FILE}" "${SOLVER}" "${EXAMPLES}" "${EXAMPLES_BL}" "${SOLVER_LIB}" "${SOLVER_FLIB}"
+ ])
+ else
+ AC_CONFIG_COMMANDS([cpodes_ser_ex],
+ [
+ IN_FILE="examples/cpodes/serial/Makefile_ex"
+ SOLVER="CPODES"
+ SOLVER_LIB="sundials_cpodes"
+ SOLVER_FLIB=""
+ EXAMPLES="cpsAdvDiff_bnd cpsAdvDiff_non cpsNewtCrd_dns cpsPend_dns cpsRoberts_dns cpsVanDPol_non"
+ EXAMPLES_BL=""
+ ${SHELL} bin/makefile-update.sh "${IN_FILE}" "${SOLVER}" "${EXAMPLES}" "${EXAMPLES_BL}" "${SOLVER_LIB}" "${SOLVER_FLIB}"
+ ])
+ fi
+ fi
+
+ if test "X${PARALLEL_C_EXAMPLES}" = "Xyes" && test -d ${srcdir}/examples/cpodes/parallel ; then
+ AC_CONFIG_COMMANDS([cpodes_par_ex],
+ [
+ IN_FILE="examples/cpodes/parallel/Makefile_ex"
+ SOLVER="CPODES"
+ SOLVER_LIB="sundials_cpodes"
+ SOLVER_FLIB=""
+ EXAMPLES="cpsHeat2D_kry_bbd_p"
+ EXAMPLES_BL=""
+ ${SHELL} bin/makefile-update.sh "${IN_FILE}" "${SOLVER}" "${EXAMPLES}" "${EXAMPLES_BL}" "${SOLVER_LIB}" "${SOLVER_FLIB}"
+ ])
+ fi
+
+fi
+
+]) dnl END SUNDIALS_POST_PROCESSING
+
+#------------------------------------------------------------------
+# PRINT STATUS REPORT
+#------------------------------------------------------------------
+
+AC_DEFUN([SUNDIALS_REPORT],
+[
+
+if test "X${SUNDIALS_WARN_FLAG}" = "Xyes"; then
+echo "
+***************
+* WARNING *
+***************
+
+At least one warning was issued. Some features were disabled.
+
+Review the configure output and/or the contents of config.log
+before proceeding with the build.
+"
+fi
+
+echo "
+------------------------------
+SUNDIALS Configuration Summary
+------------------------------"
+
+echo "
+Configuration
+-------------
+
+ Host System: ${host}
+ Build System: ${build}
+
+ C Preprocessor: ${CPP}
+ C Preprocessor Flags: ${CPPFLAGS}
+ C Compiler: ${CC}
+ C Compiler Flags ${CFLAGS}
+ C Linker: ${CC}
+ Linker Flags: ${LDFLAGS}
+ Libraries: ${LIBS}"
+
+if test "X${F77_OK}" = "Xyes"; then
+echo "
+ Fortran Compiler: ${F77}
+ Fortran Compiler Flags: ${FFLAGS}
+ Fortran Linker: ${F77_LNKR}
+ Extra Fortran Libraries: ${FLIBS}"
+fi
+
+if test "X${MPI_ENABLED}" = "Xyes" && test "X${MPI_C_COMP_OK}" = "Xyes"; then
+echo "
+ MPI Root Directory: ${MPI_ROOT_DIR}
+ MPI Include Directory: ${MPI_INC_DIR}
+ MPI Library Directory: ${MPI_LIB_DIR}
+ MPI Flags: ${MPI_FLAGS}
+ Extra MPI Libraries: ${MPI_LIBS}
+
+ Using MPI-C script? ${USE_MPICC_SCRIPT}
+ MPI-C: ${MPICC}"
+fi
+
+if test "X${MPI_ENABLED}" = "Xyes" && test "X${F77_EXAMPLES_ENABLED}" = "Xyes" && test "X${MPI_F77_COMP_OK}" = "Xyes"; then
+echo "
+ Using MPI-Fortran script? ${USE_MPIF77_SCRIPT}
+ MPI-Fortran: ${MPIF77}
+ MPI-Fortran Linker: ${MPIF77_LNKR}"
+fi
+
+# Determine SOURCE, BUILD, and EXEC_PREFIX directories
+cv_srcdir=`( cd ${srcdir} ; pwd )`
+cv_builddir=`pwd`
+if test "X${exec_prefix}" = "XNONE"; then
+ cv_exec_prefix="${prefix}"
+else
+ cv_exec_prefix="${exec_prefix}"
+fi
+
+echo "
+ srcdir: ${cv_srcdir}
+ builddir: ${cv_builddir}
+ prefix: ${prefix}
+ exec_prefix: ${cv_exec_prefix}
+ includedir: ${includedir}
+ libdir: ${libdir}"
+
+if test "X${EXAMPLES_ENABLED}" = "Xyes"; then
+echo " examples installed in: ${EXS_INSTDIR}"
+fi
+
+echo "
+Modules
+-------
+"
+
+if test "X${CVODE_ENABLED}" = "Xyes"; then
+ THIS_LINE="CVODE"
+ if test "X${FCMIX_ENABLED}" = "Xyes"; then
+ THIS_LINE="${THIS_LINE} FCVODE"
+ fi
+ echo " ${THIS_LINE}"
+fi
+
+if test "X${CVODES_ENABLED}" = "Xyes"; then
+ THIS_LINE="CVODES"
+ echo " ${THIS_LINE}"
+fi
+
+if test "X${IDA_ENABLED}" = "Xyes"; then
+ THIS_LINE="IDA"
+ if test "X${FCMIX_ENABLED}" = "Xyes"; then
+ THIS_LINE="${THIS_LINE} FIDA"
+ fi
+ echo " ${THIS_LINE}"
+fi
+
+if test "X${IDAS_ENABLED}" = "Xyes"; then
+ THIS_LINE="IDAS"
+ echo " ${THIS_LINE}"
+fi
+
+if test "X${KINSOL_ENABLED}" = "Xyes"; then
+ THIS_LINE="KINSOL"
+ if test "X${FCMIX_ENABLED}" = "Xyes"; then
+ THIS_LINE="${THIS_LINE} FKINSOL"
+ fi
+ echo " ${THIS_LINE}"
+fi
+
+if test "X${CPODES_ENABLED}" = "Xyes"; then
+ THIS_LINE="CPODES"
+ echo " ${THIS_LINE}"
+fi
+
+if test "X${EXAMPLES_ENABLED}" = "Xyes"; then
+echo "
+Examples
+--------
+"
+
+echo " Serial C examples: ${SERIAL_C_EXAMPLES}"
+echo " Parallel C examples: ${PARALLEL_C_EXAMPLES}"
+echo " Serial Fortran examples: ${SERIAL_F77_EXAMPLES}"
+echo " Parallel Fortran examples: ${PARALLEL_F77_EXAMPLES}"
+
+fi
+
+
+echo "
+ Type 'make' and then 'make install' to build and install ${PACKAGE_STRING}."
+
+
+
+echo "
+----------------------------------
+Finished SUNDIALS Configure Script
+----------------------------------
+"
+
+]) dnl END SUNDIALS_REPORT
diff --git a/bin/fortran-update.in b/bin/fortran-update.in
new file mode 100644
index 0000000..744372d
--- /dev/null
+++ b/bin/fortran-update.in
@@ -0,0 +1,490 @@
+# -----------------------------------------------------------------
+# $Revision: 1.1 $
+# $Date: 2007/01/30 15:23:24 $
+# -----------------------------------------------------------------
+# Programmer(s): Aaron Collier @ LLNL
+# -----------------------------------------------------------------
+# Copyright (c) 2002, The Regents of the University of California.
+# Produced at the Lawrence Livermore National Laboratory.
+# All rights reserved.
+# For details, see the LICENSE file.
+# -----------------------------------------------------------------
+# This script updates Fortran source code according to the level
+# of precision specified using the --with-precision option. It also
+# updates variable type specifiers according to the sizes of the
+# C types 'long int' and 'int' and the SUNDIALS-specific type
+# 'realtype'.
+# -----------------------------------------------------------------
+# Notes:
+#
+# (1) The environment variable F77_KEYWORD_LIST should contain
+# a list of all intrinsic functions/procedures used in the
+# Fortran examples (defined under 'update' target).
+#
+# (2) F77_MPI_REAL_* is set to MPI_REAL#, where # is the number
+# of bytes in realtype (SUNDIALS-specific data type). However,
+# if MPI_REAL# is NOT defined in the header file 'mpif.h',
+# then MPI_REAL is used instead. Also, if the file 'mpif.h'
+# does NOT exist under the directory MPI_INC_DIR, then
+# MPI_REAL# is still used, but there is NO guarantee that
+# it is actually defined. Of course, the problem can easily
+# be avoided by adding -I<mpi_inc_dir> to FFLAGS or
+# --with-fflags.
+# -----------------------------------------------------------------
+
+SAVED_LC_ALL="${LC_ALL}"
+LC_ALL="C"
+
+abs_top_builddir="@abs_top_builddir@"
+prefix="@prefix@"
+includedir="@includedir@"
+
+FLOAT_TYPE="@FLOAT_TYPE@"
+
+MPI_INC_DIR="@MPI_INC_DIR@"
+
+EGREP="@EGREP@"
+FGREP="@FGREP@"
+
+MPI_COMM_F2C="@F77_MPI_COMM_F2C@"
+TEMP_A=`echo "${MPI_COMM_F2C}" | ${FGREP} "#define SUNDIALS_MPI_COMM_F2C 1"`
+if test "X${TEMP_A}" = "X"; then
+ USE_MPI_COMM_F2C_EXT="no"
+else
+ USE_MPI_COMM_F2C_EXT="yes"
+fi
+
+INSTALL="@INSTALL@"
+TEMP_INSTALL=`echo "${INSTALL}" | cut -d' ' -f1`
+if test -f ${TEMP_INSTALL} ; then
+ :
+else
+ INSTALL="${abs_top_builddir}/config/${INSTALL}"
+fi
+CP_FILE="@INSTALL_DATA@"
+
+srcdir="${1}"
+SOURCE_FILE="${2}"
+
+builddir="."
+
+F77_KEYWORD_LIST="FLOAT/DBLE/QFLOAT,float/dble/qfloat SIN/DSIN/QSIN,sin/dsin/qsin"
+F77_KEYWORD_LIST="${F77_KEYWORD_LIST} EXP/DEXP/QEXP,exp/dexp/qexp"
+F77_KEYWORD_LIST="${F77_KEYWORD_LIST} ABS/DABS/QABS,abs/dabs/qabs"
+F77_KEYWORD_LIST="${F77_KEYWORD_LIST} AMAX1/DMAX1/QMAX1,amax1/dmax1/qmax1"
+
+TEMP_A=`${FGREP} "#define SIZEOF_INT 4" ${abs_top_builddir}/config.h`
+if test "X${TEMP_A}" = "X"; then
+ TEMP_A=`${FGREP} "#define SIZEOF_INT 8" ${abs_top_builddir}/config.h`
+ if test "X${TEMP_A}" = "X"; then
+ INT_BYTES="4"
+ else
+ INT_BYTES="8"
+ fi
+else
+ INT_BYTES="4"
+fi
+F77_INT_UPPER="INTEGER\*${INT_BYTES}"
+F77_INT_LOWER="integer\*${INT_BYTES}"
+TEMP_A=`${FGREP} "#define SIZEOF_LONG_INT 4" ${abs_top_builddir}/config.h`
+if test "X${TEMP_A}" = "X"; then
+ TEMP_A=`${FGREP} "#define SIZEOF_LONG_INT 8" ${abs_top_builddir}/config.h`
+ if test "X${TEMP_A}" = "X"; then
+ LONG_INT_BYTES="4"
+ else
+ LONG_INT_BYTES="8"
+ fi
+else
+ LONG_INT_BYTES="4"
+fi
+F77_LONG_INT_UPPER="INTEGER\*${LONG_INT_BYTES}"
+F77_LONG_INT_LOWER="integer\*${LONG_INT_BYTES}"
+if test "X${FLOAT_TYPE}" = "Xsingle"; then
+ TEMP_A=`${FGREP} "#define SIZEOF_FLOAT 4" ${abs_top_builddir}/config.h`
+ if test "X${TEMP_A}" = "X"; then
+ TEMP_A=`${FGREP} "#define SIZEOF_FLOAT 8" ${abs_top_builddir}/config.h`
+ if test "X${TEMP_A}" = "X"; then
+ TEMP_A=`${FGREP} "#define SIZEOF_FLOAT 16" ${abs_top_builddir}/config.h`
+ if test "X${TEMP_A}" = "X"; then
+ FLOAT_BYTES=""
+ else
+ FLOAT_BYTES="16"
+ fi
+ else
+ FLOAT_BYTES="8"
+ fi
+ else
+ FLOAT_BYTES="4"
+ fi
+elif test "X${FLOAT_TYPE}" = "Xdouble"; then
+ TEMP_A=`${FGREP} "#define SIZEOF_DOUBLE 4" ${abs_top_builddir}/config.h`
+ if test "X${TEMP_A}" = "X"; then
+ TEMP_A=`${FGREP} "#define SIZEOF_DOUBLE 8" ${abs_top_builddir}/config.h`
+ if test "X${TEMP_A}" = "X"; then
+ TEMP_A=`${FGREP} "#define SIZEOF_DOUBLE 16" ${abs_top_builddir}/config.h`
+ if test "X${TEMP_A}" = "X"; then
+ FLOAT_BYTES=""
+ else
+ FLOAT_BYTES="16"
+ fi
+ else
+ FLOAT_BYTES="8"
+ fi
+ else
+ FLOAT_BYTES="4"
+ fi
+elif test "X${FLOAT_TYPE}" = "Xextended"; then
+ TEMP_A=`${FGREP} "#define SIZEOF_LONG_DOUBLE 4" ${abs_top_builddir}/config.h`
+ if test "X${TEMP_A}" = "X"; then
+ TEMP_A=`${FGREP} "#define SIZEOF_LONG_DOUBLE 8" ${abs_top_builddir}/config.h`
+ if test "X${TEMP_A}" = "X"; then
+ TEMP_A=`${FGREP} "#define SIZEOF_LONG_DOUBLE 16" ${abs_top_builddir}/config.h`
+ if test "X${TEMP_A}" = "X"; then
+ FLOAT_BYTES=""
+ else
+ FLOAT_BYTES="16"
+ fi
+ else
+ FLOAT_BYTES="8"
+ fi
+ else
+ FLOAT_BYTES="4"
+ fi
+fi
+if test "X${FLOAT_BYTES}" = "X" || test "X${FLOAT_TYPE}" = "Xdouble"; then
+ F77_FLOAT_UPPER=""
+ F77_FLOAT_LOWER=""
+elif test "X${FLOAT_TYPE}" = "Xsingle" || test "X${FLOAT_TYPE}" = "Xextended"; then
+ F77_FLOAT_UPPER="REAL\*${FLOAT_BYTES}"
+ F77_FLOAT_LOWER="real\*${FLOAT_BYTES}"
+fi
+if test "X${FLOAT_TYPE}" = "Xsingle"; then
+ C_FLOAT_TYPE="float"
+elif test "X${FLOAT_TYPE}" = "Xdouble"; then
+ C_FLOAT_TYPE="double"
+elif test "X${FLOAT_TYPE}" = "Xextended"; then
+ C_FLOAT_TYPE="long double"
+fi
+TEMP_A=`echo "${srcdir}" | ${FGREP} "examples_par"`
+if test "X${TEMP_A}" = "X"; then
+ :
+else
+ if test -f ${MPI_INC_DIR}/mpif.h ; then
+ TEMP_A=`${FGREP} "MPI_REAL${FLOAT_BYTES}" ${MPI_INC_DIR}/mpif.h`
+ if test "X${TEMP_A}" = "X"; then
+ TEMP_A=`${FGREP} "mpi_real${FLOAT_BYTES}" ${MPI_INC_DIR}/mpif.h`
+ fi
+ if test "X${TEMP_A}" = "X"; then
+ F77_MPI_REAL_UPPER="MPI_REAL"
+ F77_MPI_REAL_LOWER="mpi_real"
+ else
+ F77_MPI_REAL_UPPER="MPI_REAL${FLOAT_BYTES}"
+ F77_MPI_REAL_LOWER="mpi_real${FLOAT_BYTES}"
+ fi
+ else
+ echo ""
+ echo "WARNING: using MPI_REAL${FLOAT_BYTES} since unable to find mpif.h"
+ echo ""
+ F77_MPI_REAL_UPPER="MPI_REAL${FLOAT_BYTES}"
+ F77_MPI_REAL_LOWER="mpi_real${FLOAT_BYTES}"
+ fi
+fi
+if test "X${FLOAT_BYTES}" = "X"; then
+ echo ""
+ echo "WARNING: ${C_FLOAT_TYPE} floating-point data type has NO Fortran equivalent"
+ echo ""
+fi
+if test -f ${srcdir}/${SOURCE_FILE} ; then
+ echo "Updating ${SOURCE_FILE}..."
+ ${CP_FILE} ${srcdir}/${SOURCE_FILE} ${builddir}/temp1.f
+ TEMP_A=`${FGREP} "INTEGER*4" ${builddir}/temp1.f`
+ TEMP_B=`${FGREP} "integer*4" ${builddir}/temp1.f`
+ TEMP_A="${TEMP_A} ${TEMP_B}"
+ for j in ${TEMP_A} ; do
+ TEMP_B=`echo "${j}" | ${FGREP} "INTEGER*4"`
+ F77_CASE="upper"
+ if test "X${TEMP_B}" = "X"; then
+ TEMP_B=`echo "${j}" | ${FGREP} "integer*4"`
+ F77_CASE="lower"
+ fi
+ if test "X${TEMP_B}" = "X"; then
+ :
+ else
+ TEMP1=`echo "${j}" | cut -d'*' -f1`
+ TEMP2=`echo "${j}" | cut -d'*' -f2`
+ j="${TEMP1}\*${TEMP2}"
+ if test "X${F77_CASE}" = "Xupper"; then
+ sed "s,${j},${F77_LONG_INT_UPPER}," ${builddir}/temp1.f > ${builddir}/temp2.f
+ else
+ sed "s,${j},${F77_LONG_INT_LOWER}," ${builddir}/temp1.f > ${builddir}/temp2.f
+ fi
+ ${CP_FILE} ${builddir}/temp2.f ${builddir}/temp1.f
+ fi
+ done
+ TEMP_A=`${FGREP} "INTEGER " ${builddir}/temp1.f`
+ TEMP_B=`${FGREP} "integer " ${builddir}/temp1.f`
+ TEMP_A="${TEMP_A} ${TEMP_B}"
+ for j in ${TEMP_A} ; do
+ TEMP_B=`echo "${j}" | ${FGREP} "INTEGER"`
+ F77_CASE="upper"
+ if test "X${TEMP_B}" = "X"; then
+ TEMP_B=`echo "${j}" | ${FGREP} "integer"`
+ F77_CASE="lower"
+ fi
+ if test "X${TEMP_B}" = "X"; then
+ :
+ else
+ if test "X${F77_CASE}" = "Xupper"; then
+ sed "s,${j} ,${F77_INT_UPPER} ," ${builddir}/temp1.f > ${builddir}/temp2.f
+ else
+ sed "s,${j} ,${F77_INT_LOWER} ," ${builddir}/temp1.f > ${builddir}/temp2.f
+ fi
+ ${CP_FILE} ${builddir}/temp2.f ${builddir}/temp1.f
+ fi
+ done
+ if test "X${FLOAT_TYPE}" = "Xdouble" || test "X${FLOAT_BYTES}" = "X"; then
+ :
+ elif test "X${FLOAT_TYPE}" = "Xsingle"; then
+ CONTINUE="yes"
+ while test "X${CONTINUE}" = "Xyes" ; do
+ TEMP_A=`${FGREP} "DOUBLE PRECISION" ${builddir}/temp1.f`
+ F77_CASE="upper"
+ if test "X${TEMP_A}" = "X"; then
+ TEMP_A=`${FGREP} "double precision" ${builddir}/temp1.f`
+ F77_CASE="lower"
+ fi
+ if test "X${TEMP_A}" = "X"; then
+ CONTINUE="no"
+ else
+ if test "X${F77_CASE}" = "Xupper"; then
+ sed "s,DOUBLE PRECISION,${F77_FLOAT_UPPER}," ${builddir}/temp1.f > ${builddir}/temp2.f
+ else
+ sed "s,double precision,${F77_FLOAT_LOWER}," ${builddir}/temp1.f > ${builddir}/temp2.f
+ fi
+ ${CP_FILE} ${builddir}/temp2.f ${builddir}/temp1.f
+ fi
+ done
+ CONTINUE="yes"
+ while test "X${CONTINUE}" = "Xyes" ; do
+ TEMP_A=`${FGREP} "MPI_DOUBLE_PRECISION" ${builddir}/temp1.f`
+ F77_CASE="upper"
+ if test "X${TEMP_A}" = "X"; then
+ TEMP_A=`${FGREP} "mpi_double_precision" ${builddir}/temp1.f`
+ F77_CASE="lower"
+ fi
+ if test "X${TEMP_A}" = "X"; then
+ CONTINUE="no"
+ else
+ if test "X${F77_CASE}" = "Xupper"; then
+ sed "s,MPI_DOUBLE_PRECISION,${F77_MPI_REAL_UPPER}," ${builddir}/temp1.f > ${builddir}/temp2.f
+ else
+ sed "s,mpi_double_precision,${F77_MPI_REAL_LOWER}," ${builddir}/temp1.f > ${builddir}/temp2.f
+ fi
+ ${CP_FILE} ${builddir}/temp2.f ${builddir}/temp1.f
+ fi
+ done
+ TEMP_A=`${EGREP} "[/]?[[:digit:]]+[.]{1}[[:digit:]]*[dD]{1}[+-]?[[:digit:]]+[/]?" ${builddir}/temp1.f`
+ CONTINUE="yes"
+ while test "X${CONTINUE}" = "Xyes" ; do
+ TEMP_B=`echo "${TEMP_A}" | ${FGREP} ","`
+ if test "X${TEMP_B}" = "X"; then
+ CONTINUE="no"
+ else
+ TEMP_A=`echo "${TEMP_A}" | sed "s,\,, ,"`
+ fi
+ done
+ CONTINUE="yes"
+ while test "X${CONTINUE}" = "Xyes" ; do
+ TEMP_B=`echo "${TEMP_A}" | ${FGREP} "("`
+ if test "X${TEMP_B}" = "X"; then
+ CONTINUE="no"
+ else
+ TEMP_A=`echo "${TEMP_A}" | sed "s,(, ,"`
+ fi
+ done
+ for j in ${TEMP_A} ; do
+ TEMP_B=`echo "${j}" | ${EGREP} "[/]?[[:digit:]]+[.]{1}[[:digit:]]*[dD]{1}[+-]?[[:digit:]]+[/]?"`
+ if test "X${TEMP_B}" = "X"; then
+ :
+ else
+ TEMP_B=`echo "${j}" | ${FGREP} "/"`
+ if test "X${TEMP_B}" = "X"; then
+ TEMP_B=`echo "${j}" | sed "s,D,E,"`
+ TEMP_B=`echo "${TEMP_B}" | sed "s,d,e,"`
+ sed "s,${j},${TEMP_B}," ${builddir}/temp1.f > ${builddir}/temp2.f
+ else
+ TEMP_B=`echo "${j}" | cut -d'/' -f2`
+ TEMP_C=`echo "${TEMP_B}" | sed "s,D,E,"`
+ TEMP_C=`echo "${TEMP_C}" | sed "s,d,e,"`
+ TEMP_C=`echo "${j}" | sed "s,${TEMP_B},${TEMP_C},"`
+ sed "s,${j},${TEMP_C}," ${builddir}/temp1.f > ${builddir}/temp2.f
+ fi
+ ${CP_FILE} ${builddir}/temp2.f ${builddir}/temp1.f
+ fi
+ done
+ for k in ${F77_KEYWORD_LIST} ; do
+ F77_LIST_UPPER=`echo "${k}" | cut -d',' -f1`
+ F77_LIST_LOWER=`echo "${k}" | cut -d',' -f2`
+ DEFAULT_KEYWORD_UPPER=`echo "${F77_LIST_UPPER}" | cut -d'/' -f2`
+ DEFAULT_KEYWORD_LOWER=`echo "${F77_LIST_LOWER}" | cut -d'/' -f2`
+ TEMP_A=`${FGREP} "${DEFAULT_KEYWORD_UPPER}(" ${builddir}/temp1.f`
+ TEMP_B=`${FGREP} "${DEFAULT_KEYWORD_LOWER}(" ${builddir}/temp1.f`
+ TEMP_A="${TEMP_A} ${TEMP_B}"
+ CONTINUE="yes"
+ while test "X${CONTINUE}" = "Xyes" ; do
+ TEMP_B=`echo "${TEMP_A}" | ${FGREP} ","`
+ if test "X${TEMP_B}" = "X"; then
+ CONTINUE="no"
+ else
+ TEMP_A=`echo "${TEMP_A}" | sed "s,\,, ,"`
+ fi
+ done
+ for j in ${TEMP_A} ; do
+ TEMP_B=`echo "${j}" | ${FGREP} "${DEFAULT_KEYWORD_UPPER}("`
+ F77_CASE="upper"
+ if test "X${TEMP_B}" = "X"; then
+ TEMP_B=`echo "${j}" | ${FGREP} "${DEFAULT_KEYWORD_LOWER}("`
+ F77_CASE="lower"
+ fi
+ if test "X${TEMP_B}" = "X"; then
+ :
+ else
+ if test "X${F77_CASE}" = "Xupper"; then
+ TEMP_C=`echo "${F77_LIST_UPPER}" | cut -d'/' -f1`
+ TEMP_B=`echo "${j}" | sed "s,${DEFAULT_KEYWORD_UPPER}(,${TEMP_C}(,"`
+ else
+ TEMP_C=`echo "${F77_LIST_LOWER}" | cut -d'/' -f1`
+ TEMP_B=`echo "${j}" | sed "s,${DEFAULT_KEYWORD_LOWER}(,${TEMP_C}(,"`
+ fi
+ sed "s,${j},${TEMP_B}," ${builddir}/temp1.f > ${builddir}/temp2.f
+ ${CP_FILE} ${builddir}/temp2.f ${builddir}/temp1.f
+ fi
+ done
+ done
+ elif test "X${FLOAT_TYPE}" = "Xextended"; then
+ CONTINUE="yes"
+ while test "X${CONTINUE}" = "Xyes" ; do
+ TEMP_A=`${FGREP} "DOUBLE PRECISION" ${builddir}/temp1.f`
+ F77_CASE="upper"
+ if test "X${TEMP_A}" = "X"; then
+ TEMP_A=`${FGREP} "double precision" ${builddir}/temp1.f`
+ F77_CASE="lower"
+ fi
+ if test "X${TEMP_A}" = "X"; then
+ CONTINUE="no"
+ else
+ if test "X${F77_CASE}" = "Xupper"; then
+ sed "s,DOUBLE PRECISION,${F77_FLOAT_UPPER}," ${builddir}/temp1.f > ${builddir}/temp2.f
+ else
+ sed "s,double precision,${F77_FLOAT_LOWER}," ${builddir}/temp1.f > ${builddir}/temp2.f
+ fi
+ ${CP_FILE} ${builddir}/temp2.f ${builddir}/temp1.f
+ fi
+ done
+ CONTINUE="yes"
+ while test "X${CONTINUE}" = "Xyes" ; do
+ TEMP_A=`${FGREP} "MPI_DOUBLE_PRECISION" ${builddir}/temp1.f`
+ F77_CASE="upper"
+ if test "X${TEMP_A}" = "X"; then
+ TEMP_A=`${FGREP} "mpi_double_precision" ${builddir}/temp1.f`
+ F77_CASE="lower"
+ fi
+ if test "X${TEMP_A}" = "X"; then
+ CONTINUE="no"
+ else
+ if test "X${F77_CASE}" = "Xupper"; then
+ sed "s,MPI_DOUBLE_PRECISION,${F77_MPI_REAL_UPPER}," ${builddir}/temp1.f > ${builddir}/temp2.f
+ else
+ sed "s,mpi_double_precision,${F77_MPI_REAL_LOWER}," ${builddir}/temp1.f > ${builddir}/temp2.f
+ fi
+ ${CP_FILE} ${builddir}/temp2.f ${builddir}/temp1.f
+ fi
+ done
+ if test "X${FLOAT_BYTES}" = "X16"; then
+ for k in ${F77_KEYWORD_LIST} ; do
+ F77_LIST_UPPER=`echo "${k}" | cut -d',' -f1`
+ F77_LIST_LOWER=`echo "${k}" | cut -d',' -f2`
+ DEFAULT_KEYWORD_UPPER=`echo "${F77_LIST_UPPER}" | cut -d'/' -f2`
+ DEFAULT_KEYWORD_LOWER=`echo "${F77_LIST_LOWER}" | cut -d'/' -f2`
+ TEMP_A=`${FGREP} "${DEFAULT_KEYWORD_UPPER}(" ${builddir}/temp1.f`
+ TEMP_B=`${FGREP} "${DEFAULT_KEYWORD_LOWER}(" ${builddir}/temp1.f`
+ TEMP_A="${TEMP_A} ${TEMP_B}"
+ CONTINUE="yes"
+ while test "X${CONTINUE}" = "Xyes" ; do
+ TEMP_B=`echo "${TEMP_A}" | ${FGREP} ","`
+ if test "X${TEMP_B}" = "X"; then
+ CONTINUE="no"
+ else
+ TEMP_A=`echo "${TEMP_A}" | sed "s,\,, ,"`
+ fi
+ done
+ for j in ${TEMP_A} ; do
+ TEMP_B=`echo "${j}" | ${FGREP} "${DEFAULT_KEYWORD_UPPER}("`
+ F77_CASE="upper"
+ if test "X${TEMP_B}" = "X"; then
+ TEMP_B=`echo "${j}" | ${FGREP} "${DEFAULT_KEYWORD_LOWER}("`
+ F77_CASE="lower"
+ fi
+ if test "X${TEMP_B}" = "X"; then
+ :
+ else
+ if test "X${F77_CASE}" = "Xupper"; then
+ TEMP_C=`echo "${F77_LIST_UPPER}" | cut -d'/' -f3`
+ TEMP_B=`echo "${j}" | sed "s,${DEFAULT_KEYWORD_UPPER}(,${TEMP_C}(,"`
+ else
+ TEMP_C=`echo "${F77_LIST_LOWER}" | cut -d'/' -f3`
+ TEMP_B=`echo "${j}" | sed "s,${DEFAULT_KEYWORD_LOWER}(,${TEMP_C}(,"`
+ fi
+ sed "s,${j},${TEMP_B}," ${builddir}/temp1.f > ${builddir}/temp2.f
+ ${CP_FILE} ${builddir}/temp2.f ${builddir}/temp1.f
+ fi
+ done
+ done
+ fi
+ fi
+
+ F77_MPI_KEYWORD_LIST="FNVINITP,fnvinitp FNVINITPQ,fnvinitpq FNVINITPS,fnvinitps"
+ F77_MPI_KEYWORD_LIST="${F77_MPI_KEYWORD_LIST} FNVINITPB,fnvinitpb FNVINITPQB,fnvinitpqb"
+
+ if test "X${USE_MPI_COMM_F2C_EXT}" = "Xno"; then
+ F77_MPI_KEYWORD=""
+ for z in ${F77_MPI_KEYWORD_LIST} ; do
+ F77_MPI_A=`echo "${z}" | cut -d',' -f1`
+ F77_MPI_B=`echo "${z}" | cut -d',' -f2`
+ TEMP_A=`${FGREP} "${F77_MPI_A}(" ${builddir}/temp1.f`
+ if test "X${TEMP_A}" = "X"; then
+ TEMP_A=`${FGREP} "${F77_MPI_B}(" ${builddir}/temp1.f`
+ if test "X${TEMP_A}" = "X"; then
+ F77_SKIP_MPI_UPDATE="yes"
+ else
+ F77_MPI_KEYWORD="${F77_MPI_B}"
+ F77_MPI_CASE="lower"
+ F77_SKIP_MPI_UPDATE="no"
+ fi
+ else
+ F77_MPI_KEYWORD="${F77_MPI_A}"
+ F77_MPI_CASE="upper"
+ F77_SKIP_MPI_UPDATE="no"
+ fi
+ if test "X${F77_SKIP_MPI_UPDATE}" = "Xno"; then
+ break
+ fi
+ done
+ if test "X${F77_SKIP_MPI_UPDATE}" = "Xno"; then
+ if test "X${F77_MPI_CASE}" = "Xupper"; then
+ sed "s,${F77_MPI_KEYWORD}(MPI\_COMM\_WORLD\, ,${F77_MPI_KEYWORD}(0\, ," ${builddir}/temp1.f > ${builddir}/temp2.f
+ ${CP_FILE} ${builddir}/temp2.f ${builddir}/temp1.f
+ else
+ sed "s,${F77_MPI_KEYWORD}(mpi\_comm\_world\, ,${F77_MPI_KEYWORD}(0\, ," ${builddir}/temp1.f > ${builddir}/temp2.f
+ ${CP_FILE} ${builddir}/temp2.f ${builddir}/temp1.f
+ fi
+ fi
+ fi
+
+ SOURCE_FILE=`echo "${SOURCE_FILE}" | cut -d'.' -f1`
+ SOURCE_FILE="${SOURCE_FILE}-updated.f"
+ ${CP_FILE} ${builddir}/temp1.f ${builddir}/${SOURCE_FILE}
+ rm -f ${builddir}/temp1.f ${builddir}/temp2.f
+fi
+
+LC_ALL="${SAVED_LC_ALL}"
diff --git a/bin/makefile-update.in b/bin/makefile-update.in
new file mode 100644
index 0000000..bd7c4b0
--- /dev/null
+++ b/bin/makefile-update.in
@@ -0,0 +1,32 @@
+#! @SHELL@
+# -----------------------------------------------------------------------------------
+# $Revision: 1.2 $
+# $Date: 2007/12/19 20:33:59 $
+# -----------------------------------------------------------------
+# Programmer(s): Radu Serban @ LLNL
+# -----------------------------------------------------------------
+# Copyright (c) 2007, The Regents of the University of California.
+# Produced at the Lawrence Livermore National Laboratory.
+# All rights reserved.
+# For details, see the LICENSE file.
+# -----------------------------------------------------------------
+# This script updates example Makefiles before export.
+# It is called by the configure script, after an initial export
+# Makefile_ex has been created by config.status.
+# -----------------------------------------------------------------
+
+infile="${1}"
+solver="${2}"
+examples="${3}"
+examples_bl="${4}"
+solver_lib="${5}"
+solver_flib="${6}"
+
+sed "s/@SOLVER@/${solver}/" ${infile} | \
+sed "s/@EXAMPLES@/${examples}/" | \
+sed "s/@EXAMPLES_BL@/${examples_bl}/" | \
+sed "s/@SOLVER_LIB@/${solver_lib}/" | \
+sed "s/@SOLVER_FLIB@/${solver_flib}/" > foo_makefile
+
+mv foo_makefile ${infile}
+
diff --git a/bin/sundials-config.in b/bin/sundials-config.in
new file mode 100644
index 0000000..11ff711
--- /dev/null
+++ b/bin/sundials-config.in
@@ -0,0 +1,136 @@
+#! @SHELL@
+# -----------------------------------------------------------------------------------
+
+ NAME_="sundials-config"
+ PURPOSE_="returns required flags for linking to SUNDIALS libraries"
+SYNOPSIS_="$NAME_ -m cvode|cvodes|ida|idas|kinsol -t s|p -l c|f [-s libs|cppflags -hv]"
+REQUIRES_="standard GNU commands"
+ VERSION_="0.1"
+ DATE_="2006-07-25"
+ AUTHOR_="Radu Serban <radu at llnl.gov>"
+
+# -----------------------------------------------------------------------------------
+
+usage () {
+
+echo >&2 "$NAME_ $VERSION_ - $PURPOSE_
+Usage: $SYNOPSIS_
+Requires: $REQUIRES_
+Options:
+ -m cvode|cvodes|ida|idas|kinsol SUNDIALS module
+ -t s|p use serial or parallel vectors
+ -l c|f use C or Fortran
+ -s libs|cppflags show linking flags or C preprocessor flags.
+ (show both if option not given.)
+ -h usage and options (this help)
+ -v view this script
+Notes:
+ '-l f' is not valid for '-m cvodes' or '-m idas'
+ '-s cppflags' returns an empty string for '-l f'"
+ exit 1
+}
+
+
+# args check
+[ $# -eq 0 ] && { echo >&2 missing argument, type $NAME_ -h for help; exit 1; }
+
+# process args
+while getopts hvm:t:l:s: options
+do
+ case $options in
+ m) module=$OPTARG ;;
+ t) vector=$OPTARG ;;
+ l) lang=$OPTARG ;;
+ s) show=$OPTARG ;;
+ h) usage ;;
+ v) more $0; exit 1 ;;
+ \?) echo invalid argument, type $NAME_ -h for help; exit 1 ;;
+ esac
+done
+shift $(( $OPTIND - 1 ))
+
+# args check
+[[ $module ]] || { echo >&2 the -m option and argument must be specified; exit 1; }
+[[ $vector ]] || { echo >&2 the -t option and argument must be specified; exit 1; }
+[[ $lang ]] || { echo >&2 the -l option and argument must be specified; exit 1; }
+[[ $show ]] || { show=both; }
+
+# main
+
+prefix=@prefix@;
+exec_prefix=@exec_prefix@;
+includedir=@includedir@;
+libdir=@libdir@;
+
+abs_includedir=`cd "${includedir}" > /dev/null 2>&1 && pwd`;
+abs_libdir=`cd "${libdir}" > /dev/null 2>&1 && pwd`;
+
+if test $abs_includedir != /usr/include ; then
+ includes=-I$abs_includedir
+fi
+
+libdirs=-L$abs_libdir
+
+case $module in
+ cvode)
+ sun_lib="-lsundials_cvode";
+ sun_flib="-lsundials_fcvode";
+ ;;
+ cvodes)
+ sun_lib="-lsundials_cvodes";
+ sun_flib=;
+ ;;
+ ida)
+ sun_lib="-lsundials_ida";
+ sun_flib="-lsundials_fida";
+ ;;
+ idas)
+ sun_lib="-lsundials_idas";
+ sun_flib=;
+ ;;
+ kinsol)
+ sun_lib="-lsundials_kinsol";
+ sun_flib="-lsundials_fkinsol";
+ ;;
+esac
+
+case $vector in
+ s)
+ nvec_lib="-lsundials_nvecserial";
+ nvec_flib="-lsundials_fnvecserial";
+ ;;
+ p)
+ nvec_lib="-lsundials_nvecparallel";
+ nvec_flib="-lsundials_fnvecparallel";
+ ;;
+esac
+
+case $lang in
+ c)
+ cppflags=$includes;
+ libs="$libdirs $sun_lib $nvec_lib @LIBS@";
+ ;;
+ f)
+ cppflags=;
+ if test $module = cvodes ; then
+ libs="Fortran interface not available for CVODES";
+ else
+ libs="$libdirs $sun_flib $sun_lib $nvec_flib $nvec_lib @LIBS@ @FLIBS@";
+ fi
+ ;;
+esac
+
+case $show in
+ cppflags)
+ echo $cppflags
+ ;;
+ libs)
+ echo $libs
+ ;;
+ both)
+ echo $cppflags
+ echo $libs
+ ;;
+esac
+
+# end script
diff --git a/config.hin b/config.hin
new file mode 100644
index 0000000..4a7e8d2
--- /dev/null
+++ b/config.hin
@@ -0,0 +1,97 @@
+/* config.hin. Generated from configure.ac by autoheader. */
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#undef HAVE_DLFCN_H
+
+/* Define to 1 if you have the <float.h> header file. */
+#undef HAVE_FLOAT_H
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define to 1 if you have the `m' library (-lm). */
+#undef HAVE_LIBM
+
+/* Define to 1 if you have the <math.h> header file. */
+#undef HAVE_MATH_H
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* The size of a `double', as computed by sizeof. */
+#undef SIZEOF_DOUBLE
+
+/* The size of a `float', as computed by sizeof. */
+#undef SIZEOF_FLOAT
+
+/* The size of a `int', as computed by sizeof. */
+#undef SIZEOF_INT
+
+/* The size of a `long double', as computed by sizeof. */
+#undef SIZEOF_LONG_DOUBLE
+
+/* The size of a `long int', as computed by sizeof. */
+#undef SIZEOF_LONG_INT
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Availability of Blas/Lapack libraries */
+#undef SUNDIALS_BLAS_LAPACK
+
+/* Define SUNDIALS data type 'realtype' as 'double' */
+#undef SUNDIALS_DOUBLE_PRECISION
+
+/* Define SUNDIALS data type 'realtype' as 'long double' */
+#undef SUNDIALS_EXTENDED_PRECISION
+
+/* FCMIX: Define name-mangling macro for C identifiers */
+#undef SUNDIALS_F77_FUNC
+
+/* FCMIX: Define name-mangling macro for C identifiers with underscores */
+#undef SUNDIALS_F77_FUNC_
+
+/* FNVECTOR: Allow user to specify different MPI communicator */
+#undef SUNDIALS_MPI_COMM_F2C
+
+/* Define SUNDIALS data type 'realtype' as 'float' */
+#undef SUNDIALS_SINGLE_PRECISION
+
+/* Use generic math functions */
+#undef SUNDIALS_USE_GENERIC_MATH
diff --git a/config/CheckFortranFunctionExists.cmake b/config/CheckFortranFunctionExists.cmake
new file mode 100644
index 0000000..b6b9444
--- /dev/null
+++ b/config/CheckFortranFunctionExists.cmake
@@ -0,0 +1,49 @@
+# - Check if the Fortran function exists.
+# CHECK_FORTRAN_FUNCTION_EXISTS(FUNCTION VARIABLE)
+# - macro which checks if the Fortran function exists
+# FUNCTION - the name of the Fortran function
+# VARIABLE - variable to store the result
+#
+# The following variables may be set before calling this macro to
+# modify the way the check is run:
+#
+# CMAKE_REQUIRED_LIBRARIES = list of libraries to link
+
+macro(CHECK_FORTRAN_FUNCTION_EXISTS FUNCTION VARIABLE)
+ if(NOT DEFINED ${VARIABLE})
+ message(STATUS "Looking for Fortran ${FUNCTION}")
+ if(CMAKE_REQUIRED_LIBRARIES)
+ set(CHECK_FUNCTION_EXISTS_ADD_LIBRARIES
+ "-DLINK_LIBRARIES:STRING=${CMAKE_REQUIRED_LIBRARIES}")
+ else(CMAKE_REQUIRED_LIBRARIES)
+ set(CHECK_FUNCTION_EXISTS_ADD_LIBRARIES)
+ endif(CMAKE_REQUIRED_LIBRARIES)
+ FILE(WRITE
+ ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testFortranCompiler.f
+ "
+ program TESTFortran
+ external ${FUNCTION}
+ end
+ "
+ )
+ try_compile(${VARIABLE}
+ ${CMAKE_BINARY_DIR}
+ ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testFortranCompiler.f
+ CMAKE_FLAGS "${CHECK_FUNCTION_EXISTS_ADD_LIBRARIES}"
+ OUTPUT_VARIABLE OUTPUT
+ )
+ if(${VARIABLE})
+ set(${VARIABLE} 1 CACHE INTERNAL "Have Fortran function ${FUNCTION}")
+ message(STATUS "Looking for Fortran ${FUNCTION} - found")
+ file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
+ "Determining if the Fortran ${FUNCTION} exists passed with the following output:\n"
+ "${OUTPUT}\n\n")
+ else(${VARIABLE})
+ message(STATUS "Looking for Fortran ${FUNCTION} - not found")
+ set(${VARIABLE} "" CACHE INTERNAL "Have Fortran function ${FUNCTION}")
+ file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
+ "Determining if the Fortran ${FUNCTION} exists failed with the following output:\n"
+ "${OUTPUT}\n\n")
+ endif(${VARIABLE})
+ endif(NOT DEFINED ${VARIABLE})
+endmacro(CHECK_FORTRAN_FUNCTION_EXISTS)
diff --git a/config/FindBLAS.cmake b/config/FindBLAS.cmake
new file mode 100644
index 0000000..52f445b
--- /dev/null
+++ b/config/FindBLAS.cmake
@@ -0,0 +1,186 @@
+# - Find BLAS library
+# This module finds an installed fortran library that implements the BLAS
+# linear-algebra interface (see http://www.netlib.org/blas/).
+# The list of libraries searched for is taken
+# from the autoconf macro file, acx_blas.m4 (distributed at
+# http://ac-archive.sourceforge.net/ac-archive/acx_blas.html).
+#
+# This module sets the following variables:
+# BLAS_FOUND - set to true if a library implementing the BLAS interface
+# is found
+# BLAS_LINKER_FLAGS - uncached list of required linker flags (excluding -l
+# and -L).
+# BLAS_LIBRARIES - uncached list of libraries (using full path name) to
+# link against to use BLAS
+#
+
+include(CheckFortranFunctionExists)
+
+macro(Check_Fortran_Libraries LIBRARIES _prefix _name _flags _list)
+# This macro checks for the existence of the combination of fortran libraries
+# given by _list. If the combination is found, this macro checks (using the
+# Check_Fortran_Function_Exists macro) whether can link against that library
+# combination using the name of a routine given by _name using the linker
+# flags given by _flags. If the combination of libraries is found and passes
+# the link test, LIBRARIES is set to the list of complete library paths that
+# have been found. Otherwise, LIBRARIES is set to FALSE.
+
+# N.B. _prefix is the prefix applied to the names of all cached variables that
+# are generated internally and marked advanced by this macro.
+
+set(_libraries_work TRUE)
+set(${LIBRARIES})
+set(_combined_name)
+foreach(_library ${_list})
+ set(_combined_name ${_combined_name}_${_library})
+ if(_libraries_work)
+ find_library(${_prefix}_${_library}_LIBRARY
+ NAMES ${_library}
+ PATHS /usr/local/lib /usr/lib
+ )
+ mark_as_advanced(${_prefix}_${_library}_LIBRARY)
+ set(${LIBRARIES} ${${LIBRARIES}} ${${_prefix}_${_library}_LIBRARY})
+ set(_libraries_work ${${_prefix}_${_library}_LIBRARY})
+ endif(_libraries_work)
+endforeach(_library ${_list})
+if(_libraries_work)
+ # Test this combination of libraries.
+ set(CMAKE_REQUIRED_LIBRARIES ${_flags} ${${LIBRARIES}})
+ #message("DEBUG: CMAKE_REQUIRED_LIBRARIES = ${CMAKE_REQUIRED_LIBRARIES}")
+ check_fortran_function_exists(${_name} ${_prefix}${_combined_name}_WORKS)
+ set(CMAKE_REQUIRED_LIBRARIES)
+ mark_as_advanced(${_prefix}${_combined_name}_WORKS)
+ set(_libraries_work ${${_prefix}${_combined_name}_WORKS})
+endif(_libraries_work)
+if(NOT _libraries_work)
+ set(${LIBRARIES} FALSE)
+endif(NOT _libraries_work)
+#message("DEBUG: ${LIBRARIES} = ${${LIBRARIES}}")
+endmacro(Check_Fortran_Libraries)
+
+set(BLAS_LINKER_FLAGS)
+set(BLAS_LIBRARIES)
+if(NOT BLAS_LIBRARIES)
+ # BLAS in ATLAS library? (http://math-atlas.sourceforge.net/)
+ check_fortran_libraries(
+ BLAS_LIBRARIES
+ BLAS
+ cblas_dgemm
+ ""
+ "cblas;f77blas;atlas"
+ )
+endif(NOT BLAS_LIBRARIES)
+
+# BLAS in PhiPACK libraries? (requires generic BLAS lib, too)
+if(NOT BLAS_LIBRARIES)
+ check_fortran_libraries(
+ BLAS_LIBRARIES
+ BLAS
+ sgemm
+ ""
+ "sgemm;dgemm;blas"
+ )
+endif(NOT BLAS_LIBRARIES)
+
+# BLAS in Alpha CXML library?
+if(NOT BLAS_LIBRARIES)
+ check_fortran_libraries(
+ BLAS_LIBRARIES
+ BLAS
+ sgemm
+ ""
+ "cxml"
+ )
+endif(NOT BLAS_LIBRARIES)
+
+# BLAS in Alpha DXML library? (now called CXML, see above)
+if(NOT BLAS_LIBRARIES)
+ check_fortran_libraries(
+ BLAS_LIBRARIES
+ BLAS
+ sgemm
+ ""
+ "dxml"
+ )
+endif(NOT BLAS_LIBRARIES)
+
+# BLAS in Sun Performance library?
+if(NOT BLAS_LIBRARIES)
+ check_fortran_libraries(
+ BLAS_LIBRARIES
+ BLAS
+ sgemm
+ "-xlic_lib=sunperf"
+ "sunperf;sunmath"
+ )
+ if(BLAS_LIBRARIES)
+ set(BLAS_LINKER_FLAGS "-xlic_lib=sunperf")
+ endif(BLAS_LIBRARIES)
+
+endif(NOT BLAS_LIBRARIES)
+
+# BLAS in SCSL library? (SGI/Cray Scientific Library)
+if(NOT BLAS_LIBRARIES)
+ check_fortran_libraries(
+ BLAS_LIBRARIES
+ BLAS
+ sgemm
+ ""
+ "scsl"
+ )
+endif(NOT BLAS_LIBRARIES)
+
+# BLAS in SGIMATH library?
+if(NOT BLAS_LIBRARIES)
+ check_fortran_libraries(
+ BLAS_LIBRARIES
+ BLAS
+ sgemm
+ ""
+ "complib.sgimath"
+ )
+endif(NOT BLAS_LIBRARIES)
+
+# BLAS in IBM ESSL library? (requires generic BLAS lib, too)
+if(NOT BLAS_LIBRARIES)
+ check_fortran_libraries(
+ BLAS_LIBRARIES
+ BLAS
+ sgemm
+ ""
+ "essl;blas"
+ )
+endif(NOT BLAS_LIBRARIES)
+
+# Generic BLAS library?
+if(NOT BLAS_LIBRARIES)
+ check_fortran_libraries(
+ BLAS_LIBRARIES
+ BLAS
+ sgemm
+ ""
+ "blas"
+ )
+endif(NOT BLAS_LIBRARIES)
+
+if(BLAS_LIBRARIES)
+ set(BLAS_FOUND TRUE)
+else(BLAS_LIBRARIES)
+ set(BLAS_FOUND FALSE)
+endif(BLAS_LIBRARIES)
+
+if(NOT BLAS_FIND_QUIETLY)
+ if(BLAS_FOUND)
+ message(STATUS "A library with BLAS API found.")
+ else(BLAS_FOUND)
+ if(BLAS_FIND_REQUIRED)
+ message(FATAL_ERROR
+ "A library with BLAS API not found. Please specify library location."
+ )
+ else(BLAS_FIND_REQUIRED)
+ message(STATUS
+ "A library with BLAS API not found. Please specify library location."
+ )
+ endif(BLAS_FIND_REQUIRED)
+ endif(BLAS_FOUND)
+endif(NOT BLAS_FIND_QUIETLY)
diff --git a/config/FindLAPACK.cmake b/config/FindLAPACK.cmake
new file mode 100644
index 0000000..8c2ca6e
--- /dev/null
+++ b/config/FindLAPACK.cmake
@@ -0,0 +1,96 @@
+# - Find LAPACK library
+# This module finds an installed fortran library that implements the LAPACK
+# linear-algebra interface (see http://www.netlib.org/lapack/).
+#
+# The approach follows that taken for the autoconf macro file, acx_lapack.m4
+# (distributed at http://ac-archive.sourceforge.net/ac-archive/acx_lapack.html).
+#
+# This module sets the following variables:
+# LAPACK_FOUND - set to true if a library implementing the LAPACK interface
+# is found
+# LAPACK_LINKER_FLAGS - uncached list of required linker flags (excluding -l
+# and -L).
+# LAPACK_LIBRARIES - uncached list of libraries (using full path name) to
+# link against to use LAPACK
+#
+
+include(CheckFortranFunctionExists)
+set(LAPACK_FOUND FALSE)
+
+if(LAPACK_FIND_QUIETLY OR NOT LAPACK_FIND_REQUIRED)
+ find_package(BLAS)
+else(LAPACK_FIND_QUIETLY OR NOT LAPACK_FIND_REQUIRED)
+ find_package(BLAS REQUIRED)
+endif(LAPACK_FIND_QUIETLY OR NOT LAPACK_FIND_REQUIRED)
+
+if(BLAS_FOUND)
+ set(LAPACK_LINKER_FLAGS ${BLAS_LINKER_FLAGS})
+ # LAPACK linked to by default? (is sometimes included in BLAS lib)
+ set(CMAKE_REQUIRED_LIBRARIES ${BLAS_LINKER_FLAGS} ${BLAS_LIBRARIES})
+ check_fortran_function_exists(cheev LAPACK_BLAS_WORKS)
+ mark_as_advanced(LAPACK_BLAS_WORKS)
+ if(LAPACK_BLAS_WORKS)
+ set(LAPACK_FOUND TRUE)
+ set(LAPACK_LIBRARIES ${BLAS_LIBRARIES})
+ endif(LAPACK_BLAS_WORKS)
+ # Generic LAPACK library?
+ if(NOT LAPACK_FOUND)
+ find_library(LAPACK_LAPACK_LIBRARY
+ NAMES lapack
+ PATHS /usr/local/lib /usr/lib
+ )
+ mark_as_advanced(LAPACK_LAPACK_LIBRARY)
+ if(LAPACK_LAPACK_LIBRARY)
+ set(LAPACK_LIBRARIES ${LAPACK_LAPACK_LIBRARY} ${BLAS_LIBRARIES})
+ # Test this combination of libraries.
+ set(CMAKE_REQUIRED_LIBRARIES ${LAPACK_LINKER_FLAGS} ${LAPACK_LIBRARIES})
+ check_fortran_function_exists(cheev LAPACK_LAPACK_WORKS)
+ mark_as_advanced(LAPACK_LAPACK_WORKS)
+ set(CMAKE_REQUIRED_LIBRARIES)
+ if(LAPACK_LAPACK_WORKS)
+ set(LAPACK_FOUND TRUE)
+ else(LAPACK_LAPACK_WORKS)
+ set(LAPACK_LIBRARIES)
+ endif(LAPACK_LAPACK_WORKS)
+ endif(LAPACK_LAPACK_LIBRARY)
+ endif(NOT LAPACK_FOUND)
+ # Generic LAPACK rs6k library?
+ if(NOT LAPACK_FOUND)
+ find_library(LAPACK_RS6K_LIBRARY
+ NAMES lapack_rs6k
+ PATHS /usr/local/lib /usr/lib
+ )
+ mark_as_advanced(LAPACK_RS6K_LIBRARY)
+ if(LAPACK_RS6K_LIBRARY)
+ set(LAPACK_LIBRARIES ${LAPACK_RS6K_LIBRARY} ${BLAS_LIBRARIES})
+ # Test this combination of libraries.
+ set(CMAKE_REQUIRED_LIBRARIES ${LAPACK_LINKER_FLAGS} ${LAPACK_LIBRARIES})
+ check_fortran_function_exists(cheev LAPACK_RS6K_WORKS)
+ mark_as_advanced(LAPACK_RS6K_WORKS)
+ set(CMAKE_REQUIRED_LIBRARIES)
+ if(LAPACK_RS6K_WORKS)
+ set(LAPACK_FOUND TRUE)
+ else(LAPACK_RS6K_WORKS)
+ set(LAPACK_LIBRARIES)
+ endif(LAPACK_RS6K_WORKS)
+ endif(LAPACK_RS6K_LIBRARY)
+ endif(NOT LAPACK_FOUND)
+else(BLAS_FOUND)
+ message(STATUS "LAPACK requires BLAS")
+endif(BLAS_FOUND)
+
+if(NOT LAPACK_FIND_QUIETLY)
+ if(LAPACK_FOUND)
+ message(STATUS "A library with LAPACK API found.")
+ else(LAPACK_FOUND)
+ if(LAPACK_FIND_REQUIRED)
+ message(FATAL_ERROR
+ "A library with LAPACK API not found. Please specify library location."
+ )
+ else(LAPACK_FIND_REQUIRED)
+ message(STATUS
+ "A library with LAPACK API not found. Please specify library location."
+ )
+ endif(LAPACK_FIND_REQUIRED)
+ endif(LAPACK_FOUND)
+endif(NOT LAPACK_FIND_QUIETLY)
diff --git a/config/FindMPI.cmake b/config/FindMPI.cmake
new file mode 100644
index 0000000..f0c5f0c
--- /dev/null
+++ b/config/FindMPI.cmake
@@ -0,0 +1,36 @@
+# - Find MPI
+# This module looks for MPI (Message Passing Interface) support
+# it will define the following values
+# MPI_INCLUDE_PATH = cached location of mpi.h
+# MPI_LIBRARIES = cached list of libraries to link in (mpi mpich etc)
+
+FIND_PATH(MPI_INCLUDE_PATH mpi.h
+ PATHS /usr/local/include
+ /usr/include
+ /usr/include/mpi
+ /usr/local/mpi/include
+ "$ENV{ProgramFiles}/MPICH/SDK/Include"
+ "$ENV{ProgramFiles}/MPICH2/include"
+ "C:/Program Files/MPICH/SDK/Include"
+ )
+
+FIND_LIBRARY(MPI_LIBRARIES
+ NAMES mpich2 mpi mpich
+ PATHS /usr/lib /usr/local/lib /usr/local/mpi/lib
+ "$ENV{ProgramFiles}/MPICH/SDK/Lib"
+ "$ENV{ProgramFiles}/MPICH2/Lib"
+ "C:/Program Files/MPICH/SDK/Lib"
+ )
+
+FIND_LIBRARY(MPI_EXTRA_LIBRARIES
+ NAMES mpi++
+ PATHS /usr/lib /usr/local/lib /usr/local/mpi/lib
+ "$ENV{ProgramFiles}/MPICH/SDK/Lib"
+ "C:/Program Files/MPICH/SDK/Lib"
+ DOC "If a second mpi library is necessary, specify it here.")
+MARK_AS_ADVANCED(MPI_EXTRA_LIBRARIES)
+
+IF(MPI_EXTRA_LIBRARIES)
+ SET(MPI_LIBRARIES ${MPI_LIBRARIES} ${MPI_EXTRA_LIBRARIES})
+ENDIF(MPI_EXTRA_LIBRARIES)
+
diff --git a/config/SundialsFortran.cmake b/config/SundialsFortran.cmake
new file mode 100644
index 0000000..39addcf
--- /dev/null
+++ b/config/SundialsFortran.cmake
@@ -0,0 +1,176 @@
+# ---------------------------------------------------------------
+# $Revision: 1.1 $
+# $Date: 2009/02/17 02:58:46 $
+# ---------------------------------------------------------------
+# Programmer: Radu Serban @ LLNL
+# ---------------------------------------------------------------
+# Copyright (c) 2008, The Regents of the University of California.
+# Produced at the Lawrence Livermore National Laboratory.
+# All rights reserved.
+# For details, see the LICENSE file.
+# ---------------------------------------------------------------
+# Fortran-related tests for SUNDIALS CMake-based configuration.
+#
+# Determining the name-mangling scheme
+# ------------------------------------
+# In general, names of symbols with and without underscore may be mangled
+# differently (e.g. g77 mangles mysub to mysub_ and my_sub to my_sub__),
+# we have to consider both cases.
+# Method:
+# 1) create a library from a Fortran source file which defines a function "mysub"
+# 2) attempt to link with this library a C source file which calls the "mysub"
+# function using various possible schemes (6 different schemes, corresponding
+# to all combinations lower/upper case and none/one/two underscores)
+# 3) define the name-mangling scheme based on the test that was successful.
+# On exit, if we were able to infer the scheme, the variables
+# CMAKE_Fortran_SCHEME_NO_UNDERSCORES and CMAKE_Fortran_SCHEME_WITH_UNDERSCORES
+# contain the mangled names for "mysub" and "my_sub", respectively.
+
+set(F77_FOUND FALSE)
+set(F77SCHEME_FOUND FALSE)
+
+set(CMAKE_Fortran_SCHEME_NO_UNDERSCORES "")
+set(CMAKE_Fortran_SCHEME_WITH_UNDERSCORES "")
+
+include(CMakeDetermineFortranCompiler)
+
+if(CMAKE_Fortran_COMPILER)
+ message(STATUS "Searching for a Fortran compiler... ${CMAKE_Fortran_COMPILER}")
+ # Enable the language for next steps
+ enable_language(Fortran)
+ mark_as_advanced(CLEAR
+ CMAKE_Fortran_COMPILER
+ CMAKE_Fortran_FLAGS
+ CMAKE_Fortran_FLAGS_DEBUG
+ CMAKE_Fortran_FLAGS_MINSIZEREL
+ CMAKE_Fortran_FLAGS_RELEASE
+ CMAKE_Fortran_FLAGS_RELWITHDEB)
+ # 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
+ "PROJECT(ftest Fortran)\n"
+ "SET(CMAKE_VERBOSE_MAKEFILE ON)\n"
+ "SET(CMAKE_BUILD_TYPE \"${CMAKE_BUILD_TYPE}\")\n"
+ "SET(CMAKE_Fortran_FLAGS \"${CMAKE_Fortran_FLAGS}\")\n"
+ "SET(CMAKE_Fortran_FLAGS_RELEASE \"${CMAKE_Fortran_FLAGS_RELEASE}\")\n"
+ "SET(CMAKE_Fortran_FLAGS_DEBUG \"${CMAKE_Fortran_FLAGS_DEBUG}\")\n"
+ "SET(CMAKE_Fortran_FLAGS_RELWITHDEBUGINFO \"${CMAKE_Fortran_FLAGS_RELWITHDEBUGINFO}\")\n"
+ "SET(CMAKE_Fortran_FLAGS_MINSIZE \"${CMAKE_Fortran_FLAGS_MINSIZE}\")\n"
+ "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"
+ " RETURN\n"
+ " END\n"
+ " 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
+ "PROJECT(ctest1 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(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})
+ # Get the current list entry (current scheme)
+ list(GET options ${iopt} opt)
+ # Generate C source which calls the "mysub" function using the current scheme
+ file(WRITE ${FortranTest_DIR}/ctest1.c "int main(){${opt}();return(0);}\n")
+ # Use TRY_COMPILE to make the "ctest1" executable from the current C source
+ # and linking to the previously created "flib" library.
+ try_compile(CTEST_OK ${FortranTest_DIR} ${FortranTest_DIR}
+ ctest1 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)
+ # Test if we successfully created the "ctest" executable.
+ # If yes, save the current scheme, and set the counter "iopt" to "imax"
+ # so that we exit the while loop.
+ # Otherwise, increment the counter "iopt" and go back in the while loop.
+ if(CTEST_OK)
+ set(CMAKE_Fortran_SCHEME_NO_UNDERSCORES ${opt})
+ set(iopt ${imax})
+ else(CTEST_OK)
+ 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
+ "PROJECT(ctest2 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(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)
+ while(${iopt} LESS ${imax})
+ list(GET options ${iopt} opt)
+ file(WRITE ${FortranTest_DIR}/ctest2.c "int main(){${opt}();return(0);}\n")
+ try_compile(CTEST_OK ${FortranTest_DIR} ${FortranTest_DIR}
+ ctest2 OUTPUT_VARIABLE MY_OUTPUT)
+ file(REMOVE_RECURSE ${FortranTest_DIR}/CMakeFiles)
+ if(CTEST_OK)
+ set(CMAKE_Fortran_SCHEME_WITH_UNDERSCORES ${opt})
+ set(iopt ${imax})
+ else(CTEST_OK)
+ 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")
+ set(F77SCHEME_FOUND TRUE)
+ 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/SundialsLapack.cmake b/config/SundialsLapack.cmake
new file mode 100644
index 0000000..aa7a9e4
--- /dev/null
+++ b/config/SundialsLapack.cmake
@@ -0,0 +1,85 @@
+# ---------------------------------------------------------------
+# $Revision: 1.1 $
+# $Date: 2009/02/17 02:58:46 $
+# ---------------------------------------------------------------
+# Programmer: Radu Serban @ LLNL
+# ---------------------------------------------------------------
+# Copyright (c) 2008, The Regents of the University of California.
+# Produced at the Lawrence Livermore National Laboratory.
+# All rights reserved.
+# For details, see the LICENSE file.
+# ---------------------------------------------------------------
+# BLAS/LAPACK tests for SUNDIALS CMake-based configuration.
+#
+#
+
+SET(LAPACK_FOUND FALSE)
+
+# If LAPACK 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 LAPACK_LIBRARIES)
+ if(F77_FOUND)
+ include(FindLAPACK)
+ else(F77_FOUND)
+ find_library(LAPACK_LIBRARIES
+ NAMES lapack
+ PATHS /usr/lib /usr/local/lib
+ "$ENV{ProgramFiles}/LAPACK/Lib"
+ )
+ endif(F77_FOUND)
+endif(NOT LAPACK_LIBRARIES)
+# If using a GNU C compiler, it is quite likely we'll want LAPACK_LINKER_FLAGS
+# to include -lg2c (if not already present)
+if(CMAKE_COMPILER_IS_GNUCC AND NOT LAPACK_LINKER_FLAGS MATCHES "g2c")
+ set(LAPACK_LINKER_FLAGS "${LAPACK_LINKER_FLAGS} -lg2c")
+endif(CMAKE_COMPILER_IS_GNUCC AND NOT LAPACK_LINKER_FLAGS MATCHES "g2c")
+# 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
+ "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"
+ "SET(CMAKE_EXE_LINKER_FLAGS \"\${CMAKE_EXE_LINKER_FLAGS} ${LAPACK_LINKER_FLAGS}\")\n"
+ "ADD_EXECUTABLE(ltest ltest.c)\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"
+ "#define dcopy_f77 SUNDIALS_F77_FUNC(dcopy, DCOPY)\n"
+ "#define dgetrf_f77 SUNDIALS_F77_FUNC(dgetrf, DGETRF)\n"
+ "extern void dcopy_f77(int *n, const double *x, const int *inc_x, double *y, const int *inc_y);\n"
+ "extern void dgetrf_f77(const int *m, const int *n, double *a, int *lda, int *ipiv, int *info);\n"
+ "int main(){\n"
+ "int n=1;\n"
+ "double x, y;\n"
+ "dcopy_f77(&n, &x, &n, &y, &n);\n"
+ "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)
+ # 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")
+ set(LAPACK_FOUND TRUE)
+ else(LTEST_OK)
+ 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
new file mode 100644
index 0000000..c708e68
--- /dev/null
+++ b/config/SundialsMPIC.cmake
@@ -0,0 +1,181 @@
+# ---------------------------------------------------------------
+# $Revision: 1.1 $
+# $Date: 2009/02/17 02:58:46 $
+# ---------------------------------------------------------------
+# Programmer: Radu Serban @ LLNL
+# ---------------------------------------------------------------
+# Copyright (c) 2008, The Regents of the University of California.
+# Produced at the Lawrence Livermore National Laboratory.
+# All rights reserved.
+# For details, see the LICENSE file.
+# ---------------------------------------------------------------
+# MPI-C tests for SUNDIALS CMake-based configuration.
+#
+#
+
+set(MPIC_FOUND FALSE)
+set(MPIC_MPI2 FALSE)
+
+# Local variable indicating whether to test MPI
+set(MPIC_PERFORM_TEST FALSE)
+# By default, we try to use the MPI compiler script
+# Search for the MPICC compiler script
+find_program(MPI_MPICC NAMES mpicc DOC "mpicc program")
+if(MPI_MPICC)
+ message(STATUS "Looking for MPI C compiler script... ${MPI_MPICC}")
+ # Test the MPI compiler script
+ set(MPIC_PERFORM_TEST TRUE)
+else(MPI_MPICC)
+ message(STATUS "Looking for MPI C compiler script... FAILED")
+ # If not already available, search for MPI headers and libraries.
+ # Define the following values
+ # MPI_INCLUDE_PATH = cached location of mpi.h
+ # MPI_LIBRARIES = cached list of libraries to link in (mpi mpich etc)
+ if(NOT MPI_LIBRARIES)
+ find_path(MPI_INCLUDE_PATH mpi.h
+ PATHS /usr/local/include
+ /usr/include
+ /usr/include/mpi
+ /usr/local/mpi/include
+ "$ENV{ProgramFiles}/MPICH/SDK/Include"
+ "$ENV{ProgramFiles}/MPICH2/include"
+ "C:/Program Files/MPICH/SDK/Include"
+ )
+ find_library(MPI_LIBRARIES
+ NAMES mpich2 mpi mpich
+ PATHS /usr/lib /usr/local/lib /usr/local/mpi/lib
+ "$ENV{ProgramFiles}/MPICH/SDK/Lib"
+ "$ENV{ProgramFiles}/MPICH2/Lib"
+ "C:/Program Files/MPICH/SDK/Lib"
+ )
+ find_library(MPI_EXTRA_LIBRARIES
+ NAMES mpi++
+ PATHS /usr/lib /usr/local/lib /usr/local/mpi/lib
+ "$ENV{ProgramFiles}/MPICH/SDK/Lib"
+ "C:/Program Files/MPICH/SDK/Lib"
+ DOC "If a second mpi library is necessary, specify it here.")
+ if(MPI_EXTRA_LIBRARIES)
+ set(MPI_LIBRARIES ${MPI_LIBRARIES} ${MPI_EXTRA_LIBRARIES})
+ endif(MPI_EXTRA_LIBRARIES)
+ endif(NOT MPI_LIBRARIES)
+ if(MPI_LIBRARIES)
+ message(STATUS "Looking for MPI libraries... ${MPI_LIBRARIES}")
+ # Test the MPI libraries
+ set(MPIC_PERFORM_TEST TRUE)
+ else(MPI_LIBRARIES)
+ message(STATUS "Looking for MPI libraries... FAILED")
+ endif(MPI_LIBRARIES)
+endif(MPI_MPICC)
+# If we have what to test, do it now
+if(MPIC_PERFORM_TEST)
+ # Create the MPITest directory
+ set(MPITest_DIR ${PROJECT_BINARY_DIR}/MPITest)
+ file(MAKE_DIRECTORY ${MPITest_DIR})
+ # Create a CMakeLists.txt file which will generate the "mpictest" executable
+ if(MPI_MPICC)
+ file(WRITE ${MPITest_DIR}/CMakeLists.txt
+ "PROJECT(mpictest C)\n"
+ "SET(CMAKE_VERBOSE_MAKEFILE ON)\n"
+ "SET(CMAKE_C_COMPILER ${MPI_MPICC})\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(mpictest mpictest.c)\n")
+ else(MPI_MPICC)
+ file(WRITE ${MPITest_DIR}/CMakeLists.txt
+ "PROJECT(mpictest 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"
+ "INCLUDE_DIRECTORIES(${MPI_INCLUDE_PATH})\n"
+ "ADD_EXECUTABLE(mpictest mpictest.c)\n"
+ "TARGET_LINK_LIBRARIES(mpictest ${MPI_LIBRARIES})\n")
+ endif(MPI_MPICC)
+ # Create a simple C source which only calls the MPI_Init and MPI_Finalize functions
+ file(WRITE ${MPITest_DIR}/mpictest.c
+ "#include <mpi.h>\n"
+ "int main(){\n"
+ "int c;\n"
+ "char **v;\n"
+ "MPI_Init(&c, &v);\n"
+ "MPI_Finalize();\n"
+ "return(0);\n"
+ "}\n")
+ # Use TRY_COMPILE to make the target "mpictest"
+ try_compile(MPITEST_OK ${MPITest_DIR} ${MPITest_DIR}
+ mpitest OUTPUT_VARIABLE MY_OUTPUT)
+ # To ensure we do not use stuff from the previous attempts,
+ # we must remove the CMakeFiles directory.
+ file(REMOVE_RECURSE ${MPITest_DIR}/CMakeFiles)
+ # Process test result
+ if(MPITEST_OK)
+ message(STATUS "Trying to compile and link a simple MPI C program... OK")
+ set(MPIC_FOUND TRUE)
+ else(MPITEST_OK)
+ message(STATUS "Trying to compile and link a simple MPI C program... FAILED")
+ endif(MPITEST_OK)
+endif(MPIC_PERFORM_TEST)
+# Finally, if MPI-C was found and is working,
+# also check if it provides MPI-2 support
+if(MPIC_FOUND)
+ # Create a CMakeLists.txt file which will generate the "mpi2test" executable
+ if(MPI_MPICC)
+ file(WRITE ${MPITest_DIR}/CMakeLists.txt
+ "PROJECT(mpi2test C)\n"
+ "SET(CMAKE_VERBOSE_MAKEFILE ON)\n"
+ "SET(CMAKE_C_COMPILER ${MPI_MPICC})\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(mpi2test mpi2test.c)\n")
+ else(MPI_MPICC)
+ file(WRITE ${MPITest_DIR}/CMakeLists.txt
+ "PROJECT(mpi2test 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"
+ "INCLUDE_DIRECTORIES(${MPI_INCLUDE_PATH})\n"
+ "ADD_EXECUTABLE(mpi2test mpi2test.c)\n"
+ "TARGET_LINK_LIBRARIES(mpi2test ${MPI_LIBRARIES})\n")
+ endif(MPI_MPICC)
+ # Create a simple C source which calls the MPI_Comm_f2c function
+ file(WRITE ${MPITest_DIR}/mpi2test.c
+ "#include <mpi.h>\n"
+ "int main(){\n"
+ "int c;\n"
+ "char **v;\n"
+ "MPI_Comm C_comm;\n"
+ "MPI_Init(&c, &v);\n"
+ "C_comm = MPI_Comm_f2c((MPI_Fint) 1);\n"
+ "MPI_Finalize();\n"
+ "return(0);\n"
+ "}\n")
+ # Use TRY_COMPILE to make the target "mpi2test"
+ try_compile(MPITEST_OK ${MPITest_DIR} ${MPITest_DIR}
+ mpi2test OUTPUT_VARIABLE MY_OUTPUT)
+ # To ensure we do not use stuff from the previous attempts,
+ # we must remove the CMakeFiles directory.
+ FILE(REMOVE_RECURSE ${MPITest_DIR}/CMakeFiles)
+ # Interpret test results
+ if(MPITEST_OK)
+ message(STATUS "Checking for MPI-2 support... OK")
+ set(MPIC_MPI2 TRUE)
+ else(MPITEST_OK)
+ message(STATUS "Checking for MPI-2 support... FAILED")
+ endif(MPITEST_OK)
+endif(MPIC_FOUND)
+
diff --git a/config/SundialsMPIF.cmake b/config/SundialsMPIF.cmake
new file mode 100644
index 0000000..c0a5a43
--- /dev/null
+++ b/config/SundialsMPIF.cmake
@@ -0,0 +1,108 @@
+# ---------------------------------------------------------------
+# $Revision: 1.1 $
+# $Date: 2009/02/17 02:58:46 $
+# ---------------------------------------------------------------
+# Programmer: Radu Serban @ LLNL
+# ---------------------------------------------------------------
+# Copyright (c) 2008, The Regents of the University of California.
+# Produced at the Lawrence Livermore National Laboratory.
+# All rights reserved.
+# For details, see the LICENSE file.
+# ---------------------------------------------------------------
+# MPI-Fortran tests for SUNDIALS CMake-based configuration.
+#
+#
+
+set(MPIF_FOUND FALSE)
+
+# Local variable indicating whether to test MPI
+set(MPIF_PERFORM_TEST FALSE)
+# By default, we try to use the MPI compiler script
+# Search for the MPIF77 compiler script
+find_program(MPI_MPIF77 NAMES mpif77 DOC "mpif77 program")
+if(MPI_MPIF77)
+ message(STATUS "Looking for MPI Fortran compiler script... ${MPI_MPIF77}")
+ # Test the MPI compiler script
+ set(MPIF_PERFORM_TEST TRUE)
+else(MPI_MPIF77)
+ message(STATUS "Looking for MPI Fortran compiler script... FAILED")
+ # If not already available, search for MPI headers and libraries.
+ if(NOT MPI_LIBRARIES)
+ find_path(MPI_INCLUDE_PATH mpi.h
+ PATHS /usr/local/include
+ /usr/include
+ /usr/include/mpi
+ /usr/local/mpi/include
+ "$ENV{ProgramFiles}/MPICH/SDK/Include"
+ "$ENV{ProgramFiles}/MPICH2/include"
+ "C:/Program Files/MPICH/SDK/Include"
+ )
+ find_library(MPI_LIBRARIES
+ NAMES mpich2 mpi mpich
+ PATHS /usr/lib /usr/local/lib /usr/local/mpi/lib
+ "$ENV{ProgramFiles}/MPICH/SDK/Lib"
+ "$ENV{ProgramFiles}/MPICH2/Lib"
+ "C:/Program Files/MPICH/SDK/Lib"
+ )
+ find_library(MPI_EXTRA_LIBRARIES
+ NAMES mpi++
+ PATHS /usr/lib /usr/local/lib /usr/local/mpi/lib
+ "$ENV{ProgramFiles}/MPICH/SDK/Lib"
+ "C:/Program Files/MPICH/SDK/Lib"
+ DOC "If a second mpi library is necessary, specify it here.")
+ if(MPI_EXTRA_LIBRARIES)
+ set(MPI_LIBRARIES ${MPI_LIBRARIES} ${MPI_EXTRA_LIBRARIES})
+ endif(MPI_EXTRA_LIBRARIES)
+ endif(NOT MPI_LIBRARIES)
+ if(MPI_LIBRARIES)
+ message(STATUS "Looking for MPI libraries... ${MPI_LIBRARIES}")
+ # Test the MPI libraries
+ set(MPIF_PERFORM_TEST TRUE)
+ else(MPI_LIBRARIES)
+ message(STATUS "Looking for MPI libraries... FAILED")
+ endif(MPI_LIBRARIES)
+endif(MPI_MPIF77)
+# If we have what to test, do it now
+if(MPIF_PERFORM_TEST)
+ # Create the MPITest directory
+ set(MPITest_DIR ${PROJECT_BINARY_DIR}/MPITest)
+ file(MAKE_DIRECTORY ${MPITest_DIR})
+ # Create a CMakeLists.txt file which will generate the "mpiftest" executable
+ if(MPI_MPIF77)
+ file(WRITE ${MPITest_DIR}/CMakeLists.txt
+ "PROJECT(mpiftest Fortran)\n"
+ "SET(CMAKE_VERBOSE_MAKEFILE ON)\n"
+ "SET(CMAKE_Fortran_COMPILER ${MPI_MPIF77})\n"
+ "SET(CMAKE_Fortran_FLAGS \"${TMP_Fortran_FLAGS}\")\n"
+ "ADD_EXECUTABLE(mpiftest mpiftest.f)\n")
+ else(MPI_MPIF77)
+ file(WRITE ${MPITest_DIR}/CMakeLists.txt
+ "PROJECT(mpiftest Fortran)\n"
+ "SET(CMAKE_VERBOSE_MAKEFILE ON)\n"
+ "SET(CMAKE_Fortran_FLAGS \"${TMP_Fortran_FLAGS}\")\n"
+ "INCLUDE_DIRECTORIES(${MPI_INCLUDE_PATH})\n"
+ "ADD_EXECUTABLE(mpiftest mpiftest.f)\n"
+ "TARGET_LINK_LIBRARIES(mpiftest ${MPI_LIBRARIES})\n")
+ endif(MPI_MPIF77)
+ # Create a simple F77 source which only calls the MPI_Init and MPI_Finalize functions
+ file(WRITE ${MPITest_DIR}/mpiftest.f
+ " INCLUDE \"mpif.h\"\n"
+ " INTEGER IER\n"
+ " CALL MPI_INIT(IER)\n"
+ " CALL MPI_FINALIZE(IER)\n"
+ " STOP\n"
+ " END\n")
+ # Use TRY_COMPILE to make the target "mpiftest"
+ try_compile(MPITEST_OK ${MPITest_DIR} ${MPITest_DIR}
+ mpiftest OUTPUT_VARIABLE MY_OUTPUT)
+ # To ensure we do not use stuff from the previous attempts,
+ # we must remove the CMakeFiles directory.
+ file(REMOVE_RECURSE ${MPITest_DIR}/CMakeFiles)
+ # Process test result
+ if(MPITEST_OK)
+ message(STATUS "Trying to compile and link a simple MPI Fortran program... OK")
+ set(MPIF_FOUND TRUE)
+ else(MPITEST_OK)
+ message(STATUS "Trying to compile and link a simple MPI Fortran program... FAILED")
+ endif(MPITEST_OK)
+endif(MPIF_PERFORM_TEST)
\ No newline at end of file
diff --git a/config/config.guess b/config/config.guess
new file mode 100755
index 0000000..e3ef63f
--- /dev/null
+++ b/config/config.guess
@@ -0,0 +1,1471 @@
+#! /bin/sh
+# Attempt to guess a canonical system name.
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+# 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+
+timestamp='2005-12-13'
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
+# 02110-1301, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+
+# Originally written by Per Bothner <per at bothner.com>.
+# Please send patches to <config-patches at gnu.org>. Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# This script attempts to guess a canonical system name similar to
+# config.sub. If it succeeds, it prints the system name on stdout, and
+# exits with 0. Otherwise, it exits with 1.
+#
+# The plan is that this can be called by configure scripts if you
+# don't specify an explicit build system type.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION]
+
+Output the configuration name of the system \`$me' is run on.
+
+Operation modes:
+ -h, --help print this help, then exit
+ -t, --time-stamp print date of last modification, then exit
+ -v, --version print version number, then exit
+
+Report bugs and patches to <config-patches at gnu.org>."
+
+version="\
+GNU config.guess ($timestamp)
+
+Originally written by Per Bothner.
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+ case $1 in
+ --time-stamp | --time* | -t )
+ echo "$timestamp" ; exit ;;
+ --version | -v )
+ echo "$version" ; exit ;;
+ --help | --h* | -h )
+ echo "$usage"; exit ;;
+ -- ) # Stop option processing
+ shift; break ;;
+ - ) # Use stdin as input.
+ break ;;
+ -* )
+ echo "$me: invalid option $1$help" >&2
+ exit 1 ;;
+ * )
+ break ;;
+ esac
+done
+
+if test $# != 0; then
+ echo "$me: too many arguments$help" >&2
+ exit 1
+fi
+
+trap 'exit 1' 1 2 15
+
+# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
+# compiler to aid in system detection is discouraged as it requires
+# temporary files to be created and, as you can see below, it is a
+# headache to deal with in a portable fashion.
+
+# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
+# use `HOST_CC' if defined, but it is deprecated.
+
+# Portable tmp directory creation inspired by the Autoconf team.
+
+set_cc_for_build='
+trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
+trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
+: ${TMPDIR=/tmp} ;
+ { tmp=`(umask 077 && mktemp -d -q "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
+ { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
+ { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
+ { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
+dummy=$tmp/dummy ;
+tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
+case $CC_FOR_BUILD,$HOST_CC,$CC in
+ ,,) echo "int x;" > $dummy.c ;
+ for c in cc gcc c89 c99 ; do
+ if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then
+ CC_FOR_BUILD="$c"; break ;
+ fi ;
+ done ;
+ if test x"$CC_FOR_BUILD" = x ; then
+ CC_FOR_BUILD=no_compiler_found ;
+ fi
+ ;;
+ ,,*) CC_FOR_BUILD=$CC ;;
+ ,*,*) CC_FOR_BUILD=$HOST_CC ;;
+esac ; set_cc_for_build= ;'
+
+# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
+# (ghazi at noc.rutgers.edu 1994-08-24)
+if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
+ PATH=$PATH:/.attbin ; export PATH
+fi
+
+UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
+UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
+UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
+UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+
+# Note: order is significant - the case branches are not exclusive.
+
+case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
+ *:NetBSD:*:*)
+ # NetBSD (nbsd) targets should (where applicable) match one or
+ # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*,
+ # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently
+ # switched to ELF, *-*-netbsd* would select the old
+ # object file format. This provides both forward
+ # compatibility and a consistent mechanism for selecting the
+ # object file format.
+ #
+ # Note: NetBSD doesn't particularly care about the vendor
+ # portion of the name. We always set it to "unknown".
+ sysctl="sysctl -n hw.machine_arch"
+ UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \
+ /usr/sbin/$sysctl 2>/dev/null || echo unknown)`
+ case "${UNAME_MACHINE_ARCH}" in
+ armeb) machine=armeb-unknown ;;
+ arm*) machine=arm-unknown ;;
+ sh3el) machine=shl-unknown ;;
+ sh3eb) machine=sh-unknown ;;
+ *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
+ esac
+ # The Operating System including object format, if it has switched
+ # to ELF recently, or will in the future.
+ case "${UNAME_MACHINE_ARCH}" in
+ arm*|i386|m68k|ns32k|sh3*|sparc|vax)
+ eval $set_cc_for_build
+ if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
+ | grep __ELF__ >/dev/null
+ then
+ # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
+ # Return netbsd for either. FIX?
+ os=netbsd
+ else
+ os=netbsdelf
+ fi
+ ;;
+ *)
+ os=netbsd
+ ;;
+ esac
+ # The OS release
+ # Debian GNU/NetBSD machines have a different userland, and
+ # thus, need a distinct triplet. However, they do not need
+ # kernel version information, so it can be replaced with a
+ # suitable tag, in the style of linux-gnu.
+ case "${UNAME_VERSION}" in
+ Debian*)
+ release='-gnu'
+ ;;
+ *)
+ release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+ ;;
+ esac
+ # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
+ # contains redundant information, the shorter form:
+ # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
+ echo "${machine}-${os}${release}"
+ exit ;;
+ *:OpenBSD:*:*)
+ UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
+ echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
+ exit ;;
+ *:ekkoBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
+ exit ;;
+ macppc:MirBSD:*:*)
+ echo powerppc-unknown-mirbsd${UNAME_RELEASE}
+ exit ;;
+ *:MirBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
+ exit ;;
+ alpha:OSF1:*:*)
+ case $UNAME_RELEASE in
+ *4.0)
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+ ;;
+ *5.*)
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
+ ;;
+ esac
+ # According to Compaq, /usr/sbin/psrinfo has been available on
+ # OSF/1 and Tru64 systems produced since 1995. I hope that
+ # covers most systems running today. This code pipes the CPU
+ # types through head -n 1, so we only detect the type of CPU 0.
+ ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1`
+ case "$ALPHA_CPU_TYPE" in
+ "EV4 (21064)")
+ UNAME_MACHINE="alpha" ;;
+ "EV4.5 (21064)")
+ UNAME_MACHINE="alpha" ;;
+ "LCA4 (21066/21068)")
+ UNAME_MACHINE="alpha" ;;
+ "EV5 (21164)")
+ UNAME_MACHINE="alphaev5" ;;
+ "EV5.6 (21164A)")
+ UNAME_MACHINE="alphaev56" ;;
+ "EV5.6 (21164PC)")
+ UNAME_MACHINE="alphapca56" ;;
+ "EV5.7 (21164PC)")
+ UNAME_MACHINE="alphapca57" ;;
+ "EV6 (21264)")
+ UNAME_MACHINE="alphaev6" ;;
+ "EV6.7 (21264A)")
+ UNAME_MACHINE="alphaev67" ;;
+ "EV6.8CB (21264C)")
+ UNAME_MACHINE="alphaev68" ;;
+ "EV6.8AL (21264B)")
+ UNAME_MACHINE="alphaev68" ;;
+ "EV6.8CX (21264D)")
+ UNAME_MACHINE="alphaev68" ;;
+ "EV6.9A (21264/EV69A)")
+ UNAME_MACHINE="alphaev69" ;;
+ "EV7 (21364)")
+ UNAME_MACHINE="alphaev7" ;;
+ "EV7.9 (21364A)")
+ UNAME_MACHINE="alphaev79" ;;
+ esac
+ # A Pn.n version is a patched version.
+ # A Vn.n version is a released version.
+ # A Tn.n version is a released field test version.
+ # A Xn.n version is an unreleased experimental baselevel.
+ # 1.2 uses "1.2" for uname -r.
+ echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ exit ;;
+ Alpha\ *:Windows_NT*:*)
+ # How do we know it's Interix rather than the generic POSIX subsystem?
+ # Should we change UNAME_MACHINE based on the output of uname instead
+ # of the specific Alpha model?
+ echo alpha-pc-interix
+ exit ;;
+ 21064:Windows_NT:50:3)
+ echo alpha-dec-winnt3.5
+ exit ;;
+ Amiga*:UNIX_System_V:4.0:*)
+ echo m68k-unknown-sysv4
+ exit ;;
+ *:[Aa]miga[Oo][Ss]:*:*)
+ echo ${UNAME_MACHINE}-unknown-amigaos
+ exit ;;
+ *:[Mm]orph[Oo][Ss]:*:*)
+ echo ${UNAME_MACHINE}-unknown-morphos
+ exit ;;
+ *:OS/390:*:*)
+ echo i370-ibm-openedition
+ exit ;;
+ *:z/VM:*:*)
+ echo s390-ibm-zvmoe
+ exit ;;
+ *:OS400:*:*)
+ echo powerpc-ibm-os400
+ exit ;;
+ arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+ echo arm-acorn-riscix${UNAME_RELEASE}
+ exit ;;
+ arm:riscos:*:*|arm:RISCOS:*:*)
+ echo arm-unknown-riscos
+ exit ;;
+ SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
+ echo hppa1.1-hitachi-hiuxmpp
+ exit ;;
+ Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
+ # akee at wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
+ if test "`(/bin/universe) 2>/dev/null`" = att ; then
+ echo pyramid-pyramid-sysv3
+ else
+ echo pyramid-pyramid-bsd
+ fi
+ exit ;;
+ NILE*:*:*:dcosx)
+ echo pyramid-pyramid-svr4
+ exit ;;
+ DRS?6000:unix:4.0:6*)
+ echo sparc-icl-nx6
+ exit ;;
+ DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
+ case `/usr/bin/uname -p` in
+ sparc) echo sparc-icl-nx7; exit ;;
+ esac ;;
+ sun4H:SunOS:5.*:*)
+ echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
+ echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ i86pc:SunOS:5.*:*)
+ echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ sun4*:SunOS:6*:*)
+ # According to config.sub, this is the proper way to canonicalize
+ # SunOS6. Hard to guess exactly what SunOS6 will be like, but
+ # it's likely to be more like Solaris than SunOS4.
+ echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ sun4*:SunOS:*:*)
+ case "`/usr/bin/arch -k`" in
+ Series*|S4*)
+ UNAME_RELEASE=`uname -v`
+ ;;
+ esac
+ # Japanese Language versions have a version number like `4.1.3-JL'.
+ echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
+ exit ;;
+ sun3*:SunOS:*:*)
+ echo m68k-sun-sunos${UNAME_RELEASE}
+ exit ;;
+ sun*:*:4.2BSD:*)
+ UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
+ test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
+ case "`/bin/arch`" in
+ sun3)
+ echo m68k-sun-sunos${UNAME_RELEASE}
+ ;;
+ sun4)
+ echo sparc-sun-sunos${UNAME_RELEASE}
+ ;;
+ esac
+ exit ;;
+ aushp:SunOS:*:*)
+ echo sparc-auspex-sunos${UNAME_RELEASE}
+ exit ;;
+ # The situation for MiNT is a little confusing. The machine name
+ # can be virtually everything (everything which is not
+ # "atarist" or "atariste" at least should have a processor
+ # > m68000). The system name ranges from "MiNT" over "FreeMiNT"
+ # to the lowercase version "mint" (or "freemint"). Finally
+ # the system name "TOS" denotes a system which is actually not
+ # MiNT. But MiNT is downward compatible to TOS, so this should
+ # be no problem.
+ atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit ;;
+ atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit ;;
+ *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit ;;
+ milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
+ echo m68k-milan-mint${UNAME_RELEASE}
+ exit ;;
+ hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
+ echo m68k-hades-mint${UNAME_RELEASE}
+ exit ;;
+ *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
+ echo m68k-unknown-mint${UNAME_RELEASE}
+ exit ;;
+ m68k:machten:*:*)
+ echo m68k-apple-machten${UNAME_RELEASE}
+ exit ;;
+ powerpc:machten:*:*)
+ echo powerpc-apple-machten${UNAME_RELEASE}
+ exit ;;
+ RISC*:Mach:*:*)
+ echo mips-dec-mach_bsd4.3
+ exit ;;
+ RISC*:ULTRIX:*:*)
+ echo mips-dec-ultrix${UNAME_RELEASE}
+ exit ;;
+ VAX*:ULTRIX*:*:*)
+ echo vax-dec-ultrix${UNAME_RELEASE}
+ exit ;;
+ 2020:CLIX:*:* | 2430:CLIX:*:*)
+ echo clipper-intergraph-clix${UNAME_RELEASE}
+ exit ;;
+ mips:*:*:UMIPS | mips:*:*:RISCos)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+#ifdef __cplusplus
+#include <stdio.h> /* for printf() prototype */
+ int main (int argc, char *argv[]) {
+#else
+ int main (argc, argv) int argc; char *argv[]; {
+#endif
+ #if defined (host_mips) && defined (MIPSEB)
+ #if defined (SYSTYPE_SYSV)
+ printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_SVR4)
+ printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
+ printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
+ #endif
+ #endif
+ exit (-1);
+ }
+EOF
+ $CC_FOR_BUILD -o $dummy $dummy.c &&
+ dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` &&
+ SYSTEM_NAME=`$dummy $dummyarg` &&
+ { echo "$SYSTEM_NAME"; exit; }
+ echo mips-mips-riscos${UNAME_RELEASE}
+ exit ;;
+ Motorola:PowerMAX_OS:*:*)
+ echo powerpc-motorola-powermax
+ exit ;;
+ Motorola:*:4.3:PL8-*)
+ echo powerpc-harris-powermax
+ exit ;;
+ Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
+ echo powerpc-harris-powermax
+ exit ;;
+ Night_Hawk:Power_UNIX:*:*)
+ echo powerpc-harris-powerunix
+ exit ;;
+ m88k:CX/UX:7*:*)
+ echo m88k-harris-cxux7
+ exit ;;
+ m88k:*:4*:R4*)
+ echo m88k-motorola-sysv4
+ exit ;;
+ m88k:*:3*:R3*)
+ echo m88k-motorola-sysv3
+ exit ;;
+ AViiON:dgux:*:*)
+ # DG/UX returns AViiON for all architectures
+ UNAME_PROCESSOR=`/usr/bin/uname -p`
+ if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
+ then
+ if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
+ [ ${TARGET_BINARY_INTERFACE}x = x ]
+ then
+ echo m88k-dg-dgux${UNAME_RELEASE}
+ else
+ echo m88k-dg-dguxbcs${UNAME_RELEASE}
+ fi
+ else
+ echo i586-dg-dgux${UNAME_RELEASE}
+ fi
+ exit ;;
+ M88*:DolphinOS:*:*) # DolphinOS (SVR3)
+ echo m88k-dolphin-sysv3
+ exit ;;
+ M88*:*:R3*:*)
+ # Delta 88k system running SVR3
+ echo m88k-motorola-sysv3
+ exit ;;
+ XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+ echo m88k-tektronix-sysv3
+ exit ;;
+ Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+ echo m68k-tektronix-bsd
+ exit ;;
+ *:IRIX*:*:*)
+ echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
+ exit ;;
+ ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
+ echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id
+ exit ;; # Note that: echo "'`uname -s`'" gives 'AIX '
+ i*86:AIX:*:*)
+ echo i386-ibm-aix
+ exit ;;
+ ia64:AIX:*:*)
+ if [ -x /usr/bin/oslevel ] ; then
+ IBM_REV=`/usr/bin/oslevel`
+ else
+ IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+ fi
+ echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
+ exit ;;
+ *:AIX:2:3)
+ if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <sys/systemcfg.h>
+
+ main()
+ {
+ if (!__power_pc())
+ exit(1);
+ puts("powerpc-ibm-aix3.2.5");
+ exit(0);
+ }
+EOF
+ if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy`
+ then
+ echo "$SYSTEM_NAME"
+ else
+ echo rs6000-ibm-aix3.2.5
+ fi
+ elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
+ echo rs6000-ibm-aix3.2.4
+ else
+ echo rs6000-ibm-aix3.2
+ fi
+ exit ;;
+ *:AIX:*:[45])
+ IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
+ if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
+ IBM_ARCH=rs6000
+ else
+ IBM_ARCH=powerpc
+ fi
+ if [ -x /usr/bin/oslevel ] ; then
+ IBM_REV=`/usr/bin/oslevel`
+ else
+ IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+ fi
+ echo ${IBM_ARCH}-ibm-aix${IBM_REV}
+ exit ;;
+ *:AIX:*:*)
+ echo rs6000-ibm-aix
+ exit ;;
+ ibmrt:4.4BSD:*|romp-ibm:BSD:*)
+ echo romp-ibm-bsd4.4
+ exit ;;
+ ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and
+ echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to
+ exit ;; # report: romp-ibm BSD 4.3
+ *:BOSX:*:*)
+ echo rs6000-bull-bosx
+ exit ;;
+ DPX/2?00:B.O.S.:*:*)
+ echo m68k-bull-sysv3
+ exit ;;
+ 9000/[34]??:4.3bsd:1.*:*)
+ echo m68k-hp-bsd
+ exit ;;
+ hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+ echo m68k-hp-bsd4.4
+ exit ;;
+ 9000/[34678]??:HP-UX:*:*)
+ HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+ case "${UNAME_MACHINE}" in
+ 9000/31? ) HP_ARCH=m68000 ;;
+ 9000/[34]?? ) HP_ARCH=m68k ;;
+ 9000/[678][0-9][0-9])
+ if [ -x /usr/bin/getconf ]; then
+ sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
+ sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
+ case "${sc_cpu_version}" in
+ 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
+ 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
+ 532) # CPU_PA_RISC2_0
+ case "${sc_kernel_bits}" in
+ 32) HP_ARCH="hppa2.0n" ;;
+ 64) HP_ARCH="hppa2.0w" ;;
+ '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20
+ esac ;;
+ esac
+ fi
+ if [ "${HP_ARCH}" = "" ]; then
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+
+ #define _HPUX_SOURCE
+ #include <stdlib.h>
+ #include <unistd.h>
+
+ int main ()
+ {
+ #if defined(_SC_KERNEL_BITS)
+ long bits = sysconf(_SC_KERNEL_BITS);
+ #endif
+ long cpu = sysconf (_SC_CPU_VERSION);
+
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+ case CPU_PA_RISC2_0:
+ #if defined(_SC_KERNEL_BITS)
+ switch (bits)
+ {
+ case 64: puts ("hppa2.0w"); break;
+ case 32: puts ("hppa2.0n"); break;
+ default: puts ("hppa2.0"); break;
+ } break;
+ #else /* !defined(_SC_KERNEL_BITS) */
+ puts ("hppa2.0"); break;
+ #endif
+ default: puts ("hppa1.0"); break;
+ }
+ exit (0);
+ }
+EOF
+ (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
+ test -z "$HP_ARCH" && HP_ARCH=hppa
+ fi ;;
+ esac
+ if [ ${HP_ARCH} = "hppa2.0w" ]
+ then
+ eval $set_cc_for_build
+
+ # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating
+ # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler
+ # generating 64-bit code. GNU and HP use different nomenclature:
+ #
+ # $ CC_FOR_BUILD=cc ./config.guess
+ # => hppa2.0w-hp-hpux11.23
+ # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess
+ # => hppa64-hp-hpux11.23
+
+ if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) |
+ grep __LP64__ >/dev/null
+ then
+ HP_ARCH="hppa2.0w"
+ else
+ HP_ARCH="hppa64"
+ fi
+ fi
+ echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+ exit ;;
+ ia64:HP-UX:*:*)
+ HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+ echo ia64-hp-hpux${HPUX_REV}
+ exit ;;
+ 3050*:HI-UX:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <unistd.h>
+ int
+ main ()
+ {
+ long cpu = sysconf (_SC_CPU_VERSION);
+ /* The order matters, because CPU_IS_HP_MC68K erroneously returns
+ true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct
+ results, however. */
+ if (CPU_IS_PA_RISC (cpu))
+ {
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
+ default: puts ("hppa-hitachi-hiuxwe2"); break;
+ }
+ }
+ else if (CPU_IS_HP_MC68K (cpu))
+ puts ("m68k-hitachi-hiuxwe2");
+ else puts ("unknown-hitachi-hiuxwe2");
+ exit (0);
+ }
+EOF
+ $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` &&
+ { echo "$SYSTEM_NAME"; exit; }
+ echo unknown-hitachi-hiuxwe2
+ exit ;;
+ 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
+ echo hppa1.1-hp-bsd
+ exit ;;
+ 9000/8??:4.3bsd:*:*)
+ echo hppa1.0-hp-bsd
+ exit ;;
+ *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
+ echo hppa1.0-hp-mpeix
+ exit ;;
+ hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
+ echo hppa1.1-hp-osf
+ exit ;;
+ hp8??:OSF1:*:*)
+ echo hppa1.0-hp-osf
+ exit ;;
+ i*86:OSF1:*:*)
+ if [ -x /usr/sbin/sysversion ] ; then
+ echo ${UNAME_MACHINE}-unknown-osf1mk
+ else
+ echo ${UNAME_MACHINE}-unknown-osf1
+ fi
+ exit ;;
+ parisc*:Lites*:*:*)
+ echo hppa1.1-hp-lites
+ exit ;;
+ C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+ echo c1-convex-bsd
+ exit ;;
+ C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit ;;
+ C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+ echo c34-convex-bsd
+ exit ;;
+ C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+ echo c38-convex-bsd
+ exit ;;
+ C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+ echo c4-convex-bsd
+ exit ;;
+ CRAY*Y-MP:*:*:*)
+ echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*[A-Z]90:*:*:*)
+ echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
+ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
+ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
+ -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*TS:*:*:*)
+ echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*T3E:*:*:*)
+ echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*SV1:*:*:*)
+ echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ *:UNICOS/mp:*:*)
+ echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
+ FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+ FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+ echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+ exit ;;
+ 5000:UNIX_System_V:4.*:*)
+ FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+ FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
+ echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+ exit ;;
+ i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
+ echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
+ exit ;;
+ sparc*:BSD/OS:*:*)
+ echo sparc-unknown-bsdi${UNAME_RELEASE}
+ exit ;;
+ *:BSD/OS:*:*)
+ echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
+ exit ;;
+ *:FreeBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+ exit ;;
+ i*:CYGWIN*:*)
+ echo ${UNAME_MACHINE}-pc-cygwin
+ exit ;;
+ i*:MINGW*:*)
+ echo ${UNAME_MACHINE}-pc-mingw32
+ exit ;;
+ i*:windows32*:*)
+ # uname -m includes "-pc" on this system.
+ echo ${UNAME_MACHINE}-mingw32
+ exit ;;
+ i*:PW*:*)
+ echo ${UNAME_MACHINE}-pc-pw32
+ exit ;;
+ x86:Interix*:[345]*)
+ echo i586-pc-interix${UNAME_RELEASE}|sed -e 's/\..*//'
+ exit ;;
+ [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
+ echo i${UNAME_MACHINE}-pc-mks
+ exit ;;
+ i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
+ # How do we know it's Interix rather than the generic POSIX subsystem?
+ # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
+ # UNAME_MACHINE based on the output of uname instead of i386?
+ echo i586-pc-interix
+ exit ;;
+ i*:UWIN*:*)
+ echo ${UNAME_MACHINE}-pc-uwin
+ exit ;;
+ amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)
+ echo x86_64-unknown-cygwin
+ exit ;;
+ p*:CYGWIN*:*)
+ echo powerpcle-unknown-cygwin
+ exit ;;
+ prep*:SunOS:5.*:*)
+ echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ *:GNU:*:*)
+ # the GNU system
+ echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+ exit ;;
+ *:GNU/*:*:*)
+ # other systems with GNU libc and userland
+ echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu
+ exit ;;
+ i*86:Minix:*:*)
+ echo ${UNAME_MACHINE}-pc-minix
+ exit ;;
+ arm*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ cris:Linux:*:*)
+ echo cris-axis-linux-gnu
+ exit ;;
+ crisv32:Linux:*:*)
+ echo crisv32-axis-linux-gnu
+ exit ;;
+ frv:Linux:*:*)
+ echo frv-unknown-linux-gnu
+ exit ;;
+ ia64:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ m32r*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ m68*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ mips:Linux:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #undef CPU
+ #undef mips
+ #undef mipsel
+ #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+ CPU=mipsel
+ #else
+ #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+ CPU=mips
+ #else
+ CPU=
+ #endif
+ #endif
+EOF
+ eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '/^CPU/{s: ::g;p;}'`"
+ test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
+ ;;
+ mips64:Linux:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #undef CPU
+ #undef mips64
+ #undef mips64el
+ #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+ CPU=mips64el
+ #else
+ #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+ CPU=mips64
+ #else
+ CPU=
+ #endif
+ #endif
+EOF
+ eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '/^CPU/{s: ::g;p;}'`"
+ test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
+ ;;
+ or32:Linux:*:*)
+ echo or32-unknown-linux-gnu
+ exit ;;
+ ppc:Linux:*:*)
+ echo powerpc-unknown-linux-gnu
+ exit ;;
+ ppc64:Linux:*:*)
+ echo powerpc64-unknown-linux-gnu
+ exit ;;
+ alpha:Linux:*:*)
+ case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
+ EV5) UNAME_MACHINE=alphaev5 ;;
+ EV56) UNAME_MACHINE=alphaev56 ;;
+ PCA56) UNAME_MACHINE=alphapca56 ;;
+ PCA57) UNAME_MACHINE=alphapca56 ;;
+ EV6) UNAME_MACHINE=alphaev6 ;;
+ EV67) UNAME_MACHINE=alphaev67 ;;
+ EV68*) UNAME_MACHINE=alphaev68 ;;
+ esac
+ objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null
+ if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
+ echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
+ exit ;;
+ parisc:Linux:*:* | hppa:Linux:*:*)
+ # Look for CPU level
+ case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
+ PA7*) echo hppa1.1-unknown-linux-gnu ;;
+ PA8*) echo hppa2.0-unknown-linux-gnu ;;
+ *) echo hppa-unknown-linux-gnu ;;
+ esac
+ exit ;;
+ parisc64:Linux:*:* | hppa64:Linux:*:*)
+ echo hppa64-unknown-linux-gnu
+ exit ;;
+ s390:Linux:*:* | s390x:Linux:*:*)
+ echo ${UNAME_MACHINE}-ibm-linux
+ exit ;;
+ sh64*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ sh*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ sparc:Linux:*:* | sparc64:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ vax:Linux:*:*)
+ echo ${UNAME_MACHINE}-dec-linux-gnu
+ exit ;;
+ x86_64:Linux:*:*)
+ echo x86_64-unknown-linux-gnu
+ exit ;;
+ i*86:Linux:*:*)
+ # The BFD linker knows what the default object file format is, so
+ # first see if it will tell us. cd to the root directory to prevent
+ # problems with other programs or directories called `ld' in the path.
+ # Set LC_ALL=C to ensure ld outputs messages in English.
+ ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \
+ | sed -ne '/supported targets:/!d
+ s/[ ][ ]*/ /g
+ s/.*supported targets: *//
+ s/ .*//
+ p'`
+ case "$ld_supported_targets" in
+ elf32-i386)
+ TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu"
+ ;;
+ a.out-i386-linux)
+ echo "${UNAME_MACHINE}-pc-linux-gnuaout"
+ exit ;;
+ coff-i386)
+ echo "${UNAME_MACHINE}-pc-linux-gnucoff"
+ exit ;;
+ "")
+ # Either a pre-BFD a.out linker (linux-gnuoldld) or
+ # one that does not give us useful --help.
+ echo "${UNAME_MACHINE}-pc-linux-gnuoldld"
+ exit ;;
+ esac
+ # Determine whether the default compiler is a.out or elf
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <features.h>
+ #ifdef __ELF__
+ # ifdef __GLIBC__
+ # if __GLIBC__ >= 2
+ LIBC=gnu
+ # else
+ LIBC=gnulibc1
+ # endif
+ # else
+ LIBC=gnulibc1
+ # endif
+ #else
+ #if defined(__INTEL_COMPILER) || defined(__PGI)
+ LIBC=gnu
+ #else
+ LIBC=gnuaout
+ #endif
+ #endif
+ #ifdef __dietlibc__
+ LIBC=dietlibc
+ #endif
+EOF
+ eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '/^LIBC/{s: ::g;p;}'`"
+ test x"${LIBC}" != x && {
+ echo "${UNAME_MACHINE}-pc-linux-${LIBC}"
+ exit
+ }
+ test x"${TENTATIVE}" != x && { echo "${TENTATIVE}"; exit; }
+ ;;
+ i*86:DYNIX/ptx:4*:*)
+ # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
+ # earlier versions are messed up and put the nodename in both
+ # sysname and nodename.
+ echo i386-sequent-sysv4
+ exit ;;
+ i*86:UNIX_SV:4.2MP:2.*)
+ # Unixware is an offshoot of SVR4, but it has its own version
+ # number series starting with 2...
+ # I am not positive that other SVR4 systems won't match this,
+ # I just have to hope. -- rms.
+ # Use sysv4.2uw... so that sysv4* matches it.
+ echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
+ exit ;;
+ i*86:OS/2:*:*)
+ # If we were able to find `uname', then EMX Unix compatibility
+ # is probably installed.
+ echo ${UNAME_MACHINE}-pc-os2-emx
+ exit ;;
+ i*86:XTS-300:*:STOP)
+ echo ${UNAME_MACHINE}-unknown-stop
+ exit ;;
+ i*86:atheos:*:*)
+ echo ${UNAME_MACHINE}-unknown-atheos
+ exit ;;
+ i*86:syllable:*:*)
+ echo ${UNAME_MACHINE}-pc-syllable
+ exit ;;
+ i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*)
+ echo i386-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ i*86:*DOS:*:*)
+ echo ${UNAME_MACHINE}-pc-msdosdjgpp
+ exit ;;
+ i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
+ UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
+ if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
+ echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
+ else
+ echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
+ fi
+ exit ;;
+ i*86:*:5:[678]*)
+ # UnixWare 7.x, OpenUNIX and OpenServer 6.
+ case `/bin/uname -X | grep "^Machine"` in
+ *486*) UNAME_MACHINE=i486 ;;
+ *Pentium) UNAME_MACHINE=i586 ;;
+ *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
+ esac
+ echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
+ exit ;;
+ i*86:*:3.2:*)
+ if test -f /usr/options/cb.name; then
+ UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+ echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+ elif /bin/uname -X 2>/dev/null >/dev/null ; then
+ UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
+ (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
+ (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
+ && UNAME_MACHINE=i586
+ (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
+ && UNAME_MACHINE=i686
+ (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
+ && UNAME_MACHINE=i686
+ echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
+ else
+ echo ${UNAME_MACHINE}-pc-sysv32
+ fi
+ exit ;;
+ pc:*:*:*)
+ # Left here for compatibility:
+ # uname -m prints for DJGPP always 'pc', but it prints nothing about
+ # the processor, so we play safe by assuming i386.
+ echo i386-pc-msdosdjgpp
+ exit ;;
+ Intel:Mach:3*:*)
+ echo i386-pc-mach3
+ exit ;;
+ paragon:*:*:*)
+ echo i860-intel-osf1
+ exit ;;
+ i860:*:4.*:*) # i860-SVR4
+ if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
+ echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
+ else # Add other i860-SVR4 vendors below as they are discovered.
+ echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4
+ fi
+ exit ;;
+ mini*:CTIX:SYS*5:*)
+ # "miniframe"
+ echo m68010-convergent-sysv
+ exit ;;
+ mc68k:UNIX:SYSTEM5:3.51m)
+ echo m68k-convergent-sysv
+ exit ;;
+ M680?0:D-NIX:5.3:*)
+ echo m68k-diab-dnix
+ exit ;;
+ M68*:*:R3V[5678]*:*)
+ test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;;
+ 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
+ OS_REL=''
+ test -r /etc/.relid \
+ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
+ /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
+ 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && { echo i486-ncr-sysv4; exit; } ;;
+ m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
+ echo m68k-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ mc68030:UNIX_System_V:4.*:*)
+ echo m68k-atari-sysv4
+ exit ;;
+ TSUNAMI:LynxOS:2.*:*)
+ echo sparc-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ rs6000:LynxOS:2.*:*)
+ echo rs6000-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*)
+ echo powerpc-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ SM[BE]S:UNIX_SV:*:*)
+ echo mips-dde-sysv${UNAME_RELEASE}
+ exit ;;
+ RM*:ReliantUNIX-*:*:*)
+ echo mips-sni-sysv4
+ exit ;;
+ RM*:SINIX-*:*:*)
+ echo mips-sni-sysv4
+ exit ;;
+ *:SINIX-*:*:*)
+ if uname -p 2>/dev/null >/dev/null ; then
+ UNAME_MACHINE=`(uname -p) 2>/dev/null`
+ echo ${UNAME_MACHINE}-sni-sysv4
+ else
+ echo ns32k-sni-sysv
+ fi
+ exit ;;
+ PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+ # says <Richard.M.Bartel at ccMail.Census.GOV>
+ echo i586-unisys-sysv4
+ exit ;;
+ *:UNIX_System_V:4*:FTX*)
+ # From Gerald Hewes <hewes at openmarket.com>.
+ # How about differentiating between stratus architectures? -djm
+ echo hppa1.1-stratus-sysv4
+ exit ;;
+ *:*:*:FTX*)
+ # From seanf at swdc.stratus.com.
+ echo i860-stratus-sysv4
+ exit ;;
+ i*86:VOS:*:*)
+ # From Paul.Green at stratus.com.
+ echo ${UNAME_MACHINE}-stratus-vos
+ exit ;;
+ *:VOS:*:*)
+ # From Paul.Green at stratus.com.
+ echo hppa1.1-stratus-vos
+ exit ;;
+ mc68*:A/UX:*:*)
+ echo m68k-apple-aux${UNAME_RELEASE}
+ exit ;;
+ news*:NEWS-OS:6*:*)
+ echo mips-sony-newsos6
+ exit ;;
+ R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
+ if [ -d /usr/nec ]; then
+ echo mips-nec-sysv${UNAME_RELEASE}
+ else
+ echo mips-unknown-sysv${UNAME_RELEASE}
+ fi
+ exit ;;
+ BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only.
+ echo powerpc-be-beos
+ exit ;;
+ BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only.
+ echo powerpc-apple-beos
+ exit ;;
+ BePC:BeOS:*:*) # BeOS running on Intel PC compatible.
+ echo i586-pc-beos
+ exit ;;
+ SX-4:SUPER-UX:*:*)
+ echo sx4-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-5:SUPER-UX:*:*)
+ echo sx5-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-6:SUPER-UX:*:*)
+ echo sx6-nec-superux${UNAME_RELEASE}
+ exit ;;
+ Power*:Rhapsody:*:*)
+ echo powerpc-apple-rhapsody${UNAME_RELEASE}
+ exit ;;
+ *:Rhapsody:*:*)
+ echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
+ exit ;;
+ *:Darwin:*:*)
+ UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
+ case $UNAME_PROCESSOR in
+ unknown) UNAME_PROCESSOR=powerpc ;;
+ esac
+ echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
+ exit ;;
+ *:procnto*:*:* | *:QNX:[0123456789]*:*)
+ UNAME_PROCESSOR=`uname -p`
+ if test "$UNAME_PROCESSOR" = "x86"; then
+ UNAME_PROCESSOR=i386
+ UNAME_MACHINE=pc
+ fi
+ echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
+ exit ;;
+ *:QNX:*:4*)
+ echo i386-pc-qnx
+ exit ;;
+ NSE-?:NONSTOP_KERNEL:*:*)
+ echo nse-tandem-nsk${UNAME_RELEASE}
+ exit ;;
+ NSR-?:NONSTOP_KERNEL:*:*)
+ echo nsr-tandem-nsk${UNAME_RELEASE}
+ exit ;;
+ *:NonStop-UX:*:*)
+ echo mips-compaq-nonstopux
+ exit ;;
+ BS2000:POSIX*:*:*)
+ echo bs2000-siemens-sysv
+ exit ;;
+ DS/*:UNIX_System_V:*:*)
+ echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
+ exit ;;
+ *:Plan9:*:*)
+ # "uname -m" is not consistent, so use $cputype instead. 386
+ # is converted to i386 for consistency with other x86
+ # operating systems.
+ if test "$cputype" = "386"; then
+ UNAME_MACHINE=i386
+ else
+ UNAME_MACHINE="$cputype"
+ fi
+ echo ${UNAME_MACHINE}-unknown-plan9
+ exit ;;
+ *:TOPS-10:*:*)
+ echo pdp10-unknown-tops10
+ exit ;;
+ *:TENEX:*:*)
+ echo pdp10-unknown-tenex
+ exit ;;
+ KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
+ echo pdp10-dec-tops20
+ exit ;;
+ XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
+ echo pdp10-xkl-tops20
+ exit ;;
+ *:TOPS-20:*:*)
+ echo pdp10-unknown-tops20
+ exit ;;
+ *:ITS:*:*)
+ echo pdp10-unknown-its
+ exit ;;
+ SEI:*:*:SEIUX)
+ echo mips-sei-seiux${UNAME_RELEASE}
+ exit ;;
+ *:DragonFly:*:*)
+ echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+ exit ;;
+ *:*VMS:*:*)
+ UNAME_MACHINE=`(uname -p) 2>/dev/null`
+ case "${UNAME_MACHINE}" in
+ A*) echo alpha-dec-vms ; exit ;;
+ I*) echo ia64-dec-vms ; exit ;;
+ V*) echo vax-dec-vms ; exit ;;
+ esac ;;
+ *:XENIX:*:SysV)
+ echo i386-pc-xenix
+ exit ;;
+ i*86:skyos:*:*)
+ echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//'
+ exit ;;
+ i*86:rdos:*:*)
+ echo ${UNAME_MACHINE}-pc-rdos
+ exit ;;
+esac
+
+#echo '(No uname command or uname output not recognized.)' 1>&2
+#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
+
+eval $set_cc_for_build
+cat >$dummy.c <<EOF
+#ifdef _SEQUENT_
+# include <sys/types.h>
+# include <sys/utsname.h>
+#endif
+main ()
+{
+#if defined (sony)
+#if defined (MIPSEB)
+ /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed,
+ I don't know.... */
+ printf ("mips-sony-bsd\n"); exit (0);
+#else
+#include <sys/param.h>
+ printf ("m68k-sony-newsos%s\n",
+#ifdef NEWSOS4
+ "4"
+#else
+ ""
+#endif
+ ); exit (0);
+#endif
+#endif
+
+#if defined (__arm) && defined (__acorn) && defined (__unix)
+ printf ("arm-acorn-riscix\n"); exit (0);
+#endif
+
+#if defined (hp300) && !defined (hpux)
+ printf ("m68k-hp-bsd\n"); exit (0);
+#endif
+
+#if defined (NeXT)
+#if !defined (__ARCHITECTURE__)
+#define __ARCHITECTURE__ "m68k"
+#endif
+ int version;
+ version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
+ if (version < 4)
+ printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
+ else
+ printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
+ exit (0);
+#endif
+
+#if defined (MULTIMAX) || defined (n16)
+#if defined (UMAXV)
+ printf ("ns32k-encore-sysv\n"); exit (0);
+#else
+#if defined (CMU)
+ printf ("ns32k-encore-mach\n"); exit (0);
+#else
+ printf ("ns32k-encore-bsd\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (__386BSD__)
+ printf ("i386-pc-bsd\n"); exit (0);
+#endif
+
+#if defined (sequent)
+#if defined (i386)
+ printf ("i386-sequent-dynix\n"); exit (0);
+#endif
+#if defined (ns32000)
+ printf ("ns32k-sequent-dynix\n"); exit (0);
+#endif
+#endif
+
+#if defined (_SEQUENT_)
+ struct utsname un;
+
+ uname(&un);
+
+ if (strncmp(un.version, "V2", 2) == 0) {
+ printf ("i386-sequent-ptx2\n"); exit (0);
+ }
+ if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
+ printf ("i386-sequent-ptx1\n"); exit (0);
+ }
+ printf ("i386-sequent-ptx\n"); exit (0);
+
+#endif
+
+#if defined (vax)
+# if !defined (ultrix)
+# include <sys/param.h>
+# if defined (BSD)
+# if BSD == 43
+ printf ("vax-dec-bsd4.3\n"); exit (0);
+# else
+# if BSD == 199006
+ printf ("vax-dec-bsd4.3reno\n"); exit (0);
+# else
+ printf ("vax-dec-bsd\n"); exit (0);
+# endif
+# endif
+# else
+ printf ("vax-dec-bsd\n"); exit (0);
+# endif
+# else
+ printf ("vax-dec-ultrix\n"); exit (0);
+# endif
+#endif
+
+#if defined (alliant) && defined (i860)
+ printf ("i860-alliant-bsd\n"); exit (0);
+#endif
+
+ exit (1);
+}
+EOF
+
+$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` &&
+ { echo "$SYSTEM_NAME"; exit; }
+
+# Apollos put the system type in the environment.
+
+test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; }
+
+# Convex versions that predate uname can use getsysinfo(1)
+
+if [ -x /usr/convex/getsysinfo ]
+then
+ case `getsysinfo -f cpu_type` in
+ c1*)
+ echo c1-convex-bsd
+ exit ;;
+ c2*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit ;;
+ c34*)
+ echo c34-convex-bsd
+ exit ;;
+ c38*)
+ echo c38-convex-bsd
+ exit ;;
+ c4*)
+ echo c4-convex-bsd
+ exit ;;
+ esac
+fi
+
+cat >&2 <<EOF
+$0: unable to guess system type
+
+This script, last modified $timestamp, has failed to recognize
+the operating system you are using. It is advised that you
+download the most up to date version of the config scripts from
+
+ http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.guess
+and
+ http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.sub
+
+If the version you run ($0) is already up to date, please
+send the following data and any information you think might be
+pertinent to <config-patches at gnu.org> in order to provide the needed
+information to handle your system.
+
+config.guess timestamp = $timestamp
+
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null`
+
+hostinfo = `(hostinfo) 2>/dev/null`
+/bin/universe = `(/bin/universe) 2>/dev/null`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null`
+/bin/arch = `(/bin/arch) 2>/dev/null`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
+
+UNAME_MACHINE = ${UNAME_MACHINE}
+UNAME_RELEASE = ${UNAME_RELEASE}
+UNAME_SYSTEM = ${UNAME_SYSTEM}
+UNAME_VERSION = ${UNAME_VERSION}
+EOF
+
+exit 1
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/config/config.sub b/config/config.sub
new file mode 100755
index 0000000..2851647
--- /dev/null
+++ b/config/config.sub
@@ -0,0 +1,1599 @@
+#! /bin/sh
+# Configuration validation subroutine script.
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+# 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+
+timestamp='2005-12-11'
+
+# This file is (in principle) common to ALL GNU software.
+# The presence of a machine in this file suggests that SOME GNU software
+# can handle that machine. It does not imply ALL GNU software can.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
+# 02110-1301, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+
+# Please send patches to <config-patches at gnu.org>. Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# Configuration subroutine to validate and canonicalize a configuration type.
+# Supply the specified configuration type as an argument.
+# If it is invalid, we print an error message on stderr and exit with code 1.
+# Otherwise, we print the canonical config type on stdout and succeed.
+
+# This file is supposed to be the same for all GNU packages
+# and recognize all the CPU types, system types and aliases
+# that are meaningful with *any* GNU software.
+# Each package is responsible for reporting which valid configurations
+# it does not support. The user should be able to distinguish
+# a failure to support a valid configuration from a meaningless
+# configuration.
+
+# The goal of this file is to map all the various variations of a given
+# machine specification into a single specification in the form:
+# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or in some cases, the newer four-part form:
+# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+# It is wrong to echo any other type of specification.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION] CPU-MFR-OPSYS
+ $0 [OPTION] ALIAS
+
+Canonicalize a configuration name.
+
+Operation modes:
+ -h, --help print this help, then exit
+ -t, --time-stamp print date of last modification, then exit
+ -v, --version print version number, then exit
+
+Report bugs and patches to <config-patches at gnu.org>."
+
+version="\
+GNU config.sub ($timestamp)
+
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+ case $1 in
+ --time-stamp | --time* | -t )
+ echo "$timestamp" ; exit ;;
+ --version | -v )
+ echo "$version" ; exit ;;
+ --help | --h* | -h )
+ echo "$usage"; exit ;;
+ -- ) # Stop option processing
+ shift; break ;;
+ - ) # Use stdin as input.
+ break ;;
+ -* )
+ echo "$me: invalid option $1$help"
+ exit 1 ;;
+
+ *local*)
+ # First pass through any local machine types.
+ echo $1
+ exit ;;
+
+ * )
+ break ;;
+ esac
+done
+
+case $# in
+ 0) echo "$me: missing argument$help" >&2
+ exit 1;;
+ 1) ;;
+ *) echo "$me: too many arguments$help" >&2
+ exit 1;;
+esac
+
+# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
+# Here we must recognize all the valid KERNEL-OS combinations.
+maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
+case $maybe_os in
+ nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \
+ uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \
+ storm-chaos* | os2-emx* | rtmk-nova*)
+ os=-$maybe_os
+ basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
+ ;;
+ *)
+ basic_machine=`echo $1 | sed 's/-[^-]*$//'`
+ if [ $basic_machine != $1 ]
+ then os=`echo $1 | sed 's/.*-/-/'`
+ else os=; fi
+ ;;
+esac
+
+### Let's recognize common machines as not being operating systems so
+### that things like config.sub decstation-3100 work. We also
+### recognize some manufacturers as not being operating systems, so we
+### can provide default operating systems below.
+case $os in
+ -sun*os*)
+ # Prevent following clause from handling this invalid input.
+ ;;
+ -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
+ -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
+ -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
+ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
+ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
+ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
+ -apple | -axis | -knuth | -cray)
+ os=
+ basic_machine=$1
+ ;;
+ -sim | -cisco | -oki | -wec | -winbond)
+ os=
+ basic_machine=$1
+ ;;
+ -scout)
+ ;;
+ -wrs)
+ os=-vxworks
+ basic_machine=$1
+ ;;
+ -chorusos*)
+ os=-chorusos
+ basic_machine=$1
+ ;;
+ -chorusrdb)
+ os=-chorusrdb
+ basic_machine=$1
+ ;;
+ -hiux*)
+ os=-hiuxwe2
+ ;;
+ -sco6)
+ os=-sco5v6
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco5)
+ os=-sco3.2v5
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco4)
+ os=-sco3.2v4
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco3.2.[4-9]*)
+ os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco3.2v[4-9]*)
+ # Don't forget version if it is 3.2v4 or newer.
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco5v6*)
+ # Don't forget version if it is 3.2v4 or newer.
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco*)
+ os=-sco3.2v2
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -udk*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -isc)
+ os=-isc2.2
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -clix*)
+ basic_machine=clipper-intergraph
+ ;;
+ -isc*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -lynx*)
+ os=-lynxos
+ ;;
+ -ptx*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
+ ;;
+ -windowsnt*)
+ os=`echo $os | sed -e 's/windowsnt/winnt/'`
+ ;;
+ -psos*)
+ os=-psos
+ ;;
+ -mint | -mint[0-9]*)
+ basic_machine=m68k-atari
+ os=-mint
+ ;;
+esac
+
+# Decode aliases for certain CPU-COMPANY combinations.
+case $basic_machine in
+ # Recognize the basic CPU types without company name.
+ # Some are omitted here because they have special meanings below.
+ 1750a | 580 \
+ | a29k \
+ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
+ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
+ | am33_2.0 \
+ | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \
+ | bfin \
+ | c4x | clipper \
+ | d10v | d30v | dlx | dsp16xx \
+ | fr30 | frv \
+ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+ | i370 | i860 | i960 | ia64 \
+ | ip2k | iq2000 \
+ | m32r | m32rle | m68000 | m68k | m88k | maxq | mcore \
+ | mips | mipsbe | mipseb | mipsel | mipsle \
+ | mips16 \
+ | mips64 | mips64el \
+ | mips64vr | mips64vrel \
+ | mips64orion | mips64orionel \
+ | mips64vr4100 | mips64vr4100el \
+ | mips64vr4300 | mips64vr4300el \
+ | mips64vr5000 | mips64vr5000el \
+ | mips64vr5900 | mips64vr5900el \
+ | mipsisa32 | mipsisa32el \
+ | mipsisa32r2 | mipsisa32r2el \
+ | mipsisa64 | mipsisa64el \
+ | mipsisa64r2 | mipsisa64r2el \
+ | mipsisa64sb1 | mipsisa64sb1el \
+ | mipsisa64sr71k | mipsisa64sr71kel \
+ | mipstx39 | mipstx39el \
+ | mn10200 | mn10300 \
+ | mt \
+ | msp430 \
+ | ns16k | ns32k \
+ | or32 \
+ | pdp10 | pdp11 | pj | pjl \
+ | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
+ | pyramid \
+ | sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \
+ | sh64 | sh64le \
+ | sparc | sparc64 | sparc64b | sparc86x | sparclet | sparclite \
+ | sparcv8 | sparcv9 | sparcv9b \
+ | strongarm \
+ | tahoe | thumb | tic4x | tic80 | tron \
+ | v850 | v850e \
+ | we32k \
+ | x86 | xscale | xscalee[bl] | xstormy16 | xtensa \
+ | z8k)
+ basic_machine=$basic_machine-unknown
+ ;;
+ m32c)
+ basic_machine=$basic_machine-unknown
+ ;;
+ m6811 | m68hc11 | m6812 | m68hc12)
+ # Motorola 68HC11/12.
+ basic_machine=$basic_machine-unknown
+ os=-none
+ ;;
+ m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
+ ;;
+ ms1)
+ basic_machine=mt-unknown
+ ;;
+
+ # We use `pc' rather than `unknown'
+ # because (1) that's what they normally are, and
+ # (2) the word "unknown" tends to confuse beginning users.
+ i*86 | x86_64)
+ basic_machine=$basic_machine-pc
+ ;;
+ # Object if more than one company name word.
+ *-*-*)
+ echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+ exit 1
+ ;;
+ # Recognize the basic CPU types with company name.
+ 580-* \
+ | a29k-* \
+ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
+ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
+ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
+ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \
+ | avr-* \
+ | bfin-* | bs2000-* \
+ | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
+ | clipper-* | craynv-* | cydra-* \
+ | d10v-* | d30v-* | dlx-* \
+ | elxsi-* \
+ | f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \
+ | h8300-* | h8500-* \
+ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
+ | i*86-* | i860-* | i960-* | ia64-* \
+ | ip2k-* | iq2000-* \
+ | m32r-* | m32rle-* \
+ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
+ | m88110-* | m88k-* | maxq-* | mcore-* \
+ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
+ | mips16-* \
+ | mips64-* | mips64el-* \
+ | mips64vr-* | mips64vrel-* \
+ | mips64orion-* | mips64orionel-* \
+ | mips64vr4100-* | mips64vr4100el-* \
+ | mips64vr4300-* | mips64vr4300el-* \
+ | mips64vr5000-* | mips64vr5000el-* \
+ | mips64vr5900-* | mips64vr5900el-* \
+ | mipsisa32-* | mipsisa32el-* \
+ | mipsisa32r2-* | mipsisa32r2el-* \
+ | mipsisa64-* | mipsisa64el-* \
+ | mipsisa64r2-* | mipsisa64r2el-* \
+ | mipsisa64sb1-* | mipsisa64sb1el-* \
+ | mipsisa64sr71k-* | mipsisa64sr71kel-* \
+ | mipstx39-* | mipstx39el-* \
+ | mmix-* \
+ | mt-* \
+ | msp430-* \
+ | none-* | np1-* | ns16k-* | ns32k-* \
+ | orion-* \
+ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
+ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
+ | pyramid-* \
+ | romp-* | rs6000-* \
+ | sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | shbe-* \
+ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
+ | sparc-* | sparc64-* | sparc64b-* | sparc86x-* | sparclet-* \
+ | sparclite-* \
+ | sparcv8-* | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \
+ | tahoe-* | thumb-* \
+ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
+ | tron-* \
+ | v850-* | v850e-* | vax-* \
+ | we32k-* \
+ | x86-* | x86_64-* | xps100-* | xscale-* | xscalee[bl]-* \
+ | xstormy16-* | xtensa-* \
+ | ymp-* \
+ | z8k-*)
+ ;;
+ m32c-*)
+ ;;
+ # Recognize the various machine names and aliases which stand
+ # for a CPU type and a company and sometimes even an OS.
+ 386bsd)
+ basic_machine=i386-unknown
+ os=-bsd
+ ;;
+ 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
+ basic_machine=m68000-att
+ ;;
+ 3b*)
+ basic_machine=we32k-att
+ ;;
+ a29khif)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ abacus)
+ basic_machine=abacus-unknown
+ ;;
+ adobe68k)
+ basic_machine=m68010-adobe
+ os=-scout
+ ;;
+ alliant | fx80)
+ basic_machine=fx80-alliant
+ ;;
+ altos | altos3068)
+ basic_machine=m68k-altos
+ ;;
+ am29k)
+ basic_machine=a29k-none
+ os=-bsd
+ ;;
+ amd64)
+ basic_machine=x86_64-pc
+ ;;
+ amd64-*)
+ basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ amdahl)
+ basic_machine=580-amdahl
+ os=-sysv
+ ;;
+ amiga | amiga-*)
+ basic_machine=m68k-unknown
+ ;;
+ amigaos | amigados)
+ basic_machine=m68k-unknown
+ os=-amigaos
+ ;;
+ amigaunix | amix)
+ basic_machine=m68k-unknown
+ os=-sysv4
+ ;;
+ apollo68)
+ basic_machine=m68k-apollo
+ os=-sysv
+ ;;
+ apollo68bsd)
+ basic_machine=m68k-apollo
+ os=-bsd
+ ;;
+ aux)
+ basic_machine=m68k-apple
+ os=-aux
+ ;;
+ balance)
+ basic_machine=ns32k-sequent
+ os=-dynix
+ ;;
+ c90)
+ basic_machine=c90-cray
+ os=-unicos
+ ;;
+ convex-c1)
+ basic_machine=c1-convex
+ os=-bsd
+ ;;
+ convex-c2)
+ basic_machine=c2-convex
+ os=-bsd
+ ;;
+ convex-c32)
+ basic_machine=c32-convex
+ os=-bsd
+ ;;
+ convex-c34)
+ basic_machine=c34-convex
+ os=-bsd
+ ;;
+ convex-c38)
+ basic_machine=c38-convex
+ os=-bsd
+ ;;
+ cray | j90)
+ basic_machine=j90-cray
+ os=-unicos
+ ;;
+ craynv)
+ basic_machine=craynv-cray
+ os=-unicosmp
+ ;;
+ cr16c)
+ basic_machine=cr16c-unknown
+ os=-elf
+ ;;
+ crds | unos)
+ basic_machine=m68k-crds
+ ;;
+ crisv32 | crisv32-* | etraxfs*)
+ basic_machine=crisv32-axis
+ ;;
+ cris | cris-* | etrax*)
+ basic_machine=cris-axis
+ ;;
+ crx)
+ basic_machine=crx-unknown
+ os=-elf
+ ;;
+ da30 | da30-*)
+ basic_machine=m68k-da30
+ ;;
+ decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
+ basic_machine=mips-dec
+ ;;
+ decsystem10* | dec10*)
+ basic_machine=pdp10-dec
+ os=-tops10
+ ;;
+ decsystem20* | dec20*)
+ basic_machine=pdp10-dec
+ os=-tops20
+ ;;
+ delta | 3300 | motorola-3300 | motorola-delta \
+ | 3300-motorola | delta-motorola)
+ basic_machine=m68k-motorola
+ ;;
+ delta88)
+ basic_machine=m88k-motorola
+ os=-sysv3
+ ;;
+ djgpp)
+ basic_machine=i586-pc
+ os=-msdosdjgpp
+ ;;
+ dpx20 | dpx20-*)
+ basic_machine=rs6000-bull
+ os=-bosx
+ ;;
+ dpx2* | dpx2*-bull)
+ basic_machine=m68k-bull
+ os=-sysv3
+ ;;
+ ebmon29k)
+ basic_machine=a29k-amd
+ os=-ebmon
+ ;;
+ elxsi)
+ basic_machine=elxsi-elxsi
+ os=-bsd
+ ;;
+ encore | umax | mmax)
+ basic_machine=ns32k-encore
+ ;;
+ es1800 | OSE68k | ose68k | ose | OSE)
+ basic_machine=m68k-ericsson
+ os=-ose
+ ;;
+ fx2800)
+ basic_machine=i860-alliant
+ ;;
+ genix)
+ basic_machine=ns32k-ns
+ ;;
+ gmicro)
+ basic_machine=tron-gmicro
+ os=-sysv
+ ;;
+ go32)
+ basic_machine=i386-pc
+ os=-go32
+ ;;
+ h3050r* | hiux*)
+ basic_machine=hppa1.1-hitachi
+ os=-hiuxwe2
+ ;;
+ h8300hms)
+ basic_machine=h8300-hitachi
+ os=-hms
+ ;;
+ h8300xray)
+ basic_machine=h8300-hitachi
+ os=-xray
+ ;;
+ h8500hms)
+ basic_machine=h8500-hitachi
+ os=-hms
+ ;;
+ harris)
+ basic_machine=m88k-harris
+ os=-sysv3
+ ;;
+ hp300-*)
+ basic_machine=m68k-hp
+ ;;
+ hp300bsd)
+ basic_machine=m68k-hp
+ os=-bsd
+ ;;
+ hp300hpux)
+ basic_machine=m68k-hp
+ os=-hpux
+ ;;
+ hp3k9[0-9][0-9] | hp9[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hp9k2[0-9][0-9] | hp9k31[0-9])
+ basic_machine=m68000-hp
+ ;;
+ hp9k3[2-9][0-9])
+ basic_machine=m68k-hp
+ ;;
+ hp9k6[0-9][0-9] | hp6[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hp9k7[0-79][0-9] | hp7[0-79][0-9])
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k78[0-9] | hp78[0-9])
+ # FIXME: really hppa2.0-hp
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
+ # FIXME: really hppa2.0-hp
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[0-9][13679] | hp8[0-9][13679])
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[0-9][0-9] | hp8[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hppa-next)
+ os=-nextstep3
+ ;;
+ hppaosf)
+ basic_machine=hppa1.1-hp
+ os=-osf
+ ;;
+ hppro)
+ basic_machine=hppa1.1-hp
+ os=-proelf
+ ;;
+ i370-ibm* | ibm*)
+ basic_machine=i370-ibm
+ ;;
+# I'm not sure what "Sysv32" means. Should this be sysv3.2?
+ i*86v32)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv32
+ ;;
+ i*86v4*)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv4
+ ;;
+ i*86v)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv
+ ;;
+ i*86sol2)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-solaris2
+ ;;
+ i386mach)
+ basic_machine=i386-mach
+ os=-mach
+ ;;
+ i386-vsta | vsta)
+ basic_machine=i386-unknown
+ os=-vsta
+ ;;
+ iris | iris4d)
+ basic_machine=mips-sgi
+ case $os in
+ -irix*)
+ ;;
+ *)
+ os=-irix4
+ ;;
+ esac
+ ;;
+ isi68 | isi)
+ basic_machine=m68k-isi
+ os=-sysv
+ ;;
+ m88k-omron*)
+ basic_machine=m88k-omron
+ ;;
+ magnum | m3230)
+ basic_machine=mips-mips
+ os=-sysv
+ ;;
+ merlin)
+ basic_machine=ns32k-utek
+ os=-sysv
+ ;;
+ mingw32)
+ basic_machine=i386-pc
+ os=-mingw32
+ ;;
+ miniframe)
+ basic_machine=m68000-convergent
+ ;;
+ *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
+ basic_machine=m68k-atari
+ os=-mint
+ ;;
+ mips3*-*)
+ basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
+ ;;
+ mips3*)
+ basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
+ ;;
+ monitor)
+ basic_machine=m68k-rom68k
+ os=-coff
+ ;;
+ morphos)
+ basic_machine=powerpc-unknown
+ os=-morphos
+ ;;
+ msdos)
+ basic_machine=i386-pc
+ os=-msdos
+ ;;
+ ms1-*)
+ basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
+ ;;
+ mvs)
+ basic_machine=i370-ibm
+ os=-mvs
+ ;;
+ ncr3000)
+ basic_machine=i486-ncr
+ os=-sysv4
+ ;;
+ netbsd386)
+ basic_machine=i386-unknown
+ os=-netbsd
+ ;;
+ netwinder)
+ basic_machine=armv4l-rebel
+ os=-linux
+ ;;
+ news | news700 | news800 | news900)
+ basic_machine=m68k-sony
+ os=-newsos
+ ;;
+ news1000)
+ basic_machine=m68030-sony
+ os=-newsos
+ ;;
+ news-3600 | risc-news)
+ basic_machine=mips-sony
+ os=-newsos
+ ;;
+ necv70)
+ basic_machine=v70-nec
+ os=-sysv
+ ;;
+ next | m*-next )
+ basic_machine=m68k-next
+ case $os in
+ -nextstep* )
+ ;;
+ -ns2*)
+ os=-nextstep2
+ ;;
+ *)
+ os=-nextstep3
+ ;;
+ esac
+ ;;
+ nh3000)
+ basic_machine=m68k-harris
+ os=-cxux
+ ;;
+ nh[45]000)
+ basic_machine=m88k-harris
+ os=-cxux
+ ;;
+ nindy960)
+ basic_machine=i960-intel
+ os=-nindy
+ ;;
+ mon960)
+ basic_machine=i960-intel
+ os=-mon960
+ ;;
+ nonstopux)
+ basic_machine=mips-compaq
+ os=-nonstopux
+ ;;
+ np1)
+ basic_machine=np1-gould
+ ;;
+ nsr-tandem)
+ basic_machine=nsr-tandem
+ ;;
+ op50n-* | op60c-*)
+ basic_machine=hppa1.1-oki
+ os=-proelf
+ ;;
+ openrisc | openrisc-*)
+ basic_machine=or32-unknown
+ ;;
+ os400)
+ basic_machine=powerpc-ibm
+ os=-os400
+ ;;
+ OSE68000 | ose68000)
+ basic_machine=m68000-ericsson
+ os=-ose
+ ;;
+ os68k)
+ basic_machine=m68k-none
+ os=-os68k
+ ;;
+ pa-hitachi)
+ basic_machine=hppa1.1-hitachi
+ os=-hiuxwe2
+ ;;
+ paragon)
+ basic_machine=i860-intel
+ os=-osf
+ ;;
+ pbd)
+ basic_machine=sparc-tti
+ ;;
+ pbb)
+ basic_machine=m68k-tti
+ ;;
+ pc532 | pc532-*)
+ basic_machine=ns32k-pc532
+ ;;
+ pentium | p5 | k5 | k6 | nexgen | viac3)
+ basic_machine=i586-pc
+ ;;
+ pentiumpro | p6 | 6x86 | athlon | athlon_*)
+ basic_machine=i686-pc
+ ;;
+ pentiumii | pentium2 | pentiumiii | pentium3)
+ basic_machine=i686-pc
+ ;;
+ pentium4)
+ basic_machine=i786-pc
+ ;;
+ pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
+ basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentiumpro-* | p6-* | 6x86-* | athlon-*)
+ basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
+ basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentium4-*)
+ basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pn)
+ basic_machine=pn-gould
+ ;;
+ power) basic_machine=power-ibm
+ ;;
+ ppc) basic_machine=powerpc-unknown
+ ;;
+ ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppcle | powerpclittle | ppc-le | powerpc-little)
+ basic_machine=powerpcle-unknown
+ ;;
+ ppcle-* | powerpclittle-*)
+ basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppc64) basic_machine=powerpc64-unknown
+ ;;
+ ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppc64le | powerpc64little | ppc64-le | powerpc64-little)
+ basic_machine=powerpc64le-unknown
+ ;;
+ ppc64le-* | powerpc64little-*)
+ basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ps2)
+ basic_machine=i386-ibm
+ ;;
+ pw32)
+ basic_machine=i586-unknown
+ os=-pw32
+ ;;
+ rdos)
+ basic_machine=i386-pc
+ os=-rdos
+ ;;
+ rom68k)
+ basic_machine=m68k-rom68k
+ os=-coff
+ ;;
+ rm[46]00)
+ basic_machine=mips-siemens
+ ;;
+ rtpc | rtpc-*)
+ basic_machine=romp-ibm
+ ;;
+ s390 | s390-*)
+ basic_machine=s390-ibm
+ ;;
+ s390x | s390x-*)
+ basic_machine=s390x-ibm
+ ;;
+ sa29200)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ sb1)
+ basic_machine=mipsisa64sb1-unknown
+ ;;
+ sb1el)
+ basic_machine=mipsisa64sb1el-unknown
+ ;;
+ sei)
+ basic_machine=mips-sei
+ os=-seiux
+ ;;
+ sequent)
+ basic_machine=i386-sequent
+ ;;
+ sh)
+ basic_machine=sh-hitachi
+ os=-hms
+ ;;
+ sh64)
+ basic_machine=sh64-unknown
+ ;;
+ sparclite-wrs | simso-wrs)
+ basic_machine=sparclite-wrs
+ os=-vxworks
+ ;;
+ sps7)
+ basic_machine=m68k-bull
+ os=-sysv2
+ ;;
+ spur)
+ basic_machine=spur-unknown
+ ;;
+ st2000)
+ basic_machine=m68k-tandem
+ ;;
+ stratus)
+ basic_machine=i860-stratus
+ os=-sysv4
+ ;;
+ sun2)
+ basic_machine=m68000-sun
+ ;;
+ sun2os3)
+ basic_machine=m68000-sun
+ os=-sunos3
+ ;;
+ sun2os4)
+ basic_machine=m68000-sun
+ os=-sunos4
+ ;;
+ sun3os3)
+ basic_machine=m68k-sun
+ os=-sunos3
+ ;;
+ sun3os4)
+ basic_machine=m68k-sun
+ os=-sunos4
+ ;;
+ sun4os3)
+ basic_machine=sparc-sun
+ os=-sunos3
+ ;;
+ sun4os4)
+ basic_machine=sparc-sun
+ os=-sunos4
+ ;;
+ sun4sol2)
+ basic_machine=sparc-sun
+ os=-solaris2
+ ;;
+ sun3 | sun3-*)
+ basic_machine=m68k-sun
+ ;;
+ sun4)
+ basic_machine=sparc-sun
+ ;;
+ sun386 | sun386i | roadrunner)
+ basic_machine=i386-sun
+ ;;
+ sv1)
+ basic_machine=sv1-cray
+ os=-unicos
+ ;;
+ symmetry)
+ basic_machine=i386-sequent
+ os=-dynix
+ ;;
+ t3e)
+ basic_machine=alphaev5-cray
+ os=-unicos
+ ;;
+ t90)
+ basic_machine=t90-cray
+ os=-unicos
+ ;;
+ tic54x | c54x*)
+ basic_machine=tic54x-unknown
+ os=-coff
+ ;;
+ tic55x | c55x*)
+ basic_machine=tic55x-unknown
+ os=-coff
+ ;;
+ tic6x | c6x*)
+ basic_machine=tic6x-unknown
+ os=-coff
+ ;;
+ tx39)
+ basic_machine=mipstx39-unknown
+ ;;
+ tx39el)
+ basic_machine=mipstx39el-unknown
+ ;;
+ toad1)
+ basic_machine=pdp10-xkl
+ os=-tops20
+ ;;
+ tower | tower-32)
+ basic_machine=m68k-ncr
+ ;;
+ tpf)
+ basic_machine=s390x-ibm
+ os=-tpf
+ ;;
+ udi29k)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ ultra3)
+ basic_machine=a29k-nyu
+ os=-sym1
+ ;;
+ v810 | necv810)
+ basic_machine=v810-nec
+ os=-none
+ ;;
+ vaxv)
+ basic_machine=vax-dec
+ os=-sysv
+ ;;
+ vms)
+ basic_machine=vax-dec
+ os=-vms
+ ;;
+ vpp*|vx|vx-*)
+ basic_machine=f301-fujitsu
+ ;;
+ vxworks960)
+ basic_machine=i960-wrs
+ os=-vxworks
+ ;;
+ vxworks68)
+ basic_machine=m68k-wrs
+ os=-vxworks
+ ;;
+ vxworks29k)
+ basic_machine=a29k-wrs
+ os=-vxworks
+ ;;
+ w65*)
+ basic_machine=w65-wdc
+ os=-none
+ ;;
+ w89k-*)
+ basic_machine=hppa1.1-winbond
+ os=-proelf
+ ;;
+ xbox)
+ basic_machine=i686-pc
+ os=-mingw32
+ ;;
+ xps | xps100)
+ basic_machine=xps100-honeywell
+ ;;
+ ymp)
+ basic_machine=ymp-cray
+ os=-unicos
+ ;;
+ z8k-*-coff)
+ basic_machine=z8k-unknown
+ os=-sim
+ ;;
+ none)
+ basic_machine=none-none
+ os=-none
+ ;;
+
+# Here we handle the default manufacturer of certain CPU types. It is in
+# some cases the only manufacturer, in others, it is the most popular.
+ w89k)
+ basic_machine=hppa1.1-winbond
+ ;;
+ op50n)
+ basic_machine=hppa1.1-oki
+ ;;
+ op60c)
+ basic_machine=hppa1.1-oki
+ ;;
+ romp)
+ basic_machine=romp-ibm
+ ;;
+ mmix)
+ basic_machine=mmix-knuth
+ ;;
+ rs6000)
+ basic_machine=rs6000-ibm
+ ;;
+ vax)
+ basic_machine=vax-dec
+ ;;
+ pdp10)
+ # there are many clones, so DEC is not a safe bet
+ basic_machine=pdp10-unknown
+ ;;
+ pdp11)
+ basic_machine=pdp11-dec
+ ;;
+ we32k)
+ basic_machine=we32k-att
+ ;;
+ sh[1234] | sh[24]a | sh[34]eb | sh[1234]le | sh[23]ele)
+ basic_machine=sh-unknown
+ ;;
+ sparc | sparcv8 | sparcv9 | sparcv9b)
+ basic_machine=sparc-sun
+ ;;
+ cydra)
+ basic_machine=cydra-cydrome
+ ;;
+ orion)
+ basic_machine=orion-highlevel
+ ;;
+ orion105)
+ basic_machine=clipper-highlevel
+ ;;
+ mac | mpw | mac-mpw)
+ basic_machine=m68k-apple
+ ;;
+ pmac | pmac-mpw)
+ basic_machine=powerpc-apple
+ ;;
+ *-unknown)
+ # Make sure to match an already-canonicalized machine name.
+ ;;
+ *)
+ echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+ exit 1
+ ;;
+esac
+
+# Here we canonicalize certain aliases for manufacturers.
+case $basic_machine in
+ *-digital*)
+ basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
+ ;;
+ *-commodore*)
+ basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
+ ;;
+ *)
+ ;;
+esac
+
+# Decode manufacturer-specific aliases for certain operating systems.
+
+if [ x"$os" != x"" ]
+then
+case $os in
+ # First match some system type aliases
+ # that might get confused with valid system types.
+ # -solaris* is a basic system type, with this one exception.
+ -solaris1 | -solaris1.*)
+ os=`echo $os | sed -e 's|solaris1|sunos4|'`
+ ;;
+ -solaris)
+ os=-solaris2
+ ;;
+ -svr4*)
+ os=-sysv4
+ ;;
+ -unixware*)
+ os=-sysv4.2uw
+ ;;
+ -gnu/linux*)
+ os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
+ ;;
+ # First accept the basic system types.
+ # The portable systems comes first.
+ # Each alternative MUST END IN A *, to match a version number.
+ # -sysv* is not here because it comes later, after sysvr4.
+ -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
+ | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\
+ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
+ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
+ | -aos* \
+ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
+ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
+ | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* | -openbsd* \
+ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
+ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
+ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
+ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
+ | -chorusos* | -chorusrdb* \
+ | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+ | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \
+ | -uxpv* | -beos* | -mpeix* | -udk* \
+ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
+ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
+ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
+ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
+ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
+ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
+ | -skyos* | -haiku* | -rdos*)
+ # Remember, each alternative MUST END IN *, to match a version number.
+ ;;
+ -qnx*)
+ case $basic_machine in
+ x86-* | i*86-*)
+ ;;
+ *)
+ os=-nto$os
+ ;;
+ esac
+ ;;
+ -nto-qnx*)
+ ;;
+ -nto*)
+ os=`echo $os | sed -e 's|nto|nto-qnx|'`
+ ;;
+ -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
+ | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \
+ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
+ ;;
+ -mac*)
+ os=`echo $os | sed -e 's|mac|macos|'`
+ ;;
+ -linux-dietlibc)
+ os=-linux-dietlibc
+ ;;
+ -linux*)
+ os=`echo $os | sed -e 's|linux|linux-gnu|'`
+ ;;
+ -sunos5*)
+ os=`echo $os | sed -e 's|sunos5|solaris2|'`
+ ;;
+ -sunos6*)
+ os=`echo $os | sed -e 's|sunos6|solaris3|'`
+ ;;
+ -opened*)
+ os=-openedition
+ ;;
+ -os400*)
+ os=-os400
+ ;;
+ -wince*)
+ os=-wince
+ ;;
+ -osfrose*)
+ os=-osfrose
+ ;;
+ -osf*)
+ os=-osf
+ ;;
+ -utek*)
+ os=-bsd
+ ;;
+ -dynix*)
+ os=-bsd
+ ;;
+ -acis*)
+ os=-aos
+ ;;
+ -atheos*)
+ os=-atheos
+ ;;
+ -syllable*)
+ os=-syllable
+ ;;
+ -386bsd)
+ os=-bsd
+ ;;
+ -ctix* | -uts*)
+ os=-sysv
+ ;;
+ -nova*)
+ os=-rtmk-nova
+ ;;
+ -ns2 )
+ os=-nextstep2
+ ;;
+ -nsk*)
+ os=-nsk
+ ;;
+ # Preserve the version number of sinix5.
+ -sinix5.*)
+ os=`echo $os | sed -e 's|sinix|sysv|'`
+ ;;
+ -sinix*)
+ os=-sysv4
+ ;;
+ -tpf*)
+ os=-tpf
+ ;;
+ -triton*)
+ os=-sysv3
+ ;;
+ -oss*)
+ os=-sysv3
+ ;;
+ -svr4)
+ os=-sysv4
+ ;;
+ -svr3)
+ os=-sysv3
+ ;;
+ -sysvr4)
+ os=-sysv4
+ ;;
+ # This must come after -sysvr4.
+ -sysv*)
+ ;;
+ -ose*)
+ os=-ose
+ ;;
+ -es1800*)
+ os=-ose
+ ;;
+ -xenix)
+ os=-xenix
+ ;;
+ -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+ os=-mint
+ ;;
+ -aros*)
+ os=-aros
+ ;;
+ -kaos*)
+ os=-kaos
+ ;;
+ -zvmoe)
+ os=-zvmoe
+ ;;
+ -none)
+ ;;
+ *)
+ # Get rid of the `-' at the beginning of $os.
+ os=`echo $os | sed 's/[^-]*-//'`
+ echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
+ exit 1
+ ;;
+esac
+else
+
+# Here we handle the default operating systems that come with various machines.
+# The value should be what the vendor currently ships out the door with their
+# machine or put another way, the most popular os provided with the machine.
+
+# Note that if you're going to try to match "-MANUFACTURER" here (say,
+# "-sun"), then you have to tell the case statement up towards the top
+# that MANUFACTURER isn't an operating system. Otherwise, code above
+# will signal an error saying that MANUFACTURER isn't an operating
+# system, and we'll never get to this point.
+
+case $basic_machine in
+ *-acorn)
+ os=-riscix1.2
+ ;;
+ arm*-rebel)
+ os=-linux
+ ;;
+ arm*-semi)
+ os=-aout
+ ;;
+ c4x-* | tic4x-*)
+ os=-coff
+ ;;
+ # This must come before the *-dec entry.
+ pdp10-*)
+ os=-tops20
+ ;;
+ pdp11-*)
+ os=-none
+ ;;
+ *-dec | vax-*)
+ os=-ultrix4.2
+ ;;
+ m68*-apollo)
+ os=-domain
+ ;;
+ i386-sun)
+ os=-sunos4.0.2
+ ;;
+ m68000-sun)
+ os=-sunos3
+ # This also exists in the configure program, but was not the
+ # default.
+ # os=-sunos4
+ ;;
+ m68*-cisco)
+ os=-aout
+ ;;
+ mips*-cisco)
+ os=-elf
+ ;;
+ mips*-*)
+ os=-elf
+ ;;
+ or32-*)
+ os=-coff
+ ;;
+ *-tti) # must be before sparc entry or we get the wrong os.
+ os=-sysv3
+ ;;
+ sparc-* | *-sun)
+ os=-sunos4.1.1
+ ;;
+ *-be)
+ os=-beos
+ ;;
+ *-haiku)
+ os=-haiku
+ ;;
+ *-ibm)
+ os=-aix
+ ;;
+ *-knuth)
+ os=-mmixware
+ ;;
+ *-wec)
+ os=-proelf
+ ;;
+ *-winbond)
+ os=-proelf
+ ;;
+ *-oki)
+ os=-proelf
+ ;;
+ *-hp)
+ os=-hpux
+ ;;
+ *-hitachi)
+ os=-hiux
+ ;;
+ i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
+ os=-sysv
+ ;;
+ *-cbm)
+ os=-amigaos
+ ;;
+ *-dg)
+ os=-dgux
+ ;;
+ *-dolphin)
+ os=-sysv3
+ ;;
+ m68k-ccur)
+ os=-rtu
+ ;;
+ m88k-omron*)
+ os=-luna
+ ;;
+ *-next )
+ os=-nextstep
+ ;;
+ *-sequent)
+ os=-ptx
+ ;;
+ *-crds)
+ os=-unos
+ ;;
+ *-ns)
+ os=-genix
+ ;;
+ i370-*)
+ os=-mvs
+ ;;
+ *-next)
+ os=-nextstep3
+ ;;
+ *-gould)
+ os=-sysv
+ ;;
+ *-highlevel)
+ os=-bsd
+ ;;
+ *-encore)
+ os=-bsd
+ ;;
+ *-sgi)
+ os=-irix
+ ;;
+ *-siemens)
+ os=-sysv4
+ ;;
+ *-masscomp)
+ os=-rtu
+ ;;
+ f30[01]-fujitsu | f700-fujitsu)
+ os=-uxpv
+ ;;
+ *-rom68k)
+ os=-coff
+ ;;
+ *-*bug)
+ os=-coff
+ ;;
+ *-apple)
+ os=-macos
+ ;;
+ *-atari*)
+ os=-mint
+ ;;
+ *)
+ os=-none
+ ;;
+esac
+fi
+
+# Here we handle the case where we know the os, and the CPU type, but not the
+# manufacturer. We pick the logical manufacturer.
+vendor=unknown
+case $basic_machine in
+ *-unknown)
+ case $os in
+ -riscix*)
+ vendor=acorn
+ ;;
+ -sunos*)
+ vendor=sun
+ ;;
+ -aix*)
+ vendor=ibm
+ ;;
+ -beos*)
+ vendor=be
+ ;;
+ -hpux*)
+ vendor=hp
+ ;;
+ -mpeix*)
+ vendor=hp
+ ;;
+ -hiux*)
+ vendor=hitachi
+ ;;
+ -unos*)
+ vendor=crds
+ ;;
+ -dgux*)
+ vendor=dg
+ ;;
+ -luna*)
+ vendor=omron
+ ;;
+ -genix*)
+ vendor=ns
+ ;;
+ -mvs* | -opened*)
+ vendor=ibm
+ ;;
+ -os400*)
+ vendor=ibm
+ ;;
+ -ptx*)
+ vendor=sequent
+ ;;
+ -tpf*)
+ vendor=ibm
+ ;;
+ -vxsim* | -vxworks* | -windiss*)
+ vendor=wrs
+ ;;
+ -aux*)
+ vendor=apple
+ ;;
+ -hms*)
+ vendor=hitachi
+ ;;
+ -mpw* | -macos*)
+ vendor=apple
+ ;;
+ -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+ vendor=atari
+ ;;
+ -vos*)
+ vendor=stratus
+ ;;
+ esac
+ basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
+ ;;
+esac
+
+echo $basic_machine$os
+exit
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/config/cust_general.m4 b/config/cust_general.m4
new file mode 100644
index 0000000..73c0f7c
--- /dev/null
+++ b/config/cust_general.m4
@@ -0,0 +1,94 @@
+# This file is part of Autoconf. -*- Autoconf -*-
+# Parameterized macros.
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
+# 2002, 2003, Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+# 02111-1307, USA.
+
+# As a special exception, the Free Software Foundation gives unlimited
+# permission to copy, distribute and modify the configure scripts that
+# are the output of Autoconf. You need not follow the terms of the GNU
+# General Public License when using or distributing such scripts, even
+# though portions of the text of Autoconf appear in them. The GNU
+# General Public License (GPL) does govern all other use of the material
+# that constitutes the Autoconf program.
+#
+# Certain portions of the Autoconf source text are designed to be copied
+# (in certain cases, depending on the input) into the output of
+# Autoconf. We call these the "data" portions. The rest of the Autoconf
+# source text consists of comments plus executable code that decides which
+# of the data portions to output in any given case. We call these
+# comments and executable code the "non-data" portions. Autoconf never
+# copies any of the non-data portions into its output.
+#
+# This special exception to the GPL applies to versions of Autoconf
+# released by the Free Software Foundation. When you make and
+# distribute a modified version of Autoconf, you may extend this special
+# exception to the GPL to apply to your modified version as well, *unless*
+# your modified version has the potential to copy into its output some
+# of the text that was the non-data portion of the version that you started
+# with. (In other words, unless your change moves or copies text from
+# the non-data portions to the data portions.) If your modification has
+# such potential, you must delete any notice of this special exception
+# to the GPL from your modified version.
+#
+# Written by David MacKenzie, with help from
+# Franc,ois Pinard, Karl Berry, Richard Pixley, Ian Lance Taylor,
+# Roland McGrath, Noah Friedman, david d zuhn, and many others.
+
+
+# _AC_MSG_LOG_CONFTEST_GENERAL
+# ----------------------------
+m4_define([_AC_MSG_LOG_CONFTEST_GENERAL],
+[echo "$as_me: failed program was:" >&AS_MESSAGE_LOG_FD
+if test -f conftest.c ; then
+ sed 's/^/| /' conftest.c >&AS_MESSAGE_LOG_FD
+elif test -f conftest.cc ; then
+ sed 's/^/| /' conftest.cc >&AS_MESSAGE_LOG_FD
+elif test -f conftest.f ; then
+ sed 's/^/| /' conftest.f >&AS_MESSAGE_LOG_FD
+elif test -f conftest.${FC_SRCEXT-f} ; then
+ sed 's/^/| /' conftest.${FC_SRCEXT-f} >&AS_MESSAGE_LOG_FD
+fi
+])
+
+
+# _AC_LINKONLY_IFELSE(PROGRAM, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+# ------------------------------------------------------------------
+# Try to link PROGRAM (empty).
+# This macro can be used during the selection of a compiler.
+m4_define([_AC_LINKONLY_IFELSE],
+[m4_ifvaln([$1], [AC_LANG_CONFTEST([$1])])dnl
+AS_IF([_AC_EVAL_STDERR($ac_linkonly) &&
+ AC_TRY_COMMAND([test -z "$ac_[]_AC_LANG_ABBREV[]_werror_flag"
+ || test ! -s conftest.err]) &&
+ AC_TRY_COMMAND([test -s conftest$ac_exeext])],
+ [$2],
+ [_AC_MSG_LOG_CONFTEST_GENERAL
+m4_ifvaln([$3], [$3])dnl])[]dnl
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext m4_ifval([$1], [conftest.$ac_ext])[]dnl
+])# _AC_LINKONLY_IFELSE
+
+
+# AC_LINKONLY_IFELSE(PROGRAM, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+# -----------------------------------------------------------------
+# Try to link PROGRAM. Requires that the compiler for the current
+# language was checked for, hence do not use this macro in macros looking
+# for a compiler.
+AC_DEFUN([AC_LINKONLY_IFELSE],
+[AC_LANG_COMPILER_REQUIRE()dnl
+_AC_LINKONLY_IFELSE($@)])
diff --git a/config/install-sh b/config/install-sh
new file mode 100755
index 0000000..e9de238
--- /dev/null
+++ b/config/install-sh
@@ -0,0 +1,251 @@
+#!/bin/sh
+#
+# install - install a program, script, or datafile
+# This comes from X11R5 (mit/util/scripts/install.sh).
+#
+# Copyright 1991 by the Massachusetts Institute of Technology
+#
+# Permission to use, copy, modify, distribute, and sell this software and its
+# documentation for any purpose is hereby granted without fee, provided that
+# the above copyright notice appear in all copies and that both that
+# copyright notice and this permission notice appear in supporting
+# documentation, and that the name of M.I.T. not be used in advertising or
+# publicity pertaining to distribution of the software without specific,
+# written prior permission. M.I.T. makes no representations about the
+# suitability of this software for any purpose. It is provided "as is"
+# without express or implied warranty.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch. It can only install one file at a time, a restriction
+# shared with many OS's install programs.
+
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+
+
+# put in absolute paths if you don't have them in your path; or use env. vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+mkdirprog="${MKDIRPROG-mkdir}"
+
+transformbasename=""
+transform_arg=""
+instcmd="$mvprog"
+chmodcmd="$chmodprog 0755"
+chowncmd=""
+chgrpcmd=""
+stripcmd=""
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=""
+dst=""
+dir_arg=""
+
+while [ x"$1" != x ]; do
+ case $1 in
+ -c) instcmd="$cpprog"
+ shift
+ continue;;
+
+ -d) dir_arg=true
+ shift
+ continue;;
+
+ -m) chmodcmd="$chmodprog $2"
+ shift
+ shift
+ continue;;
+
+ -o) chowncmd="$chownprog $2"
+ shift
+ shift
+ continue;;
+
+ -g) chgrpcmd="$chgrpprog $2"
+ shift
+ shift
+ continue;;
+
+ -s) stripcmd="$stripprog"
+ shift
+ continue;;
+
+ -t=*) transformarg=`echo $1 | sed 's/-t=//'`
+ shift
+ continue;;
+
+ -b=*) transformbasename=`echo $1 | sed 's/-b=//'`
+ shift
+ continue;;
+
+ *) if [ x"$src" = x ]
+ then
+ src=$1
+ else
+ # this colon is to work around a 386BSD /bin/sh bug
+ :
+ dst=$1
+ fi
+ shift
+ continue;;
+ esac
+done
+
+if [ x"$src" = x ]
+then
+ echo "install: no input file specified"
+ exit 1
+else
+ true
+fi
+
+if [ x"$dir_arg" != x ]; then
+ dst=$src
+ src=""
+
+ if [ -d $dst ]; then
+ instcmd=:
+ chmodcmd=""
+ else
+ instcmd=mkdir
+ fi
+else
+
+# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
+# might cause directories to be created, which would be especially bad
+# if $src (and thus $dsttmp) contains '*'.
+
+ if [ -f $src -o -d $src ]
+ then
+ true
+ else
+ echo "install: $src does not exist"
+ exit 1
+ fi
+
+ if [ x"$dst" = x ]
+ then
+ echo "install: no destination specified"
+ exit 1
+ else
+ true
+ fi
+
+# If destination is a directory, append the input filename; if your system
+# does not like double slashes in filenames, you may need to add some logic
+
+ if [ -d $dst ]
+ then
+ dst="$dst"/`basename $src`
+ else
+ true
+ fi
+fi
+
+## this sed command emulates the dirname command
+dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
+
+# Make sure that the destination directory exists.
+# this part is taken from Noah Friedman's mkinstalldirs script
+
+# Skip lots of stat calls in the usual case.
+if [ ! -d "$dstdir" ]; then
+defaultIFS='
+'
+IFS="${IFS-${defaultIFS}}"
+
+oIFS="${IFS}"
+# Some sh's can't handle IFS=/ for some reason.
+IFS='%'
+set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
+IFS="${oIFS}"
+
+pathcomp=''
+
+while [ $# -ne 0 ] ; do
+ pathcomp="${pathcomp}${1}"
+ shift
+
+ if [ ! -d "${pathcomp}" ] ;
+ then
+ $mkdirprog "${pathcomp}"
+ else
+ true
+ fi
+
+ pathcomp="${pathcomp}/"
+done
+fi
+
+if [ x"$dir_arg" != x ]
+then
+ $doit $instcmd $dst &&
+
+ if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
+ if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
+ if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
+ if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
+else
+
+# If we're going to rename the final executable, determine the name now.
+
+ if [ x"$transformarg" = x ]
+ then
+ dstfile=`basename $dst`
+ else
+ dstfile=`basename $dst $transformbasename |
+ sed $transformarg`$transformbasename
+ fi
+
+# don't allow the sed command to completely eliminate the filename
+
+ if [ x"$dstfile" = x ]
+ then
+ dstfile=`basename $dst`
+ else
+ true
+ fi
+
+# Make a temp file name in the proper directory.
+
+ dsttmp=$dstdir/#inst.$$#
+
+# Move or copy the file name to the temp name
+
+ $doit $instcmd $src $dsttmp &&
+
+ trap "rm -f ${dsttmp}" 0 &&
+
+# and set any options; do chmod last to preserve setuid bits
+
+# If any of these fail, we abort the whole thing. If we want to
+# ignore errors from any of these, just make sure not to ignore
+# errors from the above "$doit $instcmd $src $dsttmp" command.
+
+ if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
+ if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
+ if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
+ if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
+
+# Now rename the file to the real destination.
+
+ $doit $rmcmd -f $dstdir/$dstfile &&
+ $doit $mvcmd $dsttmp $dstdir/$dstfile
+
+fi &&
+
+
+exit 0
diff --git a/config/ltmain.sh b/config/ltmain.sh
new file mode 100644
index 0000000..ce4a877
--- /dev/null
+++ b/config/ltmain.sh
@@ -0,0 +1,6868 @@
+# ltmain.sh - Provide generalized library-building support services.
+# NOTE: Changing this file will not affect anything until you rerun configure.
+#
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005
+# Free Software Foundation, Inc.
+# Originally by Gordon Matzigkeit <gord at gnu.ai.mit.edu>, 1996
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+basename="s,^.*/,,g"
+
+# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh
+# is ksh but when the shell is invoked as "sh" and the current value of
+# the _XPG environment variable is not equal to 1 (one), the special
+# positional parameter $0, within a function call, is the name of the
+# function.
+progpath="$0"
+
+# The name of this program:
+progname=`echo "$progpath" | $SED $basename`
+modename="$progname"
+
+# Global variables:
+EXIT_SUCCESS=0
+EXIT_FAILURE=1
+
+PROGRAM=ltmain.sh
+PACKAGE=libtool
+VERSION=1.5.22
+TIMESTAMP=" (1.1220.2.365 2005/12/18 22:14:06)"
+
+# See if we are running on zsh, and set the options which allow our
+# commands through without removal of \ escapes.
+if test -n "${ZSH_VERSION+set}" ; then
+ setopt NO_GLOB_SUBST
+fi
+
+# Check that we have a working $echo.
+if test "X$1" = X--no-reexec; then
+ # Discard the --no-reexec flag, and continue.
+ shift
+elif test "X$1" = X--fallback-echo; then
+ # Avoid inline document here, it may be left over
+ :
+elif test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then
+ # Yippee, $echo works!
+ :
+else
+ # Restart under the correct shell, and then maybe $echo will work.
+ exec $SHELL "$progpath" --no-reexec ${1+"$@"}
+fi
+
+if test "X$1" = X--fallback-echo; then
+ # used as fallback echo
+ shift
+ cat <<EOF
+$*
+EOF
+ exit $EXIT_SUCCESS
+fi
+
+default_mode=
+help="Try \`$progname --help' for more information."
+magic="%%%MAGIC variable%%%"
+mkdir="mkdir"
+mv="mv -f"
+rm="rm -f"
+
+# Sed substitution that helps us do robust quoting. It backslashifies
+# metacharacters that are still active within double-quoted strings.
+Xsed="${SED}"' -e 1s/^X//'
+sed_quote_subst='s/\([\\`\\"$\\\\]\)/\\\1/g'
+# test EBCDIC or ASCII
+case `echo X|tr X '\101'` in
+ A) # ASCII based system
+ # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr
+ SP2NL='tr \040 \012'
+ NL2SP='tr \015\012 \040\040'
+ ;;
+ *) # EBCDIC based system
+ SP2NL='tr \100 \n'
+ NL2SP='tr \r\n \100\100'
+ ;;
+esac
+
+# NLS nuisances.
+# Only set LANG and LC_ALL to C if already set.
+# These must not be set unconditionally because not all systems understand
+# e.g. LANG=C (notably SCO).
+# We save the old values to restore during execute mode.
+if test "${LC_ALL+set}" = set; then
+ save_LC_ALL="$LC_ALL"; LC_ALL=C; export LC_ALL
+fi
+if test "${LANG+set}" = set; then
+ save_LANG="$LANG"; LANG=C; export LANG
+fi
+
+# Make sure IFS has a sensible default
+lt_nl='
+'
+IFS=" $lt_nl"
+
+if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then
+ $echo "$modename: not configured to build any kind of library" 1>&2
+ $echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2
+ exit $EXIT_FAILURE
+fi
+
+# Global variables.
+mode=$default_mode
+nonopt=
+prev=
+prevopt=
+run=
+show="$echo"
+show_help=
+execute_dlfiles=
+duplicate_deps=no
+preserve_args=
+lo2o="s/\\.lo\$/.${objext}/"
+o2lo="s/\\.${objext}\$/.lo/"
+
+#####################################
+# Shell function definitions:
+# This seems to be the best place for them
+
+# func_mktempdir [string]
+# Make a temporary directory that won't clash with other running
+# libtool processes, and avoids race conditions if possible. If
+# given, STRING is the basename for that directory.
+func_mktempdir ()
+{
+ my_template="${TMPDIR-/tmp}/${1-$progname}"
+
+ if test "$run" = ":"; then
+ # Return a directory name, but don't create it in dry-run mode
+ my_tmpdir="${my_template}-$$"
+ else
+
+ # If mktemp works, use that first and foremost
+ my_tmpdir=`mktemp -d "${my_template}-XXXXXXXX" 2>/dev/null`
+
+ if test ! -d "$my_tmpdir"; then
+ # Failing that, at least try and use $RANDOM to avoid a race
+ my_tmpdir="${my_template}-${RANDOM-0}$$"
+
+ save_mktempdir_umask=`umask`
+ umask 0077
+ $mkdir "$my_tmpdir"
+ umask $save_mktempdir_umask
+ fi
+
+ # If we're not in dry-run mode, bomb out on failure
+ test -d "$my_tmpdir" || {
+ $echo "cannot create temporary directory \`$my_tmpdir'" 1>&2
+ exit $EXIT_FAILURE
+ }
+ fi
+
+ $echo "X$my_tmpdir" | $Xsed
+}
+
+
+# func_win32_libid arg
+# return the library type of file 'arg'
+#
+# Need a lot of goo to handle *both* DLLs and import libs
+# Has to be a shell function in order to 'eat' the argument
+# that is supplied when $file_magic_command is called.
+func_win32_libid ()
+{
+ win32_libid_type="unknown"
+ win32_fileres=`file -L $1 2>/dev/null`
+ case $win32_fileres in
+ *ar\ archive\ import\ library*) # definitely import
+ win32_libid_type="x86 archive import"
+ ;;
+ *ar\ archive*) # could be an import, or static
+ if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | \
+ $EGREP -e 'file format pe-i386(.*architecture: i386)?' >/dev/null ; then
+ win32_nmres=`eval $NM -f posix -A $1 | \
+ $SED -n -e '1,100{/ I /{s,.*,import,;p;q;};}'`
+ case $win32_nmres in
+ import*) win32_libid_type="x86 archive import";;
+ *) win32_libid_type="x86 archive static";;
+ esac
+ fi
+ ;;
+ *DLL*)
+ win32_libid_type="x86 DLL"
+ ;;
+ *executable*) # but shell scripts are "executable" too...
+ case $win32_fileres in
+ *MS\ Windows\ PE\ Intel*)
+ win32_libid_type="x86 DLL"
+ ;;
+ esac
+ ;;
+ esac
+ $echo $win32_libid_type
+}
+
+
+# func_infer_tag arg
+# Infer tagged configuration to use if any are available and
+# if one wasn't chosen via the "--tag" command line option.
+# Only attempt this if the compiler in the base compile
+# command doesn't match the default compiler.
+# arg is usually of the form 'gcc ...'
+func_infer_tag ()
+{
+ if test -n "$available_tags" && test -z "$tagname"; then
+ CC_quoted=
+ for arg in $CC; do
+ case $arg in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ arg="\"$arg\""
+ ;;
+ esac
+ CC_quoted="$CC_quoted $arg"
+ done
+ case $@ in
+ # Blanks in the command may have been stripped by the calling shell,
+ # but not from the CC environment variable when configure was run.
+ " $CC "* | "$CC "* | " `$echo $CC` "* | "`$echo $CC` "* | " $CC_quoted"* | "$CC_quoted "* | " `$echo $CC_quoted` "* | "`$echo $CC_quoted` "*) ;;
+ # Blanks at the start of $base_compile will cause this to fail
+ # if we don't check for them as well.
+ *)
+ for z in $available_tags; do
+ if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then
+ # Evaluate the configuration.
+ eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`"
+ CC_quoted=
+ for arg in $CC; do
+ # Double-quote args containing other shell metacharacters.
+ case $arg in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ arg="\"$arg\""
+ ;;
+ esac
+ CC_quoted="$CC_quoted $arg"
+ done
+ case "$@ " in
+ " $CC "* | "$CC "* | " `$echo $CC` "* | "`$echo $CC` "* | " $CC_quoted"* | "$CC_quoted "* | " `$echo $CC_quoted` "* | "`$echo $CC_quoted` "*)
+ # The compiler in the base compile command matches
+ # the one in the tagged configuration.
+ # Assume this is the tagged configuration we want.
+ tagname=$z
+ break
+ ;;
+ esac
+ fi
+ done
+ # If $tagname still isn't set, then no tagged configuration
+ # was found and let the user know that the "--tag" command
+ # line option must be used.
+ #
+ #
+ # Modified by R.Serban (Nov. 28, 2006) to use the default
+ # CC tag if unable to infer one
+ if test -z "$tagname"; then
+ tagname=CC
+# $echo "$modename: unable to infer tagged configuration"
+# $echo "$modename: specify a tag with \`--tag'" 1>&2
+# exit $EXIT_FAILURE
+# else
+# $echo "$modename: using $tagname tagged configuration"
+ fi
+ ;;
+ esac
+ fi
+}
+
+
+# func_extract_an_archive dir oldlib
+func_extract_an_archive ()
+{
+ f_ex_an_ar_dir="$1"; shift
+ f_ex_an_ar_oldlib="$1"
+
+ $show "(cd $f_ex_an_ar_dir && $AR x $f_ex_an_ar_oldlib)"
+ $run eval "(cd \$f_ex_an_ar_dir && $AR x \$f_ex_an_ar_oldlib)" || exit $?
+ if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then
+ :
+ else
+ $echo "$modename: ERROR: object name conflicts: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" 1>&2
+ exit $EXIT_FAILURE
+ fi
+}
+
+# func_extract_archives gentop oldlib ...
+func_extract_archives ()
+{
+ my_gentop="$1"; shift
+ my_oldlibs=${1+"$@"}
+ my_oldobjs=""
+ my_xlib=""
+ my_xabs=""
+ my_xdir=""
+ my_status=""
+
+ $show "${rm}r $my_gentop"
+ $run ${rm}r "$my_gentop"
+ $show "$mkdir $my_gentop"
+ $run $mkdir "$my_gentop"
+ my_status=$?
+ if test "$my_status" -ne 0 && test ! -d "$my_gentop"; then
+ exit $my_status
+ fi
+
+ for my_xlib in $my_oldlibs; do
+ # Extract the objects.
+ case $my_xlib in
+ [\\/]* | [A-Za-z]:[\\/]*) my_xabs="$my_xlib" ;;
+ *) my_xabs=`pwd`"/$my_xlib" ;;
+ esac
+ my_xlib=`$echo "X$my_xlib" | $Xsed -e 's%^.*/%%'`
+ my_xdir="$my_gentop/$my_xlib"
+
+ $show "${rm}r $my_xdir"
+ $run ${rm}r "$my_xdir"
+ $show "$mkdir $my_xdir"
+ $run $mkdir "$my_xdir"
+ exit_status=$?
+ if test "$exit_status" -ne 0 && test ! -d "$my_xdir"; then
+ exit $exit_status
+ fi
+ case $host in
+ *-darwin*)
+ $show "Extracting $my_xabs"
+ # Do not bother doing anything if just a dry run
+ if test -z "$run"; then
+ darwin_orig_dir=`pwd`
+ cd $my_xdir || exit $?
+ darwin_archive=$my_xabs
+ darwin_curdir=`pwd`
+ darwin_base_archive=`$echo "X$darwin_archive" | $Xsed -e 's%^.*/%%'`
+ darwin_arches=`lipo -info "$darwin_archive" 2>/dev/null | $EGREP Architectures 2>/dev/null`
+ if test -n "$darwin_arches"; then
+ darwin_arches=`echo "$darwin_arches" | $SED -e 's/.*are://'`
+ darwin_arch=
+ $show "$darwin_base_archive has multiple architectures $darwin_arches"
+ for darwin_arch in $darwin_arches ; do
+ mkdir -p "unfat-$$/${darwin_base_archive}-${darwin_arch}"
+ lipo -thin $darwin_arch -output "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" "${darwin_archive}"
+ cd "unfat-$$/${darwin_base_archive}-${darwin_arch}"
+ func_extract_an_archive "`pwd`" "${darwin_base_archive}"
+ cd "$darwin_curdir"
+ $rm "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}"
+ done # $darwin_arches
+ ## Okay now we have a bunch of thin objects, gotta fatten them up :)
+ darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print| xargs basename | sort -u | $NL2SP`
+ darwin_file=
+ darwin_files=
+ for darwin_file in $darwin_filelist; do
+ darwin_files=`find unfat-$$ -name $darwin_file -print | $NL2SP`
+ lipo -create -output "$darwin_file" $darwin_files
+ done # $darwin_filelist
+ ${rm}r unfat-$$
+ cd "$darwin_orig_dir"
+ else
+ cd "$darwin_orig_dir"
+ func_extract_an_archive "$my_xdir" "$my_xabs"
+ fi # $darwin_arches
+ fi # $run
+ ;;
+ *)
+ func_extract_an_archive "$my_xdir" "$my_xabs"
+ ;;
+ esac
+ my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | $NL2SP`
+ done
+ func_extract_archives_result="$my_oldobjs"
+}
+# End of Shell function definitions
+#####################################
+
+# Darwin sucks
+eval std_shrext=\"$shrext_cmds\"
+
+disable_libs=no
+
+# Parse our command line options once, thoroughly.
+while test "$#" -gt 0
+do
+ arg="$1"
+ shift
+
+ case $arg in
+ -*=*) optarg=`$echo "X$arg" | $Xsed -e 's/[-_a-zA-Z0-9]*=//'` ;;
+ *) optarg= ;;
+ esac
+
+ # If the previous option needs an argument, assign it.
+ if test -n "$prev"; then
+ case $prev in
+ execute_dlfiles)
+ execute_dlfiles="$execute_dlfiles $arg"
+ ;;
+ tag)
+ tagname="$arg"
+ preserve_args="${preserve_args}=$arg"
+
+ # Check whether tagname contains only valid characters
+ case $tagname in
+ *[!-_A-Za-z0-9,/]*)
+ $echo "$progname: invalid tag name: $tagname" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+ esac
+
+ case $tagname in
+ CC)
+ # Don't test for the "default" C tag, as we know, it's there, but
+ # not specially marked.
+ ;;
+ *)
+ if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$" < "$progpath" > /dev/null; then
+ taglist="$taglist $tagname"
+ # Evaluate the configuration.
+ eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$tagname'$/,/^# ### END LIBTOOL TAG CONFIG: '$tagname'$/p' < $progpath`"
+ else
+ $echo "$progname: ignoring unknown tag $tagname" 1>&2
+ fi
+ ;;
+ esac
+ ;;
+ *)
+ eval "$prev=\$arg"
+ ;;
+ esac
+
+ prev=
+ prevopt=
+ continue
+ fi
+
+ # Have we seen a non-optional argument yet?
+ case $arg in
+ --help)
+ show_help=yes
+ ;;
+
+ --version)
+ $echo "$PROGRAM (GNU $PACKAGE) $VERSION$TIMESTAMP"
+ $echo
+ $echo "Copyright (C) 2005 Free Software Foundation, Inc."
+ $echo "This is free software; see the source for copying conditions. There is NO"
+ $echo "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+ exit $?
+ ;;
+
+ --config)
+ ${SED} -e '1,/^# ### BEGIN LIBTOOL CONFIG/d' -e '/^# ### END LIBTOOL CONFIG/,$d' $progpath
+ # Now print the configurations for the tags.
+ for tagname in $taglist; do
+ ${SED} -n -e "/^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$/,/^# ### END LIBTOOL TAG CONFIG: $tagname$/p" < "$progpath"
+ done
+ exit $?
+ ;;
+
+ --debug)
+ $echo "$progname: enabling shell trace mode"
+ set -x
+ preserve_args="$preserve_args $arg"
+ ;;
+
+ --dry-run | -n)
+ run=:
+ ;;
+
+ --features)
+ $echo "host: $host"
+ if test "$build_libtool_libs" = yes; then
+ $echo "enable shared libraries"
+ else
+ $echo "disable shared libraries"
+ fi
+ if test "$build_old_libs" = yes; then
+ $echo "enable static libraries"
+ else
+ $echo "disable static libraries"
+ fi
+ exit $?
+ ;;
+
+ --finish) mode="finish" ;;
+
+ --mode) prevopt="--mode" prev=mode ;;
+ --mode=*) mode="$optarg" ;;
+
+ --preserve-dup-deps) duplicate_deps="yes" ;;
+
+ --quiet | --silent)
+ show=:
+ preserve_args="$preserve_args $arg"
+ ;;
+
+ --tag)
+ prevopt="--tag"
+ prev=tag
+ preserve_args="$preserve_args --tag"
+ ;;
+ --tag=*)
+ set tag "$optarg" ${1+"$@"}
+ shift
+ prev=tag
+ preserve_args="$preserve_args --tag"
+ ;;
+
+ -dlopen)
+ prevopt="-dlopen"
+ prev=execute_dlfiles
+ ;;
+
+ -*)
+ $echo "$modename: unrecognized option \`$arg'" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+
+ *)
+ nonopt="$arg"
+ break
+ ;;
+ esac
+done
+
+if test -n "$prevopt"; then
+ $echo "$modename: option \`$prevopt' requires an argument" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+fi
+
+case $disable_libs in
+no)
+ ;;
+shared)
+ build_libtool_libs=no
+ build_old_libs=yes
+ ;;
+static)
+ build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac`
+ ;;
+esac
+
+# If this variable is set in any of the actions, the command in it
+# will be execed at the end. This prevents here-documents from being
+# left over by shells.
+exec_cmd=
+
+if test -z "$show_help"; then
+
+ # Infer the operation mode.
+ if test -z "$mode"; then
+ $echo "*** Warning: inferring the mode of operation is deprecated." 1>&2
+ $echo "*** Future versions of Libtool will require --mode=MODE be specified." 1>&2
+ case $nonopt in
+ *cc | cc* | *++ | gcc* | *-gcc* | g++* | xlc*)
+ mode=link
+ for arg
+ do
+ case $arg in
+ -c)
+ mode=compile
+ break
+ ;;
+ esac
+ done
+ ;;
+ *db | *dbx | *strace | *truss)
+ mode=execute
+ ;;
+ *install*|cp|mv)
+ mode=install
+ ;;
+ *rm)
+ mode=uninstall
+ ;;
+ *)
+ # If we have no mode, but dlfiles were specified, then do execute mode.
+ test -n "$execute_dlfiles" && mode=execute
+
+ # Just use the default operation mode.
+ if test -z "$mode"; then
+ if test -n "$nonopt"; then
+ $echo "$modename: warning: cannot infer operation mode from \`$nonopt'" 1>&2
+ else
+ $echo "$modename: warning: cannot infer operation mode without MODE-ARGS" 1>&2
+ fi
+ fi
+ ;;
+ esac
+ fi
+
+ # Only execute mode is allowed to have -dlopen flags.
+ if test -n "$execute_dlfiles" && test "$mode" != execute; then
+ $echo "$modename: unrecognized option \`-dlopen'" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ # Change the help message to a mode-specific one.
+ generic_help="$help"
+ help="Try \`$modename --help --mode=$mode' for more information."
+
+ # These modes are in order of execution frequency so that they run quickly.
+ case $mode in
+ # libtool compile mode
+ compile)
+ modename="$modename: compile"
+ # Get the compilation command and the source file.
+ base_compile=
+ srcfile="$nonopt" # always keep a non-empty value in "srcfile"
+ suppress_opt=yes
+ suppress_output=
+ arg_mode=normal
+ libobj=
+ later=
+
+ for arg
+ do
+ case $arg_mode in
+ arg )
+ # do not "continue". Instead, add this to base_compile
+ lastarg="$arg"
+ arg_mode=normal
+ ;;
+
+ target )
+ libobj="$arg"
+ arg_mode=normal
+ continue
+ ;;
+
+ normal )
+ # Accept any command-line options.
+ case $arg in
+ -o)
+ if test -n "$libobj" ; then
+ $echo "$modename: you cannot specify \`-o' more than once" 1>&2
+ exit $EXIT_FAILURE
+ fi
+ arg_mode=target
+ continue
+ ;;
+
+ -static | -prefer-pic | -prefer-non-pic)
+ later="$later $arg"
+ continue
+ ;;
+
+ -no-suppress)
+ suppress_opt=no
+ continue
+ ;;
+
+ -Xcompiler)
+ arg_mode=arg # the next one goes into the "base_compile" arg list
+ continue # The current "srcfile" will either be retained or
+ ;; # replaced later. I would guess that would be a bug.
+
+ -Wc,*)
+ args=`$echo "X$arg" | $Xsed -e "s/^-Wc,//"`
+ lastarg=
+ save_ifs="$IFS"; IFS=','
+ for arg in $args; do
+ IFS="$save_ifs"
+
+ # Double-quote args containing other shell metacharacters.
+ # Many Bourne shells cannot handle close brackets correctly
+ # in scan sets, so we specify it separately.
+ case $arg in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ arg="\"$arg\""
+ ;;
+ esac
+ lastarg="$lastarg $arg"
+ done
+ IFS="$save_ifs"
+ lastarg=`$echo "X$lastarg" | $Xsed -e "s/^ //"`
+
+ # Add the arguments to base_compile.
+ base_compile="$base_compile $lastarg"
+ continue
+ ;;
+
+ * )
+ # Accept the current argument as the source file.
+ # The previous "srcfile" becomes the current argument.
+ #
+ lastarg="$srcfile"
+ srcfile="$arg"
+ ;;
+ esac # case $arg
+ ;;
+ esac # case $arg_mode
+
+ # Aesthetically quote the previous argument.
+ lastarg=`$echo "X$lastarg" | $Xsed -e "$sed_quote_subst"`
+
+ case $lastarg in
+ # Double-quote args containing other shell metacharacters.
+ # Many Bourne shells cannot handle close brackets correctly
+ # in scan sets, and some SunOS ksh mistreat backslash-escaping
+ # in scan sets (worked around with variable expansion),
+ # and furthermore cannot handle '|' '&' '(' ')' in scan sets
+ # at all, so we specify them separately.
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ lastarg="\"$lastarg\""
+ ;;
+ esac
+
+ base_compile="$base_compile $lastarg"
+ done # for arg
+
+ case $arg_mode in
+ arg)
+ $echo "$modename: you must specify an argument for -Xcompile"
+ exit $EXIT_FAILURE
+ ;;
+ target)
+ $echo "$modename: you must specify a target with \`-o'" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+ *)
+ # Get the name of the library object.
+ [ -z "$libobj" ] && libobj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%'`
+ ;;
+ esac
+
+ # Recognize several different file suffixes.
+ # If the user specifies -o file.o, it is replaced with file.lo
+ xform='[cCFSifmso]'
+ case $libobj in
+ *.ada) xform=ada ;;
+ *.adb) xform=adb ;;
+ *.ads) xform=ads ;;
+ *.asm) xform=asm ;;
+ *.c++) xform=c++ ;;
+ *.cc) xform=cc ;;
+ *.ii) xform=ii ;;
+ *.class) xform=class ;;
+ *.cpp) xform=cpp ;;
+ *.cxx) xform=cxx ;;
+ *.f90) xform=f90 ;;
+ *.for) xform=for ;;
+ *.java) xform=java ;;
+ esac
+
+ libobj=`$echo "X$libobj" | $Xsed -e "s/\.$xform$/.lo/"`
+
+ case $libobj in
+ *.lo) obj=`$echo "X$libobj" | $Xsed -e "$lo2o"` ;;
+ *)
+ $echo "$modename: cannot determine name of library object from \`$libobj'" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+ esac
+
+ func_infer_tag $base_compile
+
+ for arg in $later; do
+ case $arg in
+ -static)
+ build_old_libs=yes
+ continue
+ ;;
+
+ -prefer-pic)
+ pic_mode=yes
+ continue
+ ;;
+
+ -prefer-non-pic)
+ pic_mode=no
+ continue
+ ;;
+ esac
+ done
+
+ qlibobj=`$echo "X$libobj" | $Xsed -e "$sed_quote_subst"`
+ case $qlibobj in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ qlibobj="\"$qlibobj\"" ;;
+ esac
+ test "X$libobj" != "X$qlibobj" \
+ && $echo "X$libobj" | grep '[]~#^*{};<>?"'"'"' &()|`$[]' \
+ && $echo "$modename: libobj name \`$libobj' may not contain shell special characters."
+ objname=`$echo "X$obj" | $Xsed -e 's%^.*/%%'`
+ xdir=`$echo "X$obj" | $Xsed -e 's%/[^/]*$%%'`
+ if test "X$xdir" = "X$obj"; then
+ xdir=
+ else
+ xdir=$xdir/
+ fi
+ lobj=${xdir}$objdir/$objname
+
+ if test -z "$base_compile"; then
+ $echo "$modename: you must specify a compilation command" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ # Delete any leftover library objects.
+ if test "$build_old_libs" = yes; then
+ removelist="$obj $lobj $libobj ${libobj}T"
+ else
+ removelist="$lobj $libobj ${libobj}T"
+ fi
+
+ $run $rm $removelist
+ trap "$run $rm $removelist; exit $EXIT_FAILURE" 1 2 15
+
+ # On Cygwin there's no "real" PIC flag so we must build both object types
+ case $host_os in
+ cygwin* | mingw* | pw32* | os2*)
+ pic_mode=default
+ ;;
+ esac
+ if test "$pic_mode" = no && test "$deplibs_check_method" != pass_all; then
+ # non-PIC code in shared libraries is not supported
+ pic_mode=default
+ fi
+
+ # Calculate the filename of the output object if compiler does
+ # not support -o with -c
+ if test "$compiler_c_o" = no; then
+ output_obj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%' -e 's%\.[^.]*$%%'`.${objext}
+ lockfile="$output_obj.lock"
+ removelist="$removelist $output_obj $lockfile"
+ trap "$run $rm $removelist; exit $EXIT_FAILURE" 1 2 15
+ else
+ output_obj=
+ need_locks=no
+ lockfile=
+ fi
+
+ # Lock this critical section if it is needed
+ # We use this script file to make the link, it avoids creating a new file
+ if test "$need_locks" = yes; then
+ until $run ln "$progpath" "$lockfile" 2>/dev/null; do
+ $show "Waiting for $lockfile to be removed"
+ sleep 2
+ done
+ elif test "$need_locks" = warn; then
+ if test -f "$lockfile"; then
+ $echo "\
+*** ERROR, $lockfile exists and contains:
+`cat $lockfile 2>/dev/null`
+
+This indicates that another process is trying to use the same
+temporary object file, and libtool could not work around it because
+your compiler does not support \`-c' and \`-o' together. If you
+repeat this compilation, it may succeed, by chance, but you had better
+avoid parallel builds (make -j) in this platform, or get a better
+compiler."
+
+ $run $rm $removelist
+ exit $EXIT_FAILURE
+ fi
+ $echo "$srcfile" > "$lockfile"
+ fi
+
+ if test -n "$fix_srcfile_path"; then
+ eval srcfile=\"$fix_srcfile_path\"
+ fi
+ qsrcfile=`$echo "X$srcfile" | $Xsed -e "$sed_quote_subst"`
+ case $qsrcfile in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ qsrcfile="\"$qsrcfile\"" ;;
+ esac
+
+ $run $rm "$libobj" "${libobj}T"
+
+ # Create a libtool object file (analogous to a ".la" file),
+ # but don't create it if we're doing a dry run.
+ test -z "$run" && cat > ${libobj}T <<EOF
+# $libobj - a libtool object file
+# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP
+#
+# Please DO NOT delete this file!
+# It is necessary for linking the library.
+
+# Name of the PIC object.
+EOF
+
+ # Only build a PIC object if we are building libtool libraries.
+ if test "$build_libtool_libs" = yes; then
+ # Without this assignment, base_compile gets emptied.
+ fbsd_hideous_sh_bug=$base_compile
+
+ if test "$pic_mode" != no; then
+ command="$base_compile $qsrcfile $pic_flag"
+ else
+ # Don't build PIC code
+ command="$base_compile $qsrcfile"
+ fi
+
+ if test ! -d "${xdir}$objdir"; then
+ $show "$mkdir ${xdir}$objdir"
+ $run $mkdir ${xdir}$objdir
+ exit_status=$?
+ if test "$exit_status" -ne 0 && test ! -d "${xdir}$objdir"; then
+ exit $exit_status
+ fi
+ fi
+
+ if test -z "$output_obj"; then
+ # Place PIC objects in $objdir
+ command="$command -o $lobj"
+ fi
+
+ $run $rm "$lobj" "$output_obj"
+
+ $show "$command"
+ if $run eval "$command"; then :
+ else
+ test -n "$output_obj" && $run $rm $removelist
+ exit $EXIT_FAILURE
+ fi
+
+ if test "$need_locks" = warn &&
+ test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then
+ $echo "\
+*** ERROR, $lockfile contains:
+`cat $lockfile 2>/dev/null`
+
+but it should contain:
+$srcfile
+
+This indicates that another process is trying to use the same
+temporary object file, and libtool could not work around it because
+your compiler does not support \`-c' and \`-o' together. If you
+repeat this compilation, it may succeed, by chance, but you had better
+avoid parallel builds (make -j) in this platform, or get a better
+compiler."
+
+ $run $rm $removelist
+ exit $EXIT_FAILURE
+ fi
+
+ # Just move the object if needed, then go on to compile the next one
+ if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then
+ $show "$mv $output_obj $lobj"
+ if $run $mv $output_obj $lobj; then :
+ else
+ error=$?
+ $run $rm $removelist
+ exit $error
+ fi
+ fi
+
+ # Append the name of the PIC object to the libtool object file.
+ test -z "$run" && cat >> ${libobj}T <<EOF
+pic_object='$objdir/$objname'
+
+EOF
+
+ # Allow error messages only from the first compilation.
+ if test "$suppress_opt" = yes; then
+ suppress_output=' >/dev/null 2>&1'
+ fi
+ else
+ # No PIC object so indicate it doesn't exist in the libtool
+ # object file.
+ test -z "$run" && cat >> ${libobj}T <<EOF
+pic_object=none
+
+EOF
+ fi
+
+ # Only build a position-dependent object if we build old libraries.
+ if test "$build_old_libs" = yes; then
+ if test "$pic_mode" != yes; then
+ # Don't build PIC code
+ command="$base_compile $qsrcfile"
+ else
+ command="$base_compile $qsrcfile $pic_flag"
+ fi
+ if test "$compiler_c_o" = yes; then
+ command="$command -o $obj"
+ fi
+
+ # Suppress compiler output if we already did a PIC compilation.
+ command="$command$suppress_output"
+ $run $rm "$obj" "$output_obj"
+ $show "$command"
+ if $run eval "$command"; then :
+ else
+ $run $rm $removelist
+ exit $EXIT_FAILURE
+ fi
+
+ if test "$need_locks" = warn &&
+ test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then
+ $echo "\
+*** ERROR, $lockfile contains:
+`cat $lockfile 2>/dev/null`
+
+but it should contain:
+$srcfile
+
+This indicates that another process is trying to use the same
+temporary object file, and libtool could not work around it because
+your compiler does not support \`-c' and \`-o' together. If you
+repeat this compilation, it may succeed, by chance, but you had better
+avoid parallel builds (make -j) in this platform, or get a better
+compiler."
+
+ $run $rm $removelist
+ exit $EXIT_FAILURE
+ fi
+
+ # Just move the object if needed
+ if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then
+ $show "$mv $output_obj $obj"
+ if $run $mv $output_obj $obj; then :
+ else
+ error=$?
+ $run $rm $removelist
+ exit $error
+ fi
+ fi
+
+ # Append the name of the non-PIC object the libtool object file.
+ # Only append if the libtool object file exists.
+ test -z "$run" && cat >> ${libobj}T <<EOF
+# Name of the non-PIC object.
+non_pic_object='$objname'
+
+EOF
+ else
+ # Append the name of the non-PIC object the libtool object file.
+ # Only append if the libtool object file exists.
+ test -z "$run" && cat >> ${libobj}T <<EOF
+# Name of the non-PIC object.
+non_pic_object=none
+
+EOF
+ fi
+
+ $run $mv "${libobj}T" "${libobj}"
+
+ # Unlock the critical section if it was locked
+ if test "$need_locks" != no; then
+ $run $rm "$lockfile"
+ fi
+
+ exit $EXIT_SUCCESS
+ ;;
+
+ # libtool link mode
+ link | relink)
+ modename="$modename: link"
+ case $host in
+ *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*)
+ # It is impossible to link a dll without this setting, and
+ # we shouldn't force the makefile maintainer to figure out
+ # which system we are compiling for in order to pass an extra
+ # flag for every libtool invocation.
+ # allow_undefined=no
+
+ # FIXME: Unfortunately, there are problems with the above when trying
+ # to make a dll which has undefined symbols, in which case not
+ # even a static library is built. For now, we need to specify
+ # -no-undefined on the libtool link line when we can be certain
+ # that all symbols are satisfied, otherwise we get a static library.
+ allow_undefined=yes
+ ;;
+ *)
+ allow_undefined=yes
+ ;;
+ esac
+ libtool_args="$nonopt"
+ base_compile="$nonopt $@"
+ compile_command="$nonopt"
+ finalize_command="$nonopt"
+
+ compile_rpath=
+ finalize_rpath=
+ compile_shlibpath=
+ finalize_shlibpath=
+ convenience=
+ old_convenience=
+ deplibs=
+ old_deplibs=
+ compiler_flags=
+ linker_flags=
+ dllsearchpath=
+ lib_search_path=`pwd`
+ inst_prefix_dir=
+
+ avoid_version=no
+ dlfiles=
+ dlprefiles=
+ dlself=no
+ export_dynamic=no
+ export_symbols=
+ export_symbols_regex=
+ generated=
+ libobjs=
+ ltlibs=
+ module=no
+ no_install=no
+ objs=
+ non_pic_objects=
+ notinst_path= # paths that contain not-installed libtool libraries
+ precious_files_regex=
+ prefer_static_libs=no
+ preload=no
+ prev=
+ prevarg=
+ release=
+ rpath=
+ xrpath=
+ perm_rpath=
+ temp_rpath=
+ thread_safe=no
+ vinfo=
+ vinfo_number=no
+
+ func_infer_tag $base_compile
+
+ # We need to know -static, to get the right output filenames.
+ for arg
+ do
+ case $arg in
+ -all-static | -static)
+ if test "X$arg" = "X-all-static"; then
+ if test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then
+ $echo "$modename: warning: complete static linking is impossible in this configuration" 1>&2
+ fi
+ if test -n "$link_static_flag"; then
+ dlopen_self=$dlopen_self_static
+ fi
+ prefer_static_libs=yes
+ else
+ if test -z "$pic_flag" && test -n "$link_static_flag"; then
+ dlopen_self=$dlopen_self_static
+ fi
+ prefer_static_libs=built
+ fi
+ build_libtool_libs=no
+ build_old_libs=yes
+ break
+ ;;
+ esac
+ done
+
+ # See if our shared archives depend on static archives.
+ test -n "$old_archive_from_new_cmds" && build_old_libs=yes
+
+ # Go through the arguments, transforming them on the way.
+ while test "$#" -gt 0; do
+ arg="$1"
+ shift
+ case $arg in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ qarg=\"`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`\" ### testsuite: skip nested quoting test
+ ;;
+ *) qarg=$arg ;;
+ esac
+ libtool_args="$libtool_args $qarg"
+
+ # If the previous option needs an argument, assign it.
+ if test -n "$prev"; then
+ case $prev in
+ output)
+ compile_command="$compile_command @OUTPUT@"
+ finalize_command="$finalize_command @OUTPUT@"
+ ;;
+ esac
+
+ case $prev in
+ dlfiles|dlprefiles)
+ if test "$preload" = no; then
+ # Add the symbol object into the linking commands.
+ compile_command="$compile_command @SYMFILE@"
+ finalize_command="$finalize_command @SYMFILE@"
+ preload=yes
+ fi
+ case $arg in
+ *.la | *.lo) ;; # We handle these cases below.
+ force)
+ if test "$dlself" = no; then
+ dlself=needless
+ export_dynamic=yes
+ fi
+ prev=
+ continue
+ ;;
+ self)
+ if test "$prev" = dlprefiles; then
+ dlself=yes
+ elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then
+ dlself=yes
+ else
+ dlself=needless
+ export_dynamic=yes
+ fi
+ prev=
+ continue
+ ;;
+ *)
+ if test "$prev" = dlfiles; then
+ dlfiles="$dlfiles $arg"
+ else
+ dlprefiles="$dlprefiles $arg"
+ fi
+ prev=
+ continue
+ ;;
+ esac
+ ;;
+ expsyms)
+ export_symbols="$arg"
+ if test ! -f "$arg"; then
+ $echo "$modename: symbol file \`$arg' does not exist"
+ exit $EXIT_FAILURE
+ fi
+ prev=
+ continue
+ ;;
+ expsyms_regex)
+ export_symbols_regex="$arg"
+ prev=
+ continue
+ ;;
+ inst_prefix)
+ inst_prefix_dir="$arg"
+ prev=
+ continue
+ ;;
+ precious_regex)
+ precious_files_regex="$arg"
+ prev=
+ continue
+ ;;
+ release)
+ release="-$arg"
+ prev=
+ continue
+ ;;
+ objectlist)
+ if test -f "$arg"; then
+ save_arg=$arg
+ moreargs=
+ for fil in `cat $save_arg`
+ do
+# moreargs="$moreargs $fil"
+ arg=$fil
+ # A libtool-controlled object.
+
+ # Check to see that this really is a libtool object.
+ if (${SED} -e '2q' $arg | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+ pic_object=
+ non_pic_object=
+
+ # Read the .lo file
+ # If there is no directory component, then add one.
+ case $arg in
+ */* | *\\*) . $arg ;;
+ *) . ./$arg ;;
+ esac
+
+ if test -z "$pic_object" || \
+ test -z "$non_pic_object" ||
+ test "$pic_object" = none && \
+ test "$non_pic_object" = none; then
+ $echo "$modename: cannot find name of object for \`$arg'" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ # Extract subdirectory from the argument.
+ xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'`
+ if test "X$xdir" = "X$arg"; then
+ xdir=
+ else
+ xdir="$xdir/"
+ fi
+
+ if test "$pic_object" != none; then
+ # Prepend the subdirectory the object is found in.
+ pic_object="$xdir$pic_object"
+
+ if test "$prev" = dlfiles; then
+ if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then
+ dlfiles="$dlfiles $pic_object"
+ prev=
+ continue
+ else
+ # If libtool objects are unsupported, then we need to preload.
+ prev=dlprefiles
+ fi
+ fi
+
+ # CHECK ME: I think I busted this. -Ossama
+ if test "$prev" = dlprefiles; then
+ # Preload the old-style object.
+ dlprefiles="$dlprefiles $pic_object"
+ prev=
+ fi
+
+ # A PIC object.
+ libobjs="$libobjs $pic_object"
+ arg="$pic_object"
+ fi
+
+ # Non-PIC object.
+ if test "$non_pic_object" != none; then
+ # Prepend the subdirectory the object is found in.
+ non_pic_object="$xdir$non_pic_object"
+
+ # A standard non-PIC object
+ non_pic_objects="$non_pic_objects $non_pic_object"
+ if test -z "$pic_object" || test "$pic_object" = none ; then
+ arg="$non_pic_object"
+ fi
+ else
+ # If the PIC object exists, use it instead.
+ # $xdir was prepended to $pic_object above.
+ non_pic_object="$pic_object"
+ non_pic_objects="$non_pic_objects $non_pic_object"
+ fi
+ else
+ # Only an error if not doing a dry-run.
+ if test -z "$run"; then
+ $echo "$modename: \`$arg' is not a valid libtool object" 1>&2
+ exit $EXIT_FAILURE
+ else
+ # Dry-run case.
+
+ # Extract subdirectory from the argument.
+ xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'`
+ if test "X$xdir" = "X$arg"; then
+ xdir=
+ else
+ xdir="$xdir/"
+ fi
+
+ pic_object=`$echo "X${xdir}${objdir}/${arg}" | $Xsed -e "$lo2o"`
+ non_pic_object=`$echo "X${xdir}${arg}" | $Xsed -e "$lo2o"`
+ libobjs="$libobjs $pic_object"
+ non_pic_objects="$non_pic_objects $non_pic_object"
+ fi
+ fi
+ done
+ else
+ $echo "$modename: link input file \`$save_arg' does not exist"
+ exit $EXIT_FAILURE
+ fi
+ arg=$save_arg
+ prev=
+ continue
+ ;;
+ rpath | xrpath)
+ # We need an absolute path.
+ case $arg in
+ [\\/]* | [A-Za-z]:[\\/]*) ;;
+ *)
+ $echo "$modename: only absolute run-paths are allowed" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+ esac
+ if test "$prev" = rpath; then
+ case "$rpath " in
+ *" $arg "*) ;;
+ *) rpath="$rpath $arg" ;;
+ esac
+ else
+ case "$xrpath " in
+ *" $arg "*) ;;
+ *) xrpath="$xrpath $arg" ;;
+ esac
+ fi
+ prev=
+ continue
+ ;;
+ xcompiler)
+ compiler_flags="$compiler_flags $qarg"
+ prev=
+ compile_command="$compile_command $qarg"
+ finalize_command="$finalize_command $qarg"
+ continue
+ ;;
+ xlinker)
+ linker_flags="$linker_flags $qarg"
+ compiler_flags="$compiler_flags $wl$qarg"
+ prev=
+ compile_command="$compile_command $wl$qarg"
+ finalize_command="$finalize_command $wl$qarg"
+ continue
+ ;;
+ xcclinker)
+ linker_flags="$linker_flags $qarg"
+ compiler_flags="$compiler_flags $qarg"
+ prev=
+ compile_command="$compile_command $qarg"
+ finalize_command="$finalize_command $qarg"
+ continue
+ ;;
+ shrext)
+ shrext_cmds="$arg"
+ prev=
+ continue
+ ;;
+ darwin_framework|darwin_framework_skip)
+ test "$prev" = "darwin_framework" && compiler_flags="$compiler_flags $arg"
+ compile_command="$compile_command $arg"
+ finalize_command="$finalize_command $arg"
+ prev=
+ continue
+ ;;
+ *)
+ eval "$prev=\"\$arg\""
+ prev=
+ continue
+ ;;
+ esac
+ fi # test -n "$prev"
+
+ prevarg="$arg"
+
+ case $arg in
+ -all-static)
+ if test -n "$link_static_flag"; then
+ compile_command="$compile_command $link_static_flag"
+ finalize_command="$finalize_command $link_static_flag"
+ fi
+ continue
+ ;;
+
+ -allow-undefined)
+ # FIXME: remove this flag sometime in the future.
+ $echo "$modename: \`-allow-undefined' is deprecated because it is the default" 1>&2
+ continue
+ ;;
+
+ -avoid-version)
+ avoid_version=yes
+ continue
+ ;;
+
+ -dlopen)
+ prev=dlfiles
+ continue
+ ;;
+
+ -dlpreopen)
+ prev=dlprefiles
+ continue
+ ;;
+
+ -export-dynamic)
+ export_dynamic=yes
+ continue
+ ;;
+
+ -export-symbols | -export-symbols-regex)
+ if test -n "$export_symbols" || test -n "$export_symbols_regex"; then
+ $echo "$modename: more than one -exported-symbols argument is not allowed"
+ exit $EXIT_FAILURE
+ fi
+ if test "X$arg" = "X-export-symbols"; then
+ prev=expsyms
+ else
+ prev=expsyms_regex
+ fi
+ continue
+ ;;
+
+ -framework|-arch|-isysroot)
+ case " $CC " in
+ *" ${arg} ${1} "* | *" ${arg} ${1} "*)
+ prev=darwin_framework_skip ;;
+ *) compiler_flags="$compiler_flags $arg"
+ prev=darwin_framework ;;
+ esac
+ compile_command="$compile_command $arg"
+ finalize_command="$finalize_command $arg"
+ continue
+ ;;
+
+ -inst-prefix-dir)
+ prev=inst_prefix
+ continue
+ ;;
+
+ # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:*
+ # so, if we see these flags be careful not to treat them like -L
+ -L[A-Z][A-Z]*:*)
+ case $with_gcc/$host in
+ no/*-*-irix* | /*-*-irix*)
+ compile_command="$compile_command $arg"
+ finalize_command="$finalize_command $arg"
+ ;;
+ esac
+ continue
+ ;;
+
+ -L*)
+ dir=`$echo "X$arg" | $Xsed -e 's/^-L//'`
+ # We need an absolute path.
+ case $dir in
+ [\\/]* | [A-Za-z]:[\\/]*) ;;
+ *)
+ absdir=`cd "$dir" && pwd`
+ if test -z "$absdir"; then
+ $echo "$modename: cannot determine absolute directory name of \`$dir'" 1>&2
+ absdir="$dir"
+ notinst_path="$notinst_path $dir"
+ fi
+ dir="$absdir"
+ ;;
+ esac
+ case "$deplibs " in
+ *" -L$dir "*) ;;
+ *)
+ deplibs="$deplibs -L$dir"
+ lib_search_path="$lib_search_path $dir"
+ ;;
+ esac
+ case $host in
+ *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*)
+ testbindir=`$echo "X$dir" | $Xsed -e 's*/lib$*/bin*'`
+ case :$dllsearchpath: in
+ *":$dir:"*) ;;
+ *) dllsearchpath="$dllsearchpath:$dir";;
+ esac
+ case :$dllsearchpath: in
+ *":$testbindir:"*) ;;
+ *) dllsearchpath="$dllsearchpath:$testbindir";;
+ esac
+ ;;
+ esac
+ continue
+ ;;
+
+ -l*)
+ if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then
+ case $host in
+ *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos*)
+ # These systems don't actually have a C or math library (as such)
+ continue
+ ;;
+ *-*-os2*)
+ # These systems don't actually have a C library (as such)
+ test "X$arg" = "X-lc" && continue
+ ;;
+ *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*)
+ # Do not include libc due to us having libc/libc_r.
+ test "X$arg" = "X-lc" && continue
+ ;;
+ *-*-rhapsody* | *-*-darwin1.[012])
+ # Rhapsody C and math libraries are in the System framework
+ deplibs="$deplibs -framework System"
+ continue
+ ;;
+ *-*-sco3.2v5* | *-*-sco5v6*)
+ # Causes problems with __ctype
+ test "X$arg" = "X-lc" && continue
+ ;;
+ *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*)
+ # Compiler inserts libc in the correct place for threads to work
+ test "X$arg" = "X-lc" && continue
+ ;;
+ esac
+ elif test "X$arg" = "X-lc_r"; then
+ case $host in
+ *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*)
+ # Do not include libc_r directly, use -pthread flag.
+ continue
+ ;;
+ esac
+ fi
+ deplibs="$deplibs $arg"
+ continue
+ ;;
+
+ # Tru64 UNIX uses -model [arg] to determine the layout of C++
+ # classes, name mangling, and exception handling.
+ -model)
+ compile_command="$compile_command $arg"
+ compiler_flags="$compiler_flags $arg"
+ finalize_command="$finalize_command $arg"
+ prev=xcompiler
+ continue
+ ;;
+
+ -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe)
+ compiler_flags="$compiler_flags $arg"
+ compile_command="$compile_command $arg"
+ finalize_command="$finalize_command $arg"
+ continue
+ ;;
+
+ -module)
+ module=yes
+ continue
+ ;;
+
+ # -64, -mips[0-9] enable 64-bit mode on the SGI compiler
+ # -r[0-9][0-9]* specifies the processor on the SGI compiler
+ # -xarch=*, -xtarget=* enable 64-bit mode on the Sun compiler
+ # +DA*, +DD* enable 64-bit mode on the HP compiler
+ # -q* pass through compiler args for the IBM compiler
+ # -m* pass through architecture-specific compiler args for GCC
+ # -m*, -t[45]*, -txscale* pass through architecture-specific
+ # compiler args for GCC
+ # -pg pass through profiling flag for GCC
+ # @file GCC response files
+ -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*|-pg| \
+ -t[45]*|-txscale*|@*)
+
+ # Unknown arguments in both finalize_command and compile_command need
+ # to be aesthetically quoted because they are evaled later.
+ arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
+ case $arg in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ arg="\"$arg\""
+ ;;
+ esac
+ compile_command="$compile_command $arg"
+ finalize_command="$finalize_command $arg"
+ compiler_flags="$compiler_flags $arg"
+ continue
+ ;;
+
+ -shrext)
+ prev=shrext
+ continue
+ ;;
+
+ -no-fast-install)
+ fast_install=no
+ continue
+ ;;
+
+ -no-install)
+ case $host in
+ *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*)
+ # The PATH hackery in wrapper scripts is required on Windows
+ # in order for the loader to find any dlls it needs.
+ $echo "$modename: warning: \`-no-install' is ignored for $host" 1>&2
+ $echo "$modename: warning: assuming \`-no-fast-install' instead" 1>&2
+ fast_install=no
+ ;;
+ *) no_install=yes ;;
+ esac
+ continue
+ ;;
+
+ -no-undefined)
+ allow_undefined=no
+ continue
+ ;;
+
+ -objectlist)
+ prev=objectlist
+ continue
+ ;;
+
+ -o) prev=output ;;
+
+ -precious-files-regex)
+ prev=precious_regex
+ continue
+ ;;
+
+ -release)
+ prev=release
+ continue
+ ;;
+
+ -rpath)
+ prev=rpath
+ continue
+ ;;
+
+ -R)
+ prev=xrpath
+ continue
+ ;;
+
+ -R*)
+ dir=`$echo "X$arg" | $Xsed -e 's/^-R//'`
+ # We need an absolute path.
+ case $dir in
+ [\\/]* | [A-Za-z]:[\\/]*) ;;
+ *)
+ $echo "$modename: only absolute run-paths are allowed" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+ esac
+ case "$xrpath " in
+ *" $dir "*) ;;
+ *) xrpath="$xrpath $dir" ;;
+ esac
+ continue
+ ;;
+
+ -static)
+ # The effects of -static are defined in a previous loop.
+ # We used to do the same as -all-static on platforms that
+ # didn't have a PIC flag, but the assumption that the effects
+ # would be equivalent was wrong. It would break on at least
+ # Digital Unix and AIX.
+ continue
+ ;;
+
+ -thread-safe)
+ thread_safe=yes
+ continue
+ ;;
+
+ -version-info)
+ prev=vinfo
+ continue
+ ;;
+ -version-number)
+ prev=vinfo
+ vinfo_number=yes
+ continue
+ ;;
+
+ -Wc,*)
+ args=`$echo "X$arg" | $Xsed -e "$sed_quote_subst" -e 's/^-Wc,//'`
+ arg=
+ save_ifs="$IFS"; IFS=','
+ for flag in $args; do
+ IFS="$save_ifs"
+ case $flag in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ flag="\"$flag\""
+ ;;
+ esac
+ arg="$arg $wl$flag"
+ compiler_flags="$compiler_flags $flag"
+ done
+ IFS="$save_ifs"
+ arg=`$echo "X$arg" | $Xsed -e "s/^ //"`
+ ;;
+
+ -Wl,*)
+ args=`$echo "X$arg" | $Xsed -e "$sed_quote_subst" -e 's/^-Wl,//'`
+ arg=
+ save_ifs="$IFS"; IFS=','
+ for flag in $args; do
+ IFS="$save_ifs"
+ case $flag in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ flag="\"$flag\""
+ ;;
+ esac
+ arg="$arg $wl$flag"
+ compiler_flags="$compiler_flags $wl$flag"
+ linker_flags="$linker_flags $flag"
+ done
+ IFS="$save_ifs"
+ arg=`$echo "X$arg" | $Xsed -e "s/^ //"`
+ ;;
+
+ -Xcompiler)
+ prev=xcompiler
+ continue
+ ;;
+
+ -Xlinker)
+ prev=xlinker
+ continue
+ ;;
+
+ -XCClinker)
+ prev=xcclinker
+ continue
+ ;;
+
+ # Some other compiler flag.
+ -* | +*)
+ # Unknown arguments in both finalize_command and compile_command need
+ # to be aesthetically quoted because they are evaled later.
+ arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
+ case $arg in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ arg="\"$arg\""
+ ;;
+ esac
+ ;;
+
+ *.$objext)
+ # A standard object.
+ objs="$objs $arg"
+ ;;
+
+ *.lo)
+ # A libtool-controlled object.
+
+ # Check to see that this really is a libtool object.
+ if (${SED} -e '2q' $arg | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+ pic_object=
+ non_pic_object=
+
+ # Read the .lo file
+ # If there is no directory component, then add one.
+ case $arg in
+ */* | *\\*) . $arg ;;
+ *) . ./$arg ;;
+ esac
+
+ if test -z "$pic_object" || \
+ test -z "$non_pic_object" ||
+ test "$pic_object" = none && \
+ test "$non_pic_object" = none; then
+ $echo "$modename: cannot find name of object for \`$arg'" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ # Extract subdirectory from the argument.
+ xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'`
+ if test "X$xdir" = "X$arg"; then
+ xdir=
+ else
+ xdir="$xdir/"
+ fi
+
+ if test "$pic_object" != none; then
+ # Prepend the subdirectory the object is found in.
+ pic_object="$xdir$pic_object"
+
+ if test "$prev" = dlfiles; then
+ if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then
+ dlfiles="$dlfiles $pic_object"
+ prev=
+ continue
+ else
+ # If libtool objects are unsupported, then we need to preload.
+ prev=dlprefiles
+ fi
+ fi
+
+ # CHECK ME: I think I busted this. -Ossama
+ if test "$prev" = dlprefiles; then
+ # Preload the old-style object.
+ dlprefiles="$dlprefiles $pic_object"
+ prev=
+ fi
+
+ # A PIC object.
+ libobjs="$libobjs $pic_object"
+ arg="$pic_object"
+ fi
+
+ # Non-PIC object.
+ if test "$non_pic_object" != none; then
+ # Prepend the subdirectory the object is found in.
+ non_pic_object="$xdir$non_pic_object"
+
+ # A standard non-PIC object
+ non_pic_objects="$non_pic_objects $non_pic_object"
+ if test -z "$pic_object" || test "$pic_object" = none ; then
+ arg="$non_pic_object"
+ fi
+ else
+ # If the PIC object exists, use it instead.
+ # $xdir was prepended to $pic_object above.
+ non_pic_object="$pic_object"
+ non_pic_objects="$non_pic_objects $non_pic_object"
+ fi
+ else
+ # Only an error if not doing a dry-run.
+ if test -z "$run"; then
+ $echo "$modename: \`$arg' is not a valid libtool object" 1>&2
+ exit $EXIT_FAILURE
+ else
+ # Dry-run case.
+
+ # Extract subdirectory from the argument.
+ xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'`
+ if test "X$xdir" = "X$arg"; then
+ xdir=
+ else
+ xdir="$xdir/"
+ fi
+
+ pic_object=`$echo "X${xdir}${objdir}/${arg}" | $Xsed -e "$lo2o"`
+ non_pic_object=`$echo "X${xdir}${arg}" | $Xsed -e "$lo2o"`
+ libobjs="$libobjs $pic_object"
+ non_pic_objects="$non_pic_objects $non_pic_object"
+ fi
+ fi
+ ;;
+
+ *.$libext)
+ # An archive.
+ deplibs="$deplibs $arg"
+ old_deplibs="$old_deplibs $arg"
+ continue
+ ;;
+
+ *.la)
+ # A libtool-controlled library.
+
+ if test "$prev" = dlfiles; then
+ # This library was specified with -dlopen.
+ dlfiles="$dlfiles $arg"
+ prev=
+ elif test "$prev" = dlprefiles; then
+ # The library was specified with -dlpreopen.
+ dlprefiles="$dlprefiles $arg"
+ prev=
+ else
+ deplibs="$deplibs $arg"
+ fi
+ continue
+ ;;
+
+ # Some other compiler argument.
+ *)
+ # Unknown arguments in both finalize_command and compile_command need
+ # to be aesthetically quoted because they are evaled later.
+ arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
+ case $arg in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ arg="\"$arg\""
+ ;;
+ esac
+ ;;
+ esac # arg
+
+ # Now actually substitute the argument into the commands.
+ if test -n "$arg"; then
+ compile_command="$compile_command $arg"
+ finalize_command="$finalize_command $arg"
+ fi
+ done # argument parsing loop
+
+ if test -n "$prev"; then
+ $echo "$modename: the \`$prevarg' option requires an argument" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then
+ eval arg=\"$export_dynamic_flag_spec\"
+ compile_command="$compile_command $arg"
+ finalize_command="$finalize_command $arg"
+ fi
+
+ oldlibs=
+ # calculate the name of the file, without its directory
+ outputname=`$echo "X$output" | $Xsed -e 's%^.*/%%'`
+ libobjs_save="$libobjs"
+
+ if test -n "$shlibpath_var"; then
+ # get the directories listed in $shlibpath_var
+ eval shlib_search_path=\`\$echo \"X\${$shlibpath_var}\" \| \$Xsed -e \'s/:/ /g\'\`
+ else
+ shlib_search_path=
+ fi
+ eval sys_lib_search_path=\"$sys_lib_search_path_spec\"
+ eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\"
+
+ output_objdir=`$echo "X$output" | $Xsed -e 's%/[^/]*$%%'`
+ if test "X$output_objdir" = "X$output"; then
+ output_objdir="$objdir"
+ else
+ output_objdir="$output_objdir/$objdir"
+ fi
+ # Create the object directory.
+ if test ! -d "$output_objdir"; then
+ $show "$mkdir $output_objdir"
+ $run $mkdir $output_objdir
+ exit_status=$?
+ if test "$exit_status" -ne 0 && test ! -d "$output_objdir"; then
+ exit $exit_status
+ fi
+ fi
+
+ # Determine the type of output
+ case $output in
+ "")
+ $echo "$modename: you must specify an output file" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+ *.$libext) linkmode=oldlib ;;
+ *.lo | *.$objext) linkmode=obj ;;
+ *.la) linkmode=lib ;;
+ *) linkmode=prog ;; # Anything else should be a program.
+ esac
+
+ case $host in
+ *cygwin* | *mingw* | *pw32*)
+ # don't eliminate duplications in $postdeps and $predeps
+ duplicate_compiler_generated_deps=yes
+ ;;
+ *)
+ duplicate_compiler_generated_deps=$duplicate_deps
+ ;;
+ esac
+ specialdeplibs=
+
+ libs=
+ # Find all interdependent deplibs by searching for libraries
+ # that are linked more than once (e.g. -la -lb -la)
+ for deplib in $deplibs; do
+ if test "X$duplicate_deps" = "Xyes" ; then
+ case "$libs " in
+ *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
+ esac
+ fi
+ libs="$libs $deplib"
+ done
+
+ if test "$linkmode" = lib; then
+ libs="$predeps $libs $compiler_lib_search_path $postdeps"
+
+ # Compute libraries that are listed more than once in $predeps
+ # $postdeps and mark them as special (i.e., whose duplicates are
+ # not to be eliminated).
+ pre_post_deps=
+ if test "X$duplicate_compiler_generated_deps" = "Xyes" ; then
+ for pre_post_dep in $predeps $postdeps; do
+ case "$pre_post_deps " in
+ *" $pre_post_dep "*) specialdeplibs="$specialdeplibs $pre_post_deps" ;;
+ esac
+ pre_post_deps="$pre_post_deps $pre_post_dep"
+ done
+ fi
+ pre_post_deps=
+ fi
+
+ deplibs=
+ newdependency_libs=
+ newlib_search_path=
+ need_relink=no # whether we're linking any uninstalled libtool libraries
+ notinst_deplibs= # not-installed libtool libraries
+ case $linkmode in
+ lib)
+ passes="conv link"
+ for file in $dlfiles $dlprefiles; do
+ case $file in
+ *.la) ;;
+ *)
+ $echo "$modename: libraries can \`-dlopen' only libtool libraries: $file" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+ esac
+ done
+ ;;
+ prog)
+ compile_deplibs=
+ finalize_deplibs=
+ alldeplibs=no
+ newdlfiles=
+ newdlprefiles=
+ passes="conv scan dlopen dlpreopen link"
+ ;;
+ *) passes="conv"
+ ;;
+ esac
+ for pass in $passes; do
+ if test "$linkmode,$pass" = "lib,link" ||
+ test "$linkmode,$pass" = "prog,scan"; then
+ libs="$deplibs"
+ deplibs=
+ fi
+ if test "$linkmode" = prog; then
+ case $pass in
+ dlopen) libs="$dlfiles" ;;
+ dlpreopen) libs="$dlprefiles" ;;
+ link) libs="$deplibs %DEPLIBS% $dependency_libs" ;;
+ esac
+ fi
+ if test "$pass" = dlopen; then
+ # Collect dlpreopened libraries
+ save_deplibs="$deplibs"
+ deplibs=
+ fi
+ for deplib in $libs; do
+ lib=
+ found=no
+ case $deplib in
+ -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe)
+ if test "$linkmode,$pass" = "prog,link"; then
+ compile_deplibs="$deplib $compile_deplibs"
+ finalize_deplibs="$deplib $finalize_deplibs"
+ else
+ compiler_flags="$compiler_flags $deplib"
+ fi
+ continue
+ ;;
+ -l*)
+ if test "$linkmode" != lib && test "$linkmode" != prog; then
+ $echo "$modename: warning: \`-l' is ignored for archives/objects" 1>&2
+ continue
+ fi
+ name=`$echo "X$deplib" | $Xsed -e 's/^-l//'`
+ for searchdir in $newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path; do
+ for search_ext in .la $std_shrext .so .a; do
+ # Search the libtool library
+ lib="$searchdir/lib${name}${search_ext}"
+ if test -f "$lib"; then
+ if test "$search_ext" = ".la"; then
+ found=yes
+ else
+ found=no
+ fi
+ break 2
+ fi
+ done
+ done
+ if test "$found" != yes; then
+ # deplib doesn't seem to be a libtool library
+ if test "$linkmode,$pass" = "prog,link"; then
+ compile_deplibs="$deplib $compile_deplibs"
+ finalize_deplibs="$deplib $finalize_deplibs"
+ else
+ deplibs="$deplib $deplibs"
+ test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs"
+ fi
+ continue
+ else # deplib is a libtool library
+ # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib,
+ # We need to do some special things here, and not later.
+ if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+ case " $predeps $postdeps " in
+ *" $deplib "*)
+ if (${SED} -e '2q' $lib |
+ grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+ library_names=
+ old_library=
+ case $lib in
+ */* | *\\*) . $lib ;;
+ *) . ./$lib ;;
+ esac
+ for l in $old_library $library_names; do
+ ll="$l"
+ done
+ if test "X$ll" = "X$old_library" ; then # only static version available
+ found=no
+ ladir=`$echo "X$lib" | $Xsed -e 's%/[^/]*$%%'`
+ test "X$ladir" = "X$lib" && ladir="."
+ lib=$ladir/$old_library
+ if test "$linkmode,$pass" = "prog,link"; then
+ compile_deplibs="$deplib $compile_deplibs"
+ finalize_deplibs="$deplib $finalize_deplibs"
+ else
+ deplibs="$deplib $deplibs"
+ test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs"
+ fi
+ continue
+ fi
+ fi
+ ;;
+ *) ;;
+ esac
+ fi
+ fi
+ ;; # -l
+ -L*)
+ case $linkmode in
+ lib)
+ deplibs="$deplib $deplibs"
+ test "$pass" = conv && continue
+ newdependency_libs="$deplib $newdependency_libs"
+ newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'`
+ ;;
+ prog)
+ if test "$pass" = conv; then
+ deplibs="$deplib $deplibs"
+ continue
+ fi
+ if test "$pass" = scan; then
+ deplibs="$deplib $deplibs"
+ else
+ compile_deplibs="$deplib $compile_deplibs"
+ finalize_deplibs="$deplib $finalize_deplibs"
+ fi
+ newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'`
+ ;;
+ *)
+ $echo "$modename: warning: \`-L' is ignored for archives/objects" 1>&2
+ ;;
+ esac # linkmode
+ continue
+ ;; # -L
+ -R*)
+ if test "$pass" = link; then
+ dir=`$echo "X$deplib" | $Xsed -e 's/^-R//'`
+ # Make sure the xrpath contains only unique directories.
+ case "$xrpath " in
+ *" $dir "*) ;;
+ *) xrpath="$xrpath $dir" ;;
+ esac
+ fi
+ deplibs="$deplib $deplibs"
+ continue
+ ;;
+ *.la) lib="$deplib" ;;
+ *.$libext)
+ if test "$pass" = conv; then
+ deplibs="$deplib $deplibs"
+ continue
+ fi
+ case $linkmode in
+ lib)
+ valid_a_lib=no
+ case $deplibs_check_method in
+ match_pattern*)
+ set dummy $deplibs_check_method
+ match_pattern_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"`
+ if eval $echo \"$deplib\" 2>/dev/null \
+ | $SED 10q \
+ | $EGREP "$match_pattern_regex" > /dev/null; then
+ valid_a_lib=yes
+ fi
+ ;;
+ pass_all)
+ valid_a_lib=yes
+ ;;
+ esac
+ if test "$valid_a_lib" != yes; then
+ $echo
+ $echo "*** Warning: Trying to link with static lib archive $deplib."
+ $echo "*** I have the capability to make that library automatically link in when"
+ $echo "*** you link to this library. But I can only do this if you have a"
+ $echo "*** shared version of the library, which you do not appear to have"
+ $echo "*** because the file extensions .$libext of this argument makes me believe"
+ $echo "*** that it is just a static archive that I should not used here."
+ else
+ $echo
+ $echo "*** Warning: Linking the shared library $output against the"
+ $echo "*** static library $deplib is not portable!"
+ deplibs="$deplib $deplibs"
+ fi
+ continue
+ ;;
+ prog)
+ if test "$pass" != link; then
+ deplibs="$deplib $deplibs"
+ else
+ compile_deplibs="$deplib $compile_deplibs"
+ finalize_deplibs="$deplib $finalize_deplibs"
+ fi
+ continue
+ ;;
+ esac # linkmode
+ ;; # *.$libext
+ *.lo | *.$objext)
+ if test "$pass" = conv; then
+ deplibs="$deplib $deplibs"
+ elif test "$linkmode" = prog; then
+ if test "$pass" = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then
+ # If there is no dlopen support or we're linking statically,
+ # we need to preload.
+ newdlprefiles="$newdlprefiles $deplib"
+ compile_deplibs="$deplib $compile_deplibs"
+ finalize_deplibs="$deplib $finalize_deplibs"
+ else
+ newdlfiles="$newdlfiles $deplib"
+ fi
+ fi
+ continue
+ ;;
+ %DEPLIBS%)
+ alldeplibs=yes
+ continue
+ ;;
+ esac # case $deplib
+ if test "$found" = yes || test -f "$lib"; then :
+ else
+ $echo "$modename: cannot find the library \`$lib' or unhandled argument \`$deplib'" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ # Check to see that this really is a libtool archive.
+ if (${SED} -e '2q' $lib | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then :
+ else
+ $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ ladir=`$echo "X$lib" | $Xsed -e 's%/[^/]*$%%'`
+ test "X$ladir" = "X$lib" && ladir="."
+
+ dlname=
+ dlopen=
+ dlpreopen=
+ libdir=
+ library_names=
+ old_library=
+ # If the library was installed with an old release of libtool,
+ # it will not redefine variables installed, or shouldnotlink
+ installed=yes
+ shouldnotlink=no
+ avoidtemprpath=
+
+
+ # Read the .la file
+ case $lib in
+ */* | *\\*) . $lib ;;
+ *) . ./$lib ;;
+ esac
+
+ if test "$linkmode,$pass" = "lib,link" ||
+ test "$linkmode,$pass" = "prog,scan" ||
+ { test "$linkmode" != prog && test "$linkmode" != lib; }; then
+ test -n "$dlopen" && dlfiles="$dlfiles $dlopen"
+ test -n "$dlpreopen" && dlprefiles="$dlprefiles $dlpreopen"
+ fi
+
+ if test "$pass" = conv; then
+ # Only check for convenience libraries
+ deplibs="$lib $deplibs"
+ if test -z "$libdir"; then
+ if test -z "$old_library"; then
+ $echo "$modename: cannot find name of link library for \`$lib'" 1>&2
+ exit $EXIT_FAILURE
+ fi
+ # It is a libtool convenience library, so add in its objects.
+ convenience="$convenience $ladir/$objdir/$old_library"
+ old_convenience="$old_convenience $ladir/$objdir/$old_library"
+ tmp_libs=
+ for deplib in $dependency_libs; do
+ deplibs="$deplib $deplibs"
+ if test "X$duplicate_deps" = "Xyes" ; then
+ case "$tmp_libs " in
+ *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
+ esac
+ fi
+ tmp_libs="$tmp_libs $deplib"
+ done
+ elif test "$linkmode" != prog && test "$linkmode" != lib; then
+ $echo "$modename: \`$lib' is not a convenience library" 1>&2
+ exit $EXIT_FAILURE
+ fi
+ continue
+ fi # $pass = conv
+
+
+ # Get the name of the library we link against.
+ linklib=
+ for l in $old_library $library_names; do
+ linklib="$l"
+ done
+ if test -z "$linklib"; then
+ $echo "$modename: cannot find name of link library for \`$lib'" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ # This library was specified with -dlopen.
+ if test "$pass" = dlopen; then
+ if test -z "$libdir"; then
+ $echo "$modename: cannot -dlopen a convenience library: \`$lib'" 1>&2
+ exit $EXIT_FAILURE
+ fi
+ if test -z "$dlname" ||
+ test "$dlopen_support" != yes ||
+ test "$build_libtool_libs" = no; then
+ # If there is no dlname, no dlopen support or we're linking
+ # statically, we need to preload. We also need to preload any
+ # dependent libraries so libltdl's deplib preloader doesn't
+ # bomb out in the load deplibs phase.
+ dlprefiles="$dlprefiles $lib $dependency_libs"
+ else
+ newdlfiles="$newdlfiles $lib"
+ fi
+ continue
+ fi # $pass = dlopen
+
+ # We need an absolute path.
+ case $ladir in
+ [\\/]* | [A-Za-z]:[\\/]*) abs_ladir="$ladir" ;;
+ *)
+ abs_ladir=`cd "$ladir" && pwd`
+ if test -z "$abs_ladir"; then
+ $echo "$modename: warning: cannot determine absolute directory name of \`$ladir'" 1>&2
+ $echo "$modename: passing it literally to the linker, although it might fail" 1>&2
+ abs_ladir="$ladir"
+ fi
+ ;;
+ esac
+ laname=`$echo "X$lib" | $Xsed -e 's%^.*/%%'`
+
+ # Find the relevant object directory and library name.
+ if test "X$installed" = Xyes; then
+ if test ! -f "$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then
+ $echo "$modename: warning: library \`$lib' was moved." 1>&2
+ dir="$ladir"
+ absdir="$abs_ladir"
+ libdir="$abs_ladir"
+ else
+ dir="$libdir"
+ absdir="$libdir"
+ fi
+ test "X$hardcode_automatic" = Xyes && avoidtemprpath=yes
+ else
+ if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then
+ dir="$ladir"
+ absdir="$abs_ladir"
+ # Remove this search path later
+ notinst_path="$notinst_path $abs_ladir"
+ else
+ dir="$ladir/$objdir"
+ absdir="$abs_ladir/$objdir"
+ # Remove this search path later
+ notinst_path="$notinst_path $abs_ladir"
+ fi
+ fi # $installed = yes
+ name=`$echo "X$laname" | $Xsed -e 's/\.la$//' -e 's/^lib//'`
+
+ # This library was specified with -dlpreopen.
+ if test "$pass" = dlpreopen; then
+ if test -z "$libdir"; then
+ $echo "$modename: cannot -dlpreopen a convenience library: \`$lib'" 1>&2
+ exit $EXIT_FAILURE
+ fi
+ # Prefer using a static library (so that no silly _DYNAMIC symbols
+ # are required to link).
+ if test -n "$old_library"; then
+ newdlprefiles="$newdlprefiles $dir/$old_library"
+ # Otherwise, use the dlname, so that lt_dlopen finds it.
+ elif test -n "$dlname"; then
+ newdlprefiles="$newdlprefiles $dir/$dlname"
+ else
+ newdlprefiles="$newdlprefiles $dir/$linklib"
+ fi
+ fi # $pass = dlpreopen
+
+ if test -z "$libdir"; then
+ # Link the convenience library
+ if test "$linkmode" = lib; then
+ deplibs="$dir/$old_library $deplibs"
+ elif test "$linkmode,$pass" = "prog,link"; then
+ compile_deplibs="$dir/$old_library $compile_deplibs"
+ finalize_deplibs="$dir/$old_library $finalize_deplibs"
+ else
+ deplibs="$lib $deplibs" # used for prog,scan pass
+ fi
+ continue
+ fi
+
+
+ if test "$linkmode" = prog && test "$pass" != link; then
+ newlib_search_path="$newlib_search_path $ladir"
+ deplibs="$lib $deplibs"
+
+ linkalldeplibs=no
+ if test "$link_all_deplibs" != no || test -z "$library_names" ||
+ test "$build_libtool_libs" = no; then
+ linkalldeplibs=yes
+ fi
+
+ tmp_libs=
+ for deplib in $dependency_libs; do
+ case $deplib in
+ -L*) newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'`;; ### testsuite: skip nested quoting test
+ esac
+ # Need to link against all dependency_libs?
+ if test "$linkalldeplibs" = yes; then
+ deplibs="$deplib $deplibs"
+ else
+ # Need to hardcode shared library paths
+ # or/and link against static libraries
+ newdependency_libs="$deplib $newdependency_libs"
+ fi
+ if test "X$duplicate_deps" = "Xyes" ; then
+ case "$tmp_libs " in
+ *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
+ esac
+ fi
+ tmp_libs="$tmp_libs $deplib"
+ done # for deplib
+ continue
+ fi # $linkmode = prog...
+
+ if test "$linkmode,$pass" = "prog,link"; then
+ if test -n "$library_names" &&
+ { test "$prefer_static_libs" = no || test -z "$old_library"; }; then
+ # We need to hardcode the library path
+ if test -n "$shlibpath_var" && test -z "$avoidtemprpath" ; then
+ # Make sure the rpath contains only unique directories.
+ case "$temp_rpath " in
+ *" $dir "*) ;;
+ *" $absdir "*) ;;
+ *) temp_rpath="$temp_rpath $absdir" ;;
+ esac
+ fi
+
+ # Hardcode the library path.
+ # Skip directories that are in the system default run-time
+ # search path.
+ case " $sys_lib_dlsearch_path " in
+ *" $absdir "*) ;;
+ *)
+ case "$compile_rpath " in
+ *" $absdir "*) ;;
+ *) compile_rpath="$compile_rpath $absdir"
+ esac
+ ;;
+ esac
+ case " $sys_lib_dlsearch_path " in
+ *" $libdir "*) ;;
+ *)
+ case "$finalize_rpath " in
+ *" $libdir "*) ;;
+ *) finalize_rpath="$finalize_rpath $libdir"
+ esac
+ ;;
+ esac
+ fi # $linkmode,$pass = prog,link...
+
+ if test "$alldeplibs" = yes &&
+ { test "$deplibs_check_method" = pass_all ||
+ { test "$build_libtool_libs" = yes &&
+ test -n "$library_names"; }; }; then
+ # We only need to search for static libraries
+ continue
+ fi
+ fi
+
+ link_static=no # Whether the deplib will be linked statically
+ use_static_libs=$prefer_static_libs
+ if test "$use_static_libs" = built && test "$installed" = yes ; then
+ use_static_libs=no
+ fi
+ if test -n "$library_names" &&
+ { test "$use_static_libs" = no || test -z "$old_library"; }; then
+ if test "$installed" = no; then
+ notinst_deplibs="$notinst_deplibs $lib"
+ need_relink=yes
+ fi
+ # This is a shared library
+
+ # Warn about portability, can't link against -module's on
+ # some systems (darwin)
+ if test "$shouldnotlink" = yes && test "$pass" = link ; then
+ $echo
+ if test "$linkmode" = prog; then
+ $echo "*** Warning: Linking the executable $output against the loadable module"
+ else
+ $echo "*** Warning: Linking the shared library $output against the loadable module"
+ fi
+ $echo "*** $linklib is not portable!"
+ fi
+ if test "$linkmode" = lib &&
+ test "$hardcode_into_libs" = yes; then
+ # Hardcode the library path.
+ # Skip directories that are in the system default run-time
+ # search path.
+ case " $sys_lib_dlsearch_path " in
+ *" $absdir "*) ;;
+ *)
+ case "$compile_rpath " in
+ *" $absdir "*) ;;
+ *) compile_rpath="$compile_rpath $absdir"
+ esac
+ ;;
+ esac
+ case " $sys_lib_dlsearch_path " in
+ *" $libdir "*) ;;
+ *)
+ case "$finalize_rpath " in
+ *" $libdir "*) ;;
+ *) finalize_rpath="$finalize_rpath $libdir"
+ esac
+ ;;
+ esac
+ fi
+
+ if test -n "$old_archive_from_expsyms_cmds"; then
+ # figure out the soname
+ set dummy $library_names
+ realname="$2"
+ shift; shift
+ libname=`eval \\$echo \"$libname_spec\"`
+ # use dlname if we got it. it's perfectly good, no?
+ if test -n "$dlname"; then
+ soname="$dlname"
+ elif test -n "$soname_spec"; then
+ # bleh windows
+ case $host in
+ *cygwin* | mingw*)
+ major=`expr $current - $age`
+ versuffix="-$major"
+ ;;
+ esac
+ eval soname=\"$soname_spec\"
+ else
+ soname="$realname"
+ fi
+
+ # Make a new name for the extract_expsyms_cmds to use
+ soroot="$soname"
+ soname=`$echo $soroot | ${SED} -e 's/^.*\///'`
+ newlib="libimp-`$echo $soname | ${SED} 's/^lib//;s/\.dll$//'`.a"
+
+ # If the library has no export list, then create one now
+ if test -f "$output_objdir/$soname-def"; then :
+ else
+ $show "extracting exported symbol list from \`$soname'"
+ save_ifs="$IFS"; IFS='~'
+ cmds=$extract_expsyms_cmds
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ eval cmd=\"$cmd\"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+ fi
+
+ # Create $newlib
+ if test -f "$output_objdir/$newlib"; then :; else
+ $show "generating import library for \`$soname'"
+ save_ifs="$IFS"; IFS='~'
+ cmds=$old_archive_from_expsyms_cmds
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ eval cmd=\"$cmd\"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+ fi
+ # make sure the library variables are pointing to the new library
+ dir=$output_objdir
+ linklib=$newlib
+ fi # test -n "$old_archive_from_expsyms_cmds"
+
+ if test "$linkmode" = prog || test "$mode" != relink; then
+ add_shlibpath=
+ add_dir=
+ add=
+ lib_linked=yes
+ case $hardcode_action in
+ immediate | unsupported)
+ if test "$hardcode_direct" = no; then
+ add="$dir/$linklib"
+ case $host in
+ *-*-sco3.2v5.0.[024]*) add_dir="-L$dir" ;;
+ *-*-sysv4*uw2*) add_dir="-L$dir" ;;
+ *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \
+ *-*-unixware7*) add_dir="-L$dir" ;;
+ *-*-darwin* )
+ # if the lib is a module then we can not link against
+ # it, someone is ignoring the new warnings I added
+ if /usr/bin/file -L $add 2> /dev/null |
+ $EGREP ": [^:]* bundle" >/dev/null ; then
+ $echo "** Warning, lib $linklib is a module, not a shared library"
+ if test -z "$old_library" ; then
+ $echo
+ $echo "** And there doesn't seem to be a static archive available"
+ $echo "** The link will probably fail, sorry"
+ else
+ add="$dir/$old_library"
+ fi
+ fi
+ esac
+ elif test "$hardcode_minus_L" = no; then
+ case $host in
+ *-*-sunos*) add_shlibpath="$dir" ;;
+ esac
+ add_dir="-L$dir"
+ add="-l$name"
+ elif test "$hardcode_shlibpath_var" = no; then
+ add_shlibpath="$dir"
+ add="-l$name"
+ else
+ lib_linked=no
+ fi
+ ;;
+ relink)
+ if test "$hardcode_direct" = yes; then
+ add="$dir/$linklib"
+ elif test "$hardcode_minus_L" = yes; then
+ add_dir="-L$dir"
+ # Try looking first in the location we're being installed to.
+ if test -n "$inst_prefix_dir"; then
+ case $libdir in
+ [\\/]*)
+ add_dir="$add_dir -L$inst_prefix_dir$libdir"
+ ;;
+ esac
+ fi
+ add="-l$name"
+ elif test "$hardcode_shlibpath_var" = yes; then
+ add_shlibpath="$dir"
+ add="-l$name"
+ else
+ lib_linked=no
+ fi
+ ;;
+ *) lib_linked=no ;;
+ esac
+
+ if test "$lib_linked" != yes; then
+ $echo "$modename: configuration error: unsupported hardcode properties"
+ exit $EXIT_FAILURE
+ fi
+
+ if test -n "$add_shlibpath"; then
+ case :$compile_shlibpath: in
+ *":$add_shlibpath:"*) ;;
+ *) compile_shlibpath="$compile_shlibpath$add_shlibpath:" ;;
+ esac
+ fi
+ if test "$linkmode" = prog; then
+ test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs"
+ test -n "$add" && compile_deplibs="$add $compile_deplibs"
+ else
+ test -n "$add_dir" && deplibs="$add_dir $deplibs"
+ test -n "$add" && deplibs="$add $deplibs"
+ if test "$hardcode_direct" != yes && \
+ test "$hardcode_minus_L" != yes && \
+ test "$hardcode_shlibpath_var" = yes; then
+ case :$finalize_shlibpath: in
+ *":$libdir:"*) ;;
+ *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;;
+ esac
+ fi
+ fi
+ fi
+
+ if test "$linkmode" = prog || test "$mode" = relink; then
+ add_shlibpath=
+ add_dir=
+ add=
+ # Finalize command for both is simple: just hardcode it.
+ if test "$hardcode_direct" = yes; then
+ add="$libdir/$linklib"
+ elif test "$hardcode_minus_L" = yes; then
+ add_dir="-L$libdir"
+ add="-l$name"
+ elif test "$hardcode_shlibpath_var" = yes; then
+ case :$finalize_shlibpath: in
+ *":$libdir:"*) ;;
+ *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;;
+ esac
+ add="-l$name"
+ elif test "$hardcode_automatic" = yes; then
+ if test -n "$inst_prefix_dir" &&
+ test -f "$inst_prefix_dir$libdir/$linklib" ; then
+ add="$inst_prefix_dir$libdir/$linklib"
+ else
+ add="$libdir/$linklib"
+ fi
+ else
+ # We cannot seem to hardcode it, guess we'll fake it.
+ add_dir="-L$libdir"
+ # Try looking first in the location we're being installed to.
+ if test -n "$inst_prefix_dir"; then
+ case $libdir in
+ [\\/]*)
+ add_dir="$add_dir -L$inst_prefix_dir$libdir"
+ ;;
+ esac
+ fi
+ add="-l$name"
+ fi
+
+ if test "$linkmode" = prog; then
+ test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs"
+ test -n "$add" && finalize_deplibs="$add $finalize_deplibs"
+ else
+ test -n "$add_dir" && deplibs="$add_dir $deplibs"
+ test -n "$add" && deplibs="$add $deplibs"
+ fi
+ fi
+ elif test "$linkmode" = prog; then
+ # Here we assume that one of hardcode_direct or hardcode_minus_L
+ # is not unsupported. This is valid on all known static and
+ # shared platforms.
+ if test "$hardcode_direct" != unsupported; then
+ test -n "$old_library" && linklib="$old_library"
+ compile_deplibs="$dir/$linklib $compile_deplibs"
+ finalize_deplibs="$dir/$linklib $finalize_deplibs"
+ else
+ compile_deplibs="-l$name -L$dir $compile_deplibs"
+ finalize_deplibs="-l$name -L$dir $finalize_deplibs"
+ fi
+ elif test "$build_libtool_libs" = yes; then
+ # Not a shared library
+ if test "$deplibs_check_method" != pass_all; then
+ # We're trying link a shared library against a static one
+ # but the system doesn't support it.
+
+ # Just print a warning and add the library to dependency_libs so
+ # that the program can be linked against the static library.
+ $echo
+ $echo "*** Warning: This system can not link to static lib archive $lib."
+ $echo "*** I have the capability to make that library automatically link in when"
+ $echo "*** you link to this library. But I can only do this if you have a"
+ $echo "*** shared version of the library, which you do not appear to have."
+ if test "$module" = yes; then
+ $echo "*** But as you try to build a module library, libtool will still create "
+ $echo "*** a static module, that should work as long as the dlopening application"
+ $echo "*** is linked with the -dlopen flag to resolve symbols at runtime."
+ if test -z "$global_symbol_pipe"; then
+ $echo
+ $echo "*** However, this would only work if libtool was able to extract symbol"
+ $echo "*** lists from a program, using \`nm' or equivalent, but libtool could"
+ $echo "*** not find such a program. So, this module is probably useless."
+ $echo "*** \`nm' from GNU binutils and a full rebuild may help."
+ fi
+ if test "$build_old_libs" = no; then
+ build_libtool_libs=module
+ build_old_libs=yes
+ else
+ build_libtool_libs=no
+ fi
+ fi
+ else
+ deplibs="$dir/$old_library $deplibs"
+ link_static=yes
+ fi
+ fi # link shared/static library?
+
+ if test "$linkmode" = lib; then
+ if test -n "$dependency_libs" &&
+ { test "$hardcode_into_libs" != yes ||
+ test "$build_old_libs" = yes ||
+ test "$link_static" = yes; }; then
+ # Extract -R from dependency_libs
+ temp_deplibs=
+ for libdir in $dependency_libs; do
+ case $libdir in
+ -R*) temp_xrpath=`$echo "X$libdir" | $Xsed -e 's/^-R//'`
+ case " $xrpath " in
+ *" $temp_xrpath "*) ;;
+ *) xrpath="$xrpath $temp_xrpath";;
+ esac;;
+ *) temp_deplibs="$temp_deplibs $libdir";;
+ esac
+ done
+ dependency_libs="$temp_deplibs"
+ fi
+
+ newlib_search_path="$newlib_search_path $absdir"
+ # Link against this library
+ test "$link_static" = no && newdependency_libs="$abs_ladir/$laname $newdependency_libs"
+ # ... and its dependency_libs
+ tmp_libs=
+ for deplib in $dependency_libs; do
+ newdependency_libs="$deplib $newdependency_libs"
+ if test "X$duplicate_deps" = "Xyes" ; then
+ case "$tmp_libs " in
+ *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
+ esac
+ fi
+ tmp_libs="$tmp_libs $deplib"
+ done
+
+ if test "$link_all_deplibs" != no; then
+ # Add the search paths of all dependency libraries
+ for deplib in $dependency_libs; do
+ case $deplib in
+ -L*) path="$deplib" ;;
+ *.la)
+ dir=`$echo "X$deplib" | $Xsed -e 's%/[^/]*$%%'`
+ test "X$dir" = "X$deplib" && dir="."
+ # We need an absolute path.
+ case $dir in
+ [\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;;
+ *)
+ absdir=`cd "$dir" && pwd`
+ if test -z "$absdir"; then
+ $echo "$modename: warning: cannot determine absolute directory name of \`$dir'" 1>&2
+ absdir="$dir"
+ fi
+ ;;
+ esac
+ if grep "^installed=no" $deplib > /dev/null; then
+ path="$absdir/$objdir"
+ else
+ eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib`
+ if test -z "$libdir"; then
+ $echo "$modename: \`$deplib' is not a valid libtool archive" 1>&2
+ exit $EXIT_FAILURE
+ fi
+ if test "$absdir" != "$libdir"; then
+ $echo "$modename: warning: \`$deplib' seems to be moved" 1>&2
+ fi
+ path="$absdir"
+ fi
+ depdepl=
+ case $host in
+ *-*-darwin*)
+ # we do not want to link against static libs,
+ # but need to link against shared
+ eval deplibrary_names=`${SED} -n -e 's/^library_names=\(.*\)$/\1/p' $deplib`
+ if test -n "$deplibrary_names" ; then
+ for tmp in $deplibrary_names ; do
+ depdepl=$tmp
+ done
+ if test -f "$path/$depdepl" ; then
+ depdepl="$path/$depdepl"
+ fi
+ # do not add paths which are already there
+ case " $newlib_search_path " in
+ *" $path "*) ;;
+ *) newlib_search_path="$newlib_search_path $path";;
+ esac
+ fi
+ path=""
+ ;;
+ *)
+ path="-L$path"
+ ;;
+ esac
+ ;;
+ -l*)
+ case $host in
+ *-*-darwin*)
+ # Again, we only want to link against shared libraries
+ eval tmp_libs=`$echo "X$deplib" | $Xsed -e "s,^\-l,,"`
+ for tmp in $newlib_search_path ; do
+ if test -f "$tmp/lib$tmp_libs.dylib" ; then
+ eval depdepl="$tmp/lib$tmp_libs.dylib"
+ break
+ fi
+ done
+ path=""
+ ;;
+ *) continue ;;
+ esac
+ ;;
+ *) continue ;;
+ esac
+ case " $deplibs " in
+ *" $path "*) ;;
+ *) deplibs="$path $deplibs" ;;
+ esac
+ case " $deplibs " in
+ *" $depdepl "*) ;;
+ *) deplibs="$depdepl $deplibs" ;;
+ esac
+ done
+ fi # link_all_deplibs != no
+ fi # linkmode = lib
+ done # for deplib in $libs
+ dependency_libs="$newdependency_libs"
+ if test "$pass" = dlpreopen; then
+ # Link the dlpreopened libraries before other libraries
+ for deplib in $save_deplibs; do
+ deplibs="$deplib $deplibs"
+ done
+ fi
+ if test "$pass" != dlopen; then
+ if test "$pass" != conv; then
+ # Make sure lib_search_path contains only unique directories.
+ lib_search_path=
+ for dir in $newlib_search_path; do
+ case "$lib_search_path " in
+ *" $dir "*) ;;
+ *) lib_search_path="$lib_search_path $dir" ;;
+ esac
+ done
+ newlib_search_path=
+ fi
+
+ if test "$linkmode,$pass" != "prog,link"; then
+ vars="deplibs"
+ else
+ vars="compile_deplibs finalize_deplibs"
+ fi
+ for var in $vars dependency_libs; do
+ # Add libraries to $var in reverse order
+ eval tmp_libs=\"\$$var\"
+ new_libs=
+ for deplib in $tmp_libs; do
+ # FIXME: Pedantically, this is the right thing to do, so
+ # that some nasty dependency loop isn't accidentally
+ # broken:
+ #new_libs="$deplib $new_libs"
+ # Pragmatically, this seems to cause very few problems in
+ # practice:
+ case $deplib in
+ -L*) new_libs="$deplib $new_libs" ;;
+ -R*) ;;
+ *)
+ # And here is the reason: when a library appears more
+ # than once as an explicit dependence of a library, or
+ # is implicitly linked in more than once by the
+ # compiler, it is considered special, and multiple
+ # occurrences thereof are not removed. Compare this
+ # with having the same library being listed as a
+ # dependency of multiple other libraries: in this case,
+ # we know (pedantically, we assume) the library does not
+ # need to be listed more than once, so we keep only the
+ # last copy. This is not always right, but it is rare
+ # enough that we require users that really mean to play
+ # such unportable linking tricks to link the library
+ # using -Wl,-lname, so that libtool does not consider it
+ # for duplicate removal.
+ case " $specialdeplibs " in
+ *" $deplib "*) new_libs="$deplib $new_libs" ;;
+ *)
+ case " $new_libs " in
+ *" $deplib "*) ;;
+ *) new_libs="$deplib $new_libs" ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ done
+ tmp_libs=
+ for deplib in $new_libs; do
+ case $deplib in
+ -L*)
+ case " $tmp_libs " in
+ *" $deplib "*) ;;
+ *) tmp_libs="$tmp_libs $deplib" ;;
+ esac
+ ;;
+ *) tmp_libs="$tmp_libs $deplib" ;;
+ esac
+ done
+ eval $var=\"$tmp_libs\"
+ done # for var
+ fi
+ # Last step: remove runtime libs from dependency_libs
+ # (they stay in deplibs)
+ tmp_libs=
+ for i in $dependency_libs ; do
+ case " $predeps $postdeps $compiler_lib_search_path " in
+ *" $i "*)
+ i=""
+ ;;
+ esac
+ if test -n "$i" ; then
+ tmp_libs="$tmp_libs $i"
+ fi
+ done
+ dependency_libs=$tmp_libs
+ done # for pass
+ if test "$linkmode" = prog; then
+ dlfiles="$newdlfiles"
+ dlprefiles="$newdlprefiles"
+ fi
+
+ case $linkmode in
+ oldlib)
+ if test -n "$deplibs"; then
+ $echo "$modename: warning: \`-l' and \`-L' are ignored for archives" 1>&2
+ fi
+
+ if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
+ $echo "$modename: warning: \`-dlopen' is ignored for archives" 1>&2
+ fi
+
+ if test -n "$rpath"; then
+ $echo "$modename: warning: \`-rpath' is ignored for archives" 1>&2
+ fi
+
+ if test -n "$xrpath"; then
+ $echo "$modename: warning: \`-R' is ignored for archives" 1>&2
+ fi
+
+ if test -n "$vinfo"; then
+ $echo "$modename: warning: \`-version-info/-version-number' is ignored for archives" 1>&2
+ fi
+
+ if test -n "$release"; then
+ $echo "$modename: warning: \`-release' is ignored for archives" 1>&2
+ fi
+
+ if test -n "$export_symbols" || test -n "$export_symbols_regex"; then
+ $echo "$modename: warning: \`-export-symbols' is ignored for archives" 1>&2
+ fi
+
+ # Now set the variables for building old libraries.
+ build_libtool_libs=no
+ oldlibs="$output"
+ objs="$objs$old_deplibs"
+ ;;
+
+ lib)
+ # Make sure we only generate libraries of the form `libNAME.la'.
+ case $outputname in
+ lib*)
+ name=`$echo "X$outputname" | $Xsed -e 's/\.la$//' -e 's/^lib//'`
+ eval shared_ext=\"$shrext_cmds\"
+ eval libname=\"$libname_spec\"
+ ;;
+ *)
+ if test "$module" = no; then
+ $echo "$modename: libtool library \`$output' must begin with \`lib'" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ fi
+ if test "$need_lib_prefix" != no; then
+ # Add the "lib" prefix for modules if required
+ name=`$echo "X$outputname" | $Xsed -e 's/\.la$//'`
+ eval shared_ext=\"$shrext_cmds\"
+ eval libname=\"$libname_spec\"
+ else
+ libname=`$echo "X$outputname" | $Xsed -e 's/\.la$//'`
+ fi
+ ;;
+ esac
+
+ if test -n "$objs"; then
+ if test "$deplibs_check_method" != pass_all; then
+ $echo "$modename: cannot build libtool library \`$output' from non-libtool objects on this host:$objs" 2>&1
+ exit $EXIT_FAILURE
+ else
+ $echo
+ $echo "*** Warning: Linking the shared library $output against the non-libtool"
+ $echo "*** objects $objs is not portable!"
+ libobjs="$libobjs $objs"
+ fi
+ fi
+
+ if test "$dlself" != no; then
+ $echo "$modename: warning: \`-dlopen self' is ignored for libtool libraries" 1>&2
+ fi
+
+ set dummy $rpath
+ if test "$#" -gt 2; then
+ $echo "$modename: warning: ignoring multiple \`-rpath's for a libtool library" 1>&2
+ fi
+ install_libdir="$2"
+
+ oldlibs=
+ if test -z "$rpath"; then
+ if test "$build_libtool_libs" = yes; then
+ # Building a libtool convenience library.
+ # Some compilers have problems with a `.al' extension so
+ # convenience libraries should have the same extension an
+ # archive normally would.
+ oldlibs="$output_objdir/$libname.$libext $oldlibs"
+ build_libtool_libs=convenience
+ build_old_libs=yes
+ fi
+
+ if test -n "$vinfo"; then
+ $echo "$modename: warning: \`-version-info/-version-number' is ignored for convenience libraries" 1>&2
+ fi
+
+ if test -n "$release"; then
+ $echo "$modename: warning: \`-release' is ignored for convenience libraries" 1>&2
+ fi
+ else
+
+ # Parse the version information argument.
+ save_ifs="$IFS"; IFS=':'
+ set dummy $vinfo 0 0 0
+ IFS="$save_ifs"
+
+ if test -n "$8"; then
+ $echo "$modename: too many parameters to \`-version-info'" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ # convert absolute version numbers to libtool ages
+ # this retains compatibility with .la files and attempts
+ # to make the code below a bit more comprehensible
+
+ case $vinfo_number in
+ yes)
+ number_major="$2"
+ number_minor="$3"
+ number_revision="$4"
+ #
+ # There are really only two kinds -- those that
+ # use the current revision as the major version
+ # and those that subtract age and use age as
+ # a minor version. But, then there is irix
+ # which has an extra 1 added just for fun
+ #
+ case $version_type in
+ darwin|linux|osf|windows)
+ current=`expr $number_major + $number_minor`
+ age="$number_minor"
+ revision="$number_revision"
+ ;;
+ freebsd-aout|freebsd-elf|sunos)
+ current="$number_major"
+ revision="$number_minor"
+ age="0"
+ ;;
+ irix|nonstopux)
+ current=`expr $number_major + $number_minor - 1`
+ age="$number_minor"
+ revision="$number_minor"
+ ;;
+ esac
+ ;;
+ no)
+ current="$2"
+ revision="$3"
+ age="$4"
+ ;;
+ esac
+
+ # Check that each of the things are valid numbers.
+ case $current in
+ 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
+ *)
+ $echo "$modename: CURRENT \`$current' must be a nonnegative integer" 1>&2
+ $echo "$modename: \`$vinfo' is not valid version information" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+ esac
+
+ case $revision in
+ 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
+ *)
+ $echo "$modename: REVISION \`$revision' must be a nonnegative integer" 1>&2
+ $echo "$modename: \`$vinfo' is not valid version information" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+ esac
+
+ case $age in
+ 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
+ *)
+ $echo "$modename: AGE \`$age' must be a nonnegative integer" 1>&2
+ $echo "$modename: \`$vinfo' is not valid version information" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+ esac
+
+ if test "$age" -gt "$current"; then
+ $echo "$modename: AGE \`$age' is greater than the current interface number \`$current'" 1>&2
+ $echo "$modename: \`$vinfo' is not valid version information" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ # Calculate the version variables.
+ major=
+ versuffix=
+ verstring=
+ case $version_type in
+ none) ;;
+
+ darwin)
+ # Like Linux, but with the current version available in
+ # verstring for coding it into the library header
+ major=.`expr $current - $age`
+ versuffix="$major.$age.$revision"
+ # Darwin ld doesn't like 0 for these options...
+ minor_current=`expr $current + 1`
+ verstring="${wl}-compatibility_version ${wl}$minor_current ${wl}-current_version ${wl}$minor_current.$revision"
+ ;;
+
+ freebsd-aout)
+ major=".$current"
+ versuffix=".$current.$revision";
+ ;;
+
+ freebsd-elf)
+ major=".$current"
+ versuffix=".$current";
+ ;;
+
+ irix | nonstopux)
+ major=`expr $current - $age + 1`
+
+ case $version_type in
+ nonstopux) verstring_prefix=nonstopux ;;
+ *) verstring_prefix=sgi ;;
+ esac
+ verstring="$verstring_prefix$major.$revision"
+
+ # Add in all the interfaces that we are compatible with.
+ loop=$revision
+ while test "$loop" -ne 0; do
+ iface=`expr $revision - $loop`
+ loop=`expr $loop - 1`
+ verstring="$verstring_prefix$major.$iface:$verstring"
+ done
+
+ # Before this point, $major must not contain `.'.
+ major=.$major
+ versuffix="$major.$revision"
+ ;;
+
+ linux)
+ major=.`expr $current - $age`
+ versuffix="$major.$age.$revision"
+ ;;
+
+ osf)
+ major=.`expr $current - $age`
+ versuffix=".$current.$age.$revision"
+ verstring="$current.$age.$revision"
+
+ # Add in all the interfaces that we are compatible with.
+ loop=$age
+ while test "$loop" -ne 0; do
+ iface=`expr $current - $loop`
+ loop=`expr $loop - 1`
+ verstring="$verstring:${iface}.0"
+ done
+
+ # Make executables depend on our current version.
+ verstring="$verstring:${current}.0"
+ ;;
+
+ sunos)
+ major=".$current"
+ versuffix=".$current.$revision"
+ ;;
+
+ windows)
+ # Use '-' rather than '.', since we only want one
+ # extension on DOS 8.3 filesystems.
+ major=`expr $current - $age`
+ versuffix="-$major"
+ ;;
+
+ *)
+ $echo "$modename: unknown library version type \`$version_type'" 1>&2
+ $echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2
+ exit $EXIT_FAILURE
+ ;;
+ esac
+
+ # Clear the version info if we defaulted, and they specified a release.
+ if test -z "$vinfo" && test -n "$release"; then
+ major=
+ case $version_type in
+ darwin)
+ # we can't check for "0.0" in archive_cmds due to quoting
+ # problems, so we reset it completely
+ verstring=
+ ;;
+ *)
+ verstring="0.0"
+ ;;
+ esac
+ if test "$need_version" = no; then
+ versuffix=
+ else
+ versuffix=".0.0"
+ fi
+ fi
+
+ # Remove version info from name if versioning should be avoided
+ if test "$avoid_version" = yes && test "$need_version" = no; then
+ major=
+ versuffix=
+ verstring=""
+ fi
+
+ # Check to see if the archive will have undefined symbols.
+ if test "$allow_undefined" = yes; then
+ if test "$allow_undefined_flag" = unsupported; then
+ $echo "$modename: warning: undefined symbols not allowed in $host shared libraries" 1>&2
+ build_libtool_libs=no
+ build_old_libs=yes
+ fi
+ else
+ # Don't allow undefined symbols.
+ allow_undefined_flag="$no_undefined_flag"
+ fi
+ fi
+
+ if test "$mode" != relink; then
+ # Remove our outputs, but don't remove object files since they
+ # may have been created when compiling PIC objects.
+ removelist=
+ tempremovelist=`$echo "$output_objdir/*"`
+ for p in $tempremovelist; do
+ case $p in
+ *.$objext)
+ ;;
+ $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/${libname}${release}.*)
+ if test "X$precious_files_regex" != "X"; then
+ if echo $p | $EGREP -e "$precious_files_regex" >/dev/null 2>&1
+ then
+ continue
+ fi
+ fi
+ removelist="$removelist $p"
+ ;;
+ *) ;;
+ esac
+ done
+ if test -n "$removelist"; then
+ $show "${rm}r $removelist"
+ $run ${rm}r $removelist
+ fi
+ fi
+
+ # Now set the variables for building old libraries.
+ if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then
+ oldlibs="$oldlibs $output_objdir/$libname.$libext"
+
+ # Transform .lo files to .o files.
+ oldobjs="$objs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e "$lo2o" | $NL2SP`
+ fi
+
+ # Eliminate all temporary directories.
+ for path in $notinst_path; do
+ lib_search_path=`$echo "$lib_search_path " | ${SED} -e "s% $path % %g"`
+ deplibs=`$echo "$deplibs " | ${SED} -e "s% -L$path % %g"`
+ dependency_libs=`$echo "$dependency_libs " | ${SED} -e "s% -L$path % %g"`
+ done
+
+ if test -n "$xrpath"; then
+ # If the user specified any rpath flags, then add them.
+ temp_xrpath=
+ for libdir in $xrpath; do
+ temp_xrpath="$temp_xrpath -R$libdir"
+ case "$finalize_rpath " in
+ *" $libdir "*) ;;
+ *) finalize_rpath="$finalize_rpath $libdir" ;;
+ esac
+ done
+ if test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes; then
+ dependency_libs="$temp_xrpath $dependency_libs"
+ fi
+ fi
+
+ # Make sure dlfiles contains only unique files that won't be dlpreopened
+ old_dlfiles="$dlfiles"
+ dlfiles=
+ for lib in $old_dlfiles; do
+ case " $dlprefiles $dlfiles " in
+ *" $lib "*) ;;
+ *) dlfiles="$dlfiles $lib" ;;
+ esac
+ done
+
+ # Make sure dlprefiles contains only unique files
+ old_dlprefiles="$dlprefiles"
+ dlprefiles=
+ for lib in $old_dlprefiles; do
+ case "$dlprefiles " in
+ *" $lib "*) ;;
+ *) dlprefiles="$dlprefiles $lib" ;;
+ esac
+ done
+
+ if test "$build_libtool_libs" = yes; then
+ if test -n "$rpath"; then
+ case $host in
+ *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos*)
+ # these systems don't actually have a c library (as such)!
+ ;;
+ *-*-rhapsody* | *-*-darwin1.[012])
+ # Rhapsody C library is in the System framework
+ deplibs="$deplibs -framework System"
+ ;;
+ *-*-netbsd*)
+ # Don't link with libc until the a.out ld.so is fixed.
+ ;;
+ *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*)
+ # Do not include libc due to us having libc/libc_r.
+ ;;
+ *-*-sco3.2v5* | *-*-sco5v6*)
+ # Causes problems with __ctype
+ ;;
+ *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*)
+ # Compiler inserts libc in the correct place for threads to work
+ ;;
+ *)
+ # Add libc to deplibs on all other systems if necessary.
+ if test "$build_libtool_need_lc" = "yes"; then
+ deplibs="$deplibs -lc"
+ fi
+ ;;
+ esac
+ fi
+
+ # Transform deplibs into only deplibs that can be linked in shared.
+ name_save=$name
+ libname_save=$libname
+ release_save=$release
+ versuffix_save=$versuffix
+ major_save=$major
+ # I'm not sure if I'm treating the release correctly. I think
+ # release should show up in the -l (ie -lgmp5) so we don't want to
+ # add it in twice. Is that correct?
+ release=""
+ versuffix=""
+ major=""
+ newdeplibs=
+ droppeddeps=no
+ case $deplibs_check_method in
+ pass_all)
+ # Don't check for shared/static. Everything works.
+ # This might be a little naive. We might want to check
+ # whether the library exists or not. But this is on
+ # osf3 & osf4 and I'm not really sure... Just
+ # implementing what was already the behavior.
+ newdeplibs=$deplibs
+ ;;
+ test_compile)
+ # This code stresses the "libraries are programs" paradigm to its
+ # limits. Maybe even breaks it. We compile a program, linking it
+ # against the deplibs as a proxy for the library. Then we can check
+ # whether they linked in statically or dynamically with ldd.
+ $rm conftest.c
+ cat > conftest.c <<EOF
+ int main() { return 0; }
+EOF
+ $rm conftest
+ $LTCC $LTCFLAGS -o conftest conftest.c $deplibs
+ if test "$?" -eq 0 ; then
+ ldd_output=`ldd conftest`
+ for i in $deplibs; do
+ name=`expr $i : '-l\(.*\)'`
+ # If $name is empty we are operating on a -L argument.
+ if test "$name" != "" && test "$name" -ne "0"; then
+ if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+ case " $predeps $postdeps " in
+ *" $i "*)
+ newdeplibs="$newdeplibs $i"
+ i=""
+ ;;
+ esac
+ fi
+ if test -n "$i" ; then
+ libname=`eval \\$echo \"$libname_spec\"`
+ deplib_matches=`eval \\$echo \"$library_names_spec\"`
+ set dummy $deplib_matches
+ deplib_match=$2
+ if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then
+ newdeplibs="$newdeplibs $i"
+ else
+ droppeddeps=yes
+ $echo
+ $echo "*** Warning: dynamic linker does not accept needed library $i."
+ $echo "*** I have the capability to make that library automatically link in when"
+ $echo "*** you link to this library. But I can only do this if you have a"
+ $echo "*** shared version of the library, which I believe you do not have"
+ $echo "*** because a test_compile did reveal that the linker did not use it for"
+ $echo "*** its dynamic dependency list that programs get resolved with at runtime."
+ fi
+ fi
+ else
+ newdeplibs="$newdeplibs $i"
+ fi
+ done
+ else
+ # Error occurred in the first compile. Let's try to salvage
+ # the situation: Compile a separate program for each library.
+ for i in $deplibs; do
+ name=`expr $i : '-l\(.*\)'`
+ # If $name is empty we are operating on a -L argument.
+ if test "$name" != "" && test "$name" != "0"; then
+ $rm conftest
+ $LTCC $LTCFLAGS -o conftest conftest.c $i
+ # Did it work?
+ if test "$?" -eq 0 ; then
+ ldd_output=`ldd conftest`
+ if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+ case " $predeps $postdeps " in
+ *" $i "*)
+ newdeplibs="$newdeplibs $i"
+ i=""
+ ;;
+ esac
+ fi
+ if test -n "$i" ; then
+ libname=`eval \\$echo \"$libname_spec\"`
+ deplib_matches=`eval \\$echo \"$library_names_spec\"`
+ set dummy $deplib_matches
+ deplib_match=$2
+ if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then
+ newdeplibs="$newdeplibs $i"
+ else
+ droppeddeps=yes
+ $echo
+ $echo "*** Warning: dynamic linker does not accept needed library $i."
+ $echo "*** I have the capability to make that library automatically link in when"
+ $echo "*** you link to this library. But I can only do this if you have a"
+ $echo "*** shared version of the library, which you do not appear to have"
+ $echo "*** because a test_compile did reveal that the linker did not use this one"
+ $echo "*** as a dynamic dependency that programs can get resolved with at runtime."
+ fi
+ fi
+ else
+ droppeddeps=yes
+ $echo
+ $echo "*** Warning! Library $i is needed by this library but I was not able to"
+ $echo "*** make it link in! You will probably need to install it or some"
+ $echo "*** library that it depends on before this library will be fully"
+ $echo "*** functional. Installing it before continuing would be even better."
+ fi
+ else
+ newdeplibs="$newdeplibs $i"
+ fi
+ done
+ fi
+ ;;
+ file_magic*)
+ set dummy $deplibs_check_method
+ file_magic_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"`
+ for a_deplib in $deplibs; do
+ name=`expr $a_deplib : '-l\(.*\)'`
+ # If $name is empty we are operating on a -L argument.
+ if test "$name" != "" && test "$name" != "0"; then
+ if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+ case " $predeps $postdeps " in
+ *" $a_deplib "*)
+ newdeplibs="$newdeplibs $a_deplib"
+ a_deplib=""
+ ;;
+ esac
+ fi
+ if test -n "$a_deplib" ; then
+ libname=`eval \\$echo \"$libname_spec\"`
+ for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do
+ potential_libs=`ls $i/$libname[.-]* 2>/dev/null`
+ for potent_lib in $potential_libs; do
+ # Follow soft links.
+ if ls -lLd "$potent_lib" 2>/dev/null \
+ | grep " -> " >/dev/null; then
+ continue
+ fi
+ # The statement above tries to avoid entering an
+ # endless loop below, in case of cyclic links.
+ # We might still enter an endless loop, since a link
+ # loop can be closed while we follow links,
+ # but so what?
+ potlib="$potent_lib"
+ while test -h "$potlib" 2>/dev/null; do
+ potliblink=`ls -ld $potlib | ${SED} 's/.* -> //'`
+ case $potliblink in
+ [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";;
+ *) potlib=`$echo "X$potlib" | $Xsed -e 's,[^/]*$,,'`"$potliblink";;
+ esac
+ done
+ if eval $file_magic_cmd \"\$potlib\" 2>/dev/null \
+ | ${SED} 10q \
+ | $EGREP "$file_magic_regex" > /dev/null; then
+ newdeplibs="$newdeplibs $a_deplib"
+ a_deplib=""
+ break 2
+ fi
+ done
+ done
+ fi
+ if test -n "$a_deplib" ; then
+ droppeddeps=yes
+ $echo
+ $echo "*** Warning: linker path does not have real file for library $a_deplib."
+ $echo "*** I have the capability to make that library automatically link in when"
+ $echo "*** you link to this library. But I can only do this if you have a"
+ $echo "*** shared version of the library, which you do not appear to have"
+ $echo "*** because I did check the linker path looking for a file starting"
+ if test -z "$potlib" ; then
+ $echo "*** with $libname but no candidates were found. (...for file magic test)"
+ else
+ $echo "*** with $libname and none of the candidates passed a file format test"
+ $echo "*** using a file magic. Last file checked: $potlib"
+ fi
+ fi
+ else
+ # Add a -L argument.
+ newdeplibs="$newdeplibs $a_deplib"
+ fi
+ done # Gone through all deplibs.
+ ;;
+ match_pattern*)
+ set dummy $deplibs_check_method
+ match_pattern_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"`
+ for a_deplib in $deplibs; do
+ name=`expr $a_deplib : '-l\(.*\)'`
+ # If $name is empty we are operating on a -L argument.
+ if test -n "$name" && test "$name" != "0"; then
+ if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+ case " $predeps $postdeps " in
+ *" $a_deplib "*)
+ newdeplibs="$newdeplibs $a_deplib"
+ a_deplib=""
+ ;;
+ esac
+ fi
+ if test -n "$a_deplib" ; then
+ libname=`eval \\$echo \"$libname_spec\"`
+ for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do
+ potential_libs=`ls $i/$libname[.-]* 2>/dev/null`
+ for potent_lib in $potential_libs; do
+ potlib="$potent_lib" # see symlink-check above in file_magic test
+ if eval $echo \"$potent_lib\" 2>/dev/null \
+ | ${SED} 10q \
+ | $EGREP "$match_pattern_regex" > /dev/null; then
+ newdeplibs="$newdeplibs $a_deplib"
+ a_deplib=""
+ break 2
+ fi
+ done
+ done
+ fi
+ if test -n "$a_deplib" ; then
+ droppeddeps=yes
+ $echo
+ $echo "*** Warning: linker path does not have real file for library $a_deplib."
+ $echo "*** I have the capability to make that library automatically link in when"
+ $echo "*** you link to this library. But I can only do this if you have a"
+ $echo "*** shared version of the library, which you do not appear to have"
+ $echo "*** because I did check the linker path looking for a file starting"
+ if test -z "$potlib" ; then
+ $echo "*** with $libname but no candidates were found. (...for regex pattern test)"
+ else
+ $echo "*** with $libname and none of the candidates passed a file format test"
+ $echo "*** using a regex pattern. Last file checked: $potlib"
+ fi
+ fi
+ else
+ # Add a -L argument.
+ newdeplibs="$newdeplibs $a_deplib"
+ fi
+ done # Gone through all deplibs.
+ ;;
+ none | unknown | *)
+ newdeplibs=""
+ tmp_deplibs=`$echo "X $deplibs" | $Xsed -e 's/ -lc$//' \
+ -e 's/ -[LR][^ ]*//g'`
+ if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+ for i in $predeps $postdeps ; do
+ # can't use Xsed below, because $i might contain '/'
+ tmp_deplibs=`$echo "X $tmp_deplibs" | ${SED} -e "1s,^X,," -e "s,$i,,"`
+ done
+ fi
+ if $echo "X $tmp_deplibs" | $Xsed -e 's/[ ]//g' \
+ | grep . >/dev/null; then
+ $echo
+ if test "X$deplibs_check_method" = "Xnone"; then
+ $echo "*** Warning: inter-library dependencies are not supported in this platform."
+ else
+ $echo "*** Warning: inter-library dependencies are not known to be supported."
+ fi
+ $echo "*** All declared inter-library dependencies are being dropped."
+ droppeddeps=yes
+ fi
+ ;;
+ esac
+ versuffix=$versuffix_save
+ major=$major_save
+ release=$release_save
+ libname=$libname_save
+ name=$name_save
+
+ case $host in
+ *-*-rhapsody* | *-*-darwin1.[012])
+ # On Rhapsody replace the C library is the System framework
+ newdeplibs=`$echo "X $newdeplibs" | $Xsed -e 's/ -lc / -framework System /'`
+ ;;
+ esac
+
+ if test "$droppeddeps" = yes; then
+ if test "$module" = yes; then
+ $echo
+ $echo "*** Warning: libtool could not satisfy all declared inter-library"
+ $echo "*** dependencies of module $libname. Therefore, libtool will create"
+ $echo "*** a static module, that should work as long as the dlopening"
+ $echo "*** application is linked with the -dlopen flag."
+ if test -z "$global_symbol_pipe"; then
+ $echo
+ $echo "*** However, this would only work if libtool was able to extract symbol"
+ $echo "*** lists from a program, using \`nm' or equivalent, but libtool could"
+ $echo "*** not find such a program. So, this module is probably useless."
+ $echo "*** \`nm' from GNU binutils and a full rebuild may help."
+ fi
+ if test "$build_old_libs" = no; then
+ oldlibs="$output_objdir/$libname.$libext"
+ build_libtool_libs=module
+ build_old_libs=yes
+ else
+ build_libtool_libs=no
+ fi
+ else
+ $echo "*** The inter-library dependencies that have been dropped here will be"
+ $echo "*** automatically added whenever a program is linked with this library"
+ $echo "*** or is declared to -dlopen it."
+
+ if test "$allow_undefined" = no; then
+ $echo
+ $echo "*** Since this library must not contain undefined symbols,"
+ $echo "*** because either the platform does not support them or"
+ $echo "*** it was explicitly requested with -no-undefined,"
+ $echo "*** libtool will only create a static version of it."
+ if test "$build_old_libs" = no; then
+ oldlibs="$output_objdir/$libname.$libext"
+ build_libtool_libs=module
+ build_old_libs=yes
+ else
+ build_libtool_libs=no
+ fi
+ fi
+ fi
+ fi
+ # Done checking deplibs!
+ deplibs=$newdeplibs
+ fi
+
+
+ # move library search paths that coincide with paths to not yet
+ # installed libraries to the beginning of the library search list
+ new_libs=
+ for path in $notinst_path; do
+ case " $new_libs " in
+ *" -L$path/$objdir "*) ;;
+ *)
+ case " $deplibs " in
+ *" -L$path/$objdir "*)
+ new_libs="$new_libs -L$path/$objdir" ;;
+ esac
+ ;;
+ esac
+ done
+ for deplib in $deplibs; do
+ case $deplib in
+ -L*)
+ case " $new_libs " in
+ *" $deplib "*) ;;
+ *) new_libs="$new_libs $deplib" ;;
+ esac
+ ;;
+ *) new_libs="$new_libs $deplib" ;;
+ esac
+ done
+ deplibs="$new_libs"
+
+
+ # All the library-specific variables (install_libdir is set above).
+ library_names=
+ old_library=
+ dlname=
+
+ # Test again, we may have decided not to build it any more
+ if test "$build_libtool_libs" = yes; then
+ if test "$hardcode_into_libs" = yes; then
+ # Hardcode the library paths
+ hardcode_libdirs=
+ dep_rpath=
+ rpath="$finalize_rpath"
+ test "$mode" != relink && rpath="$compile_rpath$rpath"
+ for libdir in $rpath; do
+ if test -n "$hardcode_libdir_flag_spec"; then
+ if test -n "$hardcode_libdir_separator"; then
+ if test -z "$hardcode_libdirs"; then
+ hardcode_libdirs="$libdir"
+ else
+ # Just accumulate the unique libdirs.
+ case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
+ *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
+ ;;
+ *)
+ hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
+ ;;
+ esac
+ fi
+ else
+ eval flag=\"$hardcode_libdir_flag_spec\"
+ dep_rpath="$dep_rpath $flag"
+ fi
+ elif test -n "$runpath_var"; then
+ case "$perm_rpath " in
+ *" $libdir "*) ;;
+ *) perm_rpath="$perm_rpath $libdir" ;;
+ esac
+ fi
+ done
+ # Substitute the hardcoded libdirs into the rpath.
+ if test -n "$hardcode_libdir_separator" &&
+ test -n "$hardcode_libdirs"; then
+ libdir="$hardcode_libdirs"
+ if test -n "$hardcode_libdir_flag_spec_ld"; then
+ eval dep_rpath=\"$hardcode_libdir_flag_spec_ld\"
+ else
+ eval dep_rpath=\"$hardcode_libdir_flag_spec\"
+ fi
+ fi
+ if test -n "$runpath_var" && test -n "$perm_rpath"; then
+ # We should set the runpath_var.
+ rpath=
+ for dir in $perm_rpath; do
+ rpath="$rpath$dir:"
+ done
+ eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var"
+ fi
+ test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs"
+ fi
+
+ shlibpath="$finalize_shlibpath"
+ test "$mode" != relink && shlibpath="$compile_shlibpath$shlibpath"
+ if test -n "$shlibpath"; then
+ eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var"
+ fi
+
+ # Get the real and link names of the library.
+ eval shared_ext=\"$shrext_cmds\"
+ eval library_names=\"$library_names_spec\"
+ set dummy $library_names
+ realname="$2"
+ shift; shift
+
+ if test -n "$soname_spec"; then
+ eval soname=\"$soname_spec\"
+ else
+ soname="$realname"
+ fi
+ if test -z "$dlname"; then
+ dlname=$soname
+ fi
+
+ lib="$output_objdir/$realname"
+ linknames=
+ for link
+ do
+ linknames="$linknames $link"
+ done
+
+ # Use standard objects if they are pic
+ test -z "$pic_flag" && libobjs=`$echo "X$libobjs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
+
+ # Prepare the list of exported symbols
+ if test -z "$export_symbols"; then
+ if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then
+ $show "generating symbol list for \`$libname.la'"
+ export_symbols="$output_objdir/$libname.exp"
+ $run $rm $export_symbols
+ cmds=$export_symbols_cmds
+ save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ eval cmd=\"$cmd\"
+ if len=`expr "X$cmd" : ".*"` &&
+ test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ skipped_export=false
+ else
+ # The command line is too long to execute in one step.
+ $show "using reloadable object file for export list..."
+ skipped_export=:
+ # Break out early, otherwise skipped_export may be
+ # set to false by a later but shorter cmd.
+ break
+ fi
+ done
+ IFS="$save_ifs"
+ if test -n "$export_symbols_regex"; then
+ $show "$EGREP -e \"$export_symbols_regex\" \"$export_symbols\" > \"${export_symbols}T\""
+ $run eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"'
+ $show "$mv \"${export_symbols}T\" \"$export_symbols\""
+ $run eval '$mv "${export_symbols}T" "$export_symbols"'
+ fi
+ fi
+ fi
+
+ if test -n "$export_symbols" && test -n "$include_expsyms"; then
+ $run eval '$echo "X$include_expsyms" | $SP2NL >> "$export_symbols"'
+ fi
+
+ tmp_deplibs=
+ for test_deplib in $deplibs; do
+ case " $convenience " in
+ *" $test_deplib "*) ;;
+ *)
+ tmp_deplibs="$tmp_deplibs $test_deplib"
+ ;;
+ esac
+ done
+ deplibs="$tmp_deplibs"
+
+ if test -n "$convenience"; then
+ if test -n "$whole_archive_flag_spec"; then
+ save_libobjs=$libobjs
+ eval libobjs=\"\$libobjs $whole_archive_flag_spec\"
+ else
+ gentop="$output_objdir/${outputname}x"
+ generated="$generated $gentop"
+
+ func_extract_archives $gentop $convenience
+ libobjs="$libobjs $func_extract_archives_result"
+ fi
+ fi
+
+ if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then
+ eval flag=\"$thread_safe_flag_spec\"
+ linker_flags="$linker_flags $flag"
+ fi
+
+ # Make a backup of the uninstalled library when relinking
+ if test "$mode" = relink; then
+ $run eval '(cd $output_objdir && $rm ${realname}U && $mv $realname ${realname}U)' || exit $?
+ fi
+
+ # Do each of the archive commands.
+ if test "$module" = yes && test -n "$module_cmds" ; then
+ if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then
+ eval test_cmds=\"$module_expsym_cmds\"
+ cmds=$module_expsym_cmds
+ else
+ eval test_cmds=\"$module_cmds\"
+ cmds=$module_cmds
+ fi
+ else
+ if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then
+ eval test_cmds=\"$archive_expsym_cmds\"
+ cmds=$archive_expsym_cmds
+ else
+ eval test_cmds=\"$archive_cmds\"
+ cmds=$archive_cmds
+ fi
+ fi
+
+ if test "X$skipped_export" != "X:" &&
+ len=`expr "X$test_cmds" : ".*" 2>/dev/null` &&
+ test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then
+ :
+ else
+ # The command line is too long to link in one step, link piecewise.
+ $echo "creating reloadable object files..."
+
+ # Save the value of $output and $libobjs because we want to
+ # use them later. If we have whole_archive_flag_spec, we
+ # want to use save_libobjs as it was before
+ # whole_archive_flag_spec was expanded, because we can't
+ # assume the linker understands whole_archive_flag_spec.
+ # This may have to be revisited, in case too many
+ # convenience libraries get linked in and end up exceeding
+ # the spec.
+ if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then
+ save_libobjs=$libobjs
+ fi
+ save_output=$output
+ output_la=`$echo "X$output" | $Xsed -e "$basename"`
+
+ # Clear the reloadable object creation command queue and
+ # initialize k to one.
+ test_cmds=
+ concat_cmds=
+ objlist=
+ delfiles=
+ last_robj=
+ k=1
+ output=$output_objdir/$output_la-${k}.$objext
+ # Loop over the list of objects to be linked.
+ for obj in $save_libobjs
+ do
+ eval test_cmds=\"$reload_cmds $objlist $last_robj\"
+ if test "X$objlist" = X ||
+ { len=`expr "X$test_cmds" : ".*" 2>/dev/null` &&
+ test "$len" -le "$max_cmd_len"; }; then
+ objlist="$objlist $obj"
+ else
+ # The command $test_cmds is almost too long, add a
+ # command to the queue.
+ if test "$k" -eq 1 ; then
+ # The first file doesn't have a previous command to add.
+ eval concat_cmds=\"$reload_cmds $objlist $last_robj\"
+ else
+ # All subsequent reloadable object files will link in
+ # the last one created.
+ eval concat_cmds=\"\$concat_cmds~$reload_cmds $objlist $last_robj\"
+ fi
+ last_robj=$output_objdir/$output_la-${k}.$objext
+ k=`expr $k + 1`
+ output=$output_objdir/$output_la-${k}.$objext
+ objlist=$obj
+ len=1
+ fi
+ done
+ # Handle the remaining objects by creating one last
+ # reloadable object file. All subsequent reloadable object
+ # files will link in the last one created.
+ test -z "$concat_cmds" || concat_cmds=$concat_cmds~
+ eval concat_cmds=\"\${concat_cmds}$reload_cmds $objlist $last_robj\"
+
+ if ${skipped_export-false}; then
+ $show "generating symbol list for \`$libname.la'"
+ export_symbols="$output_objdir/$libname.exp"
+ $run $rm $export_symbols
+ libobjs=$output
+ # Append the command to create the export file.
+ eval concat_cmds=\"\$concat_cmds~$export_symbols_cmds\"
+ fi
+
+ # Set up a command to remove the reloadable object files
+ # after they are used.
+ i=0
+ while test "$i" -lt "$k"
+ do
+ i=`expr $i + 1`
+ delfiles="$delfiles $output_objdir/$output_la-${i}.$objext"
+ done
+
+ $echo "creating a temporary reloadable object file: $output"
+
+ # Loop through the commands generated above and execute them.
+ save_ifs="$IFS"; IFS='~'
+ for cmd in $concat_cmds; do
+ IFS="$save_ifs"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+
+ libobjs=$output
+ # Restore the value of output.
+ output=$save_output
+
+ if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then
+ eval libobjs=\"\$libobjs $whole_archive_flag_spec\"
+ fi
+ # Expand the library linking commands again to reset the
+ # value of $libobjs for piecewise linking.
+
+ # Do each of the archive commands.
+ if test "$module" = yes && test -n "$module_cmds" ; then
+ if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then
+ cmds=$module_expsym_cmds
+ else
+ cmds=$module_cmds
+ fi
+ else
+ if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then
+ cmds=$archive_expsym_cmds
+ else
+ cmds=$archive_cmds
+ fi
+ fi
+
+ # Append the command to remove the reloadable object files
+ # to the just-reset $cmds.
+ eval cmds=\"\$cmds~\$rm $delfiles\"
+ fi
+ save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ eval cmd=\"$cmd\"
+ $show "$cmd"
+ $run eval "$cmd" || {
+ lt_exit=$?
+
+ # Restore the uninstalled library and exit
+ if test "$mode" = relink; then
+ $run eval '(cd $output_objdir && $rm ${realname}T && $mv ${realname}U $realname)'
+ fi
+
+ exit $lt_exit
+ }
+ done
+ IFS="$save_ifs"
+
+ # Restore the uninstalled library and exit
+ if test "$mode" = relink; then
+ $run eval '(cd $output_objdir && $rm ${realname}T && $mv $realname ${realname}T && $mv "$realname"U $realname)' || exit $?
+
+ if test -n "$convenience"; then
+ if test -z "$whole_archive_flag_spec"; then
+ $show "${rm}r $gentop"
+ $run ${rm}r "$gentop"
+ fi
+ fi
+
+ exit $EXIT_SUCCESS
+ fi
+
+ # Create links to the real library.
+ for linkname in $linknames; do
+ if test "$realname" != "$linkname"; then
+ $show "(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)"
+ $run eval '(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)' || exit $?
+ fi
+ done
+
+ # If -module or -export-dynamic was specified, set the dlname.
+ if test "$module" = yes || test "$export_dynamic" = yes; then
+ # On all known operating systems, these are identical.
+ dlname="$soname"
+ fi
+ fi
+ ;;
+
+ obj)
+ if test -n "$deplibs"; then
+ $echo "$modename: warning: \`-l' and \`-L' are ignored for objects" 1>&2
+ fi
+
+ if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
+ $echo "$modename: warning: \`-dlopen' is ignored for objects" 1>&2
+ fi
+
+ if test -n "$rpath"; then
+ $echo "$modename: warning: \`-rpath' is ignored for objects" 1>&2
+ fi
+
+ if test -n "$xrpath"; then
+ $echo "$modename: warning: \`-R' is ignored for objects" 1>&2
+ fi
+
+ if test -n "$vinfo"; then
+ $echo "$modename: warning: \`-version-info' is ignored for objects" 1>&2
+ fi
+
+ if test -n "$release"; then
+ $echo "$modename: warning: \`-release' is ignored for objects" 1>&2
+ fi
+
+ case $output in
+ *.lo)
+ if test -n "$objs$old_deplibs"; then
+ $echo "$modename: cannot build library object \`$output' from non-libtool objects" 1>&2
+ exit $EXIT_FAILURE
+ fi
+ libobj="$output"
+ obj=`$echo "X$output" | $Xsed -e "$lo2o"`
+ ;;
+ *)
+ libobj=
+ obj="$output"
+ ;;
+ esac
+
+ # Delete the old objects.
+ $run $rm $obj $libobj
+
+ # Objects from convenience libraries. This assumes
+ # single-version convenience libraries. Whenever we create
+ # different ones for PIC/non-PIC, this we'll have to duplicate
+ # the extraction.
+ reload_conv_objs=
+ gentop=
+ # reload_cmds runs $LD directly, so let us get rid of
+ # -Wl from whole_archive_flag_spec
+ wl=
+
+ if test -n "$convenience"; then
+ if test -n "$whole_archive_flag_spec"; then
+ eval reload_conv_objs=\"\$reload_objs $whole_archive_flag_spec\"
+ else
+ gentop="$output_objdir/${obj}x"
+ generated="$generated $gentop"
+
+ func_extract_archives $gentop $convenience
+ reload_conv_objs="$reload_objs $func_extract_archives_result"
+ fi
+ fi
+
+ # Create the old-style object.
+ reload_objs="$objs$old_deplibs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}$'/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test
+
+ output="$obj"
+ cmds=$reload_cmds
+ save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ eval cmd=\"$cmd\"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+
+ # Exit if we aren't doing a library object file.
+ if test -z "$libobj"; then
+ if test -n "$gentop"; then
+ $show "${rm}r $gentop"
+ $run ${rm}r $gentop
+ fi
+
+ exit $EXIT_SUCCESS
+ fi
+
+ if test "$build_libtool_libs" != yes; then
+ if test -n "$gentop"; then
+ $show "${rm}r $gentop"
+ $run ${rm}r $gentop
+ fi
+
+ # Create an invalid libtool object if no PIC, so that we don't
+ # accidentally link it into a program.
+ # $show "echo timestamp > $libobj"
+ # $run eval "echo timestamp > $libobj" || exit $?
+ exit $EXIT_SUCCESS
+ fi
+
+ if test -n "$pic_flag" || test "$pic_mode" != default; then
+ # Only do commands if we really have different PIC objects.
+ reload_objs="$libobjs $reload_conv_objs"
+ output="$libobj"
+ cmds=$reload_cmds
+ save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ eval cmd=\"$cmd\"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+ fi
+
+ if test -n "$gentop"; then
+ $show "${rm}r $gentop"
+ $run ${rm}r $gentop
+ fi
+
+ exit $EXIT_SUCCESS
+ ;;
+
+ prog)
+ case $host in
+ *cygwin*) output=`$echo $output | ${SED} -e 's,.exe$,,;s,$,.exe,'` ;;
+ esac
+ if test -n "$vinfo"; then
+ $echo "$modename: warning: \`-version-info' is ignored for programs" 1>&2
+ fi
+
+ if test -n "$release"; then
+ $echo "$modename: warning: \`-release' is ignored for programs" 1>&2
+ fi
+
+ if test "$preload" = yes; then
+ if test "$dlopen_support" = unknown && test "$dlopen_self" = unknown &&
+ test "$dlopen_self_static" = unknown; then
+ $echo "$modename: warning: \`AC_LIBTOOL_DLOPEN' not used. Assuming no dlopen support."
+ fi
+ fi
+
+ case $host in
+ *-*-rhapsody* | *-*-darwin1.[012])
+ # On Rhapsody replace the C library is the System framework
+ compile_deplibs=`$echo "X $compile_deplibs" | $Xsed -e 's/ -lc / -framework System /'`
+ finalize_deplibs=`$echo "X $finalize_deplibs" | $Xsed -e 's/ -lc / -framework System /'`
+ ;;
+ esac
+
+ case $host in
+ *darwin*)
+ # Don't allow lazy linking, it breaks C++ global constructors
+ if test "$tagname" = CXX ; then
+ compile_command="$compile_command ${wl}-bind_at_load"
+ finalize_command="$finalize_command ${wl}-bind_at_load"
+ fi
+ ;;
+ esac
+
+
+ # move library search paths that coincide with paths to not yet
+ # installed libraries to the beginning of the library search list
+ new_libs=
+ for path in $notinst_path; do
+ case " $new_libs " in
+ *" -L$path/$objdir "*) ;;
+ *)
+ case " $compile_deplibs " in
+ *" -L$path/$objdir "*)
+ new_libs="$new_libs -L$path/$objdir" ;;
+ esac
+ ;;
+ esac
+ done
+ for deplib in $compile_deplibs; do
+ case $deplib in
+ -L*)
+ case " $new_libs " in
+ *" $deplib "*) ;;
+ *) new_libs="$new_libs $deplib" ;;
+ esac
+ ;;
+ *) new_libs="$new_libs $deplib" ;;
+ esac
+ done
+ compile_deplibs="$new_libs"
+
+
+ compile_command="$compile_command $compile_deplibs"
+ finalize_command="$finalize_command $finalize_deplibs"
+
+ if test -n "$rpath$xrpath"; then
+ # If the user specified any rpath flags, then add them.
+ for libdir in $rpath $xrpath; do
+ # This is the magic to use -rpath.
+ case "$finalize_rpath " in
+ *" $libdir "*) ;;
+ *) finalize_rpath="$finalize_rpath $libdir" ;;
+ esac
+ done
+ fi
+
+ # Now hardcode the library paths
+ rpath=
+ hardcode_libdirs=
+ for libdir in $compile_rpath $finalize_rpath; do
+ if test -n "$hardcode_libdir_flag_spec"; then
+ if test -n "$hardcode_libdir_separator"; then
+ if test -z "$hardcode_libdirs"; then
+ hardcode_libdirs="$libdir"
+ else
+ # Just accumulate the unique libdirs.
+ case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
+ *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
+ ;;
+ *)
+ hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
+ ;;
+ esac
+ fi
+ else
+ eval flag=\"$hardcode_libdir_flag_spec\"
+ rpath="$rpath $flag"
+ fi
+ elif test -n "$runpath_var"; then
+ case "$perm_rpath " in
+ *" $libdir "*) ;;
+ *) perm_rpath="$perm_rpath $libdir" ;;
+ esac
+ fi
+ case $host in
+ *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*)
+ testbindir=`$echo "X$libdir" | $Xsed -e 's*/lib$*/bin*'`
+ case :$dllsearchpath: in
+ *":$libdir:"*) ;;
+ *) dllsearchpath="$dllsearchpath:$libdir";;
+ esac
+ case :$dllsearchpath: in
+ *":$testbindir:"*) ;;
+ *) dllsearchpath="$dllsearchpath:$testbindir";;
+ esac
+ ;;
+ esac
+ done
+ # Substitute the hardcoded libdirs into the rpath.
+ if test -n "$hardcode_libdir_separator" &&
+ test -n "$hardcode_libdirs"; then
+ libdir="$hardcode_libdirs"
+ eval rpath=\" $hardcode_libdir_flag_spec\"
+ fi
+ compile_rpath="$rpath"
+
+ rpath=
+ hardcode_libdirs=
+ for libdir in $finalize_rpath; do
+ if test -n "$hardcode_libdir_flag_spec"; then
+ if test -n "$hardcode_libdir_separator"; then
+ if test -z "$hardcode_libdirs"; then
+ hardcode_libdirs="$libdir"
+ else
+ # Just accumulate the unique libdirs.
+ case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
+ *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
+ ;;
+ *)
+ hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
+ ;;
+ esac
+ fi
+ else
+ eval flag=\"$hardcode_libdir_flag_spec\"
+ rpath="$rpath $flag"
+ fi
+ elif test -n "$runpath_var"; then
+ case "$finalize_perm_rpath " in
+ *" $libdir "*) ;;
+ *) finalize_perm_rpath="$finalize_perm_rpath $libdir" ;;
+ esac
+ fi
+ done
+ # Substitute the hardcoded libdirs into the rpath.
+ if test -n "$hardcode_libdir_separator" &&
+ test -n "$hardcode_libdirs"; then
+ libdir="$hardcode_libdirs"
+ eval rpath=\" $hardcode_libdir_flag_spec\"
+ fi
+ finalize_rpath="$rpath"
+
+ if test -n "$libobjs" && test "$build_old_libs" = yes; then
+ # Transform all the library objects into standard objects.
+ compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
+ finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
+ fi
+
+ dlsyms=
+ if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
+ if test -n "$NM" && test -n "$global_symbol_pipe"; then
+ dlsyms="${outputname}S.c"
+ else
+ $echo "$modename: not configured to extract global symbols from dlpreopened files" 1>&2
+ fi
+ fi
+
+ if test -n "$dlsyms"; then
+ case $dlsyms in
+ "") ;;
+ *.c)
+ # Discover the nlist of each of the dlfiles.
+ nlist="$output_objdir/${outputname}.nm"
+
+ $show "$rm $nlist ${nlist}S ${nlist}T"
+ $run $rm "$nlist" "${nlist}S" "${nlist}T"
+
+ # Parse the name list into a source file.
+ $show "creating $output_objdir/$dlsyms"
+
+ test -z "$run" && $echo > "$output_objdir/$dlsyms" "\
+/* $dlsyms - symbol resolution table for \`$outputname' dlsym emulation. */
+/* Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP */
+
+#ifdef __cplusplus
+extern \"C\" {
+#endif
+
+/* Prevent the only kind of declaration conflicts we can make. */
+#define lt_preloaded_symbols some_other_symbol
+
+/* External symbol declarations for the compiler. */\
+"
+
+ if test "$dlself" = yes; then
+ $show "generating symbol list for \`$output'"
+
+ test -z "$run" && $echo ': @PROGRAM@ ' > "$nlist"
+
+ # Add our own program objects to the symbol list.
+ progfiles=`$echo "X$objs$old_deplibs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
+ for arg in $progfiles; do
+ $show "extracting global C symbols from \`$arg'"
+ $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'"
+ done
+
+ if test -n "$exclude_expsyms"; then
+ $run eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T'
+ $run eval '$mv "$nlist"T "$nlist"'
+ fi
+
+ if test -n "$export_symbols_regex"; then
+ $run eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T'
+ $run eval '$mv "$nlist"T "$nlist"'
+ fi
+
+ # Prepare the list of exported symbols
+ if test -z "$export_symbols"; then
+ export_symbols="$output_objdir/$outputname.exp"
+ $run $rm $export_symbols
+ $run eval "${SED} -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"'
+ case $host in
+ *cygwin* | *mingw* )
+ $run eval "echo EXPORTS "'> "$output_objdir/$outputname.def"'
+ $run eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"'
+ ;;
+ esac
+ else
+ $run eval "${SED} -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"'
+ $run eval 'grep -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T'
+ $run eval 'mv "$nlist"T "$nlist"'
+ case $host in
+ *cygwin* | *mingw* )
+ $run eval "echo EXPORTS "'> "$output_objdir/$outputname.def"'
+ $run eval 'cat "$nlist" >> "$output_objdir/$outputname.def"'
+ ;;
+ esac
+ fi
+ fi
+
+ for arg in $dlprefiles; do
+ $show "extracting global C symbols from \`$arg'"
+ name=`$echo "$arg" | ${SED} -e 's%^.*/%%'`
+ $run eval '$echo ": $name " >> "$nlist"'
+ $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'"
+ done
+
+ if test -z "$run"; then
+ # Make sure we have at least an empty file.
+ test -f "$nlist" || : > "$nlist"
+
+ if test -n "$exclude_expsyms"; then
+ $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T
+ $mv "$nlist"T "$nlist"
+ fi
+
+ # Try sorting and uniquifying the output.
+ if grep -v "^: " < "$nlist" |
+ if sort -k 3 </dev/null >/dev/null 2>&1; then
+ sort -k 3
+ else
+ sort +2
+ fi |
+ uniq > "$nlist"S; then
+ :
+ else
+ grep -v "^: " < "$nlist" > "$nlist"S
+ fi
+
+ if test -f "$nlist"S; then
+ eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$dlsyms"'
+ else
+ $echo '/* NONE */' >> "$output_objdir/$dlsyms"
+ fi
+
+ $echo >> "$output_objdir/$dlsyms" "\
+
+#undef lt_preloaded_symbols
+
+#if defined (__STDC__) && __STDC__
+# define lt_ptr void *
+#else
+# define lt_ptr char *
+# define const
+#endif
+
+/* The mapping between symbol names and symbols. */
+"
+
+ case $host in
+ *cygwin* | *mingw* )
+ $echo >> "$output_objdir/$dlsyms" "\
+/* DATA imports from DLLs on WIN32 can't be const, because
+ runtime relocations are performed -- see ld's documentation
+ on pseudo-relocs */
+struct {
+"
+ ;;
+ * )
+ $echo >> "$output_objdir/$dlsyms" "\
+const struct {
+"
+ ;;
+ esac
+
+
+ $echo >> "$output_objdir/$dlsyms" "\
+ const char *name;
+ lt_ptr address;
+}
+lt_preloaded_symbols[] =
+{\
+"
+
+ eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$dlsyms"
+
+ $echo >> "$output_objdir/$dlsyms" "\
+ {0, (lt_ptr) 0}
+};
+
+/* This works around a problem in FreeBSD linker */
+#ifdef FREEBSD_WORKAROUND
+static const void *lt_preloaded_setup() {
+ return lt_preloaded_symbols;
+}
+#endif
+
+#ifdef __cplusplus
+}
+#endif\
+"
+ fi
+
+ pic_flag_for_symtable=
+ case $host in
+ # compiling the symbol table file with pic_flag works around
+ # a FreeBSD bug that causes programs to crash when -lm is
+ # linked before any other PIC object. But we must not use
+ # pic_flag when linking with -static. The problem exists in
+ # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1.
+ *-*-freebsd2*|*-*-freebsd3.0*|*-*-freebsdelf3.0*)
+ case "$compile_command " in
+ *" -static "*) ;;
+ *) pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND";;
+ esac;;
+ *-*-hpux*)
+ case "$compile_command " in
+ *" -static "*) ;;
+ *) pic_flag_for_symtable=" $pic_flag";;
+ esac
+ esac
+
+ # Now compile the dynamic symbol file.
+ $show "(cd $output_objdir && $LTCC $LTCFLAGS -c$no_builtin_flag$pic_flag_for_symtable \"$dlsyms\")"
+ $run eval '(cd $output_objdir && $LTCC $LTCFLAGS -c$no_builtin_flag$pic_flag_for_symtable "$dlsyms")' || exit $?
+
+ # Clean up the generated files.
+ $show "$rm $output_objdir/$dlsyms $nlist ${nlist}S ${nlist}T"
+ $run $rm "$output_objdir/$dlsyms" "$nlist" "${nlist}S" "${nlist}T"
+
+ # Transform the symbol file into the correct name.
+ case $host in
+ *cygwin* | *mingw* )
+ if test -f "$output_objdir/${outputname}.def" ; then
+ compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}.def $output_objdir/${outputname}S.${objext}%"`
+ finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}.def $output_objdir/${outputname}S.${objext}%"`
+ else
+ compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"`
+ finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"`
+ fi
+ ;;
+ * )
+ compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"`
+ finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"`
+ ;;
+ esac
+ ;;
+ *)
+ $echo "$modename: unknown suffix for \`$dlsyms'" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+ esac
+ else
+ # We keep going just in case the user didn't refer to
+ # lt_preloaded_symbols. The linker will fail if global_symbol_pipe
+ # really was required.
+
+ # Nullify the symbol file.
+ compile_command=`$echo "X$compile_command" | $Xsed -e "s% @SYMFILE@%%"`
+ finalize_command=`$echo "X$finalize_command" | $Xsed -e "s% @SYMFILE@%%"`
+ fi
+
+ if test "$need_relink" = no || test "$build_libtool_libs" != yes; then
+ # Replace the output file specification.
+ compile_command=`$echo "X$compile_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'`
+ link_command="$compile_command$compile_rpath"
+
+ # We have no uninstalled library dependencies, so finalize right now.
+ $show "$link_command"
+ $run eval "$link_command"
+ exit_status=$?
+
+ # Delete the generated files.
+ if test -n "$dlsyms"; then
+ $show "$rm $output_objdir/${outputname}S.${objext}"
+ $run $rm "$output_objdir/${outputname}S.${objext}"
+ fi
+
+ exit $exit_status
+ fi
+
+ if test -n "$shlibpath_var"; then
+ # We should set the shlibpath_var
+ rpath=
+ for dir in $temp_rpath; do
+ case $dir in
+ [\\/]* | [A-Za-z]:[\\/]*)
+ # Absolute path.
+ rpath="$rpath$dir:"
+ ;;
+ *)
+ # Relative path: add a thisdir entry.
+ rpath="$rpath\$thisdir/$dir:"
+ ;;
+ esac
+ done
+ temp_rpath="$rpath"
+ fi
+
+ if test -n "$compile_shlibpath$finalize_shlibpath"; then
+ compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command"
+ fi
+ if test -n "$finalize_shlibpath"; then
+ finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command"
+ fi
+
+ compile_var=
+ finalize_var=
+ if test -n "$runpath_var"; then
+ if test -n "$perm_rpath"; then
+ # We should set the runpath_var.
+ rpath=
+ for dir in $perm_rpath; do
+ rpath="$rpath$dir:"
+ done
+ compile_var="$runpath_var=\"$rpath\$$runpath_var\" "
+ fi
+ if test -n "$finalize_perm_rpath"; then
+ # We should set the runpath_var.
+ rpath=
+ for dir in $finalize_perm_rpath; do
+ rpath="$rpath$dir:"
+ done
+ finalize_var="$runpath_var=\"$rpath\$$runpath_var\" "
+ fi
+ fi
+
+ if test "$no_install" = yes; then
+ # We don't need to create a wrapper script.
+ link_command="$compile_var$compile_command$compile_rpath"
+ # Replace the output file specification.
+ link_command=`$echo "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'`
+ # Delete the old output file.
+ $run $rm $output
+ # Link the executable and exit
+ $show "$link_command"
+ $run eval "$link_command" || exit $?
+ exit $EXIT_SUCCESS
+ fi
+
+ if test "$hardcode_action" = relink; then
+ # Fast installation is not supported
+ link_command="$compile_var$compile_command$compile_rpath"
+ relink_command="$finalize_var$finalize_command$finalize_rpath"
+
+ $echo "$modename: warning: this platform does not like uninstalled shared libraries" 1>&2
+ $echo "$modename: \`$output' will be relinked during installation" 1>&2
+ else
+ if test "$fast_install" != no; then
+ link_command="$finalize_var$compile_command$finalize_rpath"
+ if test "$fast_install" = yes; then
+ relink_command=`$echo "X$compile_var$compile_command$compile_rpath" | $Xsed -e 's%@OUTPUT@%\$progdir/\$file%g'`
+ else
+ # fast_install is set to needless
+ relink_command=
+ fi
+ else
+ link_command="$compile_var$compile_command$compile_rpath"
+ relink_command="$finalize_var$finalize_command$finalize_rpath"
+ fi
+ fi
+
+ # Replace the output file specification.
+ link_command=`$echo "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'`
+
+ # Delete the old output files.
+ $run $rm $output $output_objdir/$outputname $output_objdir/lt-$outputname
+
+ $show "$link_command"
+ $run eval "$link_command" || exit $?
+
+ # Now create the wrapper script.
+ $show "creating $output"
+
+ # Quote the relink command for shipping.
+ if test -n "$relink_command"; then
+ # Preserve any variables that may affect compiler behavior
+ for var in $variables_saved_for_relink; do
+ if eval test -z \"\${$var+set}\"; then
+ relink_command="{ test -z \"\${$var+set}\" || unset $var || { $var=; export $var; }; }; $relink_command"
+ elif eval var_value=\$$var; test -z "$var_value"; then
+ relink_command="$var=; export $var; $relink_command"
+ else
+ var_value=`$echo "X$var_value" | $Xsed -e "$sed_quote_subst"`
+ relink_command="$var=\"$var_value\"; export $var; $relink_command"
+ fi
+ done
+ relink_command="(cd `pwd`; $relink_command)"
+ relink_command=`$echo "X$relink_command" | $Xsed -e "$sed_quote_subst"`
+ fi
+
+ # Quote $echo for shipping.
+ if test "X$echo" = "X$SHELL $progpath --fallback-echo"; then
+ case $progpath in
+ [\\/]* | [A-Za-z]:[\\/]*) qecho="$SHELL $progpath --fallback-echo";;
+ *) qecho="$SHELL `pwd`/$progpath --fallback-echo";;
+ esac
+ qecho=`$echo "X$qecho" | $Xsed -e "$sed_quote_subst"`
+ else
+ qecho=`$echo "X$echo" | $Xsed -e "$sed_quote_subst"`
+ fi
+
+ # Only actually do things if our run command is non-null.
+ if test -z "$run"; then
+ # win32 will think the script is a binary if it has
+ # a .exe suffix, so we strip it off here.
+ case $output in
+ *.exe) output=`$echo $output|${SED} 's,.exe$,,'` ;;
+ esac
+ # test for cygwin because mv fails w/o .exe extensions
+ case $host in
+ *cygwin*)
+ exeext=.exe
+ outputname=`$echo $outputname|${SED} 's,.exe$,,'` ;;
+ *) exeext= ;;
+ esac
+ case $host in
+ *cygwin* | *mingw* )
+ output_name=`basename $output`
+ output_path=`dirname $output`
+ cwrappersource="$output_path/$objdir/lt-$output_name.c"
+ cwrapper="$output_path/$output_name.exe"
+ $rm $cwrappersource $cwrapper
+ trap "$rm $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15
+
+ cat > $cwrappersource <<EOF
+
+/* $cwrappersource - temporary wrapper executable for $objdir/$outputname
+ Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP
+
+ The $output program cannot be directly executed until all the libtool
+ libraries that it depends on are installed.
+
+ This wrapper executable should never be moved out of the build directory.
+ If it is, it will not operate correctly.
+
+ Currently, it simply execs the wrapper *script* "/bin/sh $output",
+ but could eventually absorb all of the scripts functionality and
+ exec $objdir/$outputname directly.
+*/
+EOF
+ cat >> $cwrappersource<<"EOF"
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <malloc.h>
+#include <stdarg.h>
+#include <assert.h>
+#include <string.h>
+#include <ctype.h>
+#include <sys/stat.h>
+
+#if defined(PATH_MAX)
+# define LT_PATHMAX PATH_MAX
+#elif defined(MAXPATHLEN)
+# define LT_PATHMAX MAXPATHLEN
+#else
+# define LT_PATHMAX 1024
+#endif
+
+#ifndef DIR_SEPARATOR
+# define DIR_SEPARATOR '/'
+# define PATH_SEPARATOR ':'
+#endif
+
+#if defined (_WIN32) || defined (__MSDOS__) || defined (__DJGPP__) || \
+ defined (__OS2__)
+# define HAVE_DOS_BASED_FILE_SYSTEM
+# ifndef DIR_SEPARATOR_2
+# define DIR_SEPARATOR_2 '\\'
+# endif
+# ifndef PATH_SEPARATOR_2
+# define PATH_SEPARATOR_2 ';'
+# endif
+#endif
+
+#ifndef DIR_SEPARATOR_2
+# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR)
+#else /* DIR_SEPARATOR_2 */
+# define IS_DIR_SEPARATOR(ch) \
+ (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2))
+#endif /* DIR_SEPARATOR_2 */
+
+#ifndef PATH_SEPARATOR_2
+# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR)
+#else /* PATH_SEPARATOR_2 */
+# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2)
+#endif /* PATH_SEPARATOR_2 */
+
+#define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type)))
+#define XFREE(stale) do { \
+ if (stale) { free ((void *) stale); stale = 0; } \
+} while (0)
+
+/* -DDEBUG is fairly common in CFLAGS. */
+#undef DEBUG
+#if defined DEBUGWRAPPER
+# define DEBUG(format, ...) fprintf(stderr, format, __VA_ARGS__)
+#else
+# define DEBUG(format, ...)
+#endif
+
+const char *program_name = NULL;
+
+void * xmalloc (size_t num);
+char * xstrdup (const char *string);
+const char * base_name (const char *name);
+char * find_executable(const char *wrapper);
+int check_executable(const char *path);
+char * strendzap(char *str, const char *pat);
+void lt_fatal (const char *message, ...);
+
+int
+main (int argc, char *argv[])
+{
+ char **newargz;
+ int i;
+
+ program_name = (char *) xstrdup (base_name (argv[0]));
+ DEBUG("(main) argv[0] : %s\n",argv[0]);
+ DEBUG("(main) program_name : %s\n",program_name);
+ newargz = XMALLOC(char *, argc+2);
+EOF
+
+ cat >> $cwrappersource <<EOF
+ newargz[0] = (char *) xstrdup("$SHELL");
+EOF
+
+ cat >> $cwrappersource <<"EOF"
+ newargz[1] = find_executable(argv[0]);
+ if (newargz[1] == NULL)
+ lt_fatal("Couldn't find %s", argv[0]);
+ DEBUG("(main) found exe at : %s\n",newargz[1]);
+ /* we know the script has the same name, without the .exe */
+ /* so make sure newargz[1] doesn't end in .exe */
+ strendzap(newargz[1],".exe");
+ for (i = 1; i < argc; i++)
+ newargz[i+1] = xstrdup(argv[i]);
+ newargz[argc+1] = NULL;
+
+ for (i=0; i<argc+1; i++)
+ {
+ DEBUG("(main) newargz[%d] : %s\n",i,newargz[i]);
+ ;
+ }
+
+EOF
+
+ case $host_os in
+ mingw*)
+ cat >> $cwrappersource <<EOF
+ execv("$SHELL",(char const **)newargz);
+EOF
+ ;;
+ *)
+ cat >> $cwrappersource <<EOF
+ execv("$SHELL",newargz);
+EOF
+ ;;
+ esac
+
+ cat >> $cwrappersource <<"EOF"
+ return 127;
+}
+
+void *
+xmalloc (size_t num)
+{
+ void * p = (void *) malloc (num);
+ if (!p)
+ lt_fatal ("Memory exhausted");
+
+ return p;
+}
+
+char *
+xstrdup (const char *string)
+{
+ return string ? strcpy ((char *) xmalloc (strlen (string) + 1), string) : NULL
+;
+}
+
+const char *
+base_name (const char *name)
+{
+ const char *base;
+
+#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
+ /* Skip over the disk name in MSDOS pathnames. */
+ if (isalpha ((unsigned char)name[0]) && name[1] == ':')
+ name += 2;
+#endif
+
+ for (base = name; *name; name++)
+ if (IS_DIR_SEPARATOR (*name))
+ base = name + 1;
+ return base;
+}
+
+int
+check_executable(const char * path)
+{
+ struct stat st;
+
+ DEBUG("(check_executable) : %s\n", path ? (*path ? path : "EMPTY!") : "NULL!");
+ if ((!path) || (!*path))
+ return 0;
+
+ if ((stat (path, &st) >= 0) &&
+ (
+ /* MinGW & native WIN32 do not support S_IXOTH or S_IXGRP */
+#if defined (S_IXOTH)
+ ((st.st_mode & S_IXOTH) == S_IXOTH) ||
+#endif
+#if defined (S_IXGRP)
+ ((st.st_mode & S_IXGRP) == S_IXGRP) ||
+#endif
+ ((st.st_mode & S_IXUSR) == S_IXUSR))
+ )
+ return 1;
+ else
+ return 0;
+}
+
+/* Searches for the full path of the wrapper. Returns
+ newly allocated full path name if found, NULL otherwise */
+char *
+find_executable (const char* wrapper)
+{
+ int has_slash = 0;
+ const char* p;
+ const char* p_next;
+ /* static buffer for getcwd */
+ char tmp[LT_PATHMAX + 1];
+ int tmp_len;
+ char* concat_name;
+
+ DEBUG("(find_executable) : %s\n", wrapper ? (*wrapper ? wrapper : "EMPTY!") : "NULL!");
+
+ if ((wrapper == NULL) || (*wrapper == '\0'))
+ return NULL;
+
+ /* Absolute path? */
+#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
+ if (isalpha ((unsigned char)wrapper[0]) && wrapper[1] == ':')
+ {
+ concat_name = xstrdup (wrapper);
+ if (check_executable(concat_name))
+ return concat_name;
+ XFREE(concat_name);
+ }
+ else
+ {
+#endif
+ if (IS_DIR_SEPARATOR (wrapper[0]))
+ {
+ concat_name = xstrdup (wrapper);
+ if (check_executable(concat_name))
+ return concat_name;
+ XFREE(concat_name);
+ }
+#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
+ }
+#endif
+
+ for (p = wrapper; *p; p++)
+ if (*p == '/')
+ {
+ has_slash = 1;
+ break;
+ }
+ if (!has_slash)
+ {
+ /* no slashes; search PATH */
+ const char* path = getenv ("PATH");
+ if (path != NULL)
+ {
+ for (p = path; *p; p = p_next)
+ {
+ const char* q;
+ size_t p_len;
+ for (q = p; *q; q++)
+ if (IS_PATH_SEPARATOR(*q))
+ break;
+ p_len = q - p;
+ p_next = (*q == '\0' ? q : q + 1);
+ if (p_len == 0)
+ {
+ /* empty path: current directory */
+ if (getcwd (tmp, LT_PATHMAX) == NULL)
+ lt_fatal ("getcwd failed");
+ tmp_len = strlen(tmp);
+ concat_name = XMALLOC(char, tmp_len + 1 + strlen(wrapper) + 1);
+ memcpy (concat_name, tmp, tmp_len);
+ concat_name[tmp_len] = '/';
+ strcpy (concat_name + tmp_len + 1, wrapper);
+ }
+ else
+ {
+ concat_name = XMALLOC(char, p_len + 1 + strlen(wrapper) + 1);
+ memcpy (concat_name, p, p_len);
+ concat_name[p_len] = '/';
+ strcpy (concat_name + p_len + 1, wrapper);
+ }
+ if (check_executable(concat_name))
+ return concat_name;
+ XFREE(concat_name);
+ }
+ }
+ /* not found in PATH; assume curdir */
+ }
+ /* Relative path | not found in path: prepend cwd */
+ if (getcwd (tmp, LT_PATHMAX) == NULL)
+ lt_fatal ("getcwd failed");
+ tmp_len = strlen(tmp);
+ concat_name = XMALLOC(char, tmp_len + 1 + strlen(wrapper) + 1);
+ memcpy (concat_name, tmp, tmp_len);
+ concat_name[tmp_len] = '/';
+ strcpy (concat_name + tmp_len + 1, wrapper);
+
+ if (check_executable(concat_name))
+ return concat_name;
+ XFREE(concat_name);
+ return NULL;
+}
+
+char *
+strendzap(char *str, const char *pat)
+{
+ size_t len, patlen;
+
+ assert(str != NULL);
+ assert(pat != NULL);
+
+ len = strlen(str);
+ patlen = strlen(pat);
+
+ if (patlen <= len)
+ {
+ str += len - patlen;
+ if (strcmp(str, pat) == 0)
+ *str = '\0';
+ }
+ return str;
+}
+
+static void
+lt_error_core (int exit_status, const char * mode,
+ const char * message, va_list ap)
+{
+ fprintf (stderr, "%s: %s: ", program_name, mode);
+ vfprintf (stderr, message, ap);
+ fprintf (stderr, ".\n");
+
+ if (exit_status >= 0)
+ exit (exit_status);
+}
+
+void
+lt_fatal (const char *message, ...)
+{
+ va_list ap;
+ va_start (ap, message);
+ lt_error_core (EXIT_FAILURE, "FATAL", message, ap);
+ va_end (ap);
+}
+EOF
+ # we should really use a build-platform specific compiler
+ # here, but OTOH, the wrappers (shell script and this C one)
+ # are only useful if you want to execute the "real" binary.
+ # Since the "real" binary is built for $host, then this
+ # wrapper might as well be built for $host, too.
+ $run $LTCC $LTCFLAGS -s -o $cwrapper $cwrappersource
+ ;;
+ esac
+ $rm $output
+ trap "$rm $output; exit $EXIT_FAILURE" 1 2 15
+
+ $echo > $output "\
+#! $SHELL
+
+# $output - temporary wrapper script for $objdir/$outputname
+# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP
+#
+# The $output program cannot be directly executed until all the libtool
+# libraries that it depends on are installed.
+#
+# This wrapper script should never be moved out of the build directory.
+# If it is, it will not operate correctly.
+
+# Sed substitution that helps us do robust quoting. It backslashifies
+# metacharacters that are still active within double-quoted strings.
+Xsed='${SED} -e 1s/^X//'
+sed_quote_subst='$sed_quote_subst'
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+relink_command=\"$relink_command\"
+
+# This environment variable determines our operation mode.
+if test \"\$libtool_install_magic\" = \"$magic\"; then
+ # install mode needs the following variable:
+ notinst_deplibs='$notinst_deplibs'
+else
+ # When we are sourced in execute mode, \$file and \$echo are already set.
+ if test \"\$libtool_execute_magic\" != \"$magic\"; then
+ echo=\"$qecho\"
+ file=\"\$0\"
+ # Make sure echo works.
+ if test \"X\$1\" = X--no-reexec; then
+ # Discard the --no-reexec flag, and continue.
+ shift
+ elif test \"X\`(\$echo '\t') 2>/dev/null\`\" = 'X\t'; then
+ # Yippee, \$echo works!
+ :
+ else
+ # Restart under the correct shell, and then maybe \$echo will work.
+ exec $SHELL \"\$0\" --no-reexec \${1+\"\$@\"}
+ fi
+ fi\
+"
+ $echo >> $output "\
+
+ # Find the directory that this script lives in.
+ thisdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*$%%'\`
+ test \"x\$thisdir\" = \"x\$file\" && thisdir=.
+
+ # Follow symbolic links until we get to the real thisdir.
+ file=\`ls -ld \"\$file\" | ${SED} -n 's/.*-> //p'\`
+ while test -n \"\$file\"; do
+ destdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*\$%%'\`
+
+ # If there was a directory component, then change thisdir.
+ if test \"x\$destdir\" != \"x\$file\"; then
+ case \"\$destdir\" in
+ [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;;
+ *) thisdir=\"\$thisdir/\$destdir\" ;;
+ esac
+ fi
+
+ file=\`\$echo \"X\$file\" | \$Xsed -e 's%^.*/%%'\`
+ file=\`ls -ld \"\$thisdir/\$file\" | ${SED} -n 's/.*-> //p'\`
+ done
+
+ # Try to get the absolute directory name.
+ absdir=\`cd \"\$thisdir\" && pwd\`
+ test -n \"\$absdir\" && thisdir=\"\$absdir\"
+"
+
+ if test "$fast_install" = yes; then
+ $echo >> $output "\
+ program=lt-'$outputname'$exeext
+ progdir=\"\$thisdir/$objdir\"
+
+ if test ! -f \"\$progdir/\$program\" || \\
+ { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | ${SED} 1q\`; \\
+ test \"X\$file\" != \"X\$progdir/\$program\"; }; then
+
+ file=\"\$\$-\$program\"
+
+ if test ! -d \"\$progdir\"; then
+ $mkdir \"\$progdir\"
+ else
+ $rm \"\$progdir/\$file\"
+ fi"
+
+ $echo >> $output "\
+
+ # relink executable if necessary
+ if test -n \"\$relink_command\"; then
+ if relink_command_output=\`eval \$relink_command 2>&1\`; then :
+ else
+ $echo \"\$relink_command_output\" >&2
+ $rm \"\$progdir/\$file\"
+ exit $EXIT_FAILURE
+ fi
+ fi
+
+ $mv \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null ||
+ { $rm \"\$progdir/\$program\";
+ $mv \"\$progdir/\$file\" \"\$progdir/\$program\"; }
+ $rm \"\$progdir/\$file\"
+ fi"
+ else
+ $echo >> $output "\
+ program='$outputname'
+ progdir=\"\$thisdir/$objdir\"
+"
+ fi
+
+ $echo >> $output "\
+
+ if test -f \"\$progdir/\$program\"; then"
+
+ # Export our shlibpath_var if we have one.
+ if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then
+ $echo >> $output "\
+ # Add our own library path to $shlibpath_var
+ $shlibpath_var=\"$temp_rpath\$$shlibpath_var\"
+
+ # Some systems cannot cope with colon-terminated $shlibpath_var
+ # The second colon is a workaround for a bug in BeOS R4 sed
+ $shlibpath_var=\`\$echo \"X\$$shlibpath_var\" | \$Xsed -e 's/::*\$//'\`
+
+ export $shlibpath_var
+"
+ fi
+
+ # fixup the dll searchpath if we need to.
+ if test -n "$dllsearchpath"; then
+ $echo >> $output "\
+ # Add the dll search path components to the executable PATH
+ PATH=$dllsearchpath:\$PATH
+"
+ fi
+
+ $echo >> $output "\
+ if test \"\$libtool_execute_magic\" != \"$magic\"; then
+ # Run the actual program with our arguments.
+"
+ case $host in
+ # Backslashes separate directories on plain windows
+ *-*-mingw | *-*-os2*)
+ $echo >> $output "\
+ exec \"\$progdir\\\\\$program\" \${1+\"\$@\"}
+"
+ ;;
+
+ *)
+ $echo >> $output "\
+ exec \"\$progdir/\$program\" \${1+\"\$@\"}
+"
+ ;;
+ esac
+ $echo >> $output "\
+ \$echo \"\$0: cannot exec \$program \${1+\"\$@\"}\"
+ exit $EXIT_FAILURE
+ fi
+ else
+ # The program doesn't exist.
+ \$echo \"\$0: error: \\\`\$progdir/\$program' does not exist\" 1>&2
+ \$echo \"This script is just a wrapper for \$program.\" 1>&2
+ $echo \"See the $PACKAGE documentation for more information.\" 1>&2
+ exit $EXIT_FAILURE
+ fi
+fi\
+"
+ chmod +x $output
+ fi
+ exit $EXIT_SUCCESS
+ ;;
+ esac
+
+ # See if we need to build an old-fashioned archive.
+ for oldlib in $oldlibs; do
+
+ if test "$build_libtool_libs" = convenience; then
+ oldobjs="$libobjs_save"
+ addlibs="$convenience"
+ build_libtool_libs=no
+ else
+ if test "$build_libtool_libs" = module; then
+ oldobjs="$libobjs_save"
+ build_libtool_libs=no
+ else
+ oldobjs="$old_deplibs $non_pic_objects"
+ fi
+ addlibs="$old_convenience"
+ fi
+
+ if test -n "$addlibs"; then
+ gentop="$output_objdir/${outputname}x"
+ generated="$generated $gentop"
+
+ func_extract_archives $gentop $addlibs
+ oldobjs="$oldobjs $func_extract_archives_result"
+ fi
+
+ # Do each command in the archive commands.
+ if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then
+ cmds=$old_archive_from_new_cmds
+ else
+ # POSIX demands no paths to be encoded in archives. We have
+ # to avoid creating archives with duplicate basenames if we
+ # might have to extract them afterwards, e.g., when creating a
+ # static archive out of a convenience library, or when linking
+ # the entirety of a libtool archive into another (currently
+ # not supported by libtool).
+ if (for obj in $oldobjs
+ do
+ $echo "X$obj" | $Xsed -e 's%^.*/%%'
+ done | sort | sort -uc >/dev/null 2>&1); then
+ :
+ else
+ $echo "copying selected object files to avoid basename conflicts..."
+
+ if test -z "$gentop"; then
+ gentop="$output_objdir/${outputname}x"
+ generated="$generated $gentop"
+
+ $show "${rm}r $gentop"
+ $run ${rm}r "$gentop"
+ $show "$mkdir $gentop"
+ $run $mkdir "$gentop"
+ exit_status=$?
+ if test "$exit_status" -ne 0 && test ! -d "$gentop"; then
+ exit $exit_status
+ fi
+ fi
+
+ save_oldobjs=$oldobjs
+ oldobjs=
+ counter=1
+ for obj in $save_oldobjs
+ do
+ objbase=`$echo "X$obj" | $Xsed -e 's%^.*/%%'`
+ case " $oldobjs " in
+ " ") oldobjs=$obj ;;
+ *[\ /]"$objbase "*)
+ while :; do
+ # Make sure we don't pick an alternate name that also
+ # overlaps.
+ newobj=lt$counter-$objbase
+ counter=`expr $counter + 1`
+ case " $oldobjs " in
+ *[\ /]"$newobj "*) ;;
+ *) if test ! -f "$gentop/$newobj"; then break; fi ;;
+ esac
+ done
+ $show "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj"
+ $run ln "$obj" "$gentop/$newobj" ||
+ $run cp "$obj" "$gentop/$newobj"
+ oldobjs="$oldobjs $gentop/$newobj"
+ ;;
+ *) oldobjs="$oldobjs $obj" ;;
+ esac
+ done
+ fi
+
+ eval cmds=\"$old_archive_cmds\"
+
+ if len=`expr "X$cmds" : ".*"` &&
+ test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then
+ cmds=$old_archive_cmds
+ else
+ # the command line is too long to link in one step, link in parts
+ $echo "using piecewise archive linking..."
+ save_RANLIB=$RANLIB
+ RANLIB=:
+ objlist=
+ concat_cmds=
+ save_oldobjs=$oldobjs
+
+ # Is there a better way of finding the last object in the list?
+ for obj in $save_oldobjs
+ do
+ last_oldobj=$obj
+ done
+ for obj in $save_oldobjs
+ do
+ oldobjs="$objlist $obj"
+ objlist="$objlist $obj"
+ eval test_cmds=\"$old_archive_cmds\"
+ if len=`expr "X$test_cmds" : ".*" 2>/dev/null` &&
+ test "$len" -le "$max_cmd_len"; then
+ :
+ else
+ # the above command should be used before it gets too long
+ oldobjs=$objlist
+ if test "$obj" = "$last_oldobj" ; then
+ RANLIB=$save_RANLIB
+ fi
+ test -z "$concat_cmds" || concat_cmds=$concat_cmds~
+ eval concat_cmds=\"\${concat_cmds}$old_archive_cmds\"
+ objlist=
+ fi
+ done
+ RANLIB=$save_RANLIB
+ oldobjs=$objlist
+ if test "X$oldobjs" = "X" ; then
+ eval cmds=\"\$concat_cmds\"
+ else
+ eval cmds=\"\$concat_cmds~\$old_archive_cmds\"
+ fi
+ fi
+ fi
+ save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ eval cmd=\"$cmd\"
+ IFS="$save_ifs"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+ done
+
+ if test -n "$generated"; then
+ $show "${rm}r$generated"
+ $run ${rm}r$generated
+ fi
+
+ # Now create the libtool archive.
+ case $output in
+ *.la)
+ old_library=
+ test "$build_old_libs" = yes && old_library="$libname.$libext"
+ $show "creating $output"
+
+ # Preserve any variables that may affect compiler behavior
+ for var in $variables_saved_for_relink; do
+ if eval test -z \"\${$var+set}\"; then
+ relink_command="{ test -z \"\${$var+set}\" || unset $var || { $var=; export $var; }; }; $relink_command"
+ elif eval var_value=\$$var; test -z "$var_value"; then
+ relink_command="$var=; export $var; $relink_command"
+ else
+ var_value=`$echo "X$var_value" | $Xsed -e "$sed_quote_subst"`
+ relink_command="$var=\"$var_value\"; export $var; $relink_command"
+ fi
+ done
+ # Quote the link command for shipping.
+ relink_command="(cd `pwd`; $SHELL $progpath $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)"
+ relink_command=`$echo "X$relink_command" | $Xsed -e "$sed_quote_subst"`
+ if test "$hardcode_automatic" = yes ; then
+ relink_command=
+ fi
+
+
+ # Only create the output if not a dry run.
+ if test -z "$run"; then
+ for installed in no yes; do
+ if test "$installed" = yes; then
+ if test -z "$install_libdir"; then
+ break
+ fi
+ output="$output_objdir/$outputname"i
+ # Replace all uninstalled libtool libraries with the installed ones
+ newdependency_libs=
+ for deplib in $dependency_libs; do
+ case $deplib in
+ *.la)
+ name=`$echo "X$deplib" | $Xsed -e 's%^.*/%%'`
+ eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib`
+ if test -z "$libdir"; then
+ $echo "$modename: \`$deplib' is not a valid libtool archive" 1>&2
+ exit $EXIT_FAILURE
+ fi
+ newdependency_libs="$newdependency_libs $libdir/$name"
+ ;;
+ *) newdependency_libs="$newdependency_libs $deplib" ;;
+ esac
+ done
+ dependency_libs="$newdependency_libs"
+ newdlfiles=
+ for lib in $dlfiles; do
+ name=`$echo "X$lib" | $Xsed -e 's%^.*/%%'`
+ eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib`
+ if test -z "$libdir"; then
+ $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2
+ exit $EXIT_FAILURE
+ fi
+ newdlfiles="$newdlfiles $libdir/$name"
+ done
+ dlfiles="$newdlfiles"
+ newdlprefiles=
+ for lib in $dlprefiles; do
+ name=`$echo "X$lib" | $Xsed -e 's%^.*/%%'`
+ eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib`
+ if test -z "$libdir"; then
+ $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2
+ exit $EXIT_FAILURE
+ fi
+ newdlprefiles="$newdlprefiles $libdir/$name"
+ done
+ dlprefiles="$newdlprefiles"
+ else
+ newdlfiles=
+ for lib in $dlfiles; do
+ case $lib in
+ [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;;
+ *) abs=`pwd`"/$lib" ;;
+ esac
+ newdlfiles="$newdlfiles $abs"
+ done
+ dlfiles="$newdlfiles"
+ newdlprefiles=
+ for lib in $dlprefiles; do
+ case $lib in
+ [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;;
+ *) abs=`pwd`"/$lib" ;;
+ esac
+ newdlprefiles="$newdlprefiles $abs"
+ done
+ dlprefiles="$newdlprefiles"
+ fi
+ $rm $output
+ # place dlname in correct position for cygwin
+ tdlname=$dlname
+ case $host,$output,$installed,$module,$dlname in
+ *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll) tdlname=../bin/$dlname ;;
+ esac
+ $echo > $output "\
+# $outputname - a libtool library file
+# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP
+#
+# Please DO NOT delete this file!
+# It is necessary for linking the library.
+
+# The name that we can dlopen(3).
+dlname='$tdlname'
+
+# Names of this library.
+library_names='$library_names'
+
+# The name of the static archive.
+old_library='$old_library'
+
+# Libraries that this one depends upon.
+dependency_libs='$dependency_libs'
+
+# Version information for $libname.
+current=$current
+age=$age
+revision=$revision
+
+# Is this an already installed library?
+installed=$installed
+
+# Should we warn about portability when linking against -modules?
+shouldnotlink=$module
+
+# Files to dlopen/dlpreopen
+dlopen='$dlfiles'
+dlpreopen='$dlprefiles'
+
+# Directory that this library needs to be installed in:
+libdir='$install_libdir'"
+ if test "$installed" = no && test "$need_relink" = yes; then
+ $echo >> $output "\
+relink_command=\"$relink_command\""
+ fi
+ done
+ fi
+
+ # Do a symbolic link so that the libtool archive can be found in
+ # LD_LIBRARY_PATH before the program is installed.
+ $show "(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)"
+ $run eval '(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)' || exit $?
+ ;;
+ esac
+ exit $EXIT_SUCCESS
+ ;;
+
+ # libtool install mode
+ install)
+ modename="$modename: install"
+
+ # There may be an optional sh(1) argument at the beginning of
+ # install_prog (especially on Windows NT).
+ if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh ||
+ # Allow the use of GNU shtool's install command.
+ $echo "X$nonopt" | grep shtool > /dev/null; then
+ # Aesthetically quote it.
+ arg=`$echo "X$nonopt" | $Xsed -e "$sed_quote_subst"`
+ case $arg in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ arg="\"$arg\""
+ ;;
+ esac
+ install_prog="$arg "
+ arg="$1"
+ shift
+ else
+ install_prog=
+ arg=$nonopt
+ fi
+
+ # The real first argument should be the name of the installation program.
+ # Aesthetically quote it.
+ arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
+ case $arg in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ arg="\"$arg\""
+ ;;
+ esac
+ install_prog="$install_prog$arg"
+
+ # We need to accept at least all the BSD install flags.
+ dest=
+ files=
+ opts=
+ prev=
+ install_type=
+ isdir=no
+ stripme=
+ for arg
+ do
+ if test -n "$dest"; then
+ files="$files $dest"
+ dest=$arg
+ continue
+ fi
+
+ case $arg in
+ -d) isdir=yes ;;
+ -f)
+ case " $install_prog " in
+ *[\\\ /]cp\ *) ;;
+ *) prev=$arg ;;
+ esac
+ ;;
+ -g | -m | -o) prev=$arg ;;
+ -s)
+ stripme=" -s"
+ continue
+ ;;
+ -*)
+ ;;
+ *)
+ # If the previous option needed an argument, then skip it.
+ if test -n "$prev"; then
+ prev=
+ else
+ dest=$arg
+ continue
+ fi
+ ;;
+ esac
+
+ # Aesthetically quote the argument.
+ arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
+ case $arg in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ arg="\"$arg\""
+ ;;
+ esac
+ install_prog="$install_prog $arg"
+ done
+
+ if test -z "$install_prog"; then
+ $echo "$modename: you must specify an install program" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ if test -n "$prev"; then
+ $echo "$modename: the \`$prev' option requires an argument" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ if test -z "$files"; then
+ if test -z "$dest"; then
+ $echo "$modename: no file or destination specified" 1>&2
+ else
+ $echo "$modename: you must specify a destination" 1>&2
+ fi
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ # Strip any trailing slash from the destination.
+ dest=`$echo "X$dest" | $Xsed -e 's%/$%%'`
+
+ # Check to see that the destination is a directory.
+ test -d "$dest" && isdir=yes
+ if test "$isdir" = yes; then
+ destdir="$dest"
+ destname=
+ else
+ destdir=`$echo "X$dest" | $Xsed -e 's%/[^/]*$%%'`
+ test "X$destdir" = "X$dest" && destdir=.
+ destname=`$echo "X$dest" | $Xsed -e 's%^.*/%%'`
+
+ # Not a directory, so check to see that there is only one file specified.
+ set dummy $files
+ if test "$#" -gt 2; then
+ $echo "$modename: \`$dest' is not a directory" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ fi
+ fi
+ case $destdir in
+ [\\/]* | [A-Za-z]:[\\/]*) ;;
+ *)
+ for file in $files; do
+ case $file in
+ *.lo) ;;
+ *)
+ $echo "$modename: \`$destdir' must be an absolute directory name" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+ esac
+ done
+ ;;
+ esac
+
+ # This variable tells wrapper scripts just to set variables rather
+ # than running their programs.
+ libtool_install_magic="$magic"
+
+ staticlibs=
+ future_libdirs=
+ current_libdirs=
+ for file in $files; do
+
+ # Do each installation.
+ case $file in
+ *.$libext)
+ # Do the static libraries later.
+ staticlibs="$staticlibs $file"
+ ;;
+
+ *.la)
+ # Check to see that this really is a libtool archive.
+ if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then :
+ else
+ $echo "$modename: \`$file' is not a valid libtool archive" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ library_names=
+ old_library=
+ relink_command=
+ # If there is no directory component, then add one.
+ case $file in
+ */* | *\\*) . $file ;;
+ *) . ./$file ;;
+ esac
+
+ # Add the libdir to current_libdirs if it is the destination.
+ if test "X$destdir" = "X$libdir"; then
+ case "$current_libdirs " in
+ *" $libdir "*) ;;
+ *) current_libdirs="$current_libdirs $libdir" ;;
+ esac
+ else
+ # Note the libdir as a future libdir.
+ case "$future_libdirs " in
+ *" $libdir "*) ;;
+ *) future_libdirs="$future_libdirs $libdir" ;;
+ esac
+ fi
+
+ dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`/
+ test "X$dir" = "X$file/" && dir=
+ dir="$dir$objdir"
+
+ if test -n "$relink_command"; then
+ # Determine the prefix the user has applied to our future dir.
+ inst_prefix_dir=`$echo "$destdir" | $SED "s%$libdir\$%%"`
+
+ # Don't allow the user to place us outside of our expected
+ # location b/c this prevents finding dependent libraries that
+ # are installed to the same prefix.
+ # At present, this check doesn't affect windows .dll's that
+ # are installed into $libdir/../bin (currently, that works fine)
+ # but it's something to keep an eye on.
+ if test "$inst_prefix_dir" = "$destdir"; then
+ $echo "$modename: error: cannot install \`$file' to a directory not ending in $libdir" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ if test -n "$inst_prefix_dir"; then
+ # Stick the inst_prefix_dir data into the link command.
+ relink_command=`$echo "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"`
+ else
+ relink_command=`$echo "$relink_command" | $SED "s%@inst_prefix_dir@%%"`
+ fi
+
+ $echo "$modename: warning: relinking \`$file'" 1>&2
+ $show "$relink_command"
+ if $run eval "$relink_command"; then :
+ else
+ $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2
+ exit $EXIT_FAILURE
+ fi
+ fi
+
+ # See the names of the shared library.
+ set dummy $library_names
+ if test -n "$2"; then
+ realname="$2"
+ shift
+ shift
+
+ srcname="$realname"
+ test -n "$relink_command" && srcname="$realname"T
+
+ # Install the shared library and build the symlinks.
+ $show "$install_prog $dir/$srcname $destdir/$realname"
+ $run eval "$install_prog $dir/$srcname $destdir/$realname" || exit $?
+ if test -n "$stripme" && test -n "$striplib"; then
+ $show "$striplib $destdir/$realname"
+ $run eval "$striplib $destdir/$realname" || exit $?
+ fi
+
+ if test "$#" -gt 0; then
+ # Delete the old symlinks, and create new ones.
+ # Try `ln -sf' first, because the `ln' binary might depend on
+ # the symlink we replace! Solaris /bin/ln does not understand -f,
+ # so we also need to try rm && ln -s.
+ for linkname
+ do
+ if test "$linkname" != "$realname"; then
+ $show "(cd $destdir && { $LN_S -f $realname $linkname || { $rm $linkname && $LN_S $realname $linkname; }; })"
+ $run eval "(cd $destdir && { $LN_S -f $realname $linkname || { $rm $linkname && $LN_S $realname $linkname; }; })"
+ fi
+ done
+ fi
+
+ # Do each command in the postinstall commands.
+ lib="$destdir/$realname"
+ cmds=$postinstall_cmds
+ save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ eval cmd=\"$cmd\"
+ $show "$cmd"
+ $run eval "$cmd" || {
+ lt_exit=$?
+
+ # Restore the uninstalled library and exit
+ if test "$mode" = relink; then
+ $run eval '(cd $output_objdir && $rm ${realname}T && $mv ${realname}U $realname)'
+ fi
+
+ exit $lt_exit
+ }
+ done
+ IFS="$save_ifs"
+ fi
+
+ # Install the pseudo-library for information purposes.
+ name=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
+ instname="$dir/$name"i
+ $show "$install_prog $instname $destdir/$name"
+ $run eval "$install_prog $instname $destdir/$name" || exit $?
+
+ # Maybe install the static library, too.
+ test -n "$old_library" && staticlibs="$staticlibs $dir/$old_library"
+ ;;
+
+ *.lo)
+ # Install (i.e. copy) a libtool object.
+
+ # Figure out destination file name, if it wasn't already specified.
+ if test -n "$destname"; then
+ destfile="$destdir/$destname"
+ else
+ destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
+ destfile="$destdir/$destfile"
+ fi
+
+ # Deduce the name of the destination old-style object file.
+ case $destfile in
+ *.lo)
+ staticdest=`$echo "X$destfile" | $Xsed -e "$lo2o"`
+ ;;
+ *.$objext)
+ staticdest="$destfile"
+ destfile=
+ ;;
+ *)
+ $echo "$modename: cannot copy a libtool object to \`$destfile'" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+ esac
+
+ # Install the libtool object if requested.
+ if test -n "$destfile"; then
+ $show "$install_prog $file $destfile"
+ $run eval "$install_prog $file $destfile" || exit $?
+ fi
+
+ # Install the old object if enabled.
+ if test "$build_old_libs" = yes; then
+ # Deduce the name of the old-style object file.
+ staticobj=`$echo "X$file" | $Xsed -e "$lo2o"`
+
+ $show "$install_prog $staticobj $staticdest"
+ $run eval "$install_prog \$staticobj \$staticdest" || exit $?
+ fi
+ exit $EXIT_SUCCESS
+ ;;
+
+ *)
+ # Figure out destination file name, if it wasn't already specified.
+ if test -n "$destname"; then
+ destfile="$destdir/$destname"
+ else
+ destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
+ destfile="$destdir/$destfile"
+ fi
+
+ # If the file is missing, and there is a .exe on the end, strip it
+ # because it is most likely a libtool script we actually want to
+ # install
+ stripped_ext=""
+ case $file in
+ *.exe)
+ if test ! -f "$file"; then
+ file=`$echo $file|${SED} 's,.exe$,,'`
+ stripped_ext=".exe"
+ fi
+ ;;
+ esac
+
+ # Do a test to see if this is really a libtool program.
+ case $host in
+ *cygwin*|*mingw*)
+ wrapper=`$echo $file | ${SED} -e 's,.exe$,,'`
+ ;;
+ *)
+ wrapper=$file
+ ;;
+ esac
+ if (${SED} -e '4q' $wrapper | grep "^# Generated by .*$PACKAGE")>/dev/null 2>&1; then
+ notinst_deplibs=
+ relink_command=
+
+ # Note that it is not necessary on cygwin/mingw to append a dot to
+ # foo even if both foo and FILE.exe exist: automatic-append-.exe
+ # behavior happens only for exec(3), not for open(2)! Also, sourcing
+ # `FILE.' does not work on cygwin managed mounts.
+ #
+ # If there is no directory component, then add one.
+ case $wrapper in
+ */* | *\\*) . ${wrapper} ;;
+ *) . ./${wrapper} ;;
+ esac
+
+ # Check the variables that should have been set.
+ if test -z "$notinst_deplibs"; then
+ $echo "$modename: invalid libtool wrapper script \`$wrapper'" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ finalize=yes
+ for lib in $notinst_deplibs; do
+ # Check to see that each library is installed.
+ libdir=
+ if test -f "$lib"; then
+ # If there is no directory component, then add one.
+ case $lib in
+ */* | *\\*) . $lib ;;
+ *) . ./$lib ;;
+ esac
+ fi
+ libfile="$libdir/"`$echo "X$lib" | $Xsed -e 's%^.*/%%g'` ### testsuite: skip nested quoting test
+ if test -n "$libdir" && test ! -f "$libfile"; then
+ $echo "$modename: warning: \`$lib' has not been installed in \`$libdir'" 1>&2
+ finalize=no
+ fi
+ done
+
+ relink_command=
+ # Note that it is not necessary on cygwin/mingw to append a dot to
+ # foo even if both foo and FILE.exe exist: automatic-append-.exe
+ # behavior happens only for exec(3), not for open(2)! Also, sourcing
+ # `FILE.' does not work on cygwin managed mounts.
+ #
+ # If there is no directory component, then add one.
+ case $wrapper in
+ */* | *\\*) . ${wrapper} ;;
+ *) . ./${wrapper} ;;
+ esac
+
+ outputname=
+ if test "$fast_install" = no && test -n "$relink_command"; then
+ if test "$finalize" = yes && test -z "$run"; then
+ tmpdir=`func_mktempdir`
+ file=`$echo "X$file$stripped_ext" | $Xsed -e 's%^.*/%%'`
+ outputname="$tmpdir/$file"
+ # Replace the output file specification.
+ relink_command=`$echo "X$relink_command" | $Xsed -e 's%@OUTPUT@%'"$outputname"'%g'`
+
+ $show "$relink_command"
+ if $run eval "$relink_command"; then :
+ else
+ $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2
+ ${rm}r "$tmpdir"
+ continue
+ fi
+ file="$outputname"
+ else
+ $echo "$modename: warning: cannot relink \`$file'" 1>&2
+ fi
+ else
+ # Install the binary that we compiled earlier.
+ file=`$echo "X$file$stripped_ext" | $Xsed -e "s%\([^/]*\)$%$objdir/\1%"`
+ fi
+ fi
+
+ # remove .exe since cygwin /usr/bin/install will append another
+ # one anyway
+ case $install_prog,$host in
+ */usr/bin/install*,*cygwin*)
+ case $file:$destfile in
+ *.exe:*.exe)
+ # this is ok
+ ;;
+ *.exe:*)
+ destfile=$destfile.exe
+ ;;
+ *:*.exe)
+ destfile=`$echo $destfile | ${SED} -e 's,.exe$,,'`
+ ;;
+ esac
+ ;;
+ esac
+ $show "$install_prog$stripme $file $destfile"
+ $run eval "$install_prog\$stripme \$file \$destfile" || exit $?
+ test -n "$outputname" && ${rm}r "$tmpdir"
+ ;;
+ esac
+ done
+
+ for file in $staticlibs; do
+ name=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
+
+ # Set up the ranlib parameters.
+ oldlib="$destdir/$name"
+
+ $show "$install_prog $file $oldlib"
+ $run eval "$install_prog \$file \$oldlib" || exit $?
+
+ if test -n "$stripme" && test -n "$old_striplib"; then
+ $show "$old_striplib $oldlib"
+ $run eval "$old_striplib $oldlib" || exit $?
+ fi
+
+ # Do each command in the postinstall commands.
+ cmds=$old_postinstall_cmds
+ save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ eval cmd=\"$cmd\"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+ done
+
+ if test -n "$future_libdirs"; then
+ $echo "$modename: warning: remember to run \`$progname --finish$future_libdirs'" 1>&2
+ fi
+
+ if test -n "$current_libdirs"; then
+ # Maybe just do a dry run.
+ test -n "$run" && current_libdirs=" -n$current_libdirs"
+ exec_cmd='$SHELL $progpath $preserve_args --finish$current_libdirs'
+ else
+ exit $EXIT_SUCCESS
+ fi
+ ;;
+
+ # libtool finish mode
+ finish)
+ modename="$modename: finish"
+ libdirs="$nonopt"
+ admincmds=
+
+ if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then
+ for dir
+ do
+ libdirs="$libdirs $dir"
+ done
+
+ for libdir in $libdirs; do
+ if test -n "$finish_cmds"; then
+ # Do each command in the finish commands.
+ cmds=$finish_cmds
+ save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ eval cmd=\"$cmd\"
+ $show "$cmd"
+ $run eval "$cmd" || admincmds="$admincmds
+ $cmd"
+ done
+ IFS="$save_ifs"
+ fi
+ if test -n "$finish_eval"; then
+ # Do the single finish_eval.
+ eval cmds=\"$finish_eval\"
+ $run eval "$cmds" || admincmds="$admincmds
+ $cmds"
+ fi
+ done
+ fi
+
+ # Exit here if they wanted silent mode.
+ test "$show" = : && exit $EXIT_SUCCESS
+
+ $echo "X----------------------------------------------------------------------" | $Xsed
+ $echo "Libraries have been installed in:"
+ for libdir in $libdirs; do
+ $echo " $libdir"
+ done
+ $echo
+ $echo "If you ever happen to want to link against installed libraries"
+ $echo "in a given directory, LIBDIR, you must either use libtool, and"
+ $echo "specify the full pathname of the library, or use the \`-LLIBDIR'"
+ $echo "flag during linking and do at least one of the following:"
+ if test -n "$shlibpath_var"; then
+ $echo " - add LIBDIR to the \`$shlibpath_var' environment variable"
+ $echo " during execution"
+ fi
+ if test -n "$runpath_var"; then
+ $echo " - add LIBDIR to the \`$runpath_var' environment variable"
+ $echo " during linking"
+ fi
+ if test -n "$hardcode_libdir_flag_spec"; then
+ libdir=LIBDIR
+ eval flag=\"$hardcode_libdir_flag_spec\"
+
+ $echo " - use the \`$flag' linker flag"
+ fi
+ if test -n "$admincmds"; then
+ $echo " - have your system administrator run these commands:$admincmds"
+ fi
+ if test -f /etc/ld.so.conf; then
+ $echo " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'"
+ fi
+ $echo
+ $echo "See any operating system documentation about shared libraries for"
+ $echo "more information, such as the ld(1) and ld.so(8) manual pages."
+ $echo "X----------------------------------------------------------------------" | $Xsed
+ exit $EXIT_SUCCESS
+ ;;
+
+ # libtool execute mode
+ execute)
+ modename="$modename: execute"
+
+ # The first argument is the command name.
+ cmd="$nonopt"
+ if test -z "$cmd"; then
+ $echo "$modename: you must specify a COMMAND" 1>&2
+ $echo "$help"
+ exit $EXIT_FAILURE
+ fi
+
+ # Handle -dlopen flags immediately.
+ for file in $execute_dlfiles; do
+ if test ! -f "$file"; then
+ $echo "$modename: \`$file' is not a file" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ dir=
+ case $file in
+ *.la)
+ # Check to see that this really is a libtool archive.
+ if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then :
+ else
+ $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ # Read the libtool library.
+ dlname=
+ library_names=
+
+ # If there is no directory component, then add one.
+ case $file in
+ */* | *\\*) . $file ;;
+ *) . ./$file ;;
+ esac
+
+ # Skip this library if it cannot be dlopened.
+ if test -z "$dlname"; then
+ # Warn if it was a shared library.
+ test -n "$library_names" && $echo "$modename: warning: \`$file' was not linked with \`-export-dynamic'"
+ continue
+ fi
+
+ dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`
+ test "X$dir" = "X$file" && dir=.
+
+ if test -f "$dir/$objdir/$dlname"; then
+ dir="$dir/$objdir"
+ else
+ $echo "$modename: cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" 1>&2
+ exit $EXIT_FAILURE
+ fi
+ ;;
+
+ *.lo)
+ # Just add the directory containing the .lo file.
+ dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`
+ test "X$dir" = "X$file" && dir=.
+ ;;
+
+ *)
+ $echo "$modename: warning \`-dlopen' is ignored for non-libtool libraries and objects" 1>&2
+ continue
+ ;;
+ esac
+
+ # Get the absolute pathname.
+ absdir=`cd "$dir" && pwd`
+ test -n "$absdir" && dir="$absdir"
+
+ # Now add the directory to shlibpath_var.
+ if eval "test -z \"\$$shlibpath_var\""; then
+ eval "$shlibpath_var=\"\$dir\""
+ else
+ eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\""
+ fi
+ done
+
+ # This variable tells wrapper scripts just to set shlibpath_var
+ # rather than running their programs.
+ libtool_execute_magic="$magic"
+
+ # Check if any of the arguments is a wrapper script.
+ args=
+ for file
+ do
+ case $file in
+ -*) ;;
+ *)
+ # Do a test to see if this is really a libtool program.
+ if (${SED} -e '4q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+ # If there is no directory component, then add one.
+ case $file in
+ */* | *\\*) . $file ;;
+ *) . ./$file ;;
+ esac
+
+ # Transform arg to wrapped name.
+ file="$progdir/$program"
+ fi
+ ;;
+ esac
+ # Quote arguments (to preserve shell metacharacters).
+ file=`$echo "X$file" | $Xsed -e "$sed_quote_subst"`
+ args="$args \"$file\""
+ done
+
+ if test -z "$run"; then
+ if test -n "$shlibpath_var"; then
+ # Export the shlibpath_var.
+ eval "export $shlibpath_var"
+ fi
+
+ # Restore saved environment variables
+ if test "${save_LC_ALL+set}" = set; then
+ LC_ALL="$save_LC_ALL"; export LC_ALL
+ fi
+ if test "${save_LANG+set}" = set; then
+ LANG="$save_LANG"; export LANG
+ fi
+
+ # Now prepare to actually exec the command.
+ exec_cmd="\$cmd$args"
+ else
+ # Display what would be done.
+ if test -n "$shlibpath_var"; then
+ eval "\$echo \"\$shlibpath_var=\$$shlibpath_var\""
+ $echo "export $shlibpath_var"
+ fi
+ $echo "$cmd$args"
+ exit $EXIT_SUCCESS
+ fi
+ ;;
+
+ # libtool clean and uninstall mode
+ clean | uninstall)
+ modename="$modename: $mode"
+ rm="$nonopt"
+ files=
+ rmforce=
+ exit_status=0
+
+ # This variable tells wrapper scripts just to set variables rather
+ # than running their programs.
+ libtool_install_magic="$magic"
+
+ for arg
+ do
+ case $arg in
+ -f) rm="$rm $arg"; rmforce=yes ;;
+ -*) rm="$rm $arg" ;;
+ *) files="$files $arg" ;;
+ esac
+ done
+
+ if test -z "$rm"; then
+ $echo "$modename: you must specify an RM program" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ rmdirs=
+
+ origobjdir="$objdir"
+ for file in $files; do
+ dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`
+ if test "X$dir" = "X$file"; then
+ dir=.
+ objdir="$origobjdir"
+ else
+ objdir="$dir/$origobjdir"
+ fi
+ name=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
+ test "$mode" = uninstall && objdir="$dir"
+
+ # Remember objdir for removal later, being careful to avoid duplicates
+ if test "$mode" = clean; then
+ case " $rmdirs " in
+ *" $objdir "*) ;;
+ *) rmdirs="$rmdirs $objdir" ;;
+ esac
+ fi
+
+ # Don't error if the file doesn't exist and rm -f was used.
+ if (test -L "$file") >/dev/null 2>&1 \
+ || (test -h "$file") >/dev/null 2>&1 \
+ || test -f "$file"; then
+ :
+ elif test -d "$file"; then
+ exit_status=1
+ continue
+ elif test "$rmforce" = yes; then
+ continue
+ fi
+
+ rmfiles="$file"
+
+ case $name in
+ *.la)
+ # Possibly a libtool archive, so verify it.
+ if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+ . $dir/$name
+
+ # Delete the libtool libraries and symlinks.
+ for n in $library_names; do
+ rmfiles="$rmfiles $objdir/$n"
+ done
+ test -n "$old_library" && rmfiles="$rmfiles $objdir/$old_library"
+
+ case "$mode" in
+ clean)
+ case " $library_names " in
+ # " " in the beginning catches empty $dlname
+ *" $dlname "*) ;;
+ *) rmfiles="$rmfiles $objdir/$dlname" ;;
+ esac
+ test -n "$libdir" && rmfiles="$rmfiles $objdir/$name $objdir/${name}i"
+ ;;
+ uninstall)
+ if test -n "$library_names"; then
+ # Do each command in the postuninstall commands.
+ cmds=$postuninstall_cmds
+ save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ eval cmd=\"$cmd\"
+ $show "$cmd"
+ $run eval "$cmd"
+ if test "$?" -ne 0 && test "$rmforce" != yes; then
+ exit_status=1
+ fi
+ done
+ IFS="$save_ifs"
+ fi
+
+ if test -n "$old_library"; then
+ # Do each command in the old_postuninstall commands.
+ cmds=$old_postuninstall_cmds
+ save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ eval cmd=\"$cmd\"
+ $show "$cmd"
+ $run eval "$cmd"
+ if test "$?" -ne 0 && test "$rmforce" != yes; then
+ exit_status=1
+ fi
+ done
+ IFS="$save_ifs"
+ fi
+ # FIXME: should reinstall the best remaining shared library.
+ ;;
+ esac
+ fi
+ ;;
+
+ *.lo)
+ # Possibly a libtool object, so verify it.
+ if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+
+ # Read the .lo file
+ . $dir/$name
+
+ # Add PIC object to the list of files to remove.
+ if test -n "$pic_object" \
+ && test "$pic_object" != none; then
+ rmfiles="$rmfiles $dir/$pic_object"
+ fi
+
+ # Add non-PIC object to the list of files to remove.
+ if test -n "$non_pic_object" \
+ && test "$non_pic_object" != none; then
+ rmfiles="$rmfiles $dir/$non_pic_object"
+ fi
+ fi
+ ;;
+
+ *)
+ if test "$mode" = clean ; then
+ noexename=$name
+ case $file in
+ *.exe)
+ file=`$echo $file|${SED} 's,.exe$,,'`
+ noexename=`$echo $name|${SED} 's,.exe$,,'`
+ # $file with .exe has already been added to rmfiles,
+ # add $file without .exe
+ rmfiles="$rmfiles $file"
+ ;;
+ esac
+ # Do a test to see if this is a libtool program.
+ if (${SED} -e '4q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+ relink_command=
+ . $dir/$noexename
+
+ # note $name still contains .exe if it was in $file originally
+ # as does the version of $file that was added into $rmfiles
+ rmfiles="$rmfiles $objdir/$name $objdir/${name}S.${objext}"
+ if test "$fast_install" = yes && test -n "$relink_command"; then
+ rmfiles="$rmfiles $objdir/lt-$name"
+ fi
+ if test "X$noexename" != "X$name" ; then
+ rmfiles="$rmfiles $objdir/lt-${noexename}.c"
+ fi
+ fi
+ fi
+ ;;
+ esac
+ $show "$rm $rmfiles"
+ $run $rm $rmfiles || exit_status=1
+ done
+ objdir="$origobjdir"
+
+ # Try to remove the ${objdir}s in the directories where we deleted files
+ for dir in $rmdirs; do
+ if test -d "$dir"; then
+ $show "rmdir $dir"
+ $run rmdir $dir >/dev/null 2>&1
+ fi
+ done
+
+ exit $exit_status
+ ;;
+
+ "")
+ $echo "$modename: you must specify a MODE" 1>&2
+ $echo "$generic_help" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+ esac
+
+ if test -z "$exec_cmd"; then
+ $echo "$modename: invalid operation mode \`$mode'" 1>&2
+ $echo "$generic_help" 1>&2
+ exit $EXIT_FAILURE
+ fi
+fi # test -z "$show_help"
+
+if test -n "$exec_cmd"; then
+ eval exec $exec_cmd
+ exit $EXIT_FAILURE
+fi
+
+# We need to display help for each of the modes.
+case $mode in
+"") $echo \
+"Usage: $modename [OPTION]... [MODE-ARG]...
+
+Provide generalized library-building support services.
+
+ --config show all configuration variables
+ --debug enable verbose shell tracing
+-n, --dry-run display commands without modifying any files
+ --features display basic configuration information and exit
+ --finish same as \`--mode=finish'
+ --help display this help message and exit
+ --mode=MODE use operation mode MODE [default=inferred from MODE-ARGS]
+ --quiet same as \`--silent'
+ --silent don't print informational messages
+ --tag=TAG use configuration variables from tag TAG
+ --version print version information
+
+MODE must be one of the following:
+
+ clean remove files from the build directory
+ compile compile a source file into a libtool object
+ execute automatically set library path, then run a program
+ finish complete the installation of libtool libraries
+ install install libraries or executables
+ link create a library or an executable
+ uninstall remove libraries from an installed directory
+
+MODE-ARGS vary depending on the MODE. Try \`$modename --help --mode=MODE' for
+a more detailed description of MODE.
+
+Report bugs to <bug-libtool at gnu.org>."
+ exit $EXIT_SUCCESS
+ ;;
+
+clean)
+ $echo \
+"Usage: $modename [OPTION]... --mode=clean RM [RM-OPTION]... FILE...
+
+Remove files from the build directory.
+
+RM is the name of the program to use to delete files associated with each FILE
+(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed
+to RM.
+
+If FILE is a libtool library, object or program, all the files associated
+with it are deleted. Otherwise, only FILE itself is deleted using RM."
+ ;;
+
+compile)
+ $echo \
+"Usage: $modename [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE
+
+Compile a source file into a libtool library object.
+
+This mode accepts the following additional options:
+
+ -o OUTPUT-FILE set the output file name to OUTPUT-FILE
+ -prefer-pic try to building PIC objects only
+ -prefer-non-pic try to building non-PIC objects only
+ -static always build a \`.o' file suitable for static linking
+
+COMPILE-COMMAND is a command to be used in creating a \`standard' object file
+from the given SOURCEFILE.
+
+The output file name is determined by removing the directory component from
+SOURCEFILE, then substituting the C source code suffix \`.c' with the
+library object suffix, \`.lo'."
+ ;;
+
+execute)
+ $echo \
+"Usage: $modename [OPTION]... --mode=execute COMMAND [ARGS]...
+
+Automatically set library path, then run a program.
+
+This mode accepts the following additional options:
+
+ -dlopen FILE add the directory containing FILE to the library path
+
+This mode sets the library path environment variable according to \`-dlopen'
+flags.
+
+If any of the ARGS are libtool executable wrappers, then they are translated
+into their corresponding uninstalled binary, and any of their required library
+directories are added to the library path.
+
+Then, COMMAND is executed, with ARGS as arguments."
+ ;;
+
+finish)
+ $echo \
+"Usage: $modename [OPTION]... --mode=finish [LIBDIR]...
+
+Complete the installation of libtool libraries.
+
+Each LIBDIR is a directory that contains libtool libraries.
+
+The commands that this mode executes may require superuser privileges. Use
+the \`--dry-run' option if you just want to see what would be executed."
+ ;;
+
+install)
+ $echo \
+"Usage: $modename [OPTION]... --mode=install INSTALL-COMMAND...
+
+Install executables or libraries.
+
+INSTALL-COMMAND is the installation command. The first component should be
+either the \`install' or \`cp' program.
+
+The rest of the components are interpreted as arguments to that command (only
+BSD-compatible install options are recognized)."
+ ;;
+
+link)
+ $echo \
+"Usage: $modename [OPTION]... --mode=link LINK-COMMAND...
+
+Link object files or libraries together to form another library, or to
+create an executable program.
+
+LINK-COMMAND is a command using the C compiler that you would use to create
+a program from several object files.
+
+The following components of LINK-COMMAND are treated specially:
+
+ -all-static do not do any dynamic linking at all
+ -avoid-version do not add a version suffix if possible
+ -dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime
+ -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols
+ -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3)
+ -export-symbols SYMFILE
+ try to export only the symbols listed in SYMFILE
+ -export-symbols-regex REGEX
+ try to export only the symbols matching REGEX
+ -LLIBDIR search LIBDIR for required installed libraries
+ -lNAME OUTPUT-FILE requires the installed library libNAME
+ -module build a library that can dlopened
+ -no-fast-install disable the fast-install mode
+ -no-install link a not-installable executable
+ -no-undefined declare that a library does not refer to external symbols
+ -o OUTPUT-FILE create OUTPUT-FILE from the specified objects
+ -objectlist FILE Use a list of object files found in FILE to specify objects
+ -precious-files-regex REGEX
+ don't remove output files matching REGEX
+ -release RELEASE specify package release information
+ -rpath LIBDIR the created library will eventually be installed in LIBDIR
+ -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries
+ -static do not do any dynamic linking of libtool libraries
+ -version-info CURRENT[:REVISION[:AGE]]
+ specify library version info [each variable defaults to 0]
+
+All other options (arguments beginning with \`-') are ignored.
+
+Every other argument is treated as a filename. Files ending in \`.la' are
+treated as uninstalled libtool libraries, other files are standard or library
+object files.
+
+If the OUTPUT-FILE ends in \`.la', then a libtool library is created,
+only library objects (\`.lo' files) may be specified, and \`-rpath' is
+required, except when creating a convenience library.
+
+If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created
+using \`ar' and \`ranlib', or on Windows using \`lib'.
+
+If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file
+is created, otherwise an executable program is created."
+ ;;
+
+uninstall)
+ $echo \
+"Usage: $modename [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE...
+
+Remove libraries from an installation directory.
+
+RM is the name of the program to use to delete files associated with each FILE
+(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed
+to RM.
+
+If FILE is a libtool library, all the files associated with it are deleted.
+Otherwise, only FILE itself is deleted using RM."
+ ;;
+
+*)
+ $echo "$modename: invalid operation mode \`$mode'" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+esac
+
+$echo
+$echo "Try \`$modename --help' for more information about other modes."
+
+exit $?
+
+# The TAGs below are defined such that we never get into a situation
+# in which we disable both kinds of libraries. Given conflicting
+# choices, we go for a static library, that is the most portable,
+# since we can't tell whether shared libraries were disabled because
+# the user asked for that or because the platform doesn't support
+# them. This is particularly important on AIX, because we don't
+# support having both static and shared libraries enabled at the same
+# time on that platform, so we default to a shared-only configuration.
+# If a disable-shared tag is given, we'll fallback to a static-only
+# configuration. But we'll never go from static-only to shared-only.
+
+# ### BEGIN LIBTOOL TAG CONFIG: disable-shared
+disable_libs=shared
+# ### END LIBTOOL TAG CONFIG: disable-shared
+
+# ### BEGIN LIBTOOL TAG CONFIG: disable-static
+disable_libs=static
+# ### END LIBTOOL TAG CONFIG: disable-static
+
+# Local Variables:
+# mode:shell-script
+# sh-indentation:2
+# End:
diff --git a/config/mkinstalldirs b/config/mkinstalldirs
new file mode 100755
index 0000000..a55cff6
--- /dev/null
+++ b/config/mkinstalldirs
@@ -0,0 +1,137 @@
+#! /bin/sh
+# mkinstalldirs --- make directory hierarchy
+# Original author: Noah Friedman <friedman at prep.ai.mit.edu>
+# Created: 1993-05-16
+# Public domain.
+
+scriptversion=2003-09-26.19
+
+errstatus=0
+dirmode=""
+
+usage="\
+Usage: mkinstalldirs [-h] [--help] [--version] [-m MODE] DIR ...
+
+Create each directory DIR (with mode MODE, if specified), including all
+leading file name components.
+"
+
+# process command line arguments
+while test $# -gt 0 ; do
+ case $1 in
+ -h | --help | --h*) # -h for help
+ echo "$usage"
+ exit 0
+ ;;
+ -m) # -m PERM arg
+ shift
+ test $# -eq 0 && { echo "$usage" 1>&2; exit 1; }
+ dirmode=$1
+ shift
+ ;;
+ --version)
+ echo "$0 $scriptversion"
+ exit 0
+ ;;
+ --) # stop option processing
+ shift
+ break
+ ;;
+ -*) # unknown option
+ echo "$usage" 1>&2
+ exit 1
+ ;;
+ *) # first non-opt arg
+ break
+ ;;
+ esac
+done
+
+for file
+do
+ if test -d "$file"; then
+ shift
+ else
+ break
+ fi
+done
+
+case $# in
+ 0) exit 0 ;;
+esac
+
+case $dirmode in
+ '')
+ if mkdir -p -- . 2>/dev/null; then
+ echo "mkdir -p -- $*"
+ exec mkdir -p -- "$@"
+ else
+ # On NextStep and OpenStep, the `mkdir' command does not
+ # recognize any option. It will interpret all options as
+ # directories to create, and then abort because `.' already
+ # exists.
+ test -d ./-p && rmdir ./-p
+ test -d ./-- && rmdir ./--
+ fi
+ ;;
+ *)
+ if mkdir -m "$dirmode" -p -- . 2>/dev/null; then
+ echo "mkdir -m $dirmode -p -- $*"
+ exec mkdir -m "$dirmode" -p -- "$@"
+ else
+ # Clean up after NextStep and OpenStep mkdir.
+ for d in ./-m ./-p ./-- "./$dirmode";
+ do
+ test -d $d && rmdir $d
+ done
+ fi
+ ;;
+esac
+
+for file
+do
+ set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'`
+ shift
+
+ pathcomp=
+ for d
+ do
+ pathcomp="$pathcomp$d"
+ case $pathcomp in
+ -*) pathcomp=./$pathcomp ;;
+ esac
+
+ if test ! -d "$pathcomp"; then
+ echo "mkdir $pathcomp"
+
+ mkdir "$pathcomp" || lasterr=$?
+
+ if test ! -d "$pathcomp"; then
+ errstatus=$lasterr
+ else
+ if test ! -z "$dirmode"; then
+ echo "chmod $dirmode $pathcomp"
+ lasterr=""
+ chmod "$dirmode" "$pathcomp" || lasterr=$?
+
+ if test ! -z "$lasterr"; then
+ errstatus=$lasterr
+ fi
+ fi
+ fi
+ fi
+
+ pathcomp="$pathcomp/"
+ done
+done
+
+exit $errstatus
+
+# Local Variables:
+# mode: shell-script
+# sh-indentation: 2
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-end: "$"
+# End:
diff --git a/config/mod_c.m4 b/config/mod_c.m4
new file mode 100644
index 0000000..8f95212
--- /dev/null
+++ b/config/mod_c.m4
@@ -0,0 +1,62 @@
+# This file is part of Autoconf. -*- Autoconf -*-
+# Programming languages support.
+# Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+# 02111-1307, USA.
+#
+# As a special exception, the Free Software Foundation gives unlimited
+# permission to copy, distribute and modify the configure scripts that
+# are the output of Autoconf. You need not follow the terms of the GNU
+# General Public License when using or distributing such scripts, even
+# though portions of the text of Autoconf appear in them. The GNU
+# General Public License (GPL) does govern all other use of the material
+# that constitutes the Autoconf program.
+#
+# Certain portions of the Autoconf source text are designed to be copied
+# (in certain cases, depending on the input) into the output of
+# Autoconf. We call these the "data" portions. The rest of the Autoconf
+# source text consists of comments plus executable code that decides which
+# of the data portions to output in any given case. We call these
+# comments and executable code the "non-data" portions. Autoconf never
+# copies any of the non-data portions into its output.
+#
+# This special exception to the GPL applies to versions of Autoconf
+# released by the Free Software Foundation. When you make and
+# distribute a modified version of Autoconf, you may extend this special
+# exception to the GPL to apply to your modified version as well, *unless*
+# your modified version has the potential to copy into its output some
+# of the text that was the non-data portion of the version that you started
+# with. (In other words, unless your change moves or copies text from
+# the non-data portions to the data portions.) If your modification has
+# such potential, you must delete any notice of this special exception
+# to the GPL from your modified version.
+#
+# Written by David MacKenzie, with help from
+# Franc,ois Pinard, Karl Berry, Richard Pixley, Ian Lance Taylor,
+# Roland McGrath, Noah Friedman, david d zuhn, and many others.
+
+
+# AC_LANG(C)
+# ----------
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+m4_define([AC_LANG(C)],
+[ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&AS_MESSAGE_LOG_FD'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&AS_MESSAGE_LOG_FD'
+ac_linkonly='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_objext $LIBS >&AS_MESSAGE_LOG_FD'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+])
diff --git a/config/mod_fortran.m4 b/config/mod_fortran.m4
new file mode 100644
index 0000000..1f02709
--- /dev/null
+++ b/config/mod_fortran.m4
@@ -0,0 +1,117 @@
+# This file is part of Autoconf. -*- Autoconf -*-
+# Fortran languages support.
+# Copyright (C) 2001, 2003
+# Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+# 02111-1307, USA.
+#
+# As a special exception, the Free Software Foundation gives unlimited
+# permission to copy, distribute and modify the configure scripts that
+# are the output of Autoconf. You need not follow the terms of the GNU
+# General Public License when using or distributing such scripts, even
+# though portions of the text of Autoconf appear in them. The GNU
+# General Public License (GPL) does govern all other use of the material
+# that constitutes the Autoconf program.
+#
+# Certain portions of the Autoconf source text are designed to be copied
+# (in certain cases, depending on the input) into the output of
+# Autoconf. We call these the "data" portions. The rest of the Autoconf
+# source text consists of comments plus executable code that decides which
+# of the data portions to output in any given case. We call these
+# comments and executable code the "non-data" portions. Autoconf never
+# copies any of the non-data portions into its output.
+#
+# This special exception to the GPL applies to versions of Autoconf
+# released by the Free Software Foundation. When you make and
+# distribute a modified version of Autoconf, you may extend this special
+# exception to the GPL to apply to your modified version as well, *unless*
+# your modified version has the potential to copy into its output some
+# of the text that was the non-data portion of the version that you started
+# with. (In other words, unless your change moves or copies text from
+# the non-data portions to the data portions.) If your modification has
+# such potential, you must delete any notice of this special exception
+# to the GPL from your modified version.
+#
+# Written by David MacKenzie, with help from
+# Franc,ois Pinard, Karl Berry, Richard Pixley, Ian Lance Taylor,
+# Roland McGrath, Noah Friedman, david d zuhn, and many others.
+
+# Fortran vs. Fortran 77:
+# This file contains macros for both "Fortran 77" and "Fortran", where
+# the former is the "classic" autoconf Fortran interface and is intended
+# for legacy F77 codes, while the latter is intended to support newer Fortran
+# dialects. Fortran 77 uses environment variables F77, FFLAGS, and FLIBS,
+# while Fortran uses FC, FCFLAGS, and FCLIBS. For each user-callable AC_*
+# macro, there is generally both an F77 and an FC version, where both versions
+# share the same _AC_*_FC_* backend. This backend macro requires that
+# the appropriate language be AC_LANG_PUSH'ed, and uses _AC_LANG_ABBREV and
+# _AC_LANG_PREFIX in order to name cache and environment variables, etc.
+
+
+# _AC_PROG_FC_V_OUTPUT([FLAG = $ac_cv_prog_{f77/fc}_v])
+# -------------------------------------------------
+# Link a trivial Fortran program, compiling with a verbose output FLAG
+# (whose default value, $ac_cv_prog_{f77/fc}_v, is computed by
+# _AC_PROG_FC_V), and return the output in $ac_{f77/fc}_v_output. This
+# output is processed in the way expected by _AC_FC_LIBRARY_LDFLAGS,
+# so that any link flags that are echoed by the compiler appear as
+# space-separated items.
+AC_DEFUN([_AC_PROG_FC_V_OUTPUT],
+[_AC_FORTRAN_ASSERT()dnl
+AC_LANG_CONFTEST([AC_LANG_PROGRAM([])])
+
+# Compile and link our simple test program by passing a flag (argument
+# 1 to this macro) to the Fortran compiler in order to get
+# "verbose" output that we can then parse for the Fortran linker
+# flags.
+ac_save_FFLAGS=$[]_AC_LANG_PREFIX[]FLAGS
+_AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS m4_default([$1], [$ac_cv_prog_[]_AC_LANG_ABBREV[]_v])"
+(eval echo $as_me:__oline__: \"$ac_link\") >&AS_MESSAGE_LOG_FD
+ac_[]_AC_LANG_ABBREV[]_v_output=`eval $ac_link AS_MESSAGE_LOG_FD>&1 2>&1 | grep -v 'Driving:'`
+echo "$ac_[]_AC_LANG_ABBREV[]_v_output" >&AS_MESSAGE_LOG_FD
+_AC_LANG_PREFIX[]FLAGS=$ac_save_FFLAGS
+
+rm -f conftest*
+
+# On HP/UX there is a line like: "LPATH is: /foo:/bar:/baz" where
+# /foo, /bar, and /baz are search directories for the Fortran linker.
+# Here, we change these into -L/foo -L/bar -L/baz (and put it first):
+ac_[]_AC_LANG_ABBREV[]_v_output="`echo $ac_[]_AC_LANG_ABBREV[]_v_output |
+ grep 'LPATH is:' |
+ sed 's,.*LPATH is\(: *[[^ ]]*\).*,\1,;s,: */, -L/,g'` $ac_[]_AC_LANG_ABBREV[]_v_output"
+
+case $ac_[]_AC_LANG_ABBREV[]_v_output in
+ # If we are using xlf then replace all the commas with spaces.
+ *xlfentry*)
+ ac_[]_AC_LANG_ABBREV[]_v_output=`echo $ac_[]_AC_LANG_ABBREV[]_v_output | sed 's/,/ /g'` ;;
+
+ # With Intel ifc, ignore the quoted -mGLOB_options_string stuff (quoted
+ # $LIBS confuse us, and the libraries appear later in the output anyway).
+ *mGLOB_options_string*)
+ ac_[]_AC_LANG_ABBREV[]_v_output=`echo $ac_[]_AC_LANG_ABBREV[]_v_output | sed 's/"-mGLOB[[^"]]*"/ /g'` ;;
+
+ # Portland Group compiler has quoted -cmdline argument
+ *-cmdline*)
+ ac_[]_AC_LANG_ABBREV[]_v_output=`echo $ac_[]_AC_LANG_ABBREV[]_v_output | sed "s/-cmdline '[[^']]*'/ /g"` ;;
+
+ # If we are using Cray Fortran then delete quotes.
+ # Use "\"" instead of '"' for font-lock-mode.
+ # FIXME: a more general fix for quoted arguments with spaces?
+ *cft90*)
+ ac_[]_AC_LANG_ABBREV[]_v_output=`echo $ac_[]_AC_LANG_ABBREV[]_v_output | sed "s/\"//g"` ;;
+esac
+
+])# _AC_PROG_FC_V_OUTPUT
diff --git a/config/rminstalldirs b/config/rminstalldirs
new file mode 100755
index 0000000..7a3871c
--- /dev/null
+++ b/config/rminstalldirs
@@ -0,0 +1,20 @@
+#! /bin/sh
+# rminstalldirs -- remove directory if empty with checks
+# Author: Radu Serban
+
+for arg in ${1+"$@"} ; do
+
+ path=`echo "$arg" | sed -e 's,/$,,' | tr -s '/'`
+
+ case "$path" in
+ -* ) path="./$path" ;;
+ esac
+
+ if test -d "$path" ; then
+ if test x"`ls -A "$path"`" = x ; then
+ echo "rmdir $path"
+ rmdir "$path" > /dev/null 2>&1 || errstatus=$?
+ fi
+ fi
+
+done
\ No newline at end of file
diff --git a/configure b/configure
new file mode 100755
index 0000000..1a4e6e3
--- /dev/null
+++ b/configure
@@ -0,0 +1,28297 @@
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.59 for SUNDIALS 2.5.0.
+#
+# Report bugs to <radu at llnl.gov>.
+#
+# Copyright (C) 2003 Free Software Foundation, Inc.
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+#
+#
+# Copyright (c) 2002, The Regents of the University of California.
+# Produced at the Lawrence Livermore National Laboratory.
+# All rights reserved.
+# For details, see the LICENSE file.
+#
+## --------------------- ##
+## M4sh Initialization. ##
+## --------------------- ##
+
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
+ set -o posix
+fi
+DUALCASE=1; export DUALCASE # for MKS sh
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+ as_unset=unset
+else
+ as_unset=false
+fi
+
+
+# Work around bugs in pre-3.0 UWIN ksh.
+$as_unset ENV MAIL MAILPATH
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+ LC_TELEPHONE LC_TIME
+do
+ if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
+ eval $as_var=C; export $as_var
+ else
+ $as_unset $as_var
+ fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)$' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; }
+ /^X\/\(\/\/\)$/{ s//\1/; q; }
+ /^X\/\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+
+
+# PATH needs CR, and LINENO needs CR and PATH.
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ echo "#! /bin/sh" >conf$$.sh
+ echo "exit 0" >>conf$$.sh
+ chmod +x conf$$.sh
+ if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+ PATH_SEPARATOR=';'
+ else
+ PATH_SEPARATOR=:
+ fi
+ rm -f conf$$.sh
+fi
+
+
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x$as_lineno_3" = "x$as_lineno_2" || {
+ # Find who we are. Look in the path if we contain no path at all
+ # relative or not.
+ case $0 in
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+
+ ;;
+ esac
+ # We did not find ourselves, most probably we were run as `sh COMMAND'
+ # in which case we are not to be found in the path.
+ if test "x$as_myself" = x; then
+ as_myself=$0
+ fi
+ if test ! -f "$as_myself"; then
+ { echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2
+ { (exit 1); exit 1; }; }
+ fi
+ case $CONFIG_SHELL in
+ '')
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for as_base in sh bash ksh sh5; do
+ case $as_dir in
+ /*)
+ if ("$as_dir/$as_base" -c '
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then
+ $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; }
+ $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; }
+ CONFIG_SHELL=$as_dir/$as_base
+ export CONFIG_SHELL
+ exec "$CONFIG_SHELL" "$0" ${1+"$@"}
+ fi;;
+ esac
+ done
+done
+;;
+ esac
+
+ # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+ # uniformly replaced by the line number. The first 'sed' inserts a
+ # line-number line before each line; the second 'sed' does the real
+ # work. The second script uses 'N' to pair each line-number line
+ # with the numbered line, and appends trailing '-' during
+ # substitution so that $LINENO is not a special case at line end.
+ # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+ # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-)
+ sed '=' <$as_myself |
+ sed '
+ N
+ s,$,-,
+ : loop
+ s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3,
+ t loop
+ s,-$,,
+ s,^['$as_cr_digits']*\n,,
+ ' >$as_me.lineno &&
+ chmod +x $as_me.lineno ||
+ { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
+ { (exit 1); exit 1; }; }
+
+ # Don't try to exec as it changes $[0], causing all sort of problems
+ # (the dirname of $[0] is not the place where we might find the
+ # original and so on. Autoconf is especially sensible to this).
+ . ./$as_me.lineno
+ # Exit status is that of the last command.
+ exit
+}
+
+
+case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in
+ *c*,-n*) ECHO_N= ECHO_C='
+' ECHO_T=' ' ;;
+ *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;;
+ *) ECHO_N= ECHO_C='\c' ECHO_T= ;;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+ # We could just check for DJGPP; but this test a) works b) is more generic
+ # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04).
+ if test -f conf$$.exe; then
+ # Don't use ln at all; we don't have any links
+ as_ln_s='cp -p'
+ else
+ as_ln_s='ln -s'
+ fi
+elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+else
+ as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.file
+
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p=:
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+as_executable_p="test -f"
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.
+as_nl='
+'
+IFS=" $as_nl"
+
+# CDPATH.
+$as_unset CDPATH
+
+
+
+# Check that we are running under the correct shell.
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+case X$ECHO in
+X*--fallback-echo)
+ # Remove one level of quotation (which was required for Make).
+ ECHO=`echo "$ECHO" | sed 's,\\\\\$\\$0,'$0','`
+ ;;
+esac
+
+echo=${ECHO-echo}
+if test "X$1" = X--no-reexec; then
+ # Discard the --no-reexec flag, and continue.
+ shift
+elif test "X$1" = X--fallback-echo; then
+ # Avoid inline document here, it may be left over
+ :
+elif test "X`($echo '\t') 2>/dev/null`" = 'X\t' ; then
+ # Yippee, $echo works!
+ :
+else
+ # Restart under the correct shell.
+ exec $SHELL "$0" --no-reexec ${1+"$@"}
+fi
+
+if test "X$1" = X--fallback-echo; then
+ # used as fallback echo
+ shift
+ cat <<EOF
+$*
+EOF
+ exit 0
+fi
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+if test -z "$ECHO"; then
+if test "X${echo_test_string+set}" != Xset; then
+# find a string as large as possible, as long as the shell can cope with it
+ for cmd in 'sed 50q "$0"' 'sed 20q "$0"' 'sed 10q "$0"' 'sed 2q "$0"' 'echo test'; do
+ # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ...
+ if (echo_test_string=`eval $cmd`) 2>/dev/null &&
+ echo_test_string=`eval $cmd` &&
+ (test "X$echo_test_string" = "X$echo_test_string") 2>/dev/null
+ then
+ break
+ fi
+ done
+fi
+
+if test "X`($echo '\t') 2>/dev/null`" = 'X\t' &&
+ echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ :
+else
+ # The Solaris, AIX, and Digital Unix default echo programs unquote
+ # backslashes. This makes it impossible to quote backslashes using
+ # echo "$something" | sed 's/\\/\\\\/g'
+ #
+ # So, first we look for a working echo in the user's PATH.
+
+ lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+ for dir in $PATH /usr/ucb; do
+ IFS="$lt_save_ifs"
+ if (test -f $dir/echo || test -f $dir/echo$ac_exeext) &&
+ test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' &&
+ echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ echo="$dir/echo"
+ break
+ fi
+ done
+ IFS="$lt_save_ifs"
+
+ if test "X$echo" = Xecho; then
+ # We didn't find a better echo, so look for alternatives.
+ if test "X`(print -r '\t') 2>/dev/null`" = 'X\t' &&
+ echo_testing_string=`(print -r "$echo_test_string") 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ # This shell has a builtin print -r that does the trick.
+ echo='print -r'
+ elif (test -f /bin/ksh || test -f /bin/ksh$ac_exeext) &&
+ test "X$CONFIG_SHELL" != X/bin/ksh; then
+ # If we have ksh, try running configure again with it.
+ ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh}
+ export ORIGINAL_CONFIG_SHELL
+ CONFIG_SHELL=/bin/ksh
+ export CONFIG_SHELL
+ exec $CONFIG_SHELL "$0" --no-reexec ${1+"$@"}
+ else
+ # Try using printf.
+ echo='printf %s\n'
+ if test "X`($echo '\t') 2>/dev/null`" = 'X\t' &&
+ echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ # Cool, printf works
+ :
+ elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` &&
+ test "X$echo_testing_string" = 'X\t' &&
+ echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL
+ export CONFIG_SHELL
+ SHELL="$CONFIG_SHELL"
+ export SHELL
+ echo="$CONFIG_SHELL $0 --fallback-echo"
+ elif echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` &&
+ test "X$echo_testing_string" = 'X\t' &&
+ echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ echo="$CONFIG_SHELL $0 --fallback-echo"
+ else
+ # maybe with a smaller string...
+ prev=:
+
+ for cmd in 'echo test' 'sed 2q "$0"' 'sed 10q "$0"' 'sed 20q "$0"' 'sed 50q "$0"'; do
+ if (test "X$echo_test_string" = "X`eval $cmd`") 2>/dev/null
+ then
+ break
+ fi
+ prev="$cmd"
+ done
+
+ if test "$prev" != 'sed 50q "$0"'; then
+ echo_test_string=`eval $prev`
+ export echo_test_string
+ exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "$0" ${1+"$@"}
+ else
+ # Oops. We lost completely, so just stick with echo.
+ echo=echo
+ fi
+ fi
+ fi
+ fi
+fi
+fi
+
+# Copy echo and quote the copy suitably for passing to libtool from
+# the Makefile, instead of quoting the original, which is used later.
+ECHO=$echo
+if test "X$ECHO" = "X$CONFIG_SHELL $0 --fallback-echo"; then
+ ECHO="$CONFIG_SHELL \\\$\$0 --fallback-echo"
+fi
+
+
+
+
+tagnames=${tagnames+${tagnames},}CXX
+
+tagnames=${tagnames+${tagnames},}F77
+
+# Name of the host.
+# hostname on some systems (SVR3.2, Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+exec 6>&1
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_config_libobj_dir=.
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+# Maximum number of lines to put in a shell here document.
+# This variable seems obsolete. It should probably be removed, and
+# only ac_max_sed_lines should be used.
+: ${ac_max_here_lines=38}
+
+# Identity of this package.
+PACKAGE_NAME='SUNDIALS'
+PACKAGE_TARNAME='sundials'
+PACKAGE_VERSION='2.5.0'
+PACKAGE_STRING='SUNDIALS 2.5.0'
+PACKAGE_BUGREPORT='radu at llnl.gov'
+
+ac_unique_file="/src/sundials/sundials_nvector.c"
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include <stdio.h>
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#if HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#if STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# if HAVE_STDLIB_H
+# include <stdlib.h>
+# endif
+#endif
+#if HAVE_STRING_H
+# if !STDC_HEADERS && HAVE_MEMORY_H
+# include <memory.h>
+# endif
+# include <string.h>
+#endif
+#if HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#if HAVE_INTTYPES_H
+# include <inttypes.h>
+#else
+# if HAVE_STDINT_H
+# include <stdint.h>
+# endif
+#endif
+#if HAVE_UNISTD_H
+# include <unistd.h>
+#endif"
+
+ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os SET_MAKE INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CC CFLAGS LDFLAGS CPPFL [...]
+ac_subst_files=''
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datadir='${prefix}/share'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+libdir='${exec_prefix}/lib'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+infodir='${prefix}/info'
+mandir='${prefix}/man'
+
+ac_prev=
+for ac_option
+do
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval "$ac_prev=\$ac_option"
+ ac_prev=
+ continue
+ fi
+
+ ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'`
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case $ac_option in
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir=$ac_optarg ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build_alias ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build_alias=$ac_optarg ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file=$ac_optarg ;;
+
+ --config-cache | -C)
+ cache_file=config.cache ;;
+
+ -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
+ | --da=*)
+ datadir=$ac_optarg ;;
+
+ -disable-* | --disable-*)
+ ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+ { (exit 1); exit 1; }; }
+ ac_feature=`echo $ac_feature | sed 's/-/_/g'`
+ eval "enable_$ac_feature=no" ;;
+
+ -enable-* | --enable-*)
+ ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+ { (exit 1); exit 1; }; }
+ ac_feature=`echo $ac_feature | sed 's/-/_/g'`
+ case $ac_option in
+ *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "enable_$ac_feature='$ac_optarg'" ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix=$ac_optarg ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he | -h)
+ ac_init_help=long ;;
+ -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+ ac_init_help=recursive ;;
+ -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+ ac_init_help=short ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host_alias ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host_alias=$ac_optarg ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir=$ac_optarg ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir=$ac_optarg ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir=$ac_optarg ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir=$ac_optarg ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst \
+ | --locals | --local | --loca | --loc | --lo)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* \
+ | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
+ localstatedir=$ac_optarg ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir=$ac_optarg ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c | -n)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir=$ac_optarg ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix=$ac_optarg ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix=$ac_optarg ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix=$ac_optarg ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name=$ac_optarg ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir=$ac_optarg ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir=$ac_optarg ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site=$ac_optarg ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir=$ac_optarg ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir=$ac_optarg ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target_alias ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target_alias=$ac_optarg ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers | -V)
+ ac_init_version=: ;;
+
+ -with-* | --with-*)
+ ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid package name: $ac_package" >&2
+ { (exit 1); exit 1; }; }
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ case $ac_option in
+ *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "with_$ac_package='$ac_optarg'" ;;
+
+ -without-* | --without-*)
+ ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid package name: $ac_package" >&2
+ { (exit 1); exit 1; }; }
+ ac_package=`echo $ac_package | sed 's/-/_/g'`
+ eval "with_$ac_package=no" ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes=$ac_optarg ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries=$ac_optarg ;;
+
+ -*) { echo "$as_me: error: unrecognized option: $ac_option
+Try \`$0 --help' for more information." >&2
+ { (exit 1); exit 1; }; }
+ ;;
+
+ *=*)
+ ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid variable name: $ac_envvar" >&2
+ { (exit 1); exit 1; }; }
+ ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`
+ eval "$ac_envvar='$ac_optarg'"
+ export $ac_envvar ;;
+
+ *)
+ # FIXME: should be removed in autoconf 3.0.
+ echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+ expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+ : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+ { echo "$as_me: error: missing argument to $ac_option" >&2
+ { (exit 1); exit 1; }; }
+fi
+
+# Be sure to have absolute paths.
+for ac_var in exec_prefix prefix
+do
+ eval ac_val=$`echo $ac_var`
+ case $ac_val in
+ [\\/$]* | ?:[\\/]* | NONE | '' ) ;;
+ *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
+ { (exit 1); exit 1; }; };;
+ esac
+done
+
+# Be sure to have absolute paths.
+for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \
+ localstatedir libdir includedir oldincludedir infodir mandir
+do
+ eval ac_val=$`echo $ac_var`
+ case $ac_val in
+ [\\/$]* | ?:[\\/]* ) ;;
+ *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
+ { (exit 1); exit 1; }; };;
+ esac
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+ if test "x$build_alias" = x; then
+ cross_compiling=maybe
+ echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host.
+ If a cross compiler is detected then cross compile mode will be used." >&2
+ elif test "x$build_alias" != "x$host_alias"; then
+ cross_compiling=yes
+ fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then its parent.
+ ac_confdir=`(dirname "$0") 2>/dev/null ||
+$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$0" : 'X\(//\)[^/]' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X"$0" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+ /^X\(\/\/\)$/{ s//\1/; q; }
+ /^X\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+ srcdir=$ac_confdir
+ if test ! -r $srcdir/$ac_unique_file; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r $srcdir/$ac_unique_file; then
+ if test "$ac_srcdir_defaulted" = yes; then
+ { echo "$as_me: error: cannot find sources ($ac_unique_file) in $ac_confdir or .." >&2
+ { (exit 1); exit 1; }; }
+ else
+ { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2
+ { (exit 1); exit 1; }; }
+ fi
+fi
+(cd $srcdir && test -r ./$ac_unique_file) 2>/dev/null ||
+ { echo "$as_me: error: sources are in $srcdir, but \`cd $srcdir' does not work" >&2
+ { (exit 1); exit 1; }; }
+srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'`
+ac_env_build_alias_set=${build_alias+set}
+ac_env_build_alias_value=$build_alias
+ac_cv_env_build_alias_set=${build_alias+set}
+ac_cv_env_build_alias_value=$build_alias
+ac_env_host_alias_set=${host_alias+set}
+ac_env_host_alias_value=$host_alias
+ac_cv_env_host_alias_set=${host_alias+set}
+ac_cv_env_host_alias_value=$host_alias
+ac_env_target_alias_set=${target_alias+set}
+ac_env_target_alias_value=$target_alias
+ac_cv_env_target_alias_set=${target_alias+set}
+ac_cv_env_target_alias_value=$target_alias
+ac_env_CC_set=${CC+set}
+ac_env_CC_value=$CC
+ac_cv_env_CC_set=${CC+set}
+ac_cv_env_CC_value=$CC
+ac_env_CFLAGS_set=${CFLAGS+set}
+ac_env_CFLAGS_value=$CFLAGS
+ac_cv_env_CFLAGS_set=${CFLAGS+set}
+ac_cv_env_CFLAGS_value=$CFLAGS
+ac_env_LDFLAGS_set=${LDFLAGS+set}
+ac_env_LDFLAGS_value=$LDFLAGS
+ac_cv_env_LDFLAGS_set=${LDFLAGS+set}
+ac_cv_env_LDFLAGS_value=$LDFLAGS
+ac_env_CPPFLAGS_set=${CPPFLAGS+set}
+ac_env_CPPFLAGS_value=$CPPFLAGS
+ac_cv_env_CPPFLAGS_set=${CPPFLAGS+set}
+ac_cv_env_CPPFLAGS_value=$CPPFLAGS
+ac_env_CPP_set=${CPP+set}
+ac_env_CPP_value=$CPP
+ac_cv_env_CPP_set=${CPP+set}
+ac_cv_env_CPP_value=$CPP
+ac_env_F77_set=${F77+set}
+ac_env_F77_value=$F77
+ac_cv_env_F77_set=${F77+set}
+ac_cv_env_F77_value=$F77
+ac_env_FFLAGS_set=${FFLAGS+set}
+ac_env_FFLAGS_value=$FFLAGS
+ac_cv_env_FFLAGS_set=${FFLAGS+set}
+ac_cv_env_FFLAGS_value=$FFLAGS
+ac_env_CXX_set=${CXX+set}
+ac_env_CXX_value=$CXX
+ac_cv_env_CXX_set=${CXX+set}
+ac_cv_env_CXX_value=$CXX
+ac_env_CXXFLAGS_set=${CXXFLAGS+set}
+ac_env_CXXFLAGS_value=$CXXFLAGS
+ac_cv_env_CXXFLAGS_set=${CXXFLAGS+set}
+ac_cv_env_CXXFLAGS_value=$CXXFLAGS
+ac_env_CXXCPP_set=${CXXCPP+set}
+ac_env_CXXCPP_value=$CXXCPP
+ac_cv_env_CXXCPP_set=${CXXCPP+set}
+ac_cv_env_CXXCPP_value=$CXXCPP
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat <<_ACEOF
+\`configure' configures SUNDIALS 2.5.0 to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE. See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+ -h, --help display this help and exit
+ --help=short display options specific to this package
+ --help=recursive display the short help of all the included packages
+ -V, --version display version information and exit
+ -q, --quiet, --silent do not print \`checking...' messages
+ --cache-file=FILE cache test results in FILE [disabled]
+ -C, --config-cache alias for \`--cache-file=config.cache'
+ -n, --no-create do not create output files
+ --srcdir=DIR find the sources in DIR [configure dir or \`..']
+
+_ACEOF
+
+ cat <<_ACEOF
+Installation directories:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+ --bindir=DIR user executables [EPREFIX/bin]
+ --sbindir=DIR system admin executables [EPREFIX/sbin]
+ --libexecdir=DIR program executables [EPREFIX/libexec]
+ --datadir=DIR read-only architecture-independent data [PREFIX/share]
+ --sysconfdir=DIR read-only single-machine data [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data [PREFIX/var]
+ --libdir=DIR object code libraries [EPREFIX/lib]
+ --includedir=DIR C header files [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc [/usr/include]
+ --infodir=DIR info documentation [PREFIX/info]
+ --mandir=DIR man documentation [PREFIX/man]
+_ACEOF
+
+ cat <<\_ACEOF
+
+System types:
+ --build=BUILD configure for building on BUILD [guessed]
+ --host=HOST cross-compile to build programs to run on HOST [BUILD]
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+ case $ac_init_help in
+ short | recursive ) echo "Configuration of SUNDIALS 2.5.0:";;
+ esac
+ cat <<\_ACEOF
+
+Optional Features:
+ --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
+ --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
+ --disable-cvode disable configuration of CVODE
+ --disable-cvodes disable configuration of CVODES
+ --disable-ida disable configuration of IDA
+ --disable-idas disable configuration of IDAS
+ --disable-kinsol disable configuration of KINSOL
+ --disable-cpodes disable configuration of CPODES
+ --disable-fcmix disable Fortran-C support
+ --disable-lapack disable Lapack support
+ --disable-mpi disable MPI support
+ --enable-examples enable configuration of examples
+ --enable-shared[=PKGS]
+ build shared libraries [default=no]
+ --enable-static[=PKGS]
+ build static libraries [default=yes]
+ --enable-fast-install[=PKGS]
+ optimize for fast installation [default=yes]
+ --disable-libtool-lock avoid locking (might break parallel builds)
+
+Optional Packages:
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+
+ --with-precision=ARG specify floating-point precision
+ (single/double/extended) [double]
+
+ --with-cflags=ARG specify C compiler flags (CFLAGS will be overridden)
+ --with-cppflags=ARG specify C/C++ preprocessor flags (CPPFLAGS will be
+ overridden)
+ --with-ldflags=ARG specify linker flags (LDFLAGS will be overridden)
+ --with-libs=ARG add extra libraries
+ --with-fflags=ARG add extra Fortran compiler flags
+ --with-blas=ARG specify Blas library
+ --with-lapack=ARG specify Lapack library
+
+ --with-mpi-root=MPIROOT use MPI root directory
+ --with-mpi-incdir=DIR MPI include directory [MPIROOT/include]
+ --with-mpi-libdir=DIR MPI library directory [MPIROOT/lib]
+ --with-mpi-libs=ARG MPI libraries
+ --with-mpi-flags=ARG MPI-specific flags
+ --with-mpicc[=ARG] specify MPI-C compiler to use [mpicc]
+ --with-mpif77[=ARG] specify MPI-Fortran compiler to use [mpif77]
+
+ --with-exinstdir=DIR install SUNDIALS examples in DIR
+ [EPREFIX/examples]
+ --with-gnu-ld assume the C compiler uses GNU ld [default=no]
+ --with-pic try to use only PIC/non-PIC objects [default=use
+ both]
+ --with-tags[=TAGS]
+ include additional configurations [automatic]
+
+NOTES
+ It is legal to set --with-exinstdir to "no", in which case the examples
+ are built but not installed.
+ Enabling the compilation of the examples (--enable-examples) but disabling their
+ installation (--with-exinstdir=no) can be used to test the SUNDIALS libraries.
+
+Some influential environment variables:
+ CC C compiler command
+ CFLAGS C compiler flags
+ LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a
+ nonstandard directory <lib dir>
+ CPPFLAGS C/C++ preprocessor flags, e.g. -I<include dir> if you have
+ headers in a nonstandard directory <include dir>
+ CPP C preprocessor
+ F77 Fortran 77 compiler command
+ FFLAGS Fortran 77 compiler flags
+ CXX C++ compiler command
+ CXXFLAGS C++ compiler flags
+ CXXCPP C++ preprocessor
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+Report bugs to <radu at llnl.gov>.
+_ACEOF
+fi
+
+if test "$ac_init_help" = "recursive"; then
+ # If there are subdirs, report their specific --help.
+ ac_popdir=`pwd`
+ for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+ test -d $ac_dir || continue
+ ac_builddir=.
+
+if test "$ac_dir" != .; then
+ ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+ # A "../" for each directory in $ac_dir_suffix.
+ ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
+else
+ ac_dir_suffix= ac_top_builddir=
+fi
+
+case $srcdir in
+ .) # No --srcdir option. We are building in place.
+ ac_srcdir=.
+ if test -z "$ac_top_builddir"; then
+ ac_top_srcdir=.
+ else
+ ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
+ fi ;;
+ [\\/]* | ?:[\\/]* ) # Absolute path.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir ;;
+ *) # Relative path.
+ ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_builddir$srcdir ;;
+esac
+
+# Do not use `cd foo && pwd` to compute absolute paths, because
+# the directories may not exist.
+case `pwd` in
+.) ac_abs_builddir="$ac_dir";;
+*)
+ case "$ac_dir" in
+ .) ac_abs_builddir=`pwd`;;
+ [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";;
+ *) ac_abs_builddir=`pwd`/"$ac_dir";;
+ esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_builddir=${ac_top_builddir}.;;
+*)
+ case ${ac_top_builddir}. in
+ .) ac_abs_top_builddir=$ac_abs_builddir;;
+ [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
+ *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
+ esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_srcdir=$ac_srcdir;;
+*)
+ case $ac_srcdir in
+ .) ac_abs_srcdir=$ac_abs_builddir;;
+ [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
+ *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
+ esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_srcdir=$ac_top_srcdir;;
+*)
+ case $ac_top_srcdir in
+ .) ac_abs_top_srcdir=$ac_abs_builddir;;
+ [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
+ *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
+ esac;;
+esac
+
+ cd $ac_dir
+ # Check for guested configure; otherwise get Cygnus style configure.
+ if test -f $ac_srcdir/configure.gnu; then
+ echo
+ $SHELL $ac_srcdir/configure.gnu --help=recursive
+ elif test -f $ac_srcdir/configure; then
+ echo
+ $SHELL $ac_srcdir/configure --help=recursive
+ elif test -f $ac_srcdir/configure.ac ||
+ test -f $ac_srcdir/configure.in; then
+ echo
+ $ac_configure --help
+ else
+ echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+ fi
+ cd $ac_popdir
+ done
+fi
+
+test -n "$ac_init_help" && exit 0
+if $ac_init_version; then
+ cat <<\_ACEOF
+SUNDIALS configure 2.5.0
+generated by GNU Autoconf 2.59
+
+Copyright (C) 2003 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+
+
+Copyright (c) 2002, The Regents of the University of California.
+Produced at the Lawrence Livermore National Laboratory.
+All rights reserved.
+For details, see the LICENSE file.
+
+_ACEOF
+ exit 0
+fi
+exec 5>config.log
+cat >&5 <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by SUNDIALS $as_me 2.5.0, which was
+generated by GNU Autoconf 2.59. Invocation command line was
+
+ $ $0 $@
+
+_ACEOF
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown`
+
+/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+hostinfo = `(hostinfo) 2>/dev/null || echo unknown`
+/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown`
+/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ echo "PATH: $as_dir"
+done
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_sep=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+ for ac_arg
+ do
+ case $ac_arg in
+ -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ continue ;;
+ *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*)
+ ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ case $ac_pass in
+ 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;;
+ 2)
+ ac_configure_args1="$ac_configure_args1 '$ac_arg'"
+ if test $ac_must_keep_next = true; then
+ ac_must_keep_next=false # Got value, back to normal.
+ else
+ case $ac_arg in
+ *=* | --config-cache | -C | -disable-* | --disable-* \
+ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+ | -with-* | --with-* | -without-* | --without-* | --x)
+ case "$ac_configure_args0 " in
+ "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+ esac
+ ;;
+ -* ) ac_must_keep_next=true ;;
+ esac
+ fi
+ ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'"
+ # Get rid of the leading space.
+ ac_sep=" "
+ ;;
+ esac
+ done
+done
+$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; }
+$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; }
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log. We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Be sure not to use single quotes in there, as some shells,
+# such as our DU 5.0 friend, will then `close' the trap.
+trap 'exit_status=$?
+ # Save into config.log some information that might help in debugging.
+ {
+ echo
+
+ cat <<\_ASBOX
+## ---------------- ##
+## Cache variables. ##
+## ---------------- ##
+_ASBOX
+ echo
+ # The following way of writing the cache mishandles newlines in values,
+{
+ (set) 2>&1 |
+ case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in
+ *ac_space=\ *)
+ sed -n \
+ "s/'"'"'/'"'"'\\\\'"'"''"'"'/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p"
+ ;;
+ *)
+ sed -n \
+ "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
+ ;;
+ esac;
+}
+ echo
+
+ cat <<\_ASBOX
+## ----------------- ##
+## Output variables. ##
+## ----------------- ##
+_ASBOX
+ echo
+ for ac_var in $ac_subst_vars
+ do
+ eval ac_val=$`echo $ac_var`
+ echo "$ac_var='"'"'$ac_val'"'"'"
+ done | sort
+ echo
+
+ if test -n "$ac_subst_files"; then
+ cat <<\_ASBOX
+## ------------- ##
+## Output files. ##
+## ------------- ##
+_ASBOX
+ echo
+ for ac_var in $ac_subst_files
+ do
+ eval ac_val=$`echo $ac_var`
+ echo "$ac_var='"'"'$ac_val'"'"'"
+ done | sort
+ echo
+ fi
+
+ if test -s confdefs.h; then
+ cat <<\_ASBOX
+## ----------- ##
+## confdefs.h. ##
+## ----------- ##
+_ASBOX
+ echo
+ sed "/^$/d" confdefs.h | sort
+ echo
+ fi
+ test "$ac_signal" != 0 &&
+ echo "$as_me: caught signal $ac_signal"
+ echo "$as_me: exit $exit_status"
+ } >&5
+ rm -f core *.core &&
+ rm -rf conftest* confdefs* conf$$* $ac_clean_files &&
+ exit $exit_status
+ ' 0
+for ac_signal in 1 2 13 15; do
+ trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -rf conftest* confdefs.h
+# AIX cpp loses on an empty file, so make sure it contains at least a newline.
+echo >confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer explicitly selected file to automatically selected ones.
+if test -z "$CONFIG_SITE"; then
+ if test "x$prefix" != xNONE; then
+ CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
+ else
+ CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
+ fi
+fi
+for ac_site_file in $CONFIG_SITE; do
+ if test -r "$ac_site_file"; then
+ { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5
+echo "$as_me: loading site script $ac_site_file" >&6;}
+ sed 's/^/| /' "$ac_site_file" >&5
+ . "$ac_site_file"
+ fi
+done
+
+if test -r "$cache_file"; then
+ # Some versions of bash will fail to source /dev/null (special
+ # files actually), so we avoid doing that.
+ if test -f "$cache_file"; then
+ { echo "$as_me:$LINENO: loading cache $cache_file" >&5
+echo "$as_me: loading cache $cache_file" >&6;}
+ case $cache_file in
+ [\\/]* | ?:[\\/]* ) . $cache_file;;
+ *) . ./$cache_file;;
+ esac
+ fi
+else
+ { echo "$as_me:$LINENO: creating cache $cache_file" >&5
+echo "$as_me: creating cache $cache_file" >&6;}
+ >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in `(set) 2>&1 |
+ sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do
+ eval ac_old_set=\$ac_cv_env_${ac_var}_set
+ eval ac_new_set=\$ac_env_${ac_var}_set
+ eval ac_old_val="\$ac_cv_env_${ac_var}_value"
+ eval ac_new_val="\$ac_env_${ac_var}_value"
+ case $ac_old_set,$ac_new_set in
+ set,)
+ { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,set)
+ { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,);;
+ *)
+ if test "x$ac_old_val" != "x$ac_new_val"; then
+ { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5
+echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+ { echo "$as_me:$LINENO: former value: $ac_old_val" >&5
+echo "$as_me: former value: $ac_old_val" >&2;}
+ { echo "$as_me:$LINENO: current value: $ac_new_val" >&5
+echo "$as_me: current value: $ac_new_val" >&2;}
+ ac_cache_corrupted=:
+ fi;;
+ esac
+ # Pass precious variables to config.status.
+ if test "$ac_new_set" = set; then
+ case $ac_new_val in
+ *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*)
+ ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+ *) ac_arg=$ac_var=$ac_new_val ;;
+ esac
+ case " $ac_configure_args " in
+ *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy.
+ *) ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+ esac
+ fi
+done
+if $ac_cache_corrupted; then
+ { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5
+echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+ { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5
+echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# Display greeting
+
+
+# Say Hi!
+echo "
+---------------------------------
+Running SUNDIALS Configure Script
+---------------------------------
+"
+
+
+
+# Specify directory containing auxillary build tools and M4 files
+ac_aux_dir=
+for ac_dir in config $srcdir/config; do
+ if test -f $ac_dir/install-sh; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install-sh -c"
+ break
+ elif test -f $ac_dir/install.sh; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install.sh -c"
+ break
+ elif test -f $ac_dir/shtool; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/shtool install -c"
+ break
+ fi
+done
+if test -z "$ac_aux_dir"; then
+ { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in config $srcdir/config" >&5
+echo "$as_me: error: cannot find install-sh or install.sh in config $srcdir/config" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+ac_config_guess="$SHELL $ac_aux_dir/config.guess"
+ac_config_sub="$SHELL $ac_aux_dir/config.sub"
+ac_configure="$SHELL $ac_aux_dir/configure" # This should be Cygnus configure.
+
+
+# Miscellaneous SUNDIALS initializations
+echo "Initialization"
+echo "--------------"
+echo ""
+
+
+# Reference custom macros
+# This file is part of Autoconf. -*- Autoconf -*-
+# Fortran languages support.
+# Copyright (C) 2001, 2003
+# Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+# 02111-1307, USA.
+#
+# As a special exception, the Free Software Foundation gives unlimited
+# permission to copy, distribute and modify the configure scripts that
+# are the output of Autoconf. You need not follow the terms of the GNU
+# General Public License when using or distributing such scripts, even
+# though portions of the text of Autoconf appear in them. The GNU
+# General Public License (GPL) does govern all other use of the material
+# that constitutes the Autoconf program.
+#
+# Certain portions of the Autoconf source text are designed to be copied
+# (in certain cases, depending on the input) into the output of
+# Autoconf. We call these the "data" portions. The rest of the Autoconf
+# source text consists of comments plus executable code that decides which
+# of the data portions to output in any given case. We call these
+# comments and executable code the "non-data" portions. Autoconf never
+# copies any of the non-data portions into its output.
+#
+# This special exception to the GPL applies to versions of Autoconf
+# released by the Free Software Foundation. When you make and
+# distribute a modified version of Autoconf, you may extend this special
+# exception to the GPL to apply to your modified version as well, *unless*
+# your modified version has the potential to copy into its output some
+# of the text that was the non-data portion of the version that you started
+# with. (In other words, unless your change moves or copies text from
+# the non-data portions to the data portions.) If your modification has
+# such potential, you must delete any notice of this special exception
+# to the GPL from your modified version.
+#
+# Written by David MacKenzie, with help from
+# Franc,ois Pinard, Karl Berry, Richard Pixley, Ian Lance Taylor,
+# Roland McGrath, Noah Friedman, david d zuhn, and many others.
+
+# Fortran vs. Fortran 77:
+# This file contains macros for both "Fortran 77" and "Fortran", where
+# the former is the "classic" autoconf Fortran interface and is intended
+# for legacy F77 codes, while the latter is intended to support newer Fortran
+# dialects. Fortran 77 uses environment variables F77, FFLAGS, and FLIBS,
+# while Fortran uses FC, FCFLAGS, and FCLIBS. For each user-callable AC_*
+# macro, there is generally both an F77 and an FC version, where both versions
+# share the same _AC_*_FC_* backend. This backend macro requires that
+# the appropriate language be AC_LANG_PUSH'ed, and uses _AC_LANG_ABBREV and
+# _AC_LANG_PREFIX in order to name cache and environment variables, etc.
+
+
+# _AC_PROG_FC_V_OUTPUT([FLAG = $ac_cv_prog_{f77/fc}_v])
+# -------------------------------------------------
+# Link a trivial Fortran program, compiling with a verbose output FLAG
+# (whose default value, $ac_cv_prog_{f77/fc}_v, is computed by
+# _AC_PROG_FC_V), and return the output in $ac_{f77/fc}_v_output. This
+# output is processed in the way expected by _AC_FC_LIBRARY_LDFLAGS,
+# so that any link flags that are echoed by the compiler appear as
+# space-separated items.
+# _AC_PROG_FC_V_OUTPUT
+
+# This file is part of Autoconf. -*- Autoconf -*-
+# Programming languages support.
+# Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+# 02111-1307, USA.
+#
+# As a special exception, the Free Software Foundation gives unlimited
+# permission to copy, distribute and modify the configure scripts that
+# are the output of Autoconf. You need not follow the terms of the GNU
+# General Public License when using or distributing such scripts, even
+# though portions of the text of Autoconf appear in them. The GNU
+# General Public License (GPL) does govern all other use of the material
+# that constitutes the Autoconf program.
+#
+# Certain portions of the Autoconf source text are designed to be copied
+# (in certain cases, depending on the input) into the output of
+# Autoconf. We call these the "data" portions. The rest of the Autoconf
+# source text consists of comments plus executable code that decides which
+# of the data portions to output in any given case. We call these
+# comments and executable code the "non-data" portions. Autoconf never
+# copies any of the non-data portions into its output.
+#
+# This special exception to the GPL applies to versions of Autoconf
+# released by the Free Software Foundation. When you make and
+# distribute a modified version of Autoconf, you may extend this special
+# exception to the GPL to apply to your modified version as well, *unless*
+# your modified version has the potential to copy into its output some
+# of the text that was the non-data portion of the version that you started
+# with. (In other words, unless your change moves or copies text from
+# the non-data portions to the data portions.) If your modification has
+# such potential, you must delete any notice of this special exception
+# to the GPL from your modified version.
+#
+# Written by David MacKenzie, with help from
+# Franc,ois Pinard, Karl Berry, Richard Pixley, Ian Lance Taylor,
+# Roland McGrath, Noah Friedman, david d zuhn, and many others.
+
+
+# AC_LANG(C)
+# ----------
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+
+
+# This file is part of Autoconf. -*- Autoconf -*-
+# Parameterized macros.
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
+# 2002, 2003, Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+# 02111-1307, USA.
+
+# As a special exception, the Free Software Foundation gives unlimited
+# permission to copy, distribute and modify the configure scripts that
+# are the output of Autoconf. You need not follow the terms of the GNU
+# General Public License when using or distributing such scripts, even
+# though portions of the text of Autoconf appear in them. The GNU
+# General Public License (GPL) does govern all other use of the material
+# that constitutes the Autoconf program.
+#
+# Certain portions of the Autoconf source text are designed to be copied
+# (in certain cases, depending on the input) into the output of
+# Autoconf. We call these the "data" portions. The rest of the Autoconf
+# source text consists of comments plus executable code that decides which
+# of the data portions to output in any given case. We call these
+# comments and executable code the "non-data" portions. Autoconf never
+# copies any of the non-data portions into its output.
+#
+# This special exception to the GPL applies to versions of Autoconf
+# released by the Free Software Foundation. When you make and
+# distribute a modified version of Autoconf, you may extend this special
+# exception to the GPL to apply to your modified version as well, *unless*
+# your modified version has the potential to copy into its output some
+# of the text that was the non-data portion of the version that you started
+# with. (In other words, unless your change moves or copies text from
+# the non-data portions to the data portions.) If your modification has
+# such potential, you must delete any notice of this special exception
+# to the GPL from your modified version.
+#
+# Written by David MacKenzie, with help from
+# Franc,ois Pinard, Karl Berry, Richard Pixley, Ian Lance Taylor,
+# Roland McGrath, Noah Friedman, david d zuhn, and many others.
+
+
+# _AC_MSG_LOG_CONFTEST_GENERAL
+# ----------------------------
+
+
+
+# _AC_LINKONLY_IFELSE(PROGRAM, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+# ------------------------------------------------------------------
+# Try to link PROGRAM (empty).
+# This macro can be used during the selection of a compiler.
+# _AC_LINKONLY_IFELSE
+
+
+# AC_LINKONLY_IFELSE(PROGRAM, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+# -----------------------------------------------------------------
+# Try to link PROGRAM. Requires that the compiler for the current
+# language was checked for, hence do not use this macro in macros looking
+# for a compiler.
+
+
+
+# Make input filename DOS compatible (change config.h.in to config.hin)
+ ac_config_headers="$ac_config_headers config.h:config.hin"
+
+
+# Make user aware of copyright notice (input COPYRIGHT information)
+
+
+# Specify root of source tree
+# Given file is guaranteed to exist in all SUNDIALS packages
+
+
+# Get host information
+# AC_CANONICAL_BUILD defines the following variables: build, build_cpu,
+# build_vendor, and build_os
+# Make sure we can run config.sub.
+$ac_config_sub sun4 >/dev/null 2>&1 ||
+ { { echo "$as_me:$LINENO: error: cannot run $ac_config_sub" >&5
+echo "$as_me: error: cannot run $ac_config_sub" >&2;}
+ { (exit 1); exit 1; }; }
+
+echo "$as_me:$LINENO: checking build system type" >&5
+echo $ECHO_N "checking build system type... $ECHO_C" >&6
+if test "${ac_cv_build+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_cv_build_alias=$build_alias
+test -z "$ac_cv_build_alias" &&
+ ac_cv_build_alias=`$ac_config_guess`
+test -z "$ac_cv_build_alias" &&
+ { { echo "$as_me:$LINENO: error: cannot guess build type; you must specify one" >&5
+echo "$as_me: error: cannot guess build type; you must specify one" >&2;}
+ { (exit 1); exit 1; }; }
+ac_cv_build=`$ac_config_sub $ac_cv_build_alias` ||
+ { { echo "$as_me:$LINENO: error: $ac_config_sub $ac_cv_build_alias failed" >&5
+echo "$as_me: error: $ac_config_sub $ac_cv_build_alias failed" >&2;}
+ { (exit 1); exit 1; }; }
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_build" >&5
+echo "${ECHO_T}$ac_cv_build" >&6
+build=$ac_cv_build
+build_cpu=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+build_vendor=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+build_os=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+
+
+# AC_CANONICAL_HOST defines the following variables: host, host_cpu,
+# host_vendor, and host_os
+echo "$as_me:$LINENO: checking host system type" >&5
+echo $ECHO_N "checking host system type... $ECHO_C" >&6
+if test "${ac_cv_host+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_cv_host_alias=$host_alias
+test -z "$ac_cv_host_alias" &&
+ ac_cv_host_alias=$ac_cv_build_alias
+ac_cv_host=`$ac_config_sub $ac_cv_host_alias` ||
+ { { echo "$as_me:$LINENO: error: $ac_config_sub $ac_cv_host_alias failed" >&5
+echo "$as_me: error: $ac_config_sub $ac_cv_host_alias failed" >&2;}
+ { (exit 1); exit 1; }; }
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_host" >&5
+echo "${ECHO_T}$ac_cv_host" >&6
+host=$ac_cv_host
+host_cpu=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+host_vendor=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+host_os=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+
+
+
+# Set MAKE if necessary
+# Must include @SET_MAKE@ in each Makefile.in file
+# AC_SUBST is called automatically for SET_MAKE
+echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \$(MAKE)" >&5
+echo $ECHO_N "checking whether ${MAKE-make} sets \$(MAKE)... $ECHO_C" >&6
+set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y,:./+-,___p_,'`
+if eval "test \"\${ac_cv_prog_make_${ac_make}_set+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.make <<\_ACEOF
+all:
+ @echo 'ac_maketemp="$(MAKE)"'
+_ACEOF
+# GNU make sometimes prints "make[1]: Entering...", which would confuse us.
+eval `${MAKE-make} -f conftest.make 2>/dev/null | grep temp=`
+if test -n "$ac_maketemp"; then
+ eval ac_cv_prog_make_${ac_make}_set=yes
+else
+ eval ac_cv_prog_make_${ac_make}_set=no
+fi
+rm -f conftest.make
+fi
+if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then
+ echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+ SET_MAKE=
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+ SET_MAKE="MAKE=${MAKE-make}"
+fi
+
+
+# Defines INSTALL (sets to path of "install" program)
+# Also sets INSTALL_PROGRAM and INSTALL_SCRIPT
+# Find a good install program. We prefer a C program (faster),
+# so one script is as good as another. But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AmigaOS /C/install, which installs bootblocks on floppy discs
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# OS/2's system install, which has a completely different semantic
+# ./install, which can be erroneously created by make from ./install.sh.
+echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5
+echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6
+if test -z "$INSTALL"; then
+if test "${ac_cv_path_install+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ # Account for people who put trailing slashes in PATH elements.
+case $as_dir/ in
+ ./ | .// | /cC/* | \
+ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
+ ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \
+ /usr/ucb/* ) ;;
+ *)
+ # OSF1 and SCO ODT 3.0 have their own names for install.
+ # Don't use installbsd from OSF since it installs stuff as root
+ # by default.
+ for ac_prog in ginstall scoinst install; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then
+ if test $ac_prog = install &&
+ grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+ # AIX install. It has an incompatible calling convention.
+ :
+ elif test $ac_prog = install &&
+ grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+ # program-specific install script used by HP pwplus--don't use.
+ :
+ else
+ ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
+ break 3
+ fi
+ fi
+ done
+ done
+ ;;
+esac
+done
+
+
+fi
+ if test "${ac_cv_path_install+set}" = set; then
+ INSTALL=$ac_cv_path_install
+ else
+ # As a last resort, use the slow shell script. We don't cache a
+ # path for INSTALL within a source directory, because that will
+ # break other packages using the cache if that directory is
+ # removed, or if the path is relative.
+ INSTALL=$ac_install_sh
+ fi
+fi
+echo "$as_me:$LINENO: result: $INSTALL" >&5
+echo "${ECHO_T}$INSTALL" >&6
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+
+# Set defaults for config/sundials_config.in file
+F77_MANGLE_MACRO1=""
+F77_MANGLE_MACRO2=""
+PRECISION_LEVEL=""
+GENERIC_MATH_LIB=""
+BLAS_LAPACK_MACRO=""
+F77_MPI_COMM_F2C=""
+SUNDIALS_EXPORT="#define SUNDIALS_EXPORT"
+
+# Initialize enable status of various modules, options, and features
+# to their default values
+#
+# NOTE: when CPODES is released, change its default to enabled.
+#
+CVODE_ENABLED="yes"
+CVODES_ENABLED="yes"
+IDA_ENABLED="yes"
+IDAS_ENABLED="yes"
+KINSOL_ENABLED="yes"
+LAPACK_ENABLED="yes"
+FCMIX_ENABLED="yes"
+MPI_ENABLED="yes"
+#
+CPODES_ENABLED="no"
+#
+EXAMPLES_ENABLED="no"
+F77_EXAMPLES_ENABLED="no"
+
+# Initialize variables that may NOT necessarily be initialized
+# during normal execution. Should NOT use uninitialized variables
+F77_OK="no"
+LAPACK_OK="no"
+MPI_C_COMP_OK="no"
+MPI_F77_COMP_OK="no"
+
+# This variable is set to "yes" if an AC_MSG_WARN statement
+# was executed
+SUNDIALS_WARN_FLAG="no"
+
+
+
+# Test enable/disable features
+
+
+# Check if user wants to disable CVODE module
+# If not, then make certain source directory actually exists
+# Check whether --enable-cvode or --disable-cvode was given.
+if test "${enable_cvode+set}" = set; then
+ enableval="$enable_cvode"
+
+if test "X${enableval}" = "Xno"; then
+ CVODE_ENABLED="no"
+fi
+
+else
+
+if test -d ${srcdir}/src/cvode ; then
+ CVODE_ENABLED="yes"
+else
+ CVODE_ENABLED="no"
+fi
+
+fi;
+
+# Check if user wants to disable CVODES module
+# If not, then make certain source directory actually exists
+# Check whether --enable-cvodes or --disable-cvodes was given.
+if test "${enable_cvodes+set}" = set; then
+ enableval="$enable_cvodes"
+
+if test "X${enableval}" = "Xno"; then
+ CVODES_ENABLED="no"
+fi
+
+else
+
+if test -d ${srcdir}/src/cvodes ; then
+ CVODES_ENABLED="yes"
+else
+ CVODES_ENABLED="no"
+fi
+
+fi;
+
+# Check if user wants to disable IDA module
+# If not, then make certain source directory actually exists
+# Check whether --enable-ida or --disable-ida was given.
+if test "${enable_ida+set}" = set; then
+ enableval="$enable_ida"
+
+if test "X${enableval}" = "Xno"; then
+ IDA_ENABLED="no"
+fi
+
+else
+
+if test -d ${srcdir}/src/ida ; then
+ IDA_ENABLED="yes"
+else
+ IDA_ENABLED="no"
+fi
+
+fi;
+
+# Check if user wants to disable IDAS module
+# If not, then make certain source directory actually exists
+# Check whether --enable-idas or --disable-idas was given.
+if test "${enable_idas+set}" = set; then
+ enableval="$enable_idas"
+
+if test "X${enableval}" = "Xno"; then
+ IDAS_ENABLED="no"
+fi
+
+else
+
+if test -d ${srcdir}/src/idas ; then
+ IDAS_ENABLED="yes"
+else
+ IDAS_ENABLED="no"
+fi
+
+fi;
+
+# Check if user wants to disable KINSOL MODULE
+# If not, then make certain source directory actually exists
+# Check whether --enable-kinsol or --disable-kinsol was given.
+if test "${enable_kinsol+set}" = set; then
+ enableval="$enable_kinsol"
+
+if test "X${enableval}" = "Xno"; then
+ KINSOL_ENABLED="no"
+fi
+
+else
+
+if test -d ${srcdir}/src/kinsol ; then
+ KINSOL_ENABLED="yes"
+else
+ KINSOL_ENABLED="no"
+fi
+
+fi;
+
+# Check if user wants to disable CPODES module
+# If not, then make certain source directory actually exists
+# Check whether --enable-cpodes or --disable-cpodes was given.
+if test "${enable_cpodes+set}" = set; then
+ enableval="$enable_cpodes"
+
+if test "X${enableval}" = "Xno"; then
+ CPODES_ENABLED="no"
+fi
+
+else
+
+if test -d ${srcdir}/src/cpodes ; then
+ CPODES_ENABLED="yes"
+else
+ CPODES_ENABLED="no"
+fi
+
+fi;
+
+# Check if user wants to disable Fortran support (FCMIX components).
+# Check whether --enable-fcmix or --disable-fcmix was given.
+if test "${enable_fcmix+set}" = set; then
+ enableval="$enable_fcmix"
+
+if test "X${enableval}" = "Xno"; then
+ FCMIX_ENABLED="no"
+fi
+
+else
+
+if test "X${CVODE_ENABLED}" = "Xno" && test "X${KINSOL_ENABLED}" = "Xno" && test "X${IDA_ENABLED}" = "Xno"; then
+ FCMIX_ENABLED="no"
+fi
+
+fi;
+
+# Check if user wants to disable Lapack support.
+# Check whether --enable-lapack or --disable-lapack was given.
+if test "${enable_lapack+set}" = set; then
+ enableval="$enable_lapack"
+
+if test "X${enableval}" = "Xno"; then
+ LAPACK_ENABLED="no"
+fi
+
+fi;
+
+# Check if user wants to disable support for MPI.
+# If not, set the default based on whetehr certain source directories exist
+# Check whether --enable-mpi or --disable-mpi was given.
+if test "${enable_mpi+set}" = set; then
+ enableval="$enable_mpi"
+
+if test "X${enableval}" = "Xno"; then
+ MPI_ENABLED="no"
+fi
+
+else
+
+if test -d ${srcdir}/src/nvec_par || test -d ${srcdir}/src/nvec_spcpar; then
+ MPI_ENABLED="yes"
+else
+ MPI_ENABLED="no"
+fi
+
+fi;
+
+# Check if user wants to enable all examples.
+# Examples are NOT built by default
+# Check whether --enable-examples or --disable-examples was given.
+if test "${enable_examples+set}" = set; then
+ enableval="$enable_examples"
+
+if test "X${enableval}" = "Xno"; then
+ EXAMPLES_ENABLED="no"
+else
+ EXAMPLES_ENABLED="yes"
+fi
+
+fi;
+
+# Fortran examples are enabled only if both FCMIX and EXAMPLES are enabled
+if test "X${FCMIX_ENABLED}" = "Xyes" && test "X${EXAMPLES_ENABLED}" = "Xyes"; then
+ F77_EXAMPLES_ENABLED="yes"
+fi
+
+
+
+# Set C compilation (Required)
+echo ""
+echo "C Compiler Settings"
+echo "-------------------"
+echo ""
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_linkonly='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_objext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+ for ac_prog in cc gcc
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ test -n "$CC" && break
+ done
+fi
+if test -z "$CC"; then
+ ac_ct_CC=$CC
+ for ac_prog in cc gcc
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CC="$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ test -n "$ac_ct_CC" && break
+done
+
+ CC=$ac_ct_CC
+fi
+
+
+test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&5
+echo "$as_me: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+
+# Provide some information about the compiler.
+echo "$as_me:$LINENO:" \
+ "checking for C compiler version" >&5
+ac_compiler=`set X $ac_compile; echo $2`
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version </dev/null >&5\"") >&5
+ (eval $ac_compiler --version </dev/null >&5) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v </dev/null >&5\"") >&5
+ (eval $ac_compiler -v </dev/null >&5) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V </dev/null >&5\"") >&5
+ (eval $ac_compiler -V </dev/null >&5) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+echo "$as_me:$LINENO: checking for C compiler default output file name" >&5
+echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6
+ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+if { (eval echo "$as_me:$LINENO: \"$ac_link_default\"") >&5
+ (eval $ac_link_default) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ # Find the output, starting from the most likely. This scheme is
+# not robust to junk in `.', hence go to wildcards (a.*) only as a last
+# resort.
+
+# Be careful to initialize this variable, since it used to be cached.
+# Otherwise an old cache value of `no' led to `EXEEXT = no' in a Makefile.
+ac_cv_exeext=
+# b.out is created by i960 compilers.
+for ac_file in a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out
+do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj )
+ ;;
+ conftest.$ac_ext )
+ # This is the source file.
+ ;;
+ [ab].out )
+ # We found the default executable, but exeext='' is most
+ # certainly right.
+ break;;
+ *.* )
+ ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ # FIXME: I believe we export ac_cv_exeext for Libtool,
+ # but it would be cool to find out if it's true. Does anybody
+ # maintain Libtool? --akim.
+ export ac_cv_exeext
+ break;;
+ * )
+ break;;
+ esac
+done
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: C compiler cannot create executables
+See \`config.log' for more details." >&5
+echo "$as_me: error: C compiler cannot create executables
+See \`config.log' for more details." >&2;}
+ { (exit 77); exit 77; }; }
+fi
+
+ac_exeext=$ac_cv_exeext
+echo "$as_me:$LINENO: result: $ac_file" >&5
+echo "${ECHO_T}$ac_file" >&6
+
+# Check the compiler produces executables we can run. If not, either
+# the compiler is broken, or we cross compile.
+echo "$as_me:$LINENO: checking whether the C compiler works" >&5
+echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6
+# FIXME: These cross compiler hacks should be removed for Autoconf 3.0
+# If not cross compiling, check that we can run a simple program.
+if test "$cross_compiling" != yes; then
+ if { ac_try='./$ac_file'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ cross_compiling=no
+ else
+ if test "$cross_compiling" = maybe; then
+ cross_compiling=yes
+ else
+ { { echo "$as_me:$LINENO: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+ fi
+fi
+echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+
+rm -f a.out a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+# Check the compiler produces executables we can run. If not, either
+# the compiler is broken, or we cross compile.
+echo "$as_me:$LINENO: checking whether we are cross compiling" >&5
+echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6
+echo "$as_me:$LINENO: result: $cross_compiling" >&5
+echo "${ECHO_T}$cross_compiling" >&6
+
+echo "$as_me:$LINENO: checking for suffix of executables" >&5
+echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;;
+ *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ export ac_cv_exeext
+ break;;
+ * ) break;;
+ esac
+done
+else
+ { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+rm -f conftest$ac_cv_exeext
+echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5
+echo "${ECHO_T}$ac_cv_exeext" >&6
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+echo "$as_me:$LINENO: checking for suffix of object files" >&5
+echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6
+if test "${ac_cv_objext+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ for ac_file in `(ls conftest.o conftest.obj; ls conftest.*) 2>/dev/null`; do
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg ) ;;
+ *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+ break;;
+ esac
+done
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_objext" >&5
+echo "${ECHO_T}$ac_cv_objext" >&6
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5
+echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6
+if test "${ac_cv_c_compiler_gnu+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+#ifndef __GNUC__
+ choke me
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_compiler_gnu=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_compiler_gnu=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5
+echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6
+GCC=`test $ac_compiler_gnu = yes && echo yes`
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+CFLAGS="-g"
+echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5
+echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6
+if test "${ac_cv_prog_cc_g+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_prog_cc_g=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_prog_cc_g=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_g" >&6
+if test "$ac_test_CFLAGS" = set; then
+ CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+ if test "$GCC" = yes; then
+ CFLAGS="-g -O2"
+ else
+ CFLAGS="-g"
+ fi
+else
+ if test "$GCC" = yes; then
+ CFLAGS="-O2"
+ else
+ CFLAGS=
+ fi
+fi
+echo "$as_me:$LINENO: checking for $CC option to accept ANSI C" >&5
+echo $ECHO_N "checking for $CC option to accept ANSI C... $ECHO_C" >&6
+if test "${ac_cv_prog_cc_stdc+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_cv_prog_cc_stdc=no
+ac_save_CC=$CC
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+ char **p;
+ int i;
+{
+ return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+ char *s;
+ va_list v;
+ va_start (v,p);
+ s = g (p, va_arg (v,int));
+ va_end (v);
+ return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
+ function prototypes and stuff, but not '\xHH' hex character constants.
+ These don't provoke an error unfortunately, instead are silently treated
+ as 'x'. The following induces an error, until -std1 is added to get
+ proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an
+ array size at least. It's necessary to write '\x00'==0 to get something
+ that's true only with -std1. */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
+ ;
+ return 0;
+}
+_ACEOF
+# Don't try gcc -ansi; that turns off useful extensions and
+# breaks some systems' header files.
+# AIX -qlanglvl=ansi
+# Ultrix and OSF/1 -std1
+# HP-UX 10.20 and later -Ae
+# HP-UX older versions -Aa -D_HPUX_SOURCE
+# SVR4 -Xc -D__EXTENSIONS__
+for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+ CC="$ac_save_CC $ac_arg"
+ rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_prog_cc_stdc=$ac_arg
+break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext
+done
+rm -f conftest.$ac_ext conftest.$ac_objext
+CC=$ac_save_CC
+
+fi
+
+case "x$ac_cv_prog_cc_stdc" in
+ x|xno)
+ echo "$as_me:$LINENO: result: none needed" >&5
+echo "${ECHO_T}none needed" >&6 ;;
+ *)
+ echo "$as_me:$LINENO: result: $ac_cv_prog_cc_stdc" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6
+ CC="$CC $ac_cv_prog_cc_stdc" ;;
+esac
+
+# Some people use a C++ compiler to compile C. Since we use `exit',
+# in C++ we need to declare it. In case someone uses the same compiler
+# for both compiling C and C++ we need to have the C++ compiler decide
+# the declaration of exit, since it's the most demanding environment.
+cat >conftest.$ac_ext <<_ACEOF
+#ifndef __cplusplus
+ choke me
+#endif
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ for ac_declaration in \
+ '' \
+ 'extern "C" void std::exit (int) throw (); using std::exit;' \
+ 'extern "C" void std::exit (int); using std::exit;' \
+ 'extern "C" void exit (int) throw ();' \
+ 'extern "C" void exit (int);' \
+ 'void exit (int);'
+do
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_declaration
+#include <stdlib.h>
+int
+main ()
+{
+exit (42);
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+continue
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_declaration
+int
+main ()
+{
+exit (42);
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+rm -f conftest*
+if test -n "$ac_declaration"; then
+ echo '#ifdef __cplusplus' >>confdefs.h
+ echo $ac_declaration >>confdefs.h
+ echo '#endif' >>confdefs.h
+fi
+
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_linkonly='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_objext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+echo "$as_me:$LINENO: checking for egrep" >&5
+echo $ECHO_N "checking for egrep... $ECHO_C" >&6
+if test "${ac_cv_prog_egrep+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if echo a | (grep -E '(a|b)') >/dev/null 2>&1
+ then ac_cv_prog_egrep='grep -E'
+ else ac_cv_prog_egrep='egrep'
+ fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_prog_egrep" >&5
+echo "${ECHO_T}$ac_cv_prog_egrep" >&6
+ EGREP=$ac_cv_prog_egrep
+
+
+# On IRIX 5.3, sys/types and inttypes.h are conflicting.
+
+
+
+
+
+
+
+
+
+for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
+ inttypes.h stdint.h unistd.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ eval "$as_ac_Header=yes"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_Header=no"
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+
+
+
+if test "X${CC}" = "X"; then
+
+ echo ""
+ echo " Unable to find a working C compiler"
+ echo ""
+ echo " Try using CC to explicitly specify a C compiler"
+ echo ""
+
+ { { echo "$as_me:$LINENO: error: cannot find a C compiler" >&5
+echo "$as_me: error: cannot find a C compiler" >&2;}
+ { (exit 1); exit 1; }; }
+
+else
+
+
+
+# Default is C programming language (initialize language stack)
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_linkonly='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_objext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+# Check whether --with- or --without- was given.
+if test "${with_+set}" = set; then
+ withval="$with_"
+
+fi;
+
+# Set floating-point precision: single [C type 'float']
+# double [C type 'double'] (default)
+# extended [C type 'long double']
+# Provide variable description templates for config.hin and config.h files
+# Required by autoheader utility
+
+
+
+
+
+
+
+echo "$as_me:$LINENO: checking floating-point data type to use" >&5
+echo $ECHO_N "checking floating-point data type to use... $ECHO_C" >&6
+
+# Check whether --with-precision or --without-precision was given.
+if test "${with_precision+set}" = set; then
+ withval="$with_precision"
+
+if test "X${withval}" = "Xsingle"; then
+ echo "$as_me:$LINENO: result: float" >&5
+echo "${ECHO_T}float" >&6
+ cat >>confdefs.h <<\_ACEOF
+#define SUNDIALS_SINGLE_PRECISION 1
+_ACEOF
+
+ FLOAT_TYPE="single"
+ PRECISION_LEVEL="#define SUNDIALS_SINGLE_PRECISION 1"
+elif test "X${withval}" = "Xdouble"; then
+ echo "$as_me:$LINENO: result: double" >&5
+echo "${ECHO_T}double" >&6
+ cat >>confdefs.h <<\_ACEOF
+#define SUNDIALS_DOUBLE_PRECISION 1
+_ACEOF
+
+ FLOAT_TYPE="double"
+ PRECISION_LEVEL="#define SUNDIALS_DOUBLE_PRECISION 1"
+elif test "X${withval}" = "Xextended"; then
+ echo "$as_me:$LINENO: result: long double" >&5
+echo "${ECHO_T}long double" >&6
+ cat >>confdefs.h <<\_ACEOF
+#define SUNDIALS_EXTENDED_PRECISION 1
+_ACEOF
+
+ FLOAT_TYPE="extended"
+ PRECISION_LEVEL="#define SUNDIALS_EXTENDED_PRECISION 1"
+else
+ { { echo "$as_me:$LINENO: error: invalid input" >&5
+echo "$as_me: error: invalid input" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+else
+
+# Use 'double' by default
+echo "$as_me:$LINENO: result: double" >&5
+echo "${ECHO_T}double" >&6
+cat >>confdefs.h <<\_ACEOF
+#define SUNDIALS_DOUBLE_PRECISION 1
+_ACEOF
+
+FLOAT_TYPE="double"
+PRECISION_LEVEL="#define SUNDIALS_DOUBLE_PRECISION 1"
+
+fi;
+
+
+# Check whether --with- or --without- was given.
+if test "${with_+set}" = set; then
+ withval="$with_"
+
+fi;
+
+# Overwrite CFLAGS
+echo "$as_me:$LINENO: checking for C compiler flags" >&5
+echo $ECHO_N "checking for C compiler flags... $ECHO_C" >&6
+
+# Check whether --with-cflags or --without-cflags was given.
+if test "${with_cflags+set}" = set; then
+ withval="$with_cflags"
+
+echo "$as_me:$LINENO: result: ${withval}" >&5
+echo "${ECHO_T}${withval}" >&6
+CFLAGS="${withval}"
+
+else
+
+echo "$as_me:$LINENO: result: none" >&5
+echo "${ECHO_T}none" >&6
+
+fi;
+
+# Set CPP to command that runs C preprocessor
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_linkonly='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_objext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5
+echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+ CPP=
+fi
+if test -z "$CPP"; then
+ if test "${ac_cv_prog_CPP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ # Double quotes because CPP needs to be expanded
+ for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+ do
+ ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether non-existent headers
+ # can be detected and how.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ # Broken: success on invalid input.
+continue
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+ break
+fi
+
+ done
+ ac_cv_prog_CPP=$CPP
+
+fi
+ CPP=$ac_cv_prog_CPP
+else
+ ac_cv_prog_CPP=$CPP
+fi
+echo "$as_me:$LINENO: result: $CPP" >&5
+echo "${ECHO_T}$CPP" >&6
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether non-existent headers
+ # can be detected and how.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ # Broken: success on invalid input.
+continue
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+ :
+else
+ { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." >&5
+echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_linkonly='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_objext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+# Overwrite CPPFLAGS
+echo "$as_me:$LINENO: checking for C/C++ preprocessor flags" >&5
+echo $ECHO_N "checking for C/C++ preprocessor flags... $ECHO_C" >&6
+
+# Check whether --with-cppflags or --without-cppflags was given.
+if test "${with_cppflags+set}" = set; then
+ withval="$with_cppflags"
+
+echo "$as_me:$LINENO: result: ${withval}" >&5
+echo "${ECHO_T}${withval}" >&6
+CPPFLAGS="${withval}"
+
+else
+
+echo "$as_me:$LINENO: result: none" >&5
+echo "${ECHO_T}none" >&6
+
+fi;
+
+# Overwrite LDFLAGS
+echo "$as_me:$LINENO: checking for linker flags" >&5
+echo $ECHO_N "checking for linker flags... $ECHO_C" >&6
+
+# Check whether --with-ldflags or --without-ldflags was given.
+if test "${with_ldflags+set}" = set; then
+ withval="$with_ldflags"
+
+echo "$as_me:$LINENO: result: ${withval}" >&5
+echo "${ECHO_T}${withval}" >&6
+LDFLAGS="${withval}"
+
+else
+
+echo "$as_me:$LINENO: result: none" >&5
+echo "${ECHO_T}none" >&6
+
+fi;
+
+# Add any additional libraries
+echo "$as_me:$LINENO: checking for extra libraries" >&5
+echo $ECHO_N "checking for extra libraries... $ECHO_C" >&6
+
+# Check whether --with-libs or --without-libs was given.
+if test "${with_libs+set}" = set; then
+ withval="$with_libs"
+
+echo "$as_me:$LINENO: result: ${withval}" >&5
+echo "${ECHO_T}${withval}" >&6
+if test "X${LIBS}" = "X"; then
+ LIBS="${withval}"
+else
+ LIBS="${LIBS} ${withval}"
+fi
+
+else
+
+echo "$as_me:$LINENO: result: none" >&5
+echo "${ECHO_T}none" >&6
+
+fi;
+
+# Defines STDC_HEADERS if the following header files are found: stdlib.h,
+# stdarg.h, string.h, and float.h
+# We really only need stdlib.h and float.h
+echo "$as_me:$LINENO: checking for ANSI C header files" >&5
+echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6
+if test "${ac_cv_header_stdc+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_header_stdc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_header_stdc=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+ # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "memchr" >/dev/null 2>&1; then
+ :
+else
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "free" >/dev/null 2>&1; then
+ :
+else
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+ if test "$cross_compiling" = yes; then
+ :
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <ctype.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+ (('a' <= (c) && (c) <= 'i') \
+ || ('j' <= (c) && (c) <= 'r') \
+ || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+ int i;
+ for (i = 0; i < 256; i++)
+ if (XOR (islower (i), ISLOWER (i))
+ || toupper (i) != TOUPPER (i))
+ exit(2);
+ exit (0);
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ :
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_header_stdc=no
+fi
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5
+echo "${ECHO_T}$ac_cv_header_stdc" >&6
+if test $ac_cv_header_stdc = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define STDC_HEADERS 1
+_ACEOF
+
+fi
+
+
+
+
+for ac_header in stdlib.h float.h math.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+else
+ # Is the header compilable?
+echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <$ac_header>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ ac_header_preproc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+ yes:no: )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+ ac_header_preproc=yes
+ ;;
+ no:yes:* )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+ (
+ cat <<\_ASBOX
+## ---------------------------- ##
+## Report this to radu at llnl.gov ##
+## ---------------------------- ##
+_ASBOX
+ ) |
+ sed "s/^/$as_me: WARNING: /" >&2
+ ;;
+esac
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ eval "$as_ac_Header=\$ac_header_preproc"
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+# Set flag indicating if generic function names should be used
+# Provide variable description template for config.hin and config.h files
+# Required by autoheader utility
+
+
+
+# Check if math library contains abs(), fabs(), pow(), and sqrt() functions (required)
+# May update LIBS (meaning add additional library, namely libm)
+MATH_FABS_OK="yes"
+MATH_POW_OK="yes"
+MATH_SQRT_OK="yes"
+# Save copy of LIBS variable and unset LIBS
+SAVED_LIBS="${LIBS}"
+LIBS=""
+# The abs routine is defined for an integer argument, so check for it regardless of
+# the level of precision chosen
+
+echo "$as_me:$LINENO: checking for abs in -lm" >&5
+echo $ECHO_N "checking for abs in -lm... $ECHO_C" >&6
+if test "${ac_cv_lib_m_abs+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lm $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char abs ();
+int
+main ()
+{
+abs ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_lib_m_abs=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_m_abs=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_m_abs" >&5
+echo "${ECHO_T}$ac_cv_lib_m_abs" >&6
+if test $ac_cv_lib_m_abs = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBM 1
+_ACEOF
+
+ LIBS="-lm $LIBS"
+
+else
+ { { echo "$as_me:$LINENO: error: cannot find abs function" >&5
+echo "$as_me: error: cannot find abs function" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+TEMP_MATH_LIB="${LIBS}"
+LIBS=""
+# Check for single-precision math routines
+if test "X${FLOAT_TYPE}" = "Xsingle"; then
+
+echo "$as_me:$LINENO: checking for fabsf in -lm" >&5
+echo $ECHO_N "checking for fabsf in -lm... $ECHO_C" >&6
+if test "${ac_cv_lib_m_fabsf+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lm $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char fabsf ();
+int
+main ()
+{
+fabsf ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_lib_m_fabsf=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_m_fabsf=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_m_fabsf" >&5
+echo "${ECHO_T}$ac_cv_lib_m_fabsf" >&6
+if test $ac_cv_lib_m_fabsf = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBM 1
+_ACEOF
+
+ LIBS="-lm $LIBS"
+
+else
+ MATH_FABS_OK="no"
+fi
+
+
+echo "$as_me:$LINENO: checking for powf in -lm" >&5
+echo $ECHO_N "checking for powf in -lm... $ECHO_C" >&6
+if test "${ac_cv_lib_m_powf+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lm $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char powf ();
+int
+main ()
+{
+powf ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_lib_m_powf=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_m_powf=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_m_powf" >&5
+echo "${ECHO_T}$ac_cv_lib_m_powf" >&6
+if test $ac_cv_lib_m_powf = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBM 1
+_ACEOF
+
+ LIBS="-lm $LIBS"
+
+else
+ MATH_POW_OK="no"
+fi
+
+
+echo "$as_me:$LINENO: checking for sqrtf in -lm" >&5
+echo $ECHO_N "checking for sqrtf in -lm... $ECHO_C" >&6
+if test "${ac_cv_lib_m_sqrtf+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lm $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char sqrtf ();
+int
+main ()
+{
+sqrtf ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_lib_m_sqrtf=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_m_sqrtf=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_m_sqrtf" >&5
+echo "${ECHO_T}$ac_cv_lib_m_sqrtf" >&6
+if test $ac_cv_lib_m_sqrtf = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBM 1
+_ACEOF
+
+ LIBS="-lm $LIBS"
+
+else
+ MATH_SQRT_OK="no"
+fi
+
+# Check for extended-precision math routines
+elif test "X${FLOAT_TYPE}" = "Xextended"; then
+
+echo "$as_me:$LINENO: checking for fabsl in -lm" >&5
+echo $ECHO_N "checking for fabsl in -lm... $ECHO_C" >&6
+if test "${ac_cv_lib_m_fabsl+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lm $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char fabsl ();
+int
+main ()
+{
+fabsl ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_lib_m_fabsl=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_m_fabsl=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_m_fabsl" >&5
+echo "${ECHO_T}$ac_cv_lib_m_fabsl" >&6
+if test $ac_cv_lib_m_fabsl = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBM 1
+_ACEOF
+
+ LIBS="-lm $LIBS"
+
+else
+ MATH_FABS_OK="no"
+fi
+
+
+echo "$as_me:$LINENO: checking for powl in -lm" >&5
+echo $ECHO_N "checking for powl in -lm... $ECHO_C" >&6
+if test "${ac_cv_lib_m_powl+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lm $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char powl ();
+int
+main ()
+{
+powl ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_lib_m_powl=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_m_powl=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_m_powl" >&5
+echo "${ECHO_T}$ac_cv_lib_m_powl" >&6
+if test $ac_cv_lib_m_powl = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBM 1
+_ACEOF
+
+ LIBS="-lm $LIBS"
+
+else
+ MATH_POW_OK="no"
+fi
+
+
+echo "$as_me:$LINENO: checking for sqrtl in -lm" >&5
+echo $ECHO_N "checking for sqrtl in -lm... $ECHO_C" >&6
+if test "${ac_cv_lib_m_sqrtl+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lm $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char sqrtl ();
+int
+main ()
+{
+sqrtl ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_lib_m_sqrtl=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_m_sqrtl=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_m_sqrtl" >&5
+echo "${ECHO_T}$ac_cv_lib_m_sqrtl" >&6
+if test $ac_cv_lib_m_sqrtl = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBM 1
+_ACEOF
+
+ LIBS="-lm $LIBS"
+
+else
+ MATH_SQRT_OK="no"
+fi
+
+# Check for (generic) double-precision math routines
+elif test "X${FLOAT_TYPE}" = "Xdouble"; then
+
+echo "$as_me:$LINENO: checking for fabs in -lm" >&5
+echo $ECHO_N "checking for fabs in -lm... $ECHO_C" >&6
+if test "${ac_cv_lib_m_fabs+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lm $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char fabs ();
+int
+main ()
+{
+fabs ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_lib_m_fabs=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_m_fabs=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_m_fabs" >&5
+echo "${ECHO_T}$ac_cv_lib_m_fabs" >&6
+if test $ac_cv_lib_m_fabs = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBM 1
+_ACEOF
+
+ LIBS="-lm $LIBS"
+
+else
+ { { echo "$as_me:$LINENO: error: cannot find fabs function" >&5
+echo "$as_me: error: cannot find fabs function" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+
+echo "$as_me:$LINENO: checking for pow in -lm" >&5
+echo $ECHO_N "checking for pow in -lm... $ECHO_C" >&6
+if test "${ac_cv_lib_m_pow+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lm $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char pow ();
+int
+main ()
+{
+pow ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_lib_m_pow=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_m_pow=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_m_pow" >&5
+echo "${ECHO_T}$ac_cv_lib_m_pow" >&6
+if test $ac_cv_lib_m_pow = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBM 1
+_ACEOF
+
+ LIBS="-lm $LIBS"
+
+else
+ { { echo "$as_me:$LINENO: error: cannot find pow function" >&5
+echo "$as_me: error: cannot find pow function" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+
+echo "$as_me:$LINENO: checking for sqrt in -lm" >&5
+echo $ECHO_N "checking for sqrt in -lm... $ECHO_C" >&6
+if test "${ac_cv_lib_m_sqrt+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lm $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char sqrt ();
+int
+main ()
+{
+sqrt ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_lib_m_sqrt=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_m_sqrt=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_m_sqrt" >&5
+echo "${ECHO_T}$ac_cv_lib_m_sqrt" >&6
+if test $ac_cv_lib_m_sqrt = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBM 1
+_ACEOF
+
+ LIBS="-lm $LIBS"
+
+else
+ { { echo "$as_me:$LINENO: error: cannot find sqrt function" >&5
+echo "$as_me: error: cannot find sqrt function" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+fi
+# If cannot find precision-specific implementations, then check for generic versions
+if test "X${MATH_FABS_OK}" = "Xno" || test "X${MATH_POW_OK}" = "Xno" || test "X${MATH_SQRT_OK}" = "Xno"; then
+
+echo "$as_me:$LINENO: checking for fabs in -lm" >&5
+echo $ECHO_N "checking for fabs in -lm... $ECHO_C" >&6
+if test "${ac_cv_lib_m_fabs+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lm $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char fabs ();
+int
+main ()
+{
+fabs ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_lib_m_fabs=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_m_fabs=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_m_fabs" >&5
+echo "${ECHO_T}$ac_cv_lib_m_fabs" >&6
+if test $ac_cv_lib_m_fabs = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBM 1
+_ACEOF
+
+ LIBS="-lm $LIBS"
+
+else
+ { { echo "$as_me:$LINENO: error: cannot find fabs function" >&5
+echo "$as_me: error: cannot find fabs function" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+
+echo "$as_me:$LINENO: checking for pow in -lm" >&5
+echo $ECHO_N "checking for pow in -lm... $ECHO_C" >&6
+if test "${ac_cv_lib_m_pow+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lm $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char pow ();
+int
+main ()
+{
+pow ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_lib_m_pow=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_m_pow=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_m_pow" >&5
+echo "${ECHO_T}$ac_cv_lib_m_pow" >&6
+if test $ac_cv_lib_m_pow = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBM 1
+_ACEOF
+
+ LIBS="-lm $LIBS"
+
+else
+ { { echo "$as_me:$LINENO: error: cannot find pow function" >&5
+echo "$as_me: error: cannot find pow function" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+
+echo "$as_me:$LINENO: checking for sqrt in -lm" >&5
+echo $ECHO_N "checking for sqrt in -lm... $ECHO_C" >&6
+if test "${ac_cv_lib_m_sqrt+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lm $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char sqrt ();
+int
+main ()
+{
+sqrt ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_lib_m_sqrt=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_m_sqrt=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_m_sqrt" >&5
+echo "${ECHO_T}$ac_cv_lib_m_sqrt" >&6
+if test $ac_cv_lib_m_sqrt = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBM 1
+_ACEOF
+
+ LIBS="-lm $LIBS"
+
+else
+ { { echo "$as_me:$LINENO: error: cannot find sqrt function" >&5
+echo "$as_me: error: cannot find sqrt function" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+ # If all generic math routines are available, then set SUNDIALS_USE_GENERIC_MATH flag
+ # for use by sundials_math.c file (preprocessor macros)
+ cat >>confdefs.h <<\_ACEOF
+#define SUNDIALS_USE_GENERIC_MATH 1
+_ACEOF
+
+ GENERIC_MATH_LIB="#define SUNDIALS_USE_GENERIC_MATH"
+# If found all precision-specific routines, then set SUNDIALS_USE_GENERIC_MATH only if
+# building SUNDIALS libraries with double-precision
+else
+ if test "X${FLOAT_TYPE}" = "Xdouble"; then
+ cat >>confdefs.h <<\_ACEOF
+#define SUNDIALS_USE_GENERIC_MATH 1
+_ACEOF
+
+ GENERIC_MATH_LIB="#define SUNDIALS_USE_GENERIC_MATH"
+ else
+ cat >>confdefs.h <<\_ACEOF
+#define SUNDIALS_USE_GENERIC_MATH 0
+_ACEOF
+
+ fi
+fi
+
+# Add math library to LIBS environment variable
+LIBS="${TEMP_MATH_LIB}"
+echo "$as_me:$LINENO: checking for additional required C libraries" >&5
+echo $ECHO_N "checking for additional required C libraries... $ECHO_C" >&6
+if test "X${LIBS}" = "X"; then
+ if test "X${SAVED_LIBS}" = "X"; then
+ LIBS=""
+ else
+ LIBS="${SAVED_LIBS}"
+ fi
+ echo "$as_me:$LINENO: result: none" >&5
+echo "${ECHO_T}none" >&6
+else
+ echo "$as_me:$LINENO: result: ${LIBS}" >&5
+echo "${ECHO_T}${LIBS}" >&6
+ if test "X${SAVED_LIBS}" = "X"; then
+ LIBS="${LIBS}"
+ else
+ LIBS="${LIBS} ${SAVED_LIBS}"
+ fi
+fi
+
+# Check sizeof(int) - used to modify Fortran examples
+echo "$as_me:$LINENO: checking for int" >&5
+echo $ECHO_N "checking for int... $ECHO_C" >&6
+if test "${ac_cv_type_int+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+if ((int *) 0)
+ return 0;
+if (sizeof (int))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_type_int=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_type_int=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_type_int" >&5
+echo "${ECHO_T}$ac_cv_type_int" >&6
+
+echo "$as_me:$LINENO: checking size of int" >&5
+echo $ECHO_N "checking size of int... $ECHO_C" >&6
+if test "${ac_cv_sizeof_int+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test "$ac_cv_type_int" = yes; then
+ # The cast to unsigned long works around a bug in the HP C Compiler
+ # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+ # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+ # This bug is HP SR number 8606223364.
+ if test "$cross_compiling" = yes; then
+ # Depending upon the size, compute the lo and hi bounds.
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (int))) >= 0)];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_lo=0 ac_mid=0
+ while :; do
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (int))) <= $ac_mid)];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_hi=$ac_mid; break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_lo=`expr $ac_mid + 1`
+ if test $ac_lo -le $ac_mid; then
+ ac_lo= ac_hi=
+ break
+ fi
+ ac_mid=`expr 2 '*' $ac_mid + 1`
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ done
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (int))) < 0)];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_hi=-1 ac_mid=-1
+ while :; do
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (int))) >= $ac_mid)];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_lo=$ac_mid; break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_hi=`expr '(' $ac_mid ')' - 1`
+ if test $ac_mid -le $ac_hi; then
+ ac_lo= ac_hi=
+ break
+ fi
+ ac_mid=`expr 2 '*' $ac_mid`
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ done
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_lo= ac_hi=
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+# Binary search between lo and hi bounds.
+while test "x$ac_lo" != "x$ac_hi"; do
+ ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo`
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (int))) <= $ac_mid)];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_hi=$ac_mid
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_lo=`expr '(' $ac_mid ')' + 1`
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+case $ac_lo in
+?*) ac_cv_sizeof_int=$ac_lo;;
+'') { { echo "$as_me:$LINENO: error: cannot compute sizeof (int), 77
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute sizeof (int), 77
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; } ;;
+esac
+else
+ if test "$cross_compiling" = yes; then
+ { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+long longval () { return (long) (sizeof (int)); }
+unsigned long ulongval () { return (long) (sizeof (int)); }
+#include <stdio.h>
+#include <stdlib.h>
+int
+main ()
+{
+
+ FILE *f = fopen ("conftest.val", "w");
+ if (! f)
+ exit (1);
+ if (((long) (sizeof (int))) < 0)
+ {
+ long i = longval ();
+ if (i != ((long) (sizeof (int))))
+ exit (1);
+ fprintf (f, "%ld\n", i);
+ }
+ else
+ {
+ unsigned long i = ulongval ();
+ if (i != ((long) (sizeof (int))))
+ exit (1);
+ fprintf (f, "%lu\n", i);
+ }
+ exit (ferror (f) || fclose (f) != 0);
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_sizeof_int=`cat conftest.val`
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+{ { echo "$as_me:$LINENO: error: cannot compute sizeof (int), 77
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute sizeof (int), 77
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+rm -f conftest.val
+else
+ ac_cv_sizeof_int=0
+fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_sizeof_int" >&5
+echo "${ECHO_T}$ac_cv_sizeof_int" >&6
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_INT $ac_cv_sizeof_int
+_ACEOF
+
+
+
+# Check sizeof(long int) - used to modify Fortran examples
+echo "$as_me:$LINENO: checking for long int" >&5
+echo $ECHO_N "checking for long int... $ECHO_C" >&6
+if test "${ac_cv_type_long_int+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+if ((long int *) 0)
+ return 0;
+if (sizeof (long int))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_type_long_int=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_type_long_int=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_type_long_int" >&5
+echo "${ECHO_T}$ac_cv_type_long_int" >&6
+
+echo "$as_me:$LINENO: checking size of long int" >&5
+echo $ECHO_N "checking size of long int... $ECHO_C" >&6
+if test "${ac_cv_sizeof_long_int+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test "$ac_cv_type_long_int" = yes; then
+ # The cast to unsigned long works around a bug in the HP C Compiler
+ # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+ # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+ # This bug is HP SR number 8606223364.
+ if test "$cross_compiling" = yes; then
+ # Depending upon the size, compute the lo and hi bounds.
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (long int))) >= 0)];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_lo=0 ac_mid=0
+ while :; do
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (long int))) <= $ac_mid)];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_hi=$ac_mid; break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_lo=`expr $ac_mid + 1`
+ if test $ac_lo -le $ac_mid; then
+ ac_lo= ac_hi=
+ break
+ fi
+ ac_mid=`expr 2 '*' $ac_mid + 1`
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ done
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (long int))) < 0)];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_hi=-1 ac_mid=-1
+ while :; do
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (long int))) >= $ac_mid)];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_lo=$ac_mid; break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_hi=`expr '(' $ac_mid ')' - 1`
+ if test $ac_mid -le $ac_hi; then
+ ac_lo= ac_hi=
+ break
+ fi
+ ac_mid=`expr 2 '*' $ac_mid`
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ done
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_lo= ac_hi=
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+# Binary search between lo and hi bounds.
+while test "x$ac_lo" != "x$ac_hi"; do
+ ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo`
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (long int))) <= $ac_mid)];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_hi=$ac_mid
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_lo=`expr '(' $ac_mid ')' + 1`
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+case $ac_lo in
+?*) ac_cv_sizeof_long_int=$ac_lo;;
+'') { { echo "$as_me:$LINENO: error: cannot compute sizeof (long int), 77
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute sizeof (long int), 77
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; } ;;
+esac
+else
+ if test "$cross_compiling" = yes; then
+ { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+long longval () { return (long) (sizeof (long int)); }
+unsigned long ulongval () { return (long) (sizeof (long int)); }
+#include <stdio.h>
+#include <stdlib.h>
+int
+main ()
+{
+
+ FILE *f = fopen ("conftest.val", "w");
+ if (! f)
+ exit (1);
+ if (((long) (sizeof (long int))) < 0)
+ {
+ long i = longval ();
+ if (i != ((long) (sizeof (long int))))
+ exit (1);
+ fprintf (f, "%ld\n", i);
+ }
+ else
+ {
+ unsigned long i = ulongval ();
+ if (i != ((long) (sizeof (long int))))
+ exit (1);
+ fprintf (f, "%lu\n", i);
+ }
+ exit (ferror (f) || fclose (f) != 0);
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_sizeof_long_int=`cat conftest.val`
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+{ { echo "$as_me:$LINENO: error: cannot compute sizeof (long int), 77
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute sizeof (long int), 77
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+rm -f conftest.val
+else
+ ac_cv_sizeof_long_int=0
+fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_sizeof_long_int" >&5
+echo "${ECHO_T}$ac_cv_sizeof_long_int" >&6
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_LONG_INT $ac_cv_sizeof_long_int
+_ACEOF
+
+
+
+# Check sizeof(realtype), where realtype is either float, double
+# or long double - used to modify Fortran examples
+if test "X${FLOAT_TYPE}" = "Xsingle"; then
+ echo "$as_me:$LINENO: checking for float" >&5
+echo $ECHO_N "checking for float... $ECHO_C" >&6
+if test "${ac_cv_type_float+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+if ((float *) 0)
+ return 0;
+if (sizeof (float))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_type_float=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_type_float=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_type_float" >&5
+echo "${ECHO_T}$ac_cv_type_float" >&6
+
+echo "$as_me:$LINENO: checking size of float" >&5
+echo $ECHO_N "checking size of float... $ECHO_C" >&6
+if test "${ac_cv_sizeof_float+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test "$ac_cv_type_float" = yes; then
+ # The cast to unsigned long works around a bug in the HP C Compiler
+ # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+ # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+ # This bug is HP SR number 8606223364.
+ if test "$cross_compiling" = yes; then
+ # Depending upon the size, compute the lo and hi bounds.
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (float))) >= 0)];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_lo=0 ac_mid=0
+ while :; do
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (float))) <= $ac_mid)];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_hi=$ac_mid; break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_lo=`expr $ac_mid + 1`
+ if test $ac_lo -le $ac_mid; then
+ ac_lo= ac_hi=
+ break
+ fi
+ ac_mid=`expr 2 '*' $ac_mid + 1`
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ done
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (float))) < 0)];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_hi=-1 ac_mid=-1
+ while :; do
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (float))) >= $ac_mid)];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_lo=$ac_mid; break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_hi=`expr '(' $ac_mid ')' - 1`
+ if test $ac_mid -le $ac_hi; then
+ ac_lo= ac_hi=
+ break
+ fi
+ ac_mid=`expr 2 '*' $ac_mid`
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ done
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_lo= ac_hi=
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+# Binary search between lo and hi bounds.
+while test "x$ac_lo" != "x$ac_hi"; do
+ ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo`
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (float))) <= $ac_mid)];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_hi=$ac_mid
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_lo=`expr '(' $ac_mid ')' + 1`
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+case $ac_lo in
+?*) ac_cv_sizeof_float=$ac_lo;;
+'') { { echo "$as_me:$LINENO: error: cannot compute sizeof (float), 77
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute sizeof (float), 77
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; } ;;
+esac
+else
+ if test "$cross_compiling" = yes; then
+ { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+long longval () { return (long) (sizeof (float)); }
+unsigned long ulongval () { return (long) (sizeof (float)); }
+#include <stdio.h>
+#include <stdlib.h>
+int
+main ()
+{
+
+ FILE *f = fopen ("conftest.val", "w");
+ if (! f)
+ exit (1);
+ if (((long) (sizeof (float))) < 0)
+ {
+ long i = longval ();
+ if (i != ((long) (sizeof (float))))
+ exit (1);
+ fprintf (f, "%ld\n", i);
+ }
+ else
+ {
+ unsigned long i = ulongval ();
+ if (i != ((long) (sizeof (float))))
+ exit (1);
+ fprintf (f, "%lu\n", i);
+ }
+ exit (ferror (f) || fclose (f) != 0);
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_sizeof_float=`cat conftest.val`
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+{ { echo "$as_me:$LINENO: error: cannot compute sizeof (float), 77
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute sizeof (float), 77
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+rm -f conftest.val
+else
+ ac_cv_sizeof_float=0
+fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_sizeof_float" >&5
+echo "${ECHO_T}$ac_cv_sizeof_float" >&6
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_FLOAT $ac_cv_sizeof_float
+_ACEOF
+
+
+elif test "X${FLOAT_TYPE}" = "Xdouble"; then
+ echo "$as_me:$LINENO: checking for double" >&5
+echo $ECHO_N "checking for double... $ECHO_C" >&6
+if test "${ac_cv_type_double+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+if ((double *) 0)
+ return 0;
+if (sizeof (double))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_type_double=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_type_double=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_type_double" >&5
+echo "${ECHO_T}$ac_cv_type_double" >&6
+
+echo "$as_me:$LINENO: checking size of double" >&5
+echo $ECHO_N "checking size of double... $ECHO_C" >&6
+if test "${ac_cv_sizeof_double+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test "$ac_cv_type_double" = yes; then
+ # The cast to unsigned long works around a bug in the HP C Compiler
+ # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+ # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+ # This bug is HP SR number 8606223364.
+ if test "$cross_compiling" = yes; then
+ # Depending upon the size, compute the lo and hi bounds.
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (double))) >= 0)];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_lo=0 ac_mid=0
+ while :; do
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (double))) <= $ac_mid)];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_hi=$ac_mid; break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_lo=`expr $ac_mid + 1`
+ if test $ac_lo -le $ac_mid; then
+ ac_lo= ac_hi=
+ break
+ fi
+ ac_mid=`expr 2 '*' $ac_mid + 1`
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ done
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (double))) < 0)];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_hi=-1 ac_mid=-1
+ while :; do
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (double))) >= $ac_mid)];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_lo=$ac_mid; break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_hi=`expr '(' $ac_mid ')' - 1`
+ if test $ac_mid -le $ac_hi; then
+ ac_lo= ac_hi=
+ break
+ fi
+ ac_mid=`expr 2 '*' $ac_mid`
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ done
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_lo= ac_hi=
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+# Binary search between lo and hi bounds.
+while test "x$ac_lo" != "x$ac_hi"; do
+ ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo`
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (double))) <= $ac_mid)];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_hi=$ac_mid
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_lo=`expr '(' $ac_mid ')' + 1`
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+case $ac_lo in
+?*) ac_cv_sizeof_double=$ac_lo;;
+'') { { echo "$as_me:$LINENO: error: cannot compute sizeof (double), 77
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute sizeof (double), 77
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; } ;;
+esac
+else
+ if test "$cross_compiling" = yes; then
+ { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+long longval () { return (long) (sizeof (double)); }
+unsigned long ulongval () { return (long) (sizeof (double)); }
+#include <stdio.h>
+#include <stdlib.h>
+int
+main ()
+{
+
+ FILE *f = fopen ("conftest.val", "w");
+ if (! f)
+ exit (1);
+ if (((long) (sizeof (double))) < 0)
+ {
+ long i = longval ();
+ if (i != ((long) (sizeof (double))))
+ exit (1);
+ fprintf (f, "%ld\n", i);
+ }
+ else
+ {
+ unsigned long i = ulongval ();
+ if (i != ((long) (sizeof (double))))
+ exit (1);
+ fprintf (f, "%lu\n", i);
+ }
+ exit (ferror (f) || fclose (f) != 0);
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_sizeof_double=`cat conftest.val`
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+{ { echo "$as_me:$LINENO: error: cannot compute sizeof (double), 77
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute sizeof (double), 77
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+rm -f conftest.val
+else
+ ac_cv_sizeof_double=0
+fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_sizeof_double" >&5
+echo "${ECHO_T}$ac_cv_sizeof_double" >&6
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_DOUBLE $ac_cv_sizeof_double
+_ACEOF
+
+
+elif test "X${FLOAT_TYPE}" = "Xextended"; then
+ echo "$as_me:$LINENO: checking for long double" >&5
+echo $ECHO_N "checking for long double... $ECHO_C" >&6
+if test "${ac_cv_type_long_double+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+if ((long double *) 0)
+ return 0;
+if (sizeof (long double))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_type_long_double=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_type_long_double=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_type_long_double" >&5
+echo "${ECHO_T}$ac_cv_type_long_double" >&6
+
+echo "$as_me:$LINENO: checking size of long double" >&5
+echo $ECHO_N "checking size of long double... $ECHO_C" >&6
+if test "${ac_cv_sizeof_long_double+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test "$ac_cv_type_long_double" = yes; then
+ # The cast to unsigned long works around a bug in the HP C Compiler
+ # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+ # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+ # This bug is HP SR number 8606223364.
+ if test "$cross_compiling" = yes; then
+ # Depending upon the size, compute the lo and hi bounds.
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (long double))) >= 0)];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_lo=0 ac_mid=0
+ while :; do
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (long double))) <= $ac_mid)];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_hi=$ac_mid; break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_lo=`expr $ac_mid + 1`
+ if test $ac_lo -le $ac_mid; then
+ ac_lo= ac_hi=
+ break
+ fi
+ ac_mid=`expr 2 '*' $ac_mid + 1`
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ done
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (long double))) < 0)];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_hi=-1 ac_mid=-1
+ while :; do
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (long double))) >= $ac_mid)];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_lo=$ac_mid; break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_hi=`expr '(' $ac_mid ')' - 1`
+ if test $ac_mid -le $ac_hi; then
+ ac_lo= ac_hi=
+ break
+ fi
+ ac_mid=`expr 2 '*' $ac_mid`
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ done
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_lo= ac_hi=
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+# Binary search between lo and hi bounds.
+while test "x$ac_lo" != "x$ac_hi"; do
+ ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo`
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (long double))) <= $ac_mid)];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_hi=$ac_mid
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_lo=`expr '(' $ac_mid ')' + 1`
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+case $ac_lo in
+?*) ac_cv_sizeof_long_double=$ac_lo;;
+'') { { echo "$as_me:$LINENO: error: cannot compute sizeof (long double), 77
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute sizeof (long double), 77
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; } ;;
+esac
+else
+ if test "$cross_compiling" = yes; then
+ { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+long longval () { return (long) (sizeof (long double)); }
+unsigned long ulongval () { return (long) (sizeof (long double)); }
+#include <stdio.h>
+#include <stdlib.h>
+int
+main ()
+{
+
+ FILE *f = fopen ("conftest.val", "w");
+ if (! f)
+ exit (1);
+ if (((long) (sizeof (long double))) < 0)
+ {
+ long i = longval ();
+ if (i != ((long) (sizeof (long double))))
+ exit (1);
+ fprintf (f, "%ld\n", i);
+ }
+ else
+ {
+ unsigned long i = ulongval ();
+ if (i != ((long) (sizeof (long double))))
+ exit (1);
+ fprintf (f, "%lu\n", i);
+ }
+ exit (ferror (f) || fclose (f) != 0);
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_sizeof_long_double=`cat conftest.val`
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+{ { echo "$as_me:$LINENO: error: cannot compute sizeof (long double), 77
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute sizeof (long double), 77
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+rm -f conftest.val
+else
+ ac_cv_sizeof_long_double=0
+fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_sizeof_long_double" >&5
+echo "${ECHO_T}$ac_cv_sizeof_long_double" >&6
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_LONG_DOUBLE $ac_cv_sizeof_long_double
+_ACEOF
+
+
+fi
+
+# Defines EGREP and exports via AC_SUBST - used by FCMIX Makefile's
+echo "$as_me:$LINENO: checking for egrep" >&5
+echo $ECHO_N "checking for egrep... $ECHO_C" >&6
+if test "${ac_cv_prog_egrep+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if echo a | (grep -E '(a|b)') >/dev/null 2>&1
+ then ac_cv_prog_egrep='grep -E'
+ else ac_cv_prog_egrep='egrep'
+ fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_prog_egrep" >&5
+echo "${ECHO_T}$ac_cv_prog_egrep" >&6
+ EGREP=$ac_cv_prog_egrep
+
+
+
+# Defines FGREP and exports via AC_SUBST - used by FCMIX Makefile's
+echo "$as_me:$LINENO: checking for fgrep" >&5
+echo $ECHO_N "checking for fgrep... $ECHO_C" >&6
+if test "${ac_cv_prog_fgrep+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if echo 'ab*c' | (grep -F 'ab*c') >/dev/null 2>&1
+ then ac_cv_prog_fgrep='grep -F'
+ else ac_cv_prog_fgrep='fgrep'
+ fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_prog_fgrep" >&5
+echo "${ECHO_T}$ac_cv_prog_fgrep" >&6
+ FGREP=$ac_cv_prog_fgrep
+
+
+
+# Check if CC is a C++ compiler
+# Note: If CC is a C++ compiler and MPI is enabled, then we will
+# check for "mpiCC" instead of "mpicc" if an MPI compiler was NOT specified
+
+
+# Rename argument
+COMP_NAME="${CC}"
+
+# Update the language stack
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_linkonly='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_objext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+# Check if using a C++ compiler
+echo "$as_me:$LINENO: checking if ${COMP_NAME} is a C++ compiler" >&5
+echo $ECHO_N "checking if ${COMP_NAME} is a C++ compiler... $ECHO_C" >&6
+if test "$cross_compiling" = yes; then
+ { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+#ifdef __cplusplus
+ return(0);
+#else
+ return(1);
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+
+echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+# COMP_NAME is a C++ compiler
+USING_CPLUSPLUS_COMP="yes"
+
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+
+echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+# COMP_NAMPE is NOT a C++ compiler
+USING_CPLUSPLUS_COMP="no"
+
+fi
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+# Revert back to previous language
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_linkonly='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_objext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+
+
+
+fi
+
+
+
+# Set Fortran support
+if test "X${FCMIX_ENABLED}" = "Xyes" || test "X${LAPACK_ENABLED}" = "Xyes"; then
+ echo ""
+ echo "Fortran Settings"
+ echo "----------------"
+ echo ""
+
+
+
+F77_OK="yes"
+
+# Look for a F77 compiler
+# If unsuccessful, disable all Fortran support
+
+ac_ext=f
+ac_compile='$F77 -c $FFLAGS conftest.$ac_ext >&5'
+ac_link='$F77 -o conftest$ac_exeext $FFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_f77_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+ for ac_prog in f77 g77
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_F77+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$F77"; then
+ ac_cv_prog_F77="$F77" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_F77="$ac_tool_prefix$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+F77=$ac_cv_prog_F77
+if test -n "$F77"; then
+ echo "$as_me:$LINENO: result: $F77" >&5
+echo "${ECHO_T}$F77" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ test -n "$F77" && break
+ done
+fi
+if test -z "$F77"; then
+ ac_ct_F77=$F77
+ for ac_prog in f77 g77
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_F77+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_F77"; then
+ ac_cv_prog_ac_ct_F77="$ac_ct_F77" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_F77="$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+ac_ct_F77=$ac_cv_prog_ac_ct_F77
+if test -n "$ac_ct_F77"; then
+ echo "$as_me:$LINENO: result: $ac_ct_F77" >&5
+echo "${ECHO_T}$ac_ct_F77" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ test -n "$ac_ct_F77" && break
+done
+
+ F77=$ac_ct_F77
+fi
+
+
+# Provide some information about the compiler.
+echo "$as_me:7176:" \
+ "checking for Fortran 77 compiler version" >&5
+ac_compiler=`set X $ac_compile; echo $2`
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version </dev/null >&5\"") >&5
+ (eval $ac_compiler --version </dev/null >&5) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v </dev/null >&5\"") >&5
+ (eval $ac_compiler -v </dev/null >&5) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V </dev/null >&5\"") >&5
+ (eval $ac_compiler -V </dev/null >&5) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+rm -f a.out
+
+# If we don't use `.F' as extension, the preprocessor is not run on the
+# input file. (Note that this only needs to work for GNU compilers.)
+ac_save_ext=$ac_ext
+ac_ext=F
+echo "$as_me:$LINENO: checking whether we are using the GNU Fortran 77 compiler" >&5
+echo $ECHO_N "checking whether we are using the GNU Fortran 77 compiler... $ECHO_C" >&6
+if test "${ac_cv_f77_compiler_gnu+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+ program main
+#ifndef __GNUC__
+ choke me
+#endif
+
+ end
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_f77_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_compiler_gnu=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_compiler_gnu=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_f77_compiler_gnu=$ac_compiler_gnu
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_f77_compiler_gnu" >&5
+echo "${ECHO_T}$ac_cv_f77_compiler_gnu" >&6
+ac_ext=$ac_save_ext
+ac_test_FFLAGS=${FFLAGS+set}
+ac_save_FFLAGS=$FFLAGS
+FFLAGS=
+echo "$as_me:$LINENO: checking whether $F77 accepts -g" >&5
+echo $ECHO_N "checking whether $F77 accepts -g... $ECHO_C" >&6
+if test "${ac_cv_prog_f77_g+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ FFLAGS=-g
+cat >conftest.$ac_ext <<_ACEOF
+ program main
+
+ end
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_f77_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_prog_f77_g=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_prog_f77_g=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_prog_f77_g" >&5
+echo "${ECHO_T}$ac_cv_prog_f77_g" >&6
+if test "$ac_test_FFLAGS" = set; then
+ FFLAGS=$ac_save_FFLAGS
+elif test $ac_cv_prog_f77_g = yes; then
+ if test "x$ac_cv_f77_compiler_gnu" = xyes; then
+ FFLAGS="-g -O2"
+ else
+ FFLAGS="-g"
+ fi
+else
+ if test "x$ac_cv_f77_compiler_gnu" = xyes; then
+ FFLAGS="-O2"
+ else
+ FFLAGS=
+ fi
+fi
+
+G77=`test $ac_compiler_gnu = yes && echo yes`
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_linkonly='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_objext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+if test "X${F77}" = "X"; then
+
+ F77_OK="no"
+ SUNDIALS_WARN_FLAG="yes"
+
+ echo ""
+ echo " Unable to find a working Fortran compiler"
+ echo ""
+ echo " Try using F77 to explicitly specify a C compiler"
+ echo ""
+ if test "X${FCMIX_ENABLED}" = "Xyes"; then
+ echo " Disabling compilation of Fortran-C interfaces..."
+ fi
+ if test "X${LAPACK_ENABLED}" = "Xyes"; then
+ echo " Disabling compilation of Blas/Lapack interfaces..."
+ fi
+ echo ""
+
+ FCMIX_ENABLED="no"
+ LAPACK_ENABLED="no"
+ F77_EXAMPLES_ENABLED="no"
+
+fi
+
+# Check Fortran compiler
+# If unsuccessful, disable all Fortran support
+
+if test "X${F77_OK}" = "Xyes"; then
+
+
+
+ac_ext=f
+ac_compile='$F77 -c $FFLAGS conftest.$ac_ext >&5'
+ac_link='$F77 -o conftest$ac_exeext $FFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_f77_compiler_gnu
+
+
+# Add any additional FFLAGS
+echo "$as_me:$LINENO: checking for extra Fortran compiler flags" >&5
+echo $ECHO_N "checking for extra Fortran compiler flags... $ECHO_C" >&6
+
+# Check whether --with-fflags or --without-fflags was given.
+if test "${with_fflags+set}" = set; then
+ withval="$with_fflags"
+
+echo "$as_me:$LINENO: result: ${withval}" >&5
+echo "${ECHO_T}${withval}" >&6
+FFLAGS="${FFLAGS} ${withval}"
+
+else
+
+echo "$as_me:$LINENO: result: none" >&5
+echo "${ECHO_T}none" >&6
+
+fi;
+
+# Add any required linker flags to FLIBS
+# Note: if FLIBS is defined, it is left unchanged
+ac_ext=f
+ac_compile='$F77 -c $FFLAGS conftest.$ac_ext >&5'
+ac_link='$F77 -o conftest$ac_exeext $FFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_f77_compiler_gnu
+echo "$as_me:$LINENO: checking how to get verbose linking output from $F77" >&5
+echo $ECHO_N "checking how to get verbose linking output from $F77... $ECHO_C" >&6
+if test "${ac_cv_prog_f77_v+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+ program main
+
+ end
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_f77_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_prog_f77_v=
+# Try some options frequently used verbose output
+for ac_verb in -v -verbose --verbose -V -\#\#\#; do
+ cat >conftest.$ac_ext <<_ACEOF
+ program main
+
+ end
+_ACEOF
+
+# Compile and link our simple test program by passing a flag (argument
+# 1 to this macro) to the Fortran compiler in order to get
+# "verbose" output that we can then parse for the Fortran linker
+# flags.
+ac_save_FFLAGS=$FFLAGS
+FFLAGS="$FFLAGS $ac_verb"
+(eval echo $as_me:7431: \"$ac_link\") >&5
+ac_f77_v_output=`eval $ac_link 5>&1 2>&1 | grep -v 'Driving:'`
+echo "$ac_f77_v_output" >&5
+FFLAGS=$ac_save_FFLAGS
+
+rm -f conftest*
+
+# On HP/UX there is a line like: "LPATH is: /foo:/bar:/baz" where
+# /foo, /bar, and /baz are search directories for the Fortran linker.
+# Here, we change these into -L/foo -L/bar -L/baz (and put it first):
+ac_f77_v_output="`echo $ac_f77_v_output |
+ grep 'LPATH is:' |
+ sed 's,.*LPATH is\(: *[^ ]*\).*,\1,;s,: */, -L/,g'` $ac_f77_v_output"
+
+case $ac_f77_v_output in
+ # If we are using xlf then replace all the commas with spaces.
+ *xlfentry*)
+ ac_f77_v_output=`echo $ac_f77_v_output | sed 's/,/ /g'` ;;
+
+ # With Intel ifc, ignore the quoted -mGLOB_options_string stuff (quoted
+ # $LIBS confuse us, and the libraries appear later in the output anyway).
+ *mGLOB_options_string*)
+ ac_f77_v_output=`echo $ac_f77_v_output | sed 's/"-mGLOB[^"]*"/ /g'` ;;
+
+ # Portland Group compiler has quoted -cmdline argument
+ *-cmdline*)
+ ac_f77_v_output=`echo $ac_f77_v_output | sed "s/-cmdline '[^']*'/ /g"` ;;
+
+ # If we are using Cray Fortran then delete quotes.
+ # Use "\"" instead of '"' for font-lock-mode.
+ # FIXME: a more general fix for quoted arguments with spaces?
+ *cft90*)
+ ac_f77_v_output=`echo $ac_f77_v_output | sed "s/\"//g"` ;;
+esac
+
+
+ # look for -l* and *.a constructs in the output
+ for ac_arg in $ac_f77_v_output; do
+ case $ac_arg in
+ [\\/]*.a | ?:[\\/]*.a | -[lLRu]*)
+ ac_cv_prog_f77_v=$ac_verb
+ break 2 ;;
+ esac
+ done
+done
+if test -z "$ac_cv_prog_f77_v"; then
+ { echo "$as_me:$LINENO: WARNING: cannot determine how to obtain linking information from $F77" >&5
+echo "$as_me: WARNING: cannot determine how to obtain linking information from $F77" >&2;}
+fi
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ echo "$as_me:$LINENO: WARNING: compilation failed" >&5
+echo "$as_me: WARNING: compilation failed" >&2;}
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_prog_f77_v" >&5
+echo "${ECHO_T}$ac_cv_prog_f77_v" >&6
+echo "$as_me:$LINENO: checking for Fortran libraries of $F77" >&5
+echo $ECHO_N "checking for Fortran libraries of $F77... $ECHO_C" >&6
+if test "${ac_cv_f77_libs+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test "x$FLIBS" != "x"; then
+ ac_cv_f77_libs="$FLIBS" # Let the user override the test.
+else
+
+cat >conftest.$ac_ext <<_ACEOF
+ program main
+
+ end
+_ACEOF
+
+# Compile and link our simple test program by passing a flag (argument
+# 1 to this macro) to the Fortran compiler in order to get
+# "verbose" output that we can then parse for the Fortran linker
+# flags.
+ac_save_FFLAGS=$FFLAGS
+FFLAGS="$FFLAGS $ac_cv_prog_f77_v"
+(eval echo $as_me:7513: \"$ac_link\") >&5
+ac_f77_v_output=`eval $ac_link 5>&1 2>&1 | grep -v 'Driving:'`
+echo "$ac_f77_v_output" >&5
+FFLAGS=$ac_save_FFLAGS
+
+rm -f conftest*
+
+# On HP/UX there is a line like: "LPATH is: /foo:/bar:/baz" where
+# /foo, /bar, and /baz are search directories for the Fortran linker.
+# Here, we change these into -L/foo -L/bar -L/baz (and put it first):
+ac_f77_v_output="`echo $ac_f77_v_output |
+ grep 'LPATH is:' |
+ sed 's,.*LPATH is\(: *[^ ]*\).*,\1,;s,: */, -L/,g'` $ac_f77_v_output"
+
+case $ac_f77_v_output in
+ # If we are using xlf then replace all the commas with spaces.
+ *xlfentry*)
+ ac_f77_v_output=`echo $ac_f77_v_output | sed 's/,/ /g'` ;;
+
+ # With Intel ifc, ignore the quoted -mGLOB_options_string stuff (quoted
+ # $LIBS confuse us, and the libraries appear later in the output anyway).
+ *mGLOB_options_string*)
+ ac_f77_v_output=`echo $ac_f77_v_output | sed 's/"-mGLOB[^"]*"/ /g'` ;;
+
+ # Portland Group compiler has quoted -cmdline argument
+ *-cmdline*)
+ ac_f77_v_output=`echo $ac_f77_v_output | sed "s/-cmdline '[^']*'/ /g"` ;;
+
+ # If we are using Cray Fortran then delete quotes.
+ # Use "\"" instead of '"' for font-lock-mode.
+ # FIXME: a more general fix for quoted arguments with spaces?
+ *cft90*)
+ ac_f77_v_output=`echo $ac_f77_v_output | sed "s/\"//g"` ;;
+esac
+
+
+
+ac_cv_f77_libs=
+
+# Save positional arguments (if any)
+ac_save_positional="$@"
+
+set X $ac_f77_v_output
+while test $# != 1; do
+ shift
+ ac_arg=$1
+ case $ac_arg in
+ [\\/]*.a | ?:[\\/]*.a)
+ ac_exists=false
+ for ac_i in $ac_cv_f77_libs; do
+ if test x"$ac_arg" = x"$ac_i"; then
+ ac_exists=true
+ break
+ fi
+ done
+
+ if test x"$ac_exists" = xtrue; then
+ :
+else
+ ac_cv_f77_libs="$ac_cv_f77_libs $ac_arg"
+fi
+
+ ;;
+ -bI:*)
+ ac_exists=false
+ for ac_i in $ac_cv_f77_libs; do
+ if test x"$ac_arg" = x"$ac_i"; then
+ ac_exists=true
+ break
+ fi
+ done
+
+ if test x"$ac_exists" = xtrue; then
+ :
+else
+ if test "$ac_compiler_gnu" = yes; then
+ for ac_link_opt in $ac_arg; do
+ ac_cv_f77_libs="$ac_cv_f77_libs -Xlinker $ac_link_opt"
+ done
+else
+ ac_cv_f77_libs="$ac_cv_f77_libs $ac_arg"
+fi
+fi
+
+ ;;
+ # Ignore these flags.
+ -lang* | -lcrt[01].o | -lcrtbegin.o | -lc | -lgcc | -libmil | -LANG:=*)
+ ;;
+ -lkernel32)
+ test x"$CYGWIN" != xyes && ac_cv_f77_libs="$ac_cv_f77_libs $ac_arg"
+ ;;
+ -[LRuY])
+ # These flags, when seen by themselves, take an argument.
+ # We remove the space between option and argument and re-iterate
+ # unless we find an empty arg or a new option (starting with -)
+ case $2 in
+ "" | -*);;
+ *)
+ ac_arg="$ac_arg$2"
+ shift; shift
+ set X $ac_arg "$@"
+ ;;
+ esac
+ ;;
+ -YP,*)
+ for ac_j in `echo $ac_arg | sed -e 's/-YP,/-L/;s/:/ -L/g'`; do
+ ac_exists=false
+ for ac_i in $ac_cv_f77_libs; do
+ if test x"$ac_j" = x"$ac_i"; then
+ ac_exists=true
+ break
+ fi
+ done
+
+ if test x"$ac_exists" = xtrue; then
+ :
+else
+ ac_arg="$ac_arg $ac_j"
+ ac_cv_f77_libs="$ac_cv_f77_libs $ac_j"
+fi
+
+ done
+ ;;
+ -[lLR]*)
+ ac_exists=false
+ for ac_i in $ac_cv_f77_libs; do
+ if test x"$ac_arg" = x"$ac_i"; then
+ ac_exists=true
+ break
+ fi
+ done
+
+ if test x"$ac_exists" = xtrue; then
+ :
+else
+ ac_cv_f77_libs="$ac_cv_f77_libs $ac_arg"
+fi
+
+ ;;
+ # Ignore everything else.
+ esac
+done
+# restore positional arguments
+set X $ac_save_positional; shift
+
+# We only consider "LD_RUN_PATH" on Solaris systems. If this is seen,
+# then we insist that the "run path" must be an absolute path (i.e. it
+# must begin with a "/").
+case `(uname -sr) 2>/dev/null` in
+ "SunOS 5"*)
+ ac_ld_run_path=`echo $ac_f77_v_output |
+ sed -n 's,^.*LD_RUN_PATH *= *\(/[^ ]*\).*$,-R\1,p'`
+ test "x$ac_ld_run_path" != x &&
+ if test "$ac_compiler_gnu" = yes; then
+ for ac_link_opt in $ac_ld_run_path; do
+ ac_cv_f77_libs="$ac_cv_f77_libs -Xlinker $ac_link_opt"
+ done
+else
+ ac_cv_f77_libs="$ac_cv_f77_libs $ac_ld_run_path"
+fi
+ ;;
+esac
+fi # test "x$[]_AC_LANG_PREFIX[]LIBS" = "x"
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_f77_libs" >&5
+echo "${ECHO_T}$ac_cv_f77_libs" >&6
+FLIBS="$ac_cv_f77_libs"
+
+
+ac_ext=f
+ac_compile='$F77 -c $FFLAGS conftest.$ac_ext >&5'
+ac_link='$F77 -o conftest$ac_exeext $FFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_f77_compiler_gnu
+
+
+# Try to compile a simple Fortran program (no linking)
+cat >conftest.$ac_ext <<_ACEOF
+
+ SUBROUTINE SUNDIALS()
+ RETURN
+ END
+
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_f77_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ F77_OK="yes"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+F77_OK="no"
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+
+# If CC is a C++ compiler (decided in SUNDIALS_CPLUSPLUS_CHECK), we must use
+# it to link the Fortran examples. In this case, test if that is successful.
+# Otherwise, simply use F77 as the linker
+
+if test "X${F77_OK}" = "Xyes"; then
+ echo "$as_me:$LINENO: checking which linker to use" >&5
+echo $ECHO_N "checking which linker to use... $ECHO_C" >&6
+ if test "X${USING_CPLUSPLUS_COMP}" = "Xyes"; then
+
+
+F77_LNKR_CHECK_OK="no"
+
+# Compile simple Fortran example, but do NOT link
+# Note: result stored as conftest.${ac_objext}
+cat >conftest.$ac_ext <<_ACEOF
+
+ PROGRAM SUNDIALS
+ WRITE(*,*)'TEST'
+ END
+
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_f77_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+
+
+# Temporarily reset LIBS environment variable to perform test
+SAVED_LIBS="${LIBS}"
+LIBS="${LIBS} ${FLIBS}"
+
+# Switch working language to C for next test
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_linkonly='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_objext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+# Check if CC can link Fortran example
+# Note: AC_LINKONLY_IFELSE is a custom macro (modifications made to
+# general.m4 and c.m4) (see config/cust_general.m4 and config/mod_c.m4)
+if { (eval echo "$as_me:$LINENO: \"$ac_linkonly\"") >&5
+ (eval $ac_linkonly) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ F77_LNKR_CHECK_OK="yes"
+else
+ echo "$as_me: failed program was:" >&5
+if test -f conftest.c ; then
+ sed 's/^/| /' conftest.c >&5
+elif test -f conftest.cc ; then
+ sed 's/^/| /' conftest.cc >&5
+elif test -f conftest.f ; then
+ sed 's/^/| /' conftest.f >&5
+elif test -f conftest.${FC_SRCEXT-f} ; then
+ sed 's/^/| /' conftest.${FC_SRCEXT-f} >&5
+fi
+
+F77_LNKR_CHECK_OK="no"
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext
+
+# Revert back to previous language (Fortran 77)
+ac_ext=f
+ac_compile='$F77 -c $FFLAGS conftest.$ac_ext >&5'
+ac_link='$F77 -o conftest$ac_exeext $FFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_f77_compiler_gnu
+
+
+# Set LIBS environment variable back to original value
+LIBS="${SAVED_LIBS}"
+
+
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+
+# If either the compilation or the linking failed, we should
+# disable building the Fortran examples
+# For now, use F77 as the linker...
+if test "X${F77_LNKR_CHECK_OK}" = "Xyes"; then
+ F77_LNKR="${CC}"
+else
+ F77_LNKR="${F77}"
+fi
+
+
+ else
+ F77_LNKR="${F77}"
+ fi
+ echo "$as_me:$LINENO: result: ${F77_LNKR}" >&5
+echo "${ECHO_T}${F77_LNKR}" >&6
+fi
+
+# Reset language (remove 'Fortran 77' from stack)
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_linkonly='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_objext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+
+ if test "X${F77_OK}" = "Xno"; then
+
+ SUNDIALS_WARN_FLAG="yes"
+
+ echo ""
+ echo " Unable to compile test program using given Fortran compiler."
+ echo ""
+ if test "X${FCMIX_ENABLED}" = "Xyes"; then
+ echo " Disabling compilation of Fortran-C interfaces..."
+ fi
+ if test "X${LAPACK_ENABLED}" = "Xyes"; then
+ echo " Disabling compilation of Blas/Lapack interfaces..."
+ fi
+ echo ""
+
+ FCMIX_ENABLED="no"
+ LAPACK_ENABLED="no"
+ F77_EXAMPLES_ENABLED="no"
+
+ fi
+
+fi
+
+
+# Determine the Fortran name-mangling scheme
+# If successfull, provide variable description templates for config.hin
+# and config.h files required by autoheader utility
+# Otherwise, disable all Fortran support.
+
+if test "X${F77_OK}" = "Xyes"; then
+
+
+
+ac_ext=f
+ac_compile='$F77 -c $FFLAGS conftest.$ac_ext >&5'
+ac_link='$F77 -o conftest$ac_exeext $FFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_f77_compiler_gnu
+
+
+# (1) Compile a dummy Fortran subroutine named SUNDIALS
+
+FNAME_STATUS="none"
+
+cat >conftest.$ac_ext <<_ACEOF
+
+ SUBROUTINE SUNDIALS()
+ RETURN
+ END
+
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_f77_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+
+
+ mv conftest.${ac_objext} f77_wrapper_check.${ac_objext}
+
+ # Temporarily reset LIBS environment variable to perform test
+ SAVED_LIBS="${LIBS}"
+ LIBS="f77_wrapper_check.${ac_objext} ${LIBS} ${FLIBS}"
+
+ ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_linkonly='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_objext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+ for i in "sundials" "SUNDIALS"
+ do
+ for j in "" "_" "__"
+ do
+ F77_MANGLED_NAME="${i}${j}"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char ${F77_MANGLED_NAME} ();
+int
+main ()
+{
+${F77_MANGLED_NAME} ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ FNAME_STATUS="set" ; break 2
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ done
+ done
+
+ ac_ext=f
+ac_compile='$F77 -c $FFLAGS conftest.$ac_ext >&5'
+ac_link='$F77 -o conftest$ac_exeext $FFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_f77_compiler_gnu
+
+
+ # If test succeeded, then set the F77_MANGLE_MACRO1 macro
+
+ if test "X${FNAME_STATUS}" = "Xset"; then
+
+ if test "X${i}" = "Xsundials"; then
+
+ FNAME_MSG="lower case "
+
+ if test "X${j}" = "X"; then
+ FNAME_MSG="${FNAME_MSG} + no underscore"
+ cat >>confdefs.h <<\_ACEOF
+#define SUNDIALS_F77_FUNC(name,NAME) name
+_ACEOF
+
+ F77_MANGLE_MACRO1="#define SUNDIALS_F77_FUNC(name,NAME) name"
+ dgemm="dgemm"
+ dgetrf="dgetrf"
+ elif test "X${j}" = "X_"; then
+ FNAME_MSG="${FNAME_MSG} + one underscore"
+ cat >>confdefs.h <<\_ACEOF
+#define SUNDIALS_F77_FUNC(name,NAME) name ## _
+_ACEOF
+
+ F77_MANGLE_MACRO1="#define SUNDIALS_F77_FUNC(name,NAME) name ## _"
+ dgemm="dgemm_"
+ dgetrf="dgetrf_"
+ else
+ FNAME_MSG="${FNAME_MSG} + two underscores"
+ cat >>confdefs.h <<\_ACEOF
+#define SUNDIALS_F77_FUNC(name,NAME) name ## __
+_ACEOF
+
+ F77_MANGLE_MACRO1="#define SUNDIALS_F77_FUNC(name,NAME) name ## __"
+ dgemm="dgemm__"
+ dgetrf="dgetrf__"
+ fi
+
+ else
+
+ FNAME_MSG="upper case "
+
+ if test "X${j}" = "X"; then
+ FNAME_MSG="${FNAME_MSG} + no underscore"
+ cat >>confdefs.h <<\_ACEOF
+#define SUNDIALS_F77_FUNC(name,NAME) name
+_ACEOF
+
+ F77_MANGLE_MACRO1="#define SUNDIALS_F77_FUNC(name,NAME) NAME"
+ dgemm="DGEMM"
+ dgetrf="DGETRF"
+ elif test "X${j}" = "X_"; then
+ FNAME_MSG="${FNAME_MSG} + one underscore"
+ cat >>confdefs.h <<\_ACEOF
+#define SUNDIALS_F77_FUNC(name,NAME) name ## _
+_ACEOF
+
+ F77_MANGLE_MACRO1="#define SUNDIALS_F77_FUNC(name,NAME) NAME ## _"
+ dgemm="DGEMM_"
+ dgetrf="DGETRF_"
+ else
+ FNAME_MSG="${FNAME_MSG} + two underscores"
+ cat >>confdefs.h <<\_ACEOF
+#define SUNDIALS_F77_FUNC(name,NAME) name ## __
+_ACEOF
+
+ F77_MANGLE_MACRO1="#define SUNDIALS_F77_FUNC(name,NAME) NAME ## __"
+ dgemm="DGEMM__"
+ dgetrf="DGETRF__"
+ fi
+
+ fi
+
+ echo "$as_me:$LINENO: checking for Fortran name-mangling scheme of C identifiers" >&5
+echo $ECHO_N "checking for Fortran name-mangling scheme of C identifiers... $ECHO_C" >&6
+ echo "$as_me:$LINENO: result: ${FNAME_MSG}" >&5
+echo "${ECHO_T}${FNAME_MSG}" >&6
+
+ else
+
+ F77_OK="no"
+
+ fi
+
+ # Set LIBS environment variable back to original value
+ LIBS="${SAVED_LIBS}"
+
+
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+
+# Remove temporary file
+rm -f f77_wrapper_check.${ac_objext}
+
+
+# (2) Compile a dummy Fortran subroutine named SUN_DIALS
+
+FNAME_STATUS="none"
+
+cat >conftest.$ac_ext <<_ACEOF
+
+ SUBROUTINE SUN_DIALS()
+ RETURN
+ END
+
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_f77_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+
+
+ mv conftest.${ac_objext} f77_wrapper_check.${ac_objext}
+
+ # Temporarily reset LIBS environment variable to perform test
+ SAVED_LIBS="${LIBS}"
+ LIBS="f77_wrapper_check.${ac_objext} ${LIBS} ${FLIBS}"
+
+ ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_linkonly='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_objext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+ for i in "sun_dials" "SUN_DIALS"
+ do
+ for j in "" "_" "__"
+ do
+ F77_MANGLED_NAME="${i}${j}"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char ${F77_MANGLED_NAME} ();
+int
+main ()
+{
+${F77_MANGLED_NAME} ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ FNAME_STATUS="set" ; break 2
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ done
+ done
+
+ ac_ext=f
+ac_compile='$F77 -c $FFLAGS conftest.$ac_ext >&5'
+ac_link='$F77 -o conftest$ac_exeext $FFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_f77_compiler_gnu
+
+
+ # If test succeeded, then set the F77_MANGLE_MACRO2 macro
+
+ if test "X${FNAME_STATUS}" = "Xset"; then
+
+ if test "X${i}" = "Xsun_dials"; then
+
+ FNAME_MSG="lower case "
+
+ if test "X${j}" = "X"; then
+ FNAME_MSG="${FNAME_MSG} + no underscore"
+ cat >>confdefs.h <<\_ACEOF
+#define SUNDIALS_F77_FUNC_(name,NAME) name
+_ACEOF
+
+ F77_MANGLE_MACRO2="#define SUNDIALS_F77_FUNC_(name,NAME) name"
+ elif test "X${j}" = "X_"; then
+ FNAME_MSG="${FNAME_MSG} + one underscore"
+ cat >>confdefs.h <<\_ACEOF
+#define SUNDIALS_F77_FUNC_(name,NAME) name ## _
+_ACEOF
+
+ F77_MANGLE_MACRO2="#define SUNDIALS_F77_FUNC_(name,NAME) name ## _"
+ else
+ FNAME_MSG="${FNAME_MSG} + two underscores"
+ cat >>confdefs.h <<\_ACEOF
+#define SUNDIALS_F77_FUNC_(name,NAME) name ## __
+_ACEOF
+
+ F77_MANGLE_MACRO2="#define SUNDIALS_F77_FUNC_(name,NAME) name ## __"
+ fi
+
+ else
+
+ FNAME_MSG="upper case "
+
+ if test "X${j}" = "X"; then
+ FNAME_MSG="${FNAME_MSG} + no underscore"
+ cat >>confdefs.h <<\_ACEOF
+#define SUNDIALS_F77_FUNC_(name,NAME) name
+_ACEOF
+
+ F77_MANGLE_MACRO2="#define SUNDIALS_F77_FUNC_(name,NAME) NAME"
+ elif test "X${j}" = "X_"; then
+ FNAME_MSG="${FNAME_MSG} + one underscore"
+ cat >>confdefs.h <<\_ACEOF
+#define SUNDIALS_F77_FUNC_(name,NAME) name ## _
+_ACEOF
+
+ F77_MANGLE_MACRO2="#define SUNDIALS_F77_FUNC_(name,NAME) NAME ## _"
+ else
+ FNAME_MSG="${FNAME_MSG} + two underscores"
+ cat >>confdefs.h <<\_ACEOF
+#define SUNDIALS_F77_FUNC_(name,NAME) name ## __
+_ACEOF
+
+ F77_MANGLE_MACRO2="#define SUNDIALS_F77_FUNC_(name,NAME) NAME ## __"
+ fi
+
+ fi
+
+ echo "$as_me:$LINENO: checking for Fortran name-mangling scheme of C identifiers with underscores" >&5
+echo $ECHO_N "checking for Fortran name-mangling scheme of C identifiers with underscores... $ECHO_C" >&6
+ echo "$as_me:$LINENO: result: ${FNAME_MSG}" >&5
+echo "${ECHO_T}${FNAME_MSG}" >&6
+
+ else
+
+ F77_OK="no"
+
+ fi
+
+ # Set LIBS environment variable back to original value
+ LIBS="${SAVED_LIBS}"
+
+
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+
+# Remove temporary file
+rm -f f77_wrapper_check.${ac_objext}
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_linkonly='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_objext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+
+
+
+
+
+
+ if test "X${F77_OK}" = "Xno"; then
+
+ SUNDIALS_WARN_FLAG="yes"
+
+ echo ""
+ echo " Unable to determine Fortran name-mangling scheme."
+ echo ""
+ if test "X${FCMIX_ENABLED}" = "Xyes"; then
+ echo " Disabling compilation of Fortran-C interfaces..."
+ fi
+ if test "X${LAPACK_ENABLED}" = "Xyes"; then
+ echo " Disabling compilation of Blas/Lapack interfaces..."
+ fi
+ echo ""
+
+ F77_EXAMPLES_ENABLED="no"
+ FCMIX_ENABLED="no"
+ LAPACK_ENABLED="no"
+
+ fi
+
+fi
+
+
+# If LAPACK is enabled, determine the proper library linkage
+# If successful, set the libaries
+# Otherwise, disable all Blas/Lapack support.
+
+if test "X${LAPACK_ENABLED}" = "Xyes" && test "X${F77_OK}" = "Xyes"; then
+
+
+
+
+# Check if the user specifies Blas libraries
+
+# Check whether --with-blas or --without-blas was given.
+if test "${with_blas+set}" = set; then
+ withval="$with_blas"
+
+ case $withval in
+ -* | */* | *.a | *.so | *.so.* | *.o)
+ BLAS_LIBS="$withval"
+ ;;
+ *)
+ BLAS_LIBS="-l$withval"
+ ;;
+ esac
+
+fi;
+
+# Check if the user specifies Lapack libraries
+
+# Check whether --with-lapack or --without-lapack was given.
+if test "${with_lapack+set}" = set; then
+ withval="$with_lapack"
+
+ case $withval in
+ -* | */* | *.a | *.so | *.so.* | *.o)
+ LAPACK_LIBS="$withval"
+ ;;
+ *)
+ LAPACK_LIBS="-l$withval"
+ ;;
+ esac
+
+fi;
+
+acx_blas_ok=no
+acx_lapack_ok=no
+
+# BLAS_LIBS
+# ---------
+
+acx_blas_save_LIBS="$LIBS"
+LIBS="$LIBS $FLIBS"
+
+# First, check BLAS_LIBS environment variable
+if test "x$BLAS_LIBS" != x; then
+ save_LIBS="$LIBS"
+ LIBS="$BLAS_LIBS $LIBS"
+ echo "$as_me:$LINENO: checking aha for $dgemm in $BLAS_LIBS" >&5
+echo $ECHO_N "checking aha for $dgemm in $BLAS_LIBS... $ECHO_C" >&6
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $dgemm ();
+int
+main ()
+{
+$dgemm ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ acx_blas_ok=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+BLAS_LIBS=""
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ echo "$as_me:$LINENO: result: $acx_blas_ok" >&5
+echo "${ECHO_T}$acx_blas_ok" >&6
+ LIBS="$save_LIBS"
+fi
+
+# BLAS linked to by default? (happens on some supercomputers)
+if test $acx_blas_ok = no; then
+ save_LIBS="$LIBS"; LIBS="$LIBS"
+ as_ac_var=`echo "ac_cv_func_$dgemm" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $dgemm" >&5
+echo $ECHO_N "checking for $dgemm... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define $dgemm to an innocuous variant, in case <limits.h> declares $dgemm.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define $dgemm innocuous_$dgemm
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $dgemm (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $dgemm
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $dgemm ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$dgemm) || defined (__stub___$dgemm)
+choke me
+#else
+char (*f) () = $dgemm;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != $dgemm;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ eval "$as_ac_var=yes"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_var=no"
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+ acx_blas_ok=yes
+fi
+
+ LIBS="$save_LIBS"
+fi
+
+# BLAS in Alpha CXML library?
+if test $acx_blas_ok = no; then
+ as_ac_Lib=`echo "ac_cv_lib_cxml_$dgemm" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $dgemm in -lcxml" >&5
+echo $ECHO_N "checking for $dgemm in -lcxml... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Lib+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lcxml $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $dgemm ();
+int
+main ()
+{
+$dgemm ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ eval "$as_ac_Lib=yes"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_Lib=no"
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Lib'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Lib'}'`" >&6
+if test `eval echo '${'$as_ac_Lib'}'` = yes; then
+ acx_blas_ok=yes;BLAS_LIBS="-lcxml"
+fi
+
+fi
+
+# BLAS in Alpha DXML library? (now called CXML, see above)
+if test $acx_blas_ok = no; then
+ as_ac_Lib=`echo "ac_cv_lib_dxml_$dgemm" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $dgemm in -ldxml" >&5
+echo $ECHO_N "checking for $dgemm in -ldxml... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Lib+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldxml $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $dgemm ();
+int
+main ()
+{
+$dgemm ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ eval "$as_ac_Lib=yes"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_Lib=no"
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Lib'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Lib'}'`" >&6
+if test `eval echo '${'$as_ac_Lib'}'` = yes; then
+ acx_blas_ok=yes;BLAS_LIBS="-ldxml"
+fi
+
+fi
+
+# BLAS in Sun Performance library?
+if test $acx_blas_ok = no; then
+ if test "x$GCC" != xyes; then # only works with Sun CC
+ echo "$as_me:$LINENO: checking for acosp in -lsunmath" >&5
+echo $ECHO_N "checking for acosp in -lsunmath... $ECHO_C" >&6
+if test "${ac_cv_lib_sunmath_acosp+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lsunmath $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char acosp ();
+int
+main ()
+{
+acosp ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_lib_sunmath_acosp=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_sunmath_acosp=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_sunmath_acosp" >&5
+echo "${ECHO_T}$ac_cv_lib_sunmath_acosp" >&6
+if test $ac_cv_lib_sunmath_acosp = yes; then
+ as_ac_Lib=`echo "ac_cv_lib_sunperf_$dgemm" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $dgemm in -lsunperf" >&5
+echo $ECHO_N "checking for $dgemm in -lsunperf... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Lib+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lsunperf -lsunmath $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $dgemm ();
+int
+main ()
+{
+$dgemm ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ eval "$as_ac_Lib=yes"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_Lib=no"
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Lib'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Lib'}'`" >&6
+if test `eval echo '${'$as_ac_Lib'}'` = yes; then
+ BLAS_LIBS="-xlic_lib=sunperf -lsunmath"
+ acx_blas_ok=yes
+fi
+
+fi
+
+ fi
+fi
+
+# BLAS in SCSL library? (SGI/Cray Scientific Library)
+if test $acx_blas_ok = no; then
+ as_ac_Lib=`echo "ac_cv_lib_scs_$dgemm" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $dgemm in -lscs" >&5
+echo $ECHO_N "checking for $dgemm in -lscs... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Lib+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lscs $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $dgemm ();
+int
+main ()
+{
+$dgemm ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ eval "$as_ac_Lib=yes"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_Lib=no"
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Lib'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Lib'}'`" >&6
+if test `eval echo '${'$as_ac_Lib'}'` = yes; then
+ acx_blas_ok=yes; BLAS_LIBS="-lscs"
+fi
+
+fi
+
+# BLAS in SGIMATH library?
+if test $acx_blas_ok = no; then
+ as_ac_Lib=`echo "ac_cv_lib_complib.sgimath_$dgemm" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $dgemm in -lcomplib.sgimath" >&5
+echo $ECHO_N "checking for $dgemm in -lcomplib.sgimath... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Lib+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lcomplib.sgimath $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $dgemm ();
+int
+main ()
+{
+$dgemm ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ eval "$as_ac_Lib=yes"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_Lib=no"
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Lib'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Lib'}'`" >&6
+if test `eval echo '${'$as_ac_Lib'}'` = yes; then
+ acx_blas_ok=yes; BLAS_LIBS="-lcomplib.sgimath"
+fi
+
+fi
+
+# BLAS in IBM ESSL library? (requires generic BLAS lib, too)
+if test $acx_blas_ok = no; then
+ as_ac_Lib=`echo "ac_cv_lib_blas_$dgemm" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $dgemm in -lblas" >&5
+echo $ECHO_N "checking for $dgemm in -lblas... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Lib+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lblas $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $dgemm ();
+int
+main ()
+{
+$dgemm ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ eval "$as_ac_Lib=yes"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_Lib=no"
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Lib'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Lib'}'`" >&6
+if test `eval echo '${'$as_ac_Lib'}'` = yes; then
+ as_ac_Lib=`echo "ac_cv_lib_essl_$dgemm" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $dgemm in -lessl" >&5
+echo $ECHO_N "checking for $dgemm in -lessl... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Lib+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lessl -lblas $FLIBS $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $dgemm ();
+int
+main ()
+{
+$dgemm ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ eval "$as_ac_Lib=yes"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_Lib=no"
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Lib'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Lib'}'`" >&6
+if test `eval echo '${'$as_ac_Lib'}'` = yes; then
+ acx_blas_ok=yes; BLAS_LIBS="-lessl -lblas"
+fi
+
+fi
+
+fi
+
+# Generic BLAS library?
+if test $acx_blas_ok = no; then
+ as_ac_Lib=`echo "ac_cv_lib_blas_$dgemm" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $dgemm in -lblas" >&5
+echo $ECHO_N "checking for $dgemm in -lblas... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Lib+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lblas $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $dgemm ();
+int
+main ()
+{
+$dgemm ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ eval "$as_ac_Lib=yes"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_Lib=no"
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Lib'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Lib'}'`" >&6
+if test `eval echo '${'$as_ac_Lib'}'` = yes; then
+ acx_blas_ok=yes; BLAS_LIBS="-lblas"
+fi
+
+fi
+
+LIBS="$acx_blas_save_LIBS"
+
+# LAPACK
+# ------
+
+# If we didn't find a Blas implementation, disable tests for Lapack
+if test $acx_blas_ok = no; then
+ acx_lapack_ok=disabled
+fi
+
+# Check LAPACK_LIBS environment variable
+if test $acx_lapack_ok = no; then
+if test "x$LAPACK_LIBS" != x; then
+ save_LIBS="$LIBS";
+ LIBS="$LAPACK_LIBS $BLAS_LIBS $LIBS $FLIBS"
+ echo "$as_me:$LINENO: checking for $dgetrf in $LAPACK_LIBS" >&5
+echo $ECHO_N "checking for $dgetrf in $LAPACK_LIBS... $ECHO_C" >&6
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $dgetrf ();
+int
+main ()
+{
+$dgetrf ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ acx_lapack_ok=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+LAPACK_LIBS=""
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ echo "$as_me:$LINENO: result: $acx_lapack_ok" >&5
+echo "${ECHO_T}$acx_lapack_ok" >&6
+ LIBS="$save_LIBS"
+ if test acx_lapack_ok = no; then
+ LAPACK_LIBS=""
+ fi
+fi
+fi
+
+# LAPACK linked to by default? (is sometimes included in BLAS lib)
+if test $acx_lapack_ok = no; then
+ save_LIBS="$LIBS"
+ LIBS="$LIBS $BLAS_LIBS $FLIBS"
+ as_ac_var=`echo "ac_cv_func_$dgetrf" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $dgetrf" >&5
+echo $ECHO_N "checking for $dgetrf... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define $dgetrf to an innocuous variant, in case <limits.h> declares $dgetrf.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define $dgetrf innocuous_$dgetrf
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $dgetrf (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $dgetrf
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $dgetrf ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$dgetrf) || defined (__stub___$dgetrf)
+choke me
+#else
+char (*f) () = $dgetrf;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != $dgetrf;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ eval "$as_ac_var=yes"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_var=no"
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+ acx_lapack_ok=yes
+fi
+
+ LIBS="$save_LIBS"
+fi
+
+# Generic LAPACK library?
+for lapack in lapack lapack_rs6k; do
+ if test $acx_lapack_ok = no; then
+ save_LIBS="$LIBS"
+ LIBS="$BLAS_LIBS $LIBS"
+ as_ac_Lib=`echo "ac_cv_lib_$lapack''_$dgetrf" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $dgetrf in -l$lapack" >&5
+echo $ECHO_N "checking for $dgetrf in -l$lapack... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Lib+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-l$lapack $FLIBS $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $dgetrf ();
+int
+main ()
+{
+$dgetrf ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ eval "$as_ac_Lib=yes"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_Lib=no"
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Lib'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Lib'}'`" >&6
+if test `eval echo '${'$as_ac_Lib'}'` = yes; then
+ acx_lapack_ok=yes; LAPACK_LIBS="-l$lapack"
+fi
+
+ LIBS="$save_LIBS"
+ fi
+done
+
+# If we have both libraries, set LAPACK_OK to yes
+# -----------------------------------------------------
+
+if test $acx_blas_ok = yes && test $acx_lapack_ok = yes; then
+ LAPACK_OK="yes"
+else
+ LAPACK_OK="no"
+fi
+
+
+
+ if test "X${LAPACK_OK}" = "Xyes"; then
+
+ echo "$as_me:$LINENO: checking for Blas/Lapack library linkage" >&5
+echo $ECHO_N "checking for Blas/Lapack library linkage... $ECHO_C" >&6
+ BLAS_LAPACK_LIBS="${LAPACK_LIBS} ${BLAS_LIBS} ${LIBS} ${FLIBS}"
+ echo "$as_me:$LINENO: result: ${LAPACK_LIBS} ${BLAS_LIBS}" >&5
+echo "${ECHO_T}${LAPACK_LIBS} ${BLAS_LIBS}" >&6
+
+ else
+
+ SUNDIALS_WARN_FLAG="yes"
+ echo "$as_me:$LINENO: checking for Blas/Lapack library linkage" >&5
+echo $ECHO_N "checking for Blas/Lapack library linkage... $ECHO_C" >&6
+ echo "$as_me:$LINENO: result: \"no\"" >&5
+echo "${ECHO_T}\"no\"" >&6
+ echo ""
+ echo " Unable to determine Blas/Lapack library linkage."
+ echo ""
+ echo " Try using --with-blas and --with-lapack."
+ echo ""
+ echo " Disabling compilation of Blas/Lapack interfaces..."
+
+ LAPACK_ENABLED="no"
+
+ fi
+
+fi
+
+
+# Set the macro BLAS_LAPACK_MACRO for expansion in sundials_config.h
+
+
+
+
+if test "X${LAPACK_ENABLED}" = "Xyes"; then
+ cat >>confdefs.h <<\_ACEOF
+#define SUNDIALS_BLAS_LAPACK 1
+_ACEOF
+
+ BLAS_LAPACK_MACRO="#define SUNDIALS_BLAS_LAPACK 1"
+else
+ cat >>confdefs.h <<\_ACEOF
+#define SUNDIALS_BLAS_LAPACK 0
+_ACEOF
+
+ BLAS_LAPACK_MACRO="#define SUNDIALS_BLAS_LAPACK 0"
+fi
+
+
+fi
+
+# Set MPI support (Optional)
+if test "X${MPI_ENABLED}" = "Xyes"; then
+ echo ""
+ echo "MPI-C Settings"
+ echo "--------------"
+ echo ""
+
+
+
+# Check whether --with- or --without- was given.
+if test "${with_+set}" = set; then
+ withval="$with_"
+
+fi;
+
+# MPI root directory
+
+# Check whether --with-mpi-root or --without-mpi-root was given.
+if test "${with_mpi_root+set}" = set; then
+ withval="$with_mpi_root"
+
+MPI_ROOT_DIR="${withval}"
+
+else
+
+MPI_ROOT_DIR=""
+
+fi;
+
+# MPI include directory
+
+# Check whether --with-mpi-incdir or --without-mpi-incdir was given.
+if test "${with_mpi_incdir+set}" = set; then
+ withval="$with_mpi_incdir"
+
+MPI_INC_DIR="${withval}"
+
+else
+
+MPI_INC_DIR=""
+
+fi;
+
+# MPI library directory
+
+# Check whether --with-mpi-libdir or --without-mpi-libdir was given.
+if test "${with_mpi_libdir+set}" = set; then
+ withval="$with_mpi_libdir"
+
+MPI_LIB_DIR="${withval}"
+
+else
+
+MPI_LIB_DIR=""
+
+fi;
+
+# MPI libraries
+
+# Check whether --with-mpi-libs or --without-mpi-libs was given.
+if test "${with_mpi_libs+set}" = set; then
+ withval="$with_mpi_libs"
+
+MPI_LIBS="${withval}"
+
+else
+
+MPI_LIBS=""
+
+fi;
+
+# MPI flags
+
+# Check whether --with-mpi-flags or --without-mpi-flags was given.
+if test "${with_mpi_flags+set}" = set; then
+ withval="$with_mpi_flags"
+
+MPI_FLAGS="${withval}"
+MPI_FLAGS_OK="yes"
+
+else
+
+MPI_FLAGS=""
+MPI_FLAGS_OK="no"
+
+fi;
+
+# MPI-C compiler
+MPICC_COMP_GIVEN="yes"
+echo "$as_me:$LINENO: checking if using MPI-C script" >&5
+echo $ECHO_N "checking if using MPI-C script... $ECHO_C" >&6
+
+# Check whether --with-mpicc or --without-mpicc was given.
+if test "${with_mpicc+set}" = set; then
+ withval="$with_mpicc"
+
+if test "X${withval}" = "Xno"; then
+ USE_MPICC_SCRIPT="no"
+else
+ USE_MPICC_SCRIPT="yes"
+ MPICC_COMP="${withval}"
+fi
+
+else
+
+ USE_MPICC_SCRIPT="yes"
+ MPICC_COMP="mpicc"
+ MPICC_COMP_GIVEN="no"
+
+fi;
+echo "$as_me:$LINENO: result: ${USE_MPICC_SCRIPT}" >&5
+echo "${ECHO_T}${USE_MPICC_SCRIPT}" >&6
+
+# If CC is a C++ compiler, then we certainly do NOT want to use an MPI-C script
+# Note: USING_CPLUSPLUS_COMP was defined by a call to SUNDIALS_CPLUSPLUS_CHECK
+# in SUNDIALS_SET_CC
+# Note: If the user specified an MPI-C script, then we will NOT do anything for now
+if test "X${MPICC_COMP_GIVEN}" = "Xno" && test "X${USING_CPLUSPLUS_COMP}" = "Xyes"; then
+ MPICC_COMP="mpiCC"
+fi
+
+# Check MPI-C compiler (either MPI compiler script or regular C compiler)
+if test "X${USE_MPICC_SCRIPT}" = "Xyes"; then
+
+
+# Test MPI-C compiler (meaning test MPICC_COMP)
+# Check if MPI-C compiler can be found
+
+echo "$as_me:$LINENO: checking if absolute path to ${MPICC_COMP} was given" >&5
+echo $ECHO_N "checking if absolute path to ${MPICC_COMP} was given... $ECHO_C" >&6
+
+# CASE 1: MPICC_COMP was found (cannot check if executable because the
+# "-x" flag is NOT portable)
+if test -f ${MPICC_COMP} ; then
+
+ echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+ MPICC_COMP_EXISTS="yes"
+ # Determine MPI_INC_DIR and MPI_LIB_DIR for use by Makefile
+ MPI_BASE_DIR=`(dirname "${MPICC_COMP}") 2>/dev/null ||
+$as_expr X"${MPICC_COMP}" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"${MPICC_COMP}" : 'X\(//\)[^/]' \| \
+ X"${MPICC_COMP}" : 'X\(//\)$' \| \
+ X"${MPICC_COMP}" : 'X\(/\)' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X"${MPICC_COMP}" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+ /^X\(\/\/\)$/{ s//\1/; q; }
+ /^X\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+ TMP_MPI_INC_DIR="${MPI_BASE_DIR}/../include"
+ TMP_MPI_LIB_DIR="${MPI_BASE_DIR}/../lib"
+
+# CASE 2: MPICC_COMP could NOT be found and MPI_ROOT_DIR was NOT specified,
+# so search in PATH
+else
+
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+
+ if test "X${MPI_ROOT_DIR}" = "X"; then
+ # Try to find location of executable (perhaps directory was entered
+ # incorrectly)
+ TEMP_MPICC_COMP=`basename "${MPICC_COMP}"`
+ # Extract the first word of "${TEMP_MPICC_COMP}", so it can be a program name with args.
+set dummy ${TEMP_MPICC_COMP}; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_path_MPICC_COMP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ case $MPICC_COMP in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_MPICC_COMP="$MPICC_COMP" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_path_MPICC_COMP="$as_dir/$ac_word$ac_exec_ext"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+ test -z "$ac_cv_path_MPICC_COMP" && ac_cv_path_MPICC_COMP="none"
+ ;;
+esac
+fi
+MPICC_COMP=$ac_cv_path_MPICC_COMP
+
+if test -n "$MPICC_COMP"; then
+ echo "$as_me:$LINENO: result: $MPICC_COMP" >&5
+echo "${ECHO_T}$MPICC_COMP" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ # Cannot find executable in PATH
+ if test "X${MPICC_COMP}" = "Xnone"; then
+ MPICC_COMP_EXISTS="no"
+ MPICC_COMP=""
+ # Found executable and set MPICC_COMP to absolute pathname
+ else
+ MPICC_COMP_EXISTS="yes"
+ MPI_BASE_DIR=`(dirname "${MPICC_COMP}") 2>/dev/null ||
+$as_expr X"${MPICC_COMP}" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"${MPICC_COMP}" : 'X\(//\)[^/]' \| \
+ X"${MPICC_COMP}" : 'X\(//\)$' \| \
+ X"${MPICC_COMP}" : 'X\(/\)' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X"${MPICC_COMP}" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+ /^X\(\/\/\)$/{ s//\1/; q; }
+ /^X\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+ TMP_MPI_INC_DIR="${MPI_BASE_DIR}/../include"
+ TMP_MPI_LIB_DIR="${MPI_BASE_DIR}/../lib"
+ fi
+
+ # CASE 3: MPICC_COMP could NOT be found, but MPI_ROOT_DIR was specified
+ else
+
+ echo "$as_me:$LINENO: checking if ${MPICC_COMP} exists in ${MPI_ROOT_DIR}/bin" >&5
+echo $ECHO_N "checking if ${MPICC_COMP} exists in ${MPI_ROOT_DIR}/bin... $ECHO_C" >&6
+ # MPICC_COMP should really only contain an executable name
+ # Found location of MPICC_COMP
+ if test -f ${MPI_ROOT_DIR}/bin/${MPICC_COMP} ; then
+ echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+ MPICC_COMP_EXISTS="yes"
+ MPICC_COMP="${MPI_ROOT_DIR}/bin/${MPICC_COMP}"
+ TMP_MPI_INC_DIR="${MPI_ROOT_DIR}/include"
+ TMP_MPI_LIB_DIR="${MPI_ROOT_DIR}/lib"
+ # Could NOT find MPICC_COMP anywhere
+ else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+ MPICC_COMP_EXISTS="no"
+ MPICC_COMP=""
+ fi
+
+ fi
+
+fi
+
+# If MPICC_COMP exists, set MPICC and (conditionally) set MPI_INC_DIR
+# and MPI_LIB_DIR so that we do not end up with empty -I options.
+# Otherwise, issue warning message
+if test "X${MPICC_COMP_EXISTS}" = "Xyes"; then
+
+ MPICC="${MPICC_COMP}"
+ MPI_C_COMP_OK="yes"
+
+ # If MPI_INC_DIR is empty, set it to TMP_MPI_INC_DIR
+ if test "X${MPI_INC_DIR}" = "X"; then
+ MPI_INC_DIR="$TMP_MPI_INC_DIR"
+ fi
+
+ # If MPI_LIB_DIR is empty, set it to TMP_MPI_LIB_DIR
+ if test "X${MPI_LIB_DIR}" = "X"; then
+ MPI_LIB_DIR="$TMP_MPI_LIB_DIR"
+ fi
+
+else
+
+ { echo "$as_me:$LINENO: WARNING: cannot find MPI-C compiler" >&5
+echo "$as_me: WARNING: cannot find MPI-C compiler" >&2;}
+ echo ""
+ echo " Unable to find a functional MPI-C compiler."
+ echo ""
+ echo " Try using --with-mpicc to specify a MPI-C compiler script,"
+ echo " --with-mpi-incdir, --with-mpi-libdir and --with-mpi-libs"
+ echo " to specify the locations of all relevant MPI files, or"
+ echo " --with-mpi-root to specify the base installation directory"
+ echo " of the MPI implementation to be used."
+ echo ""
+ echo " Disabling the parallel NVECTOR module and all parallel examples..."
+ echo ""
+ MPICC=""
+ MPI_C_COMP_OK="no"
+ SUNDIALS_WARN_FLAG="yes"
+
+fi
+
+
+else
+ MPICC_COMP="${CC}"
+ MPICC="${CC}"
+
+
+# Test if we can compile MPI programs using the CC compiler
+# and current MPI settings
+
+{ echo "$as_me:$LINENO: Testing CC with MPI settings" >&5
+echo "$as_me: Testing CC with MPI settings" >&6;}
+
+# Save copies of CPPFLAGS, LDFLAGS and LIBS (preserve information)
+# Temporarily overwritten so we can test MPI implementation
+SAVED_CPPFLAGS="${CPPFLAGS}"
+SAVED_LDFLAGS="${LDFLAGS}"
+SAVED_LIBS="${LIBS}"
+
+# Determine location of MPI header files (find MPI include directory)
+MPI_EXISTS="yes"
+
+echo "$as_me:$LINENO: checking for location of MPI implementation" >&5
+echo $ECHO_N "checking for location of MPI implementation... $ECHO_C" >&6
+
+# If MPI include directory was NOT explicitly specified, check if MPI root
+# directory was given by user
+if test "X${MPI_INC_DIR}" = "X"; then
+ # If MPI root directory was NOT given so issue a warning message
+ if test "X${MPI_ROOT_DIR}" = "X"; then
+ echo "$as_me:$LINENO: result: not found" >&5
+echo "${ECHO_T}not found" >&6
+ MPI_EXISTS="no"
+ { echo "$as_me:$LINENO: WARNING: cannot find MPI implementation files" >&5
+echo "$as_me: WARNING: cannot find MPI implementation files" >&2;}
+ echo ""
+ echo " Unable to find MPI implementation files."
+ echo ""
+ echo " Try using --with-mpicc to specify a MPI-C compiler script,"
+ echo " --with-mpi-incdir, --with-mpi-libdir and --with-mpi-libs"
+ echo " to specify the locations of all relevant MPI files, or"
+ echo " --with-mpi-root to specify the base installation directory"
+ echo " of the MPI implementation to be used."
+ echo ""
+ echo " Disabling the parallel NVECTOR module and all parallel examples..."
+ echo ""
+ SUNDIALS_WARN_FLAG="yes"
+ # MPI root directory was given so set MPI_INC_DIR accordingly
+ # Update CPPFLAGS
+ else
+ MPI_INC_DIR="${MPI_ROOT_DIR}/include"
+ echo "$as_me:$LINENO: result: ${MPI_INC_DIR}" >&5
+echo "${ECHO_T}${MPI_INC_DIR}" >&6
+ if test "X${CPPFLAGS}" = "X"; then
+ CPPFLAGS="-I${MPI_INC_DIR}"
+ else
+ CPPFLAGS="${CPPFLAGS} -I${MPI_INC_DIR}"
+ fi
+ # Add MPI_FLAGS if non-empty
+ if test "X${MPI_FLAGS}" = "X"; then
+ CPPFLAGS="${CPPFLAGS}"
+ else
+ CPPFLAGS="${CPPFLAGS} ${MPI_FLAGS}"
+ fi
+ fi
+# MPI include directory was specified so update CPPFLAGS
+else
+ echo "$as_me:$LINENO: result: ${MPI_INC_DIR}" >&5
+echo "${ECHO_T}${MPI_INC_DIR}" >&6
+ if test "X${CPPFLAGS}" = "X"; then
+ CPPFLAGS="-I${MPI_INC_DIR}"
+ else
+ CPPFLAGS="${CPPFLAGS} -I${MPI_INC_DIR}"
+ fi
+ # Add MPI_FLAGS if non-empty
+ if test "X${MPI_FLAGS}" = "X"; then
+ CPPFLAGS="${CPPFLAGS}"
+ else
+ CPPFLAGS="${CPPFLAGS} ${MPI_FLAGS}"
+ fi
+fi
+
+# Only continue if found an MPI implementation
+if test "X${MPI_EXISTS}" = "Xyes"; then
+
+ echo "$as_me:$LINENO: checking for location of MPI libraries" >&5
+echo $ECHO_N "checking for location of MPI libraries... $ECHO_C" >&6
+
+ # Determine location of MPI libraries
+ # MPI library directory was NOT specified by user so set based upon MPI_ROOT_DIR
+ # Update LDFLAGS
+ if test "X${MPI_LIB_DIR}" = "X"; then
+ MPI_LIB_DIR="${MPI_ROOT_DIR}/lib"
+ echo "$as_me:$LINENO: result: ${MPI_LIB_DIR}" >&5
+echo "${ECHO_T}${MPI_LIB_DIR}" >&6
+ if test "X${LDFLAGS}" = "X"; then
+ LDFLAGS="-L${MPI_LIB_DIR}"
+ else
+ LDFLAGS="${LDFLAGS} -L${MPI_LIB_DIR}"
+ fi
+ # MPI library directory was specified so update LDFLAGS
+ else
+ echo "$as_me:$LINENO: result: ${MPI_LIB_DIR}" >&5
+echo "${ECHO_T}${MPI_LIB_DIR}" >&6
+ if test "X${LDFLAGS}" = "X"; then
+ LDFLAGS="-L${MPI_LIB_DIR}"
+ else
+ LDFLAGS="${LDFLAGS} -L${MPI_LIB_DIR}"
+ fi
+ fi
+
+ # Check if user specified which MPI libraries must be included
+ # If no libraries are given, then issue a warning message
+ echo "$as_me:$LINENO: checking for MPI libraries" >&5
+echo $ECHO_N "checking for MPI libraries... $ECHO_C" >&6
+ if test "X${MPI_LIBS}" = "X"; then
+ echo "$as_me:$LINENO: result: none" >&5
+echo "${ECHO_T}none" >&6
+ { echo "$as_me:$LINENO: WARNING: no MPI libraries were given" >&5
+echo "$as_me: WARNING: no MPI libraries were given" >&2;}
+ echo ""
+ echo " Unable to compile MPI program using C compiler because"
+ echo " MPI libraries were not specified."
+ echo ""
+ echo " Try using --with-mpi-libdir and --with-mpi-libs to"
+ echo " specify the location and names of the MPI libraries."
+ echo ""
+ echo " Disabling the parallel NVECTOR module and all parallel examples..."
+ echo ""
+ MPI_C_COMP_OK="no"
+ SUNDIALS_WARN_FLAG="yes"
+ # MPI libraries were specified so update LIBS
+ else
+ echo "$as_me:$LINENO: result: ${MPI_LIBS}" >&5
+echo "${ECHO_T}${MPI_LIBS}" >&6
+ if test "X${LIBS}" = "X"; then
+ LIBS="${MPI_LIBS}"
+ else
+ LIBS="${LIBS} ${MPI_LIBS}"
+ fi
+ # Set the MPI_C_COMP_OK variable to NULL so we can conditionally execute
+ # the next test
+ MPI_C_COMP_OK=""
+ fi
+
+ if test "X${MPI_C_COMP_OK}" = "X"; then
+ echo "$as_me:$LINENO: checking if C compiler can compile MPI programs" >&5
+echo $ECHO_N "checking if C compiler can compile MPI programs... $ECHO_C" >&6
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include "mpi.h"
+int
+main ()
+{
+int c; char **v; MPI_Init(&c,&v);
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+ MPI_C_COMP_OK="yes"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+ { echo "$as_me:$LINENO: WARNING: C compiler cannot compile MPI programs" >&5
+echo "$as_me: WARNING: C compiler cannot compile MPI programs" >&2;}
+ echo ""
+ echo " Unable to compile MPI program using C compiler."
+ echo ""
+ echo " Try using --with-mpicc to specify a MPI-C compiler script,"
+ echo " --with-mpi-incdir, --with-mpi-libdir and --with-mpi-libs"
+ echo " to specify the locations of all relevant MPI files, or"
+ echo " --with-mpi-root to specify the base installation directory"
+ echo " of the MPI implementation to be used."
+ echo ""
+ echo " Disabling the parallel NVECTOR module and all parallel examples..."
+ echo ""
+ MPI_C_COMP_OK="no"
+ SUNDIALS_WARN_FLAG="yes"
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ fi
+else
+ MPI_C_COMP_OK="no"
+fi
+
+# Restore CPPFLAGS, LDFLAGS and LIBS
+CPPFLAGS="${SAVED_CPPFLAGS}"
+LDFLAGS="${SAVED_LDFLAGS}"
+LIBS="${SAVED_LIBS}"
+
+
+fi
+
+
+fi
+if test "X${MPI_C_COMP_OK}" = "Xyes"; then
+ if test "X${FCMIX_ENABLED}" = "Xyes"; then
+ echo ""
+ echo "MPI-2 Functionality"
+ echo "-------------------"
+ echo ""
+
+
+# Determine if MPI implementation used to build SUNDIALS provides
+# MPI-2 functionality.
+#
+# Test for MPI_Comm_f2c() function:
+# (1) NO : FNVECTOR_PARALLEL module will NOT allow user to specify
+# an MPI communicator and MPI_COMM_WORLD will be used
+# (2) YES : FNVECTOR_PARALLEL module will allow user to specify
+# an MPI communicator
+#
+
+# Provide variable description templates for config.hin and config.h files
+# Required by autoheader utility
+
+
+
+# Save copies of CPPFLAGS, LDFLAGS and LIBS (preserve information)
+# Temporarily overwritten so we can test MPI implementation
+SAVED_CPPFLAGS="${CPPFLAGS}"
+SAVED_LDFLAGS="${LDFLAGS}"
+SAVED_LIBS="${LIBS}"
+
+# Determine location of MPI header files (find MPI include directory)
+MPI_EXISTS="yes"
+
+# MPI include directory was NOT explicitly specified so check if MPI root
+# directory was given by user
+if test "X${MPI_INC_DIR}" = "X"; then
+ # MPI root directory was NOT given so issue a warning message
+ if test "X${MPI_ROOT_DIR}" = "X"; then
+ MPI_EXISTS="no"
+ { echo "$as_me:$LINENO: WARNING: cannot find MPI implementation files" >&5
+echo "$as_me: WARNING: cannot find MPI implementation files" >&2;}
+ echo ""
+ echo " Unable to find MPI implementation files."
+ echo ""
+ echo " Try using --with-mpicc to specify a MPI-C compiler script,"
+ echo " --with-mpi-incdir, --with-mpi-libdir and --with-mpi-libs"
+ echo " to specify the locations of all relevant MPI files, or"
+ echo " --with-mpi-root to specify the base installation directory"
+ echo " of the MPI implementation to be used."
+ echo ""
+ echo " Disabling FNVECTOR_PARALLEL support for user-specified"
+ echo " MPI communicator..."
+ echo ""
+ SUNDIALS_WARN_FLAG="yes"
+ # MPI root directory was given so set MPI_INC_DIR accordingly
+ # Update CPPFLAGS
+ else
+ MPI_INC_DIR="${MPI_ROOT_DIR}/include"
+ if test "X${CPPFLAGS}" = "X"; then
+ CPPFLAGS="-I${MPI_INC_DIR}"
+ else
+ CPPFLAGS="${CPPFLAGS} -I${MPI_INC_DIR}"
+ fi
+ # Add MPI_FLAGS if non-empty
+ if test "X${MPI_FLAGS}" = "X"; then
+ CPPFLAGS="${CPPFLAGS}"
+ else
+ CPPFLAGS="${CPPFLAGS} ${MPI_FLAGS}"
+ fi
+ fi
+# MPI include directory was specified so update CPPFLAGS
+else
+ if test "X${CPPFLAGS}" = "X"; then
+ CPPFLAGS="-I${MPI_INC_DIR}"
+ else
+ CPPFLAGS="${CPPFLAGS} -I${MPI_INC_DIR}"
+ fi
+ # Add MPI_FLAGS if non-empty
+ if test "X${MPI_FLAGS}" = "X"; then
+ CPPFLAGS="${CPPFLAGS}"
+ else
+ CPPFLAGS="${CPPFLAGS} ${MPI_FLAGS}"
+ fi
+fi
+
+# Only continue if found an MPI implementation
+if test "X${MPI_EXISTS}" = "Xyes"; then
+
+ # Determine location of MPI libraries
+ # MPI library directory was NOT specified by user so set based upon MPI_ROOT_DIR
+ # Update LDFLAGS
+ if test "X${MPI_LIB_DIR}" = "X"; then
+ MPI_LIB_DIR="${MPI_ROOT_DIR}/lib"
+ if test "X${LDFLAGS}" = "X"; then
+ LDFLAGS="-L${MPI_LIB_DIR}"
+ else
+ LDFLAGS="${LDFLAGS} -L${MPI_LIB_DIR}"
+ fi
+ # MPI library directory was specified so update LDFLAGS
+ else
+ if test "X${LDFLAGS}" = "X"; then
+ LDFLAGS="-L${MPI_LIB_DIR}"
+ else
+ LDFLAGS="${LDFLAGS} -L${MPI_LIB_DIR}"
+ fi
+ fi
+
+ # Check if user specified which MPI libraries linker should be use
+ if test "X${MPI_LIBS}" = "X"; then
+ :
+ # MPI libraries were specified so update LIBS
+ else
+ if test "X${LIBS}" = "X"; then
+ LIBS="${MPI_LIBS}"
+ else
+ LIBS="${LIBS} ${MPI_LIBS}"
+ fi
+ fi
+
+ # Since AC_LINK_IFELSE uses CC, set CC = MPICC if using
+ # an MPI compiler script
+ if test "X${USE_MPICC_SCRIPT}" = "Xyes"; then
+ SAVED_CC="${CC}"
+ CC="${MPICC_COMP}"
+ fi
+
+ # Check if MPI implementation supports MPI_Comm_f2c() from
+ # MPI-2 specification
+ if test "X${FCMIX_ENABLED}" = "Xyes"; then
+ echo "$as_me:$LINENO: checking for MPI_Comm_f2c() from MPI-2 specification" >&5
+echo $ECHO_N "checking for MPI_Comm_f2c() from MPI-2 specification... $ECHO_C" >&6
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include "mpi.h"
+int
+main ()
+{
+
+ int c;
+ char **v;
+ MPI_Comm C_comm;
+ MPI_Init(&c, &v);
+ C_comm = MPI_Comm_f2c((MPI_Fint) 1);
+ MPI_Finalize();
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+ cat >>confdefs.h <<\_ACEOF
+#define SUNDIALS_MPI_COMM_F2C 1
+_ACEOF
+
+ F77_MPI_COMM_F2C="#define SUNDIALS_MPI_COMM_F2C 1"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+ cat >>confdefs.h <<\_ACEOF
+#define SUNDIALS_MPI_COMM_F2C 0
+_ACEOF
+
+ F77_MPI_COMM_F2C="#define SUNDIALS_MPI_COMM_F2C 0"
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ fi
+
+ # Reset CC if necessary
+ if test "X${USE_MPICC_SCRIPT}" = "Xyes"; then
+ CC="${SAVED_CC}"
+ fi
+
+else
+ cat >>confdefs.h <<\_ACEOF
+#define SUNDIALS_MPI_COMM_F2C 0
+_ACEOF
+
+ F77_MPI_COMM_F2C="#define SUNDIALS_MPI_COMM_F2C 0"
+fi
+
+# Restore CPPFLAGS, LDFLAGS and LIBS
+CPPFLAGS="${SAVED_CPPFLAGS}"
+LDFLAGS="${SAVED_LDFLAGS}"
+LIBS="${SAVED_LIBS}"
+
+
+ fi
+ if test "X${F77_EXAMPLES_ENABLED}" = "Xyes"; then
+ echo ""
+ echo "MPI-Fortran Settings"
+ echo "--------------------"
+ echo ""
+
+
+echo "$as_me:$LINENO: checking if using MPI-Fortran script" >&5
+echo $ECHO_N "checking if using MPI-Fortran script... $ECHO_C" >&6
+
+# Check whether --with-mpif77 or --without-mpif77 was given.
+if test "${with_mpif77+set}" = set; then
+ withval="$with_mpif77"
+
+if test "X${withval}" = "Xno"; then
+ USE_MPIF77_SCRIPT="no"
+else
+ USE_MPIF77_SCRIPT="yes"
+ MPIF77_COMP="${withval}"
+fi
+
+else
+
+USE_MPIF77_SCRIPT="yes"
+MPIF77_COMP="mpif77"
+
+fi;
+echo "$as_me:$LINENO: result: ${USE_MPIF77_SCRIPT}" >&5
+echo "${ECHO_T}${USE_MPIF77_SCRIPT}" >&6
+
+# Check MPI-Fortran compiler (either MPI compiler script or regular Fortran compiler)
+if test "X${USE_MPIF77_SCRIPT}" = "Xyes"; then
+
+
+# Test the MPI-Fortran compiler (meaning test MPIF77_COMP)
+# Check if MPI-Fortran compiler can be found
+
+echo "$as_me:$LINENO: checking if absolute path to ${MPIF77_COMP} was given" >&5
+echo $ECHO_N "checking if absolute path to ${MPIF77_COMP} was given... $ECHO_C" >&6
+
+# CASE 1: MPIF77_COMP was found (cannot check if executable because the
+# "-x" flag is NOT portable)
+if test -f ${MPIF77_COMP} ; then
+
+ echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+ MPIF77_COMP_EXISTS="yes"
+ # Determine MPI_INC_DIR and MPI_LIB_DIR for use by Makefile
+ MPI_BASE_DIR=`(dirname "${MPIF77_COMP}") 2>/dev/null ||
+$as_expr X"${MPIF77_COMP}" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"${MPIF77_COMP}" : 'X\(//\)[^/]' \| \
+ X"${MPIF77_COMP}" : 'X\(//\)$' \| \
+ X"${MPIF77_COMP}" : 'X\(/\)' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X"${MPIF77_COMP}" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+ /^X\(\/\/\)$/{ s//\1/; q; }
+ /^X\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+
+# CASE 2: MPIF77_COMP could NOT be found and MPI_ROOT_DIR was NOT specified,
+# so search in PATH
+else
+
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+
+ if test "X${MPI_ROOT_DIR}" = "X"; then
+
+ # Try to find location of executable (perhaps directory was entered incorrectly)
+ TEMP_MPIF77_COMP=`basename "${MPIF77_COMP}"`
+ # Extract the first word of "${TEMP_MPIF77_COMP}", so it can be a program name with args.
+set dummy ${TEMP_MPIF77_COMP}; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_path_MPIF77_COMP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ case $MPIF77_COMP in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_MPIF77_COMP="$MPIF77_COMP" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_path_MPIF77_COMP="$as_dir/$ac_word$ac_exec_ext"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+ test -z "$ac_cv_path_MPIF77_COMP" && ac_cv_path_MPIF77_COMP="none"
+ ;;
+esac
+fi
+MPIF77_COMP=$ac_cv_path_MPIF77_COMP
+
+if test -n "$MPIF77_COMP"; then
+ echo "$as_me:$LINENO: result: $MPIF77_COMP" >&5
+echo "${ECHO_T}$MPIF77_COMP" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ # Cannot find executable in PATH
+ if test "X${MPIF77_COMP}" = "Xnone"; then
+ MPIF77_COMP_EXISTS="no"
+ MPIF77_COMP=""
+ # Found executable and set MPIF77_COMP to absolute pathname
+ else
+ MPIF77_COMP_EXISTS="yes"
+ MPI_BASE_DIR=`(dirname "${MPIF77_COMP}") 2>/dev/null ||
+$as_expr X"${MPIF77_COMP}" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"${MPIF77_COMP}" : 'X\(//\)[^/]' \| \
+ X"${MPIF77_COMP}" : 'X\(//\)$' \| \
+ X"${MPIF77_COMP}" : 'X\(/\)' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X"${MPIF77_COMP}" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+ /^X\(\/\/\)$/{ s//\1/; q; }
+ /^X\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+ fi
+
+ # CASE 3: MPIF77_COMP could NOT be found, but MPI_ROOT_DIR was specified
+ else
+
+ echo "$as_me:$LINENO: checking if ${MPIF77_COMP} exists in ${MPI_ROOT_DIR}/bin" >&5
+echo $ECHO_N "checking if ${MPIF77_COMP} exists in ${MPI_ROOT_DIR}/bin... $ECHO_C" >&6
+ # MPIF77_COMP should really only contain an executable name
+ # Found location of MPIF77_COMP
+ if test -f ${MPI_ROOT_DIR}/bin/${MPIF77_COMP} ; then
+ echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+ MPIF77_COMP_EXISTS="yes"
+ MPIF77_COMP="${MPI_ROOT_DIR}/bin/${MPIF77_COMP}"
+ # Could NOT find MPIF77_COMP anywhere
+ else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+ MPIF77_COMP_EXISTS="no"
+ MPIF77_COMP=""
+ fi
+
+ fi
+
+fi
+
+# Issue warning message if MPIF77_COMP does NOT exist, else set MPIF77
+if test "X${MPIF77_COMP_EXISTS}" = "Xyes"; then
+
+ MPIF77="${MPIF77_COMP}"
+ MPI_F77_COMP_OK="yes"
+
+ # Note that we do not have to worry about empty MPI_INC_DIR and MPI_LIB_DIR
+ # here as they were set in SUNDIALS_CHECK_MPICC
+
+ # Check if we must use the MPI-Fortran compiler script (MPIF77) to link
+ # the Fortran examples (default is to use MPICC)
+
+
+# If we are NOT using an MPI script, then MPICC_COMP == CC and we do NOT need
+# to check again if CC is a C++ compiler as we already know the answer
+if test "X${USE_MPICC_SCRIPT}" = "Xyes"; then
+
+ # Check if using a C++ compiler (meaning MPI-C++ script)
+ # Save result from CC check
+ SAVED_USING_CPLUSPLUS_COMP="${USING_CPLUSPLUS_COMP}"
+
+
+# Rename argument
+COMP_NAME="${MPICC_COMP}"
+
+# Update the language stack
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_linkonly='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_objext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+# Check if using a C++ compiler
+echo "$as_me:$LINENO: checking if ${COMP_NAME} is a C++ compiler" >&5
+echo $ECHO_N "checking if ${COMP_NAME} is a C++ compiler... $ECHO_C" >&6
+if test "$cross_compiling" = yes; then
+ { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+#ifdef __cplusplus
+ return(0);
+#else
+ return(1);
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+
+echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+# COMP_NAME is a C++ compiler
+USING_CPLUSPLUS_COMP="yes"
+
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+
+echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+# COMP_NAMPE is NOT a C++ compiler
+USING_CPLUSPLUS_COMP="no"
+
+fi
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+# Revert back to previous language
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_linkonly='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_objext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+ # MPICC uses a C++ compiler so run the next test
+ if test "X${USING_CPLUSPLUS_COMP}" = "Xyes" && test "X${SAVED_USING_CPLUSPLUS_COMP}" = "Xyes"; then
+ RUN_MPIF77_LNKR_CHECK="yes"
+ # ERROR
+ elif test "X${USING_CPLUSPLUS_COMP}" = "Xyes" && test "X${SAVED_USING_CPLUSPLUS_COMP}" = "Xno"; then
+ { { echo "$as_me:$LINENO: error: ${MPICC_COMP} is a C++ compiler but ${CC} is a C compiler" >&5
+echo "$as_me: error: ${MPICC_COMP} is a C++ compiler but ${CC} is a C compiler" >&2;}
+ { (exit 1); exit 1; }; }
+ # MPICC uses a C compiler so skip the next test
+ elif test "X${USING_CPLUSPLUS_COMP}" = "Xno" && test "X${SAVED_USING_CPLUSPLUS_COMP}" = "Xno" ; then
+ RUN_MPIF77_LNKR_CHECK="no"
+ # ERROR
+ elif test "X${USING_CPLUSPLUS_COMP}" = "Xno" && test "X${SAVED_USING_CPLUSPLUS_COMP}" = "Xyes" ; then
+ { { echo "$as_me:$LINENO: error: ${MPICC_COMP} is a C compiler but ${CC} is a C++ compiler" >&5
+echo "$as_me: error: ${MPICC_COMP} is a C compiler but ${CC} is a C++ compiler" >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+ # Restore result from CC check
+ USING_CPLUSPLUS_COMP="${SAVED_USING_CPLUSPLUS_COMP}"
+
+else
+
+ echo "$as_me:$LINENO: checking if ${MPICC_COMP} is a C++ compiler" >&5
+echo $ECHO_N "checking if ${MPICC_COMP} is a C++ compiler... $ECHO_C" >&6
+ if test "X${USING_CPLUSPLUS_COMP}" = "Xyes"; then
+ echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+ else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+ fi
+
+fi
+
+echo "$as_me:$LINENO: checking which linker to use" >&5
+echo $ECHO_N "checking which linker to use... $ECHO_C" >&6
+# Perform the next test only if using a C++ compiler to build NVECTOR_PARALLEL
+if test "X${RUN_MPIF77_LNKR_CHECK}" = "Xyes"; then
+
+ MPIF77_LNKR_CHECK_OK="no"
+
+ # Switch language to "Fortran 77"
+ ac_ext=f
+ac_compile='$F77 -c $FFLAGS conftest.$ac_ext >&5'
+ac_link='$F77 -o conftest$ac_exeext $FFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_f77_compiler_gnu
+
+
+ # Temporarily reset F77 environment variable to perform test
+ SAVED_F77="${F77}"
+ F77="${MPIF77_COMP}"
+
+ # Compile simple Fortran example, but do NOT link
+ # Note: result stored as conftest.${ac_objext}
+ cat >conftest.$ac_ext <<_ACEOF
+
+ PROGRAM SUNDIALS
+ INTEGER IER
+ CALL MPI_INIT(IER)
+ END
+
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_f77_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+
+
+ # Reset F77 to original value
+ F77="${SAVED_F77}"
+
+ # Revert to previous language
+ ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_linkonly='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_objext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+ # Temporarily reset LIBS environment variable to perform test
+ SAVED_LIBS="${LIBS}"
+ LIBS="${LIBS} ${FLIBS}"
+
+ # Switch working language to C for next test
+ ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_linkonly='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_objext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+ # Temporarily reset CC environment variable to perform next test
+ SAVED_CC="${CC}"
+ CC="${MPICC_COMP}"
+
+ # Check if MPICC_COMP can link Fortran example
+ # Note: AC_LINKONLY_IFELSE is a custom macro (modifications made to
+ # general.m4 and c.m4)
+ if { (eval echo "$as_me:$LINENO: \"$ac_linkonly\"") >&5
+ (eval $ac_linkonly) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ MPIF77_LNKR_CHECK_OK="yes"
+else
+ echo "$as_me: failed program was:" >&5
+if test -f conftest.c ; then
+ sed 's/^/| /' conftest.c >&5
+elif test -f conftest.cc ; then
+ sed 's/^/| /' conftest.cc >&5
+elif test -f conftest.f ; then
+ sed 's/^/| /' conftest.f >&5
+elif test -f conftest.${FC_SRCEXT-f} ; then
+ sed 's/^/| /' conftest.${FC_SRCEXT-f} >&5
+fi
+
+MPIF77_LNKR_CHECK_OK="no"
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext
+
+ # Reset CC to original value
+ CC="${SAVED_CC}"
+
+ # Revert back to previous language (Fortran 77)
+ ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_linkonly='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_objext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+ # Set LIBS environment variable back to original value
+ LIBS="${SAVED_LIBS}"
+
+
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+
+ # If either the compilation or the linking failed, we should
+ # disable building the parallel Fortran examples
+ # For now, use MPIF77 as the linker...
+
+ if test "X${MPIF77_LNKR_CHECK_OK}" = "Xyes"; then
+ MPIF77_LNKR="${MPICC}"
+ else
+ MPIF77_LNKR="${MPIF77}"
+ fi
+
+else
+
+ # Using a C compiler so use MPIF77 to link parallel Fortran examples
+ MPIF77_LNKR="${MPIF77}"
+
+fi
+echo "$as_me:$LINENO: result: ${MPIF77_LNKR}" >&5
+echo "${ECHO_T}${MPIF77_LNKR}" >&6
+
+
+
+
+else
+
+ { echo "$as_me:$LINENO: WARNING: cannot find MPI-Fortran compiler" >&5
+echo "$as_me: WARNING: cannot find MPI-Fortran compiler" >&2;}
+ echo ""
+ echo " Unable to find a functional MPI-Fortran compiler."
+ echo ""
+ echo " Try using --with-mpif77 to specify a MPI-Fortran compiler script,"
+ echo " --with-mpi-incdir, --with-mpi-libdir and --with-mpi-libs"
+ echo " to specify the locations of all relevant MPI files, or"
+ echo " --with-mpi-root to specify the base installation directory"
+ echo " of the MPI implementation to be used."
+ echo ""
+ echo " Disabling parallel Fortran examples...."
+ echo ""
+ MPIF77=""
+ MPI_F77_COMP_OK="no"
+ SUNDIALS_WARN_FLAG="yes"
+
+fi
+
+
+else
+ MPIF77_COMP="${F77}"
+ MPIF77="${F77}"
+
+
+# Test if we can compile MPI programs using the F77 compiler
+# and current MPI settings
+
+{ echo "$as_me:$LINENO: Testing F77 with MPI settings" >&5
+echo "$as_me: Testing F77 with MPI settings" >&6;}
+
+ac_ext=f
+ac_compile='$F77 -c $FFLAGS conftest.$ac_ext >&5'
+ac_link='$F77 -o conftest$ac_exeext $FFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_f77_compiler_gnu
+
+
+# Save copies of FFLAGS, LDFLAGS and LIBS (preserve information)
+# Temporarily overwritten so we can test MPI implementation
+SAVED_FFLAGS="${FFLAGS}"
+SAVED_LDFLAGS="${LDFLAGS}"
+SAVED_LIBS="${LIBS}"
+
+# This may seem redundant, but we are not guaranteed that
+# SUNDIALS_CC_WITH_MPI_CHECK has been executed
+# Determine location of MPI header files (find MPI include directory)
+MPI_EXISTS="yes"
+
+echo "$as_me:$LINENO: checking for location of MPI implementation" >&5
+echo $ECHO_N "checking for location of MPI implementation... $ECHO_C" >&6
+
+# If MPI include directory was NOT explicitly specified so check if MPI root
+# directory was given by user
+if test "X${MPI_INC_DIR}" = "X"; then
+ # If MPI root directory was NOT given so issue a warning message
+ if test "X${MPI_ROOT_DIR}" = "X"; then
+ echo "$as_me:$LINENO: result: not found" >&5
+echo "${ECHO_T}not found" >&6
+ MPI_EXISTS="no"
+ { echo "$as_me:$LINENO: WARNING: cannot find MPI implementation files" >&5
+echo "$as_me: WARNING: cannot find MPI implementation files" >&2;}
+ echo ""
+ echo " Unable to find MPI implementation files."
+ echo ""
+ echo " Try using --with-mpif77 to specify a MPI-Fortran compiler script,"
+ echo " --with-mpi-incdir, --with-mpi-libdir and --with-mpi-libs"
+ echo " to specify the locations of all relevant MPI files, or"
+ echo " --with-mpi-root to specify the base installation directory"
+ echo " of the MPI implementation to be used."
+ echo ""
+ echo " Disabling all parallel Fortran examples..."
+ echo ""
+ SUNDIALS_WARN_FLAG="yes"
+ # MPI root directory was given so set MPI_INC_DIR accordingly
+ # Update FFLAGS
+ else
+ MPI_INC_DIR="${MPI_ROOT_DIR}/include"
+ echo "$as_me:$LINENO: result: ${MPI_INC_DIR}" >&5
+echo "${ECHO_T}${MPI_INC_DIR}" >&6
+ if test "X${FFLAGS}" = "X"; then
+ FFLAGS="-I${MPI_INC_DIR}"
+ else
+ FFLAGS="${FFLAGS} -I${MPI_INC_DIR}"
+ fi
+ fi
+# MPI include directory was specified so update FFLAGS
+else
+ echo "$as_me:$LINENO: result: ${MPI_INC_DIR}" >&5
+echo "${ECHO_T}${MPI_INC_DIR}" >&6
+ if test "X${FFLAGS}" = "X"; then
+ FFLAGS="-I${MPI_INC_DIR}"
+ else
+ FFLAGS="${FFLAGS} -I${MPI_INC_DIR}"
+ fi
+fi
+
+# Only continue if found an MPI implementation
+if test "X${MPI_EXISTS}" = "Xyes"; then
+
+ echo "$as_me:$LINENO: checking for location of MPI libraries" >&5
+echo $ECHO_N "checking for location of MPI libraries... $ECHO_C" >&6
+
+ # Determine location of MPI libraries
+ # MPI library directory was NOT specified by user so set based upon MPI_ROOT_DIR
+ # Update LDFLAGS
+ if test "X${MPI_LIB_DIR}" = "X"; then
+ MPI_LIB_DIR="${MPI_ROOT_DIR}/lib"
+ echo "$as_me:$LINENO: result: ${MPI_LIB_DIR}" >&5
+echo "${ECHO_T}${MPI_LIB_DIR}" >&6
+ if test "X${LDFLAGS}" = "X"; then
+ LDFLAGS="-L${MPI_LIB_DIR}"
+ else
+ LDFLAGS="${LDFLAGS} -L${MPI_LIB_DIR}"
+ fi
+ # MPI library directory was specified so update LDFLAGS
+ else
+ echo "$as_me:$LINENO: result: ${MPI_LIB_DIR}" >&5
+echo "${ECHO_T}${MPI_LIB_DIR}" >&6
+ if test "X${LDFLAGS}" = "X"; then
+ LDFLAGS="-L${MPI_LIB_DIR}"
+ else
+ LDFLAGS="${LDFLAGS} -L${MPI_LIB_DIR}"
+ fi
+ fi
+
+ # Check if user specified which MPI libraries must be included
+ # If no libraries are given, then issue a warning message
+ echo "$as_me:$LINENO: checking for MPI libraries" >&5
+echo $ECHO_N "checking for MPI libraries... $ECHO_C" >&6
+ if test "X${MPI_LIBS}" = "X"; then
+ echo "$as_me:$LINENO: result: none" >&5
+echo "${ECHO_T}none" >&6
+ echo ""
+ echo " Unable to compile MPI program using Fortran compiler because"
+ echo " MPI libraries were not specified."
+ echo ""
+ echo " Try using --with-mpi-libdir and --with-mpi-libs to"
+ echo " specify the location and names of the MPI libraries."
+ echo ""
+ echo " Disabling all parallel Fortran examples..."
+ echo ""
+ MPI_F77_COMP_OK="no"
+ # MPI libraries were specified so update LIBS
+ else
+ echo "$as_me:$LINENO: result: ${MPI_LIBS}" >&5
+echo "${ECHO_T}${MPI_LIBS}" >&6
+ if test "X${LIBS}" = "X"; then
+ LIBS="${MPI_LIBS}"
+ else
+ LIBS="${LIBS} ${MPI_LIBS}"
+ fi
+ # Set the MPI_F77_COMP_OK variable to NULL so we can conditionally execute
+ # the next test
+ MPI_F77_COMP_OK=""
+ fi
+
+ if test "X${MPI_F77_COMP_OK}" = "X"; then
+ echo "$as_me:$LINENO: checking if Fortran compiler can compile MPI programs" >&5
+echo $ECHO_N "checking if Fortran compiler can compile MPI programs... $ECHO_C" >&6
+ cat >conftest.$ac_ext <<_ACEOF
+ program main
+
+ INCLUDE "mpif.h"
+ CALL MPI_INIT(IER)
+
+ end
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_f77_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+ MPI_F77_COMP_OK="yes"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+ { echo "$as_me:$LINENO: WARNING: Fortran compiler cannot compile MPI programs" >&5
+echo "$as_me: WARNING: Fortran compiler cannot compile MPI programs" >&2;}
+ echo ""
+ echo " Unable to compile MPI program using Fortran compiler."
+ echo ""
+ echo " Try using --with-mpif77 to specify a MPI-Fortran compiler script,"
+ echo " --with-mpi-incdir, --with-mpi-libdir and --with-mpi-libs"
+ echo " to specify the locations of all relevant MPI files, or"
+ echo " --with-mpi-root to specify the base installation directory"
+ echo " of the MPI implementation to be used."
+ echo ""
+ echo " Disabling all parallel Fortran examples..."
+ echo ""
+ MPI_F77_COMP_OK="no"
+ SUNDIALS_WARN_FLAG="yes"
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+
+ # Set MPIF77_LNKR based on value of F77_LNKR
+ # Note: setting MPIF77_LNKR is trivial if NOT using the MPI compiler script
+ # since the SUNDIALS_F77_LNKR_CHECK macro already checked if CC or F77
+ # should be used
+ echo "$as_me:$LINENO: checking which linker to use" >&5
+echo $ECHO_N "checking which linker to use... $ECHO_C" >&6
+ if test "X${F77_LNKR}" = "X${CC}"; then
+ MPIF77_LNKR="${MPICC}"
+ elif test "X${F77_LNKR}" = "X${F77}"; then
+ MPIF77_LNKR="${MPIF77}"
+ fi
+ echo "$as_me:$LINENO: result: ${MPIF77_LNKR}" >&5
+echo "${ECHO_T}${MPIF77_LNKR}" >&6
+ fi
+
+else
+ MPI_F77_COMP_OK="no"
+fi
+
+# Restore FFLAGS, LDFLAGS and LIBS
+FFLAGS="${SAVED_FFLAGS}"
+LDFLAGS="${SAVED_LDFLAGS}"
+LIBS="${SAVED_LIBS}"
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_linkonly='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_objext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+fi
+
+
+ fi
+fi
+
+# Set examples modules
+if test "X${EXAMPLES_ENABLED}" = "Xyes"; then
+ echo ""
+ echo "Examples"
+ echo "--------"
+ echo ""
+
+
+# Set proper object file extension
+# Must export OBJ_EXT via AC_SUBST
+OBJEXT=".lo"
+
+# Check if serial C examples can actually be built
+SERIAL_C_EXAMPLES="yes"
+
+# Check if parallel C examples can actually be built
+if test "X${MPI_ENABLED}" = "Xyes"; then
+ if test "X${MPI_C_COMP_OK}" = "Xyes"; then
+ PARALLEL_C_EXAMPLES="yes"
+ else
+ PARALLEL_C_EXAMPLES="no"
+ fi
+else
+ PARALLEL_C_EXAMPLES="disabled"
+fi
+
+# Check if serial F77 examples can actually be built
+if test "X${FCMIX_ENABLED}" = "Xyes"; then
+ if test "X${F77_OK}" = "Xyes"; then
+ SERIAL_F77_EXAMPLES="yes"
+ else
+ SERIAL_F77_EXAMPLES="no"
+ fi
+else
+ SERIAL_F77_EXAMPLES="disabled"
+fi
+
+# Check if parallel F77 examples can actually be built
+if test "X${FCMIX_ENABLED}" = "Xyes" && test "X${MPI_ENABLED}" = "Xyes"; then
+ if test "X${MPI_F77_COMP_OK}" = "Xyes"; then
+ PARALLEL_F77_EXAMPLES="yes"
+ else
+ PARALLEL_F77_EXAMPLES="no"
+ fi
+else
+ PARALLEL_F77_EXAMPLES="disabled"
+fi
+
+# Notify user
+echo "$as_me:$LINENO: checking if we can build serial C examples" >&5
+echo $ECHO_N "checking if we can build serial C examples... $ECHO_C" >&6
+echo "$as_me:$LINENO: result: ${SERIAL_C_EXAMPLES}" >&5
+echo "${ECHO_T}${SERIAL_C_EXAMPLES}" >&6
+echo "$as_me:$LINENO: checking if we can build parallel C examples" >&5
+echo $ECHO_N "checking if we can build parallel C examples... $ECHO_C" >&6
+echo "$as_me:$LINENO: result: ${PARALLEL_C_EXAMPLES}" >&5
+echo "${ECHO_T}${PARALLEL_C_EXAMPLES}" >&6
+echo "$as_me:$LINENO: checking if we can build serial Fortran examples" >&5
+echo $ECHO_N "checking if we can build serial Fortran examples... $ECHO_C" >&6
+echo "$as_me:$LINENO: result: ${SERIAL_F77_EXAMPLES}" >&5
+echo "${ECHO_T}${SERIAL_F77_EXAMPLES}" >&6
+echo "$as_me:$LINENO: checking if we can build parallel Fortran examples" >&5
+echo $ECHO_N "checking if we can build parallel Fortran examples... $ECHO_C" >&6
+echo "$as_me:$LINENO: result: ${PARALLEL_F77_EXAMPLES}" >&5
+echo "${ECHO_T}${PARALLEL_F77_EXAMPLES}" >&6
+
+# Check if the Fortran update script (bin/fortran-update.in) is needed
+if test "X${SERIAL_F77_EXAMPLES}" = "Xyes" || test "X${PARALLEL_F77_EXAMPLES}" = "Xyes"; then
+ BUILD_F77_UPDATE_SCRIPT="yes";
+else
+ BUILD_F77_UPDATE_SCRIPT="no"
+fi
+
+# Where should we install the examples?
+# Note: setting this to "no" will disable example installation!
+echo "$as_me:$LINENO: checking where to install the SUNDIALS examples" >&5
+echo $ECHO_N "checking where to install the SUNDIALS examples... $ECHO_C" >&6
+
+# Check whether --with- or --without- was given.
+if test "${with_+set}" = set; then
+ withval="$with_"
+
+fi;
+
+# Check whether --with-exinstdir or --without-exinstdir was given.
+if test "${with_exinstdir+set}" = set; then
+ withval="$with_exinstdir"
+
+ EXS_INSTDIR="${withval}"
+
+else
+
+ if test "X${exec_prefix}" = "XNONE"; then
+ if test "X${prefix}" = "XNONE"; then
+ EXS_INSTDIR="\${exec_prefix}/examples"
+ else
+ EXS_INSTDIR="${prefix}/examples"
+ fi
+ else
+ EXS_INSTDIR="${exec_prefix}/examples"
+ fi
+
+fi;
+echo "$as_me:$LINENO: result: ${EXS_INSTDIR}" >&5
+echo "${ECHO_T}${EXS_INSTDIR}" >&6
+
+# Prepare substitution variables to create the exported example Makefiles
+
+F77_LIBS="${FLIBS} ${LIBS}"
+if test "X${F77_LNKR}" = "X${F77}"; then
+ F77_LDFLAGS="${FFLAGS} ${LDFLAGS}"
+else
+ F77_LDFLAGS="${CFLAGS} ${LDFLAGS}"
+fi
+
+
+fi
+
+# Run libtool checks
+echo ""
+echo "Libtool Settings"
+echo "----------------"
+echo ""
+# Check whether --enable-shared or --disable-shared was given.
+if test "${enable_shared+set}" = set; then
+ enableval="$enable_shared"
+ p=${PACKAGE-default}
+ case $enableval in
+ yes) enable_shared=yes ;;
+ no) enable_shared=no ;;
+ *)
+ enable_shared=no
+ # Look at the argument we got. We use all the common list separators.
+ lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+ for pkg in $enableval; do
+ IFS="$lt_save_ifs"
+ if test "X$pkg" = "X$p"; then
+ enable_shared=yes
+ fi
+ done
+ IFS="$lt_save_ifs"
+ ;;
+ esac
+else
+ enable_shared=no
+fi;
+
+
+
+
+# Check whether --enable-static or --disable-static was given.
+if test "${enable_static+set}" = set; then
+ enableval="$enable_static"
+ p=${PACKAGE-default}
+ case $enableval in
+ yes) enable_static=yes ;;
+ no) enable_static=no ;;
+ *)
+ enable_static=no
+ # Look at the argument we got. We use all the common list separators.
+ lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+ for pkg in $enableval; do
+ IFS="$lt_save_ifs"
+ if test "X$pkg" = "X$p"; then
+ enable_static=yes
+ fi
+ done
+ IFS="$lt_save_ifs"
+ ;;
+ esac
+else
+ enable_static=yes
+fi;
+
+# Check whether --enable-fast-install or --disable-fast-install was given.
+if test "${enable_fast_install+set}" = set; then
+ enableval="$enable_fast_install"
+ p=${PACKAGE-default}
+ case $enableval in
+ yes) enable_fast_install=yes ;;
+ no) enable_fast_install=no ;;
+ *)
+ enable_fast_install=no
+ # Look at the argument we got. We use all the common list separators.
+ lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+ for pkg in $enableval; do
+ IFS="$lt_save_ifs"
+ if test "X$pkg" = "X$p"; then
+ enable_fast_install=yes
+ fi
+ done
+ IFS="$lt_save_ifs"
+ ;;
+ esac
+else
+ enable_fast_install=yes
+fi;
+
+echo "$as_me:$LINENO: checking for a sed that does not truncate output" >&5
+echo $ECHO_N "checking for a sed that does not truncate output... $ECHO_C" >&6
+if test "${lt_cv_path_SED+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ # Loop through the user's path and test for sed and gsed.
+# Then use that list of sed's as ones to test for truncation.
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for lt_ac_prog in sed gsed; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then
+ lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext"
+ fi
+ done
+ done
+done
+IFS=$as_save_IFS
+lt_ac_max=0
+lt_ac_count=0
+# Add /usr/xpg4/bin/sed as it is typically found on Solaris
+# along with /bin/sed that truncates output.
+for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do
+ test ! -f $lt_ac_sed && continue
+ cat /dev/null > conftest.in
+ lt_ac_count=0
+ echo $ECHO_N "0123456789$ECHO_C" >conftest.in
+ # Check for GNU sed and select it if it is found.
+ if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then
+ lt_cv_path_SED=$lt_ac_sed
+ break
+ fi
+ while true; do
+ cat conftest.in conftest.in >conftest.tmp
+ mv conftest.tmp conftest.in
+ cp conftest.in conftest.nl
+ echo >>conftest.nl
+ $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break
+ cmp -s conftest.out conftest.nl || break
+ # 10000 chars as input seems more than enough
+ test $lt_ac_count -gt 10 && break
+ lt_ac_count=`expr $lt_ac_count + 1`
+ if test $lt_ac_count -gt $lt_ac_max; then
+ lt_ac_max=$lt_ac_count
+ lt_cv_path_SED=$lt_ac_sed
+ fi
+ done
+done
+
+fi
+
+SED=$lt_cv_path_SED
+
+echo "$as_me:$LINENO: result: $SED" >&5
+echo "${ECHO_T}$SED" >&6
+
+
+# Check whether --with-gnu-ld or --without-gnu-ld was given.
+if test "${with_gnu_ld+set}" = set; then
+ withval="$with_gnu_ld"
+ test "$withval" = no || with_gnu_ld=yes
+else
+ with_gnu_ld=no
+fi;
+ac_prog=ld
+if test "$GCC" = yes; then
+ # Check if gcc -print-prog-name=ld gives a path.
+ echo "$as_me:$LINENO: checking for ld used by $CC" >&5
+echo $ECHO_N "checking for ld used by $CC... $ECHO_C" >&6
+ case $host in
+ *-*-mingw*)
+ # gcc leaves a trailing carriage return which upsets mingw
+ ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
+ *)
+ ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
+ esac
+ case $ac_prog in
+ # Accept absolute paths.
+ [\\/]* | ?:[\\/]*)
+ re_direlt='/[^/][^/]*/\.\./'
+ # Canonicalize the pathname of ld
+ ac_prog=`echo $ac_prog| $SED 's%\\\\%/%g'`
+ while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do
+ ac_prog=`echo $ac_prog| $SED "s%$re_direlt%/%"`
+ done
+ test -z "$LD" && LD="$ac_prog"
+ ;;
+ "")
+ # If it fails, then pretend we aren't using GCC.
+ ac_prog=ld
+ ;;
+ *)
+ # If it is relative, then search for the first ld in PATH.
+ with_gnu_ld=unknown
+ ;;
+ esac
+elif test "$with_gnu_ld" = yes; then
+ echo "$as_me:$LINENO: checking for GNU ld" >&5
+echo $ECHO_N "checking for GNU ld... $ECHO_C" >&6
+else
+ echo "$as_me:$LINENO: checking for non-GNU ld" >&5
+echo $ECHO_N "checking for non-GNU ld... $ECHO_C" >&6
+fi
+if test "${lt_cv_path_LD+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -z "$LD"; then
+ lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+ for ac_dir in $PATH; do
+ IFS="$lt_save_ifs"
+ test -z "$ac_dir" && ac_dir=.
+ if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+ lt_cv_path_LD="$ac_dir/$ac_prog"
+ # Check to see if the program is GNU ld. I'd rather use --version,
+ # but apparently some variants of GNU ld only accept -v.
+ # Break only if it was the GNU/non-GNU ld that we prefer.
+ case `"$lt_cv_path_LD" -v 2>&1 </dev/null` in
+ *GNU* | *'with BFD'*)
+ test "$with_gnu_ld" != no && break
+ ;;
+ *)
+ test "$with_gnu_ld" != yes && break
+ ;;
+ esac
+ fi
+ done
+ IFS="$lt_save_ifs"
+else
+ lt_cv_path_LD="$LD" # Let the user override the test with a path.
+fi
+fi
+
+LD="$lt_cv_path_LD"
+if test -n "$LD"; then
+ echo "$as_me:$LINENO: result: $LD" >&5
+echo "${ECHO_T}$LD" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+test -z "$LD" && { { echo "$as_me:$LINENO: error: no acceptable ld found in \$PATH" >&5
+echo "$as_me: error: no acceptable ld found in \$PATH" >&2;}
+ { (exit 1); exit 1; }; }
+echo "$as_me:$LINENO: checking if the linker ($LD) is GNU ld" >&5
+echo $ECHO_N "checking if the linker ($LD) is GNU ld... $ECHO_C" >&6
+if test "${lt_cv_prog_gnu_ld+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ # I'd rather use --version here, but apparently some GNU lds only accept -v.
+case `$LD -v 2>&1 </dev/null` in
+*GNU* | *'with BFD'*)
+ lt_cv_prog_gnu_ld=yes
+ ;;
+*)
+ lt_cv_prog_gnu_ld=no
+ ;;
+esac
+fi
+echo "$as_me:$LINENO: result: $lt_cv_prog_gnu_ld" >&5
+echo "${ECHO_T}$lt_cv_prog_gnu_ld" >&6
+with_gnu_ld=$lt_cv_prog_gnu_ld
+
+
+echo "$as_me:$LINENO: checking for $LD option to reload object files" >&5
+echo $ECHO_N "checking for $LD option to reload object files... $ECHO_C" >&6
+if test "${lt_cv_ld_reload_flag+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ lt_cv_ld_reload_flag='-r'
+fi
+echo "$as_me:$LINENO: result: $lt_cv_ld_reload_flag" >&5
+echo "${ECHO_T}$lt_cv_ld_reload_flag" >&6
+reload_flag=$lt_cv_ld_reload_flag
+case $reload_flag in
+"" | " "*) ;;
+*) reload_flag=" $reload_flag" ;;
+esac
+reload_cmds='$LD$reload_flag -o $output$reload_objs'
+case $host_os in
+ darwin*)
+ if test "$GCC" = yes; then
+ reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r -o $output$reload_objs'
+ else
+ reload_cmds='$LD$reload_flag -o $output$reload_objs'
+ fi
+ ;;
+esac
+
+echo "$as_me:$LINENO: checking for BSD-compatible nm" >&5
+echo $ECHO_N "checking for BSD-compatible nm... $ECHO_C" >&6
+if test "${lt_cv_path_NM+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$NM"; then
+ # Let the user override the test.
+ lt_cv_path_NM="$NM"
+else
+ lt_nm_to_check="${ac_tool_prefix}nm"
+ if test -n "$ac_tool_prefix" && test "$build" = "$host"; then
+ lt_nm_to_check="$lt_nm_to_check nm"
+ fi
+ for lt_tmp_nm in $lt_nm_to_check; do
+ lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+ for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do
+ IFS="$lt_save_ifs"
+ test -z "$ac_dir" && ac_dir=.
+ tmp_nm="$ac_dir/$lt_tmp_nm"
+ if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then
+ # Check to see if the nm accepts a BSD-compat flag.
+ # Adding the `sed 1q' prevents false positives on HP-UX, which says:
+ # nm: unknown option "B" ignored
+ # Tru64's nm complains that /dev/null is an invalid object file
+ case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in
+ */dev/null* | *'Invalid file or object type'*)
+ lt_cv_path_NM="$tmp_nm -B"
+ break
+ ;;
+ *)
+ case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in
+ */dev/null*)
+ lt_cv_path_NM="$tmp_nm -p"
+ break
+ ;;
+ *)
+ lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but
+ continue # so that we can try to find one that supports BSD flags
+ ;;
+ esac
+ ;;
+ esac
+ fi
+ done
+ IFS="$lt_save_ifs"
+ done
+ test -z "$lt_cv_path_NM" && lt_cv_path_NM=nm
+fi
+fi
+echo "$as_me:$LINENO: result: $lt_cv_path_NM" >&5
+echo "${ECHO_T}$lt_cv_path_NM" >&6
+NM="$lt_cv_path_NM"
+
+echo "$as_me:$LINENO: checking whether ln -s works" >&5
+echo $ECHO_N "checking whether ln -s works... $ECHO_C" >&6
+LN_S=$as_ln_s
+if test "$LN_S" = "ln -s"; then
+ echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+else
+ echo "$as_me:$LINENO: result: no, using $LN_S" >&5
+echo "${ECHO_T}no, using $LN_S" >&6
+fi
+
+echo "$as_me:$LINENO: checking how to recognise dependent libraries" >&5
+echo $ECHO_N "checking how to recognise dependent libraries... $ECHO_C" >&6
+if test "${lt_cv_deplibs_check_method+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ lt_cv_file_magic_cmd='$MAGIC_CMD'
+lt_cv_file_magic_test_file=
+lt_cv_deplibs_check_method='unknown'
+# Need to set the preceding variable on all platforms that support
+# interlibrary dependencies.
+# 'none' -- dependencies not supported.
+# `unknown' -- same as none, but documents that we really don't know.
+# 'pass_all' -- all dependencies passed with no checks.
+# 'test_compile' -- check by making test program.
+# 'file_magic [[regex]]' -- check by looking for files in library path
+# which responds to the $file_magic_cmd with a given extended regex.
+# If you have `file' or equivalent on your system and you're not sure
+# whether `pass_all' will *always* work, you probably want this one.
+
+case $host_os in
+aix4* | aix5*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+beos*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+bsdi[45]*)
+ lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)'
+ lt_cv_file_magic_cmd='/usr/bin/file -L'
+ lt_cv_file_magic_test_file=/shlib/libc.so
+ ;;
+
+cygwin*)
+ # func_win32_libid is a shell function defined in ltmain.sh
+ lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
+ lt_cv_file_magic_cmd='func_win32_libid'
+ ;;
+
+mingw* | pw32*)
+ # Base MSYS/MinGW do not provide the 'file' command needed by
+ # func_win32_libid shell function, so use a weaker test based on 'objdump'.
+ lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?'
+ lt_cv_file_magic_cmd='$OBJDUMP -f'
+ ;;
+
+darwin* | rhapsody*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+freebsd* | kfreebsd*-gnu | dragonfly*)
+ if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then
+ case $host_cpu in
+ i*86 )
+ # Not sure whether the presence of OpenBSD here was a mistake.
+ # Let's accept both of them until this is cleared up.
+ lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library'
+ lt_cv_file_magic_cmd=/usr/bin/file
+ lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*`
+ ;;
+ esac
+ else
+ lt_cv_deplibs_check_method=pass_all
+ fi
+ ;;
+
+gnu*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+hpux10.20* | hpux11*)
+ lt_cv_file_magic_cmd=/usr/bin/file
+ case $host_cpu in
+ ia64*)
+ lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64'
+ lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so
+ ;;
+ hppa*64*)
+ lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - PA-RISC [0-9].[0-9]'
+ lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl
+ ;;
+ *)
+ lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9].[0-9]) shared library'
+ lt_cv_file_magic_test_file=/usr/lib/libc.sl
+ ;;
+ esac
+ ;;
+
+interix3*)
+ # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here
+ lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$'
+ ;;
+
+irix5* | irix6* | nonstopux*)
+ case $LD in
+ *-32|*"-32 ") libmagic=32-bit;;
+ *-n32|*"-n32 ") libmagic=N32;;
+ *-64|*"-64 ") libmagic=64-bit;;
+ *) libmagic=never-match;;
+ esac
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+# This must be Linux ELF.
+linux*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+netbsd*)
+ if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then
+ lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$'
+ else
+ lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$'
+ fi
+ ;;
+
+newos6*)
+ lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)'
+ lt_cv_file_magic_cmd=/usr/bin/file
+ lt_cv_file_magic_test_file=/usr/lib/libnls.so
+ ;;
+
+nto-qnx*)
+ lt_cv_deplibs_check_method=unknown
+ ;;
+
+openbsd*)
+ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$'
+ else
+ lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$'
+ fi
+ ;;
+
+osf3* | osf4* | osf5*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+solaris*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+sysv4 | sysv4.3*)
+ case $host_vendor in
+ motorola)
+ lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]'
+ lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*`
+ ;;
+ ncr)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+ sequent)
+ lt_cv_file_magic_cmd='/bin/file'
+ lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )'
+ ;;
+ sni)
+ lt_cv_file_magic_cmd='/bin/file'
+ lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib"
+ lt_cv_file_magic_test_file=/lib/libc.so
+ ;;
+ siemens)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+ pc)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+ esac
+ ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+esac
+
+fi
+echo "$as_me:$LINENO: result: $lt_cv_deplibs_check_method" >&5
+echo "${ECHO_T}$lt_cv_deplibs_check_method" >&6
+file_magic_cmd=$lt_cv_file_magic_cmd
+deplibs_check_method=$lt_cv_deplibs_check_method
+test -z "$deplibs_check_method" && deplibs_check_method=unknown
+
+
+
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# If no C compiler flags were specified, use CFLAGS.
+LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+
+# Check whether --enable-libtool-lock or --disable-libtool-lock was given.
+if test "${enable_libtool_lock+set}" = set; then
+ enableval="$enable_libtool_lock"
+
+fi;
+test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes
+
+# Some flags need to be propagated to the compiler or linker for good
+# libtool support.
+case $host in
+ia64-*-hpux*)
+ # Find out which ABI we are using.
+ echo 'int i;' > conftest.$ac_ext
+ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ case `/usr/bin/file conftest.$ac_objext` in
+ *ELF-32*)
+ HPUX_IA64_MODE="32"
+ ;;
+ *ELF-64*)
+ HPUX_IA64_MODE="64"
+ ;;
+ esac
+ fi
+ rm -rf conftest*
+ ;;
+*-*-irix6*)
+ # Find out which ABI we are using.
+ echo '#line 11692 "configure"' > conftest.$ac_ext
+ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ if test "$lt_cv_prog_gnu_ld" = yes; then
+ case `/usr/bin/file conftest.$ac_objext` in
+ *32-bit*)
+ LD="${LD-ld} -melf32bsmip"
+ ;;
+ *N32*)
+ LD="${LD-ld} -melf32bmipn32"
+ ;;
+ *64-bit*)
+ LD="${LD-ld} -melf64bmip"
+ ;;
+ esac
+ else
+ case `/usr/bin/file conftest.$ac_objext` in
+ *32-bit*)
+ LD="${LD-ld} -32"
+ ;;
+ *N32*)
+ LD="${LD-ld} -n32"
+ ;;
+ *64-bit*)
+ LD="${LD-ld} -64"
+ ;;
+ esac
+ fi
+ fi
+ rm -rf conftest*
+ ;;
+
+x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*)
+ # Find out which ABI we are using.
+ echo 'int i;' > conftest.$ac_ext
+ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ case `/usr/bin/file conftest.o` in
+ *32-bit*)
+ case $host in
+ x86_64-*linux*)
+ LD="${LD-ld} -m elf_i386"
+ ;;
+ ppc64-*linux*|powerpc64-*linux*)
+ LD="${LD-ld} -m elf32ppclinux"
+ ;;
+ s390x-*linux*)
+ LD="${LD-ld} -m elf_s390"
+ ;;
+ sparc64-*linux*)
+ LD="${LD-ld} -m elf32_sparc"
+ ;;
+ esac
+ ;;
+ *64-bit*)
+ case $host in
+ x86_64-*linux*)
+ LD="${LD-ld} -m elf_x86_64"
+ ;;
+ ppc*-*linux*|powerpc*-*linux*)
+ LD="${LD-ld} -m elf64ppc"
+ ;;
+ s390*-*linux*)
+ LD="${LD-ld} -m elf64_s390"
+ ;;
+ sparc*-*linux*)
+ LD="${LD-ld} -m elf64_sparc"
+ ;;
+ esac
+ ;;
+ esac
+ fi
+ rm -rf conftest*
+ ;;
+
+*-*-sco3.2v5*)
+ # On SCO OpenServer 5, we need -belf to get full-featured binaries.
+ SAVE_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -belf"
+ echo "$as_me:$LINENO: checking whether the C compiler needs -belf" >&5
+echo $ECHO_N "checking whether the C compiler needs -belf... $ECHO_C" >&6
+if test "${lt_cv_cc_needs_belf+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_linkonly='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_objext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ lt_cv_cc_needs_belf=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+lt_cv_cc_needs_belf=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_linkonly='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_objext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+fi
+echo "$as_me:$LINENO: result: $lt_cv_cc_needs_belf" >&5
+echo "${ECHO_T}$lt_cv_cc_needs_belf" >&6
+ if test x"$lt_cv_cc_needs_belf" != x"yes"; then
+ # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf
+ CFLAGS="$SAVE_CFLAGS"
+ fi
+ ;;
+sparc*-*solaris*)
+ # Find out which ABI we are using.
+ echo 'int i;' > conftest.$ac_ext
+ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ case `/usr/bin/file conftest.o` in
+ *64-bit*)
+ case $lt_cv_prog_gnu_ld in
+ yes*) LD="${LD-ld} -m elf64_sparc" ;;
+ *) LD="${LD-ld} -64" ;;
+ esac
+ ;;
+ esac
+ fi
+ rm -rf conftest*
+ ;;
+
+*-*-cygwin* | *-*-mingw* | *-*-pw32*)
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args.
+set dummy ${ac_tool_prefix}dlltool; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_DLLTOOL+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$DLLTOOL"; then
+ ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+DLLTOOL=$ac_cv_prog_DLLTOOL
+if test -n "$DLLTOOL"; then
+ echo "$as_me:$LINENO: result: $DLLTOOL" >&5
+echo "${ECHO_T}$DLLTOOL" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_DLLTOOL"; then
+ ac_ct_DLLTOOL=$DLLTOOL
+ # Extract the first word of "dlltool", so it can be a program name with args.
+set dummy dlltool; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_DLLTOOL+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_DLLTOOL"; then
+ ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_DLLTOOL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_DLLTOOL="dlltool"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+ test -z "$ac_cv_prog_ac_ct_DLLTOOL" && ac_cv_prog_ac_ct_DLLTOOL="false"
+fi
+fi
+ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL
+if test -n "$ac_ct_DLLTOOL"; then
+ echo "$as_me:$LINENO: result: $ac_ct_DLLTOOL" >&5
+echo "${ECHO_T}$ac_ct_DLLTOOL" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ DLLTOOL=$ac_ct_DLLTOOL
+else
+ DLLTOOL="$ac_cv_prog_DLLTOOL"
+fi
+
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}as", so it can be a program name with args.
+set dummy ${ac_tool_prefix}as; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_AS+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$AS"; then
+ ac_cv_prog_AS="$AS" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_AS="${ac_tool_prefix}as"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+AS=$ac_cv_prog_AS
+if test -n "$AS"; then
+ echo "$as_me:$LINENO: result: $AS" >&5
+echo "${ECHO_T}$AS" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_AS"; then
+ ac_ct_AS=$AS
+ # Extract the first word of "as", so it can be a program name with args.
+set dummy as; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_AS+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_AS"; then
+ ac_cv_prog_ac_ct_AS="$ac_ct_AS" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_AS="as"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+ test -z "$ac_cv_prog_ac_ct_AS" && ac_cv_prog_ac_ct_AS="false"
+fi
+fi
+ac_ct_AS=$ac_cv_prog_ac_ct_AS
+if test -n "$ac_ct_AS"; then
+ echo "$as_me:$LINENO: result: $ac_ct_AS" >&5
+echo "${ECHO_T}$ac_ct_AS" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ AS=$ac_ct_AS
+else
+ AS="$ac_cv_prog_AS"
+fi
+
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args.
+set dummy ${ac_tool_prefix}objdump; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_OBJDUMP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$OBJDUMP"; then
+ ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+OBJDUMP=$ac_cv_prog_OBJDUMP
+if test -n "$OBJDUMP"; then
+ echo "$as_me:$LINENO: result: $OBJDUMP" >&5
+echo "${ECHO_T}$OBJDUMP" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_OBJDUMP"; then
+ ac_ct_OBJDUMP=$OBJDUMP
+ # Extract the first word of "objdump", so it can be a program name with args.
+set dummy objdump; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_OBJDUMP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_OBJDUMP"; then
+ ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_OBJDUMP="objdump"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+ test -z "$ac_cv_prog_ac_ct_OBJDUMP" && ac_cv_prog_ac_ct_OBJDUMP="false"
+fi
+fi
+ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP
+if test -n "$ac_ct_OBJDUMP"; then
+ echo "$as_me:$LINENO: result: $ac_ct_OBJDUMP" >&5
+echo "${ECHO_T}$ac_ct_OBJDUMP" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ OBJDUMP=$ac_ct_OBJDUMP
+else
+ OBJDUMP="$ac_cv_prog_OBJDUMP"
+fi
+
+ ;;
+
+esac
+
+need_locks="$enable_libtool_lock"
+
+
+
+for ac_header in dlfcn.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+else
+ # Is the header compilable?
+echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <$ac_header>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ ac_header_preproc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+ yes:no: )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+ ac_header_preproc=yes
+ ;;
+ no:yes:* )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+ (
+ cat <<\_ASBOX
+## ---------------------------- ##
+## Report this to radu at llnl.gov ##
+## ---------------------------- ##
+_ASBOX
+ ) |
+ sed "s/^/$as_me: WARNING: /" >&2
+ ;;
+esac
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ eval "$as_ac_Header=\$ac_header_preproc"
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+ac_ext=cc
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+ for ac_prog in $CCC g++ c++ gpp aCC CC cxx cc++ cl FCC KCC RCC xlC_r xlC
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CXX+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CXX"; then
+ ac_cv_prog_CXX="$CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CXX="$ac_tool_prefix$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+CXX=$ac_cv_prog_CXX
+if test -n "$CXX"; then
+ echo "$as_me:$LINENO: result: $CXX" >&5
+echo "${ECHO_T}$CXX" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ test -n "$CXX" && break
+ done
+fi
+if test -z "$CXX"; then
+ ac_ct_CXX=$CXX
+ for ac_prog in $CCC g++ c++ gpp aCC CC cxx cc++ cl FCC KCC RCC xlC_r xlC
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_CXX+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_CXX"; then
+ ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CXX="$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+ac_ct_CXX=$ac_cv_prog_ac_ct_CXX
+if test -n "$ac_ct_CXX"; then
+ echo "$as_me:$LINENO: result: $ac_ct_CXX" >&5
+echo "${ECHO_T}$ac_ct_CXX" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ test -n "$ac_ct_CXX" && break
+done
+test -n "$ac_ct_CXX" || ac_ct_CXX="g++"
+
+ CXX=$ac_ct_CXX
+fi
+
+
+# Provide some information about the compiler.
+echo "$as_me:$LINENO:" \
+ "checking for C++ compiler version" >&5
+ac_compiler=`set X $ac_compile; echo $2`
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version </dev/null >&5\"") >&5
+ (eval $ac_compiler --version </dev/null >&5) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v </dev/null >&5\"") >&5
+ (eval $ac_compiler -v </dev/null >&5) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V </dev/null >&5\"") >&5
+ (eval $ac_compiler -V </dev/null >&5) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+
+echo "$as_me:$LINENO: checking whether we are using the GNU C++ compiler" >&5
+echo $ECHO_N "checking whether we are using the GNU C++ compiler... $ECHO_C" >&6
+if test "${ac_cv_cxx_compiler_gnu+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+#ifndef __GNUC__
+ choke me
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_cxx_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_compiler_gnu=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_compiler_gnu=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_cxx_compiler_gnu=$ac_compiler_gnu
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_cxx_compiler_gnu" >&5
+echo "${ECHO_T}$ac_cv_cxx_compiler_gnu" >&6
+GXX=`test $ac_compiler_gnu = yes && echo yes`
+ac_test_CXXFLAGS=${CXXFLAGS+set}
+ac_save_CXXFLAGS=$CXXFLAGS
+CXXFLAGS="-g"
+echo "$as_me:$LINENO: checking whether $CXX accepts -g" >&5
+echo $ECHO_N "checking whether $CXX accepts -g... $ECHO_C" >&6
+if test "${ac_cv_prog_cxx_g+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_cxx_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_prog_cxx_g=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_prog_cxx_g=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_prog_cxx_g" >&5
+echo "${ECHO_T}$ac_cv_prog_cxx_g" >&6
+if test "$ac_test_CXXFLAGS" = set; then
+ CXXFLAGS=$ac_save_CXXFLAGS
+elif test $ac_cv_prog_cxx_g = yes; then
+ if test "$GXX" = yes; then
+ CXXFLAGS="-g -O2"
+ else
+ CXXFLAGS="-g"
+ fi
+else
+ if test "$GXX" = yes; then
+ CXXFLAGS="-O2"
+ else
+ CXXFLAGS=
+ fi
+fi
+for ac_declaration in \
+ '' \
+ 'extern "C" void std::exit (int) throw (); using std::exit;' \
+ 'extern "C" void std::exit (int); using std::exit;' \
+ 'extern "C" void exit (int) throw ();' \
+ 'extern "C" void exit (int);' \
+ 'void exit (int);'
+do
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_declaration
+#include <stdlib.h>
+int
+main ()
+{
+exit (42);
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_cxx_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+continue
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_declaration
+int
+main ()
+{
+exit (42);
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_cxx_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+rm -f conftest*
+if test -n "$ac_declaration"; then
+ echo '#ifdef __cplusplus' >>confdefs.h
+ echo $ac_declaration >>confdefs.h
+ echo '#endif' >>confdefs.h
+fi
+
+ac_ext=cc
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+
+
+if test -n "$CXX" && ( test "X$CXX" != "Xno" &&
+ ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) ||
+ (test "X$CXX" != "Xg++"))) ; then
+ ac_ext=cc
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+echo "$as_me:$LINENO: checking how to run the C++ preprocessor" >&5
+echo $ECHO_N "checking how to run the C++ preprocessor... $ECHO_C" >&6
+if test -z "$CXXCPP"; then
+ if test "${ac_cv_prog_CXXCPP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ # Double quotes because CXXCPP needs to be expanded
+ for CXXCPP in "$CXX -E" "/lib/cpp"
+ do
+ ac_preproc_ok=false
+for ac_cxx_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_cxx_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether non-existent headers
+ # can be detected and how.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_cxx_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ # Broken: success on invalid input.
+continue
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+ break
+fi
+
+ done
+ ac_cv_prog_CXXCPP=$CXXCPP
+
+fi
+ CXXCPP=$ac_cv_prog_CXXCPP
+else
+ ac_cv_prog_CXXCPP=$CXXCPP
+fi
+echo "$as_me:$LINENO: result: $CXXCPP" >&5
+echo "${ECHO_T}$CXXCPP" >&6
+ac_preproc_ok=false
+for ac_cxx_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_cxx_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether non-existent headers
+ # can be detected and how.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_cxx_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ # Broken: success on invalid input.
+continue
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+ :
+else
+ { { echo "$as_me:$LINENO: error: C++ preprocessor \"$CXXCPP\" fails sanity check
+See \`config.log' for more details." >&5
+echo "$as_me: error: C++ preprocessor \"$CXXCPP\" fails sanity check
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+ac_ext=cc
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+fi
+
+
+
+# Autoconf 2.13's AC_OBJEXT and AC_EXEEXT macros only works for C compilers!
+
+# find the maximum length of command line arguments
+echo "$as_me:$LINENO: checking the maximum length of command line arguments" >&5
+echo $ECHO_N "checking the maximum length of command line arguments... $ECHO_C" >&6
+if test "${lt_cv_sys_max_cmd_len+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ i=0
+ teststring="ABCD"
+
+ case $build_os in
+ msdosdjgpp*)
+ # On DJGPP, this test can blow up pretty badly due to problems in libc
+ # (any single argument exceeding 2000 bytes causes a buffer overrun
+ # during glob expansion). Even if it were fixed, the result of this
+ # check would be larger than it should be.
+ lt_cv_sys_max_cmd_len=12288; # 12K is about right
+ ;;
+
+ gnu*)
+ # Under GNU Hurd, this test is not required because there is
+ # no limit to the length of command line arguments.
+ # Libtool will interpret -1 as no limit whatsoever
+ lt_cv_sys_max_cmd_len=-1;
+ ;;
+
+ cygwin* | mingw*)
+ # On Win9x/ME, this test blows up -- it succeeds, but takes
+ # about 5 minutes as the teststring grows exponentially.
+ # Worse, since 9x/ME are not pre-emptively multitasking,
+ # you end up with a "frozen" computer, even though with patience
+ # the test eventually succeeds (with a max line length of 256k).
+ # Instead, let's just punt: use the minimum linelength reported by
+ # all of the supported platforms: 8192 (on NT/2K/XP).
+ lt_cv_sys_max_cmd_len=8192;
+ ;;
+
+ amigaos*)
+ # On AmigaOS with pdksh, this test takes hours, literally.
+ # So we just punt and use a minimum line length of 8192.
+ lt_cv_sys_max_cmd_len=8192;
+ ;;
+
+ netbsd* | freebsd* | openbsd* | darwin* | dragonfly*)
+ # This has been around since 386BSD, at least. Likely further.
+ if test -x /sbin/sysctl; then
+ lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax`
+ elif test -x /usr/sbin/sysctl; then
+ lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax`
+ else
+ lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs
+ fi
+ # And add a safety zone
+ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
+ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
+ ;;
+
+ interix*)
+ # We know the value 262144 and hardcode it with a safety zone (like BSD)
+ lt_cv_sys_max_cmd_len=196608
+ ;;
+
+ osf*)
+ # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure
+ # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not
+ # nice to cause kernel panics so lets avoid the loop below.
+ # First set a reasonable default.
+ lt_cv_sys_max_cmd_len=16384
+ #
+ if test -x /sbin/sysconfig; then
+ case `/sbin/sysconfig -q proc exec_disable_arg_limit` in
+ *1*) lt_cv_sys_max_cmd_len=-1 ;;
+ esac
+ fi
+ ;;
+ sco3.2v5*)
+ lt_cv_sys_max_cmd_len=102400
+ ;;
+ sysv5* | sco5v6* | sysv4.2uw2*)
+ kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null`
+ if test -n "$kargmax"; then
+ lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[ ]//'`
+ else
+ lt_cv_sys_max_cmd_len=32768
+ fi
+ ;;
+ *)
+ # If test is not a shell built-in, we'll probably end up computing a
+ # maximum length that is only half of the actual maximum length, but
+ # we can't tell.
+ SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}}
+ while (test "X"`$SHELL $0 --fallback-echo "X$teststring" 2>/dev/null` \
+ = "XX$teststring") >/dev/null 2>&1 &&
+ new_result=`expr "X$teststring" : ".*" 2>&1` &&
+ lt_cv_sys_max_cmd_len=$new_result &&
+ test $i != 17 # 1/2 MB should be enough
+ do
+ i=`expr $i + 1`
+ teststring=$teststring$teststring
+ done
+ teststring=
+ # Add a significant safety factor because C++ compilers can tack on massive
+ # amounts of additional arguments before passing them to the linker.
+ # It appears as though 1/2 is a usable value.
+ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2`
+ ;;
+ esac
+
+fi
+
+if test -n $lt_cv_sys_max_cmd_len ; then
+ echo "$as_me:$LINENO: result: $lt_cv_sys_max_cmd_len" >&5
+echo "${ECHO_T}$lt_cv_sys_max_cmd_len" >&6
+else
+ echo "$as_me:$LINENO: result: none" >&5
+echo "${ECHO_T}none" >&6
+fi
+
+
+
+
+# Check for command to grab the raw symbol name followed by C symbol from nm.
+echo "$as_me:$LINENO: checking command to parse $NM output from $compiler object" >&5
+echo $ECHO_N "checking command to parse $NM output from $compiler object... $ECHO_C" >&6
+if test "${lt_cv_sys_global_symbol_pipe+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+# These are sane defaults that work on at least a few old systems.
+# [They come from Ultrix. What could be older than Ultrix?!! ;)]
+
+# Character class describing NM global symbol codes.
+symcode='[BCDEGRST]'
+
+# Regexp to match symbols that can be accessed directly from C.
+sympat='\([_A-Za-z][_A-Za-z0-9]*\)'
+
+# Transform an extracted symbol line into a proper C declaration
+lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern int \1;/p'"
+
+# Transform an extracted symbol line into symbol name and symbol address
+lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode \([^ ]*\) \([^ ]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'"
+
+# Define system-specific variables.
+case $host_os in
+aix*)
+ symcode='[BCDT]'
+ ;;
+cygwin* | mingw* | pw32*)
+ symcode='[ABCDGISTW]'
+ ;;
+hpux*) # Its linker distinguishes data from code symbols
+ if test "$host_cpu" = ia64; then
+ symcode='[ABCDEGRST]'
+ fi
+ lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'"
+ lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'"
+ ;;
+linux*)
+ if test "$host_cpu" = ia64; then
+ symcode='[ABCDGIRSTW]'
+ lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'"
+ lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'"
+ fi
+ ;;
+irix* | nonstopux*)
+ symcode='[BCDEGRST]'
+ ;;
+osf*)
+ symcode='[BCDEGQRST]'
+ ;;
+solaris*)
+ symcode='[BDRT]'
+ ;;
+sco3.2v5*)
+ symcode='[DT]'
+ ;;
+sysv4.2uw2*)
+ symcode='[DT]'
+ ;;
+sysv5* | sco5v6* | unixware* | OpenUNIX*)
+ symcode='[ABDT]'
+ ;;
+sysv4)
+ symcode='[DFNSTU]'
+ ;;
+esac
+
+# Handle CRLF in mingw tool chain
+opt_cr=
+case $build_os in
+mingw*)
+ opt_cr=`echo 'x\{0,1\}' | tr x '\015'` # option cr in regexp
+ ;;
+esac
+
+# If we're using GNU nm, then use its standard symbol codes.
+case `$NM -V 2>&1` in
+*GNU* | *'with BFD'*)
+ symcode='[ABCDGIRSTW]' ;;
+esac
+
+# Try without a prefix undercore, then with it.
+for ac_symprfx in "" "_"; do
+
+ # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol.
+ symxfrm="\\1 $ac_symprfx\\2 \\2"
+
+ # Write the raw and C identifiers.
+ lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'"
+
+ # Check to see that the pipe works correctly.
+ pipe_works=no
+
+ rm -f conftest*
+ cat > conftest.$ac_ext <<EOF
+#ifdef __cplusplus
+extern "C" {
+#endif
+char nm_test_var;
+void nm_test_func(){}
+#ifdef __cplusplus
+}
+#endif
+int main(){nm_test_var='a';nm_test_func();return(0);}
+EOF
+
+ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ # Now try to grab the symbols.
+ nlist=conftest.nm
+ if { (eval echo "$as_me:$LINENO: \"$NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist\"") >&5
+ (eval $NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && test -s "$nlist"; then
+ # Try sorting and uniquifying the output.
+ if sort "$nlist" | uniq > "$nlist"T; then
+ mv -f "$nlist"T "$nlist"
+ else
+ rm -f "$nlist"T
+ fi
+
+ # Make sure that we snagged all the symbols we need.
+ if grep ' nm_test_var$' "$nlist" >/dev/null; then
+ if grep ' nm_test_func$' "$nlist" >/dev/null; then
+ cat <<EOF > conftest.$ac_ext
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+EOF
+ # Now generate the symbol file.
+ eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | grep -v main >> conftest.$ac_ext'
+
+ cat <<EOF >> conftest.$ac_ext
+#if defined (__STDC__) && __STDC__
+# define lt_ptr_t void *
+#else
+# define lt_ptr_t char *
+# define const
+#endif
+
+/* The mapping between symbol names and symbols. */
+const struct {
+ const char *name;
+ lt_ptr_t address;
+}
+lt_preloaded_symbols[] =
+{
+EOF
+ $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (lt_ptr_t) \&\2},/" < "$nlist" | grep -v main >> conftest.$ac_ext
+ cat <<\EOF >> conftest.$ac_ext
+ {0, (lt_ptr_t) 0}
+};
+
+#ifdef __cplusplus
+}
+#endif
+EOF
+ # Now try linking the two files.
+ mv conftest.$ac_objext conftstm.$ac_objext
+ lt_save_LIBS="$LIBS"
+ lt_save_CFLAGS="$CFLAGS"
+ LIBS="conftstm.$ac_objext"
+ CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag"
+ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && test -s conftest${ac_exeext}; then
+ pipe_works=yes
+ fi
+ LIBS="$lt_save_LIBS"
+ CFLAGS="$lt_save_CFLAGS"
+ else
+ echo "cannot find nm_test_func in $nlist" >&5
+ fi
+ else
+ echo "cannot find nm_test_var in $nlist" >&5
+ fi
+ else
+ echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5
+ fi
+ else
+ echo "$progname: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ fi
+ rm -f conftest* conftst*
+
+ # Do not use the global_symbol_pipe unless it works.
+ if test "$pipe_works" = yes; then
+ break
+ else
+ lt_cv_sys_global_symbol_pipe=
+ fi
+done
+
+fi
+
+if test -z "$lt_cv_sys_global_symbol_pipe"; then
+ lt_cv_sys_global_symbol_to_cdecl=
+fi
+if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then
+ echo "$as_me:$LINENO: result: failed" >&5
+echo "${ECHO_T}failed" >&6
+else
+ echo "$as_me:$LINENO: result: ok" >&5
+echo "${ECHO_T}ok" >&6
+fi
+
+echo "$as_me:$LINENO: checking for objdir" >&5
+echo $ECHO_N "checking for objdir... $ECHO_C" >&6
+if test "${lt_cv_objdir+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ rm -f .libs 2>/dev/null
+mkdir .libs 2>/dev/null
+if test -d .libs; then
+ lt_cv_objdir=.libs
+else
+ # MS-DOS does not allow filenames that begin with a dot.
+ lt_cv_objdir=_libs
+fi
+rmdir .libs 2>/dev/null
+fi
+echo "$as_me:$LINENO: result: $lt_cv_objdir" >&5
+echo "${ECHO_T}$lt_cv_objdir" >&6
+objdir=$lt_cv_objdir
+
+
+
+
+
+case $host_os in
+aix3*)
+ # AIX sometimes has problems with the GCC collect2 program. For some
+ # reason, if we set the COLLECT_NAMES environment variable, the problems
+ # vanish in a puff of smoke.
+ if test "X${COLLECT_NAMES+set}" != Xset; then
+ COLLECT_NAMES=
+ export COLLECT_NAMES
+ fi
+ ;;
+esac
+
+# Sed substitution that helps us do robust quoting. It backslashifies
+# metacharacters that are still active within double-quoted strings.
+Xsed='sed -e 1s/^X//'
+sed_quote_subst='s/\([\\"\\`$\\\\]\)/\\\1/g'
+
+# Same as above, but do not quote variable references.
+double_quote_subst='s/\([\\"\\`\\\\]\)/\\\1/g'
+
+# Sed substitution to delay expansion of an escaped shell variable in a
+# double_quote_subst'ed string.
+delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g'
+
+# Sed substitution to avoid accidental globbing in evaled expressions
+no_glob_subst='s/\*/\\\*/g'
+
+# Constants:
+rm="rm -f"
+
+# Global variables:
+default_ofile=libtool
+can_build_shared=yes
+
+# All known linkers require a `.a' archive for static linking (except MSVC,
+# which needs '.lib').
+libext=a
+ltmain="$ac_aux_dir/ltmain.sh"
+ofile="$default_ofile"
+with_gnu_ld="$lt_cv_prog_gnu_ld"
+
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ar; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_AR+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$AR"; then
+ ac_cv_prog_AR="$AR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_AR="${ac_tool_prefix}ar"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+AR=$ac_cv_prog_AR
+if test -n "$AR"; then
+ echo "$as_me:$LINENO: result: $AR" >&5
+echo "${ECHO_T}$AR" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_AR"; then
+ ac_ct_AR=$AR
+ # Extract the first word of "ar", so it can be a program name with args.
+set dummy ar; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_AR+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_AR"; then
+ ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_AR="ar"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+ test -z "$ac_cv_prog_ac_ct_AR" && ac_cv_prog_ac_ct_AR="false"
+fi
+fi
+ac_ct_AR=$ac_cv_prog_ac_ct_AR
+if test -n "$ac_ct_AR"; then
+ echo "$as_me:$LINENO: result: $ac_ct_AR" >&5
+echo "${ECHO_T}$ac_ct_AR" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ AR=$ac_ct_AR
+else
+ AR="$ac_cv_prog_AR"
+fi
+
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ranlib; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_RANLIB+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$RANLIB"; then
+ ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+RANLIB=$ac_cv_prog_RANLIB
+if test -n "$RANLIB"; then
+ echo "$as_me:$LINENO: result: $RANLIB" >&5
+echo "${ECHO_T}$RANLIB" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_RANLIB"; then
+ ac_ct_RANLIB=$RANLIB
+ # Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_RANLIB"; then
+ ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_RANLIB="ranlib"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+ test -z "$ac_cv_prog_ac_ct_RANLIB" && ac_cv_prog_ac_ct_RANLIB=":"
+fi
+fi
+ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
+if test -n "$ac_ct_RANLIB"; then
+ echo "$as_me:$LINENO: result: $ac_ct_RANLIB" >&5
+echo "${ECHO_T}$ac_ct_RANLIB" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ RANLIB=$ac_ct_RANLIB
+else
+ RANLIB="$ac_cv_prog_RANLIB"
+fi
+
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
+set dummy ${ac_tool_prefix}strip; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_STRIP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$STRIP"; then
+ ac_cv_prog_STRIP="$STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_STRIP="${ac_tool_prefix}strip"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+STRIP=$ac_cv_prog_STRIP
+if test -n "$STRIP"; then
+ echo "$as_me:$LINENO: result: $STRIP" >&5
+echo "${ECHO_T}$STRIP" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_STRIP"; then
+ ac_ct_STRIP=$STRIP
+ # Extract the first word of "strip", so it can be a program name with args.
+set dummy strip; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_STRIP"; then
+ ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_STRIP="strip"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+ test -z "$ac_cv_prog_ac_ct_STRIP" && ac_cv_prog_ac_ct_STRIP=":"
+fi
+fi
+ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP
+if test -n "$ac_ct_STRIP"; then
+ echo "$as_me:$LINENO: result: $ac_ct_STRIP" >&5
+echo "${ECHO_T}$ac_ct_STRIP" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ STRIP=$ac_ct_STRIP
+else
+ STRIP="$ac_cv_prog_STRIP"
+fi
+
+
+old_CC="$CC"
+old_CFLAGS="$CFLAGS"
+
+# Set sane defaults for various variables
+test -z "$AR" && AR=ar
+test -z "$AR_FLAGS" && AR_FLAGS=cru
+test -z "$AS" && AS=as
+test -z "$CC" && CC=cc
+test -z "$LTCC" && LTCC=$CC
+test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS
+test -z "$DLLTOOL" && DLLTOOL=dlltool
+test -z "$LD" && LD=ld
+test -z "$LN_S" && LN_S="ln -s"
+test -z "$MAGIC_CMD" && MAGIC_CMD=file
+test -z "$NM" && NM=nm
+test -z "$SED" && SED=sed
+test -z "$OBJDUMP" && OBJDUMP=objdump
+test -z "$RANLIB" && RANLIB=:
+test -z "$STRIP" && STRIP=:
+test -z "$ac_objext" && ac_objext=o
+
+# Determine commands to create old-style static archives.
+old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs$old_deplibs'
+old_postinstall_cmds='chmod 644 $oldlib'
+old_postuninstall_cmds=
+
+if test -n "$RANLIB"; then
+ case $host_os in
+ openbsd*)
+ old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib"
+ ;;
+ *)
+ old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib"
+ ;;
+ esac
+ old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib"
+fi
+
+for cc_temp in $compiler""; do
+ case $cc_temp in
+ compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
+ distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
+ \-*) ;;
+ *) break;;
+ esac
+done
+cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"`
+
+
+# Only perform the check for file, if the check method requires it
+case $deplibs_check_method in
+file_magic*)
+ if test "$file_magic_cmd" = '$MAGIC_CMD'; then
+ echo "$as_me:$LINENO: checking for ${ac_tool_prefix}file" >&5
+echo $ECHO_N "checking for ${ac_tool_prefix}file... $ECHO_C" >&6
+if test "${lt_cv_path_MAGIC_CMD+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ case $MAGIC_CMD in
+[\\/*] | ?:[\\/]*)
+ lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path.
+ ;;
+*)
+ lt_save_MAGIC_CMD="$MAGIC_CMD"
+ lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+ ac_dummy="/usr/bin$PATH_SEPARATOR$PATH"
+ for ac_dir in $ac_dummy; do
+ IFS="$lt_save_ifs"
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/${ac_tool_prefix}file; then
+ lt_cv_path_MAGIC_CMD="$ac_dir/${ac_tool_prefix}file"
+ if test -n "$file_magic_test_file"; then
+ case $deplibs_check_method in
+ "file_magic "*)
+ file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"`
+ MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+ if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
+ $EGREP "$file_magic_regex" > /dev/null; then
+ :
+ else
+ cat <<EOF 1>&2
+
+*** Warning: the command libtool uses to detect shared libraries,
+*** $file_magic_cmd, produces output that libtool cannot recognize.
+*** The result is that libtool may fail to recognize shared libraries
+*** as such. This will affect the creation of libtool libraries that
+*** depend on shared libraries, but programs linked with such libtool
+*** libraries will work regardless of this problem. Nevertheless, you
+*** may want to report the problem to your system manager and/or to
+*** bug-libtool at gnu.org
+
+EOF
+ fi ;;
+ esac
+ fi
+ break
+ fi
+ done
+ IFS="$lt_save_ifs"
+ MAGIC_CMD="$lt_save_MAGIC_CMD"
+ ;;
+esac
+fi
+
+MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+if test -n "$MAGIC_CMD"; then
+ echo "$as_me:$LINENO: result: $MAGIC_CMD" >&5
+echo "${ECHO_T}$MAGIC_CMD" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+if test -z "$lt_cv_path_MAGIC_CMD"; then
+ if test -n "$ac_tool_prefix"; then
+ echo "$as_me:$LINENO: checking for file" >&5
+echo $ECHO_N "checking for file... $ECHO_C" >&6
+if test "${lt_cv_path_MAGIC_CMD+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ case $MAGIC_CMD in
+[\\/*] | ?:[\\/]*)
+ lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path.
+ ;;
+*)
+ lt_save_MAGIC_CMD="$MAGIC_CMD"
+ lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+ ac_dummy="/usr/bin$PATH_SEPARATOR$PATH"
+ for ac_dir in $ac_dummy; do
+ IFS="$lt_save_ifs"
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/file; then
+ lt_cv_path_MAGIC_CMD="$ac_dir/file"
+ if test -n "$file_magic_test_file"; then
+ case $deplibs_check_method in
+ "file_magic "*)
+ file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"`
+ MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+ if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
+ $EGREP "$file_magic_regex" > /dev/null; then
+ :
+ else
+ cat <<EOF 1>&2
+
+*** Warning: the command libtool uses to detect shared libraries,
+*** $file_magic_cmd, produces output that libtool cannot recognize.
+*** The result is that libtool may fail to recognize shared libraries
+*** as such. This will affect the creation of libtool libraries that
+*** depend on shared libraries, but programs linked with such libtool
+*** libraries will work regardless of this problem. Nevertheless, you
+*** may want to report the problem to your system manager and/or to
+*** bug-libtool at gnu.org
+
+EOF
+ fi ;;
+ esac
+ fi
+ break
+ fi
+ done
+ IFS="$lt_save_ifs"
+ MAGIC_CMD="$lt_save_MAGIC_CMD"
+ ;;
+esac
+fi
+
+MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+if test -n "$MAGIC_CMD"; then
+ echo "$as_me:$LINENO: result: $MAGIC_CMD" >&5
+echo "${ECHO_T}$MAGIC_CMD" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ else
+ MAGIC_CMD=:
+ fi
+fi
+
+ fi
+ ;;
+esac
+
+enable_dlopen=no
+enable_win32_dll=yes
+
+# Check whether --enable-libtool-lock or --disable-libtool-lock was given.
+if test "${enable_libtool_lock+set}" = set; then
+ enableval="$enable_libtool_lock"
+
+fi;
+test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes
+
+
+# Check whether --with-pic or --without-pic was given.
+if test "${with_pic+set}" = set; then
+ withval="$with_pic"
+ pic_mode="$withval"
+else
+ pic_mode=default
+fi;
+test -z "$pic_mode" && pic_mode=default
+
+# Use C for the default configuration in the libtool script
+tagname=
+lt_save_CC="$CC"
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_linkonly='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_objext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+# Source file extension for C test sources.
+ac_ext=c
+
+# Object file extension for compiled C test sources.
+objext=o
+objext=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="int some_variable = 0;\n"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='int main(){return(0);}\n'
+
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# If no C compiler flags were specified, use CFLAGS.
+LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+
+
+# save warnings/boilerplate of simple test code
+ac_outfile=conftest.$ac_objext
+printf "$lt_simple_compile_test_code" >conftest.$ac_ext
+eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_compiler_boilerplate=`cat conftest.err`
+$rm conftest*
+
+ac_outfile=conftest.$ac_objext
+printf "$lt_simple_link_test_code" >conftest.$ac_ext
+eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_linker_boilerplate=`cat conftest.err`
+$rm conftest*
+
+
+
+lt_prog_compiler_no_builtin_flag=
+
+if test "$GCC" = yes; then
+ lt_prog_compiler_no_builtin_flag=' -fno-builtin'
+
+
+echo "$as_me:$LINENO: checking if $compiler supports -fno-rtti -fno-exceptions" >&5
+echo $ECHO_N "checking if $compiler supports -fno-rtti -fno-exceptions... $ECHO_C" >&6
+if test "${lt_cv_prog_compiler_rtti_exceptions+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ lt_cv_prog_compiler_rtti_exceptions=no
+ ac_outfile=conftest.$ac_objext
+ printf "$lt_simple_compile_test_code" > conftest.$ac_ext
+ lt_compiler_flag="-fno-rtti -fno-exceptions"
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ # The option is referenced via a variable to avoid confusing sed.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:13780: $lt_compile\"" >&5)
+ (eval "$lt_compile" 2>conftest.err)
+ ac_status=$?
+ cat conftest.err >&5
+ echo "$as_me:13784: \$? = $ac_status" >&5
+ if (exit $ac_status) && test -s "$ac_outfile"; then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings other than the usual output.
+ $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp
+ $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+ if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
+ lt_cv_prog_compiler_rtti_exceptions=yes
+ fi
+ fi
+ $rm conftest*
+
+fi
+echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_rtti_exceptions" >&5
+echo "${ECHO_T}$lt_cv_prog_compiler_rtti_exceptions" >&6
+
+if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then
+ lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions"
+else
+ :
+fi
+
+fi
+
+lt_prog_compiler_wl=
+lt_prog_compiler_pic=
+lt_prog_compiler_static=
+
+echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5
+echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6
+
+ if test "$GCC" = yes; then
+ lt_prog_compiler_wl='-Wl,'
+ lt_prog_compiler_static='-static'
+
+ case $host_os in
+ aix*)
+ # All AIX code is PIC.
+ if test "$host_cpu" = ia64; then
+ # AIX 5 now supports IA64 processor
+ lt_prog_compiler_static='-Bstatic'
+ fi
+ ;;
+
+ amigaos*)
+ # FIXME: we need at least 68020 code to build shared libraries, but
+ # adding the `-m68020' flag to GCC prevents building anything better,
+ # like `-m68040'.
+ lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4'
+ ;;
+
+ beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+ # PIC is the default for these OSes.
+ ;;
+
+ mingw* | pw32* | os2*)
+ # This hack is so that the source file can tell whether it is being
+ # built for inclusion in a dll (and should export symbols for example).
+ lt_prog_compiler_pic='-DDLL_EXPORT'
+ ;;
+
+ darwin* | rhapsody*)
+ # PIC is the default on this platform
+ # Common symbols not allowed in MH_DYLIB files
+ lt_prog_compiler_pic='-fno-common'
+ ;;
+
+ interix3*)
+ # Interix 3.x gcc -fpic/-fPIC options generate broken code.
+ # Instead, we relocate shared libraries at runtime.
+ ;;
+
+ msdosdjgpp*)
+ # Just because we use GCC doesn't mean we suddenly get shared libraries
+ # on systems that don't support them.
+ lt_prog_compiler_can_build_shared=no
+ enable_shared=no
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ lt_prog_compiler_pic=-Kconform_pic
+ fi
+ ;;
+
+ hpux*)
+ # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+ # not for PA HP-UX.
+ case $host_cpu in
+ hppa*64*|ia64*)
+ # +Z the default
+ ;;
+ *)
+ lt_prog_compiler_pic='-fPIC'
+ ;;
+ esac
+ ;;
+
+ *)
+ lt_prog_compiler_pic='-fPIC'
+ ;;
+ esac
+ else
+ # PORTME Check for flag to pass linker flags through the system compiler.
+ case $host_os in
+ aix*)
+ lt_prog_compiler_wl='-Wl,'
+ if test "$host_cpu" = ia64; then
+ # AIX 5 now supports IA64 processor
+ lt_prog_compiler_static='-Bstatic'
+ else
+ lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp'
+ fi
+ ;;
+ darwin*)
+ # PIC is the default on this platform
+ # Common symbols not allowed in MH_DYLIB files
+ case $cc_basename in
+ xlc*)
+ lt_prog_compiler_pic='-qnocommon'
+ lt_prog_compiler_wl='-Wl,'
+ ;;
+ esac
+ ;;
+
+ mingw* | pw32* | os2*)
+ # This hack is so that the source file can tell whether it is being
+ # built for inclusion in a dll (and should export symbols for example).
+ lt_prog_compiler_pic='-DDLL_EXPORT'
+ ;;
+
+ hpux9* | hpux10* | hpux11*)
+ lt_prog_compiler_wl='-Wl,'
+ # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+ # not for PA HP-UX.
+ case $host_cpu in
+ hppa*64*|ia64*)
+ # +Z the default
+ ;;
+ *)
+ lt_prog_compiler_pic='+Z'
+ ;;
+ esac
+ # Is there a better lt_prog_compiler_static that works with the bundled CC?
+ lt_prog_compiler_static='${wl}-a ${wl}archive'
+ ;;
+
+ irix5* | irix6* | nonstopux*)
+ lt_prog_compiler_wl='-Wl,'
+ # PIC (with -KPIC) is the default.
+ lt_prog_compiler_static='-non_shared'
+ ;;
+
+ newsos6)
+ lt_prog_compiler_pic='-KPIC'
+ lt_prog_compiler_static='-Bstatic'
+ ;;
+
+ linux*)
+ case $cc_basename in
+ icc* | ecc*)
+ lt_prog_compiler_wl='-Wl,'
+ lt_prog_compiler_pic='-KPIC'
+ lt_prog_compiler_static='-static'
+ ;;
+ pgcc* | pgf77* | pgf90* | pgf95*)
+ # Portland Group compilers (*not* the Pentium gcc compiler,
+ # which looks to be a dead project)
+ lt_prog_compiler_wl='-Wl,'
+ lt_prog_compiler_pic='-fpic'
+ lt_prog_compiler_static='-Bstatic'
+ ;;
+ ccc*)
+ lt_prog_compiler_wl='-Wl,'
+ # All Alpha code is PIC.
+ lt_prog_compiler_static='-non_shared'
+ ;;
+ esac
+ ;;
+
+ osf3* | osf4* | osf5*)
+ lt_prog_compiler_wl='-Wl,'
+ # All OSF/1 code is PIC.
+ lt_prog_compiler_static='-non_shared'
+ ;;
+
+ solaris*)
+ lt_prog_compiler_pic='-KPIC'
+ lt_prog_compiler_static='-Bstatic'
+ case $cc_basename in
+ f77* | f90* | f95*)
+ lt_prog_compiler_wl='-Qoption ld ';;
+ *)
+ lt_prog_compiler_wl='-Wl,';;
+ esac
+ ;;
+
+ sunos4*)
+ lt_prog_compiler_wl='-Qoption ld '
+ lt_prog_compiler_pic='-PIC'
+ lt_prog_compiler_static='-Bstatic'
+ ;;
+
+ sysv4 | sysv4.2uw2* | sysv4.3*)
+ lt_prog_compiler_wl='-Wl,'
+ lt_prog_compiler_pic='-KPIC'
+ lt_prog_compiler_static='-Bstatic'
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec ;then
+ lt_prog_compiler_pic='-Kconform_pic'
+ lt_prog_compiler_static='-Bstatic'
+ fi
+ ;;
+
+ sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
+ lt_prog_compiler_wl='-Wl,'
+ lt_prog_compiler_pic='-KPIC'
+ lt_prog_compiler_static='-Bstatic'
+ ;;
+
+ unicos*)
+ lt_prog_compiler_wl='-Wl,'
+ lt_prog_compiler_can_build_shared=no
+ ;;
+
+ uts4*)
+ lt_prog_compiler_pic='-pic'
+ lt_prog_compiler_static='-Bstatic'
+ ;;
+
+ *)
+ lt_prog_compiler_can_build_shared=no
+ ;;
+ esac
+ fi
+
+echo "$as_me:$LINENO: result: $lt_prog_compiler_pic" >&5
+echo "${ECHO_T}$lt_prog_compiler_pic" >&6
+
+#
+# Check to make sure the PIC flag actually works.
+#
+if test -n "$lt_prog_compiler_pic"; then
+
+echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5
+echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic works... $ECHO_C" >&6
+if test "${lt_prog_compiler_pic_works+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ lt_prog_compiler_pic_works=no
+ ac_outfile=conftest.$ac_objext
+ printf "$lt_simple_compile_test_code" > conftest.$ac_ext
+ lt_compiler_flag="$lt_prog_compiler_pic -DPIC"
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ # The option is referenced via a variable to avoid confusing sed.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:14048: $lt_compile\"" >&5)
+ (eval "$lt_compile" 2>conftest.err)
+ ac_status=$?
+ cat conftest.err >&5
+ echo "$as_me:14052: \$? = $ac_status" >&5
+ if (exit $ac_status) && test -s "$ac_outfile"; then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings other than the usual output.
+ $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp
+ $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+ if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
+ lt_prog_compiler_pic_works=yes
+ fi
+ fi
+ $rm conftest*
+
+fi
+echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works" >&5
+echo "${ECHO_T}$lt_prog_compiler_pic_works" >&6
+
+if test x"$lt_prog_compiler_pic_works" = xyes; then
+ case $lt_prog_compiler_pic in
+ "" | " "*) ;;
+ *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;;
+ esac
+else
+ lt_prog_compiler_pic=
+ lt_prog_compiler_can_build_shared=no
+fi
+
+fi
+case $host_os in
+ # For platforms which do not support PIC, -DPIC is meaningless:
+ *djgpp*)
+ lt_prog_compiler_pic=
+ ;;
+ *)
+ lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC"
+ ;;
+esac
+
+#
+# Check to make sure the static flag actually works.
+#
+wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\"
+echo "$as_me:$LINENO: checking if $compiler static flag $lt_tmp_static_flag works" >&5
+echo $ECHO_N "checking if $compiler static flag $lt_tmp_static_flag works... $ECHO_C" >&6
+if test "${lt_prog_compiler_static_works+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ lt_prog_compiler_static_works=no
+ save_LDFLAGS="$LDFLAGS"
+ LDFLAGS="$LDFLAGS $lt_tmp_static_flag"
+ printf "$lt_simple_link_test_code" > conftest.$ac_ext
+ if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
+ # The linker can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ if test -s conftest.err; then
+ # Append any errors to the config.log.
+ cat conftest.err 1>&5
+ $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp
+ $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+ if diff conftest.exp conftest.er2 >/dev/null; then
+ lt_prog_compiler_static_works=yes
+ fi
+ else
+ lt_prog_compiler_static_works=yes
+ fi
+ fi
+ $rm conftest*
+ LDFLAGS="$save_LDFLAGS"
+
+fi
+echo "$as_me:$LINENO: result: $lt_prog_compiler_static_works" >&5
+echo "${ECHO_T}$lt_prog_compiler_static_works" >&6
+
+if test x"$lt_prog_compiler_static_works" = xyes; then
+ :
+else
+ lt_prog_compiler_static=
+fi
+
+
+echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5
+echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6
+if test "${lt_cv_prog_compiler_c_o+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ lt_cv_prog_compiler_c_o=no
+ $rm -r conftest 2>/dev/null
+ mkdir conftest
+ cd conftest
+ mkdir out
+ printf "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+ lt_compiler_flag="-o out/conftest2.$ac_objext"
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:14152: $lt_compile\"" >&5)
+ (eval "$lt_compile" 2>out/conftest.err)
+ ac_status=$?
+ cat out/conftest.err >&5
+ echo "$as_me:14156: \$? = $ac_status" >&5
+ if (exit $ac_status) && test -s out/conftest2.$ac_objext
+ then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp
+ $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
+ if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
+ lt_cv_prog_compiler_c_o=yes
+ fi
+ fi
+ chmod u+w . 2>&5
+ $rm conftest*
+ # SGI C++ compiler will create directory out/ii_files/ for
+ # template instantiation
+ test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files
+ $rm out/* && rmdir out
+ cd ..
+ rmdir conftest
+ $rm conftest*
+
+fi
+echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o" >&5
+echo "${ECHO_T}$lt_cv_prog_compiler_c_o" >&6
+
+
+hard_links="nottested"
+if test "$lt_cv_prog_compiler_c_o" = no && test "$need_locks" != no; then
+ # do not overwrite the value of need_locks provided by the user
+ echo "$as_me:$LINENO: checking if we can lock with hard links" >&5
+echo $ECHO_N "checking if we can lock with hard links... $ECHO_C" >&6
+ hard_links=yes
+ $rm conftest*
+ ln conftest.a conftest.b 2>/dev/null && hard_links=no
+ touch conftest.a
+ ln conftest.a conftest.b 2>&5 || hard_links=no
+ ln conftest.a conftest.b 2>/dev/null && hard_links=no
+ echo "$as_me:$LINENO: result: $hard_links" >&5
+echo "${ECHO_T}$hard_links" >&6
+ if test "$hard_links" = no; then
+ { echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5
+echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;}
+ need_locks=warn
+ fi
+else
+ need_locks=no
+fi
+
+echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5
+echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6
+
+ runpath_var=
+ allow_undefined_flag=
+ enable_shared_with_static_runtimes=no
+ archive_cmds=
+ archive_expsym_cmds=
+ old_archive_From_new_cmds=
+ old_archive_from_expsyms_cmds=
+ export_dynamic_flag_spec=
+ whole_archive_flag_spec=
+ thread_safe_flag_spec=
+ hardcode_libdir_flag_spec=
+ hardcode_libdir_flag_spec_ld=
+ hardcode_libdir_separator=
+ hardcode_direct=no
+ hardcode_minus_L=no
+ hardcode_shlibpath_var=unsupported
+ link_all_deplibs=unknown
+ hardcode_automatic=no
+ module_cmds=
+ module_expsym_cmds=
+ always_export_symbols=no
+ export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+ # include_expsyms should be a list of space-separated symbols to be *always*
+ # included in the symbol list
+ include_expsyms=
+ # exclude_expsyms can be an extended regexp of symbols to exclude
+ # it will be wrapped by ` (' and `)$', so one must not match beginning or
+ # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc',
+ # as well as any symbol that contains `d'.
+ exclude_expsyms="_GLOBAL_OFFSET_TABLE_"
+ # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
+ # platforms (ab)use it in PIC code, but their linkers get confused if
+ # the symbol is explicitly referenced. Since portable code cannot
+ # rely on this symbol name, it's probably fine to never include it in
+ # preloaded symbol tables.
+ extract_expsyms_cmds=
+ # Just being paranoid about ensuring that cc_basename is set.
+ for cc_temp in $compiler""; do
+ case $cc_temp in
+ compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
+ distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
+ \-*) ;;
+ *) break;;
+ esac
+done
+cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"`
+
+ case $host_os in
+ cygwin* | mingw* | pw32*)
+ # FIXME: the MSVC++ port hasn't been tested in a loooong time
+ # When not using gcc, we currently assume that we are using
+ # Microsoft Visual C++.
+ if test "$GCC" != yes; then
+ with_gnu_ld=no
+ fi
+ ;;
+ interix*)
+ # we just hope/assume this is gcc and not c89 (= MSVC++)
+ with_gnu_ld=yes
+ ;;
+ openbsd*)
+ with_gnu_ld=no
+ ;;
+ esac
+
+ ld_shlibs=yes
+ if test "$with_gnu_ld" = yes; then
+ # If archive_cmds runs LD, not CC, wlarc should be empty
+ wlarc='${wl}'
+
+ # Set some defaults for GNU ld with shared library support. These
+ # are reset later if shared libraries are not supported. Putting them
+ # here allows them to be overridden if necessary.
+ runpath_var=LD_RUN_PATH
+ hardcode_libdir_flag_spec='${wl}--rpath ${wl}$libdir'
+ export_dynamic_flag_spec='${wl}--export-dynamic'
+ # ancient GNU ld didn't support --whole-archive et. al.
+ if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then
+ whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+ else
+ whole_archive_flag_spec=
+ fi
+ supports_anon_versioning=no
+ case `$LD -v 2>/dev/null` in
+ *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11
+ *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ...
+ *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ...
+ *\ 2.11.*) ;; # other 2.11 versions
+ *) supports_anon_versioning=yes ;;
+ esac
+
+ # See if GNU ld supports shared libraries.
+ case $host_os in
+ aix3* | aix4* | aix5*)
+ # On AIX/PPC, the GNU linker is very broken
+ if test "$host_cpu" != ia64; then
+ ld_shlibs=no
+ cat <<EOF 1>&2
+
+*** Warning: the GNU linker, at least up to release 2.9.1, is reported
+*** to be unable to reliably create shared libraries on AIX.
+*** Therefore, libtool is disabling shared libraries support. If you
+*** really care for shared libraries, you may want to modify your PATH
+*** so that a non-GNU linker is found, and then restart.
+
+EOF
+ fi
+ ;;
+
+ amigaos*)
+ archive_cmds='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_minus_L=yes
+
+ # Samuel A. Falvo II <kc5tja at dolphin.openprojects.net> reports
+ # that the semantics of dynamic libraries on AmigaOS, at least up
+ # to version 4, is to share data among multiple programs linked
+ # with the same dynamic library. Since this doesn't match the
+ # behavior of shared libraries on other platforms, we can't use
+ # them.
+ ld_shlibs=no
+ ;;
+
+ beos*)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ allow_undefined_flag=unsupported
+ # Joseph Beckenbach <jrb3 at best.com> says some releases of gcc
+ # support --undefined. This deserves some investigation. FIXME
+ archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ else
+ ld_shlibs=no
+ fi
+ ;;
+
+ cygwin* | mingw* | pw32*)
+ # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless,
+ # as there is no search path for DLLs.
+ hardcode_libdir_flag_spec='-L$libdir'
+ allow_undefined_flag=unsupported
+ always_export_symbols=no
+ enable_shared_with_static_runtimes=yes
+ export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS] /s/.* \([^ ]*\)/\1 DATA/'\'' | $SED -e '\''/^[AITW] /s/.* //'\'' | sort | uniq > $export_symbols'
+
+ if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then
+ archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+ # If the export-symbols file already is a .def file (1st line
+ # is EXPORTS), use it as is; otherwise, prepend...
+ archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
+ cp $export_symbols $output_objdir/$soname.def;
+ else
+ echo EXPORTS > $output_objdir/$soname.def;
+ cat $export_symbols >> $output_objdir/$soname.def;
+ fi~
+ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+ else
+ ld_shlibs=no
+ fi
+ ;;
+
+ interix3*)
+ hardcode_direct=no
+ hardcode_shlibpath_var=no
+ hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
+ export_dynamic_flag_spec='${wl}-E'
+ # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
+ # Instead, shared libraries are loaded at an image base (0x10000000 by
+ # default) and relocated if they conflict, which is a slow very memory
+ # consuming and fragmenting process. To avoid this, we pick a random,
+ # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
+ # time. Moving up from 0x10000000 also allows more sbrk(2) space.
+ archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+ archive_expsym_cmds='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+ ;;
+
+ linux*)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ tmp_addflag=
+ case $cc_basename,$host_cpu in
+ pgcc*) # Portland Group C compiler
+ whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
+ tmp_addflag=' $pic_flag'
+ ;;
+ pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers
+ whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
+ tmp_addflag=' $pic_flag -Mnomain' ;;
+ ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64
+ tmp_addflag=' -i_dynamic' ;;
+ efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64
+ tmp_addflag=' -i_dynamic -nofor_main' ;;
+ ifc* | ifort*) # Intel Fortran compiler
+ tmp_addflag=' -nofor_main' ;;
+ esac
+ archive_cmds='$CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+
+ if test $supports_anon_versioning = yes; then
+ archive_expsym_cmds='$echo "{ global:" > $output_objdir/$libname.ver~
+ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+ $echo "local: *; };" >> $output_objdir/$libname.ver~
+ $CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib'
+ fi
+ else
+ ld_shlibs=no
+ fi
+ ;;
+
+ netbsd*)
+ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+ archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
+ wlarc=
+ else
+ archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ fi
+ ;;
+
+ solaris*)
+ if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then
+ ld_shlibs=no
+ cat <<EOF 1>&2
+
+*** Warning: The releases 2.8.* of the GNU linker cannot reliably
+*** create shared libraries on Solaris systems. Therefore, libtool
+*** is disabling shared libraries support. We urge you to upgrade GNU
+*** binutils to release 2.9.1 or newer. Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+EOF
+ elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ else
+ ld_shlibs=no
+ fi
+ ;;
+
+ sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*)
+ case `$LD -v 2>&1` in
+ *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*)
+ ld_shlibs=no
+ cat <<_LT_EOF 1>&2
+
+*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not
+*** reliably create shared libraries on SCO systems. Therefore, libtool
+*** is disabling shared libraries support. We urge you to upgrade GNU
+*** binutils to release 2.16.91.0.3 or newer. Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+_LT_EOF
+ ;;
+ *)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`'
+ archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib'
+ archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname,-retain-symbols-file,$export_symbols -o $lib'
+ else
+ ld_shlibs=no
+ fi
+ ;;
+ esac
+ ;;
+
+ sunos4*)
+ archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+ wlarc=
+ hardcode_direct=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ *)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ else
+ ld_shlibs=no
+ fi
+ ;;
+ esac
+
+ if test "$ld_shlibs" = no; then
+ runpath_var=
+ hardcode_libdir_flag_spec=
+ export_dynamic_flag_spec=
+ whole_archive_flag_spec=
+ fi
+ else
+ # PORTME fill in a description of your system's linker (not GNU ld)
+ case $host_os in
+ aix3*)
+ allow_undefined_flag=unsupported
+ always_export_symbols=yes
+ archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname'
+ # Note: this linker hardcodes the directories in LIBPATH if there
+ # are no directories specified by -L.
+ hardcode_minus_L=yes
+ if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then
+ # Neither direct hardcoding nor static linking is supported with a
+ # broken collect2.
+ hardcode_direct=unsupported
+ fi
+ ;;
+
+ aix4* | aix5*)
+ if test "$host_cpu" = ia64; then
+ # On IA64, the linker does run time linking by default, so we don't
+ # have to do anything special.
+ aix_use_runtimelinking=no
+ exp_sym_flag='-Bexport'
+ no_entry_flag=""
+ else
+ # If we're using GNU nm, then we don't want the "-C" option.
+ # -C means demangle to AIX nm, but means don't demangle with GNU nm
+ if $NM -V 2>&1 | grep 'GNU' > /dev/null; then
+ export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols'
+ else
+ export_symbols_cmds='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols'
+ fi
+ aix_use_runtimelinking=no
+
+ # Test if we are trying to use run time linking or normal
+ # AIX style linking. If -brtl is somewhere in LDFLAGS, we
+ # need to do runtime linking.
+ case $host_os in aix4.[23]|aix4.[23].*|aix5*)
+ for ld_flag in $LDFLAGS; do
+ if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then
+ aix_use_runtimelinking=yes
+ break
+ fi
+ done
+ ;;
+ esac
+
+ exp_sym_flag='-bexport'
+ no_entry_flag='-bnoentry'
+ fi
+
+ # When large executables or shared objects are built, AIX ld can
+ # have problems creating the table of contents. If linking a library
+ # or program results in "error TOC overflow" add -mminimal-toc to
+ # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not
+ # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+ archive_cmds=''
+ hardcode_direct=yes
+ hardcode_libdir_separator=':'
+ link_all_deplibs=yes
+
+ if test "$GCC" = yes; then
+ case $host_os in aix4.[012]|aix4.[012].*)
+ # We only want to do this on AIX 4.2 and lower, the check
+ # below for broken collect2 doesn't work under 4.3+
+ collect2name=`${CC} -print-prog-name=collect2`
+ if test -f "$collect2name" && \
+ strings "$collect2name" | grep resolve_lib_name >/dev/null
+ then
+ # We have reworked collect2
+ hardcode_direct=yes
+ else
+ # We have old collect2
+ hardcode_direct=unsupported
+ # It fails to find uninstalled libraries when the uninstalled
+ # path is not listed in the libpath. Setting hardcode_minus_L
+ # to unsupported forces relinking
+ hardcode_minus_L=yes
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_libdir_separator=
+ fi
+ ;;
+ esac
+ shared_flag='-shared'
+ if test "$aix_use_runtimelinking" = yes; then
+ shared_flag="$shared_flag "'${wl}-G'
+ fi
+ else
+ # not using gcc
+ if test "$host_cpu" = ia64; then
+ # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+ # chokes on -Wl,-G. The following line is correct:
+ shared_flag='-G'
+ else
+ if test "$aix_use_runtimelinking" = yes; then
+ shared_flag='${wl}-G'
+ else
+ shared_flag='${wl}-bM:SRE'
+ fi
+ fi
+ fi
+
+ # It seems that -bexpall does not export symbols beginning with
+ # underscore (_), so it is better to generate a list of symbols to export.
+ always_export_symbols=yes
+ if test "$aix_use_runtimelinking" = yes; then
+ # Warning - without using the other runtime loading flags (-brtl),
+ # -berok will link without error, but may produce a broken library.
+ allow_undefined_flag='-berok'
+ # Determine the default libpath from the value encoded in an empty executable.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+
+aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`
+# Check for a 64-bit object if we didn't find anything.
+if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`; fi
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+
+ hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath"
+ archive_expsym_cmds="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+ else
+ if test "$host_cpu" = ia64; then
+ hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib'
+ allow_undefined_flag="-z nodefs"
+ archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols"
+ else
+ # Determine the default libpath from the value encoded in an empty executable.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+
+aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`
+# Check for a 64-bit object if we didn't find anything.
+if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`; fi
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+
+ hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath"
+ # Warning - without using the other run time loading flags,
+ # -berok will link without error, but may produce a broken library.
+ no_undefined_flag=' ${wl}-bernotok'
+ allow_undefined_flag=' ${wl}-berok'
+ # Exported symbols can be pulled into shared objects from archives
+ whole_archive_flag_spec='$convenience'
+ archive_cmds_need_lc=yes
+ # This is similar to how AIX traditionally builds its shared libraries.
+ archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
+ fi
+ fi
+ ;;
+
+ amigaos*)
+ archive_cmds='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_minus_L=yes
+ # see comment about different semantics on the GNU ld section
+ ld_shlibs=no
+ ;;
+
+ bsdi[45]*)
+ export_dynamic_flag_spec=-rdynamic
+ ;;
+
+ cygwin* | mingw* | pw32*)
+ # When not using gcc, we currently assume that we are using
+ # Microsoft Visual C++.
+ # hardcode_libdir_flag_spec is actually meaningless, as there is
+ # no search path for DLLs.
+ hardcode_libdir_flag_spec=' '
+ allow_undefined_flag=unsupported
+ # Tell ltmain to make .lib files, not .a files.
+ libext=lib
+ # Tell ltmain to make .dll files, not .so files.
+ shrext_cmds=".dll"
+ # FIXME: Setting linknames here is a bad hack.
+ archive_cmds='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames='
+ # The linker will automatically build a .lib file if we build a DLL.
+ old_archive_From_new_cmds='true'
+ # FIXME: Should let the user specify the lib program.
+ old_archive_cmds='lib /OUT:$oldlib$oldobjs$old_deplibs'
+ fix_srcfile_path='`cygpath -w "$srcfile"`'
+ enable_shared_with_static_runtimes=yes
+ ;;
+
+ darwin* | rhapsody*)
+ case $host_os in
+ rhapsody* | darwin1.[012])
+ allow_undefined_flag='${wl}-undefined ${wl}suppress'
+ ;;
+ *) # Darwin 1.3 on
+ if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then
+ allow_undefined_flag='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
+ else
+ case ${MACOSX_DEPLOYMENT_TARGET} in
+ 10.[012])
+ allow_undefined_flag='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
+ ;;
+ 10.*)
+ allow_undefined_flag='${wl}-undefined ${wl}dynamic_lookup'
+ ;;
+ esac
+ fi
+ ;;
+ esac
+ archive_cmds_need_lc=no
+ hardcode_direct=no
+ hardcode_automatic=yes
+ hardcode_shlibpath_var=unsupported
+ whole_archive_flag_spec=''
+ link_all_deplibs=yes
+ if test "$GCC" = yes ; then
+ output_verbose_link_cmd='echo'
+ archive_cmds='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring'
+ module_cmds='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
+ # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
+ archive_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ module_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ else
+ case $cc_basename in
+ xlc*)
+ output_verbose_link_cmd='echo'
+ archive_cmds='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring'
+ module_cmds='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
+ # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
+ archive_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ module_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ ;;
+ *)
+ ld_shlibs=no
+ ;;
+ esac
+ fi
+ ;;
+
+ dgux*)
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_shlibpath_var=no
+ ;;
+
+ freebsd1*)
+ ld_shlibs=no
+ ;;
+
+ # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
+ # support. Future versions do this automatically, but an explicit c++rt0.o
+ # does not break anything, and helps significantly (at the cost of a little
+ # extra space).
+ freebsd2.2*)
+ archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o'
+ hardcode_libdir_flag_spec='-R$libdir'
+ hardcode_direct=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ # Unfortunately, older versions of FreeBSD 2 do not have this feature.
+ freebsd2*)
+ archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_direct=yes
+ hardcode_minus_L=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
+ freebsd* | kfreebsd*-gnu | dragonfly*)
+ archive_cmds='$CC -shared -o $lib $libobjs $deplibs $compiler_flags'
+ hardcode_libdir_flag_spec='-R$libdir'
+ hardcode_direct=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ hpux9*)
+ if test "$GCC" = yes; then
+ archive_cmds='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+ else
+ archive_cmds='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+ fi
+ hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
+ hardcode_libdir_separator=:
+ hardcode_direct=yes
+
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ hardcode_minus_L=yes
+ export_dynamic_flag_spec='${wl}-E'
+ ;;
+
+ hpux10*)
+ if test "$GCC" = yes -a "$with_gnu_ld" = no; then
+ archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
+ fi
+ if test "$with_gnu_ld" = no; then
+ hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
+ hardcode_libdir_separator=:
+
+ hardcode_direct=yes
+ export_dynamic_flag_spec='${wl}-E'
+
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ hardcode_minus_L=yes
+ fi
+ ;;
+
+ hpux11*)
+ if test "$GCC" = yes -a "$with_gnu_ld" = no; then
+ case $host_cpu in
+ hppa*64*)
+ archive_cmds='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ ia64*)
+ archive_cmds='$CC -shared ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ *)
+ archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ esac
+ else
+ case $host_cpu in
+ hppa*64*)
+ archive_cmds='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ ia64*)
+ archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ *)
+ archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ esac
+ fi
+ if test "$with_gnu_ld" = no; then
+ hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
+ hardcode_libdir_separator=:
+
+ case $host_cpu in
+ hppa*64*|ia64*)
+ hardcode_libdir_flag_spec_ld='+b $libdir'
+ hardcode_direct=no
+ hardcode_shlibpath_var=no
+ ;;
+ *)
+ hardcode_direct=yes
+ export_dynamic_flag_spec='${wl}-E'
+
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ hardcode_minus_L=yes
+ ;;
+ esac
+ fi
+ ;;
+
+ irix5* | irix6* | nonstopux*)
+ if test "$GCC" = yes; then
+ archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ else
+ archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+ hardcode_libdir_flag_spec_ld='-rpath $libdir'
+ fi
+ hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator=:
+ link_all_deplibs=yes
+ ;;
+
+ netbsd*)
+ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+ archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out
+ else
+ archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF
+ fi
+ hardcode_libdir_flag_spec='-R$libdir'
+ hardcode_direct=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ newsos6)
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_direct=yes
+ hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator=:
+ hardcode_shlibpath_var=no
+ ;;
+
+ openbsd*)
+ hardcode_direct=yes
+ hardcode_shlibpath_var=no
+ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols'
+ hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
+ export_dynamic_flag_spec='${wl}-E'
+ else
+ case $host_os in
+ openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*)
+ archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_libdir_flag_spec='-R$libdir'
+ ;;
+ *)
+ archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+ hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
+ ;;
+ esac
+ fi
+ ;;
+
+ os2*)
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_minus_L=yes
+ allow_undefined_flag=unsupported
+ archive_cmds='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def'
+ old_archive_From_new_cmds='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def'
+ ;;
+
+ osf3*)
+ if test "$GCC" = yes; then
+ allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*'
+ archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ else
+ allow_undefined_flag=' -expect_unresolved \*'
+ archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+ fi
+ hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator=:
+ ;;
+
+ osf4* | osf5*) # as osf3* with the addition of -msym flag
+ if test "$GCC" = yes; then
+ allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*'
+ archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+ else
+ allow_undefined_flag=' -expect_unresolved \*'
+ archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+ archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~
+ $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~$rm $lib.exp'
+
+ # Both c and cxx compiler support -rpath directly
+ hardcode_libdir_flag_spec='-rpath $libdir'
+ fi
+ hardcode_libdir_separator=:
+ ;;
+
+ solaris*)
+ no_undefined_flag=' -z text'
+ if test "$GCC" = yes; then
+ wlarc='${wl}'
+ archive_cmds='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+ $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp'
+ else
+ wlarc=''
+ archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp'
+ fi
+ hardcode_libdir_flag_spec='-R$libdir'
+ hardcode_shlibpath_var=no
+ case $host_os in
+ solaris2.[0-5] | solaris2.[0-5].*) ;;
+ *)
+ # The compiler driver will combine linker options so we
+ # cannot just pass the convience library names through
+ # without $wl, iff we do not link with $LD.
+ # Luckily, gcc supports the same syntax we need for Sun Studio.
+ # Supported since Solaris 2.6 (maybe 2.5.1?)
+ case $wlarc in
+ '')
+ whole_archive_flag_spec='-z allextract$convenience -z defaultextract' ;;
+ *)
+ whole_archive_flag_spec='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract' ;;
+ esac ;;
+ esac
+ link_all_deplibs=yes
+ ;;
+
+ sunos4*)
+ if test "x$host_vendor" = xsequent; then
+ # Use $CC to link under sequent, because it throws in some extra .o
+ # files that make .init and .fini sections work.
+ archive_cmds='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags'
+ fi
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_direct=yes
+ hardcode_minus_L=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ sysv4)
+ case $host_vendor in
+ sni)
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_direct=yes # is this really true???
+ ;;
+ siemens)
+ ## LD is ld it makes a PLAMLIB
+ ## CC just makes a GrossModule.
+ archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags'
+ reload_cmds='$CC -r -o $output$reload_objs'
+ hardcode_direct=no
+ ;;
+ motorola)
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_direct=no #Motorola manual says yes, but my tests say they lie
+ ;;
+ esac
+ runpath_var='LD_RUN_PATH'
+ hardcode_shlibpath_var=no
+ ;;
+
+ sysv4.3*)
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_shlibpath_var=no
+ export_dynamic_flag_spec='-Bexport'
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_shlibpath_var=no
+ runpath_var=LD_RUN_PATH
+ hardcode_runpath_var=yes
+ ld_shlibs=yes
+ fi
+ ;;
+
+ sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7*)
+ no_undefined_flag='${wl}-z,text'
+ archive_cmds_need_lc=no
+ hardcode_shlibpath_var=no
+ runpath_var='LD_RUN_PATH'
+
+ if test "$GCC" = yes; then
+ archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ fi
+ ;;
+
+ sysv5* | sco3.2v5* | sco5v6*)
+ # Note: We can NOT use -z defs as we might desire, because we do not
+ # link with -lc, and that would cause any symbols used from libc to
+ # always be unresolved, which means just about no library would
+ # ever link correctly. If we're not using GNU ld we use -z text
+ # though, which does catch some bad symbols but isn't as heavy-handed
+ # as -z defs.
+ no_undefined_flag='${wl}-z,text'
+ allow_undefined_flag='${wl}-z,nodefs'
+ archive_cmds_need_lc=no
+ hardcode_shlibpath_var=no
+ hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`'
+ hardcode_libdir_separator=':'
+ link_all_deplibs=yes
+ export_dynamic_flag_spec='${wl}-Bexport'
+ runpath_var='LD_RUN_PATH'
+
+ if test "$GCC" = yes; then
+ archive_cmds='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ archive_cmds='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ fi
+ ;;
+
+ uts4*)
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_shlibpath_var=no
+ ;;
+
+ *)
+ ld_shlibs=no
+ ;;
+ esac
+ fi
+
+echo "$as_me:$LINENO: result: $ld_shlibs" >&5
+echo "${ECHO_T}$ld_shlibs" >&6
+test "$ld_shlibs" = no && can_build_shared=no
+
+#
+# Do we need to explicitly link libc?
+#
+case "x$archive_cmds_need_lc" in
+x|xyes)
+ # Assume -lc should be added
+ archive_cmds_need_lc=yes
+
+ if test "$enable_shared" = yes && test "$GCC" = yes; then
+ case $archive_cmds in
+ *'~'*)
+ # FIXME: we may have to deal with multi-command sequences.
+ ;;
+ '$CC '*)
+ # Test whether the compiler implicitly links with -lc since on some
+ # systems, -lgcc has to come before -lc. If gcc already passes -lc
+ # to ld, don't add -lc before -lgcc.
+ echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5
+echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6
+ $rm conftest*
+ printf "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } 2>conftest.err; then
+ soname=conftest
+ lib=conftest
+ libobjs=conftest.$ac_objext
+ deplibs=
+ wl=$lt_prog_compiler_wl
+ pic_flag=$lt_prog_compiler_pic
+ compiler_flags=-v
+ linker_flags=-v
+ verstring=
+ output_objdir=.
+ libname=conftest
+ lt_save_allow_undefined_flag=$allow_undefined_flag
+ allow_undefined_flag=
+ if { (eval echo "$as_me:$LINENO: \"$archive_cmds 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\"") >&5
+ (eval $archive_cmds 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+ then
+ archive_cmds_need_lc=no
+ else
+ archive_cmds_need_lc=yes
+ fi
+ allow_undefined_flag=$lt_save_allow_undefined_flag
+ else
+ cat conftest.err 1>&5
+ fi
+ $rm conftest*
+ echo "$as_me:$LINENO: result: $archive_cmds_need_lc" >&5
+echo "${ECHO_T}$archive_cmds_need_lc" >&6
+ ;;
+ esac
+ fi
+ ;;
+esac
+
+echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5
+echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6
+library_names_spec=
+libname_spec='lib$name'
+soname_spec=
+shrext_cmds=".so"
+postinstall_cmds=
+postuninstall_cmds=
+finish_cmds=
+finish_eval=
+shlibpath_var=
+shlibpath_overrides_runpath=unknown
+version_type=none
+dynamic_linker="$host_os ld.so"
+sys_lib_dlsearch_path_spec="/lib /usr/lib"
+if test "$GCC" = yes; then
+ sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
+ if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then
+ # if the path contains ";" then we assume it to be the separator
+ # otherwise default to the standard path separator (i.e. ":") - it is
+ # assumed that no part of a normal pathname contains ";" but that should
+ # okay in the real world where ";" in dirpaths is itself problematic.
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+ else
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+ fi
+else
+ sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
+fi
+need_lib_prefix=unknown
+hardcode_into_libs=no
+
+# when you set need_version to no, make sure it does not cause -set_version
+# flags to be left without arguments
+need_version=unknown
+
+case $host_os in
+aix3*)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a'
+ shlibpath_var=LIBPATH
+
+ # AIX 3 has no versioning support, so we append a major version to the name.
+ soname_spec='${libname}${release}${shared_ext}$major'
+ ;;
+
+aix4* | aix5*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ hardcode_into_libs=yes
+ if test "$host_cpu" = ia64; then
+ # AIX 5 supports IA64
+ library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ else
+ # With GCC up to 2.95.x, collect2 would create an import file
+ # for dependence libraries. The import file would start with
+ # the line `#! .'. This would cause the generated library to
+ # depend on `.', always an invalid library. This was fixed in
+ # development snapshots of GCC prior to 3.0.
+ case $host_os in
+ aix4 | aix4.[01] | aix4.[01].*)
+ if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
+ echo ' yes '
+ echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then
+ :
+ else
+ can_build_shared=no
+ fi
+ ;;
+ esac
+ # AIX (on Power*) has no versioning support, so currently we can not hardcode correct
+ # soname into executable. Probably we can add versioning support to
+ # collect2, so additional links can be useful in future.
+ if test "$aix_use_runtimelinking" = yes; then
+ # If using run time linking (on AIX 4.2 or later) use lib<name>.so
+ # instead of lib<name>.a to let people know that these are not
+ # typical AIX shared libraries.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ else
+ # We preserve .a as extension for shared libraries through AIX4.2
+ # and later when we are not doing run time linking.
+ library_names_spec='${libname}${release}.a $libname.a'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ fi
+ shlibpath_var=LIBPATH
+ fi
+ ;;
+
+amigaos*)
+ library_names_spec='$libname.ixlibrary $libname.a'
+ # Create ${libname}_ixlibrary.a entries in /sys/libs.
+ finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
+ ;;
+
+beos*)
+ library_names_spec='${libname}${shared_ext}'
+ dynamic_linker="$host_os ld.so"
+ shlibpath_var=LIBRARY_PATH
+ ;;
+
+bsdi[45]*)
+ version_type=linux
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
+ sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
+ # the default ld.so.conf also contains /usr/contrib/lib and
+ # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
+ # libtool to hard-code these into programs
+ ;;
+
+cygwin* | mingw* | pw32*)
+ version_type=windows
+ shrext_cmds=".dll"
+ need_version=no
+ need_lib_prefix=no
+
+ case $GCC,$host_os in
+ yes,cygwin* | yes,mingw* | yes,pw32*)
+ library_names_spec='$libname.dll.a'
+ # DLL is installed to $(libdir)/../bin by postinstall_cmds
+ postinstall_cmds='base_file=`basename \${file}`~
+ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~
+ dldir=$destdir/`dirname \$dlpath`~
+ test -d \$dldir || mkdir -p \$dldir~
+ $install_prog $dir/$dlname \$dldir/$dlname~
+ chmod a+x \$dldir/$dlname'
+ postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+ dlpath=$dir/\$dldll~
+ $rm \$dlpath'
+ shlibpath_overrides_runpath=yes
+
+ case $host_os in
+ cygwin*)
+ # Cygwin DLLs use 'cyg' prefix rather than 'lib'
+ soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+ sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib"
+ ;;
+ mingw*)
+ # MinGW DLLs use traditional 'lib' prefix
+ soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+ sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
+ if echo "$sys_lib_search_path_spec" | grep ';[c-zC-Z]:/' >/dev/null; then
+ # It is most probably a Windows format PATH printed by
+ # mingw gcc, but we are running on Cygwin. Gcc prints its search
+ # path with ; separators, and with drive letters. We can handle the
+ # drive letters (cygwin fileutils understands them), so leave them,
+ # especially as we might pass files found there to a mingw objdump,
+ # which wouldn't understand a cygwinified path. Ahh.
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+ else
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+ fi
+ ;;
+ pw32*)
+ # pw32 DLLs use 'pw' prefix rather than 'lib'
+ library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+ ;;
+ esac
+ ;;
+
+ *)
+ library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib'
+ ;;
+ esac
+ dynamic_linker='Win32 ld.exe'
+ # FIXME: first we should search . and the directory the executable is in
+ shlibpath_var=PATH
+ ;;
+
+darwin* | rhapsody*)
+ dynamic_linker="$host_os dyld"
+ version_type=darwin
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext'
+ soname_spec='${libname}${release}${major}$shared_ext'
+ shlibpath_overrides_runpath=yes
+ shlibpath_var=DYLD_LIBRARY_PATH
+ shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
+ # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same.
+ if test "$GCC" = yes; then
+ sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"`
+ else
+ sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib'
+ fi
+ sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
+ ;;
+
+dgux*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+freebsd1*)
+ dynamic_linker=no
+ ;;
+
+kfreebsd*-gnu)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ dynamic_linker='GNU ld.so'
+ ;;
+
+freebsd* | dragonfly*)
+ # DragonFly does not have aout. When/if they implement a new
+ # versioning mechanism, adjust this.
+ if test -x /usr/bin/objformat; then
+ objformat=`/usr/bin/objformat`
+ else
+ case $host_os in
+ freebsd[123]*) objformat=aout ;;
+ *) objformat=elf ;;
+ esac
+ fi
+ version_type=freebsd-$objformat
+ case $version_type in
+ freebsd-elf*)
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+ need_version=no
+ need_lib_prefix=no
+ ;;
+ freebsd-*)
+ library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix'
+ need_version=yes
+ ;;
+ esac
+ shlibpath_var=LD_LIBRARY_PATH
+ case $host_os in
+ freebsd2*)
+ shlibpath_overrides_runpath=yes
+ ;;
+ freebsd3.[01]* | freebsdelf3.[01]*)
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+ freebsd3.[2-9]* | freebsdelf3.[2-9]* | \
+ freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1)
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ ;;
+ freebsd*) # from 4.6 on
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+ esac
+ ;;
+
+gnu*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ hardcode_into_libs=yes
+ ;;
+
+hpux9* | hpux10* | hpux11*)
+ # Give a soname corresponding to the major version so that dld.sl refuses to
+ # link against other versions.
+ version_type=sunos
+ need_lib_prefix=no
+ need_version=no
+ case $host_cpu in
+ ia64*)
+ shrext_cmds='.so'
+ hardcode_into_libs=yes
+ dynamic_linker="$host_os dld.so"
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ if test "X$HPUX_IA64_MODE" = X32; then
+ sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
+ else
+ sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
+ fi
+ sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+ ;;
+ hppa*64*)
+ shrext_cmds='.sl'
+ hardcode_into_libs=yes
+ dynamic_linker="$host_os dld.sl"
+ shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
+ shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
+ sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+ ;;
+ *)
+ shrext_cmds='.sl'
+ dynamic_linker="$host_os dld.sl"
+ shlibpath_var=SHLIB_PATH
+ shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ ;;
+ esac
+ # HP-UX runs *really* slowly unless shared libraries are mode 555.
+ postinstall_cmds='chmod 555 $lib'
+ ;;
+
+interix3*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ ;;
+
+irix5* | irix6* | nonstopux*)
+ case $host_os in
+ nonstopux*) version_type=nonstopux ;;
+ *)
+ if test "$lt_cv_prog_gnu_ld" = yes; then
+ version_type=linux
+ else
+ version_type=irix
+ fi ;;
+ esac
+ need_lib_prefix=no
+ need_version=no
+ soname_spec='${libname}${release}${shared_ext}$major'
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}'
+ case $host_os in
+ irix5* | nonstopux*)
+ libsuff= shlibsuff=
+ ;;
+ *)
+ case $LD in # libtool.m4 will add one of these switches to LD
+ *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ")
+ libsuff= shlibsuff= libmagic=32-bit;;
+ *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ")
+ libsuff=32 shlibsuff=N32 libmagic=N32;;
+ *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ")
+ libsuff=64 shlibsuff=64 libmagic=64-bit;;
+ *) libsuff= shlibsuff= libmagic=never-match;;
+ esac
+ ;;
+ esac
+ shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
+ shlibpath_overrides_runpath=no
+ sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
+ sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
+ hardcode_into_libs=yes
+ ;;
+
+# No shared lib support for Linux oldld, aout, or coff.
+linux*oldld* | linux*aout* | linux*coff*)
+ dynamic_linker=no
+ ;;
+
+# This must be Linux ELF.
+linux*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ # This implies no fast_install, which is unacceptable.
+ # Some rework will be needed to allow for fast_install
+ # before this can be enabled.
+ hardcode_into_libs=yes
+
+ # find out which ABI we are using
+ libsuff=
+ case "$host_cpu" in
+ x86_64*|s390x*|powerpc64*)
+ echo '#line 15621 "configure"' > conftest.$ac_ext
+ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ case `/usr/bin/file conftest.$ac_objext` in
+ *64-bit*)
+ libsuff=64
+ sys_lib_search_path_spec="/lib${libsuff} /usr/lib${libsuff} /usr/local/lib${libsuff}"
+ ;;
+ esac
+ fi
+ rm -rf conftest*
+ ;;
+ esac
+
+ # Append ld.so.conf contents to the search path
+ if test -f /etc/ld.so.conf; then
+ lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '`
+ sys_lib_dlsearch_path_spec="/lib${libsuff} /usr/lib${libsuff} $lt_ld_extra"
+ fi
+
+ # We used to test for /lib/ld.so.1 and disable shared libraries on
+ # powerpc, because MkLinux only supported shared libraries with the
+ # GNU dynamic linker. Since this was broken with cross compilers,
+ # most powerpc-linux boxes support dynamic linking these days and
+ # people can always --disable-shared, the test was removed, and we
+ # assume the GNU/Linux dynamic linker is in use.
+ dynamic_linker='GNU/Linux ld.so'
+ ;;
+
+knetbsd*-gnu)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ dynamic_linker='GNU ld.so'
+ ;;
+
+netbsd*)
+ version_type=sunos
+ need_lib_prefix=no
+ need_version=no
+ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+ dynamic_linker='NetBSD (a.out) ld.so'
+ else
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ dynamic_linker='NetBSD ld.elf_so'
+ fi
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+
+newsos6)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ ;;
+
+nto-qnx*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ ;;
+
+openbsd*)
+ version_type=sunos
+ sys_lib_dlsearch_path_spec="/usr/lib"
+ need_lib_prefix=no
+ # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs.
+ case $host_os in
+ openbsd3.3 | openbsd3.3.*) need_version=yes ;;
+ *) need_version=no ;;
+ esac
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ case $host_os in
+ openbsd2.[89] | openbsd2.[89].*)
+ shlibpath_overrides_runpath=no
+ ;;
+ *)
+ shlibpath_overrides_runpath=yes
+ ;;
+ esac
+ else
+ shlibpath_overrides_runpath=yes
+ fi
+ ;;
+
+os2*)
+ libname_spec='$name'
+ shrext_cmds=".dll"
+ need_lib_prefix=no
+ library_names_spec='$libname${shared_ext} $libname.a'
+ dynamic_linker='OS/2 ld.exe'
+ shlibpath_var=LIBPATH
+ ;;
+
+osf3* | osf4* | osf5*)
+ version_type=osf
+ need_lib_prefix=no
+ need_version=no
+ soname_spec='${libname}${release}${shared_ext}$major'
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
+ sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec"
+ ;;
+
+solaris*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ # ldd complains unless libraries are executable
+ postinstall_cmds='chmod +x $lib'
+ ;;
+
+sunos4*)
+ version_type=sunos
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ if test "$with_gnu_ld" = yes; then
+ need_lib_prefix=no
+ fi
+ need_version=yes
+ ;;
+
+sysv4 | sysv4.3*)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ case $host_vendor in
+ sni)
+ shlibpath_overrides_runpath=no
+ need_lib_prefix=no
+ export_dynamic_flag_spec='${wl}-Blargedynsym'
+ runpath_var=LD_RUN_PATH
+ ;;
+ siemens)
+ need_lib_prefix=no
+ ;;
+ motorola)
+ need_lib_prefix=no
+ need_version=no
+ shlibpath_overrides_runpath=no
+ sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
+ ;;
+ esac
+ ;;
+
+sysv4*MP*)
+ if test -d /usr/nec ;then
+ version_type=linux
+ library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}'
+ soname_spec='$libname${shared_ext}.$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ fi
+ ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+ version_type=freebsd-elf
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ hardcode_into_libs=yes
+ if test "$with_gnu_ld" = yes; then
+ sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib'
+ shlibpath_overrides_runpath=no
+ else
+ sys_lib_search_path_spec='/usr/ccs/lib /usr/lib'
+ shlibpath_overrides_runpath=yes
+ case $host_os in
+ sco3.2v5*)
+ sys_lib_search_path_spec="$sys_lib_search_path_spec /lib"
+ ;;
+ esac
+ fi
+ sys_lib_dlsearch_path_spec='/usr/lib'
+ ;;
+
+uts4*)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+*)
+ dynamic_linker=no
+ ;;
+esac
+echo "$as_me:$LINENO: result: $dynamic_linker" >&5
+echo "${ECHO_T}$dynamic_linker" >&6
+test "$dynamic_linker" = no && can_build_shared=no
+
+variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
+if test "$GCC" = yes; then
+ variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
+fi
+
+echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5
+echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6
+hardcode_action=
+if test -n "$hardcode_libdir_flag_spec" || \
+ test -n "$runpath_var" || \
+ test "X$hardcode_automatic" = "Xyes" ; then
+
+ # We can hardcode non-existant directories.
+ if test "$hardcode_direct" != no &&
+ # If the only mechanism to avoid hardcoding is shlibpath_var, we
+ # have to relink, otherwise we might link with an installed library
+ # when we should be linking with a yet-to-be-installed one
+ ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, )" != no &&
+ test "$hardcode_minus_L" != no; then
+ # Linking always hardcodes the temporary library directory.
+ hardcode_action=relink
+ else
+ # We can link without hardcoding, and we can hardcode nonexisting dirs.
+ hardcode_action=immediate
+ fi
+else
+ # We cannot hardcode anything, or else we can only hardcode existing
+ # directories.
+ hardcode_action=unsupported
+fi
+echo "$as_me:$LINENO: result: $hardcode_action" >&5
+echo "${ECHO_T}$hardcode_action" >&6
+
+if test "$hardcode_action" = relink; then
+ # Fast installation is not supported
+ enable_fast_install=no
+elif test "$shlibpath_overrides_runpath" = yes ||
+ test "$enable_shared" = no; then
+ # Fast installation is not necessary
+ enable_fast_install=needless
+fi
+
+striplib=
+old_striplib=
+echo "$as_me:$LINENO: checking whether stripping libraries is possible" >&5
+echo $ECHO_N "checking whether stripping libraries is possible... $ECHO_C" >&6
+if test -n "$STRIP" && $STRIP -V 2>&1 | grep "GNU strip" >/dev/null; then
+ test -z "$old_striplib" && old_striplib="$STRIP --strip-debug"
+ test -z "$striplib" && striplib="$STRIP --strip-unneeded"
+ echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+else
+# FIXME - insert some real tests, host_os isn't really good enough
+ case $host_os in
+ darwin*)
+ if test -n "$STRIP" ; then
+ striplib="$STRIP -x"
+ echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+ else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+ ;;
+ *)
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+ ;;
+ esac
+fi
+
+if test "x$enable_dlopen" != xyes; then
+ enable_dlopen=unknown
+ enable_dlopen_self=unknown
+ enable_dlopen_self_static=unknown
+else
+ lt_cv_dlopen=no
+ lt_cv_dlopen_libs=
+
+ case $host_os in
+ beos*)
+ lt_cv_dlopen="load_add_on"
+ lt_cv_dlopen_libs=
+ lt_cv_dlopen_self=yes
+ ;;
+
+ mingw* | pw32*)
+ lt_cv_dlopen="LoadLibrary"
+ lt_cv_dlopen_libs=
+ ;;
+
+ cygwin*)
+ lt_cv_dlopen="dlopen"
+ lt_cv_dlopen_libs=
+ ;;
+
+ darwin*)
+ # if libdl is installed we need to link against it
+ echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5
+echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6
+if test "${ac_cv_lib_dl_dlopen+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldl $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char dlopen ();
+int
+main ()
+{
+dlopen ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_lib_dl_dlopen=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_dl_dlopen=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5
+echo "${ECHO_T}$ac_cv_lib_dl_dlopen" >&6
+if test $ac_cv_lib_dl_dlopen = yes; then
+ lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"
+else
+
+ lt_cv_dlopen="dyld"
+ lt_cv_dlopen_libs=
+ lt_cv_dlopen_self=yes
+
+fi
+
+ ;;
+
+ *)
+ echo "$as_me:$LINENO: checking for shl_load" >&5
+echo $ECHO_N "checking for shl_load... $ECHO_C" >&6
+if test "${ac_cv_func_shl_load+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define shl_load to an innocuous variant, in case <limits.h> declares shl_load.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define shl_load innocuous_shl_load
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char shl_load (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef shl_load
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char shl_load ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_shl_load) || defined (__stub___shl_load)
+choke me
+#else
+char (*f) () = shl_load;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != shl_load;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_func_shl_load=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_func_shl_load=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func_shl_load" >&5
+echo "${ECHO_T}$ac_cv_func_shl_load" >&6
+if test $ac_cv_func_shl_load = yes; then
+ lt_cv_dlopen="shl_load"
+else
+ echo "$as_me:$LINENO: checking for shl_load in -ldld" >&5
+echo $ECHO_N "checking for shl_load in -ldld... $ECHO_C" >&6
+if test "${ac_cv_lib_dld_shl_load+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldld $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char shl_load ();
+int
+main ()
+{
+shl_load ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_lib_dld_shl_load=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_dld_shl_load=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_dld_shl_load" >&5
+echo "${ECHO_T}$ac_cv_lib_dld_shl_load" >&6
+if test $ac_cv_lib_dld_shl_load = yes; then
+ lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-dld"
+else
+ echo "$as_me:$LINENO: checking for dlopen" >&5
+echo $ECHO_N "checking for dlopen... $ECHO_C" >&6
+if test "${ac_cv_func_dlopen+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define dlopen to an innocuous variant, in case <limits.h> declares dlopen.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define dlopen innocuous_dlopen
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char dlopen (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef dlopen
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char dlopen ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_dlopen) || defined (__stub___dlopen)
+choke me
+#else
+char (*f) () = dlopen;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != dlopen;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_func_dlopen=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_func_dlopen=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func_dlopen" >&5
+echo "${ECHO_T}$ac_cv_func_dlopen" >&6
+if test $ac_cv_func_dlopen = yes; then
+ lt_cv_dlopen="dlopen"
+else
+ echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5
+echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6
+if test "${ac_cv_lib_dl_dlopen+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldl $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char dlopen ();
+int
+main ()
+{
+dlopen ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_lib_dl_dlopen=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_dl_dlopen=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5
+echo "${ECHO_T}$ac_cv_lib_dl_dlopen" >&6
+if test $ac_cv_lib_dl_dlopen = yes; then
+ lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"
+else
+ echo "$as_me:$LINENO: checking for dlopen in -lsvld" >&5
+echo $ECHO_N "checking for dlopen in -lsvld... $ECHO_C" >&6
+if test "${ac_cv_lib_svld_dlopen+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lsvld $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char dlopen ();
+int
+main ()
+{
+dlopen ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_lib_svld_dlopen=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_svld_dlopen=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_svld_dlopen" >&5
+echo "${ECHO_T}$ac_cv_lib_svld_dlopen" >&6
+if test $ac_cv_lib_svld_dlopen = yes; then
+ lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"
+else
+ echo "$as_me:$LINENO: checking for dld_link in -ldld" >&5
+echo $ECHO_N "checking for dld_link in -ldld... $ECHO_C" >&6
+if test "${ac_cv_lib_dld_dld_link+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldld $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char dld_link ();
+int
+main ()
+{
+dld_link ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_lib_dld_dld_link=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_dld_dld_link=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_dld_dld_link" >&5
+echo "${ECHO_T}$ac_cv_lib_dld_dld_link" >&6
+if test $ac_cv_lib_dld_dld_link = yes; then
+ lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-dld"
+fi
+
+
+fi
+
+
+fi
+
+
+fi
+
+
+fi
+
+
+fi
+
+ ;;
+ esac
+
+ if test "x$lt_cv_dlopen" != xno; then
+ enable_dlopen=yes
+ else
+ enable_dlopen=no
+ fi
+
+ case $lt_cv_dlopen in
+ dlopen)
+ save_CPPFLAGS="$CPPFLAGS"
+ test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H"
+
+ save_LDFLAGS="$LDFLAGS"
+ wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\"
+
+ save_LIBS="$LIBS"
+ LIBS="$lt_cv_dlopen_libs $LIBS"
+
+ echo "$as_me:$LINENO: checking whether a program can dlopen itself" >&5
+echo $ECHO_N "checking whether a program can dlopen itself... $ECHO_C" >&6
+if test "${lt_cv_dlopen_self+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test "$cross_compiling" = yes; then :
+ lt_cv_dlopen_self=cross
+else
+ lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+ lt_status=$lt_dlunknown
+ cat > conftest.$ac_ext <<EOF
+#line 16518 "configure"
+#include "confdefs.h"
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef RTLD_GLOBAL
+# define LT_DLGLOBAL RTLD_GLOBAL
+#else
+# ifdef DL_GLOBAL
+# define LT_DLGLOBAL DL_GLOBAL
+# else
+# define LT_DLGLOBAL 0
+# endif
+#endif
+
+/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
+ find out it does not work in some platform. */
+#ifndef LT_DLLAZY_OR_NOW
+# ifdef RTLD_LAZY
+# define LT_DLLAZY_OR_NOW RTLD_LAZY
+# else
+# ifdef DL_LAZY
+# define LT_DLLAZY_OR_NOW DL_LAZY
+# else
+# ifdef RTLD_NOW
+# define LT_DLLAZY_OR_NOW RTLD_NOW
+# else
+# ifdef DL_NOW
+# define LT_DLLAZY_OR_NOW DL_NOW
+# else
+# define LT_DLLAZY_OR_NOW 0
+# endif
+# endif
+# endif
+# endif
+#endif
+
+#ifdef __cplusplus
+extern "C" void exit (int);
+#endif
+
+void fnord() { int i=42;}
+int main ()
+{
+ void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
+ int status = $lt_dlunknown;
+
+ if (self)
+ {
+ if (dlsym (self,"fnord")) status = $lt_dlno_uscore;
+ else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore;
+ /* dlclose (self); */
+ }
+ else
+ puts (dlerror ());
+
+ exit (status);
+}
+EOF
+ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && test -s conftest${ac_exeext} 2>/dev/null; then
+ (./conftest; exit; ) >&5 2>/dev/null
+ lt_status=$?
+ case x$lt_status in
+ x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;;
+ x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;;
+ x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;;
+ esac
+ else :
+ # compilation failed
+ lt_cv_dlopen_self=no
+ fi
+fi
+rm -fr conftest*
+
+
+fi
+echo "$as_me:$LINENO: result: $lt_cv_dlopen_self" >&5
+echo "${ECHO_T}$lt_cv_dlopen_self" >&6
+
+ if test "x$lt_cv_dlopen_self" = xyes; then
+ wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\"
+ echo "$as_me:$LINENO: checking whether a statically linked program can dlopen itself" >&5
+echo $ECHO_N "checking whether a statically linked program can dlopen itself... $ECHO_C" >&6
+if test "${lt_cv_dlopen_self_static+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test "$cross_compiling" = yes; then :
+ lt_cv_dlopen_self_static=cross
+else
+ lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+ lt_status=$lt_dlunknown
+ cat > conftest.$ac_ext <<EOF
+#line 16618 "configure"
+#include "confdefs.h"
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef RTLD_GLOBAL
+# define LT_DLGLOBAL RTLD_GLOBAL
+#else
+# ifdef DL_GLOBAL
+# define LT_DLGLOBAL DL_GLOBAL
+# else
+# define LT_DLGLOBAL 0
+# endif
+#endif
+
+/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
+ find out it does not work in some platform. */
+#ifndef LT_DLLAZY_OR_NOW
+# ifdef RTLD_LAZY
+# define LT_DLLAZY_OR_NOW RTLD_LAZY
+# else
+# ifdef DL_LAZY
+# define LT_DLLAZY_OR_NOW DL_LAZY
+# else
+# ifdef RTLD_NOW
+# define LT_DLLAZY_OR_NOW RTLD_NOW
+# else
+# ifdef DL_NOW
+# define LT_DLLAZY_OR_NOW DL_NOW
+# else
+# define LT_DLLAZY_OR_NOW 0
+# endif
+# endif
+# endif
+# endif
+#endif
+
+#ifdef __cplusplus
+extern "C" void exit (int);
+#endif
+
+void fnord() { int i=42;}
+int main ()
+{
+ void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
+ int status = $lt_dlunknown;
+
+ if (self)
+ {
+ if (dlsym (self,"fnord")) status = $lt_dlno_uscore;
+ else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore;
+ /* dlclose (self); */
+ }
+ else
+ puts (dlerror ());
+
+ exit (status);
+}
+EOF
+ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && test -s conftest${ac_exeext} 2>/dev/null; then
+ (./conftest; exit; ) >&5 2>/dev/null
+ lt_status=$?
+ case x$lt_status in
+ x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;;
+ x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;;
+ x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;;
+ esac
+ else :
+ # compilation failed
+ lt_cv_dlopen_self_static=no
+ fi
+fi
+rm -fr conftest*
+
+
+fi
+echo "$as_me:$LINENO: result: $lt_cv_dlopen_self_static" >&5
+echo "${ECHO_T}$lt_cv_dlopen_self_static" >&6
+ fi
+
+ CPPFLAGS="$save_CPPFLAGS"
+ LDFLAGS="$save_LDFLAGS"
+ LIBS="$save_LIBS"
+ ;;
+ esac
+
+ case $lt_cv_dlopen_self in
+ yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;;
+ *) enable_dlopen_self=unknown ;;
+ esac
+
+ case $lt_cv_dlopen_self_static in
+ yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;;
+ *) enable_dlopen_self_static=unknown ;;
+ esac
+fi
+
+
+# Report which library types will actually be built
+echo "$as_me:$LINENO: checking if libtool supports shared libraries" >&5
+echo $ECHO_N "checking if libtool supports shared libraries... $ECHO_C" >&6
+echo "$as_me:$LINENO: result: $can_build_shared" >&5
+echo "${ECHO_T}$can_build_shared" >&6
+
+echo "$as_me:$LINENO: checking whether to build shared libraries" >&5
+echo $ECHO_N "checking whether to build shared libraries... $ECHO_C" >&6
+test "$can_build_shared" = "no" && enable_shared=no
+
+# On AIX, shared libraries and static libraries use the same namespace, and
+# are all built from PIC.
+case $host_os in
+aix3*)
+ test "$enable_shared" = yes && enable_static=no
+ if test -n "$RANLIB"; then
+ archive_cmds="$archive_cmds~\$RANLIB \$lib"
+ postinstall_cmds='$RANLIB $lib'
+ fi
+ ;;
+
+aix4* | aix5*)
+ if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
+ test "$enable_shared" = yes && enable_static=no
+ fi
+ ;;
+esac
+echo "$as_me:$LINENO: result: $enable_shared" >&5
+echo "${ECHO_T}$enable_shared" >&6
+
+echo "$as_me:$LINENO: checking whether to build static libraries" >&5
+echo $ECHO_N "checking whether to build static libraries... $ECHO_C" >&6
+# Make sure either enable_shared or enable_static is yes.
+test "$enable_shared" = yes || enable_static=yes
+echo "$as_me:$LINENO: result: $enable_static" >&5
+echo "${ECHO_T}$enable_static" >&6
+
+# The else clause should only fire when bootstrapping the
+# libtool distribution, otherwise you forgot to ship ltmain.sh
+# with your package, and you will get complaints that there are
+# no rules to generate ltmain.sh.
+if test -f "$ltmain"; then
+ # See if we are running on zsh, and set the options which allow our commands through
+ # without removal of \ escapes.
+ if test -n "${ZSH_VERSION+set}" ; then
+ setopt NO_GLOB_SUBST
+ fi
+ # Now quote all the things that may contain metacharacters while being
+ # careful not to overquote the AC_SUBSTed values. We take copies of the
+ # variables and quote the copies for generation of the libtool script.
+ for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \
+ SED SHELL STRIP \
+ libname_spec library_names_spec soname_spec extract_expsyms_cmds \
+ old_striplib striplib file_magic_cmd finish_cmds finish_eval \
+ deplibs_check_method reload_flag reload_cmds need_locks \
+ lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \
+ lt_cv_sys_global_symbol_to_c_name_address \
+ sys_lib_search_path_spec sys_lib_dlsearch_path_spec \
+ old_postinstall_cmds old_postuninstall_cmds \
+ compiler \
+ CC \
+ LD \
+ lt_prog_compiler_wl \
+ lt_prog_compiler_pic \
+ lt_prog_compiler_static \
+ lt_prog_compiler_no_builtin_flag \
+ export_dynamic_flag_spec \
+ thread_safe_flag_spec \
+ whole_archive_flag_spec \
+ enable_shared_with_static_runtimes \
+ old_archive_cmds \
+ old_archive_from_new_cmds \
+ predep_objects \
+ postdep_objects \
+ predeps \
+ postdeps \
+ compiler_lib_search_path \
+ archive_cmds \
+ archive_expsym_cmds \
+ postinstall_cmds \
+ postuninstall_cmds \
+ old_archive_from_expsyms_cmds \
+ allow_undefined_flag \
+ no_undefined_flag \
+ export_symbols_cmds \
+ hardcode_libdir_flag_spec \
+ hardcode_libdir_flag_spec_ld \
+ hardcode_libdir_separator \
+ hardcode_automatic \
+ module_cmds \
+ module_expsym_cmds \
+ lt_cv_prog_compiler_c_o \
+ exclude_expsyms \
+ include_expsyms; do
+
+ case $var in
+ old_archive_cmds | \
+ old_archive_from_new_cmds | \
+ archive_cmds | \
+ archive_expsym_cmds | \
+ module_cmds | \
+ module_expsym_cmds | \
+ old_archive_from_expsyms_cmds | \
+ export_symbols_cmds | \
+ extract_expsyms_cmds | reload_cmds | finish_cmds | \
+ postinstall_cmds | postuninstall_cmds | \
+ old_postinstall_cmds | old_postuninstall_cmds | \
+ sys_lib_search_path_spec | sys_lib_dlsearch_path_spec)
+ # Double-quote double-evaled strings.
+ eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\""
+ ;;
+ *)
+ eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\""
+ ;;
+ esac
+ done
+
+ case $lt_echo in
+ *'\$0 --fallback-echo"')
+ lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'`
+ ;;
+ esac
+
+cfgfile="${ofile}T"
+ trap "$rm \"$cfgfile\"; exit 1" 1 2 15
+ $rm -f "$cfgfile"
+ { echo "$as_me:$LINENO: creating $ofile" >&5
+echo "$as_me: creating $ofile" >&6;}
+
+ cat <<__EOF__ >> "$cfgfile"
+#! $SHELL
+
+# `$echo "$cfgfile" | sed 's%^.*/%%'` - Provide generalized library-building support services.
+# Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP)
+# NOTE: Changes made to this file will be lost: look at ltmain.sh.
+#
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001
+# Free Software Foundation, Inc.
+#
+# This file is part of GNU Libtool:
+# Originally by Gordon Matzigkeit <gord at gnu.ai.mit.edu>, 1996
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# A sed program that does not truncate output.
+SED=$lt_SED
+
+# Sed that helps us avoid accidentally triggering echo(1) options like -n.
+Xsed="$SED -e 1s/^X//"
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+# The names of the tagged configurations supported by this script.
+available_tags=
+
+# ### BEGIN LIBTOOL CONFIG
+
+# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+
+# Shell to use when invoking shell scripts.
+SHELL=$lt_SHELL
+
+# Whether or not to build shared libraries.
+build_libtool_libs=$enable_shared
+
+# Whether or not to build static libraries.
+build_old_libs=$enable_static
+
+# Whether or not to add -lc for building shared libraries.
+build_libtool_need_lc=$archive_cmds_need_lc
+
+# Whether or not to disallow shared libs when runtime libs are static
+allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes
+
+# Whether or not to optimize for fast installation.
+fast_install=$enable_fast_install
+
+# The host system.
+host_alias=$host_alias
+host=$host
+host_os=$host_os
+
+# The build system.
+build_alias=$build_alias
+build=$build
+build_os=$build_os
+
+# An echo program that does not interpret backslashes.
+echo=$lt_echo
+
+# The archiver.
+AR=$lt_AR
+AR_FLAGS=$lt_AR_FLAGS
+
+# A C compiler.
+LTCC=$lt_LTCC
+
+# LTCC compiler flags.
+LTCFLAGS=$lt_LTCFLAGS
+
+# A language-specific compiler.
+CC=$lt_compiler
+
+# Is the compiler the GNU C compiler?
+with_gcc=$GCC
+
+gcc_dir=\`gcc -print-file-name=. | $SED 's,/\.$,,'\`
+gcc_ver=\`gcc -dumpversion\`
+
+# An ERE matcher.
+EGREP=$lt_EGREP
+
+# The linker used to build libraries.
+LD=$lt_LD
+
+# Whether we need hard or soft links.
+LN_S=$lt_LN_S
+
+# A BSD-compatible nm program.
+NM=$lt_NM
+
+# A symbol stripping program
+STRIP=$lt_STRIP
+
+# Used to examine libraries when file_magic_cmd begins "file"
+MAGIC_CMD=$MAGIC_CMD
+
+# Used on cygwin: DLL creation program.
+DLLTOOL="$DLLTOOL"
+
+# Used on cygwin: object dumper.
+OBJDUMP="$OBJDUMP"
+
+# Used on cygwin: assembler.
+AS="$AS"
+
+# The name of the directory that contains temporary libtool files.
+objdir=$objdir
+
+# How to create reloadable object files.
+reload_flag=$lt_reload_flag
+reload_cmds=$lt_reload_cmds
+
+# How to pass a linker flag through the compiler.
+wl=$lt_lt_prog_compiler_wl
+
+# Object file suffix (normally "o").
+objext="$ac_objext"
+
+# Old archive suffix (normally "a").
+libext="$libext"
+
+# Shared library suffix (normally ".so").
+shrext_cmds='$shrext_cmds'
+
+# Executable file suffix (normally "").
+exeext="$exeext"
+
+# Additional compiler flags for building library objects.
+pic_flag=$lt_lt_prog_compiler_pic
+pic_mode=$pic_mode
+
+# What is the maximum length of a command?
+max_cmd_len=$lt_cv_sys_max_cmd_len
+
+# Does compiler simultaneously support -c and -o options?
+compiler_c_o=$lt_lt_cv_prog_compiler_c_o
+
+# Must we lock files when doing compilation?
+need_locks=$lt_need_locks
+
+# Do we need the lib prefix for modules?
+need_lib_prefix=$need_lib_prefix
+
+# Do we need a version for libraries?
+need_version=$need_version
+
+# Whether dlopen is supported.
+dlopen_support=$enable_dlopen
+
+# Whether dlopen of programs is supported.
+dlopen_self=$enable_dlopen_self
+
+# Whether dlopen of statically linked programs is supported.
+dlopen_self_static=$enable_dlopen_self_static
+
+# Compiler flag to prevent dynamic linking.
+link_static_flag=$lt_lt_prog_compiler_static
+
+# Compiler flag to turn off builtin functions.
+no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag
+
+# Compiler flag to allow reflexive dlopens.
+export_dynamic_flag_spec=$lt_export_dynamic_flag_spec
+
+# Compiler flag to generate shared objects directly from archives.
+whole_archive_flag_spec=$lt_whole_archive_flag_spec
+
+# Compiler flag to generate thread-safe objects.
+thread_safe_flag_spec=$lt_thread_safe_flag_spec
+
+# Library versioning type.
+version_type=$version_type
+
+# Format of library name prefix.
+libname_spec=$lt_libname_spec
+
+# List of archive names. First name is the real one, the rest are links.
+# The last name is the one that the linker finds with -lNAME.
+library_names_spec=$lt_library_names_spec
+
+# The coded name of the library, if different from the real name.
+soname_spec=$lt_soname_spec
+
+# Commands used to build and install an old-style archive.
+RANLIB=$lt_RANLIB
+old_archive_cmds=$lt_old_archive_cmds
+old_postinstall_cmds=$lt_old_postinstall_cmds
+old_postuninstall_cmds=$lt_old_postuninstall_cmds
+
+# Create an old-style archive from a shared archive.
+old_archive_from_new_cmds=$lt_old_archive_from_new_cmds
+
+# Create a temporary old-style archive to link instead of a shared archive.
+old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds
+
+# Commands used to build and install a shared archive.
+archive_cmds=$lt_archive_cmds
+archive_expsym_cmds=$lt_archive_expsym_cmds
+postinstall_cmds=$lt_postinstall_cmds
+postuninstall_cmds=$lt_postuninstall_cmds
+
+# Commands used to build a loadable module (assumed same as above if empty)
+module_cmds=$lt_module_cmds
+module_expsym_cmds=$lt_module_expsym_cmds
+
+# Commands to strip libraries.
+old_striplib=$lt_old_striplib
+striplib=$lt_striplib
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predep_objects=\`echo $lt_predep_objects | \$SED -e "s@\${gcc_dir}@\\\${gcc_dir}@g;s@\${gcc_ver}@\\\${gcc_ver}@g"\`
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdep_objects=\`echo $lt_postdep_objects | \$SED -e "s@\${gcc_dir}@\\\${gcc_dir}@g;s@\${gcc_ver}@\\\${gcc_ver}@g"\`
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predeps=$lt_predeps
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdeps=$lt_postdeps
+
+# The library search path used internally by the compiler when linking
+# a shared library.
+compiler_lib_search_path=\`echo $lt_compiler_lib_search_path | \$SED -e "s@\${gcc_dir}@\\\${gcc_dir}@g;s@\${gcc_ver}@\\\${gcc_ver}@g"\`
+
+# Method to check whether dependent libraries are shared objects.
+deplibs_check_method=$lt_deplibs_check_method
+
+# Command to use when deplibs_check_method == file_magic.
+file_magic_cmd=$lt_file_magic_cmd
+
+# Flag that allows shared libraries with undefined symbols to be built.
+allow_undefined_flag=$lt_allow_undefined_flag
+
+# Flag that forces no undefined symbols.
+no_undefined_flag=$lt_no_undefined_flag
+
+# Commands used to finish a libtool library installation in a directory.
+finish_cmds=$lt_finish_cmds
+
+# Same as above, but a single script fragment to be evaled but not shown.
+finish_eval=$lt_finish_eval
+
+# Take the output of nm and produce a listing of raw symbols and C names.
+global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe
+
+# Transform the output of nm in a proper C declaration
+global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl
+
+# Transform the output of nm in a C name address pair
+global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address
+
+# This is the shared library runtime path variable.
+runpath_var=$runpath_var
+
+# This is the shared library path variable.
+shlibpath_var=$shlibpath_var
+
+# Is shlibpath searched before the hard-coded library search path?
+shlibpath_overrides_runpath=$shlibpath_overrides_runpath
+
+# How to hardcode a shared library path into an executable.
+hardcode_action=$hardcode_action
+
+# Whether we should hardcode library paths into libraries.
+hardcode_into_libs=$hardcode_into_libs
+
+# Flag to hardcode \$libdir into a binary during linking.
+# This must work even if \$libdir does not exist.
+hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec
+
+# If ld is used when linking, flag to hardcode \$libdir into
+# a binary during linking. This must work even if \$libdir does
+# not exist.
+hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld
+
+# Whether we need a single -rpath flag with a separated argument.
+hardcode_libdir_separator=$lt_hardcode_libdir_separator
+
+# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the
+# resulting binary.
+hardcode_direct=$hardcode_direct
+
+# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
+# resulting binary.
+hardcode_minus_L=$hardcode_minus_L
+
+# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into
+# the resulting binary.
+hardcode_shlibpath_var=$hardcode_shlibpath_var
+
+# Set to yes if building a shared library automatically hardcodes DIR into the library
+# and all subsequent libraries and executables linked against it.
+hardcode_automatic=$hardcode_automatic
+
+# Variables whose values should be saved in libtool wrapper scripts and
+# restored at relink time.
+variables_saved_for_relink="$variables_saved_for_relink"
+
+# Whether libtool must link a program against all its dependency libraries.
+link_all_deplibs=$link_all_deplibs
+
+# Compile-time system search path for libraries
+sys_lib_search_path_spec=\`echo $lt_sys_lib_search_path_spec | \$SED -e "s@\${gcc_dir}@\\\${gcc_dir}@g;s@\${gcc_ver}@\\\${gcc_ver}@g"\`
+
+# Run-time system search path for libraries
+sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec
+
+# Fix the shell variable \$srcfile for the compiler.
+fix_srcfile_path="$fix_srcfile_path"
+
+# Set to yes if exported symbols are required.
+always_export_symbols=$always_export_symbols
+
+# The commands to list exported symbols.
+export_symbols_cmds=$lt_export_symbols_cmds
+
+# The commands to extract the exported symbol list from a shared archive.
+extract_expsyms_cmds=$lt_extract_expsyms_cmds
+
+# Symbols that should not be listed in the preloaded symbols.
+exclude_expsyms=$lt_exclude_expsyms
+
+# Symbols that must always be exported.
+include_expsyms=$lt_include_expsyms
+
+# ### END LIBTOOL CONFIG
+
+__EOF__
+
+
+ case $host_os in
+ aix3*)
+ cat <<\EOF >> "$cfgfile"
+
+# AIX sometimes has problems with the GCC collect2 program. For some
+# reason, if we set the COLLECT_NAMES environment variable, the problems
+# vanish in a puff of smoke.
+if test "X${COLLECT_NAMES+set}" != Xset; then
+ COLLECT_NAMES=
+ export COLLECT_NAMES
+fi
+EOF
+ ;;
+ esac
+
+ # We use sed instead of cat because bash on DJGPP gets confused if
+ # if finds mixed CR/LF and LF-only lines. Since sed operates in
+ # text mode, it properly converts lines to CR/LF. This bash problem
+ # is reportedly fixed, but why not run on old versions too?
+ sed '$q' "$ltmain" >> "$cfgfile" || (rm -f "$cfgfile"; exit 1)
+
+ mv -f "$cfgfile" "$ofile" || \
+ (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile")
+ chmod +x "$ofile"
+
+else
+ # If there is no Makefile yet, we rely on a make rule to execute
+ # `config.status --recheck' to rerun these tests and create the
+ # libtool script then.
+ ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'`
+ if test -f "$ltmain_in"; then
+ test -f Makefile && make "$ltmain"
+ fi
+fi
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_linkonly='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_objext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+CC="$lt_save_CC"
+
+
+# Check whether --with-tags or --without-tags was given.
+if test "${with_tags+set}" = set; then
+ withval="$with_tags"
+ tagnames="$withval"
+fi;
+
+if test -f "$ltmain" && test -n "$tagnames"; then
+ if test ! -f "${ofile}"; then
+ { echo "$as_me:$LINENO: WARNING: output file \`$ofile' does not exist" >&5
+echo "$as_me: WARNING: output file \`$ofile' does not exist" >&2;}
+ fi
+
+ if test -z "$LTCC"; then
+ eval "`$SHELL ${ofile} --config | grep '^LTCC='`"
+ if test -z "$LTCC"; then
+ { echo "$as_me:$LINENO: WARNING: output file \`$ofile' does not look like a libtool script" >&5
+echo "$as_me: WARNING: output file \`$ofile' does not look like a libtool script" >&2;}
+ else
+ { echo "$as_me:$LINENO: WARNING: using \`LTCC=$LTCC', extracted from \`$ofile'" >&5
+echo "$as_me: WARNING: using \`LTCC=$LTCC', extracted from \`$ofile'" >&2;}
+ fi
+ fi
+ if test -z "$LTCFLAGS"; then
+ eval "`$SHELL ${ofile} --config | grep '^LTCFLAGS='`"
+ fi
+
+ # Extract list of available tagged configurations in $ofile.
+ # Note that this assumes the entire list is on one line.
+ available_tags=`grep "^available_tags=" "${ofile}" | $SED -e 's/available_tags=\(.*$\)/\1/' -e 's/\"//g'`
+
+ lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+ for tagname in $tagnames; do
+ IFS="$lt_save_ifs"
+ # Check whether tagname contains only valid characters
+ case `$echo "X$tagname" | $Xsed -e 's:[-_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890,/]::g'` in
+ "") ;;
+ *) { { echo "$as_me:$LINENO: error: invalid tag name: $tagname" >&5
+echo "$as_me: error: invalid tag name: $tagname" >&2;}
+ { (exit 1); exit 1; }; }
+ ;;
+ esac
+
+ if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$" < "${ofile}" > /dev/null
+ then
+ { { echo "$as_me:$LINENO: error: tag name \"$tagname\" already exists" >&5
+echo "$as_me: error: tag name \"$tagname\" already exists" >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+
+ # Update the list of available tags.
+ if test -n "$tagname"; then
+ echo appending configuration tag \"$tagname\" to $ofile
+
+ case $tagname in
+ CXX)
+ if test -n "$CXX" && ( test "X$CXX" != "Xno" &&
+ ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) ||
+ (test "X$CXX" != "Xg++"))) ; then
+ ac_ext=cc
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+
+
+
+archive_cmds_need_lc_CXX=no
+allow_undefined_flag_CXX=
+always_export_symbols_CXX=no
+archive_expsym_cmds_CXX=
+export_dynamic_flag_spec_CXX=
+hardcode_direct_CXX=no
+hardcode_libdir_flag_spec_CXX=
+hardcode_libdir_flag_spec_ld_CXX=
+hardcode_libdir_separator_CXX=
+hardcode_minus_L_CXX=no
+hardcode_shlibpath_var_CXX=unsupported
+hardcode_automatic_CXX=no
+module_cmds_CXX=
+module_expsym_cmds_CXX=
+link_all_deplibs_CXX=unknown
+old_archive_cmds_CXX=$old_archive_cmds
+no_undefined_flag_CXX=
+whole_archive_flag_spec_CXX=
+enable_shared_with_static_runtimes_CXX=no
+
+# Dependencies to place before and after the object being linked:
+predep_objects_CXX=
+postdep_objects_CXX=
+predeps_CXX=
+postdeps_CXX=
+compiler_lib_search_path_CXX=
+
+# Source file extension for C++ test sources.
+ac_ext=cpp
+
+# Object file extension for compiled C++ test sources.
+objext=o
+objext_CXX=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="int some_variable = 0;\n"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='int main(int, char *[]) { return(0); }\n'
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# If no C compiler flags were specified, use CFLAGS.
+LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+
+
+# save warnings/boilerplate of simple test code
+ac_outfile=conftest.$ac_objext
+printf "$lt_simple_compile_test_code" >conftest.$ac_ext
+eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_compiler_boilerplate=`cat conftest.err`
+$rm conftest*
+
+ac_outfile=conftest.$ac_objext
+printf "$lt_simple_link_test_code" >conftest.$ac_ext
+eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_linker_boilerplate=`cat conftest.err`
+$rm conftest*
+
+
+# Allow CC to be a program name with arguments.
+lt_save_CC=$CC
+lt_save_LD=$LD
+lt_save_GCC=$GCC
+GCC=$GXX
+lt_save_with_gnu_ld=$with_gnu_ld
+lt_save_path_LD=$lt_cv_path_LD
+if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then
+ lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx
+else
+ $as_unset lt_cv_prog_gnu_ld
+fi
+if test -n "${lt_cv_path_LDCXX+set}"; then
+ lt_cv_path_LD=$lt_cv_path_LDCXX
+else
+ $as_unset lt_cv_path_LD
+fi
+test -z "${LDCXX+set}" || LD=$LDCXX
+CC=${CXX-"c++"}
+compiler=$CC
+compiler_CXX=$CC
+for cc_temp in $compiler""; do
+ case $cc_temp in
+ compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
+ distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
+ \-*) ;;
+ *) break;;
+ esac
+done
+cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"`
+
+
+# We don't want -fno-exception wen compiling C++ code, so set the
+# no_builtin_flag separately
+if test "$GXX" = yes; then
+ lt_prog_compiler_no_builtin_flag_CXX=' -fno-builtin'
+else
+ lt_prog_compiler_no_builtin_flag_CXX=
+fi
+
+if test "$GXX" = yes; then
+ # Set up default GNU C++ configuration
+
+
+# Check whether --with-gnu-ld or --without-gnu-ld was given.
+if test "${with_gnu_ld+set}" = set; then
+ withval="$with_gnu_ld"
+ test "$withval" = no || with_gnu_ld=yes
+else
+ with_gnu_ld=no
+fi;
+ac_prog=ld
+if test "$GCC" = yes; then
+ # Check if gcc -print-prog-name=ld gives a path.
+ echo "$as_me:$LINENO: checking for ld used by $CC" >&5
+echo $ECHO_N "checking for ld used by $CC... $ECHO_C" >&6
+ case $host in
+ *-*-mingw*)
+ # gcc leaves a trailing carriage return which upsets mingw
+ ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
+ *)
+ ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
+ esac
+ case $ac_prog in
+ # Accept absolute paths.
+ [\\/]* | ?:[\\/]*)
+ re_direlt='/[^/][^/]*/\.\./'
+ # Canonicalize the pathname of ld
+ ac_prog=`echo $ac_prog| $SED 's%\\\\%/%g'`
+ while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do
+ ac_prog=`echo $ac_prog| $SED "s%$re_direlt%/%"`
+ done
+ test -z "$LD" && LD="$ac_prog"
+ ;;
+ "")
+ # If it fails, then pretend we aren't using GCC.
+ ac_prog=ld
+ ;;
+ *)
+ # If it is relative, then search for the first ld in PATH.
+ with_gnu_ld=unknown
+ ;;
+ esac
+elif test "$with_gnu_ld" = yes; then
+ echo "$as_me:$LINENO: checking for GNU ld" >&5
+echo $ECHO_N "checking for GNU ld... $ECHO_C" >&6
+else
+ echo "$as_me:$LINENO: checking for non-GNU ld" >&5
+echo $ECHO_N "checking for non-GNU ld... $ECHO_C" >&6
+fi
+if test "${lt_cv_path_LD+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -z "$LD"; then
+ lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+ for ac_dir in $PATH; do
+ IFS="$lt_save_ifs"
+ test -z "$ac_dir" && ac_dir=.
+ if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+ lt_cv_path_LD="$ac_dir/$ac_prog"
+ # Check to see if the program is GNU ld. I'd rather use --version,
+ # but apparently some variants of GNU ld only accept -v.
+ # Break only if it was the GNU/non-GNU ld that we prefer.
+ case `"$lt_cv_path_LD" -v 2>&1 </dev/null` in
+ *GNU* | *'with BFD'*)
+ test "$with_gnu_ld" != no && break
+ ;;
+ *)
+ test "$with_gnu_ld" != yes && break
+ ;;
+ esac
+ fi
+ done
+ IFS="$lt_save_ifs"
+else
+ lt_cv_path_LD="$LD" # Let the user override the test with a path.
+fi
+fi
+
+LD="$lt_cv_path_LD"
+if test -n "$LD"; then
+ echo "$as_me:$LINENO: result: $LD" >&5
+echo "${ECHO_T}$LD" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+test -z "$LD" && { { echo "$as_me:$LINENO: error: no acceptable ld found in \$PATH" >&5
+echo "$as_me: error: no acceptable ld found in \$PATH" >&2;}
+ { (exit 1); exit 1; }; }
+echo "$as_me:$LINENO: checking if the linker ($LD) is GNU ld" >&5
+echo $ECHO_N "checking if the linker ($LD) is GNU ld... $ECHO_C" >&6
+if test "${lt_cv_prog_gnu_ld+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ # I'd rather use --version here, but apparently some GNU lds only accept -v.
+case `$LD -v 2>&1 </dev/null` in
+*GNU* | *'with BFD'*)
+ lt_cv_prog_gnu_ld=yes
+ ;;
+*)
+ lt_cv_prog_gnu_ld=no
+ ;;
+esac
+fi
+echo "$as_me:$LINENO: result: $lt_cv_prog_gnu_ld" >&5
+echo "${ECHO_T}$lt_cv_prog_gnu_ld" >&6
+with_gnu_ld=$lt_cv_prog_gnu_ld
+
+
+
+ # Check if GNU C++ uses GNU ld as the underlying linker, since the
+ # archiving commands below assume that GNU ld is being used.
+ if test "$with_gnu_ld" = yes; then
+ archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+
+ hardcode_libdir_flag_spec_CXX='${wl}--rpath ${wl}$libdir'
+ export_dynamic_flag_spec_CXX='${wl}--export-dynamic'
+
+ # If archive_cmds runs LD, not CC, wlarc should be empty
+ # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to
+ # investigate it a little bit more. (MM)
+ wlarc='${wl}'
+
+ # ancient GNU ld didn't support --whole-archive et. al.
+ if eval "`$CC -print-prog-name=ld` --help 2>&1" | \
+ grep 'no-whole-archive' > /dev/null; then
+ whole_archive_flag_spec_CXX="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+ else
+ whole_archive_flag_spec_CXX=
+ fi
+ else
+ with_gnu_ld=no
+ wlarc=
+
+ # A generic and very simple default shared library creation
+ # command for GNU C++ for the case where it uses the native
+ # linker, instead of GNU ld. If possible, this setting should
+ # overridden to take advantage of the native linker features on
+ # the platform it is being used on.
+ archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
+ fi
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"'
+
+else
+ GXX=no
+ with_gnu_ld=no
+ wlarc=
+fi
+
+# PORTME: fill in a description of your system's C++ link characteristics
+echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5
+echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6
+ld_shlibs_CXX=yes
+case $host_os in
+ aix3*)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ aix4* | aix5*)
+ if test "$host_cpu" = ia64; then
+ # On IA64, the linker does run time linking by default, so we don't
+ # have to do anything special.
+ aix_use_runtimelinking=no
+ exp_sym_flag='-Bexport'
+ no_entry_flag=""
+ else
+ aix_use_runtimelinking=no
+
+ # Test if we are trying to use run time linking or normal
+ # AIX style linking. If -brtl is somewhere in LDFLAGS, we
+ # need to do runtime linking.
+ case $host_os in aix4.[23]|aix4.[23].*|aix5*)
+ for ld_flag in $LDFLAGS; do
+ case $ld_flag in
+ *-brtl*)
+ aix_use_runtimelinking=yes
+ break
+ ;;
+ esac
+ done
+ ;;
+ esac
+
+ exp_sym_flag='-bexport'
+ no_entry_flag='-bnoentry'
+ fi
+
+ # When large executables or shared objects are built, AIX ld can
+ # have problems creating the table of contents. If linking a library
+ # or program results in "error TOC overflow" add -mminimal-toc to
+ # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not
+ # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+ archive_cmds_CXX=''
+ hardcode_direct_CXX=yes
+ hardcode_libdir_separator_CXX=':'
+ link_all_deplibs_CXX=yes
+
+ if test "$GXX" = yes; then
+ case $host_os in aix4.[012]|aix4.[012].*)
+ # We only want to do this on AIX 4.2 and lower, the check
+ # below for broken collect2 doesn't work under 4.3+
+ collect2name=`${CC} -print-prog-name=collect2`
+ if test -f "$collect2name" && \
+ strings "$collect2name" | grep resolve_lib_name >/dev/null
+ then
+ # We have reworked collect2
+ hardcode_direct_CXX=yes
+ else
+ # We have old collect2
+ hardcode_direct_CXX=unsupported
+ # It fails to find uninstalled libraries when the uninstalled
+ # path is not listed in the libpath. Setting hardcode_minus_L
+ # to unsupported forces relinking
+ hardcode_minus_L_CXX=yes
+ hardcode_libdir_flag_spec_CXX='-L$libdir'
+ hardcode_libdir_separator_CXX=
+ fi
+ ;;
+ esac
+ shared_flag='-shared'
+ if test "$aix_use_runtimelinking" = yes; then
+ shared_flag="$shared_flag "'${wl}-G'
+ fi
+ else
+ # not using gcc
+ if test "$host_cpu" = ia64; then
+ # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+ # chokes on -Wl,-G. The following line is correct:
+ shared_flag='-G'
+ else
+ if test "$aix_use_runtimelinking" = yes; then
+ shared_flag='${wl}-G'
+ else
+ shared_flag='${wl}-bM:SRE'
+ fi
+ fi
+ fi
+
+ # It seems that -bexpall does not export symbols beginning with
+ # underscore (_), so it is better to generate a list of symbols to export.
+ always_export_symbols_CXX=yes
+ if test "$aix_use_runtimelinking" = yes; then
+ # Warning - without using the other runtime loading flags (-brtl),
+ # -berok will link without error, but may produce a broken library.
+ allow_undefined_flag_CXX='-berok'
+ # Determine the default libpath from the value encoded in an empty executable.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_cxx_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+
+aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`
+# Check for a 64-bit object if we didn't find anything.
+if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`; fi
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+
+ hardcode_libdir_flag_spec_CXX='${wl}-blibpath:$libdir:'"$aix_libpath"
+
+ archive_expsym_cmds_CXX="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+ else
+ if test "$host_cpu" = ia64; then
+ hardcode_libdir_flag_spec_CXX='${wl}-R $libdir:/usr/lib:/lib'
+ allow_undefined_flag_CXX="-z nodefs"
+ archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols"
+ else
+ # Determine the default libpath from the value encoded in an empty executable.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_cxx_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+
+aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`
+# Check for a 64-bit object if we didn't find anything.
+if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`; fi
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+
+ hardcode_libdir_flag_spec_CXX='${wl}-blibpath:$libdir:'"$aix_libpath"
+ # Warning - without using the other run time loading flags,
+ # -berok will link without error, but may produce a broken library.
+ no_undefined_flag_CXX=' ${wl}-bernotok'
+ allow_undefined_flag_CXX=' ${wl}-berok'
+ # Exported symbols can be pulled into shared objects from archives
+ whole_archive_flag_spec_CXX='$convenience'
+ archive_cmds_need_lc_CXX=yes
+ # This is similar to how AIX traditionally builds its shared libraries.
+ archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
+ fi
+ fi
+ ;;
+
+ beos*)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ allow_undefined_flag_CXX=unsupported
+ # Joseph Beckenbach <jrb3 at best.com> says some releases of gcc
+ # support --undefined. This deserves some investigation. FIXME
+ archive_cmds_CXX='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ else
+ ld_shlibs_CXX=no
+ fi
+ ;;
+
+ chorus*)
+ case $cc_basename in
+ *)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ esac
+ ;;
+
+ cygwin* | mingw* | pw32*)
+ # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, CXX) is actually meaningless,
+ # as there is no search path for DLLs.
+ hardcode_libdir_flag_spec_CXX='-L$libdir'
+ allow_undefined_flag_CXX=unsupported
+ always_export_symbols_CXX=no
+ enable_shared_with_static_runtimes_CXX=yes
+
+ if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then
+ archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+ # If the export-symbols file already is a .def file (1st line
+ # is EXPORTS), use it as is; otherwise, prepend...
+ archive_expsym_cmds_CXX='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
+ cp $export_symbols $output_objdir/$soname.def;
+ else
+ echo EXPORTS > $output_objdir/$soname.def;
+ cat $export_symbols >> $output_objdir/$soname.def;
+ fi~
+ $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+ else
+ ld_shlibs_CXX=no
+ fi
+ ;;
+ darwin* | rhapsody*)
+ case $host_os in
+ rhapsody* | darwin1.[012])
+ allow_undefined_flag_CXX='${wl}-undefined ${wl}suppress'
+ ;;
+ *) # Darwin 1.3 on
+ if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then
+ allow_undefined_flag_CXX='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
+ else
+ case ${MACOSX_DEPLOYMENT_TARGET} in
+ 10.[012])
+ allow_undefined_flag_CXX='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
+ ;;
+ 10.*)
+ allow_undefined_flag_CXX='${wl}-undefined ${wl}dynamic_lookup'
+ ;;
+ esac
+ fi
+ ;;
+ esac
+ archive_cmds_need_lc_CXX=no
+ hardcode_direct_CXX=no
+ hardcode_automatic_CXX=yes
+ hardcode_shlibpath_var_CXX=unsupported
+ whole_archive_flag_spec_CXX=''
+ link_all_deplibs_CXX=yes
+
+ if test "$GXX" = yes ; then
+ lt_int_apple_cc_single_mod=no
+ output_verbose_link_cmd='echo'
+ if $CC -dumpspecs 2>&1 | $EGREP 'single_module' >/dev/null ; then
+ lt_int_apple_cc_single_mod=yes
+ fi
+ if test "X$lt_int_apple_cc_single_mod" = Xyes ; then
+ archive_cmds_CXX='$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring'
+ else
+ archive_cmds_CXX='$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring'
+ fi
+ module_cmds_CXX='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
+ # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
+ if test "X$lt_int_apple_cc_single_mod" = Xyes ; then
+ archive_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ else
+ archive_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ fi
+ module_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ else
+ case $cc_basename in
+ xlc*)
+ output_verbose_link_cmd='echo'
+ archive_cmds_CXX='$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring'
+ module_cmds_CXX='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
+ # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
+ archive_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ module_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ ;;
+ *)
+ ld_shlibs_CXX=no
+ ;;
+ esac
+ fi
+ ;;
+
+ dgux*)
+ case $cc_basename in
+ ec++*)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ ghcx*)
+ # Green Hills C++ Compiler
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ *)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ esac
+ ;;
+ freebsd[12]*)
+ # C++ shared libraries reported to be fairly broken before switch to ELF
+ ld_shlibs_CXX=no
+ ;;
+ freebsd-elf*)
+ archive_cmds_need_lc_CXX=no
+ ;;
+ freebsd* | kfreebsd*-gnu | dragonfly*)
+ # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF
+ # conventions
+ ld_shlibs_CXX=yes
+ ;;
+ gnu*)
+ ;;
+ hpux9*)
+ hardcode_libdir_flag_spec_CXX='${wl}+b ${wl}$libdir'
+ hardcode_libdir_separator_CXX=:
+ export_dynamic_flag_spec_CXX='${wl}-E'
+ hardcode_direct_CXX=yes
+ hardcode_minus_L_CXX=yes # Not in the search PATH,
+ # but as the default
+ # location of the library.
+
+ case $cc_basename in
+ CC*)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ aCC*)
+ archive_cmds_CXX='$rm $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "[-]L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+ ;;
+ *)
+ if test "$GXX" = yes; then
+ archive_cmds_CXX='$rm $output_objdir/$soname~$CC -shared -nostdlib -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+ else
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ fi
+ ;;
+ esac
+ ;;
+ hpux10*|hpux11*)
+ if test $with_gnu_ld = no; then
+ hardcode_libdir_flag_spec_CXX='${wl}+b ${wl}$libdir'
+ hardcode_libdir_separator_CXX=:
+
+ case $host_cpu in
+ hppa*64*|ia64*)
+ hardcode_libdir_flag_spec_ld_CXX='+b $libdir'
+ ;;
+ *)
+ export_dynamic_flag_spec_CXX='${wl}-E'
+ ;;
+ esac
+ fi
+ case $host_cpu in
+ hppa*64*|ia64*)
+ hardcode_direct_CXX=no
+ hardcode_shlibpath_var_CXX=no
+ ;;
+ *)
+ hardcode_direct_CXX=yes
+ hardcode_minus_L_CXX=yes # Not in the search PATH,
+ # but as the default
+ # location of the library.
+ ;;
+ esac
+
+ case $cc_basename in
+ CC*)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ aCC*)
+ case $host_cpu in
+ hppa*64*)
+ archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ ia64*)
+ archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ *)
+ archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ esac
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+ ;;
+ *)
+ if test "$GXX" = yes; then
+ if test $with_gnu_ld = no; then
+ case $host_cpu in
+ hppa*64*)
+ archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ ia64*)
+ archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ *)
+ archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ esac
+ fi
+ else
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ fi
+ ;;
+ esac
+ ;;
+ interix3*)
+ hardcode_direct_CXX=no
+ hardcode_shlibpath_var_CXX=no
+ hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir'
+ export_dynamic_flag_spec_CXX='${wl}-E'
+ # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
+ # Instead, shared libraries are loaded at an image base (0x10000000 by
+ # default) and relocated if they conflict, which is a slow very memory
+ # consuming and fragmenting process. To avoid this, we pick a random,
+ # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
+ # time. Moving up from 0x10000000 also allows more sbrk(2) space.
+ archive_cmds_CXX='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+ archive_expsym_cmds_CXX='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+ ;;
+ irix5* | irix6*)
+ case $cc_basename in
+ CC*)
+ # SGI C++
+ archive_cmds_CXX='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+
+ # Archives containing C++ object files must be created using
+ # "CC -ar", where "CC" is the IRIX C++ compiler. This is
+ # necessary to make sure instantiated templates are included
+ # in the archive.
+ old_archive_cmds_CXX='$CC -ar -WR,-u -o $oldlib $oldobjs'
+ ;;
+ *)
+ if test "$GXX" = yes; then
+ if test "$with_gnu_ld" = no; then
+ archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ else
+ archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` -o $lib'
+ fi
+ fi
+ link_all_deplibs_CXX=yes
+ ;;
+ esac
+ hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator_CXX=:
+ ;;
+ linux*)
+ case $cc_basename in
+ KCC*)
+ # Kuck and Associates, Inc. (KAI) C++ Compiler
+
+ # KCC will only create a shared library if the output file
+ # ends with ".so" (or ".sl" for HP-UX), so rename the library
+ # to its proper name (with version) after linking.
+ archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
+ archive_expsym_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib'
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | grep "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+
+ hardcode_libdir_flag_spec_CXX='${wl}--rpath,$libdir'
+ export_dynamic_flag_spec_CXX='${wl}--export-dynamic'
+
+ # Archives containing C++ object files must be created using
+ # "CC -Bstatic", where "CC" is the KAI C++ compiler.
+ old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs'
+ ;;
+ icpc*)
+ # Intel C++
+ with_gnu_ld=yes
+ # version 8.0 and above of icpc choke on multiply defined symbols
+ # if we add $predep_objects and $postdep_objects, however 7.1 and
+ # earlier do not add the objects themselves.
+ case `$CC -V 2>&1` in
+ *"Version 7."*)
+ archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ ;;
+ *) # Version 8.0 or newer
+ tmp_idyn=
+ case $host_cpu in
+ ia64*) tmp_idyn=' -i_dynamic';;
+ esac
+ archive_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ ;;
+ esac
+ archive_cmds_need_lc_CXX=no
+ hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir'
+ export_dynamic_flag_spec_CXX='${wl}--export-dynamic'
+ whole_archive_flag_spec_CXX='${wl}--whole-archive$convenience ${wl}--no-whole-archive'
+ ;;
+ pgCC*)
+ # Portland Group C++ compiler
+ archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib'
+ archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib'
+
+ hardcode_libdir_flag_spec_CXX='${wl}--rpath ${wl}$libdir'
+ export_dynamic_flag_spec_CXX='${wl}--export-dynamic'
+ whole_archive_flag_spec_CXX='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
+ ;;
+ cxx*)
+ # Compaq C++
+ archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols'
+
+ runpath_var=LD_RUN_PATH
+ hardcode_libdir_flag_spec_CXX='-rpath $libdir'
+ hardcode_libdir_separator_CXX=:
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+ ;;
+ esac
+ ;;
+ lynxos*)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ m88k*)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ mvs*)
+ case $cc_basename in
+ cxx*)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ *)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ esac
+ ;;
+ netbsd*)
+ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+ archive_cmds_CXX='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags'
+ wlarc=
+ hardcode_libdir_flag_spec_CXX='-R$libdir'
+ hardcode_direct_CXX=yes
+ hardcode_shlibpath_var_CXX=no
+ fi
+ # Workaround some broken pre-1.5 toolchains
+ output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"'
+ ;;
+ openbsd2*)
+ # C++ shared libraries are fairly broken
+ ld_shlibs_CXX=no
+ ;;
+ openbsd*)
+ hardcode_direct_CXX=yes
+ hardcode_shlibpath_var_CXX=no
+ archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
+ hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir'
+ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib'
+ export_dynamic_flag_spec_CXX='${wl}-E'
+ whole_archive_flag_spec_CXX="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+ fi
+ output_verbose_link_cmd='echo'
+ ;;
+ osf3*)
+ case $cc_basename in
+ KCC*)
+ # Kuck and Associates, Inc. (KAI) C++ Compiler
+
+ # KCC will only create a shared library if the output file
+ # ends with ".so" (or ".sl" for HP-UX), so rename the library
+ # to its proper name (with version) after linking.
+ archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
+
+ hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir'
+ hardcode_libdir_separator_CXX=:
+
+ # Archives containing C++ object files must be created using
+ # "CC -Bstatic", where "CC" is the KAI C++ compiler.
+ old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs'
+
+ ;;
+ RCC*)
+ # Rational C++ 2.4.1
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ cxx*)
+ allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*'
+ archive_cmds_CXX='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && echo ${wl}-set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+
+ hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator_CXX=:
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+ ;;
+ *)
+ if test "$GXX" = yes && test "$with_gnu_ld" = no; then
+ allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*'
+ archive_cmds_CXX='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+
+ hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator_CXX=:
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"'
+
+ else
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ fi
+ ;;
+ esac
+ ;;
+ osf4* | osf5*)
+ case $cc_basename in
+ KCC*)
+ # Kuck and Associates, Inc. (KAI) C++ Compiler
+
+ # KCC will only create a shared library if the output file
+ # ends with ".so" (or ".sl" for HP-UX), so rename the library
+ # to its proper name (with version) after linking.
+ archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
+
+ hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir'
+ hardcode_libdir_separator_CXX=:
+
+ # Archives containing C++ object files must be created using
+ # the KAI C++ compiler.
+ old_archive_cmds_CXX='$CC -o $oldlib $oldobjs'
+ ;;
+ RCC*)
+ # Rational C++ 2.4.1
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ cxx*)
+ allow_undefined_flag_CXX=' -expect_unresolved \*'
+ archive_cmds_CXX='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+ archive_expsym_cmds_CXX='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~
+ echo "-hidden">> $lib.exp~
+ $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname -Wl,-input -Wl,$lib.exp `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~
+ $rm $lib.exp'
+
+ hardcode_libdir_flag_spec_CXX='-rpath $libdir'
+ hardcode_libdir_separator_CXX=:
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+ ;;
+ *)
+ if test "$GXX" = yes && test "$with_gnu_ld" = no; then
+ allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*'
+ archive_cmds_CXX='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+
+ hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator_CXX=:
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"'
+
+ else
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ fi
+ ;;
+ esac
+ ;;
+ psos*)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ sunos4*)
+ case $cc_basename in
+ CC*)
+ # Sun C++ 4.x
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ lcc*)
+ # Lucid
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ *)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ esac
+ ;;
+ solaris*)
+ case $cc_basename in
+ CC*)
+ # Sun C++ 4.2, 5.x and Centerline C++
+ archive_cmds_need_lc_CXX=yes
+ no_undefined_flag_CXX=' -zdefs'
+ archive_cmds_CXX='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ archive_expsym_cmds_CXX='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+ $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp'
+
+ hardcode_libdir_flag_spec_CXX='-R$libdir'
+ hardcode_shlibpath_var_CXX=no
+ case $host_os in
+ solaris2.[0-5] | solaris2.[0-5].*) ;;
+ *)
+ # The C++ compiler is used as linker so we must use $wl
+ # flag to pass the commands to the underlying system
+ # linker. We must also pass each convience library through
+ # to the system linker between allextract/defaultextract.
+ # The C++ compiler will combine linker options so we
+ # cannot just pass the convience library names through
+ # without $wl.
+ # Supported since Solaris 2.6 (maybe 2.5.1?)
+ whole_archive_flag_spec_CXX='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract'
+ ;;
+ esac
+ link_all_deplibs_CXX=yes
+
+ output_verbose_link_cmd='echo'
+
+ # Archives containing C++ object files must be created using
+ # "CC -xar", where "CC" is the Sun C++ compiler. This is
+ # necessary to make sure instantiated templates are included
+ # in the archive.
+ old_archive_cmds_CXX='$CC -xar -o $oldlib $oldobjs'
+ ;;
+ gcx*)
+ # Green Hills C++ Compiler
+ archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
+
+ # The C++ compiler must be used to create the archive.
+ old_archive_cmds_CXX='$CC $LDFLAGS -archive -o $oldlib $oldobjs'
+ ;;
+ *)
+ # GNU C++ compiler with Solaris linker
+ if test "$GXX" = yes && test "$with_gnu_ld" = no; then
+ no_undefined_flag_CXX=' ${wl}-z ${wl}defs'
+ if $CC --version | grep -v '^2\.7' > /dev/null; then
+ archive_cmds_CXX='$CC -shared -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
+ archive_expsym_cmds_CXX='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+ $CC -shared -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp'
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ output_verbose_link_cmd="$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\""
+ else
+ # g++ 2.7 appears to require `-G' NOT `-shared' on this
+ # platform.
+ archive_cmds_CXX='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
+ archive_expsym_cmds_CXX='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+ $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp'
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ output_verbose_link_cmd="$CC -G $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\""
+ fi
+
+ hardcode_libdir_flag_spec_CXX='${wl}-R $wl$libdir'
+ fi
+ ;;
+ esac
+ ;;
+ sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*)
+ no_undefined_flag_CXX='${wl}-z,text'
+ archive_cmds_need_lc_CXX=no
+ hardcode_shlibpath_var_CXX=no
+ runpath_var='LD_RUN_PATH'
+
+ case $cc_basename in
+ CC*)
+ archive_cmds_CXX='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds_CXX='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ *)
+ archive_cmds_CXX='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds_CXX='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ esac
+ ;;
+ sysv5* | sco3.2v5* | sco5v6*)
+ # Note: We can NOT use -z defs as we might desire, because we do not
+ # link with -lc, and that would cause any symbols used from libc to
+ # always be unresolved, which means just about no library would
+ # ever link correctly. If we're not using GNU ld we use -z text
+ # though, which does catch some bad symbols but isn't as heavy-handed
+ # as -z defs.
+ # For security reasons, it is highly recommended that you always
+ # use absolute paths for naming shared libraries, and exclude the
+ # DT_RUNPATH tag from executables and libraries. But doing so
+ # requires that you compile everything twice, which is a pain.
+ # So that behaviour is only enabled if SCOABSPATH is set to a
+ # non-empty value in the environment. Most likely only useful for
+ # creating official distributions of packages.
+ # This is a hack until libtool officially supports absolute path
+ # names for shared libraries.
+ no_undefined_flag_CXX='${wl}-z,text'
+ allow_undefined_flag_CXX='${wl}-z,nodefs'
+ archive_cmds_need_lc_CXX=no
+ hardcode_shlibpath_var_CXX=no
+ hardcode_libdir_flag_spec_CXX='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`'
+ hardcode_libdir_separator_CXX=':'
+ link_all_deplibs_CXX=yes
+ export_dynamic_flag_spec_CXX='${wl}-Bexport'
+ runpath_var='LD_RUN_PATH'
+
+ case $cc_basename in
+ CC*)
+ archive_cmds_CXX='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds_CXX='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ *)
+ archive_cmds_CXX='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds_CXX='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ esac
+ ;;
+ tandem*)
+ case $cc_basename in
+ NCC*)
+ # NonStop-UX NCC 3.20
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ *)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ esac
+ ;;
+ vxworks*)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ *)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+esac
+echo "$as_me:$LINENO: result: $ld_shlibs_CXX" >&5
+echo "${ECHO_T}$ld_shlibs_CXX" >&6
+test "$ld_shlibs_CXX" = no && can_build_shared=no
+
+GCC_CXX="$GXX"
+LD_CXX="$LD"
+
+
+cat > conftest.$ac_ext <<EOF
+class Foo
+{
+public:
+ Foo (void) { a = 0; }
+private:
+ int a;
+};
+EOF
+
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ # Parse the compiler output and extract the necessary
+ # objects, libraries and library flags.
+
+ # Sentinel used to keep track of whether or not we are before
+ # the conftest object file.
+ pre_test_object_deps_done=no
+
+ # The `*' in the case matches for architectures that use `case' in
+ # $output_verbose_cmd can trigger glob expansion during the loop
+ # eval without this substitution.
+ output_verbose_link_cmd=`$echo "X$output_verbose_link_cmd" | $Xsed -e "$no_glob_subst"`
+
+ for p in `eval $output_verbose_link_cmd`; do
+ case $p in
+
+ -L* | -R* | -l*)
+ # Some compilers place space between "-{L,R}" and the path.
+ # Remove the space.
+ if test $p = "-L" \
+ || test $p = "-R"; then
+ prev=$p
+ continue
+ else
+ prev=
+ fi
+
+ if test "$pre_test_object_deps_done" = no; then
+ case $p in
+ -L* | -R*)
+ # Internal compiler library paths should come after those
+ # provided the user. The postdeps already come after the
+ # user supplied libs so there is no need to process them.
+ if test -z "$compiler_lib_search_path_CXX"; then
+ compiler_lib_search_path_CXX="${prev}${p}"
+ else
+ compiler_lib_search_path_CXX="${compiler_lib_search_path_CXX} ${prev}${p}"
+ fi
+ ;;
+ # The "-l" case would never come before the object being
+ # linked, so don't bother handling this case.
+ esac
+ else
+ if test -z "$postdeps_CXX"; then
+ postdeps_CXX="${prev}${p}"
+ else
+ postdeps_CXX="${postdeps_CXX} ${prev}${p}"
+ fi
+ fi
+ ;;
+
+ *.$objext)
+ # This assumes that the test object file only shows up
+ # once in the compiler output.
+ if test "$p" = "conftest.$objext"; then
+ pre_test_object_deps_done=yes
+ continue
+ fi
+
+ if test "$pre_test_object_deps_done" = no; then
+ if test -z "$predep_objects_CXX"; then
+ predep_objects_CXX="$p"
+ else
+ predep_objects_CXX="$predep_objects_CXX $p"
+ fi
+ else
+ if test -z "$postdep_objects_CXX"; then
+ postdep_objects_CXX="$p"
+ else
+ postdep_objects_CXX="$postdep_objects_CXX $p"
+ fi
+ fi
+ ;;
+
+ *) ;; # Ignore the rest.
+
+ esac
+ done
+
+ # Clean up.
+ rm -f a.out a.exe
+else
+ echo "libtool.m4: error: problem compiling CXX test program"
+fi
+
+$rm -f confest.$objext
+
+# PORTME: override above test on systems where it is broken
+case $host_os in
+interix3*)
+ # Interix 3.5 installs completely hosed .la files for C++, so rather than
+ # hack all around it, let's just trust "g++" to DTRT.
+ predep_objects_CXX=
+ postdep_objects_CXX=
+ postdeps_CXX=
+ ;;
+
+solaris*)
+ case $cc_basename in
+ CC*)
+ # Adding this requires a known-good setup of shared libraries for
+ # Sun compiler versions before 5.6, else PIC objects from an old
+ # archive will be linked into the output, leading to subtle bugs.
+ postdeps_CXX='-lCstd -lCrun'
+ ;;
+ esac
+ ;;
+esac
+
+
+case " $postdeps_CXX " in
+*" -lc "*) archive_cmds_need_lc_CXX=no ;;
+esac
+
+lt_prog_compiler_wl_CXX=
+lt_prog_compiler_pic_CXX=
+lt_prog_compiler_static_CXX=
+
+echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5
+echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6
+
+ # C++ specific cases for pic, static, wl, etc.
+ if test "$GXX" = yes; then
+ lt_prog_compiler_wl_CXX='-Wl,'
+ lt_prog_compiler_static_CXX='-static'
+
+ case $host_os in
+ aix*)
+ # All AIX code is PIC.
+ if test "$host_cpu" = ia64; then
+ # AIX 5 now supports IA64 processor
+ lt_prog_compiler_static_CXX='-Bstatic'
+ fi
+ ;;
+ amigaos*)
+ # FIXME: we need at least 68020 code to build shared libraries, but
+ # adding the `-m68020' flag to GCC prevents building anything better,
+ # like `-m68040'.
+ lt_prog_compiler_pic_CXX='-m68020 -resident32 -malways-restore-a4'
+ ;;
+ beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+ # PIC is the default for these OSes.
+ ;;
+ mingw* | os2* | pw32*)
+ # This hack is so that the source file can tell whether it is being
+ # built for inclusion in a dll (and should export symbols for example).
+ lt_prog_compiler_pic_CXX='-DDLL_EXPORT'
+ ;;
+ darwin* | rhapsody*)
+ # PIC is the default on this platform
+ # Common symbols not allowed in MH_DYLIB files
+ lt_prog_compiler_pic_CXX='-fno-common'
+ ;;
+ *djgpp*)
+ # DJGPP does not support shared libraries at all
+ lt_prog_compiler_pic_CXX=
+ ;;
+ interix3*)
+ # Interix 3.x gcc -fpic/-fPIC options generate broken code.
+ # Instead, we relocate shared libraries at runtime.
+ ;;
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ lt_prog_compiler_pic_CXX=-Kconform_pic
+ fi
+ ;;
+ hpux*)
+ # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+ # not for PA HP-UX.
+ case $host_cpu in
+ hppa*64*|ia64*)
+ ;;
+ *)
+ lt_prog_compiler_pic_CXX='-fPIC'
+ ;;
+ esac
+ ;;
+ *)
+ lt_prog_compiler_pic_CXX='-fPIC'
+ ;;
+ esac
+ else
+ case $host_os in
+ aix4* | aix5*)
+ # All AIX code is PIC.
+ if test "$host_cpu" = ia64; then
+ # AIX 5 now supports IA64 processor
+ lt_prog_compiler_static_CXX='-Bstatic'
+ else
+ lt_prog_compiler_static_CXX='-bnso -bI:/lib/syscalls.exp'
+ fi
+ ;;
+ chorus*)
+ case $cc_basename in
+ cxch68*)
+ # Green Hills C++ Compiler
+ # _LT_AC_TAGVAR(lt_prog_compiler_static, CXX)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a"
+ ;;
+ esac
+ ;;
+ darwin*)
+ # PIC is the default on this platform
+ # Common symbols not allowed in MH_DYLIB files
+ case $cc_basename in
+ xlc*)
+ lt_prog_compiler_pic_CXX='-qnocommon'
+ lt_prog_compiler_wl_CXX='-Wl,'
+ ;;
+ esac
+ ;;
+ dgux*)
+ case $cc_basename in
+ ec++*)
+ lt_prog_compiler_pic_CXX='-KPIC'
+ ;;
+ ghcx*)
+ # Green Hills C++ Compiler
+ lt_prog_compiler_pic_CXX='-pic'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ freebsd* | kfreebsd*-gnu | dragonfly*)
+ # FreeBSD uses GNU C++
+ ;;
+ hpux9* | hpux10* | hpux11*)
+ case $cc_basename in
+ CC*)
+ lt_prog_compiler_wl_CXX='-Wl,'
+ lt_prog_compiler_static_CXX='${wl}-a ${wl}archive'
+ if test "$host_cpu" != ia64; then
+ lt_prog_compiler_pic_CXX='+Z'
+ fi
+ ;;
+ aCC*)
+ lt_prog_compiler_wl_CXX='-Wl,'
+ lt_prog_compiler_static_CXX='${wl}-a ${wl}archive'
+ case $host_cpu in
+ hppa*64*|ia64*)
+ # +Z the default
+ ;;
+ *)
+ lt_prog_compiler_pic_CXX='+Z'
+ ;;
+ esac
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ interix*)
+ # This is c89, which is MS Visual C++ (no shared libs)
+ # Anyone wants to do a port?
+ ;;
+ irix5* | irix6* | nonstopux*)
+ case $cc_basename in
+ CC*)
+ lt_prog_compiler_wl_CXX='-Wl,'
+ lt_prog_compiler_static_CXX='-non_shared'
+ # CC pic flag -KPIC is the default.
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ linux*)
+ case $cc_basename in
+ KCC*)
+ # KAI C++ Compiler
+ lt_prog_compiler_wl_CXX='--backend -Wl,'
+ lt_prog_compiler_pic_CXX='-fPIC'
+ ;;
+ icpc* | ecpc*)
+ # Intel C++
+ lt_prog_compiler_wl_CXX='-Wl,'
+ lt_prog_compiler_pic_CXX='-KPIC'
+ lt_prog_compiler_static_CXX='-static'
+ ;;
+ pgCC*)
+ # Portland Group C++ compiler.
+ lt_prog_compiler_wl_CXX='-Wl,'
+ lt_prog_compiler_pic_CXX='-fpic'
+ lt_prog_compiler_static_CXX='-Bstatic'
+ ;;
+ cxx*)
+ # Compaq C++
+ # Make sure the PIC flag is empty. It appears that all Alpha
+ # Linux and Compaq Tru64 Unix objects are PIC.
+ lt_prog_compiler_pic_CXX=
+ lt_prog_compiler_static_CXX='-non_shared'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ lynxos*)
+ ;;
+ m88k*)
+ ;;
+ mvs*)
+ case $cc_basename in
+ cxx*)
+ lt_prog_compiler_pic_CXX='-W c,exportall'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ netbsd*)
+ ;;
+ osf3* | osf4* | osf5*)
+ case $cc_basename in
+ KCC*)
+ lt_prog_compiler_wl_CXX='--backend -Wl,'
+ ;;
+ RCC*)
+ # Rational C++ 2.4.1
+ lt_prog_compiler_pic_CXX='-pic'
+ ;;
+ cxx*)
+ # Digital/Compaq C++
+ lt_prog_compiler_wl_CXX='-Wl,'
+ # Make sure the PIC flag is empty. It appears that all Alpha
+ # Linux and Compaq Tru64 Unix objects are PIC.
+ lt_prog_compiler_pic_CXX=
+ lt_prog_compiler_static_CXX='-non_shared'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ psos*)
+ ;;
+ solaris*)
+ case $cc_basename in
+ CC*)
+ # Sun C++ 4.2, 5.x and Centerline C++
+ lt_prog_compiler_pic_CXX='-KPIC'
+ lt_prog_compiler_static_CXX='-Bstatic'
+ lt_prog_compiler_wl_CXX='-Qoption ld '
+ ;;
+ gcx*)
+ # Green Hills C++ Compiler
+ lt_prog_compiler_pic_CXX='-PIC'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ sunos4*)
+ case $cc_basename in
+ CC*)
+ # Sun C++ 4.x
+ lt_prog_compiler_pic_CXX='-pic'
+ lt_prog_compiler_static_CXX='-Bstatic'
+ ;;
+ lcc*)
+ # Lucid
+ lt_prog_compiler_pic_CXX='-pic'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ tandem*)
+ case $cc_basename in
+ NCC*)
+ # NonStop-UX NCC 3.20
+ lt_prog_compiler_pic_CXX='-KPIC'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
+ case $cc_basename in
+ CC*)
+ lt_prog_compiler_wl_CXX='-Wl,'
+ lt_prog_compiler_pic_CXX='-KPIC'
+ lt_prog_compiler_static_CXX='-Bstatic'
+ ;;
+ esac
+ ;;
+ vxworks*)
+ ;;
+ *)
+ lt_prog_compiler_can_build_shared_CXX=no
+ ;;
+ esac
+ fi
+
+echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_CXX" >&5
+echo "${ECHO_T}$lt_prog_compiler_pic_CXX" >&6
+
+#
+# Check to make sure the PIC flag actually works.
+#
+if test -n "$lt_prog_compiler_pic_CXX"; then
+
+echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works" >&5
+echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works... $ECHO_C" >&6
+if test "${lt_prog_compiler_pic_works_CXX+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ lt_prog_compiler_pic_works_CXX=no
+ ac_outfile=conftest.$ac_objext
+ printf "$lt_simple_compile_test_code" > conftest.$ac_ext
+ lt_compiler_flag="$lt_prog_compiler_pic_CXX -DPIC"
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ # The option is referenced via a variable to avoid confusing sed.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:18962: $lt_compile\"" >&5)
+ (eval "$lt_compile" 2>conftest.err)
+ ac_status=$?
+ cat conftest.err >&5
+ echo "$as_me:18966: \$? = $ac_status" >&5
+ if (exit $ac_status) && test -s "$ac_outfile"; then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings other than the usual output.
+ $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp
+ $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+ if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
+ lt_prog_compiler_pic_works_CXX=yes
+ fi
+ fi
+ $rm conftest*
+
+fi
+echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works_CXX" >&5
+echo "${ECHO_T}$lt_prog_compiler_pic_works_CXX" >&6
+
+if test x"$lt_prog_compiler_pic_works_CXX" = xyes; then
+ case $lt_prog_compiler_pic_CXX in
+ "" | " "*) ;;
+ *) lt_prog_compiler_pic_CXX=" $lt_prog_compiler_pic_CXX" ;;
+ esac
+else
+ lt_prog_compiler_pic_CXX=
+ lt_prog_compiler_can_build_shared_CXX=no
+fi
+
+fi
+case $host_os in
+ # For platforms which do not support PIC, -DPIC is meaningless:
+ *djgpp*)
+ lt_prog_compiler_pic_CXX=
+ ;;
+ *)
+ lt_prog_compiler_pic_CXX="$lt_prog_compiler_pic_CXX -DPIC"
+ ;;
+esac
+
+#
+# Check to make sure the static flag actually works.
+#
+wl=$lt_prog_compiler_wl_CXX eval lt_tmp_static_flag=\"$lt_prog_compiler_static_CXX\"
+echo "$as_me:$LINENO: checking if $compiler static flag $lt_tmp_static_flag works" >&5
+echo $ECHO_N "checking if $compiler static flag $lt_tmp_static_flag works... $ECHO_C" >&6
+if test "${lt_prog_compiler_static_works_CXX+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ lt_prog_compiler_static_works_CXX=no
+ save_LDFLAGS="$LDFLAGS"
+ LDFLAGS="$LDFLAGS $lt_tmp_static_flag"
+ printf "$lt_simple_link_test_code" > conftest.$ac_ext
+ if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
+ # The linker can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ if test -s conftest.err; then
+ # Append any errors to the config.log.
+ cat conftest.err 1>&5
+ $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp
+ $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+ if diff conftest.exp conftest.er2 >/dev/null; then
+ lt_prog_compiler_static_works_CXX=yes
+ fi
+ else
+ lt_prog_compiler_static_works_CXX=yes
+ fi
+ fi
+ $rm conftest*
+ LDFLAGS="$save_LDFLAGS"
+
+fi
+echo "$as_me:$LINENO: result: $lt_prog_compiler_static_works_CXX" >&5
+echo "${ECHO_T}$lt_prog_compiler_static_works_CXX" >&6
+
+if test x"$lt_prog_compiler_static_works_CXX" = xyes; then
+ :
+else
+ lt_prog_compiler_static_CXX=
+fi
+
+
+echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5
+echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6
+if test "${lt_cv_prog_compiler_c_o_CXX+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ lt_cv_prog_compiler_c_o_CXX=no
+ $rm -r conftest 2>/dev/null
+ mkdir conftest
+ cd conftest
+ mkdir out
+ printf "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+ lt_compiler_flag="-o out/conftest2.$ac_objext"
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:19066: $lt_compile\"" >&5)
+ (eval "$lt_compile" 2>out/conftest.err)
+ ac_status=$?
+ cat out/conftest.err >&5
+ echo "$as_me:19070: \$? = $ac_status" >&5
+ if (exit $ac_status) && test -s out/conftest2.$ac_objext
+ then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp
+ $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
+ if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
+ lt_cv_prog_compiler_c_o_CXX=yes
+ fi
+ fi
+ chmod u+w . 2>&5
+ $rm conftest*
+ # SGI C++ compiler will create directory out/ii_files/ for
+ # template instantiation
+ test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files
+ $rm out/* && rmdir out
+ cd ..
+ rmdir conftest
+ $rm conftest*
+
+fi
+echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o_CXX" >&5
+echo "${ECHO_T}$lt_cv_prog_compiler_c_o_CXX" >&6
+
+
+hard_links="nottested"
+if test "$lt_cv_prog_compiler_c_o_CXX" = no && test "$need_locks" != no; then
+ # do not overwrite the value of need_locks provided by the user
+ echo "$as_me:$LINENO: checking if we can lock with hard links" >&5
+echo $ECHO_N "checking if we can lock with hard links... $ECHO_C" >&6
+ hard_links=yes
+ $rm conftest*
+ ln conftest.a conftest.b 2>/dev/null && hard_links=no
+ touch conftest.a
+ ln conftest.a conftest.b 2>&5 || hard_links=no
+ ln conftest.a conftest.b 2>/dev/null && hard_links=no
+ echo "$as_me:$LINENO: result: $hard_links" >&5
+echo "${ECHO_T}$hard_links" >&6
+ if test "$hard_links" = no; then
+ { echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5
+echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;}
+ need_locks=warn
+ fi
+else
+ need_locks=no
+fi
+
+echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5
+echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6
+
+ export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+ case $host_os in
+ aix4* | aix5*)
+ # If we're using GNU nm, then we don't want the "-C" option.
+ # -C means demangle to AIX nm, but means don't demangle with GNU nm
+ if $NM -V 2>&1 | grep 'GNU' > /dev/null; then
+ export_symbols_cmds_CXX='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols'
+ else
+ export_symbols_cmds_CXX='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols'
+ fi
+ ;;
+ pw32*)
+ export_symbols_cmds_CXX="$ltdll_cmds"
+ ;;
+ cygwin* | mingw*)
+ export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS] /s/.* \([^ ]*\)/\1 DATA/;/^.* __nm__/s/^.* __nm__\([^ ]*\) [^ ]*/\1 DATA/;/^I /d;/^[AITW] /s/.* //'\'' | sort | uniq > $export_symbols'
+ ;;
+ *)
+ export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+ ;;
+ esac
+
+echo "$as_me:$LINENO: result: $ld_shlibs_CXX" >&5
+echo "${ECHO_T}$ld_shlibs_CXX" >&6
+test "$ld_shlibs_CXX" = no && can_build_shared=no
+
+#
+# Do we need to explicitly link libc?
+#
+case "x$archive_cmds_need_lc_CXX" in
+x|xyes)
+ # Assume -lc should be added
+ archive_cmds_need_lc_CXX=yes
+
+ if test "$enable_shared" = yes && test "$GCC" = yes; then
+ case $archive_cmds_CXX in
+ *'~'*)
+ # FIXME: we may have to deal with multi-command sequences.
+ ;;
+ '$CC '*)
+ # Test whether the compiler implicitly links with -lc since on some
+ # systems, -lgcc has to come before -lc. If gcc already passes -lc
+ # to ld, don't add -lc before -lgcc.
+ echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5
+echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6
+ $rm conftest*
+ printf "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } 2>conftest.err; then
+ soname=conftest
+ lib=conftest
+ libobjs=conftest.$ac_objext
+ deplibs=
+ wl=$lt_prog_compiler_wl_CXX
+ pic_flag=$lt_prog_compiler_pic_CXX
+ compiler_flags=-v
+ linker_flags=-v
+ verstring=
+ output_objdir=.
+ libname=conftest
+ lt_save_allow_undefined_flag=$allow_undefined_flag_CXX
+ allow_undefined_flag_CXX=
+ if { (eval echo "$as_me:$LINENO: \"$archive_cmds_CXX 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\"") >&5
+ (eval $archive_cmds_CXX 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+ then
+ archive_cmds_need_lc_CXX=no
+ else
+ archive_cmds_need_lc_CXX=yes
+ fi
+ allow_undefined_flag_CXX=$lt_save_allow_undefined_flag
+ else
+ cat conftest.err 1>&5
+ fi
+ $rm conftest*
+ echo "$as_me:$LINENO: result: $archive_cmds_need_lc_CXX" >&5
+echo "${ECHO_T}$archive_cmds_need_lc_CXX" >&6
+ ;;
+ esac
+ fi
+ ;;
+esac
+
+echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5
+echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6
+library_names_spec=
+libname_spec='lib$name'
+soname_spec=
+shrext_cmds=".so"
+postinstall_cmds=
+postuninstall_cmds=
+finish_cmds=
+finish_eval=
+shlibpath_var=
+shlibpath_overrides_runpath=unknown
+version_type=none
+dynamic_linker="$host_os ld.so"
+sys_lib_dlsearch_path_spec="/lib /usr/lib"
+if test "$GCC" = yes; then
+ sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
+ if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then
+ # if the path contains ";" then we assume it to be the separator
+ # otherwise default to the standard path separator (i.e. ":") - it is
+ # assumed that no part of a normal pathname contains ";" but that should
+ # okay in the real world where ";" in dirpaths is itself problematic.
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+ else
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+ fi
+else
+ sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
+fi
+need_lib_prefix=unknown
+hardcode_into_libs=no
+
+# when you set need_version to no, make sure it does not cause -set_version
+# flags to be left without arguments
+need_version=unknown
+
+case $host_os in
+aix3*)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a'
+ shlibpath_var=LIBPATH
+
+ # AIX 3 has no versioning support, so we append a major version to the name.
+ soname_spec='${libname}${release}${shared_ext}$major'
+ ;;
+
+aix4* | aix5*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ hardcode_into_libs=yes
+ if test "$host_cpu" = ia64; then
+ # AIX 5 supports IA64
+ library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ else
+ # With GCC up to 2.95.x, collect2 would create an import file
+ # for dependence libraries. The import file would start with
+ # the line `#! .'. This would cause the generated library to
+ # depend on `.', always an invalid library. This was fixed in
+ # development snapshots of GCC prior to 3.0.
+ case $host_os in
+ aix4 | aix4.[01] | aix4.[01].*)
+ if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
+ echo ' yes '
+ echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then
+ :
+ else
+ can_build_shared=no
+ fi
+ ;;
+ esac
+ # AIX (on Power*) has no versioning support, so currently we can not hardcode correct
+ # soname into executable. Probably we can add versioning support to
+ # collect2, so additional links can be useful in future.
+ if test "$aix_use_runtimelinking" = yes; then
+ # If using run time linking (on AIX 4.2 or later) use lib<name>.so
+ # instead of lib<name>.a to let people know that these are not
+ # typical AIX shared libraries.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ else
+ # We preserve .a as extension for shared libraries through AIX4.2
+ # and later when we are not doing run time linking.
+ library_names_spec='${libname}${release}.a $libname.a'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ fi
+ shlibpath_var=LIBPATH
+ fi
+ ;;
+
+amigaos*)
+ library_names_spec='$libname.ixlibrary $libname.a'
+ # Create ${libname}_ixlibrary.a entries in /sys/libs.
+ finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
+ ;;
+
+beos*)
+ library_names_spec='${libname}${shared_ext}'
+ dynamic_linker="$host_os ld.so"
+ shlibpath_var=LIBRARY_PATH
+ ;;
+
+bsdi[45]*)
+ version_type=linux
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
+ sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
+ # the default ld.so.conf also contains /usr/contrib/lib and
+ # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
+ # libtool to hard-code these into programs
+ ;;
+
+cygwin* | mingw* | pw32*)
+ version_type=windows
+ shrext_cmds=".dll"
+ need_version=no
+ need_lib_prefix=no
+
+ case $GCC,$host_os in
+ yes,cygwin* | yes,mingw* | yes,pw32*)
+ library_names_spec='$libname.dll.a'
+ # DLL is installed to $(libdir)/../bin by postinstall_cmds
+ postinstall_cmds='base_file=`basename \${file}`~
+ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~
+ dldir=$destdir/`dirname \$dlpath`~
+ test -d \$dldir || mkdir -p \$dldir~
+ $install_prog $dir/$dlname \$dldir/$dlname~
+ chmod a+x \$dldir/$dlname'
+ postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+ dlpath=$dir/\$dldll~
+ $rm \$dlpath'
+ shlibpath_overrides_runpath=yes
+
+ case $host_os in
+ cygwin*)
+ # Cygwin DLLs use 'cyg' prefix rather than 'lib'
+ soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+ sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib"
+ ;;
+ mingw*)
+ # MinGW DLLs use traditional 'lib' prefix
+ soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+ sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
+ if echo "$sys_lib_search_path_spec" | grep ';[c-zC-Z]:/' >/dev/null; then
+ # It is most probably a Windows format PATH printed by
+ # mingw gcc, but we are running on Cygwin. Gcc prints its search
+ # path with ; separators, and with drive letters. We can handle the
+ # drive letters (cygwin fileutils understands them), so leave them,
+ # especially as we might pass files found there to a mingw objdump,
+ # which wouldn't understand a cygwinified path. Ahh.
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+ else
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+ fi
+ ;;
+ pw32*)
+ # pw32 DLLs use 'pw' prefix rather than 'lib'
+ library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+ ;;
+ esac
+ ;;
+
+ *)
+ library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib'
+ ;;
+ esac
+ dynamic_linker='Win32 ld.exe'
+ # FIXME: first we should search . and the directory the executable is in
+ shlibpath_var=PATH
+ ;;
+
+darwin* | rhapsody*)
+ dynamic_linker="$host_os dyld"
+ version_type=darwin
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext'
+ soname_spec='${libname}${release}${major}$shared_ext'
+ shlibpath_overrides_runpath=yes
+ shlibpath_var=DYLD_LIBRARY_PATH
+ shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
+ # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same.
+ if test "$GCC" = yes; then
+ sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"`
+ else
+ sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib'
+ fi
+ sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
+ ;;
+
+dgux*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+freebsd1*)
+ dynamic_linker=no
+ ;;
+
+kfreebsd*-gnu)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ dynamic_linker='GNU ld.so'
+ ;;
+
+freebsd* | dragonfly*)
+ # DragonFly does not have aout. When/if they implement a new
+ # versioning mechanism, adjust this.
+ if test -x /usr/bin/objformat; then
+ objformat=`/usr/bin/objformat`
+ else
+ case $host_os in
+ freebsd[123]*) objformat=aout ;;
+ *) objformat=elf ;;
+ esac
+ fi
+ version_type=freebsd-$objformat
+ case $version_type in
+ freebsd-elf*)
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+ need_version=no
+ need_lib_prefix=no
+ ;;
+ freebsd-*)
+ library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix'
+ need_version=yes
+ ;;
+ esac
+ shlibpath_var=LD_LIBRARY_PATH
+ case $host_os in
+ freebsd2*)
+ shlibpath_overrides_runpath=yes
+ ;;
+ freebsd3.[01]* | freebsdelf3.[01]*)
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+ freebsd3.[2-9]* | freebsdelf3.[2-9]* | \
+ freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1)
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ ;;
+ freebsd*) # from 4.6 on
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+ esac
+ ;;
+
+gnu*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ hardcode_into_libs=yes
+ ;;
+
+hpux9* | hpux10* | hpux11*)
+ # Give a soname corresponding to the major version so that dld.sl refuses to
+ # link against other versions.
+ version_type=sunos
+ need_lib_prefix=no
+ need_version=no
+ case $host_cpu in
+ ia64*)
+ shrext_cmds='.so'
+ hardcode_into_libs=yes
+ dynamic_linker="$host_os dld.so"
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ if test "X$HPUX_IA64_MODE" = X32; then
+ sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
+ else
+ sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
+ fi
+ sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+ ;;
+ hppa*64*)
+ shrext_cmds='.sl'
+ hardcode_into_libs=yes
+ dynamic_linker="$host_os dld.sl"
+ shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
+ shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
+ sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+ ;;
+ *)
+ shrext_cmds='.sl'
+ dynamic_linker="$host_os dld.sl"
+ shlibpath_var=SHLIB_PATH
+ shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ ;;
+ esac
+ # HP-UX runs *really* slowly unless shared libraries are mode 555.
+ postinstall_cmds='chmod 555 $lib'
+ ;;
+
+interix3*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ ;;
+
+irix5* | irix6* | nonstopux*)
+ case $host_os in
+ nonstopux*) version_type=nonstopux ;;
+ *)
+ if test "$lt_cv_prog_gnu_ld" = yes; then
+ version_type=linux
+ else
+ version_type=irix
+ fi ;;
+ esac
+ need_lib_prefix=no
+ need_version=no
+ soname_spec='${libname}${release}${shared_ext}$major'
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}'
+ case $host_os in
+ irix5* | nonstopux*)
+ libsuff= shlibsuff=
+ ;;
+ *)
+ case $LD in # libtool.m4 will add one of these switches to LD
+ *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ")
+ libsuff= shlibsuff= libmagic=32-bit;;
+ *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ")
+ libsuff=32 shlibsuff=N32 libmagic=N32;;
+ *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ")
+ libsuff=64 shlibsuff=64 libmagic=64-bit;;
+ *) libsuff= shlibsuff= libmagic=never-match;;
+ esac
+ ;;
+ esac
+ shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
+ shlibpath_overrides_runpath=no
+ sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
+ sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
+ hardcode_into_libs=yes
+ ;;
+
+# No shared lib support for Linux oldld, aout, or coff.
+linux*oldld* | linux*aout* | linux*coff*)
+ dynamic_linker=no
+ ;;
+
+# This must be Linux ELF.
+linux*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ # This implies no fast_install, which is unacceptable.
+ # Some rework will be needed to allow for fast_install
+ # before this can be enabled.
+ hardcode_into_libs=yes
+
+ # find out which ABI we are using
+ libsuff=
+ case "$host_cpu" in
+ x86_64*|s390x*|powerpc64*)
+ echo '#line 19602 "configure"' > conftest.$ac_ext
+ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ case `/usr/bin/file conftest.$ac_objext` in
+ *64-bit*)
+ libsuff=64
+ sys_lib_search_path_spec="/lib${libsuff} /usr/lib${libsuff} /usr/local/lib${libsuff}"
+ ;;
+ esac
+ fi
+ rm -rf conftest*
+ ;;
+ esac
+
+ # Append ld.so.conf contents to the search path
+ if test -f /etc/ld.so.conf; then
+ lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '`
+ sys_lib_dlsearch_path_spec="/lib${libsuff} /usr/lib${libsuff} $lt_ld_extra"
+ fi
+
+ # We used to test for /lib/ld.so.1 and disable shared libraries on
+ # powerpc, because MkLinux only supported shared libraries with the
+ # GNU dynamic linker. Since this was broken with cross compilers,
+ # most powerpc-linux boxes support dynamic linking these days and
+ # people can always --disable-shared, the test was removed, and we
+ # assume the GNU/Linux dynamic linker is in use.
+ dynamic_linker='GNU/Linux ld.so'
+ ;;
+
+knetbsd*-gnu)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ dynamic_linker='GNU ld.so'
+ ;;
+
+netbsd*)
+ version_type=sunos
+ need_lib_prefix=no
+ need_version=no
+ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+ dynamic_linker='NetBSD (a.out) ld.so'
+ else
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ dynamic_linker='NetBSD ld.elf_so'
+ fi
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+
+newsos6)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ ;;
+
+nto-qnx*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ ;;
+
+openbsd*)
+ version_type=sunos
+ sys_lib_dlsearch_path_spec="/usr/lib"
+ need_lib_prefix=no
+ # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs.
+ case $host_os in
+ openbsd3.3 | openbsd3.3.*) need_version=yes ;;
+ *) need_version=no ;;
+ esac
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ case $host_os in
+ openbsd2.[89] | openbsd2.[89].*)
+ shlibpath_overrides_runpath=no
+ ;;
+ *)
+ shlibpath_overrides_runpath=yes
+ ;;
+ esac
+ else
+ shlibpath_overrides_runpath=yes
+ fi
+ ;;
+
+os2*)
+ libname_spec='$name'
+ shrext_cmds=".dll"
+ need_lib_prefix=no
+ library_names_spec='$libname${shared_ext} $libname.a'
+ dynamic_linker='OS/2 ld.exe'
+ shlibpath_var=LIBPATH
+ ;;
+
+osf3* | osf4* | osf5*)
+ version_type=osf
+ need_lib_prefix=no
+ need_version=no
+ soname_spec='${libname}${release}${shared_ext}$major'
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
+ sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec"
+ ;;
+
+solaris*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ # ldd complains unless libraries are executable
+ postinstall_cmds='chmod +x $lib'
+ ;;
+
+sunos4*)
+ version_type=sunos
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ if test "$with_gnu_ld" = yes; then
+ need_lib_prefix=no
+ fi
+ need_version=yes
+ ;;
+
+sysv4 | sysv4.3*)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ case $host_vendor in
+ sni)
+ shlibpath_overrides_runpath=no
+ need_lib_prefix=no
+ export_dynamic_flag_spec='${wl}-Blargedynsym'
+ runpath_var=LD_RUN_PATH
+ ;;
+ siemens)
+ need_lib_prefix=no
+ ;;
+ motorola)
+ need_lib_prefix=no
+ need_version=no
+ shlibpath_overrides_runpath=no
+ sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
+ ;;
+ esac
+ ;;
+
+sysv4*MP*)
+ if test -d /usr/nec ;then
+ version_type=linux
+ library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}'
+ soname_spec='$libname${shared_ext}.$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ fi
+ ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+ version_type=freebsd-elf
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ hardcode_into_libs=yes
+ if test "$with_gnu_ld" = yes; then
+ sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib'
+ shlibpath_overrides_runpath=no
+ else
+ sys_lib_search_path_spec='/usr/ccs/lib /usr/lib'
+ shlibpath_overrides_runpath=yes
+ case $host_os in
+ sco3.2v5*)
+ sys_lib_search_path_spec="$sys_lib_search_path_spec /lib"
+ ;;
+ esac
+ fi
+ sys_lib_dlsearch_path_spec='/usr/lib'
+ ;;
+
+uts4*)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+*)
+ dynamic_linker=no
+ ;;
+esac
+echo "$as_me:$LINENO: result: $dynamic_linker" >&5
+echo "${ECHO_T}$dynamic_linker" >&6
+test "$dynamic_linker" = no && can_build_shared=no
+
+variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
+if test "$GCC" = yes; then
+ variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
+fi
+
+echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5
+echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6
+hardcode_action_CXX=
+if test -n "$hardcode_libdir_flag_spec_CXX" || \
+ test -n "$runpath_var_CXX" || \
+ test "X$hardcode_automatic_CXX" = "Xyes" ; then
+
+ # We can hardcode non-existant directories.
+ if test "$hardcode_direct_CXX" != no &&
+ # If the only mechanism to avoid hardcoding is shlibpath_var, we
+ # have to relink, otherwise we might link with an installed library
+ # when we should be linking with a yet-to-be-installed one
+ ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, CXX)" != no &&
+ test "$hardcode_minus_L_CXX" != no; then
+ # Linking always hardcodes the temporary library directory.
+ hardcode_action_CXX=relink
+ else
+ # We can link without hardcoding, and we can hardcode nonexisting dirs.
+ hardcode_action_CXX=immediate
+ fi
+else
+ # We cannot hardcode anything, or else we can only hardcode existing
+ # directories.
+ hardcode_action_CXX=unsupported
+fi
+echo "$as_me:$LINENO: result: $hardcode_action_CXX" >&5
+echo "${ECHO_T}$hardcode_action_CXX" >&6
+
+if test "$hardcode_action_CXX" = relink; then
+ # Fast installation is not supported
+ enable_fast_install=no
+elif test "$shlibpath_overrides_runpath" = yes ||
+ test "$enable_shared" = no; then
+ # Fast installation is not necessary
+ enable_fast_install=needless
+fi
+
+
+# The else clause should only fire when bootstrapping the
+# libtool distribution, otherwise you forgot to ship ltmain.sh
+# with your package, and you will get complaints that there are
+# no rules to generate ltmain.sh.
+if test -f "$ltmain"; then
+ # See if we are running on zsh, and set the options which allow our commands through
+ # without removal of \ escapes.
+ if test -n "${ZSH_VERSION+set}" ; then
+ setopt NO_GLOB_SUBST
+ fi
+ # Now quote all the things that may contain metacharacters while being
+ # careful not to overquote the AC_SUBSTed values. We take copies of the
+ # variables and quote the copies for generation of the libtool script.
+ for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \
+ SED SHELL STRIP \
+ libname_spec library_names_spec soname_spec extract_expsyms_cmds \
+ old_striplib striplib file_magic_cmd finish_cmds finish_eval \
+ deplibs_check_method reload_flag reload_cmds need_locks \
+ lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \
+ lt_cv_sys_global_symbol_to_c_name_address \
+ sys_lib_search_path_spec sys_lib_dlsearch_path_spec \
+ old_postinstall_cmds old_postuninstall_cmds \
+ compiler_CXX \
+ CC_CXX \
+ LD_CXX \
+ lt_prog_compiler_wl_CXX \
+ lt_prog_compiler_pic_CXX \
+ lt_prog_compiler_static_CXX \
+ lt_prog_compiler_no_builtin_flag_CXX \
+ export_dynamic_flag_spec_CXX \
+ thread_safe_flag_spec_CXX \
+ whole_archive_flag_spec_CXX \
+ enable_shared_with_static_runtimes_CXX \
+ old_archive_cmds_CXX \
+ old_archive_from_new_cmds_CXX \
+ predep_objects_CXX \
+ postdep_objects_CXX \
+ predeps_CXX \
+ postdeps_CXX \
+ compiler_lib_search_path_CXX \
+ archive_cmds_CXX \
+ archive_expsym_cmds_CXX \
+ postinstall_cmds_CXX \
+ postuninstall_cmds_CXX \
+ old_archive_from_expsyms_cmds_CXX \
+ allow_undefined_flag_CXX \
+ no_undefined_flag_CXX \
+ export_symbols_cmds_CXX \
+ hardcode_libdir_flag_spec_CXX \
+ hardcode_libdir_flag_spec_ld_CXX \
+ hardcode_libdir_separator_CXX \
+ hardcode_automatic_CXX \
+ module_cmds_CXX \
+ module_expsym_cmds_CXX \
+ lt_cv_prog_compiler_c_o_CXX \
+ exclude_expsyms_CXX \
+ include_expsyms_CXX; do
+
+ case $var in
+ old_archive_cmds_CXX | \
+ old_archive_from_new_cmds_CXX | \
+ archive_cmds_CXX | \
+ archive_expsym_cmds_CXX | \
+ module_cmds_CXX | \
+ module_expsym_cmds_CXX | \
+ old_archive_from_expsyms_cmds_CXX | \
+ export_symbols_cmds_CXX | \
+ extract_expsyms_cmds | reload_cmds | finish_cmds | \
+ postinstall_cmds | postuninstall_cmds | \
+ old_postinstall_cmds | old_postuninstall_cmds | \
+ sys_lib_search_path_spec | sys_lib_dlsearch_path_spec)
+ # Double-quote double-evaled strings.
+ eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\""
+ ;;
+ *)
+ eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\""
+ ;;
+ esac
+ done
+
+ case $lt_echo in
+ *'\$0 --fallback-echo"')
+ lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'`
+ ;;
+ esac
+
+cfgfile="$ofile"
+
+ cat <<__EOF__ >> "$cfgfile"
+# ### BEGIN LIBTOOL TAG CONFIG: $tagname
+
+# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+
+# Shell to use when invoking shell scripts.
+SHELL=$lt_SHELL
+
+# Whether or not to build shared libraries.
+build_libtool_libs=$enable_shared
+
+# Whether or not to build static libraries.
+build_old_libs=$enable_static
+
+# Whether or not to add -lc for building shared libraries.
+build_libtool_need_lc=$archive_cmds_need_lc_CXX
+
+# Whether or not to disallow shared libs when runtime libs are static
+allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_CXX
+
+# Whether or not to optimize for fast installation.
+fast_install=$enable_fast_install
+
+# The host system.
+host_alias=$host_alias
+host=$host
+host_os=$host_os
+
+# The build system.
+build_alias=$build_alias
+build=$build
+build_os=$build_os
+
+# An echo program that does not interpret backslashes.
+echo=$lt_echo
+
+# The archiver.
+AR=$lt_AR
+AR_FLAGS=$lt_AR_FLAGS
+
+# A C compiler.
+LTCC=$lt_LTCC
+
+# LTCC compiler flags.
+LTCFLAGS=$lt_LTCFLAGS
+
+# A language-specific compiler.
+CC=$lt_compiler_CXX
+
+# Is the compiler the GNU C compiler?
+with_gcc=$GCC_CXX
+
+gcc_dir=\`gcc -print-file-name=. | $SED 's,/\.$,,'\`
+gcc_ver=\`gcc -dumpversion\`
+
+# An ERE matcher.
+EGREP=$lt_EGREP
+
+# The linker used to build libraries.
+LD=$lt_LD_CXX
+
+# Whether we need hard or soft links.
+LN_S=$lt_LN_S
+
+# A BSD-compatible nm program.
+NM=$lt_NM
+
+# A symbol stripping program
+STRIP=$lt_STRIP
+
+# Used to examine libraries when file_magic_cmd begins "file"
+MAGIC_CMD=$MAGIC_CMD
+
+# Used on cygwin: DLL creation program.
+DLLTOOL="$DLLTOOL"
+
+# Used on cygwin: object dumper.
+OBJDUMP="$OBJDUMP"
+
+# Used on cygwin: assembler.
+AS="$AS"
+
+# The name of the directory that contains temporary libtool files.
+objdir=$objdir
+
+# How to create reloadable object files.
+reload_flag=$lt_reload_flag
+reload_cmds=$lt_reload_cmds
+
+# How to pass a linker flag through the compiler.
+wl=$lt_lt_prog_compiler_wl_CXX
+
+# Object file suffix (normally "o").
+objext="$ac_objext"
+
+# Old archive suffix (normally "a").
+libext="$libext"
+
+# Shared library suffix (normally ".so").
+shrext_cmds='$shrext_cmds'
+
+# Executable file suffix (normally "").
+exeext="$exeext"
+
+# Additional compiler flags for building library objects.
+pic_flag=$lt_lt_prog_compiler_pic_CXX
+pic_mode=$pic_mode
+
+# What is the maximum length of a command?
+max_cmd_len=$lt_cv_sys_max_cmd_len
+
+# Does compiler simultaneously support -c and -o options?
+compiler_c_o=$lt_lt_cv_prog_compiler_c_o_CXX
+
+# Must we lock files when doing compilation?
+need_locks=$lt_need_locks
+
+# Do we need the lib prefix for modules?
+need_lib_prefix=$need_lib_prefix
+
+# Do we need a version for libraries?
+need_version=$need_version
+
+# Whether dlopen is supported.
+dlopen_support=$enable_dlopen
+
+# Whether dlopen of programs is supported.
+dlopen_self=$enable_dlopen_self
+
+# Whether dlopen of statically linked programs is supported.
+dlopen_self_static=$enable_dlopen_self_static
+
+# Compiler flag to prevent dynamic linking.
+link_static_flag=$lt_lt_prog_compiler_static_CXX
+
+# Compiler flag to turn off builtin functions.
+no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_CXX
+
+# Compiler flag to allow reflexive dlopens.
+export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_CXX
+
+# Compiler flag to generate shared objects directly from archives.
+whole_archive_flag_spec=$lt_whole_archive_flag_spec_CXX
+
+# Compiler flag to generate thread-safe objects.
+thread_safe_flag_spec=$lt_thread_safe_flag_spec_CXX
+
+# Library versioning type.
+version_type=$version_type
+
+# Format of library name prefix.
+libname_spec=$lt_libname_spec
+
+# List of archive names. First name is the real one, the rest are links.
+# The last name is the one that the linker finds with -lNAME.
+library_names_spec=$lt_library_names_spec
+
+# The coded name of the library, if different from the real name.
+soname_spec=$lt_soname_spec
+
+# Commands used to build and install an old-style archive.
+RANLIB=$lt_RANLIB
+old_archive_cmds=$lt_old_archive_cmds_CXX
+old_postinstall_cmds=$lt_old_postinstall_cmds
+old_postuninstall_cmds=$lt_old_postuninstall_cmds
+
+# Create an old-style archive from a shared archive.
+old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_CXX
+
+# Create a temporary old-style archive to link instead of a shared archive.
+old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_CXX
+
+# Commands used to build and install a shared archive.
+archive_cmds=$lt_archive_cmds_CXX
+archive_expsym_cmds=$lt_archive_expsym_cmds_CXX
+postinstall_cmds=$lt_postinstall_cmds
+postuninstall_cmds=$lt_postuninstall_cmds
+
+# Commands used to build a loadable module (assumed same as above if empty)
+module_cmds=$lt_module_cmds_CXX
+module_expsym_cmds=$lt_module_expsym_cmds_CXX
+
+# Commands to strip libraries.
+old_striplib=$lt_old_striplib
+striplib=$lt_striplib
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predep_objects=\`echo $lt_predep_objects_CXX | \$SED -e "s@\${gcc_dir}@\\\${gcc_dir}@g;s@\${gcc_ver}@\\\${gcc_ver}@g"\`
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdep_objects=\`echo $lt_postdep_objects_CXX | \$SED -e "s@\${gcc_dir}@\\\${gcc_dir}@g;s@\${gcc_ver}@\\\${gcc_ver}@g"\`
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predeps=$lt_predeps_CXX
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdeps=$lt_postdeps_CXX
+
+# The library search path used internally by the compiler when linking
+# a shared library.
+compiler_lib_search_path=\`echo $lt_compiler_lib_search_path_CXX | \$SED -e "s@\${gcc_dir}@\\\${gcc_dir}@g;s@\${gcc_ver}@\\\${gcc_ver}@g"\`
+
+# Method to check whether dependent libraries are shared objects.
+deplibs_check_method=$lt_deplibs_check_method
+
+# Command to use when deplibs_check_method == file_magic.
+file_magic_cmd=$lt_file_magic_cmd
+
+# Flag that allows shared libraries with undefined symbols to be built.
+allow_undefined_flag=$lt_allow_undefined_flag_CXX
+
+# Flag that forces no undefined symbols.
+no_undefined_flag=$lt_no_undefined_flag_CXX
+
+# Commands used to finish a libtool library installation in a directory.
+finish_cmds=$lt_finish_cmds
+
+# Same as above, but a single script fragment to be evaled but not shown.
+finish_eval=$lt_finish_eval
+
+# Take the output of nm and produce a listing of raw symbols and C names.
+global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe
+
+# Transform the output of nm in a proper C declaration
+global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl
+
+# Transform the output of nm in a C name address pair
+global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address
+
+# This is the shared library runtime path variable.
+runpath_var=$runpath_var
+
+# This is the shared library path variable.
+shlibpath_var=$shlibpath_var
+
+# Is shlibpath searched before the hard-coded library search path?
+shlibpath_overrides_runpath=$shlibpath_overrides_runpath
+
+# How to hardcode a shared library path into an executable.
+hardcode_action=$hardcode_action_CXX
+
+# Whether we should hardcode library paths into libraries.
+hardcode_into_libs=$hardcode_into_libs
+
+# Flag to hardcode \$libdir into a binary during linking.
+# This must work even if \$libdir does not exist.
+hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_CXX
+
+# If ld is used when linking, flag to hardcode \$libdir into
+# a binary during linking. This must work even if \$libdir does
+# not exist.
+hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_CXX
+
+# Whether we need a single -rpath flag with a separated argument.
+hardcode_libdir_separator=$lt_hardcode_libdir_separator_CXX
+
+# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the
+# resulting binary.
+hardcode_direct=$hardcode_direct_CXX
+
+# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
+# resulting binary.
+hardcode_minus_L=$hardcode_minus_L_CXX
+
+# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into
+# the resulting binary.
+hardcode_shlibpath_var=$hardcode_shlibpath_var_CXX
+
+# Set to yes if building a shared library automatically hardcodes DIR into the library
+# and all subsequent libraries and executables linked against it.
+hardcode_automatic=$hardcode_automatic_CXX
+
+# Variables whose values should be saved in libtool wrapper scripts and
+# restored at relink time.
+variables_saved_for_relink="$variables_saved_for_relink"
+
+# Whether libtool must link a program against all its dependency libraries.
+link_all_deplibs=$link_all_deplibs_CXX
+
+# Compile-time system search path for libraries
+sys_lib_search_path_spec=\`echo $lt_sys_lib_search_path_spec | \$SED -e "s@\${gcc_dir}@\\\${gcc_dir}@g;s@\${gcc_ver}@\\\${gcc_ver}@g"\`
+
+# Run-time system search path for libraries
+sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec
+
+# Fix the shell variable \$srcfile for the compiler.
+fix_srcfile_path="$fix_srcfile_path_CXX"
+
+# Set to yes if exported symbols are required.
+always_export_symbols=$always_export_symbols_CXX
+
+# The commands to list exported symbols.
+export_symbols_cmds=$lt_export_symbols_cmds_CXX
+
+# The commands to extract the exported symbol list from a shared archive.
+extract_expsyms_cmds=$lt_extract_expsyms_cmds
+
+# Symbols that should not be listed in the preloaded symbols.
+exclude_expsyms=$lt_exclude_expsyms_CXX
+
+# Symbols that must always be exported.
+include_expsyms=$lt_include_expsyms_CXX
+
+# ### END LIBTOOL TAG CONFIG: $tagname
+
+__EOF__
+
+
+else
+ # If there is no Makefile yet, we rely on a make rule to execute
+ # `config.status --recheck' to rerun these tests and create the
+ # libtool script then.
+ ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'`
+ if test -f "$ltmain_in"; then
+ test -f Makefile && make "$ltmain"
+ fi
+fi
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_linkonly='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_objext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+CC=$lt_save_CC
+LDCXX=$LD
+LD=$lt_save_LD
+GCC=$lt_save_GCC
+with_gnu_ldcxx=$with_gnu_ld
+with_gnu_ld=$lt_save_with_gnu_ld
+lt_cv_path_LDCXX=$lt_cv_path_LD
+lt_cv_path_LD=$lt_save_path_LD
+lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld
+lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld
+
+ else
+ tagname=""
+ fi
+ ;;
+
+ F77)
+ if test -n "$F77" && test "X$F77" != "Xno"; then
+
+ac_ext=f
+ac_compile='$F77 -c $FFLAGS conftest.$ac_ext >&5'
+ac_link='$F77 -o conftest$ac_exeext $FFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_f77_compiler_gnu
+
+
+archive_cmds_need_lc_F77=no
+allow_undefined_flag_F77=
+always_export_symbols_F77=no
+archive_expsym_cmds_F77=
+export_dynamic_flag_spec_F77=
+hardcode_direct_F77=no
+hardcode_libdir_flag_spec_F77=
+hardcode_libdir_flag_spec_ld_F77=
+hardcode_libdir_separator_F77=
+hardcode_minus_L_F77=no
+hardcode_automatic_F77=no
+module_cmds_F77=
+module_expsym_cmds_F77=
+link_all_deplibs_F77=unknown
+old_archive_cmds_F77=$old_archive_cmds
+no_undefined_flag_F77=
+whole_archive_flag_spec_F77=
+enable_shared_with_static_runtimes_F77=no
+
+# Source file extension for f77 test sources.
+ac_ext=f
+
+# Object file extension for compiled f77 test sources.
+objext=o
+objext_F77=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code=" subroutine t\n return\n end\n"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code=" program t\n end\n"
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# If no C compiler flags were specified, use CFLAGS.
+LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+
+
+# save warnings/boilerplate of simple test code
+ac_outfile=conftest.$ac_objext
+printf "$lt_simple_compile_test_code" >conftest.$ac_ext
+eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_compiler_boilerplate=`cat conftest.err`
+$rm conftest*
+
+ac_outfile=conftest.$ac_objext
+printf "$lt_simple_link_test_code" >conftest.$ac_ext
+eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_linker_boilerplate=`cat conftest.err`
+$rm conftest*
+
+
+# Allow CC to be a program name with arguments.
+lt_save_CC="$CC"
+CC=${F77-"f77"}
+compiler=$CC
+compiler_F77=$CC
+for cc_temp in $compiler""; do
+ case $cc_temp in
+ compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
+ distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
+ \-*) ;;
+ *) break;;
+ esac
+done
+cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"`
+
+
+echo "$as_me:$LINENO: checking if libtool supports shared libraries" >&5
+echo $ECHO_N "checking if libtool supports shared libraries... $ECHO_C" >&6
+echo "$as_me:$LINENO: result: $can_build_shared" >&5
+echo "${ECHO_T}$can_build_shared" >&6
+
+echo "$as_me:$LINENO: checking whether to build shared libraries" >&5
+echo $ECHO_N "checking whether to build shared libraries... $ECHO_C" >&6
+test "$can_build_shared" = "no" && enable_shared=no
+
+# On AIX, shared libraries and static libraries use the same namespace, and
+# are all built from PIC.
+case $host_os in
+aix3*)
+ test "$enable_shared" = yes && enable_static=no
+ if test -n "$RANLIB"; then
+ archive_cmds="$archive_cmds~\$RANLIB \$lib"
+ postinstall_cmds='$RANLIB $lib'
+ fi
+ ;;
+aix4* | aix5*)
+ if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
+ test "$enable_shared" = yes && enable_static=no
+ fi
+ ;;
+esac
+echo "$as_me:$LINENO: result: $enable_shared" >&5
+echo "${ECHO_T}$enable_shared" >&6
+
+echo "$as_me:$LINENO: checking whether to build static libraries" >&5
+echo $ECHO_N "checking whether to build static libraries... $ECHO_C" >&6
+# Make sure either enable_shared or enable_static is yes.
+test "$enable_shared" = yes || enable_static=yes
+echo "$as_me:$LINENO: result: $enable_static" >&5
+echo "${ECHO_T}$enable_static" >&6
+
+GCC_F77="$G77"
+LD_F77="$LD"
+
+lt_prog_compiler_wl_F77=
+lt_prog_compiler_pic_F77=
+lt_prog_compiler_static_F77=
+
+echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5
+echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6
+
+ if test "$GCC" = yes; then
+ lt_prog_compiler_wl_F77='-Wl,'
+ lt_prog_compiler_static_F77='-static'
+
+ case $host_os in
+ aix*)
+ # All AIX code is PIC.
+ if test "$host_cpu" = ia64; then
+ # AIX 5 now supports IA64 processor
+ lt_prog_compiler_static_F77='-Bstatic'
+ fi
+ ;;
+
+ amigaos*)
+ # FIXME: we need at least 68020 code to build shared libraries, but
+ # adding the `-m68020' flag to GCC prevents building anything better,
+ # like `-m68040'.
+ lt_prog_compiler_pic_F77='-m68020 -resident32 -malways-restore-a4'
+ ;;
+
+ beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+ # PIC is the default for these OSes.
+ ;;
+
+ mingw* | pw32* | os2*)
+ # This hack is so that the source file can tell whether it is being
+ # built for inclusion in a dll (and should export symbols for example).
+ lt_prog_compiler_pic_F77='-DDLL_EXPORT'
+ ;;
+
+ darwin* | rhapsody*)
+ # PIC is the default on this platform
+ # Common symbols not allowed in MH_DYLIB files
+ lt_prog_compiler_pic_F77='-fno-common'
+ ;;
+
+ interix3*)
+ # Interix 3.x gcc -fpic/-fPIC options generate broken code.
+ # Instead, we relocate shared libraries at runtime.
+ ;;
+
+ msdosdjgpp*)
+ # Just because we use GCC doesn't mean we suddenly get shared libraries
+ # on systems that don't support them.
+ lt_prog_compiler_can_build_shared_F77=no
+ enable_shared=no
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ lt_prog_compiler_pic_F77=-Kconform_pic
+ fi
+ ;;
+
+ hpux*)
+ # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+ # not for PA HP-UX.
+ case $host_cpu in
+ hppa*64*|ia64*)
+ # +Z the default
+ ;;
+ *)
+ lt_prog_compiler_pic_F77='-fPIC'
+ ;;
+ esac
+ ;;
+
+ *)
+ lt_prog_compiler_pic_F77='-fPIC'
+ ;;
+ esac
+ else
+ # PORTME Check for flag to pass linker flags through the system compiler.
+ case $host_os in
+ aix*)
+ lt_prog_compiler_wl_F77='-Wl,'
+ if test "$host_cpu" = ia64; then
+ # AIX 5 now supports IA64 processor
+ lt_prog_compiler_static_F77='-Bstatic'
+ else
+ lt_prog_compiler_static_F77='-bnso -bI:/lib/syscalls.exp'
+ fi
+ ;;
+ darwin*)
+ # PIC is the default on this platform
+ # Common symbols not allowed in MH_DYLIB files
+ case $cc_basename in
+ xlc*)
+ lt_prog_compiler_pic_F77='-qnocommon'
+ lt_prog_compiler_wl_F77='-Wl,'
+ ;;
+ esac
+ ;;
+
+ mingw* | pw32* | os2*)
+ # This hack is so that the source file can tell whether it is being
+ # built for inclusion in a dll (and should export symbols for example).
+ lt_prog_compiler_pic_F77='-DDLL_EXPORT'
+ ;;
+
+ hpux9* | hpux10* | hpux11*)
+ lt_prog_compiler_wl_F77='-Wl,'
+ # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+ # not for PA HP-UX.
+ case $host_cpu in
+ hppa*64*|ia64*)
+ # +Z the default
+ ;;
+ *)
+ lt_prog_compiler_pic_F77='+Z'
+ ;;
+ esac
+ # Is there a better lt_prog_compiler_static that works with the bundled CC?
+ lt_prog_compiler_static_F77='${wl}-a ${wl}archive'
+ ;;
+
+ irix5* | irix6* | nonstopux*)
+ lt_prog_compiler_wl_F77='-Wl,'
+ # PIC (with -KPIC) is the default.
+ lt_prog_compiler_static_F77='-non_shared'
+ ;;
+
+ newsos6)
+ lt_prog_compiler_pic_F77='-KPIC'
+ lt_prog_compiler_static_F77='-Bstatic'
+ ;;
+
+ linux*)
+ case $cc_basename in
+ icc* | ecc*)
+ lt_prog_compiler_wl_F77='-Wl,'
+ lt_prog_compiler_pic_F77='-KPIC'
+ lt_prog_compiler_static_F77='-static'
+ ;;
+ pgcc* | pgf77* | pgf90* | pgf95*)
+ # Portland Group compilers (*not* the Pentium gcc compiler,
+ # which looks to be a dead project)
+ lt_prog_compiler_wl_F77='-Wl,'
+ lt_prog_compiler_pic_F77='-fpic'
+ lt_prog_compiler_static_F77='-Bstatic'
+ ;;
+ ccc*)
+ lt_prog_compiler_wl_F77='-Wl,'
+ # All Alpha code is PIC.
+ lt_prog_compiler_static_F77='-non_shared'
+ ;;
+ esac
+ ;;
+
+ osf3* | osf4* | osf5*)
+ lt_prog_compiler_wl_F77='-Wl,'
+ # All OSF/1 code is PIC.
+ lt_prog_compiler_static_F77='-non_shared'
+ ;;
+
+ solaris*)
+ lt_prog_compiler_pic_F77='-KPIC'
+ lt_prog_compiler_static_F77='-Bstatic'
+ case $cc_basename in
+ f77* | f90* | f95*)
+ lt_prog_compiler_wl_F77='-Qoption ld ';;
+ *)
+ lt_prog_compiler_wl_F77='-Wl,';;
+ esac
+ ;;
+
+ sunos4*)
+ lt_prog_compiler_wl_F77='-Qoption ld '
+ lt_prog_compiler_pic_F77='-PIC'
+ lt_prog_compiler_static_F77='-Bstatic'
+ ;;
+
+ sysv4 | sysv4.2uw2* | sysv4.3*)
+ lt_prog_compiler_wl_F77='-Wl,'
+ lt_prog_compiler_pic_F77='-KPIC'
+ lt_prog_compiler_static_F77='-Bstatic'
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec ;then
+ lt_prog_compiler_pic_F77='-Kconform_pic'
+ lt_prog_compiler_static_F77='-Bstatic'
+ fi
+ ;;
+
+ sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
+ lt_prog_compiler_wl_F77='-Wl,'
+ lt_prog_compiler_pic_F77='-KPIC'
+ lt_prog_compiler_static_F77='-Bstatic'
+ ;;
+
+ unicos*)
+ lt_prog_compiler_wl_F77='-Wl,'
+ lt_prog_compiler_can_build_shared_F77=no
+ ;;
+
+ uts4*)
+ lt_prog_compiler_pic_F77='-pic'
+ lt_prog_compiler_static_F77='-Bstatic'
+ ;;
+
+ *)
+ lt_prog_compiler_can_build_shared_F77=no
+ ;;
+ esac
+ fi
+
+echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_F77" >&5
+echo "${ECHO_T}$lt_prog_compiler_pic_F77" >&6
+
+#
+# Check to make sure the PIC flag actually works.
+#
+if test -n "$lt_prog_compiler_pic_F77"; then
+
+echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic_F77 works" >&5
+echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic_F77 works... $ECHO_C" >&6
+if test "${lt_prog_compiler_pic_works_F77+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ lt_prog_compiler_pic_works_F77=no
+ ac_outfile=conftest.$ac_objext
+ printf "$lt_simple_compile_test_code" > conftest.$ac_ext
+ lt_compiler_flag="$lt_prog_compiler_pic_F77"
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ # The option is referenced via a variable to avoid confusing sed.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:20661: $lt_compile\"" >&5)
+ (eval "$lt_compile" 2>conftest.err)
+ ac_status=$?
+ cat conftest.err >&5
+ echo "$as_me:20665: \$? = $ac_status" >&5
+ if (exit $ac_status) && test -s "$ac_outfile"; then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings other than the usual output.
+ $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp
+ $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+ if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
+ lt_prog_compiler_pic_works_F77=yes
+ fi
+ fi
+ $rm conftest*
+
+fi
+echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works_F77" >&5
+echo "${ECHO_T}$lt_prog_compiler_pic_works_F77" >&6
+
+if test x"$lt_prog_compiler_pic_works_F77" = xyes; then
+ case $lt_prog_compiler_pic_F77 in
+ "" | " "*) ;;
+ *) lt_prog_compiler_pic_F77=" $lt_prog_compiler_pic_F77" ;;
+ esac
+else
+ lt_prog_compiler_pic_F77=
+ lt_prog_compiler_can_build_shared_F77=no
+fi
+
+fi
+case $host_os in
+ # For platforms which do not support PIC, -DPIC is meaningless:
+ *djgpp*)
+ lt_prog_compiler_pic_F77=
+ ;;
+ *)
+ lt_prog_compiler_pic_F77="$lt_prog_compiler_pic_F77"
+ ;;
+esac
+
+#
+# Check to make sure the static flag actually works.
+#
+wl=$lt_prog_compiler_wl_F77 eval lt_tmp_static_flag=\"$lt_prog_compiler_static_F77\"
+echo "$as_me:$LINENO: checking if $compiler static flag $lt_tmp_static_flag works" >&5
+echo $ECHO_N "checking if $compiler static flag $lt_tmp_static_flag works... $ECHO_C" >&6
+if test "${lt_prog_compiler_static_works_F77+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ lt_prog_compiler_static_works_F77=no
+ save_LDFLAGS="$LDFLAGS"
+ LDFLAGS="$LDFLAGS $lt_tmp_static_flag"
+ printf "$lt_simple_link_test_code" > conftest.$ac_ext
+ if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
+ # The linker can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ if test -s conftest.err; then
+ # Append any errors to the config.log.
+ cat conftest.err 1>&5
+ $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp
+ $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+ if diff conftest.exp conftest.er2 >/dev/null; then
+ lt_prog_compiler_static_works_F77=yes
+ fi
+ else
+ lt_prog_compiler_static_works_F77=yes
+ fi
+ fi
+ $rm conftest*
+ LDFLAGS="$save_LDFLAGS"
+
+fi
+echo "$as_me:$LINENO: result: $lt_prog_compiler_static_works_F77" >&5
+echo "${ECHO_T}$lt_prog_compiler_static_works_F77" >&6
+
+if test x"$lt_prog_compiler_static_works_F77" = xyes; then
+ :
+else
+ lt_prog_compiler_static_F77=
+fi
+
+
+echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5
+echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6
+if test "${lt_cv_prog_compiler_c_o_F77+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ lt_cv_prog_compiler_c_o_F77=no
+ $rm -r conftest 2>/dev/null
+ mkdir conftest
+ cd conftest
+ mkdir out
+ printf "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+ lt_compiler_flag="-o out/conftest2.$ac_objext"
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:20765: $lt_compile\"" >&5)
+ (eval "$lt_compile" 2>out/conftest.err)
+ ac_status=$?
+ cat out/conftest.err >&5
+ echo "$as_me:20769: \$? = $ac_status" >&5
+ if (exit $ac_status) && test -s out/conftest2.$ac_objext
+ then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp
+ $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
+ if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
+ lt_cv_prog_compiler_c_o_F77=yes
+ fi
+ fi
+ chmod u+w . 2>&5
+ $rm conftest*
+ # SGI C++ compiler will create directory out/ii_files/ for
+ # template instantiation
+ test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files
+ $rm out/* && rmdir out
+ cd ..
+ rmdir conftest
+ $rm conftest*
+
+fi
+echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o_F77" >&5
+echo "${ECHO_T}$lt_cv_prog_compiler_c_o_F77" >&6
+
+
+hard_links="nottested"
+if test "$lt_cv_prog_compiler_c_o_F77" = no && test "$need_locks" != no; then
+ # do not overwrite the value of need_locks provided by the user
+ echo "$as_me:$LINENO: checking if we can lock with hard links" >&5
+echo $ECHO_N "checking if we can lock with hard links... $ECHO_C" >&6
+ hard_links=yes
+ $rm conftest*
+ ln conftest.a conftest.b 2>/dev/null && hard_links=no
+ touch conftest.a
+ ln conftest.a conftest.b 2>&5 || hard_links=no
+ ln conftest.a conftest.b 2>/dev/null && hard_links=no
+ echo "$as_me:$LINENO: result: $hard_links" >&5
+echo "${ECHO_T}$hard_links" >&6
+ if test "$hard_links" = no; then
+ { echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5
+echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;}
+ need_locks=warn
+ fi
+else
+ need_locks=no
+fi
+
+echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5
+echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6
+
+ runpath_var=
+ allow_undefined_flag_F77=
+ enable_shared_with_static_runtimes_F77=no
+ archive_cmds_F77=
+ archive_expsym_cmds_F77=
+ old_archive_From_new_cmds_F77=
+ old_archive_from_expsyms_cmds_F77=
+ export_dynamic_flag_spec_F77=
+ whole_archive_flag_spec_F77=
+ thread_safe_flag_spec_F77=
+ hardcode_libdir_flag_spec_F77=
+ hardcode_libdir_flag_spec_ld_F77=
+ hardcode_libdir_separator_F77=
+ hardcode_direct_F77=no
+ hardcode_minus_L_F77=no
+ hardcode_shlibpath_var_F77=unsupported
+ link_all_deplibs_F77=unknown
+ hardcode_automatic_F77=no
+ module_cmds_F77=
+ module_expsym_cmds_F77=
+ always_export_symbols_F77=no
+ export_symbols_cmds_F77='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+ # include_expsyms should be a list of space-separated symbols to be *always*
+ # included in the symbol list
+ include_expsyms_F77=
+ # exclude_expsyms can be an extended regexp of symbols to exclude
+ # it will be wrapped by ` (' and `)$', so one must not match beginning or
+ # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc',
+ # as well as any symbol that contains `d'.
+ exclude_expsyms_F77="_GLOBAL_OFFSET_TABLE_"
+ # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
+ # platforms (ab)use it in PIC code, but their linkers get confused if
+ # the symbol is explicitly referenced. Since portable code cannot
+ # rely on this symbol name, it's probably fine to never include it in
+ # preloaded symbol tables.
+ extract_expsyms_cmds=
+ # Just being paranoid about ensuring that cc_basename is set.
+ for cc_temp in $compiler""; do
+ case $cc_temp in
+ compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
+ distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
+ \-*) ;;
+ *) break;;
+ esac
+done
+cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"`
+
+ case $host_os in
+ cygwin* | mingw* | pw32*)
+ # FIXME: the MSVC++ port hasn't been tested in a loooong time
+ # When not using gcc, we currently assume that we are using
+ # Microsoft Visual C++.
+ if test "$GCC" != yes; then
+ with_gnu_ld=no
+ fi
+ ;;
+ interix*)
+ # we just hope/assume this is gcc and not c89 (= MSVC++)
+ with_gnu_ld=yes
+ ;;
+ openbsd*)
+ with_gnu_ld=no
+ ;;
+ esac
+
+ ld_shlibs_F77=yes
+ if test "$with_gnu_ld" = yes; then
+ # If archive_cmds runs LD, not CC, wlarc should be empty
+ wlarc='${wl}'
+
+ # Set some defaults for GNU ld with shared library support. These
+ # are reset later if shared libraries are not supported. Putting them
+ # here allows them to be overridden if necessary.
+ runpath_var=LD_RUN_PATH
+ hardcode_libdir_flag_spec_F77='${wl}--rpath ${wl}$libdir'
+ export_dynamic_flag_spec_F77='${wl}--export-dynamic'
+ # ancient GNU ld didn't support --whole-archive et. al.
+ if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then
+ whole_archive_flag_spec_F77="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+ else
+ whole_archive_flag_spec_F77=
+ fi
+ supports_anon_versioning=no
+ case `$LD -v 2>/dev/null` in
+ *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11
+ *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ...
+ *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ...
+ *\ 2.11.*) ;; # other 2.11 versions
+ *) supports_anon_versioning=yes ;;
+ esac
+
+ # See if GNU ld supports shared libraries.
+ case $host_os in
+ aix3* | aix4* | aix5*)
+ # On AIX/PPC, the GNU linker is very broken
+ if test "$host_cpu" != ia64; then
+ ld_shlibs_F77=no
+ cat <<EOF 1>&2
+
+*** Warning: the GNU linker, at least up to release 2.9.1, is reported
+*** to be unable to reliably create shared libraries on AIX.
+*** Therefore, libtool is disabling shared libraries support. If you
+*** really care for shared libraries, you may want to modify your PATH
+*** so that a non-GNU linker is found, and then restart.
+
+EOF
+ fi
+ ;;
+
+ amigaos*)
+ archive_cmds_F77='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+ hardcode_libdir_flag_spec_F77='-L$libdir'
+ hardcode_minus_L_F77=yes
+
+ # Samuel A. Falvo II <kc5tja at dolphin.openprojects.net> reports
+ # that the semantics of dynamic libraries on AmigaOS, at least up
+ # to version 4, is to share data among multiple programs linked
+ # with the same dynamic library. Since this doesn't match the
+ # behavior of shared libraries on other platforms, we can't use
+ # them.
+ ld_shlibs_F77=no
+ ;;
+
+ beos*)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ allow_undefined_flag_F77=unsupported
+ # Joseph Beckenbach <jrb3 at best.com> says some releases of gcc
+ # support --undefined. This deserves some investigation. FIXME
+ archive_cmds_F77='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ else
+ ld_shlibs_F77=no
+ fi
+ ;;
+
+ cygwin* | mingw* | pw32*)
+ # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, F77) is actually meaningless,
+ # as there is no search path for DLLs.
+ hardcode_libdir_flag_spec_F77='-L$libdir'
+ allow_undefined_flag_F77=unsupported
+ always_export_symbols_F77=no
+ enable_shared_with_static_runtimes_F77=yes
+ export_symbols_cmds_F77='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS] /s/.* \([^ ]*\)/\1 DATA/'\'' | $SED -e '\''/^[AITW] /s/.* //'\'' | sort | uniq > $export_symbols'
+
+ if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then
+ archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+ # If the export-symbols file already is a .def file (1st line
+ # is EXPORTS), use it as is; otherwise, prepend...
+ archive_expsym_cmds_F77='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
+ cp $export_symbols $output_objdir/$soname.def;
+ else
+ echo EXPORTS > $output_objdir/$soname.def;
+ cat $export_symbols >> $output_objdir/$soname.def;
+ fi~
+ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+ else
+ ld_shlibs_F77=no
+ fi
+ ;;
+
+ interix3*)
+ hardcode_direct_F77=no
+ hardcode_shlibpath_var_F77=no
+ hardcode_libdir_flag_spec_F77='${wl}-rpath,$libdir'
+ export_dynamic_flag_spec_F77='${wl}-E'
+ # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
+ # Instead, shared libraries are loaded at an image base (0x10000000 by
+ # default) and relocated if they conflict, which is a slow very memory
+ # consuming and fragmenting process. To avoid this, we pick a random,
+ # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
+ # time. Moving up from 0x10000000 also allows more sbrk(2) space.
+ archive_cmds_F77='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+ archive_expsym_cmds_F77='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+ ;;
+
+ linux*)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ tmp_addflag=
+ case $cc_basename,$host_cpu in
+ pgcc*) # Portland Group C compiler
+ whole_archive_flag_spec_F77='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
+ tmp_addflag=' $pic_flag'
+ ;;
+ pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers
+ whole_archive_flag_spec_F77='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
+ tmp_addflag=' $pic_flag -Mnomain' ;;
+ ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64
+ tmp_addflag=' -i_dynamic' ;;
+ efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64
+ tmp_addflag=' -i_dynamic -nofor_main' ;;
+ ifc* | ifort*) # Intel Fortran compiler
+ tmp_addflag=' -nofor_main' ;;
+ esac
+ archive_cmds_F77='$CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+
+ if test $supports_anon_versioning = yes; then
+ archive_expsym_cmds_F77='$echo "{ global:" > $output_objdir/$libname.ver~
+ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+ $echo "local: *; };" >> $output_objdir/$libname.ver~
+ $CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib'
+ fi
+ else
+ ld_shlibs_F77=no
+ fi
+ ;;
+
+ netbsd*)
+ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+ archive_cmds_F77='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
+ wlarc=
+ else
+ archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ fi
+ ;;
+
+ solaris*)
+ if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then
+ ld_shlibs_F77=no
+ cat <<EOF 1>&2
+
+*** Warning: The releases 2.8.* of the GNU linker cannot reliably
+*** create shared libraries on Solaris systems. Therefore, libtool
+*** is disabling shared libraries support. We urge you to upgrade GNU
+*** binutils to release 2.9.1 or newer. Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+EOF
+ elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ else
+ ld_shlibs_F77=no
+ fi
+ ;;
+
+ sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*)
+ case `$LD -v 2>&1` in
+ *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*)
+ ld_shlibs_F77=no
+ cat <<_LT_EOF 1>&2
+
+*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not
+*** reliably create shared libraries on SCO systems. Therefore, libtool
+*** is disabling shared libraries support. We urge you to upgrade GNU
+*** binutils to release 2.16.91.0.3 or newer. Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+_LT_EOF
+ ;;
+ *)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ hardcode_libdir_flag_spec_F77='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`'
+ archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib'
+ archive_expsym_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname,-retain-symbols-file,$export_symbols -o $lib'
+ else
+ ld_shlibs_F77=no
+ fi
+ ;;
+ esac
+ ;;
+
+ sunos4*)
+ archive_cmds_F77='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+ wlarc=
+ hardcode_direct_F77=yes
+ hardcode_shlibpath_var_F77=no
+ ;;
+
+ *)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ else
+ ld_shlibs_F77=no
+ fi
+ ;;
+ esac
+
+ if test "$ld_shlibs_F77" = no; then
+ runpath_var=
+ hardcode_libdir_flag_spec_F77=
+ export_dynamic_flag_spec_F77=
+ whole_archive_flag_spec_F77=
+ fi
+ else
+ # PORTME fill in a description of your system's linker (not GNU ld)
+ case $host_os in
+ aix3*)
+ allow_undefined_flag_F77=unsupported
+ always_export_symbols_F77=yes
+ archive_expsym_cmds_F77='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname'
+ # Note: this linker hardcodes the directories in LIBPATH if there
+ # are no directories specified by -L.
+ hardcode_minus_L_F77=yes
+ if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then
+ # Neither direct hardcoding nor static linking is supported with a
+ # broken collect2.
+ hardcode_direct_F77=unsupported
+ fi
+ ;;
+
+ aix4* | aix5*)
+ if test "$host_cpu" = ia64; then
+ # On IA64, the linker does run time linking by default, so we don't
+ # have to do anything special.
+ aix_use_runtimelinking=no
+ exp_sym_flag='-Bexport'
+ no_entry_flag=""
+ else
+ # If we're using GNU nm, then we don't want the "-C" option.
+ # -C means demangle to AIX nm, but means don't demangle with GNU nm
+ if $NM -V 2>&1 | grep 'GNU' > /dev/null; then
+ export_symbols_cmds_F77='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols'
+ else
+ export_symbols_cmds_F77='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols'
+ fi
+ aix_use_runtimelinking=no
+
+ # Test if we are trying to use run time linking or normal
+ # AIX style linking. If -brtl is somewhere in LDFLAGS, we
+ # need to do runtime linking.
+ case $host_os in aix4.[23]|aix4.[23].*|aix5*)
+ for ld_flag in $LDFLAGS; do
+ if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then
+ aix_use_runtimelinking=yes
+ break
+ fi
+ done
+ ;;
+ esac
+
+ exp_sym_flag='-bexport'
+ no_entry_flag='-bnoentry'
+ fi
+
+ # When large executables or shared objects are built, AIX ld can
+ # have problems creating the table of contents. If linking a library
+ # or program results in "error TOC overflow" add -mminimal-toc to
+ # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not
+ # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+ archive_cmds_F77=''
+ hardcode_direct_F77=yes
+ hardcode_libdir_separator_F77=':'
+ link_all_deplibs_F77=yes
+
+ if test "$GCC" = yes; then
+ case $host_os in aix4.[012]|aix4.[012].*)
+ # We only want to do this on AIX 4.2 and lower, the check
+ # below for broken collect2 doesn't work under 4.3+
+ collect2name=`${CC} -print-prog-name=collect2`
+ if test -f "$collect2name" && \
+ strings "$collect2name" | grep resolve_lib_name >/dev/null
+ then
+ # We have reworked collect2
+ hardcode_direct_F77=yes
+ else
+ # We have old collect2
+ hardcode_direct_F77=unsupported
+ # It fails to find uninstalled libraries when the uninstalled
+ # path is not listed in the libpath. Setting hardcode_minus_L
+ # to unsupported forces relinking
+ hardcode_minus_L_F77=yes
+ hardcode_libdir_flag_spec_F77='-L$libdir'
+ hardcode_libdir_separator_F77=
+ fi
+ ;;
+ esac
+ shared_flag='-shared'
+ if test "$aix_use_runtimelinking" = yes; then
+ shared_flag="$shared_flag "'${wl}-G'
+ fi
+ else
+ # not using gcc
+ if test "$host_cpu" = ia64; then
+ # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+ # chokes on -Wl,-G. The following line is correct:
+ shared_flag='-G'
+ else
+ if test "$aix_use_runtimelinking" = yes; then
+ shared_flag='${wl}-G'
+ else
+ shared_flag='${wl}-bM:SRE'
+ fi
+ fi
+ fi
+
+ # It seems that -bexpall does not export symbols beginning with
+ # underscore (_), so it is better to generate a list of symbols to export.
+ always_export_symbols_F77=yes
+ if test "$aix_use_runtimelinking" = yes; then
+ # Warning - without using the other runtime loading flags (-brtl),
+ # -berok will link without error, but may produce a broken library.
+ allow_undefined_flag_F77='-berok'
+ # Determine the default libpath from the value encoded in an empty executable.
+ cat >conftest.$ac_ext <<_ACEOF
+ program main
+
+ end
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_f77_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+
+aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`
+# Check for a 64-bit object if we didn't find anything.
+if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`; fi
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+
+ hardcode_libdir_flag_spec_F77='${wl}-blibpath:$libdir:'"$aix_libpath"
+ archive_expsym_cmds_F77="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+ else
+ if test "$host_cpu" = ia64; then
+ hardcode_libdir_flag_spec_F77='${wl}-R $libdir:/usr/lib:/lib'
+ allow_undefined_flag_F77="-z nodefs"
+ archive_expsym_cmds_F77="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols"
+ else
+ # Determine the default libpath from the value encoded in an empty executable.
+ cat >conftest.$ac_ext <<_ACEOF
+ program main
+
+ end
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_f77_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+
+aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`
+# Check for a 64-bit object if we didn't find anything.
+if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`; fi
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+
+ hardcode_libdir_flag_spec_F77='${wl}-blibpath:$libdir:'"$aix_libpath"
+ # Warning - without using the other run time loading flags,
+ # -berok will link without error, but may produce a broken library.
+ no_undefined_flag_F77=' ${wl}-bernotok'
+ allow_undefined_flag_F77=' ${wl}-berok'
+ # Exported symbols can be pulled into shared objects from archives
+ whole_archive_flag_spec_F77='$convenience'
+ archive_cmds_need_lc_F77=yes
+ # This is similar to how AIX traditionally builds its shared libraries.
+ archive_expsym_cmds_F77="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
+ fi
+ fi
+ ;;
+
+ amigaos*)
+ archive_cmds_F77='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+ hardcode_libdir_flag_spec_F77='-L$libdir'
+ hardcode_minus_L_F77=yes
+ # see comment about different semantics on the GNU ld section
+ ld_shlibs_F77=no
+ ;;
+
+ bsdi[45]*)
+ export_dynamic_flag_spec_F77=-rdynamic
+ ;;
+
+ cygwin* | mingw* | pw32*)
+ # When not using gcc, we currently assume that we are using
+ # Microsoft Visual C++.
+ # hardcode_libdir_flag_spec is actually meaningless, as there is
+ # no search path for DLLs.
+ hardcode_libdir_flag_spec_F77=' '
+ allow_undefined_flag_F77=unsupported
+ # Tell ltmain to make .lib files, not .a files.
+ libext=lib
+ # Tell ltmain to make .dll files, not .so files.
+ shrext_cmds=".dll"
+ # FIXME: Setting linknames here is a bad hack.
+ archive_cmds_F77='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames='
+ # The linker will automatically build a .lib file if we build a DLL.
+ old_archive_From_new_cmds_F77='true'
+ # FIXME: Should let the user specify the lib program.
+ old_archive_cmds_F77='lib /OUT:$oldlib$oldobjs$old_deplibs'
+ fix_srcfile_path_F77='`cygpath -w "$srcfile"`'
+ enable_shared_with_static_runtimes_F77=yes
+ ;;
+
+ darwin* | rhapsody*)
+ case $host_os in
+ rhapsody* | darwin1.[012])
+ allow_undefined_flag_F77='${wl}-undefined ${wl}suppress'
+ ;;
+ *) # Darwin 1.3 on
+ if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then
+ allow_undefined_flag_F77='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
+ else
+ case ${MACOSX_DEPLOYMENT_TARGET} in
+ 10.[012])
+ allow_undefined_flag_F77='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
+ ;;
+ 10.*)
+ allow_undefined_flag_F77='${wl}-undefined ${wl}dynamic_lookup'
+ ;;
+ esac
+ fi
+ ;;
+ esac
+ archive_cmds_need_lc_F77=no
+ hardcode_direct_F77=no
+ hardcode_automatic_F77=yes
+ hardcode_shlibpath_var_F77=unsupported
+ whole_archive_flag_spec_F77=''
+ link_all_deplibs_F77=yes
+ if test "$GCC" = yes ; then
+ output_verbose_link_cmd='echo'
+ archive_cmds_F77='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring'
+ module_cmds_F77='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
+ # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
+ archive_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ module_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ else
+ case $cc_basename in
+ xlc*)
+ output_verbose_link_cmd='echo'
+ archive_cmds_F77='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring'
+ module_cmds_F77='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
+ # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
+ archive_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ module_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ ;;
+ *)
+ ld_shlibs_F77=no
+ ;;
+ esac
+ fi
+ ;;
+
+ dgux*)
+ archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_libdir_flag_spec_F77='-L$libdir'
+ hardcode_shlibpath_var_F77=no
+ ;;
+
+ freebsd1*)
+ ld_shlibs_F77=no
+ ;;
+
+ # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
+ # support. Future versions do this automatically, but an explicit c++rt0.o
+ # does not break anything, and helps significantly (at the cost of a little
+ # extra space).
+ freebsd2.2*)
+ archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o'
+ hardcode_libdir_flag_spec_F77='-R$libdir'
+ hardcode_direct_F77=yes
+ hardcode_shlibpath_var_F77=no
+ ;;
+
+ # Unfortunately, older versions of FreeBSD 2 do not have this feature.
+ freebsd2*)
+ archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_direct_F77=yes
+ hardcode_minus_L_F77=yes
+ hardcode_shlibpath_var_F77=no
+ ;;
+
+ # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
+ freebsd* | kfreebsd*-gnu | dragonfly*)
+ archive_cmds_F77='$CC -shared -o $lib $libobjs $deplibs $compiler_flags'
+ hardcode_libdir_flag_spec_F77='-R$libdir'
+ hardcode_direct_F77=yes
+ hardcode_shlibpath_var_F77=no
+ ;;
+
+ hpux9*)
+ if test "$GCC" = yes; then
+ archive_cmds_F77='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+ else
+ archive_cmds_F77='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+ fi
+ hardcode_libdir_flag_spec_F77='${wl}+b ${wl}$libdir'
+ hardcode_libdir_separator_F77=:
+ hardcode_direct_F77=yes
+
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ hardcode_minus_L_F77=yes
+ export_dynamic_flag_spec_F77='${wl}-E'
+ ;;
+
+ hpux10*)
+ if test "$GCC" = yes -a "$with_gnu_ld" = no; then
+ archive_cmds_F77='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ archive_cmds_F77='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
+ fi
+ if test "$with_gnu_ld" = no; then
+ hardcode_libdir_flag_spec_F77='${wl}+b ${wl}$libdir'
+ hardcode_libdir_separator_F77=:
+
+ hardcode_direct_F77=yes
+ export_dynamic_flag_spec_F77='${wl}-E'
+
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ hardcode_minus_L_F77=yes
+ fi
+ ;;
+
+ hpux11*)
+ if test "$GCC" = yes -a "$with_gnu_ld" = no; then
+ case $host_cpu in
+ hppa*64*)
+ archive_cmds_F77='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ ia64*)
+ archive_cmds_F77='$CC -shared ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ *)
+ archive_cmds_F77='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ esac
+ else
+ case $host_cpu in
+ hppa*64*)
+ archive_cmds_F77='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ ia64*)
+ archive_cmds_F77='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ *)
+ archive_cmds_F77='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ esac
+ fi
+ if test "$with_gnu_ld" = no; then
+ hardcode_libdir_flag_spec_F77='${wl}+b ${wl}$libdir'
+ hardcode_libdir_separator_F77=:
+
+ case $host_cpu in
+ hppa*64*|ia64*)
+ hardcode_libdir_flag_spec_ld_F77='+b $libdir'
+ hardcode_direct_F77=no
+ hardcode_shlibpath_var_F77=no
+ ;;
+ *)
+ hardcode_direct_F77=yes
+ export_dynamic_flag_spec_F77='${wl}-E'
+
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ hardcode_minus_L_F77=yes
+ ;;
+ esac
+ fi
+ ;;
+
+ irix5* | irix6* | nonstopux*)
+ if test "$GCC" = yes; then
+ archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ else
+ archive_cmds_F77='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+ hardcode_libdir_flag_spec_ld_F77='-rpath $libdir'
+ fi
+ hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator_F77=:
+ link_all_deplibs_F77=yes
+ ;;
+
+ netbsd*)
+ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+ archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out
+ else
+ archive_cmds_F77='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF
+ fi
+ hardcode_libdir_flag_spec_F77='-R$libdir'
+ hardcode_direct_F77=yes
+ hardcode_shlibpath_var_F77=no
+ ;;
+
+ newsos6)
+ archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_direct_F77=yes
+ hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator_F77=:
+ hardcode_shlibpath_var_F77=no
+ ;;
+
+ openbsd*)
+ hardcode_direct_F77=yes
+ hardcode_shlibpath_var_F77=no
+ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ archive_cmds_F77='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds_F77='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols'
+ hardcode_libdir_flag_spec_F77='${wl}-rpath,$libdir'
+ export_dynamic_flag_spec_F77='${wl}-E'
+ else
+ case $host_os in
+ openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*)
+ archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_libdir_flag_spec_F77='-R$libdir'
+ ;;
+ *)
+ archive_cmds_F77='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+ hardcode_libdir_flag_spec_F77='${wl}-rpath,$libdir'
+ ;;
+ esac
+ fi
+ ;;
+
+ os2*)
+ hardcode_libdir_flag_spec_F77='-L$libdir'
+ hardcode_minus_L_F77=yes
+ allow_undefined_flag_F77=unsupported
+ archive_cmds_F77='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def'
+ old_archive_From_new_cmds_F77='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def'
+ ;;
+
+ osf3*)
+ if test "$GCC" = yes; then
+ allow_undefined_flag_F77=' ${wl}-expect_unresolved ${wl}\*'
+ archive_cmds_F77='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ else
+ allow_undefined_flag_F77=' -expect_unresolved \*'
+ archive_cmds_F77='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+ fi
+ hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator_F77=:
+ ;;
+
+ osf4* | osf5*) # as osf3* with the addition of -msym flag
+ if test "$GCC" = yes; then
+ allow_undefined_flag_F77=' ${wl}-expect_unresolved ${wl}\*'
+ archive_cmds_F77='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir'
+ else
+ allow_undefined_flag_F77=' -expect_unresolved \*'
+ archive_cmds_F77='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+ archive_expsym_cmds_F77='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~
+ $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~$rm $lib.exp'
+
+ # Both c and cxx compiler support -rpath directly
+ hardcode_libdir_flag_spec_F77='-rpath $libdir'
+ fi
+ hardcode_libdir_separator_F77=:
+ ;;
+
+ solaris*)
+ no_undefined_flag_F77=' -z text'
+ if test "$GCC" = yes; then
+ wlarc='${wl}'
+ archive_cmds_F77='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds_F77='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+ $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp'
+ else
+ wlarc=''
+ archive_cmds_F77='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ archive_expsym_cmds_F77='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp'
+ fi
+ hardcode_libdir_flag_spec_F77='-R$libdir'
+ hardcode_shlibpath_var_F77=no
+ case $host_os in
+ solaris2.[0-5] | solaris2.[0-5].*) ;;
+ *)
+ # The compiler driver will combine linker options so we
+ # cannot just pass the convience library names through
+ # without $wl, iff we do not link with $LD.
+ # Luckily, gcc supports the same syntax we need for Sun Studio.
+ # Supported since Solaris 2.6 (maybe 2.5.1?)
+ case $wlarc in
+ '')
+ whole_archive_flag_spec_F77='-z allextract$convenience -z defaultextract' ;;
+ *)
+ whole_archive_flag_spec_F77='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract' ;;
+ esac ;;
+ esac
+ link_all_deplibs_F77=yes
+ ;;
+
+ sunos4*)
+ if test "x$host_vendor" = xsequent; then
+ # Use $CC to link under sequent, because it throws in some extra .o
+ # files that make .init and .fini sections work.
+ archive_cmds_F77='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ archive_cmds_F77='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags'
+ fi
+ hardcode_libdir_flag_spec_F77='-L$libdir'
+ hardcode_direct_F77=yes
+ hardcode_minus_L_F77=yes
+ hardcode_shlibpath_var_F77=no
+ ;;
+
+ sysv4)
+ case $host_vendor in
+ sni)
+ archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_direct_F77=yes # is this really true???
+ ;;
+ siemens)
+ ## LD is ld it makes a PLAMLIB
+ ## CC just makes a GrossModule.
+ archive_cmds_F77='$LD -G -o $lib $libobjs $deplibs $linker_flags'
+ reload_cmds_F77='$CC -r -o $output$reload_objs'
+ hardcode_direct_F77=no
+ ;;
+ motorola)
+ archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_direct_F77=no #Motorola manual says yes, but my tests say they lie
+ ;;
+ esac
+ runpath_var='LD_RUN_PATH'
+ hardcode_shlibpath_var_F77=no
+ ;;
+
+ sysv4.3*)
+ archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_shlibpath_var_F77=no
+ export_dynamic_flag_spec_F77='-Bexport'
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_shlibpath_var_F77=no
+ runpath_var=LD_RUN_PATH
+ hardcode_runpath_var=yes
+ ld_shlibs_F77=yes
+ fi
+ ;;
+
+ sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7*)
+ no_undefined_flag_F77='${wl}-z,text'
+ archive_cmds_need_lc_F77=no
+ hardcode_shlibpath_var_F77=no
+ runpath_var='LD_RUN_PATH'
+
+ if test "$GCC" = yes; then
+ archive_cmds_F77='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds_F77='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ archive_cmds_F77='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds_F77='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ fi
+ ;;
+
+ sysv5* | sco3.2v5* | sco5v6*)
+ # Note: We can NOT use -z defs as we might desire, because we do not
+ # link with -lc, and that would cause any symbols used from libc to
+ # always be unresolved, which means just about no library would
+ # ever link correctly. If we're not using GNU ld we use -z text
+ # though, which does catch some bad symbols but isn't as heavy-handed
+ # as -z defs.
+ no_undefined_flag_F77='${wl}-z,text'
+ allow_undefined_flag_F77='${wl}-z,nodefs'
+ archive_cmds_need_lc_F77=no
+ hardcode_shlibpath_var_F77=no
+ hardcode_libdir_flag_spec_F77='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`'
+ hardcode_libdir_separator_F77=':'
+ link_all_deplibs_F77=yes
+ export_dynamic_flag_spec_F77='${wl}-Bexport'
+ runpath_var='LD_RUN_PATH'
+
+ if test "$GCC" = yes; then
+ archive_cmds_F77='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds_F77='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ archive_cmds_F77='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds_F77='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ fi
+ ;;
+
+ uts4*)
+ archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_libdir_flag_spec_F77='-L$libdir'
+ hardcode_shlibpath_var_F77=no
+ ;;
+
+ *)
+ ld_shlibs_F77=no
+ ;;
+ esac
+ fi
+
+echo "$as_me:$LINENO: result: $ld_shlibs_F77" >&5
+echo "${ECHO_T}$ld_shlibs_F77" >&6
+test "$ld_shlibs_F77" = no && can_build_shared=no
+
+#
+# Do we need to explicitly link libc?
+#
+case "x$archive_cmds_need_lc_F77" in
+x|xyes)
+ # Assume -lc should be added
+ archive_cmds_need_lc_F77=yes
+
+ if test "$enable_shared" = yes && test "$GCC" = yes; then
+ case $archive_cmds_F77 in
+ *'~'*)
+ # FIXME: we may have to deal with multi-command sequences.
+ ;;
+ '$CC '*)
+ # Test whether the compiler implicitly links with -lc since on some
+ # systems, -lgcc has to come before -lc. If gcc already passes -lc
+ # to ld, don't add -lc before -lgcc.
+ echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5
+echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6
+ $rm conftest*
+ printf "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } 2>conftest.err; then
+ soname=conftest
+ lib=conftest
+ libobjs=conftest.$ac_objext
+ deplibs=
+ wl=$lt_prog_compiler_wl_F77
+ pic_flag=$lt_prog_compiler_pic_F77
+ compiler_flags=-v
+ linker_flags=-v
+ verstring=
+ output_objdir=.
+ libname=conftest
+ lt_save_allow_undefined_flag=$allow_undefined_flag_F77
+ allow_undefined_flag_F77=
+ if { (eval echo "$as_me:$LINENO: \"$archive_cmds_F77 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\"") >&5
+ (eval $archive_cmds_F77 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+ then
+ archive_cmds_need_lc_F77=no
+ else
+ archive_cmds_need_lc_F77=yes
+ fi
+ allow_undefined_flag_F77=$lt_save_allow_undefined_flag
+ else
+ cat conftest.err 1>&5
+ fi
+ $rm conftest*
+ echo "$as_me:$LINENO: result: $archive_cmds_need_lc_F77" >&5
+echo "${ECHO_T}$archive_cmds_need_lc_F77" >&6
+ ;;
+ esac
+ fi
+ ;;
+esac
+
+echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5
+echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6
+library_names_spec=
+libname_spec='lib$name'
+soname_spec=
+shrext_cmds=".so"
+postinstall_cmds=
+postuninstall_cmds=
+finish_cmds=
+finish_eval=
+shlibpath_var=
+shlibpath_overrides_runpath=unknown
+version_type=none
+dynamic_linker="$host_os ld.so"
+sys_lib_dlsearch_path_spec="/lib /usr/lib"
+if test "$GCC" = yes; then
+ sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
+ if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then
+ # if the path contains ";" then we assume it to be the separator
+ # otherwise default to the standard path separator (i.e. ":") - it is
+ # assumed that no part of a normal pathname contains ";" but that should
+ # okay in the real world where ";" in dirpaths is itself problematic.
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+ else
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+ fi
+else
+ sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
+fi
+need_lib_prefix=unknown
+hardcode_into_libs=no
+
+# when you set need_version to no, make sure it does not cause -set_version
+# flags to be left without arguments
+need_version=unknown
+
+case $host_os in
+aix3*)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a'
+ shlibpath_var=LIBPATH
+
+ # AIX 3 has no versioning support, so we append a major version to the name.
+ soname_spec='${libname}${release}${shared_ext}$major'
+ ;;
+
+aix4* | aix5*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ hardcode_into_libs=yes
+ if test "$host_cpu" = ia64; then
+ # AIX 5 supports IA64
+ library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ else
+ # With GCC up to 2.95.x, collect2 would create an import file
+ # for dependence libraries. The import file would start with
+ # the line `#! .'. This would cause the generated library to
+ # depend on `.', always an invalid library. This was fixed in
+ # development snapshots of GCC prior to 3.0.
+ case $host_os in
+ aix4 | aix4.[01] | aix4.[01].*)
+ if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
+ echo ' yes '
+ echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then
+ :
+ else
+ can_build_shared=no
+ fi
+ ;;
+ esac
+ # AIX (on Power*) has no versioning support, so currently we can not hardcode correct
+ # soname into executable. Probably we can add versioning support to
+ # collect2, so additional links can be useful in future.
+ if test "$aix_use_runtimelinking" = yes; then
+ # If using run time linking (on AIX 4.2 or later) use lib<name>.so
+ # instead of lib<name>.a to let people know that these are not
+ # typical AIX shared libraries.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ else
+ # We preserve .a as extension for shared libraries through AIX4.2
+ # and later when we are not doing run time linking.
+ library_names_spec='${libname}${release}.a $libname.a'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ fi
+ shlibpath_var=LIBPATH
+ fi
+ ;;
+
+amigaos*)
+ library_names_spec='$libname.ixlibrary $libname.a'
+ # Create ${libname}_ixlibrary.a entries in /sys/libs.
+ finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
+ ;;
+
+beos*)
+ library_names_spec='${libname}${shared_ext}'
+ dynamic_linker="$host_os ld.so"
+ shlibpath_var=LIBRARY_PATH
+ ;;
+
+bsdi[45]*)
+ version_type=linux
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
+ sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
+ # the default ld.so.conf also contains /usr/contrib/lib and
+ # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
+ # libtool to hard-code these into programs
+ ;;
+
+cygwin* | mingw* | pw32*)
+ version_type=windows
+ shrext_cmds=".dll"
+ need_version=no
+ need_lib_prefix=no
+
+ case $GCC,$host_os in
+ yes,cygwin* | yes,mingw* | yes,pw32*)
+ library_names_spec='$libname.dll.a'
+ # DLL is installed to $(libdir)/../bin by postinstall_cmds
+ postinstall_cmds='base_file=`basename \${file}`~
+ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~
+ dldir=$destdir/`dirname \$dlpath`~
+ test -d \$dldir || mkdir -p \$dldir~
+ $install_prog $dir/$dlname \$dldir/$dlname~
+ chmod a+x \$dldir/$dlname'
+ postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+ dlpath=$dir/\$dldll~
+ $rm \$dlpath'
+ shlibpath_overrides_runpath=yes
+
+ case $host_os in
+ cygwin*)
+ # Cygwin DLLs use 'cyg' prefix rather than 'lib'
+ soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+ sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib"
+ ;;
+ mingw*)
+ # MinGW DLLs use traditional 'lib' prefix
+ soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+ sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
+ if echo "$sys_lib_search_path_spec" | grep ';[c-zC-Z]:/' >/dev/null; then
+ # It is most probably a Windows format PATH printed by
+ # mingw gcc, but we are running on Cygwin. Gcc prints its search
+ # path with ; separators, and with drive letters. We can handle the
+ # drive letters (cygwin fileutils understands them), so leave them,
+ # especially as we might pass files found there to a mingw objdump,
+ # which wouldn't understand a cygwinified path. Ahh.
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+ else
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+ fi
+ ;;
+ pw32*)
+ # pw32 DLLs use 'pw' prefix rather than 'lib'
+ library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+ ;;
+ esac
+ ;;
+
+ *)
+ library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib'
+ ;;
+ esac
+ dynamic_linker='Win32 ld.exe'
+ # FIXME: first we should search . and the directory the executable is in
+ shlibpath_var=PATH
+ ;;
+
+darwin* | rhapsody*)
+ dynamic_linker="$host_os dyld"
+ version_type=darwin
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext'
+ soname_spec='${libname}${release}${major}$shared_ext'
+ shlibpath_overrides_runpath=yes
+ shlibpath_var=DYLD_LIBRARY_PATH
+ shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
+ # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same.
+ if test "$GCC" = yes; then
+ sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"`
+ else
+ sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib'
+ fi
+ sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
+ ;;
+
+dgux*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+freebsd1*)
+ dynamic_linker=no
+ ;;
+
+kfreebsd*-gnu)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ dynamic_linker='GNU ld.so'
+ ;;
+
+freebsd* | dragonfly*)
+ # DragonFly does not have aout. When/if they implement a new
+ # versioning mechanism, adjust this.
+ if test -x /usr/bin/objformat; then
+ objformat=`/usr/bin/objformat`
+ else
+ case $host_os in
+ freebsd[123]*) objformat=aout ;;
+ *) objformat=elf ;;
+ esac
+ fi
+ version_type=freebsd-$objformat
+ case $version_type in
+ freebsd-elf*)
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+ need_version=no
+ need_lib_prefix=no
+ ;;
+ freebsd-*)
+ library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix'
+ need_version=yes
+ ;;
+ esac
+ shlibpath_var=LD_LIBRARY_PATH
+ case $host_os in
+ freebsd2*)
+ shlibpath_overrides_runpath=yes
+ ;;
+ freebsd3.[01]* | freebsdelf3.[01]*)
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+ freebsd3.[2-9]* | freebsdelf3.[2-9]* | \
+ freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1)
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ ;;
+ freebsd*) # from 4.6 on
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+ esac
+ ;;
+
+gnu*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ hardcode_into_libs=yes
+ ;;
+
+hpux9* | hpux10* | hpux11*)
+ # Give a soname corresponding to the major version so that dld.sl refuses to
+ # link against other versions.
+ version_type=sunos
+ need_lib_prefix=no
+ need_version=no
+ case $host_cpu in
+ ia64*)
+ shrext_cmds='.so'
+ hardcode_into_libs=yes
+ dynamic_linker="$host_os dld.so"
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ if test "X$HPUX_IA64_MODE" = X32; then
+ sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
+ else
+ sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
+ fi
+ sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+ ;;
+ hppa*64*)
+ shrext_cmds='.sl'
+ hardcode_into_libs=yes
+ dynamic_linker="$host_os dld.sl"
+ shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
+ shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
+ sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+ ;;
+ *)
+ shrext_cmds='.sl'
+ dynamic_linker="$host_os dld.sl"
+ shlibpath_var=SHLIB_PATH
+ shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ ;;
+ esac
+ # HP-UX runs *really* slowly unless shared libraries are mode 555.
+ postinstall_cmds='chmod 555 $lib'
+ ;;
+
+interix3*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ ;;
+
+irix5* | irix6* | nonstopux*)
+ case $host_os in
+ nonstopux*) version_type=nonstopux ;;
+ *)
+ if test "$lt_cv_prog_gnu_ld" = yes; then
+ version_type=linux
+ else
+ version_type=irix
+ fi ;;
+ esac
+ need_lib_prefix=no
+ need_version=no
+ soname_spec='${libname}${release}${shared_ext}$major'
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}'
+ case $host_os in
+ irix5* | nonstopux*)
+ libsuff= shlibsuff=
+ ;;
+ *)
+ case $LD in # libtool.m4 will add one of these switches to LD
+ *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ")
+ libsuff= shlibsuff= libmagic=32-bit;;
+ *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ")
+ libsuff=32 shlibsuff=N32 libmagic=N32;;
+ *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ")
+ libsuff=64 shlibsuff=64 libmagic=64-bit;;
+ *) libsuff= shlibsuff= libmagic=never-match;;
+ esac
+ ;;
+ esac
+ shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
+ shlibpath_overrides_runpath=no
+ sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
+ sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
+ hardcode_into_libs=yes
+ ;;
+
+# No shared lib support for Linux oldld, aout, or coff.
+linux*oldld* | linux*aout* | linux*coff*)
+ dynamic_linker=no
+ ;;
+
+# This must be Linux ELF.
+linux*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ # This implies no fast_install, which is unacceptable.
+ # Some rework will be needed to allow for fast_install
+ # before this can be enabled.
+ hardcode_into_libs=yes
+
+ # find out which ABI we are using
+ libsuff=
+ case "$host_cpu" in
+ x86_64*|s390x*|powerpc64*)
+ echo '#line 22214 "configure"' > conftest.$ac_ext
+ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ case `/usr/bin/file conftest.$ac_objext` in
+ *64-bit*)
+ libsuff=64
+ sys_lib_search_path_spec="/lib${libsuff} /usr/lib${libsuff} /usr/local/lib${libsuff}"
+ ;;
+ esac
+ fi
+ rm -rf conftest*
+ ;;
+ esac
+
+ # Append ld.so.conf contents to the search path
+ if test -f /etc/ld.so.conf; then
+ lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '`
+ sys_lib_dlsearch_path_spec="/lib${libsuff} /usr/lib${libsuff} $lt_ld_extra"
+ fi
+
+ # We used to test for /lib/ld.so.1 and disable shared libraries on
+ # powerpc, because MkLinux only supported shared libraries with the
+ # GNU dynamic linker. Since this was broken with cross compilers,
+ # most powerpc-linux boxes support dynamic linking these days and
+ # people can always --disable-shared, the test was removed, and we
+ # assume the GNU/Linux dynamic linker is in use.
+ dynamic_linker='GNU/Linux ld.so'
+ ;;
+
+knetbsd*-gnu)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ dynamic_linker='GNU ld.so'
+ ;;
+
+netbsd*)
+ version_type=sunos
+ need_lib_prefix=no
+ need_version=no
+ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+ dynamic_linker='NetBSD (a.out) ld.so'
+ else
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ dynamic_linker='NetBSD ld.elf_so'
+ fi
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+
+newsos6)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ ;;
+
+nto-qnx*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ ;;
+
+openbsd*)
+ version_type=sunos
+ sys_lib_dlsearch_path_spec="/usr/lib"
+ need_lib_prefix=no
+ # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs.
+ case $host_os in
+ openbsd3.3 | openbsd3.3.*) need_version=yes ;;
+ *) need_version=no ;;
+ esac
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ case $host_os in
+ openbsd2.[89] | openbsd2.[89].*)
+ shlibpath_overrides_runpath=no
+ ;;
+ *)
+ shlibpath_overrides_runpath=yes
+ ;;
+ esac
+ else
+ shlibpath_overrides_runpath=yes
+ fi
+ ;;
+
+os2*)
+ libname_spec='$name'
+ shrext_cmds=".dll"
+ need_lib_prefix=no
+ library_names_spec='$libname${shared_ext} $libname.a'
+ dynamic_linker='OS/2 ld.exe'
+ shlibpath_var=LIBPATH
+ ;;
+
+osf3* | osf4* | osf5*)
+ version_type=osf
+ need_lib_prefix=no
+ need_version=no
+ soname_spec='${libname}${release}${shared_ext}$major'
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
+ sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec"
+ ;;
+
+solaris*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ # ldd complains unless libraries are executable
+ postinstall_cmds='chmod +x $lib'
+ ;;
+
+sunos4*)
+ version_type=sunos
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ if test "$with_gnu_ld" = yes; then
+ need_lib_prefix=no
+ fi
+ need_version=yes
+ ;;
+
+sysv4 | sysv4.3*)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ case $host_vendor in
+ sni)
+ shlibpath_overrides_runpath=no
+ need_lib_prefix=no
+ export_dynamic_flag_spec='${wl}-Blargedynsym'
+ runpath_var=LD_RUN_PATH
+ ;;
+ siemens)
+ need_lib_prefix=no
+ ;;
+ motorola)
+ need_lib_prefix=no
+ need_version=no
+ shlibpath_overrides_runpath=no
+ sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
+ ;;
+ esac
+ ;;
+
+sysv4*MP*)
+ if test -d /usr/nec ;then
+ version_type=linux
+ library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}'
+ soname_spec='$libname${shared_ext}.$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ fi
+ ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+ version_type=freebsd-elf
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ hardcode_into_libs=yes
+ if test "$with_gnu_ld" = yes; then
+ sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib'
+ shlibpath_overrides_runpath=no
+ else
+ sys_lib_search_path_spec='/usr/ccs/lib /usr/lib'
+ shlibpath_overrides_runpath=yes
+ case $host_os in
+ sco3.2v5*)
+ sys_lib_search_path_spec="$sys_lib_search_path_spec /lib"
+ ;;
+ esac
+ fi
+ sys_lib_dlsearch_path_spec='/usr/lib'
+ ;;
+
+uts4*)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+*)
+ dynamic_linker=no
+ ;;
+esac
+echo "$as_me:$LINENO: result: $dynamic_linker" >&5
+echo "${ECHO_T}$dynamic_linker" >&6
+test "$dynamic_linker" = no && can_build_shared=no
+
+variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
+if test "$GCC" = yes; then
+ variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
+fi
+
+echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5
+echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6
+hardcode_action_F77=
+if test -n "$hardcode_libdir_flag_spec_F77" || \
+ test -n "$runpath_var_F77" || \
+ test "X$hardcode_automatic_F77" = "Xyes" ; then
+
+ # We can hardcode non-existant directories.
+ if test "$hardcode_direct_F77" != no &&
+ # If the only mechanism to avoid hardcoding is shlibpath_var, we
+ # have to relink, otherwise we might link with an installed library
+ # when we should be linking with a yet-to-be-installed one
+ ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, F77)" != no &&
+ test "$hardcode_minus_L_F77" != no; then
+ # Linking always hardcodes the temporary library directory.
+ hardcode_action_F77=relink
+ else
+ # We can link without hardcoding, and we can hardcode nonexisting dirs.
+ hardcode_action_F77=immediate
+ fi
+else
+ # We cannot hardcode anything, or else we can only hardcode existing
+ # directories.
+ hardcode_action_F77=unsupported
+fi
+echo "$as_me:$LINENO: result: $hardcode_action_F77" >&5
+echo "${ECHO_T}$hardcode_action_F77" >&6
+
+if test "$hardcode_action_F77" = relink; then
+ # Fast installation is not supported
+ enable_fast_install=no
+elif test "$shlibpath_overrides_runpath" = yes ||
+ test "$enable_shared" = no; then
+ # Fast installation is not necessary
+ enable_fast_install=needless
+fi
+
+
+# The else clause should only fire when bootstrapping the
+# libtool distribution, otherwise you forgot to ship ltmain.sh
+# with your package, and you will get complaints that there are
+# no rules to generate ltmain.sh.
+if test -f "$ltmain"; then
+ # See if we are running on zsh, and set the options which allow our commands through
+ # without removal of \ escapes.
+ if test -n "${ZSH_VERSION+set}" ; then
+ setopt NO_GLOB_SUBST
+ fi
+ # Now quote all the things that may contain metacharacters while being
+ # careful not to overquote the AC_SUBSTed values. We take copies of the
+ # variables and quote the copies for generation of the libtool script.
+ for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \
+ SED SHELL STRIP \
+ libname_spec library_names_spec soname_spec extract_expsyms_cmds \
+ old_striplib striplib file_magic_cmd finish_cmds finish_eval \
+ deplibs_check_method reload_flag reload_cmds need_locks \
+ lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \
+ lt_cv_sys_global_symbol_to_c_name_address \
+ sys_lib_search_path_spec sys_lib_dlsearch_path_spec \
+ old_postinstall_cmds old_postuninstall_cmds \
+ compiler_F77 \
+ CC_F77 \
+ LD_F77 \
+ lt_prog_compiler_wl_F77 \
+ lt_prog_compiler_pic_F77 \
+ lt_prog_compiler_static_F77 \
+ lt_prog_compiler_no_builtin_flag_F77 \
+ export_dynamic_flag_spec_F77 \
+ thread_safe_flag_spec_F77 \
+ whole_archive_flag_spec_F77 \
+ enable_shared_with_static_runtimes_F77 \
+ old_archive_cmds_F77 \
+ old_archive_from_new_cmds_F77 \
+ predep_objects_F77 \
+ postdep_objects_F77 \
+ predeps_F77 \
+ postdeps_F77 \
+ compiler_lib_search_path_F77 \
+ archive_cmds_F77 \
+ archive_expsym_cmds_F77 \
+ postinstall_cmds_F77 \
+ postuninstall_cmds_F77 \
+ old_archive_from_expsyms_cmds_F77 \
+ allow_undefined_flag_F77 \
+ no_undefined_flag_F77 \
+ export_symbols_cmds_F77 \
+ hardcode_libdir_flag_spec_F77 \
+ hardcode_libdir_flag_spec_ld_F77 \
+ hardcode_libdir_separator_F77 \
+ hardcode_automatic_F77 \
+ module_cmds_F77 \
+ module_expsym_cmds_F77 \
+ lt_cv_prog_compiler_c_o_F77 \
+ exclude_expsyms_F77 \
+ include_expsyms_F77; do
+
+ case $var in
+ old_archive_cmds_F77 | \
+ old_archive_from_new_cmds_F77 | \
+ archive_cmds_F77 | \
+ archive_expsym_cmds_F77 | \
+ module_cmds_F77 | \
+ module_expsym_cmds_F77 | \
+ old_archive_from_expsyms_cmds_F77 | \
+ export_symbols_cmds_F77 | \
+ extract_expsyms_cmds | reload_cmds | finish_cmds | \
+ postinstall_cmds | postuninstall_cmds | \
+ old_postinstall_cmds | old_postuninstall_cmds | \
+ sys_lib_search_path_spec | sys_lib_dlsearch_path_spec)
+ # Double-quote double-evaled strings.
+ eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\""
+ ;;
+ *)
+ eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\""
+ ;;
+ esac
+ done
+
+ case $lt_echo in
+ *'\$0 --fallback-echo"')
+ lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'`
+ ;;
+ esac
+
+cfgfile="$ofile"
+
+ cat <<__EOF__ >> "$cfgfile"
+# ### BEGIN LIBTOOL TAG CONFIG: $tagname
+
+# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+
+# Shell to use when invoking shell scripts.
+SHELL=$lt_SHELL
+
+# Whether or not to build shared libraries.
+build_libtool_libs=$enable_shared
+
+# Whether or not to build static libraries.
+build_old_libs=$enable_static
+
+# Whether or not to add -lc for building shared libraries.
+build_libtool_need_lc=$archive_cmds_need_lc_F77
+
+# Whether or not to disallow shared libs when runtime libs are static
+allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_F77
+
+# Whether or not to optimize for fast installation.
+fast_install=$enable_fast_install
+
+# The host system.
+host_alias=$host_alias
+host=$host
+host_os=$host_os
+
+# The build system.
+build_alias=$build_alias
+build=$build
+build_os=$build_os
+
+# An echo program that does not interpret backslashes.
+echo=$lt_echo
+
+# The archiver.
+AR=$lt_AR
+AR_FLAGS=$lt_AR_FLAGS
+
+# A C compiler.
+LTCC=$lt_LTCC
+
+# LTCC compiler flags.
+LTCFLAGS=$lt_LTCFLAGS
+
+# A language-specific compiler.
+CC=$lt_compiler_F77
+
+# Is the compiler the GNU C compiler?
+with_gcc=$GCC_F77
+
+gcc_dir=\`gcc -print-file-name=. | $SED 's,/\.$,,'\`
+gcc_ver=\`gcc -dumpversion\`
+
+# An ERE matcher.
+EGREP=$lt_EGREP
+
+# The linker used to build libraries.
+LD=$lt_LD_F77
+
+# Whether we need hard or soft links.
+LN_S=$lt_LN_S
+
+# A BSD-compatible nm program.
+NM=$lt_NM
+
+# A symbol stripping program
+STRIP=$lt_STRIP
+
+# Used to examine libraries when file_magic_cmd begins "file"
+MAGIC_CMD=$MAGIC_CMD
+
+# Used on cygwin: DLL creation program.
+DLLTOOL="$DLLTOOL"
+
+# Used on cygwin: object dumper.
+OBJDUMP="$OBJDUMP"
+
+# Used on cygwin: assembler.
+AS="$AS"
+
+# The name of the directory that contains temporary libtool files.
+objdir=$objdir
+
+# How to create reloadable object files.
+reload_flag=$lt_reload_flag
+reload_cmds=$lt_reload_cmds
+
+# How to pass a linker flag through the compiler.
+wl=$lt_lt_prog_compiler_wl_F77
+
+# Object file suffix (normally "o").
+objext="$ac_objext"
+
+# Old archive suffix (normally "a").
+libext="$libext"
+
+# Shared library suffix (normally ".so").
+shrext_cmds='$shrext_cmds'
+
+# Executable file suffix (normally "").
+exeext="$exeext"
+
+# Additional compiler flags for building library objects.
+pic_flag=$lt_lt_prog_compiler_pic_F77
+pic_mode=$pic_mode
+
+# What is the maximum length of a command?
+max_cmd_len=$lt_cv_sys_max_cmd_len
+
+# Does compiler simultaneously support -c and -o options?
+compiler_c_o=$lt_lt_cv_prog_compiler_c_o_F77
+
+# Must we lock files when doing compilation?
+need_locks=$lt_need_locks
+
+# Do we need the lib prefix for modules?
+need_lib_prefix=$need_lib_prefix
+
+# Do we need a version for libraries?
+need_version=$need_version
+
+# Whether dlopen is supported.
+dlopen_support=$enable_dlopen
+
+# Whether dlopen of programs is supported.
+dlopen_self=$enable_dlopen_self
+
+# Whether dlopen of statically linked programs is supported.
+dlopen_self_static=$enable_dlopen_self_static
+
+# Compiler flag to prevent dynamic linking.
+link_static_flag=$lt_lt_prog_compiler_static_F77
+
+# Compiler flag to turn off builtin functions.
+no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_F77
+
+# Compiler flag to allow reflexive dlopens.
+export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_F77
+
+# Compiler flag to generate shared objects directly from archives.
+whole_archive_flag_spec=$lt_whole_archive_flag_spec_F77
+
+# Compiler flag to generate thread-safe objects.
+thread_safe_flag_spec=$lt_thread_safe_flag_spec_F77
+
+# Library versioning type.
+version_type=$version_type
+
+# Format of library name prefix.
+libname_spec=$lt_libname_spec
+
+# List of archive names. First name is the real one, the rest are links.
+# The last name is the one that the linker finds with -lNAME.
+library_names_spec=$lt_library_names_spec
+
+# The coded name of the library, if different from the real name.
+soname_spec=$lt_soname_spec
+
+# Commands used to build and install an old-style archive.
+RANLIB=$lt_RANLIB
+old_archive_cmds=$lt_old_archive_cmds_F77
+old_postinstall_cmds=$lt_old_postinstall_cmds
+old_postuninstall_cmds=$lt_old_postuninstall_cmds
+
+# Create an old-style archive from a shared archive.
+old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_F77
+
+# Create a temporary old-style archive to link instead of a shared archive.
+old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_F77
+
+# Commands used to build and install a shared archive.
+archive_cmds=$lt_archive_cmds_F77
+archive_expsym_cmds=$lt_archive_expsym_cmds_F77
+postinstall_cmds=$lt_postinstall_cmds
+postuninstall_cmds=$lt_postuninstall_cmds
+
+# Commands used to build a loadable module (assumed same as above if empty)
+module_cmds=$lt_module_cmds_F77
+module_expsym_cmds=$lt_module_expsym_cmds_F77
+
+# Commands to strip libraries.
+old_striplib=$lt_old_striplib
+striplib=$lt_striplib
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predep_objects=\`echo $lt_predep_objects_F77 | \$SED -e "s@\${gcc_dir}@\\\${gcc_dir}@g;s@\${gcc_ver}@\\\${gcc_ver}@g"\`
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdep_objects=\`echo $lt_postdep_objects_F77 | \$SED -e "s@\${gcc_dir}@\\\${gcc_dir}@g;s@\${gcc_ver}@\\\${gcc_ver}@g"\`
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predeps=$lt_predeps_F77
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdeps=$lt_postdeps_F77
+
+# The library search path used internally by the compiler when linking
+# a shared library.
+compiler_lib_search_path=\`echo $lt_compiler_lib_search_path_F77 | \$SED -e "s@\${gcc_dir}@\\\${gcc_dir}@g;s@\${gcc_ver}@\\\${gcc_ver}@g"\`
+
+# Method to check whether dependent libraries are shared objects.
+deplibs_check_method=$lt_deplibs_check_method
+
+# Command to use when deplibs_check_method == file_magic.
+file_magic_cmd=$lt_file_magic_cmd
+
+# Flag that allows shared libraries with undefined symbols to be built.
+allow_undefined_flag=$lt_allow_undefined_flag_F77
+
+# Flag that forces no undefined symbols.
+no_undefined_flag=$lt_no_undefined_flag_F77
+
+# Commands used to finish a libtool library installation in a directory.
+finish_cmds=$lt_finish_cmds
+
+# Same as above, but a single script fragment to be evaled but not shown.
+finish_eval=$lt_finish_eval
+
+# Take the output of nm and produce a listing of raw symbols and C names.
+global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe
+
+# Transform the output of nm in a proper C declaration
+global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl
+
+# Transform the output of nm in a C name address pair
+global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address
+
+# This is the shared library runtime path variable.
+runpath_var=$runpath_var
+
+# This is the shared library path variable.
+shlibpath_var=$shlibpath_var
+
+# Is shlibpath searched before the hard-coded library search path?
+shlibpath_overrides_runpath=$shlibpath_overrides_runpath
+
+# How to hardcode a shared library path into an executable.
+hardcode_action=$hardcode_action_F77
+
+# Whether we should hardcode library paths into libraries.
+hardcode_into_libs=$hardcode_into_libs
+
+# Flag to hardcode \$libdir into a binary during linking.
+# This must work even if \$libdir does not exist.
+hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_F77
+
+# If ld is used when linking, flag to hardcode \$libdir into
+# a binary during linking. This must work even if \$libdir does
+# not exist.
+hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_F77
+
+# Whether we need a single -rpath flag with a separated argument.
+hardcode_libdir_separator=$lt_hardcode_libdir_separator_F77
+
+# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the
+# resulting binary.
+hardcode_direct=$hardcode_direct_F77
+
+# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
+# resulting binary.
+hardcode_minus_L=$hardcode_minus_L_F77
+
+# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into
+# the resulting binary.
+hardcode_shlibpath_var=$hardcode_shlibpath_var_F77
+
+# Set to yes if building a shared library automatically hardcodes DIR into the library
+# and all subsequent libraries and executables linked against it.
+hardcode_automatic=$hardcode_automatic_F77
+
+# Variables whose values should be saved in libtool wrapper scripts and
+# restored at relink time.
+variables_saved_for_relink="$variables_saved_for_relink"
+
+# Whether libtool must link a program against all its dependency libraries.
+link_all_deplibs=$link_all_deplibs_F77
+
+# Compile-time system search path for libraries
+sys_lib_search_path_spec=\`echo $lt_sys_lib_search_path_spec | \$SED -e "s@\${gcc_dir}@\\\${gcc_dir}@g;s@\${gcc_ver}@\\\${gcc_ver}@g"\`
+
+# Run-time system search path for libraries
+sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec
+
+# Fix the shell variable \$srcfile for the compiler.
+fix_srcfile_path="$fix_srcfile_path_F77"
+
+# Set to yes if exported symbols are required.
+always_export_symbols=$always_export_symbols_F77
+
+# The commands to list exported symbols.
+export_symbols_cmds=$lt_export_symbols_cmds_F77
+
+# The commands to extract the exported symbol list from a shared archive.
+extract_expsyms_cmds=$lt_extract_expsyms_cmds
+
+# Symbols that should not be listed in the preloaded symbols.
+exclude_expsyms=$lt_exclude_expsyms_F77
+
+# Symbols that must always be exported.
+include_expsyms=$lt_include_expsyms_F77
+
+# ### END LIBTOOL TAG CONFIG: $tagname
+
+__EOF__
+
+
+else
+ # If there is no Makefile yet, we rely on a make rule to execute
+ # `config.status --recheck' to rerun these tests and create the
+ # libtool script then.
+ ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'`
+ if test -f "$ltmain_in"; then
+ test -f Makefile && make "$ltmain"
+ fi
+fi
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_linkonly='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_objext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+CC="$lt_save_CC"
+
+ else
+ tagname=""
+ fi
+ ;;
+
+ GCJ)
+ if test -n "$GCJ" && test "X$GCJ" != "Xno"; then
+
+
+
+# Source file extension for Java test sources.
+ac_ext=java
+
+# Object file extension for compiled Java test sources.
+objext=o
+objext_GCJ=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="class foo {}\n"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='public class conftest { public static void main(String[] argv) {}; }\n'
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# If no C compiler flags were specified, use CFLAGS.
+LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+
+
+# save warnings/boilerplate of simple test code
+ac_outfile=conftest.$ac_objext
+printf "$lt_simple_compile_test_code" >conftest.$ac_ext
+eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_compiler_boilerplate=`cat conftest.err`
+$rm conftest*
+
+ac_outfile=conftest.$ac_objext
+printf "$lt_simple_link_test_code" >conftest.$ac_ext
+eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_linker_boilerplate=`cat conftest.err`
+$rm conftest*
+
+
+# Allow CC to be a program name with arguments.
+lt_save_CC="$CC"
+CC=${GCJ-"gcj"}
+compiler=$CC
+compiler_GCJ=$CC
+for cc_temp in $compiler""; do
+ case $cc_temp in
+ compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
+ distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
+ \-*) ;;
+ *) break;;
+ esac
+done
+cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"`
+
+
+# GCJ did not exist at the time GCC didn't implicitly link libc in.
+archive_cmds_need_lc_GCJ=no
+
+old_archive_cmds_GCJ=$old_archive_cmds
+
+
+lt_prog_compiler_no_builtin_flag_GCJ=
+
+if test "$GCC" = yes; then
+ lt_prog_compiler_no_builtin_flag_GCJ=' -fno-builtin'
+
+
+echo "$as_me:$LINENO: checking if $compiler supports -fno-rtti -fno-exceptions" >&5
+echo $ECHO_N "checking if $compiler supports -fno-rtti -fno-exceptions... $ECHO_C" >&6
+if test "${lt_cv_prog_compiler_rtti_exceptions+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ lt_cv_prog_compiler_rtti_exceptions=no
+ ac_outfile=conftest.$ac_objext
+ printf "$lt_simple_compile_test_code" > conftest.$ac_ext
+ lt_compiler_flag="-fno-rtti -fno-exceptions"
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ # The option is referenced via a variable to avoid confusing sed.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:22993: $lt_compile\"" >&5)
+ (eval "$lt_compile" 2>conftest.err)
+ ac_status=$?
+ cat conftest.err >&5
+ echo "$as_me:22997: \$? = $ac_status" >&5
+ if (exit $ac_status) && test -s "$ac_outfile"; then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings other than the usual output.
+ $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp
+ $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+ if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
+ lt_cv_prog_compiler_rtti_exceptions=yes
+ fi
+ fi
+ $rm conftest*
+
+fi
+echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_rtti_exceptions" >&5
+echo "${ECHO_T}$lt_cv_prog_compiler_rtti_exceptions" >&6
+
+if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then
+ lt_prog_compiler_no_builtin_flag_GCJ="$lt_prog_compiler_no_builtin_flag_GCJ -fno-rtti -fno-exceptions"
+else
+ :
+fi
+
+fi
+
+lt_prog_compiler_wl_GCJ=
+lt_prog_compiler_pic_GCJ=
+lt_prog_compiler_static_GCJ=
+
+echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5
+echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6
+
+ if test "$GCC" = yes; then
+ lt_prog_compiler_wl_GCJ='-Wl,'
+ lt_prog_compiler_static_GCJ='-static'
+
+ case $host_os in
+ aix*)
+ # All AIX code is PIC.
+ if test "$host_cpu" = ia64; then
+ # AIX 5 now supports IA64 processor
+ lt_prog_compiler_static_GCJ='-Bstatic'
+ fi
+ ;;
+
+ amigaos*)
+ # FIXME: we need at least 68020 code to build shared libraries, but
+ # adding the `-m68020' flag to GCC prevents building anything better,
+ # like `-m68040'.
+ lt_prog_compiler_pic_GCJ='-m68020 -resident32 -malways-restore-a4'
+ ;;
+
+ beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+ # PIC is the default for these OSes.
+ ;;
+
+ mingw* | pw32* | os2*)
+ # This hack is so that the source file can tell whether it is being
+ # built for inclusion in a dll (and should export symbols for example).
+ lt_prog_compiler_pic_GCJ='-DDLL_EXPORT'
+ ;;
+
+ darwin* | rhapsody*)
+ # PIC is the default on this platform
+ # Common symbols not allowed in MH_DYLIB files
+ lt_prog_compiler_pic_GCJ='-fno-common'
+ ;;
+
+ interix3*)
+ # Interix 3.x gcc -fpic/-fPIC options generate broken code.
+ # Instead, we relocate shared libraries at runtime.
+ ;;
+
+ msdosdjgpp*)
+ # Just because we use GCC doesn't mean we suddenly get shared libraries
+ # on systems that don't support them.
+ lt_prog_compiler_can_build_shared_GCJ=no
+ enable_shared=no
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ lt_prog_compiler_pic_GCJ=-Kconform_pic
+ fi
+ ;;
+
+ hpux*)
+ # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+ # not for PA HP-UX.
+ case $host_cpu in
+ hppa*64*|ia64*)
+ # +Z the default
+ ;;
+ *)
+ lt_prog_compiler_pic_GCJ='-fPIC'
+ ;;
+ esac
+ ;;
+
+ *)
+ lt_prog_compiler_pic_GCJ='-fPIC'
+ ;;
+ esac
+ else
+ # PORTME Check for flag to pass linker flags through the system compiler.
+ case $host_os in
+ aix*)
+ lt_prog_compiler_wl_GCJ='-Wl,'
+ if test "$host_cpu" = ia64; then
+ # AIX 5 now supports IA64 processor
+ lt_prog_compiler_static_GCJ='-Bstatic'
+ else
+ lt_prog_compiler_static_GCJ='-bnso -bI:/lib/syscalls.exp'
+ fi
+ ;;
+ darwin*)
+ # PIC is the default on this platform
+ # Common symbols not allowed in MH_DYLIB files
+ case $cc_basename in
+ xlc*)
+ lt_prog_compiler_pic_GCJ='-qnocommon'
+ lt_prog_compiler_wl_GCJ='-Wl,'
+ ;;
+ esac
+ ;;
+
+ mingw* | pw32* | os2*)
+ # This hack is so that the source file can tell whether it is being
+ # built for inclusion in a dll (and should export symbols for example).
+ lt_prog_compiler_pic_GCJ='-DDLL_EXPORT'
+ ;;
+
+ hpux9* | hpux10* | hpux11*)
+ lt_prog_compiler_wl_GCJ='-Wl,'
+ # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+ # not for PA HP-UX.
+ case $host_cpu in
+ hppa*64*|ia64*)
+ # +Z the default
+ ;;
+ *)
+ lt_prog_compiler_pic_GCJ='+Z'
+ ;;
+ esac
+ # Is there a better lt_prog_compiler_static that works with the bundled CC?
+ lt_prog_compiler_static_GCJ='${wl}-a ${wl}archive'
+ ;;
+
+ irix5* | irix6* | nonstopux*)
+ lt_prog_compiler_wl_GCJ='-Wl,'
+ # PIC (with -KPIC) is the default.
+ lt_prog_compiler_static_GCJ='-non_shared'
+ ;;
+
+ newsos6)
+ lt_prog_compiler_pic_GCJ='-KPIC'
+ lt_prog_compiler_static_GCJ='-Bstatic'
+ ;;
+
+ linux*)
+ case $cc_basename in
+ icc* | ecc*)
+ lt_prog_compiler_wl_GCJ='-Wl,'
+ lt_prog_compiler_pic_GCJ='-KPIC'
+ lt_prog_compiler_static_GCJ='-static'
+ ;;
+ pgcc* | pgf77* | pgf90* | pgf95*)
+ # Portland Group compilers (*not* the Pentium gcc compiler,
+ # which looks to be a dead project)
+ lt_prog_compiler_wl_GCJ='-Wl,'
+ lt_prog_compiler_pic_GCJ='-fpic'
+ lt_prog_compiler_static_GCJ='-Bstatic'
+ ;;
+ ccc*)
+ lt_prog_compiler_wl_GCJ='-Wl,'
+ # All Alpha code is PIC.
+ lt_prog_compiler_static_GCJ='-non_shared'
+ ;;
+ esac
+ ;;
+
+ osf3* | osf4* | osf5*)
+ lt_prog_compiler_wl_GCJ='-Wl,'
+ # All OSF/1 code is PIC.
+ lt_prog_compiler_static_GCJ='-non_shared'
+ ;;
+
+ solaris*)
+ lt_prog_compiler_pic_GCJ='-KPIC'
+ lt_prog_compiler_static_GCJ='-Bstatic'
+ case $cc_basename in
+ f77* | f90* | f95*)
+ lt_prog_compiler_wl_GCJ='-Qoption ld ';;
+ *)
+ lt_prog_compiler_wl_GCJ='-Wl,';;
+ esac
+ ;;
+
+ sunos4*)
+ lt_prog_compiler_wl_GCJ='-Qoption ld '
+ lt_prog_compiler_pic_GCJ='-PIC'
+ lt_prog_compiler_static_GCJ='-Bstatic'
+ ;;
+
+ sysv4 | sysv4.2uw2* | sysv4.3*)
+ lt_prog_compiler_wl_GCJ='-Wl,'
+ lt_prog_compiler_pic_GCJ='-KPIC'
+ lt_prog_compiler_static_GCJ='-Bstatic'
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec ;then
+ lt_prog_compiler_pic_GCJ='-Kconform_pic'
+ lt_prog_compiler_static_GCJ='-Bstatic'
+ fi
+ ;;
+
+ sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
+ lt_prog_compiler_wl_GCJ='-Wl,'
+ lt_prog_compiler_pic_GCJ='-KPIC'
+ lt_prog_compiler_static_GCJ='-Bstatic'
+ ;;
+
+ unicos*)
+ lt_prog_compiler_wl_GCJ='-Wl,'
+ lt_prog_compiler_can_build_shared_GCJ=no
+ ;;
+
+ uts4*)
+ lt_prog_compiler_pic_GCJ='-pic'
+ lt_prog_compiler_static_GCJ='-Bstatic'
+ ;;
+
+ *)
+ lt_prog_compiler_can_build_shared_GCJ=no
+ ;;
+ esac
+ fi
+
+echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_GCJ" >&5
+echo "${ECHO_T}$lt_prog_compiler_pic_GCJ" >&6
+
+#
+# Check to make sure the PIC flag actually works.
+#
+if test -n "$lt_prog_compiler_pic_GCJ"; then
+
+echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic_GCJ works" >&5
+echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic_GCJ works... $ECHO_C" >&6
+if test "${lt_prog_compiler_pic_works_GCJ+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ lt_prog_compiler_pic_works_GCJ=no
+ ac_outfile=conftest.$ac_objext
+ printf "$lt_simple_compile_test_code" > conftest.$ac_ext
+ lt_compiler_flag="$lt_prog_compiler_pic_GCJ"
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ # The option is referenced via a variable to avoid confusing sed.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:23261: $lt_compile\"" >&5)
+ (eval "$lt_compile" 2>conftest.err)
+ ac_status=$?
+ cat conftest.err >&5
+ echo "$as_me:23265: \$? = $ac_status" >&5
+ if (exit $ac_status) && test -s "$ac_outfile"; then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings other than the usual output.
+ $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp
+ $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+ if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
+ lt_prog_compiler_pic_works_GCJ=yes
+ fi
+ fi
+ $rm conftest*
+
+fi
+echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works_GCJ" >&5
+echo "${ECHO_T}$lt_prog_compiler_pic_works_GCJ" >&6
+
+if test x"$lt_prog_compiler_pic_works_GCJ" = xyes; then
+ case $lt_prog_compiler_pic_GCJ in
+ "" | " "*) ;;
+ *) lt_prog_compiler_pic_GCJ=" $lt_prog_compiler_pic_GCJ" ;;
+ esac
+else
+ lt_prog_compiler_pic_GCJ=
+ lt_prog_compiler_can_build_shared_GCJ=no
+fi
+
+fi
+case $host_os in
+ # For platforms which do not support PIC, -DPIC is meaningless:
+ *djgpp*)
+ lt_prog_compiler_pic_GCJ=
+ ;;
+ *)
+ lt_prog_compiler_pic_GCJ="$lt_prog_compiler_pic_GCJ"
+ ;;
+esac
+
+#
+# Check to make sure the static flag actually works.
+#
+wl=$lt_prog_compiler_wl_GCJ eval lt_tmp_static_flag=\"$lt_prog_compiler_static_GCJ\"
+echo "$as_me:$LINENO: checking if $compiler static flag $lt_tmp_static_flag works" >&5
+echo $ECHO_N "checking if $compiler static flag $lt_tmp_static_flag works... $ECHO_C" >&6
+if test "${lt_prog_compiler_static_works_GCJ+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ lt_prog_compiler_static_works_GCJ=no
+ save_LDFLAGS="$LDFLAGS"
+ LDFLAGS="$LDFLAGS $lt_tmp_static_flag"
+ printf "$lt_simple_link_test_code" > conftest.$ac_ext
+ if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
+ # The linker can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ if test -s conftest.err; then
+ # Append any errors to the config.log.
+ cat conftest.err 1>&5
+ $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp
+ $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+ if diff conftest.exp conftest.er2 >/dev/null; then
+ lt_prog_compiler_static_works_GCJ=yes
+ fi
+ else
+ lt_prog_compiler_static_works_GCJ=yes
+ fi
+ fi
+ $rm conftest*
+ LDFLAGS="$save_LDFLAGS"
+
+fi
+echo "$as_me:$LINENO: result: $lt_prog_compiler_static_works_GCJ" >&5
+echo "${ECHO_T}$lt_prog_compiler_static_works_GCJ" >&6
+
+if test x"$lt_prog_compiler_static_works_GCJ" = xyes; then
+ :
+else
+ lt_prog_compiler_static_GCJ=
+fi
+
+
+echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5
+echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6
+if test "${lt_cv_prog_compiler_c_o_GCJ+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ lt_cv_prog_compiler_c_o_GCJ=no
+ $rm -r conftest 2>/dev/null
+ mkdir conftest
+ cd conftest
+ mkdir out
+ printf "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+ lt_compiler_flag="-o out/conftest2.$ac_objext"
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:23365: $lt_compile\"" >&5)
+ (eval "$lt_compile" 2>out/conftest.err)
+ ac_status=$?
+ cat out/conftest.err >&5
+ echo "$as_me:23369: \$? = $ac_status" >&5
+ if (exit $ac_status) && test -s out/conftest2.$ac_objext
+ then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp
+ $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
+ if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
+ lt_cv_prog_compiler_c_o_GCJ=yes
+ fi
+ fi
+ chmod u+w . 2>&5
+ $rm conftest*
+ # SGI C++ compiler will create directory out/ii_files/ for
+ # template instantiation
+ test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files
+ $rm out/* && rmdir out
+ cd ..
+ rmdir conftest
+ $rm conftest*
+
+fi
+echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o_GCJ" >&5
+echo "${ECHO_T}$lt_cv_prog_compiler_c_o_GCJ" >&6
+
+
+hard_links="nottested"
+if test "$lt_cv_prog_compiler_c_o_GCJ" = no && test "$need_locks" != no; then
+ # do not overwrite the value of need_locks provided by the user
+ echo "$as_me:$LINENO: checking if we can lock with hard links" >&5
+echo $ECHO_N "checking if we can lock with hard links... $ECHO_C" >&6
+ hard_links=yes
+ $rm conftest*
+ ln conftest.a conftest.b 2>/dev/null && hard_links=no
+ touch conftest.a
+ ln conftest.a conftest.b 2>&5 || hard_links=no
+ ln conftest.a conftest.b 2>/dev/null && hard_links=no
+ echo "$as_me:$LINENO: result: $hard_links" >&5
+echo "${ECHO_T}$hard_links" >&6
+ if test "$hard_links" = no; then
+ { echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5
+echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;}
+ need_locks=warn
+ fi
+else
+ need_locks=no
+fi
+
+echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5
+echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6
+
+ runpath_var=
+ allow_undefined_flag_GCJ=
+ enable_shared_with_static_runtimes_GCJ=no
+ archive_cmds_GCJ=
+ archive_expsym_cmds_GCJ=
+ old_archive_From_new_cmds_GCJ=
+ old_archive_from_expsyms_cmds_GCJ=
+ export_dynamic_flag_spec_GCJ=
+ whole_archive_flag_spec_GCJ=
+ thread_safe_flag_spec_GCJ=
+ hardcode_libdir_flag_spec_GCJ=
+ hardcode_libdir_flag_spec_ld_GCJ=
+ hardcode_libdir_separator_GCJ=
+ hardcode_direct_GCJ=no
+ hardcode_minus_L_GCJ=no
+ hardcode_shlibpath_var_GCJ=unsupported
+ link_all_deplibs_GCJ=unknown
+ hardcode_automatic_GCJ=no
+ module_cmds_GCJ=
+ module_expsym_cmds_GCJ=
+ always_export_symbols_GCJ=no
+ export_symbols_cmds_GCJ='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+ # include_expsyms should be a list of space-separated symbols to be *always*
+ # included in the symbol list
+ include_expsyms_GCJ=
+ # exclude_expsyms can be an extended regexp of symbols to exclude
+ # it will be wrapped by ` (' and `)$', so one must not match beginning or
+ # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc',
+ # as well as any symbol that contains `d'.
+ exclude_expsyms_GCJ="_GLOBAL_OFFSET_TABLE_"
+ # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
+ # platforms (ab)use it in PIC code, but their linkers get confused if
+ # the symbol is explicitly referenced. Since portable code cannot
+ # rely on this symbol name, it's probably fine to never include it in
+ # preloaded symbol tables.
+ extract_expsyms_cmds=
+ # Just being paranoid about ensuring that cc_basename is set.
+ for cc_temp in $compiler""; do
+ case $cc_temp in
+ compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
+ distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
+ \-*) ;;
+ *) break;;
+ esac
+done
+cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"`
+
+ case $host_os in
+ cygwin* | mingw* | pw32*)
+ # FIXME: the MSVC++ port hasn't been tested in a loooong time
+ # When not using gcc, we currently assume that we are using
+ # Microsoft Visual C++.
+ if test "$GCC" != yes; then
+ with_gnu_ld=no
+ fi
+ ;;
+ interix*)
+ # we just hope/assume this is gcc and not c89 (= MSVC++)
+ with_gnu_ld=yes
+ ;;
+ openbsd*)
+ with_gnu_ld=no
+ ;;
+ esac
+
+ ld_shlibs_GCJ=yes
+ if test "$with_gnu_ld" = yes; then
+ # If archive_cmds runs LD, not CC, wlarc should be empty
+ wlarc='${wl}'
+
+ # Set some defaults for GNU ld with shared library support. These
+ # are reset later if shared libraries are not supported. Putting them
+ # here allows them to be overridden if necessary.
+ runpath_var=LD_RUN_PATH
+ hardcode_libdir_flag_spec_GCJ='${wl}--rpath ${wl}$libdir'
+ export_dynamic_flag_spec_GCJ='${wl}--export-dynamic'
+ # ancient GNU ld didn't support --whole-archive et. al.
+ if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then
+ whole_archive_flag_spec_GCJ="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+ else
+ whole_archive_flag_spec_GCJ=
+ fi
+ supports_anon_versioning=no
+ case `$LD -v 2>/dev/null` in
+ *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11
+ *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ...
+ *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ...
+ *\ 2.11.*) ;; # other 2.11 versions
+ *) supports_anon_versioning=yes ;;
+ esac
+
+ # See if GNU ld supports shared libraries.
+ case $host_os in
+ aix3* | aix4* | aix5*)
+ # On AIX/PPC, the GNU linker is very broken
+ if test "$host_cpu" != ia64; then
+ ld_shlibs_GCJ=no
+ cat <<EOF 1>&2
+
+*** Warning: the GNU linker, at least up to release 2.9.1, is reported
+*** to be unable to reliably create shared libraries on AIX.
+*** Therefore, libtool is disabling shared libraries support. If you
+*** really care for shared libraries, you may want to modify your PATH
+*** so that a non-GNU linker is found, and then restart.
+
+EOF
+ fi
+ ;;
+
+ amigaos*)
+ archive_cmds_GCJ='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+ hardcode_libdir_flag_spec_GCJ='-L$libdir'
+ hardcode_minus_L_GCJ=yes
+
+ # Samuel A. Falvo II <kc5tja at dolphin.openprojects.net> reports
+ # that the semantics of dynamic libraries on AmigaOS, at least up
+ # to version 4, is to share data among multiple programs linked
+ # with the same dynamic library. Since this doesn't match the
+ # behavior of shared libraries on other platforms, we can't use
+ # them.
+ ld_shlibs_GCJ=no
+ ;;
+
+ beos*)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ allow_undefined_flag_GCJ=unsupported
+ # Joseph Beckenbach <jrb3 at best.com> says some releases of gcc
+ # support --undefined. This deserves some investigation. FIXME
+ archive_cmds_GCJ='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ else
+ ld_shlibs_GCJ=no
+ fi
+ ;;
+
+ cygwin* | mingw* | pw32*)
+ # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, GCJ) is actually meaningless,
+ # as there is no search path for DLLs.
+ hardcode_libdir_flag_spec_GCJ='-L$libdir'
+ allow_undefined_flag_GCJ=unsupported
+ always_export_symbols_GCJ=no
+ enable_shared_with_static_runtimes_GCJ=yes
+ export_symbols_cmds_GCJ='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS] /s/.* \([^ ]*\)/\1 DATA/'\'' | $SED -e '\''/^[AITW] /s/.* //'\'' | sort | uniq > $export_symbols'
+
+ if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then
+ archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+ # If the export-symbols file already is a .def file (1st line
+ # is EXPORTS), use it as is; otherwise, prepend...
+ archive_expsym_cmds_GCJ='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
+ cp $export_symbols $output_objdir/$soname.def;
+ else
+ echo EXPORTS > $output_objdir/$soname.def;
+ cat $export_symbols >> $output_objdir/$soname.def;
+ fi~
+ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+ else
+ ld_shlibs_GCJ=no
+ fi
+ ;;
+
+ interix3*)
+ hardcode_direct_GCJ=no
+ hardcode_shlibpath_var_GCJ=no
+ hardcode_libdir_flag_spec_GCJ='${wl}-rpath,$libdir'
+ export_dynamic_flag_spec_GCJ='${wl}-E'
+ # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
+ # Instead, shared libraries are loaded at an image base (0x10000000 by
+ # default) and relocated if they conflict, which is a slow very memory
+ # consuming and fragmenting process. To avoid this, we pick a random,
+ # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
+ # time. Moving up from 0x10000000 also allows more sbrk(2) space.
+ archive_cmds_GCJ='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+ archive_expsym_cmds_GCJ='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+ ;;
+
+ linux*)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ tmp_addflag=
+ case $cc_basename,$host_cpu in
+ pgcc*) # Portland Group C compiler
+ whole_archive_flag_spec_GCJ='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
+ tmp_addflag=' $pic_flag'
+ ;;
+ pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers
+ whole_archive_flag_spec_GCJ='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
+ tmp_addflag=' $pic_flag -Mnomain' ;;
+ ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64
+ tmp_addflag=' -i_dynamic' ;;
+ efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64
+ tmp_addflag=' -i_dynamic -nofor_main' ;;
+ ifc* | ifort*) # Intel Fortran compiler
+ tmp_addflag=' -nofor_main' ;;
+ esac
+ archive_cmds_GCJ='$CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+
+ if test $supports_anon_versioning = yes; then
+ archive_expsym_cmds_GCJ='$echo "{ global:" > $output_objdir/$libname.ver~
+ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+ $echo "local: *; };" >> $output_objdir/$libname.ver~
+ $CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib'
+ fi
+ else
+ ld_shlibs_GCJ=no
+ fi
+ ;;
+
+ netbsd*)
+ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+ archive_cmds_GCJ='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
+ wlarc=
+ else
+ archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ fi
+ ;;
+
+ solaris*)
+ if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then
+ ld_shlibs_GCJ=no
+ cat <<EOF 1>&2
+
+*** Warning: The releases 2.8.* of the GNU linker cannot reliably
+*** create shared libraries on Solaris systems. Therefore, libtool
+*** is disabling shared libraries support. We urge you to upgrade GNU
+*** binutils to release 2.9.1 or newer. Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+EOF
+ elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ else
+ ld_shlibs_GCJ=no
+ fi
+ ;;
+
+ sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*)
+ case `$LD -v 2>&1` in
+ *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*)
+ ld_shlibs_GCJ=no
+ cat <<_LT_EOF 1>&2
+
+*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not
+*** reliably create shared libraries on SCO systems. Therefore, libtool
+*** is disabling shared libraries support. We urge you to upgrade GNU
+*** binutils to release 2.16.91.0.3 or newer. Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+_LT_EOF
+ ;;
+ *)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ hardcode_libdir_flag_spec_GCJ='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`'
+ archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib'
+ archive_expsym_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname,-retain-symbols-file,$export_symbols -o $lib'
+ else
+ ld_shlibs_GCJ=no
+ fi
+ ;;
+ esac
+ ;;
+
+ sunos4*)
+ archive_cmds_GCJ='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+ wlarc=
+ hardcode_direct_GCJ=yes
+ hardcode_shlibpath_var_GCJ=no
+ ;;
+
+ *)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ else
+ ld_shlibs_GCJ=no
+ fi
+ ;;
+ esac
+
+ if test "$ld_shlibs_GCJ" = no; then
+ runpath_var=
+ hardcode_libdir_flag_spec_GCJ=
+ export_dynamic_flag_spec_GCJ=
+ whole_archive_flag_spec_GCJ=
+ fi
+ else
+ # PORTME fill in a description of your system's linker (not GNU ld)
+ case $host_os in
+ aix3*)
+ allow_undefined_flag_GCJ=unsupported
+ always_export_symbols_GCJ=yes
+ archive_expsym_cmds_GCJ='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname'
+ # Note: this linker hardcodes the directories in LIBPATH if there
+ # are no directories specified by -L.
+ hardcode_minus_L_GCJ=yes
+ if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then
+ # Neither direct hardcoding nor static linking is supported with a
+ # broken collect2.
+ hardcode_direct_GCJ=unsupported
+ fi
+ ;;
+
+ aix4* | aix5*)
+ if test "$host_cpu" = ia64; then
+ # On IA64, the linker does run time linking by default, so we don't
+ # have to do anything special.
+ aix_use_runtimelinking=no
+ exp_sym_flag='-Bexport'
+ no_entry_flag=""
+ else
+ # If we're using GNU nm, then we don't want the "-C" option.
+ # -C means demangle to AIX nm, but means don't demangle with GNU nm
+ if $NM -V 2>&1 | grep 'GNU' > /dev/null; then
+ export_symbols_cmds_GCJ='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols'
+ else
+ export_symbols_cmds_GCJ='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols'
+ fi
+ aix_use_runtimelinking=no
+
+ # Test if we are trying to use run time linking or normal
+ # AIX style linking. If -brtl is somewhere in LDFLAGS, we
+ # need to do runtime linking.
+ case $host_os in aix4.[23]|aix4.[23].*|aix5*)
+ for ld_flag in $LDFLAGS; do
+ if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then
+ aix_use_runtimelinking=yes
+ break
+ fi
+ done
+ ;;
+ esac
+
+ exp_sym_flag='-bexport'
+ no_entry_flag='-bnoentry'
+ fi
+
+ # When large executables or shared objects are built, AIX ld can
+ # have problems creating the table of contents. If linking a library
+ # or program results in "error TOC overflow" add -mminimal-toc to
+ # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not
+ # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+ archive_cmds_GCJ=''
+ hardcode_direct_GCJ=yes
+ hardcode_libdir_separator_GCJ=':'
+ link_all_deplibs_GCJ=yes
+
+ if test "$GCC" = yes; then
+ case $host_os in aix4.[012]|aix4.[012].*)
+ # We only want to do this on AIX 4.2 and lower, the check
+ # below for broken collect2 doesn't work under 4.3+
+ collect2name=`${CC} -print-prog-name=collect2`
+ if test -f "$collect2name" && \
+ strings "$collect2name" | grep resolve_lib_name >/dev/null
+ then
+ # We have reworked collect2
+ hardcode_direct_GCJ=yes
+ else
+ # We have old collect2
+ hardcode_direct_GCJ=unsupported
+ # It fails to find uninstalled libraries when the uninstalled
+ # path is not listed in the libpath. Setting hardcode_minus_L
+ # to unsupported forces relinking
+ hardcode_minus_L_GCJ=yes
+ hardcode_libdir_flag_spec_GCJ='-L$libdir'
+ hardcode_libdir_separator_GCJ=
+ fi
+ ;;
+ esac
+ shared_flag='-shared'
+ if test "$aix_use_runtimelinking" = yes; then
+ shared_flag="$shared_flag "'${wl}-G'
+ fi
+ else
+ # not using gcc
+ if test "$host_cpu" = ia64; then
+ # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+ # chokes on -Wl,-G. The following line is correct:
+ shared_flag='-G'
+ else
+ if test "$aix_use_runtimelinking" = yes; then
+ shared_flag='${wl}-G'
+ else
+ shared_flag='${wl}-bM:SRE'
+ fi
+ fi
+ fi
+
+ # It seems that -bexpall does not export symbols beginning with
+ # underscore (_), so it is better to generate a list of symbols to export.
+ always_export_symbols_GCJ=yes
+ if test "$aix_use_runtimelinking" = yes; then
+ # Warning - without using the other runtime loading flags (-brtl),
+ # -berok will link without error, but may produce a broken library.
+ allow_undefined_flag_GCJ='-berok'
+ # Determine the default libpath from the value encoded in an empty executable.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+
+aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`
+# Check for a 64-bit object if we didn't find anything.
+if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`; fi
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+
+ hardcode_libdir_flag_spec_GCJ='${wl}-blibpath:$libdir:'"$aix_libpath"
+ archive_expsym_cmds_GCJ="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+ else
+ if test "$host_cpu" = ia64; then
+ hardcode_libdir_flag_spec_GCJ='${wl}-R $libdir:/usr/lib:/lib'
+ allow_undefined_flag_GCJ="-z nodefs"
+ archive_expsym_cmds_GCJ="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols"
+ else
+ # Determine the default libpath from the value encoded in an empty executable.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+
+aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`
+# Check for a 64-bit object if we didn't find anything.
+if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`; fi
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+
+ hardcode_libdir_flag_spec_GCJ='${wl}-blibpath:$libdir:'"$aix_libpath"
+ # Warning - without using the other run time loading flags,
+ # -berok will link without error, but may produce a broken library.
+ no_undefined_flag_GCJ=' ${wl}-bernotok'
+ allow_undefined_flag_GCJ=' ${wl}-berok'
+ # Exported symbols can be pulled into shared objects from archives
+ whole_archive_flag_spec_GCJ='$convenience'
+ archive_cmds_need_lc_GCJ=yes
+ # This is similar to how AIX traditionally builds its shared libraries.
+ archive_expsym_cmds_GCJ="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
+ fi
+ fi
+ ;;
+
+ amigaos*)
+ archive_cmds_GCJ='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+ hardcode_libdir_flag_spec_GCJ='-L$libdir'
+ hardcode_minus_L_GCJ=yes
+ # see comment about different semantics on the GNU ld section
+ ld_shlibs_GCJ=no
+ ;;
+
+ bsdi[45]*)
+ export_dynamic_flag_spec_GCJ=-rdynamic
+ ;;
+
+ cygwin* | mingw* | pw32*)
+ # When not using gcc, we currently assume that we are using
+ # Microsoft Visual C++.
+ # hardcode_libdir_flag_spec is actually meaningless, as there is
+ # no search path for DLLs.
+ hardcode_libdir_flag_spec_GCJ=' '
+ allow_undefined_flag_GCJ=unsupported
+ # Tell ltmain to make .lib files, not .a files.
+ libext=lib
+ # Tell ltmain to make .dll files, not .so files.
+ shrext_cmds=".dll"
+ # FIXME: Setting linknames here is a bad hack.
+ archive_cmds_GCJ='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames='
+ # The linker will automatically build a .lib file if we build a DLL.
+ old_archive_From_new_cmds_GCJ='true'
+ # FIXME: Should let the user specify the lib program.
+ old_archive_cmds_GCJ='lib /OUT:$oldlib$oldobjs$old_deplibs'
+ fix_srcfile_path_GCJ='`cygpath -w "$srcfile"`'
+ enable_shared_with_static_runtimes_GCJ=yes
+ ;;
+
+ darwin* | rhapsody*)
+ case $host_os in
+ rhapsody* | darwin1.[012])
+ allow_undefined_flag_GCJ='${wl}-undefined ${wl}suppress'
+ ;;
+ *) # Darwin 1.3 on
+ if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then
+ allow_undefined_flag_GCJ='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
+ else
+ case ${MACOSX_DEPLOYMENT_TARGET} in
+ 10.[012])
+ allow_undefined_flag_GCJ='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
+ ;;
+ 10.*)
+ allow_undefined_flag_GCJ='${wl}-undefined ${wl}dynamic_lookup'
+ ;;
+ esac
+ fi
+ ;;
+ esac
+ archive_cmds_need_lc_GCJ=no
+ hardcode_direct_GCJ=no
+ hardcode_automatic_GCJ=yes
+ hardcode_shlibpath_var_GCJ=unsupported
+ whole_archive_flag_spec_GCJ=''
+ link_all_deplibs_GCJ=yes
+ if test "$GCC" = yes ; then
+ output_verbose_link_cmd='echo'
+ archive_cmds_GCJ='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring'
+ module_cmds_GCJ='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
+ # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
+ archive_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ module_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ else
+ case $cc_basename in
+ xlc*)
+ output_verbose_link_cmd='echo'
+ archive_cmds_GCJ='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring'
+ module_cmds_GCJ='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
+ # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
+ archive_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ module_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ ;;
+ *)
+ ld_shlibs_GCJ=no
+ ;;
+ esac
+ fi
+ ;;
+
+ dgux*)
+ archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_libdir_flag_spec_GCJ='-L$libdir'
+ hardcode_shlibpath_var_GCJ=no
+ ;;
+
+ freebsd1*)
+ ld_shlibs_GCJ=no
+ ;;
+
+ # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
+ # support. Future versions do this automatically, but an explicit c++rt0.o
+ # does not break anything, and helps significantly (at the cost of a little
+ # extra space).
+ freebsd2.2*)
+ archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o'
+ hardcode_libdir_flag_spec_GCJ='-R$libdir'
+ hardcode_direct_GCJ=yes
+ hardcode_shlibpath_var_GCJ=no
+ ;;
+
+ # Unfortunately, older versions of FreeBSD 2 do not have this feature.
+ freebsd2*)
+ archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_direct_GCJ=yes
+ hardcode_minus_L_GCJ=yes
+ hardcode_shlibpath_var_GCJ=no
+ ;;
+
+ # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
+ freebsd* | kfreebsd*-gnu | dragonfly*)
+ archive_cmds_GCJ='$CC -shared -o $lib $libobjs $deplibs $compiler_flags'
+ hardcode_libdir_flag_spec_GCJ='-R$libdir'
+ hardcode_direct_GCJ=yes
+ hardcode_shlibpath_var_GCJ=no
+ ;;
+
+ hpux9*)
+ if test "$GCC" = yes; then
+ archive_cmds_GCJ='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+ else
+ archive_cmds_GCJ='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+ fi
+ hardcode_libdir_flag_spec_GCJ='${wl}+b ${wl}$libdir'
+ hardcode_libdir_separator_GCJ=:
+ hardcode_direct_GCJ=yes
+
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ hardcode_minus_L_GCJ=yes
+ export_dynamic_flag_spec_GCJ='${wl}-E'
+ ;;
+
+ hpux10*)
+ if test "$GCC" = yes -a "$with_gnu_ld" = no; then
+ archive_cmds_GCJ='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ archive_cmds_GCJ='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
+ fi
+ if test "$with_gnu_ld" = no; then
+ hardcode_libdir_flag_spec_GCJ='${wl}+b ${wl}$libdir'
+ hardcode_libdir_separator_GCJ=:
+
+ hardcode_direct_GCJ=yes
+ export_dynamic_flag_spec_GCJ='${wl}-E'
+
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ hardcode_minus_L_GCJ=yes
+ fi
+ ;;
+
+ hpux11*)
+ if test "$GCC" = yes -a "$with_gnu_ld" = no; then
+ case $host_cpu in
+ hppa*64*)
+ archive_cmds_GCJ='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ ia64*)
+ archive_cmds_GCJ='$CC -shared ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ *)
+ archive_cmds_GCJ='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ esac
+ else
+ case $host_cpu in
+ hppa*64*)
+ archive_cmds_GCJ='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ ia64*)
+ archive_cmds_GCJ='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ *)
+ archive_cmds_GCJ='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ esac
+ fi
+ if test "$with_gnu_ld" = no; then
+ hardcode_libdir_flag_spec_GCJ='${wl}+b ${wl}$libdir'
+ hardcode_libdir_separator_GCJ=:
+
+ case $host_cpu in
+ hppa*64*|ia64*)
+ hardcode_libdir_flag_spec_ld_GCJ='+b $libdir'
+ hardcode_direct_GCJ=no
+ hardcode_shlibpath_var_GCJ=no
+ ;;
+ *)
+ hardcode_direct_GCJ=yes
+ export_dynamic_flag_spec_GCJ='${wl}-E'
+
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ hardcode_minus_L_GCJ=yes
+ ;;
+ esac
+ fi
+ ;;
+
+ irix5* | irix6* | nonstopux*)
+ if test "$GCC" = yes; then
+ archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ else
+ archive_cmds_GCJ='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+ hardcode_libdir_flag_spec_ld_GCJ='-rpath $libdir'
+ fi
+ hardcode_libdir_flag_spec_GCJ='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator_GCJ=:
+ link_all_deplibs_GCJ=yes
+ ;;
+
+ netbsd*)
+ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+ archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out
+ else
+ archive_cmds_GCJ='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF
+ fi
+ hardcode_libdir_flag_spec_GCJ='-R$libdir'
+ hardcode_direct_GCJ=yes
+ hardcode_shlibpath_var_GCJ=no
+ ;;
+
+ newsos6)
+ archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_direct_GCJ=yes
+ hardcode_libdir_flag_spec_GCJ='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator_GCJ=:
+ hardcode_shlibpath_var_GCJ=no
+ ;;
+
+ openbsd*)
+ hardcode_direct_GCJ=yes
+ hardcode_shlibpath_var_GCJ=no
+ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ archive_cmds_GCJ='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds_GCJ='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols'
+ hardcode_libdir_flag_spec_GCJ='${wl}-rpath,$libdir'
+ export_dynamic_flag_spec_GCJ='${wl}-E'
+ else
+ case $host_os in
+ openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*)
+ archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_libdir_flag_spec_GCJ='-R$libdir'
+ ;;
+ *)
+ archive_cmds_GCJ='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+ hardcode_libdir_flag_spec_GCJ='${wl}-rpath,$libdir'
+ ;;
+ esac
+ fi
+ ;;
+
+ os2*)
+ hardcode_libdir_flag_spec_GCJ='-L$libdir'
+ hardcode_minus_L_GCJ=yes
+ allow_undefined_flag_GCJ=unsupported
+ archive_cmds_GCJ='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def'
+ old_archive_From_new_cmds_GCJ='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def'
+ ;;
+
+ osf3*)
+ if test "$GCC" = yes; then
+ allow_undefined_flag_GCJ=' ${wl}-expect_unresolved ${wl}\*'
+ archive_cmds_GCJ='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ else
+ allow_undefined_flag_GCJ=' -expect_unresolved \*'
+ archive_cmds_GCJ='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+ fi
+ hardcode_libdir_flag_spec_GCJ='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator_GCJ=:
+ ;;
+
+ osf4* | osf5*) # as osf3* with the addition of -msym flag
+ if test "$GCC" = yes; then
+ allow_undefined_flag_GCJ=' ${wl}-expect_unresolved ${wl}\*'
+ archive_cmds_GCJ='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ hardcode_libdir_flag_spec_GCJ='${wl}-rpath ${wl}$libdir'
+ else
+ allow_undefined_flag_GCJ=' -expect_unresolved \*'
+ archive_cmds_GCJ='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+ archive_expsym_cmds_GCJ='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~
+ $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~$rm $lib.exp'
+
+ # Both c and cxx compiler support -rpath directly
+ hardcode_libdir_flag_spec_GCJ='-rpath $libdir'
+ fi
+ hardcode_libdir_separator_GCJ=:
+ ;;
+
+ solaris*)
+ no_undefined_flag_GCJ=' -z text'
+ if test "$GCC" = yes; then
+ wlarc='${wl}'
+ archive_cmds_GCJ='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds_GCJ='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+ $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp'
+ else
+ wlarc=''
+ archive_cmds_GCJ='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ archive_expsym_cmds_GCJ='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp'
+ fi
+ hardcode_libdir_flag_spec_GCJ='-R$libdir'
+ hardcode_shlibpath_var_GCJ=no
+ case $host_os in
+ solaris2.[0-5] | solaris2.[0-5].*) ;;
+ *)
+ # The compiler driver will combine linker options so we
+ # cannot just pass the convience library names through
+ # without $wl, iff we do not link with $LD.
+ # Luckily, gcc supports the same syntax we need for Sun Studio.
+ # Supported since Solaris 2.6 (maybe 2.5.1?)
+ case $wlarc in
+ '')
+ whole_archive_flag_spec_GCJ='-z allextract$convenience -z defaultextract' ;;
+ *)
+ whole_archive_flag_spec_GCJ='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract' ;;
+ esac ;;
+ esac
+ link_all_deplibs_GCJ=yes
+ ;;
+
+ sunos4*)
+ if test "x$host_vendor" = xsequent; then
+ # Use $CC to link under sequent, because it throws in some extra .o
+ # files that make .init and .fini sections work.
+ archive_cmds_GCJ='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ archive_cmds_GCJ='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags'
+ fi
+ hardcode_libdir_flag_spec_GCJ='-L$libdir'
+ hardcode_direct_GCJ=yes
+ hardcode_minus_L_GCJ=yes
+ hardcode_shlibpath_var_GCJ=no
+ ;;
+
+ sysv4)
+ case $host_vendor in
+ sni)
+ archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_direct_GCJ=yes # is this really true???
+ ;;
+ siemens)
+ ## LD is ld it makes a PLAMLIB
+ ## CC just makes a GrossModule.
+ archive_cmds_GCJ='$LD -G -o $lib $libobjs $deplibs $linker_flags'
+ reload_cmds_GCJ='$CC -r -o $output$reload_objs'
+ hardcode_direct_GCJ=no
+ ;;
+ motorola)
+ archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_direct_GCJ=no #Motorola manual says yes, but my tests say they lie
+ ;;
+ esac
+ runpath_var='LD_RUN_PATH'
+ hardcode_shlibpath_var_GCJ=no
+ ;;
+
+ sysv4.3*)
+ archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_shlibpath_var_GCJ=no
+ export_dynamic_flag_spec_GCJ='-Bexport'
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_shlibpath_var_GCJ=no
+ runpath_var=LD_RUN_PATH
+ hardcode_runpath_var=yes
+ ld_shlibs_GCJ=yes
+ fi
+ ;;
+
+ sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7*)
+ no_undefined_flag_GCJ='${wl}-z,text'
+ archive_cmds_need_lc_GCJ=no
+ hardcode_shlibpath_var_GCJ=no
+ runpath_var='LD_RUN_PATH'
+
+ if test "$GCC" = yes; then
+ archive_cmds_GCJ='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds_GCJ='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ archive_cmds_GCJ='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds_GCJ='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ fi
+ ;;
+
+ sysv5* | sco3.2v5* | sco5v6*)
+ # Note: We can NOT use -z defs as we might desire, because we do not
+ # link with -lc, and that would cause any symbols used from libc to
+ # always be unresolved, which means just about no library would
+ # ever link correctly. If we're not using GNU ld we use -z text
+ # though, which does catch some bad symbols but isn't as heavy-handed
+ # as -z defs.
+ no_undefined_flag_GCJ='${wl}-z,text'
+ allow_undefined_flag_GCJ='${wl}-z,nodefs'
+ archive_cmds_need_lc_GCJ=no
+ hardcode_shlibpath_var_GCJ=no
+ hardcode_libdir_flag_spec_GCJ='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`'
+ hardcode_libdir_separator_GCJ=':'
+ link_all_deplibs_GCJ=yes
+ export_dynamic_flag_spec_GCJ='${wl}-Bexport'
+ runpath_var='LD_RUN_PATH'
+
+ if test "$GCC" = yes; then
+ archive_cmds_GCJ='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds_GCJ='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ archive_cmds_GCJ='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds_GCJ='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ fi
+ ;;
+
+ uts4*)
+ archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_libdir_flag_spec_GCJ='-L$libdir'
+ hardcode_shlibpath_var_GCJ=no
+ ;;
+
+ *)
+ ld_shlibs_GCJ=no
+ ;;
+ esac
+ fi
+
+echo "$as_me:$LINENO: result: $ld_shlibs_GCJ" >&5
+echo "${ECHO_T}$ld_shlibs_GCJ" >&6
+test "$ld_shlibs_GCJ" = no && can_build_shared=no
+
+#
+# Do we need to explicitly link libc?
+#
+case "x$archive_cmds_need_lc_GCJ" in
+x|xyes)
+ # Assume -lc should be added
+ archive_cmds_need_lc_GCJ=yes
+
+ if test "$enable_shared" = yes && test "$GCC" = yes; then
+ case $archive_cmds_GCJ in
+ *'~'*)
+ # FIXME: we may have to deal with multi-command sequences.
+ ;;
+ '$CC '*)
+ # Test whether the compiler implicitly links with -lc since on some
+ # systems, -lgcc has to come before -lc. If gcc already passes -lc
+ # to ld, don't add -lc before -lgcc.
+ echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5
+echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6
+ $rm conftest*
+ printf "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } 2>conftest.err; then
+ soname=conftest
+ lib=conftest
+ libobjs=conftest.$ac_objext
+ deplibs=
+ wl=$lt_prog_compiler_wl_GCJ
+ pic_flag=$lt_prog_compiler_pic_GCJ
+ compiler_flags=-v
+ linker_flags=-v
+ verstring=
+ output_objdir=.
+ libname=conftest
+ lt_save_allow_undefined_flag=$allow_undefined_flag_GCJ
+ allow_undefined_flag_GCJ=
+ if { (eval echo "$as_me:$LINENO: \"$archive_cmds_GCJ 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\"") >&5
+ (eval $archive_cmds_GCJ 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+ then
+ archive_cmds_need_lc_GCJ=no
+ else
+ archive_cmds_need_lc_GCJ=yes
+ fi
+ allow_undefined_flag_GCJ=$lt_save_allow_undefined_flag
+ else
+ cat conftest.err 1>&5
+ fi
+ $rm conftest*
+ echo "$as_me:$LINENO: result: $archive_cmds_need_lc_GCJ" >&5
+echo "${ECHO_T}$archive_cmds_need_lc_GCJ" >&6
+ ;;
+ esac
+ fi
+ ;;
+esac
+
+echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5
+echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6
+library_names_spec=
+libname_spec='lib$name'
+soname_spec=
+shrext_cmds=".so"
+postinstall_cmds=
+postuninstall_cmds=
+finish_cmds=
+finish_eval=
+shlibpath_var=
+shlibpath_overrides_runpath=unknown
+version_type=none
+dynamic_linker="$host_os ld.so"
+sys_lib_dlsearch_path_spec="/lib /usr/lib"
+if test "$GCC" = yes; then
+ sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
+ if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then
+ # if the path contains ";" then we assume it to be the separator
+ # otherwise default to the standard path separator (i.e. ":") - it is
+ # assumed that no part of a normal pathname contains ";" but that should
+ # okay in the real world where ";" in dirpaths is itself problematic.
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+ else
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+ fi
+else
+ sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
+fi
+need_lib_prefix=unknown
+hardcode_into_libs=no
+
+# when you set need_version to no, make sure it does not cause -set_version
+# flags to be left without arguments
+need_version=unknown
+
+case $host_os in
+aix3*)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a'
+ shlibpath_var=LIBPATH
+
+ # AIX 3 has no versioning support, so we append a major version to the name.
+ soname_spec='${libname}${release}${shared_ext}$major'
+ ;;
+
+aix4* | aix5*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ hardcode_into_libs=yes
+ if test "$host_cpu" = ia64; then
+ # AIX 5 supports IA64
+ library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ else
+ # With GCC up to 2.95.x, collect2 would create an import file
+ # for dependence libraries. The import file would start with
+ # the line `#! .'. This would cause the generated library to
+ # depend on `.', always an invalid library. This was fixed in
+ # development snapshots of GCC prior to 3.0.
+ case $host_os in
+ aix4 | aix4.[01] | aix4.[01].*)
+ if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
+ echo ' yes '
+ echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then
+ :
+ else
+ can_build_shared=no
+ fi
+ ;;
+ esac
+ # AIX (on Power*) has no versioning support, so currently we can not hardcode correct
+ # soname into executable. Probably we can add versioning support to
+ # collect2, so additional links can be useful in future.
+ if test "$aix_use_runtimelinking" = yes; then
+ # If using run time linking (on AIX 4.2 or later) use lib<name>.so
+ # instead of lib<name>.a to let people know that these are not
+ # typical AIX shared libraries.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ else
+ # We preserve .a as extension for shared libraries through AIX4.2
+ # and later when we are not doing run time linking.
+ library_names_spec='${libname}${release}.a $libname.a'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ fi
+ shlibpath_var=LIBPATH
+ fi
+ ;;
+
+amigaos*)
+ library_names_spec='$libname.ixlibrary $libname.a'
+ # Create ${libname}_ixlibrary.a entries in /sys/libs.
+ finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
+ ;;
+
+beos*)
+ library_names_spec='${libname}${shared_ext}'
+ dynamic_linker="$host_os ld.so"
+ shlibpath_var=LIBRARY_PATH
+ ;;
+
+bsdi[45]*)
+ version_type=linux
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
+ sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
+ # the default ld.so.conf also contains /usr/contrib/lib and
+ # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
+ # libtool to hard-code these into programs
+ ;;
+
+cygwin* | mingw* | pw32*)
+ version_type=windows
+ shrext_cmds=".dll"
+ need_version=no
+ need_lib_prefix=no
+
+ case $GCC,$host_os in
+ yes,cygwin* | yes,mingw* | yes,pw32*)
+ library_names_spec='$libname.dll.a'
+ # DLL is installed to $(libdir)/../bin by postinstall_cmds
+ postinstall_cmds='base_file=`basename \${file}`~
+ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~
+ dldir=$destdir/`dirname \$dlpath`~
+ test -d \$dldir || mkdir -p \$dldir~
+ $install_prog $dir/$dlname \$dldir/$dlname~
+ chmod a+x \$dldir/$dlname'
+ postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+ dlpath=$dir/\$dldll~
+ $rm \$dlpath'
+ shlibpath_overrides_runpath=yes
+
+ case $host_os in
+ cygwin*)
+ # Cygwin DLLs use 'cyg' prefix rather than 'lib'
+ soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+ sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib"
+ ;;
+ mingw*)
+ # MinGW DLLs use traditional 'lib' prefix
+ soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+ sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
+ if echo "$sys_lib_search_path_spec" | grep ';[c-zC-Z]:/' >/dev/null; then
+ # It is most probably a Windows format PATH printed by
+ # mingw gcc, but we are running on Cygwin. Gcc prints its search
+ # path with ; separators, and with drive letters. We can handle the
+ # drive letters (cygwin fileutils understands them), so leave them,
+ # especially as we might pass files found there to a mingw objdump,
+ # which wouldn't understand a cygwinified path. Ahh.
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+ else
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+ fi
+ ;;
+ pw32*)
+ # pw32 DLLs use 'pw' prefix rather than 'lib'
+ library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+ ;;
+ esac
+ ;;
+
+ *)
+ library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib'
+ ;;
+ esac
+ dynamic_linker='Win32 ld.exe'
+ # FIXME: first we should search . and the directory the executable is in
+ shlibpath_var=PATH
+ ;;
+
+darwin* | rhapsody*)
+ dynamic_linker="$host_os dyld"
+ version_type=darwin
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext'
+ soname_spec='${libname}${release}${major}$shared_ext'
+ shlibpath_overrides_runpath=yes
+ shlibpath_var=DYLD_LIBRARY_PATH
+ shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
+ # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same.
+ if test "$GCC" = yes; then
+ sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"`
+ else
+ sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib'
+ fi
+ sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
+ ;;
+
+dgux*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+freebsd1*)
+ dynamic_linker=no
+ ;;
+
+kfreebsd*-gnu)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ dynamic_linker='GNU ld.so'
+ ;;
+
+freebsd* | dragonfly*)
+ # DragonFly does not have aout. When/if they implement a new
+ # versioning mechanism, adjust this.
+ if test -x /usr/bin/objformat; then
+ objformat=`/usr/bin/objformat`
+ else
+ case $host_os in
+ freebsd[123]*) objformat=aout ;;
+ *) objformat=elf ;;
+ esac
+ fi
+ version_type=freebsd-$objformat
+ case $version_type in
+ freebsd-elf*)
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+ need_version=no
+ need_lib_prefix=no
+ ;;
+ freebsd-*)
+ library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix'
+ need_version=yes
+ ;;
+ esac
+ shlibpath_var=LD_LIBRARY_PATH
+ case $host_os in
+ freebsd2*)
+ shlibpath_overrides_runpath=yes
+ ;;
+ freebsd3.[01]* | freebsdelf3.[01]*)
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+ freebsd3.[2-9]* | freebsdelf3.[2-9]* | \
+ freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1)
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ ;;
+ freebsd*) # from 4.6 on
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+ esac
+ ;;
+
+gnu*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ hardcode_into_libs=yes
+ ;;
+
+hpux9* | hpux10* | hpux11*)
+ # Give a soname corresponding to the major version so that dld.sl refuses to
+ # link against other versions.
+ version_type=sunos
+ need_lib_prefix=no
+ need_version=no
+ case $host_cpu in
+ ia64*)
+ shrext_cmds='.so'
+ hardcode_into_libs=yes
+ dynamic_linker="$host_os dld.so"
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ if test "X$HPUX_IA64_MODE" = X32; then
+ sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
+ else
+ sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
+ fi
+ sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+ ;;
+ hppa*64*)
+ shrext_cmds='.sl'
+ hardcode_into_libs=yes
+ dynamic_linker="$host_os dld.sl"
+ shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
+ shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
+ sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+ ;;
+ *)
+ shrext_cmds='.sl'
+ dynamic_linker="$host_os dld.sl"
+ shlibpath_var=SHLIB_PATH
+ shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ ;;
+ esac
+ # HP-UX runs *really* slowly unless shared libraries are mode 555.
+ postinstall_cmds='chmod 555 $lib'
+ ;;
+
+interix3*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ ;;
+
+irix5* | irix6* | nonstopux*)
+ case $host_os in
+ nonstopux*) version_type=nonstopux ;;
+ *)
+ if test "$lt_cv_prog_gnu_ld" = yes; then
+ version_type=linux
+ else
+ version_type=irix
+ fi ;;
+ esac
+ need_lib_prefix=no
+ need_version=no
+ soname_spec='${libname}${release}${shared_ext}$major'
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}'
+ case $host_os in
+ irix5* | nonstopux*)
+ libsuff= shlibsuff=
+ ;;
+ *)
+ case $LD in # libtool.m4 will add one of these switches to LD
+ *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ")
+ libsuff= shlibsuff= libmagic=32-bit;;
+ *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ")
+ libsuff=32 shlibsuff=N32 libmagic=N32;;
+ *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ")
+ libsuff=64 shlibsuff=64 libmagic=64-bit;;
+ *) libsuff= shlibsuff= libmagic=never-match;;
+ esac
+ ;;
+ esac
+ shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
+ shlibpath_overrides_runpath=no
+ sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
+ sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
+ hardcode_into_libs=yes
+ ;;
+
+# No shared lib support for Linux oldld, aout, or coff.
+linux*oldld* | linux*aout* | linux*coff*)
+ dynamic_linker=no
+ ;;
+
+# This must be Linux ELF.
+linux*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ # This implies no fast_install, which is unacceptable.
+ # Some rework will be needed to allow for fast_install
+ # before this can be enabled.
+ hardcode_into_libs=yes
+
+ # find out which ABI we are using
+ libsuff=
+ case "$host_cpu" in
+ x86_64*|s390x*|powerpc64*)
+ echo '#line 24834 "configure"' > conftest.$ac_ext
+ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ case `/usr/bin/file conftest.$ac_objext` in
+ *64-bit*)
+ libsuff=64
+ sys_lib_search_path_spec="/lib${libsuff} /usr/lib${libsuff} /usr/local/lib${libsuff}"
+ ;;
+ esac
+ fi
+ rm -rf conftest*
+ ;;
+ esac
+
+ # Append ld.so.conf contents to the search path
+ if test -f /etc/ld.so.conf; then
+ lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '`
+ sys_lib_dlsearch_path_spec="/lib${libsuff} /usr/lib${libsuff} $lt_ld_extra"
+ fi
+
+ # We used to test for /lib/ld.so.1 and disable shared libraries on
+ # powerpc, because MkLinux only supported shared libraries with the
+ # GNU dynamic linker. Since this was broken with cross compilers,
+ # most powerpc-linux boxes support dynamic linking these days and
+ # people can always --disable-shared, the test was removed, and we
+ # assume the GNU/Linux dynamic linker is in use.
+ dynamic_linker='GNU/Linux ld.so'
+ ;;
+
+knetbsd*-gnu)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ dynamic_linker='GNU ld.so'
+ ;;
+
+netbsd*)
+ version_type=sunos
+ need_lib_prefix=no
+ need_version=no
+ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+ dynamic_linker='NetBSD (a.out) ld.so'
+ else
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ dynamic_linker='NetBSD ld.elf_so'
+ fi
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+
+newsos6)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ ;;
+
+nto-qnx*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ ;;
+
+openbsd*)
+ version_type=sunos
+ sys_lib_dlsearch_path_spec="/usr/lib"
+ need_lib_prefix=no
+ # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs.
+ case $host_os in
+ openbsd3.3 | openbsd3.3.*) need_version=yes ;;
+ *) need_version=no ;;
+ esac
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ case $host_os in
+ openbsd2.[89] | openbsd2.[89].*)
+ shlibpath_overrides_runpath=no
+ ;;
+ *)
+ shlibpath_overrides_runpath=yes
+ ;;
+ esac
+ else
+ shlibpath_overrides_runpath=yes
+ fi
+ ;;
+
+os2*)
+ libname_spec='$name'
+ shrext_cmds=".dll"
+ need_lib_prefix=no
+ library_names_spec='$libname${shared_ext} $libname.a'
+ dynamic_linker='OS/2 ld.exe'
+ shlibpath_var=LIBPATH
+ ;;
+
+osf3* | osf4* | osf5*)
+ version_type=osf
+ need_lib_prefix=no
+ need_version=no
+ soname_spec='${libname}${release}${shared_ext}$major'
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
+ sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec"
+ ;;
+
+solaris*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ # ldd complains unless libraries are executable
+ postinstall_cmds='chmod +x $lib'
+ ;;
+
+sunos4*)
+ version_type=sunos
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ if test "$with_gnu_ld" = yes; then
+ need_lib_prefix=no
+ fi
+ need_version=yes
+ ;;
+
+sysv4 | sysv4.3*)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ case $host_vendor in
+ sni)
+ shlibpath_overrides_runpath=no
+ need_lib_prefix=no
+ export_dynamic_flag_spec='${wl}-Blargedynsym'
+ runpath_var=LD_RUN_PATH
+ ;;
+ siemens)
+ need_lib_prefix=no
+ ;;
+ motorola)
+ need_lib_prefix=no
+ need_version=no
+ shlibpath_overrides_runpath=no
+ sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
+ ;;
+ esac
+ ;;
+
+sysv4*MP*)
+ if test -d /usr/nec ;then
+ version_type=linux
+ library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}'
+ soname_spec='$libname${shared_ext}.$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ fi
+ ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+ version_type=freebsd-elf
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ hardcode_into_libs=yes
+ if test "$with_gnu_ld" = yes; then
+ sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib'
+ shlibpath_overrides_runpath=no
+ else
+ sys_lib_search_path_spec='/usr/ccs/lib /usr/lib'
+ shlibpath_overrides_runpath=yes
+ case $host_os in
+ sco3.2v5*)
+ sys_lib_search_path_spec="$sys_lib_search_path_spec /lib"
+ ;;
+ esac
+ fi
+ sys_lib_dlsearch_path_spec='/usr/lib'
+ ;;
+
+uts4*)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+*)
+ dynamic_linker=no
+ ;;
+esac
+echo "$as_me:$LINENO: result: $dynamic_linker" >&5
+echo "${ECHO_T}$dynamic_linker" >&6
+test "$dynamic_linker" = no && can_build_shared=no
+
+variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
+if test "$GCC" = yes; then
+ variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
+fi
+
+echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5
+echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6
+hardcode_action_GCJ=
+if test -n "$hardcode_libdir_flag_spec_GCJ" || \
+ test -n "$runpath_var_GCJ" || \
+ test "X$hardcode_automatic_GCJ" = "Xyes" ; then
+
+ # We can hardcode non-existant directories.
+ if test "$hardcode_direct_GCJ" != no &&
+ # If the only mechanism to avoid hardcoding is shlibpath_var, we
+ # have to relink, otherwise we might link with an installed library
+ # when we should be linking with a yet-to-be-installed one
+ ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, GCJ)" != no &&
+ test "$hardcode_minus_L_GCJ" != no; then
+ # Linking always hardcodes the temporary library directory.
+ hardcode_action_GCJ=relink
+ else
+ # We can link without hardcoding, and we can hardcode nonexisting dirs.
+ hardcode_action_GCJ=immediate
+ fi
+else
+ # We cannot hardcode anything, or else we can only hardcode existing
+ # directories.
+ hardcode_action_GCJ=unsupported
+fi
+echo "$as_me:$LINENO: result: $hardcode_action_GCJ" >&5
+echo "${ECHO_T}$hardcode_action_GCJ" >&6
+
+if test "$hardcode_action_GCJ" = relink; then
+ # Fast installation is not supported
+ enable_fast_install=no
+elif test "$shlibpath_overrides_runpath" = yes ||
+ test "$enable_shared" = no; then
+ # Fast installation is not necessary
+ enable_fast_install=needless
+fi
+
+
+# The else clause should only fire when bootstrapping the
+# libtool distribution, otherwise you forgot to ship ltmain.sh
+# with your package, and you will get complaints that there are
+# no rules to generate ltmain.sh.
+if test -f "$ltmain"; then
+ # See if we are running on zsh, and set the options which allow our commands through
+ # without removal of \ escapes.
+ if test -n "${ZSH_VERSION+set}" ; then
+ setopt NO_GLOB_SUBST
+ fi
+ # Now quote all the things that may contain metacharacters while being
+ # careful not to overquote the AC_SUBSTed values. We take copies of the
+ # variables and quote the copies for generation of the libtool script.
+ for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \
+ SED SHELL STRIP \
+ libname_spec library_names_spec soname_spec extract_expsyms_cmds \
+ old_striplib striplib file_magic_cmd finish_cmds finish_eval \
+ deplibs_check_method reload_flag reload_cmds need_locks \
+ lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \
+ lt_cv_sys_global_symbol_to_c_name_address \
+ sys_lib_search_path_spec sys_lib_dlsearch_path_spec \
+ old_postinstall_cmds old_postuninstall_cmds \
+ compiler_GCJ \
+ CC_GCJ \
+ LD_GCJ \
+ lt_prog_compiler_wl_GCJ \
+ lt_prog_compiler_pic_GCJ \
+ lt_prog_compiler_static_GCJ \
+ lt_prog_compiler_no_builtin_flag_GCJ \
+ export_dynamic_flag_spec_GCJ \
+ thread_safe_flag_spec_GCJ \
+ whole_archive_flag_spec_GCJ \
+ enable_shared_with_static_runtimes_GCJ \
+ old_archive_cmds_GCJ \
+ old_archive_from_new_cmds_GCJ \
+ predep_objects_GCJ \
+ postdep_objects_GCJ \
+ predeps_GCJ \
+ postdeps_GCJ \
+ compiler_lib_search_path_GCJ \
+ archive_cmds_GCJ \
+ archive_expsym_cmds_GCJ \
+ postinstall_cmds_GCJ \
+ postuninstall_cmds_GCJ \
+ old_archive_from_expsyms_cmds_GCJ \
+ allow_undefined_flag_GCJ \
+ no_undefined_flag_GCJ \
+ export_symbols_cmds_GCJ \
+ hardcode_libdir_flag_spec_GCJ \
+ hardcode_libdir_flag_spec_ld_GCJ \
+ hardcode_libdir_separator_GCJ \
+ hardcode_automatic_GCJ \
+ module_cmds_GCJ \
+ module_expsym_cmds_GCJ \
+ lt_cv_prog_compiler_c_o_GCJ \
+ exclude_expsyms_GCJ \
+ include_expsyms_GCJ; do
+
+ case $var in
+ old_archive_cmds_GCJ | \
+ old_archive_from_new_cmds_GCJ | \
+ archive_cmds_GCJ | \
+ archive_expsym_cmds_GCJ | \
+ module_cmds_GCJ | \
+ module_expsym_cmds_GCJ | \
+ old_archive_from_expsyms_cmds_GCJ | \
+ export_symbols_cmds_GCJ | \
+ extract_expsyms_cmds | reload_cmds | finish_cmds | \
+ postinstall_cmds | postuninstall_cmds | \
+ old_postinstall_cmds | old_postuninstall_cmds | \
+ sys_lib_search_path_spec | sys_lib_dlsearch_path_spec)
+ # Double-quote double-evaled strings.
+ eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\""
+ ;;
+ *)
+ eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\""
+ ;;
+ esac
+ done
+
+ case $lt_echo in
+ *'\$0 --fallback-echo"')
+ lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'`
+ ;;
+ esac
+
+cfgfile="$ofile"
+
+ cat <<__EOF__ >> "$cfgfile"
+# ### BEGIN LIBTOOL TAG CONFIG: $tagname
+
+# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+
+# Shell to use when invoking shell scripts.
+SHELL=$lt_SHELL
+
+# Whether or not to build shared libraries.
+build_libtool_libs=$enable_shared
+
+# Whether or not to build static libraries.
+build_old_libs=$enable_static
+
+# Whether or not to add -lc for building shared libraries.
+build_libtool_need_lc=$archive_cmds_need_lc_GCJ
+
+# Whether or not to disallow shared libs when runtime libs are static
+allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_GCJ
+
+# Whether or not to optimize for fast installation.
+fast_install=$enable_fast_install
+
+# The host system.
+host_alias=$host_alias
+host=$host
+host_os=$host_os
+
+# The build system.
+build_alias=$build_alias
+build=$build
+build_os=$build_os
+
+# An echo program that does not interpret backslashes.
+echo=$lt_echo
+
+# The archiver.
+AR=$lt_AR
+AR_FLAGS=$lt_AR_FLAGS
+
+# A C compiler.
+LTCC=$lt_LTCC
+
+# LTCC compiler flags.
+LTCFLAGS=$lt_LTCFLAGS
+
+# A language-specific compiler.
+CC=$lt_compiler_GCJ
+
+# Is the compiler the GNU C compiler?
+with_gcc=$GCC_GCJ
+
+gcc_dir=\`gcc -print-file-name=. | $SED 's,/\.$,,'\`
+gcc_ver=\`gcc -dumpversion\`
+
+# An ERE matcher.
+EGREP=$lt_EGREP
+
+# The linker used to build libraries.
+LD=$lt_LD_GCJ
+
+# Whether we need hard or soft links.
+LN_S=$lt_LN_S
+
+# A BSD-compatible nm program.
+NM=$lt_NM
+
+# A symbol stripping program
+STRIP=$lt_STRIP
+
+# Used to examine libraries when file_magic_cmd begins "file"
+MAGIC_CMD=$MAGIC_CMD
+
+# Used on cygwin: DLL creation program.
+DLLTOOL="$DLLTOOL"
+
+# Used on cygwin: object dumper.
+OBJDUMP="$OBJDUMP"
+
+# Used on cygwin: assembler.
+AS="$AS"
+
+# The name of the directory that contains temporary libtool files.
+objdir=$objdir
+
+# How to create reloadable object files.
+reload_flag=$lt_reload_flag
+reload_cmds=$lt_reload_cmds
+
+# How to pass a linker flag through the compiler.
+wl=$lt_lt_prog_compiler_wl_GCJ
+
+# Object file suffix (normally "o").
+objext="$ac_objext"
+
+# Old archive suffix (normally "a").
+libext="$libext"
+
+# Shared library suffix (normally ".so").
+shrext_cmds='$shrext_cmds'
+
+# Executable file suffix (normally "").
+exeext="$exeext"
+
+# Additional compiler flags for building library objects.
+pic_flag=$lt_lt_prog_compiler_pic_GCJ
+pic_mode=$pic_mode
+
+# What is the maximum length of a command?
+max_cmd_len=$lt_cv_sys_max_cmd_len
+
+# Does compiler simultaneously support -c and -o options?
+compiler_c_o=$lt_lt_cv_prog_compiler_c_o_GCJ
+
+# Must we lock files when doing compilation?
+need_locks=$lt_need_locks
+
+# Do we need the lib prefix for modules?
+need_lib_prefix=$need_lib_prefix
+
+# Do we need a version for libraries?
+need_version=$need_version
+
+# Whether dlopen is supported.
+dlopen_support=$enable_dlopen
+
+# Whether dlopen of programs is supported.
+dlopen_self=$enable_dlopen_self
+
+# Whether dlopen of statically linked programs is supported.
+dlopen_self_static=$enable_dlopen_self_static
+
+# Compiler flag to prevent dynamic linking.
+link_static_flag=$lt_lt_prog_compiler_static_GCJ
+
+# Compiler flag to turn off builtin functions.
+no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_GCJ
+
+# Compiler flag to allow reflexive dlopens.
+export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_GCJ
+
+# Compiler flag to generate shared objects directly from archives.
+whole_archive_flag_spec=$lt_whole_archive_flag_spec_GCJ
+
+# Compiler flag to generate thread-safe objects.
+thread_safe_flag_spec=$lt_thread_safe_flag_spec_GCJ
+
+# Library versioning type.
+version_type=$version_type
+
+# Format of library name prefix.
+libname_spec=$lt_libname_spec
+
+# List of archive names. First name is the real one, the rest are links.
+# The last name is the one that the linker finds with -lNAME.
+library_names_spec=$lt_library_names_spec
+
+# The coded name of the library, if different from the real name.
+soname_spec=$lt_soname_spec
+
+# Commands used to build and install an old-style archive.
+RANLIB=$lt_RANLIB
+old_archive_cmds=$lt_old_archive_cmds_GCJ
+old_postinstall_cmds=$lt_old_postinstall_cmds
+old_postuninstall_cmds=$lt_old_postuninstall_cmds
+
+# Create an old-style archive from a shared archive.
+old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_GCJ
+
+# Create a temporary old-style archive to link instead of a shared archive.
+old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_GCJ
+
+# Commands used to build and install a shared archive.
+archive_cmds=$lt_archive_cmds_GCJ
+archive_expsym_cmds=$lt_archive_expsym_cmds_GCJ
+postinstall_cmds=$lt_postinstall_cmds
+postuninstall_cmds=$lt_postuninstall_cmds
+
+# Commands used to build a loadable module (assumed same as above if empty)
+module_cmds=$lt_module_cmds_GCJ
+module_expsym_cmds=$lt_module_expsym_cmds_GCJ
+
+# Commands to strip libraries.
+old_striplib=$lt_old_striplib
+striplib=$lt_striplib
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predep_objects=\`echo $lt_predep_objects_GCJ | \$SED -e "s@\${gcc_dir}@\\\${gcc_dir}@g;s@\${gcc_ver}@\\\${gcc_ver}@g"\`
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdep_objects=\`echo $lt_postdep_objects_GCJ | \$SED -e "s@\${gcc_dir}@\\\${gcc_dir}@g;s@\${gcc_ver}@\\\${gcc_ver}@g"\`
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predeps=$lt_predeps_GCJ
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdeps=$lt_postdeps_GCJ
+
+# The library search path used internally by the compiler when linking
+# a shared library.
+compiler_lib_search_path=\`echo $lt_compiler_lib_search_path_GCJ | \$SED -e "s@\${gcc_dir}@\\\${gcc_dir}@g;s@\${gcc_ver}@\\\${gcc_ver}@g"\`
+
+# Method to check whether dependent libraries are shared objects.
+deplibs_check_method=$lt_deplibs_check_method
+
+# Command to use when deplibs_check_method == file_magic.
+file_magic_cmd=$lt_file_magic_cmd
+
+# Flag that allows shared libraries with undefined symbols to be built.
+allow_undefined_flag=$lt_allow_undefined_flag_GCJ
+
+# Flag that forces no undefined symbols.
+no_undefined_flag=$lt_no_undefined_flag_GCJ
+
+# Commands used to finish a libtool library installation in a directory.
+finish_cmds=$lt_finish_cmds
+
+# Same as above, but a single script fragment to be evaled but not shown.
+finish_eval=$lt_finish_eval
+
+# Take the output of nm and produce a listing of raw symbols and C names.
+global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe
+
+# Transform the output of nm in a proper C declaration
+global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl
+
+# Transform the output of nm in a C name address pair
+global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address
+
+# This is the shared library runtime path variable.
+runpath_var=$runpath_var
+
+# This is the shared library path variable.
+shlibpath_var=$shlibpath_var
+
+# Is shlibpath searched before the hard-coded library search path?
+shlibpath_overrides_runpath=$shlibpath_overrides_runpath
+
+# How to hardcode a shared library path into an executable.
+hardcode_action=$hardcode_action_GCJ
+
+# Whether we should hardcode library paths into libraries.
+hardcode_into_libs=$hardcode_into_libs
+
+# Flag to hardcode \$libdir into a binary during linking.
+# This must work even if \$libdir does not exist.
+hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_GCJ
+
+# If ld is used when linking, flag to hardcode \$libdir into
+# a binary during linking. This must work even if \$libdir does
+# not exist.
+hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_GCJ
+
+# Whether we need a single -rpath flag with a separated argument.
+hardcode_libdir_separator=$lt_hardcode_libdir_separator_GCJ
+
+# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the
+# resulting binary.
+hardcode_direct=$hardcode_direct_GCJ
+
+# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
+# resulting binary.
+hardcode_minus_L=$hardcode_minus_L_GCJ
+
+# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into
+# the resulting binary.
+hardcode_shlibpath_var=$hardcode_shlibpath_var_GCJ
+
+# Set to yes if building a shared library automatically hardcodes DIR into the library
+# and all subsequent libraries and executables linked against it.
+hardcode_automatic=$hardcode_automatic_GCJ
+
+# Variables whose values should be saved in libtool wrapper scripts and
+# restored at relink time.
+variables_saved_for_relink="$variables_saved_for_relink"
+
+# Whether libtool must link a program against all its dependency libraries.
+link_all_deplibs=$link_all_deplibs_GCJ
+
+# Compile-time system search path for libraries
+sys_lib_search_path_spec=\`echo $lt_sys_lib_search_path_spec | \$SED -e "s@\${gcc_dir}@\\\${gcc_dir}@g;s@\${gcc_ver}@\\\${gcc_ver}@g"\`
+
+# Run-time system search path for libraries
+sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec
+
+# Fix the shell variable \$srcfile for the compiler.
+fix_srcfile_path="$fix_srcfile_path_GCJ"
+
+# Set to yes if exported symbols are required.
+always_export_symbols=$always_export_symbols_GCJ
+
+# The commands to list exported symbols.
+export_symbols_cmds=$lt_export_symbols_cmds_GCJ
+
+# The commands to extract the exported symbol list from a shared archive.
+extract_expsyms_cmds=$lt_extract_expsyms_cmds
+
+# Symbols that should not be listed in the preloaded symbols.
+exclude_expsyms=$lt_exclude_expsyms_GCJ
+
+# Symbols that must always be exported.
+include_expsyms=$lt_include_expsyms_GCJ
+
+# ### END LIBTOOL TAG CONFIG: $tagname
+
+__EOF__
+
+
+else
+ # If there is no Makefile yet, we rely on a make rule to execute
+ # `config.status --recheck' to rerun these tests and create the
+ # libtool script then.
+ ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'`
+ if test -f "$ltmain_in"; then
+ test -f Makefile && make "$ltmain"
+ fi
+fi
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_linkonly='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_objext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+CC="$lt_save_CC"
+
+ else
+ tagname=""
+ fi
+ ;;
+
+ RC)
+
+
+
+# Source file extension for RC test sources.
+ac_ext=rc
+
+# Object file extension for compiled RC test sources.
+objext=o
+objext_RC=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }\n'
+
+# Code to be used in simple link tests
+lt_simple_link_test_code="$lt_simple_compile_test_code"
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# If no C compiler flags were specified, use CFLAGS.
+LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+
+
+# save warnings/boilerplate of simple test code
+ac_outfile=conftest.$ac_objext
+printf "$lt_simple_compile_test_code" >conftest.$ac_ext
+eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_compiler_boilerplate=`cat conftest.err`
+$rm conftest*
+
+ac_outfile=conftest.$ac_objext
+printf "$lt_simple_link_test_code" >conftest.$ac_ext
+eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_linker_boilerplate=`cat conftest.err`
+$rm conftest*
+
+
+# Allow CC to be a program name with arguments.
+lt_save_CC="$CC"
+CC=${RC-"windres"}
+compiler=$CC
+compiler_RC=$CC
+for cc_temp in $compiler""; do
+ case $cc_temp in
+ compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
+ distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
+ \-*) ;;
+ *) break;;
+ esac
+done
+cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"`
+
+lt_cv_prog_compiler_c_o_RC=yes
+
+# The else clause should only fire when bootstrapping the
+# libtool distribution, otherwise you forgot to ship ltmain.sh
+# with your package, and you will get complaints that there are
+# no rules to generate ltmain.sh.
+if test -f "$ltmain"; then
+ # See if we are running on zsh, and set the options which allow our commands through
+ # without removal of \ escapes.
+ if test -n "${ZSH_VERSION+set}" ; then
+ setopt NO_GLOB_SUBST
+ fi
+ # Now quote all the things that may contain metacharacters while being
+ # careful not to overquote the AC_SUBSTed values. We take copies of the
+ # variables and quote the copies for generation of the libtool script.
+ for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \
+ SED SHELL STRIP \
+ libname_spec library_names_spec soname_spec extract_expsyms_cmds \
+ old_striplib striplib file_magic_cmd finish_cmds finish_eval \
+ deplibs_check_method reload_flag reload_cmds need_locks \
+ lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \
+ lt_cv_sys_global_symbol_to_c_name_address \
+ sys_lib_search_path_spec sys_lib_dlsearch_path_spec \
+ old_postinstall_cmds old_postuninstall_cmds \
+ compiler_RC \
+ CC_RC \
+ LD_RC \
+ lt_prog_compiler_wl_RC \
+ lt_prog_compiler_pic_RC \
+ lt_prog_compiler_static_RC \
+ lt_prog_compiler_no_builtin_flag_RC \
+ export_dynamic_flag_spec_RC \
+ thread_safe_flag_spec_RC \
+ whole_archive_flag_spec_RC \
+ enable_shared_with_static_runtimes_RC \
+ old_archive_cmds_RC \
+ old_archive_from_new_cmds_RC \
+ predep_objects_RC \
+ postdep_objects_RC \
+ predeps_RC \
+ postdeps_RC \
+ compiler_lib_search_path_RC \
+ archive_cmds_RC \
+ archive_expsym_cmds_RC \
+ postinstall_cmds_RC \
+ postuninstall_cmds_RC \
+ old_archive_from_expsyms_cmds_RC \
+ allow_undefined_flag_RC \
+ no_undefined_flag_RC \
+ export_symbols_cmds_RC \
+ hardcode_libdir_flag_spec_RC \
+ hardcode_libdir_flag_spec_ld_RC \
+ hardcode_libdir_separator_RC \
+ hardcode_automatic_RC \
+ module_cmds_RC \
+ module_expsym_cmds_RC \
+ lt_cv_prog_compiler_c_o_RC \
+ exclude_expsyms_RC \
+ include_expsyms_RC; do
+
+ case $var in
+ old_archive_cmds_RC | \
+ old_archive_from_new_cmds_RC | \
+ archive_cmds_RC | \
+ archive_expsym_cmds_RC | \
+ module_cmds_RC | \
+ module_expsym_cmds_RC | \
+ old_archive_from_expsyms_cmds_RC | \
+ export_symbols_cmds_RC | \
+ extract_expsyms_cmds | reload_cmds | finish_cmds | \
+ postinstall_cmds | postuninstall_cmds | \
+ old_postinstall_cmds | old_postuninstall_cmds | \
+ sys_lib_search_path_spec | sys_lib_dlsearch_path_spec)
+ # Double-quote double-evaled strings.
+ eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\""
+ ;;
+ *)
+ eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\""
+ ;;
+ esac
+ done
+
+ case $lt_echo in
+ *'\$0 --fallback-echo"')
+ lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'`
+ ;;
+ esac
+
+cfgfile="$ofile"
+
+ cat <<__EOF__ >> "$cfgfile"
+# ### BEGIN LIBTOOL TAG CONFIG: $tagname
+
+# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+
+# Shell to use when invoking shell scripts.
+SHELL=$lt_SHELL
+
+# Whether or not to build shared libraries.
+build_libtool_libs=$enable_shared
+
+# Whether or not to build static libraries.
+build_old_libs=$enable_static
+
+# Whether or not to add -lc for building shared libraries.
+build_libtool_need_lc=$archive_cmds_need_lc_RC
+
+# Whether or not to disallow shared libs when runtime libs are static
+allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_RC
+
+# Whether or not to optimize for fast installation.
+fast_install=$enable_fast_install
+
+# The host system.
+host_alias=$host_alias
+host=$host
+host_os=$host_os
+
+# The build system.
+build_alias=$build_alias
+build=$build
+build_os=$build_os
+
+# An echo program that does not interpret backslashes.
+echo=$lt_echo
+
+# The archiver.
+AR=$lt_AR
+AR_FLAGS=$lt_AR_FLAGS
+
+# A C compiler.
+LTCC=$lt_LTCC
+
+# LTCC compiler flags.
+LTCFLAGS=$lt_LTCFLAGS
+
+# A language-specific compiler.
+CC=$lt_compiler_RC
+
+# Is the compiler the GNU C compiler?
+with_gcc=$GCC_RC
+
+gcc_dir=\`gcc -print-file-name=. | $SED 's,/\.$,,'\`
+gcc_ver=\`gcc -dumpversion\`
+
+# An ERE matcher.
+EGREP=$lt_EGREP
+
+# The linker used to build libraries.
+LD=$lt_LD_RC
+
+# Whether we need hard or soft links.
+LN_S=$lt_LN_S
+
+# A BSD-compatible nm program.
+NM=$lt_NM
+
+# A symbol stripping program
+STRIP=$lt_STRIP
+
+# Used to examine libraries when file_magic_cmd begins "file"
+MAGIC_CMD=$MAGIC_CMD
+
+# Used on cygwin: DLL creation program.
+DLLTOOL="$DLLTOOL"
+
+# Used on cygwin: object dumper.
+OBJDUMP="$OBJDUMP"
+
+# Used on cygwin: assembler.
+AS="$AS"
+
+# The name of the directory that contains temporary libtool files.
+objdir=$objdir
+
+# How to create reloadable object files.
+reload_flag=$lt_reload_flag
+reload_cmds=$lt_reload_cmds
+
+# How to pass a linker flag through the compiler.
+wl=$lt_lt_prog_compiler_wl_RC
+
+# Object file suffix (normally "o").
+objext="$ac_objext"
+
+# Old archive suffix (normally "a").
+libext="$libext"
+
+# Shared library suffix (normally ".so").
+shrext_cmds='$shrext_cmds'
+
+# Executable file suffix (normally "").
+exeext="$exeext"
+
+# Additional compiler flags for building library objects.
+pic_flag=$lt_lt_prog_compiler_pic_RC
+pic_mode=$pic_mode
+
+# What is the maximum length of a command?
+max_cmd_len=$lt_cv_sys_max_cmd_len
+
+# Does compiler simultaneously support -c and -o options?
+compiler_c_o=$lt_lt_cv_prog_compiler_c_o_RC
+
+# Must we lock files when doing compilation?
+need_locks=$lt_need_locks
+
+# Do we need the lib prefix for modules?
+need_lib_prefix=$need_lib_prefix
+
+# Do we need a version for libraries?
+need_version=$need_version
+
+# Whether dlopen is supported.
+dlopen_support=$enable_dlopen
+
+# Whether dlopen of programs is supported.
+dlopen_self=$enable_dlopen_self
+
+# Whether dlopen of statically linked programs is supported.
+dlopen_self_static=$enable_dlopen_self_static
+
+# Compiler flag to prevent dynamic linking.
+link_static_flag=$lt_lt_prog_compiler_static_RC
+
+# Compiler flag to turn off builtin functions.
+no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_RC
+
+# Compiler flag to allow reflexive dlopens.
+export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_RC
+
+# Compiler flag to generate shared objects directly from archives.
+whole_archive_flag_spec=$lt_whole_archive_flag_spec_RC
+
+# Compiler flag to generate thread-safe objects.
+thread_safe_flag_spec=$lt_thread_safe_flag_spec_RC
+
+# Library versioning type.
+version_type=$version_type
+
+# Format of library name prefix.
+libname_spec=$lt_libname_spec
+
+# List of archive names. First name is the real one, the rest are links.
+# The last name is the one that the linker finds with -lNAME.
+library_names_spec=$lt_library_names_spec
+
+# The coded name of the library, if different from the real name.
+soname_spec=$lt_soname_spec
+
+# Commands used to build and install an old-style archive.
+RANLIB=$lt_RANLIB
+old_archive_cmds=$lt_old_archive_cmds_RC
+old_postinstall_cmds=$lt_old_postinstall_cmds
+old_postuninstall_cmds=$lt_old_postuninstall_cmds
+
+# Create an old-style archive from a shared archive.
+old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_RC
+
+# Create a temporary old-style archive to link instead of a shared archive.
+old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_RC
+
+# Commands used to build and install a shared archive.
+archive_cmds=$lt_archive_cmds_RC
+archive_expsym_cmds=$lt_archive_expsym_cmds_RC
+postinstall_cmds=$lt_postinstall_cmds
+postuninstall_cmds=$lt_postuninstall_cmds
+
+# Commands used to build a loadable module (assumed same as above if empty)
+module_cmds=$lt_module_cmds_RC
+module_expsym_cmds=$lt_module_expsym_cmds_RC
+
+# Commands to strip libraries.
+old_striplib=$lt_old_striplib
+striplib=$lt_striplib
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predep_objects=\`echo $lt_predep_objects_RC | \$SED -e "s@\${gcc_dir}@\\\${gcc_dir}@g;s@\${gcc_ver}@\\\${gcc_ver}@g"\`
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdep_objects=\`echo $lt_postdep_objects_RC | \$SED -e "s@\${gcc_dir}@\\\${gcc_dir}@g;s@\${gcc_ver}@\\\${gcc_ver}@g"\`
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predeps=$lt_predeps_RC
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdeps=$lt_postdeps_RC
+
+# The library search path used internally by the compiler when linking
+# a shared library.
+compiler_lib_search_path=\`echo $lt_compiler_lib_search_path_RC | \$SED -e "s@\${gcc_dir}@\\\${gcc_dir}@g;s@\${gcc_ver}@\\\${gcc_ver}@g"\`
+
+# Method to check whether dependent libraries are shared objects.
+deplibs_check_method=$lt_deplibs_check_method
+
+# Command to use when deplibs_check_method == file_magic.
+file_magic_cmd=$lt_file_magic_cmd
+
+# Flag that allows shared libraries with undefined symbols to be built.
+allow_undefined_flag=$lt_allow_undefined_flag_RC
+
+# Flag that forces no undefined symbols.
+no_undefined_flag=$lt_no_undefined_flag_RC
+
+# Commands used to finish a libtool library installation in a directory.
+finish_cmds=$lt_finish_cmds
+
+# Same as above, but a single script fragment to be evaled but not shown.
+finish_eval=$lt_finish_eval
+
+# Take the output of nm and produce a listing of raw symbols and C names.
+global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe
+
+# Transform the output of nm in a proper C declaration
+global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl
+
+# Transform the output of nm in a C name address pair
+global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address
+
+# This is the shared library runtime path variable.
+runpath_var=$runpath_var
+
+# This is the shared library path variable.
+shlibpath_var=$shlibpath_var
+
+# Is shlibpath searched before the hard-coded library search path?
+shlibpath_overrides_runpath=$shlibpath_overrides_runpath
+
+# How to hardcode a shared library path into an executable.
+hardcode_action=$hardcode_action_RC
+
+# Whether we should hardcode library paths into libraries.
+hardcode_into_libs=$hardcode_into_libs
+
+# Flag to hardcode \$libdir into a binary during linking.
+# This must work even if \$libdir does not exist.
+hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_RC
+
+# If ld is used when linking, flag to hardcode \$libdir into
+# a binary during linking. This must work even if \$libdir does
+# not exist.
+hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_RC
+
+# Whether we need a single -rpath flag with a separated argument.
+hardcode_libdir_separator=$lt_hardcode_libdir_separator_RC
+
+# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the
+# resulting binary.
+hardcode_direct=$hardcode_direct_RC
+
+# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
+# resulting binary.
+hardcode_minus_L=$hardcode_minus_L_RC
+
+# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into
+# the resulting binary.
+hardcode_shlibpath_var=$hardcode_shlibpath_var_RC
+
+# Set to yes if building a shared library automatically hardcodes DIR into the library
+# and all subsequent libraries and executables linked against it.
+hardcode_automatic=$hardcode_automatic_RC
+
+# Variables whose values should be saved in libtool wrapper scripts and
+# restored at relink time.
+variables_saved_for_relink="$variables_saved_for_relink"
+
+# Whether libtool must link a program against all its dependency libraries.
+link_all_deplibs=$link_all_deplibs_RC
+
+# Compile-time system search path for libraries
+sys_lib_search_path_spec=\`echo $lt_sys_lib_search_path_spec | \$SED -e "s@\${gcc_dir}@\\\${gcc_dir}@g;s@\${gcc_ver}@\\\${gcc_ver}@g"\`
+
+# Run-time system search path for libraries
+sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec
+
+# Fix the shell variable \$srcfile for the compiler.
+fix_srcfile_path="$fix_srcfile_path_RC"
+
+# Set to yes if exported symbols are required.
+always_export_symbols=$always_export_symbols_RC
+
+# The commands to list exported symbols.
+export_symbols_cmds=$lt_export_symbols_cmds_RC
+
+# The commands to extract the exported symbol list from a shared archive.
+extract_expsyms_cmds=$lt_extract_expsyms_cmds
+
+# Symbols that should not be listed in the preloaded symbols.
+exclude_expsyms=$lt_exclude_expsyms_RC
+
+# Symbols that must always be exported.
+include_expsyms=$lt_include_expsyms_RC
+
+# ### END LIBTOOL TAG CONFIG: $tagname
+
+__EOF__
+
+
+else
+ # If there is no Makefile yet, we rely on a make rule to execute
+ # `config.status --recheck' to rerun these tests and create the
+ # libtool script then.
+ ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'`
+ if test -f "$ltmain_in"; then
+ test -f Makefile && make "$ltmain"
+ fi
+fi
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_linkonly='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_objext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+CC="$lt_save_CC"
+
+ ;;
+
+ *)
+ { { echo "$as_me:$LINENO: error: Unsupported tag name: $tagname" >&5
+echo "$as_me: error: Unsupported tag name: $tagname" >&2;}
+ { (exit 1); exit 1; }; }
+ ;;
+ esac
+
+ # Append the new tag name to the list of available tags.
+ if test -n "$tagname" ; then
+ available_tags="$available_tags $tagname"
+ fi
+ fi
+ done
+ IFS="$lt_save_ifs"
+
+ # Now substitute the updated list of available tags.
+ if eval "sed -e 's/^available_tags=.*\$/available_tags=\"$available_tags\"/' \"$ofile\" > \"${ofile}T\""; then
+ mv "${ofile}T" "$ofile"
+ chmod +x "$ofile"
+ else
+ rm -f "${ofile}T"
+ { { echo "$as_me:$LINENO: error: unable to update list of available tagged configurations." >&5
+echo "$as_me: error: unable to update list of available tagged configurations." >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+fi
+
+
+
+# This can be used to rebuild libtool when needed
+LIBTOOL_DEPS="$ac_aux_dir/ltmain.sh"
+
+# Always use our own libtool.
+LIBTOOL='$(SHELL) $(top_builddir)/libtool'
+
+# Prevent multiple expansion
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# Do we build shared libraries?
+# (enable_shared is set by the function AC_ENABLE_SHARED in libtool.m4)
+SHARED_LIBS="${enable_shared}"
+
+# Print a few more lines for configure --help
+
+
+
+# Check whether --with- or --without- was given.
+if test "${with_+set}" = set; then
+ withval="$with_"
+
+fi;
+
+# Check whether --with- or --without- was given.
+if test "${with_+set}" = set; then
+ withval="$with_"
+
+fi;
+
+# Check whether --with- or --without- was given.
+if test "${with_+set}" = set; then
+ withval="$with_"
+
+fi;
+
+# Check whether --with- or --without- was given.
+if test "${with_+set}" = set; then
+ withval="$with_"
+
+fi;
+
+# Check whether --with- or --without- was given.
+if test "${with_+set}" = set; then
+ withval="$with_"
+
+fi;
+
+# Check whether --with- or --without- was given.
+if test "${with_+set}" = set; then
+ withval="$with_"
+
+fi;
+
+
+
+# Substitute variables
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# Generate makefiles
+echo ""
+echo "Create Makefiles and configuration files"
+echo "----------------------------------------"
+echo ""
+
+
+# Initialize the list of Makefiles to be created
+SUNDIALS_MAKEFILES="Makefile"
+
+# Initialize list of additional configure files to be created
+SUNDIALS_CONFIGFILES="include/sundials/sundials_config.h:include/sundials/sundials_config.in"
+SUNDIALS_CONFIGFILES="${SUNDIALS_CONFIGFILES} bin/sundials-config:bin/sundials-config.in"
+
+# Initialize lists of solver modules and example modules
+SLV_MODULES="src/sundials"
+SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} src/sundials/Makefile"
+
+EXS_MODULES=""
+
+# NVECTOR modules
+if test -d ${srcdir}/src/nvec_ser ; then
+ SLV_MODULES="${SLV_MODULES} src/nvec_ser"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} src/nvec_ser/Makefile"
+fi
+
+if test -d ${srcdir}/src/nvec_par && test "X${MPI_C_COMP_OK}" = "Xyes"; then
+ SLV_MODULES="${SLV_MODULES} src/nvec_par"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} src/nvec_par/Makefile"
+fi
+
+if test -d ${srcdir}/src/nvec_spcpar && test "X${MPI_C_COMP_OK}" = "Xyes"; then
+ SLV_MODULES="${SLV_MODULES} src/nvec_spcpar"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} src/nvec_spcpar/Makefile"
+fi
+
+# CVODE module
+if test "X${CVODE_ENABLED}" = "Xyes"; then
+
+ SLV_MODULES="${SLV_MODULES} src/cvode"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} src/cvode/Makefile"
+
+ if test "X${FCMIX_ENABLED}" = "Xyes" && test -d ${srcdir}/src/cvode/fcmix ; then
+ SLV_MODULES="${SLV_MODULES} src/cvode/fcmix"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} src/cvode/fcmix/Makefile"
+ fi
+
+ if test "X${SERIAL_C_EXAMPLES}" = "Xyes" && test -d ${srcdir}/examples/cvode/serial ; then
+ EXS_MODULES="${EXS_MODULES} examples/cvode/serial"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} examples/cvode/serial/Makefile"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} examples/cvode/serial/Makefile_ex:examples/templates/makefile_serial_C_ex.in"
+ fi
+
+ if test "X${SERIAL_F77_EXAMPLES}" = "Xyes" && test -d ${srcdir}/examples/cvode/fcmix_serial ; then
+ EXS_MODULES="${EXS_MODULES} examples/cvode/fcmix_serial"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} examples/cvode/fcmix_serial/Makefile"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} examples/cvode/fcmix_serial/Makefile_ex:examples/templates/makefile_serial_F77_ex.in"
+ fi
+
+ if test "X${PARALLEL_C_EXAMPLES}" = "Xyes" && test -d ${srcdir}/examples/cvode/parallel ; then
+ EXS_MODULES="${EXS_MODULES} examples/cvode/parallel"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} examples/cvode/parallel/Makefile"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} examples/cvode/parallel/Makefile_ex:examples/templates/makefile_parallel_C_ex.in"
+ fi
+
+ if test "X${PARALLEL_F77_EXAMPLES}" = "Xyes" && test -d ${srcdir}/examples/cvode/fcmix_parallel ; then
+ EXS_MODULES="${EXS_MODULES} examples/cvode/fcmix_parallel"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} examples/cvode/fcmix_parallel/Makefile"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} examples/cvode/fcmix_parallel/Makefile_ex:examples/templates/makefile_parallel_F77_ex.in"
+ fi
+
+fi
+
+# CVODES module
+if test "X${CVODES_ENABLED}" = "Xyes"; then
+
+ SLV_MODULES="${SLV_MODULES} src/cvodes"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} src/cvodes/Makefile"
+
+ if test "X${SERIAL_C_EXAMPLES}" = "Xyes" && test -d ${srcdir}/examples/cvodes/serial ; then
+ EXS_MODULES="${EXS_MODULES} examples/cvodes/serial"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} examples/cvodes/serial/Makefile"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} examples/cvodes/serial/Makefile_ex:examples/templates/makefile_serial_C_ex.in"
+ fi
+
+ if test "X${PARALLEL_C_EXAMPLES}" = "Xyes" && test -d ${srcdir}/examples/cvodes/parallel ; then
+ EXS_MODULES="${EXS_MODULES} examples/cvodes/parallel"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} examples/cvodes/parallel/Makefile"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} examples/cvodes/parallel/Makefile_ex:examples/templates/makefile_parallel_C_ex.in"
+ fi
+
+fi
+
+# IDA module
+if test "X${IDA_ENABLED}" = "Xyes"; then
+
+ SLV_MODULES="${SLV_MODULES} src/ida"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} src/ida/Makefile"
+
+ if test "X${FCMIX_ENABLED}" = "Xyes" && test -d ${srcdir}/src/ida/fcmix ; then
+ SLV_MODULES="${SLV_MODULES} src/ida/fcmix"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} src/ida/fcmix/Makefile"
+ fi
+
+ if test "X${SERIAL_C_EXAMPLES}" = "Xyes" && test -d ${srcdir}/examples/ida/serial ; then
+ EXS_MODULES="${EXS_MODULES} examples/ida/serial"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} examples/ida/serial/Makefile"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} examples/ida/serial/Makefile_ex:examples/templates/makefile_serial_C_ex.in"
+ fi
+
+ if test "X${SERIAL_F77_EXAMPLES}" = "Xyes" && test -d ${srcdir}/examples/ida/fcmix_serial ; then
+ EXS_MODULES="${EXS_MODULES} examples/ida/fcmix_serial"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} examples/ida/fcmix_serial/Makefile"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} examples/ida/fcmix_serial/Makefile_ex:examples/templates/makefile_serial_F77_ex.in"
+ fi
+
+ if test "X${PARALLEL_C_EXAMPLES}" = "Xyes" && test -d ${srcdir}/examples/ida/parallel ; then
+ EXS_MODULES="${EXS_MODULES} examples/ida/parallel"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} examples/ida/parallel/Makefile"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} examples/ida/parallel/Makefile_ex:examples/templates/makefile_parallel_C_ex.in"
+ fi
+
+ if test "X${PARALLEL_F77_EXAMPLES}" = "Xyes" && test -d ${srcdir}/examples/ida/fcmix_parallel ; then
+ EXS_MODULES="${EXS_MODULES} examples/ida/fcmix_parallel"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} examples/ida/fcmix_parallel/Makefile"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} examples/ida/fcmix_parallel/Makefile_ex:examples/templates/makefile_parallel_F77_ex.in"
+ fi
+
+fi
+
+# IDAS module
+if test "X${IDAS_ENABLED}" = "Xyes"; then
+
+ SLV_MODULES="${SLV_MODULES} src/idas"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} src/idas/Makefile"
+
+ if test "X${SERIAL_C_EXAMPLES}" = "Xyes" && test -d ${srcdir}/examples/idas/serial ; then
+ EXS_MODULES="${EXS_MODULES} examples/idas/serial"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} examples/idas/serial/Makefile"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} examples/idas/serial/Makefile_ex:examples/templates/makefile_serial_C_ex.in"
+ fi
+
+ if test "X${PARALLEL_C_EXAMPLES}" = "Xyes" && test -d ${srcdir}/examples/idas/parallel ; then
+ EXS_MODULES="${EXS_MODULES} examples/idas/parallel"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} examples/idas/parallel/Makefile"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} examples/idas/parallel/Makefile_ex:examples/templates/makefile_parallel_C_ex.in"
+ fi
+
+fi
+
+# KINSOL module
+if test "X${KINSOL_ENABLED}" = "Xyes"; then
+
+ SLV_MODULES="${SLV_MODULES} src/kinsol"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} src/kinsol/Makefile"
+
+ if test "X${FCMIX_ENABLED}" = "Xyes" && test -d ${srcdir}/src/kinsol/fcmix ; then
+ SLV_MODULES="${SLV_MODULES} src/kinsol/fcmix"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} src/kinsol/fcmix/Makefile"
+ fi
+
+ if test "X${SERIAL_C_EXAMPLES}" = "Xyes" && test -d ${srcdir}/examples/kinsol/serial ; then
+ EXS_MODULES="${EXS_MODULES} examples/kinsol/serial"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} examples/kinsol/serial/Makefile"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} examples/kinsol/serial/Makefile_ex:examples/templates/makefile_serial_C_ex.in"
+ fi
+
+ if test "X${SERIAL_F77_EXAMPLES}" = "Xyes" && test -d ${srcdir}/examples/kinsol/fcmix_serial ; then
+ EXS_MODULES="${EXS_MODULES} examples/kinsol/fcmix_serial"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} examples/kinsol/fcmix_serial/Makefile"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} examples/kinsol/fcmix_serial/Makefile_ex:examples/templates/makefile_serial_F77_ex.in"
+ fi
+
+ if test "X${PARALLEL_C_EXAMPLES}" = "Xyes" && test -d ${srcdir}/examples/kinsol/parallel ; then
+ EXS_MODULES="${EXS_MODULES} examples/kinsol/parallel"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} examples/kinsol/parallel/Makefile"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} examples/kinsol/parallel/Makefile_ex:examples/templates/makefile_parallel_C_ex.in"
+ fi
+
+ if test "X${PARALLEL_F77_EXAMPLES}" = "Xyes" && test -d ${srcdir}/examples/kinsol/fcmix_parallel ; then
+ EXS_MODULES="${EXS_MODULES} examples/kinsol/fcmix_parallel"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} examples/kinsol/fcmix_parallel/Makefile"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} examples/kinsol/fcmix_parallel/Makefile_ex:examples/templates/makefile_parallel_F77_ex.in"
+ fi
+
+fi
+
+# CPODES module
+if test "X${CPODES_ENABLED}" = "Xyes"; then
+
+ SLV_MODULES="${SLV_MODULES} src/cpodes"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} src/cpodes/Makefile"
+
+ if test "X${SERIAL_C_EXAMPLES}" = "Xyes" && test -d ${srcdir}/examples/cpodes/serial ; then
+ EXS_MODULES="${EXS_MODULES} examples/cpodes/serial"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} examples/cpodes/serial/Makefile"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} examples/cpodes/serial/Makefile_ex:examples/templates/makefile_serial_C_ex.in"
+ fi
+
+ if test "X${PARALLEL_C_EXAMPLES}" = "Xyes" && test -d ${srcdir}/examples/cpodes/parallel ; then
+ EXS_MODULES="${EXS_MODULES} examples/cpodes/parallel"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} examples/cpodes/parallel/Makefile"
+ SUNDIALS_MAKEFILES="${SUNDIALS_MAKEFILES} examples/cpodes/parallel/Makefile_ex:examples/templates/makefile_parallel_C_ex.in"
+ fi
+
+fi
+
+# Add Fortran update script to the list of additional files to be generated
+if test "X${BUILD_F77_UPDATE_SCRIPT}" = "Xyes"; then
+ SUNDIALS_CONFIGFILES="${SUNDIALS_CONFIGFILES} bin/fortran-update.sh:bin/fortran-update.in"
+fi
+
+# If needed, add Makefile update script to the list of additional files to be generated
+if test "X${EXAMPLES_ENABLED}" = "Xyes" && test "X${EXS_INSTDIR}" != "Xno"; then
+ SUNDIALS_CONFIGFILES="${SUNDIALS_CONFIGFILES} bin/makefile-update.sh:bin/makefile-update.in"
+fi
+
+
+
+# Set-up postprocessing commands
+if test "X${EXAMPLES_ENABLED}" = "Xyes" && test "X${EXS_INSTDIR}" != "Xno"; then
+ ac_config_commands="$ac_config_commands postprocessing"
+
+
+
+# If installing examples, the Makefiles that will be exported must
+# be post-processed to complete the substitution of all variables.
+# After config.status runs, each example subdirectory contains an
+# export makefile, named Makefile_ex, which was created from the
+# common template in examples/templates.
+#
+# The following variables are still to be substituted at this point:
+# SOLVER
+# EXAMPLES
+# EXAMPLES_BL
+# SOLVER_LIB SOLVER_FLIB
+# NVEC_LIB NVEC_FLIB
+#
+# This function is called ONLY if examples are enabled AND examples will
+# be installed. If so, it sets up commands to be called after config.status
+# has generated a first version of the Makefiles for export:
+#
+# (1) For each solver, proceed ONLY if the solver is enabled.
+# (2) For each type of examples, proceed ONLY if they can be compiled AND
+# the example directory exists.
+
+# CVODE module
+if test "X${CVODE_ENABLED}" = "Xyes"; then
+
+ if test "X${SERIAL_C_EXAMPLES}" = "Xyes" && test -d ${srcdir}/examples/cvode/serial ; then
+ if test "X${LAPACK_ENABLED}" = "Xyes"; then
+ ac_config_commands="$ac_config_commands cvode_ser_ex_bl"
+
+ else
+ ac_config_commands="$ac_config_commands cvode_ser_ex"
+
+ fi
+ fi
+
+ if test "X${SERIAL_F77_EXAMPLES}" = "Xyes" && test -d ${srcdir}/examples/cvode/fcmix_serial ; then
+ if test "X${LAPACK_ENABLED}" = "Xyes"; then
+ ac_config_commands="$ac_config_commands cvode_fser_ex_bl"
+
+ else
+ ac_config_commands="$ac_config_commands cvode_fser_ex"
+
+ fi
+ fi
+
+ if test "X${PARALLEL_C_EXAMPLES}" = "Xyes" && test -d ${srcdir}/examples/cvode/parallel ; then
+ ac_config_commands="$ac_config_commands cvode_par_ex"
+
+ fi
+
+ if test "X${PARALLEL_F77_EXAMPLES}" = "Xyes" && test -d ${srcdir}/examples/cvode/fcmix_parallel ; then
+ ac_config_commands="$ac_config_commands cvode_fpar_ex"
+
+ fi
+
+fi
+
+
+# CVODES module
+if test "X${CVODES_ENABLED}" = "Xyes"; then
+
+ if test "X${SERIAL_C_EXAMPLES}" = "Xyes" && test -d ${srcdir}/examples/cvodes/serial ; then
+ if test "X${LAPACK_ENABLED}" = "Xyes"; then
+ ac_config_commands="$ac_config_commands cvodes_ser_ex_bl"
+
+ else
+ ac_config_commands="$ac_config_commands cvodes_ser_ex"
+
+ fi
+ fi
+
+ if test "X${PARALLEL_C_EXAMPLES}" = "Xyes" && test -d ${srcdir}/examples/cvodes/parallel ; then
+ ac_config_commands="$ac_config_commands cvodes_par_ex"
+
+ fi
+
+fi
+
+
+# IDA module
+if test "X${IDA_ENABLED}" = "Xyes"; then
+
+ if test "X${SERIAL_C_EXAMPLES}" = "Xyes" && test -d ${srcdir}/examples/ida/serial ; then
+ if test "X${LAPACK_ENABLED}" = "Xyes"; then
+ ac_config_commands="$ac_config_commands ida_ser_ex_bl"
+
+ else
+ ac_config_commands="$ac_config_commands ida_ser_ex"
+
+ fi
+ fi
+
+ if test "X${SERIAL_F77_EXAMPLES}" = "Xyes" && test -d ${srcdir}/examples/ida/fcmix_serial ; then
+ if test "X${LAPACK_ENABLED}" = "Xyes"; then
+ ac_config_commands="$ac_config_commands ida_fser_ex_bl"
+
+ else
+ ac_config_commands="$ac_config_commands ida_fser_ex"
+
+ fi
+ fi
+
+ if test "X${PARALLEL_C_EXAMPLES}" = "Xyes" && test -d ${srcdir}/examples/ida/parallel ; then
+ ac_config_commands="$ac_config_commands ida_par_ex"
+
+ fi
+
+ if test "X${PARALLEL_F77_EXAMPLES}" = "Xyes" && test -d ${srcdir}/examples/ida/fcmix_parallel ; then
+ ac_config_commands="$ac_config_commands ida_fpar_ex"
+
+ fi
+
+fi
+
+
+# IDAS module
+if test "X${IDAS_ENABLED}" = "Xyes"; then
+
+ if test "X${SERIAL_C_EXAMPLES}" = "Xyes" && test -d ${srcdir}/examples/idas/serial ; then
+ if test "X${LAPACK_ENABLED}" = "Xyes"; then
+ ac_config_commands="$ac_config_commands idas_ser_ex_bl"
+
+ else
+ ac_config_commands="$ac_config_commands idas_ser_ex"
+
+ fi
+ fi
+
+ if test "X${PARALLEL_C_EXAMPLES}" = "Xyes" && test -d ${srcdir}/examples/idas/parallel ; then
+ ac_config_commands="$ac_config_commands idas_par_ex"
+
+ fi
+
+fi
+
+
+# KINSOL module
+if test "X${KINSOL_ENABLED}" = "Xyes"; then
+
+ if test "X${SERIAL_C_EXAMPLES}" = "Xyes" && test -d ${srcdir}/examples/kinsol/serial ; then
+ if test "X${LAPACK_ENABLED}" = "Xyes"; then
+ ac_config_commands="$ac_config_commands kinsol_ser_ex_bl"
+
+ else
+ ac_config_commands="$ac_config_commands kinsol_ser_ex"
+
+ fi
+ fi
+
+ if test "X${SERIAL_F77_EXAMPLES}" = "Xyes" && test -d ${srcdir}/examples/kinsol/fcmix_serial ; then
+ if test "X${LAPACK_ENABLED}" = "Xyes"; then
+ ac_config_commands="$ac_config_commands kinsol_fser_ex_bl"
+
+ else
+ ac_config_commands="$ac_config_commands kinsol_fser_ex"
+
+ fi
+ fi
+
+ if test "X${PARALLEL_C_EXAMPLES}" = "Xyes" && test -d ${srcdir}/examples/kinsol/parallel ; then
+ ac_config_commands="$ac_config_commands kinsol_par_ex"
+
+ fi
+
+ if test "X${PARALLEL_F77_EXAMPLES}" = "Xyes" && test -d ${srcdir}/examples/kinsol/fcmix_parallel ; then
+ ac_config_commands="$ac_config_commands kinsol_fpar_ex"
+
+ fi
+
+fi
+
+
+# CPODES module
+if test "X${CPODES_ENABLED}" = "Xyes"; then
+
+ if test "X${SERIAL_C_EXAMPLES}" = "Xyes" && test -d ${srcdir}/examples/cpodes/serial ; then
+ if test "X${LAPACK_ENABLED}" = "Xyes"; then
+ ac_config_commands="$ac_config_commands cpodes_ser_ex_bl"
+
+ else
+ ac_config_commands="$ac_config_commands cpodes_ser_ex"
+
+ fi
+ fi
+
+ if test "X${PARALLEL_C_EXAMPLES}" = "Xyes" && test -d ${srcdir}/examples/cpodes/parallel ; then
+ ac_config_commands="$ac_config_commands cpodes_par_ex"
+
+ fi
+
+fi
+
+
+fi
+
+# Specify files to be configured and call AC_OUTPUT
+ ac_config_files="$ac_config_files ${SUNDIALS_MAKEFILES}"
+
+ ac_config_files="$ac_config_files ${SUNDIALS_CONFIGFILES}"
+
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems. If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, don't put newlines in cache variables' values.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+{
+ (set) 2>&1 |
+ case `(ac_space=' '; set | grep ac_space) 2>&1` in
+ *ac_space=\ *)
+ # `set' does not quote correctly, so add quotes (double-quote
+ # substitution turns \\\\ into \\, and sed turns \\ into \).
+ sed -n \
+ "s/'/'\\\\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+ ;;
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n \
+ "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
+ ;;
+ esac;
+} |
+ sed '
+ t clear
+ : clear
+ s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+ t end
+ /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+ : end' >>confcache
+if diff $cache_file confcache >/dev/null 2>&1; then :; else
+ if test -w $cache_file; then
+ test "x$cache_file" != "x/dev/null" && echo "updating cache $cache_file"
+ cat confcache >$cache_file
+ else
+ echo "not updating unwritable cache $cache_file"
+ fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# VPATH may cause trouble with some makes, so we remove $(srcdir),
+# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=/{
+s/:*\$(srcdir):*/:/;
+s/:*\${srcdir}:*/:/;
+s/:*@srcdir@:*/:/;
+s/^\([^=]*=[ ]*\):*/\1/;
+s/:*$//;
+s/^[^=]*=[ ]*$//;
+}'
+fi
+
+DEFS=-DHAVE_CONFIG_H
+
+ac_libobjs=
+ac_ltlibobjs=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+ # 1. Remove the extension, and $U if already installed.
+ ac_i=`echo "$ac_i" |
+ sed 's/\$U\././;s/\.o$//;s/\.obj$//'`
+ # 2. Add them.
+ ac_libobjs="$ac_libobjs $ac_i\$U.$ac_objext"
+ ac_ltlibobjs="$ac_ltlibobjs $ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+
+: ${CONFIG_STATUS=./config.status}
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5
+echo "$as_me: creating $CONFIG_STATUS" >&6;}
+cat >$CONFIG_STATUS <<_ACEOF
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+SHELL=\${CONFIG_SHELL-$SHELL}
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+## --------------------- ##
+## M4sh Initialization. ##
+## --------------------- ##
+
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
+ set -o posix
+fi
+DUALCASE=1; export DUALCASE # for MKS sh
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+ as_unset=unset
+else
+ as_unset=false
+fi
+
+
+# Work around bugs in pre-3.0 UWIN ksh.
+$as_unset ENV MAIL MAILPATH
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+ LC_TELEPHONE LC_TIME
+do
+ if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
+ eval $as_var=C; export $as_var
+ else
+ $as_unset $as_var
+ fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)$' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; }
+ /^X\/\(\/\/\)$/{ s//\1/; q; }
+ /^X\/\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+
+
+# PATH needs CR, and LINENO needs CR and PATH.
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ echo "#! /bin/sh" >conf$$.sh
+ echo "exit 0" >>conf$$.sh
+ chmod +x conf$$.sh
+ if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+ PATH_SEPARATOR=';'
+ else
+ PATH_SEPARATOR=:
+ fi
+ rm -f conf$$.sh
+fi
+
+
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x$as_lineno_3" = "x$as_lineno_2" || {
+ # Find who we are. Look in the path if we contain no path at all
+ # relative or not.
+ case $0 in
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+
+ ;;
+ esac
+ # We did not find ourselves, most probably we were run as `sh COMMAND'
+ # in which case we are not to be found in the path.
+ if test "x$as_myself" = x; then
+ as_myself=$0
+ fi
+ if test ! -f "$as_myself"; then
+ { { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5
+echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+ case $CONFIG_SHELL in
+ '')
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for as_base in sh bash ksh sh5; do
+ case $as_dir in
+ /*)
+ if ("$as_dir/$as_base" -c '
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then
+ $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; }
+ $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; }
+ CONFIG_SHELL=$as_dir/$as_base
+ export CONFIG_SHELL
+ exec "$CONFIG_SHELL" "$0" ${1+"$@"}
+ fi;;
+ esac
+ done
+done
+;;
+ esac
+
+ # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+ # uniformly replaced by the line number. The first 'sed' inserts a
+ # line-number line before each line; the second 'sed' does the real
+ # work. The second script uses 'N' to pair each line-number line
+ # with the numbered line, and appends trailing '-' during
+ # substitution so that $LINENO is not a special case at line end.
+ # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+ # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-)
+ sed '=' <$as_myself |
+ sed '
+ N
+ s,$,-,
+ : loop
+ s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3,
+ t loop
+ s,-$,,
+ s,^['$as_cr_digits']*\n,,
+ ' >$as_me.lineno &&
+ chmod +x $as_me.lineno ||
+ { { echo "$as_me:$LINENO: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&5
+echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2;}
+ { (exit 1); exit 1; }; }
+
+ # Don't try to exec as it changes $[0], causing all sort of problems
+ # (the dirname of $[0] is not the place where we might find the
+ # original and so on. Autoconf is especially sensible to this).
+ . ./$as_me.lineno
+ # Exit status is that of the last command.
+ exit
+}
+
+
+case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in
+ *c*,-n*) ECHO_N= ECHO_C='
+' ECHO_T=' ' ;;
+ *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;;
+ *) ECHO_N= ECHO_C='\c' ECHO_T= ;;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+ # We could just check for DJGPP; but this test a) works b) is more generic
+ # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04).
+ if test -f conf$$.exe; then
+ # Don't use ln at all; we don't have any links
+ as_ln_s='cp -p'
+ else
+ as_ln_s='ln -s'
+ fi
+elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+else
+ as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.file
+
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p=:
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+as_executable_p="test -f"
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.
+as_nl='
+'
+IFS=" $as_nl"
+
+# CDPATH.
+$as_unset CDPATH
+
+exec 6>&1
+
+# Open the log real soon, to keep \$[0] and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling. Logging --version etc. is OK.
+exec 5>>config.log
+{
+ echo
+ sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+} >&5
+cat >&5 <<_CSEOF
+
+This file was extended by SUNDIALS $as_me 2.5.0, which was
+generated by GNU Autoconf 2.59. Invocation command line was
+
+ CONFIG_FILES = $CONFIG_FILES
+ CONFIG_HEADERS = $CONFIG_HEADERS
+ CONFIG_LINKS = $CONFIG_LINKS
+ CONFIG_COMMANDS = $CONFIG_COMMANDS
+ $ $0 $@
+
+_CSEOF
+echo "on `(hostname || uname -n) 2>/dev/null | sed 1q`" >&5
+echo >&5
+_ACEOF
+
+# Files that config.status was made for.
+if test -n "$ac_config_files"; then
+ echo "config_files=\"$ac_config_files\"" >>$CONFIG_STATUS
+fi
+
+if test -n "$ac_config_headers"; then
+ echo "config_headers=\"$ac_config_headers\"" >>$CONFIG_STATUS
+fi
+
+if test -n "$ac_config_links"; then
+ echo "config_links=\"$ac_config_links\"" >>$CONFIG_STATUS
+fi
+
+if test -n "$ac_config_commands"; then
+ echo "config_commands=\"$ac_config_commands\"" >>$CONFIG_STATUS
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+ac_cs_usage="\
+\`$as_me' instantiates files from templates according to the
+current configuration.
+
+Usage: $0 [OPTIONS] [FILE]...
+
+ -h, --help print this help, then exit
+ -V, --version print version number, then exit
+ -q, --quiet do not print progress messages
+ -d, --debug don't remove temporary files
+ --recheck update $as_me by reconfiguring in the same conditions
+ --file=FILE[:TEMPLATE]
+ instantiate the configuration file FILE
+ --header=FILE[:TEMPLATE]
+ instantiate the configuration header FILE
+
+Configuration files:
+$config_files
+
+Configuration headers:
+$config_headers
+
+Configuration commands:
+$config_commands
+
+Report bugs to <bug-autoconf at gnu.org>."
+_ACEOF
+
+cat >>$CONFIG_STATUS <<_ACEOF
+ac_cs_version="\\
+SUNDIALS config.status 2.5.0
+configured by $0, generated by GNU Autoconf 2.59,
+ with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\"
+
+Copyright (C) 2003 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+srcdir=$srcdir
+INSTALL="$INSTALL"
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+# If no file are specified by the user, then we need to provide default
+# value. By we need to know if files were specified by the user.
+ac_need_defaults=:
+while test $# != 0
+do
+ case $1 in
+ --*=*)
+ ac_option=`expr "x$1" : 'x\([^=]*\)='`
+ ac_optarg=`expr "x$1" : 'x[^=]*=\(.*\)'`
+ ac_shift=:
+ ;;
+ -*)
+ ac_option=$1
+ ac_optarg=$2
+ ac_shift=shift
+ ;;
+ *) # This is not an option, so the user has probably given explicit
+ # arguments.
+ ac_option=$1
+ ac_need_defaults=false;;
+ esac
+
+ case $ac_option in
+ # Handling of the options.
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ ac_cs_recheck=: ;;
+ --version | --vers* | -V )
+ echo "$ac_cs_version"; exit 0 ;;
+ --he | --h)
+ # Conflict between --help and --header
+ { { echo "$as_me:$LINENO: error: ambiguous option: $1
+Try \`$0 --help' for more information." >&5
+echo "$as_me: error: ambiguous option: $1
+Try \`$0 --help' for more information." >&2;}
+ { (exit 1); exit 1; }; };;
+ --help | --hel | -h )
+ echo "$ac_cs_usage"; exit 0 ;;
+ --debug | --d* | -d )
+ debug=: ;;
+ --file | --fil | --fi | --f )
+ $ac_shift
+ CONFIG_FILES="$CONFIG_FILES $ac_optarg"
+ ac_need_defaults=false;;
+ --header | --heade | --head | --hea )
+ $ac_shift
+ CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg"
+ ac_need_defaults=false;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil | --si | --s)
+ ac_cs_silent=: ;;
+
+ # This is an error.
+ -*) { { echo "$as_me:$LINENO: error: unrecognized option: $1
+Try \`$0 --help' for more information." >&5
+echo "$as_me: error: unrecognized option: $1
+Try \`$0 --help' for more information." >&2;}
+ { (exit 1); exit 1; }; } ;;
+
+ *) ac_config_targets="$ac_config_targets $1" ;;
+
+ esac
+ shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+ exec 6>/dev/null
+ ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+if \$ac_cs_recheck; then
+ echo "running $SHELL $0 " $ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6
+ exec $SHELL $0 $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+fi
+
+_ACEOF
+
+
+
+
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+for ac_config_target in $ac_config_targets
+do
+ case "$ac_config_target" in
+ # Handling of arguments.
+ "${SUNDIALS_MAKEFILES}" ) CONFIG_FILES="$CONFIG_FILES ${SUNDIALS_MAKEFILES}" ;;
+ "${SUNDIALS_CONFIGFILES}" ) CONFIG_FILES="$CONFIG_FILES ${SUNDIALS_CONFIGFILES}" ;;
+ "postprocessing" ) CONFIG_COMMANDS="$CONFIG_COMMANDS postprocessing" ;;
+ "cvode_ser_ex_bl" ) CONFIG_COMMANDS="$CONFIG_COMMANDS cvode_ser_ex_bl" ;;
+ "cvode_ser_ex" ) CONFIG_COMMANDS="$CONFIG_COMMANDS cvode_ser_ex" ;;
+ "cvode_fser_ex_bl" ) CONFIG_COMMANDS="$CONFIG_COMMANDS cvode_fser_ex_bl" ;;
+ "cvode_fser_ex" ) CONFIG_COMMANDS="$CONFIG_COMMANDS cvode_fser_ex" ;;
+ "cvode_par_ex" ) CONFIG_COMMANDS="$CONFIG_COMMANDS cvode_par_ex" ;;
+ "cvode_fpar_ex" ) CONFIG_COMMANDS="$CONFIG_COMMANDS cvode_fpar_ex" ;;
+ "cvodes_ser_ex_bl" ) CONFIG_COMMANDS="$CONFIG_COMMANDS cvodes_ser_ex_bl" ;;
+ "cvodes_ser_ex" ) CONFIG_COMMANDS="$CONFIG_COMMANDS cvodes_ser_ex" ;;
+ "cvodes_par_ex" ) CONFIG_COMMANDS="$CONFIG_COMMANDS cvodes_par_ex" ;;
+ "ida_ser_ex_bl" ) CONFIG_COMMANDS="$CONFIG_COMMANDS ida_ser_ex_bl" ;;
+ "ida_ser_ex" ) CONFIG_COMMANDS="$CONFIG_COMMANDS ida_ser_ex" ;;
+ "ida_fser_ex_bl" ) CONFIG_COMMANDS="$CONFIG_COMMANDS ida_fser_ex_bl" ;;
+ "ida_fser_ex" ) CONFIG_COMMANDS="$CONFIG_COMMANDS ida_fser_ex" ;;
+ "ida_par_ex" ) CONFIG_COMMANDS="$CONFIG_COMMANDS ida_par_ex" ;;
+ "ida_fpar_ex" ) CONFIG_COMMANDS="$CONFIG_COMMANDS ida_fpar_ex" ;;
+ "idas_ser_ex_bl" ) CONFIG_COMMANDS="$CONFIG_COMMANDS idas_ser_ex_bl" ;;
+ "idas_ser_ex" ) CONFIG_COMMANDS="$CONFIG_COMMANDS idas_ser_ex" ;;
+ "idas_par_ex" ) CONFIG_COMMANDS="$CONFIG_COMMANDS idas_par_ex" ;;
+ "kinsol_ser_ex_bl" ) CONFIG_COMMANDS="$CONFIG_COMMANDS kinsol_ser_ex_bl" ;;
+ "kinsol_ser_ex" ) CONFIG_COMMANDS="$CONFIG_COMMANDS kinsol_ser_ex" ;;
+ "kinsol_fser_ex_bl" ) CONFIG_COMMANDS="$CONFIG_COMMANDS kinsol_fser_ex_bl" ;;
+ "kinsol_fser_ex" ) CONFIG_COMMANDS="$CONFIG_COMMANDS kinsol_fser_ex" ;;
+ "kinsol_par_ex" ) CONFIG_COMMANDS="$CONFIG_COMMANDS kinsol_par_ex" ;;
+ "kinsol_fpar_ex" ) CONFIG_COMMANDS="$CONFIG_COMMANDS kinsol_fpar_ex" ;;
+ "cpodes_ser_ex_bl" ) CONFIG_COMMANDS="$CONFIG_COMMANDS cpodes_ser_ex_bl" ;;
+ "cpodes_ser_ex" ) CONFIG_COMMANDS="$CONFIG_COMMANDS cpodes_ser_ex" ;;
+ "cpodes_par_ex" ) CONFIG_COMMANDS="$CONFIG_COMMANDS cpodes_par_ex" ;;
+ "config.h" ) CONFIG_HEADERS="$CONFIG_HEADERS config.h:config.hin" ;;
+ *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5
+echo "$as_me: error: invalid argument: $ac_config_target" >&2;}
+ { (exit 1); exit 1; }; };;
+ esac
+done
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used. Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+ test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+ test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
+ test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands
+fi
+
+# Have a temporary directory for convenience. Make it in the build tree
+# simply because there is no reason to put it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Create a temporary directory, and hook for its removal unless debugging.
+$debug ||
+{
+ trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0
+ trap '{ (exit 1); exit 1; }' 1 2 13 15
+}
+
+# Create a (secure) tmp directory for tmp files.
+
+{
+ tmp=`(umask 077 && mktemp -d -q "./confstatXXXXXX") 2>/dev/null` &&
+ test -n "$tmp" && test -d "$tmp"
+} ||
+{
+ tmp=./confstat$$-$RANDOM
+ (umask 077 && mkdir $tmp)
+} ||
+{
+ echo "$me: cannot create a temporary directory in ." >&2
+ { (exit 1); exit 1; }
+}
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<_ACEOF
+
+#
+# CONFIG_FILES section.
+#
+
+# No need to generate the scripts if there are no CONFIG_FILES.
+# This happens for instance when ./config.status config.h
+if test -n "\$CONFIG_FILES"; then
+ # Protect against being on the right side of a sed subst in config.status.
+ sed 's/,@/@@/; s/@,/@@/; s/,;t t\$/@;t t/; /@;t t\$/s/[\\\\&,]/\\\\&/g;
+ s/@@/,@/; s/@@/@,/; s/@;t t\$/,;t t/' >\$tmp/subs.sed <<\\CEOF
+s, at SHELL@,$SHELL,;t t
+s, at PATH_SEPARATOR@,$PATH_SEPARATOR,;t t
+s, at PACKAGE_NAME@,$PACKAGE_NAME,;t t
+s, at PACKAGE_TARNAME@,$PACKAGE_TARNAME,;t t
+s, at PACKAGE_VERSION@,$PACKAGE_VERSION,;t t
+s, at PACKAGE_STRING@,$PACKAGE_STRING,;t t
+s, at PACKAGE_BUGREPORT@,$PACKAGE_BUGREPORT,;t t
+s, at exec_prefix@,$exec_prefix,;t t
+s, at prefix@,$prefix,;t t
+s, at program_transform_name@,$program_transform_name,;t t
+s, at bindir@,$bindir,;t t
+s, at sbindir@,$sbindir,;t t
+s, at libexecdir@,$libexecdir,;t t
+s, at datadir@,$datadir,;t t
+s, at sysconfdir@,$sysconfdir,;t t
+s, at sharedstatedir@,$sharedstatedir,;t t
+s, at localstatedir@,$localstatedir,;t t
+s, at libdir@,$libdir,;t t
+s, at includedir@,$includedir,;t t
+s, at oldincludedir@,$oldincludedir,;t t
+s, at infodir@,$infodir,;t t
+s, at mandir@,$mandir,;t t
+s, at build_alias@,$build_alias,;t t
+s, at host_alias@,$host_alias,;t t
+s, at target_alias@,$target_alias,;t t
+s, at DEFS@,$DEFS,;t t
+s, at ECHO_C@,$ECHO_C,;t t
+s, at ECHO_N@,$ECHO_N,;t t
+s, at ECHO_T@,$ECHO_T,;t t
+s, at LIBS@,$LIBS,;t t
+s, at build@,$build,;t t
+s, at build_cpu@,$build_cpu,;t t
+s, at build_vendor@,$build_vendor,;t t
+s, at build_os@,$build_os,;t t
+s, at host@,$host,;t t
+s, at host_cpu@,$host_cpu,;t t
+s, at host_vendor@,$host_vendor,;t t
+s, at host_os@,$host_os,;t t
+s, at SET_MAKE@,$SET_MAKE,;t t
+s, at INSTALL_PROGRAM@,$INSTALL_PROGRAM,;t t
+s, at INSTALL_SCRIPT@,$INSTALL_SCRIPT,;t t
+s, at INSTALL_DATA@,$INSTALL_DATA,;t t
+s, at CC@,$CC,;t t
+s, at CFLAGS@,$CFLAGS,;t t
+s, at LDFLAGS@,$LDFLAGS,;t t
+s, at CPPFLAGS@,$CPPFLAGS,;t t
+s, at ac_ct_CC@,$ac_ct_CC,;t t
+s, at EXEEXT@,$EXEEXT,;t t
+s, at OBJEXT@,$OBJEXT,;t t
+s, at CPP@,$CPP,;t t
+s, at EGREP@,$EGREP,;t t
+s, at FGREP@,$FGREP,;t t
+s, at F77@,$F77,;t t
+s, at FFLAGS@,$FFLAGS,;t t
+s, at ac_ct_F77@,$ac_ct_F77,;t t
+s, at FLIBS@,$FLIBS,;t t
+s, at MPICC_COMP@,$MPICC_COMP,;t t
+s, at MPIF77_COMP@,$MPIF77_COMP,;t t
+s, at SED@,$SED,;t t
+s, at LN_S@,$LN_S,;t t
+s, at ECHO@,$ECHO,;t t
+s, at AR@,$AR,;t t
+s, at ac_ct_AR@,$ac_ct_AR,;t t
+s, at RANLIB@,$RANLIB,;t t
+s, at ac_ct_RANLIB@,$ac_ct_RANLIB,;t t
+s, at STRIP@,$STRIP,;t t
+s, at ac_ct_STRIP@,$ac_ct_STRIP,;t t
+s, at DLLTOOL@,$DLLTOOL,;t t
+s, at ac_ct_DLLTOOL@,$ac_ct_DLLTOOL,;t t
+s, at AS@,$AS,;t t
+s, at ac_ct_AS@,$ac_ct_AS,;t t
+s, at OBJDUMP@,$OBJDUMP,;t t
+s, at ac_ct_OBJDUMP@,$ac_ct_OBJDUMP,;t t
+s, at CXX@,$CXX,;t t
+s, at CXXFLAGS@,$CXXFLAGS,;t t
+s, at ac_ct_CXX@,$ac_ct_CXX,;t t
+s, at CXXCPP@,$CXXCPP,;t t
+s, at LIBTOOL@,$LIBTOOL,;t t
+s, at SHARED_LIBS@,$SHARED_LIBS,;t t
+s, at MPICC@,$MPICC,;t t
+s, at MPIF77@,$MPIF77,;t t
+s, at MPI_INC_DIR@,$MPI_INC_DIR,;t t
+s, at MPI_LIB_DIR@,$MPI_LIB_DIR,;t t
+s, at MPI_LIBS@,$MPI_LIBS,;t t
+s, at MPI_FLAGS@,$MPI_FLAGS,;t t
+s, at FCMIX_ENABLED@,$FCMIX_ENABLED,;t t
+s, at FLOAT_TYPE@,$FLOAT_TYPE,;t t
+s, at LIBTOOL_DEPS@,$LIBTOOL_DEPS,;t t
+s, at F77_MANGLE_MACRO1@,$F77_MANGLE_MACRO1,;t t
+s, at F77_MANGLE_MACRO2@,$F77_MANGLE_MACRO2,;t t
+s, at F77_CASE@,$F77_CASE,;t t
+s, at F77_UNDERSCORES@,$F77_UNDERSCORES,;t t
+s, at PRECISION_LEVEL@,$PRECISION_LEVEL,;t t
+s, at GENERIC_MATH_LIB@,$GENERIC_MATH_LIB,;t t
+s, at BLAS_LAPACK_MACRO@,$BLAS_LAPACK_MACRO,;t t
+s, at SUNDIALS_EXPORT@,$SUNDIALS_EXPORT,;t t
+s, at F77_MPI_COMM_F2C@,$F77_MPI_COMM_F2C,;t t
+s, at F77_LNKR@,$F77_LNKR,;t t
+s, at F77_LIBS@,$F77_LIBS,;t t
+s, at F77_LDFLAGS@,$F77_LDFLAGS,;t t
+s, at LAPACK_ENABLED@,$LAPACK_ENABLED,;t t
+s, at BLAS_LAPACK_LIBS@,$BLAS_LAPACK_LIBS,;t t
+s, at MPIF77_LNKR@,$MPIF77_LNKR,;t t
+s, at SLV_MODULES@,$SLV_MODULES,;t t
+s, at EXS_MODULES@,$EXS_MODULES,;t t
+s, at EXS_INSTDIR@,$EXS_INSTDIR,;t t
+s, at LIBOBJS@,$LIBOBJS,;t t
+s, at LTLIBOBJS@,$LTLIBOBJS,;t t
+CEOF
+
+_ACEOF
+
+ cat >>$CONFIG_STATUS <<\_ACEOF
+ # Split the substitutions into bite-sized pieces for seds with
+ # small command number limits, like on Digital OSF/1 and HP-UX.
+ ac_max_sed_lines=48
+ ac_sed_frag=1 # Number of current file.
+ ac_beg=1 # First line for current file.
+ ac_end=$ac_max_sed_lines # Line after last line for current file.
+ ac_more_lines=:
+ ac_sed_cmds=
+ while $ac_more_lines; do
+ if test $ac_beg -gt 1; then
+ sed "1,${ac_beg}d; ${ac_end}q" $tmp/subs.sed >$tmp/subs.frag
+ else
+ sed "${ac_end}q" $tmp/subs.sed >$tmp/subs.frag
+ fi
+ if test ! -s $tmp/subs.frag; then
+ ac_more_lines=false
+ else
+ # The purpose of the label and of the branching condition is to
+ # speed up the sed processing (if there are no `@' at all, there
+ # is no need to browse any of the substitutions).
+ # These are the two extra sed commands mentioned above.
+ (echo ':t
+ /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed
+ if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed"
+ else
+ ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed"
+ fi
+ ac_sed_frag=`expr $ac_sed_frag + 1`
+ ac_beg=$ac_end
+ ac_end=`expr $ac_end + $ac_max_sed_lines`
+ fi
+ done
+ if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds=cat
+ fi
+fi # test -n "$CONFIG_FILES"
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue
+ # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+ case $ac_file in
+ - | *:- | *:-:* ) # input from stdin
+ cat >$tmp/stdin
+ ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+ ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+ *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+ ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+ * ) ac_file_in=$ac_file.in ;;
+ esac
+
+ # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories.
+ ac_dir=`(dirname "$ac_file") 2>/dev/null ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$ac_file" : 'X\(//\)[^/]' \| \
+ X"$ac_file" : 'X\(//\)$' \| \
+ X"$ac_file" : 'X\(/\)' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X"$ac_file" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+ /^X\(\/\/\)$/{ s//\1/; q; }
+ /^X\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+ { if $as_mkdir_p; then
+ mkdir -p "$ac_dir"
+ else
+ as_dir="$ac_dir"
+ as_dirs=
+ while test ! -d "$as_dir"; do
+ as_dirs="$as_dir $as_dirs"
+ as_dir=`(dirname "$as_dir") 2>/dev/null ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+ /^X\(\/\/\)$/{ s//\1/; q; }
+ /^X\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+ done
+ test ! -n "$as_dirs" || mkdir $as_dirs
+ fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5
+echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;}
+ { (exit 1); exit 1; }; }; }
+
+ ac_builddir=.
+
+if test "$ac_dir" != .; then
+ ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+ # A "../" for each directory in $ac_dir_suffix.
+ ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
+else
+ ac_dir_suffix= ac_top_builddir=
+fi
+
+case $srcdir in
+ .) # No --srcdir option. We are building in place.
+ ac_srcdir=.
+ if test -z "$ac_top_builddir"; then
+ ac_top_srcdir=.
+ else
+ ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
+ fi ;;
+ [\\/]* | ?:[\\/]* ) # Absolute path.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir ;;
+ *) # Relative path.
+ ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_builddir$srcdir ;;
+esac
+
+# Do not use `cd foo && pwd` to compute absolute paths, because
+# the directories may not exist.
+case `pwd` in
+.) ac_abs_builddir="$ac_dir";;
+*)
+ case "$ac_dir" in
+ .) ac_abs_builddir=`pwd`;;
+ [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";;
+ *) ac_abs_builddir=`pwd`/"$ac_dir";;
+ esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_builddir=${ac_top_builddir}.;;
+*)
+ case ${ac_top_builddir}. in
+ .) ac_abs_top_builddir=$ac_abs_builddir;;
+ [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
+ *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
+ esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_srcdir=$ac_srcdir;;
+*)
+ case $ac_srcdir in
+ .) ac_abs_srcdir=$ac_abs_builddir;;
+ [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
+ *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
+ esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_srcdir=$ac_top_srcdir;;
+*)
+ case $ac_top_srcdir in
+ .) ac_abs_top_srcdir=$ac_abs_builddir;;
+ [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
+ *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
+ esac;;
+esac
+
+
+ case $INSTALL in
+ [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
+ *) ac_INSTALL=$ac_top_builddir$INSTALL ;;
+ esac
+
+ if test x"$ac_file" != x-; then
+ { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+ rm -f "$ac_file"
+ fi
+ # Let's still pretend it is `configure' which instantiates (i.e., don't
+ # use $as_me), people would be surprised to read:
+ # /* config.h. Generated by config.status. */
+ if test x"$ac_file" = x-; then
+ configure_input=
+ else
+ configure_input="$ac_file. "
+ fi
+ configure_input=$configure_input"Generated from `echo $ac_file_in |
+ sed 's,.*/,,'` by configure."
+
+ # First look for the input files in the build tree, otherwise in the
+ # src tree.
+ ac_file_inputs=`IFS=:
+ for f in $ac_file_in; do
+ case $f in
+ -) echo $tmp/stdin ;;
+ [\\/$]*)
+ # Absolute (can't be DOS-style, as IFS=:)
+ test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+ { (exit 1); exit 1; }; }
+ echo "$f";;
+ *) # Relative
+ if test -f "$f"; then
+ # Build tree
+ echo "$f"
+ elif test -f "$srcdir/$f"; then
+ # Source tree
+ echo "$srcdir/$f"
+ else
+ # /dev/null tree
+ { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+ { (exit 1); exit 1; }; }
+ fi;;
+ esac
+ done` || { (exit 1); exit 1; }
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+ sed "$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s, at configure_input@,$configure_input,;t t
+s, at srcdir@,$ac_srcdir,;t t
+s, at abs_srcdir@,$ac_abs_srcdir,;t t
+s, at top_srcdir@,$ac_top_srcdir,;t t
+s, at abs_top_srcdir@,$ac_abs_top_srcdir,;t t
+s, at builddir@,$ac_builddir,;t t
+s, at abs_builddir@,$ac_abs_builddir,;t t
+s, at top_builddir@,$ac_top_builddir,;t t
+s, at abs_top_builddir@,$ac_abs_top_builddir,;t t
+s, at INSTALL@,$ac_INSTALL,;t t
+" $ac_file_inputs | (eval "$ac_sed_cmds") >$tmp/out
+ rm -f $tmp/stdin
+ if test x"$ac_file" != x-; then
+ mv $tmp/out $ac_file
+ else
+ cat $tmp/out
+ rm -f $tmp/out
+ fi
+
+done
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+#
+# CONFIG_HEADER section.
+#
+
+# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where
+# NAME is the cpp macro being defined and VALUE is the value it is being given.
+#
+# ac_d sets the value in "#define NAME VALUE" lines.
+ac_dA='s,^\([ ]*\)#\([ ]*define[ ][ ]*\)'
+ac_dB='[ ].*$,\1#\2'
+ac_dC=' '
+ac_dD=',;t'
+# ac_u turns "#undef NAME" without trailing blanks into "#define NAME VALUE".
+ac_uA='s,^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)'
+ac_uB='$,\1#\2define\3'
+ac_uC=' '
+ac_uD=',;t'
+
+for ac_file in : $CONFIG_HEADERS; do test "x$ac_file" = x: && continue
+ # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+ case $ac_file in
+ - | *:- | *:-:* ) # input from stdin
+ cat >$tmp/stdin
+ ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+ ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+ *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+ ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+ * ) ac_file_in=$ac_file.in ;;
+ esac
+
+ test x"$ac_file" != x- && { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+
+ # First look for the input files in the build tree, otherwise in the
+ # src tree.
+ ac_file_inputs=`IFS=:
+ for f in $ac_file_in; do
+ case $f in
+ -) echo $tmp/stdin ;;
+ [\\/$]*)
+ # Absolute (can't be DOS-style, as IFS=:)
+ test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+ { (exit 1); exit 1; }; }
+ # Do quote $f, to prevent DOS paths from being IFS'd.
+ echo "$f";;
+ *) # Relative
+ if test -f "$f"; then
+ # Build tree
+ echo "$f"
+ elif test -f "$srcdir/$f"; then
+ # Source tree
+ echo "$srcdir/$f"
+ else
+ # /dev/null tree
+ { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+ { (exit 1); exit 1; }; }
+ fi;;
+ esac
+ done` || { (exit 1); exit 1; }
+ # Remove the trailing spaces.
+ sed 's/[ ]*$//' $ac_file_inputs >$tmp/in
+
+_ACEOF
+
+# Transform confdefs.h into two sed scripts, `conftest.defines' and
+# `conftest.undefs', that substitutes the proper values into
+# config.h.in to produce config.h. The first handles `#define'
+# templates, and the second `#undef' templates.
+# And first: Protect against being on the right side of a sed subst in
+# config.status. Protect against being in an unquoted here document
+# in config.status.
+rm -f conftest.defines conftest.undefs
+# Using a here document instead of a string reduces the quoting nightmare.
+# Putting comments in sed scripts is not portable.
+#
+# `end' is used to avoid that the second main sed command (meant for
+# 0-ary CPP macros) applies to n-ary macro definitions.
+# See the Autoconf documentation for `clear'.
+cat >confdef2sed.sed <<\_ACEOF
+s/[\\&,]/\\&/g
+s,[\\$`],\\&,g
+t clear
+: clear
+s,^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*\)\(([^)]*)\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1\2${ac_dC}\3${ac_dD},gp
+t end
+s,^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD},gp
+: end
+_ACEOF
+# If some macros were called several times there might be several times
+# the same #defines, which is useless. Nevertheless, we may not want to
+# sort them, since we want the *last* AC-DEFINE to be honored.
+uniq confdefs.h | sed -n -f confdef2sed.sed >conftest.defines
+sed 's/ac_d/ac_u/g' conftest.defines >conftest.undefs
+rm -f confdef2sed.sed
+
+# This sed command replaces #undef with comments. This is necessary, for
+# example, in the case of _POSIX_SOURCE, which is predefined and required
+# on some systems where configure will not decide to define it.
+cat >>conftest.undefs <<\_ACEOF
+s,^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*,/* & */,
+_ACEOF
+
+# Break up conftest.defines because some shells have a limit on the size
+# of here documents, and old seds have small limits too (100 cmds).
+echo ' # Handle all the #define templates only if necessary.' >>$CONFIG_STATUS
+echo ' if grep "^[ ]*#[ ]*define" $tmp/in >/dev/null; then' >>$CONFIG_STATUS
+echo ' # If there are no defines, we may have an empty if/fi' >>$CONFIG_STATUS
+echo ' :' >>$CONFIG_STATUS
+rm -f conftest.tail
+while grep . conftest.defines >/dev/null
+do
+ # Write a limited-size here document to $tmp/defines.sed.
+ echo ' cat >$tmp/defines.sed <<CEOF' >>$CONFIG_STATUS
+ # Speed up: don't consider the non `#define' lines.
+ echo '/^[ ]*#[ ]*define/!b' >>$CONFIG_STATUS
+ # Work around the forget-to-reset-the-flag bug.
+ echo 't clr' >>$CONFIG_STATUS
+ echo ': clr' >>$CONFIG_STATUS
+ sed ${ac_max_here_lines}q conftest.defines >>$CONFIG_STATUS
+ echo 'CEOF
+ sed -f $tmp/defines.sed $tmp/in >$tmp/out
+ rm -f $tmp/in
+ mv $tmp/out $tmp/in
+' >>$CONFIG_STATUS
+ sed 1,${ac_max_here_lines}d conftest.defines >conftest.tail
+ rm -f conftest.defines
+ mv conftest.tail conftest.defines
+done
+rm -f conftest.defines
+echo ' fi # grep' >>$CONFIG_STATUS
+echo >>$CONFIG_STATUS
+
+# Break up conftest.undefs because some shells have a limit on the size
+# of here documents, and old seds have small limits too (100 cmds).
+echo ' # Handle all the #undef templates' >>$CONFIG_STATUS
+rm -f conftest.tail
+while grep . conftest.undefs >/dev/null
+do
+ # Write a limited-size here document to $tmp/undefs.sed.
+ echo ' cat >$tmp/undefs.sed <<CEOF' >>$CONFIG_STATUS
+ # Speed up: don't consider the non `#undef'
+ echo '/^[ ]*#[ ]*undef/!b' >>$CONFIG_STATUS
+ # Work around the forget-to-reset-the-flag bug.
+ echo 't clr' >>$CONFIG_STATUS
+ echo ': clr' >>$CONFIG_STATUS
+ sed ${ac_max_here_lines}q conftest.undefs >>$CONFIG_STATUS
+ echo 'CEOF
+ sed -f $tmp/undefs.sed $tmp/in >$tmp/out
+ rm -f $tmp/in
+ mv $tmp/out $tmp/in
+' >>$CONFIG_STATUS
+ sed 1,${ac_max_here_lines}d conftest.undefs >conftest.tail
+ rm -f conftest.undefs
+ mv conftest.tail conftest.undefs
+done
+rm -f conftest.undefs
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+ # Let's still pretend it is `configure' which instantiates (i.e., don't
+ # use $as_me), people would be surprised to read:
+ # /* config.h. Generated by config.status. */
+ if test x"$ac_file" = x-; then
+ echo "/* Generated by configure. */" >$tmp/config.h
+ else
+ echo "/* $ac_file. Generated by configure. */" >$tmp/config.h
+ fi
+ cat $tmp/in >>$tmp/config.h
+ rm -f $tmp/in
+ if test x"$ac_file" != x-; then
+ if diff $ac_file $tmp/config.h >/dev/null 2>&1; then
+ { echo "$as_me:$LINENO: $ac_file is unchanged" >&5
+echo "$as_me: $ac_file is unchanged" >&6;}
+ else
+ ac_dir=`(dirname "$ac_file") 2>/dev/null ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$ac_file" : 'X\(//\)[^/]' \| \
+ X"$ac_file" : 'X\(//\)$' \| \
+ X"$ac_file" : 'X\(/\)' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X"$ac_file" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+ /^X\(\/\/\)$/{ s//\1/; q; }
+ /^X\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+ { if $as_mkdir_p; then
+ mkdir -p "$ac_dir"
+ else
+ as_dir="$ac_dir"
+ as_dirs=
+ while test ! -d "$as_dir"; do
+ as_dirs="$as_dir $as_dirs"
+ as_dir=`(dirname "$as_dir") 2>/dev/null ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+ /^X\(\/\/\)$/{ s//\1/; q; }
+ /^X\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+ done
+ test ! -n "$as_dirs" || mkdir $as_dirs
+ fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5
+echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;}
+ { (exit 1); exit 1; }; }; }
+
+ rm -f $ac_file
+ mv $tmp/config.h $ac_file
+ fi
+ else
+ cat $tmp/config.h
+ rm -f $tmp/config.h
+ fi
+done
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+#
+# CONFIG_COMMANDS section.
+#
+for ac_file in : $CONFIG_COMMANDS; do test "x$ac_file" = x: && continue
+ ac_dest=`echo "$ac_file" | sed 's,:.*,,'`
+ ac_source=`echo "$ac_file" | sed 's,[^:]*:,,'`
+ ac_dir=`(dirname "$ac_dest") 2>/dev/null ||
+$as_expr X"$ac_dest" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$ac_dest" : 'X\(//\)[^/]' \| \
+ X"$ac_dest" : 'X\(//\)$' \| \
+ X"$ac_dest" : 'X\(/\)' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X"$ac_dest" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+ /^X\(\/\/\)$/{ s//\1/; q; }
+ /^X\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+ { if $as_mkdir_p; then
+ mkdir -p "$ac_dir"
+ else
+ as_dir="$ac_dir"
+ as_dirs=
+ while test ! -d "$as_dir"; do
+ as_dirs="$as_dir $as_dirs"
+ as_dir=`(dirname "$as_dir") 2>/dev/null ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+ /^X\(\/\/\)$/{ s//\1/; q; }
+ /^X\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+ done
+ test ! -n "$as_dirs" || mkdir $as_dirs
+ fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5
+echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;}
+ { (exit 1); exit 1; }; }; }
+
+ ac_builddir=.
+
+if test "$ac_dir" != .; then
+ ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+ # A "../" for each directory in $ac_dir_suffix.
+ ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
+else
+ ac_dir_suffix= ac_top_builddir=
+fi
+
+case $srcdir in
+ .) # No --srcdir option. We are building in place.
+ ac_srcdir=.
+ if test -z "$ac_top_builddir"; then
+ ac_top_srcdir=.
+ else
+ ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
+ fi ;;
+ [\\/]* | ?:[\\/]* ) # Absolute path.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir ;;
+ *) # Relative path.
+ ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_builddir$srcdir ;;
+esac
+
+# Do not use `cd foo && pwd` to compute absolute paths, because
+# the directories may not exist.
+case `pwd` in
+.) ac_abs_builddir="$ac_dir";;
+*)
+ case "$ac_dir" in
+ .) ac_abs_builddir=`pwd`;;
+ [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";;
+ *) ac_abs_builddir=`pwd`/"$ac_dir";;
+ esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_builddir=${ac_top_builddir}.;;
+*)
+ case ${ac_top_builddir}. in
+ .) ac_abs_top_builddir=$ac_abs_builddir;;
+ [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
+ *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
+ esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_srcdir=$ac_srcdir;;
+*)
+ case $ac_srcdir in
+ .) ac_abs_srcdir=$ac_abs_builddir;;
+ [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
+ *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
+ esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_srcdir=$ac_top_srcdir;;
+*)
+ case $ac_top_srcdir in
+ .) ac_abs_top_srcdir=$ac_abs_builddir;;
+ [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
+ *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
+ esac;;
+esac
+
+
+ { echo "$as_me:$LINENO: executing $ac_dest commands" >&5
+echo "$as_me: executing $ac_dest commands" >&6;}
+ case $ac_dest in
+ postprocessing )
+ echo ""
+ echo "Postprocess exported Makefiles"
+ echo "------------------------------"
+ echo ""
+ ;;
+ cvode_ser_ex_bl )
+ IN_FILE="examples/cvode/serial/Makefile_ex"
+ SOLVER="CVODE"
+ SOLVER_LIB="sundials_cvode"
+ SOLVER_FLIB=""
+ EXAMPLES="cvAdvDiff_bnd cvDirectDemo_ls cvDiurnal_kry_bp cvDiurnal_kry cvKrylovDemo_ls cvKrylovDemo_prec cvRoberts_dns cvRoberts_dns_uw"
+ EXAMPLES_BL="cvAdvDiff_bndL cvRoberts_dnsL"
+ ${SHELL} bin/makefile-update.sh "${IN_FILE}" "${SOLVER}" "${EXAMPLES}" "${EXAMPLES_BL}" "${SOLVER_LIB}" "${SOLVER_FLIB}"
+ ;;
+ cvode_ser_ex )
+ IN_FILE="examples/cvode/serial/Makefile_ex"
+ SOLVER="CVODE"
+ SOLVER_LIB="sundials_cvode"
+ SOLVER_FLIB=""
+ EXAMPLES="cvAdvDiff_bnd cvDirectDemo_ls cvDiurnal_kry_bp cvDiurnal_kry cvKrylovDemo_ls cvKrylovDemo_prec cvRoberts_dns cvRoberts_dns_uw"
+ EXAMPLES_BL=""
+ ${SHELL} bin/makefile-update.sh "${IN_FILE}" "${SOLVER}" "${EXAMPLES}" "${EXAMPLES_BL}" "${SOLVER_LIB}" "${SOLVER_FLIB}"
+ ;;
+ cvode_fser_ex_bl )
+ IN_FILE="examples/cvode/fcmix_serial/Makefile_ex"
+ SOLVER="CVODE"
+ SOLVER_LIB="sundials_cvode"
+ SOLVER_FLIB="sundials_fcvode"
+ EXAMPLES="fcvAdvDiff_bnd fcvDiurnal_kry_bp fcvDiurnal_kry fcvRoberts_dns"
+ EXAMPLES_BL="fcvRoberts_dnsL"
+ ${SHELL} bin/makefile-update.sh "${IN_FILE}" "${SOLVER}" "${EXAMPLES}" "${EXAMPLES_BL}" "${SOLVER_LIB}" "${SOLVER_FLIB}"
+ ;;
+ cvode_fser_ex )
+ IN_FILE="examples/cvode/fcmix_serial/Makefile_ex"
+ SOLVER="CVODE"
+ SOLVER_LIB="sundials_cvode"
+ SOLVER_FLIB="sundials_fcvode"
+ EXAMPLES="fcvAdvDiff_bnd fcvDiurnal_kry_bp fcvDiurnal_kry fcvRoberts_dns"
+ EXAMPLES_BL=""
+ ${SHELL} bin/makefile-update.sh "${IN_FILE}" "${SOLVER}" "${EXAMPLES}" "${EXAMPLES_BL}" "${SOLVER_LIB}" "${SOLVER_FLIB}"
+ ;;
+ cvode_par_ex )
+ IN_FILE="examples/cvode/parallel/Makefile_ex"
+ SOLVER="CVODE"
+ SOLVER_LIB="sundials_cvode"
+ SOLVER_FLIB=""
+ EXAMPLES="cvAdvDiff_non_p cvDiurnal_kry_bbd_p cvDiurnal_kry_p"
+ EXAMPLES_BL=""
+ ${SHELL} bin/makefile-update.sh "${IN_FILE}" "${SOLVER}" "${EXAMPLES}" "${EXAMPLES_BL}" "${SOLVER_LIB}" "${SOLVER_FLIB}"
+ ;;
+ cvode_fpar_ex )
+ IN_FILE="examples/cvode/fcmix_parallel/Makefile_ex"
+ SOLVER="CVODE"
+ SOLVER_LIB="sundials_cvode"
+ SOLVER_FLIB="sundials_fcvode"
+ EXAMPLES="fcvDiag_non_p fcvDiag_kry_bbd_p fcvDiag_kry_p"
+ EXAMPLES_BL=""
+ ${SHELL} bin/makefile-update.sh "${IN_FILE}" "${SOLVER}" "${EXAMPLES}" "${EXAMPLES_BL}" "${SOLVER_LIB}" "${SOLVER_FLIB}"
+ ;;
+ cvodes_ser_ex_bl )
+ IN_FILE="examples/cvodes/serial/Makefile_ex"
+ SOLVER="CVODES"
+ SOLVER_LIB="sundials_cvodes"
+ SOLVER_FLIB=""
+ EXAMPLES="cvsAdvDiff_ASAi_bnd cvsAdvDiff_FSA_non cvsDiurnal_kry_bp cvsFoodWeb_ASAp_kry cvsKrylovDemo_prec cvsAdvDiff_bnd cvsDirectDemo_ls cvsDiurnal_kry cvsHessian_ASA_FSA cvsRoberts_ASAi_dns cvsRoberts_dns_uw cvsDiurnal_FSA_kry cvsFoodWeb_ASAi_kry cvsKrylovDemo_ls cvsRoberts_dns cvsRoberts_FSA_dns"
+ EXAMPLES_BL="cvsRoberts_dnsL cvsAdvDiff_bndL"
+ ${SHELL} bin/makefile-update.sh "${IN_FILE}" "${SOLVER}" "${EXAMPLES}" "${EXAMPLES_BL}" "${SOLVER_LIB}" "${SOLVER_FLIB}"
+ ;;
+ cvodes_ser_ex )
+ IN_FILE="examples/cvodes/serial/Makefile_ex"
+ SOLVER="CVODES"
+ SOLVER_LIB="sundials_cvodes"
+ SOLVER_FLIB=""
+ EXAMPLES="cvsAdvDiff_ASAi_bnd cvsAdvDiff_FSA_non cvsDiurnal_kry_bp cvsFoodWeb_ASAp_kry cvsKrylovDemo_prec cvsAdvDiff_bnd cvsDirectDemo_ls cvsDiurnal_kry cvsHessian_ASA_FSA cvsRoberts_ASAi_dns cvsRoberts_dns_uw cvsDiurnal_FSA_kry cvsFoodWeb_ASAi_kry cvsKrylovDemo_ls cvsRoberts_dns cvsRoberts_FSA_dns"
+ EXAMPLES_BL=""
+ ${SHELL} bin/makefile-update.sh "${IN_FILE}" "${SOLVER}" "${EXAMPLES}" "${EXAMPLES_BL}" "${SOLVER_LIB}" "${SOLVER_FLIB}"
+ ;;
+ cvodes_par_ex )
+ IN_FILE="examples/cvodes/parallel/Makefile_ex"
+ SOLVER="CVODES"
+ SOLVER_LIB="sundials_cvodes"
+ SOLVER_FLIB=""
+ EXAMPLES="cvsAdvDiff_ASAp_non_p cvsAdvDiff_non_p cvsDiurnal_FSA_kry_p cvsDiurnal_kry_p cvsAdvDiff_FSA_non_p cvsAtmDisp_ASAi_kry_bbd_p cvsDiurnal_kry_bbd_p"
+ EXAMPLES_BL=""
+ ${SHELL} bin/makefile-update.sh "${IN_FILE}" "${SOLVER}" "${EXAMPLES}" "${EXAMPLES_BL}" "${SOLVER_LIB}" "${SOLVER_FLIB}"
+ ;;
+ ida_ser_ex_bl )
+ IN_FILE="examples/ida/serial/Makefile_ex"
+ SOLVER="IDA"
+ SOLVER_LIB="sundials_ida"
+ SOLVER_FLIB=""
+ EXAMPLES="idaFoodWeb_bnd idaHeat2D_bnd idaHeat2D_kry idaKrylovDemo_ls idaRoberts_dns idaSlCrank_dns"
+ EXAMPLES_BL=""
+ ${SHELL} bin/makefile-update.sh "${IN_FILE}" "${SOLVER}" "${EXAMPLES}" "${EXAMPLES_BL}" "${SOLVER_LIB}" "${SOLVER_FLIB}"
+ ;;
+ ida_ser_ex )
+ IN_FILE="examples/ida/serial/Makefile_ex"
+ SOLVER="IDA"
+ SOLVER_LIB="sundials_ida"
+ SOLVER_FLIB=""
+ EXAMPLES="idaFoodWeb_bnd idaHeat2D_bnd idaHeat2D_kry idaKrylovDemo_ls idaRoberts_dns idaSlCrank_dns"
+ EXAMPLES_BL=""
+ ${SHELL} bin/makefile-update.sh "${IN_FILE}" "${SOLVER}" "${EXAMPLES}" "${EXAMPLES_BL}" "${SOLVER_LIB}" "${SOLVER_FLIB}"
+ ;;
+ ida_fser_ex_bl )
+ IN_FILE="examples/ida/fcmix_serial/Makefile_ex"
+ SOLVER="IDA"
+ SOLVER_LIB="sundials_ida"
+ SOLVER_FLIB="sundials_fida"
+ EXAMPLES="fidaRoberts_dns"
+ EXAMPLES_BL=""
+ ${SHELL} bin/makefile-update.sh "${IN_FILE}" "${SOLVER}" "${EXAMPLES}" "${EXAMPLES_BL}" "${SOLVER_LIB}" "${SOLVER_FLIB}"
+ ;;
+ ida_fser_ex )
+ IN_FILE="examples/ida/fcmix_serial/Makefile_ex"
+ SOLVER="IDA"
+ SOLVER_LIB="sundials_ida"
+ SOLVER_FLIB="sundials_fida"
+ EXAMPLES="fidaRoberts_dns"
+ EXAMPLES_BL=""
+ ${SHELL} bin/makefile-update.sh "${IN_FILE}" "${SOLVER}" "${EXAMPLES}" "${EXAMPLES_BL}" "${SOLVER_LIB}" "${SOLVER_FLIB}"
+ ;;
+ ida_par_ex )
+ IN_FILE="examples/ida/parallel/Makefile_ex"
+ SOLVER="IDA"
+ SOLVER_LIB="sundials_ida"
+ SOLVER_FLIB=""
+ EXAMPLES="idaFoodWeb_kry_bbd_p idaFoodWeb_kry_p idaHeat2D_kry_bbd_p idaHeat2D_kry_p"
+ EXAMPLES_BL=""
+ ${SHELL} bin/makefile-update.sh "${IN_FILE}" "${SOLVER}" "${EXAMPLES}" "${EXAMPLES_BL}" "${SOLVER_LIB}" "${SOLVER_FLIB}"
+ ;;
+ ida_fpar_ex )
+ IN_FILE="examples/ida/fcmix_parallel/Makefile_ex"
+ SOLVER="IDA"
+ SOLVER_LIB="sundials_ida"
+ SOLVER_FLIB="sundials_fida"
+ EXAMPLES="fidaHeat2D_kry_bbd_p"
+ EXAMPLES_BL=""
+ ${SHELL} bin/makefile-update.sh "${IN_FILE}" "${SOLVER}" "${EXAMPLES}" "${EXAMPLES_BL}" "${SOLVER_LIB}" "${SOLVER_FLIB}"
+ ;;
+ idas_ser_ex_bl )
+ IN_FILE="examples/idas/serial/Makefile_ex"
+ SOLVER="IDAS"
+ SOLVER_LIB="sundials_idas"
+ SOLVER_FLIB=""
+ EXAMPLES="idasAkzoNob_ASAi_dns idasFoodWeb_bnd idasHeat2D_kry idasKrylovDemo_ls idasRoberts_dns idasSlCrank_dns idasAkzoNob_dns idasHeat2D_bnd idasHessian_ASA_FSA idasRoberts_ASAi_dns idasRoberts_FSA_dns idasSlCrank_FSA_dns"
+ EXAMPLES_BL=""
+ ${SHELL} bin/makefile-update.sh "${IN_FILE}" "${SOLVER}" "${EXAMPLES}" "${EXAMPLES_BL}" "${SOLVER_LIB}" "${SOLVER_FLIB}"
+ ;;
+ idas_ser_ex )
+ IN_FILE="examples/idas/serial/Makefile_ex"
+ SOLVER="IDAS"
+ SOLVER_LIB="sundials_idas"
+ SOLVER_FLIB=""
+ EXAMPLES="idasAkzoNob_ASAi_dns idasFoodWeb_bnd idasHeat2D_kry idasKrylovDemo_ls idasRoberts_dns idasSlCrank_dns idasAkzoNob_dns idasHeat2D_bnd idasHessian_ASA_FSA idasRoberts_ASAi_dns idasRoberts_FSA_dns idasSlCrank_FSA_dns"
+ EXAMPLES_BL=""
+ ${SHELL} bin/makefile-update.sh "${IN_FILE}" "${SOLVER}" "${EXAMPLES}" "${EXAMPLES_BL}" "${SOLVER_LIB}" "${SOLVER_FLIB}"
+ ;;
+ idas_par_ex )
+ IN_FILE="examples/idas/parallel/Makefile_ex"
+ SOLVER="IDAS"
+ SOLVER_LIB="sundials_idas"
+ SOLVER_FLIB=""
+ EXAMPLES="idasBruss_ASAp_kry_bbd_p idasBruss_kry_bbd_p idasFoodWeb_kry_p idasHeat2D_kry_bbd_p idasBruss_FSA_kry_bbd_p idasFoodWeb_kry_bbd_p idasHeat2D_FSA_kry_bbd_p idasHeat2D_kry_p"
+ EXAMPLES_BL=""
+ ${SHELL} bin/makefile-update.sh "${IN_FILE}" "${SOLVER}" "${EXAMPLES}" "${EXAMPLES_BL}" "${SOLVER_LIB}" "${SOLVER_FLIB}"
+ ;;
+ kinsol_ser_ex_bl )
+ IN_FILE="examples/kinsol/serial/Makefile_ex"
+ SOLVER="KINSOL"
+ SOLVER_LIB="sundials_kinsol"
+ SOLVER_FLIB=""
+ EXAMPLES="kinFerTron_dns kinFoodWeb_kry kinKrylovDemo_ls kinLaplace_bnd kinRoboKin_dns"
+ EXAMPLES_BL=""
+ ${SHELL} bin/makefile-update.sh "${IN_FILE}" "${SOLVER}" "${EXAMPLES}" "${EXAMPLES_BL}" "${SOLVER_LIB}" "${SOLVER_FLIB}"
+ ;;
+ kinsol_ser_ex )
+ IN_FILE="examples/kinsol/serial/Makefile_ex"
+ SOLVER="KINSOL"
+ SOLVER_LIB="sundials_kinsol"
+ SOLVER_FLIB=""
+ EXAMPLES="kinFerTron_dns kinFoodWeb_kry kinKrylovDemo_ls kinLaplace_bnd kinRoboKin_dns"
+ EXAMPLES_BL=""
+ ${SHELL} bin/makefile-update.sh "${IN_FILE}" "${SOLVER}" "${EXAMPLES}" "${EXAMPLES_BL}" "${SOLVER_LIB}" "${SOLVER_FLIB}"
+ ;;
+ kinsol_fser_ex_bl )
+ IN_FILE="examples/kinsol/fcmix_serial/Makefile_ex"
+ SOLVER="KINSOL"
+ SOLVER_LIB="sundials_kinsol"
+ SOLVER_FLIB="sundials_fkinsol"
+ EXAMPLES="fkinDiagon_kry"
+ EXAMPLES_BL=""
+ ${SHELL} bin/makefile-update.sh "${IN_FILE}" "${SOLVER}" "${EXAMPLES}" "${EXAMPLES_BL}" "${SOLVER_LIB}" "${SOLVER_FLIB}"
+ ;;
+ kinsol_fser_ex )
+ IN_FILE="examples/kinsol/fcmix_serial/Makefile_ex"
+ SOLVER="KINSOL"
+ SOLVER_LIB="sundials_kinsol"
+ SOLVER_FLIB="sundials_fkinsol"
+ EXAMPLES="fkinDiagon_kry"
+ EXAMPLES_BL=""
+ ${SHELL} bin/makefile-update.sh "${IN_FILE}" "${SOLVER}" "${EXAMPLES}" "${EXAMPLES_BL}" "${SOLVER_LIB}" "${SOLVER_FLIB}"
+ ;;
+ kinsol_par_ex )
+ IN_FILE="examples/kinsol/parallel/Makefile_ex"
+ SOLVER="KINSOL"
+ SOLVER_LIB="sundials_kinsol"
+ SOLVER_FLIB=""
+ EXAMPLES="kinFoodWeb_kry_bbd_p kinFoodWeb_kry_p"
+ EXAMPLES_BL=""
+ ${SHELL} bin/makefile-update.sh "${IN_FILE}" "${SOLVER}" "${EXAMPLES}" "${EXAMPLES_BL}" "${SOLVER_LIB}" "${SOLVER_FLIB}"
+ ;;
+ kinsol_fpar_ex )
+ IN_FILE="examples/kinsol/fcmix_parallel/Makefile_ex"
+ SOLVER="KINSOL"
+ SOLVER_LIB="sundials_kinsol"
+ SOLVER_FLIB="sundials_fkinsol"
+ EXAMPLES="fkinDiagon_kry_p"
+ EXAMPLES_BL=""
+ ${SHELL} bin/makefile-update.sh "${IN_FILE}" "${SOLVER}" "${EXAMPLES}" "${EXAMPLES_BL}" "${SOLVER_LIB}" "${SOLVER_FLIB}"
+ ;;
+ cpodes_ser_ex_bl )
+ IN_FILE="examples/cpodes/serial/Makefile_ex"
+ SOLVER="CPODES"
+ SOLVER_LIB="sundials_cpodes"
+ SOLVER_FLIB=""
+ EXAMPLES="cpsAdvDiff_bnd cpsAdvDiff_non cpsNewtCrd_dns cpsPend_dns cpsRoberts_dns cpsVanDPol_non"
+ EXAMPLES_BL="cpsAdvDiff_bndL cpsPend_dnsL cpsRoberts_dnsL"
+ ${SHELL} bin/makefile-update.sh "${IN_FILE}" "${SOLVER}" "${EXAMPLES}" "${EXAMPLES_BL}" "${SOLVER_LIB}" "${SOLVER_FLIB}"
+ ;;
+ cpodes_ser_ex )
+ IN_FILE="examples/cpodes/serial/Makefile_ex"
+ SOLVER="CPODES"
+ SOLVER_LIB="sundials_cpodes"
+ SOLVER_FLIB=""
+ EXAMPLES="cpsAdvDiff_bnd cpsAdvDiff_non cpsNewtCrd_dns cpsPend_dns cpsRoberts_dns cpsVanDPol_non"
+ EXAMPLES_BL=""
+ ${SHELL} bin/makefile-update.sh "${IN_FILE}" "${SOLVER}" "${EXAMPLES}" "${EXAMPLES_BL}" "${SOLVER_LIB}" "${SOLVER_FLIB}"
+ ;;
+ cpodes_par_ex )
+ IN_FILE="examples/cpodes/parallel/Makefile_ex"
+ SOLVER="CPODES"
+ SOLVER_LIB="sundials_cpodes"
+ SOLVER_FLIB=""
+ EXAMPLES="cpsHeat2D_kry_bbd_p"
+ EXAMPLES_BL=""
+ ${SHELL} bin/makefile-update.sh "${IN_FILE}" "${SOLVER}" "${EXAMPLES}" "${EXAMPLES_BL}" "${SOLVER_LIB}" "${SOLVER_FLIB}"
+ ;;
+ esac
+done
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+{ (exit 0); exit 0; }
+_ACEOF
+chmod +x $CONFIG_STATUS
+ac_clean_files=$ac_clean_files_save
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded. So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status. When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+ ac_cs_success=:
+ ac_config_status_args=
+ test "$silent" = yes &&
+ ac_config_status_args="$ac_config_status_args --quiet"
+ exec 5>/dev/null
+ $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+ exec 5>>config.log
+ # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+ # would make configure fail if this is the last instruction.
+ $ac_cs_success || { (exit 1); exit 1; }
+fi
+
+
+# Display summary
+
+
+if test "X${SUNDIALS_WARN_FLAG}" = "Xyes"; then
+echo "
+***************
+* WARNING *
+***************
+
+At least one warning was issued. Some features were disabled.
+
+Review the configure output and/or the contents of config.log
+before proceeding with the build.
+"
+fi
+
+echo "
+------------------------------
+SUNDIALS Configuration Summary
+------------------------------"
+
+echo "
+Configuration
+-------------
+
+ Host System: ${host}
+ Build System: ${build}
+
+ C Preprocessor: ${CPP}
+ C Preprocessor Flags: ${CPPFLAGS}
+ C Compiler: ${CC}
+ C Compiler Flags ${CFLAGS}
+ C Linker: ${CC}
+ Linker Flags: ${LDFLAGS}
+ Libraries: ${LIBS}"
+
+if test "X${F77_OK}" = "Xyes"; then
+echo "
+ Fortran Compiler: ${F77}
+ Fortran Compiler Flags: ${FFLAGS}
+ Fortran Linker: ${F77_LNKR}
+ Extra Fortran Libraries: ${FLIBS}"
+fi
+
+if test "X${MPI_ENABLED}" = "Xyes" && test "X${MPI_C_COMP_OK}" = "Xyes"; then
+echo "
+ MPI Root Directory: ${MPI_ROOT_DIR}
+ MPI Include Directory: ${MPI_INC_DIR}
+ MPI Library Directory: ${MPI_LIB_DIR}
+ MPI Flags: ${MPI_FLAGS}
+ Extra MPI Libraries: ${MPI_LIBS}
+
+ Using MPI-C script? ${USE_MPICC_SCRIPT}
+ MPI-C: ${MPICC}"
+fi
+
+if test "X${MPI_ENABLED}" = "Xyes" && test "X${F77_EXAMPLES_ENABLED}" = "Xyes" && test "X${MPI_F77_COMP_OK}" = "Xyes"; then
+echo "
+ Using MPI-Fortran script? ${USE_MPIF77_SCRIPT}
+ MPI-Fortran: ${MPIF77}
+ MPI-Fortran Linker: ${MPIF77_LNKR}"
+fi
+
+# Determine SOURCE, BUILD, and EXEC_PREFIX directories
+cv_srcdir=`( cd ${srcdir} ; pwd )`
+cv_builddir=`pwd`
+if test "X${exec_prefix}" = "XNONE"; then
+ cv_exec_prefix="${prefix}"
+else
+ cv_exec_prefix="${exec_prefix}"
+fi
+
+echo "
+ srcdir: ${cv_srcdir}
+ builddir: ${cv_builddir}
+ prefix: ${prefix}
+ exec_prefix: ${cv_exec_prefix}
+ includedir: ${includedir}
+ libdir: ${libdir}"
+
+if test "X${EXAMPLES_ENABLED}" = "Xyes"; then
+echo " examples installed in: ${EXS_INSTDIR}"
+fi
+
+echo "
+Modules
+-------
+"
+
+if test "X${CVODE_ENABLED}" = "Xyes"; then
+ THIS_LINE="CVODE"
+ if test "X${FCMIX_ENABLED}" = "Xyes"; then
+ THIS_LINE="${THIS_LINE} FCVODE"
+ fi
+ echo " ${THIS_LINE}"
+fi
+
+if test "X${CVODES_ENABLED}" = "Xyes"; then
+ THIS_LINE="CVODES"
+ echo " ${THIS_LINE}"
+fi
+
+if test "X${IDA_ENABLED}" = "Xyes"; then
+ THIS_LINE="IDA"
+ if test "X${FCMIX_ENABLED}" = "Xyes"; then
+ THIS_LINE="${THIS_LINE} FIDA"
+ fi
+ echo " ${THIS_LINE}"
+fi
+
+if test "X${IDAS_ENABLED}" = "Xyes"; then
+ THIS_LINE="IDAS"
+ echo " ${THIS_LINE}"
+fi
+
+if test "X${KINSOL_ENABLED}" = "Xyes"; then
+ THIS_LINE="KINSOL"
+ if test "X${FCMIX_ENABLED}" = "Xyes"; then
+ THIS_LINE="${THIS_LINE} FKINSOL"
+ fi
+ echo " ${THIS_LINE}"
+fi
+
+if test "X${CPODES_ENABLED}" = "Xyes"; then
+ THIS_LINE="CPODES"
+ echo " ${THIS_LINE}"
+fi
+
+if test "X${EXAMPLES_ENABLED}" = "Xyes"; then
+echo "
+Examples
+--------
+"
+
+echo " Serial C examples: ${SERIAL_C_EXAMPLES}"
+echo " Parallel C examples: ${PARALLEL_C_EXAMPLES}"
+echo " Serial Fortran examples: ${SERIAL_F77_EXAMPLES}"
+echo " Parallel Fortran examples: ${PARALLEL_F77_EXAMPLES}"
+
+fi
+
+
+echo "
+ Type 'make' and then 'make install' to build and install ${PACKAGE_STRING}."
+
+
+
+echo "
+----------------------------------
+Finished SUNDIALS Configure Script
+----------------------------------
+"
+
+
diff --git a/configure.ac b/configure.ac
new file mode 100644
index 0000000..51d70b8
--- /dev/null
+++ b/configure.ac
@@ -0,0 +1,157 @@
+# ------------------------------------------------------------------------
+# $Revision: 1.52 $
+# $Date: 2009/02/17 03:11:47 $
+# ------------------------------------------------------------------------
+# Programmer(s): Radu Serban and Aaron Collier @ LLNL
+# ------------------------------------------------------------------------
+# Copyright (c) 2007, The Regents of the University of California.
+# Produced at the Lawrence Livermore National Laboratory.
+# All rights reserved.
+# For details, see the LICENSE file.
+# ------------------------------------------------------------------------
+# Process this file with autoconf to produce a configure script.
+# ------------------------------------------------------------------------
+
+# Initialize configure
+AC_INIT(SUNDIALS, 2.5.0, radu at llnl.gov)
+
+# Display greeting
+SUNDIALS_GREETING
+
+# Specify directory containing auxillary build tools and M4 files
+AC_CONFIG_AUX_DIR([config])
+
+# Miscellaneous SUNDIALS initializations
+echo "Initialization"
+echo "--------------"
+echo ""
+SUNDIALS_INITIALIZE
+
+# Test enable/disable features
+SUNDIALS_ENABLES
+
+# Set C compilation (Required)
+echo ""
+echo "C Compiler Settings"
+echo "-------------------"
+echo ""
+AC_PROG_CC(cc gcc)
+SUNDIALS_SET_CC
+
+# Set Fortran support
+if test "X${FCMIX_ENABLED}" = "Xyes" || test "X${LAPACK_ENABLED}" = "Xyes"; then
+ echo ""
+ echo "Fortran Settings"
+ echo "----------------"
+ echo ""
+ SUNDIALS_F77_SUPPORT
+fi
+
+# Set MPI support (Optional)
+if test "X${MPI_ENABLED}" = "Xyes"; then
+ echo ""
+ echo "MPI-C Settings"
+ echo "--------------"
+ echo ""
+ SUNDIALS_SET_MPICC
+fi
+if test "X${MPI_C_COMP_OK}" = "Xyes"; then
+ if test "X${FCMIX_ENABLED}" = "Xyes"; then
+ echo ""
+ echo "MPI-2 Functionality"
+ echo "-------------------"
+ echo ""
+ SUNDIALS_CHECK_MPI2
+ fi
+ if test "X${F77_EXAMPLES_ENABLED}" = "Xyes"; then
+ echo ""
+ echo "MPI-Fortran Settings"
+ echo "--------------------"
+ echo ""
+ SUNDIALS_SET_MPIF77
+ fi
+fi
+
+# Set examples modules
+if test "X${EXAMPLES_ENABLED}" = "Xyes"; then
+ echo ""
+ echo "Examples"
+ echo "--------"
+ echo ""
+ SUNDIALS_SET_EXAMPLES
+fi
+
+# Run libtool checks
+echo ""
+echo "Libtool Settings"
+echo "----------------"
+echo ""
+AC_DISABLE_SHARED
+AC_LIBTOOL_WIN32_DLL
+AC_PROG_LIBTOOL
+
+# Do we build shared libraries?
+# (enable_shared is set by the function AC_ENABLE_SHARED in libtool.m4)
+SHARED_LIBS="${enable_shared}"
+
+# Print a few more lines for configure --help
+SUNDIALS_MORE_HELP
+
+# Substitute variables
+AC_SUBST(SHARED_LIBS)
+AC_SUBST(MPICC)
+AC_SUBST(MPIF77)
+AC_SUBST(MPI_INC_DIR)
+AC_SUBST(MPI_LIB_DIR)
+AC_SUBST(MPI_LIBS)
+AC_SUBST(MPI_FLAGS)
+AC_SUBST(FCMIX_ENABLED)
+AC_SUBST(FLOAT_TYPE)
+AC_SUBST(LIBTOOL_DEPS)
+AC_SUBST(F77_MANGLE_MACRO1)
+AC_SUBST(F77_MANGLE_MACRO2)
+AC_SUBST(F77_CASE)
+AC_SUBST(F77_UNDERSCORES)
+AC_SUBST(PRECISION_LEVEL)
+AC_SUBST(GENERIC_MATH_LIB)
+AC_SUBST(BLAS_LAPACK_MACRO)
+AC_SUBST(SUNDIALS_EXPORT)
+AC_SUBST(F77_MPI_COMM_F2C)
+AC_SUBST(F77_LNKR)
+AC_SUBST(F77_LIBS)
+AC_SUBST(F77_LDFLAGS)
+AC_SUBST(LAPACK_ENABLED)
+AC_SUBST(BLAS_LAPACK_LIBS)
+AC_SUBST(MPIF77_LNKR)
+AC_SUBST(OBJEXT)
+AC_SUBST(EXEEXT)
+AC_SUBST(SLV_MODULES)
+AC_SUBST(EXS_MODULES)
+AC_SUBST(EXS_INSTDIR)
+
+# Generate makefiles
+echo ""
+echo "Create Makefiles and configuration files"
+echo "----------------------------------------"
+echo ""
+SUNDIALS_BUILD_MODULES_LIST
+
+# Set-up postprocessing commands
+if test "X${EXAMPLES_ENABLED}" = "Xyes" && test "X${EXS_INSTDIR}" != "Xno"; then
+ AC_CONFIG_COMMANDS([postprocessing],
+ [
+ echo ""
+ echo "Postprocess exported Makefiles"
+ echo "------------------------------"
+ echo ""
+ ])
+ SUNDIALS_POST_PROCESSING
+fi
+
+# Specify files to be configured and call AC_OUTPUT
+AC_CONFIG_FILES([${SUNDIALS_MAKEFILES}])
+AC_CONFIG_FILES([${SUNDIALS_CONFIGFILES}])
+AC_OUTPUT
+
+# Display summary
+SUNDIALS_REPORT
diff --git a/debian/README.Debian b/debian/README.Debian
deleted file mode 100644
index 0033dc2..0000000
--- a/debian/README.Debian
+++ /dev/null
@@ -1,23 +0,0 @@
-sundials for Debian
-----------------
-
-Configuring Octave's startup
-
-
-"""
-Matlab will execute a file named 'startup.m' in the directory it was called from on the command line. Octave does not. It will, however, execute a file named '.octaverc' which can be edited to execute existing files
-
-if ( exist ('startup.m', 'file') )
- source ('startup.m') # load startup.m like matlab
-endif
-"""
-
-According to the above doc create or add the folliwng lines to your .octaverc to activate sundials bindings for octave:
-
- % SUNDIALS Toolbox startup M-file, if it exists.
- if ( exist('startup_STB.m','file') )
- source ('startup_STB.m') # load startup.m like matlab
- end
-
-
- -- Christophe Trophime <christophe.trophime at lncmi.cnrs.fr> Mon, 24 Oct 2011 15:01:41 +0200
diff --git a/debian/README.source b/debian/README.source
deleted file mode 100644
index 94c2cb7..0000000
--- a/debian/README.source
+++ /dev/null
@@ -1,9 +0,0 @@
-sundials source for Debian
----------------------------
-
-Packaging makes use of CDBS and quilt. For the latter see
-`/usr/share/doc/quilt/README.source'.
-
-Documentation files included in the distribution have been removed
-You can find sundials documentation on
-https://computation.llnl.gov/casc/sundials/documentation/documentation.html
diff --git a/debian/changelog b/debian/changelog
deleted file mode 100644
index 284fa3b..0000000
--- a/debian/changelog
+++ /dev/null
@@ -1,301 +0,0 @@
-sundials (2.5.0-4) unstable; urgency=medium
-
- * Remove myself from the uploaders
-
- -- Sylvestre Ledru <sylvestre at debian.org> Sat, 26 Dec 2015 23:50:53 +0100
-
-sundials (2.5.0-3) unstable; urgency=low
-
- * Team upload.
- * Revert changes from experimental version which inadvertently made it into
- the previous upload.
- * Improve the fix for missing BLAS and LAPACK dependencies (closes: #700525)
- + no longer pass BLAS and LAPACK through LDFLAGS
- + link-blas-lapack.patch: new patch which rather adds the dependencies at
- the libtool link level
- + add missing dependency of libsundials-serial-dev on libblas-dev and
- liblapack-dev
- * Fix the dependency of octave-sundials on octave.
-
- -- Sébastien Villemot <sebastien at debian.org> Wed, 27 Feb 2013 16:58:32 +0100
-
-sundials (2.5.0-2) unstable; urgency=low
-
- * debian/rules:
- - Add -lblas -llapack -lm to LDFLAGS (closes: #700525)
-
- -- Christophe Trophime <christophe.trophime at lncmi.cnrs.fr> Thu, 14 Feb 2013 16:58:48 +0100
-
-sundials (2.5.0-2~exp1) experimental; urgency=low
-
- [ Andrew Miller ]
- * Fix spelling of suite (closes: #680881)
- * Add a -dbg package (closes: #680878)
-
- [ Rafael Laboissiere ]
- * debian/rules:
- - Install .mex files in the appropriate directory
-
- * Switch to buildsystem to cmake
- * Switch to debhelper 9
- * Switch to dpkg-source 3.0 (quilt) format
-
- * Add support for parallel version
- * Add a separate package for examples
- * Modify check.sh to run serial tests
-
- -- Christophe Trophime <christophe.trophime at lncmi.cnrs.fr> Mon, 9 Jul 2012 09:40:03 +1200
-
-sundials (2.5.0-1) unstable; urgency=low
-
- * New upstream release
- * Remove sh4.patch
- * Standards-Version changed to 3.9.3
-
- [Kamaraju Kusumanchi][Rafael Laboissiere]
- * Adjust for the new octave package version 3.6.1 (closes: #668830)
-
- -- Christophe Trophime <christophe.trophime at lncmi.cnrs.fr> Tue, 24 Apr 2012 08:49:39 +0200
-
-sundials (2.4.0-6) unstable; urgency=low
-
- * Rebuild using the last version of hdf5.
-
- -- Sylvestre Ledru <sylvestre at debian.org> Thu, 26 Jan 2012 10:18:07 +0100
-
-sundials (2.4.0-5) unstable; urgency=low
-
- * debian/rules: remove duplicate definition of debexp var.
- This brings back the missing static libraries (closes: #650933)
- * debian/control: add DM-Upload-Allowed
-
- -- Christophe Trophime <christophe.trophime at lncmi.cnrs.fr> Mon, 05 Dec 2011 08:36:33 +0100
-
-sundials (2.4.0-4) unstable; urgency=low
-
- * add octave support
-
- [Peter Green]
- * debian/patches: add fix-format-error.patch (Closes: #646457)
-
- -- Christophe Trophime <christophe.trophime at lncmi.cnrs.fr> Mon, 24 Oct 2011 15:01:41 +0200
-
-sundials (2.4.0-3) unstable; urgency=low
-
- * Change the uploader to Debian Science
- * Standards-Version changed to 3.9.2
-
- -- Sylvestre Ledru <sylvestre at debian.org> Mon, 08 Aug 2011 22:29:34 +0200
-
-sundials (2.4.0-2) unstable; urgency=low
-
- [Nobuhiro Iwamatsu]
- * debian/patches: add sh4.patch (Closes: #602160)
-
- -- Christophe Trophime <christophe.trophime at grenoble.cnrs.fr> Mon, 14 Feb 2011 11:25:18 +0100
-
-sundials (2.4.0-1) unstable; urgency=low
-
- * Standards-Version changed to 3.9.1
-
- [ Christophe Trophime ]
- * Team upload
- * New upstream version
- * Add a separate package for IDAS
- * Remove pdf from the orig tarball
- * debian/control: add missing builddependencies on blas/lapack
- * debian/control: remove libsundials-serial-doc
- * debian/rules: modify get-orig-rules target to remove pdf from the orig
- tarball
- * debian/orig-tarball.sh: change to force download to tarballs directory
-
- -- Sylvestre Ledru <sylvestre at debian.org> Sat, 09 Oct 2010 18:18:22 +0200
-
-sundials (2.3.0-2) unstable; urgency=low
-
- * Package moved to debian-science
- * Raphael removed and add myself in the Uploaders list (Closes: #571898)
- * Missing replace/conflicts added (Closes: #540498)
- * No longer install *.la files
- * bashim removed (Closes: #530983)
- * Standards-Version updated to version 3.8.4
-
- -- Sylvestre Ledru <sylvestre at debian.org> Tue, 30 Mar 2010 22:54:48 +0200
-
-sundials (2.3.0-1) unstable; urgency=low
-
- [ Andrey Romanenko ]
- * New upstream release
- * Added sundials-config man page
-
- [ Rafael Laboissiere ]
- * Switch from CDBS' simple-patchsys to quilt
- * Split the libsundials-serial package into individual library packages
- * debian/clean: Add file for removing config.log (Lintian warning) and the
- .libs/* files, which are not cleaned by make clean but should
- * debian/compat: Bump debhelper compatibility to v7
- * debian/control:
- + Build-depends on debhelper >= 7, such that debian/clean is taken
- into account
- + Added Homepage, Vcs-Svn, and Vcs-Browser fields to the Source
- section
- + Dropped the Homepage pseudo-header from the extended descriptions
- + Bumped Standards-Version to 3.8.0
- + Switch from ${Source-Version} substvar to ${binary:Version}
- + Fix Lintian warnings debhelper-but-no-misc-depends
- + Drop duplicated Section fields in the Package stanzas
- * debian/sundials-config.1: Drop .NH macro
- * debian/watch: Add file for uscan
- * debian/orig-tarball.sh: Add script for use by uscan. This is necessary
- because of the javascript URL investigated in debian/watch.
- * debian/{libsundials-cvode0,libsundials-cvodes1,libsundials-ida1,
- libsundials-kinsol0,libsundials-nvecserial0}.symbols : Add shared
- library symbols files
- * debian/check.sh: Add script for exercising the serial checks
- * debian/rules:
- + (build/libsundials-serial): Call debian/check.sh
- + (binary-install/libsundials-serial-dev): Install
- the *.c, *.f, *.out, and READMe files from the examples/ directory.
- * debian/control: Mention the presence of the examples in the
- description of the libsundials-serial-dev package
- * debian/patches/modern-ltmain.sh.patch: Add header and make Lintian happy
- * debian/source.lintian-overrides: Override the ancient-libtool warning
-
- [ Daniel Leidert ]
- * debian/control (Depends): Added gfortran to build FORTRAN examples.
- * debian/libsundials-cvode0.install: Removed DEB_DESTDIR from path.
- * debian/libsundials-cvodes1.install: Ditto.
- * debian/libsundials-ida1.install: Ditto.
- * debian/libsundials-kinsol0.install: Ditto.
- * debian/libsundials-nvecserial0.install: Ditto.
- * debian/libsundials-serial-dev.install: Ditto. Further removed manpage
- installation (done with dh_installman).
- * debian/sundials-config.1: Minor format changes.
- * debian/rules: Added get-orig-source target to retieve source code via
- wget, which works atm. Set gfortran as FORTRAN compiler. Install
- everything from DEB_DESTDIR.
- (DEB_CONFIGURE_EXTRA_FLAGS): Removed --enable-fortran, which is not a
- valid option.
- (install/libsundials-serial-dev): Removed target. Better done with
- DEB_INSTALL_MANPAGES.
-
- -- Rafael Laboissiere <rafael at debian.org> Wed, 11 Feb 2009 17:58:22 +0100
-
-sundials (2.2.0-3) unstable; urgency=low
-
- * debian/control: Changed maintainer to the pkg-scicomp team at Alioth
-
- -- Rafael Laboissiere <rafael at debian.org> Sat, 16 Sep 2006 13:11:09 +0200
-
-sundials (2.2.0-2) unstable; urgency=low
-
- * debian/rules:
- - Create directories $(DEB_DESTDIR)/usr/{lib,include} before
- installing the package. This should be done by the upstream
- Makefiles (but it is not) and was preventing the libsundials_nvec
- library and associated include files from being shipped in the
- package (closes: #385630).
- - Also reported in Bug#385630 was the fact that the libdir lines in
- the *.la files were wrong. again, this is an upstream defect,
- because there is no way to prevent the -rpath option from being
- used. This problem is fixed in this version.
-
- -- Rafael Laboissiere <rafael at debian.org> Sun, 3 Sep 2006 14:31:59 +0200
-
-sundials (2.2.0-1) unstable; urgency=low
-
- [ Andrey Romanenko ]
- * New upstream release
- * debian/libsundials-serial-dev.install: add lines to copy the content of
- include/sundials subdirectories
- * config/ltmain.sh: upgrade with the current version to solve the .so
- extension problem
- * debian/libsundials-serial.lintian: removed
- * debian/lintian/libsundials-serial0: new file
-
- [ Rafael Laboissiere ]
- * Switched to cdbs
- * Since upstream is using soversion numbers for the libraries, the
- package is renamed from libsundials-serial to libsundials-serial0
- * debian/control: Bumped Standards-Version to 3.7.2 (no changes needed)
-
- -- Rafael Laboissiere <rafael at debian.org> Mon, 8 May 2006 12:32:29 +0200
-
-sundials (2.1.1-7) unstable; urgency=low
-
- +++ Changes by Rafael Laboissiere
-
- * debian/control: Bumped Standards-Version to 3.7.0 (no changes needed)
-
- -- Debian Octave Group <pkg-octave-devel at lists.alioth.debian.org> Thu, 3 May 2006 22:24:39 +0000
-
-sundials (2.1.1-6) unstable; urgency=low
-
- +++ Changes by Thomas Weber
-
- * debian/control: make doc package architecture "all"
- debian/rules: dito (closes: #346392)
-
- -- Debian Octave Group <pkg-octave-devel at lists.alioth.debian.org> Sun, 8 Jan 2006 23:24:39 +0100
-
-sundials (2.1.1-5) unstable; urgency=low
-
- +++ Changes by Rafael Laboissiere
-
- * First official Debian release (closes: #341565)
-
- -- Debian Octave Group <pkg-octave-devel at lists.alioth.debian.org> Tue, 6 Dec 2005 19:52:13 +0100
-
-sundials (2.1.1-4) unstable; urgency=low
-
- +++ Changes by Rafael Laboissiere
-
- * debian/control: Changed the name of the source package to sundials.
- This corresponds to the name of the origianl usptream tarball.
-
- -- Debian Octave Group <pkg-octave-devel at lists.alioth.debian.org> Thu, 1 Dec 2005 08:32:22 +0100
-
-libsundials-serial (2.1.1-3) unstable; urgency=low
-
- +++ Changes by Andrey Romanenko
-
- * Set Maintainer to Debian Octave Group <pkg-octave-devel at lists.alioth.debian.org>
- * Create a documentation package that contains the user guides of the
- solvers
- * Change the name of the package containing the dynamic libraries to
- sundials-serial
- * added a lintian override file
-
- +++ Changes by Rafael Laboissiere
-
- * Centralize the /usr/share/doc/<pkg>* directories, by symlinking both
- <pkg>-dev and <pkg>-doc to <pkg>. This forces the dependency of
- libsundails-serial-doc on libsundials-serial.
-
- -- Debian Octave Group <pkg-octave-devel at lists.alioth.debian.org> Wed, 26 Oct 2005 12:47:56 +0100
-
-libsundials-serial (2.1.1-2) unstable; urgency=low
-
- * Move header files into /usr/include/sundials
-
- -- Andrey Romanenko <andrey at enginum.com> Fri, 21 Oct 2005 17:20:49 +0100
-
-libsundials-serial (2.1.1-1) unstable; urgency=low
-
- * Initial release
-
- -- Andrey Romanenko <andrey at enginum.com> Fri, 21 Oct 2005 17:19:32 +0100
-
-Local Variables:
-eval: (progn
- (make-local-hook 'debian-changelog-add-version-hook)
- (add-hook
- 'debian-changelog-add-version-hook
- (lambda ()
- (save-excursion
- (forward-line -1)
- (beginning-of-line)
- (insert "\n NOT YET RELEASED!\n\n [ "
- (or (getenv "DEBFULLNAME") (user-full-name)) " ]")))
- nil t))
-End:
diff --git a/debian/check.sh b/debian/check.sh
deleted file mode 100644
index 5cba9e2..0000000
--- a/debian/check.sh
+++ /dev/null
@@ -1,45 +0,0 @@
-#!/bin/sh
-
-## Simple script for exercising the serial checks of Sundials
-## Author: Rafael Laboissiere <rafael at debian.org>
-
-RESULTS=$(tempfile)
-
-cleanup(){
- rm -f $RESULTS
-}
-trap "cleanup" 1 2 3 13 15
-
-CWD=$(pwd)
-cd $1/examples
-
-for dir in $(find . -type d -maxdepth 1 -mindepth 1) ; do
- #for mode in "serial" "fcmix_serial" "parallel" "fcmix_parallel" ; do
- for mode in "serial" ; do
- cd $dir/$mode
- echo "tests in " $mode
- for prog in $(find . -executable -type f) ; do
- echo -n "Checking $prog... "
- if [ "$mode" != "parallel" ]; then
- ./$prog > $RESULTS
- else
- OMPI_MCA_plm_rsh_agent=/bin/false ./$prog > $RESULTS
- fi
-
- if test -e $2/examples/$dir/serial/$prog.out ; then
- DIFF=$(diff -u $2/examples/$dir/serial/$prog.out $RESULTS)
- if test -z "$DIFF" ; then
- echo success
- else
- echo fail
- echo "$DIFF"
- fi
- else
- echo pass
- fi
- done
- cd $1/examples
- done
-done
-
-cd $CWD
diff --git a/debian/clean b/debian/clean
deleted file mode 100644
index 8f4dafa..0000000
--- a/debian/clean
+++ /dev/null
@@ -1,3 +0,0 @@
-config.log
-src/*/.libs/*
-src/*/*/.libs/*
diff --git a/debian/compat b/debian/compat
deleted file mode 100644
index ec63514..0000000
--- a/debian/compat
+++ /dev/null
@@ -1 +0,0 @@
-9
diff --git a/debian/control b/debian/control
deleted file mode 100644
index 02f9d76..0000000
--- a/debian/control
+++ /dev/null
@@ -1,193 +0,0 @@
-Source: sundials
-Priority: optional
-Section: libs
-Maintainer: Debian Science Team <debian-science-maintainers at lists.alioth.debian.org>
-Uploaders: Christophe Trophime <christophe.trophime at lncmi.cnrs.fr>
-Build-Depends: debhelper (>= 9), cmake, gfortran, mpi-default-dev,
- libblas-dev | libblas-3gf.so, liblapack-dev | liblapack-3gf.so,
- octave-pkg-dev (>= 0.7.0)
-Standards-Version: 3.9.3
-Homepage: http://www.llnl.gov/CASC/sundials/
-Vcs-Svn: svn://svn.debian.org/svn/debian-science/packages/sundials/trunk/
-Vcs-Browser: http://svn.debian.org/viewsvn/debian-science/packages/sundials/trunk/
-
-Package: libsundials-serial
-Architecture: any
-Depends: libsundials-cvode1, libsundials-cvodes2, libsundials-ida2,
- libsundials-idas0, libsundials-kinsol1, libsundials-nvecserial0, ${misc:Depends}
-Conflicts: libsundials-serial0
-Replaces: libsundials-serial0
-Description: SUite of Nonlinear and DIfferential/ALgebraic equation Solvers
- The family of solvers referred to as SUNDIALS consists of solvers CVODE
- (for ODE systems), CVODES (ODE with sensitivity analysis capabilities),
- IDA (for differential-algebraic systems), and KINSOL (for nonlinear
- algebraic systems).
- .
- This package depends on all other packages containing the shared
- libraries for the subcomponents of SUNDIALS: CVODE, CVODES, IDA,
- KINSOL, and NVECTOR_SERIAL.
-
-Package: libsundials-parallel
-Architecture: any
-Depends: libsundials-cvode1, libsundials-cvodes2, libsundials-ida2,
- libsundials-idas0, libsundials-kinsol1, libsundials-nvecparallel0,
- ${misc:Depends}, mpi-default-run
-Description: SUite of Nonlinear and DIfferential/ALgebraic equation Solvers
- The family of solvers referred to as SUNDIALS consists of solvers CVODE
- (for ODE systems), CVODES (ODE with sensitivity analysis capabilities),
- IDA (for differential-algebraic systems), and KINSOL (for nonlinear
- algebraic systems).
- .
- This package depends on all other packages containing the shared
- libraries for the subcomponents of SUNDIALS: CVODE, CVODES, IDA,
- KINSOL, and NVECTOR_PARALLEL.
-
-Package: libsundials-cvode1
-Architecture: any
-Depends: ${shlibs:Depends}, ${misc:Depends}
-Description: ordinary differentialequation solver (SUNDIALS library)
- This package contains the library for ordinary differential equation
- (ODE) system solvers from SUNDIALS (SUite of Nonlinear and
- DIfferential/ALgebraic equation Solvers).
-
-Package: libsundials-cvodes2
-Architecture: any
-Depends: ${shlibs:Depends}, ${misc:Depends}
-Description: ODE solver with sensistivity analysis (SUNDIALS library)
- This package contains the library for ordinary differential equation
- (ODE) system solver with sensistivity analysis capabilities from
- SUNDIALS (SUite of Nonlinear and DIfferential/ALgebraic equation
- Solvers).
-
-Package: libsundials-ida2
-Architecture: any
-Depends: ${shlibs:Depends}, ${misc:Depends}
-Description: differential-algebraic system solver (SUNDIALS library)
- This package contains the library for differential-algebraic system
- (IDA) solver from SUNDIALS (SUite of Nonlinear and
- DIfferential/ALgebraic equation Solvers).
-
-Package: libsundials-idas0
-Architecture: any
-Depends: ${shlibs:Depends}, ${misc:Depends}
-Description: IDA solver with sensitivity capabilities (SUNDIALS library)
- This package contains the library for differential-algebraic system
- with Sensitivity capabilities (IDAS) solver from SUNDIALS (SUite of
- Nonlinear and DIfferential/ALgebraic equation Solvers).
-
-Package: libsundials-kinsol1
-Architecture: any
-Depends: ${shlibs:Depends}, ${misc:Depends}
-Description: KINSOL solver (SUNDIALS library)
- This package contain the library for KINSOL (nonlinear algebraic
- systems) system solver from SUNDIALS (SUite of Nonlinear and
- DIfferential/ALgebraic equation Solvers).
-
-Package: libsundials-nvecserial0
-Architecture: any
-Depends: ${shlibs:Depends}, ${misc:Depends}
-Description: vector operations library (SUNDIALS library)
- This package provides implementations for all vector operations
- defined by the generic NVECTOR module in the table of operations for
- SUNDIALS (SUite of Nonlinear and DIfferential/ALgebraic equation
- Solvers).
-
-Package: libsundials-nvecparallel0
-Architecture: any
-Depends: ${shlibs:Depends}, ${misc:Depends}, mpi-default-run
-Description: MPI vector operations library (SUNDIALS library)
- This package provides implementations for all vector operations
- defined by the generic NVECTOR module in the table of operations for
- SUNDIALS (SUite of Nonlinear and DIfferential/ALgebraic equation
- Solvers).
-
-Package: libsundials-serial-dev
-Section: libdevel
-Architecture: any
-Depends: libsundials-serial (= ${binary:Version}), ${misc:Depends},
- libblas-dev | libatlas-base-dev | libopenblas-dev,
- liblapack-dev | libatlas-base-dev
-Recommends: libsundials-serial-dbg
-Description: SUNDIALS development files
- The family of solvers referred to as SUNDIALS (SUite of Nonlinear and
- DIfferential/ALgebraic equation Solvers) consists of solvers CVODE
- (for ODE systems), CVODES (ODE with sensitivity analysis capabilities),
- IDA (for differential-algebraic systems), and KINSOL (for nonlinear
- algebraic systems).
- .
- This package contains files necessary for development applications using
- SUNDIALS in C and, in case of FCVODE and FKINSOL, Fortran. It also
- contains various example programs distributed by the upstream authors.
-
-Package: libsundials-nvecparallel-dev
-Section: libdevel
-Architecture: any
-Depends: libsundials-nvecparallel0 (= ${binary:Version}), ${misc:Depends}
-Description: MPI vector operations library (SUNDIALS library)
- This package provides implementations for all vector operations
- defined by the generic NVECTOR module in the table of operations for
- SUNDIALS (SUite of Nonlinear and DIfferential/ALgebraic equation
- Solvers).
- .
- This package contains files necessary for development applications using
- SUNDIALS in C and, in case of FCVODE and FKINSOL, Fortran. It also
- contains various example programs distributed by the upstream authors.
- .
- This package provides MPI version
-
-Package: libsundials-doc
-Section: doc
-Architecture: all
-Depends: ${misc:Depends}
-Recommends: libsundials-serial-dev
-Description: SUNDIALS examples files
- The family of solvers referred to as SUNDIALS (SUite of Nonlinear and
- DIfferential/ALgebraic equation Solvers) consists of solvers CVODE
- (for ODE systems), CVODES (ODE with sensitivity analysis capabilities),
- IDA (for differential-algebraic systems), and KINSOL (for nonlinear
- algebraic systems).
- .
- This package contains SUNDIALS examples.
-
-Package: octave-sundials
-Architecture: any
-Depends: ${misc:Depends}, ${shlibs:Depends}, octave
-Recommends: libsundials-serial-dev
-Description: SUNDIALS for octave
- The family of solvers referred to as SUNDIALS (SUite of Nonlinear and
- DIfferential/ALgebraic equation Solvers) consists of solvers CVODE
- (for ODE systems), CVODES (ODE with sensitivity analysis capabilities),
- IDA (for differential-algebraic systems), and KINSOL (for nonlinear
- algebraic systems).
- .
- This package contains SUNDIALS plugins for octave.
-
-Package: libsundials-serial-dbg
-Section: debug
-Architecture: any
-Priority: extra
-Depends: libsundials-serial, ${misc:Depends}
-Description: SUite of Nonlinear and DIfferential/ALgebraic equation Solvers
- The family of solvers referred to as SUNDIALS consists of solvers CVODE
- (for ODE systems), CVODES (ODE with sensitivity analysis capabilities),
- IDA (for differential-algebraic systems), and KINSOL (for nonlinear
- algebraic systems).
- .
- This package contains the debugging symbols for SUNDIALS.
-
-Package: libsundials-nvecparallel-dbg
-Section: debug
-Architecture: any
-Priority: extra
-Depends: libsundials-nvecparallel0 (= ${binary:Version}), ${misc:Depends}
-Description: MPI vector operations library (SUNDIALS library)
- This package provides implementations for all vector operations
- defined by the generic NVECTOR module in the table of operations for
- SUNDIALS (SUite of Nonlinear and DIfferential/ALgebraic equation
- Solvers).
- .
- This package contains files necessary for development applications using
- SUNDIALS in C and, in case of FCVODE and FKINSOL, Fortran. It also
- contains various example programs distributed by the upstream authors.
- .
- This package contains the debugging symbols.
diff --git a/debian/docs b/debian/docs
deleted file mode 100644
index e845566..0000000
--- a/debian/docs
+++ /dev/null
@@ -1 +0,0 @@
-README
diff --git a/debian/libsundials-cvode1.install b/debian/libsundials-cvode1.install
deleted file mode 100644
index 51e86a6..0000000
--- a/debian/libsundials-cvode1.install
+++ /dev/null
@@ -1 +0,0 @@
-usr/lib/libsundials_cvode.so.*
diff --git a/debian/libsundials-cvode1.symbols b/debian/libsundials-cvode1.symbols
deleted file mode 100644
index e918f19..0000000
--- a/debian/libsundials-cvode1.symbols
+++ /dev/null
@@ -1,189 +0,0 @@
-libsundials_cvode.so.1 libsundials-cvode1 #MINVER#
- AddIdentity at Base 2.5.0
- BandCopy at Base 2.5.0
- BandGBTRF at Base 2.5.0
- BandGBTRS at Base 2.5.0
- BandScale at Base 2.5.0
- CVBBDPrecGetNumGfnEvals at Base 2.5.0
- CVBBDPrecGetWorkSpace at Base 2.5.0
- CVBBDPrecInit at Base 2.5.0
- CVBBDPrecReInit at Base 2.5.0
- CVBand at Base 2.5.0
- CVBandPrecGetNumRhsEvals at Base 2.5.0
- CVBandPrecGetWorkSpace at Base 2.5.0
- CVBandPrecInit at Base 2.5.0
- CVDense at Base 2.5.0
- CVDiag at Base 2.5.0
- CVDiagGetLastFlag at Base 2.5.0
- CVDiagGetNumRhsEvals at Base 2.5.0
- CVDiagGetReturnFlagName at Base 2.5.0
- CVDiagGetWorkSpace at Base 2.5.0
- CVDlsGetLastFlag at Base 2.5.0
- CVDlsGetNumJacEvals at Base 2.5.0
- CVDlsGetNumRhsEvals at Base 2.5.0
- CVDlsGetReturnFlagName at Base 2.5.0
- CVDlsGetWorkSpace at Base 2.5.0
- CVDlsSetBandJacFn at Base 2.5.0
- CVDlsSetDenseJacFn at Base 2.5.0
- CVErrHandler at Base 2.5.0
- CVEwtSet at Base 2.5.0
- CVLapackBand at Base 2.5.0
- CVLapackDense at Base 2.5.0
- CVProcessError at Base 2.5.0
- CVSpbcg at Base 2.5.0
- CVSpgmr at Base 2.5.0
- CVSpilsAtimes at Base 2.5.0
- CVSpilsDQJtimes at Base 2.5.0
- CVSpilsGetLastFlag at Base 2.5.0
- CVSpilsGetNumConvFails at Base 2.5.0
- CVSpilsGetNumJtimesEvals at Base 2.5.0
- CVSpilsGetNumLinIters at Base 2.5.0
- CVSpilsGetNumPrecEvals at Base 2.5.0
- CVSpilsGetNumPrecSolves at Base 2.5.0
- CVSpilsGetNumRhsEvals at Base 2.5.0
- CVSpilsGetReturnFlagName at Base 2.5.0
- CVSpilsGetWorkSpace at Base 2.5.0
- CVSpilsPSolve at Base 2.5.0
- CVSpilsSetEpsLin at Base 2.5.0
- CVSpilsSetGSType at Base 2.5.0
- CVSpilsSetJacTimesVecFn at Base 2.5.0
- CVSpilsSetMaxl at Base 2.5.0
- CVSpilsSetPrecType at Base 2.5.0
- CVSpilsSetPreconditioner at Base 2.5.0
- CVSptfqmr at Base 2.5.0
- CVode at Base 2.5.0
- CVodeCreate at Base 2.5.0
- CVodeFree at Base 2.5.0
- CVodeGetActualInitStep at Base 2.5.0
- CVodeGetCurrentOrder at Base 2.5.0
- CVodeGetCurrentStep at Base 2.5.0
- CVodeGetCurrentTime at Base 2.5.0
- CVodeGetDky at Base 2.5.0
- CVodeGetErrWeights at Base 2.5.0
- CVodeGetEstLocalErrors at Base 2.5.0
- CVodeGetIntegratorStats at Base 2.5.0
- CVodeGetLastOrder at Base 2.5.0
- CVodeGetLastStep at Base 2.5.0
- CVodeGetNonlinSolvStats at Base 2.5.0
- CVodeGetNumErrTestFails at Base 2.5.0
- CVodeGetNumGEvals at Base 2.5.0
- CVodeGetNumLinSolvSetups at Base 2.5.0
- CVodeGetNumNonlinSolvConvFails at Base 2.5.0
- CVodeGetNumNonlinSolvIters at Base 2.5.0
- CVodeGetNumRhsEvals at Base 2.5.0
- CVodeGetNumStabLimOrderReds at Base 2.5.0
- CVodeGetNumSteps at Base 2.5.0
- CVodeGetReturnFlagName at Base 2.5.0
- CVodeGetRootInfo at Base 2.5.0
- CVodeGetTolScaleFactor at Base 2.5.0
- CVodeGetWorkSpace at Base 2.5.0
- CVodeInit at Base 2.5.0
- CVodeReInit at Base 2.5.0
- CVodeRootInit at Base 2.5.0
- CVodeSStolerances at Base 2.5.0
- CVodeSVtolerances at Base 2.5.0
- CVodeSetErrFile at Base 2.5.0
- CVodeSetErrHandlerFn at Base 2.5.0
- CVodeSetInitStep at Base 2.5.0
- CVodeSetIterType at Base 2.5.0
- CVodeSetMaxConvFails at Base 2.5.0
- CVodeSetMaxErrTestFails at Base 2.5.0
- CVodeSetMaxHnilWarns at Base 2.5.0
- CVodeSetMaxNonlinIters at Base 2.5.0
- CVodeSetMaxNumSteps at Base 2.5.0
- CVodeSetMaxOrd at Base 2.5.0
- CVodeSetMaxStep at Base 2.5.0
- CVodeSetMinStep at Base 2.5.0
- CVodeSetNoInactiveRootWarn at Base 2.5.0
- CVodeSetNonlinConvCoef at Base 2.5.0
- CVodeSetRootDirection at Base 2.5.0
- CVodeSetStabLimDet at Base 2.5.0
- CVodeSetStopTime at Base 2.5.0
- CVodeSetUserData at Base 2.5.0
- CVodeWFtolerances at Base 2.5.0
- ClassicalGS at Base 2.5.0
- DenseCopy at Base 2.5.0
- DenseGEQRF at Base 2.5.0
- DenseGETRF at Base 2.5.0
- DenseGETRS at Base 2.5.0
- DenseORMQR at Base 2.5.0
- DensePOTRF at Base 2.5.0
- DensePOTRS at Base 2.5.0
- DenseScale at Base 2.5.0
- DestroyArray at Base 2.5.0
- DestroyMat at Base 2.5.0
- ModifiedGS at Base 2.5.0
- N_VAbs at Base 2.5.0
- N_VAddConst at Base 2.5.0
- N_VClone at Base 2.5.0
- N_VCloneEmpty at Base 2.5.0
- N_VCloneEmptyVectorArray at Base 2.5.0
- N_VCloneVectorArray at Base 2.5.0
- N_VCompare at Base 2.5.0
- N_VConst at Base 2.5.0
- N_VConstrMask at Base 2.5.0
- N_VDestroy at Base 2.5.0
- N_VDestroyVectorArray at Base 2.5.0
- N_VDiv at Base 2.5.0
- N_VDotProd at Base 2.5.0
- N_VGetArrayPointer at Base 2.5.0
- N_VInv at Base 2.5.0
- N_VInvTest at Base 2.5.0
- N_VL1Norm at Base 2.5.0
- N_VLinearSum at Base 2.5.0
- N_VMaxNorm at Base 2.5.0
- N_VMin at Base 2.5.0
- N_VMinQuotient at Base 2.5.0
- N_VProd at Base 2.5.0
- N_VScale at Base 2.5.0
- N_VSetArrayPointer at Base 2.5.0
- N_VSpace at Base 2.5.0
- N_VWL2Norm at Base 2.5.0
- N_VWrmsNorm at Base 2.5.0
- N_VWrmsNormMask at Base 2.5.0
- NewBandMat at Base 2.5.0
- NewDenseMat at Base 2.5.0
- NewIntArray at Base 2.5.0
- NewLintArray at Base 2.5.0
- NewRealArray at Base 2.5.0
- PrintMat at Base 2.5.0
- QRfact at Base 2.5.0
- QRsol at Base 2.5.0
- RAbs at Base 2.5.0
- RExp at Base 2.5.0
- RPowerI at Base 2.5.0
- RPowerR at Base 2.5.0
- RSqrt at Base 2.5.0
- SetToZero at Base 2.5.0
- SpbcgFree at Base 2.5.0
- SpbcgMalloc at Base 2.5.0
- SpbcgSolve at Base 2.5.0
- SpgmrFree at Base 2.5.0
- SpgmrMalloc at Base 2.5.0
- SpgmrSolve at Base 2.5.0
- SptfqmrFree at Base 2.5.0
- SptfqmrMalloc at Base 2.5.0
- SptfqmrSolve at Base 2.5.0
- bandAddIdentity at Base 2.5.0
- bandCopy at Base 2.5.0
- bandGBTRF at Base 2.5.0
- bandGBTRS at Base 2.5.0
- bandScale at Base 2.5.0
- cvDlsBandDQJac at Base 2.5.0
- cvDlsDenseDQJac at Base 2.5.0
- denseAddIdentity at Base 2.5.0
- denseCopy at Base 2.5.0
- denseGEQRF at Base 2.5.0
- denseGETRF at Base 2.5.0
- denseGETRS at Base 2.5.0
- denseORMQR at Base 2.5.0
- densePOTRF at Base 2.5.0
- densePOTRS at Base 2.5.0
- denseScale at Base 2.5.0
- destroyArray at Base 2.5.0
- destroyMat at Base 2.5.0
- newBandMat at Base 2.5.0
- newDenseMat at Base 2.5.0
- newIntArray at Base 2.5.0
- newLintArray at Base 2.5.0
- newRealArray at Base 2.5.0
diff --git a/debian/libsundials-cvodes2.install b/debian/libsundials-cvodes2.install
deleted file mode 100644
index 1c26287..0000000
--- a/debian/libsundials-cvodes2.install
+++ /dev/null
@@ -1 +0,0 @@
-usr/lib/libsundials_cvodes.so.*
diff --git a/debian/libsundials-cvodes2.symbols b/debian/libsundials-cvodes2.symbols
deleted file mode 100644
index 99e5185..0000000
--- a/debian/libsundials-cvodes2.symbols
+++ /dev/null
@@ -1,300 +0,0 @@
-libsundials_cvodes.so.2 libsundials-cvodes2 #MINVER#
- AddIdentity at Base 2.5.0
- BandCopy at Base 2.5.0
- BandGBTRF at Base 2.5.0
- BandGBTRS at Base 2.5.0
- BandScale at Base 2.5.0
- CVBBDPrecGetNumGfnEvals at Base 2.5.0
- CVBBDPrecGetWorkSpace at Base 2.5.0
- CVBBDPrecInit at Base 2.5.0
- CVBBDPrecInitB at Base 2.5.0
- CVBBDPrecReInit at Base 2.5.0
- CVBBDPrecReInitB at Base 2.5.0
- CVBand at Base 2.5.0
- CVBandB at Base 2.5.0
- CVBandPrecGetNumRhsEvals at Base 2.5.0
- CVBandPrecGetWorkSpace at Base 2.5.0
- CVBandPrecInit at Base 2.5.0
- CVBandPrecInitB at Base 2.5.0
- CVDense at Base 2.5.0
- CVDenseB at Base 2.5.0
- CVDiag at Base 2.5.0
- CVDiagB at Base 2.5.0
- CVDiagGetLastFlag at Base 2.5.0
- CVDiagGetNumRhsEvals at Base 2.5.0
- CVDiagGetReturnFlagName at Base 2.5.0
- CVDiagGetWorkSpace at Base 2.5.0
- CVDlsGetLastFlag at Base 2.5.0
- CVDlsGetNumJacEvals at Base 2.5.0
- CVDlsGetNumRhsEvals at Base 2.5.0
- CVDlsGetReturnFlagName at Base 2.5.0
- CVDlsGetWorkSpace at Base 2.5.0
- CVDlsSetBandJacFn at Base 2.5.0
- CVDlsSetBandJacFnB at Base 2.5.0
- CVDlsSetDenseJacFn at Base 2.5.0
- CVDlsSetDenseJacFnB at Base 2.5.0
- CVLapackBand at Base 2.5.0
- CVLapackBandB at Base 2.5.0
- CVLapackDense at Base 2.5.0
- CVLapackDenseB at Base 2.5.0
- CVSpbcg at Base 2.5.0
- CVSpbcgB at Base 2.5.0
- CVSpgmr at Base 2.5.0
- CVSpgmrB at Base 2.5.0
- CVSpilsAtimes at Base 2.5.0
- CVSpilsDQJtimes at Base 2.5.0
- CVSpilsGetLastFlag at Base 2.5.0
- CVSpilsGetNumConvFails at Base 2.5.0
- CVSpilsGetNumJtimesEvals at Base 2.5.0
- CVSpilsGetNumLinIters at Base 2.5.0
- CVSpilsGetNumPrecEvals at Base 2.5.0
- CVSpilsGetNumPrecSolves at Base 2.5.0
- CVSpilsGetNumRhsEvals at Base 2.5.0
- CVSpilsGetReturnFlagName at Base 2.5.0
- CVSpilsGetWorkSpace at Base 2.5.0
- CVSpilsPSolve at Base 2.5.0
- CVSpilsSetEpsLin at Base 2.5.0
- CVSpilsSetEpsLinB at Base 2.5.0
- CVSpilsSetGSType at Base 2.5.0
- CVSpilsSetGSTypeB at Base 2.5.0
- CVSpilsSetJacTimesVecFn at Base 2.5.0
- CVSpilsSetJacTimesVecFnB at Base 2.5.0
- CVSpilsSetMaxl at Base 2.5.0
- CVSpilsSetMaxlB at Base 2.5.0
- CVSpilsSetPrecType at Base 2.5.0
- CVSpilsSetPrecTypeB at Base 2.5.0
- CVSpilsSetPreconditioner at Base 2.5.0
- CVSpilsSetPreconditionerB at Base 2.5.0
- CVSptfqmr at Base 2.5.0
- CVSptfqmrB at Base 2.5.0
- CVode at Base 2.5.0
- CVodeAdjFree at Base 2.5.0
- CVodeAdjInit at Base 2.5.0
- CVodeAdjReInit at Base 2.5.0
- CVodeB at Base 2.5.0
- CVodeCreate at Base 2.5.0
- CVodeCreateB at Base 2.5.0
- CVodeF at Base 2.5.0
- CVodeFree at Base 2.5.0
- CVodeGetActualInitStep at Base 2.5.0
- CVodeGetAdjCVodeBmem at Base 2.5.0
- CVodeGetAdjCheckPointsInfo at Base 2.5.0
- CVodeGetAdjCurrentCheckPoint at Base 2.5.0
- CVodeGetAdjDataPointHermite at Base 2.5.0
- CVodeGetAdjDataPointPolynomial at Base 2.5.0
- CVodeGetAdjY at Base 2.5.0
- CVodeGetB at Base 2.5.0
- CVodeGetCurrentOrder at Base 2.5.0
- CVodeGetCurrentStep at Base 2.5.0
- CVodeGetCurrentTime at Base 2.5.0
- CVodeGetDky at Base 2.5.0
- CVodeGetErrWeights at Base 2.5.0
- CVodeGetEstLocalErrors at Base 2.5.0
- CVodeGetIntegratorStats at Base 2.5.0
- CVodeGetLastOrder at Base 2.5.0
- CVodeGetLastStep at Base 2.5.0
- CVodeGetNonlinSolvStats at Base 2.5.0
- CVodeGetNumErrTestFails at Base 2.5.0
- CVodeGetNumGEvals at Base 2.5.0
- CVodeGetNumLinSolvSetups at Base 2.5.0
- CVodeGetNumNonlinSolvConvFails at Base 2.5.0
- CVodeGetNumNonlinSolvIters at Base 2.5.0
- CVodeGetNumRhsEvals at Base 2.5.0
- CVodeGetNumRhsEvalsSens at Base 2.5.0
- CVodeGetNumStabLimOrderReds at Base 2.5.0
- CVodeGetNumSteps at Base 2.5.0
- CVodeGetQuad at Base 2.5.0
- CVodeGetQuadB at Base 2.5.0
- CVodeGetQuadDky at Base 2.5.0
- CVodeGetQuadErrWeights at Base 2.5.0
- CVodeGetQuadNumErrTestFails at Base 2.5.0
- CVodeGetQuadNumRhsEvals at Base 2.5.0
- CVodeGetQuadSens1 at Base 2.5.0
- CVodeGetQuadSens at Base 2.5.0
- CVodeGetQuadSensDky1 at Base 2.5.0
- CVodeGetQuadSensDky at Base 2.5.0
- CVodeGetQuadSensErrWeights at Base 2.5.0
- CVodeGetQuadSensNumErrTestFails at Base 2.5.0
- CVodeGetQuadSensNumRhsEvals at Base 2.5.0
- CVodeGetQuadSensStats at Base 2.5.0
- CVodeGetQuadStats at Base 2.5.0
- CVodeGetReturnFlagName at Base 2.5.0
- CVodeGetRootInfo at Base 2.5.0
- CVodeGetSens1 at Base 2.5.0
- CVodeGetSens at Base 2.5.0
- CVodeGetSensDky1 at Base 2.5.0
- CVodeGetSensDky at Base 2.5.0
- CVodeGetSensErrWeights at Base 2.5.0
- CVodeGetSensNonlinSolvStats at Base 2.5.0
- CVodeGetSensNumErrTestFails at Base 2.5.0
- CVodeGetSensNumLinSolvSetups at Base 2.5.0
- CVodeGetSensNumNonlinSolvConvFails at Base 2.5.0
- CVodeGetSensNumNonlinSolvIters at Base 2.5.0
- CVodeGetSensNumRhsEvals at Base 2.5.0
- CVodeGetSensStats at Base 2.5.0
- CVodeGetStgrSensNumNonlinSolvConvFails at Base 2.5.0
- CVodeGetStgrSensNumNonlinSolvIters at Base 2.5.0
- CVodeGetTolScaleFactor at Base 2.5.0
- CVodeGetWorkSpace at Base 2.5.0
- CVodeInit at Base 2.5.0
- CVodeInitB at Base 2.5.0
- CVodeInitBS at Base 2.5.0
- CVodeQuadFree at Base 2.5.0
- CVodeQuadInit at Base 2.5.0
- CVodeQuadInitB at Base 2.5.0
- CVodeQuadInitBS at Base 2.5.0
- CVodeQuadReInit at Base 2.5.0
- CVodeQuadReInitB at Base 2.5.0
- CVodeQuadSStolerances at Base 2.5.0
- CVodeQuadSStolerancesB at Base 2.5.0
- CVodeQuadSVtolerances at Base 2.5.0
- CVodeQuadSVtolerancesB at Base 2.5.0
- CVodeQuadSensEEtolerances at Base 2.5.0
- CVodeQuadSensFree at Base 2.5.0
- CVodeQuadSensInit at Base 2.5.0
- CVodeQuadSensReInit at Base 2.5.0
- CVodeQuadSensSStolerances at Base 2.5.0
- CVodeQuadSensSVtolerances at Base 2.5.0
- CVodeReInit at Base 2.5.0
- CVodeReInitB at Base 2.5.0
- CVodeRootInit at Base 2.5.0
- CVodeSStolerances at Base 2.5.0
- CVodeSStolerancesB at Base 2.5.0
- CVodeSVtolerances at Base 2.5.0
- CVodeSVtolerancesB at Base 2.5.0
- CVodeSensEEtolerances at Base 2.5.0
- CVodeSensFree at Base 2.5.0
- CVodeSensInit1 at Base 2.5.0
- CVodeSensInit at Base 2.5.0
- CVodeSensReInit at Base 2.5.0
- CVodeSensSStolerances at Base 2.5.0
- CVodeSensSVtolerances at Base 2.5.0
- CVodeSensToggleOff at Base 2.5.0
- CVodeSetAdjNoSensi at Base 2.5.0
- CVodeSetErrFile at Base 2.5.0
- CVodeSetErrHandlerFn at Base 2.5.0
- CVodeSetInitStep at Base 2.5.0
- CVodeSetInitStepB at Base 2.5.0
- CVodeSetIterType at Base 2.5.0
- CVodeSetIterTypeB at Base 2.5.0
- CVodeSetMaxConvFails at Base 2.5.0
- CVodeSetMaxErrTestFails at Base 2.5.0
- CVodeSetMaxHnilWarns at Base 2.5.0
- CVodeSetMaxNonlinIters at Base 2.5.0
- CVodeSetMaxNumSteps at Base 2.5.0
- CVodeSetMaxNumStepsB at Base 2.5.0
- CVodeSetMaxOrd at Base 2.5.0
- CVodeSetMaxOrdB at Base 2.5.0
- CVodeSetMaxStep at Base 2.5.0
- CVodeSetMaxStepB at Base 2.5.0
- CVodeSetMinStep at Base 2.5.0
- CVodeSetMinStepB at Base 2.5.0
- CVodeSetNoInactiveRootWarn at Base 2.5.0
- CVodeSetNonlinConvCoef at Base 2.5.0
- CVodeSetQuadErrCon at Base 2.5.0
- CVodeSetQuadErrConB at Base 2.5.0
- CVodeSetQuadSensErrCon at Base 2.5.0
- CVodeSetRootDirection at Base 2.5.0
- CVodeSetSensDQMethod at Base 2.5.0
- CVodeSetSensErrCon at Base 2.5.0
- CVodeSetSensMaxNonlinIters at Base 2.5.0
- CVodeSetSensParams at Base 2.5.0
- CVodeSetStabLimDet at Base 2.5.0
- CVodeSetStabLimDetB at Base 2.5.0
- CVodeSetStopTime at Base 2.5.0
- CVodeSetUserData at Base 2.5.0
- CVodeSetUserDataB at Base 2.5.0
- CVodeWFtolerances at Base 2.5.0
- ClassicalGS at Base 2.5.0
- DenseCopy at Base 2.5.0
- DenseGEQRF at Base 2.5.0
- DenseGETRF at Base 2.5.0
- DenseGETRS at Base 2.5.0
- DenseORMQR at Base 2.5.0
- DensePOTRF at Base 2.5.0
- DensePOTRS at Base 2.5.0
- DenseScale at Base 2.5.0
- DestroyArray at Base 2.5.0
- DestroyMat at Base 2.5.0
- ModifiedGS at Base 2.5.0
- N_VAbs at Base 2.5.0
- N_VAddConst at Base 2.5.0
- N_VClone at Base 2.5.0
- N_VCloneEmpty at Base 2.5.0
- N_VCloneEmptyVectorArray at Base 2.5.0
- N_VCloneVectorArray at Base 2.5.0
- N_VCompare at Base 2.5.0
- N_VConst at Base 2.5.0
- N_VConstrMask at Base 2.5.0
- N_VDestroy at Base 2.5.0
- N_VDestroyVectorArray at Base 2.5.0
- N_VDiv at Base 2.5.0
- N_VDotProd at Base 2.5.0
- N_VGetArrayPointer at Base 2.5.0
- N_VInv at Base 2.5.0
- N_VInvTest at Base 2.5.0
- N_VL1Norm at Base 2.5.0
- N_VLinearSum at Base 2.5.0
- N_VMaxNorm at Base 2.5.0
- N_VMin at Base 2.5.0
- N_VMinQuotient at Base 2.5.0
- N_VProd at Base 2.5.0
- N_VScale at Base 2.5.0
- N_VSetArrayPointer at Base 2.5.0
- N_VSpace at Base 2.5.0
- N_VWL2Norm at Base 2.5.0
- N_VWrmsNorm at Base 2.5.0
- N_VWrmsNormMask at Base 2.5.0
- NewBandMat at Base 2.5.0
- NewDenseMat at Base 2.5.0
- NewIntArray at Base 2.5.0
- NewLintArray at Base 2.5.0
- NewRealArray at Base 2.5.0
- PrintMat at Base 2.5.0
- QRfact at Base 2.5.0
- QRsol at Base 2.5.0
- RAbs at Base 2.5.0
- RExp at Base 2.5.0
- RPowerI at Base 2.5.0
- RPowerR at Base 2.5.0
- RSqrt at Base 2.5.0
- SetToZero at Base 2.5.0
- SpbcgFree at Base 2.5.0
- SpbcgMalloc at Base 2.5.0
- SpbcgSolve at Base 2.5.0
- SpgmrFree at Base 2.5.0
- SpgmrMalloc at Base 2.5.0
- SpgmrSolve at Base 2.5.0
- SptfqmrFree at Base 2.5.0
- SptfqmrMalloc at Base 2.5.0
- SptfqmrSolve at Base 2.5.0
- bandAddIdentity at Base 2.5.0
- bandCopy at Base 2.5.0
- bandGBTRF at Base 2.5.0
- bandGBTRS at Base 2.5.0
- bandScale at Base 2.5.0
- cvDlsBandDQJac at Base 2.5.0
- cvDlsDenseDQJac at Base 2.5.0
- cvErrHandler at Base 2.5.0
- cvEwtSet at Base 2.5.0
- cvProcessError at Base 2.5.0
- cvSensRhs1InternalDQ at Base 2.5.0
- cvSensRhs1Wrapper at Base 2.5.0
- cvSensRhsInternalDQ at Base 2.5.0
- cvSensRhsWrapper at Base 2.5.0
- denseAddIdentity at Base 2.5.0
- denseCopy at Base 2.5.0
- denseGEQRF at Base 2.5.0
- denseGETRF at Base 2.5.0
- denseGETRS at Base 2.5.0
- denseORMQR at Base 2.5.0
- densePOTRF at Base 2.5.0
- densePOTRS at Base 2.5.0
- denseScale at Base 2.5.0
- destroyArray at Base 2.5.0
- destroyMat at Base 2.5.0
- newBandMat at Base 2.5.0
- newDenseMat at Base 2.5.0
- newIntArray at Base 2.5.0
- newLintArray at Base 2.5.0
- newRealArray at Base 2.5.0
diff --git a/debian/libsundials-doc.install b/debian/libsundials-doc.install
deleted file mode 100644
index c857f66..0000000
--- a/debian/libsundials-doc.install
+++ /dev/null
@@ -1 +0,0 @@
-examples usr/share/doc/libsundials-doc
diff --git a/debian/libsundials-ida2.install b/debian/libsundials-ida2.install
deleted file mode 100644
index c3066dd..0000000
--- a/debian/libsundials-ida2.install
+++ /dev/null
@@ -1 +0,0 @@
-usr/lib/libsundials_ida.so.*
diff --git a/debian/libsundials-ida2.symbols b/debian/libsundials-ida2.symbols
deleted file mode 100644
index 4773f09..0000000
--- a/debian/libsundials-ida2.symbols
+++ /dev/null
@@ -1,192 +0,0 @@
-libsundials_ida.so.2 libsundials-ida2 #MINVER#
- AddIdentity at Base 2.5.0
- BandCopy at Base 2.5.0
- BandGBTRF at Base 2.5.0
- BandGBTRS at Base 2.5.0
- BandScale at Base 2.5.0
- ClassicalGS at Base 2.5.0
- DenseCopy at Base 2.5.0
- DenseGEQRF at Base 2.5.0
- DenseGETRF at Base 2.5.0
- DenseGETRS at Base 2.5.0
- DenseORMQR at Base 2.5.0
- DensePOTRF at Base 2.5.0
- DensePOTRS at Base 2.5.0
- DenseScale at Base 2.5.0
- DestroyArray at Base 2.5.0
- DestroyMat at Base 2.5.0
- IDABBDPrecGetNumGfnEvals at Base 2.5.0
- IDABBDPrecGetWorkSpace at Base 2.5.0
- IDABBDPrecInit at Base 2.5.0
- IDABBDPrecReInit at Base 2.5.0
- IDABand at Base 2.5.0
- IDACalcIC at Base 2.5.0
- IDACreate at Base 2.5.0
- IDADense at Base 2.5.0
- IDADlsGetLastFlag at Base 2.5.0
- IDADlsGetNumJacEvals at Base 2.5.0
- IDADlsGetNumResEvals at Base 2.5.0
- IDADlsGetReturnFlagName at Base 2.5.0
- IDADlsGetWorkSpace at Base 2.5.0
- IDADlsSetBandJacFn at Base 2.5.0
- IDADlsSetDenseJacFn at Base 2.5.0
- IDAErrHandler at Base 2.5.0
- IDAEwtSet at Base 2.5.0
- IDAFree at Base 2.5.0
- IDAGetActualInitStep at Base 2.5.0
- IDAGetConsistentIC at Base 2.5.0
- IDAGetCurrentOrder at Base 2.5.0
- IDAGetCurrentStep at Base 2.5.0
- IDAGetCurrentTime at Base 2.5.0
- IDAGetDky at Base 2.5.0
- IDAGetErrWeights at Base 2.5.0
- IDAGetEstLocalErrors at Base 2.5.0
- IDAGetIntegratorStats at Base 2.5.0
- IDAGetLastOrder at Base 2.5.0
- IDAGetLastStep at Base 2.5.0
- IDAGetNonlinSolvStats at Base 2.5.0
- IDAGetNumBacktrackOps at Base 2.5.0
- IDAGetNumErrTestFails at Base 2.5.0
- IDAGetNumGEvals at Base 2.5.0
- IDAGetNumLinSolvSetups at Base 2.5.0
- IDAGetNumNonlinSolvConvFails at Base 2.5.0
- IDAGetNumNonlinSolvIters at Base 2.5.0
- IDAGetNumResEvals at Base 2.5.0
- IDAGetNumSteps at Base 2.5.0
- IDAGetReturnFlagName at Base 2.5.0
- IDAGetRootInfo at Base 2.5.0
- IDAGetSolution at Base 2.5.0
- IDAGetTolScaleFactor at Base 2.5.0
- IDAGetWorkSpace at Base 2.5.0
- IDAInit at Base 2.5.0
- IDAInitialSetup at Base 2.5.0
- IDALapackBand at Base 2.5.0
- IDALapackDense at Base 2.5.0
- IDAProcessError at Base 2.5.0
- IDAReInit at Base 2.5.0
- IDARootInit at Base 2.5.0
- IDASStolerances at Base 2.5.0
- IDASVtolerances at Base 2.5.0
- IDASetConstraints at Base 2.5.0
- IDASetErrFile at Base 2.5.0
- IDASetErrHandlerFn at Base 2.5.0
- IDASetId at Base 2.5.0
- IDASetInitStep at Base 2.5.0
- IDASetLineSearchOffIC at Base 2.5.0
- IDASetMaxConvFails at Base 2.5.0
- IDASetMaxErrTestFails at Base 2.5.0
- IDASetMaxNonlinIters at Base 2.5.0
- IDASetMaxNumItersIC at Base 2.5.0
- IDASetMaxNumJacsIC at Base 2.5.0
- IDASetMaxNumSteps at Base 2.5.0
- IDASetMaxNumStepsIC at Base 2.5.0
- IDASetMaxOrd at Base 2.5.0
- IDASetMaxStep at Base 2.5.0
- IDASetNoInactiveRootWarn at Base 2.5.0
- IDASetNonlinConvCoef at Base 2.5.0
- IDASetNonlinConvCoefIC at Base 2.5.0
- IDASetRootDirection at Base 2.5.0
- IDASetStepToleranceIC at Base 2.5.0
- IDASetStopTime at Base 2.5.0
- IDASetSuppressAlg at Base 2.5.0
- IDASetUserData at Base 2.5.0
- IDASolve at Base 2.5.0
- IDASpbcg at Base 2.5.0
- IDASpgmr at Base 2.5.0
- IDASpilsAtimes at Base 2.5.0
- IDASpilsDQJtimes at Base 2.5.0
- IDASpilsGetLastFlag at Base 2.5.0
- IDASpilsGetNumConvFails at Base 2.5.0
- IDASpilsGetNumJtimesEvals at Base 2.5.0
- IDASpilsGetNumLinIters at Base 2.5.0
- IDASpilsGetNumPrecEvals at Base 2.5.0
- IDASpilsGetNumPrecSolves at Base 2.5.0
- IDASpilsGetNumResEvals at Base 2.5.0
- IDASpilsGetReturnFlagName at Base 2.5.0
- IDASpilsGetWorkSpace at Base 2.5.0
- IDASpilsPSolve at Base 2.5.0
- IDASpilsSetEpsLin at Base 2.5.0
- IDASpilsSetGSType at Base 2.5.0
- IDASpilsSetIncrementFactor at Base 2.5.0
- IDASpilsSetJacTimesVecFn at Base 2.5.0
- IDASpilsSetMaxRestarts at Base 2.5.0
- IDASpilsSetMaxl at Base 2.5.0
- IDASpilsSetPreconditioner at Base 2.5.0
- IDASptfqmr at Base 2.5.0
- IDAWFtolerances at Base 2.5.0
- IDAWrmsNorm at Base 2.5.0
- ModifiedGS at Base 2.5.0
- N_VAbs at Base 2.5.0
- N_VAddConst at Base 2.5.0
- N_VClone at Base 2.5.0
- N_VCloneEmpty at Base 2.5.0
- N_VCloneEmptyVectorArray at Base 2.5.0
- N_VCloneVectorArray at Base 2.5.0
- N_VCompare at Base 2.5.0
- N_VConst at Base 2.5.0
- N_VConstrMask at Base 2.5.0
- N_VDestroy at Base 2.5.0
- N_VDestroyVectorArray at Base 2.5.0
- N_VDiv at Base 2.5.0
- N_VDotProd at Base 2.5.0
- N_VGetArrayPointer at Base 2.5.0
- N_VInv at Base 2.5.0
- N_VInvTest at Base 2.5.0
- N_VL1Norm at Base 2.5.0
- N_VLinearSum at Base 2.5.0
- N_VMaxNorm at Base 2.5.0
- N_VMin at Base 2.5.0
- N_VMinQuotient at Base 2.5.0
- N_VProd at Base 2.5.0
- N_VScale at Base 2.5.0
- N_VSetArrayPointer at Base 2.5.0
- N_VSpace at Base 2.5.0
- N_VWL2Norm at Base 2.5.0
- N_VWrmsNorm at Base 2.5.0
- N_VWrmsNormMask at Base 2.5.0
- NewBandMat at Base 2.5.0
- NewDenseMat at Base 2.5.0
- NewIntArray at Base 2.5.0
- NewLintArray at Base 2.5.0
- NewRealArray at Base 2.5.0
- PrintMat at Base 2.5.0
- QRfact at Base 2.5.0
- QRsol at Base 2.5.0
- RAbs at Base 2.5.0
- RExp at Base 2.5.0
- RPowerI at Base 2.5.0
- RPowerR at Base 2.5.0
- RSqrt at Base 2.5.0
- SetToZero at Base 2.5.0
- SpbcgFree at Base 2.5.0
- SpbcgMalloc at Base 2.5.0
- SpbcgSolve at Base 2.5.0
- SpgmrFree at Base 2.5.0
- SpgmrMalloc at Base 2.5.0
- SpgmrSolve at Base 2.5.0
- SptfqmrFree at Base 2.5.0
- SptfqmrMalloc at Base 2.5.0
- SptfqmrSolve at Base 2.5.0
- bandAddIdentity at Base 2.5.0
- bandCopy at Base 2.5.0
- bandGBTRF at Base 2.5.0
- bandGBTRS at Base 2.5.0
- bandScale at Base 2.5.0
- denseAddIdentity at Base 2.5.0
- denseCopy at Base 2.5.0
- denseGEQRF at Base 2.5.0
- denseGETRF at Base 2.5.0
- denseGETRS at Base 2.5.0
- denseORMQR at Base 2.5.0
- densePOTRF at Base 2.5.0
- densePOTRS at Base 2.5.0
- denseScale at Base 2.5.0
- destroyArray at Base 2.5.0
- destroyMat at Base 2.5.0
- idaDlsBandDQJac at Base 2.5.0
- idaDlsDenseDQJac at Base 2.5.0
- newBandMat at Base 2.5.0
- newDenseMat at Base 2.5.0
- newIntArray at Base 2.5.0
- newLintArray at Base 2.5.0
- newRealArray at Base 2.5.0
diff --git a/debian/libsundials-idas0.install b/debian/libsundials-idas0.install
deleted file mode 100644
index 9cd7c0b..0000000
--- a/debian/libsundials-idas0.install
+++ /dev/null
@@ -1 +0,0 @@
-usr/lib/libsundials_idas.so.*
diff --git a/debian/libsundials-idas0.symbols b/debian/libsundials-idas0.symbols
deleted file mode 100644
index 75bf8b2..0000000
--- a/debian/libsundials-idas0.symbols
+++ /dev/null
@@ -1,302 +0,0 @@
-libsundials_idas.so.0 libsundials-idas0 #MINVER#
- AddIdentity at Base 2.5.0
- BandCopy at Base 2.5.0
- BandGBTRF at Base 2.5.0
- BandGBTRS at Base 2.5.0
- BandScale at Base 2.5.0
- ClassicalGS at Base 2.5.0
- DenseCopy at Base 2.5.0
- DenseGEQRF at Base 2.5.0
- DenseGETRF at Base 2.5.0
- DenseGETRS at Base 2.5.0
- DenseORMQR at Base 2.5.0
- DensePOTRF at Base 2.5.0
- DensePOTRS at Base 2.5.0
- DenseScale at Base 2.5.0
- DestroyArray at Base 2.5.0
- DestroyMat at Base 2.5.0
- IDAAdjFree at Base 2.5.0
- IDAAdjInit at Base 2.5.0
- IDAAdjReInit at Base 2.5.0
- IDAAdjSetNoSensi at Base 2.5.0
- IDABBDPrecGetNumGfnEvals at Base 2.5.0
- IDABBDPrecGetWorkSpace at Base 2.5.0
- IDABBDPrecInit at Base 2.5.0
- IDABBDPrecInitB at Base 2.5.0
- IDABBDPrecReInit at Base 2.5.0
- IDABBDPrecReInitB at Base 2.5.0
- IDABand at Base 2.5.0
- IDABandB at Base 2.5.0
- IDACalcIC at Base 2.5.0
- IDACalcICB at Base 2.5.0
- IDACalcICBS at Base 2.5.0
- IDACreate at Base 2.5.0
- IDACreateB at Base 2.5.0
- IDADense at Base 2.5.0
- IDADenseB at Base 2.5.0
- IDADlsGetLastFlag at Base 2.5.0
- IDADlsGetNumJacEvals at Base 2.5.0
- IDADlsGetNumResEvals at Base 2.5.0
- IDADlsGetReturnFlagName at Base 2.5.0
- IDADlsGetWorkSpace at Base 2.5.0
- IDADlsSetBandJacFn at Base 2.5.0
- IDADlsSetBandJacFnB at Base 2.5.0
- IDADlsSetDenseJacFn at Base 2.5.0
- IDADlsSetDenseJacFnB at Base 2.5.0
- IDAErrHandler at Base 2.5.0
- IDAEwtSet at Base 2.5.0
- IDAFree at Base 2.5.0
- IDAGetActualInitStep at Base 2.5.0
- IDAGetAdjCheckPointsInfo at Base 2.5.0
- IDAGetAdjCurrentCheckPoint at Base 2.5.0
- IDAGetAdjDataPointHermite at Base 2.5.0
- IDAGetAdjDataPointPolynomial at Base 2.5.0
- IDAGetAdjIDABmem at Base 2.5.0
- IDAGetAdjY at Base 2.5.0
- IDAGetB at Base 2.5.0
- IDAGetConsistentIC at Base 2.5.0
- IDAGetConsistentICB at Base 2.5.0
- IDAGetCurrentOrder at Base 2.5.0
- IDAGetCurrentStep at Base 2.5.0
- IDAGetCurrentTime at Base 2.5.0
- IDAGetDky at Base 2.5.0
- IDAGetErrWeights at Base 2.5.0
- IDAGetEstLocalErrors at Base 2.5.0
- IDAGetIntegratorStats at Base 2.5.0
- IDAGetLastOrder at Base 2.5.0
- IDAGetLastStep at Base 2.5.0
- IDAGetNonlinSolvStats at Base 2.5.0
- IDAGetNumBacktrackOps at Base 2.5.0
- IDAGetNumErrTestFails at Base 2.5.0
- IDAGetNumGEvals at Base 2.5.0
- IDAGetNumLinSolvSetups at Base 2.5.0
- IDAGetNumNonlinSolvConvFails at Base 2.5.0
- IDAGetNumNonlinSolvIters at Base 2.5.0
- IDAGetNumResEvals at Base 2.5.0
- IDAGetNumResEvalsSens at Base 2.5.0
- IDAGetNumSteps at Base 2.5.0
- IDAGetQuad at Base 2.5.0
- IDAGetQuadB at Base 2.5.0
- IDAGetQuadDky at Base 2.5.0
- IDAGetQuadErrWeights at Base 2.5.0
- IDAGetQuadNumErrTestFails at Base 2.5.0
- IDAGetQuadNumRhsEvals at Base 2.5.0
- IDAGetQuadSens1 at Base 2.5.0
- IDAGetQuadSens at Base 2.5.0
- IDAGetQuadSensDky1 at Base 2.5.0
- IDAGetQuadSensDky at Base 2.5.0
- IDAGetQuadSensErrWeights at Base 2.5.0
- IDAGetQuadSensNumErrTestFails at Base 2.5.0
- IDAGetQuadSensNumRhsEvals at Base 2.5.0
- IDAGetQuadSensStats at Base 2.5.0
- IDAGetQuadStats at Base 2.5.0
- IDAGetReturnFlagName at Base 2.5.0
- IDAGetRootInfo at Base 2.5.0
- IDAGetSens1 at Base 2.5.0
- IDAGetSens at Base 2.5.0
- IDAGetSensConsistentIC at Base 2.5.0
- IDAGetSensDky1 at Base 2.5.0
- IDAGetSensDky at Base 2.5.0
- IDAGetSensErrWeights at Base 2.5.0
- IDAGetSensNonlinSolvStats at Base 2.5.0
- IDAGetSensNumErrTestFails at Base 2.5.0
- IDAGetSensNumLinSolvSetups at Base 2.5.0
- IDAGetSensNumNonlinSolvConvFails at Base 2.5.0
- IDAGetSensNumNonlinSolvIters at Base 2.5.0
- IDAGetSensNumResEvals at Base 2.5.0
- IDAGetSensStats at Base 2.5.0
- IDAGetSolution at Base 2.5.0
- IDAGetTolScaleFactor at Base 2.5.0
- IDAGetWorkSpace at Base 2.5.0
- IDAInit at Base 2.5.0
- IDAInitB at Base 2.5.0
- IDAInitBS at Base 2.5.0
- IDAInitialSetup at Base 2.5.0
- IDALapackBand at Base 2.5.0
- IDALapackDense at Base 2.5.0
- IDAProcessError at Base 2.5.0
- IDAQuadFree at Base 2.5.0
- IDAQuadInit at Base 2.5.0
- IDAQuadInitB at Base 2.5.0
- IDAQuadInitBS at Base 2.5.0
- IDAQuadReInit at Base 2.5.0
- IDAQuadReInitB at Base 2.5.0
- IDAQuadSStolerances at Base 2.5.0
- IDAQuadSStolerancesB at Base 2.5.0
- IDAQuadSVtolerances at Base 2.5.0
- IDAQuadSVtolerancesB at Base 2.5.0
- IDAQuadSensEEtolerances at Base 2.5.0
- IDAQuadSensEwtSet at Base 2.5.0
- IDAQuadSensFree at Base 2.5.0
- IDAQuadSensInit at Base 2.5.0
- IDAQuadSensReInit at Base 2.5.0
- IDAQuadSensSStolerances at Base 2.5.0
- IDAQuadSensSVtolerances at Base 2.5.0
- IDAReInit at Base 2.5.0
- IDAReInitB at Base 2.5.0
- IDARootInit at Base 2.5.0
- IDASStolerances at Base 2.5.0
- IDASStolerancesB at Base 2.5.0
- IDASVtolerances at Base 2.5.0
- IDASVtolerancesB at Base 2.5.0
- IDASensEEtolerances at Base 2.5.0
- IDASensEwtSet at Base 2.5.0
- IDASensFree at Base 2.5.0
- IDASensInit at Base 2.5.0
- IDASensReInit at Base 2.5.0
- IDASensResDQ at Base 2.5.0
- IDASensSStolerances at Base 2.5.0
- IDASensSVtolerances at Base 2.5.0
- IDASensToggleOff at Base 2.5.0
- IDASensWrmsNorm at Base 2.5.0
- IDASensWrmsNormUpdate at Base 2.5.0
- IDASetConstraints at Base 2.5.0
- IDASetConstraintsB at Base 2.5.0
- IDASetErrFile at Base 2.5.0
- IDASetErrHandlerFn at Base 2.5.0
- IDASetId at Base 2.5.0
- IDASetIdB at Base 2.5.0
- IDASetInitStep at Base 2.5.0
- IDASetInitStepB at Base 2.5.0
- IDASetLineSearchOffIC at Base 2.5.0
- IDASetMaxConvFails at Base 2.5.0
- IDASetMaxErrTestFails at Base 2.5.0
- IDASetMaxNonlinIters at Base 2.5.0
- IDASetMaxNumItersIC at Base 2.5.0
- IDASetMaxNumJacsIC at Base 2.5.0
- IDASetMaxNumSteps at Base 2.5.0
- IDASetMaxNumStepsB at Base 2.5.0
- IDASetMaxNumStepsIC at Base 2.5.0
- IDASetMaxOrd at Base 2.5.0
- IDASetMaxOrdB at Base 2.5.0
- IDASetMaxStep at Base 2.5.0
- IDASetMaxStepB at Base 2.5.0
- IDASetNoInactiveRootWarn at Base 2.5.0
- IDASetNonlinConvCoef at Base 2.5.0
- IDASetNonlinConvCoefIC at Base 2.5.0
- IDASetQuadErrCon at Base 2.5.0
- IDASetQuadErrConB at Base 2.5.0
- IDASetQuadSensErrCon at Base 2.5.0
- IDASetRootDirection at Base 2.5.0
- IDASetSensDQMethod at Base 2.5.0
- IDASetSensErrCon at Base 2.5.0
- IDASetSensMaxNonlinIters at Base 2.5.0
- IDASetSensParams at Base 2.5.0
- IDASetStepToleranceIC at Base 2.5.0
- IDASetStopTime at Base 2.5.0
- IDASetSuppressAlg at Base 2.5.0
- IDASetSuppressAlgB at Base 2.5.0
- IDASetUserData at Base 2.5.0
- IDASetUserDataB at Base 2.5.0
- IDASolve at Base 2.5.0
- IDASolveB at Base 2.5.0
- IDASolveF at Base 2.5.0
- IDASpbcg at Base 2.5.0
- IDASpbcgB at Base 2.5.0
- IDASpgmr at Base 2.5.0
- IDASpgmrB at Base 2.5.0
- IDASpilsAtimes at Base 2.5.0
- IDASpilsDQJtimes at Base 2.5.0
- IDASpilsGetLastFlag at Base 2.5.0
- IDASpilsGetNumConvFails at Base 2.5.0
- IDASpilsGetNumJtimesEvals at Base 2.5.0
- IDASpilsGetNumLinIters at Base 2.5.0
- IDASpilsGetNumPrecEvals at Base 2.5.0
- IDASpilsGetNumPrecSolves at Base 2.5.0
- IDASpilsGetNumResEvals at Base 2.5.0
- IDASpilsGetReturnFlagName at Base 2.5.0
- IDASpilsGetWorkSpace at Base 2.5.0
- IDASpilsPSolve at Base 2.5.0
- IDASpilsSetEpsLin at Base 2.5.0
- IDASpilsSetEpsLinB at Base 2.5.0
- IDASpilsSetGSType at Base 2.5.0
- IDASpilsSetGSTypeB at Base 2.5.0
- IDASpilsSetIncrementFactor at Base 2.5.0
- IDASpilsSetIncrementFactorB at Base 2.5.0
- IDASpilsSetJacTimesVecFn at Base 2.5.0
- IDASpilsSetJacTimesVecFnB at Base 2.5.0
- IDASpilsSetMaxRestarts at Base 2.5.0
- IDASpilsSetMaxRestartsB at Base 2.5.0
- IDASpilsSetMaxl at Base 2.5.0
- IDASpilsSetMaxlB at Base 2.5.0
- IDASpilsSetPreconditioner at Base 2.5.0
- IDASpilsSetPreconditionerB at Base 2.5.0
- IDASptfqmr at Base 2.5.0
- IDASptfqmrB at Base 2.5.0
- IDAWFtolerances at Base 2.5.0
- IDAWrmsNorm at Base 2.5.0
- ModifiedGS at Base 2.5.0
- N_VAbs at Base 2.5.0
- N_VAddConst at Base 2.5.0
- N_VClone at Base 2.5.0
- N_VCloneEmpty at Base 2.5.0
- N_VCloneEmptyVectorArray at Base 2.5.0
- N_VCloneVectorArray at Base 2.5.0
- N_VCompare at Base 2.5.0
- N_VConst at Base 2.5.0
- N_VConstrMask at Base 2.5.0
- N_VDestroy at Base 2.5.0
- N_VDestroyVectorArray at Base 2.5.0
- N_VDiv at Base 2.5.0
- N_VDotProd at Base 2.5.0
- N_VGetArrayPointer at Base 2.5.0
- N_VInv at Base 2.5.0
- N_VInvTest at Base 2.5.0
- N_VL1Norm at Base 2.5.0
- N_VLinearSum at Base 2.5.0
- N_VMaxNorm at Base 2.5.0
- N_VMin at Base 2.5.0
- N_VMinQuotient at Base 2.5.0
- N_VProd at Base 2.5.0
- N_VScale at Base 2.5.0
- N_VSetArrayPointer at Base 2.5.0
- N_VSpace at Base 2.5.0
- N_VWL2Norm at Base 2.5.0
- N_VWrmsNorm at Base 2.5.0
- N_VWrmsNormMask at Base 2.5.0
- NewBandMat at Base 2.5.0
- NewDenseMat at Base 2.5.0
- NewIntArray at Base 2.5.0
- NewLintArray at Base 2.5.0
- NewRealArray at Base 2.5.0
- PrintMat at Base 2.5.0
- QRfact at Base 2.5.0
- QRsol at Base 2.5.0
- RAbs at Base 2.5.0
- RExp at Base 2.5.0
- RPowerI at Base 2.5.0
- RPowerR at Base 2.5.0
- RSqrt at Base 2.5.0
- SetToZero at Base 2.5.0
- SpbcgFree at Base 2.5.0
- SpbcgMalloc at Base 2.5.0
- SpbcgSolve at Base 2.5.0
- SpgmrFree at Base 2.5.0
- SpgmrMalloc at Base 2.5.0
- SpgmrSolve at Base 2.5.0
- SptfqmrFree at Base 2.5.0
- SptfqmrMalloc at Base 2.5.0
- SptfqmrSolve at Base 2.5.0
- bandAddIdentity at Base 2.5.0
- bandCopy at Base 2.5.0
- bandGBTRF at Base 2.5.0
- bandGBTRS at Base 2.5.0
- bandScale at Base 2.5.0
- denseAddIdentity at Base 2.5.0
- denseCopy at Base 2.5.0
- denseGEQRF at Base 2.5.0
- denseGETRF at Base 2.5.0
- denseGETRS at Base 2.5.0
- denseORMQR at Base 2.5.0
- densePOTRF at Base 2.5.0
- densePOTRS at Base 2.5.0
- denseScale at Base 2.5.0
- destroyArray at Base 2.5.0
- destroyMat at Base 2.5.0
- idaDlsBandDQJac at Base 2.5.0
- idaDlsDenseDQJac at Base 2.5.0
- newBandMat at Base 2.5.0
- newDenseMat at Base 2.5.0
- newIntArray at Base 2.5.0
- newLintArray at Base 2.5.0
- newRealArray at Base 2.5.0
diff --git a/debian/libsundials-kinsol1.install b/debian/libsundials-kinsol1.install
deleted file mode 100644
index 4c515ed..0000000
--- a/debian/libsundials-kinsol1.install
+++ /dev/null
@@ -1 +0,0 @@
-usr/lib/libsundials_kinsol.so.*
diff --git a/debian/libsundials-kinsol1.symbols b/debian/libsundials-kinsol1.symbols
deleted file mode 100644
index 404e00f..0000000
--- a/debian/libsundials-kinsol1.symbols
+++ /dev/null
@@ -1,164 +0,0 @@
-libsundials_kinsol.so.1 libsundials-kinsol1 #MINVER#
- AddIdentity at Base 2.5.0
- BandCopy at Base 2.5.0
- BandGBTRF at Base 2.5.0
- BandGBTRS at Base 2.5.0
- BandScale at Base 2.5.0
- ClassicalGS at Base 2.5.0
- DenseCopy at Base 2.5.0
- DenseGEQRF at Base 2.5.0
- DenseGETRF at Base 2.5.0
- DenseGETRS at Base 2.5.0
- DenseORMQR at Base 2.5.0
- DensePOTRF at Base 2.5.0
- DensePOTRS at Base 2.5.0
- DenseScale at Base 2.5.0
- DestroyArray at Base 2.5.0
- DestroyMat at Base 2.5.0
- KINBBDPrecGetNumGfnEvals at Base 2.5.0
- KINBBDPrecGetWorkSpace at Base 2.5.0
- KINBBDPrecInit at Base 2.5.0
- KINBand at Base 2.5.0
- KINCreate at Base 2.5.0
- KINDense at Base 2.5.0
- KINDlsGetLastFlag at Base 2.5.0
- KINDlsGetNumFuncEvals at Base 2.5.0
- KINDlsGetNumJacEvals at Base 2.5.0
- KINDlsGetReturnFlagName at Base 2.5.0
- KINDlsGetWorkSpace at Base 2.5.0
- KINDlsSetBandJacFn at Base 2.5.0
- KINDlsSetDenseJacFn at Base 2.5.0
- KINErrHandler at Base 2.5.0
- KINFree at Base 2.5.0
- KINGetFuncNorm at Base 2.5.0
- KINGetNumBacktrackOps at Base 2.5.0
- KINGetNumBetaCondFails at Base 2.5.0
- KINGetNumFuncEvals at Base 2.5.0
- KINGetNumNonlinSolvIters at Base 2.5.0
- KINGetReturnFlagName at Base 2.5.0
- KINGetStepLength at Base 2.5.0
- KINGetWorkSpace at Base 2.5.0
- KINInfoHandler at Base 2.5.0
- KINInit at Base 2.5.0
- KINLapackBand at Base 2.5.0
- KINLapackDense at Base 2.5.0
- KINPrintInfo at Base 2.5.0
- KINProcessError at Base 2.5.0
- KINSetConstraints at Base 2.5.0
- KINSetErrFile at Base 2.5.0
- KINSetErrHandlerFn at Base 2.5.0
- KINSetEtaConstValue at Base 2.5.0
- KINSetEtaForm at Base 2.5.0
- KINSetEtaParams at Base 2.5.0
- KINSetFuncNormTol at Base 2.5.0
- KINSetInfoFile at Base 2.5.0
- KINSetInfoHandlerFn at Base 2.5.0
- KINSetMaxBetaFails at Base 2.5.0
- KINSetMaxNewtonStep at Base 2.5.0
- KINSetMaxSetupCalls at Base 2.5.0
- KINSetMaxSubSetupCalls at Base 2.5.0
- KINSetNoInitSetup at Base 2.5.0
- KINSetNoMinEps at Base 2.5.0
- KINSetNoResMon at Base 2.5.0
- KINSetNumMaxIters at Base 2.5.0
- KINSetPrintLevel at Base 2.5.0
- KINSetRelErrFunc at Base 2.5.0
- KINSetResMonConstValue at Base 2.5.0
- KINSetResMonParams at Base 2.5.0
- KINSetScaledStepTol at Base 2.5.0
- KINSetSysFunc at Base 2.5.0
- KINSetUserData at Base 2.5.0
- KINSol at Base 2.5.0
- KINSpbcg at Base 2.5.0
- KINSpgmr at Base 2.5.0
- KINSpilsAtimes at Base 2.5.0
- KINSpilsDQJtimes at Base 2.5.0
- KINSpilsGetLastFlag at Base 2.5.0
- KINSpilsGetNumConvFails at Base 2.5.0
- KINSpilsGetNumFuncEvals at Base 2.5.0
- KINSpilsGetNumJtimesEvals at Base 2.5.0
- KINSpilsGetNumLinIters at Base 2.5.0
- KINSpilsGetNumPrecEvals at Base 2.5.0
- KINSpilsGetNumPrecSolves at Base 2.5.0
- KINSpilsGetReturnFlagName at Base 2.5.0
- KINSpilsGetWorkSpace at Base 2.5.0
- KINSpilsPSolve at Base 2.5.0
- KINSpilsSetJacTimesVecFn at Base 2.5.0
- KINSpilsSetMaxRestarts at Base 2.5.0
- KINSpilsSetPreconditioner at Base 2.5.0
- KINSptfqmr at Base 2.5.0
- ModifiedGS at Base 2.5.0
- N_VAbs at Base 2.5.0
- N_VAddConst at Base 2.5.0
- N_VClone at Base 2.5.0
- N_VCloneEmpty at Base 2.5.0
- N_VCloneEmptyVectorArray at Base 2.5.0
- N_VCloneVectorArray at Base 2.5.0
- N_VCompare at Base 2.5.0
- N_VConst at Base 2.5.0
- N_VConstrMask at Base 2.5.0
- N_VDestroy at Base 2.5.0
- N_VDestroyVectorArray at Base 2.5.0
- N_VDiv at Base 2.5.0
- N_VDotProd at Base 2.5.0
- N_VGetArrayPointer at Base 2.5.0
- N_VInv at Base 2.5.0
- N_VInvTest at Base 2.5.0
- N_VL1Norm at Base 2.5.0
- N_VLinearSum at Base 2.5.0
- N_VMaxNorm at Base 2.5.0
- N_VMin at Base 2.5.0
- N_VMinQuotient at Base 2.5.0
- N_VProd at Base 2.5.0
- N_VScale at Base 2.5.0
- N_VSetArrayPointer at Base 2.5.0
- N_VSpace at Base 2.5.0
- N_VWL2Norm at Base 2.5.0
- N_VWrmsNorm at Base 2.5.0
- N_VWrmsNormMask at Base 2.5.0
- NewBandMat at Base 2.5.0
- NewDenseMat at Base 2.5.0
- NewIntArray at Base 2.5.0
- NewLintArray at Base 2.5.0
- NewRealArray at Base 2.5.0
- PrintMat at Base 2.5.0
- QRfact at Base 2.5.0
- QRsol at Base 2.5.0
- RAbs at Base 2.5.0
- RExp at Base 2.5.0
- RPowerI at Base 2.5.0
- RPowerR at Base 2.5.0
- RSqrt at Base 2.5.0
- SetToZero at Base 2.5.0
- SpbcgFree at Base 2.5.0
- SpbcgMalloc at Base 2.5.0
- SpbcgSolve at Base 2.5.0
- SpgmrFree at Base 2.5.0
- SpgmrMalloc at Base 2.5.0
- SpgmrSolve at Base 2.5.0
- SptfqmrFree at Base 2.5.0
- SptfqmrMalloc at Base 2.5.0
- SptfqmrSolve at Base 2.5.0
- bandAddIdentity at Base 2.5.0
- bandCopy at Base 2.5.0
- bandGBTRF at Base 2.5.0
- bandGBTRS at Base 2.5.0
- bandScale at Base 2.5.0
- denseAddIdentity at Base 2.5.0
- denseCopy at Base 2.5.0
- denseGEQRF at Base 2.5.0
- denseGETRF at Base 2.5.0
- denseGETRS at Base 2.5.0
- denseORMQR at Base 2.5.0
- densePOTRF at Base 2.5.0
- densePOTRS at Base 2.5.0
- denseScale at Base 2.5.0
- destroyArray at Base 2.5.0
- destroyMat at Base 2.5.0
- kinDlsBandDQJac at Base 2.5.0
- kinDlsDenseDQJac at Base 2.5.0
- newBandMat at Base 2.5.0
- newDenseMat at Base 2.5.0
- newIntArray at Base 2.5.0
- newLintArray at Base 2.5.0
- newRealArray at Base 2.5.0
diff --git a/debian/libsundials-nvecparallel-dev.install b/debian/libsundials-nvecparallel-dev.install
deleted file mode 100644
index 2dcc27a..0000000
--- a/debian/libsundials-nvecparallel-dev.install
+++ /dev/null
@@ -1,6 +0,0 @@
-usr/lib/libsundials_nvecparallel.a
-usr/lib/libsundials_fnvecparallel.a
-usr/lib/libsundials_nvecparallel.so
-usr/lib/libsundials_fnvecparallel.so
-
-usr/include/nvector/nvector_parallel.h
diff --git a/debian/libsundials-nvecparallel0.install b/debian/libsundials-nvecparallel0.install
deleted file mode 100644
index 93e2da7..0000000
--- a/debian/libsundials-nvecparallel0.install
+++ /dev/null
@@ -1,2 +0,0 @@
-usr/lib/libsundials_nvecparallel.so.*
-usr/lib/libsundials_fnvecparallel.so.*
diff --git a/debian/libsundials-nvecparallel0.symbols b/debian/libsundials-nvecparallel0.symbols
deleted file mode 100644
index 698af24..0000000
--- a/debian/libsundials-nvecparallel0.symbols
+++ /dev/null
@@ -1,55 +0,0 @@
-libsundials_nvecparallel.so.0 libsundials-nvecparallel0 #MINVER#
- N_VAbs_Parallel at Base 2.5.0
- N_VAddConst_Parallel at Base 2.5.0
- N_VCloneEmpty_Parallel at Base 2.5.0
- N_VCloneVectorArrayEmpty_Parallel at Base 2.5.0
- N_VCloneVectorArray_Parallel at Base 2.5.0
- N_VClone_Parallel at Base 2.5.0
- N_VCompare_Parallel at Base 2.5.0
- N_VConst_Parallel at Base 2.5.0
- N_VConstrMask_Parallel at Base 2.5.0
- N_VDestroyVectorArray_Parallel at Base 2.5.0
- N_VDestroy_Parallel at Base 2.5.0
- N_VDiv_Parallel at Base 2.5.0
- N_VDotProd_Parallel at Base 2.5.0
- N_VGetArrayPointer_Parallel at Base 2.5.0
- N_VInvTest_Parallel at Base 2.5.0
- N_VInv_Parallel at Base 2.5.0
- N_VL1Norm_Parallel at Base 2.5.0
- N_VLinearSum_Parallel at Base 2.5.0
- N_VMake_Parallel at Base 2.5.0
- N_VMaxNorm_Parallel at Base 2.5.0
- N_VMinQuotient_Parallel at Base 2.5.0
- N_VMin_Parallel at Base 2.5.0
- N_VNewEmpty_Parallel at Base 2.5.0
- N_VNew_Parallel at Base 2.5.0
- N_VPrint_Parallel at Base 2.5.0
- N_VProd_Parallel at Base 2.5.0
- N_VScale_Parallel at Base 2.5.0
- N_VSetArrayPointer_Parallel at Base 2.5.0
- N_VSpace_Parallel at Base 2.5.0
- N_VWL2Norm_Parallel at Base 2.5.0
- N_VWrmsNormMask_Parallel at Base 2.5.0
- N_VWrmsNorm_Parallel at Base 2.5.0
- RAbs at Base 2.5.0
- RExp at Base 2.5.0
- RPowerI at Base 2.5.0
- RPowerR at Base 2.5.0
- RSqrt at Base 2.5.0
-libsundials_fnvecparallel.so.0 libsundials-nvecparallel0 #MINVER#
- F2C_CVODE_vec at Base 2.5.0
- F2C_CVODE_vecB at Base 2.5.0
- F2C_CVODE_vecQ at Base 2.5.0
- F2C_CVODE_vecQB at Base 2.5.0
- F2C_CVODE_vecS at Base 2.5.0
- F2C_IDA_vec at Base 2.5.0
- F2C_IDA_vecB at Base 2.5.0
- F2C_IDA_vecQ at Base 2.5.0
- F2C_IDA_vecQB at Base 2.5.0
- F2C_IDA_vecS at Base 2.5.0
- F2C_KINSOL_vec at Base 2.5.0
- fnvinitp_ at Base 2.5.0
- fnvinitp_b_ at Base 2.5.0
- fnvinitp_q_ at Base 2.5.0
- fnvinitp_qb_ at Base 2.5.0
- fnvinitp_s_ at Base 2.5.0
diff --git a/debian/libsundials-nvecserial0.install b/debian/libsundials-nvecserial0.install
deleted file mode 100644
index f6ef1af..0000000
--- a/debian/libsundials-nvecserial0.install
+++ /dev/null
@@ -1,2 +0,0 @@
-usr/lib/libsundials_nvecserial.so.*
-usr/lib/libsundials_fnvecserial.so.*
diff --git a/debian/libsundials-nvecserial0.symbols b/debian/libsundials-nvecserial0.symbols
deleted file mode 100644
index bee6165..0000000
--- a/debian/libsundials-nvecserial0.symbols
+++ /dev/null
@@ -1,55 +0,0 @@
-libsundials_nvecserial.so.0 libsundials-nvecserial0 #MINVER#
- N_VAbs_Serial at Base 2.5.0
- N_VAddConst_Serial at Base 2.5.0
- N_VCloneEmpty_Serial at Base 2.5.0
- N_VCloneVectorArrayEmpty_Serial at Base 2.5.0
- N_VCloneVectorArray_Serial at Base 2.5.0
- N_VClone_Serial at Base 2.5.0
- N_VCompare_Serial at Base 2.5.0
- N_VConst_Serial at Base 2.5.0
- N_VConstrMask_Serial at Base 2.5.0
- N_VDestroyVectorArray_Serial at Base 2.5.0
- N_VDestroy_Serial at Base 2.5.0
- N_VDiv_Serial at Base 2.5.0
- N_VDotProd_Serial at Base 2.5.0
- N_VGetArrayPointer_Serial at Base 2.5.0
- N_VInvTest_Serial at Base 2.5.0
- N_VInv_Serial at Base 2.5.0
- N_VL1Norm_Serial at Base 2.5.0
- N_VLinearSum_Serial at Base 2.5.0
- N_VMake_Serial at Base 2.5.0
- N_VMaxNorm_Serial at Base 2.5.0
- N_VMinQuotient_Serial at Base 2.5.0
- N_VMin_Serial at Base 2.5.0
- N_VNewEmpty_Serial at Base 2.5.0
- N_VNew_Serial at Base 2.5.0
- N_VPrint_Serial at Base 2.5.0
- N_VProd_Serial at Base 2.5.0
- N_VScale_Serial at Base 2.5.0
- N_VSetArrayPointer_Serial at Base 2.5.0
- N_VSpace_Serial at Base 2.5.0
- N_VWL2Norm_Serial at Base 2.5.0
- N_VWrmsNormMask_Serial at Base 2.5.0
- N_VWrmsNorm_Serial at Base 2.5.0
- RAbs at Base 2.5.0
- RExp at Base 2.5.0
- RPowerI at Base 2.5.0
- RPowerR at Base 2.5.0
- RSqrt at Base 2.5.0
-libsundials_fnvecserial.so.0 libsundials-nvecserial0 #MINVER#
- F2C_CVODE_vec at Base 2.5.0
- F2C_CVODE_vecB at Base 2.5.0
- F2C_CVODE_vecQ at Base 2.5.0
- F2C_CVODE_vecQB at Base 2.5.0
- F2C_CVODE_vecS at Base 2.5.0
- F2C_IDA_vec at Base 2.5.0
- F2C_IDA_vecB at Base 2.5.0
- F2C_IDA_vecQ at Base 2.5.0
- F2C_IDA_vecQB at Base 2.5.0
- F2C_IDA_vecS at Base 2.5.0
- F2C_KINSOL_vec at Base 2.5.0
- fnvinits_ at Base 2.5.0
- fnvinits_b_ at Base 2.5.0
- fnvinits_q_ at Base 2.5.0
- fnvinits_qb_ at Base 2.5.0
- fnvinits_s_ at Base 2.5.0
diff --git a/debian/libsundials-parallel.lintian-overrides b/debian/libsundials-parallel.lintian-overrides
deleted file mode 100644
index b4e8118..0000000
--- a/debian/libsundials-parallel.lintian-overrides
+++ /dev/null
@@ -1,2 +0,0 @@
-# This package will install all serial libraries
-libsundials-parallel: empty-binary-package
diff --git a/debian/libsundials-serial-dev.install b/debian/libsundials-serial-dev.install
deleted file mode 100644
index 9aa026c..0000000
--- a/debian/libsundials-serial-dev.install
+++ /dev/null
@@ -1,21 +0,0 @@
-usr/lib/libsundials_cvode*.a
-usr/lib/libsundials_cvode*.so
-usr/lib/libsundials_ida*.a
-usr/lib/libsundials_ida*.so
-usr/lib/libsundials_kinsol.a
-usr/lib/libsundials_*serial.a
-usr/lib/libsundials_*serial.so
-
-usr/lib/libsundials_kinsol.so
-
-usr/include/cvode
-usr/include/cvodes
-usr/include/ida
-usr/include/idas
-usr/include/kinsol
-usr/include/nvector/nvector_serial.h
-usr/include/sundials
-
-bin/sundials-config usr/bin
-
-debian/sundials-config.1 usr/share/man/man1
diff --git a/debian/libsundials-serial-doc.docs b/debian/libsundials-serial-doc.docs
deleted file mode 100644
index bb06dd9..0000000
--- a/debian/libsundials-serial-doc.docs
+++ /dev/null
@@ -1,11 +0,0 @@
-./doc/ida/ida_guide.pdf
-./doc/ida/ida_examples.pdf
-./doc/cvodes/cvs_guide.pdf
-./doc/cvodes/cvs_examples.pdf
-./doc/sundialsTB/sundialsTB.pdf
-./doc/idas/idas_examples.pdf
-./doc/idas/idas_guide.pdf
-./doc/kinsol/kin_examples.pdf
-./doc/kinsol/kin_guide.pdf
-./doc/cvode/cv_guide.pdf
-./doc/cvode/cv_examples.pdf
diff --git a/debian/libsundials-serial.lintian-overrides b/debian/libsundials-serial.lintian-overrides
deleted file mode 100644
index e8157b7..0000000
--- a/debian/libsundials-serial.lintian-overrides
+++ /dev/null
@@ -1,2 +0,0 @@
-# This package will install all serial libraries
-libsundials-serial: empty-binary-package
diff --git a/debian/octave-sundials.install b/debian/octave-sundials.install
deleted file mode 100644
index 1c79c6a..0000000
--- a/debian/octave-sundials.install
+++ /dev/null
@@ -1,2 +0,0 @@
-usr/share/octave/
-usr/lib/*/octave/
diff --git a/debian/orig-tar.exclude b/debian/orig-tar.exclude
deleted file mode 100644
index bd98a73..0000000
--- a/debian/orig-tar.exclude
+++ /dev/null
@@ -1,2 +0,0 @@
-*.pdf
-
diff --git a/debian/orig-tarball.sh b/debian/orig-tarball.sh
deleted file mode 100644
index c71e5fa..0000000
--- a/debian/orig-tarball.sh
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/sh -e
-
-# called by uscan with '--upstream-version' <version> <file>
-PKG=sundials
-VER=$2
-echo "plop :" $3
-tar zxvf $3
-tar -c -z -f $3 -X debian/orig-tar.exclude $PKG-$VER
-rm -rf $PKG-$VER
-# move to directory 'tarballs'
-if [ -r .svn/deb-layout ]; then
- . .svn/deb-layout
- mv $TAR $origDir
- echo "moved $TAR to $origDir"
-fi
-
-exit 0
diff --git a/debian/patches/bashim.diff b/debian/patches/bashim.diff
deleted file mode 100644
index 3b3e1ad..0000000
--- a/debian/patches/bashim.diff
+++ /dev/null
@@ -1,19 +0,0 @@
-Index: sundials-2.3.0/config/sundials-config.in
-===================================================================
---- sundials-2.3.0.orig/config/sundials-config.in 2010-03-30 23:15:34.000000000 +0200
-+++ sundials-2.3.0/config/sundials-config.in 2010-03-30 23:17:00.000000000 +0200
-@@ -50,10 +50,10 @@
- shift $(( $OPTIND - 1 ))
-
- # args check
--[[ $module ]] || { echo >&2 the -m option and argument must be specified; exit 1; }
--[[ $vector ]] || { echo >&2 the -t option and argument must be specified; exit 1; }
--[[ $lang ]] || { echo >&2 the -l option and argument must be specified; exit 1; }
--[[ $show ]] || { show=both; }
-+[ $module ] || { echo >&2 the -m option and argument must be specified; exit 1; }
-+[ $vector ] || { echo >&2 the -t option and argument must be specified; exit 1; }
-+[ $lang ] || { echo >&2 the -l option and argument must be specified; exit 1; }
-+[ $show ] || { show=both; }
-
- # main
-
diff --git a/debian/patches/cmake.patch b/debian/patches/cmake.patch
deleted file mode 100644
index 949cb06..0000000
--- a/debian/patches/cmake.patch
+++ /dev/null
@@ -1,111 +0,0 @@
-Index: sundials-2.5.0/CMakeLists.txt
-===================================================================
---- sundials-2.5.0.orig/CMakeLists.txt 2012-07-09 16:10:55.000000000 +0200
-+++ sundials-2.5.0/CMakeLists.txt 2012-07-09 16:14:25.000000000 +0200
-@@ -18,7 +18,7 @@
-
- # Require a fairly recent cmake version
-
--CMAKE_MINIMUM_REQUIRED(VERSION 2.2)
-+CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
-
- # Project SUNDIALS (initially only C supported)
-
-@@ -28,9 +28,9 @@
-
- SET(PACKAGE_BUGREPORT "radu at llnl.gov")
- SET(PACKAGE_NAME "SUNDIALS")
--SET(PACKAGE_STRING "SUNDIALS 2.4.0")
-+SET(PACKAGE_STRING "SUNDIALS 2.5.0")
- SET(PACKAGE_TARNAME "sundials")
--SET(PACKAGE_VERSION "2.4.0")
-+SET(PACKAGE_VERSION "2.5.0")
-
- # Prohibit in-source build
-
-@@ -229,6 +229,7 @@
-
- IF(UNIX)
- OPTION(USE_GENERIC_MATH "Use generic (std-c) math libraries" ON)
-+ MESSAGE(STATUS "Use generic (std-c) math libraries")
- IF(USE_GENERIC_MATH)
- # executables will be linked against -lm
- SET(EXTRA_LINK_LIBS -lm)
-Index: sundials-2.5.0/config/SundialsLapack.cmake
-===================================================================
---- sundials-2.5.0.orig/config/SundialsLapack.cmake 2012-07-09 16:10:55.000000000 +0200
-+++ sundials-2.5.0/config/SundialsLapack.cmake 2012-07-09 16:14:55.000000000 +0200
-@@ -31,9 +31,9 @@
- endif(NOT LAPACK_LIBRARIES)
- # If using a GNU C compiler, it is quite likely we'll want LAPACK_LINKER_FLAGS
- # to include -lg2c (if not already present)
--if(CMAKE_COMPILER_IS_GNUCC AND NOT LAPACK_LINKER_FLAGS MATCHES "g2c")
-- set(LAPACK_LINKER_FLAGS "${LAPACK_LINKER_FLAGS} -lg2c")
--endif(CMAKE_COMPILER_IS_GNUCC AND NOT LAPACK_LINKER_FLAGS MATCHES "g2c")
-+if(CMAKE_COMPILER_IS_GNUCC AND NOT LAPACK_LINKER_FLAGS MATCHES "gfortran")
-+ set(LAPACK_LINKER_FLAGS "${LAPACK_LINKER_FLAGS} -lgfortran")
-+endif(CMAKE_COMPILER_IS_GNUCC AND NOT LAPACK_LINKER_FLAGS MATCHES "gfortran")
- # If we have the LAPACK libraries, test them
- if(LAPACK_LIBRARIES)
- message(STATUS "Looking for LAPACK libraries... OK")
-@@ -69,7 +69,9 @@
- "}\n")
- # Attempt to link the "ltest" executable
- try_compile(LTEST_OK ${LapackTest_DIR} ${LapackTest_DIR}
-- ltest OUTPUT_VARIABLE MY_OUTPUT)
-+ ltest
-+ LINK_LIBRARIES ${LAPACK_LIBRARIES}
-+ 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)
-Index: sundials-2.5.0/config/SundialsFortran.cmake
-===================================================================
---- sundials-2.5.0.orig/config/SundialsFortran.cmake 2012-07-09 16:10:55.000000000 +0200
-+++ sundials-2.5.0/config/SundialsFortran.cmake 2012-07-09 16:14:25.000000000 +0200
-@@ -52,6 +52,7 @@
- # and an executable "ftest"
- file(WRITE ${FortranTest_DIR}/CMakeLists.txt
- "PROJECT(ftest Fortran)\n"
-+ "CMAKE_MINIMUM_REQUIRED(VERSION 2.8)\n"
- "SET(CMAKE_VERBOSE_MAKEFILE ON)\n"
- "SET(CMAKE_BUILD_TYPE \"${CMAKE_BUILD_TYPE}\")\n"
- "SET(CMAKE_Fortran_FLAGS \"${CMAKE_Fortran_FLAGS}\")\n"
-@@ -90,6 +91,7 @@
- # Overwrite CMakeLists.txt with one which will generate the "ctest1" executable
- file(WRITE ${FortranTest_DIR}/CMakeLists.txt
- "PROJECT(ctest1 C)\n"
-+ "CMAKE_MINIMUM_REQUIRED(VERSION 2.8)\n"
- "SET(CMAKE_VERBOSE_MAKEFILE ON)\n"
- "SET(CMAKE_BUILD_TYPE \"${CMAKE_BUILD_TYPE}\")\n"
- "SET(CMAKE_C_FLAGS \"${CMAKE_C_FLAGS}\")\n"
-@@ -134,6 +136,7 @@
- # Practically a duplicate of the previous steps.
- file(WRITE ${FortranTest_DIR}/CMakeLists.txt
- "PROJECT(ctest2 C)\n"
-+ "CMAKE_MINIMUM_REQUIRED(VERSION 2.8)\n"
- "SET(CMAKE_VERBOSE_MAKEFILE ON)\n"
- "SET(CMAKE_BUILD_TYPE \"${CMAKE_BUILD_TYPE}\")\n"
- "SET(CMAKE_C_FLAGS \"${CMAKE_C_FLAGS}\")\n"
-Index: sundials-2.5.0/config/FindLAPACK.cmake
-===================================================================
---- sundials-2.5.0.orig/config/FindLAPACK.cmake 2012-07-09 16:10:55.000000000 +0200
-+++ sundials-2.5.0/config/FindLAPACK.cmake 2012-07-09 16:14:25.000000000 +0200
-@@ -30,7 +30,7 @@
- check_fortran_function_exists(cheev LAPACK_BLAS_WORKS)
- mark_as_advanced(LAPACK_BLAS_WORKS)
- if(LAPACK_BLAS_WORKS)
-- set(LAPACK_FOUND TRUE)
-+ #???set(LAPACK_FOUND TRUE)
- set(LAPACK_LIBRARIES ${BLAS_LIBRARIES})
- endif(LAPACK_BLAS_WORKS)
- # Generic LAPACK library?
-@@ -81,7 +81,7 @@
-
- if(NOT LAPACK_FIND_QUIETLY)
- if(LAPACK_FOUND)
-- message(STATUS "A library with LAPACK API found.")
-+ message(STATUS "A library with LAPACK API found ${LAPACK_LIBRARIES}")
- else(LAPACK_FOUND)
- if(LAPACK_FIND_REQUIRED)
- message(FATAL_ERROR
diff --git a/debian/patches/fix-format-error.patch b/debian/patches/fix-format-error.patch
deleted file mode 100644
index 313e326..0000000
--- a/debian/patches/fix-format-error.patch
+++ /dev/null
@@ -1,65 +0,0 @@
-Index: sundials-2.4.0/src/cvode/cvode.c
-===================================================================
---- sundials-2.4.0.orig/src/cvode/cvode.c 2009-05-10 00:22:28.000000000 +0000
-+++ sundials-2.4.0/src/cvode/cvode.c 2011-11-12 13:23:18.000000000 +0000
-@@ -4128,7 +4128,7 @@
-
- #ifndef NO_FPRINTF_OUTPUT
- fprintf(stderr, "\n[%s ERROR] %s\n ", module, fname);
-- fprintf(stderr, msgfmt);
-+ vfprintf(stderr, msgfmt, ap);
- fprintf(stderr, "\n\n");
- #endif
-
-Index: sundials-2.4.0/src/cvodes/cvodes.c
-===================================================================
---- sundials-2.4.0.orig/src/cvodes/cvodes.c 2009-05-10 00:22:35.000000000 +0000
-+++ sundials-2.4.0/src/cvodes/cvodes.c 2011-11-12 13:26:19.000000000 +0000
-@@ -8942,7 +8942,7 @@
-
- #ifndef NO_FPRINTF_OUTPUT
- fprintf(stderr, "\n[%s ERROR] %s\n ", module, fname);
-- fprintf(stderr, msg);
-+ fprintf(stderr, "%s",msg);
- fprintf(stderr, "\n\n");
- #endif
-
-Index: sundials-2.4.0/src/ida/ida.c
-===================================================================
---- sundials-2.4.0.orig/src/ida/ida.c 2009-05-10 00:22:51.000000000 +0000
-+++ sundials-2.4.0/src/ida/ida.c 2011-11-12 13:28:56.000000000 +0000
-@@ -3248,7 +3248,7 @@
-
- #ifndef NO_FPRINTF_OUTPUT
- fprintf(stderr, "\n[%s ERROR] %s\n ", module, fname);
-- fprintf(stderr, msgfmt);
-+ vfprintf(stderr, msgfmt,ap);
- fprintf(stderr, "\n\n");
- #endif
-
-Index: sundials-2.4.0/src/idas/idas.c
-===================================================================
---- sundials-2.4.0.orig/src/idas/idas.c 2009-05-10 00:22:58.000000000 +0000
-+++ sundials-2.4.0/src/idas/idas.c 2011-11-12 13:30:16.000000000 +0000
-@@ -7170,7 +7170,7 @@
-
- #ifndef NO_FPRINTF_OUTPUT
- fprintf(stderr, "\n[%s ERROR] %s\n ", module, fname);
-- fprintf(stderr, msgfmt);
-+ vfprintf(stderr, msgfmt,ap);
- fprintf(stderr, "\n\n");
- #endif
-
-Index: sundials-2.4.0/src/kinsol/kinsol.c
-===================================================================
---- sundials-2.4.0.orig/src/kinsol/kinsol.c 2009-05-10 00:23:08.000000000 +0000
-+++ sundials-2.4.0/src/kinsol/kinsol.c 2011-11-12 13:31:25.000000000 +0000
-@@ -1864,7 +1864,7 @@
-
- #ifndef NO_FPRINTF_OUTPUT
- fprintf(stderr, "\n[%s ERROR] %s\n ", module, fname);
-- fprintf(stderr, msgfmt);
-+ vfprintf(stderr, msgfmt,ap);
- fprintf(stderr, "\n\n");
- #endif
-
diff --git a/debian/patches/link-blas-lapack.patch b/debian/patches/link-blas-lapack.patch
deleted file mode 100644
index 8b7bc53..0000000
--- a/debian/patches/link-blas-lapack.patch
+++ /dev/null
@@ -1,104 +0,0 @@
-Description: Ensure that libraries are linked against BLAS and LAPACK when needed
- In particular, this ensures that the shared libraries packages have correct
- dependencies.
-Author: Sébastien Villemot <sebastien at debian.org>
-Bug-Debian: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=700525
-Forwarded: no
-Last-Update: 2013-02-27
----
-This patch header follows DEP-3: http://dep.debian.net/deps/dep3/
---- a/src/cvode/Makefile.in
-+++ b/src/cvode/Makefile.in
-@@ -42,6 +42,7 @@
- LIBS = @LIBS@
-
- LAPACK_ENABLED = @LAPACK_ENABLED@
-+BLAS_LAPACK_LIBS = @BLAS_LAPACK_LIBS@
-
- top_srcdir = $(srcdir)/../..
-
-@@ -88,7 +89,7 @@
- $(LIBTOOL) --mode=link $(CC) $(CFLAGS) -o $(CVODE_LIB) $(CVODE_LIB_FILES) $(SHARED_LIB_FILES) -rpath $(libdir) $(LDFLAGS) $(LIBS) -version-info $(LIB_REVISION)
-
- lib_with_bl: shared $(CVODE_LIB_FILES) $(CVODE_BL_LIB_FILES)
-- $(LIBTOOL) --mode=link $(CC) $(CFLAGS) -o $(CVODE_LIB) $(CVODE_LIB_FILES) $(CVODE_BL_LIB_FILES) $(SHARED_LIB_FILES) -rpath $(libdir) $(LDFLAGS) $(LIBS) -version-info $(LIB_REVISION)
-+ $(LIBTOOL) --mode=link $(CC) $(CFLAGS) -o $(CVODE_LIB) $(CVODE_LIB_FILES) $(CVODE_BL_LIB_FILES) $(SHARED_LIB_FILES) -rpath $(libdir) $(LDFLAGS) $(LIBS) $(BLAS_LAPACK_LIBS) -version-info $(LIB_REVISION)
-
- install: $(CVODE_LIB)
- $(mkinstalldirs) $(includedir)/cvode
---- a/src/cvodes/Makefile.in
-+++ b/src/cvodes/Makefile.in
-@@ -42,6 +42,7 @@
- LIBS = @LIBS@
-
- LAPACK_ENABLED = @LAPACK_ENABLED@
-+BLAS_LAPACK_LIBS = @BLAS_LAPACK_LIBS@
-
- top_srcdir = $(srcdir)/../..
-
-@@ -88,7 +89,7 @@
- $(LIBTOOL) --mode=link $(CC) $(CFLAGS) -o $(CVODES_LIB) $(CVODES_LIB_FILES) $(SHARED_LIB_FILES) -rpath $(libdir) $(LDFLAGS) $(LIBS) -version-info $(LIB_REVISION)
-
- lib_with_bl: shared $(CVODES_LIB_FILES) $(CVODES_BL_LIB_FILES)
-- $(LIBTOOL) --mode=link $(CC) $(CFLAGS) -o $(CVODES_LIB) $(CVODES_LIB_FILES) $(CVODES_BL_LIB_FILES) $(SHARED_LIB_FILES) -rpath $(libdir) $(LDFLAGS) $(LIBS) -version-info $(LIB_REVISION)
-+ $(LIBTOOL) --mode=link $(CC) $(CFLAGS) -o $(CVODES_LIB) $(CVODES_LIB_FILES) $(CVODES_BL_LIB_FILES) $(SHARED_LIB_FILES) -rpath $(libdir) $(LDFLAGS) $(LIBS) $(BLAS_LAPACK_LIBS) -version-info $(LIB_REVISION)
-
- install: $(CVODES_LIB)
- $(mkinstalldirs) $(includedir)/cvodes
---- a/src/ida/Makefile.in
-+++ b/src/ida/Makefile.in
-@@ -42,6 +42,7 @@
- LIBS = @LIBS@
-
- LAPACK_ENABLED = @LAPACK_ENABLED@
-+BLAS_LAPACK_LIBS = @BLAS_LAPACK_LIBS@
-
- top_srcdir = $(srcdir)/../..
-
-@@ -88,7 +89,7 @@
- $(LIBTOOL) --mode=link $(CC) $(CFLAGS) -o $(IDA_LIB) $(IDA_LIB_FILES) $(SHARED_LIB_FILES) -rpath $(libdir) $(LDFLAGS) $(LIBS) -version-info $(LIB_REVISION)
-
- lib_with_bl: shared $(IDA_LIB_FILES) $(IDA_BL_LIB_FILES)
-- $(LIBTOOL) --mode=link $(CC) $(CFLAGS) -o $(IDA_LIB) $(IDA_LIB_FILES) $(IDA_BL_LIB_FILES) $(SHARED_LIB_FILES) -rpath $(libdir) $(LDFLAGS) $(LIBS) -version-info $(LIB_REVISION)
-+ $(LIBTOOL) --mode=link $(CC) $(CFLAGS) -o $(IDA_LIB) $(IDA_LIB_FILES) $(IDA_BL_LIB_FILES) $(SHARED_LIB_FILES) -rpath $(libdir) $(LDFLAGS) $(LIBS) $(BLAS_LAPACK_LIBS) -version-info $(LIB_REVISION)
-
- install: $(IDA_LIB)
- $(mkinstalldirs) $(includedir)/ida
---- a/src/idas/Makefile.in
-+++ b/src/idas/Makefile.in
-@@ -42,6 +42,7 @@
- LIBS = @LIBS@
-
- LAPACK_ENABLED = @LAPACK_ENABLED@
-+BLAS_LAPACK_LIBS = @BLAS_LAPACK_LIBS@
-
- top_srcdir = $(srcdir)/../..
-
-@@ -88,7 +89,7 @@
- $(LIBTOOL) --mode=link $(CC) $(CFLAGS) -o $(IDAS_LIB) $(IDAS_LIB_FILES) $(SHARED_LIB_FILES) -rpath $(libdir) $(LDFLAGS) $(LIBS) -version-info $(LIB_REVISION)
-
- lib_with_bl: shared $(IDAS_LIB_FILES) $(IDAS_BL_LIB_FILES)
-- $(LIBTOOL) --mode=link $(CC) $(CFLAGS) -o $(IDAS_LIB) $(IDAS_LIB_FILES) $(IDAS_BL_LIB_FILES) $(SHARED_LIB_FILES) -rpath $(libdir) $(LDFLAGS) $(LIBS) -version-info $(LIB_REVISION)
-+ $(LIBTOOL) --mode=link $(CC) $(CFLAGS) -o $(IDAS_LIB) $(IDAS_LIB_FILES) $(IDAS_BL_LIB_FILES) $(SHARED_LIB_FILES) -rpath $(libdir) $(LDFLAGS) $(LIBS) $(BLAS_LAPACK_LIBS) -version-info $(LIB_REVISION)
-
- install: $(IDAS_LIB)
- $(mkinstalldirs) $(includedir)/idas
---- a/src/kinsol/Makefile.in
-+++ b/src/kinsol/Makefile.in
-@@ -42,6 +42,7 @@
- LIBS = @LIBS@
-
- LAPACK_ENABLED = @LAPACK_ENABLED@
-+BLAS_LAPACK_LIBS = @BLAS_LAPACK_LIBS@
-
- top_srcdir = $(srcdir)/../..
-
-@@ -88,7 +89,7 @@
- $(LIBTOOL) --mode=link $(CC) $(CFLAGS) -o $(KINSOL_LIB) $(KINSOL_LIB_FILES) $(SHARED_LIB_FILES) -rpath $(libdir) $(LDFLAGS) $(LIBS) -version-info $(LIB_REVISION)
-
- lib_with_bl: shared $(KINSOL_LIB_FILES) $(KINSOL_BL_LIB_FILES)
-- $(LIBTOOL) --mode=link $(CC) $(CFLAGS) -o $(KINSOL_LIB) $(KINSOL_LIB_FILES) $(KINSOL_BL_LIB_FILES) $(SHARED_LIB_FILES) -rpath $(libdir) $(LDFLAGS) $(LIBS) -version-info $(LIB_REVISION)
-+ $(LIBTOOL) --mode=link $(CC) $(CFLAGS) -o $(KINSOL_LIB) $(KINSOL_LIB_FILES) $(KINSOL_BL_LIB_FILES) $(SHARED_LIB_FILES) -rpath $(libdir) $(LDFLAGS) $(LIBS) $(BLAS_LAPACK_LIBS) -version-info $(LIB_REVISION)
-
- install: $(KINSOL_LIB)
- $(mkinstalldirs) $(includedir)/kinsol
diff --git a/debian/patches/makefile.patch b/debian/patches/makefile.patch
deleted file mode 100644
index 8f5ef1c..0000000
--- a/debian/patches/makefile.patch
+++ /dev/null
@@ -1,465 +0,0 @@
-Index: sundials-2.4.0/examples/cvode/fcmix_parallel/Makefile.in
-===================================================================
---- sundials-2.4.0.orig/examples/cvode/fcmix_parallel/Makefile.in 2009-05-10 02:22:28.000000000 +0200
-+++ sundials-2.4.0/examples/cvode/fcmix_parallel/Makefile.in 2010-03-02 13:40:30.000000000 +0100
-@@ -84,7 +84,7 @@
- $(INSTALL_FILE) $(top_srcdir)/examples/cvode/fcmix_parallel/README $(EXS_INSTDIR)/cvode/fcmix_parallel/
- for i in ${EXAMPLES} ; do \
- $(INSTALL_FILE) $(top_srcdir)/examples/cvode/fcmix_parallel/$${i}.f $(EXS_INSTDIR)/cvode/fcmix_parallel/ ; \
-- $(INSTALL_FILE) $(top_srcdir)/examples/cvode/fcmix_parallel/$${i}.out $(EXS_INSTDIR)/cvode/fcmix_parallel/ ; \
-+ $(INSTALL_FILE) $(top_srcdir)/examples/cvode/fcmix_parallel/$${i} $(EXS_INSTDIR)/cvode/fcmix_parallel/ ; \
- done
-
- uninstall:
-@@ -92,7 +92,7 @@
- rm -f $(EXS_INSTDIR)/cvode/fcmix_parallel/README
- for i in ${EXAMPLES} ; do \
- rm -f $(EXS_INSTDIR)/cvode/fcmix_parallel/$${i}.f ; \
-- rm -f $(EXS_INSTDIR)/cvode/fcmix_parallel/$${i}.out ; \
-+ rm -f $(EXS_INSTDIR)/cvode/fcmix_parallel/$${i} ; \
- done
- $(rminstalldirs) $(EXS_INSTDIR)/cvode/fcmix_parallel
- $(rminstalldirs) $(EXS_INSTDIR)/cvode
-Index: sundials-2.4.0/examples/cvode/fcmix_serial/Makefile.in
-===================================================================
---- sundials-2.4.0.orig/examples/cvode/fcmix_serial/Makefile.in 2009-05-10 02:22:28.000000000 +0200
-+++ sundials-2.4.0/examples/cvode/fcmix_serial/Makefile.in 2010-03-02 13:40:30.000000000 +0100
-@@ -93,12 +93,12 @@
- $(INSTALL_FILE) $(top_srcdir)/examples/cvode/fcmix_serial/README $(EXS_INSTDIR)/cvode/fcmix_serial/
- for i in ${EXAMPLES} ; do \
- $(INSTALL_FILE) $(top_srcdir)/examples/cvode/fcmix_serial/$${i}.f $(EXS_INSTDIR)/cvode/fcmix_serial/ ; \
-- $(INSTALL_FILE) $(top_srcdir)/examples/cvode/fcmix_serial/$${i}.out $(EXS_INSTDIR)/cvode/fcmix_serial/ ; \
-+ $(INSTALL_FILE) $(top_srcdir)/examples/cvode/fcmix_serial/$${i} $(EXS_INSTDIR)/cvode/fcmix_serial/ ; \
- done
- @if test "X${LAPACK_ENABLED}" = "Xyes"; then \
- for i in ${EXAMPLES_BL} ; do \
- $(INSTALL_FILE) $(top_srcdir)/examples/cvode/fcmix_serial/$${i}.f $(EXS_INSTDIR)/cvode/fcmix_serial/ ; \
-- $(INSTALL_FILE) $(top_srcdir)/examples/cvode/fcmix_serial/$${i}.out $(EXS_INSTDIR)/cvode/fcmix_serial/ ; \
-+ $(INSTALL_FILE) $(top_srcdir)/examples/cvode/fcmix_serial/$${i} $(EXS_INSTDIR)/cvode/fcmix_serial/ ; \
- done ; \
- fi
-
-@@ -107,12 +107,12 @@
- rm -f $(EXS_INSTDIR)/cvode/fcmix_serial/README
- for i in ${EXAMPLES} ; do \
- rm -f $(EXS_INSTDIR)/cvode/fcmix_serial/$${i}.f ; \
-- rm -f $(EXS_INSTDIR)/cvode/fcmix_serial/$${i}.out ; \
-+ rm -f $(EXS_INSTDIR)/cvode/fcmix_serial/$${i} ; \
- done
- @if test "X${LAPACK_ENABLED}" = "Xyes"; then \
- for i in ${EXAMPLES_BL} ; do \
- rm -f $(EXS_INSTDIR)/cvode/fcmix_serial/$${i}.f ; \
-- rm -f $(EXS_INSTDIR)/cvode/fcmix_serial/$${i}.out ; \
-+ rm -f $(EXS_INSTDIR)/cvode/fcmix_serial/$${i} ; \
- done ; \
- fi
- $(rminstalldirs) $(EXS_INSTDIR)/cvode/fcmix_serial
-Index: sundials-2.4.0/examples/cvode/parallel/Makefile.in
-===================================================================
---- sundials-2.4.0.orig/examples/cvode/parallel/Makefile.in 2009-05-10 02:22:28.000000000 +0200
-+++ sundials-2.4.0/examples/cvode/parallel/Makefile.in 2010-03-02 13:40:30.000000000 +0100
-@@ -82,7 +82,7 @@
- $(INSTALL_FILE) $(top_srcdir)/examples/cvode/parallel/README $(EXS_INSTDIR)/cvode/parallel/
- for i in ${EXAMPLES} ; do \
- $(INSTALL_FILE) $(top_srcdir)/examples/cvode/parallel/$${i}.c $(EXS_INSTDIR)/cvode/parallel/ ; \
-- $(INSTALL_FILE) $(top_srcdir)/examples/cvode/parallel/$${i}.out $(EXS_INSTDIR)/cvode/parallel/ ; \
-+ $(INSTALL_FILE) $(top_srcdir)/examples/cvode/parallel/$${i} $(EXS_INSTDIR)/cvode/parallel/ ; \
- done
-
- uninstall:
-@@ -90,7 +90,7 @@
- rm -f $(EXS_INSTDIR)/cvode/parallel/README
- for i in ${EXAMPLES} ; do \
- rm -f $(EXS_INSTDIR)/cvode/parallel/$${i}.c ; \
-- rm -f $(EXS_INSTDIR)/cvode/parallel/$${i}.out ; \
-+ rm -f $(EXS_INSTDIR)/cvode/parallel/$${i} ; \
- done
- $(rminstalldirs) $(EXS_INSTDIR)/cvode/parallel
- $(rminstalldirs) $(EXS_INSTDIR)/cvode
-Index: sundials-2.4.0/examples/cvode/serial/Makefile.in
-===================================================================
---- sundials-2.4.0.orig/examples/cvode/serial/Makefile.in 2009-05-10 02:22:28.000000000 +0200
-+++ sundials-2.4.0/examples/cvode/serial/Makefile.in 2010-03-02 13:40:30.000000000 +0100
-@@ -96,12 +96,12 @@
- $(INSTALL_FILE) $(top_srcdir)/examples/cvode/serial/README $(EXS_INSTDIR)/cvode/serial/
- for i in ${EXAMPLES} ; do \
- $(INSTALL_FILE) $(top_srcdir)/examples/cvode/serial/$${i}.c $(EXS_INSTDIR)/cvode/serial/ ; \
-- $(INSTALL_FILE) $(top_srcdir)/examples/cvode/serial/$${i}.out $(EXS_INSTDIR)/cvode/serial/ ; \
-+ $(INSTALL_FILE) $(top_srcdir)/examples/cvode/serial/$${i} $(EXS_INSTDIR)/cvode/serial/ ; \
- done
- @if test "X${LAPACK_ENABLED}" = "Xyes"; then \
- for i in ${EXAMPLES_BL} ; do \
- $(INSTALL_FILE) $(top_srcdir)/examples/cvode/serial/$${i}.c $(EXS_INSTDIR)/cvode/serial/ ; \
-- $(INSTALL_FILE) $(top_srcdir)/examples/cvode/serial/$${i}.out $(EXS_INSTDIR)/cvode/serial/ ; \
-+ $(INSTALL_FILE) $(top_srcdir)/examples/cvode/serial/$${i} $(EXS_INSTDIR)/cvode/serial/ ; \
- done ; \
- fi
-
-@@ -110,12 +110,12 @@
- rm -f $(EXS_INSTDIR)/cvode/serial/README
- for i in ${EXAMPLES} ; do \
- rm -f $(EXS_INSTDIR)/cvode/serial/$${i}.c ; \
-- rm -f $(EXS_INSTDIR)/cvode/serial/$${i}.out ; \
-+ rm -f $(EXS_INSTDIR)/cvode/serial/$${i} ; \
- done
- @if test "X${LAPACK_ENABLED}" = "Xyes"; then \
- for i in ${EXAMPLES_BL} ; do \
- rm -f $(EXS_INSTDIR)/cvode/serial/$${i}.c ; \
-- rm -f $(EXS_INSTDIR)/cvode/serial/$${i}.out ; \
-+ rm -f $(EXS_INSTDIR)/cvode/serial/$${i} ; \
- done ; \
- fi
- $(rminstalldirs) $(EXS_INSTDIR)/cvode/serial
-Index: sundials-2.4.0/examples/cvodes/parallel/Makefile.in
-===================================================================
---- sundials-2.4.0.orig/examples/cvodes/parallel/Makefile.in 2009-05-10 02:22:36.000000000 +0200
-+++ sundials-2.4.0/examples/cvodes/parallel/Makefile.in 2010-03-02 13:40:30.000000000 +0100
-@@ -85,7 +85,7 @@
- $(INSTALL_FILE) $(top_srcdir)/examples/cvodes/parallel/README $(EXS_INSTDIR)/cvodes/parallel/
- for i in ${EXAMPLES} ; do \
- $(INSTALL_FILE) $(top_srcdir)/examples/cvodes/parallel/$${i}.c $(EXS_INSTDIR)/cvodes/parallel/ ; \
-- $(INSTALL_FILE) $(top_srcdir)/examples/cvodes/parallel/$${i}.out $(EXS_INSTDIR)/cvodes/parallel/ ; \
-+ $(INSTALL_FILE) $(top_srcdir)/examples/cvodes/parallel/$${i} $(EXS_INSTDIR)/cvodes/parallel/ ; \
- done
-
- uninstall:
-@@ -93,7 +93,7 @@
- rm -f $(EXS_INSTDIR)/cvodes/parallel/README
- for i in ${EXAMPLES} ; do \
- rm -f $(EXS_INSTDIR)/cvodes/parallel/$${i}.c ; \
-- rm -f $(EXS_INSTDIR)/cvodes/parallel/$${i}.out ; \
-+ rm -f $(EXS_INSTDIR)/cvodes/parallel/$${i} ; \
- done
- $(rminstalldirs) $(EXS_INSTDIR)/cvodes/parallel
- $(rminstalldirs) $(EXS_INSTDIR)/cvodes
-Index: sundials-2.4.0/examples/cvodes/serial/Makefile.in
-===================================================================
---- sundials-2.4.0.orig/examples/cvodes/serial/Makefile.in 2009-05-10 02:22:36.000000000 +0200
-+++ sundials-2.4.0/examples/cvodes/serial/Makefile.in 2010-03-02 13:40:30.000000000 +0100
-@@ -103,12 +103,12 @@
- $(INSTALL_FILE) $(top_srcdir)/examples/cvodes/serial/README $(EXS_INSTDIR)/cvodes/serial/
- for i in ${EXAMPLES} ; do \
- $(INSTALL_FILE) $(top_srcdir)/examples/cvodes/serial/$${i}.c $(EXS_INSTDIR)/cvodes/serial/ ; \
-- $(INSTALL_FILE) $(top_srcdir)/examples/cvodes/serial/$${i}.out $(EXS_INSTDIR)/cvodes/serial/ ; \
-+ $(INSTALL_FILE) $(top_srcdir)/examples/cvodes/serial/$${i} $(EXS_INSTDIR)/cvodes/serial/ ; \
- done
- @if test "X${LAPACK_ENABLED}" = "Xyes"; then \
- for i in ${EXAMPLES_BL} ; do \
- $(INSTALL_FILE) $(top_srcdir)/examples/cvodes/serial/$${i}.c $(EXS_INSTDIR)/cvodes/serial/ ; \
-- $(INSTALL_FILE) $(top_srcdir)/examples/cvodes/serial/$${i}.out $(EXS_INSTDIR)/cvodes/serial/ ; \
-+ $(INSTALL_FILE) $(top_srcdir)/examples/cvodes/serial/$${i} $(EXS_INSTDIR)/cvodes/serial/ ; \
- done ; \
- fi
-
-@@ -117,12 +117,12 @@
- rm -f $(EXS_INSTDIR)/cvodes/serial/README
- for i in ${EXAMPLES} ; do \
- rm -f $(EXS_INSTDIR)/cvodes/serial/$${i}.c ; \
-- rm -f $(EXS_INSTDIR)/cvodes/serial/$${i}.out ; \
-+ rm -f $(EXS_INSTDIR)/cvodes/serial/$${i} ; \
- done
- @if test "X${LAPACK_ENABLED}" = "Xyes"; then \
- for i in ${EXAMPLES_BL} ; do \
- rm -f $(EXS_INSTDIR)/cvodes/serial/$${i}.c ; \
-- rm -f $(EXS_INSTDIR)/cvodes/serial/$${i}.out ; \
-+ rm -f $(EXS_INSTDIR)/cvodes/serial/$${i} ; \
- done ; \
- fi
- $(rminstalldirs) $(EXS_INSTDIR)/cvodes/serial
-Index: sundials-2.4.0/examples/ida/fcmix_parallel/Makefile.in
-===================================================================
---- sundials-2.4.0.orig/examples/ida/fcmix_parallel/Makefile.in 2009-05-10 02:22:51.000000000 +0200
-+++ sundials-2.4.0/examples/ida/fcmix_parallel/Makefile.in 2010-03-02 13:40:30.000000000 +0100
-@@ -82,7 +82,7 @@
- $(INSTALL_FILE) $(top_srcdir)/examples/ida/fcmix_parallel/README $(EXS_INSTDIR)/ida/fcmix_parallel/
- for i in ${EXAMPLES} ; do \
- $(INSTALL_FILE) $(top_srcdir)/examples/ida/fcmix_parallel/$${i}.f $(EXS_INSTDIR)/ida/fcmix_parallel/ ; \
-- $(INSTALL_FILE) $(top_srcdir)/examples/ida/fcmix_parallel/$${i}.out $(EXS_INSTDIR)/ida/fcmix_parallel/ ; \
-+ $(INSTALL_FILE) $(top_srcdir)/examples/ida/fcmix_parallel/$${i} $(EXS_INSTDIR)/ida/fcmix_parallel/ ; \
- done
-
- uninstall:
-@@ -90,7 +90,7 @@
- rm -f $(EXS_INSTDIR)/ida/fcmix_parallel/README
- for i in ${EXAMPLES} ; do \
- rm -f $(EXS_INSTDIR)/ida/fcmix_parallel/$${i}.f ; \
-- rm -f $(EXS_INSTDIR)/ida/fcmix_parallel/$${i}.out ; \
-+ rm -f $(EXS_INSTDIR)/ida/fcmix_parallel/$${i} ; \
- done
- $(rminstalldirs) $(EXS_INSTDIR)/ida/fcmix_parallel
- $(rminstalldirs) $(EXS_INSTDIR)/ida
-Index: sundials-2.4.0/examples/ida/fcmix_serial/Makefile.in
-===================================================================
---- sundials-2.4.0.orig/examples/ida/fcmix_serial/Makefile.in 2009-05-10 02:22:51.000000000 +0200
-+++ sundials-2.4.0/examples/ida/fcmix_serial/Makefile.in 2010-03-02 13:40:30.000000000 +0100
-@@ -90,12 +90,12 @@
- $(INSTALL_FILE) $(top_srcdir)/examples/ida/fcmix_serial/README $(EXS_INSTDIR)/ida/fcmix_serial/
- for i in ${EXAMPLES} ; do \
- $(INSTALL_FILE) $(top_srcdir)/examples/ida/fcmix_serial/$${i}.f $(EXS_INSTDIR)/ida/fcmix_serial/ ; \
-- $(INSTALL_FILE) $(top_srcdir)/examples/ida/fcmix_serial/$${i}.out $(EXS_INSTDIR)/ida/fcmix_serial/ ; \
-+ $(INSTALL_FILE) $(top_srcdir)/examples/ida/fcmix_serial/$${i} $(EXS_INSTDIR)/ida/fcmix_serial/ ; \
- done
- @if test "X${LAPACK_ENABLED}" = "Xyes"; then \
- for i in ${EXAMPLES_BL} ; do \
- $(INSTALL_FILE) $(top_srcdir)/examples/ida/fcmix_serial/$${i}.f $(EXS_INSTDIR)/ida/fcmix_serial/ ; \
-- $(INSTALL_FILE) $(top_srcdir)/examples/ida/fcmix_serial/$${i}.out $(EXS_INSTDIR)/ida/fcmix_serial/ ; \
-+ $(INSTALL_FILE) $(top_srcdir)/examples/ida/fcmix_serial/$${i} $(EXS_INSTDIR)/ida/fcmix_serial/ ; \
- done ; \
- fi
-
-@@ -104,12 +104,12 @@
- rm -f $(EXS_INSTDIR)/ida/fcmix_serial/README
- for i in ${EXAMPLES} ; do \
- rm -f $(EXS_INSTDIR)/ida/fcmix_serial/$${i}.f ; \
-- rm -f $(EXS_INSTDIR)/ida/fcmix_serial/$${i}.out ; \
-+ rm -f $(EXS_INSTDIR)/ida/fcmix_serial/$${i} ; \
- done
- @if test "X${LAPACK_ENABLED}" = "Xyes"; then \
- for i in ${EXAMPLES_BL} ; do \
- rm -f $(EXS_INSTDIR)/ida/fcmix_serial/$${i}.f ; \
-- rm -f $(EXS_INSTDIR)/ida/fcmix_serial/$${i}.out ; \
-+ rm -f $(EXS_INSTDIR)/ida/fcmix_serial/$${i} ; \
- done ; \
- fi
- $(rminstalldirs) $(EXS_INSTDIR)/ida/fcmix_serial
-Index: sundials-2.4.0/examples/ida/parallel/Makefile.in
-===================================================================
---- sundials-2.4.0.orig/examples/ida/parallel/Makefile.in 2009-05-10 02:22:51.000000000 +0200
-+++ sundials-2.4.0/examples/ida/parallel/Makefile.in 2010-03-02 13:40:30.000000000 +0100
-@@ -82,7 +82,7 @@
- $(INSTALL_FILE) $(top_srcdir)/examples/ida/parallel/README $(EXS_INSTDIR)/ida/parallel/
- for i in ${EXAMPLES} ; do \
- $(INSTALL_FILE) $(top_srcdir)/examples/ida/parallel/$${i}.c $(EXS_INSTDIR)/ida/parallel/ ; \
-- $(INSTALL_FILE) $(top_srcdir)/examples/ida/parallel/$${i}.out $(EXS_INSTDIR)/ida/parallel/ ; \
-+ $(INSTALL_FILE) $(top_srcdir)/examples/ida/parallel/$${i} $(EXS_INSTDIR)/ida/parallel/ ; \
- done
-
- uninstall:
-@@ -90,7 +90,7 @@
- rm -f $(EXS_INSTDIR)/ida/parallel/README
- for i in ${EXAMPLES} ; do \
- rm -f $(EXS_INSTDIR)/ida/parallel/$${i}.c ; \
-- rm -f $(EXS_INSTDIR)/ida/parallel/$${i}.out ; \
-+ rm -f $(EXS_INSTDIR)/ida/parallel/$${i} ; \
- done
- $(rminstalldirs) $(EXS_INSTDIR)/ida/parallel
- $(rminstalldirs) $(EXS_INSTDIR)/ida
-Index: sundials-2.4.0/examples/ida/serial/Makefile.in
-===================================================================
---- sundials-2.4.0.orig/examples/ida/serial/Makefile.in 2009-05-10 02:22:51.000000000 +0200
-+++ sundials-2.4.0/examples/ida/serial/Makefile.in 2010-03-02 13:40:30.000000000 +0100
-@@ -91,12 +91,12 @@
- $(INSTALL_FILE) $(top_srcdir)/examples/ida/serial/README $(EXS_INSTDIR)/ida/serial/
- for i in ${EXAMPLES} ; do \
- $(INSTALL_FILE) $(top_srcdir)/examples/ida/serial/$${i}.c $(EXS_INSTDIR)/ida/serial/ ; \
-- $(INSTALL_FILE) $(top_srcdir)/examples/ida/serial/$${i}.out $(EXS_INSTDIR)/ida/serial/ ; \
-+ $(INSTALL_FILE) $(top_srcdir)/examples/ida/serial/$${i} $(EXS_INSTDIR)/ida/serial/ ; \
- done
- @if test "X${LAPACK_ENABLED}" = "Xyes"; then \
- for i in ${EXAMPLES_BL} ; do \
- $(INSTALL_FILE) $(top_srcdir)/examples/ida/serial/$${i}.c $(EXS_INSTDIR)/ida/serial/ ; \
-- $(INSTALL_FILE) $(top_srcdir)/examples/ida/serial/$${i}.out $(EXS_INSTDIR)/ida/serial/ ; \
-+ $(INSTALL_FILE) $(top_srcdir)/examples/ida/serial/$${i} $(EXS_INSTDIR)/ida/serial/ ; \
- done ; \
- fi
-
-@@ -105,12 +105,12 @@
- rm -f $(EXS_INSTDIR)/ida/serial/README
- for i in ${EXAMPLES} ; do \
- rm -f $(EXS_INSTDIR)/ida/serial/$${i}.c ; \
-- rm -f $(EXS_INSTDIR)/ida/serial/$${i}.out ; \
-+ rm -f $(EXS_INSTDIR)/ida/serial/$${i} ; \
- done
- @if test "X${LAPACK_ENABLED}" = "Xyes"; then \
- for i in ${EXAMPLES_BL} ; do \
- rm -f $(EXS_INSTDIR)/ida/serial/$${i}.c ; \
-- rm -f $(EXS_INSTDIR)/ida/serial/$${i}.out ; \
-+ rm -f $(EXS_INSTDIR)/ida/serial/$${i} ; \
- done ; \
- fi
- $(rminstalldirs) $(EXS_INSTDIR)/ida/serial
-Index: sundials-2.4.0/examples/idas/parallel/Makefile.in
-===================================================================
---- sundials-2.4.0.orig/examples/idas/parallel/Makefile.in 2009-05-10 02:22:58.000000000 +0200
-+++ sundials-2.4.0/examples/idas/parallel/Makefile.in 2010-03-02 13:40:30.000000000 +0100
-@@ -86,7 +86,7 @@
- $(INSTALL_FILE) $(top_srcdir)/examples/idas/parallel/README $(EXS_INSTDIR)/idas/parallel/
- for i in ${EXAMPLES} ; do \
- $(INSTALL_FILE) $(top_srcdir)/examples/idas/parallel/$${i}.c $(EXS_INSTDIR)/idas/parallel/ ; \
-- $(INSTALL_FILE) $(top_srcdir)/examples/idas/parallel/$${i}.out $(EXS_INSTDIR)/idas/parallel/ ; \
-+ $(INSTALL_FILE) $(top_srcdir)/examples/idas/parallel/$${i} $(EXS_INSTDIR)/idas/parallel/ ; \
- done
-
- uninstall:
-@@ -94,7 +94,7 @@
- rm -f $(EXS_INSTDIR)/idas/parallel/README
- for i in ${EXAMPLES} ; do \
- rm -f $(EXS_INSTDIR)/idas/parallel/$${i}.c ; \
-- rm -f $(EXS_INSTDIR)/idas/parallel/$${i}.out ; \
-+ rm -f $(EXS_INSTDIR)/idas/parallel/$${i} ; \
- done
- $(rminstalldirs) $(EXS_INSTDIR)/idas/parallel
- $(rminstalldirs) $(EXS_INSTDIR)/idas
-Index: sundials-2.4.0/examples/idas/serial/Makefile.in
-===================================================================
---- sundials-2.4.0.orig/examples/idas/serial/Makefile.in 2009-05-10 02:22:58.000000000 +0200
-+++ sundials-2.4.0/examples/idas/serial/Makefile.in 2010-03-02 13:40:30.000000000 +0100
-@@ -97,12 +97,12 @@
- $(INSTALL_FILE) $(top_srcdir)/examples/idas/serial/README $(EXS_INSTDIR)/idas/serial/
- for i in ${EXAMPLES} ; do \
- $(INSTALL_FILE) $(top_srcdir)/examples/idas/serial/$${i}.c $(EXS_INSTDIR)/idas/serial/ ; \
-- $(INSTALL_FILE) $(top_srcdir)/examples/idas/serial/$${i}.out $(EXS_INSTDIR)/idas/serial/ ; \
-+ $(INSTALL_FILE) $(top_srcdir)/examples/idas/serial/$${i} $(EXS_INSTDIR)/idas/serial/ ; \
- done
- @if test "X${LAPACK_ENABLED}" = "Xyes"; then \
- for i in ${EXAMPLES_BL} ; do \
- $(INSTALL_FILE) $(top_srcdir)/examples/idas/serial/$${i}.c $(EXS_INSTDIR)/idas/serial/ ; \
-- $(INSTALL_FILE) $(top_srcdir)/examples/idas/serial/$${i}.out $(EXS_INSTDIR)/idas/serial/ ; \
-+ $(INSTALL_FILE) $(top_srcdir)/examples/idas/serial/$${i} $(EXS_INSTDIR)/idas/serial/ ; \
- done ; \
- fi
-
-@@ -111,12 +111,12 @@
- rm -f $(EXS_INSTDIR)/idas/serial/README
- for i in ${EXAMPLES} ; do \
- rm -f $(EXS_INSTDIR)/idas/serial/$${i}.c ; \
-- rm -f $(EXS_INSTDIR)/idas/serial/$${i}.out ; \
-+ rm -f $(EXS_INSTDIR)/idas/serial/$${i} ; \
- done
- @if test "X${LAPACK_ENABLED}" = "Xyes"; then \
- for i in ${EXAMPLES_BL} ; do \
- rm -f $(EXS_INSTDIR)/idas/serial/$${i}.c ; \
-- rm -f $(EXS_INSTDIR)/idas/serial/$${i}.out ; \
-+ rm -f $(EXS_INSTDIR)/idas/serial/$${i} ; \
- done ; \
- fi
- $(rminstalldirs) $(EXS_INSTDIR)/idas/serial
-Index: sundials-2.4.0/examples/kinsol/fcmix_parallel/Makefile.in
-===================================================================
---- sundials-2.4.0.orig/examples/kinsol/fcmix_parallel/Makefile.in 2009-05-10 02:23:08.000000000 +0200
-+++ sundials-2.4.0/examples/kinsol/fcmix_parallel/Makefile.in 2010-03-02 13:40:30.000000000 +0100
-@@ -82,7 +82,7 @@
- $(INSTALL_FILE) $(top_srcdir)/examples/kinsol/fcmix_parallel/README $(EXS_INSTDIR)/kinsol/fcmix_parallel/
- for i in ${EXAMPLES} ; do \
- $(INSTALL_FILE) $(top_srcdir)/examples/kinsol/fcmix_parallel/$${i}.f $(EXS_INSTDIR)/kinsol/fcmix_parallel/ ; \
-- $(INSTALL_FILE) $(top_srcdir)/examples/kinsol/fcmix_parallel/$${i}.out $(EXS_INSTDIR)/kinsol/fcmix_parallel/ ; \
-+ $(INSTALL_FILE) $(top_srcdir)/examples/kinsol/fcmix_parallel/$${i} $(EXS_INSTDIR)/kinsol/fcmix_parallel/ ; \
- done
-
- uninstall:
-@@ -90,7 +90,7 @@
- rm -f $(EXS_INSTDIR)/kinsol/fcmix_parallel/README
- for i in ${EXAMPLES} ; do \
- rm -f $(EXS_INSTDIR)/kinsol/fcmix_parallel/$${i}.f ; \
-- rm -f $(EXS_INSTDIR)/kinsol/fcmix_parallel/$${i}.out ; \
-+ rm -f $(EXS_INSTDIR)/kinsol/fcmix_parallel/$${i} ; \
- done
- $(rminstalldirs) $(EXS_INSTDIR)/kinsol/fcmix_parallel
- $(rminstalldirs) $(EXS_INSTDIR)/kinsol
-Index: sundials-2.4.0/examples/kinsol/fcmix_serial/Makefile.in
-===================================================================
---- sundials-2.4.0.orig/examples/kinsol/fcmix_serial/Makefile.in 2009-05-10 02:23:08.000000000 +0200
-+++ sundials-2.4.0/examples/kinsol/fcmix_serial/Makefile.in 2010-03-02 13:40:30.000000000 +0100
-@@ -90,12 +90,12 @@
- $(INSTALL_FILE) $(top_srcdir)/examples/kinsol/fcmix_serial/README $(EXS_INSTDIR)/kinsol/fcmix_serial/
- for i in ${EXAMPLES} ; do \
- $(INSTALL_FILE) $(top_srcdir)/examples/kinsol/fcmix_serial/$${i}.f $(EXS_INSTDIR)/kinsol/fcmix_serial/ ; \
-- $(INSTALL_FILE) $(top_srcdir)/examples/kinsol/fcmix_serial/$${i}.out $(EXS_INSTDIR)/kinsol/fcmix_serial/ ; \
-+ $(INSTALL_FILE) $(top_srcdir)/examples/kinsol/fcmix_serial/$${i} $(EXS_INSTDIR)/kinsol/fcmix_serial/ ; \
- done
- @if test "X${LAPACK_ENABLED}" = "Xyes"; then \
- for i in ${EXAMPLES_BL} ; do \
- $(INSTALL_FILE) $(top_srcdir)/examples/kinsol/fcmix_serial/$${i}.f $(EXS_INSTDIR)/kinsol/fcmix_serial/ ; \
-- $(INSTALL_FILE) $(top_srcdir)/examples/kinsol/fcmix_serial/$${i}.out $(EXS_INSTDIR)/kinsol/fcmix_serial/ ; \
-+ $(INSTALL_FILE) $(top_srcdir)/examples/kinsol/fcmix_serial/$${i} $(EXS_INSTDIR)/kinsol/fcmix_serial/ ; \
- done ; \
- fi
-
-@@ -104,12 +104,12 @@
- rm -f $(EXS_INSTDIR)/kinsol/fcmix_serial/README
- for i in ${EXAMPLES} ; do \
- rm -f $(EXS_INSTDIR)/kinsol/fcmix_serial/$${i}.f ; \
-- rm -f $(EXS_INSTDIR)/kinsol/fcmix_serial/$${i}.out ; \
-+ rm -f $(EXS_INSTDIR)/kinsol/fcmix_serial/$${i} ; \
- done
- @if test "X${LAPACK_ENABLED}" = "Xyes"; then \
- for i in ${EXAMPLES_BL} ; do \
- rm -f $(EXS_INSTDIR)/kinsol/fcmix_serial/$${i}.f ; \
-- rm -f $(EXS_INSTDIR)/kinsol/fcmix_serial/$${i}.out ; \
-+ rm -f $(EXS_INSTDIR)/kinsol/fcmix_serial/$${i} ; \
- done ; \
- fi
- $(rminstalldirs) $(EXS_INSTDIR)/kinsol/fcmix_serial
-Index: sundials-2.4.0/examples/kinsol/parallel/Makefile.in
-===================================================================
---- sundials-2.4.0.orig/examples/kinsol/parallel/Makefile.in 2009-05-10 02:23:08.000000000 +0200
-+++ sundials-2.4.0/examples/kinsol/parallel/Makefile.in 2010-03-02 13:40:30.000000000 +0100
-@@ -80,7 +80,7 @@
- $(INSTALL_FILE) $(top_srcdir)/examples/kinsol/parallel/README $(EXS_INSTDIR)/kinsol/parallel/
- for i in ${EXAMPLES} ; do \
- $(INSTALL_FILE) $(top_srcdir)/examples/kinsol/parallel/$${i}.c $(EXS_INSTDIR)/kinsol/parallel/ ; \
-- $(INSTALL_FILE) $(top_srcdir)/examples/kinsol/parallel/$${i}.out $(EXS_INSTDIR)/kinsol/parallel/ ; \
-+ $(INSTALL_FILE) $(top_srcdir)/examples/kinsol/parallel/$${i} $(EXS_INSTDIR)/kinsol/parallel/ ; \
- done
-
- uninstall:
-@@ -88,7 +88,7 @@
- rm -f $(EXS_INSTDIR)/kinsol/parallel/README
- for i in ${EXAMPLES} ; do \
- rm -f $(EXS_INSTDIR)/kinsol/parallel/$${i}.c ; \
-- rm -f $(EXS_INSTDIR)/kinsol/parallel/$${i}.out ; \
-+ rm -f $(EXS_INSTDIR)/kinsol/parallel/$${i} ; \
- done
- $(rminstalldirs) $(EXS_INSTDIR)/kinsol/parallel
- $(rminstalldirs) $(EXS_INSTDIR)/kinsol
-Index: sundials-2.4.0/examples/kinsol/serial/Makefile.in
-===================================================================
---- sundials-2.4.0.orig/examples/kinsol/serial/Makefile.in 2009-05-10 02:23:08.000000000 +0200
-+++ sundials-2.4.0/examples/kinsol/serial/Makefile.in 2010-03-02 13:40:30.000000000 +0100
-@@ -90,12 +90,12 @@
- $(INSTALL_FILE) $(top_srcdir)/examples/kinsol/serial/README $(EXS_INSTDIR)/kinsol/serial/
- for i in ${EXAMPLES} ; do \
- $(INSTALL_FILE) $(top_srcdir)/examples/kinsol/serial/$${i}.c $(EXS_INSTDIR)/kinsol/serial/ ; \
-- $(INSTALL_FILE) $(top_srcdir)/examples/kinsol/serial/$${i}.out $(EXS_INSTDIR)/kinsol/serial/ ; \
-+ $(INSTALL_FILE) $(top_srcdir)/examples/kinsol/serial/$${i} $(EXS_INSTDIR)/kinsol/serial/ ; \
- done
- @if test "X${LAPACK_ENABLED}" = "Xyes"; then \
- for i in ${EXAMPLES_BL} ; do \
- $(INSTALL_FILE) $(top_srcdir)/examples/kinsol/serial/$${i}.c $(EXS_INSTDIR)/kinsol/serial/ ; \
-- $(INSTALL_FILE) $(top_srcdir)/examples/kinsol/serial/$${i}.out $(EXS_INSTDIR)/kinsol/serial/ ; \
-+ $(INSTALL_FILE) $(top_srcdir)/examples/kinsol/serial/$${i} $(EXS_INSTDIR)/kinsol/serial/ ; \
- done ; \
- fi
-
-@@ -104,12 +104,12 @@
- rm -f $(EXS_INSTDIR)/kinsol/serial/README
- for i in ${EXAMPLES} ; do \
- rm -f $(EXS_INSTDIR)/kinsol/serial/$${i}.c ; \
-- rm -f $(EXS_INSTDIR)/kinsol/serial/$${i}.out ; \
-+ rm -f $(EXS_INSTDIR)/kinsol/serial/$${i} ; \
- done
- @if test "X${LAPACK_ENABLED}" = "Xyes"; then \
- for i in ${EXAMPLES_BL} ; do \
- rm -f $(EXS_INSTDIR)/kinsol/serial/$${i}.c ; \
-- rm -f $(EXS_INSTDIR)/kinsol/serial/$${i}.out ; \
-+ rm -f $(EXS_INSTDIR)/kinsol/serial/$${i} ; \
- done ; \
- fi
- $(rminstalldirs) $(EXS_INSTDIR)/kinsol/serial
-Index: sundials-2.5.0/Makefile.in
-===================================================================
---- sundials-2.5.0.orig/Makefile.in 2012-04-24 09:28:20.000000000 +0200
-+++ sundials-2.5.0/Makefile.in 2012-04-24 09:28:23.000000000 +0200
-@@ -59,9 +59,9 @@
-
- install:
- $(mkinstalldirs) $(bindir)
-- $(INSTALL_PROG) $(top_builddir)/bin/sundials-config $(bindir)/
-- @if test -f $(top_builddir)/bin/fortran-update.sh ; then \
-- $(INSTALL_PROG) $(top_builddir)/bin/fortran-update.sh $(bindir)/ ;\
-+ $(INSTALL_PROG) $(top_srcdir)/bin/sundials-config $(bindir)/
-+ @if test -f $(top_srcdir)/bin/fortran-update.sh ; then \
-+ $(INSTALL_PROG) $(top_srcdir)/bin/fortran-update.sh $(bindir)/ ;\
- fi
- @for i in ${SLV_MODULES} ; do \
- if test -d $${i} ; then \
diff --git a/debian/patches/modern-ltmain.sh.patch b/debian/patches/modern-ltmain.sh.patch
deleted file mode 100644
index 8d538af..0000000
--- a/debian/patches/modern-ltmain.sh.patch
+++ /dev/null
@@ -1,5878 +0,0 @@
-Upgrade with the current version to solve the .so extension problem
-(done by Andrey Romanenko)
-
- -- Rafael Laboissiere <rafael at debian.org> Mon, 8 May 2006 12:32:29 +0200
-
-diff -Nur sundials/config/ltmain.sh sundials.new/config/ltmain.sh
---- sundials/config/ltmain.sh 2005-08-09 19:32:42.000000000 +0200
-+++ sundials.new/config/ltmain.sh 2006-05-05 08:23:35.225280328 +0200
-@@ -1,7 +1,7 @@
- # ltmain.sh - Provide generalized library-building support services.
- # NOTE: Changing this file will not affect anything until you rerun configure.
- #
--# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001
-+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005
- # Free Software Foundation, Inc.
- # Originally by Gordon Matzigkeit <gord at gnu.ai.mit.edu>, 1996
- #
-@@ -17,13 +17,42 @@
- #
- # You should have received a copy of the GNU General Public License
- # along with this program; if not, write to the Free Software
--# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- #
- # As a special exception to the GNU General Public License, if you
- # distribute this file as part of a program that contains a
- # configuration script generated by Autoconf, you may include it under
- # the same distribution terms that you use for the rest of that program.
-
-+SED=/bin/sed
-+basename="s,^.*/,,g"
-+
-+# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh
-+# is ksh but when the shell is invoked as "sh" and the current value of
-+# the _XPG environment variable is not equal to 1 (one), the special
-+# positional parameter $0, within a function call, is the name of the
-+# function.
-+progpath="$0"
-+
-+# The name of this program:
-+progname=`echo "$progpath" | $SED $basename`
-+modename="$progname"
-+
-+# Global variables:
-+EXIT_SUCCESS=0
-+EXIT_FAILURE=1
-+
-+PROGRAM=ltmain.sh
-+PACKAGE=libtool
-+VERSION="1.5.22 Debian 1.5.22-4"
-+TIMESTAMP=" (1.1220.2.365 2005/12/18 22:14:06)"
-+
-+# See if we are running on zsh, and set the options which allow our
-+# commands through without removal of \ escapes.
-+if test -n "${ZSH_VERSION+set}" ; then
-+ setopt NO_GLOB_SUBST
-+fi
-+
- # Check that we have a working $echo.
- if test "X$1" = X--no-reexec; then
- # Discard the --no-reexec flag, and continue.
-@@ -36,7 +65,7 @@
- :
- else
- # Restart under the correct shell, and then maybe $echo will work.
-- exec $SHELL "$0" --no-reexec ${1+"$@"}
-+ exec $SHELL "$progpath" --no-reexec ${1+"$@"}
- fi
-
- if test "X$1" = X--fallback-echo; then
-@@ -45,19 +74,9 @@
- cat <<EOF
- $*
- EOF
-- exit 0
-+ exit $EXIT_SUCCESS
- fi
-
--# The name of this program.
--progname=`$echo "$0" | ${SED} 's%^.*/%%'`
--modename="$progname"
--
--# Constants.
--PROGRAM=ltmain.sh
--PACKAGE=libtool
--VERSION=1.4.3
--TIMESTAMP=" (1.922.2.110 2002/10/23 01:39:54)"
--
- default_mode=
- help="Try \`$progname --help' for more information."
- magic="%%%MAGIC variable%%%"
-@@ -69,17 +88,18 @@
- # metacharacters that are still active within double-quoted strings.
- Xsed="${SED}"' -e 1s/^X//'
- sed_quote_subst='s/\([\\`\\"$\\\\]\)/\\\1/g'
--# test EBCDIC or ASCII
--case `echo A|od -x` in
-- *[Cc]1*) # EBCDIC based system
-- SP2NL="tr '\100' '\n'"
-- NL2SP="tr '\r\n' '\100\100'"
-- ;;
-- *) # Assume ASCII based system
-- SP2NL="tr '\040' '\012'"
-- NL2SP="tr '\015\012' '\040\040'"
-- ;;
--esac
-+# test EBCDIC or ASCII
-+case `echo X|tr X '\101'` in
-+ A) # ASCII based system
-+ # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr
-+ SP2NL='tr \040 \012'
-+ NL2SP='tr \015\012 \040\040'
-+ ;;
-+ *) # EBCDIC based system
-+ SP2NL='tr \100 \n'
-+ NL2SP='tr \r\n \100\100'
-+ ;;
-+esac
-
- # NLS nuisances.
- # Only set LANG and LC_ALL to C if already set.
-@@ -94,13 +114,10 @@
- fi
-
- # Make sure IFS has a sensible default
--: ${IFS=" "}
-+lt_nl='
-+'
-+IFS=" $lt_nl"
-
--if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then
-- echo "$modename: not configured to build any kind of library" 1>&2
-- echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2
-- exit 1
--fi
-
- # Global variables.
- mode=$default_mode
-@@ -111,11 +128,268 @@
- show="$echo"
- show_help=
- execute_dlfiles=
-+duplicate_deps=no
-+preserve_args=
- lo2o="s/\\.lo\$/.${objext}/"
- o2lo="s/\\.${objext}\$/.lo/"
-
-+#####################################
-+# Shell function definitions:
-+# This seems to be the best place for them
-+
-+# func_mktempdir [string]
-+# Make a temporary directory that won't clash with other running
-+# libtool processes, and avoids race conditions if possible. If
-+# given, STRING is the basename for that directory.
-+func_mktempdir ()
-+{
-+ my_template="${TMPDIR-/tmp}/${1-$progname}"
-+
-+ if test "$run" = ":"; then
-+ # Return a directory name, but don't create it in dry-run mode
-+ my_tmpdir="${my_template}-$$"
-+ else
-+
-+ # If mktemp works, use that first and foremost
-+ my_tmpdir=`mktemp -d "${my_template}-XXXXXXXX" 2>/dev/null`
-+
-+ if test ! -d "$my_tmpdir"; then
-+ # Failing that, at least try and use $RANDOM to avoid a race
-+ my_tmpdir="${my_template}-${RANDOM-0}$$"
-+
-+ save_mktempdir_umask=`umask`
-+ umask 0077
-+ $mkdir "$my_tmpdir"
-+ umask $save_mktempdir_umask
-+ fi
-+
-+ # If we're not in dry-run mode, bomb out on failure
-+ test -d "$my_tmpdir" || {
-+ $echo "cannot create temporary directory \`$my_tmpdir'" 1>&2
-+ exit $EXIT_FAILURE
-+ }
-+ fi
-+
-+ $echo "X$my_tmpdir" | $Xsed
-+}
-+
-+
-+# func_win32_libid arg
-+# return the library type of file 'arg'
-+#
-+# Need a lot of goo to handle *both* DLLs and import libs
-+# Has to be a shell function in order to 'eat' the argument
-+# that is supplied when $file_magic_command is called.
-+func_win32_libid ()
-+{
-+ win32_libid_type="unknown"
-+ win32_fileres=`file -L $1 2>/dev/null`
-+ case $win32_fileres in
-+ *ar\ archive\ import\ library*) # definitely import
-+ win32_libid_type="x86 archive import"
-+ ;;
-+ *ar\ archive*) # could be an import, or static
-+ if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | \
-+ $EGREP -e 'file format pe-i386(.*architecture: i386)?' >/dev/null ; then
-+ win32_nmres=`eval $NM -f posix -A $1 | \
-+ $SED -n -e '1,100{/ I /{s,.*,import,;p;q;};}'`
-+ case $win32_nmres in
-+ import*) win32_libid_type="x86 archive import";;
-+ *) win32_libid_type="x86 archive static";;
-+ esac
-+ fi
-+ ;;
-+ *DLL*)
-+ win32_libid_type="x86 DLL"
-+ ;;
-+ *executable*) # but shell scripts are "executable" too...
-+ case $win32_fileres in
-+ *MS\ Windows\ PE\ Intel*)
-+ win32_libid_type="x86 DLL"
-+ ;;
-+ esac
-+ ;;
-+ esac
-+ $echo $win32_libid_type
-+}
-+
-+
-+# func_infer_tag arg
-+# Infer tagged configuration to use if any are available and
-+# if one wasn't chosen via the "--tag" command line option.
-+# Only attempt this if the compiler in the base compile
-+# command doesn't match the default compiler.
-+# arg is usually of the form 'gcc ...'
-+func_infer_tag ()
-+{
-+ if test -n "$available_tags" && test -z "$tagname"; then
-+ CC_quoted=
-+ for arg in $CC; do
-+ case $arg in
-+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
-+ arg="\"$arg\""
-+ ;;
-+ esac
-+ CC_quoted="$CC_quoted $arg"
-+ done
-+ case $@ in
-+ # Blanks in the command may have been stripped by the calling shell,
-+ # but not from the CC environment variable when configure was run.
-+ " $CC "* | "$CC "* | " `$echo $CC` "* | "`$echo $CC` "* | " $CC_quoted"* | "$CC_quoted "* | " `$echo $CC_quoted` "* | "`$echo $CC_quoted` "*) ;;
-+ # Blanks at the start of $base_compile will cause this to fail
-+ # if we don't check for them as well.
-+ *)
-+ for z in $available_tags; do
-+ if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then
-+ # Evaluate the configuration.
-+ eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`"
-+ CC_quoted=
-+ for arg in $CC; do
-+ # Double-quote args containing other shell metacharacters.
-+ case $arg in
-+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
-+ arg="\"$arg\""
-+ ;;
-+ esac
-+ CC_quoted="$CC_quoted $arg"
-+ done
-+ case "$@ " in
-+ " $CC "* | "$CC "* | " `$echo $CC` "* | "`$echo $CC` "* | " $CC_quoted"* | "$CC_quoted "* | " `$echo $CC_quoted` "* | "`$echo $CC_quoted` "*)
-+ # The compiler in the base compile command matches
-+ # the one in the tagged configuration.
-+ # Assume this is the tagged configuration we want.
-+ tagname=$z
-+ break
-+ ;;
-+ esac
-+ fi
-+ done
-+ # If $tagname still isn't set, then no tagged configuration
-+ # was found and let the user know that the "--tag" command
-+ # line option must be used.
-+ if test -z "$tagname"; then
-+ $echo "$modename: unable to infer tagged configuration"
-+ $echo "$modename: specify a tag with \`--tag'" 1>&2
-+ exit $EXIT_FAILURE
-+# else
-+# $echo "$modename: using $tagname tagged configuration"
-+ fi
-+ ;;
-+ esac
-+ fi
-+}
-+
-+
-+# func_extract_an_archive dir oldlib
-+func_extract_an_archive ()
-+{
-+ f_ex_an_ar_dir="$1"; shift
-+ f_ex_an_ar_oldlib="$1"
-+
-+ $show "(cd $f_ex_an_ar_dir && $AR x $f_ex_an_ar_oldlib)"
-+ $run eval "(cd \$f_ex_an_ar_dir && $AR x \$f_ex_an_ar_oldlib)" || exit $?
-+ if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then
-+ :
-+ else
-+ $echo "$modename: ERROR: object name conflicts: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" 1>&2
-+ exit $EXIT_FAILURE
-+ fi
-+}
-+
-+# func_extract_archives gentop oldlib ...
-+func_extract_archives ()
-+{
-+ my_gentop="$1"; shift
-+ my_oldlibs=${1+"$@"}
-+ my_oldobjs=""
-+ my_xlib=""
-+ my_xabs=""
-+ my_xdir=""
-+ my_status=""
-+
-+ $show "${rm}r $my_gentop"
-+ $run ${rm}r "$my_gentop"
-+ $show "$mkdir $my_gentop"
-+ $run $mkdir "$my_gentop"
-+ my_status=$?
-+ if test "$my_status" -ne 0 && test ! -d "$my_gentop"; then
-+ exit $my_status
-+ fi
-+
-+ for my_xlib in $my_oldlibs; do
-+ # Extract the objects.
-+ case $my_xlib in
-+ [\\/]* | [A-Za-z]:[\\/]*) my_xabs="$my_xlib" ;;
-+ *) my_xabs=`pwd`"/$my_xlib" ;;
-+ esac
-+ my_xlib=`$echo "X$my_xlib" | $Xsed -e 's%^.*/%%'`
-+ my_xdir="$my_gentop/$my_xlib"
-+
-+ $show "${rm}r $my_xdir"
-+ $run ${rm}r "$my_xdir"
-+ $show "$mkdir $my_xdir"
-+ $run $mkdir "$my_xdir"
-+ exit_status=$?
-+ if test "$exit_status" -ne 0 && test ! -d "$my_xdir"; then
-+ exit $exit_status
-+ fi
-+ case $host in
-+ *-darwin*)
-+ $show "Extracting $my_xabs"
-+ # Do not bother doing anything if just a dry run
-+ if test -z "$run"; then
-+ darwin_orig_dir=`pwd`
-+ cd $my_xdir || exit $?
-+ darwin_archive=$my_xabs
-+ darwin_curdir=`pwd`
-+ darwin_base_archive=`$echo "X$darwin_archive" | $Xsed -e 's%^.*/%%'`
-+ darwin_arches=`lipo -info "$darwin_archive" 2>/dev/null | $EGREP Architectures 2>/dev/null`
-+ if test -n "$darwin_arches"; then
-+ darwin_arches=`echo "$darwin_arches" | $SED -e 's/.*are://'`
-+ darwin_arch=
-+ $show "$darwin_base_archive has multiple architectures $darwin_arches"
-+ for darwin_arch in $darwin_arches ; do
-+ mkdir -p "unfat-$$/${darwin_base_archive}-${darwin_arch}"
-+ lipo -thin $darwin_arch -output "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" "${darwin_archive}"
-+ cd "unfat-$$/${darwin_base_archive}-${darwin_arch}"
-+ func_extract_an_archive "`pwd`" "${darwin_base_archive}"
-+ cd "$darwin_curdir"
-+ $rm "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}"
-+ done # $darwin_arches
-+ ## Okay now we have a bunch of thin objects, gotta fatten them up :)
-+ darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print| xargs basename | sort -u | $NL2SP`
-+ darwin_file=
-+ darwin_files=
-+ for darwin_file in $darwin_filelist; do
-+ darwin_files=`find unfat-$$ -name $darwin_file -print | $NL2SP`
-+ lipo -create -output "$darwin_file" $darwin_files
-+ done # $darwin_filelist
-+ ${rm}r unfat-$$
-+ cd "$darwin_orig_dir"
-+ else
-+ cd "$darwin_orig_dir"
-+ func_extract_an_archive "$my_xdir" "$my_xabs"
-+ fi # $darwin_arches
-+ fi # $run
-+ ;;
-+ *)
-+ func_extract_an_archive "$my_xdir" "$my_xabs"
-+ ;;
-+ esac
-+ my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | $NL2SP`
-+ done
-+ func_extract_archives_result="$my_oldobjs"
-+}
-+# End of Shell function definitions
-+#####################################
-+
-+# Darwin sucks
-+eval std_shrext=\"$shrext_cmds\"
-+
-+disable_libs=no
-+
- # Parse our command line options once, thoroughly.
--while test $# -gt 0
-+while test "$#" -gt 0
- do
- arg="$1"
- shift
-@@ -131,6 +405,34 @@
- execute_dlfiles)
- execute_dlfiles="$execute_dlfiles $arg"
- ;;
-+ tag)
-+ tagname="$arg"
-+ preserve_args="${preserve_args}=$arg"
-+
-+ # Check whether tagname contains only valid characters
-+ case $tagname in
-+ *[!-_A-Za-z0-9,/]*)
-+ $echo "$progname: invalid tag name: $tagname" 1>&2
-+ exit $EXIT_FAILURE
-+ ;;
-+ esac
-+
-+ case $tagname in
-+ CC)
-+ # Don't test for the "default" C tag, as we know, it's there, but
-+ # not specially marked.
-+ ;;
-+ *)
-+ if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$" < "$progpath" > /dev/null; then
-+ taglist="$taglist $tagname"
-+ # Evaluate the configuration.
-+ eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$tagname'$/,/^# ### END LIBTOOL TAG CONFIG: '$tagname'$/p' < $progpath`"
-+ else
-+ $echo "$progname: ignoring unknown tag $tagname" 1>&2
-+ fi
-+ ;;
-+ esac
-+ ;;
- *)
- eval "$prev=\$arg"
- ;;
-@@ -148,18 +450,27 @@
- ;;
-
- --version)
-- echo "$PROGRAM (GNU $PACKAGE) $VERSION$TIMESTAMP"
-- exit 0
-+ $echo "$PROGRAM (GNU $PACKAGE) $VERSION$TIMESTAMP"
-+ $echo
-+ $echo "Copyright (C) 2005 Free Software Foundation, Inc."
-+ $echo "This is free software; see the source for copying conditions. There is NO"
-+ $echo "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
-+ exit $?
- ;;
-
- --config)
-- ${SED} -e '1,/^# ### BEGIN LIBTOOL CONFIG/d' -e '/^# ### END LIBTOOL CONFIG/,$d' $0
-- exit 0
-+ ${SED} -e '1,/^# ### BEGIN LIBTOOL CONFIG/d' -e '/^# ### END LIBTOOL CONFIG/,$d' $progpath
-+ # Now print the configurations for the tags.
-+ for tagname in $taglist; do
-+ ${SED} -n -e "/^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$/,/^# ### END LIBTOOL TAG CONFIG: $tagname$/p" < "$progpath"
-+ done
-+ exit $?
- ;;
-
- --debug)
-- echo "$progname: enabling shell trace mode"
-+ $echo "$progname: enabling shell trace mode"
- set -x
-+ preserve_args="$preserve_args $arg"
- ;;
-
- --dry-run | -n)
-@@ -167,18 +478,18 @@
- ;;
-
- --features)
-- echo "host: $host"
-+ $echo "host: $host"
- if test "$build_libtool_libs" = yes; then
-- echo "enable shared libraries"
-+ $echo "enable shared libraries"
- else
-- echo "disable shared libraries"
-+ $echo "disable shared libraries"
- fi
- if test "$build_old_libs" = yes; then
-- echo "enable static libraries"
-+ $echo "enable static libraries"
- else
-- echo "disable static libraries"
-+ $echo "disable static libraries"
- fi
-- exit 0
-+ exit $?
- ;;
-
- --finish) mode="finish" ;;
-@@ -190,6 +501,19 @@
-
- --quiet | --silent)
- show=:
-+ preserve_args="$preserve_args $arg"
-+ ;;
-+
-+ --tag)
-+ prevopt="--tag"
-+ prev=tag
-+ preserve_args="$preserve_args --tag"
-+ ;;
-+ --tag=*)
-+ set tag "$optarg" ${1+"$@"}
-+ shift
-+ prev=tag
-+ preserve_args="$preserve_args --tag"
- ;;
-
- -dlopen)
-@@ -200,7 +524,7 @@
- -*)
- $echo "$modename: unrecognized option \`$arg'" 1>&2
- $echo "$help" 1>&2
-- exit 1
-+ exit $EXIT_FAILURE
- ;;
-
- *)
-@@ -213,9 +537,21 @@
- if test -n "$prevopt"; then
- $echo "$modename: option \`$prevopt' requires an argument" 1>&2
- $echo "$help" 1>&2
-- exit 1
-+ exit $EXIT_FAILURE
- fi
-
-+case $disable_libs in
-+no)
-+ ;;
-+shared)
-+ build_libtool_libs=no
-+ build_old_libs=yes
-+ ;;
-+static)
-+ build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac`
-+ ;;
-+esac
-+
- # If this variable is set in any of the actions, the command in it
- # will be execed at the end. This prevents here-documents from being
- # left over by shells.
-@@ -225,8 +561,10 @@
-
- # Infer the operation mode.
- if test -z "$mode"; then
-+ $echo "*** Warning: inferring the mode of operation is deprecated." 1>&2
-+ $echo "*** Future versions of Libtool will require --mode=MODE be specified." 1>&2
- case $nonopt in
-- *cc | *++ | gcc* | *-gcc* | xlc*)
-+ *cc | cc* | *++ | gcc* | *-gcc* | g++* | xlc*)
- mode=link
- for arg
- do
-@@ -267,7 +605,7 @@
- if test -n "$execute_dlfiles" && test "$mode" != execute; then
- $echo "$modename: unrecognized option \`-dlopen'" 1>&2
- $echo "$help" 1>&2
-- exit 1
-+ exit $EXIT_FAILURE
- fi
-
- # Change the help message to a mode-specific one.
-@@ -281,158 +619,127 @@
- modename="$modename: compile"
- # Get the compilation command and the source file.
- base_compile=
-- prev=
-- lastarg=
-- srcfile="$nonopt"
-+ srcfile="$nonopt" # always keep a non-empty value in "srcfile"
-+ suppress_opt=yes
- suppress_output=
-+ arg_mode=normal
-+ libobj=
-+ later=
-
-- user_target=no
- for arg
- do
-- case $prev in
-- "") ;;
-- xcompiler)
-- # Aesthetically quote the previous argument.
-- prev=
-- lastarg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
--
-- case $arg in
-- # Double-quote args containing other shell metacharacters.
-- # Many Bourne shells cannot handle close brackets correctly
-- # in scan sets, so we specify it separately.
-- *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
-- arg="\"$arg\""
-- ;;
-- esac
--
-- # Add the previous argument to base_compile.
-- if test -z "$base_compile"; then
-- base_compile="$lastarg"
-- else
-- base_compile="$base_compile $lastarg"
-- fi
-- continue
-- ;;
-- esac
--
-- # Accept any command-line options.
-- case $arg in
-- -o)
-- if test "$user_target" != "no"; then
-- $echo "$modename: you cannot specify \`-o' more than once" 1>&2
-- exit 1
-- fi
-- user_target=next
-+ case $arg_mode in
-+ arg )
-+ # do not "continue". Instead, add this to base_compile
-+ lastarg="$arg"
-+ arg_mode=normal
- ;;
-
-- -static)
-- build_old_libs=yes
-+ target )
-+ libobj="$arg"
-+ arg_mode=normal
- continue
- ;;
-
-- -prefer-pic)
-- pic_mode=yes
-- continue
-- ;;
-+ normal )
-+ # Accept any command-line options.
-+ case $arg in
-+ -o)
-+ if test -n "$libobj" ; then
-+ $echo "$modename: you cannot specify \`-o' more than once" 1>&2
-+ exit $EXIT_FAILURE
-+ fi
-+ arg_mode=target
-+ continue
-+ ;;
-
-- -prefer-non-pic)
-- pic_mode=no
-- continue
-- ;;
-+ -static | -prefer-pic | -prefer-non-pic)
-+ later="$later $arg"
-+ continue
-+ ;;
-
-- -Xcompiler)
-- prev=xcompiler
-- continue
-- ;;
-+ -no-suppress)
-+ suppress_opt=no
-+ continue
-+ ;;
-
-- -Wc,*)
-- args=`$echo "X$arg" | $Xsed -e "s/^-Wc,//"`
-- lastarg=
-- save_ifs="$IFS"; IFS=','
-- for arg in $args; do
-- IFS="$save_ifs"
-+ -Xcompiler)
-+ arg_mode=arg # the next one goes into the "base_compile" arg list
-+ continue # The current "srcfile" will either be retained or
-+ ;; # replaced later. I would guess that would be a bug.
-+
-+ -Wc,*)
-+ args=`$echo "X$arg" | $Xsed -e "s/^-Wc,//"`
-+ lastarg=
-+ save_ifs="$IFS"; IFS=','
-+ for arg in $args; do
-+ IFS="$save_ifs"
-
-- # Double-quote args containing other shell metacharacters.
-- # Many Bourne shells cannot handle close brackets correctly
-- # in scan sets, so we specify it separately.
-- case $arg in
-- *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
-- arg="\"$arg\""
-- ;;
-- esac
-- lastarg="$lastarg $arg"
-- done
-- IFS="$save_ifs"
-- lastarg=`$echo "X$lastarg" | $Xsed -e "s/^ //"`
-+ # Double-quote args containing other shell metacharacters.
-+ # Many Bourne shells cannot handle close brackets correctly
-+ # in scan sets, so we specify it separately.
-+ case $arg in
-+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
-+ arg="\"$arg\""
-+ ;;
-+ esac
-+ lastarg="$lastarg $arg"
-+ done
-+ IFS="$save_ifs"
-+ lastarg=`$echo "X$lastarg" | $Xsed -e "s/^ //"`
-
-- # Add the arguments to base_compile.
-- if test -z "$base_compile"; then
-- base_compile="$lastarg"
-- else
-+ # Add the arguments to base_compile.
- base_compile="$base_compile $lastarg"
-- fi
-- continue
-- ;;
-- esac
-+ continue
-+ ;;
-
-- case $user_target in
-- next)
-- # The next one is the -o target name
-- user_target=yes
-- continue
-- ;;
-- yes)
-- # We got the output file
-- user_target=set
-- libobj="$arg"
-- continue
-+ * )
-+ # Accept the current argument as the source file.
-+ # The previous "srcfile" becomes the current argument.
-+ #
-+ lastarg="$srcfile"
-+ srcfile="$arg"
-+ ;;
-+ esac # case $arg
- ;;
-- esac
--
-- # Accept the current argument as the source file.
-- lastarg="$srcfile"
-- srcfile="$arg"
-+ esac # case $arg_mode
-
- # Aesthetically quote the previous argument.
--
-- # Backslashify any backslashes, double quotes, and dollar signs.
-- # These are the only characters that are still specially
-- # interpreted inside of double-quoted scrings.
- lastarg=`$echo "X$lastarg" | $Xsed -e "$sed_quote_subst"`
-
-+ case $lastarg in
- # Double-quote args containing other shell metacharacters.
- # Many Bourne shells cannot handle close brackets correctly
-- # in scan sets, so we specify it separately.
-- case $lastarg in
-+ # in scan sets, and some SunOS ksh mistreat backslash-escaping
-+ # in scan sets (worked around with variable expansion),
-+ # and furthermore cannot handle '|' '&' '(' ')' in scan sets
-+ # at all, so we specify them separately.
- *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
- lastarg="\"$lastarg\""
- ;;
- esac
-
-- # Add the previous argument to base_compile.
-- if test -z "$base_compile"; then
-- base_compile="$lastarg"
-- else
-- base_compile="$base_compile $lastarg"
-- fi
-- done
-+ base_compile="$base_compile $lastarg"
-+ done # for arg
-
-- case $user_target in
-- set)
-+ case $arg_mode in
-+ arg)
-+ $echo "$modename: you must specify an argument for -Xcompile"
-+ exit $EXIT_FAILURE
- ;;
-- no)
-- # Get the name of the library object.
-- libobj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%'`
-+ target)
-+ $echo "$modename: you must specify a target with \`-o'" 1>&2
-+ exit $EXIT_FAILURE
- ;;
- *)
-- $echo "$modename: you must specify a target with \`-o'" 1>&2
-- exit 1
-+ # Get the name of the library object.
-+ [ -z "$libobj" ] && libobj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%'`
- ;;
- esac
-
- # Recognize several different file suffixes.
- # If the user specifies -o file.o, it is replaced with file.lo
-- xform='[cCFSfmso]'
-+ xform='[cCFSifmso]'
- case $libobj in
- *.ada) xform=ada ;;
- *.adb) xform=adb ;;
-@@ -440,10 +747,13 @@
- *.asm) xform=asm ;;
- *.c++) xform=c++ ;;
- *.cc) xform=cc ;;
-+ *.ii) xform=ii ;;
-+ *.class) xform=class ;;
- *.cpp) xform=cpp ;;
- *.cxx) xform=cxx ;;
- *.f90) xform=f90 ;;
- *.for) xform=for ;;
-+ *.java) xform=java ;;
- esac
-
- libobj=`$echo "X$libobj" | $Xsed -e "s/\.$xform$/.lo/"`
-@@ -452,25 +762,63 @@
- *.lo) obj=`$echo "X$libobj" | $Xsed -e "$lo2o"` ;;
- *)
- $echo "$modename: cannot determine name of library object from \`$libobj'" 1>&2
-- exit 1
-+ exit $EXIT_FAILURE
- ;;
- esac
-
-+ func_infer_tag $base_compile
-+
-+ for arg in $later; do
-+ case $arg in
-+ -static)
-+ build_old_libs=yes
-+ continue
-+ ;;
-+
-+ -prefer-pic)
-+ pic_mode=yes
-+ continue
-+ ;;
-+
-+ -prefer-non-pic)
-+ pic_mode=no
-+ continue
-+ ;;
-+ esac
-+ done
-+
-+ qlibobj=`$echo "X$libobj" | $Xsed -e "$sed_quote_subst"`
-+ case $qlibobj in
-+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
-+ qlibobj="\"$qlibobj\"" ;;
-+ esac
-+ test "X$libobj" != "X$qlibobj" \
-+ && $echo "X$libobj" | grep '[]~#^*{};<>?"'"'"' &()|`$[]' \
-+ && $echo "$modename: libobj name \`$libobj' may not contain shell special characters."
-+ objname=`$echo "X$obj" | $Xsed -e 's%^.*/%%'`
-+ xdir=`$echo "X$obj" | $Xsed -e 's%/[^/]*$%%'`
-+ if test "X$xdir" = "X$obj"; then
-+ xdir=
-+ else
-+ xdir=$xdir/
-+ fi
-+ lobj=${xdir}$objdir/$objname
-+
- if test -z "$base_compile"; then
- $echo "$modename: you must specify a compilation command" 1>&2
- $echo "$help" 1>&2
-- exit 1
-+ exit $EXIT_FAILURE
- fi
-
- # Delete any leftover library objects.
- if test "$build_old_libs" = yes; then
-- removelist="$obj $libobj"
-+ removelist="$obj $lobj $libobj ${libobj}T"
- else
-- removelist="$libobj"
-+ removelist="$lobj $libobj ${libobj}T"
- fi
-
- $run $rm $removelist
-- trap "$run $rm $removelist; exit 1" 1 2 15
-+ trap "$run $rm $removelist; exit $EXIT_FAILURE" 1 2 15
-
- # On Cygwin there's no "real" PIC flag so we must build both object types
- case $host_os in
-@@ -489,8 +837,9 @@
- output_obj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%' -e 's%\.[^.]*$%%'`.${objext}
- lockfile="$output_obj.lock"
- removelist="$removelist $output_obj $lockfile"
-- trap "$run $rm $removelist; exit 1" 1 2 15
-+ trap "$run $rm $removelist; exit $EXIT_FAILURE" 1 2 15
- else
-+ output_obj=
- need_locks=no
- lockfile=
- fi
-@@ -498,13 +847,13 @@
- # Lock this critical section if it is needed
- # We use this script file to make the link, it avoids creating a new file
- if test "$need_locks" = yes; then
-- until $run ln "$0" "$lockfile" 2>/dev/null; do
-+ until $run ln "$progpath" "$lockfile" 2>/dev/null; do
- $show "Waiting for $lockfile to be removed"
- sleep 2
- done
- elif test "$need_locks" = warn; then
- if test -f "$lockfile"; then
-- echo "\
-+ $echo "\
- *** ERROR, $lockfile exists and contains:
- `cat $lockfile 2>/dev/null`
-
-@@ -516,14 +865,33 @@
- compiler."
-
- $run $rm $removelist
-- exit 1
-+ exit $EXIT_FAILURE
- fi
-- echo $srcfile > "$lockfile"
-+ $echo "$srcfile" > "$lockfile"
- fi
-
- if test -n "$fix_srcfile_path"; then
- eval srcfile=\"$fix_srcfile_path\"
- fi
-+ qsrcfile=`$echo "X$srcfile" | $Xsed -e "$sed_quote_subst"`
-+ case $qsrcfile in
-+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
-+ qsrcfile="\"$qsrcfile\"" ;;
-+ esac
-+
-+ $run $rm "$libobj" "${libobj}T"
-+
-+ # Create a libtool object file (analogous to a ".la" file),
-+ # but don't create it if we're doing a dry run.
-+ test -z "$run" && cat > ${libobj}T <<EOF
-+# $libobj - a libtool object file
-+# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP
-+#
-+# Please DO NOT delete this file!
-+# It is necessary for linking the library.
-+
-+# Name of the PIC object.
-+EOF
-
- # Only build a PIC object if we are building libtool libraries.
- if test "$build_libtool_libs" = yes; then
-@@ -531,53 +899,38 @@
- fbsd_hideous_sh_bug=$base_compile
-
- if test "$pic_mode" != no; then
-- # All platforms use -DPIC, to notify preprocessed assembler code.
-- command="$base_compile $srcfile $pic_flag -DPIC"
-+ command="$base_compile $qsrcfile $pic_flag"
- else
- # Don't build PIC code
-- command="$base_compile $srcfile"
-+ command="$base_compile $qsrcfile"
- fi
-- if test "$build_old_libs" = yes; then
-- lo_libobj="$libobj"
-- dir=`$echo "X$libobj" | $Xsed -e 's%/[^/]*$%%'`
-- if test "X$dir" = "X$libobj"; then
-- dir="$objdir"
-- else
-- dir="$dir/$objdir"
-- fi
-- libobj="$dir/"`$echo "X$libobj" | $Xsed -e 's%^.*/%%'`
-
-- if test -d "$dir"; then
-- $show "$rm $libobj"
-- $run $rm $libobj
-- else
-- $show "$mkdir $dir"
-- $run $mkdir $dir
-- status=$?
-- if test $status -ne 0 && test ! -d $dir; then
-- exit $status
-- fi
-+ if test ! -d "${xdir}$objdir"; then
-+ $show "$mkdir ${xdir}$objdir"
-+ $run $mkdir ${xdir}$objdir
-+ exit_status=$?
-+ if test "$exit_status" -ne 0 && test ! -d "${xdir}$objdir"; then
-+ exit $exit_status
- fi
- fi
-- if test "$compiler_o_lo" = yes; then
-- output_obj="$libobj"
-- command="$command -o $output_obj"
-- elif test "$compiler_c_o" = yes; then
-- output_obj="$obj"
-- command="$command -o $output_obj"
-+
-+ if test -z "$output_obj"; then
-+ # Place PIC objects in $objdir
-+ command="$command -o $lobj"
- fi
-
-- $run $rm "$output_obj"
-+ $run $rm "$lobj" "$output_obj"
-+
- $show "$command"
- if $run eval "$command"; then :
- else
- test -n "$output_obj" && $run $rm $removelist
-- exit 1
-+ exit $EXIT_FAILURE
- fi
-
- if test "$need_locks" = warn &&
-- test x"`cat $lockfile 2>/dev/null`" != x"$srcfile"; then
-- echo "\
-+ test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then
-+ $echo "\
- *** ERROR, $lockfile contains:
- `cat $lockfile 2>/dev/null`
-
-@@ -592,13 +945,13 @@
- compiler."
-
- $run $rm $removelist
-- exit 1
-+ exit $EXIT_FAILURE
- fi
-
- # Just move the object if needed, then go on to compile the next one
-- if test x"$output_obj" != x"$libobj"; then
-- $show "$mv $output_obj $libobj"
-- if $run $mv $output_obj $libobj; then :
-+ if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then
-+ $show "$mv $output_obj $lobj"
-+ if $run $mv $output_obj $lobj; then :
- else
- error=$?
- $run $rm $removelist
-@@ -606,77 +959,50 @@
- fi
- fi
-
-- # If we have no pic_flag, then copy the object into place and finish.
-- if (test -z "$pic_flag" || test "$pic_mode" != default) &&
-- test "$build_old_libs" = yes; then
-- # Rename the .lo from within objdir to obj
-- if test -f $obj; then
-- $show $rm $obj
-- $run $rm $obj
-- fi
-+ # Append the name of the PIC object to the libtool object file.
-+ test -z "$run" && cat >> ${libobj}T <<EOF
-+pic_object='$objdir/$objname'
-
-- $show "$mv $libobj $obj"
-- if $run $mv $libobj $obj; then :
-- else
-- error=$?
-- $run $rm $removelist
-- exit $error
-- fi
-+EOF
-
-- xdir=`$echo "X$obj" | $Xsed -e 's%/[^/]*$%%'`
-- if test "X$xdir" = "X$obj"; then
-- xdir="."
-- else
-- xdir="$xdir"
-- fi
-- baseobj=`$echo "X$obj" | $Xsed -e "s%.*/%%"`
-- libobj=`$echo "X$baseobj" | $Xsed -e "$o2lo"`
-- # Now arrange that obj and lo_libobj become the same file
-- $show "(cd $xdir && $LN_S $baseobj $libobj)"
-- if $run eval '(cd $xdir && $LN_S $baseobj $libobj)'; then
-- # Unlock the critical section if it was locked
-- if test "$need_locks" != no; then
-- $run $rm "$lockfile"
-- fi
-- exit 0
-- else
-- error=$?
-- $run $rm $removelist
-- exit $error
-- fi
-+ # Allow error messages only from the first compilation.
-+ if test "$suppress_opt" = yes; then
-+ suppress_output=' >/dev/null 2>&1'
- fi
-+ else
-+ # No PIC object so indicate it doesn't exist in the libtool
-+ # object file.
-+ test -z "$run" && cat >> ${libobj}T <<EOF
-+pic_object=none
-
-- # Allow error messages only from the first compilation.
-- suppress_output=' >/dev/null 2>&1'
-+EOF
- fi
-
- # Only build a position-dependent object if we build old libraries.
- if test "$build_old_libs" = yes; then
- if test "$pic_mode" != yes; then
- # Don't build PIC code
-- command="$base_compile $srcfile"
-+ command="$base_compile $qsrcfile"
- else
-- # All platforms use -DPIC, to notify preprocessed assembler code.
-- command="$base_compile $srcfile $pic_flag -DPIC"
-+ command="$base_compile $qsrcfile $pic_flag"
- fi
- if test "$compiler_c_o" = yes; then
- command="$command -o $obj"
-- output_obj="$obj"
- fi
-
- # Suppress compiler output if we already did a PIC compilation.
- command="$command$suppress_output"
-- $run $rm "$output_obj"
-+ $run $rm "$obj" "$output_obj"
- $show "$command"
- if $run eval "$command"; then :
- else
- $run $rm $removelist
-- exit 1
-+ exit $EXIT_FAILURE
- fi
-
- if test "$need_locks" = warn &&
-- test x"`cat $lockfile 2>/dev/null`" != x"$srcfile"; then
-- echo "\
-+ test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then
-+ $echo "\
- *** ERROR, $lockfile contains:
- `cat $lockfile 2>/dev/null`
-
-@@ -691,11 +1017,11 @@
- compiler."
-
- $run $rm $removelist
-- exit 1
-+ exit $EXIT_FAILURE
- fi
-
- # Just move the object if needed
-- if test x"$output_obj" != x"$obj"; then
-+ if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then
- $show "$mv $output_obj $obj"
- if $run $mv $output_obj $obj; then :
- else
-@@ -705,29 +1031,31 @@
- fi
- fi
-
-- # Create an invalid libtool object if no PIC, so that we do not
-- # accidentally link it into a program.
-- if test "$build_libtool_libs" != yes; then
-- $show "echo timestamp > $libobj"
-- $run eval "echo timestamp > \$libobj" || exit $?
-- else
-- # Move the .lo from within objdir
-- $show "$mv $libobj $lo_libobj"
-- if $run $mv $libobj $lo_libobj; then :
-- else
-- error=$?
-- $run $rm $removelist
-- exit $error
-- fi
-- fi
-+ # Append the name of the non-PIC object the libtool object file.
-+ # Only append if the libtool object file exists.
-+ test -z "$run" && cat >> ${libobj}T <<EOF
-+# Name of the non-PIC object.
-+non_pic_object='$objname'
-+
-+EOF
-+ else
-+ # Append the name of the non-PIC object the libtool object file.
-+ # Only append if the libtool object file exists.
-+ test -z "$run" && cat >> ${libobj}T <<EOF
-+# Name of the non-PIC object.
-+non_pic_object=none
-+
-+EOF
- fi
-
-+ $run $mv "${libobj}T" "${libobj}"
-+
- # Unlock the critical section if it was locked
- if test "$need_locks" != no; then
- $run $rm "$lockfile"
- fi
-
-- exit 0
-+ exit $EXIT_SUCCESS
- ;;
-
- # libtool link mode
-@@ -738,7 +1066,7 @@
- # It is impossible to link a dll without this setting, and
- # we shouldn't force the makefile maintainer to figure out
- # which system we are compiling for in order to pass an extra
-- # flag for every libtool invokation.
-+ # flag for every libtool invocation.
- # allow_undefined=no
-
- # FIXME: Unfortunately, there are problems with the above when trying
-@@ -753,6 +1081,7 @@
- ;;
- esac
- libtool_args="$nonopt"
-+ base_compile="$nonopt $@"
- compile_command="$nonopt"
- finalize_command="$nonopt"
-
-@@ -768,6 +1097,7 @@
- linker_flags=
- dllsearchpath=
- lib_search_path=`pwd`
-+ inst_prefix_dir=
-
- avoid_version=no
- dlfiles=
-@@ -782,6 +1112,9 @@
- module=no
- no_install=no
- objs=
-+ non_pic_objects=
-+ notinst_path= # paths that contain not-installed libtool libraries
-+ precious_files_regex=
- prefer_static_libs=no
- preload=no
- prev=
-@@ -793,6 +1126,9 @@
- temp_rpath=
- thread_safe=no
- vinfo=
-+ vinfo_number=no
-+
-+ func_infer_tag $base_compile
-
- # We need to know -static, to get the right output filenames.
- for arg
-@@ -806,14 +1142,15 @@
- if test -n "$link_static_flag"; then
- dlopen_self=$dlopen_self_static
- fi
-+ prefer_static_libs=yes
- else
- if test -z "$pic_flag" && test -n "$link_static_flag"; then
- dlopen_self=$dlopen_self_static
- fi
-+ prefer_static_libs=built
- fi
- build_libtool_libs=no
- build_old_libs=yes
-- prefer_static_libs=yes
- break
- ;;
- esac
-@@ -823,7 +1160,7 @@
- test -n "$old_archive_from_new_cmds" && build_old_libs=yes
-
- # Go through the arguments, transforming them on the way.
-- while test $# -gt 0; do
-+ while test "$#" -gt 0; do
- arg="$1"
- shift
- case $arg in
-@@ -888,7 +1225,7 @@
- export_symbols="$arg"
- if test ! -f "$arg"; then
- $echo "$modename: symbol file \`$arg' does not exist"
-- exit 1
-+ exit $EXIT_FAILURE
- fi
- prev=
- continue
-@@ -898,18 +1235,140 @@
- prev=
- continue
- ;;
-+ inst_prefix)
-+ inst_prefix_dir="$arg"
-+ prev=
-+ continue
-+ ;;
-+ precious_regex)
-+ precious_files_regex="$arg"
-+ prev=
-+ continue
-+ ;;
- release)
- release="-$arg"
- prev=
- continue
- ;;
-+ objectlist)
-+ if test -f "$arg"; then
-+ save_arg=$arg
-+ moreargs=
-+ for fil in `cat $save_arg`
-+ do
-+# moreargs="$moreargs $fil"
-+ arg=$fil
-+ # A libtool-controlled object.
-+
-+ # Check to see that this really is a libtool object.
-+ if (${SED} -e '2q' $arg | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
-+ pic_object=
-+ non_pic_object=
-+
-+ # Read the .lo file
-+ # If there is no directory component, then add one.
-+ case $arg in
-+ */* | *\\*) . $arg ;;
-+ *) . ./$arg ;;
-+ esac
-+
-+ if test -z "$pic_object" || \
-+ test -z "$non_pic_object" ||
-+ test "$pic_object" = none && \
-+ test "$non_pic_object" = none; then
-+ $echo "$modename: cannot find name of object for \`$arg'" 1>&2
-+ exit $EXIT_FAILURE
-+ fi
-+
-+ # Extract subdirectory from the argument.
-+ xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'`
-+ if test "X$xdir" = "X$arg"; then
-+ xdir=
-+ else
-+ xdir="$xdir/"
-+ fi
-+
-+ if test "$pic_object" != none; then
-+ # Prepend the subdirectory the object is found in.
-+ pic_object="$xdir$pic_object"
-+
-+ if test "$prev" = dlfiles; then
-+ if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then
-+ dlfiles="$dlfiles $pic_object"
-+ prev=
-+ continue
-+ else
-+ # If libtool objects are unsupported, then we need to preload.
-+ prev=dlprefiles
-+ fi
-+ fi
-+
-+ # CHECK ME: I think I busted this. -Ossama
-+ if test "$prev" = dlprefiles; then
-+ # Preload the old-style object.
-+ dlprefiles="$dlprefiles $pic_object"
-+ prev=
-+ fi
-+
-+ # A PIC object.
-+ libobjs="$libobjs $pic_object"
-+ arg="$pic_object"
-+ fi
-+
-+ # Non-PIC object.
-+ if test "$non_pic_object" != none; then
-+ # Prepend the subdirectory the object is found in.
-+ non_pic_object="$xdir$non_pic_object"
-+
-+ # A standard non-PIC object
-+ non_pic_objects="$non_pic_objects $non_pic_object"
-+ if test -z "$pic_object" || test "$pic_object" = none ; then
-+ arg="$non_pic_object"
-+ fi
-+ else
-+ # If the PIC object exists, use it instead.
-+ # $xdir was prepended to $pic_object above.
-+ non_pic_object="$pic_object"
-+ non_pic_objects="$non_pic_objects $non_pic_object"
-+ fi
-+ else
-+ # Only an error if not doing a dry-run.
-+ if test -z "$run"; then
-+ $echo "$modename: \`$arg' is not a valid libtool object" 1>&2
-+ exit $EXIT_FAILURE
-+ else
-+ # Dry-run case.
-+
-+ # Extract subdirectory from the argument.
-+ xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'`
-+ if test "X$xdir" = "X$arg"; then
-+ xdir=
-+ else
-+ xdir="$xdir/"
-+ fi
-+
-+ pic_object=`$echo "X${xdir}${objdir}/${arg}" | $Xsed -e "$lo2o"`
-+ non_pic_object=`$echo "X${xdir}${arg}" | $Xsed -e "$lo2o"`
-+ libobjs="$libobjs $pic_object"
-+ non_pic_objects="$non_pic_objects $non_pic_object"
-+ fi
-+ fi
-+ done
-+ else
-+ $echo "$modename: link input file \`$save_arg' does not exist"
-+ exit $EXIT_FAILURE
-+ fi
-+ arg=$save_arg
-+ prev=
-+ continue
-+ ;;
- rpath | xrpath)
- # We need an absolute path.
- case $arg in
- [\\/]* | [A-Za-z]:[\\/]*) ;;
- *)
- $echo "$modename: only absolute run-paths are allowed" 1>&2
-- exit 1
-+ exit $EXIT_FAILURE
- ;;
- esac
- if test "$prev" = rpath; then
-@@ -941,13 +1400,33 @@
- finalize_command="$finalize_command $wl$qarg"
- continue
- ;;
-+ xcclinker)
-+ linker_flags="$linker_flags $qarg"
-+ compiler_flags="$compiler_flags $qarg"
-+ prev=
-+ compile_command="$compile_command $qarg"
-+ finalize_command="$finalize_command $qarg"
-+ continue
-+ ;;
-+ shrext)
-+ shrext_cmds="$arg"
-+ prev=
-+ continue
-+ ;;
-+ darwin_framework|darwin_framework_skip)
-+ test "$prev" = "darwin_framework" && compiler_flags="$compiler_flags $arg"
-+ compile_command="$compile_command $arg"
-+ finalize_command="$finalize_command $arg"
-+ prev=
-+ continue
-+ ;;
- *)
- eval "$prev=\"\$arg\""
- prev=
- continue
- ;;
- esac
-- fi # test -n $prev
-+ fi # test -n "$prev"
-
- prevarg="$arg"
-
-@@ -989,7 +1468,7 @@
- -export-symbols | -export-symbols-regex)
- if test -n "$export_symbols" || test -n "$export_symbols_regex"; then
- $echo "$modename: more than one -exported-symbols argument is not allowed"
-- exit 1
-+ exit $EXIT_FAILURE
- fi
- if test "X$arg" = "X-export-symbols"; then
- prev=expsyms
-@@ -999,11 +1478,28 @@
- continue
- ;;
-
-+ -framework|-arch|-isysroot)
-+ case " $CC " in
-+ *" ${arg} ${1} "* | *" ${arg} ${1} "*)
-+ prev=darwin_framework_skip ;;
-+ *) compiler_flags="$compiler_flags $arg"
-+ prev=darwin_framework ;;
-+ esac
-+ compile_command="$compile_command $arg"
-+ finalize_command="$finalize_command $arg"
-+ continue
-+ ;;
-+
-+ -inst-prefix-dir)
-+ prev=inst_prefix
-+ continue
-+ ;;
-+
- # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:*
- # so, if we see these flags be careful not to treat them like -L
- -L[A-Z][A-Z]*:*)
- case $with_gcc/$host in
-- no/*-*-irix* | no/*-*-nonstopux*)
-+ no/*-*-irix* | /*-*-irix*)
- compile_command="$compile_command $arg"
- finalize_command="$finalize_command $arg"
- ;;
-@@ -1020,7 +1516,8 @@
- absdir=`cd "$dir" && pwd`
- if test -z "$absdir"; then
- $echo "$modename: cannot determine absolute directory name of \`$dir'" 1>&2
-- exit 1
-+ absdir="$dir"
-+ notinst_path="$notinst_path $dir"
- fi
- dir="$absdir"
- ;;
-@@ -1034,10 +1531,15 @@
- esac
- case $host in
- *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*)
-+ testbindir=`$echo "X$dir" | $Xsed -e 's*/lib$*/bin*'`
- case :$dllsearchpath: in
- *":$dir:"*) ;;
- *) dllsearchpath="$dllsearchpath:$dir";;
- esac
-+ case :$dllsearchpath: in
-+ *":$testbindir:"*) ;;
-+ *) dllsearchpath="$dllsearchpath:$testbindir";;
-+ esac
- ;;
- esac
- continue
-@@ -1046,36 +1548,98 @@
- -l*)
- if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then
- case $host in
-- *-*-cygwin* | *-*-pw32* | *-*-beos*)
-+ *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos*)
- # These systems don't actually have a C or math library (as such)
- continue
- ;;
-- *-*-mingw* | *-*-os2*)
-+ *-*-os2*)
- # These systems don't actually have a C library (as such)
- test "X$arg" = "X-lc" && continue
- ;;
-- *-*-openbsd* | *-*-freebsd*)
-+ *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*)
- # Do not include libc due to us having libc/libc_r.
- test "X$arg" = "X-lc" && continue
- ;;
-- esac
-- elif test "X$arg" = "X-lc_r"; then
-- case $host in
-- *-*-openbsd* | *-*-freebsd*)
-- # Do not include libc_r directly, use -pthread flag.
-+ *-*-rhapsody* | *-*-darwin1.[012])
-+ # Rhapsody C and math libraries are in the System framework
-+ deplibs="$deplibs -framework System"
- continue
- ;;
-+ *-*-sco3.2v5* | *-*-sco5v6*)
-+ # Causes problems with __ctype
-+ test "X$arg" = "X-lc" && continue
-+ ;;
-+ *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*)
-+ # Compiler inserts libc in the correct place for threads to work
-+ test "X$arg" = "X-lc" && continue
-+ ;;
- esac
-+ elif test "X$arg" = "X-lc_r"; then
-+ case $host in
-+ *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*)
-+ # Do not include libc_r directly, use -pthread flag.
-+ continue
-+ ;;
-+ esac
- fi
- deplibs="$deplibs $arg"
- continue
- ;;
-
-+ # Tru64 UNIX uses -model [arg] to determine the layout of C++
-+ # classes, name mangling, and exception handling.
-+ -model)
-+ compile_command="$compile_command $arg"
-+ compiler_flags="$compiler_flags $arg"
-+ finalize_command="$finalize_command $arg"
-+ prev=xcompiler
-+ continue
-+ ;;
-+
-+ -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe)
-+ compiler_flags="$compiler_flags $arg"
-+ compile_command="$compile_command $arg"
-+ finalize_command="$finalize_command $arg"
-+ continue
-+ ;;
-+
- -module)
- module=yes
- continue
- ;;
-
-+ # -64, -mips[0-9] enable 64-bit mode on the SGI compiler
-+ # -r[0-9][0-9]* specifies the processor on the SGI compiler
-+ # -xarch=*, -xtarget=* enable 64-bit mode on the Sun compiler
-+ # +DA*, +DD* enable 64-bit mode on the HP compiler
-+ # -q* pass through compiler args for the IBM compiler
-+ # -m* pass through architecture-specific compiler args for GCC
-+ # -m*, -t[45]*, -txscale* pass through architecture-specific
-+ # compiler args for GCC
-+ # -pg pass through profiling flag for GCC
-+ # @file GCC response files
-+ -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*|-pg| \
-+ -t[45]*|-txscale*|@*)
-+
-+ # Unknown arguments in both finalize_command and compile_command need
-+ # to be aesthetically quoted because they are evaled later.
-+ arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
-+ case $arg in
-+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
-+ arg="\"$arg\""
-+ ;;
-+ esac
-+ compile_command="$compile_command $arg"
-+ finalize_command="$finalize_command $arg"
-+ compiler_flags="$compiler_flags $arg"
-+ continue
-+ ;;
-+
-+ -shrext)
-+ prev=shrext
-+ continue
-+ ;;
-+
- -no-fast-install)
- fast_install=no
- continue
-@@ -1100,8 +1664,18 @@
- continue
- ;;
-
-+ -objectlist)
-+ prev=objectlist
-+ continue
-+ ;;
-+
- -o) prev=output ;;
-
-+ -precious-files-regex)
-+ prev=precious_regex
-+ continue
-+ ;;
-+
- -release)
- prev=release
- continue
-@@ -1124,7 +1698,7 @@
- [\\/]* | [A-Za-z]:[\\/]*) ;;
- *)
- $echo "$modename: only absolute run-paths are allowed" 1>&2
-- exit 1
-+ exit $EXIT_FAILURE
- ;;
- esac
- case "$xrpath " in
-@@ -1152,6 +1726,11 @@
- prev=vinfo
- continue
- ;;
-+ -version-number)
-+ prev=vinfo
-+ vinfo_number=yes
-+ continue
-+ ;;
-
- -Wc,*)
- args=`$echo "X$arg" | $Xsed -e "$sed_quote_subst" -e 's/^-Wc,//'`
-@@ -1200,6 +1779,11 @@
- continue
- ;;
-
-+ -XCClinker)
-+ prev=xcclinker
-+ continue
-+ ;;
-+
- # Some other compiler flag.
- -* | +*)
- # Unknown arguments in both finalize_command and compile_command need
-@@ -1212,29 +1796,106 @@
- esac
- ;;
-
-- *.lo | *.$objext)
-- # A library or standard object.
-- if test "$prev" = dlfiles; then
-- # This file was specified with -dlopen.
-- if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then
-- dlfiles="$dlfiles $arg"
-- prev=
-- continue
-- else
-- # If libtool objects are unsupported, then we need to preload.
-- prev=dlprefiles
-+ *.$objext)
-+ # A standard object.
-+ objs="$objs $arg"
-+ ;;
-+
-+ *.lo)
-+ # A libtool-controlled object.
-+
-+ # Check to see that this really is a libtool object.
-+ if (${SED} -e '2q' $arg | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
-+ pic_object=
-+ non_pic_object=
-+
-+ # Read the .lo file
-+ # If there is no directory component, then add one.
-+ case $arg in
-+ */* | *\\*) . $arg ;;
-+ *) . ./$arg ;;
-+ esac
-+
-+ if test -z "$pic_object" || \
-+ test -z "$non_pic_object" ||
-+ test "$pic_object" = none && \
-+ test "$non_pic_object" = none; then
-+ $echo "$modename: cannot find name of object for \`$arg'" 1>&2
-+ exit $EXIT_FAILURE
-+ fi
-+
-+ # Extract subdirectory from the argument.
-+ xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'`
-+ if test "X$xdir" = "X$arg"; then
-+ xdir=
-+ else
-+ xdir="$xdir/"
-+ fi
-+
-+ if test "$pic_object" != none; then
-+ # Prepend the subdirectory the object is found in.
-+ pic_object="$xdir$pic_object"
-+
-+ if test "$prev" = dlfiles; then
-+ if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then
-+ dlfiles="$dlfiles $pic_object"
-+ prev=
-+ continue
-+ else
-+ # If libtool objects are unsupported, then we need to preload.
-+ prev=dlprefiles
-+ fi
-+ fi
-+
-+ # CHECK ME: I think I busted this. -Ossama
-+ if test "$prev" = dlprefiles; then
-+ # Preload the old-style object.
-+ dlprefiles="$dlprefiles $pic_object"
-+ prev=
-+ fi
-+
-+ # A PIC object.
-+ libobjs="$libobjs $pic_object"
-+ arg="$pic_object"
- fi
-- fi
-
-- if test "$prev" = dlprefiles; then
-- # Preload the old-style object.
-- dlprefiles="$dlprefiles "`$echo "X$arg" | $Xsed -e "$lo2o"`
-- prev=
-+ # Non-PIC object.
-+ if test "$non_pic_object" != none; then
-+ # Prepend the subdirectory the object is found in.
-+ non_pic_object="$xdir$non_pic_object"
-+
-+ # A standard non-PIC object
-+ non_pic_objects="$non_pic_objects $non_pic_object"
-+ if test -z "$pic_object" || test "$pic_object" = none ; then
-+ arg="$non_pic_object"
-+ fi
-+ else
-+ # If the PIC object exists, use it instead.
-+ # $xdir was prepended to $pic_object above.
-+ non_pic_object="$pic_object"
-+ non_pic_objects="$non_pic_objects $non_pic_object"
-+ fi
- else
-- case $arg in
-- *.lo) libobjs="$libobjs $arg" ;;
-- *) objs="$objs $arg" ;;
-- esac
-+ # Only an error if not doing a dry-run.
-+ if test -z "$run"; then
-+ $echo "$modename: \`$arg' is not a valid libtool object" 1>&2
-+ exit $EXIT_FAILURE
-+ else
-+ # Dry-run case.
-+
-+ # Extract subdirectory from the argument.
-+ xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'`
-+ if test "X$xdir" = "X$arg"; then
-+ xdir=
-+ else
-+ xdir="$xdir/"
-+ fi
-+
-+ pic_object=`$echo "X${xdir}${objdir}/${arg}" | $Xsed -e "$lo2o"`
-+ non_pic_object=`$echo "X${xdir}${arg}" | $Xsed -e "$lo2o"`
-+ libobjs="$libobjs $pic_object"
-+ non_pic_objects="$non_pic_objects $non_pic_object"
-+ fi
- fi
- ;;
-
-@@ -1285,7 +1946,7 @@
- if test -n "$prev"; then
- $echo "$modename: the \`$prevarg' option requires an argument" 1>&2
- $echo "$help" 1>&2
-- exit 1
-+ exit $EXIT_FAILURE
- fi
-
- if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then
-@@ -1294,6 +1955,7 @@
- finalize_command="$finalize_command $arg"
- fi
-
-+ oldlibs=
- # calculate the name of the file, without its directory
- outputname=`$echo "X$output" | $Xsed -e 's%^.*/%%'`
- libobjs_save="$libobjs"
-@@ -1314,12 +1976,12 @@
- output_objdir="$output_objdir/$objdir"
- fi
- # Create the object directory.
-- if test ! -d $output_objdir; then
-+ if test ! -d "$output_objdir"; then
- $show "$mkdir $output_objdir"
- $run $mkdir $output_objdir
-- status=$?
-- if test $status -ne 0 && test ! -d $output_objdir; then
-- exit $status
-+ exit_status=$?
-+ if test "$exit_status" -ne 0 && test ! -d "$output_objdir"; then
-+ exit $exit_status
- fi
- fi
-
-@@ -1328,7 +1990,7 @@
- "")
- $echo "$modename: you must specify an output file" 1>&2
- $echo "$help" 1>&2
-- exit 1
-+ exit $EXIT_FAILURE
- ;;
- *.$libext) linkmode=oldlib ;;
- *.lo | *.$objext) linkmode=obj ;;
-@@ -1336,7 +1998,17 @@
- *) linkmode=prog ;; # Anything else should be a program.
- esac
-
-+ case $host in
-+ *cygwin* | *mingw* | *pw32*)
-+ # don't eliminate duplications in $postdeps and $predeps
-+ duplicate_compiler_generated_deps=yes
-+ ;;
-+ *)
-+ duplicate_compiler_generated_deps=$duplicate_deps
-+ ;;
-+ esac
- specialdeplibs=
-+
- libs=
- # Find all interdependent deplibs by searching for libraries
- # that are linked more than once (e.g. -la -lb -la)
-@@ -1348,12 +2020,30 @@
- fi
- libs="$libs $deplib"
- done
-+
-+ if test "$linkmode" = lib; then
-+ libs="$predeps $libs $compiler_lib_search_path $postdeps"
-+
-+ # Compute libraries that are listed more than once in $predeps
-+ # $postdeps and mark them as special (i.e., whose duplicates are
-+ # not to be eliminated).
-+ pre_post_deps=
-+ if test "X$duplicate_compiler_generated_deps" = "Xyes" ; then
-+ for pre_post_dep in $predeps $postdeps; do
-+ case "$pre_post_deps " in
-+ *" $pre_post_dep "*) specialdeplibs="$specialdeplibs $pre_post_deps" ;;
-+ esac
-+ pre_post_deps="$pre_post_deps $pre_post_dep"
-+ done
-+ fi
-+ pre_post_deps=
-+ fi
-+
- deplibs=
- newdependency_libs=
- newlib_search_path=
- need_relink=no # whether we're linking any uninstalled libtool libraries
- notinst_deplibs= # not-installed libtool libraries
-- notinst_path= # paths that contain not-installed libtool libraries
- case $linkmode in
- lib)
- passes="conv link"
-@@ -1362,7 +2052,7 @@
- *.la) ;;
- *)
- $echo "$modename: libraries can \`-dlopen' only libtool libraries: $file" 1>&2
-- exit 1
-+ exit $EXIT_FAILURE
- ;;
- esac
- done
-@@ -1379,39 +2069,58 @@
- ;;
- esac
- for pass in $passes; do
-- if test $linkmode = prog; then
-- # Determine which files to process
-+ if test "$linkmode,$pass" = "lib,link" ||
-+ test "$linkmode,$pass" = "prog,scan"; then
-+ libs="$deplibs"
-+ deplibs=
-+ fi
-+ if test "$linkmode" = prog; then
- case $pass in
-- dlopen)
-- libs="$dlfiles"
-- save_deplibs="$deplibs" # Collect dlpreopened libraries
-- deplibs=
-- ;;
-+ dlopen) libs="$dlfiles" ;;
- dlpreopen) libs="$dlprefiles" ;;
-- link) libs="$deplibs %DEPLIBS% $dependency_libs" ;;
-+ link)
-+ libs="$deplibs %DEPLIBS%"
-+ test "X$link_all_deplibs" != Xno && libs="$libs $dependency_libs"
-+ ;;
- esac
- fi
-+ if test "$pass" = dlopen; then
-+ # Collect dlpreopened libraries
-+ save_deplibs="$deplibs"
-+ deplibs=
-+ fi
- for deplib in $libs; do
- lib=
- found=no
- case $deplib in
-- -l*)
-- if test $linkmode = oldlib && test $linkmode = obj; then
-- $echo "$modename: warning: \`-l' is ignored for archives/objects: $deplib" 1>&2
-- continue
-+ -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe)
-+ if test "$linkmode,$pass" = "prog,link"; then
-+ compile_deplibs="$deplib $compile_deplibs"
-+ finalize_deplibs="$deplib $finalize_deplibs"
-+ else
-+ compiler_flags="$compiler_flags $deplib"
- fi
-- if test $pass = conv; then
-- deplibs="$deplib $deplibs"
-+ continue
-+ ;;
-+ -l*)
-+ if test "$linkmode" != lib && test "$linkmode" != prog; then
-+ $echo "$modename: warning: \`-l' is ignored for archives/objects" 1>&2
- continue
- fi
- name=`$echo "X$deplib" | $Xsed -e 's/^-l//'`
- for searchdir in $newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path; do
-- # Search the libtool library
-- lib="$searchdir/lib${name}.la"
-- if test -f "$lib"; then
-- found=yes
-- break
-- fi
-+ for search_ext in .la $std_shrext .so .a; do
-+ # Search the libtool library
-+ lib="$searchdir/lib${name}${search_ext}"
-+ if test -f "$lib"; then
-+ if test "$search_ext" = ".la"; then
-+ found=yes
-+ else
-+ found=no
-+ fi
-+ break 2
-+ fi
-+ done
- done
- if test "$found" != yes; then
- # deplib doesn't seem to be a libtool library
-@@ -1420,40 +2129,76 @@
- finalize_deplibs="$deplib $finalize_deplibs"
- else
- deplibs="$deplib $deplibs"
-- test $linkmode = lib && newdependency_libs="$deplib $newdependency_libs"
-+ test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs"
- fi
- continue
-+ else # deplib is a libtool library
-+ # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib,
-+ # We need to do some special things here, and not later.
-+ if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
-+ case " $predeps $postdeps " in
-+ *" $deplib "*)
-+ if (${SED} -e '2q' $lib |
-+ grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
-+ library_names=
-+ old_library=
-+ case $lib in
-+ */* | *\\*) . $lib ;;
-+ *) . ./$lib ;;
-+ esac
-+ for l in $old_library $library_names; do
-+ ll="$l"
-+ done
-+ if test "X$ll" = "X$old_library" ; then # only static version available
-+ found=no
-+ ladir=`$echo "X$lib" | $Xsed -e 's%/[^/]*$%%'`
-+ test "X$ladir" = "X$lib" && ladir="."
-+ lib=$ladir/$old_library
-+ if test "$linkmode,$pass" = "prog,link"; then
-+ compile_deplibs="$deplib $compile_deplibs"
-+ finalize_deplibs="$deplib $finalize_deplibs"
-+ else
-+ deplibs="$deplib $deplibs"
-+ test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs"
-+ fi
-+ continue
-+ fi
-+ fi
-+ ;;
-+ *) ;;
-+ esac
-+ fi
- fi
- ;; # -l
- -L*)
- case $linkmode in
- lib)
- deplibs="$deplib $deplibs"
-- test $pass = conv && continue
-+ test "$pass" = conv && continue
- newdependency_libs="$deplib $newdependency_libs"
- newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'`
- ;;
- prog)
-- if test $pass = conv; then
-+ if test "$pass" = conv; then
- deplibs="$deplib $deplibs"
- continue
- fi
-- if test $pass = scan; then
-+ if test "$pass" = scan; then
- deplibs="$deplib $deplibs"
-- newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'`
- else
- compile_deplibs="$deplib $compile_deplibs"
- finalize_deplibs="$deplib $finalize_deplibs"
- fi
-+ newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'`
- ;;
- *)
-- $echo "$modename: warning: \`-L' is ignored for archives/objects: $deplib" 1>&2
-+ $echo "$modename: warning: \`-L' is ignored for archives/objects" 1>&2
- ;;
- esac # linkmode
- continue
- ;; # -L
- -R*)
-- if test $pass = link; then
-+ if test "$pass" = link; then
- dir=`$echo "X$deplib" | $Xsed -e 's/^-R//'`
- # Make sure the xrpath contains only unique directories.
- case "$xrpath " in
-@@ -1466,30 +2211,45 @@
- ;;
- *.la) lib="$deplib" ;;
- *.$libext)
-- if test $pass = conv; then
-+ if test "$pass" = conv; then
- deplibs="$deplib $deplibs"
- continue
- fi
- case $linkmode in
- lib)
-- if test "$deplibs_check_method" != pass_all; then
-- echo
-- echo "*** Warning: Trying to link with static lib archive $deplib."
-- echo "*** I have the capability to make that library automatically link in when"
-- echo "*** you link to this library. But I can only do this if you have a"
-- echo "*** shared version of the library, which you do not appear to have"
-- echo "*** because the file extensions .$libext of this argument makes me believe"
-- echo "*** that it is just a static archive that I should not used here."
-+ valid_a_lib=no
-+ case $deplibs_check_method in
-+ match_pattern*)
-+ set dummy $deplibs_check_method
-+ match_pattern_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"`
-+ if eval $echo \"$deplib\" 2>/dev/null \
-+ | $SED 10q \
-+ | $EGREP "$match_pattern_regex" > /dev/null; then
-+ valid_a_lib=yes
-+ fi
-+ ;;
-+ pass_all)
-+ valid_a_lib=yes
-+ ;;
-+ esac
-+ if test "$valid_a_lib" != yes; then
-+ $echo
-+ $echo "*** Warning: Trying to link with static lib archive $deplib."
-+ $echo "*** I have the capability to make that library automatically link in when"
-+ $echo "*** you link to this library. But I can only do this if you have a"
-+ $echo "*** shared version of the library, which you do not appear to have"
-+ $echo "*** because the file extensions .$libext of this argument makes me believe"
-+ $echo "*** that it is just a static archive that I should not used here."
- else
-- echo
-- echo "*** Warning: Linking the shared library $output against the"
-- echo "*** static library $deplib is not portable!"
-+ $echo
-+ $echo "*** Warning: Linking the shared library $output against the"
-+ $echo "*** static library $deplib is not portable!"
- deplibs="$deplib $deplibs"
- fi
- continue
- ;;
- prog)
-- if test $pass != link; then
-+ if test "$pass" != link; then
- deplibs="$deplib $deplibs"
- else
- compile_deplibs="$deplib $compile_deplibs"
-@@ -1500,14 +2260,18 @@
- esac # linkmode
- ;; # *.$libext
- *.lo | *.$objext)
-- if test $pass = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then
-- # If there is no dlopen support or we're linking statically,
-- # we need to preload.
-- newdlprefiles="$newdlprefiles $deplib"
-- compile_deplibs="$deplib $compile_deplibs"
-- finalize_deplibs="$deplib $finalize_deplibs"
-- else
-- newdlfiles="$newdlfiles $deplib"
-+ if test "$pass" = conv; then
-+ deplibs="$deplib $deplibs"
-+ elif test "$linkmode" = prog; then
-+ if test "$pass" = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then
-+ # If there is no dlopen support or we're linking statically,
-+ # we need to preload.
-+ newdlprefiles="$newdlprefiles $deplib"
-+ compile_deplibs="$deplib $compile_deplibs"
-+ finalize_deplibs="$deplib $finalize_deplibs"
-+ else
-+ newdlfiles="$newdlfiles $deplib"
-+ fi
- fi
- continue
- ;;
-@@ -1516,17 +2280,17 @@
- continue
- ;;
- esac # case $deplib
-- if test $found = yes || test -f "$lib"; then :
-+ if test "$found" = yes || test -f "$lib"; then :
- else
-- $echo "$modename: cannot find the library \`$lib'" 1>&2
-- exit 1
-+ $echo "$modename: cannot find the library \`$lib' or unhandled argument \`$deplib'" 1>&2
-+ exit $EXIT_FAILURE
- fi
-
- # Check to see that this really is a libtool archive.
-- if (${SED} -e '2q' $lib | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then :
-+ if (${SED} -e '2q' $lib | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then :
- else
- $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2
-- exit 1
-+ exit $EXIT_FAILURE
- fi
-
- ladir=`$echo "X$lib" | $Xsed -e 's%/[^/]*$%%'`
-@@ -1539,8 +2303,11 @@
- library_names=
- old_library=
- # If the library was installed with an old release of libtool,
-- # it will not redefine variable installed.
-+ # it will not redefine variables installed, or shouldnotlink
- installed=yes
-+ shouldnotlink=no
-+ avoidtemprpath=
-+
-
- # Read the .la file
- case $lib in
-@@ -1550,19 +2317,18 @@
-
- if test "$linkmode,$pass" = "lib,link" ||
- test "$linkmode,$pass" = "prog,scan" ||
-- { test $linkmode = oldlib && test $linkmode = obj; }; then
-- # Add dl[pre]opened files of deplib
-+ { test "$linkmode" != prog && test "$linkmode" != lib; }; then
- test -n "$dlopen" && dlfiles="$dlfiles $dlopen"
- test -n "$dlpreopen" && dlprefiles="$dlprefiles $dlpreopen"
- fi
-
-- if test $pass = conv; then
-+ if test "$pass" = conv; then
- # Only check for convenience libraries
- deplibs="$lib $deplibs"
- if test -z "$libdir"; then
- if test -z "$old_library"; then
- $echo "$modename: cannot find name of link library for \`$lib'" 1>&2
-- exit 1
-+ exit $EXIT_FAILURE
- fi
- # It is a libtool convenience library, so add in its objects.
- convenience="$convenience $ladir/$objdir/$old_library"
-@@ -1577,13 +2343,14 @@
- fi
- tmp_libs="$tmp_libs $deplib"
- done
-- elif test $linkmode != prog && test $linkmode != lib; then
-+ elif test "$linkmode" != prog && test "$linkmode" != lib; then
- $echo "$modename: \`$lib' is not a convenience library" 1>&2
-- exit 1
-+ exit $EXIT_FAILURE
- fi
- continue
- fi # $pass = conv
-
-+
- # Get the name of the library we link against.
- linklib=
- for l in $old_library $library_names; do
-@@ -1591,19 +2358,23 @@
- done
- if test -z "$linklib"; then
- $echo "$modename: cannot find name of link library for \`$lib'" 1>&2
-- exit 1
-+ exit $EXIT_FAILURE
- fi
-
- # This library was specified with -dlopen.
-- if test $pass = dlopen; then
-+ if test "$pass" = dlopen; then
- if test -z "$libdir"; then
- $echo "$modename: cannot -dlopen a convenience library: \`$lib'" 1>&2
-- exit 1
-+ exit $EXIT_FAILURE
- fi
-- if test -z "$dlname" || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then
-+ if test -z "$dlname" ||
-+ test "$dlopen_support" != yes ||
-+ test "$build_libtool_libs" = no; then
- # If there is no dlname, no dlopen support or we're linking
-- # statically, we need to preload.
-- dlprefiles="$dlprefiles $lib"
-+ # statically, we need to preload. We also need to preload any
-+ # dependent libraries so libltdl's deplib preloader doesn't
-+ # bomb out in the load deplibs phase.
-+ dlprefiles="$dlprefiles $lib $dependency_libs"
- else
- newdlfiles="$newdlfiles $lib"
- fi
-@@ -1635,19 +2406,27 @@
- dir="$libdir"
- absdir="$libdir"
- fi
-+ test "X$hardcode_automatic" = Xyes && avoidtemprpath=yes
- else
-- dir="$ladir/$objdir"
-- absdir="$abs_ladir/$objdir"
-- # Remove this search path later
-- notinst_path="$notinst_path $abs_ladir"
-+ if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then
-+ dir="$ladir"
-+ absdir="$abs_ladir"
-+ # Remove this search path later
-+ notinst_path="$notinst_path $abs_ladir"
-+ else
-+ dir="$ladir/$objdir"
-+ absdir="$abs_ladir/$objdir"
-+ # Remove this search path later
-+ notinst_path="$notinst_path $abs_ladir"
-+ fi
- fi # $installed = yes
- name=`$echo "X$laname" | $Xsed -e 's/\.la$//' -e 's/^lib//'`
-
- # This library was specified with -dlpreopen.
-- if test $pass = dlpreopen; then
-+ if test "$pass" = dlpreopen; then
- if test -z "$libdir"; then
- $echo "$modename: cannot -dlpreopen a convenience library: \`$lib'" 1>&2
-- exit 1
-+ exit $EXIT_FAILURE
- fi
- # Prefer using a static library (so that no silly _DYNAMIC symbols
- # are required to link).
-@@ -1663,18 +2442,19 @@
-
- if test -z "$libdir"; then
- # Link the convenience library
-- if test $linkmode = lib; then
-+ if test "$linkmode" = lib; then
- deplibs="$dir/$old_library $deplibs"
- elif test "$linkmode,$pass" = "prog,link"; then
- compile_deplibs="$dir/$old_library $compile_deplibs"
- finalize_deplibs="$dir/$old_library $finalize_deplibs"
- else
-- deplibs="$lib $deplibs"
-+ deplibs="$lib $deplibs" # used for prog,scan pass
- fi
- continue
- fi
-
-- if test $linkmode = prog && test $pass != link; then
-+
-+ if test "$linkmode" = prog && test "$pass" != link; then
- newlib_search_path="$newlib_search_path $ladir"
- deplibs="$lib $deplibs"
-
-@@ -1690,7 +2470,7 @@
- -L*) newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'`;; ### testsuite: skip nested quoting test
- esac
- # Need to link against all dependency_libs?
-- if test $linkalldeplibs = yes; then
-+ if test "$linkalldeplibs" = yes; then
- deplibs="$deplib $deplibs"
- else
- # Need to hardcode shared library paths
-@@ -1707,13 +2487,19 @@
- continue
- fi # $linkmode = prog...
-
-- link_static=no # Whether the deplib will be linked statically
-- if test -n "$library_names" &&
-- { test "$prefer_static_libs" = no || test -z "$old_library"; }; then
-- # Link against this shared library
-+ if test "$linkmode,$pass" = "prog,link"; then
-+ if test -n "$library_names" &&
-+ { test "$prefer_static_libs" = no || test -z "$old_library"; }; then
-+ # We need to hardcode the library path
-+ if test -n "$shlibpath_var" && test -z "$avoidtemprpath" ; then
-+ # Make sure the rpath contains only unique directories.
-+ case "$temp_rpath " in
-+ *" $dir "*) ;;
-+ *" $absdir "*) ;;
-+ *) temp_rpath="$temp_rpath $absdir" ;;
-+ esac
-+ fi
-
-- if test "$linkmode,$pass" = "prog,link" ||
-- { test $linkmode = lib && test $hardcode_into_libs = yes; }; then
- # Hardcode the library path.
- # Skip directories that are in the system default run-time
- # search path.
-@@ -1735,17 +2521,6 @@
- esac
- ;;
- esac
-- if test $linkmode = prog; then
-- # We need to hardcode the library path
-- if test -n "$shlibpath_var"; then
-- # Make sure the rpath contains only unique directories.
-- case "$temp_rpath " in
-- *" $dir "*) ;;
-- *" $absdir "*) ;;
-- *) temp_rpath="$temp_rpath $dir" ;;
-- esac
-- fi
-- fi
- fi # $linkmode,$pass = prog,link...
-
- if test "$alldeplibs" = yes &&
-@@ -1755,11 +2530,56 @@
- # We only need to search for static libraries
- continue
- fi
-+ fi
-
-+ link_static=no # Whether the deplib will be linked statically
-+ use_static_libs=$prefer_static_libs
-+ if test "$use_static_libs" = built && test "$installed" = yes ; then
-+ use_static_libs=no
-+ fi
-+ if test -n "$library_names" &&
-+ { test "$use_static_libs" = no || test -z "$old_library"; }; then
- if test "$installed" = no; then
- notinst_deplibs="$notinst_deplibs $lib"
- need_relink=yes
- fi
-+ # This is a shared library
-+
-+ # Warn about portability, can't link against -module's on
-+ # some systems (darwin)
-+ if test "$shouldnotlink" = yes && test "$pass" = link ; then
-+ $echo
-+ if test "$linkmode" = prog; then
-+ $echo "*** Warning: Linking the executable $output against the loadable module"
-+ else
-+ $echo "*** Warning: Linking the shared library $output against the loadable module"
-+ fi
-+ $echo "*** $linklib is not portable!"
-+ fi
-+ if test "$linkmode" = lib &&
-+ test "$hardcode_into_libs" = yes; then
-+ # Hardcode the library path.
-+ # Skip directories that are in the system default run-time
-+ # search path.
-+ case " $sys_lib_dlsearch_path " in
-+ *" $absdir "*) ;;
-+ *)
-+ case "$compile_rpath " in
-+ *" $absdir "*) ;;
-+ *) compile_rpath="$compile_rpath $absdir"
-+ esac
-+ ;;
-+ esac
-+ case " $sys_lib_dlsearch_path " in
-+ *" $libdir "*) ;;
-+ *)
-+ case "$finalize_rpath " in
-+ *" $libdir "*) ;;
-+ *) finalize_rpath="$finalize_rpath $libdir"
-+ esac
-+ ;;
-+ esac
-+ fi
-
- if test -n "$old_archive_from_expsyms_cmds"; then
- # figure out the soname
-@@ -1773,7 +2593,7 @@
- elif test -n "$soname_spec"; then
- # bleh windows
- case $host in
-- *cygwin*)
-+ *cygwin* | mingw*)
- major=`expr $current - $age`
- versuffix="-$major"
- ;;
-@@ -1785,17 +2605,18 @@
-
- # Make a new name for the extract_expsyms_cmds to use
- soroot="$soname"
-- soname=`echo $soroot | ${SED} -e 's/^.*\///'`
-- newlib="libimp-`echo $soname | ${SED} 's/^lib//;s/\.dll$//'`.a"
-+ soname=`$echo $soroot | ${SED} -e 's/^.*\///'`
-+ newlib="libimp-`$echo $soname | ${SED} 's/^lib//;s/\.dll$//'`.a"
-
- # If the library has no export list, then create one now
- if test -f "$output_objdir/$soname-def"; then :
- else
- $show "extracting exported symbol list from \`$soname'"
- save_ifs="$IFS"; IFS='~'
-- eval cmds=\"$extract_expsyms_cmds\"
-+ cmds=$extract_expsyms_cmds
- for cmd in $cmds; do
- IFS="$save_ifs"
-+ eval cmd=\"$cmd\"
- $show "$cmd"
- $run eval "$cmd" || exit $?
- done
-@@ -1806,9 +2627,10 @@
- if test -f "$output_objdir/$newlib"; then :; else
- $show "generating import library for \`$soname'"
- save_ifs="$IFS"; IFS='~'
-- eval cmds=\"$old_archive_from_expsyms_cmds\"
-+ cmds=$old_archive_from_expsyms_cmds
- for cmd in $cmds; do
- IFS="$save_ifs"
-+ eval cmd=\"$cmd\"
- $show "$cmd"
- $run eval "$cmd" || exit $?
- done
-@@ -1817,9 +2639,9 @@
- # make sure the library variables are pointing to the new library
- dir=$output_objdir
- linklib=$newlib
-- fi # test -n $old_archive_from_expsyms_cmds
-+ fi # test -n "$old_archive_from_expsyms_cmds"
-
-- if test $linkmode = prog || test "$mode" != relink; then
-+ if test "$linkmode" = prog || test "$mode" != relink; then
- add_shlibpath=
- add_dir=
- add=
-@@ -1828,6 +2650,26 @@
- immediate | unsupported)
- if test "$hardcode_direct" = no; then
- add="$dir/$linklib"
-+ case $host in
-+ *-*-sco3.2v5.0.[024]*) add_dir="-L$dir" ;;
-+ *-*-sysv4*uw2*) add_dir="-L$dir" ;;
-+ *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \
-+ *-*-unixware7*) add_dir="-L$dir" ;;
-+ *-*-darwin* )
-+ # if the lib is a module then we can not link against
-+ # it, someone is ignoring the new warnings I added
-+ if /usr/bin/file -L $add 2> /dev/null |
-+ $EGREP ": [^:]* bundle" >/dev/null ; then
-+ $echo "** Warning, lib $linklib is a module, not a shared library"
-+ if test -z "$old_library" ; then
-+ $echo
-+ $echo "** And there doesn't seem to be a static archive available"
-+ $echo "** The link will probably fail, sorry"
-+ else
-+ add="$dir/$old_library"
-+ fi
-+ fi
-+ esac
- elif test "$hardcode_minus_L" = no; then
- case $host in
- *-*-sunos*) add_shlibpath="$dir" ;;
-@@ -1846,6 +2688,14 @@
- add="$dir/$linklib"
- elif test "$hardcode_minus_L" = yes; then
- add_dir="-L$dir"
-+ # Try looking first in the location we're being installed to.
-+ if test -n "$inst_prefix_dir"; then
-+ case $libdir in
-+ [\\/]*)
-+ add_dir="$add_dir -L$inst_prefix_dir$libdir"
-+ ;;
-+ esac
-+ fi
- add="-l$name"
- elif test "$hardcode_shlibpath_var" = yes; then
- add_shlibpath="$dir"
-@@ -1859,7 +2709,7 @@
-
- if test "$lib_linked" != yes; then
- $echo "$modename: configuration error: unsupported hardcode properties"
-- exit 1
-+ exit $EXIT_FAILURE
- fi
-
- if test -n "$add_shlibpath"; then
-@@ -1868,7 +2718,7 @@
- *) compile_shlibpath="$compile_shlibpath$add_shlibpath:" ;;
- esac
- fi
-- if test $linkmode = prog; then
-+ if test "$linkmode" = prog; then
- test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs"
- test -n "$add" && compile_deplibs="$add $compile_deplibs"
- else
-@@ -1885,7 +2735,7 @@
- fi
- fi
-
-- if test $linkmode = prog || test "$mode" = relink; then
-+ if test "$linkmode" = prog || test "$mode" = relink; then
- add_shlibpath=
- add_dir=
- add=
-@@ -1901,13 +2751,28 @@
- *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;;
- esac
- add="-l$name"
-+ elif test "$hardcode_automatic" = yes; then
-+ if test -n "$inst_prefix_dir" &&
-+ test -f "$inst_prefix_dir$libdir/$linklib" ; then
-+ add="$inst_prefix_dir$libdir/$linklib"
-+ else
-+ add="$libdir/$linklib"
-+ fi
- else
- # We cannot seem to hardcode it, guess we'll fake it.
- add_dir="-L$libdir"
-+ # Try looking first in the location we're being installed to.
-+ if test -n "$inst_prefix_dir"; then
-+ case $libdir in
-+ [\\/]*)
-+ add_dir="$add_dir -L$inst_prefix_dir$libdir"
-+ ;;
-+ esac
-+ fi
- add="-l$name"
- fi
-
-- if test $linkmode = prog; then
-+ if test "$linkmode" = prog; then
- test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs"
- test -n "$add" && finalize_deplibs="$add $finalize_deplibs"
- else
-@@ -1915,16 +2780,7 @@
- test -n "$add" && deplibs="$add $deplibs"
- fi
- fi
-- elif test $linkmode = prog; then
-- if test "$alldeplibs" = yes &&
-- { test "$deplibs_check_method" = pass_all ||
-- { test "$build_libtool_libs" = yes &&
-- test -n "$library_names"; }; }; then
-- # We only need to search for static libraries
-- continue
-- fi
--
-- # Try to link the static library
-+ elif test "$linkmode" = prog; then
- # Here we assume that one of hardcode_direct or hardcode_minus_L
- # is not unsupported. This is valid on all known static and
- # shared platforms.
-@@ -1944,21 +2800,21 @@
-
- # Just print a warning and add the library to dependency_libs so
- # that the program can be linked against the static library.
-- echo
-- echo "*** Warning: This system can not link to static lib archive $lib."
-- echo "*** I have the capability to make that library automatically link in when"
-- echo "*** you link to this library. But I can only do this if you have a"
-- echo "*** shared version of the library, which you do not appear to have."
-+ $echo
-+ $echo "*** Warning: This system can not link to static lib archive $lib."
-+ $echo "*** I have the capability to make that library automatically link in when"
-+ $echo "*** you link to this library. But I can only do this if you have a"
-+ $echo "*** shared version of the library, which you do not appear to have."
- if test "$module" = yes; then
-- echo "*** But as you try to build a module library, libtool will still create "
-- echo "*** a static module, that should work as long as the dlopening application"
-- echo "*** is linked with the -dlopen flag to resolve symbols at runtime."
-+ $echo "*** But as you try to build a module library, libtool will still create "
-+ $echo "*** a static module, that should work as long as the dlopening application"
-+ $echo "*** is linked with the -dlopen flag to resolve symbols at runtime."
- if test -z "$global_symbol_pipe"; then
-- echo
-- echo "*** However, this would only work if libtool was able to extract symbol"
-- echo "*** lists from a program, using \`nm' or equivalent, but libtool could"
-- echo "*** not find such a program. So, this module is probably useless."
-- echo "*** \`nm' from GNU binutils and a full rebuild may help."
-+ $echo
-+ $echo "*** However, this would only work if libtool was able to extract symbol"
-+ $echo "*** lists from a program, using \`nm' or equivalent, but libtool could"
-+ $echo "*** not find such a program. So, this module is probably useless."
-+ $echo "*** \`nm' from GNU binutils and a full rebuild may help."
- fi
- if test "$build_old_libs" = no; then
- build_libtool_libs=module
-@@ -1968,17 +2824,16 @@
- fi
- fi
- else
-- convenience="$convenience $dir/$old_library"
-- old_convenience="$old_convenience $dir/$old_library"
- deplibs="$dir/$old_library $deplibs"
- link_static=yes
- fi
- fi # link shared/static library?
-
-- if test $linkmode = lib; then
-+ if test "$linkmode" = lib; then
- if test -n "$dependency_libs" &&
-- { test $hardcode_into_libs != yes || test $build_old_libs = yes ||
-- test $link_static = yes; }; then
-+ { test "$hardcode_into_libs" != yes ||
-+ test "$build_old_libs" = yes ||
-+ test "$link_static" = yes; }; then
- # Extract -R from dependency_libs
- temp_deplibs=
- for libdir in $dependency_libs; do
-@@ -2009,7 +2864,7 @@
- tmp_libs="$tmp_libs $deplib"
- done
-
-- if test $link_all_deplibs != no; then
-+ if test "$link_all_deplibs" != no; then
- # Add the search paths of all dependency libraries
- for deplib in $dependency_libs; do
- case $deplib in
-@@ -2029,38 +2884,83 @@
- ;;
- esac
- if grep "^installed=no" $deplib > /dev/null; then
-- path="-L$absdir/$objdir"
-+ path="$absdir/$objdir"
- else
- eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib`
- if test -z "$libdir"; then
- $echo "$modename: \`$deplib' is not a valid libtool archive" 1>&2
-- exit 1
-+ exit $EXIT_FAILURE
- fi
- if test "$absdir" != "$libdir"; then
- $echo "$modename: warning: \`$deplib' seems to be moved" 1>&2
- fi
-- path="-L$absdir"
-+ path="$absdir"
- fi
-+ depdepl=
-+ case $host in
-+ *-*-darwin*)
-+ # we do not want to link against static libs,
-+ # but need to link against shared
-+ eval deplibrary_names=`${SED} -n -e 's/^library_names=\(.*\)$/\1/p' $deplib`
-+ if test -n "$deplibrary_names" ; then
-+ for tmp in $deplibrary_names ; do
-+ depdepl=$tmp
-+ done
-+ if test -f "$path/$depdepl" ; then
-+ depdepl="$path/$depdepl"
-+ fi
-+ # do not add paths which are already there
-+ case " $newlib_search_path " in
-+ *" $path "*) ;;
-+ *) newlib_search_path="$newlib_search_path $path";;
-+ esac
-+ fi
-+ path=""
-+ ;;
-+ *)
-+ path="-L$path"
-+ ;;
-+ esac
-+ ;;
-+ -l*)
-+ case $host in
-+ *-*-darwin*)
-+ # Again, we only want to link against shared libraries
-+ eval tmp_libs=`$echo "X$deplib" | $Xsed -e "s,^\-l,,"`
-+ for tmp in $newlib_search_path ; do
-+ if test -f "$tmp/lib$tmp_libs.dylib" ; then
-+ eval depdepl="$tmp/lib$tmp_libs.dylib"
-+ break
-+ fi
-+ done
-+ path=""
-+ ;;
-+ *) continue ;;
-+ esac
- ;;
- *) continue ;;
- esac
- case " $deplibs " in
- *" $path "*) ;;
-- *) deplibs="$deplibs $path" ;;
-+ *) deplibs="$path $deplibs" ;;
-+ esac
-+ case " $deplibs " in
-+ *" $depdepl "*) ;;
-+ *) deplibs="$depdepl $deplibs" ;;
- esac
- done
- fi # link_all_deplibs != no
- fi # linkmode = lib
- done # for deplib in $libs
-- if test $pass = dlpreopen; then
-+ dependency_libs="$newdependency_libs"
-+ if test "$pass" = dlpreopen; then
- # Link the dlpreopened libraries before other libraries
- for deplib in $save_deplibs; do
- deplibs="$deplib $deplibs"
- done
- fi
-- if test $pass != dlopen; then
-- test $pass != scan && dependency_libs="$newdependency_libs"
-- if test $pass != conv; then
-+ if test "$pass" != dlopen; then
-+ if test "$pass" != conv; then
- # Make sure lib_search_path contains only unique directories.
- lib_search_path=
- for dir in $newlib_search_path; do
-@@ -2082,9 +2982,30 @@
- eval tmp_libs=\"\$$var\"
- new_libs=
- for deplib in $tmp_libs; do
-+ # FIXME: Pedantically, this is the right thing to do, so
-+ # that some nasty dependency loop isn't accidentally
-+ # broken:
-+ #new_libs="$deplib $new_libs"
-+ # Pragmatically, this seems to cause very few problems in
-+ # practice:
- case $deplib in
- -L*) new_libs="$deplib $new_libs" ;;
-+ -R*) ;;
- *)
-+ # And here is the reason: when a library appears more
-+ # than once as an explicit dependence of a library, or
-+ # is implicitly linked in more than once by the
-+ # compiler, it is considered special, and multiple
-+ # occurrences thereof are not removed. Compare this
-+ # with having the same library being listed as a
-+ # dependency of multiple other libraries: in this case,
-+ # we know (pedantically, we assume) the library does not
-+ # need to be listed more than once, so we keep only the
-+ # last copy. This is not always right, but it is rare
-+ # enough that we require users that really mean to play
-+ # such unportable linking tricks to link the library
-+ # using -Wl,-lname, so that libtool does not consider it
-+ # for duplicate removal.
- case " $specialdeplibs " in
- *" $deplib "*) new_libs="$deplib $new_libs" ;;
- *)
-@@ -2112,19 +3033,32 @@
- eval $var=\"$tmp_libs\"
- done # for var
- fi
-- if test "$pass" = "conv" &&
-- { test "$linkmode" = "lib" || test "$linkmode" = "prog"; }; then
-- libs="$deplibs" # reset libs
-- deplibs=
-- fi
-+ # Last step: remove runtime libs from dependency_libs
-+ # (they stay in deplibs)
-+ tmp_libs=
-+ for i in $dependency_libs ; do
-+ case " $predeps $postdeps $compiler_lib_search_path " in
-+ *" $i "*)
-+ i=""
-+ ;;
-+ esac
-+ if test -n "$i" ; then
-+ tmp_libs="$tmp_libs $i"
-+ fi
-+ done
-+ dependency_libs=$tmp_libs
- done # for pass
-- if test $linkmode = prog; then
-+ if test "$linkmode" = prog; then
- dlfiles="$newdlfiles"
- dlprefiles="$newdlprefiles"
- fi
-
- case $linkmode in
- oldlib)
-+ if test -n "$deplibs"; then
-+ $echo "$modename: warning: \`-l' and \`-L' are ignored for archives" 1>&2
-+ fi
-+
- if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
- $echo "$modename: warning: \`-dlopen' is ignored for archives" 1>&2
- fi
-@@ -2138,7 +3072,7 @@
- fi
-
- if test -n "$vinfo"; then
-- $echo "$modename: warning: \`-version-info' is ignored for archives" 1>&2
-+ $echo "$modename: warning: \`-version-info/-version-number' is ignored for archives" 1>&2
- fi
-
- if test -n "$release"; then
-@@ -2160,17 +3094,19 @@
- case $outputname in
- lib*)
- name=`$echo "X$outputname" | $Xsed -e 's/\.la$//' -e 's/^lib//'`
-+ eval shared_ext=\"$shrext_cmds\"
- eval libname=\"$libname_spec\"
- ;;
- *)
- if test "$module" = no; then
- $echo "$modename: libtool library \`$output' must begin with \`lib'" 1>&2
- $echo "$help" 1>&2
-- exit 1
-+ exit $EXIT_FAILURE
- fi
- if test "$need_lib_prefix" != no; then
- # Add the "lib" prefix for modules if required
- name=`$echo "X$outputname" | $Xsed -e 's/\.la$//'`
-+ eval shared_ext=\"$shrext_cmds\"
- eval libname=\"$libname_spec\"
- else
- libname=`$echo "X$outputname" | $Xsed -e 's/\.la$//'`
-@@ -2181,11 +3117,11 @@
- if test -n "$objs"; then
- if test "$deplibs_check_method" != pass_all; then
- $echo "$modename: cannot build libtool library \`$output' from non-libtool objects on this host:$objs" 2>&1
-- exit 1
-+ exit $EXIT_FAILURE
- else
-- echo
-- echo "*** Warning: Linking the shared library $output against the non-libtool"
-- echo "*** objects $objs is not portable!"
-+ $echo
-+ $echo "*** Warning: Linking the shared library $output against the non-libtool"
-+ $echo "*** objects $objs is not portable!"
- libobjs="$libobjs $objs"
- fi
- fi
-@@ -2195,7 +3131,7 @@
- fi
-
- set dummy $rpath
-- if test $# -gt 2; then
-+ if test "$#" -gt 2; then
- $echo "$modename: warning: ignoring multiple \`-rpath's for a libtool library" 1>&2
- fi
- install_libdir="$2"
-@@ -2204,14 +3140,16 @@
- if test -z "$rpath"; then
- if test "$build_libtool_libs" = yes; then
- # Building a libtool convenience library.
-- libext=al
-+ # Some compilers have problems with a `.al' extension so
-+ # convenience libraries should have the same extension an
-+ # archive normally would.
- oldlibs="$output_objdir/$libname.$libext $oldlibs"
- build_libtool_libs=convenience
- build_old_libs=yes
- fi
-
- if test -n "$vinfo"; then
-- $echo "$modename: warning: \`-version-info' is ignored for convenience libraries" 1>&2
-+ $echo "$modename: warning: \`-version-info/-version-number' is ignored for convenience libraries" 1>&2
- fi
-
- if test -n "$release"; then
-@@ -2227,45 +3165,87 @@
- if test -n "$8"; then
- $echo "$modename: too many parameters to \`-version-info'" 1>&2
- $echo "$help" 1>&2
-- exit 1
-+ exit $EXIT_FAILURE
- fi
-
-- current="$2"
-- revision="$3"
-- age="$4"
-+ # convert absolute version numbers to libtool ages
-+ # this retains compatibility with .la files and attempts
-+ # to make the code below a bit more comprehensible
-+
-+ case $vinfo_number in
-+ yes)
-+ number_major="$2"
-+ number_minor="$3"
-+ number_revision="$4"
-+ #
-+ # There are really only two kinds -- those that
-+ # use the current revision as the major version
-+ # and those that subtract age and use age as
-+ # a minor version. But, then there is irix
-+ # which has an extra 1 added just for fun
-+ #
-+ case $version_type in
-+ darwin|linux|osf|windows)
-+ current=`expr $number_major + $number_minor`
-+ age="$number_minor"
-+ revision="$number_revision"
-+ ;;
-+ freebsd-aout|freebsd-elf|sunos)
-+ current="$number_major"
-+ revision="$number_minor"
-+ age="0"
-+ ;;
-+ irix|nonstopux)
-+ current=`expr $number_major + $number_minor - 1`
-+ age="$number_minor"
-+ revision="$number_minor"
-+ ;;
-+ *)
-+ $echo "$modename: unknown library version type \`$version_type'" 1>&2
-+ $echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2
-+ exit $EXIT_FAILURE
-+ ;;
-+ esac
-+ ;;
-+ no)
-+ current="$2"
-+ revision="$3"
-+ age="$4"
-+ ;;
-+ esac
-
- # Check that each of the things are valid numbers.
- case $current in
-- 0 | [1-9] | [1-9][0-9] | [1-9][0-9][0-9]) ;;
-+ 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
- *)
-- $echo "$modename: CURRENT \`$current' is not a nonnegative integer" 1>&2
-+ $echo "$modename: CURRENT \`$current' must be a nonnegative integer" 1>&2
- $echo "$modename: \`$vinfo' is not valid version information" 1>&2
-- exit 1
-+ exit $EXIT_FAILURE
- ;;
- esac
-
- case $revision in
-- 0 | [1-9] | [1-9][0-9] | [1-9][0-9][0-9]) ;;
-+ 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
- *)
-- $echo "$modename: REVISION \`$revision' is not a nonnegative integer" 1>&2
-+ $echo "$modename: REVISION \`$revision' must be a nonnegative integer" 1>&2
- $echo "$modename: \`$vinfo' is not valid version information" 1>&2
-- exit 1
-+ exit $EXIT_FAILURE
- ;;
- esac
-
- case $age in
-- 0 | [1-9] | [1-9][0-9] | [1-9][0-9][0-9]) ;;
-+ 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
- *)
-- $echo "$modename: AGE \`$age' is not a nonnegative integer" 1>&2
-+ $echo "$modename: AGE \`$age' must be a nonnegative integer" 1>&2
- $echo "$modename: \`$vinfo' is not valid version information" 1>&2
-- exit 1
-+ exit $EXIT_FAILURE
- ;;
- esac
-
-- if test $age -gt $current; then
-+ if test "$age" -gt "$current"; then
- $echo "$modename: AGE \`$age' is greater than the current interface number \`$current'" 1>&2
- $echo "$modename: \`$vinfo' is not valid version information" 1>&2
-- exit 1
-+ exit $EXIT_FAILURE
- fi
-
- # Calculate the version variables.
-@@ -2282,7 +3262,7 @@
- versuffix="$major.$age.$revision"
- # Darwin ld doesn't like 0 for these options...
- minor_current=`expr $current + 1`
-- verstring="-compatibility_version $minor_current -current_version $minor_current.$revision"
-+ verstring="${wl}-compatibility_version ${wl}$minor_current ${wl}-current_version ${wl}$minor_current.$revision"
- ;;
-
- freebsd-aout)
-@@ -2306,7 +3286,7 @@
-
- # Add in all the interfaces that we are compatible with.
- loop=$revision
-- while test $loop != 0; do
-+ while test "$loop" -ne 0; do
- iface=`expr $revision - $loop`
- loop=`expr $loop - 1`
- verstring="$verstring_prefix$major.$iface:$verstring"
-@@ -2329,7 +3309,7 @@
-
- # Add in all the interfaces that we are compatible with.
- loop=$age
-- while test $loop != 0; do
-+ while test "$loop" -ne 0; do
- iface=`expr $current - $loop`
- loop=`expr $loop - 1`
- verstring="$verstring:${iface}.0"
-@@ -2353,20 +3333,19 @@
-
- *)
- $echo "$modename: unknown library version type \`$version_type'" 1>&2
-- echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2
-- exit 1
-+ $echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2
-+ exit $EXIT_FAILURE
- ;;
- esac
-
- # Clear the version info if we defaulted, and they specified a release.
- if test -z "$vinfo" && test -n "$release"; then
- major=
-- verstring="0.0"
- case $version_type in
- darwin)
- # we can't check for "0.0" in archive_cmds due to quoting
- # problems, so we reset it completely
-- verstring=""
-+ verstring=
- ;;
- *)
- verstring="0.0"
-@@ -2400,9 +3379,30 @@
- fi
-
- if test "$mode" != relink; then
-- # Remove our outputs.
-- $show "${rm}r $output_objdir/$outputname $output_objdir/$libname.* $output_objdir/${libname}${release}.*"
-- $run ${rm}r $output_objdir/$outputname $output_objdir/$libname.* $output_objdir/${libname}${release}.*
-+ # Remove our outputs, but don't remove object files since they
-+ # may have been created when compiling PIC objects.
-+ removelist=
-+ tempremovelist=`$echo "$output_objdir/*"`
-+ for p in $tempremovelist; do
-+ case $p in
-+ *.$objext)
-+ ;;
-+ $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/${libname}${release}.*)
-+ if test "X$precious_files_regex" != "X"; then
-+ if echo $p | $EGREP -e "$precious_files_regex" >/dev/null 2>&1
-+ then
-+ continue
-+ fi
-+ fi
-+ removelist="$removelist $p"
-+ ;;
-+ *) ;;
-+ esac
-+ done
-+ if test -n "$removelist"; then
-+ $show "${rm}r $removelist"
-+ $run ${rm}r $removelist
-+ fi
- fi
-
- # Now set the variables for building old libraries.
-@@ -2415,9 +3415,9 @@
-
- # Eliminate all temporary directories.
- for path in $notinst_path; do
-- lib_search_path=`echo "$lib_search_path " | ${SED} -e 's% $path % %g'`
-- deplibs=`echo "$deplibs " | ${SED} -e 's% -L$path % %g'`
-- dependency_libs=`echo "$dependency_libs " | ${SED} -e 's% -L$path % %g'`
-+ lib_search_path=`$echo "$lib_search_path " | ${SED} -e "s% $path % %g"`
-+ deplibs=`$echo "$deplibs " | ${SED} -e "s% -L$path % %g"`
-+ dependency_libs=`$echo "$dependency_libs " | ${SED} -e "s% -L$path % %g"`
- done
-
- if test -n "$xrpath"; then
-@@ -2430,7 +3430,7 @@
- *) finalize_rpath="$finalize_rpath $libdir" ;;
- esac
- done
-- if test $hardcode_into_libs != yes || test $build_old_libs = yes; then
-+ if test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes; then
- dependency_libs="$temp_xrpath $dependency_libs"
- fi
- fi
-@@ -2468,12 +3468,18 @@
- *-*-netbsd*)
- # Don't link with libc until the a.out ld.so is fixed.
- ;;
-- *-*-openbsd* | *-*-freebsd*)
-+ *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*)
- # Do not include libc due to us having libc/libc_r.
- ;;
-- *)
-+ *-*-sco3.2v5* | *-*-sco5v6*)
-+ # Causes problems with __ctype
-+ ;;
-+ *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*)
-+ # Compiler inserts libc in the correct place for threads to work
-+ ;;
-+ *)
- # Add libc to deplibs on all other systems if necessary.
-- if test $build_libtool_need_lc = "yes"; then
-+ if test "$build_libtool_need_lc" = "yes"; then
- deplibs="$deplibs -lc"
- fi
- ;;
-@@ -2500,7 +3506,7 @@
- # This might be a little naive. We might want to check
- # whether the library exists or not. But this is on
- # osf3 & osf4 and I'm not really sure... Just
-- # implementing what was already the behaviour.
-+ # implementing what was already the behavior.
- newdeplibs=$deplibs
- ;;
- test_compile)
-@@ -2513,68 +3519,88 @@
- int main() { return 0; }
- EOF
- $rm conftest
-- $CC -o conftest conftest.c $deplibs
-- if test $? -eq 0 ; then
-+ $LTCC $LTCFLAGS -o conftest conftest.c $deplibs
-+ if test "$?" -eq 0 ; then
- ldd_output=`ldd conftest`
- for i in $deplibs; do
-- name="`expr $i : '-l\(.*\)'`"
-+ name=`expr $i : '-l\(.*\)'`
- # If $name is empty we are operating on a -L argument.
-- if test -n "$name" && test "$name" != "0"; then
-- libname=`eval \\$echo \"$libname_spec\"`
-- deplib_matches=`eval \\$echo \"$library_names_spec\"`
-- set dummy $deplib_matches
-- deplib_match=$2
-- if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then
-- newdeplibs="$newdeplibs $i"
-- else
-- droppeddeps=yes
-- echo
-- echo "*** Warning: dynamic linker does not accept needed library $i."
-- echo "*** I have the capability to make that library automatically link in when"
-- echo "*** you link to this library. But I can only do this if you have a"
-- echo "*** shared version of the library, which I believe you do not have"
-- echo "*** because a test_compile did reveal that the linker did not use it for"
-- echo "*** its dynamic dependency list that programs get resolved with at runtime."
-+ if test "$name" != "" && test "$name" -ne "0"; then
-+ if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
-+ case " $predeps $postdeps " in
-+ *" $i "*)
-+ newdeplibs="$newdeplibs $i"
-+ i=""
-+ ;;
-+ esac
-+ fi
-+ if test -n "$i" ; then
-+ libname=`eval \\$echo \"$libname_spec\"`
-+ deplib_matches=`eval \\$echo \"$library_names_spec\"`
-+ set dummy $deplib_matches
-+ deplib_match=$2
-+ if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then
-+ newdeplibs="$newdeplibs $i"
-+ else
-+ droppeddeps=yes
-+ $echo
-+ $echo "*** Warning: dynamic linker does not accept needed library $i."
-+ $echo "*** I have the capability to make that library automatically link in when"
-+ $echo "*** you link to this library. But I can only do this if you have a"
-+ $echo "*** shared version of the library, which I believe you do not have"
-+ $echo "*** because a test_compile did reveal that the linker did not use it for"
-+ $echo "*** its dynamic dependency list that programs get resolved with at runtime."
-+ fi
- fi
- else
- newdeplibs="$newdeplibs $i"
- fi
- done
- else
-- # Error occured in the first compile. Let's try to salvage
-+ # Error occurred in the first compile. Let's try to salvage
- # the situation: Compile a separate program for each library.
- for i in $deplibs; do
-- name="`expr $i : '-l\(.*\)'`"
-- # If $name is empty we are operating on a -L argument.
-- if test -n "$name" && test "$name" != "0"; then
-+ name=`expr $i : '-l\(.*\)'`
-+ # If $name is empty we are operating on a -L argument.
-+ if test "$name" != "" && test "$name" != "0"; then
- $rm conftest
-- $CC -o conftest conftest.c $i
-+ $LTCC $LTCFLAGS -o conftest conftest.c $i
- # Did it work?
-- if test $? -eq 0 ; then
-+ if test "$?" -eq 0 ; then
- ldd_output=`ldd conftest`
-- libname=`eval \\$echo \"$libname_spec\"`
-- deplib_matches=`eval \\$echo \"$library_names_spec\"`
-- set dummy $deplib_matches
-- deplib_match=$2
-- if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then
-- newdeplibs="$newdeplibs $i"
-- else
-- droppeddeps=yes
-- echo
-- echo "*** Warning: dynamic linker does not accept needed library $i."
-- echo "*** I have the capability to make that library automatically link in when"
-- echo "*** you link to this library. But I can only do this if you have a"
-- echo "*** shared version of the library, which you do not appear to have"
-- echo "*** because a test_compile did reveal that the linker did not use this one"
-- echo "*** as a dynamic dependency that programs can get resolved with at runtime."
-+ if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
-+ case " $predeps $postdeps " in
-+ *" $i "*)
-+ newdeplibs="$newdeplibs $i"
-+ i=""
-+ ;;
-+ esac
-+ fi
-+ if test -n "$i" ; then
-+ libname=`eval \\$echo \"$libname_spec\"`
-+ deplib_matches=`eval \\$echo \"$library_names_spec\"`
-+ set dummy $deplib_matches
-+ deplib_match=$2
-+ if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then
-+ newdeplibs="$newdeplibs $i"
-+ else
-+ droppeddeps=yes
-+ $echo
-+ $echo "*** Warning: dynamic linker does not accept needed library $i."
-+ $echo "*** I have the capability to make that library automatically link in when"
-+ $echo "*** you link to this library. But I can only do this if you have a"
-+ $echo "*** shared version of the library, which you do not appear to have"
-+ $echo "*** because a test_compile did reveal that the linker did not use this one"
-+ $echo "*** as a dynamic dependency that programs can get resolved with at runtime."
-+ fi
- fi
- else
- droppeddeps=yes
-- echo
-- echo "*** Warning! Library $i is needed by this library but I was not able to"
-- echo "*** make it link in! You will probably need to install it or some"
-- echo "*** library that it depends on before this library will be fully"
-- echo "*** functional. Installing it before continuing would be even better."
-+ $echo
-+ $echo "*** Warning! Library $i is needed by this library but I was not able to"
-+ $echo "*** make it link in! You will probably need to install it or some"
-+ $echo "*** library that it depends on before this library will be fully"
-+ $echo "*** functional. Installing it before continuing would be even better."
- fi
- else
- newdeplibs="$newdeplibs $i"
-@@ -2586,13 +3612,22 @@
- set dummy $deplibs_check_method
- file_magic_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"`
- for a_deplib in $deplibs; do
-- name="`expr $a_deplib : '-l\(.*\)'`"
-+ name=`expr $a_deplib : '-l\(.*\)'`
- # If $name is empty we are operating on a -L argument.
-- if test -n "$name" && test "$name" != "0"; then
-- libname=`eval \\$echo \"$libname_spec\"`
-- for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do
-- potential_libs=`ls $i/$libname[.-]* 2>/dev/null`
-- for potent_lib in $potential_libs; do
-+ if test "$name" != "" && test "$name" != "0"; then
-+ if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
-+ case " $predeps $postdeps " in
-+ *" $a_deplib "*)
-+ newdeplibs="$newdeplibs $a_deplib"
-+ a_deplib=""
-+ ;;
-+ esac
-+ fi
-+ if test -n "$a_deplib" ; then
-+ libname=`eval \\$echo \"$libname_spec\"`
-+ for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do
-+ potential_libs=`ls $i/$libname[.-]* 2>/dev/null`
-+ for potent_lib in $potential_libs; do
- # Follow soft links.
- if ls -lLd "$potent_lib" 2>/dev/null \
- | grep " -> " >/dev/null; then
-@@ -2613,26 +3648,27 @@
- done
- if eval $file_magic_cmd \"\$potlib\" 2>/dev/null \
- | ${SED} 10q \
-- | egrep "$file_magic_regex" > /dev/null; then
-+ | $EGREP "$file_magic_regex" > /dev/null; then
- newdeplibs="$newdeplibs $a_deplib"
- a_deplib=""
- break 2
- fi
-- done
-- done
-+ done
-+ done
-+ fi
- if test -n "$a_deplib" ; then
- droppeddeps=yes
-- echo
-- echo "*** Warning: linker path does not have real file for library $a_deplib."
-- echo "*** I have the capability to make that library automatically link in when"
-- echo "*** you link to this library. But I can only do this if you have a"
-- echo "*** shared version of the library, which you do not appear to have"
-- echo "*** because I did check the linker path looking for a file starting"
-+ $echo
-+ $echo "*** Warning: linker path does not have real file for library $a_deplib."
-+ $echo "*** I have the capability to make that library automatically link in when"
-+ $echo "*** you link to this library. But I can only do this if you have a"
-+ $echo "*** shared version of the library, which you do not appear to have"
-+ $echo "*** because I did check the linker path looking for a file starting"
- if test -z "$potlib" ; then
-- echo "*** with $libname but no candidates were found. (...for file magic test)"
-+ $echo "*** with $libname but no candidates were found. (...for file magic test)"
- else
-- echo "*** with $libname and none of the candidates passed a file format test"
-- echo "*** using a file magic. Last file checked: $potlib"
-+ $echo "*** with $libname and none of the candidates passed a file format test"
-+ $echo "*** using a file magic. Last file checked: $potlib"
- fi
- fi
- else
-@@ -2645,36 +3681,46 @@
- set dummy $deplibs_check_method
- match_pattern_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"`
- for a_deplib in $deplibs; do
-- name="`expr $a_deplib : '-l\(.*\)'`"
-+ name=`expr $a_deplib : '-l\(.*\)'`
- # If $name is empty we are operating on a -L argument.
- if test -n "$name" && test "$name" != "0"; then
-- libname=`eval \\$echo \"$libname_spec\"`
-- for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do
-- potential_libs=`ls $i/$libname[.-]* 2>/dev/null`
-- for potent_lib in $potential_libs; do
-- potlib="$potent_lib" # see symlink-check below in file_magic test
-- if eval echo \"$potent_lib\" 2>/dev/null \
-- | ${SED} 10q \
-- | egrep "$match_pattern_regex" > /dev/null; then
-- newdeplibs="$newdeplibs $a_deplib"
-- a_deplib=""
-- break 2
-- fi
-+ if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
-+ case " $predeps $postdeps " in
-+ *" $a_deplib "*)
-+ newdeplibs="$newdeplibs $a_deplib"
-+ a_deplib=""
-+ ;;
-+ esac
-+ fi
-+ if test -n "$a_deplib" ; then
-+ libname=`eval \\$echo \"$libname_spec\"`
-+ for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do
-+ potential_libs=`ls $i/$libname[.-]* 2>/dev/null`
-+ for potent_lib in $potential_libs; do
-+ potlib="$potent_lib" # see symlink-check above in file_magic test
-+ if eval $echo \"$potent_lib\" 2>/dev/null \
-+ | ${SED} 10q \
-+ | $EGREP "$match_pattern_regex" > /dev/null; then
-+ newdeplibs="$newdeplibs $a_deplib"
-+ a_deplib=""
-+ break 2
-+ fi
-+ done
- done
-- done
-+ fi
- if test -n "$a_deplib" ; then
- droppeddeps=yes
-- echo
-- echo "*** Warning: linker path does not have real file for library $a_deplib."
-- echo "*** I have the capability to make that library automatically link in when"
-- echo "*** you link to this library. But I can only do this if you have a"
-- echo "*** shared version of the library, which you do not appear to have"
-- echo "*** because I did check the linker path looking for a file starting"
-+ $echo
-+ $echo "*** Warning: linker path does not have real file for library $a_deplib."
-+ $echo "*** I have the capability to make that library automatically link in when"
-+ $echo "*** you link to this library. But I can only do this if you have a"
-+ $echo "*** shared version of the library, which you do not appear to have"
-+ $echo "*** because I did check the linker path looking for a file starting"
- if test -z "$potlib" ; then
-- echo "*** with $libname but no candidates were found. (...for regex pattern test)"
-+ $echo "*** with $libname but no candidates were found. (...for regex pattern test)"
- else
-- echo "*** with $libname and none of the candidates passed a file format test"
-- echo "*** using a regex pattern. Last file checked: $potlib"
-+ $echo "*** with $libname and none of the candidates passed a file format test"
-+ $echo "*** using a regex pattern. Last file checked: $potlib"
- fi
- fi
- else
-@@ -2685,16 +3731,23 @@
- ;;
- none | unknown | *)
- newdeplibs=""
-- if $echo "X $deplibs" | $Xsed -e 's/ -lc$//' \
-- -e 's/ -[LR][^ ]*//g' -e 's/[ ]//g' |
-- grep . >/dev/null; then
-- echo
-+ tmp_deplibs=`$echo "X $deplibs" | $Xsed -e 's/ -lc$//' \
-+ -e 's/ -[LR][^ ]*//g'`
-+ if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
-+ for i in $predeps $postdeps ; do
-+ # can't use Xsed below, because $i might contain '/'
-+ tmp_deplibs=`$echo "X $tmp_deplibs" | ${SED} -e "1s,^X,," -e "s,$i,,"`
-+ done
-+ fi
-+ if $echo "X $tmp_deplibs" | $Xsed -e 's/[ ]//g' \
-+ | grep . >/dev/null; then
-+ $echo
- if test "X$deplibs_check_method" = "Xnone"; then
-- echo "*** Warning: inter-library dependencies are not supported in this platform."
-+ $echo "*** Warning: inter-library dependencies are not supported in this platform."
- else
-- echo "*** Warning: inter-library dependencies are not known to be supported."
-+ $echo "*** Warning: inter-library dependencies are not known to be supported."
- fi
-- echo "*** All declared inter-library dependencies are being dropped."
-+ $echo "*** All declared inter-library dependencies are being dropped."
- droppeddeps=yes
- fi
- ;;
-@@ -2714,17 +3767,17 @@
-
- if test "$droppeddeps" = yes; then
- if test "$module" = yes; then
-- echo
-- echo "*** Warning: libtool could not satisfy all declared inter-library"
-- echo "*** dependencies of module $libname. Therefore, libtool will create"
-- echo "*** a static module, that should work as long as the dlopening"
-- echo "*** application is linked with the -dlopen flag."
-+ $echo
-+ $echo "*** Warning: libtool could not satisfy all declared inter-library"
-+ $echo "*** dependencies of module $libname. Therefore, libtool will create"
-+ $echo "*** a static module, that should work as long as the dlopening"
-+ $echo "*** application is linked with the -dlopen flag."
- if test -z "$global_symbol_pipe"; then
-- echo
-- echo "*** However, this would only work if libtool was able to extract symbol"
-- echo "*** lists from a program, using \`nm' or equivalent, but libtool could"
-- echo "*** not find such a program. So, this module is probably useless."
-- echo "*** \`nm' from GNU binutils and a full rebuild may help."
-+ $echo
-+ $echo "*** However, this would only work if libtool was able to extract symbol"
-+ $echo "*** lists from a program, using \`nm' or equivalent, but libtool could"
-+ $echo "*** not find such a program. So, this module is probably useless."
-+ $echo "*** \`nm' from GNU binutils and a full rebuild may help."
- fi
- if test "$build_old_libs" = no; then
- oldlibs="$output_objdir/$libname.$libext"
-@@ -2734,16 +3787,16 @@
- build_libtool_libs=no
- fi
- else
-- echo "*** The inter-library dependencies that have been dropped here will be"
-- echo "*** automatically added whenever a program is linked with this library"
-- echo "*** or is declared to -dlopen it."
--
-- if test $allow_undefined = no; then
-- echo
-- echo "*** Since this library must not contain undefined symbols,"
-- echo "*** because either the platform does not support them or"
-- echo "*** it was explicitly requested with -no-undefined,"
-- echo "*** libtool will only create a static version of it."
-+ $echo "*** The inter-library dependencies that have been dropped here will be"
-+ $echo "*** automatically added whenever a program is linked with this library"
-+ $echo "*** or is declared to -dlopen it."
-+
-+ if test "$allow_undefined" = no; then
-+ $echo
-+ $echo "*** Since this library must not contain undefined symbols,"
-+ $echo "*** because either the platform does not support them or"
-+ $echo "*** it was explicitly requested with -no-undefined,"
-+ $echo "*** libtool will only create a static version of it."
- if test "$build_old_libs" = no; then
- oldlibs="$output_objdir/$libname.$libext"
- build_libtool_libs=module
-@@ -2758,6 +3811,35 @@
- deplibs=$newdeplibs
- fi
-
-+
-+ # move library search paths that coincide with paths to not yet
-+ # installed libraries to the beginning of the library search list
-+ new_libs=
-+ for path in $notinst_path; do
-+ case " $new_libs " in
-+ *" -L$path/$objdir "*) ;;
-+ *)
-+ case " $deplibs " in
-+ *" -L$path/$objdir "*)
-+ new_libs="$new_libs -L$path/$objdir" ;;
-+ esac
-+ ;;
-+ esac
-+ done
-+ for deplib in $deplibs; do
-+ case $deplib in
-+ -L*)
-+ case " $new_libs " in
-+ *" $deplib "*) ;;
-+ *) new_libs="$new_libs $deplib" ;;
-+ esac
-+ ;;
-+ *) new_libs="$new_libs $deplib" ;;
-+ esac
-+ done
-+ deplibs="$new_libs"
-+
-+
- # All the library-specific variables (install_libdir is set above).
- library_names=
- old_library=
-@@ -2765,7 +3847,7 @@
-
- # Test again, we may have decided not to build it any more
- if test "$build_libtool_libs" = yes; then
-- if test $hardcode_into_libs = yes; then
-+ if test "$hardcode_into_libs" = yes; then
- # Hardcode the library paths
- hardcode_libdirs=
- dep_rpath=
-@@ -2801,7 +3883,11 @@
- if test -n "$hardcode_libdir_separator" &&
- test -n "$hardcode_libdirs"; then
- libdir="$hardcode_libdirs"
-- eval dep_rpath=\"$hardcode_libdir_flag_spec\"
-+ if test -n "$hardcode_libdir_flag_spec_ld"; then
-+ eval dep_rpath=\"$hardcode_libdir_flag_spec_ld\"
-+ else
-+ eval dep_rpath=\"$hardcode_libdir_flag_spec\"
-+ fi
- fi
- if test -n "$runpath_var" && test -n "$perm_rpath"; then
- # We should set the runpath_var.
-@@ -2821,6 +3907,7 @@
- fi
-
- # Get the real and link names of the library.
-+ eval shared_ext=\"$shrext_cmds\"
- eval library_names=\"$library_names_spec\"
- set dummy $library_names
- realname="$2"
-@@ -2831,31 +3918,17 @@
- else
- soname="$realname"
- fi
-- test -z "$dlname" && dlname=$soname
-+ if test -z "$dlname"; then
-+ dlname=$soname
-+ fi
-
- lib="$output_objdir/$realname"
-+ linknames=
- for link
- do
- linknames="$linknames $link"
- done
-
-- # Ensure that we have .o objects for linkers which dislike .lo
-- # (e.g. aix) in case we are running --disable-static
-- for obj in $libobjs; do
-- xdir=`$echo "X$obj" | $Xsed -e 's%/[^/]*$%%'`
-- if test "X$xdir" = "X$obj"; then
-- xdir="."
-- else
-- xdir="$xdir"
-- fi
-- baseobj=`$echo "X$obj" | $Xsed -e 's%^.*/%%'`
-- oldobj=`$echo "X$baseobj" | $Xsed -e "$lo2o"`
-- if test ! -f $xdir/$oldobj; then
-- $show "(cd $xdir && ${LN_S} $baseobj $oldobj)"
-- $run eval '(cd $xdir && ${LN_S} $baseobj $oldobj)' || exit $?
-- fi
-- done
--
- # Use standard objects if they are pic
- test -z "$pic_flag" && libobjs=`$echo "X$libobjs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
-
-@@ -2865,17 +3938,29 @@
- $show "generating symbol list for \`$libname.la'"
- export_symbols="$output_objdir/$libname.exp"
- $run $rm $export_symbols
-- eval cmds=\"$export_symbols_cmds\"
-+ cmds=$export_symbols_cmds
- save_ifs="$IFS"; IFS='~'
- for cmd in $cmds; do
- IFS="$save_ifs"
-- $show "$cmd"
-- $run eval "$cmd" || exit $?
-+ eval cmd=\"$cmd\"
-+ if len=`expr "X$cmd" : ".*"` &&
-+ test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then
-+ $show "$cmd"
-+ $run eval "$cmd" || exit $?
-+ skipped_export=false
-+ else
-+ # The command line is too long to execute in one step.
-+ $show "using reloadable object file for export list..."
-+ skipped_export=:
-+ # Break out early, otherwise skipped_export may be
-+ # set to false by a later but shorter cmd.
-+ break
-+ fi
- done
- IFS="$save_ifs"
- if test -n "$export_symbols_regex"; then
-- $show "egrep -e \"$export_symbols_regex\" \"$export_symbols\" > \"${export_symbols}T\""
-- $run eval 'egrep -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"'
-+ $show "$EGREP -e \"$export_symbols_regex\" \"$export_symbols\" > \"${export_symbols}T\""
-+ $run eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"'
- $show "$mv \"${export_symbols}T\" \"$export_symbols\""
- $run eval '$mv "${export_symbols}T" "$export_symbols"'
- fi
-@@ -2886,46 +3971,30 @@
- $run eval '$echo "X$include_expsyms" | $SP2NL >> "$export_symbols"'
- fi
-
-+ tmp_deplibs=
-+ for test_deplib in $deplibs; do
-+ case " $convenience " in
-+ *" $test_deplib "*) ;;
-+ *)
-+ tmp_deplibs="$tmp_deplibs $test_deplib"
-+ ;;
-+ esac
-+ done
-+ deplibs="$tmp_deplibs"
-+
- if test -n "$convenience"; then
- if test -n "$whole_archive_flag_spec"; then
-+ save_libobjs=$libobjs
- eval libobjs=\"\$libobjs $whole_archive_flag_spec\"
-- else
-- gentop="$output_objdir/${outputname}x"
-- $show "${rm}r $gentop"
-- $run ${rm}r "$gentop"
-- $show "mkdir $gentop"
-- $run mkdir "$gentop"
-- status=$?
-- if test $status -ne 0 && test ! -d "$gentop"; then
-- exit $status
-- fi
-+ else
-+ gentop="$output_objdir/${outputname}x"
- generated="$generated $gentop"
-
-- for xlib in $convenience; do
-- # Extract the objects.
-- case $xlib in
-- [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;;
-- *) xabs=`pwd`"/$xlib" ;;
-- esac
-- xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'`
-- xdir="$gentop/$xlib"
--
-- $show "${rm}r $xdir"
-- $run ${rm}r "$xdir"
-- $show "mkdir $xdir"
-- $run mkdir "$xdir"
-- status=$?
-- if test $status -ne 0 && test ! -d "$xdir"; then
-- exit $status
-- fi
-- $show "(cd $xdir && $AR x $xabs)"
-- $run eval "(cd \$xdir && $AR x \$xabs)" || exit $?
--
-- libobjs="$libobjs "`find $xdir -name \*.o -print -o -name \*.lo -print | $NL2SP`
-- done
-+ func_extract_archives $gentop $convenience
-+ libobjs="$libobjs $func_extract_archives_result"
- fi
- fi
--
-+
- if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then
- eval flag=\"$thread_safe_flag_spec\"
- linker_flags="$linker_flags $flag"
-@@ -2937,34 +4006,175 @@
- fi
-
- # Do each of the archive commands.
-+ if test "$module" = yes && test -n "$module_cmds" ; then
-+ if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then
-+ eval test_cmds=\"$module_expsym_cmds\"
-+ cmds=$module_expsym_cmds
-+ else
-+ eval test_cmds=\"$module_cmds\"
-+ cmds=$module_cmds
-+ fi
-+ else
- if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then
-- eval cmds=\"$archive_expsym_cmds\"
-+ eval test_cmds=\"$archive_expsym_cmds\"
-+ cmds=$archive_expsym_cmds
-+ else
-+ eval test_cmds=\"$archive_cmds\"
-+ cmds=$archive_cmds
-+ fi
-+ fi
-+
-+ if test "X$skipped_export" != "X:" &&
-+ len=`expr "X$test_cmds" : ".*" 2>/dev/null` &&
-+ test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then
-+ :
- else
-- save_deplibs="$deplibs"
-- for conv in $convenience; do
-- tmp_deplibs=
-- for test_deplib in $deplibs; do
-- if test "$test_deplib" != "$conv"; then
-- tmp_deplibs="$tmp_deplibs $test_deplib"
-+ # The command line is too long to link in one step, link piecewise.
-+ $echo "creating reloadable object files..."
-+
-+ # Save the value of $output and $libobjs because we want to
-+ # use them later. If we have whole_archive_flag_spec, we
-+ # want to use save_libobjs as it was before
-+ # whole_archive_flag_spec was expanded, because we can't
-+ # assume the linker understands whole_archive_flag_spec.
-+ # This may have to be revisited, in case too many
-+ # convenience libraries get linked in and end up exceeding
-+ # the spec.
-+ if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then
-+ save_libobjs=$libobjs
-+ fi
-+ save_output=$output
-+ output_la=`$echo "X$output" | $Xsed -e "$basename"`
-+
-+ # Clear the reloadable object creation command queue and
-+ # initialize k to one.
-+ test_cmds=
-+ concat_cmds=
-+ objlist=
-+ delfiles=
-+ last_robj=
-+ k=1
-+ output=$output_objdir/$output_la-${k}.$objext
-+ # Loop over the list of objects to be linked.
-+ for obj in $save_libobjs
-+ do
-+ eval test_cmds=\"$reload_cmds $objlist $last_robj\"
-+ if test "X$objlist" = X ||
-+ { len=`expr "X$test_cmds" : ".*" 2>/dev/null` &&
-+ test "$len" -le "$max_cmd_len"; }; then
-+ objlist="$objlist $obj"
-+ else
-+ # The command $test_cmds is almost too long, add a
-+ # command to the queue.
-+ if test "$k" -eq 1 ; then
-+ # The first file doesn't have a previous command to add.
-+ eval concat_cmds=\"$reload_cmds $objlist $last_robj\"
-+ else
-+ # All subsequent reloadable object files will link in
-+ # the last one created.
-+ eval concat_cmds=\"\$concat_cmds~$reload_cmds $objlist $last_robj\"
- fi
-- done
-- deplibs="$tmp_deplibs"
-+ last_robj=$output_objdir/$output_la-${k}.$objext
-+ k=`expr $k + 1`
-+ output=$output_objdir/$output_la-${k}.$objext
-+ objlist=$obj
-+ len=1
-+ fi
-+ done
-+ # Handle the remaining objects by creating one last
-+ # reloadable object file. All subsequent reloadable object
-+ # files will link in the last one created.
-+ test -z "$concat_cmds" || concat_cmds=$concat_cmds~
-+ eval concat_cmds=\"\${concat_cmds}$reload_cmds $objlist $last_robj\"
-+
-+ if ${skipped_export-false}; then
-+ $show "generating symbol list for \`$libname.la'"
-+ export_symbols="$output_objdir/$libname.exp"
-+ $run $rm $export_symbols
-+ libobjs=$output
-+ # Append the command to create the export file.
-+ eval concat_cmds=\"\$concat_cmds~$export_symbols_cmds\"
-+ fi
-+
-+ # Set up a command to remove the reloadable object files
-+ # after they are used.
-+ i=0
-+ while test "$i" -lt "$k"
-+ do
-+ i=`expr $i + 1`
-+ delfiles="$delfiles $output_objdir/$output_la-${i}.$objext"
-+ done
-+
-+ $echo "creating a temporary reloadable object file: $output"
-+
-+ # Loop through the commands generated above and execute them.
-+ save_ifs="$IFS"; IFS='~'
-+ for cmd in $concat_cmds; do
-+ IFS="$save_ifs"
-+ $show "$cmd"
-+ $run eval "$cmd" || exit $?
- done
-- eval cmds=\"$archive_cmds\"
-- deplibs="$save_deplibs"
-+ IFS="$save_ifs"
-+
-+ libobjs=$output
-+ # Restore the value of output.
-+ output=$save_output
-+
-+ if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then
-+ eval libobjs=\"\$libobjs $whole_archive_flag_spec\"
-+ fi
-+ # Expand the library linking commands again to reset the
-+ # value of $libobjs for piecewise linking.
-+
-+ # Do each of the archive commands.
-+ if test "$module" = yes && test -n "$module_cmds" ; then
-+ if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then
-+ cmds=$module_expsym_cmds
-+ else
-+ cmds=$module_cmds
-+ fi
-+ else
-+ if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then
-+ cmds=$archive_expsym_cmds
-+ else
-+ cmds=$archive_cmds
-+ fi
-+ fi
-+
-+ # Append the command to remove the reloadable object files
-+ # to the just-reset $cmds.
-+ eval cmds=\"\$cmds~\$rm $delfiles\"
- fi
- save_ifs="$IFS"; IFS='~'
- for cmd in $cmds; do
- IFS="$save_ifs"
-+ eval cmd=\"$cmd\"
- $show "$cmd"
-- $run eval "$cmd" || exit $?
-+ $run eval "$cmd" || {
-+ lt_exit=$?
-+
-+ # Restore the uninstalled library and exit
-+ if test "$mode" = relink; then
-+ $run eval '(cd $output_objdir && $rm ${realname}T && $mv ${realname}U $realname)'
-+ fi
-+
-+ exit $lt_exit
-+ }
- done
- IFS="$save_ifs"
-
- # Restore the uninstalled library and exit
- if test "$mode" = relink; then
- $run eval '(cd $output_objdir && $rm ${realname}T && $mv $realname ${realname}T && $mv "$realname"U $realname)' || exit $?
-- exit 0
-+
-+ if test -n "$convenience"; then
-+ if test -z "$whole_archive_flag_spec"; then
-+ $show "${rm}r $gentop"
-+ $run ${rm}r "$gentop"
-+ fi
-+ fi
-+
-+ exit $EXIT_SUCCESS
- fi
-
- # Create links to the real library.
-@@ -3012,7 +4222,7 @@
- *.lo)
- if test -n "$objs$old_deplibs"; then
- $echo "$modename: cannot build library object \`$output' from non-libtool objects" 1>&2
-- exit 1
-+ exit $EXIT_FAILURE
- fi
- libobj="$output"
- obj=`$echo "X$output" | $Xsed -e "$lo2o"`
-@@ -3041,38 +4251,10 @@
- eval reload_conv_objs=\"\$reload_objs $whole_archive_flag_spec\"
- else
- gentop="$output_objdir/${obj}x"
-- $show "${rm}r $gentop"
-- $run ${rm}r "$gentop"
-- $show "mkdir $gentop"
-- $run mkdir "$gentop"
-- status=$?
-- if test $status -ne 0 && test ! -d "$gentop"; then
-- exit $status
-- fi
- generated="$generated $gentop"
-
-- for xlib in $convenience; do
-- # Extract the objects.
-- case $xlib in
-- [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;;
-- *) xabs=`pwd`"/$xlib" ;;
-- esac
-- xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'`
-- xdir="$gentop/$xlib"
--
-- $show "${rm}r $xdir"
-- $run ${rm}r "$xdir"
-- $show "mkdir $xdir"
-- $run mkdir "$xdir"
-- status=$?
-- if test $status -ne 0 && test ! -d "$xdir"; then
-- exit $status
-- fi
-- $show "(cd $xdir && $AR x $xabs)"
-- $run eval "(cd \$xdir && $AR x \$xabs)" || exit $?
--
-- reload_conv_objs="$reload_objs "`find $xdir -name \*.o -print -o -name \*.lo -print | $NL2SP`
-- done
-+ func_extract_archives $gentop $convenience
-+ reload_conv_objs="$reload_objs $func_extract_archives_result"
- fi
- fi
-
-@@ -3080,10 +4262,11 @@
- reload_objs="$objs$old_deplibs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}$'/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test
-
- output="$obj"
-- eval cmds=\"$reload_cmds\"
-+ cmds=$reload_cmds
- save_ifs="$IFS"; IFS='~'
- for cmd in $cmds; do
- IFS="$save_ifs"
-+ eval cmd=\"$cmd\"
- $show "$cmd"
- $run eval "$cmd" || exit $?
- done
-@@ -3096,7 +4279,7 @@
- $run ${rm}r $gentop
- fi
-
-- exit 0
-+ exit $EXIT_SUCCESS
- fi
-
- if test "$build_libtool_libs" != yes; then
-@@ -3107,37 +4290,24 @@
-
- # Create an invalid libtool object if no PIC, so that we don't
- # accidentally link it into a program.
-- $show "echo timestamp > $libobj"
-- $run eval "echo timestamp > $libobj" || exit $?
-- exit 0
-+ # $show "echo timestamp > $libobj"
-+ # $run eval "echo timestamp > $libobj" || exit $?
-+ exit $EXIT_SUCCESS
- fi
-
- if test -n "$pic_flag" || test "$pic_mode" != default; then
- # Only do commands if we really have different PIC objects.
- reload_objs="$libobjs $reload_conv_objs"
- output="$libobj"
-- eval cmds=\"$reload_cmds\"
-+ cmds=$reload_cmds
- save_ifs="$IFS"; IFS='~'
- for cmd in $cmds; do
- IFS="$save_ifs"
-+ eval cmd=\"$cmd\"
- $show "$cmd"
- $run eval "$cmd" || exit $?
- done
- IFS="$save_ifs"
-- else
-- # Just create a symlink.
-- $show $rm $libobj
-- $run $rm $libobj
-- xdir=`$echo "X$libobj" | $Xsed -e 's%/[^/]*$%%'`
-- if test "X$xdir" = "X$libobj"; then
-- xdir="."
-- else
-- xdir="$xdir"
-- fi
-- baseobj=`$echo "X$libobj" | $Xsed -e 's%^.*/%%'`
-- oldobj=`$echo "X$baseobj" | $Xsed -e "$lo2o"`
-- $show "(cd $xdir && $LN_S $oldobj $baseobj)"
-- $run eval '(cd $xdir && $LN_S $oldobj $baseobj)' || exit $?
- fi
-
- if test -n "$gentop"; then
-@@ -3145,12 +4315,12 @@
- $run ${rm}r $gentop
- fi
-
-- exit 0
-+ exit $EXIT_SUCCESS
- ;;
-
- prog)
- case $host in
-- *cygwin*) output=`echo $output | ${SED} -e 's,.exe$,,;s,$,.exe,'` ;;
-+ *cygwin*) output=`$echo $output | ${SED} -e 's,.exe$,,;s,$,.exe,'` ;;
- esac
- if test -n "$vinfo"; then
- $echo "$modename: warning: \`-version-info' is ignored for programs" 1>&2
-@@ -3172,16 +4342,48 @@
- # On Rhapsody replace the C library is the System framework
- compile_deplibs=`$echo "X $compile_deplibs" | $Xsed -e 's/ -lc / -framework System /'`
- finalize_deplibs=`$echo "X $finalize_deplibs" | $Xsed -e 's/ -lc / -framework System /'`
-- case $host in
-- *darwin*)
-- # Don't allow lazy linking, it breaks C++ global constructors
-- compile_command="$compile_command ${wl}-bind_at_load"
-- finalize_command="$finalize_command ${wl}-bind_at_load"
-- ;;
-- esac
- ;;
- esac
-
-+ case $host in
-+ *darwin*)
-+ # Don't allow lazy linking, it breaks C++ global constructors
-+ if test "$tagname" = CXX ; then
-+ compile_command="$compile_command ${wl}-bind_at_load"
-+ finalize_command="$finalize_command ${wl}-bind_at_load"
-+ fi
-+ ;;
-+ esac
-+
-+
-+ # move library search paths that coincide with paths to not yet
-+ # installed libraries to the beginning of the library search list
-+ new_libs=
-+ for path in $notinst_path; do
-+ case " $new_libs " in
-+ *" -L$path/$objdir "*) ;;
-+ *)
-+ case " $compile_deplibs " in
-+ *" -L$path/$objdir "*)
-+ new_libs="$new_libs -L$path/$objdir" ;;
-+ esac
-+ ;;
-+ esac
-+ done
-+ for deplib in $compile_deplibs; do
-+ case $deplib in
-+ -L*)
-+ case " $new_libs " in
-+ *" $deplib "*) ;;
-+ *) new_libs="$new_libs $deplib" ;;
-+ esac
-+ ;;
-+ *) new_libs="$new_libs $deplib" ;;
-+ esac
-+ done
-+ compile_deplibs="$new_libs"
-+
-+
- compile_command="$compile_command $compile_deplibs"
- finalize_command="$finalize_command $finalize_deplibs"
-
-@@ -3226,10 +4428,15 @@
- fi
- case $host in
- *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*)
-+ testbindir=`$echo "X$libdir" | $Xsed -e 's*/lib$*/bin*'`
- case :$dllsearchpath: in
- *":$libdir:"*) ;;
- *) dllsearchpath="$dllsearchpath:$libdir";;
- esac
-+ case :$dllsearchpath: in
-+ *":$testbindir:"*) ;;
-+ *) dllsearchpath="$dllsearchpath:$testbindir";;
-+ esac
- ;;
- esac
- done
-@@ -3332,31 +4539,43 @@
- done
-
- if test -n "$exclude_expsyms"; then
-- $run eval 'egrep -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T'
-+ $run eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T'
- $run eval '$mv "$nlist"T "$nlist"'
- fi
-
- if test -n "$export_symbols_regex"; then
-- $run eval 'egrep -e "$export_symbols_regex" "$nlist" > "$nlist"T'
-+ $run eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T'
- $run eval '$mv "$nlist"T "$nlist"'
- fi
-
- # Prepare the list of exported symbols
- if test -z "$export_symbols"; then
-- export_symbols="$output_objdir/$output.exp"
-+ export_symbols="$output_objdir/$outputname.exp"
- $run $rm $export_symbols
-- $run eval "${SED} -n -e '/^: @PROGRAM@$/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"'
-+ $run eval "${SED} -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"'
-+ case $host in
-+ *cygwin* | *mingw* )
-+ $run eval "echo EXPORTS "'> "$output_objdir/$outputname.def"'
-+ $run eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"'
-+ ;;
-+ esac
- else
-- $run eval "${SED} -e 's/\([][.*^$]\)/\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$output.exp"'
-- $run eval 'grep -f "$output_objdir/$output.exp" < "$nlist" > "$nlist"T'
-+ $run eval "${SED} -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"'
-+ $run eval 'grep -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T'
- $run eval 'mv "$nlist"T "$nlist"'
-+ case $host in
-+ *cygwin* | *mingw* )
-+ $run eval "echo EXPORTS "'> "$output_objdir/$outputname.def"'
-+ $run eval 'cat "$nlist" >> "$output_objdir/$outputname.def"'
-+ ;;
-+ esac
- fi
- fi
-
- for arg in $dlprefiles; do
- $show "extracting global C symbols from \`$arg'"
-- name=`echo "$arg" | ${SED} -e 's%^.*/%%'`
-- $run eval 'echo ": $name " >> "$nlist"'
-+ name=`$echo "$arg" | ${SED} -e 's%^.*/%%'`
-+ $run eval '$echo ": $name " >> "$nlist"'
- $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'"
- done
-
-@@ -3365,7 +4584,7 @@
- test -f "$nlist" || : > "$nlist"
-
- if test -n "$exclude_expsyms"; then
-- egrep -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T
-+ $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T
- $mv "$nlist"T "$nlist"
- fi
-
-@@ -3385,7 +4604,7 @@
- if test -f "$nlist"S; then
- eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$dlsyms"'
- else
-- echo '/* NONE */' >> "$output_objdir/$dlsyms"
-+ $echo '/* NONE */' >> "$output_objdir/$dlsyms"
- fi
-
- $echo >> "$output_objdir/$dlsyms" "\
-@@ -3400,7 +4619,26 @@
- #endif
-
- /* The mapping between symbol names and symbols. */
-+"
-+
-+ case $host in
-+ *cygwin* | *mingw* )
-+ $echo >> "$output_objdir/$dlsyms" "\
-+/* DATA imports from DLLs on WIN32 can't be const, because
-+ runtime relocations are performed -- see ld's documentation
-+ on pseudo-relocs */
-+struct {
-+"
-+ ;;
-+ * )
-+ $echo >> "$output_objdir/$dlsyms" "\
- const struct {
-+"
-+ ;;
-+ esac
-+
-+
-+ $echo >> "$output_objdir/$dlsyms" "\
- const char *name;
- lt_ptr address;
- }
-@@ -3437,30 +4675,43 @@
- *-*-freebsd2*|*-*-freebsd3.0*|*-*-freebsdelf3.0*)
- case "$compile_command " in
- *" -static "*) ;;
-- *) pic_flag_for_symtable=" $pic_flag -DPIC -DFREEBSD_WORKAROUND";;
-+ *) pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND";;
- esac;;
- *-*-hpux*)
- case "$compile_command " in
- *" -static "*) ;;
-- *) pic_flag_for_symtable=" $pic_flag -DPIC";;
-+ *) pic_flag_for_symtable=" $pic_flag";;
- esac
- esac
-
- # Now compile the dynamic symbol file.
-- $show "(cd $output_objdir && $CC -c$no_builtin_flag$pic_flag_for_symtable \"$dlsyms\")"
-- $run eval '(cd $output_objdir && $CC -c$no_builtin_flag$pic_flag_for_symtable "$dlsyms")' || exit $?
-+ $show "(cd $output_objdir && $LTCC $LTCFLAGS -c$no_builtin_flag$pic_flag_for_symtable \"$dlsyms\")"
-+ $run eval '(cd $output_objdir && $LTCC $LTCFLAGS -c$no_builtin_flag$pic_flag_for_symtable "$dlsyms")' || exit $?
-
- # Clean up the generated files.
- $show "$rm $output_objdir/$dlsyms $nlist ${nlist}S ${nlist}T"
- $run $rm "$output_objdir/$dlsyms" "$nlist" "${nlist}S" "${nlist}T"
-
- # Transform the symbol file into the correct name.
-- compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"`
-- finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"`
-+ case $host in
-+ *cygwin* | *mingw* )
-+ if test -f "$output_objdir/${outputname}.def" ; then
-+ compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}.def $output_objdir/${outputname}S.${objext}%"`
-+ finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}.def $output_objdir/${outputname}S.${objext}%"`
-+ else
-+ compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"`
-+ finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"`
-+ fi
-+ ;;
-+ * )
-+ compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"`
-+ finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"`
-+ ;;
-+ esac
- ;;
- *)
- $echo "$modename: unknown suffix for \`$dlsyms'" 1>&2
-- exit 1
-+ exit $EXIT_FAILURE
- ;;
- esac
- else
-@@ -3473,7 +4724,7 @@
- finalize_command=`$echo "X$finalize_command" | $Xsed -e "s% @SYMFILE@%%"`
- fi
-
-- if test $need_relink = no || test "$build_libtool_libs" != yes; then
-+ if test "$need_relink" = no || test "$build_libtool_libs" != yes; then
- # Replace the output file specification.
- compile_command=`$echo "X$compile_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'`
- link_command="$compile_command$compile_rpath"
-@@ -3481,7 +4732,7 @@
- # We have no uninstalled library dependencies, so finalize right now.
- $show "$link_command"
- $run eval "$link_command"
-- status=$?
-+ exit_status=$?
-
- # Delete the generated files.
- if test -n "$dlsyms"; then
-@@ -3489,7 +4740,7 @@
- $run $rm "$output_objdir/${outputname}S.${objext}"
- fi
-
-- exit $status
-+ exit $exit_status
- fi
-
- if test -n "$shlibpath_var"; then
-@@ -3548,7 +4799,7 @@
- # Link the executable and exit
- $show "$link_command"
- $run eval "$link_command" || exit $?
-- exit 0
-+ exit $EXIT_SUCCESS
- fi
-
- if test "$hardcode_action" = relink; then
-@@ -3603,10 +4854,10 @@
- fi
-
- # Quote $echo for shipping.
-- if test "X$echo" = "X$SHELL $0 --fallback-echo"; then
-- case $0 in
-- [\\/]* | [A-Za-z]:[\\/]*) qecho="$SHELL $0 --fallback-echo";;
-- *) qecho="$SHELL `pwd`/$0 --fallback-echo";;
-+ if test "X$echo" = "X$SHELL $progpath --fallback-echo"; then
-+ case $progpath in
-+ [\\/]* | [A-Za-z]:[\\/]*) qecho="$SHELL $progpath --fallback-echo";;
-+ *) qecho="$SHELL `pwd`/$progpath --fallback-echo";;
- esac
- qecho=`$echo "X$qecho" | $Xsed -e "$sed_quote_subst"`
- else
-@@ -3618,15 +4869,376 @@
- # win32 will think the script is a binary if it has
- # a .exe suffix, so we strip it off here.
- case $output in
-- *.exe) output=`echo $output|${SED} 's,.exe$,,'` ;;
-+ *.exe) output=`$echo $output|${SED} 's,.exe$,,'` ;;
- esac
- # test for cygwin because mv fails w/o .exe extensions
- case $host in
-- *cygwin*) exeext=.exe ;;
-+ *cygwin*)
-+ exeext=.exe
-+ outputname=`$echo $outputname|${SED} 's,.exe$,,'` ;;
- *) exeext= ;;
- esac
-- $rm $output
-- trap "$rm $output; exit 1" 1 2 15
-+ case $host in
-+ *cygwin* | *mingw* )
-+ output_name=`basename $output`
-+ output_path=`dirname $output`
-+ cwrappersource="$output_path/$objdir/lt-$output_name.c"
-+ cwrapper="$output_path/$output_name.exe"
-+ $rm $cwrappersource $cwrapper
-+ trap "$rm $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15
-+
-+ cat > $cwrappersource <<EOF
-+
-+/* $cwrappersource - temporary wrapper executable for $objdir/$outputname
-+ Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP
-+
-+ The $output program cannot be directly executed until all the libtool
-+ libraries that it depends on are installed.
-+
-+ This wrapper executable should never be moved out of the build directory.
-+ If it is, it will not operate correctly.
-+
-+ Currently, it simply execs the wrapper *script* "/bin/sh $output",
-+ but could eventually absorb all of the scripts functionality and
-+ exec $objdir/$outputname directly.
-+*/
-+EOF
-+ cat >> $cwrappersource<<"EOF"
-+#include <stdio.h>
-+#include <stdlib.h>
-+#include <unistd.h>
-+#include <malloc.h>
-+#include <stdarg.h>
-+#include <assert.h>
-+#include <string.h>
-+#include <ctype.h>
-+#include <sys/stat.h>
-+
-+#if defined(PATH_MAX)
-+# define LT_PATHMAX PATH_MAX
-+#elif defined(MAXPATHLEN)
-+# define LT_PATHMAX MAXPATHLEN
-+#else
-+# define LT_PATHMAX 1024
-+#endif
-+
-+#ifndef DIR_SEPARATOR
-+# define DIR_SEPARATOR '/'
-+# define PATH_SEPARATOR ':'
-+#endif
-+
-+#if defined (_WIN32) || defined (__MSDOS__) || defined (__DJGPP__) || \
-+ defined (__OS2__)
-+# define HAVE_DOS_BASED_FILE_SYSTEM
-+# ifndef DIR_SEPARATOR_2
-+# define DIR_SEPARATOR_2 '\\'
-+# endif
-+# ifndef PATH_SEPARATOR_2
-+# define PATH_SEPARATOR_2 ';'
-+# endif
-+#endif
-+
-+#ifndef DIR_SEPARATOR_2
-+# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR)
-+#else /* DIR_SEPARATOR_2 */
-+# define IS_DIR_SEPARATOR(ch) \
-+ (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2))
-+#endif /* DIR_SEPARATOR_2 */
-+
-+#ifndef PATH_SEPARATOR_2
-+# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR)
-+#else /* PATH_SEPARATOR_2 */
-+# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2)
-+#endif /* PATH_SEPARATOR_2 */
-+
-+#define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type)))
-+#define XFREE(stale) do { \
-+ if (stale) { free ((void *) stale); stale = 0; } \
-+} while (0)
-+
-+/* -DDEBUG is fairly common in CFLAGS. */
-+#undef DEBUG
-+#if defined DEBUGWRAPPER
-+# define DEBUG(format, ...) fprintf(stderr, format, __VA_ARGS__)
-+#else
-+# define DEBUG(format, ...)
-+#endif
-+
-+const char *program_name = NULL;
-+
-+void * xmalloc (size_t num);
-+char * xstrdup (const char *string);
-+const char * base_name (const char *name);
-+char * find_executable(const char *wrapper);
-+int check_executable(const char *path);
-+char * strendzap(char *str, const char *pat);
-+void lt_fatal (const char *message, ...);
-+
-+int
-+main (int argc, char *argv[])
-+{
-+ char **newargz;
-+ int i;
-+
-+ program_name = (char *) xstrdup (base_name (argv[0]));
-+ DEBUG("(main) argv[0] : %s\n",argv[0]);
-+ DEBUG("(main) program_name : %s\n",program_name);
-+ newargz = XMALLOC(char *, argc+2);
-+EOF
-+
-+ cat >> $cwrappersource <<EOF
-+ newargz[0] = (char *) xstrdup("$SHELL");
-+EOF
-+
-+ cat >> $cwrappersource <<"EOF"
-+ newargz[1] = find_executable(argv[0]);
-+ if (newargz[1] == NULL)
-+ lt_fatal("Couldn't find %s", argv[0]);
-+ DEBUG("(main) found exe at : %s\n",newargz[1]);
-+ /* we know the script has the same name, without the .exe */
-+ /* so make sure newargz[1] doesn't end in .exe */
-+ strendzap(newargz[1],".exe");
-+ for (i = 1; i < argc; i++)
-+ newargz[i+1] = xstrdup(argv[i]);
-+ newargz[argc+1] = NULL;
-+
-+ for (i=0; i<argc+1; i++)
-+ {
-+ DEBUG("(main) newargz[%d] : %s\n",i,newargz[i]);
-+ ;
-+ }
-+
-+EOF
-+
-+ case $host_os in
-+ mingw*)
-+ cat >> $cwrappersource <<EOF
-+ execv("$SHELL",(char const **)newargz);
-+EOF
-+ ;;
-+ *)
-+ cat >> $cwrappersource <<EOF
-+ execv("$SHELL",newargz);
-+EOF
-+ ;;
-+ esac
-+
-+ cat >> $cwrappersource <<"EOF"
-+ return 127;
-+}
-+
-+void *
-+xmalloc (size_t num)
-+{
-+ void * p = (void *) malloc (num);
-+ if (!p)
-+ lt_fatal ("Memory exhausted");
-+
-+ return p;
-+}
-+
-+char *
-+xstrdup (const char *string)
-+{
-+ return string ? strcpy ((char *) xmalloc (strlen (string) + 1), string) : NULL
-+;
-+}
-+
-+const char *
-+base_name (const char *name)
-+{
-+ const char *base;
-+
-+#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
-+ /* Skip over the disk name in MSDOS pathnames. */
-+ if (isalpha ((unsigned char)name[0]) && name[1] == ':')
-+ name += 2;
-+#endif
-+
-+ for (base = name; *name; name++)
-+ if (IS_DIR_SEPARATOR (*name))
-+ base = name + 1;
-+ return base;
-+}
-+
-+int
-+check_executable(const char * path)
-+{
-+ struct stat st;
-+
-+ DEBUG("(check_executable) : %s\n", path ? (*path ? path : "EMPTY!") : "NULL!");
-+ if ((!path) || (!*path))
-+ return 0;
-+
-+ if ((stat (path, &st) >= 0) &&
-+ (
-+ /* MinGW & native WIN32 do not support S_IXOTH or S_IXGRP */
-+#if defined (S_IXOTH)
-+ ((st.st_mode & S_IXOTH) == S_IXOTH) ||
-+#endif
-+#if defined (S_IXGRP)
-+ ((st.st_mode & S_IXGRP) == S_IXGRP) ||
-+#endif
-+ ((st.st_mode & S_IXUSR) == S_IXUSR))
-+ )
-+ return 1;
-+ else
-+ return 0;
-+}
-+
-+/* Searches for the full path of the wrapper. Returns
-+ newly allocated full path name if found, NULL otherwise */
-+char *
-+find_executable (const char* wrapper)
-+{
-+ int has_slash = 0;
-+ const char* p;
-+ const char* p_next;
-+ /* static buffer for getcwd */
-+ char tmp[LT_PATHMAX + 1];
-+ int tmp_len;
-+ char* concat_name;
-+
-+ DEBUG("(find_executable) : %s\n", wrapper ? (*wrapper ? wrapper : "EMPTY!") : "NULL!");
-+
-+ if ((wrapper == NULL) || (*wrapper == '\0'))
-+ return NULL;
-+
-+ /* Absolute path? */
-+#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
-+ if (isalpha ((unsigned char)wrapper[0]) && wrapper[1] == ':')
-+ {
-+ concat_name = xstrdup (wrapper);
-+ if (check_executable(concat_name))
-+ return concat_name;
-+ XFREE(concat_name);
-+ }
-+ else
-+ {
-+#endif
-+ if (IS_DIR_SEPARATOR (wrapper[0]))
-+ {
-+ concat_name = xstrdup (wrapper);
-+ if (check_executable(concat_name))
-+ return concat_name;
-+ XFREE(concat_name);
-+ }
-+#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
-+ }
-+#endif
-+
-+ for (p = wrapper; *p; p++)
-+ if (*p == '/')
-+ {
-+ has_slash = 1;
-+ break;
-+ }
-+ if (!has_slash)
-+ {
-+ /* no slashes; search PATH */
-+ const char* path = getenv ("PATH");
-+ if (path != NULL)
-+ {
-+ for (p = path; *p; p = p_next)
-+ {
-+ const char* q;
-+ size_t p_len;
-+ for (q = p; *q; q++)
-+ if (IS_PATH_SEPARATOR(*q))
-+ break;
-+ p_len = q - p;
-+ p_next = (*q == '\0' ? q : q + 1);
-+ if (p_len == 0)
-+ {
-+ /* empty path: current directory */
-+ if (getcwd (tmp, LT_PATHMAX) == NULL)
-+ lt_fatal ("getcwd failed");
-+ tmp_len = strlen(tmp);
-+ concat_name = XMALLOC(char, tmp_len + 1 + strlen(wrapper) + 1);
-+ memcpy (concat_name, tmp, tmp_len);
-+ concat_name[tmp_len] = '/';
-+ strcpy (concat_name + tmp_len + 1, wrapper);
-+ }
-+ else
-+ {
-+ concat_name = XMALLOC(char, p_len + 1 + strlen(wrapper) + 1);
-+ memcpy (concat_name, p, p_len);
-+ concat_name[p_len] = '/';
-+ strcpy (concat_name + p_len + 1, wrapper);
-+ }
-+ if (check_executable(concat_name))
-+ return concat_name;
-+ XFREE(concat_name);
-+ }
-+ }
-+ /* not found in PATH; assume curdir */
-+ }
-+ /* Relative path | not found in path: prepend cwd */
-+ if (getcwd (tmp, LT_PATHMAX) == NULL)
-+ lt_fatal ("getcwd failed");
-+ tmp_len = strlen(tmp);
-+ concat_name = XMALLOC(char, tmp_len + 1 + strlen(wrapper) + 1);
-+ memcpy (concat_name, tmp, tmp_len);
-+ concat_name[tmp_len] = '/';
-+ strcpy (concat_name + tmp_len + 1, wrapper);
-+
-+ if (check_executable(concat_name))
-+ return concat_name;
-+ XFREE(concat_name);
-+ return NULL;
-+}
-+
-+char *
-+strendzap(char *str, const char *pat)
-+{
-+ size_t len, patlen;
-+
-+ assert(str != NULL);
-+ assert(pat != NULL);
-+
-+ len = strlen(str);
-+ patlen = strlen(pat);
-+
-+ if (patlen <= len)
-+ {
-+ str += len - patlen;
-+ if (strcmp(str, pat) == 0)
-+ *str = '\0';
-+ }
-+ return str;
-+}
-+
-+static void
-+lt_error_core (int exit_status, const char * mode,
-+ const char * message, va_list ap)
-+{
-+ fprintf (stderr, "%s: %s: ", program_name, mode);
-+ vfprintf (stderr, message, ap);
-+ fprintf (stderr, ".\n");
-+
-+ if (exit_status >= 0)
-+ exit (exit_status);
-+}
-+
-+void
-+lt_fatal (const char *message, ...)
-+{
-+ va_list ap;
-+ va_start (ap, message);
-+ lt_error_core (EXIT_FAILURE, "FATAL", message, ap);
-+ va_end (ap);
-+}
-+EOF
-+ # we should really use a build-platform specific compiler
-+ # here, but OTOH, the wrappers (shell script and this C one)
-+ # are only useful if you want to execute the "real" binary.
-+ # Since the "real" binary is built for $host, then this
-+ # wrapper might as well be built for $host, too.
-+ $run $LTCC $LTCFLAGS -s -o $cwrapper $cwrappersource
-+ ;;
-+ esac
-+ $rm $output
-+ trap "$rm $output; exit $EXIT_FAILURE" 1 2 15
-
- $echo > $output "\
- #! $SHELL
-@@ -3642,12 +5254,12 @@
-
- # Sed substitution that helps us do robust quoting. It backslashifies
- # metacharacters that are still active within double-quoted strings.
--Xsed="${SED}"' -e 1s/^X//'
-+Xsed='${SED} -e 1s/^X//'
- sed_quote_subst='$sed_quote_subst'
-
- # The HP-UX ksh and POSIX shell print the target directory to stdout
- # if CDPATH is set.
--if test \"\${CDPATH+set}\" = set; then CDPATH=:; export CDPATH; fi
-+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
-
- relink_command=\"$relink_command\"
-
-@@ -3702,7 +5314,7 @@
- "
-
- if test "$fast_install" = yes; then
-- echo >> $output "\
-+ $echo >> $output "\
- program=lt-'$outputname'$exeext
- progdir=\"\$thisdir/$objdir\"
-
-@@ -3718,7 +5330,7 @@
- $rm \"\$progdir/\$file\"
- fi"
-
-- echo >> $output "\
-+ $echo >> $output "\
-
- # relink executable if necessary
- if test -n \"\$relink_command\"; then
-@@ -3726,7 +5338,7 @@
- else
- $echo \"\$relink_command_output\" >&2
- $rm \"\$progdir/\$file\"
-- exit 1
-+ exit $EXIT_FAILURE
- fi
- fi
-
-@@ -3736,13 +5348,13 @@
- $rm \"\$progdir/\$file\"
- fi"
- else
-- echo >> $output "\
-+ $echo >> $output "\
- program='$outputname'
- progdir=\"\$thisdir/$objdir\"
- "
- fi
-
-- echo >> $output "\
-+ $echo >> $output "\
-
- if test -f \"\$progdir/\$program\"; then"
-
-@@ -3753,7 +5365,7 @@
- $shlibpath_var=\"$temp_rpath\$$shlibpath_var\"
-
- # Some systems cannot cope with colon-terminated $shlibpath_var
-- # The second colon is a workaround for a bug in BeOS R4 ${SED}
-+ # The second colon is a workaround for a bug in BeOS R4 sed
- $shlibpath_var=\`\$echo \"X\$$shlibpath_var\" | \$Xsed -e 's/::*\$//'\`
-
- export $shlibpath_var
-@@ -3773,47 +5385,35 @@
- # Run the actual program with our arguments.
- "
- case $host in
-- # win32 systems need to use the prog path for dll
-- # lookup to work
-- *-*-cygwin* | *-*-pw32*)
-- $echo >> $output "\
-- exec \$progdir/\$program \${1+\"\$@\"}
--"
-- ;;
--
- # Backslashes separate directories on plain windows
- *-*-mingw | *-*-os2*)
- $echo >> $output "\
-- exec \$progdir\\\\\$program \${1+\"\$@\"}
-+ exec \"\$progdir\\\\\$program\" \${1+\"\$@\"}
- "
- ;;
-
- *)
- $echo >> $output "\
-- # Export the path to the program.
-- PATH=\"\$progdir:\$PATH\"
-- export PATH
--
-- exec \$program \${1+\"\$@\"}
-+ exec \"\$progdir/\$program\" \${1+\"\$@\"}
- "
- ;;
- esac
- $echo >> $output "\
- \$echo \"\$0: cannot exec \$program \${1+\"\$@\"}\"
-- exit 1
-+ exit $EXIT_FAILURE
- fi
- else
- # The program doesn't exist.
-- \$echo \"\$0: error: \$progdir/\$program does not exist\" 1>&2
-+ \$echo \"\$0: error: \\\`\$progdir/\$program' does not exist\" 1>&2
- \$echo \"This script is just a wrapper for \$program.\" 1>&2
-- echo \"See the $PACKAGE documentation for more information.\" 1>&2
-- exit 1
-+ $echo \"See the $PACKAGE documentation for more information.\" 1>&2
-+ exit $EXIT_FAILURE
- fi
- fi\
- "
- chmod +x $output
- fi
-- exit 0
-+ exit $EXIT_SUCCESS
- ;;
- esac
-
-@@ -3829,74 +5429,130 @@
- oldobjs="$libobjs_save"
- build_libtool_libs=no
- else
-- oldobjs="$objs$old_deplibs "`$echo "X$libobjs_save" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP`
-+ oldobjs="$old_deplibs $non_pic_objects"
- fi
- addlibs="$old_convenience"
- fi
-
- if test -n "$addlibs"; then
- gentop="$output_objdir/${outputname}x"
-- $show "${rm}r $gentop"
-- $run ${rm}r "$gentop"
-- $show "mkdir $gentop"
-- $run mkdir "$gentop"
-- status=$?
-- if test $status -ne 0 && test ! -d "$gentop"; then
-- exit $status
-- fi
- generated="$generated $gentop"
-
-- # Add in members from convenience archives.
-- for xlib in $addlibs; do
-- # Extract the objects.
-- case $xlib in
-- [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;;
-- *) xabs=`pwd`"/$xlib" ;;
-- esac
-- xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'`
-- xdir="$gentop/$xlib"
--
-- $show "${rm}r $xdir"
-- $run ${rm}r "$xdir"
-- $show "mkdir $xdir"
-- $run mkdir "$xdir"
-- status=$?
-- if test $status -ne 0 && test ! -d "$xdir"; then
-- exit $status
-- fi
-- $show "(cd $xdir && $AR x $xabs)"
-- $run eval "(cd \$xdir && $AR x \$xabs)" || exit $?
--
-- oldobjs="$oldobjs "`find $xdir -name \*.${objext} -print -o -name \*.lo -print | $NL2SP`
-- done
-+ func_extract_archives $gentop $addlibs
-+ oldobjs="$oldobjs $func_extract_archives_result"
- fi
-
- # Do each command in the archive commands.
- if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then
-- eval cmds=\"$old_archive_from_new_cmds\"
-+ cmds=$old_archive_from_new_cmds
- else
-- # Ensure that we have .o objects in place in case we decided
-- # not to build a shared library, and have fallen back to building
-- # static libs even though --disable-static was passed!
-- for oldobj in $oldobjs; do
-- if test ! -f $oldobj; then
-- xdir=`$echo "X$oldobj" | $Xsed -e 's%/[^/]*$%%'`
-- if test "X$xdir" = "X$oldobj"; then
-- xdir="."
-- else
-- xdir="$xdir"
-+ # POSIX demands no paths to be encoded in archives. We have
-+ # to avoid creating archives with duplicate basenames if we
-+ # might have to extract them afterwards, e.g., when creating a
-+ # static archive out of a convenience library, or when linking
-+ # the entirety of a libtool archive into another (currently
-+ # not supported by libtool).
-+ if (for obj in $oldobjs
-+ do
-+ $echo "X$obj" | $Xsed -e 's%^.*/%%'
-+ done | sort | sort -uc >/dev/null 2>&1); then
-+ :
-+ else
-+ $echo "copying selected object files to avoid basename conflicts..."
-+
-+ if test -z "$gentop"; then
-+ gentop="$output_objdir/${outputname}x"
-+ generated="$generated $gentop"
-+
-+ $show "${rm}r $gentop"
-+ $run ${rm}r "$gentop"
-+ $show "$mkdir $gentop"
-+ $run $mkdir "$gentop"
-+ exit_status=$?
-+ if test "$exit_status" -ne 0 && test ! -d "$gentop"; then
-+ exit $exit_status
- fi
-- baseobj=`$echo "X$oldobj" | $Xsed -e 's%^.*/%%'`
-- obj=`$echo "X$baseobj" | $Xsed -e "$o2lo"`
-- $show "(cd $xdir && ${LN_S} $obj $baseobj)"
-- $run eval '(cd $xdir && ${LN_S} $obj $baseobj)' || exit $?
- fi
-- done
-+
-+ save_oldobjs=$oldobjs
-+ oldobjs=
-+ counter=1
-+ for obj in $save_oldobjs
-+ do
-+ objbase=`$echo "X$obj" | $Xsed -e 's%^.*/%%'`
-+ case " $oldobjs " in
-+ " ") oldobjs=$obj ;;
-+ *[\ /]"$objbase "*)
-+ while :; do
-+ # Make sure we don't pick an alternate name that also
-+ # overlaps.
-+ newobj=lt$counter-$objbase
-+ counter=`expr $counter + 1`
-+ case " $oldobjs " in
-+ *[\ /]"$newobj "*) ;;
-+ *) if test ! -f "$gentop/$newobj"; then break; fi ;;
-+ esac
-+ done
-+ $show "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj"
-+ $run ln "$obj" "$gentop/$newobj" ||
-+ $run cp "$obj" "$gentop/$newobj"
-+ oldobjs="$oldobjs $gentop/$newobj"
-+ ;;
-+ *) oldobjs="$oldobjs $obj" ;;
-+ esac
-+ done
-+ fi
-
- eval cmds=\"$old_archive_cmds\"
-+
-+ if len=`expr "X$cmds" : ".*"` &&
-+ test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then
-+ cmds=$old_archive_cmds
-+ else
-+ # the command line is too long to link in one step, link in parts
-+ $echo "using piecewise archive linking..."
-+ save_RANLIB=$RANLIB
-+ RANLIB=:
-+ objlist=
-+ concat_cmds=
-+ save_oldobjs=$oldobjs
-+
-+ # Is there a better way of finding the last object in the list?
-+ for obj in $save_oldobjs
-+ do
-+ last_oldobj=$obj
-+ done
-+ for obj in $save_oldobjs
-+ do
-+ oldobjs="$objlist $obj"
-+ objlist="$objlist $obj"
-+ eval test_cmds=\"$old_archive_cmds\"
-+ if len=`expr "X$test_cmds" : ".*" 2>/dev/null` &&
-+ test "$len" -le "$max_cmd_len"; then
-+ :
-+ else
-+ # the above command should be used before it gets too long
-+ oldobjs=$objlist
-+ if test "$obj" = "$last_oldobj" ; then
-+ RANLIB=$save_RANLIB
-+ fi
-+ test -z "$concat_cmds" || concat_cmds=$concat_cmds~
-+ eval concat_cmds=\"\${concat_cmds}$old_archive_cmds\"
-+ objlist=
-+ fi
-+ done
-+ RANLIB=$save_RANLIB
-+ oldobjs=$objlist
-+ if test "X$oldobjs" = "X" ; then
-+ eval cmds=\"\$concat_cmds\"
-+ else
-+ eval cmds=\"\$concat_cmds~\$old_archive_cmds\"
-+ fi
-+ fi
- fi
- save_ifs="$IFS"; IFS='~'
- for cmd in $cmds; do
-+ eval cmd=\"$cmd\"
- IFS="$save_ifs"
- $show "$cmd"
- $run eval "$cmd" || exit $?
-@@ -3928,8 +5584,12 @@
- fi
- done
- # Quote the link command for shipping.
-- relink_command="(cd `pwd`; $SHELL $0 --mode=relink $libtool_args)"
-+ relink_command="(cd `pwd`; $SHELL $progpath $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)"
- relink_command=`$echo "X$relink_command" | $Xsed -e "$sed_quote_subst"`
-+ if test "$hardcode_automatic" = yes ; then
-+ relink_command=
-+ fi
-+
-
- # Only create the output if not a dry run.
- if test -z "$run"; then
-@@ -3948,7 +5608,7 @@
- eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib`
- if test -z "$libdir"; then
- $echo "$modename: \`$deplib' is not a valid libtool archive" 1>&2
-- exit 1
-+ exit $EXIT_FAILURE
- fi
- newdependency_libs="$newdependency_libs $libdir/$name"
- ;;
-@@ -3962,7 +5622,7 @@
- eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib`
- if test -z "$libdir"; then
- $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2
-- exit 1
-+ exit $EXIT_FAILURE
- fi
- newdlfiles="$newdlfiles $libdir/$name"
- done
-@@ -3973,17 +5633,36 @@
- eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib`
- if test -z "$libdir"; then
- $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2
-- exit 1
-+ exit $EXIT_FAILURE
- fi
- newdlprefiles="$newdlprefiles $libdir/$name"
- done
- dlprefiles="$newdlprefiles"
-+ else
-+ newdlfiles=
-+ for lib in $dlfiles; do
-+ case $lib in
-+ [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;;
-+ *) abs=`pwd`"/$lib" ;;
-+ esac
-+ newdlfiles="$newdlfiles $abs"
-+ done
-+ dlfiles="$newdlfiles"
-+ newdlprefiles=
-+ for lib in $dlprefiles; do
-+ case $lib in
-+ [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;;
-+ *) abs=`pwd`"/$lib" ;;
-+ esac
-+ newdlprefiles="$newdlprefiles $abs"
-+ done
-+ dlprefiles="$newdlprefiles"
- fi
- $rm $output
- # place dlname in correct position for cygwin
- tdlname=$dlname
- case $host,$output,$installed,$module,$dlname in
-- *cygwin*,*lai,yes,no,*.dll) tdlname=../bin/$dlname ;;
-+ *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll) tdlname=../bin/$dlname ;;
- esac
- $echo > $output "\
- # $outputname - a libtool library file
-@@ -4012,13 +5691,16 @@
- # Is this an already installed library?
- installed=$installed
-
-+# Should we warn about portability when linking against -modules?
-+shouldnotlink=$module
-+
- # Files to dlopen/dlpreopen
- dlopen='$dlfiles'
- dlpreopen='$dlprefiles'
-
- # Directory that this library needs to be installed in:
- libdir='$install_libdir'"
-- if test "$installed" = no && test $need_relink = yes; then
-+ if test "$installed" = no && test "$need_relink" = yes; then
- $echo >> $output "\
- relink_command=\"$relink_command\""
- fi
-@@ -4031,7 +5713,7 @@
- $run eval '(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)' || exit $?
- ;;
- esac
-- exit 0
-+ exit $EXIT_SUCCESS
- ;;
-
- # libtool install mode
-@@ -4042,11 +5724,11 @@
- # install_prog (especially on Windows NT).
- if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh ||
- # Allow the use of GNU shtool's install command.
-- $echo "X$nonopt" | $Xsed | grep shtool > /dev/null; then
-+ $echo "X$nonopt" | grep shtool > /dev/null; then
- # Aesthetically quote it.
- arg=`$echo "X$nonopt" | $Xsed -e "$sed_quote_subst"`
- case $arg in
-- *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*)
-+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
- arg="\"$arg\""
- ;;
- esac
-@@ -4055,14 +5737,14 @@
- shift
- else
- install_prog=
-- arg="$nonopt"
-+ arg=$nonopt
- fi
-
- # The real first argument should be the name of the installation program.
- # Aesthetically quote it.
- arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
- case $arg in
-- *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*)
-+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
- arg="\"$arg\""
- ;;
- esac
-@@ -4080,28 +5762,31 @@
- do
- if test -n "$dest"; then
- files="$files $dest"
-- dest="$arg"
-+ dest=$arg
- continue
- fi
-
- case $arg in
- -d) isdir=yes ;;
-- -f) prev="-f" ;;
-- -g) prev="-g" ;;
-- -m) prev="-m" ;;
-- -o) prev="-o" ;;
-+ -f)
-+ case " $install_prog " in
-+ *[\\\ /]cp\ *) ;;
-+ *) prev=$arg ;;
-+ esac
-+ ;;
-+ -g | -m | -o) prev=$arg ;;
- -s)
- stripme=" -s"
- continue
- ;;
-- -*) ;;
--
-+ -*)
-+ ;;
- *)
- # If the previous option needed an argument, then skip it.
- if test -n "$prev"; then
- prev=
- else
-- dest="$arg"
-+ dest=$arg
- continue
- fi
- ;;
-@@ -4110,7 +5795,7 @@
- # Aesthetically quote the argument.
- arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
- case $arg in
-- *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*)
-+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
- arg="\"$arg\""
- ;;
- esac
-@@ -4120,13 +5805,13 @@
- if test -z "$install_prog"; then
- $echo "$modename: you must specify an install program" 1>&2
- $echo "$help" 1>&2
-- exit 1
-+ exit $EXIT_FAILURE
- fi
-
- if test -n "$prev"; then
- $echo "$modename: the \`$prev' option requires an argument" 1>&2
- $echo "$help" 1>&2
-- exit 1
-+ exit $EXIT_FAILURE
- fi
-
- if test -z "$files"; then
-@@ -4136,7 +5821,7 @@
- $echo "$modename: you must specify a destination" 1>&2
- fi
- $echo "$help" 1>&2
-- exit 1
-+ exit $EXIT_FAILURE
- fi
-
- # Strip any trailing slash from the destination.
-@@ -4154,10 +5839,10 @@
-
- # Not a directory, so check to see that there is only one file specified.
- set dummy $files
-- if test $# -gt 2; then
-+ if test "$#" -gt 2; then
- $echo "$modename: \`$dest' is not a directory" 1>&2
- $echo "$help" 1>&2
-- exit 1
-+ exit $EXIT_FAILURE
- fi
- fi
- case $destdir in
-@@ -4169,7 +5854,7 @@
- *)
- $echo "$modename: \`$destdir' must be an absolute directory name" 1>&2
- $echo "$help" 1>&2
-- exit 1
-+ exit $EXIT_FAILURE
- ;;
- esac
- done
-@@ -4194,11 +5879,11 @@
-
- *.la)
- # Check to see that this really is a libtool archive.
-- if (${SED} -e '2q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then :
-+ if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then :
- else
- $echo "$modename: \`$file' is not a valid libtool archive" 1>&2
- $echo "$help" 1>&2
-- exit 1
-+ exit $EXIT_FAILURE
- fi
-
- library_names=
-@@ -4229,12 +5914,33 @@
- dir="$dir$objdir"
-
- if test -n "$relink_command"; then
-+ # Determine the prefix the user has applied to our future dir.
-+ inst_prefix_dir=`$echo "$destdir" | $SED "s%$libdir\$%%"`
-+
-+ # Don't allow the user to place us outside of our expected
-+ # location b/c this prevents finding dependent libraries that
-+ # are installed to the same prefix.
-+ # At present, this check doesn't affect windows .dll's that
-+ # are installed into $libdir/../bin (currently, that works fine)
-+ # but it's something to keep an eye on.
-+ if test "$inst_prefix_dir" = "$destdir"; then
-+ $echo "$modename: error: cannot install \`$file' to a directory not ending in $libdir" 1>&2
-+ exit $EXIT_FAILURE
-+ fi
-+
-+ if test -n "$inst_prefix_dir"; then
-+ # Stick the inst_prefix_dir data into the link command.
-+ relink_command=`$echo "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"`
-+ else
-+ relink_command=`$echo "$relink_command" | $SED "s%@inst_prefix_dir@%%"`
-+ fi
-+
- $echo "$modename: warning: relinking \`$file'" 1>&2
- $show "$relink_command"
- if $run eval "$relink_command"; then :
- else
- $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2
-- continue
-+ exit $EXIT_FAILURE
- fi
- fi
-
-@@ -4256,25 +5962,38 @@
- $run eval "$striplib $destdir/$realname" || exit $?
- fi
-
-- if test $# -gt 0; then
-+ if test "$#" -gt 0; then
- # Delete the old symlinks, and create new ones.
-+ # Try `ln -sf' first, because the `ln' binary might depend on
-+ # the symlink we replace! Solaris /bin/ln does not understand -f,
-+ # so we also need to try rm && ln -s.
- for linkname
- do
- if test "$linkname" != "$realname"; then
-- $show "(cd $destdir && $rm $linkname && $LN_S $realname $linkname)"
-- $run eval "(cd $destdir && $rm $linkname && $LN_S $realname $linkname)"
-+ $show "(cd $destdir && { $LN_S -f $realname $linkname || { $rm $linkname && $LN_S $realname $linkname; }; })"
-+ $run eval "(cd $destdir && { $LN_S -f $realname $linkname || { $rm $linkname && $LN_S $realname $linkname; }; })"
- fi
- done
- fi
-
- # Do each command in the postinstall commands.
- lib="$destdir/$realname"
-- eval cmds=\"$postinstall_cmds\"
-+ cmds=$postinstall_cmds
- save_ifs="$IFS"; IFS='~'
- for cmd in $cmds; do
- IFS="$save_ifs"
-+ eval cmd=\"$cmd\"
- $show "$cmd"
-- $run eval "$cmd" || exit $?
-+ $run eval "$cmd" || {
-+ lt_exit=$?
-+
-+ # Restore the uninstalled library and exit
-+ if test "$mode" = relink; then
-+ $run eval '(cd $output_objdir && $rm ${realname}T && $mv ${realname}U $realname)'
-+ fi
-+
-+ exit $lt_exit
-+ }
- done
- IFS="$save_ifs"
- fi
-@@ -4312,7 +6031,7 @@
- *)
- $echo "$modename: cannot copy a libtool object to \`$destfile'" 1>&2
- $echo "$help" 1>&2
-- exit 1
-+ exit $EXIT_FAILURE
- ;;
- esac
-
-@@ -4330,7 +6049,7 @@
- $show "$install_prog $staticobj $staticdest"
- $run eval "$install_prog \$staticobj \$staticdest" || exit $?
- fi
-- exit 0
-+ exit $EXIT_SUCCESS
- ;;
-
- *)
-@@ -4342,29 +6061,47 @@
- destfile="$destdir/$destfile"
- fi
-
-+ # If the file is missing, and there is a .exe on the end, strip it
-+ # because it is most likely a libtool script we actually want to
-+ # install
-+ stripped_ext=""
-+ case $file in
-+ *.exe)
-+ if test ! -f "$file"; then
-+ file=`$echo $file|${SED} 's,.exe$,,'`
-+ stripped_ext=".exe"
-+ fi
-+ ;;
-+ esac
-+
- # Do a test to see if this is really a libtool program.
- case $host in
- *cygwin*|*mingw*)
-- wrapper=`echo $file | ${SED} -e 's,.exe$,,'`
-+ wrapper=`$echo $file | ${SED} -e 's,.exe$,,'`
- ;;
- *)
- wrapper=$file
- ;;
- esac
-- if (${SED} -e '4q' $wrapper | egrep "^# Generated by .*$PACKAGE")>/dev/null 2>&1; then
-+ if (${SED} -e '4q' $wrapper | grep "^# Generated by .*$PACKAGE")>/dev/null 2>&1; then
- notinst_deplibs=
- relink_command=
-
-+ # Note that it is not necessary on cygwin/mingw to append a dot to
-+ # foo even if both foo and FILE.exe exist: automatic-append-.exe
-+ # behavior happens only for exec(3), not for open(2)! Also, sourcing
-+ # `FILE.' does not work on cygwin managed mounts.
-+ #
- # If there is no directory component, then add one.
-- case $file in
-- */* | *\\*) . $wrapper ;;
-- *) . ./$wrapper ;;
-+ case $wrapper in
-+ */* | *\\*) . ${wrapper} ;;
-+ *) . ./${wrapper} ;;
- esac
-
- # Check the variables that should have been set.
- if test -z "$notinst_deplibs"; then
- $echo "$modename: invalid libtool wrapper script \`$wrapper'" 1>&2
-- exit 1
-+ exit $EXIT_FAILURE
- fi
-
- finalize=yes
-@@ -4386,24 +6123,22 @@
- done
-
- relink_command=
-+ # Note that it is not necessary on cygwin/mingw to append a dot to
-+ # foo even if both foo and FILE.exe exist: automatic-append-.exe
-+ # behavior happens only for exec(3), not for open(2)! Also, sourcing
-+ # `FILE.' does not work on cygwin managed mounts.
-+ #
- # If there is no directory component, then add one.
-- case $file in
-- */* | *\\*) . $wrapper ;;
-- *) . ./$wrapper ;;
-+ case $wrapper in
-+ */* | *\\*) . ${wrapper} ;;
-+ *) . ./${wrapper} ;;
- esac
-
- outputname=
- if test "$fast_install" = no && test -n "$relink_command"; then
- if test "$finalize" = yes && test -z "$run"; then
-- tmpdir="/tmp"
-- test -n "$TMPDIR" && tmpdir="$TMPDIR"
-- tmpdir="$tmpdir/libtool-$$"
-- if $mkdir -p "$tmpdir" && chmod 700 "$tmpdir"; then :
-- else
-- $echo "$modename: error: cannot create temporary directory \`$tmpdir'" 1>&2
-- continue
-- fi
-- file=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
-+ tmpdir=`func_mktempdir`
-+ file=`$echo "X$file$stripped_ext" | $Xsed -e 's%^.*/%%'`
- outputname="$tmpdir/$file"
- # Replace the output file specification.
- relink_command=`$echo "X$relink_command" | $Xsed -e 's%@OUTPUT@%'"$outputname"'%g'`
-@@ -4421,14 +6156,14 @@
- fi
- else
- # Install the binary that we compiled earlier.
-- file=`$echo "X$file" | $Xsed -e "s%\([^/]*\)$%$objdir/\1%"`
-+ file=`$echo "X$file$stripped_ext" | $Xsed -e "s%\([^/]*\)$%$objdir/\1%"`
- fi
- fi
-
- # remove .exe since cygwin /usr/bin/install will append another
-- # one anyways
-+ # one anyway
- case $install_prog,$host in
-- /usr/bin/install*,*cygwin*)
-+ */usr/bin/install*,*cygwin*)
- case $file:$destfile in
- *.exe:*.exe)
- # this is ok
-@@ -4437,7 +6172,7 @@
- destfile=$destfile.exe
- ;;
- *:*.exe)
-- destfile=`echo $destfile | ${SED} -e 's,.exe$,,'`
-+ destfile=`$echo $destfile | ${SED} -e 's,.exe$,,'`
- ;;
- esac
- ;;
-@@ -4458,16 +6193,17 @@
- $show "$install_prog $file $oldlib"
- $run eval "$install_prog \$file \$oldlib" || exit $?
-
-- if test -n "$stripme" && test -n "$striplib"; then
-+ if test -n "$stripme" && test -n "$old_striplib"; then
- $show "$old_striplib $oldlib"
- $run eval "$old_striplib $oldlib" || exit $?
- fi
-
- # Do each command in the postinstall commands.
-- eval cmds=\"$old_postinstall_cmds\"
-+ cmds=$old_postinstall_cmds
- save_ifs="$IFS"; IFS='~'
- for cmd in $cmds; do
- IFS="$save_ifs"
-+ eval cmd=\"$cmd\"
- $show "$cmd"
- $run eval "$cmd" || exit $?
- done
-@@ -4481,9 +6217,9 @@
- if test -n "$current_libdirs"; then
- # Maybe just do a dry run.
- test -n "$run" && current_libdirs=" -n$current_libdirs"
-- exec_cmd='$SHELL $0 --finish$current_libdirs'
-+ exec_cmd='$SHELL $progpath $preserve_args --finish$current_libdirs'
- else
-- exit 0
-+ exit $EXIT_SUCCESS
- fi
- ;;
-
-@@ -4502,10 +6238,11 @@
- for libdir in $libdirs; do
- if test -n "$finish_cmds"; then
- # Do each command in the finish commands.
-- eval cmds=\"$finish_cmds\"
-+ cmds=$finish_cmds
- save_ifs="$IFS"; IFS='~'
- for cmd in $cmds; do
- IFS="$save_ifs"
-+ eval cmd=\"$cmd\"
- $show "$cmd"
- $run eval "$cmd" || admincmds="$admincmds
- $cmd"
-@@ -4522,43 +6259,43 @@
- fi
-
- # Exit here if they wanted silent mode.
-- test "$show" = ":" && exit 0
-+ test "$show" = : && exit $EXIT_SUCCESS
-
-- echo "----------------------------------------------------------------------"
-- echo "Libraries have been installed in:"
-+ $echo "X----------------------------------------------------------------------" | $Xsed
-+ $echo "Libraries have been installed in:"
- for libdir in $libdirs; do
-- echo " $libdir"
-+ $echo " $libdir"
- done
-- echo
-- echo "If you ever happen to want to link against installed libraries"
-- echo "in a given directory, LIBDIR, you must either use libtool, and"
-- echo "specify the full pathname of the library, or use the \`-LLIBDIR'"
-- echo "flag during linking and do at least one of the following:"
-+ $echo
-+ $echo "If you ever happen to want to link against installed libraries"
-+ $echo "in a given directory, LIBDIR, you must either use libtool, and"
-+ $echo "specify the full pathname of the library, or use the \`-LLIBDIR'"
-+ $echo "flag during linking and do at least one of the following:"
- if test -n "$shlibpath_var"; then
-- echo " - add LIBDIR to the \`$shlibpath_var' environment variable"
-- echo " during execution"
-+ $echo " - add LIBDIR to the \`$shlibpath_var' environment variable"
-+ $echo " during execution"
- fi
- if test -n "$runpath_var"; then
-- echo " - add LIBDIR to the \`$runpath_var' environment variable"
-- echo " during linking"
-+ $echo " - add LIBDIR to the \`$runpath_var' environment variable"
-+ $echo " during linking"
- fi
- if test -n "$hardcode_libdir_flag_spec"; then
- libdir=LIBDIR
- eval flag=\"$hardcode_libdir_flag_spec\"
-
-- echo " - use the \`$flag' linker flag"
-+ $echo " - use the \`$flag' linker flag"
- fi
- if test -n "$admincmds"; then
-- echo " - have your system administrator run these commands:$admincmds"
-+ $echo " - have your system administrator run these commands:$admincmds"
- fi
- if test -f /etc/ld.so.conf; then
-- echo " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'"
-+ $echo " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'"
- fi
-- echo
-- echo "See any operating system documentation about shared libraries for"
-- echo "more information, such as the ld(1) and ld.so(8) manual pages."
-- echo "----------------------------------------------------------------------"
-- exit 0
-+ $echo
-+ $echo "See any operating system documentation about shared libraries for"
-+ $echo "more information, such as the ld(1) and ld.so(8) manual pages."
-+ $echo "X----------------------------------------------------------------------" | $Xsed
-+ exit $EXIT_SUCCESS
- ;;
-
- # libtool execute mode
-@@ -4570,7 +6307,7 @@
- if test -z "$cmd"; then
- $echo "$modename: you must specify a COMMAND" 1>&2
- $echo "$help"
-- exit 1
-+ exit $EXIT_FAILURE
- fi
-
- # Handle -dlopen flags immediately.
-@@ -4578,18 +6315,18 @@
- if test ! -f "$file"; then
- $echo "$modename: \`$file' is not a file" 1>&2
- $echo "$help" 1>&2
-- exit 1
-+ exit $EXIT_FAILURE
- fi
-
- dir=
- case $file in
- *.la)
- # Check to see that this really is a libtool archive.
-- if (${SED} -e '2q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then :
-+ if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then :
- else
- $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2
- $echo "$help" 1>&2
-- exit 1
-+ exit $EXIT_FAILURE
- fi
-
- # Read the libtool library.
-@@ -4616,7 +6353,7 @@
- dir="$dir/$objdir"
- else
- $echo "$modename: cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" 1>&2
-- exit 1
-+ exit $EXIT_FAILURE
- fi
- ;;
-
-@@ -4656,7 +6393,7 @@
- -*) ;;
- *)
- # Do a test to see if this is really a libtool program.
-- if (${SED} -e '4q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
-+ if (${SED} -e '4q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
- # If there is no directory component, then add one.
- case $file in
- */* | *\\*) . $file ;;
-@@ -4679,7 +6416,7 @@
- eval "export $shlibpath_var"
- fi
-
-- # Restore saved enviroment variables
-+ # Restore saved environment variables
- if test "${save_LC_ALL+set}" = set; then
- LC_ALL="$save_LC_ALL"; export LC_ALL
- fi
-@@ -4696,7 +6433,7 @@
- $echo "export $shlibpath_var"
- fi
- $echo "$cmd$args"
-- exit 0
-+ exit $EXIT_SUCCESS
- fi
- ;;
-
-@@ -4724,24 +6461,25 @@
- if test -z "$rm"; then
- $echo "$modename: you must specify an RM program" 1>&2
- $echo "$help" 1>&2
-- exit 1
-+ exit $EXIT_FAILURE
- fi
-
- rmdirs=
-
-+ origobjdir="$objdir"
- for file in $files; do
- dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`
- if test "X$dir" = "X$file"; then
- dir=.
-- objdir="$objdir"
-+ objdir="$origobjdir"
- else
-- objdir="$dir/$objdir"
-+ objdir="$dir/$origobjdir"
- fi
- name=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
-- test $mode = uninstall && objdir="$dir"
-+ test "$mode" = uninstall && objdir="$dir"
-
- # Remember objdir for removal later, being careful to avoid duplicates
-- if test $mode = clean; then
-+ if test "$mode" = clean; then
- case " $rmdirs " in
- *" $objdir "*) ;;
- *) rmdirs="$rmdirs $objdir" ;;
-@@ -4765,7 +6503,7 @@
- case $name in
- *.la)
- # Possibly a libtool archive, so verify it.
-- if (${SED} -e '2q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
-+ if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
- . $dir/$name
-
- # Delete the libtool libraries and symlinks.
-@@ -4773,18 +6511,27 @@
- rmfiles="$rmfiles $objdir/$n"
- done
- test -n "$old_library" && rmfiles="$rmfiles $objdir/$old_library"
-- test $mode = clean && rmfiles="$rmfiles $objdir/$name $objdir/${name}i"
-
-- if test $mode = uninstall; then
-+ case "$mode" in
-+ clean)
-+ case " $library_names " in
-+ # " " in the beginning catches empty $dlname
-+ *" $dlname "*) ;;
-+ *) rmfiles="$rmfiles $objdir/$dlname" ;;
-+ esac
-+ test -n "$libdir" && rmfiles="$rmfiles $objdir/$name $objdir/${name}i"
-+ ;;
-+ uninstall)
- if test -n "$library_names"; then
- # Do each command in the postuninstall commands.
-- eval cmds=\"$postuninstall_cmds\"
-+ cmds=$postuninstall_cmds
- save_ifs="$IFS"; IFS='~'
- for cmd in $cmds; do
- IFS="$save_ifs"
-+ eval cmd=\"$cmd\"
- $show "$cmd"
- $run eval "$cmd"
-- if test $? != 0 && test "$rmforce" != yes; then
-+ if test "$?" -ne 0 && test "$rmforce" != yes; then
- exit_status=1
- fi
- done
-@@ -4793,40 +6540,72 @@
-
- if test -n "$old_library"; then
- # Do each command in the old_postuninstall commands.
-- eval cmds=\"$old_postuninstall_cmds\"
-+ cmds=$old_postuninstall_cmds
- save_ifs="$IFS"; IFS='~'
- for cmd in $cmds; do
- IFS="$save_ifs"
-+ eval cmd=\"$cmd\"
- $show "$cmd"
- $run eval "$cmd"
-- if test $? != 0 && test "$rmforce" != yes; then
-+ if test "$?" -ne 0 && test "$rmforce" != yes; then
- exit_status=1
- fi
- done
- IFS="$save_ifs"
- fi
- # FIXME: should reinstall the best remaining shared library.
-- fi
-+ ;;
-+ esac
- fi
- ;;
-
- *.lo)
-- if test "$build_old_libs" = yes; then
-- oldobj=`$echo "X$name" | $Xsed -e "$lo2o"`
-- rmfiles="$rmfiles $dir/$oldobj"
-+ # Possibly a libtool object, so verify it.
-+ if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
-+
-+ # Read the .lo file
-+ . $dir/$name
-+
-+ # Add PIC object to the list of files to remove.
-+ if test -n "$pic_object" \
-+ && test "$pic_object" != none; then
-+ rmfiles="$rmfiles $dir/$pic_object"
-+ fi
-+
-+ # Add non-PIC object to the list of files to remove.
-+ if test -n "$non_pic_object" \
-+ && test "$non_pic_object" != none; then
-+ rmfiles="$rmfiles $dir/$non_pic_object"
-+ fi
- fi
- ;;
-
- *)
-- # Do a test to see if this is a libtool program.
-- if test $mode = clean &&
-- (${SED} -e '4q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
-- relink_command=
-- . $dir/$file
-+ if test "$mode" = clean ; then
-+ noexename=$name
-+ case $file in
-+ *.exe)
-+ file=`$echo $file|${SED} 's,.exe$,,'`
-+ noexename=`$echo $name|${SED} 's,.exe$,,'`
-+ # $file with .exe has already been added to rmfiles,
-+ # add $file without .exe
-+ rmfiles="$rmfiles $file"
-+ ;;
-+ esac
-+ # Do a test to see if this is a libtool program.
-+ if (${SED} -e '4q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
-+ relink_command=
-+ . $dir/$noexename
-
-- rmfiles="$rmfiles $objdir/$name $objdir/${name}S.${objext}"
-- if test "$fast_install" = yes && test -n "$relink_command"; then
-- rmfiles="$rmfiles $objdir/lt-$name"
-+ # note $name still contains .exe if it was in $file originally
-+ # as does the version of $file that was added into $rmfiles
-+ rmfiles="$rmfiles $objdir/$name $objdir/${name}S.${objext}"
-+ if test "$fast_install" = yes && test -n "$relink_command"; then
-+ rmfiles="$rmfiles $objdir/lt-$name"
-+ fi
-+ if test "X$noexename" != "X$name" ; then
-+ rmfiles="$rmfiles $objdir/lt-${noexename}.c"
-+ fi
- fi
- fi
- ;;
-@@ -4834,6 +6613,7 @@
- $show "$rm $rmfiles"
- $run $rm $rmfiles || exit_status=1
- done
-+ objdir="$origobjdir"
-
- # Try to remove the ${objdir}s in the directories where we deleted files
- for dir in $rmdirs; do
-@@ -4849,20 +6629,20 @@
- "")
- $echo "$modename: you must specify a MODE" 1>&2
- $echo "$generic_help" 1>&2
-- exit 1
-+ exit $EXIT_FAILURE
- ;;
- esac
-
- if test -z "$exec_cmd"; then
- $echo "$modename: invalid operation mode \`$mode'" 1>&2
- $echo "$generic_help" 1>&2
-- exit 1
-+ exit $EXIT_FAILURE
- fi
- fi # test -z "$show_help"
-
- if test -n "$exec_cmd"; then
- eval exec $exec_cmd
-- exit 1
-+ exit $EXIT_FAILURE
- fi
-
- # We need to display help for each of the modes.
-@@ -4881,6 +6661,7 @@
- --mode=MODE use operation mode MODE [default=inferred from MODE-ARGS]
- --quiet same as \`--silent'
- --silent don't print informational messages
-+ --tag=TAG use configuration variables from tag TAG
- --version print version information
-
- MODE must be one of the following:
-@@ -4894,8 +6675,10 @@
- uninstall remove libraries from an installed directory
-
- MODE-ARGS vary depending on the MODE. Try \`$modename --help --mode=MODE' for
--a more detailed description of MODE."
-- exit 0
-+a more detailed description of MODE.
-+
-+Report bugs to <bug-libtool at gnu.org>."
-+ exit $EXIT_SUCCESS
- ;;
-
- clean)
-@@ -5006,6 +6789,9 @@
- -no-install link a not-installable executable
- -no-undefined declare that a library does not refer to external symbols
- -o OUTPUT-FILE create OUTPUT-FILE from the specified objects
-+ -objectlist FILE Use a list of object files found in FILE to specify objects
-+ -precious-files-regex REGEX
-+ don't remove output files matching REGEX
- -release RELEASE specify package release information
- -rpath LIBDIR the created library will eventually be installed in LIBDIR
- -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries
-@@ -5047,14 +6833,33 @@
- *)
- $echo "$modename: invalid operation mode \`$mode'" 1>&2
- $echo "$help" 1>&2
-- exit 1
-+ exit $EXIT_FAILURE
- ;;
- esac
-
--echo
-+$echo
- $echo "Try \`$modename --help' for more information about other modes."
-
--exit 0
-+exit $?
-+
-+# The TAGs below are defined such that we never get into a situation
-+# in which we disable both kinds of libraries. Given conflicting
-+# choices, we go for a static library, that is the most portable,
-+# since we can't tell whether shared libraries were disabled because
-+# the user asked for that or because the platform doesn't support
-+# them. This is particularly important on AIX, because we don't
-+# support having both static and shared libraries enabled at the same
-+# time on that platform, so we default to a shared-only configuration.
-+# If a disable-shared tag is given, we'll fallback to a static-only
-+# configuration. But we'll never go from static-only to shared-only.
-+
-+# ### BEGIN LIBTOOL TAG CONFIG: disable-shared
-+disable_libs=shared
-+# ### END LIBTOOL TAG CONFIG: disable-shared
-+
-+# ### BEGIN LIBTOOL TAG CONFIG: disable-static
-+disable_libs=static
-+# ### END LIBTOOL TAG CONFIG: disable-static
-
- # Local Variables:
- # mode:shell-script
diff --git a/debian/patches/octave-sundialstb.patch b/debian/patches/octave-sundialstb.patch
deleted file mode 100644
index 6177f4c..0000000
--- a/debian/patches/octave-sundialstb.patch
+++ /dev/null
@@ -1,193 +0,0 @@
-Index: sundials-2.5.0/sundialsTB/install_STB.m
-===================================================================
---- sundials-2.5.0.orig/sundialsTB/install_STB.m 2012-03-21 23:47:00.000000000 +0100
-+++ sundials-2.5.0/sundialsTB/install_STB.m 2012-06-07 10:47:47.000000000 +0200
-@@ -9,7 +9,7 @@
- % MEX compiler command
- % --------------------
-
--mexcompiler = 'mex -v';
-+mexcompiler = 'mkoctfile --mex -v';
-
- % Location of sundialsTB and top of sundials source tree
- % ------------------------------------------------------
-@@ -46,48 +46,18 @@
- % Figure out what modules exist and which ones will be built
- % ----------------------------------------------------------
-
--fprintf('\n\nSelect modules to be built\n');
-+fprintf('\n\nBuild Modules for CVODES, IDAS, KINSOL\n');
-
--q = fullfile(sun,'src','cvodes');
--if exist(q, 'dir')
-- answ = input(' Compile CVODES interface? (y/n) ','s');
-- if answ == 'y'
-- cvm_ok = true;
-- else
-- cvm_ok = false;
-- end
--end
--
--if exist(q, 'dir')
-- answ = input(' Compile IDAS interface? (y/n) ','s');
-- if answ == 'y'
-- idm_ok = true;
-- else
-- idm_ok = false;
-- end
--end
--
--q = fullfile(sun,'src','kinsol');
--if exist(q, 'dir')
-- answ = input(' Compile KINSOL interface? (y/n) ','s');
-- if answ == 'y'
-- kim_ok = true;
-- else
-- kim_ok = false;
-- end
--end
--
--if ~cvm_ok && ~idm_ok && ~kim_ok
-- fprintf('\nOK. All done.\n');
-- return
--end
-+cvm_ok = true;
-+idm_ok = true;
-+kim_ok = true;
-
- % Create sundials_config.h
- % ------------------------
-
- mkdir('sundials');
- fi = fopen(fullfile('sundials','sundials_config.h'),'w');
--fprintf(fi,'#define SUNDIALS_PACKAGE_VERSION "2.4.0"\n');
-+fprintf(fi,'#define SUNDIALS_PACKAGE_VERSION "2.5.0"\n');
- fprintf(fi,'#define SUNDIALS_DOUBLE_PRECISION 1\n');
- fprintf(fi,'#define SUNDIALS_USE_GENERIC_MATH 1\n');
- fprintf(fi,'#define SUNDIALS_EXPORT\n');
-@@ -117,17 +87,15 @@
- % ------------------
-
- fprintf('\n\nMEX files were successfully created.\n');
--answ = input(' Install toolbox? (y/n) ','s');
--if answ ~= 'y'
-- fprintf('\n\nOK. All done.\n');
-- return
--end
-+fprintf('\n\nInstall toolbox.\n');
-+answ = 'y'
-
- while true
- fprintf('\n\nSpecify the location where you wish to install the toolbox.\n');
- fprintf('The toolbox will be installed in a subdirectory "sundialsTB".\n');
- fprintf('Enter return to cancel the installation.\n');
-- where = input(' Installation directory: ','s');
-+ %where = input(' Installation directory: ','s');
-+ where = './octave';
- if isempty(where)
- go = 0;
- break;
-@@ -149,7 +117,8 @@
- go = 1;
- if exist(stbi,'dir')
- fprintf('\n\nDirectory %s exists!\n',stbi);
-- answ = input(' Replace? (y/n) ','s');
-+ %answ = input(' Replace? (y/n) ','s');
-+ answ = 'y';
- if answ == 'y'
- rmdir(stbi,'s');
- go = 1;
-@@ -210,11 +179,14 @@
- fprintf('add a call to %s\n',fullfile(stbi,'startup_STB.m'));
- fprintf('\nEnjoy!\n\n');
-
-+exit
-+endfunction
-+
- %---------------------------------------------------------------------------------
- % Check if mex works and if the user accepts the current mexopts
- %---------------------------------------------------------------------------------
-
--function mex_ok = check_mex(mexcompiler)
-+function mex_ok = check_mex (mexcompiler)
-
- % Create a dummy file
- fid = fopen('foo.c', 'w');
-@@ -232,7 +204,8 @@
- delete(sprintf('foo.%s', mexext))
-
- fprintf('\n\nMEX files will be compiled and built using the above options\n');
--answ = input(' Proceed? (y/n) ','s');
-+%answ = input(' Proceed? (y/n) ','s');
-+answ = 'y';
- if answ == 'y'
- mex_ok = true;
- else
-@@ -240,7 +213,7 @@
- mex_ok = false;
- end
-
--return
-+endfunction
-
- %---------------------------------------------------------------------------------
- % compilation of cvm MEX file
-@@ -352,6 +325,8 @@
-
- cd(stb)
-
-+endfunction
-+
- %---------------------------------------------------------------------------------
- % compilation of idm MEX file
- %---------------------------------------------------------------------------------
-@@ -461,6 +436,7 @@
-
- cd(stb)
-
-+endfunction
-
- %---------------------------------------------------------------------------------
- % compilation of KINSOL MEX file
-@@ -569,6 +545,8 @@
-
- cd(stb)
-
-+endfunction
-+
- %---------------------------------------------------------------------------------
- % Installation of common sundialsTB files
- %---------------------------------------------------------------------------------
-@@ -633,6 +611,7 @@
- break;
- end
- end
-+endfunction
-
- %---------------------------------------------------------------------------------
- % Installation of CVODES files
-@@ -795,6 +774,8 @@
- disp(msg);
- end
-
-+endfunction
-+
- %---------------------------------------------------------------------------------
- % Installation of IDAS files
- %---------------------------------------------------------------------------------
-@@ -949,7 +930,7 @@
- disp(msg);
- end
-
--
-+endfunction
-
- %---------------------------------------------------------------------------------
- % Installation of KINSOL files
-@@ -1023,3 +1004,6 @@
- end
-
-
-+endfunction
-+
-+install_STB;
diff --git a/debian/patches/series b/debian/patches/series
deleted file mode 100644
index ae92893..0000000
--- a/debian/patches/series
+++ /dev/null
@@ -1,7 +0,0 @@
-cmake.patch
-makefile.patch
-#sh4.patch
-fix-format-error.patch
-octave-sundialstb.patch
-sundials-config.patch
-link-blas-lapack.patch
diff --git a/debian/patches/sh4.patch b/debian/patches/sh4.patch
deleted file mode 100644
index d1ac1a5..0000000
--- a/debian/patches/sh4.patch
+++ /dev/null
@@ -1,13 +0,0 @@
-Index: sundials-2.4.0/configure
-===================================================================
---- sundials-2.4.0.orig/configure 2010-11-03 08:42:51.000000000 +0100
-+++ sundials-2.4.0/configure 2010-11-03 08:43:14.000000000 +0100
-@@ -8295,7 +8295,7 @@
-
- ;;
- # Ignore these flags.
-- -lang* | -lcrt*.o | -lc | -lgcc* | -lSystem | -libmil | -LANG:=* | -LIST:* | -LNO:*)
-+ -lang* | -lcrt*.o | -lc | -lgcc* | -lSystem | -libmil | -little | -LANG:=* | -LIST:* | -LNO:*)
- ;;
- -lkernel32)
- test x"$CYGWIN" != xyes && ac_cv_f77_libs="$ac_cv_f77_libs $ac_arg"
diff --git a/debian/patches/sundials-config.patch b/debian/patches/sundials-config.patch
deleted file mode 100644
index 7bfcd91..0000000
--- a/debian/patches/sundials-config.patch
+++ /dev/null
@@ -1,34 +0,0 @@
-Index: sundials-2.5.0/bin/sundials-config.in
-===================================================================
---- sundials-2.5.0.orig/bin/sundials-config.in 2012-04-12 02:31:04.000000000 +0200
-+++ sundials-2.5.0/bin/sundials-config.in 2012-07-16 17:18:30.000000000 +0200
-@@ -1,4 +1,4 @@
--#! @SHELL@
-+#! /bin/bash
- # -----------------------------------------------------------------------------------
-
- NAME_="sundials-config"
-@@ -65,7 +65,7 @@
- abs_includedir=`cd "${includedir}" > /dev/null 2>&1 && pwd`;
- abs_libdir=`cd "${libdir}" > /dev/null 2>&1 && pwd`;
-
--if test $abs_includedir != /usr/include ; then
-+if test "$abs_includedir" != "/usr/include" ; then
- includes=-I$abs_includedir
- fi
-
-Index: sundials-2.5.0/CMakeLists.txt
-===================================================================
---- sundials-2.5.0.orig/CMakeLists.txt 2012-07-16 16:21:00.000000000 +0200
-+++ sundials-2.5.0/CMakeLists.txt 2012-07-16 17:12:04.000000000 +0200
-@@ -516,6 +516,10 @@
- ${PROJECT_SOURCE_DIR}/include/sundials/sundials_config.in
- ${PROJECT_BINARY_DIR}/include/sundials/sundials_config.h
- )
-+CONFIGURE_FILE(
-+ ${PROJECT_SOURCE_DIR}/bin/sundials-config.in
-+ ${PROJECT_SOURCE_DIR}/bin/sundials-config
-+ )
-
- # Add the include directory in the source tree and the one in
- # the binary tree (for the header file sundials_config.h)
diff --git a/debian/rules b/debian/rules
deleted file mode 100755
index 6dab794..0000000
--- a/debian/rules
+++ /dev/null
@@ -1,114 +0,0 @@
-#!/usr/bin/make -f
-# -*- makefile -*-
-
-#include /usr/share/hardening-includes/hardening.make
-#
-CPPFLAGS:=$(shell dpkg-buildflags --get CPPFLAGS)
-CFLAGS:=$(shell dpkg-buildflags --get CFLAGS) $(CPPFLAGS)
-CXXFLAGS:=$(shell dpkg-buildflags --get CXXFLAGS) $(CPPFLAGS)
-LDFLAGS:=$(shell dpkg-buildflags --get LDFLAGS)
-
-
-#workaround to start MPI-applications in chroot
-export OMPI_MCA_plm_rsh_agent=/bin/false
-
-extra_flags += \
- -DCMAKE_Fortran_COMPILER=gfortran \
- -DBUILD_SHARED_LIBS:BOOL=ON \
- -DFCMIX_ENABLE:BOOL=ON \
- -DMPI_ENABLE:BOOL=ON \
- -DLAPACK_ENABLE:BOOL=ON \
- -DEXAMPLES_ENABLE:BOOL=ON \
- -DEXAMPLES_INSTALL:BOOL=OFF
-
-BUILDDIR = $(CURDIR)/debian/build
-
-# Get the appropriate paths for the installation of the Octave files
-mpath = $(shell octave-config -p LOCALFCNFILEDIR)
-bpath = $(shell octave-config -p LOCALOCTFILEDIR)
-
-
-%:
- dh $@ --buildsystem=cmake --builddirectory=$(BUILDDIR) --parallel
-
-override_dh_auto_configure:
- dh_auto_configure -- $(extra_flags)
-
-override_dh_auto_test:
- dh_auto_test
- echo "Running test..."
- $(SHELL) debian/check.sh $(BUILDDIR) $(CURDIR)
-
-override_dh_auto_build:
- dh_auto_build
-
-#
-#build/octave-sundials::
- mkdir -p sundialsTB/octave
- cd sundialsTB && octave -fV install_STB.m
-
-override_dh_auto_install:
- dh_auto_install
-#
-#install/octave-sundials::
- mkdir -p debian/tmp/$(bpath)/sundialsTB/cvodes/cvm/
- mv sundialsTB/octave/sundialsTB/cvodes/cvm/cvm.mex debian/tmp/$(bpath)/sundialsTB/cvodes/cvm
- mkdir -p debian/tmp/$(bpath)/sundialsTB/idas/idm/
- mv sundialsTB/octave/sundialsTB/idas/idm/idm.mex debian/tmp/$(bpath)/sundialsTB/idas/idm
- mkdir -p debian/tmp/$(bpath)/sundialsTB/kinsol/kim
- mv sundialsTB/octave/sundialsTB/kinsol/kim/kim.mex debian/tmp/$(bpath)/sundialsTB/kinsol/kim
-
- mkdir -p debian/tmp/$(mpath)
- mv sundialsTB/octave/* debian/tmp/$(mpath)
- rm debian/tmp/$(mpath)/sundialsTB/LICENSE
-
- dh_install -a -Nlibsundials-doc
- dh_install -plibsundials-doc -X.txt -X.out -X.in -XREADME
-
-#
-#to generate symbols
-# dpkg-gensymbols -plibsundials-parallel -O
-
-override_dh_strip:
- find debian/tmp/$(bpath) -name \*.mex | xargs -r strip
-
- dh_strip -plibsundials-cvode1 --dbg-package=libsundials-serial-dbg
- dh_strip -plibsundials-cvodes2 --dbg-package=libsundials-serial-dbg
- dh_strip -plibsundials-ida2 --dbg-package=libsundials-serial-dbg
- dh_strip -plibsundials-idas0 --dbg-package=libsundials-serial-dbg
- dh_strip -plibsundials-kinsol1 --dbg-package=libsundials-serial-dbg
- dh_strip -plibsundials-nvecserial0 --dbg-package=libsundials-serial-dbg
-
- dh_strip -plibsundials-nvecparallel0 --dbg-package=libsundials-nvecparallel-dbg
- dh_strip -a
-
- ls -l debian/tmp/usr/lib
-
-override_dh_auto_clean:
- find examples \
- -type f -a \( -name \*.o \) \
- -a -exec rm -f \{\} \;
- find sundialsTB \
- -type f -a \( -name \*.o -o -name \*.mex \) \
- -a -exec rm -f \{\} \;
- rm -rf sundialsTB/octave
- rm -rf bin/makefile-update.sh
- dh_auto_clean
-
-# Grab the version before +dfsg
-DEB_UPSTREAM_VERSION=$(shell dpkg-parsechangelog | sed -rne 's,^Version: ([^+]+).*,\1,p')
-DEB_STRIPPED_UPSTREAM_VERSION = $(shell echo $(DEB_UPSTREAM_VERSION) | sed 's/-[^-]*$$//')
-
-USCAN_DESTDIR := $(CURDIR)/../tarballs
-
-
-get-orig-source:
- mkdir -p $(USCAN_DESTDIR)
- uscan --force-download --no-symlink --verbose --destdir $(USCAN_DESTDIR)
- tar -C $(USCAN_DESTDIR) -xzf $(USCAN_DESTDIR)/sundials_$(DEB_STRIPPED_UPSTREAM_VERSION).orig.tar.gz
- rm -f $(USCAN_DESTDIR)/sundials*.tar.gz
- find $(USCAN_DESTDIR)/sundials-$(DEB_STRIPPED_UPSTREAM_VERSION) -name \*.pdf | xargs rm
- cd $(USCAN_DESTDIR) && GZIP=-9 tar -czf \
- $(CURDIR)/sundials_$(DEB_UPSTREAM_VERSION).orig.tar.gz \
- sundials-$(DEB_STRIPPED_UPSTREAM_VERSION)
- rm -rf $(USCAN_DESTDIR)/sundials-$(DEB_STRIPPED_UPSTREAM_VERSION)
diff --git a/debian/source.lintian-overrides b/debian/source.lintian-overrides
deleted file mode 100644
index 5d43fb6..0000000
--- a/debian/source.lintian-overrides
+++ /dev/null
@@ -1,5 +0,0 @@
-sundials source: ancient-libtool config/ltmain.sh 1.4.3
-# We are using cmake
-sundials source: outdated-autotools-helper-file config/config.sub 2005-12-11
-sundials source: outdated-autotools-helper-file config/config.guess 2005-12-13
-
diff --git a/debian/source/format b/debian/source/format
deleted file mode 100644
index 163aaf8..0000000
--- a/debian/source/format
+++ /dev/null
@@ -1 +0,0 @@
-3.0 (quilt)
diff --git a/debian/sundials-config.1 b/debian/sundials-config.1
deleted file mode 100644
index 93913f0..0000000
--- a/debian/sundials-config.1
+++ /dev/null
@@ -1,57 +0,0 @@
-.TH "sundials\-config" 1 "2006-07-25" "" "SUNDIALS"
-.SH NAME
-sundials-config \- returns required flags for linking to SUNDIALS libraries
-.SH SYNOPSIS
-.HP
-.B sundials\-config
-.BI "\-m {" cvode | cvodes | ida | kinsol }
-.BI "\-t {" s | p }
-.BI "\-l {" c | f }
-.BI "[-s {" libs | cppflags }]
-.B [\-hv]
-.SH DESCRIPTION
-.B sundials\-config
-provides a way to obtain various configuration options for compiling programs
-that use SUNDIALS
-.SH OPTIONS
-.TP
-.BI "\-m {" cvode | cvodes | ida | kinsol }
-Select the SUNDIALS module
-.TP
-.BI "\-t {" s | p }
-Use serial of parallel vectors
-.TP
-.BI "\-l {" c | f }
-Use C or Fortran
-.TP
-.BI "-s {" libs | cppflags }
-Show linking flags or C preprocessor flags
-(show both of no option is given)
-.TP
-.B \-h
-Get usage and options information
-.TP
-.B \-v
-View the script
-.SH NOTES
-.TP
-.B \-lf
-is not valid for
-.B \-m cvodes
-.TP
-.B \-s cppflags
-returns an empty string for
-.B \-l f
-.SH AUTHOR
-\fBRadu Serban\fR <\&radu at llnl.gov\&>
-.P
-This manual page was written by Andrey Romanenko for
-the Debian system (but may be used by others). Permission
-is granted to copy, distribute and/or modify this document under
-the terms of the &gnu; General Public License, Version 2 any
-later version published by the Free Software Foundation.
-.P
-On Debian systems, the complete text of the GNU General Public
-License can be found in \fI/usr/share/common-licenses/GPL\fR.
-.SH "SEE ALSO"
-SUNDIALS Documentation
diff --git a/debian/watch b/debian/watch
deleted file mode 100644
index ad74a64..0000000
--- a/debian/watch
+++ /dev/null
@@ -1,4 +0,0 @@
-version=3
-opts="filenamemangle=s/.*//,dversionmangle=s/\.dfsg$//" \
- http://computation.llnl.gov/casc/sundials/download/download.html \
- .*'sundials-([\d.]+)'.* debian /bin/sh debian/orig-tarball.sh
diff --git a/examples/cvode/fcmix_parallel/CMakeLists.txt b/examples/cvode/fcmix_parallel/CMakeLists.txt
new file mode 100644
index 0000000..9a28aae
--- /dev/null
+++ b/examples/cvode/fcmix_parallel/CMakeLists.txt
@@ -0,0 +1,120 @@
+# ---------------------------------------------------------------
+# $Revision: 1.5 $
+# $Date: 2009/02/17 02:58:47 $
+# ---------------------------------------------------------------
+# Programmer: Radu Serban @ LLNL
+# ---------------------------------------------------------------
+# Copyright (c) 2007, The Regents of the University of California.
+# Produced at the Lawrence Livermore National Laboratory.
+# All rights reserved.
+# For details, see the LICENSE file.
+# ---------------------------------------------------------------
+# CMakeLists.txt file for the FCVODE parallel examples
+
+
+# Add variable FCVODE_examples with the names of the parallel CVODE examples
+
+SET(FCVODE_examples
+ fcvDiag_non_p
+ fcvDiag_kry_bbd_p
+ fcvDiag_kry_p
+ )
+
+# 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 )
+ # use MPI_MPIF77 as the compiler
+ SET(CMAKE_Fortran_COMPILER ${MPI_MPIF77})
+ELSE(MPI_MPIF77)
+ # add MPI_INCLUDE_PATH to include directories
+ INCLUDE_DIRECTORIES(${MPI_INCLUDE_PATH})
+ENDIF(MPI_MPIF77)
+
+# 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")
+ SET(CVODE_LIB sundials_cvode_shared)
+ SET(NVECP_LIB sundials_nvecparallel_shared)
+ SET(FNVECP_LIB sundials_fnvecparallel_shared)
+ENDIF(LINK_LIBRARY_TYPE MATCHES "static")
+
+# 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)
+ SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${LAPACK_LINKER_FLAGS}")
+ SET(SUNDIALS_LIBS "${SUNDIALS_LIBS} ${LAPACK_LIBRARIES}")
+ENDIF(LAPACK_FOUND)
+
+# Add the build and install targets for each CVODE example
+
+FOREACH(example ${FCVODE_examples})
+ ADD_EXECUTABLE(${example} ${example}.f)
+ TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+ IF(NOT MPI_MPIF77)
+ TARGET_LINK_LIBRARIES(${example} ${MPI_LIBRARY} ${MPI_EXTRA_LIBRARIES})
+ ENDIF(NOT MPI_MPIF77)
+ IF(EXAMPLES_INSTALL)
+ INSTALL(FILES ${example}.f ${example}.out DESTINATION ${EXAMPLES_INSTALL_PATH}/cvode/fcmix_parallel)
+ ENDIF(EXAMPLES_INSTALL)
+ENDFOREACH(example ${FCVODE_examples})
+
+IF(EXAMPLES_INSTALL)
+
+ # Install the README file
+ INSTALL(FILES README DESTINATION ${EXAMPLES_INSTALL_PATH}/cvode/fcmix_parallel)
+
+ # Prepare substitution variables for Makefile and/or CMakeLists templates
+ SET(SOLVER "CVODE")
+ SET(SOLVER_LIB "sundials_cvode")
+ SET(SOLVER_FLIB "sundials_fcvode")
+ LIST2STRING(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
+ )
+
+ # install CMakelists.txt
+ INSTALL(
+ FILES ${PROJECT_BINARY_DIR}/examples/cvode/fcmix_parallel/CMakeLists.txt
+ 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
+ # 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_F77_ex.in
+ ${PROJECT_BINARY_DIR}/examples/cvode/fcmix_parallel/Makefile_ex
+ @ONLY
+ )
+ # 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
+ RENAME Makefile
+ )
+ ENDIF(UNIX)
+
+ENDIF(EXAMPLES_INSTALL)
diff --git a/examples/cvode/fcmix_parallel/Makefile.in b/examples/cvode/fcmix_parallel/Makefile.in
new file mode 100644
index 0000000..835777b
--- /dev/null
+++ b/examples/cvode/fcmix_parallel/Makefile.in
@@ -0,0 +1,116 @@
+# -----------------------------------------------------------------
+# $Revision: 1.11 $
+# $Date: 2009/03/11 23:20:14 $
+# -----------------------------------------------------------------
+# Programmer(s): Radu Serban and Aaron Collier @ LLNL
+# -----------------------------------------------------------------
+# Copyright (c) 2002, The Regents of the University of California.
+# Produced at the Lawrence Livermore National Laboratory.
+# All rights reserved.
+# For details, see the LICENSE file.
+# -----------------------------------------------------------------
+# Makefile for FCVODE parallel examples
+#
+# @configure_input@
+# -----------------------------------------------------------------
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_builddir = @top_builddir@
+builddir = @builddir@
+abs_builddir = @abs_builddir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+includedir = @includedir@
+libdir = @libdir@
+
+INSTALL = @INSTALL@
+INSTALL_PROG = @INSTALL_PROGRAM@
+INSTALL_FILE = @INSTALL_DATA@
+
+LIBTOOL = @LIBTOOL@
+LIBTOOL_DEPS = @LIBTOOL_DEPS@
+
+FFLAGS = @FFLAGS@
+F77_LDFLAGS = @F77_LDFLAGS@
+F77_LIBS = @F77_LIBS@
+
+MPIF77 = @MPIF77@
+MPI_INC_DIR = @MPI_INC_DIR@
+MPI_FLAGS = @MPI_FLAGS@
+MPIF77_LNKR = @MPIF77_LNKR@
+MPI_LIB_DIR = @MPI_LIB_DIR@
+MPI_LIBS = @MPI_LIBS@
+
+BLAS_LAPACK_LIBS = @BLAS_LAPACK_LIBS@
+
+OBJ_EXT = @OBJEXT@
+EXE_EXT = @EXEEXT@
+
+EXS_INSTDIR = @EXS_INSTDIR@
+
+top_srcdir = $(srcdir)/../../..
+
+SUNDIALS_LIBS = $(top_builddir)/src/cvode/fcmix/libsundials_fcvode.la \
+ $(top_builddir)/src/cvode/libsundials_cvode.la \
+ $(top_builddir)/src/nvec_par/libsundials_fnvecparallel.la \
+ $(top_builddir)/src/nvec_par/libsundials_nvecparallel.la
+
+fortran-update = ${SHELL} ${top_builddir}/bin/fortran-update.sh
+
+mkinstalldirs = $(SHELL) $(top_srcdir)/config/mkinstalldirs
+rminstalldirs = $(SHELL) $(top_srcdir)/config/rminstalldirs
+
+EXAMPLES = fcvDiag_non_p \
+ fcvDiag_kry_bbd_p \
+ fcvDiag_kry_p
+
+OBJECTS = ${EXAMPLES:=${OBJ_EXT}}
+EXECS = ${EXAMPLES:=${EXE_EXT}}
+
+# ----------------------------------------------------------------------------------------------------------------------
+
+all:
+ @for i in ${EXAMPLES} ; do \
+ ${fortran-update} ${srcdir} $${i}.f ; \
+ ${LIBTOOL} --mode=compile ${MPIF77} ${MPI_FLAGS} -I${MPI_INC_DIR} ${FFLAGS} -c ${builddir}/$${i}-updated.f ; \
+ ${LIBTOOL} --mode=link ${MPIF77_LNKR} -o ${builddir}/$${i}${EXE_EXT} ${builddir}/$${i}-updated${OBJ_EXT} ${MPI_FLAGS} ${F77_LDFLAGS} ${SUNDIALS_LIBS} -L${MPI_LIB_DIR} ${MPI_LIBS} ${F77_LIBS} $(BLAS_LAPACK_LIBS) ; \
+ done
+
+install:
+ $(mkinstalldirs) $(EXS_INSTDIR)/cvode/fcmix_parallel
+ $(INSTALL_FILE) Makefile_ex $(EXS_INSTDIR)/cvode/fcmix_parallel/Makefile
+ $(INSTALL_FILE) $(top_srcdir)/examples/cvode/fcmix_parallel/README $(EXS_INSTDIR)/cvode/fcmix_parallel/
+ for i in ${EXAMPLES} ; do \
+ $(INSTALL_FILE) $(top_srcdir)/examples/cvode/fcmix_parallel/$${i}.f $(EXS_INSTDIR)/cvode/fcmix_parallel/ ; \
+ $(INSTALL_FILE) $(top_srcdir)/examples/cvode/fcmix_parallel/$${i}.out $(EXS_INSTDIR)/cvode/fcmix_parallel/ ; \
+ done
+
+uninstall:
+ rm -f $(EXS_INSTDIR)/cvode/fcmix_parallel/Makefile
+ rm -f $(EXS_INSTDIR)/cvode/fcmix_parallel/README
+ for i in ${EXAMPLES} ; do \
+ rm -f $(EXS_INSTDIR)/cvode/fcmix_parallel/$${i}.f ; \
+ rm -f $(EXS_INSTDIR)/cvode/fcmix_parallel/$${i}.out ; \
+ done
+ $(rminstalldirs) $(EXS_INSTDIR)/cvode/fcmix_parallel
+ $(rminstalldirs) $(EXS_INSTDIR)/cvode
+
+clean:
+ rm -rf .libs
+ rm -f *.lo *.o
+ rm -f *-updated.f
+ rm -f ${OBJECTS}
+ rm -f $(EXECS)
+
+distclean: clean
+ rm -f Makefile
+ rm -f Makefile_ex
+
+# ----------------------------------------------------------------------------------------------------------------------
+
+libtool: $(top_builddir)/$(LIBTOOL_DEPS)
+ @cd ${top_builddir} ; \
+ ${SHELL} ./config.status --recheck ; \
+ cd ${abs_builddir}
diff --git a/examples/cvode/fcmix_parallel/README b/examples/cvode/fcmix_parallel/README
new file mode 100644
index 0000000..9fa0772
--- /dev/null
+++ b/examples/cvode/fcmix_parallel/README
@@ -0,0 +1,17 @@
+List of parallel CVODE FCMIX examples
+
+ fcvDiag_non_p : diagonal ODE example - non-stiff case (ADAMS/FUNCTIONAL)
+ fcvDiag_kry_bbd_p : diagonal ODE example - stiff case (BDF/SPGMR/FCVBBD)
+ fcvDiag_kry_p : diagonal ODE example - stiff case (BDF/SPGMR)
+
+Sample results:
+
+ SUNDIALS was built with the following options:
+
+ ./configure CC=gcc F77=gfortran CFLAGS="-g3 -O0" FFLAGS="-g3 -O0" --enable-examples
+
+ System Architecture: IA-32
+ Processor Type: Intel Pentium 4 Xeon DP (i686)
+ Operating System: Red Hat Enterprise Linux WS 3 (Taroon Update 7)
+ C/Fortran Compilers: gcc/gfortran v4.1.0
+ MPI Implementation: Open MPI v1.1
diff --git a/examples/cvode/fcmix_parallel/fcvDiag_kry_bbd_p.f b/examples/cvode/fcmix_parallel/fcvDiag_kry_bbd_p.f
new file mode 100644
index 0000000..3d9f384
--- /dev/null
+++ b/examples/cvode/fcmix_parallel/fcvDiag_kry_bbd_p.f
@@ -0,0 +1,307 @@
+C ----------------------------------------------------------------
+C $Revision: 1.1 $
+C $Date: 2009/03/11 23:18:28 $
+C ----------------------------------------------------------------
+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 Include MPI-Fortran header file for MPI_COMM_WORLD, MPI types.
+
+ IMPLICIT NONE
+C
+ INCLUDE "mpif.h"
+C
+ INTEGER*4 NLOCAL
+ 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*4 IOUT(25), IPAR(2)
+ INTEGER*4 NEQ, I, MUDQ, MLDQ, MU, ML, NETF
+ INTEGER*4 NST, NFE, NPSET, NPE, NPS, NNI, NLI, NCFN, NCFL, NGEBBD
+ INTEGER*4 LENRW, LENIW, LENRWLS, LENIWLS, LENRWBBD, LENIWBBD
+ DOUBLE PRECISION Y(1024), ROUT(10), RPAR(1)
+ DOUBLE PRECISION ALPHA, TOUT, ERMAX, AVDIM
+ DOUBLE PRECISION ATOL, ERRI, RTOL, GERMAX, DTOUT, T
+C
+ DATA ATOL/1.0D-10/, RTOL/1.0D-5/, DTOUT/0.1D0/, NOUT/10/
+ DATA LLENRW/1/, LLENIW/2/, LNST/3/, LNFE/4/, LNETF/5/, LNCF/6/,
+ 1 LNNI/7/, LNSETUP/8/, LLENRWLS/13/, LLENIWLS/14/,
+ 1 LNPE/18/, LNLI/20/, LNPS/19/, LNCFL/21/
+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
+ 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
+ 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
+C
+C Set input arguments.
+ NEQ = NPES * NLOCAL
+ T = 0.0D0
+ METH = 2
+ ITMETH = 2
+ IATOL = 1
+ ITASK = 1
+ IPRE = 1
+ IGS = 1
+C Set parameter alpha
+ ALPHA = 10.0D0
+C
+C Load IPAR and RPAR
+ IPAR(1) = NLOCAL
+ IPAR(2) = MYPE
+ RPAR(1) = ALPHA
+C
+ DO I = 1, NLOCAL
+ Y(I) = 1.0D0
+ ENDDO
+C
+ IF (MYPE .EQ. 0) THEN
+ WRITE(6,15) NEQ, ALPHA, RTOL, ATOL, NPES
+ 15 FORMAT('Diagonal test problem:'//' NEQ = ', I3, /
+ & ' parameter alpha = ', F8.3/
+ & ' ydot_i = -alpha*i * y_i (i = 1,...,NEQ)'/
+ & ' RTOL, ATOL = ', 2E10.1/
+ & ' Method is BDF/NEWTON/SPGMR'/
+ & ' Preconditioner is band-block-diagonal, using CVBBDPRE'
+ & /' 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
+C
+ CALL FCVMALLOC(T, Y, METH, ITMETH, IATOL, RTOL, ATOL,
+ & 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
+C
+ CALL FCVSPGMR(IPRE, IGS, 0, 0.0D0, IER)
+ IF (IER .NE. 0) THEN
+ WRITE(6,36) IER
+ 36 FORMAT(///' SUNDIALS_ERROR: FCVSPGMR returned IER = ', I5)
+ CALL MPI_ABORT(MPI_COMM_WORLD, 1, IER)
+ STOP
+ ENDIF
+C
+ MUDQ = 0
+ MLDQ = 0
+ MU = 0
+ ML = 0
+ CALL FCVBBDINIT(NLOCAL, MUDQ, MLDQ, MU, ML, 0.0D0, IER)
+ IF (IER .NE. 0) THEN
+ WRITE(6,35) IER
+ 35 FORMAT(///' SUNDIALS_ERROR: FCVBBDINIT returned IER = ', I5)
+ CALL MPI_ABORT(MPI_COMM_WORLD, 1, IER)
+ STOP
+ ENDIF
+C
+ IF (MYPE .EQ. 0) WRITE(6,38)
+ 38 FORMAT(/'Preconditioning on left'/)
+C
+C Looping point for cases IPRE = 1 and 2.
+C
+ 40 CONTINUE
+C
+C Loop through tout values, call solver, print output, test for failure.
+ TOUT = DTOUT
+ DO 60 JOUT = 1, NOUT
+C
+ CALL FCVODE(TOUT, T, Y, ITASK, IER)
+C
+ IF (MYPE .EQ. 0) WRITE(6,45) T, IOUT(LNST), IOUT(LNFE)
+ 45 FORMAT(' t = ', E10.2, 5X, 'no. steps = ', I5,
+ & ' no. f-s = ', I5)
+C
+ IF (IER .NE. 0) THEN
+ WRITE(6,50) IER, IOUT(15)
+ 50 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
+ 60 CONTINUE
+C
+C Get max. absolute error in the local vector.
+ ERMAX = 0.0D0
+ DO 65 I = 1, NLOCAL
+ ERRI = Y(I) - EXP(-ALPHA * (MYPE * NLOCAL + I) * T)
+ ERMAX = MAX(ERMAX, ABS(ERRI))
+ 65 CONTINUE
+C Get global max. error from MPI_REDUCE call.
+ CALL MPI_REDUCE(ERMAX, GERMAX, 1, MPI_DOUBLE_PRECISION, MPI_MAX,
+ & 0, MPI_COMM_WORLD, IER)
+ IF (IER .NE. 0) THEN
+ WRITE(6,70) IER
+ 70 FORMAT(///' MPI_ERROR: MPI_REDUCE returned IER = ', I5)
+ CALL MPI_ABORT(MPI_COMM_WORLD, 1, IER)
+ STOP
+ ENDIF
+ IF (MYPE .EQ. 0) WRITE(6,75) GERMAX
+ 75 FORMAT(/'Max. absolute error is', E10.2/)
+C
+C Print final statistics.
+ IF (MYPE .EQ. 0) THEN
+ NST = IOUT(LNST)
+ NFE = IOUT(LNFE)
+ NPSET = IOUT(LNSETUP)
+ NPE = IOUT(LNPE)
+ NPS = IOUT(LNPS)
+ NNI = IOUT(LNNI)
+ NLI = IOUT(LNLI)
+ AVDIM = DBLE(NLI) / DBLE(NNI)
+ NCFN = IOUT(LNCF)
+ NCFL = IOUT(LNCFL)
+ NETF = IOUT(LNETF)
+ LENRW = IOUT(LLENRW)
+ LENIW = IOUT(LLENIW)
+ LENRWLS = IOUT(LLENRWLS)
+ LENIWLS = IOUT(LLENIWLS)
+ WRITE(6,80) NST, NFE, NPSET, NPE, NPS, NNI, NLI, AVDIM, NCFN,
+ & NCFL, NETF, LENRW, LENIW, LENRWLS, LENIWLS
+ 80 FORMAT(/'Final statistics:'//
+ & ' number of steps = ', I5, 4X,
+ & ' number of f evals. = ', I5/
+ & ' number of prec. setups = ', I5/
+ & ' number of prec. evals. = ', I5, 4X,
+ & ' number of prec. solves = ', I5/
+ & ' number of nonl. iters. = ', I5, 4X,
+ & ' number of lin. iters. = ', I5/
+ & ' average Krylov subspace dimension (NLI/NNI) = ',F8.4/
+ & ' number of conv. failures.. nonlinear = ', I3,
+ & ' linear = ', I3/
+ & ' number of error test failures = ', I3/
+ & ' main solver real/int workspace sizes = ',2I5/
+ & ' linear solver real/int workspace sizes = ',2I5)
+ CALL FCVBBDOPT(LENRWBBD, LENIWBBD, NGEBBD)
+ WRITE(6,82) LENRWBBD, LENIWBBD, NGEBBD
+ 82 FORMAT('In CVBBDPRE:'/
+ & ' real/int local workspace = ', 2I5/
+ & ' number of g evals. = ', I5)
+ ENDIF
+C
+C If IPRE = 1, re-initialize T, Y, and the solver, and loop for
+C case IPRE = 2. Otherwise jump to final block.
+ IF (IPRE .EQ. 2) GO TO 99
+C
+ T = 0.0D0
+ DO I = 1, NLOCAL
+ Y(I) = 1.0D0
+ ENDDO
+C
+ CALL FCVREINIT(T, Y, IATOL, RTOL, ATOL, IER)
+ IF (IER .NE. 0) THEN
+ WRITE(6,91) IER
+ 91 FORMAT(///' SUNDIALS_ERROR: FCVREINIT returned IER = ', I5)
+ CALL MPI_ABORT(MPI_COMM_WORLD, 1, IER)
+ STOP
+ ENDIF
+C
+ IPRE = 2
+C
+ CALL FCVBBDREINIT(NLOCAL, MUDQ, MLDQ, 0.0D0, IER)
+ IF (IER .NE. 0) THEN
+ WRITE(6,92) IER
+ 92 FORMAT(///' SUNDIALS_ERROR: FCVBBDREINIT returned IER = ', I5)
+ CALL MPI_ABORT(MPI_COMM_WORLD, 1, IER)
+ STOP
+ ENDIF
+C
+ CALL FCVSPGMRREINIT(IPRE, IGS, 0.0D0, IER)
+ IF (IER .NE. 0) THEN
+ WRITE(6,93) IER
+ 93 FORMAT(///' SUNDIALS_ERROR: FCVSPGMRREINIT returned IER = ',I5)
+ CALL MPI_ABORT(MPI_COMM_WORLD, 1, IER)
+ STOP
+ ENDIF
+C
+ IF (MYPE .EQ. 0) WRITE(6,95)
+ 95 FORMAT(//60('-')///'Preconditioning on right'/)
+ GO TO 40
+C
+C Free the memory and finalize MPI.
+ 99 CALL FCVFREE
+ CALL MPI_FINALIZE(IER)
+C
+ STOP
+ END
+C
+C ------------------------------------------------------------------------
+C
+ SUBROUTINE FCVFUN(T, Y, YDOT, IPAR, RPAR, IER)
+C Routine for right-hand side function f
+ IMPLICIT NONE
+C
+ INTEGER*4 IPAR(*), IER
+ DOUBLE PRECISION T, Y(*), YDOT(*), RPAR(*)
+C
+ INTEGER MYPE
+ INTEGER*4 I, NLOCAL
+ DOUBLE PRECISION ALPHA
+C
+ NLOCAL = IPAR(1)
+ MYPE = IPAR(2)
+ ALPHA = RPAR(1)
+C
+ DO I = 1, NLOCAL
+ YDOT(I) = -ALPHA * (MYPE * NLOCAL + I) * Y(I)
+ ENDDO
+C
+ IER = 0
+C
+ RETURN
+ END
+C
+C ------------------------------------------------------------------------
+C
+ SUBROUTINE FCVGLOCFN(NLOC, T, YLOC, GLOC, IPAR, RPAR, IER)
+C Routine to define local approximate function g, here the same as f.
+ IMPLICIT NONE
+C
+ INTEGER*4 NLOC, IPAR(*), IER
+ DOUBLE PRECISION T, YLOC(*), GLOC(*), RPAR(*)
+C
+ CALL FCVFUN(T, YLOC, GLOC, IPAR, RPAR, IER)
+C
+ RETURN
+ END
+C
+C ------------------------------------------------------------------------
+C
+ SUBROUTINE FCVCOMMFN(NLOC, T, YLOC, IPAR, RPAR, IER)
+C Routine to perform communication required for evaluation of g.
+ 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
new file mode 100644
index 0000000..71026bd
--- /dev/null
+++ b/examples/cvode/fcmix_parallel/fcvDiag_kry_bbd_p.out
@@ -0,0 +1,76 @@
+Diagonal test problem:
+
+ NEQ = 40
+ 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
+
+
+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
+
+Max. absolute error is 0.28E-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 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
+In CVBBDPRE:
+ real/int local workspace = 20 10
+ number of g evals. = 14
+
+
+------------------------------------------------------------
+
+
+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
+
+Max. absolute error is 0.28E-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 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
+In CVBBDPRE:
+ real/int local workspace = 20 10
+ number of g evals. = 14
diff --git a/examples/cvode/fcmix_parallel/fcvDiag_kry_p.f b/examples/cvode/fcmix_parallel/fcvDiag_kry_p.f
new file mode 100644
index 0000000..35e7143
--- /dev/null
+++ b/examples/cvode/fcmix_parallel/fcvDiag_kry_p.f
@@ -0,0 +1,346 @@
+C ----------------------------------------------------------------
+C $Revision: 1.1 $
+C $Date: 2009/03/11 23:17:13 $
+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
+ INTEGER*4 NLOCAL
+ 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*4 IOUT(25), IPAR(2)
+ INTEGER*4 NEQ, I, NST, NFE, NPSET, NPE, NPS, NNI, NLI
+ INTEGER*4 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
+C
+ DATA ATOL/1.0D-10/, RTOL/1.0D-5/, DTOUT/0.1D0/, NOUT/10/
+ DATA LNST/3/, LNFE/4/, LNETF/5/, LNCF/6/, LNNI/7/, LNSETUP/8/,
+ 1 LNPE/18/, LNLI/20/, LNPS/19/, LNCFL/21/
+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
+ 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
+ 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
+C
+C Set input arguments.
+ NEQ = NPES * NLOCAL
+ T = 0.0D0
+ METH = 2
+ ITMETH = 2
+ IATOL = 1
+ ITASK = 1
+ IPRE = 1
+ IGS = 1
+C Set parameter alpha.
+ ALPHA = 10.0D0
+C
+C Load IPAR and RPAR
+ IPAR(1) = NLOCAL
+ IPAR(2) = MYPE
+ RPAR(1) = ALPHA
+C
+C Do remaining initializations for first case: IPRE = 1 (prec. on left).
+C
+ DO 10 I = 1, NLOCAL
+ 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 BDF/NEWTON/SPGMR'/
+ 1 ' Diagonal preconditioner uses approximate Jacobian')
+ WRITE(6,15) NPES
+ 15 FORMAT(' Number of processors = ', I3)
+ WRITE(6,16)
+ 16 FORMAT(//'Preconditioning on left'/)
+ 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
+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
+C
+ CALL FCVSPGMR (IPRE, IGS, 0, 0.0D0, 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)
+C
+C Loop through tout values, call solver, print output, test for failure.
+ TOUT = DTOUT
+ DO 70 JOUT = 1, NOUT
+C
+ CALL FCVODE(TOUT, T, Y, ITASK, IER)
+C
+ IF (MYPE .EQ. 0) WRITE(6,40) T, IOUT(LNST), IOUT(LNFE)
+ 40 FORMAT(' t = ', E10.2, 5X, 'no. steps = ', I5,
+ & ' 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
+C
+ TOUT = TOUT + DTOUT
+ 70 CONTINUE
+C
+C Get max. absolute error in the local vector.
+ ERMAX = 0.0D0
+ DO 75 I = 1, NLOCAL
+ ERRI = Y(I) - EXP(-ALPHA * (MYPE * NLOCAL + I) * T)
+ 75 ERMAX = MAX(ERMAX, ABS(ERRI))
+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
+ IF (MYPE .EQ. 0) WRITE(6,85) GERMAX
+ 85 FORMAT(/'Max. absolute error is ', E10.2/)
+C
+C Print final statistics.
+ NST = IOUT(LNST)
+ NFE = IOUT(LNFE)
+ NPSET = IOUT(LNSETUP)
+ NPE = IOUT(LNPE)
+ NPS = IOUT(LNPS)
+ NNI = IOUT(LNNI)
+ NLI = IOUT(LNLI)
+ AVDIM = DBLE(NLI) / DBLE(NNI)
+ NCFN = IOUT(LNCF)
+ NCFL = IOUT(LNCFL)
+ NETF = IOUT(LNETF)
+ IF (MYPE .EQ. 0)
+ 1 WRITE (6,90) NST, NFE, NPSET, NPE, NPS, NNI, NLI, AVDIM, NCFN,
+ & NCFL, NETF
+ 90 FORMAT(/'Final statistics:'//
+ & ' number of steps = ', I5, 5X,
+ & 'number of f evals. =', I5/
+ & ' number of prec. setups = ', I5/
+ & ' number of prec. evals. = ', I5, 5X,
+ & 'number of prec. solves = ', I5/
+ & ' number of nonl. iters. = ', I5, 5X,
+ & 'number of lin. iters. = ', I5/
+ & ' average Krylov subspace dimension (NLI/NNI) = ', F8.4/
+ & ' number of conv. failures.. nonlinear = ', I3,
+ & ' linear = ', I3/
+ & ' number of error test failures = ', I3)
+C
+C Re-initialize to run second case: IPRE = 2 (prec. on right).
+ IPRE = 2
+ T = 0.0D0
+ DO 110 I = 1, NLOCAL
+ 110 Y(I) = 1.0D0
+C
+ IF (MYPE .EQ. 0) WRITE(6,111)
+ 111 FORMAT(//60('-')///'Preconditioning on right'/)
+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
+ ENDIF
+C
+ CALL FCVSPGMRREINIT (IPRE, IGS, 0.0D0, IER)
+ IF (IER .NE. 0) THEN
+ WRITE(6,140) IER
+ 140 FORMAT(///' SUNDIALS_ERROR: FCVSPGMRREINIT 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
+ DO 170 JOUT = 1, NOUT
+C
+ CALL FCVODE(TOUT, T, Y, ITASK, IER)
+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
+C
+ TOUT = TOUT + DTOUT
+ 170 CONTINUE
+C
+C Get max. absolute error in the local vector.
+ ERMAX = 0.0D0
+ DO 175 I = 1, NLOCAL
+ ERRI = Y(I) - EXP(-ALPHA * (MYPE * NLOCAL + I) * T)
+ 175 ERMAX = MAX(ERMAX, ABS(ERRI))
+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
+ ENDIF
+ IF (MYPE .EQ. 0) WRITE(6,85) GERMAX
+C
+C Print final statistics.
+ NST = IOUT(LNST)
+ NFE = IOUT(LNFE)
+ NPSET = IOUT(LNSETUP)
+ NPE = IOUT(LNPE)
+ NPS = IOUT(LNPS)
+ NNI = IOUT(LNNI)
+ NLI = IOUT(LNLI)
+ AVDIM = DBLE(NLI) / DBLE(NNI)
+ NCFN = IOUT(LNCF)
+ NCFL = IOUT(LNCFL)
+ NETF = IOUT(LNETF)
+ IF (MYPE .EQ. 0)
+ 1 WRITE (6,90) NST, NFE, NPSET, NPE, NPS, NNI, NLI, AVDIM, NCFN,
+ & NCFL, NETF
+C
+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
+C
+ STOP
+ END
+C
+C ------------------------------------------------------------------------
+C
+ SUBROUTINE FCVFUN(T, Y, YDOT, IPAR, RPAR, IER)
+C Routine for right-hand side function f
+ IMPLICIT NONE
+C
+ INTEGER*4 IPAR(*), IER
+ DOUBLE PRECISION T, Y(*), YDOT(*), RPAR(*)
+C
+ INTEGER*4 I, MYPE, NLOCAL
+ DOUBLE PRECISION ALPHA
+C
+ NLOCAL = IPAR(1)
+ MYPE = IPAR(2)
+ ALPHA = RPAR(1)
+C
+ DO I = 1, NLOCAL
+ YDOT(I) = -ALPHA * (MYPE * NLOCAL + I) * Y(I)
+ ENDDO
+C
+ IER = 0
+C
+ RETURN
+ END
+C
+C ------------------------------------------------------------------------
+C
+ SUBROUTINE FCVPSOL(T, Y, FY, R, Z, GAMMA, DELTA, LR,
+ & IPAR, RPAR, VTEMP, 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:
+C J = diag(0, 0, 0, -4*alpha, ..., -N*alpha).
+C The vector r is copied to z, and the inverse of P (restricted to the
+C local vector segment) is applied to the vector z.
+ IMPLICIT NONE
+C
+ INTEGER IER, LR
+ INTEGER*4 IPAR(*)
+ DOUBLE PRECISION T, Y(*), FY(*), R(*), Z(*)
+ DOUBLE PRECISION GAMMA, DELTA, RPAR(*)
+ DOUBLE PRECISION VTEMP(*)
+C
+ INTEGER*4 I, MYPE, NLOCAL, ISTART, IBASE
+ DOUBLE PRECISION PSUBI, ALPHA
+C
+ NLOCAL = IPAR(1)
+ MYPE = IPAR(2)
+ ALPHA = RPAR(1)
+C
+ DO I = 1, NLOCAL
+ Z(I) = R(I)
+ ENDDO
+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
+ ENDDO
+C
+ RETURN
+ END
+C
+C ------------------------------------------------------------------------
+C
+ SUBROUTINE FCVPSET(T, Y, FY, JOK, JCUR, GAMMA, H,
+ & IPAR, RPAR, V1, V2, V3, IER)
+C Empty function. Not needed for the preconditioner, but required
+C by the FCVODE module.
+ RETURN
+ END
diff --git a/examples/cvode/fcmix_parallel/fcvDiag_kry_p.out b/examples/cvode/fcmix_parallel/fcvDiag_kry_p.out
new file mode 100644
index 0000000..6d37524
--- /dev/null
+++ b/examples/cvode/fcmix_parallel/fcvDiag_kry_p.out
@@ -0,0 +1,65 @@
+Diagonal test problem:
+
+ NEQ = 40 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
+
+
+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
+
+Max. absolute error is 0.15E-07
+
+
+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 conv. failures.. nonlinear = 0 linear = 0
+ number of error test failures = 5
+
+
+------------------------------------------------------------
+
+
+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
+
+Max. absolute error is 0.21E-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 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
new file mode 100644
index 0000000..21492e2
--- /dev/null
+++ b/examples/cvode/fcmix_parallel/fcvDiag_non_p.f
@@ -0,0 +1,191 @@
+C ----------------------------------------------------------------
+C $Revision: 1.1 $
+C $Date: 2009/03/11 23:16:06 $
+C ----------------------------------------------------------------
+C Diagonal ODE example. Nonstiff case: alpha = 10/NEQ.
+C ----------------------------------------------------------------
+C
+C Include MPI-Fortran header file for MPI_COMM_WORLD, MPI types.
+C
+ IMPLICIT NONE
+C
+ INCLUDE "mpif.h"
+C
+ INTEGER*4 NLOCAL
+ PARAMETER (NLOCAL=2)
+C
+ INTEGER IER, MYPE, NPES, NOUT, LNST, LNFE, LNNI, LNCF, LNETF
+ INTEGER METH, ITMETH, IATOL, ITASK, JOUT
+ INTEGER*4 NEQ, I, NST, NFE, NNI, NCFN, NETF
+ INTEGER*4 IOUT(25), IPAR(2)
+ DOUBLE PRECISION Y(128), ROUT(10), RPAR(1)
+ DOUBLE PRECISION ATOL, RTOL, DTOUT, T, ALPHA, TOUT
+ DOUBLE PRECISION ERMAX, ERRI, GERMAX
+C
+ DATA ATOL/1.0D-10/, RTOL/1.0D-5/, DTOUT/0.1D0/, NOUT/10/
+ DATA LNST/3/, LNFE/4/, LNNI/7/, LNCF/6/, LNETF/5/
+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
+ 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
+ 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
+C
+C Set input arguments.
+ NEQ = NPES * NLOCAL
+ T = 0.0D0
+ METH = 1
+ ITMETH = 1
+ IATOL = 1
+ ITASK = 1
+c Set parameter ALPHA
+ ALPHA = 10.0D0 / NEQ
+C
+C Load IPAR and RPAR
+ IPAR(1) = NLOCAL
+ IPAR(2) = MYPE
+ RPAR(1) = ALPHA
+C
+ DO 10 I = 1, NLOCAL
+ 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
+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
+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
+C
+C Loop through tout values, call solver, print output, test for failure.
+ TOUT = DTOUT
+ DO 70 JOUT = 1, NOUT
+C
+ CALL FCVODE(TOUT, T, Y, ITASK, IER)
+C
+ IF (MYPE .EQ. 0) WRITE(6,40) T, IOUT(LNST), IOUT(LNFE)
+ 40 FORMAT(' t = ', D10.2, 5X, 'no. steps = ', I5,
+ & ' 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
+C
+ TOUT = TOUT + DTOUT
+ 70 CONTINUE
+C
+C Get max. absolute error in the local vector.
+ ERMAX = 0.0D0
+ DO 75 I = 1, NLOCAL
+ ERRI = Y(I) - EXP(-ALPHA * (MYPE * NLOCAL + I) * T)
+ ERMAX = MAX(ERMAX, ABS(ERRI))
+ 75 CONTINUE
+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
+ IF (MYPE .EQ. 0) WRITE(6,85) GERMAX
+ 85 FORMAT(/'Max. absolute error is ', E10.2/)
+C
+C Print final statistics.
+ NST = IOUT(LNST)
+ NFE = IOUT(LNFE)
+ NNI = IOUT(LNNI)
+ NCFN = IOUT(LNCF)
+ NETF = IOUT(LNETF)
+ IF (MYPE .EQ. 0) WRITE (6,90) NST, NFE, NNI, NCFN, NETF
+ 90 FORMAT(/'Final statistics:'//
+ & ' number of steps = ', I5, 5X, /,
+ & ' number of f evals. = ', I5/
+ & ' number of nonlinear iters. = ', I5/
+ & ' number of nonlinear conv. failures = ', I3/
+ & ' number of error test failures = ', I3)
+C
+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
+C
+ STOP
+ END
+C
+C ------------------------------------------------------------------------
+C
+ SUBROUTINE FCVFUN(T, Y, YDOT, IPAR, RPAR, IER)
+C Routine for right-hand side function f
+C
+ IMPLICIT NONE
+C
+ INTEGER*4 IPAR(*), IER
+ DOUBLE PRECISION T, Y(*), YDOT(*), RPAR(*)
+C
+ INTEGER MYPE
+ INTEGER*4 NLOCAL, I
+ DOUBLE PRECISION ALPHA
+C
+ NLOCAL = IPAR(1)
+ MYPE = IPAR(2)
+ ALPHA = RPAR(1)
+C
+ DO I = 1, NLOCAL
+ YDOT(I) = -ALPHA * (MYPE * NLOCAL + I) * Y(I)
+ ENDDO
+C
+ IER = 0
+C
+ RETURN
+ END
diff --git a/examples/cvode/fcmix_parallel/fcvDiag_non_p.out b/examples/cvode/fcmix_parallel/fcvDiag_non_p.out
new file mode 100644
index 0000000..461a677
--- /dev/null
+++ b/examples/cvode/fcmix_parallel/fcvDiag_non_p.out
@@ -0,0 +1,31 @@
+Diagonal test problem:
+
+ NEQ = 8
+ parameter alpha = 1.250
+ 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
+
+
+ t = 0.10D+00 no. steps = 14 no. f-s = 32
+ 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
+
+Max. absolute error is 0.41E-07
+
+
+Final statistics:
+
+ number of steps = 81
+ number of f evals. = 100
+ number of nonlinear iters. = 96
+ 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
new file mode 100644
index 0000000..b91c508
--- /dev/null
+++ b/examples/cvode/fcmix_serial/CMakeLists.txt
@@ -0,0 +1,130 @@
+# ---------------------------------------------------------------
+# $Revision: 1.5 $
+# $Date: 2009/02/17 02:58:47 $
+# ---------------------------------------------------------------
+# Programmer: Radu Serban @ LLNL
+# ---------------------------------------------------------------
+# Copyright (c) 2007, The Regents of the University of California.
+# Produced at the Lawrence Livermore National Laboratory.
+# All rights reserved.
+# For details, see the LICENSE file.
+# ---------------------------------------------------------------
+# CMakeLists.txt file for the FCVODE serial examples
+
+
+# Add variable FCVODE_examples with the names of the serial FCVODE examples
+
+SET(FCVODE_examples
+ fcvAdvDiff_bnd
+ fcvDiurnal_kry_bp
+ fcvDiurnal_kry
+ fcvRoberts_dns
+ )
+
+# Add variable fcvode_bl_examples with the names of the serial FCVODE examples
+# that use Lapack
+
+SET(FCVODE_examples_BL
+ fcvRoberts_dnsL
+ )
+
+# 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")
+ SET(CVODE_LIB sundials_cvode_shared)
+ SET(NVECS_LIB sundials_nvecserial_shared)
+ SET(FNVECS_LIB sundials_fnvecserial_shared)
+ENDIF(LINK_LIBRARY_TYPE MATCHES "static")
+
+# 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)
+ SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${LAPACK_LINKER_FLAGS}")
+ SET(SUNDIALS_LIBS "${SUNDIALS_LIBS} ${LAPACK_LIBRARIES}")
+ENDIF(LAPACK_FOUND)
+
+# Add the build and install targets for each FCVODE example
+
+FOREACH(example ${FCVODE_examples})
+ ADD_EXECUTABLE(${example} ${example}.f)
+ TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+ IF(EXAMPLES_INSTALL)
+ INSTALL(FILES ${example}.f ${example}.out DESTINATION ${EXAMPLES_INSTALL_PATH}/cvode/fcmix_serial)
+ ENDIF(EXAMPLES_INSTALL)
+ENDFOREACH(example ${FCVODE_examples})
+
+# Add the build and install targets for each Lapack FCVODE example (if needed)
+
+IF(LAPACK_FOUND)
+ FOREACH(example ${FCVODE_examples_BL})
+ ADD_EXECUTABLE(${example} ${example}.f)
+ TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+ IF(EXAMPLES_INSTALL)
+ INSTALL(FILES ${example}.f ${example}.out DESTINATION ${EXAMPLES_INSTALL_PATH}/cvode/fcmix_serial)
+ ENDIF(EXAMPLES_INSTALL)
+ ENDFOREACH(example ${FCVODE_examples_BL})
+ENDIF(LAPACK_FOUND)
+
+IF(EXAMPLES_INSTALL)
+
+ # Install the README file
+ INSTALL(FILES README DESTINATION ${EXAMPLES_INSTALL_PATH}/cvode/fcmix_serial)
+
+ # Prepare substitution variables for Makefile and/or CMakeLists templates
+ SET(SOLVER "CVODE")
+ SET(SOLVER_LIB "sundials_cvode")
+ SET(SOLVER_FLIB "sundials_fcvode")
+ LIST2STRING(FCVODE_examples EXAMPLES)
+ IF(LAPACK_FOUND)
+ LIST2STRING(FCVODE_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
+ # 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
+ )
+
+ # install CMakelists.txt
+ INSTALL(
+ FILES ${PROJECT_BINARY_DIR}/examples/cvode/fcmix_serial/CMakeLists.txt
+ DESTINATION ${EXAMPLES_INSTALL_PATH}/cvode/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
+ # 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_F77_ex.in
+ ${PROJECT_BINARY_DIR}/examples/cvode/fcmix_serial/Makefile_ex
+ @ONLY
+ )
+ # install the configured Makefile_ex as Makefile
+ INSTALL(
+ FILES ${PROJECT_BINARY_DIR}/examples/cvode/fcmix_serial/Makefile_ex
+ DESTINATION ${EXAMPLES_INSTALL_PATH}/cvode/fcmix_serial
+ RENAME Makefile
+ )
+ ENDIF(UNIX)
+
+ENDIF(EXAMPLES_INSTALL)
diff --git a/examples/cvode/fcmix_serial/Makefile.in b/examples/cvode/fcmix_serial/Makefile.in
new file mode 100644
index 0000000..abce19d
--- /dev/null
+++ b/examples/cvode/fcmix_serial/Makefile.in
@@ -0,0 +1,137 @@
+# -----------------------------------------------------------------
+# $Revision: 1.11 $
+# $Date: 2009/02/17 02:58:47 $
+# -----------------------------------------------------------------
+# Programmer(s): Radu Serban and Aaron Collier @ LLNL
+# -----------------------------------------------------------------
+# Copyright (c) 2002, The Regents of the University of California.
+# Produced at the Lawrence Livermore National Laboratory.
+# All rights reserved.
+# For details, see the LICENSE file.
+# -----------------------------------------------------------------
+# Makefile for FCVODE serial examples
+#
+# @configure_input@
+# -----------------------------------------------------------------
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_builddir = @top_builddir@
+builddir = @builddir@
+abs_builddir = @abs_builddir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+includedir = @includedir@
+libdir = @libdir@
+
+INSTALL = @INSTALL@
+INSTALL_PROG = @INSTALL_PROGRAM@
+INSTALL_FILE = @INSTALL_DATA@
+
+LIBTOOL = @LIBTOOL@
+LIBTOOL_DEPS = @LIBTOOL_DEPS@
+
+F77 = @F77@
+FFLAGS = @FFLAGS@
+F77_LNKR = @F77_LNKR@
+F77_LDFLAGS = @F77_LDFLAGS@
+F77_LIBS = @F77_LIBS@
+
+LAPACK_ENABLED = @LAPACK_ENABLED@
+BLAS_LAPACK_LIBS = @BLAS_LAPACK_LIBS@
+
+OBJ_EXT = @OBJEXT@
+EXE_EXT = @EXEEXT@
+
+EXS_INSTDIR = @EXS_INSTDIR@
+
+top_srcdir = $(srcdir)/../../..
+
+SUNDIALS_LIBS = $(top_builddir)/src/cvode/fcmix/libsundials_fcvode.la \
+ $(top_builddir)/src/cvode/libsundials_cvode.la \
+ $(top_builddir)/src/nvec_ser/libsundials_fnvecserial.la \
+ $(top_builddir)/src/nvec_ser/libsundials_nvecserial.la
+
+fortran-update = ${SHELL} ${top_builddir}/bin/fortran-update.sh
+
+mkinstalldirs = $(SHELL) $(top_srcdir)/config/mkinstalldirs
+rminstalldirs = $(SHELL) $(top_srcdir)/config/rminstalldirs
+
+EXAMPLES = fcvAdvDiff_bnd \
+ fcvDiurnal_kry_bp \
+ fcvDiurnal_kry \
+ fcvRoberts_dns
+
+EXAMPLES_BL = fcvRoberts_dnsL
+
+OBJECTS = ${EXAMPLES:=${OBJ_EXT}}
+OBJECTS_BL = ${EXAMPLES_BL:=${OBJ_EXT}}
+EXECS = ${EXAMPLES:=${EXE_EXT}}
+EXECS_BL = ${EXAMPLES_BL:=${EXE_EXT}}
+
+# ----------------------------------------------------------------------------------------------------------------------
+
+all:
+ @for i in ${EXAMPLES} ; do \
+ ${fortran-update} ${srcdir} $${i}.f ; \
+ ${LIBTOOL} --mode=compile ${F77} ${FFLAGS} -c ${builddir}/$${i}-updated.f ; \
+ ${LIBTOOL} --mode=link ${F77_LNKR} -o ${builddir}/$${i}${EXE_EXT} ${builddir}/$${i}-updated${OBJ_EXT} ${F77_LDFLAGS} ${SUNDIALS_LIBS} ${F77_LIBS} ${BLAS_LAPACK_LIBS} ; \
+ done
+ @if test "X${LAPACK_ENABLED}" = "Xyes"; then \
+ for i in ${EXAMPLES_BL} ; do \
+ ${fortran-update} ${srcdir} $${i}.f ; \
+ ${LIBTOOL} --mode=compile ${F77} ${FFLAGS} -c ${builddir}/$${i}-updated.f ; \
+ ${LIBTOOL} --mode=link ${F77_LNKR} -o ${builddir}/$${i}${EXE_EXT} ${builddir}/$${i}-updated${OBJ_EXT} ${F77_LDFLAGS} ${SUNDIALS_LIBS} ${F77_LIBS} ${BLAS_LAPACK_LIBS} ; \
+ done ; \
+ fi
+
+
+install:
+ $(mkinstalldirs) $(EXS_INSTDIR)/cvode/fcmix_serial
+ $(INSTALL_FILE) Makefile_ex $(EXS_INSTDIR)/cvode/fcmix_serial/Makefile
+ $(INSTALL_FILE) $(top_srcdir)/examples/cvode/fcmix_serial/README $(EXS_INSTDIR)/cvode/fcmix_serial/
+ for i in ${EXAMPLES} ; do \
+ $(INSTALL_FILE) $(top_srcdir)/examples/cvode/fcmix_serial/$${i}.f $(EXS_INSTDIR)/cvode/fcmix_serial/ ; \
+ $(INSTALL_FILE) $(top_srcdir)/examples/cvode/fcmix_serial/$${i}.out $(EXS_INSTDIR)/cvode/fcmix_serial/ ; \
+ done
+ @if test "X${LAPACK_ENABLED}" = "Xyes"; then \
+ for i in ${EXAMPLES_BL} ; do \
+ $(INSTALL_FILE) $(top_srcdir)/examples/cvode/fcmix_serial/$${i}.f $(EXS_INSTDIR)/cvode/fcmix_serial/ ; \
+ $(INSTALL_FILE) $(top_srcdir)/examples/cvode/fcmix_serial/$${i}.out $(EXS_INSTDIR)/cvode/fcmix_serial/ ; \
+ done ; \
+ fi
+
+uninstall:
+ rm -f $(EXS_INSTDIR)/cvode/fcmix_serial/Makefile
+ rm -f $(EXS_INSTDIR)/cvode/fcmix_serial/README
+ for i in ${EXAMPLES} ; do \
+ rm -f $(EXS_INSTDIR)/cvode/fcmix_serial/$${i}.f ; \
+ rm -f $(EXS_INSTDIR)/cvode/fcmix_serial/$${i}.out ; \
+ done
+ @if test "X${LAPACK_ENABLED}" = "Xyes"; then \
+ for i in ${EXAMPLES_BL} ; do \
+ rm -f $(EXS_INSTDIR)/cvode/fcmix_serial/$${i}.f ; \
+ rm -f $(EXS_INSTDIR)/cvode/fcmix_serial/$${i}.out ; \
+ done ; \
+ fi
+ $(rminstalldirs) $(EXS_INSTDIR)/cvode/fcmix_serial
+ $(rminstalldirs) $(EXS_INSTDIR)/cvode
+
+clean:
+ rm -rf .libs
+ rm -f *.lo *.o
+ rm -f *-updated.f
+ rm -f ${OBJECTS} ${OBJECTS_BL}
+ rm -f $(EXECS) $(EXECS_BL)
+
+distclean: clean
+ rm -f Makefile
+ rm -f Makefile_ex
+
+# ----------------------------------------------------------------------------------------------------------------------
+
+libtool: $(top_builddir)/$(LIBTOOL_DEPS)
+ @cd ${top_builddir} ; \
+ ${SHELL} ./config.status --recheck ; \
+ cd ${abs_builddir}
diff --git a/examples/cvode/fcmix_serial/README b/examples/cvode/fcmix_serial/README
new file mode 100644
index 0000000..9eda1c6
--- /dev/null
+++ b/examples/cvode/fcmix_serial/README
@@ -0,0 +1,18 @@
+List of serial CVODE FCMIX examples
+
+ fcvAdvDiff_bnd : advection-diffusion example (BDF/BAND)
+ fcvDiurnal_kry_bp : kinetics-transport example (BDF/SPGMR/FCVBP)
+ fcvDiurnal_kry : kinetics-transport example (BDF/SPGMR/User Prec)
+ fcvRoberts_dns : chemical kinetics example (BDF/DENSE)
+ fcvRoberts_dnsL : chemical kinetics example (BDF/DENSE lapack)
+
+Sample results:
+
+ SUNDIALS was built with the following options:
+
+ ./configure CC=gcc F77=gfortran CFLAGS="-g3 -O0" FFLAGS="-g3 -O0" --enable-examples
+
+ System Architecture: IA-32
+ Processor Type: Intel Pentium 4 Xeon DP (i686)
+ Operating System: Red Hat Enterprise Linux WS 3 (Taroon Update 7)
+ C/Fortran Compilers: gcc/gfortran v4.1.0
diff --git a/examples/cvode/fcmix_serial/fcvAdvDiff_bnd.f b/examples/cvode/fcmix_serial/fcvAdvDiff_bnd.f
new file mode 100644
index 0000000..6824c63
--- /dev/null
+++ b/examples/cvode/fcmix_serial/fcvAdvDiff_bnd.f
@@ -0,0 +1,281 @@
+C ----------------------------------------------------------------
+C $Revision: 1.1 $
+C $Date: 2007/10/25 20:03:27 $
+C ----------------------------------------------------------------
+C FCVODE Example Problem: Advection-diffusion, banded user
+C Jacobian.
+C
+C The following is a simple example problem with a banded
+C Jacobian. The problem is the semi-discrete form of the
+C advection-diffusion equation in 2D:
+C du/dt = d^2 u / dx^2 + .5 du/dx + d^2 u / dy^2
+C on the rectangle 0 <= x <= 2, 0 <= y <= 1, and the time
+C interval 0 <= t <= 1. Homogeneous Dirichlet boundary conditions
+C are posed, and the initial condition is the following:
+C u(x,y,t=0) = x(2-x)y(1-y)exp(5xy) .
+C The PDE is discretized on a uniform MX+2 by MY+2 grid with
+C central differencing, and with boundary values eliminated,
+C leaving an ODE system of size NEQ = MX*MY.
+C This program solves this problem with CVODE, using the Fortran/C
+C interface routine package. This solution uses the BDF method,
+C a user-supplied banded Jacobian routine, and scalar relative and
+C absolute tolerances. It prints results at t = .1, .2, ..., 1.0.
+C At the end of the run, various counters of interest are printed.
+C ----------------------------------------------------------------
+C
+ IMPLICIT NONE
+C
+ INTEGER*4 MX, MY, NEQ
+ PARAMETER (MX=10, MY=5)
+ PARAMETER (NEQ=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 IOUT(25), IPAR(2)
+ INTEGER*4 MU, ML
+ DOUBLE PRECISION RTOL, ATOL, T0, T, TOUT, DTOUT, UNORM
+ DOUBLE PRECISION U(NEQ), ROUT(10), RPAR(5)
+C
+ DATA LNST/3/, LNFE/4/, LNETF/5/, LNCF/6/, LNNI/7/, LNSETUP/8/,
+ 1 LNJE/17/
+C
+ CALL INITBX(XMAX, YMAX, MX, MY, U, IPAR, RPAR)
+C
+ T0 = 0.0D0
+ METH = 2
+ ITMETH = 2
+ IATOL = 1
+ RTOL = 0.0D0
+ ATOL = 1.0D-5
+ MU = MY
+ ML = MY
+ DTOUT = 0.1D0
+ ITASK = 1
+C
+ WRITE(6,10) NEQ
+ 10 FORMAT('Band example problem:'//
+ 1 ' Advection-diffusion, NEQ = ', I2//)
+C
+ 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
+ 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
+C
+ CALL FCVBAND(NEQ, MU, ML, IER)
+ IF (IER .NE. 0) THEN
+ WRITE(6,40) IER
+ 40 FORMAT(///' SUNDIALS_ERROR: FCVBAND returned IER = ', I5)
+ CALL FCVFREE
+ STOP
+ ENDIF
+C
+ CALL FCVBANDSETJAC(1, IER)
+C
+ CALL MAXNORM(NEQ, U, UNORM)
+ WRITE(6,45) T0, UNORM
+ 45 FORMAT(' At t = ', F6.2, ' max.norm(u) = ', E14.6)
+C
+ TOUT = DTOUT
+ DO 70 JOUT = 1, 10
+C
+ CALL FCVODE(TOUT, T, U, ITASK, IER)
+C
+ CALL MAXNORM(NEQ, U, UNORM)
+ WRITE(6,50) T, UNORM, IOUT(LNST)
+ 50 FORMAT(' At t = ', F6.2, ' max.norm(u) = ', E14.6,
+ 1 ' NST = ', I4)
+C
+ IF (IER .NE. 0) THEN
+ WRITE(6,60) IER, IOUT(15)
+ 60 FORMAT(///' SUNDIALS_ERROR: FCVODE returned IER = ', I5, /,
+ 1 ' Linear Solver returned IER = ', I5)
+ CALL FCVFREE
+ STOP
+ ENDIF
+C
+ TOUT = TOUT + DTOUT
+ 70 CONTINUE
+C
+ WRITE(6,80) IOUT(LNST), IOUT(LNFE), IOUT(LNJE), IOUT(LNSETUP),
+ 1 IOUT(LNNI), IOUT(LNCF), IOUT(LNETF)
+ 80 FORMAT(//'Final statistics:'//
+ 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)
+C
+ CALL FCVFREE
+C
+ STOP
+ END
+
+C ----------------------------------------------------------------
+
+ SUBROUTINE INITBX(XMAX, YMAX, MX, MY, U0, IPAR, RPAR)
+C Load IPAR and RPAR with problem constants and U0 with initial values
+ IMPLICIT NONE
+C
+ INTEGER*4 MX, MY, IPAR(*)
+ DOUBLE PRECISION XMAX, YMAX, U0(MY,MX), RPAR(*)
+C
+ INTEGER*4 I, J
+ DOUBLE PRECISION DX, DY, X, Y, HDCOEF, HACOEF, VDCOEF
+C
+C Problem constants
+ DX = XMAX / (MX + 1)
+ DY = YMAX / (MY + 1)
+ HDCOEF = 1.0D0 / (DX * DX)
+ HACOEF = 0.5D0 / (2.0D0 * DX)
+ VDCOEF = 1.0D0 / (DY * DY)
+C Load constants in IPAR and RPAR
+ IPAR(1) = MX
+ IPAR(2) = MY
+ RPAR(1) = DX
+ RPAR(2) = DY
+ RPAR(3) = HDCOEF
+ RPAR(4) = HACOEF
+ RPAR(5) = VDCOEF
+C
+C Loop over grid and load initial values.
+ DO 20 I = 1, MX
+ X = I * DX
+ DO 10 J = 1, MY
+ Y = J * DY
+ U0(J,I) = X * (XMAX - X) * Y * (YMAX - Y) *
+ * EXP(5.0D0 * X * Y)
+ 10 CONTINUE
+ 20 CONTINUE
+C
+ RETURN
+ END
+
+ SUBROUTINE MAXNORM(N, U, UNORM)
+C Compute max-norm of array U
+ IMPLICIT NONE
+C
+ INTEGER*4 I, N
+ DOUBLE PRECISION U(*), UNORM, TEMP
+C
+ TEMP = 0.0D0
+ DO 10 I = 1, N
+ TEMP = MAX(ABS(U(I)), TEMP)
+ 10 CONTINUE
+ UNORM = TEMP
+ RETURN
+ END
+
+C ----------------------------------------------------------------
+
+ SUBROUTINE FCVFUN(T, U, UDOT, IPAR, RPAR, IER)
+C Right-hand side routine
+ IMPLICIT NONE
+C
+ DOUBLE PRECISION T, U(*), UDOT(*), RPAR(*)
+ INTEGER*4 IPAR(*), IER
+C
+ 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
+C Exract constants from IPAR and RPAR
+ MX = IPAR(1)
+ MY = IPAR(2)
+ DX = RPAR(1)
+ DY = RPAR(2)
+ HDCOEF = RPAR(3)
+ HACOEF = RPAR(4)
+ VDCOEF = RPAR(5)
+C
+C Loop over all grid points.
+ DO 20 I = 1, MX
+ IOFF = (I - 1) * MY
+ DO 10 J = 1, MY
+C
+C Extract u at x_i, y_j and four neighboring points.
+ IJ = J + IOFF
+ UIJ = U(IJ)
+ UDN = 0.0D0
+ IF (J .NE. 1) UDN = U(IJ - 1)
+ UUP = 0.0D0
+ IF (J .NE. MY) UUP = U(IJ + 1)
+ ULT = 0.0D0
+ IF (I .NE. 1) ULT = U(IJ - MY)
+ URT = 0.0D0
+ IF (I .NE. MX) URT = U(IJ + MY)
+C
+C Set diffusion and advection terms and load into UDOT.
+ HDIFF = HDCOEF * (ULT - 2.0D0 * UIJ + URT)
+ HADV = HACOEF * (URT - ULT)
+ VDIFF = VDCOEF * (UUP - 2.0D0 * UIJ + UDN)
+ UDOT(IJ) = HDIFF + HADV + VDIFF
+ 10 CONTINUE
+ 20 CONTINUE
+C
+ IER = 0
+C
+ RETURN
+ END
+
+C ----------------------------------------------------------------
+
+ SUBROUTINE FCVBJAC(N, MU, ML, MDIM, T, U, FU,
+ 1 BJAC, H, IPAR, RPAR, V1, V2, V3, IER)
+C Load banded Jacobian
+ IMPLICIT NONE
+C
+ INTEGER N, MU, ML, MDIM
+ INTEGER*4 IPAR(*), IER
+ DOUBLE PRECISION T, U(*), FU(*), BJAC(MDIM,*), H, RPAR(*)
+ DOUBLE PRECISION V1(*), V2(*), V3(*)
+C
+ INTEGER*4 MBAND, MX, MY
+ INTEGER*4 I, J, K, IOFF, MU1, MU2
+ DOUBLE PRECISION DX, DY, HDCOEF, HACOEF, VDCOEF
+C
+C Exract constants from IPAR and RPAR
+ MX = IPAR(1)
+ MY = IPAR(2)
+ DX = RPAR(1)
+ DY = RPAR(2)
+ HDCOEF = RPAR(3)
+ HACOEF = RPAR(4)
+ VDCOEF = RPAR(5)
+C
+ MU1 = MU + 1
+ MU2 = MU + 2
+ MBAND = MU + 1 + ML
+C
+C Loop over all grid points.
+ DO 20 I = 1, MX
+ IOFF = (I - 1) * MY
+ DO 10 J = 1, MY
+ K = J + IOFF
+C
+C Set Jacobian elements in column k of Jb.
+ BJAC(MU1,K) = -2.0D0 * (VDCOEF + HDCOEF)
+ IF (I .NE. 1) BJAC(1,K) = HDCOEF + HACOEF
+ IF (I .NE. MX) BJAC(MBAND,K) = HDCOEF - HACOEF
+ IF (J .NE. 1) BJAC(MU,K) = VDCOEF
+ IF (J .NE. MY) BJAC(MU2,K) = VDCOEF
+C
+ 10 CONTINUE
+ 20 CONTINUE
+C
+ IER = 0
+C
+ RETURN
+ END
diff --git a/examples/cvode/fcmix_serial/fcvAdvDiff_bnd.out b/examples/cvode/fcmix_serial/fcvAdvDiff_bnd.out
new file mode 100644
index 0000000..7f03c51
--- /dev/null
+++ b/examples/cvode/fcmix_serial/fcvAdvDiff_bnd.out
@@ -0,0 +1,24 @@
+Band example problem:
+
+ Advection-diffusion, NEQ = 50
+
+
+ At t = 0.00 max.norm(u) = 0.895472E+02
+ At t = 0.10 max.norm(u) = 0.413289E+01 NST = 85
+ At t = 0.20 max.norm(u) = 0.103929E+01 NST = 103
+ At t = 0.30 max.norm(u) = 0.297983E+00 NST = 113
+ At t = 0.40 max.norm(u) = 0.876577E-01 NST = 120
+ At t = 0.50 max.norm(u) = 0.262564E-01 NST = 126
+ At t = 0.60 max.norm(u) = 0.783042E-02 NST = 130
+ At t = 0.70 max.norm(u) = 0.232939E-02 NST = 134
+ At t = 0.80 max.norm(u) = 0.695343E-03 NST = 137
+ At t = 0.90 max.norm(u) = 0.211598E-03 NST = 140
+ At t = 1.00 max.norm(u) = 0.655685E-04 NST = 142
+
+
+Final statistics:
+
+ No. steps = 142 No. f-s = 174 No. J-s = 3 No. LU-s = 23
+ No. nonlinear iterations = 170
+ No. nonlinear convergence failures = 0
+ No. error test failures = 3
diff --git a/examples/cvode/fcmix_serial/fcvDiurnal_kry.f b/examples/cvode/fcmix_serial/fcvDiurnal_kry.f
new file mode 100644
index 0000000..00c6d8e
--- /dev/null
+++ b/examples/cvode/fcmix_serial/fcvDiurnal_kry.f
@@ -0,0 +1,993 @@
+C ----------------------------------------------------------------
+C $Revision: 1.1 $
+C $Date: 2007/10/25 20:03:27 $
+C ----------------------------------------------------------------
+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:
+C
+C dc(i)/dt = Kh*(d/dx)**2 c(i) + V*dc(i)/dx + (d/dy)(Kv(y)*dc(i)/dy)
+C + Ri(c1,c2,t) for i = 1,2, where
+C R1(c1,c2,t) = -q1*c1*c3 - q2*c1*c2 + 2*q3(t)*c3 + q4(t)*c2 ,
+C R2(c1,c2,t) = q1*c1*c3 - q2*c1*c2 - q4(t)*c2 ,
+C Kv(y) = Kv0*exp(y/5) ,
+C Kh, V, Kv0, q1, q2, and c3 are constants, and q3(t) and q4(t)
+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
+C in 0 .le. t .le. 86400 sec (1 day).
+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 the block-diagonal part of the Jacobian as a left
+C preconditioner.
+C
+C Note: this program requires the dense linear solver routines
+C DGEFA and DGESL from LINPACK, 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 ----------------------------------------------------------------
+C
+ IMPLICIT NONE
+C
+ INTEGER*4 MX, MY, NEQ
+ PARAMETER (MX=10, MY=10)
+ PARAMETER (NEQ=2*MX*MY)
+ 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 IOUT(25),IPAR(LENIPAR)
+ 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
+ DATA TWOHR/7200.0D0/, RTOL/1.0D-5/, FLOOR/100.0D0/,
+ & JPRETYPE/1/, IGSTYPE/1/, MAXL/0/, DELT/0.0D0/
+ DATA LNST/3/, LNFE/4/, LNETF/5/, LNCF/6/, LNNI/7/, LNSETUP/8/,
+ & LQ/9/, LNPE/18/, LNLI/20/, LNPS/19/, LNCFL/21/
+ DATA LH/2/
+C
+C Load problem constants into IPAR, RPAR, and set initial values
+ CALL INITKX(MX, MY, U, IPAR, RPAR)
+C
+C Set other input arguments.
+ T = 0.0D0
+ METH = 2
+ ITMETH = 2
+ IATOL = 1
+ ATOL = RTOL * FLOOR
+ ITASK = 1
+C
+ WRITE(6,10) NEQ
+ 10 FORMAT('Krylov example problem:'//
+ & ' Kinetics-transport, NEQ = ', I4/)
+C
+ 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 CVODE
+ CALL FCVMALLOC(T, U, METH, ITMETH, IATOL, RTOL, ATOL,
+ & IOUT, ROUT, IPAR, RPAR, IER)
+ IF (IER .NE. 0) THEN
+ WRITE(6,30) IER
+ 30 FORMAT(///' SUNDIALS_ERROR: FCVMALLOC returned IER = ', I5)
+ STOP
+ ENDIF
+C
+ CALL FCVSPGMR(JPRETYPE, IGSTYPE, MAXL, DELT, IER)
+ IF (IER .NE. 0) THEN
+ WRITE(6,40) IER
+ 40 FORMAT(///' SUNDIALS_ERROR: FCVSPGMR returned IER = ', I5)
+ CALL FCVFREE
+ STOP
+ ENDIF
+C
+ CALL FCVSPILSSETPREC(1, IER)
+C
+C Loop over output points, call FCVODE, print sample solution values.
+ TOUT = TWOHR
+ DO JOUT = 1, 12
+C
+ CALL FCVODE(TOUT, T, U, ITASK, IER)
+C
+ WRITE(6,50) T, IOUT(LNST), IOUT(LQ), ROUT(LH)
+ 50 FORMAT(/' t = ', E11.3, 3X, 'nst = ', I5,
+ & ' q = ', I2, ' h = ', E14.6)
+ WRITE(6,55) U(1,1,1), U(1,5,5), U(1,10,10),
+ & U(2,1,1), U(2,5,5), U(2,10,10)
+ 55 FORMAT(' c1 (bot.left/middle/top rt.) = ', 3E14.6/
+ & ' 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, /,
+ & ' Linear Solver returned IER = ', I5)
+ CALL FCVFREE
+ STOP
+ ENDIF
+C
+ TOUT = TOUT + TWOHR
+C
+ ENDDO
+
+C Print final statistics.
+ NST = IOUT(LNST)
+ NFE = IOUT(LNFE)
+ NPSET = IOUT(LNSETUP)
+ NPE = IOUT(LNPE)
+ NPS = IOUT(LNPS)
+ NNI = IOUT(LNNI)
+ NLI = IOUT(LNLI)
+ AVDIM = DBLE(NLI) / DBLE(NNI)
+ NCFN = IOUT(LNCF)
+ NCFL = IOUT(LNCFL)
+ NETF = IOUT(LNETF)
+ WRITE(6,80) NST, NFE, NPSET, NPE, NPS, NNI, NLI, AVDIM, NCFN,
+ & NCFL, NETF
+ 80 FORMAT(//'Final statistics:'//
+ & ' number of steps = ', I5, 5X,
+ & ' number of f evals. =', I5/
+ & ' number of prec. setups = ', I5/
+ & ' number of prec. evals. = ', I5, 5X,
+ & ' number of prec. solves = ', I5/
+ & ' number of nonl. iters. = ', I5, 5X,
+ & ' number of lin. iters. = ', I5/
+ & ' average Krylov subspace dimension (NLI/NNI) = ', E14.6/
+ & ' number of conv. failures.. nonlinear = ', I3,
+ & ' linear = ', I3/
+ & ' number of error test failures = ', I3)
+C
+ CALL FCVFREE
+C
+ STOP
+ END
+
+C ----------------------------------------------------------------
+
+ SUBROUTINE INITKX(MX, MY, U0, IPAR, RPAR)
+C Routine to set problem constants and initial values
+C
+ IMPLICIT NONE
+C
+ INTEGER*4 MX, MY, IPAR(*)
+ DOUBLE PRECISION RPAR(*)
+C
+ 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
+ DOUBLE PRECISION VDCO, HACO, X, Y
+ DOUBLE PRECISION CX, CY, DKH, DKV0, DX, HALFDA, PI, VEL
+C
+ DATA DKH/4.0D-6/, VEL/0.001D0/, DKV0/1.0D-8/, HALFDA/4.32D4/,
+ 1 PI/3.1415926535898D0/
+C
+C Problem constants
+ MM = MX * MY
+ Q1 = 1.63D-16
+ Q2 = 4.66D-16
+ A3 = 22.62D0
+ A4 = 7.601D0
+ OM = PI / HALFDA
+ C3 = 3.7D16
+ DX = 20.0D0 / (MX - 1.0D0)
+ DY = 20.0D0 / (MY - 1.0D0)
+ HDCO = DKH / DX**2
+ HACO = VEL / (2.0D0 * DX)
+ VDCO = (1.0D0 / DY**2) * DKV0
+C
+C Load constants in IPAR and RPAR
+ IPAR(1) = MX
+ IPAR(2) = MY
+ IPAR(3) = MM
+C
+ RPAR(1) = Q1
+ RPAR(2) = Q2
+ RPAR(3) = Q3
+ RPAR(4) = Q4
+ RPAR(5) = A3
+ RPAR(6) = A4
+ RPAR(7) = OM
+ RPAR(8) = C3
+ RPAR(9) = DY
+ RPAR(10) = HDCO
+ RPAR(11) = VDCO
+ RPAR(12) = HACO
+C
+C Pointers into IPAR and RPAR
+ P_IPP = 7
+ P_BD = 13
+ P_P = P_BD + 4*MM
+C
+ IPAR(4) = P_IPP
+ IPAR(5) = P_BD
+ IPAR(6) = P_P
+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
+ ENDDO
+ ENDDO
+C
+ RETURN
+ END
+
+C ----------------------------------------------------------------
+
+ SUBROUTINE FCVFUN(T, U, UDOT, IPAR, RPAR, IER)
+C Routine for right-hand side function f
+C
+ IMPLICIT NONE
+C
+ DOUBLE PRECISION T, U(2,*), UDOT(2,*), RPAR(*)
+ INTEGER*4 IPAR(*), IER
+C
+ INTEGER 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
+ DOUBLE PRECISION C1RT, C2RT, CYDN, CYUP, HORD1, HORD2, HORAD1
+ DOUBLE PRECISION HORAD2, QQ1, QQ2, QQ3, QQ4, RKIN1, RKIN2, S
+ DOUBLE PRECISION VERTD1, VERTD2, YDN, YUP
+C
+C Extract constants from IPAR and RPAR
+ MX = IPAR(1)
+ MY = IPAR(2)
+ MM = IPAR(3)
+C
+ Q1 = RPAR(1)
+ Q2 = RPAR(2)
+ Q3 = RPAR(3)
+ Q4 = RPAR(4)
+ A3 = RPAR(5)
+ A4 = RPAR(6)
+ OM = RPAR(7)
+ C3 = RPAR(8)
+ DY = RPAR(9)
+ HDCO = RPAR(10)
+ VDCO = RPAR(11)
+ HACO = RPAR(12)
+C
+C Set diurnal rate coefficients.
+ S = SIN(OM * T)
+ IF (S .GT. 0.0D0) THEN
+ Q3 = EXP(-A3 / S)
+ Q4 = EXP(-A4 / S)
+ ELSE
+ Q3 = 0.0D0
+ Q4 = 0.0D0
+ ENDIF
+ RPAR(3) = Q3
+ RPAR(4) = Q4
+C
+C Loop over all grid points.
+ DO JY = 1, MY
+ YDN = 30.0D0 + (JY - 1.5D0) * DY
+ YUP = YDN + DY
+ CYDN = VDCO * EXP(0.2D0 * YDN)
+ CYUP = VDCO * EXP(0.2D0 * YUP)
+ IBLOK0 = (JY - 1) * MX
+ IDN = -MX
+ IF (JY .EQ. 1) IDN = MX
+ IUP = MX
+ IF (JY .EQ. MY) IUP = -MX
+ DO JX = 1, MX
+ IBLOK = IBLOK0 + JX
+ C1 = U(1,IBLOK)
+ C2 = U(2,IBLOK)
+C Set kinetic rate terms.
+ QQ1 = Q1 * C1 * C3
+ QQ2 = Q2 * C1 * C2
+ QQ3 = Q3 * C3
+ QQ4 = Q4 * C2
+ RKIN1 = -QQ1 - QQ2 + 2.0D0 * QQ3 + QQ4
+ RKIN2 = QQ1 - QQ2 - QQ4
+C Set vertical diffusion terms.
+ C1DN = U(1,IBLOK + IDN)
+ C2DN = U(2,IBLOK + IDN)
+ C1UP = U(1,IBLOK + IUP)
+ C2UP = U(2,IBLOK + IUP)
+ VERTD1 = CYUP * (C1UP - C1) - CYDN * (C1 - C1DN)
+ VERTD2 = CYUP * (C2UP - C2) - CYDN * (C2 - C2DN)
+C Set horizontal diffusion and advection terms.
+ ILEFT = -1
+ IF (JX .EQ. 1) ILEFT = 1
+ IRIGHT = 1
+ IF (JX .EQ. MX) IRIGHT = -1
+ C1LT = U(1,IBLOK + ILEFT)
+ C2LT = U(2,IBLOK + ILEFT)
+ C1RT = U(1,IBLOK + IRIGHT)
+ C2RT = U(2,IBLOK + IRIGHT)
+ HORD1 = HDCO * (C1RT - 2.0D0 * C1 + C1LT)
+ HORD2 = HDCO * (C2RT - 2.0D0 * C2 + C2LT)
+ HORAD1 = HACO * (C1RT - C1LT)
+ HORAD2 = HACO * (C2RT - C2LT)
+C Load all terms into UDOT.
+ UDOT(1,IBLOK) = VERTD1 + HORD1 + HORAD1 + RKIN1
+ UDOT(2,IBLOK) = VERTD2 + HORD2 + HORAD2 + RKIN2
+ ENDDO
+ ENDDO
+C
+ IER = 0
+C
+ RETURN
+ END
+
+C ----------------------------------------------------------------
+
+ SUBROUTINE FCVPSET(T, U, FU, JOK, JCUR, GAMMA, H,
+ & IPAR, RPAR, V1, V2, V3, 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
+ DOUBLE PRECISION T, U(2,*), FU(*), GAMMA, H
+ INTEGER*4 IPAR(*)
+ DOUBLE PRECISION RPAR(*), V1(*), V2(*), V3(*)
+C
+ INTEGER*4 MX, MY, MM, P_IPP, P_BD, P_P
+ DOUBLE PRECISION Q1, Q2, Q3, Q4, C3, DY, HDCO, VDCO
+C
+ IER = 0
+C
+C Extract constants from IPAR and RPAR
+ MX = IPAR(1)
+ MY = IPAR(2)
+ MM = IPAR(3)
+C
+ Q1 = RPAR(1)
+ Q2 = RPAR(2)
+ Q3 = RPAR(3)
+ Q4 = RPAR(4)
+ C3 = RPAR(8)
+ DY = RPAR(9)
+ HDCO = RPAR(10)
+ VDCO = RPAR(11)
+C
+C Extract pointers into IPAR and RPAR
+ P_IPP = IPAR(4)
+ P_BD = IPAR(5)
+ P_P = IPAR(6)
+C
+C If needed, recompute BD
+C
+ IF (JOK .EQ. 1) THEN
+C JOK = 1. Reuse saved BD
+ JCUR = 0
+ ELSE
+C JOK = 0. Compute diagonal Jacobian blocks.
+C (using q4 value computed on last FCVFUN call).
+ CALL PREC_JAC(MX, MY, MM, U, RPAR(P_BD),
+ & Q1, Q2, Q3, Q4, C3, DY, HDCO, VDCO)
+ JCUR = 1
+ ENDIF
+C
+C Copy BD to P
+ CALL DCOPY(4*MM, RPAR(P_BD), 1, RPAR(P_P), 1)
+C
+C Scale P by -GAMMA
+ CALL DSCAL(4*MM, -GAMMA, RPAR(P_P), 1)
+C
+C Perform LU decomposition
+ CALL PREC_LU(MM, RPAR(P_P), IPAR(P_IPP), IER)
+C
+ RETURN
+ END
+
+C ----------------------------------------------------------------
+
+ SUBROUTINE FCVPSOL(T, U, FU, R, Z, GAMMA, DELTA, LR,
+ & IPAR, RPAR, VTEMP, IER)
+C Routine to solve preconditioner linear system.
+C
+ IMPLICIT NONE
+C
+ INTEGER IER, LR
+ INTEGER*4 IPAR(*)
+ DOUBLE PRECISION T, U(*), FU(*), R(*), Z(2,*)
+ DOUBLE PRECISION GAMMA, DELTA, RPAR(*)
+ DOUBLE PRECISION VTEMP(*)
+C
+ INTEGER*4 MM, P_IPP, P_P
+C
+ IER = 0
+C
+C Extract constants from IPAR and RPAR
+ MM = IPAR(3)
+C
+C Extract pointers into IPAR and RPAR
+ P_IPP = IPAR(4)
+ P_P = IPAR(6)
+C
+C Copy RHS into Z
+ CALL DCOPY(2*MM, R, 1, Z, 1)
+C
+C Solve the block-diagonal system Px = r using LU factors stored in P
+C and pivot data in IPP, and return the solution in Z.
+ CALL PREC_SOL(MM, RPAR(P_P), IPAR(P_IPP), Z)
+
+ RETURN
+ END
+
+C ----------------------------------------------------------------
+
+ SUBROUTINE PREC_JAC(MX, MY, MM, U, BD,
+ & Q1, Q2, Q3, Q4, C3, DY, HDCO, VDCO)
+C Routine to compute diagonal Jacobian blocks
+C
+ IMPLICIT NONE
+C
+ 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*4 JY, JX, IBLOK, IBLOK0
+ DOUBLE PRECISION C1, C2, CYDN, CYUP, DIAG, YDN, YUP
+C
+ DO JY = 1, MY
+ YDN = 30.0D0 + (JY - 1.5D0) * DY
+ YUP = YDN + DY
+ CYDN = VDCO * EXP(0.2D0 * YDN)
+ CYUP = VDCO * EXP(0.2D0 * YUP)
+ DIAG = -(CYDN + CYUP + 2.0D0 * HDCO)
+ IBLOK0 = (JY - 1) * MX
+ DO JX = 1, MX
+ IBLOK = IBLOK0 + JX
+ C1 = U(1,IBLOK)
+ C2 = U(2,IBLOK)
+ BD(1,1,IBLOK) = (-Q1 * C3 - Q2 * C2) + DIAG
+ BD(1,2,IBLOK) = -Q2 * C1 + Q4
+ BD(2,1,IBLOK) = Q1 * C3 - Q2 * C2
+ BD(2,2,IBLOK) = (-Q2 * C1 - Q4) + DIAG
+ ENDDO
+ ENDDO
+
+ RETURN
+ END
+
+C ----------------------------------------------------------------
+
+ SUBROUTINE PREC_LU(MM, P, IPP, IER)
+C Routine to perform LU decomposition on (P+I)
+C
+ IMPLICIT NONE
+C
+ INTEGER IER
+ INTEGER*4 MM, IPP(2,MM)
+ DOUBLE PRECISION P(2,2,MM)
+C
+ INTEGER*4 I
+C
+C Add identity matrix and do LU decompositions on blocks, in place.
+ DO I = 1, MM
+ P(1,1,I) = P(1,1,I) + 1.0D0
+ P(2,2,I) = P(2,2,I) + 1.0D0
+ CALL DGEFA(P(1,1,I), 2, 2, IPP(1,I), IER)
+ IF (IER .NE. 0) RETURN
+ ENDDO
+C
+ RETURN
+ END
+
+C ----------------------------------------------------------------
+
+ SUBROUTINE PREC_SOL(MM, P, IPP, Z)
+C Routine for backsolve
+C
+ IMPLICIT NONE
+C
+ INTEGER*4 MM, IPP(2,MM)
+ DOUBLE PRECISION P(2,2,MM), Z(2,MM)
+C
+ INTEGER*4 I
+C
+ DO I = 1, MM
+ CALL DGESL(P(1,1,I), 2, 2, IPP(1,I), Z(1,I), 0)
+ ENDDO
+
+ RETURN
+ END
+
+C ----------------------------------------------------------------
+
+ subroutine dgefa(a, lda, n, ipvt, info)
+c
+ implicit none
+c
+ integer info, idamax, j, k, kp1, l, nm1, n
+ integer*4 lda, ipvt(1)
+ double precision a(lda,1), t
+c
+c dgefa factors a double precision matrix by gaussian elimination.
+c
+c dgefa is usually called by dgeco, but it can be called
+c directly with a saving in time if rcond is not needed.
+c (time for dgeco) = (1 + 9/n)*(time for dgefa) .
+c
+c on entry
+c
+c a double precision(lda, n)
+c the matrix to be factored.
+c
+c lda integer
+c the leading dimension of the array a .
+c
+c n integer
+c the order of the matrix a .
+c
+c on return
+c
+c a an upper triangular matrix and the multipliers
+c which were used to obtain it.
+c the factorization can be written a = l*u where
+c l is a product of permutation and unit lower
+c triangular matrices and u is upper triangular.
+c
+c ipvt integer(n)
+c an integer vector of pivot indices.
+c
+c info integer
+c = 0 normal value.
+c = k if u(k,k) .eq. 0.0 . this is not an error
+c condition for this subroutine, but it does
+c indicate that dgesl or dgedi will divide by zero
+c if called. employ rcond in dgeco for a reliable
+c indication of singularity.
+c
+c linpack. this version dated 08/14/78 .
+c cleve moler, university of new mexico, argonne national lab.
+c
+c subroutines and functions
+c
+c blas daxpy,dscal,idamax
+c
+c internal variables
+c
+c gaussian elimination with partial pivoting
+c
+ info = 0
+ nm1 = n - 1
+ if (nm1 .lt. 1) go to 70
+ do 60 k = 1, nm1
+ kp1 = k + 1
+c
+c find l = pivot index
+c
+ l = idamax(n - k + 1, a(k,k), 1) + k - 1
+ ipvt(k) = l
+c
+c zero pivot implies this column already triangularized
+c
+ if (a(l,k) .eq. 0.0d0) go to 40
+c
+c interchange if necessary
+c
+ if (l .eq. k) go to 10
+ t = a(l,k)
+ a(l,k) = a(k,k)
+ a(k,k) = t
+ 10 continue
+c
+c compute multipliers
+c
+ t = -1.0d0 / a(k,k)
+ call dscal(n - k, t, a(k + 1,k), 1)
+c
+c row elimination with column indexing
+c
+ do 30 j = kp1, n
+ t = a(l,j)
+ if (l .eq. k) go to 20
+ a(l,j) = a(k,j)
+ a(k,j) = t
+ 20 continue
+ call daxpy(n - k, t, a(k + 1,k), 1, a(k + 1,j), 1)
+ 30 continue
+ go to 50
+ 40 continue
+ info = k
+ 50 continue
+ 60 continue
+ 70 continue
+ ipvt(n) = n
+ if (a(n,n) .eq. 0.0d0) info = n
+ return
+ end
+
+C ----------------------------------------------------------------
+
+ subroutine dgesl(a, lda, n, ipvt, b, job)
+c
+ implicit none
+c
+ integer lda, n, job, k, kb, l, nm1
+ integer*4 ipvt(1)
+ double precision a(lda,1), b(1), ddot, t
+c
+c dgesl solves the double precision system
+c a * x = b or trans(a) * x = b
+c using the factors computed by dgeco or dgefa.
+c
+c on entry
+c
+c a double precision(lda, n)
+c the output from dgeco or dgefa.
+c
+c lda integer
+c the leading dimension of the array a .
+c
+c n integer
+c the order of the matrix a .
+c
+c ipvt integer(n)
+c the pivot vector from dgeco or dgefa.
+c
+c b double precision(n)
+c the right hand side vector.
+c
+c job integer
+c = 0 to solve a*x = b ,
+c = nonzero to solve trans(a)*x = b where
+c trans(a) is the transpose.
+c
+c on return
+c
+c b the solution vector x .
+c
+c error condition
+c
+c a division by zero will occur if the input factor contains a
+c zero on the diagonal. technically this indicates singularity
+c but it is often caused by improper arguments or improper
+c setting of lda . it will not occur if the subroutines are
+c called correctly and if dgeco has set rcond .gt. 0.0
+c or dgefa has set info .eq. 0 .
+c
+c to compute inverse(a) * c where c is a matrix
+c with p columns
+c call dgeco(a,lda,n,ipvt,rcond,z)
+c if (rcond is too small) go to ...
+c do 10 j = 1, p
+c call dgesl(a,lda,n,ipvt,c(1,j),0)
+c 10 continue
+c
+c linpack. this version dated 08/14/78 .
+c cleve moler, university of new mexico, argonne national lab.
+c
+c subroutines and functions
+c
+c blas daxpy,ddot
+c
+c internal variables
+c
+ nm1 = n - 1
+ if (job .ne. 0) go to 50
+c
+c job = 0 , solve a * x = b
+c first solve l*y = b
+c
+ if (nm1 .lt. 1) go to 30
+ do 20 k = 1, nm1
+ l = ipvt(k)
+ t = b(l)
+ if (l .eq. k) go to 10
+ b(l) = b(k)
+ b(k) = t
+ 10 continue
+ call daxpy(n - k, t, a(k + 1,k), 1, b(k + 1), 1)
+ 20 continue
+ 30 continue
+c
+c now solve u*x = y
+c
+ do 40 kb = 1, n
+ k = n + 1 - kb
+ b(k) = b(k) / a(k,k)
+ t = -b(k)
+ call daxpy(k - 1, t, a(1,k), 1, b(1), 1)
+ 40 continue
+ go to 100
+ 50 continue
+c
+c job = nonzero, solve trans(a) * x = b
+c first solve trans(u)*y = b
+c
+ do 60 k = 1, n
+ t = ddot(k - 1, a(1,k), 1, b(1), 1)
+ b(k) = (b(k) - t) / a(k,k)
+ 60 continue
+c
+c now solve trans(l)*x = y
+c
+ if (nm1 .lt. 1) go to 90
+ do 80 kb = 1, nm1
+ k = n - kb
+ b(k) = b(k) + ddot(n - k, a(k + 1,k), 1, b(k + 1), 1)
+ l = ipvt(k)
+ if (l .eq. k) go to 70
+ t = b(l)
+ b(l) = b(k)
+ b(k) = t
+ 70 continue
+ 80 continue
+ 90 continue
+ 100 continue
+ return
+ end
+
+C ----------------------------------------------------------------
+
+ subroutine daxpy(n, da, dx, incx, dy, incy)
+c
+c constant times a vector plus a vector.
+c uses unrolled loops for increments equal to one.
+c jack dongarra, linpack, 3/11/78.
+c
+ implicit none
+c
+ integer i, incx, incy, ix, iy, m, mp1
+ integer*4 n
+ double precision dx(1), dy(1), da
+c
+ if (n .le. 0) return
+ if (da .eq. 0.0d0) return
+ if (incx .eq. 1 .and. incy .eq. 1) go to 20
+c
+c code for unequal increments or equal increments
+c not equal to 1
+c
+ ix = 1
+ iy = 1
+ if (incx .lt. 0) ix = (-n + 1) * incx + 1
+ if (incy .lt. 0) iy = (-n + 1) * incy + 1
+ do 10 i = 1, n
+ dy(iy) = dy(iy) + da * dx(ix)
+ ix = ix + incx
+ iy = iy + incy
+ 10 continue
+ return
+c
+c code for both increments equal to 1
+c
+c
+c clean-up loop
+c
+ 20 m = mod(n, 4)
+ if ( m .eq. 0 ) go to 40
+ do 30 i = 1, m
+ dy(i) = dy(i) + da * dx(i)
+ 30 continue
+ if ( n .lt. 4 ) return
+ 40 mp1 = m + 1
+ do 50 i = mp1, n, 4
+ dy(i) = dy(i) + da * dx(i)
+ dy(i + 1) = dy(i + 1) + da * dx(i + 1)
+ dy(i + 2) = dy(i + 2) + da * dx(i + 2)
+ dy(i + 3) = dy(i + 3) + da * dx(i + 3)
+ 50 continue
+ return
+ end
+C ----------------------------------------------------------------
+
+ subroutine dscal(n, da, dx, incx)
+c
+c scales a vector by a constant.
+c uses unrolled loops for increment equal to one.
+c jack dongarra, linpack, 3/11/78.
+c
+ implicit none
+c
+ integer i, incx, m, mp1, nincx
+ integer*4 n
+ double precision da, dx(1)
+c
+ if (n.le.0) return
+ if (incx .eq. 1) go to 20
+c
+c code for increment not equal to 1
+c
+ nincx = n * incx
+ do 10 i = 1, nincx, incx
+ dx(i) = da * dx(i)
+ 10 continue
+ return
+c
+c code for increment equal to 1
+c
+c
+c clean-up loop
+c
+ 20 m = mod(n, 5)
+ if ( m .eq. 0 ) go to 40
+ do 30 i = 1, m
+ dx(i) = da * dx(i)
+ 30 continue
+ if ( n .lt. 5 ) return
+ 40 mp1 = m + 1
+ do 50 i = mp1, n, 5
+ dx(i) = da * dx(i)
+ dx(i + 1) = da * dx(i + 1)
+ dx(i + 2) = da * dx(i + 2)
+ dx(i + 3) = da * dx(i + 3)
+ dx(i + 4) = da * dx(i + 4)
+ 50 continue
+ return
+ end
+
+C ----------------------------------------------------------------
+
+ double precision function ddot(n, dx, incx, dy, incy)
+c
+c forms the dot product of two vectors.
+c uses unrolled loops for increments equal to one.
+c jack dongarra, linpack, 3/11/78.
+c
+ implicit none
+c
+ integer i, incx, incy, ix, iy, m, mp1
+ integer*4 n
+ double precision dx(1), dy(1), dtemp
+c
+ ddot = 0.0d0
+ dtemp = 0.0d0
+ if (n .le. 0) return
+ if (incx .eq. 1 .and. incy .eq. 1) go to 20
+c
+c code for unequal increments or equal increments
+c not equal to 1
+c
+ ix = 1
+ iy = 1
+ if (incx .lt. 0) ix = (-n + 1) * incx + 1
+ if (incy .lt. 0) iy = (-n + 1) * incy + 1
+ do 10 i = 1, n
+ dtemp = dtemp + dx(ix) * dy(iy)
+ ix = ix + incx
+ iy = iy + incy
+ 10 continue
+ ddot = dtemp
+ return
+c
+c code for both increments equal to 1
+c
+c
+c clean-up loop
+c
+ 20 m = mod(n, 5)
+ if ( m .eq. 0 ) go to 40
+ do 30 i = 1,m
+ dtemp = dtemp + dx(i) * dy(i)
+ 30 continue
+ if ( n .lt. 5 ) go to 60
+ 40 mp1 = m + 1
+ do 50 i = mp1, n, 5
+ dtemp = dtemp + dx(i) * dy(i) + dx(i + 1) * dy(i + 1) +
+ * dx(i + 2) * dy(i + 2) + dx(i + 3) * dy(i + 3) +
+ * dx(i + 4) * dy(i + 4)
+ 50 continue
+ 60 ddot = dtemp
+ return
+ end
+
+C ----------------------------------------------------------------
+
+ integer function idamax(n, dx, incx)
+c
+c finds the index of element having max. absolute value.
+c jack dongarra, linpack, 3/11/78.
+c
+ implicit none
+c
+ integer i, incx, ix
+ integer*4 n
+ double precision dx(1), dmax
+c
+ idamax = 0
+ if (n .lt. 1) return
+ idamax = 1
+ if (n .eq. 1) return
+ if (incx .eq. 1) go to 20
+c
+c code for increment not equal to 1
+c
+ ix = 1
+ dmax = abs(dx(1))
+ ix = ix + incx
+ do 10 i = 2, n
+ if (abs(dx(ix)) .le. dmax) go to 5
+ idamax = i
+ dmax = abs(dx(ix))
+ 5 ix = ix + incx
+ 10 continue
+ return
+c
+c code for increment equal to 1
+c
+ 20 dmax = abs(dx(1))
+ do 30 i = 2, n
+ if (abs(dx(i)) .le. dmax) go to 30
+ idamax = i
+ dmax = abs(dx(i))
+ 30 continue
+ return
+ end
+
+C ----------------------------------------------------------------
+
+ subroutine dcopy(n, dx, incx, dy, incy)
+c
+c copies a vector, x, to a vector, y.
+c uses unrolled loops for increments equal to one.
+c jack dongarra, linpack, 3/11/78.
+c
+ implicit none
+c
+ integer i, incx, incy, ix, iy, m, mp1
+ integer*4 n
+ double precision dx(1), dy(1)
+c
+ if (n .le. 0) return
+ if (incx .eq. 1 .and. incy .eq. 1) go to 20
+c
+c code for unequal increments or equal increments
+c not equal to 1
+c
+ ix = 1
+ iy = 1
+ if (incx .lt. 0) ix = (-n + 1) * incx + 1
+ if (incy .lt. 0) iy = (-n + 1) * incy + 1
+ do 10 i = 1, n
+ dy(iy) = dx(ix)
+ ix = ix + incx
+ iy = iy + incy
+ 10 continue
+ return
+c
+c code for both increments equal to 1
+c
+c
+c clean-up loop
+c
+ 20 m = mod(n, 7)
+ if ( m .eq. 0 ) go to 40
+ do 30 i = 1, m
+ dy(i) = dx(i)
+ 30 continue
+ if ( n .lt. 7 ) return
+ 40 mp1 = m + 1
+ do 50 i = mp1, n, 7
+ dy(i) = dx(i)
+ dy(i + 1) = dx(i + 1)
+ dy(i + 2) = dx(i + 2)
+ dy(i + 3) = dx(i + 3)
+ dy(i + 4) = dx(i + 4)
+ dy(i + 5) = dx(i + 5)
+ dy(i + 6) = dx(i + 6)
+ 50 continue
+ return
+ end
diff --git a/examples/cvode/fcmix_serial/fcvDiurnal_kry.out b/examples/cvode/fcmix_serial/fcvDiurnal_kry.out
new file mode 100644
index 0000000..499269a
--- /dev/null
+++ b/examples/cvode/fcmix_serial/fcvDiurnal_kry.out
@@ -0,0 +1,63 @@
+Krylov example problem:
+
+ Kinetics-transport, NEQ = 200
+
+
+ t = 0.720E+04 nst = 219 q = 5 h = 0.158696E+03
+ c1 (bot.left/middle/top rt.) = 0.104683E+05 0.296373E+05 0.111853E+05
+ c2 (bot.left/middle/top rt.) = 0.252672E+12 0.715376E+12 0.269977E+12
+
+ t = 0.144E+05 nst = 251 q = 5 h = 0.377205E+03
+ 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
+ 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
+ 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
+ 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
+
+ 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
+ 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.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.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
+ 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.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.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
+
+
+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 conv. failures.. nonlinear = 0 linear = 0
+ number of error test failures = 34
diff --git a/examples/cvode/fcmix_serial/fcvDiurnal_kry_bp.f b/examples/cvode/fcmix_serial/fcvDiurnal_kry_bp.f
new file mode 100644
index 0000000..77fc17f
--- /dev/null
+++ b/examples/cvode/fcmix_serial/fcvDiurnal_kry_bp.f
@@ -0,0 +1,343 @@
+C ----------------------------------------------------------------
+C $Revision: 1.1 $
+C $Date: 2007/10/25 20:03:27 $
+C ----------------------------------------------------------------
+C FCVODE Example Problem: 2D kinetics-transport,
+C precond. Krylov solver.
+C
+C An ODE system is generated from the following 2-species diurnal
+C kinetics advection-diffusion PDE system in 2 space dimensions:
+C
+C dc(i)/dt = Kh*(d/dx)**2 c(i) + V*dc(i)/dx + (d/dy)(Kv(y)*dc(i)/dy)
+C + Ri(c1,c2,t) for i = 1,2, where
+C R1(c1,c2,t) = -q1*c1*c3 - q2*c1*c2 + 2*q3(t)*c3 + q4(t)*c2 ,
+C R2(c1,c2,t) = q1*c1*c3 - q2*c1*c2 - q4(t)*c2 ,
+C Kv(y) = Kv0*exp(y/5) ,
+C Kh, V, Kv0, q1, q2, and c3 are constants, and q3(t) and q4(t)
+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
+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
+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 ----------------------------------------------------------------
+C
+ IMPLICIT NONE
+C
+ INTEGER*4 MX, MY, NEQ
+ PARAMETER (MX=10, MY=10)
+ PARAMETER (NEQ=2*MX*MY)
+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 IOUT(25), IPAR(4)
+ INTEGER*4 NST, NFE, NPSET, NPE, NPS, NNI
+ INTEGER*4 NLI, NCFN, NCFL, NETF, MU, ML
+ INTEGER*4 LENRW, LENIW, LENRWLS, LENIWLS, LENRWBP, LENIWBP, NFEBP
+ DOUBLE PRECISION ATOL, AVDIM, DELT, FLOOR, RTOL, T, TOUT, TWOHR
+ DOUBLE PRECISION ROUT(10), U(2,MX,MY), RPAR(12)
+C
+ DATA TWOHR/7200.0D0/, RTOL/1.0D-5/, FLOOR/100.0D0/,
+ 1 JPRETYPE/1/, IGSTYPE/1/, MAXL/0/, DELT/0.0D0/
+ DATA LLENRW/1/, LLENIW/2/, LNST/3/, LNFE/4/, LNETF/5/, LNCF/6/,
+ 1 LNNI/7/, LNSETUP/8/, LQ/9/, LLENRWLS/13/, LLENIWLS/14/,
+ 1 LNPE/18/, LNLI/20/, LNPS/19/, LNCFL/21/
+ DATA LH/2/
+C
+C Load IPAR, RPAR, and initial values
+ CALL INITKX(MX, MY, U, IPAR, RPAR)
+C
+C Set other input arguments.
+ T = 0.0D0
+ METH = 2
+ ITMETH = 2
+ IATOL = 1
+ ATOL = RTOL * FLOOR
+ ITASK = 1
+C
+ WRITE(6,10) NEQ
+ 10 FORMAT('Krylov example problem:'//
+ 1 ' Kinetics-transport, NEQ = ', I4/)
+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
+ 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
+ ENDIF
+C
+C Initialize SPGMR solver
+ CALL FCVSPGMR(JPRETYPE, IGSTYPE, MAXL, DELT, IER)
+ IF (IER .NE. 0) THEN
+ WRITE(6,45) IER
+ 45 FORMAT(///' SUNDIALS_ERROR: FCVSPGMR returned IER = ', I5)
+ CALL FCVFREE
+ STOP
+ ENDIF
+C
+C Initialize band preconditioner
+ MU = 2
+ 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)
+ CALL FCVFREE
+ STOP
+ ENDIF
+C
+C Loop over output points, call FCVODE, print sample solution values.
+ TOUT = TWOHR
+ DO 70 JOUT = 1, 12
+C
+ CALL FCVODE(TOUT, T, U, ITASK, IER)
+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)
+ 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
+ IF (IER .NE. 0) THEN
+ WRITE(6,60) IER, IOUT(15)
+ 60 FORMAT(///' SUNDIALS_ERROR: FCVODE returned IER = ', I5, /,
+ 1 ' Linear Solver returned IER = ', I5)
+ CALL FCVFREE
+ STOP
+ ENDIF
+C
+ TOUT = TOUT + TWOHR
+ 70 CONTINUE
+
+C Print final statistics.
+ NST = IOUT(LNST)
+ NFE = IOUT(LNFE)
+ NPSET = IOUT(LNSETUP)
+ NPE = IOUT(LNPE)
+ NPS = IOUT(LNPS)
+ NNI = IOUT(LNNI)
+ NLI = IOUT(LNLI)
+ AVDIM = DBLE(NLI) / DBLE(NNI)
+ NCFN = IOUT(LNCF)
+ NCFL = IOUT(LNCFL)
+ NETF = IOUT(LNETF)
+ LENRW = IOUT(LLENRW)
+ LENIW = IOUT(LLENIW)
+ LENRWLS = IOUT(LLENRWLS)
+ LENIWLS = IOUT(LLENIWLS)
+ WRITE(6,80) NST, NFE, NPSET, NPE, NPS, NNI, NLI, AVDIM, NCFN,
+ 1 NCFL, NETF, LENRW, LENIW, LENRWLS, LENIWLS
+ 80 FORMAT(//'Final statistics:'//
+ & ' number of steps = ', I5, 4X,
+ & ' number of f evals. = ', I5/
+ & ' number of prec. setups = ', I5/
+ & ' number of prec. evals. = ', I5, 4X,
+ & ' number of prec. solves = ', I5/
+ & ' number of nonl. iters. = ', I5, 4X,
+ & ' number of lin. iters. = ', I5/
+ & ' average Krylov subspace dimension (NLI/NNI) = ', E14.6/
+ & ' number of conv. failures.. nonlinear =', I3,
+ & ' linear = ', I3/
+ & ' number of error test failures = ', I3/
+ & ' main solver real/int workspace sizes = ',2I5/
+ & ' linear solver real/int workspace sizes = ',2I5)
+ CALL FCVBPOPT(LENRWBP, LENIWBP, NFEBP)
+ WRITE(6,82) LENRWBP, LENIWBP, NFEBP
+ 82 FORMAT('In CVBANDPRE:'/
+ & ' real/int workspace sizes = ', 2I5/
+ & ' number of f evaluations = ', I5)
+C
+ CALL FCVFREE
+C
+ STOP
+ END
+
+C ----------------------------------------------------------------
+
+ SUBROUTINE INITKX(MX, MY, U0, IPAR, RPAR)
+C Routine to set problem constants and initial values
+C
+ IMPLICIT NONE
+C
+ INTEGER*4 MX, MY, IPAR(*)
+ DOUBLE PRECISION RPAR(*)
+C
+ INTEGER*4 MM, JY, JX, NEQ
+ DOUBLE PRECISION U0
+ DIMENSION U0(2,MX,MY)
+ DOUBLE PRECISION Q1, Q2, Q3, Q4, A3, A4, OM, C3, DY, HDCO
+ DOUBLE PRECISION VDCO, HACO, X, Y
+ DOUBLE PRECISION CX, CY, DKH, DKV0, DX, HALFDA, PI, VEL
+C
+ DATA DKH/4.0D-6/, VEL/0.001D0/, DKV0/1.0D-8/, HALFDA/4.32D4/,
+ 1 PI/3.1415926535898D0/
+C
+C Problem constants
+ MM = MX * MY
+ NEQ = 2 * MM
+ Q1 = 1.63D-16
+ Q2 = 4.66D-16
+ A3 = 22.62D0
+ A4 = 7.601D0
+ OM = PI / HALFDA
+ C3 = 3.7D16
+ DX = 20.0D0 / (MX - 1.0D0)
+ DY = 20.0D0 / (MY - 1.0D0)
+ HDCO = DKH / DX**2
+ HACO = VEL / (2.0D0 * DX)
+ VDCO = (1.0D0 / DY**2) * DKV0
+C Load constants in IPAR and RPAR
+ IPAR(1) = MX
+ IPAR(2) = MY
+ IPAR(3) = MM
+ IPAR(4) = NEQ
+C
+ RPAR(1) = Q1
+ RPAR(2) = Q2
+ RPAR(3) = Q3
+ RPAR(4) = Q4
+ RPAR(5) = A3
+ RPAR(6) = A4
+ RPAR(7) = OM
+ RPAR(8) = C3
+ RPAR(9) = DY
+ RPAR(10) = HDCO
+ RPAR(11) = VDCO
+ RPAR(12) = HACO
+C
+C Set initial profiles.
+ DO 20 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 10 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
+ 10 CONTINUE
+ 20 CONTINUE
+C
+ RETURN
+ END
+
+C ----------------------------------------------------------------
+
+ SUBROUTINE FCVFUN(T, U, UDOT, IPAR, RPAR, IER)
+C Routine for right-hand side function f
+ IMPLICIT NONE
+C
+ INTEGER*4 IPAR(*), IER
+ DOUBLE PRECISION T, U(2,*), UDOT(2,*), RPAR(*)
+C
+ INTEGER ILEFT, IRIGHT
+ INTEGER*4 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
+ DOUBLE PRECISION HORAD2, QQ1, QQ2, QQ3, QQ4, RKIN1, RKIN2, S
+ DOUBLE PRECISION VERTD1, VERTD2, YDN, YUP
+C
+C Extract constants from IPAR and RPAR
+ MX = IPAR(1)
+ MY = IPAR(2)
+ MM = IPAR(3)
+C
+ Q1 = RPAR(1)
+ Q2 = RPAR(2)
+ Q3 = RPAR(3)
+ Q4 = RPAR(4)
+ A3 = RPAR(5)
+ A4 = RPAR(6)
+ OM = RPAR(7)
+ C3 = RPAR(8)
+ DY = RPAR(9)
+ HDCO = RPAR(10)
+ VDCO = RPAR(11)
+ HACO = RPAR(12)
+C
+C Set diurnal rate coefficients.
+ S = SIN(OM * T)
+ IF (S .GT. 0.0D0) THEN
+ Q3 = EXP(-A3 / S)
+ Q4 = EXP(-A4 / S)
+ ELSE
+ Q3 = 0.0D0
+ Q4 = 0.0D0
+ ENDIF
+C
+C Loop over all grid points.
+ DO 20 JY = 1, MY
+ YDN = 30.0D0 + (JY - 1.5D0) * DY
+ YUP = YDN + DY
+ CYDN = VDCO * EXP(0.2D0 * YDN)
+ CYUP = VDCO * EXP(0.2D0 * YUP)
+ IBLOK0 = (JY - 1) * MX
+ IDN = -MX
+ IF (JY .EQ. 1) IDN = MX
+ IUP = MX
+ IF (JY .EQ. MY) IUP = -MX
+ DO 10 JX = 1, MX
+ IBLOK = IBLOK0 + JX
+ C1 = U(1,IBLOK)
+ C2 = U(2,IBLOK)
+C Set kinetic rate terms.
+ QQ1 = Q1 * C1 * C3
+ QQ2 = Q2 * C1 * C2
+ QQ3 = Q3 * C3
+ QQ4 = Q4 * C2
+ RKIN1 = -QQ1 - QQ2 + 2.0D0 * QQ3 + QQ4
+ RKIN2 = QQ1 - QQ2 - QQ4
+C Set vertical diffusion terms.
+ C1DN = U(1,IBLOK + IDN)
+ C2DN = U(2,IBLOK + IDN)
+ C1UP = U(1,IBLOK + IUP)
+ C2UP = U(2,IBLOK + IUP)
+ VERTD1 = CYUP * (C1UP - C1) - CYDN * (C1 - C1DN)
+ VERTD2 = CYUP * (C2UP - C2) - CYDN * (C2 - C2DN)
+C Set horizontal diffusion and advection terms.
+ ILEFT = -1
+ IF (JX .EQ. 1) ILEFT = 1
+ IRIGHT = 1
+ IF (JX .EQ. MX) IRIGHT = -1
+ C1LT = U(1,IBLOK + ILEFT)
+ C2LT = U(2,IBLOK + ILEFT)
+ C1RT = U(1,IBLOK + IRIGHT)
+ C2RT = U(2,IBLOK + IRIGHT)
+ HORD1 = HDCO * (C1RT - 2.0D0 * C1 + C1LT)
+ HORD2 = HDCO * (C2RT - 2.0D0 * C2 + C2LT)
+ HORAD1 = HACO * (C1RT - C1LT)
+ HORAD2 = HACO * (C2RT - C2LT)
+C Load all terms into UDOT.
+ UDOT(1,IBLOK) = VERTD1 + HORD1 + HORAD1 + RKIN1
+ UDOT(2,IBLOK) = VERTD2 + HORD2 + HORAD2 + RKIN2
+ 10 CONTINUE
+ 20 CONTINUE
+C
+ IER = 0
+C
+ RETURN
+ END
diff --git a/examples/cvode/fcmix_serial/fcvDiurnal_kry_bp.out b/examples/cvode/fcmix_serial/fcvDiurnal_kry_bp.out
new file mode 100644
index 0000000..f03ea46
--- /dev/null
+++ b/examples/cvode/fcmix_serial/fcvDiurnal_kry_bp.out
@@ -0,0 +1,68 @@
+Krylov example problem:
+
+ Kinetics-transport, NEQ = 200
+
+
+ t = 0.720000E+04 no. steps = 190 order = 5 stepsize = 0.160965E+03
+ c1 (bot.left/middle/top rt.) = 0.104683E+05 0.296373E+05 0.111853E+05
+ c2 (bot.left/middle/top rt.) = 0.252672E+12 0.715377E+12 0.269977E+12
+
+ t = 0.144000E+05 no. steps = 221 order = 5 stepsize = 0.382687E+03
+ 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.216000E+05 no. steps = 246 order = 5 stepsize = 0.278111E+03
+ c1 (bot.left/middle/top rt.) = 0.266497E+08 0.103640E+08 0.293077E+08
+ c2 (bot.left/middle/top rt.) = 0.299279E+12 0.102815E+12 0.331344E+12
+
+ t = 0.288000E+05 no. steps = 291 order = 4 stepsize = 0.113513E+03
+ c1 (bot.left/middle/top rt.) = 0.870208E+07 0.129196E+08 0.965001E+07
+ c2 (bot.left/middle/top rt.) = 0.338035E+12 0.502927E+12 0.375095E+12
+
+ t = 0.360000E+05 no. steps = 331 order = 4 stepsize = 0.885814E+02
+ c1 (bot.left/middle/top rt.) = 0.140403E+05 0.202899E+05 0.156090E+05
+ c2 (bot.left/middle/top rt.) = 0.338677E+12 0.489432E+12 0.376516E+12
+
+ t = 0.432000E+05 no. steps = 402 order = 4 stepsize = 0.415260E+03
+ c1 (bot.left/middle/top rt.) = -0.576856E-08 0.342117E-08 -0.386627E-08
+ c2 (bot.left/middle/top rt.) = 0.338232E+12 0.135500E+12 0.380352E+12
+
+ t = 0.504000E+05 no. steps = 415 order = 5 stepsize = 0.457901E+03
+ c1 (bot.left/middle/top rt.) = -0.497941E-17 -0.719339E-14 -0.265325E-14
+ c2 (bot.left/middle/top rt.) = 0.335816E+12 0.493026E+12 0.386444E+12
+
+ t = 0.576000E+05 no. steps = 430 order = 4 stepsize = 0.219223E+03
+ c1 (bot.left/middle/top rt.) = 0.161106E-16 0.458698E-15 -0.470389E-17
+ c2 (bot.left/middle/top rt.) = 0.332031E+12 0.964973E+12 0.390899E+12
+
+ t = 0.648000E+05 no. steps = 444 order = 4 stepsize = 0.579451E+03
+ c1 (bot.left/middle/top rt.) = 0.950457E-15 0.115369E-13 -0.231605E-15
+ c2 (bot.left/middle/top rt.) = 0.331302E+12 0.892177E+12 0.396342E+12
+
+ t = 0.720000E+05 no. steps = 457 order = 4 stepsize = 0.579451E+03
+ c1 (bot.left/middle/top rt.) = 0.390973E-15 -0.484816E-13 0.254545E-14
+ c2 (bot.left/middle/top rt.) = 0.332972E+12 0.618613E+12 0.403884E+12
+
+ t = 0.792000E+05 no. steps = 469 order = 4 stepsize = 0.579451E+03
+ c1 (bot.left/middle/top rt.) = -0.290314E-14 0.215229E-12 0.355073E-15
+ c2 (bot.left/middle/top rt.) = 0.333440E+12 0.666885E+12 0.412026E+12
+
+ t = 0.864000E+05 no. steps = 481 order = 4 stepsize = 0.579451E+03
+ c1 (bot.left/middle/top rt.) = 0.235825E-22 0.231595E-17 -0.600745E-15
+ c2 (bot.left/middle/top rt.) = 0.335178E+12 0.910810E+12 0.416250E+12
+
+
+Final statistics:
+
+ number of steps = 481 number of f evals. = 620
+ number of prec. setups = 88
+ number of prec. evals. = 9 number of prec. solves = 1096
+ number of nonl. iters. = 616 number of lin. iters. = 561
+ average Krylov subspace dimension (NLI/NNI) = 0.910714E+00
+ 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
+In CVBANDPRE:
+ real/int workspace sizes = 2400 200
+ number of f evaluations = 45
diff --git a/examples/cvode/fcmix_serial/fcvRoberts_dns.f b/examples/cvode/fcmix_serial/fcvRoberts_dns.f
new file mode 100644
index 0000000..d317b84
--- /dev/null
+++ b/examples/cvode/fcmix_serial/fcvRoberts_dns.f
@@ -0,0 +1,227 @@
+C ----------------------------------------------------------------
+C $Revision: 1.1 $
+C $Date: 2007/10/25 20:03:27 $
+C ----------------------------------------------------------------
+C FCVODE Example Problem: Robertson kinetics, 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
+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 and a user-supplied
+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
+ 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 IOUT(25), IPAR
+ INTEGER*4 NEQ
+ 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/,
+ 1 LNGE/12/, LNJE/17/
+C
+ NEQ = 3
+ T0 = 0.0D0
+ Y(1) = 1.0D0
+ Y(2) = 0.0D0
+ Y(3) = 0.0D0
+ METH = 2
+ ITMETH = 2
+ ITOL = 2
+ RTOL = 1.0D-4
+ ATOL(1) = 1.0D-8
+ ATOL(2) = 1.0D-14
+ ATOL(3) = 1.0D-6
+ TOUT = 0.4D0
+ ITASK = 1
+ JOUT = 0
+ NOUT = 12
+C
+ WRITE(6,10) NEQ
+ 10 FORMAT('Dense example problem:'//
+ 1 ' Robertson kinetics, NEQ = ', I2//)
+C
+ 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
+
+ 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
+ ENDIF
+C
+
+ CALL FCVROOTINIT(2, IER)
+ IF (IER .NE. 0) THEN
+ WRITE(6,45) IER
+ 45 FORMAT(///' SUNDIALS_ERROR: FCVROOTINIT returned IER = ', I5)
+ CALL FCVFREE
+ STOP
+ ENDIF
+C
+ CALL FCVDENSE(NEQ, IER)
+ IF (IER .NE. 0) THEN
+ WRITE(6,40) IER
+ 40 FORMAT(///' SUNDIALS_ERROR: FCVDENSE returned IER = ', I5)
+ CALL FCVFREE
+ STOP
+ ENDIF
+C
+ CALL FCVDENSESETJAC(1, IER)
+C
+ DO WHILE(JOUT .LT. NOUT)
+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) IER
+ 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
+ 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
+ ENDIF
+ WRITE(6,85) Y(1), Y(2), Y(3)
+ 85 FORMAT(/'Final value of ydot = ', 3E14.6)
+C
+ 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/
+ 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)
+C Fortran routine for right-hand side function.
+ IMPLICIT NONE
+C
+ INTEGER*4 IPAR(*), 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)
+C Fortran routine for root finding
+ IMPLICIT NONE
+C
+ DOUBLE PRECISION T, Y(*), G(*), RPAR(*)
+ INTEGER*4 IPAR(*), IER
+C
+ G(1) = Y(1) - 1.0D-4
+ G(2) = Y(3) - 1.0D-2
+C
+ IER = 0
+
+ RETURN
+ END
+
+C ----------------------------------------------------------------
+
+ SUBROUTINE FCVDJAC(N, T, Y, FY, JAC, H, IPAR, RPAR,
+ 1 V1, V2, V3, IER)
+C Fortran routine for dense user-supplied Jacobian.
+ IMPLICIT NONE
+C
+ INTEGER*4 N, IPAR(*), IER
+ DOUBLE PRECISION T, Y(*), FY(*), JAC(N,*), H, RPAR(*)
+ DOUBLE PRECISION V1(*), V2(*), V3(*)
+C
+ DOUBLE PRECISION Y1, Y2, Y3
+C
+ Y1 = Y(1)
+ Y2 = Y(2)
+ Y3 = Y(3)
+ JAC(1,1) = -0.04D0
+ JAC(1,2) = 1.0D4 * Y3
+ JAC(1,3) = 1.0D4 * Y2
+ JAC(2,1) = 0.04D0
+ JAC(2,2) = -1.0D4 * Y3 - 6.0D7 * Y2
+ JAC(2,3) = -1.0D4 * Y2
+ JAC(3,2) = 6.0D7 * Y2
+C
+ IER = 0
+C
+ RETURN
+ END
diff --git a/examples/cvode/fcmix_serial/fcvRoberts_dns.out b/examples/cvode/fcmix_serial/fcvRoberts_dns.out
new file mode 100644
index 0000000..e17fe74
--- /dev/null
+++ b/examples/cvode/fcmix_serial/fcvRoberts_dns.out
@@ -0,0 +1,32 @@
+Dense example problem:
+
+ Robertson kinetics, NEQ = 3
+
+
+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
+ 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
+
+Final value of ydot = -0.304816E-17 -0.121927E-22 0.304818E-17
+
+
+Final statistics:
+
+ No. steps = 579 No. f-s = 817 No. J-s = 12 No. LU-s = 118
+ No. nonlinear iterations = 813
+ No. nonlinear convergence failures = 0
+ No. error test failures = 31
+ No. root function evals = 615
diff --git a/examples/cvode/fcmix_serial/fcvRoberts_dnsL.f b/examples/cvode/fcmix_serial/fcvRoberts_dnsL.f
new file mode 100644
index 0000000..cf66916
--- /dev/null
+++ b/examples/cvode/fcmix_serial/fcvRoberts_dnsL.f
@@ -0,0 +1,231 @@
+C ----------------------------------------------------------------
+C $Revision: 1.1 $
+C $Date: 2007/10/25 20:03:27 $
+C ----------------------------------------------------------------
+C FCVODE Example Problem: Robertson kinetics, Lapack 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
+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 employ 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
+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
+ 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 IOUT(25), IPAR
+ INTEGER NEQ
+ 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/,
+ 1 LNGE/12/, LNJE/17/
+C
+ NEQ = 3
+ T0 = 0.0D0
+ Y(1) = 1.0D0
+ Y(2) = 0.0D0
+ Y(3) = 0.0D0
+ METH = 2
+ ITMETH = 2
+ ITOL = 2
+ RTOL = 1.0D-4
+ ATOL(1) = 1.0D-8
+ ATOL(2) = 1.0D-14
+ ATOL(3) = 1.0D-6
+ TOUT = 0.4D0
+ ITASK = 1
+ JOUT = 0
+ NOUT = 12
+C
+ WRITE(6,10) NEQ
+ 10 FORMAT('Dense example problem:'//
+ 1 ' Robertson kinetics, NEQ = ', I2//)
+C
+ 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
+
+ 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
+ ENDIF
+C
+
+ CALL FCVROOTINIT(2, IER)
+ IF (IER .NE. 0) THEN
+ WRITE(6,45) IER
+ 45 FORMAT(///' SUNDIALS_ERROR: FCVROOTINIT returned IER = ', I5)
+ CALL FCVFREE
+ STOP
+ ENDIF
+C
+ CALL FCVLAPACKDENSE(NEQ, IER)
+ IF (IER .NE. 0) THEN
+ WRITE(6,40) IER
+ 40 FORMAT(///' SUNDIALS_ERROR: FCVLAPACKDENSE returned IER = ', I5)
+ CALL FCVFREE
+ STOP
+ ENDIF
+C
+ CALL FCVLAPACKDENSESETJAC(1, IER)
+C
+ DO WHILE(JOUT .LT. NOUT)
+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) IER
+ 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
+ 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
+ ENDIF
+ WRITE(6,85) Y(1), Y(2), Y(3)
+ 85 FORMAT(/'Final value of ydot = ', 3E14.6)
+C
+ 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/
+ 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)
+C Fortran routine for right-hand side function.
+ IMPLICIT NONE
+C
+ INTEGER*4 IPAR(*), 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)
+C Fortran routine for root finding
+ IMPLICIT NONE
+C
+ DOUBLE PRECISION T, Y(*), G(*), RPAR(*)
+ INTEGER*4 IPAR(*), IER
+C
+ G(1) = Y(1) - 1.0D-4
+ G(2) = Y(3) - 1.0D-2
+C
+ IER = 0
+
+ RETURN
+ END
+
+C ----------------------------------------------------------------
+
+ SUBROUTINE FCVDJAC(N, T, Y, FY, JAC, H, IPAR, RPAR,
+ 1 V1, V2, V3, IER)
+C Fortran routine for dense user-supplied Jacobian.
+ IMPLICIT NONE
+C
+ INTEGER N, IER
+ INTEGER*4 IPAR(*)
+ DOUBLE PRECISION T, Y(*), FY(*), JAC(N,*), H, RPAR(*)
+ DOUBLE PRECISION V1(*), V2(*), V3(*)
+C
+ DOUBLE PRECISION Y1, Y2, Y3
+C
+ Y1 = Y(1)
+ Y2 = Y(2)
+ Y3 = Y(3)
+ JAC(1,1) = -0.04D0
+ JAC(1,2) = 1.0D4 * Y3
+ JAC(1,3) = 1.0D4 * Y2
+ 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
+ RETURN
+ END
diff --git a/examples/cvode/fcmix_serial/fcvRoberts_dnsL.out b/examples/cvode/fcmix_serial/fcvRoberts_dnsL.out
new file mode 100644
index 0000000..b4cd08a
--- /dev/null
+++ b/examples/cvode/fcmix_serial/fcvRoberts_dnsL.out
@@ -0,0 +1,32 @@
+Dense example problem:
+
+ Robertson kinetics, NEQ = 3
+
+
+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
+ 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
+
+Final value of ydot = -0.227814E-17 -0.911257E-23 0.227815E-17
+
+
+Final statistics:
+
+ No. steps = 577 No. f-s = 838 No. J-s = 12 No. LU-s = 125
+ No. nonlinear iterations = 834
+ No. nonlinear convergence failures = 0
+ No. error test failures = 33
+ No. root function evals = 612
diff --git a/examples/cvode/parallel/CMakeLists.txt b/examples/cvode/parallel/CMakeLists.txt
new file mode 100644
index 0000000..1e7a123
--- /dev/null
+++ b/examples/cvode/parallel/CMakeLists.txt
@@ -0,0 +1,113 @@
+# ---------------------------------------------------------------
+# $Revision: 1.4 $
+# $Date: 2009/02/17 02:58:47 $
+# ---------------------------------------------------------------
+# Programmer: Radu Serban @ LLNL
+# ---------------------------------------------------------------
+# Copyright (c) 2007, The Regents of the University of California.
+# Produced at the Lawrence Livermore National Laboratory.
+# All rights reserved.
+# For details, see the LICENSE file.
+# ---------------------------------------------------------------
+# CMakeLists.txt file for CVODE parallel examples
+
+
+# Add variable CVODE_examples with the names of the parallel CVODE examples
+
+SET(CVODE_examples
+ cvAdvDiff_non_p
+ cvDiurnal_kry_bbd_p
+ cvDiurnal_kry_p
+ )
+
+# 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)
+ # add MPI_INCLUDE_PATH to include directories
+ INCLUDE_DIRECTORIES(${MPI_INCLUDE_PATH})
+ENDIF(MPI_MPICC)
+
+# 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")
+ SET(CVODE_LIB sundials_cvode_shared)
+ SET(NVECP_LIB sundials_nvecparallel_shared)
+ENDIF(LINK_LIBRARY_TYPE MATCHES "static")
+
+# Set-up linker flags and link libraries
+
+SET(SUNDIALS_LIBS ${CVODE_LIB} ${NVECP_LIB} ${EXTRA_LINK_LIBS})
+IF(LAPACK_FOUND)
+ SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${LAPACK_LINKER_FLAGS}")
+ SET(SUNDIALS_LIBS "${SUNDIALS_LIBS} ${LAPACK_LIBRARIES}")
+ENDIF(LAPACK_FOUND)
+
+# Add the build and install targets for each CVODE example
+
+FOREACH(example ${CVODE_examples})
+ ADD_EXECUTABLE(${example} ${example}.c)
+ TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+ IF(NOT MPI_MPICC)
+ TARGET_LINK_LIBRARIES(${example} ${MPI_LIBRARY} ${MPI_EXTRA_LIBRARIES})
+ ENDIF(NOT MPI_MPICC)
+ IF(EXAMPLES_INSTALL)
+ INSTALL(FILES ${example}.c ${example}.out DESTINATION ${EXAMPLES_INSTALL_PATH}/cvode/parallel)
+ ENDIF(EXAMPLES_INSTALL)
+ENDFOREACH(example ${CVODE_examples})
+
+IF(EXAMPLES_INSTALL)
+
+ # Install the README file
+ INSTALL(FILES README DESTINATION ${EXAMPLES_INSTALL_PATH}/cvode/parallel)
+
+ # Prepare substitution variables for Makefile and/or CMakeLists templates
+ SET(SOLVER "CVODE")
+ SET(SOLVER_LIB "sundials_cvode")
+ LIST2STRING(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_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
+ )
+
+ # 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/cvode/parallel/Makefile_ex
+ @ONLY
+ )
+ # install the configured Makefile_ex as Makefile
+ INSTALL(
+ FILES ${PROJECT_BINARY_DIR}/examples/cvode/parallel/Makefile_ex
+ DESTINATION ${EXAMPLES_INSTALL_PATH}/cvode/parallel
+ RENAME Makefile
+ )
+ ENDIF(UNIX)
+
+ENDIF(EXAMPLES_INSTALL)
diff --git a/examples/cvode/parallel/Makefile.in b/examples/cvode/parallel/Makefile.in
new file mode 100644
index 0000000..20668fa
--- /dev/null
+++ b/examples/cvode/parallel/Makefile.in
@@ -0,0 +1,113 @@
+# -----------------------------------------------------------------
+# $Revision: 1.9 $
+# $Date: 2009/02/17 02:58:47 $
+# -----------------------------------------------------------------
+# Programmer(s): Radu Serban and Aaron Collier @ LLNL
+# -----------------------------------------------------------------
+# Copyright (c) 2002, The Regents of the University of California.
+# Produced at the Lawrence Livermore National Laboratory.
+# All rights reserved.
+# For details, see the LICENSE file.
+# -----------------------------------------------------------------
+# Makefile for CVODE parallel examples
+#
+# @configure_input@
+# -----------------------------------------------------------------
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_builddir = @top_builddir@
+builddir = @builddir@
+abs_builddir = @abs_builddir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+includedir = @includedir@
+libdir = @libdir@
+
+INSTALL = @INSTALL@
+INSTALL_PROG = @INSTALL_PROGRAM@
+INSTALL_FILE = @INSTALL_DATA@
+
+LIBTOOL = @LIBTOOL@
+LIBTOOL_DEPS = @LIBTOOL_DEPS@
+
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CC = @CC@
+CFLAGS = @CFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+MPICC = @MPICC@
+MPI_INC_DIR = @MPI_INC_DIR@
+MPI_LIB_DIR = @MPI_LIB_DIR@
+MPI_LIBS = @MPI_LIBS@
+MPI_FLAGS = @MPI_FLAGS@
+
+BLAS_LAPACK_LIBS = @BLAS_LAPACK_LIBS@
+
+OBJ_EXT = @OBJEXT@
+EXE_EXT = @EXEEXT@
+
+EXS_INSTDIR = @EXS_INSTDIR@
+
+top_srcdir = $(srcdir)/../../..
+
+SUNDIALS_INCS = -I$(top_srcdir)/include -I$(top_builddir)/include
+
+SUNDIALS_LIBS = $(top_builddir)/src/cvode/libsundials_cvode.la $(top_builddir)/src/nvec_par/libsundials_nvecparallel.la
+
+mkinstalldirs = $(SHELL) $(top_srcdir)/config/mkinstalldirs
+rminstalldirs = $(SHELL) $(top_srcdir)/config/rminstalldirs
+
+
+EXAMPLES = cvAdvDiff_non_p \
+ cvDiurnal_kry_bbd_p \
+ cvDiurnal_kry_p
+
+OBJECTS = ${EXAMPLES:=${OBJ_EXT}}
+EXECS = ${EXAMPLES:=${EXE_EXT}}
+
+# ----------------------------------------------------------------------------------------------------------------------
+
+all:
+ @for i in ${EXAMPLES} ; do \
+ $(LIBTOOL) --mode=compile $(MPICC) $(CPPFLAGS) $(MPI_FLAGS) $(SUNDIALS_INCS) -I$(MPI_INC_DIR) $(CFLAGS) -c $(srcdir)/$${i}.c -o $${i}${OBJ_EXT} ; \
+ $(LIBTOOL) --mode=link $(MPICC) -o $(builddir)/$${i}$(EXE_EXT) $(builddir)/$${i}$(OBJ_EXT) $(MPI_FLAGS) $(CFLAGS) $(LDFLAGS) $(SUNDIALS_LIBS) -L$(MPI_LIB_DIR) $(MPI_LIBS) $(LIBS) $(BLAS_LAPACK_LIBS) ; \
+ done
+
+install:
+ $(mkinstalldirs) $(EXS_INSTDIR)/cvode/parallel
+ $(INSTALL_FILE) Makefile_ex $(EXS_INSTDIR)/cvode/parallel/Makefile
+ $(INSTALL_FILE) $(top_srcdir)/examples/cvode/parallel/README $(EXS_INSTDIR)/cvode/parallel/
+ for i in ${EXAMPLES} ; do \
+ $(INSTALL_FILE) $(top_srcdir)/examples/cvode/parallel/$${i}.c $(EXS_INSTDIR)/cvode/parallel/ ; \
+ $(INSTALL_FILE) $(top_srcdir)/examples/cvode/parallel/$${i}.out $(EXS_INSTDIR)/cvode/parallel/ ; \
+ done
+
+uninstall:
+ rm -f $(EXS_INSTDIR)/cvode/parallel/Makefile
+ rm -f $(EXS_INSTDIR)/cvode/parallel/README
+ for i in ${EXAMPLES} ; do \
+ rm -f $(EXS_INSTDIR)/cvode/parallel/$${i}.c ; \
+ rm -f $(EXS_INSTDIR)/cvode/parallel/$${i}.out ; \
+ done
+ $(rminstalldirs) $(EXS_INSTDIR)/cvode/parallel
+ $(rminstalldirs) $(EXS_INSTDIR)/cvode
+
+clean:
+ rm -rf .libs
+ rm -f *.lo *.o
+ rm -f ${OBJECTS}
+ rm -f $(EXECS)
+
+distclean: clean
+ rm -f Makefile
+ rm -f Makefile_ex
+
+# ----------------------------------------------------------------------------------------------------------------------
+
+libtool: $(top_builddir)/$(LIBTOOL_DEPS)
+ @cd ${top_builddir} ; \
+ ${SHELL} ./config.status --recheck ; \
+ cd ${abs_builddir}
diff --git a/examples/cvode/parallel/README b/examples/cvode/parallel/README
new file mode 100644
index 0000000..3a41723
--- /dev/null
+++ b/examples/cvode/parallel/README
@@ -0,0 +1,17 @@
+List of parallel CVODE examples
+
+ cvAdvDiff_non_p : 1-D advection-diffusion (nonstiff)
+ cvDiurnal_kry_bbd_p : 2-D 2-species diurnal advection-diffusion with BBD preconditioner
+ cvDiurnal_kry_p : 2-D 2-species diurnal advection-diffusion
+
+Sample results:
+
+ SUNDIALS was built with the following options:
+
+ ./configure CC=gcc F77=gfortran CFLAGS="-g3 -O0" FFLAGS="-g3 -O0" --enable-examples
+
+ System Architecture: IA-32
+ Processor Type: Intel Pentium 4 Xeon DP (i686)
+ Operating System: Red Hat Enterprise Linux WS 3 (Taroon Update 7)
+ C/Fortran Compilers: gcc/gfortran v4.1.0
+ MPI Implementation: Open MPI v1.1
diff --git a/examples/cvode/parallel/cvAdvDiff_non_p.c b/examples/cvode/parallel/cvAdvDiff_non_p.c
new file mode 100644
index 0000000..f123ebf
--- /dev/null
+++ b/examples/cvode/parallel/cvAdvDiff_non_p.c
@@ -0,0 +1,362 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.1 $
+ * $Date: 2007/10/25 20:03:28 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh, George Byrne,
+ * and Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Example problem:
+ *
+ * The following is a simple example problem, with the program for
+ * its solution by CVODE. The problem is the semi-discrete
+ * form of the advection-diffusion equation in 1-D:
+ * du/dt = d^2 u / dx^2 + .5 du/dx
+ * on the interval 0 <= x <= 2, and the time interval 0 <= t <= 5.
+ * Homogeneous Dirichlet boundary conditions are posed, and the
+ * initial condition is the following:
+ * u(x,t=0) = x(2-x)exp(2x) .
+ * 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 option for nonstiff
+ * systems: ADAMS method and functional iteration.
+ * It uses scalar relative and absolute tolerances.
+ * Output is printed at t = .5, 1.0, ..., 5.
+ * Run statistics (optional outputs) are printed at the end.
+ *
+ * This version uses MPI for user routines.
+ * Execute with Number of Processors = N, with 1 <= N <= MX.
+ * -----------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#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 <mpi.h> /* MPI constants and types */
+
+/* Problem Constants */
+
+#define ZERO RCONST(0.0)
+
+#define XMAX RCONST(2.0) /* domain boundary */
+#define MX 10 /* mesh dimension */
+#define NEQ MX /* number of equations */
+#define ATOL RCONST(1.0e-5) /* scalar absolute tolerance */
+#define T0 ZERO /* initial time */
+#define T1 RCONST(0.5) /* first output time */
+#define DTOUT RCONST(0.5) /* output time increment */
+#define NOUT 10 /* number of output times */
+
+/* Type : UserData
+ contains grid constants, parallel machine parameters, work array. */
+
+typedef struct {
+ realtype dx, hdcoef, hacoef;
+ int npes, my_pe;
+ MPI_Comm comm;
+ realtype z[100];
+} *UserData;
+
+/* Private Helper Functions */
+
+static void SetIC(N_Vector u, realtype dx, long int my_length,
+ long int my_base);
+
+static void PrintIntro(int npes);
+
+static void PrintData(realtype t, realtype umax, long int nst);
+
+static void PrintFinalStats(void *cvode_mem);
+
+/* Functions Called by the Solver */
+
+static int f(realtype t, N_Vector u, N_Vector udot, void *user_data);
+
+/* Private function to check function return values */
+
+static int check_flag(void *flagvalue, char *funcname, int opt, int id);
+
+/***************************** Main Program ******************************/
+
+int main(int argc, char *argv[])
+{
+ realtype dx, reltol, abstol, t, tout, umax;
+ N_Vector u;
+ UserData data;
+ void *cvode_mem;
+ int iout, flag, my_pe, npes;
+ long int local_N, nperpe, nrem, my_base, nst;
+
+ MPI_Comm comm;
+
+ u = NULL;
+ data = NULL;
+ cvode_mem = NULL;
+
+ /* Get processor number, total number of pe's, and my_pe. */
+ MPI_Init(&argc, &argv);
+ comm = MPI_COMM_WORLD;
+ MPI_Comm_size(comm, &npes);
+ MPI_Comm_rank(comm, &my_pe);
+
+ /* Set local vector length. */
+ nperpe = NEQ/npes;
+ nrem = NEQ - npes*nperpe;
+ local_N = (my_pe < nrem) ? nperpe+1 : nperpe;
+ my_base = (my_pe < nrem) ? my_pe*local_N : my_pe*nperpe + nrem;
+
+ data = (UserData) malloc(sizeof *data); /* Allocate data memory */
+ if(check_flag((void *)data, "malloc", 2, my_pe)) MPI_Abort(comm, 1);
+
+ data->comm = comm;
+ data->npes = npes;
+ data->my_pe = my_pe;
+
+ u = N_VNew_Parallel(comm, local_N, NEQ); /* Allocate u vector */
+ if(check_flag((void *)u, "N_VNew", 0, my_pe)) MPI_Abort(comm, 1);
+
+ reltol = ZERO; /* Set the tolerances */
+ abstol = ATOL;
+
+ dx = data->dx = XMAX/((realtype)(MX+1)); /* Set grid coefficients in data */
+ data->hdcoef = RCONST(1.0)/(dx*dx);
+ data->hacoef = RCONST(0.5)/(RCONST(2.0)*dx);
+
+ SetIC(u, dx, local_N, my_base); /* Initialize u vector */
+
+ /* 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);
+
+ flag = CVodeSetUserData(cvode_mem, data);
+ if(check_flag(&flag, "CVodeSetUserData", 1, my_pe)) MPI_Abort(comm, 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
+ * the initial dependent variable vector u. */
+ flag = CVodeInit(cvode_mem, f, T0, u);
+ if(check_flag(&flag, "CVodeInit", 1, my_pe)) return(1);
+
+ /* Call CVodeSStolerances to specify the scalar relative tolerance
+ * and scalar absolute tolerances */
+ flag = CVodeSStolerances(cvode_mem, reltol, abstol);
+ if (check_flag(&flag, "CVodeSStolerances", 1, my_pe)) return(1);
+
+ if (my_pe == 0) PrintIntro(npes);
+
+ umax = N_VMaxNorm(u);
+
+ if (my_pe == 0) {
+ t = T0;
+ PrintData(t, umax, 0);
+ }
+
+ /* In loop over output points, call CVode, print results, test for error */
+
+ 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, my_pe)) break;
+ umax = N_VMaxNorm(u);
+ flag = CVodeGetNumSteps(cvode_mem, &nst);
+ check_flag(&flag, "CVodeGetNumSteps", 1, my_pe);
+ if (my_pe == 0) PrintData(t, umax, nst);
+ }
+
+ if (my_pe == 0)
+ PrintFinalStats(cvode_mem); /* Print some final statistics */
+
+ N_VDestroy_Parallel(u); /* Free the u vector */
+ CVodeFree(&cvode_mem); /* Free the integrator memory */
+ free(data); /* Free user data */
+
+ MPI_Finalize();
+
+ return(0);
+}
+
+/************************ Private Helper Functions ***********************/
+
+/* Set initial conditions in u vector */
+
+static void SetIC(N_Vector u, realtype dx, long int my_length,
+ long int my_base)
+{
+ int i;
+ long int iglobal;
+ realtype x;
+ realtype *udata;
+
+ /* Set pointer to data array and get local length of u. */
+ udata = NV_DATA_P(u);
+ my_length = NV_LOCLENGTH_P(u);
+
+ /* Load initial profile into u vector */
+ for (i=1; i<=my_length; i++) {
+ iglobal = my_base + i;
+ x = iglobal*dx;
+ udata[i-1] = x*(XMAX - x)*EXP(RCONST(2.0)*x);
+ }
+}
+
+/* Print problem introduction */
+
+static void PrintIntro(int npes)
+{
+ printf("\n 1-D advection-diffusion equation, mesh size =%3d \n", MX);
+ printf("\n Number of PEs = %3d \n\n", npes);
+
+ return;
+}
+
+/* Print data */
+
+static void PrintData(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);
+#else
+ printf("At t = %4.2f max.norm(u) =%14.6e nst =%4ld \n", t, umax, nst);
+#endif
+
+ return;
+}
+
+/* Print some final statistics located in the iopt array */
+
+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);
+ check_flag(&flag, "CVodeGetNumRhsEvals", 1, 0);
+ flag = CVodeGetNumErrTestFails(cvode_mem, &netf);
+ check_flag(&flag, "CVodeGetNumErrTestFails", 1, 0);
+ flag = CVodeGetNumNonlinSolvIters(cvode_mem, &nni);
+ check_flag(&flag, "CVodeGetNumNonlinSolvIters", 1, 0);
+ flag = CVodeGetNumNonlinSolvConvFails(cvode_mem, &ncfn);
+ check_flag(&flag, "CVodeGetNumNonlinSolvConvFails", 1, 0);
+
+ printf("\nFinal Statistics: \n\n");
+ printf("nst = %-6ld nfe = %-6ld ", nst, nfe);
+ printf("nni = %-6ld ncfn = %-6ld netf = %ld\n \n", nni, ncfn, netf);
+}
+
+/***************** Function Called by the Solver ***********************/
+
+/* f routine. Compute f(t,u). */
+
+static int f(realtype t, N_Vector u, N_Vector udot, void *user_data)
+{
+ realtype ui, ult, urt, hordc, horac, hdiff, hadv;
+ realtype *udata, *dudata, *z;
+ int i;
+ int npes, my_pe, my_length, my_pe_m1, my_pe_p1, last_pe, my_last;
+ UserData data;
+ MPI_Status status;
+ MPI_Comm comm;
+
+ udata = NV_DATA_P(u);
+ dudata = NV_DATA_P(udot);
+
+ /* Extract needed problem constants from data */
+ data = (UserData) user_data;
+ hordc = data->hdcoef;
+ horac = data->hacoef;
+
+ /* Extract parameters for parallel computation. */
+ comm = data->comm;
+ npes = data->npes; /* Number of processes. */
+ my_pe = data->my_pe; /* Current process number. */
+ my_length = NV_LOCLENGTH_P(u); /* Number of local elements of u. */
+ z = data->z;
+
+ /* Compute related parameters. */
+ my_pe_m1 = my_pe - 1;
+ my_pe_p1 = my_pe + 1;
+ last_pe = npes - 1;
+ my_last = my_length - 1;
+
+ /* Store local segment of u in the working array z. */
+ for (i = 1; i <= my_length; i++)
+ z[i] = udata[i - 1];
+
+ /* Pass needed data to processes before and after current process. */
+ 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);
+
+ /* Receive needed data from processes before and after current process. */
+ if (my_pe != 0)
+ MPI_Recv(&z[0], 1, PVEC_REAL_MPI_TYPE, my_pe_m1, 0, comm, &status);
+ 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);
+ else z[my_length + 1] = ZERO;
+
+ /* Loop over all grid points in current process. */
+ for (i=1; i<=my_length; i++) {
+
+ /* Extract u at x_i and two neighboring points */
+ ui = z[i];
+ ult = z[i-1];
+ urt = z[i+1];
+
+ /* Set diffusion and advection terms and load into udot */
+ hdiff = hordc*(ult - RCONST(2.0)*ui + urt);
+ hadv = horac*(urt - ult);
+ dudata[i-1] = hdiff + hadv;
+ }
+
+ 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, char *funcname, int opt, int id)
+{
+ int *errflag;
+
+ /* Check if SUNDIALS function returned NULL pointer - no memory allocated */
+ if (opt == 0 && flagvalue == NULL) {
+ fprintf(stderr, "\nSUNDIALS_ERROR(%d): %s() failed - returned NULL pointer\n\n",
+ id, funcname);
+ return(1); }
+
+ /* Check if flag < 0 */
+ else if (opt == 1) {
+ errflag = (int *) flagvalue;
+ if (*errflag < 0) {
+ fprintf(stderr, "\nSUNDIALS_ERROR(%d): %s() failed with flag = %d\n\n",
+ id, funcname, *errflag);
+ return(1); }}
+
+ /* Check if function returned NULL pointer - no memory allocated */
+ else if (opt == 2 && flagvalue == NULL) {
+ fprintf(stderr, "\nMEMORY_ERROR(%d): %s() failed - returned NULL pointer\n\n",
+ id, funcname);
+ return(1); }
+
+ return(0);
+}
diff --git a/examples/cvode/parallel/cvAdvDiff_non_p.out b/examples/cvode/parallel/cvAdvDiff_non_p.out
new file mode 100644
index 0000000..be50625
--- /dev/null
+++ b/examples/cvode/parallel/cvAdvDiff_non_p.out
@@ -0,0 +1,21 @@
+
+ 1-D advection-diffusion equation, mesh size = 10
+
+ Number of PEs = 4
+
+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
+
+Final Statistics:
+
+nst = 795 nfe = 1465 nni = 1461 ncfn = 146 netf = 5
+
diff --git a/examples/cvode/parallel/cvDiurnal_kry_bbd_p.c b/examples/cvode/parallel/cvDiurnal_kry_bbd_p.c
new file mode 100644
index 0000000..5d39061
--- /dev/null
+++ b/examples/cvode/parallel/cvDiurnal_kry_bbd_p.c
@@ -0,0 +1,891 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.4 $
+ * $Date: 2010/12/14 21:31:59 $
+ * -----------------------------------------------------------------
+ * Programmer(s): S. D. Cohen, A. C. Hindmarsh, M. R. Wittman, and
+ * Radu Serban @ LLNL
+ * --------------------------------------------------------------------
+ * Example problem:
+ *
+ * An ODE system is generated from the following 2-species diurnal
+ * kinetics advection-diffusion PDE system in 2 space dimensions:
+ *
+ * dc(i)/dt = Kh*(d/dx)^2 c(i) + V*dc(i)/dx + (d/dy)(Kv(y)*dc(i)/dy)
+ * + Ri(c1,c2,t) for i = 1,2, where
+ * R1(c1,c2,t) = -q1*c1*c3 - q2*c1*c2 + 2*q3(t)*c3 + q4(t)*c2 ,
+ * R2(c1,c2,t) = q1*c1*c3 - q2*c1*c2 - q4(t)*c2 ,
+ * Kv(y) = Kv0*exp(y/5) ,
+ * Kh, V, Kv0, q1, q2, and c3 are constants, and q3(t) and q4(t)
+ * vary diurnally. The problem is posed on the square
+ * 0 <= x <= 20, 30 <= y <= 50 (all in km),
+ * with homogeneous Neumann boundary conditions, and for time t in
+ * 0 <= t <= 86400 sec (1 day).
+ * The PDE system is treated by central differences on a uniform
+ * mesh, with simple polynomial initial profiles.
+ *
+ * The problem is solved by CVODE on NPE processors, treated
+ * as a rectangular process grid of size NPEX by NPEY, with
+ * NPE = NPEX*NPEY. Each processor contains a subgrid of size MXSUB
+ * by MYSUB of the (x,y) mesh. Thus the actual mesh sizes are
+ * MX = MXSUB*NPEX and MY = MYSUB*NPEY, and the ODE system size is
+ * 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
+ * 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
+ * blocks have half-bandwidths mukeep = mlkeep = 2.
+ * A copy of the approximate Jacobian is saved and conditionally
+ * reused within the preconditioner routine.
+ *
+ * The problem is solved twice -- with left and right preconditioning.
+ *
+ * Performance data and sampled solution values are printed at
+ * selected output times, and all performance counters are printed
+ * on completion.
+ *
+ * This version uses MPI for user routines.
+ * Execute with number of processors = NPEX*NPEY (see constants below).
+ * --------------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#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 SQR and EXP */
+
+#include <mpi.h> /* MPI constants and types */
+
+
+/* Problem Constants */
+
+#define ZERO RCONST(0.0)
+
+#define NVARS 2 /* number of species */
+#define KH RCONST(4.0e-6) /* horizontal diffusivity Kh */
+#define VEL RCONST(0.001) /* advection velocity V */
+#define KV0 RCONST(1.0e-8) /* coefficient in Kv(y) */
+#define Q1 RCONST(1.63e-16) /* coefficients q1, q2, c3 */
+#define Q2 RCONST(4.66e-16)
+#define C3 RCONST(3.7e16)
+#define A3 RCONST(22.62) /* coefficient in expression for q3(t) */
+#define A4 RCONST(7.601) /* coefficient in expression for q4(t) */
+#define C1_SCALE RCONST(1.0e6) /* coefficients in initial profiles */
+#define C2_SCALE RCONST(1.0e12)
+
+#define T0 ZERO /* initial time */
+#define NOUT 12 /* number of output times */
+#define TWOHR RCONST(7200.0) /* number of seconds in two hours */
+#define HALFDAY RCONST(4.32e4) /* number of seconds in a half day */
+#define PI RCONST(3.1415926535898) /* pi */
+
+#define XMIN ZERO /* grid boundaries in x */
+#define XMAX RCONST(20.0)
+#define YMIN RCONST(30.0) /* grid boundaries in y */
+#define YMAX RCONST(50.0)
+
+#define NPEX 2 /* no. PEs in x direction of PE array */
+#define NPEY 2 /* no. PEs in y direction of PE array */
+ /* Total no. PEs = NPEX*NPEY */
+#define MXSUB 5 /* no. x points per subgrid */
+#define MYSUB 5 /* no. y points per subgrid */
+
+#define MX (NPEX*MXSUB) /* MX = number of x mesh points */
+#define MY (NPEY*MYSUB) /* MY = number of y mesh points */
+ /* Spatial mesh is MX by MY */
+/* CVodeInit Constants */
+
+#define RTOL RCONST(1.0e-5) /* scalar relative tolerance */
+#define FLOOR RCONST(100.0) /* value of C1 or C2 at which tolerances */
+ /* change from relative to absolute */
+#define ATOL (RTOL*FLOOR) /* scalar absolute tolerance */
+
+/* Type : UserData
+ contains problem constants, extended dependent variable array,
+ grid constants, processor indices, MPI communicator */
+
+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;
+ MPI_Comm comm;
+} *UserData;
+
+/* Prototypes of private helper functions */
+
+static void InitUserData(int my_pe, long int 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 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,
+ realtype uarray[]);
+static void BRecvPost(MPI_Comm comm, MPI_Request request[],
+ int my_pe, int isubx, int isuby,
+ long int dsizex, long int dsizey,
+ realtype uext[], realtype buffer[]);
+static void BRecvWait(MPI_Request request[],
+ int isubx, int isuby,
+ long int dsizex, realtype uext[],
+ realtype buffer[]);
+
+static void fucomm(realtype t, N_Vector u, void *user_data);
+
+/* Prototype of function called by the solver */
+
+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,
+ N_Vector udot, void *user_data);
+
+/* Private function to check function return values */
+
+static int check_flag(void *flagvalue, char *funcname, int opt, int id);
+
+/***************************** Main Program ******************************/
+
+int main(int argc, char *argv[])
+{
+ UserData data;
+ 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;
+ MPI_Comm comm;
+
+ data = NULL;
+ cvode_mem = NULL;
+ u = 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;
+ MPI_Comm_size(comm, &npes);
+ MPI_Comm_rank(comm, &my_pe);
+
+ if (npes != NPEX*NPEY) {
+ if (my_pe == 0)
+ fprintf(stderr, "\nMPI_ERROR(0): npes = %d is not equal to NPEX*NPEY = %d\n\n",
+ npes, NPEX*NPEY);
+ MPI_Finalize();
+ return(1);
+ }
+
+ /* Set local length */
+ local_N = NVARS*MXSUB*MYSUB;
+
+ /* Allocate and load user data block */
+ data = (UserData) malloc(sizeof *data);
+ if(check_flag((void *)data, "malloc", 2, my_pe)) MPI_Abort(comm, 1);
+ InitUserData(my_pe, local_N, comm, data);
+
+ /* Allocate and initialize u, and set tolerances */
+ u = N_VNew_Parallel(comm, local_N, neq);
+ if(check_flag((void *)u, "N_VNew_Parallel", 0, my_pe)) MPI_Abort(comm, 1);
+ SetInitialProfiles(u, data);
+ abstol = ATOL;
+ reltol = RTOL;
+
+ /* 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, my_pe)) MPI_Abort(comm, 1);
+
+ /* Set the pointer to user-defined data */
+ flag = CVodeSetUserData(cvode_mem, data);
+ if(check_flag(&flag, "CVodeSetUserData", 1, my_pe)) MPI_Abort(comm, 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
+ * the initial dependent variable vector u. */
+ flag = CVodeInit(cvode_mem, f, T0, u);
+ if(check_flag(&flag, "CVodeInit", 1, my_pe)) return(1);
+
+ /* Call CVodeSStolerances to specify the scalar relative tolerance
+ * and scalar absolute tolerances */
+ 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);
+
+ /* 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);
+
+ /* Print heading */
+ if (my_pe == 0) PrintIntro(npes, mudq, mldq, mukeep, mlkeep);
+
+ /* 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 */
+
+ if (jpre == PREC_RIGHT) {
+
+ SetInitialProfiles(u, data);
+
+ flag = CVodeReInit(cvode_mem, T0, u);
+ if(check_flag(&flag, "CVodeReInit", 1, my_pe)) MPI_Abort(comm, 1);
+
+ 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);
+
+ if (my_pe == 0) {
+ printf("\n\n-------------------------------------------------------");
+ printf("------------\n");
+ }
+
+ }
+
+
+ if (my_pe == 0) {
+ printf("\n\nPreconditioner type is: jpre = %s\n\n",
+ (jpre == PREC_LEFT) ? "PREC_LEFT" : "PREC_RIGHT");
+ }
+
+ /* In loop over output points, call CVode, print results, test for error */
+
+ for (iout = 1, tout = TWOHR; iout <= NOUT; iout++, tout += TWOHR) {
+ flag = CVode(cvode_mem, tout, u, &t, CV_NORMAL);
+ if(check_flag(&flag, "CVode", 1, my_pe)) break;
+ PrintOutput(cvode_mem, my_pe, comm, u, t);
+ }
+
+ /* Print final statistics */
+
+ if (my_pe == 0) PrintFinalStats(cvode_mem);
+
+ } /* End of jpre loop */
+
+ /* Free memory */
+ N_VDestroy_Parallel(u);
+ free(data);
+ CVodeFree(&cvode_mem);
+
+ MPI_Finalize();
+
+ return(0);
+}
+
+/*********************** Private Helper Functions ************************/
+
+/* Load constants in data */
+
+static void InitUserData(int my_pe, long int local_N, MPI_Comm comm,
+ UserData data)
+{
+ int isubx, isuby;
+
+ /* Set problem constants */
+ data->om = PI/HALFDAY;
+ data->dx = (XMAX-XMIN)/((realtype)(MX-1));
+ data->dy = (YMAX-YMIN)/((realtype)(MY-1));
+ data->hdco = KH/SQR(data->dx);
+ data->haco = VEL/(RCONST(2.0)*data->dx);
+ data->vdco = (RCONST(1.0)/SQR(data->dy))*KV0;
+
+ /* Set machine-related constants */
+ data->comm = comm;
+ data->my_pe = my_pe;
+ data->Nlocal = local_N;
+ /* isubx and isuby are the PE grid indices corresponding to my_pe */
+ isuby = my_pe/NPEX;
+ isubx = my_pe - isuby*NPEX;
+ data->isubx = isubx;
+ data->isuby = isuby;
+ /* Set the sizes of a boundary x-line in u and uext */
+ data->nvmxsub = NVARS*MXSUB;
+ data->nvmxsub2 = NVARS*(MXSUB+2);
+}
+
+/* Set initial conditions in u */
+
+static void SetInitialProfiles(N_Vector u, UserData data)
+{
+ int isubx, isuby;
+ int lx, ly, jx, jy;
+ long int offset;
+ realtype dx, dy, x, y, cx, cy, xmid, ymid;
+ realtype *uarray;
+
+ /* Set pointer to data array in vector u */
+
+ uarray = NV_DATA_P(u);
+
+ /* Get mesh spacings, and subgrid indices for this PE */
+
+ dx = data->dx; dy = data->dy;
+ isubx = data->isubx; isuby = data->isuby;
+
+ /* Load initial profiles of c1 and c2 into local u vector.
+ Here lx and ly are local mesh point indices on the local subgrid,
+ and jx and jy are the global mesh point indices. */
+
+ offset = 0;
+ xmid = RCONST(0.5)*(XMIN + XMAX);
+ ymid = RCONST(0.5)*(YMIN + YMAX);
+ for (ly = 0; ly < MYSUB; ly++) {
+ jy = ly + isuby*MYSUB;
+ y = YMIN + jy*dy;
+ cy = SQR(RCONST(0.1)*(y - ymid));
+ cy = RCONST(1.0) - cy + RCONST(0.5)*SQR(cy);
+ for (lx = 0; lx < MXSUB; lx++) {
+ jx = lx + isubx*MXSUB;
+ x = XMIN + jx*dx;
+ cx = SQR(RCONST(0.1)*(x - xmid));
+ cx = RCONST(1.0) - cx + RCONST(0.5)*SQR(cx);
+ uarray[offset ] = C1_SCALE*cx*cy;
+ uarray[offset+1] = C2_SCALE*cx*cy;
+ offset = offset + 2;
+ }
+ }
+}
+
+/* Print problem introduction */
+
+static void PrintIntro(int npes, long int mudq, long int mldq,
+ long int mukeep, long int 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(" Retained band block half-bandwidths are");
+ printf(" mukeep = %ld, mlkeep = %ld", mukeep, mlkeep);
+
+ return;
+}
+
+/* Print current t, step count, order, stepsize, and sampled c1,c2 values */
+
+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;
+ realtype hu, *uarray, tempu[2];
+ MPI_Status status;
+
+ npelast = NPEX*NPEY - 1;
+ uarray = NV_DATA_P(u);
+
+ /* Send c1,c2 at top right mesh point to PE 0 */
+ if (my_pe == npelast) {
+ i0 = NVARS*MXSUB*MYSUB - 2;
+ i1 = i0 + 1;
+ if (npelast != 0)
+ MPI_Send(&uarray[i0], 2, PVEC_REAL_MPI_TYPE, 0, 0, comm);
+ else {
+ tempu[0] = uarray[i0];
+ tempu[1] = uarray[i1];
+ }
+ }
+
+ /* On PE 0, receive c1,c2 at top right, then print performance data
+ and sampled solution values */
+ if (my_pe == 0) {
+ if (npelast != 0)
+ MPI_Recv(&tempu[0], 2, PVEC_REAL_MPI_TYPE, npelast, 0, comm, &status);
+ flag = CVodeGetNumSteps(cvode_mem, &nst);
+ check_flag(&flag, "CVodeGetNumSteps", 1, my_pe);
+ flag = CVodeGetLastOrder(cvode_mem, &qu);
+ check_flag(&flag, "CVodeGetLastOrder", 1, my_pe);
+ flag = CVodeGetLastStep(cvode_mem, &hu);
+ check_flag(&flag, "CVodeGetLastStep", 1, my_pe);
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("t = %.2Le no. steps = %ld order = %d stepsize = %.2Le\n",
+ t, nst, qu, hu);
+ printf("At bottom left: c1, c2 = %12.3Le %12.3Le \n", uarray[0], uarray[1]);
+ printf("At top right: c1, c2 = %12.3Le %12.3Le \n\n", tempu[0], tempu[1]);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("t = %.2le no. steps = %ld order = %d stepsize = %.2le\n",
+ t, nst, qu, hu);
+ printf("At bottom left: c1, c2 = %12.3le %12.3le \n", uarray[0], uarray[1]);
+ printf("At top right: c1, c2 = %12.3le %12.3le \n\n", tempu[0], tempu[1]);
+#else
+ printf("t = %.2e no. steps = %ld order = %d stepsize = %.2e\n",
+ t, nst, qu, hu);
+ printf("At bottom left: c1, c2 = %12.3e %12.3e \n", uarray[0], uarray[1]);
+ printf("At top right: c1, c2 = %12.3e %12.3e \n\n", tempu[0], tempu[1]);
+#endif
+ }
+}
+
+/* Print final statistics contained in iopt */
+
+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 nli, npe, nps, ncfl, nfeLS;
+ int flag;
+
+ flag = CVodeGetWorkSpace(cvode_mem, &lenrw, &leniw);
+ check_flag(&flag, "CVodeGetWorkSpace", 1, 0);
+ flag = CVodeGetNumSteps(cvode_mem, &nst);
+ check_flag(&flag, "CVodeGetNumSteps", 1, 0);
+ flag = CVodeGetNumRhsEvals(cvode_mem, &nfe);
+ check_flag(&flag, "CVodeGetNumRhsEvals", 1, 0);
+ flag = CVodeGetNumLinSolvSetups(cvode_mem, &nsetups);
+ check_flag(&flag, "CVodeGetNumLinSolvSetups", 1, 0);
+ flag = CVodeGetNumErrTestFails(cvode_mem, &netf);
+ check_flag(&flag, "CVodeGetNumErrTestFails", 1, 0);
+ flag = CVodeGetNumNonlinSolvIters(cvode_mem, &nni);
+ check_flag(&flag, "CVodeGetNumNonlinSolvIters", 1, 0);
+ flag = CVodeGetNumNonlinSolvConvFails(cvode_mem, &ncfn);
+ check_flag(&flag, "CVodeGetNumNonlinSolvConvFails", 1, 0);
+
+ flag = CVSpilsGetWorkSpace(cvode_mem, &lenrwLS, &leniwLS);
+ check_flag(&flag, "CVSpilsGetWorkSpace", 1, 0);
+ flag = CVSpilsGetNumLinIters(cvode_mem, &nli);
+ check_flag(&flag, "CVSpilsGetNumLinIters", 1, 0);
+ flag = CVSpilsGetNumPrecEvals(cvode_mem, &npe);
+ check_flag(&flag, "CVSpilsGetNumPrecEvals", 1, 0);
+ flag = CVSpilsGetNumPrecSolves(cvode_mem, &nps);
+ check_flag(&flag, "CVSpilsGetNumPrecSolves", 1, 0);
+ flag = CVSpilsGetNumConvFails(cvode_mem, &ncfl);
+ check_flag(&flag, "CVSpilsGetNumConvFails", 1, 0);
+ flag = CVSpilsGetNumRhsEvals(cvode_mem, &nfeLS);
+ 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("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);
+
+ flag = CVBBDPrecGetWorkSpace(cvode_mem, &lenrwBBDP, &leniwBBDP);
+ check_flag(&flag, "CVBBDPrecGetWorkSpace", 1, 0);
+ 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);
+ 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,
+ realtype uarray[])
+{
+ int i, ly;
+ long int offsetu, offsetbuf;
+ realtype bufleft[NVARS*MYSUB], bufright[NVARS*MYSUB];
+
+ /* If isuby > 0, send data from bottom x-line of u */
+
+ if (isuby != 0)
+ MPI_Send(&uarray[0], dsizex, PVEC_REAL_MPI_TYPE, my_pe-NPEX, 0, comm);
+
+ /* If isuby < NPEY-1, send data from top x-line of u */
+
+ if (isuby != NPEY-1) {
+ offsetu = (MYSUB-1)*dsizex;
+ MPI_Send(&uarray[offsetu], dsizex, PVEC_REAL_MPI_TYPE, my_pe+NPEX, 0, comm);
+ }
+
+ /* If isubx > 0, send data from left y-line of u (via bufleft) */
+
+ if (isubx != 0) {
+ for (ly = 0; ly < MYSUB; ly++) {
+ offsetbuf = ly*NVARS;
+ offsetu = ly*dsizex;
+ for (i = 0; i < NVARS; i++)
+ bufleft[offsetbuf+i] = uarray[offsetu+i];
+ }
+ MPI_Send(&bufleft[0], dsizey, PVEC_REAL_MPI_TYPE, my_pe-1, 0, comm);
+ }
+
+ /* If isubx < NPEX-1, send data from right y-line of u (via bufright) */
+
+ if (isubx != NPEX-1) {
+ for (ly = 0; ly < MYSUB; ly++) {
+ offsetbuf = ly*NVARS;
+ offsetu = offsetbuf*MXSUB + (MXSUB-1)*NVARS;
+ for (i = 0; i < NVARS; i++)
+ bufright[offsetbuf+i] = uarray[offsetu+i];
+ }
+ MPI_Send(&bufright[0], dsizey, PVEC_REAL_MPI_TYPE, my_pe+1, 0, comm);
+ }
+
+}
+
+/* Routine to start receiving boundary data from neighboring PEs.
+ Notes:
+ 1) buffer should be able to hold 2*NVARS*MYSUB realtype entries, should be
+ passed to both the BRecvPost and BRecvWait functions, and should not
+ be manipulated between the two calls.
+ 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,
+ realtype uext[], realtype buffer[])
+{
+ long int offsetue;
+ /* Have bufleft and bufright use the same buffer */
+ realtype *bufleft = buffer, *bufright = buffer+NVARS*MYSUB;
+
+ /* If isuby > 0, receive data for bottom x-line of uext */
+ if (isuby != 0)
+ MPI_Irecv(&uext[NVARS], dsizex, PVEC_REAL_MPI_TYPE,
+ my_pe-NPEX, 0, comm, &request[0]);
+
+ /* If isuby < NPEY-1, receive data for top x-line of uext */
+ if (isuby != NPEY-1) {
+ offsetue = NVARS*(1 + (MYSUB+1)*(MXSUB+2));
+ MPI_Irecv(&uext[offsetue], dsizex, PVEC_REAL_MPI_TYPE,
+ my_pe+NPEX, 0, comm, &request[1]);
+ }
+
+ /* If isubx > 0, receive data for left y-line of uext (via bufleft) */
+ if (isubx != 0) {
+ MPI_Irecv(&bufleft[0], dsizey, PVEC_REAL_MPI_TYPE,
+ my_pe-1, 0, comm, &request[2]);
+ }
+
+ /* If isubx < NPEX-1, receive data for right y-line of uext (via bufright) */
+ if (isubx != NPEX-1) {
+ MPI_Irecv(&bufright[0], dsizey, PVEC_REAL_MPI_TYPE,
+ my_pe+1, 0, comm, &request[3]);
+ }
+
+}
+
+/* Routine to finish receiving boundary data from neighboring PEs.
+ Notes:
+ 1) buffer should be able to hold 2*NVARS*MYSUB realtype entries, should be
+ passed to both the BRecvPost and BRecvWait functions, and should not
+ be manipulated between the two calls.
+ 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[],
+ realtype buffer[])
+{
+ int i, ly;
+ long int dsizex2, offsetue, offsetbuf;
+ realtype *bufleft = buffer, *bufright = buffer+NVARS*MYSUB;
+ MPI_Status status;
+
+ dsizex2 = dsizex + 2*NVARS;
+
+ /* If isuby > 0, receive data for bottom x-line of uext */
+ if (isuby != 0)
+ MPI_Wait(&request[0],&status);
+
+ /* If isuby < NPEY-1, receive data for top x-line of uext */
+ if (isuby != NPEY-1)
+ MPI_Wait(&request[1],&status);
+
+ /* If isubx > 0, receive data for left y-line of uext (via bufleft) */
+ if (isubx != 0) {
+ MPI_Wait(&request[2],&status);
+
+ /* Copy the buffer to uext */
+ for (ly = 0; ly < MYSUB; ly++) {
+ offsetbuf = ly*NVARS;
+ offsetue = (ly+1)*dsizex2;
+ for (i = 0; i < NVARS; i++)
+ uext[offsetue+i] = bufleft[offsetbuf+i];
+ }
+ }
+
+ /* If isubx < NPEX-1, receive data for right y-line of uext (via bufright) */
+ if (isubx != NPEX-1) {
+ MPI_Wait(&request[3],&status);
+
+ /* Copy the buffer to uext */
+ for (ly = 0; ly < MYSUB; ly++) {
+ offsetbuf = ly*NVARS;
+ offsetue = (ly+2)*dsizex2 - NVARS;
+ for (i = 0; i < NVARS; i++)
+ uext[offsetue+i] = bufright[offsetbuf+i];
+ }
+ }
+}
+
+/* fucomm routine. This routine performs all inter-processor
+ communication of data in u needed to calculate f. */
+
+static void fucomm(realtype t, N_Vector u, void *user_data)
+{
+ UserData data;
+ realtype *uarray, *uext, buffer[2*NVARS*MYSUB];
+ MPI_Comm comm;
+ int my_pe, isubx, isuby;
+ long int nvmxsub, nvmysub;
+ MPI_Request request[4];
+
+ data = (UserData) user_data;
+ uarray = NV_DATA_P(u);
+
+ /* Get comm, my_pe, subgrid indices, data sizes, extended array uext */
+
+ comm = data->comm; my_pe = data->my_pe;
+ isubx = data->isubx; isuby = data->isuby;
+ nvmxsub = data->nvmxsub;
+ nvmysub = NVARS*MYSUB;
+ uext = data->uext;
+
+ /* Start receiving boundary data from neighboring PEs */
+
+ BRecvPost(comm, request, my_pe, isubx, isuby, nvmxsub, nvmysub, uext, buffer);
+
+ /* Send data from boundary of local grid to neighboring PEs */
+
+ BSend(comm, my_pe, isubx, isuby, nvmxsub, nvmysub, uarray);
+
+ /* Finish receiving boundary data from neighboring PEs */
+
+ BRecvWait(request, isubx, isuby, nvmxsub, uext, buffer);
+}
+
+/***************** Function called by the solver **************************/
+
+/* f routine. Evaluate f(t,y). First call fucomm to do communication of
+ subgrid boundary data into uext. Then calculate f by a call to flocal. */
+
+static int f(realtype t, N_Vector u, N_Vector udot, void *user_data)
+{
+ UserData data;
+
+ data = (UserData) user_data;
+
+ /* Call fucomm to do inter-processor communication */
+
+ fucomm (t, u, user_data);
+
+ /* Call flocal to calculate all right-hand sides */
+
+ flocal (data->Nlocal, t, u, udot, user_data);
+
+ return(0);
+}
+
+/***************** Functions called by the CVBBDPRE module ****************/
+
+/* 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,
+ N_Vector udot, void *user_data)
+{
+ realtype *uext;
+ 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;
+ int i, lx, ly, jx, jy;
+ int isubx, isuby;
+ long int nvmxsub, nvmxsub2, offsetu, offsetue;
+ UserData data;
+ realtype *uarray, *duarray;
+
+ uarray = NV_DATA_P(u);
+ duarray = NV_DATA_P(udot);
+
+ /* Get subgrid indices, array sizes, extended work array uext */
+
+ data = (UserData) user_data;
+ isubx = data->isubx; isuby = data->isuby;
+ nvmxsub = data->nvmxsub; nvmxsub2 = data->nvmxsub2;
+ uext = data->uext;
+
+ /* Copy local segment of u vector into the working extended array uext */
+
+ offsetu = 0;
+ offsetue = nvmxsub2 + NVARS;
+ for (ly = 0; ly < MYSUB; ly++) {
+ for (i = 0; i < nvmxsub; i++) uext[offsetue+i] = uarray[offsetu+i];
+ offsetu = offsetu + nvmxsub;
+ offsetue = offsetue + nvmxsub2;
+ }
+
+ /* To facilitate homogeneous Neumann boundary conditions, when this is
+ a boundary PE, copy data from the first interior mesh line of u to uext */
+
+ /* If isuby = 0, copy x-line 2 of u to uext */
+ if (isuby == 0) {
+ for (i = 0; i < nvmxsub; i++) uext[NVARS+i] = uarray[nvmxsub+i];
+ }
+
+ /* If isuby = NPEY-1, copy x-line MYSUB-1 of u to uext */
+ if (isuby == NPEY-1) {
+ offsetu = (MYSUB-2)*nvmxsub;
+ offsetue = (MYSUB+1)*nvmxsub2 + NVARS;
+ for (i = 0; i < nvmxsub; i++) uext[offsetue+i] = uarray[offsetu+i];
+ }
+
+ /* If isubx = 0, copy y-line 2 of u to uext */
+ if (isubx == 0) {
+ for (ly = 0; ly < MYSUB; ly++) {
+ offsetu = ly*nvmxsub + NVARS;
+ offsetue = (ly+1)*nvmxsub2;
+ for (i = 0; i < NVARS; i++) uext[offsetue+i] = uarray[offsetu+i];
+ }
+ }
+
+ /* If isubx = NPEX-1, copy y-line MXSUB-1 of u to uext */
+ if (isubx == NPEX-1) {
+ for (ly = 0; ly < MYSUB; ly++) {
+ offsetu = (ly+1)*nvmxsub - 2*NVARS;
+ offsetue = (ly+2)*nvmxsub2 - NVARS;
+ for (i = 0; i < NVARS; i++) uext[offsetue+i] = uarray[offsetu+i];
+ }
+ }
+
+ /* Make local copies of problem variables, for efficiency */
+
+ dely = data->dy;
+ verdco = data->vdco;
+ hordco = data->hdco;
+ horaco = data->haco;
+
+ /* Set diurnal rate coefficients as functions of t, and save q4 in
+ data block for use by preconditioner evaluation routine */
+
+ s = sin((data->om)*t);
+ if (s > ZERO) {
+ q3 = EXP(-A3/s);
+ q4coef = EXP(-A4/s);
+ } else {
+ q3 = ZERO;
+ q4coef = ZERO;
+ }
+ data->q4 = q4coef;
+
+
+ /* Loop over all grid points in local subgrid */
+
+ for (ly = 0; ly < MYSUB; ly++) {
+
+ jy = ly + isuby*MYSUB;
+
+ /* Set vertical diffusion coefficients at jy +- 1/2 */
+
+ ydn = YMIN + (jy - RCONST(0.5))*dely;
+ yup = ydn + dely;
+ cydn = verdco*EXP(RCONST(0.2)*ydn);
+ cyup = verdco*EXP(RCONST(0.2)*yup);
+ for (lx = 0; lx < MXSUB; lx++) {
+
+ jx = lx + isubx*MXSUB;
+
+ /* Extract c1 and c2, and set kinetic rate terms */
+
+ offsetue = (lx+1)*NVARS + (ly+1)*nvmxsub2;
+ c1 = uext[offsetue];
+ c2 = uext[offsetue+1];
+ qq1 = Q1*c1*C3;
+ qq2 = Q2*c1*c2;
+ qq3 = q3*C3;
+ qq4 = q4coef*c2;
+ rkin1 = -qq1 - qq2 + 2.0*qq3 + qq4;
+ rkin2 = qq1 - qq2 - qq4;
+
+ /* Set vertical diffusion terms */
+
+ c1dn = uext[offsetue-nvmxsub2];
+ c2dn = uext[offsetue-nvmxsub2+1];
+ c1up = uext[offsetue+nvmxsub2];
+ c2up = uext[offsetue+nvmxsub2+1];
+ vertd1 = cyup*(c1up - c1) - cydn*(c1 - c1dn);
+ vertd2 = cyup*(c2up - c2) - cydn*(c2 - c2dn);
+
+ /* Set horizontal diffusion and advection terms */
+
+ c1lt = uext[offsetue-2];
+ c2lt = uext[offsetue-1];
+ c1rt = uext[offsetue+2];
+ c2rt = uext[offsetue+3];
+ hord1 = hordco*(c1rt - RCONST(2.0)*c1 + c1lt);
+ hord2 = hordco*(c2rt - RCONST(2.0)*c2 + c2lt);
+ horad1 = horaco*(c1rt - c1lt);
+ horad2 = horaco*(c2rt - c2lt);
+
+ /* Load all terms into duarray */
+
+ offsetu = lx*NVARS + ly*nvmxsub;
+ duarray[offsetu] = vertd1 + hord1 + horad1 + rkin1;
+ duarray[offsetu+1] = vertd2 + hord2 + horad2 + rkin2;
+ }
+ }
+
+ 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, char *funcname, int opt, int id)
+{
+ int *errflag;
+
+ /* Check if SUNDIALS function returned NULL pointer - no memory allocated */
+ if (opt == 0 && flagvalue == NULL) {
+ fprintf(stderr, "\nSUNDIALS_ERROR(%d): %s() failed - returned NULL pointer\n\n",
+ id, funcname);
+ return(1); }
+
+ /* Check if flag < 0 */
+ else if (opt == 1) {
+ errflag = (int *) flagvalue;
+ if (*errflag < 0) {
+ fprintf(stderr, "\nSUNDIALS_ERROR(%d): %s() failed with flag = %d\n\n",
+ id, funcname, *errflag);
+ return(1); }}
+
+ /* Check if function returned NULL pointer - no memory allocated */
+ else if (opt == 2 && flagvalue == NULL) {
+ fprintf(stderr, "\nMEMORY_ERROR(%d): %s() failed - returned NULL pointer\n\n",
+ id, funcname);
+ return(1); }
+
+ return(0);
+}
diff --git a/examples/cvode/parallel/cvDiurnal_kry_bbd_p.out b/examples/cvode/parallel/cvDiurnal_kry_bbd_p.out
new file mode 100644
index 0000000..9a72bbb
--- /dev/null
+++ b/examples/cvode/parallel/cvDiurnal_kry_bbd_p.out
@@ -0,0 +1,140 @@
+
+2-species diurnal advection-diffusion problem
+ 10 by 10 mesh on 4 processors
+ Using CVBBDPRE preconditioner module
+ Difference-quotient half-bandwidths are mudq = 10, mldq = 10
+ Retained band block half-bandwidths are mukeep = 2, mlkeep = 2
+
+Preconditioner type is: jpre = PREC_LEFT
+
+t = 7.20e+03 no. steps = 190 order = 5 stepsize = 1.61e+02
+At bottom left: c1, c2 = 1.047e+04 2.527e+11
+At top right: c1, c2 = 1.119e+04 2.700e+11
+
+t = 1.44e+04 no. steps = 221 order = 5 stepsize = 3.85e+02
+At bottom left: c1, c2 = 6.659e+06 2.582e+11
+At top right: c1, c2 = 7.301e+06 2.833e+11
+
+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
+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
+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 = 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.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 = 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 = 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.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 = 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
+
+
+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
+ncfn = 0 ncfl = 0
+
+In CVBBDPRE: real/integer local work space sizes = 600, 50
+ no. flocal evals. = 176
+
+
+-------------------------------------------------------------------
+
+
+Preconditioner type is: jpre = PREC_RIGHT
+
+t = 7.20e+03 no. steps = 191 order = 5 stepsize = 1.22e+02
+At bottom left: c1, c2 = 1.047e+04 2.527e+11
+At top right: c1, c2 = 1.119e+04 2.700e+11
+
+t = 1.44e+04 no. steps = 223 order = 5 stepsize = 2.79e+02
+At bottom left: c1, c2 = 6.659e+06 2.582e+11
+At top right: c1, c2 = 7.301e+06 2.833e+11
+
+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
+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
+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 = 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.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 = 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 = 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.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 = 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
+
+
+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
+ncfn = 0 ncfl = 0
+
+In CVBBDPRE: real/integer local work space sizes = 600, 50
+ no. flocal evals. = 198
diff --git a/examples/cvode/parallel/cvDiurnal_kry_p.c b/examples/cvode/parallel/cvDiurnal_kry_p.c
new file mode 100644
index 0000000..c76c77a
--- /dev/null
+++ b/examples/cvode/parallel/cvDiurnal_kry_p.c
@@ -0,0 +1,975 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.5 $
+ * $Date: 2010/12/01 22:52:20 $
+ * -----------------------------------------------------------------
+ * Programmer(s): S. D. Cohen, A. C. Hindmarsh, M. R. Wittman, and
+ * Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Example problem:
+ *
+ * An ODE system is generated from the following 2-species diurnal
+ * kinetics advection-diffusion PDE system in 2 space dimensions:
+ *
+ * dc(i)/dt = Kh*(d/dx)^2 c(i) + V*dc(i)/dx + (d/dy)(Kv(y)*dc(i)/dy)
+ * + Ri(c1,c2,t) for i = 1,2, where
+ * R1(c1,c2,t) = -q1*c1*c3 - q2*c1*c2 + 2*q3(t)*c3 + q4(t)*c2 ,
+ * R2(c1,c2,t) = q1*c1*c3 - q2*c1*c2 - q4(t)*c2 ,
+ * Kv(y) = Kv0*exp(y/5) ,
+ * Kh, V, Kv0, q1, q2, and c3 are constants, and q3(t) and q4(t)
+ * vary diurnally. The problem is posed on the square
+ * 0 <= x <= 20, 30 <= y <= 50 (all in km),
+ * with homogeneous Neumann boundary conditions, and for time t in
+ * 0 <= t <= 86400 sec (1 day).
+ * The PDE system is treated by central differences on a uniform
+ * mesh, with simple polynomial initial profiles.
+ *
+ * The problem is solved by CVODE on NPE processors, treated
+ * as a rectangular process grid of size NPEX by NPEY, with
+ * NPE = NPEX*NPEY. Each processor contains a subgrid of size MXSUB
+ * by MYSUB of the (x,y) mesh. Thus the actual mesh sizes are
+ * MX = MXSUB*NPEX and MY = MYSUB*NPEY, and the ODE system size is
+ * 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
+ * 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.
+ *
+ * Performance data and sampled solution values are printed at
+ * selected output times, and all performance counters are printed
+ * on completion.
+ *
+ * This version uses MPI for user routines.
+ *
+ * Execution: mpirun -np N cvDiurnal_kry_p with N = NPEX*NPEY
+ * (see constants below).
+ * -----------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#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 SQR and EXP */
+
+#include <mpi.h> /* MPI constants and types */
+
+/* Problem Constants */
+
+#define NVARS 2 /* number of species */
+#define KH RCONST(4.0e-6) /* horizontal diffusivity Kh */
+#define VEL RCONST(0.001) /* advection velocity V */
+#define KV0 RCONST(1.0e-8) /* coefficient in Kv(y) */
+#define Q1 RCONST(1.63e-16) /* coefficients q1, q2, c3 */
+#define Q2 RCONST(4.66e-16)
+#define C3 RCONST(3.7e16)
+#define A3 RCONST(22.62) /* coefficient in expression for q3(t) */
+#define A4 RCONST(7.601) /* coefficient in expression for q4(t) */
+#define C1_SCALE RCONST(1.0e6) /* coefficients in initial profiles */
+#define C2_SCALE RCONST(1.0e12)
+
+#define T0 RCONST(0.0) /* initial time */
+#define NOUT 12 /* number of output times */
+#define TWOHR RCONST(7200.0) /* number of seconds in two hours */
+#define HALFDAY RCONST(4.32e4) /* number of seconds in a half day */
+#define PI RCONST(3.1415926535898) /* pi */
+
+#define XMIN RCONST(0.0) /* grid boundaries in x */
+#define XMAX RCONST(20.0)
+#define YMIN RCONST(30.0) /* grid boundaries in y */
+#define YMAX RCONST(50.0)
+
+#define NPEX 2 /* no. PEs in x direction of PE array */
+#define NPEY 2 /* no. PEs in y direction of PE array */
+ /* Total no. PEs = NPEX*NPEY */
+#define MXSUB 5 /* no. x points per subgrid */
+#define MYSUB 5 /* no. y points per subgrid */
+
+#define MX (NPEX*MXSUB) /* MX = number of x mesh points */
+#define MY (NPEY*MYSUB) /* MY = number of y mesh points */
+ /* Spatial mesh is MX by MY */
+/* CVodeMalloc Constants */
+
+#define RTOL RCONST(1.0e-5) /* scalar relative tolerance */
+#define FLOOR RCONST(100.0) /* value of C1 or C2 at which tolerances */
+ /* change from relative to absolute */
+#define ATOL (RTOL*FLOOR) /* scalar absolute tolerance */
+
+
+/* User-defined matrix accessor macro: IJth */
+
+/* IJth is defined in order to write code which indexes into dense
+ matrices with a (row,column) pair, where 1 <= row,column <= NVARS.
+
+ IJth(a,i,j) references the (i,j)th entry of the small matrix realtype **a,
+ where 1 <= i,j <= NVARS. The small matrix routines in sundials_dense.h
+ work with matrices stored by column in a 2-dimensional array. In C,
+ arrays are indexed starting at 0, not 1. */
+
+#define IJth(a,i,j) (a[j-1][i-1])
+
+/* Type : UserData
+ contains problem constants, preconditioner blocks, pivot arrays,
+ grid constants, and processor indices, as well as data needed
+ for the preconditiner */
+
+typedef struct {
+
+ realtype q4, om, dx, dy, hdco, haco, vdco;
+ realtype uext[NVARS*(MXSUB+2)*(MYSUB+2)];
+ int my_pe, isubx, isuby;
+ int nvmxsub, nvmxsub2;
+ MPI_Comm comm;
+
+ /* For preconditioner */
+ realtype **P[MXSUB][MYSUB], **Jbd[MXSUB][MYSUB];
+ long int *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(N_Vector u, UserData data);
+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,
+ realtype udata[]);
+static void BRecvPost(MPI_Comm comm, MPI_Request request[],
+ int my_pe, int isubx, int isuby,
+ long int dsizex, long int dsizey,
+ realtype uext[], realtype buffer[]);
+static void BRecvWait(MPI_Request request[],
+ int isubx, int isuby,
+ long int 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);
+
+
+/* Functions Called by the Solver */
+
+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 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);
+
+
+/* Private function to check function return values */
+
+static int check_flag(void *flagvalue, char *funcname, int opt, int id);
+
+
+/***************************** Main Program ******************************/
+
+int main(int argc, char *argv[])
+{
+ realtype abstol, reltol, t, tout;
+ N_Vector u;
+ UserData data;
+ void *cvode_mem;
+ int iout, flag, my_pe, npes;
+ long int neq, local_N;
+ MPI_Comm comm;
+
+ u = NULL;
+ data = NULL;
+ cvode_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;
+ MPI_Comm_size(comm, &npes);
+ MPI_Comm_rank(comm, &my_pe);
+
+ if (npes != NPEX*NPEY) {
+ if (my_pe == 0)
+ fprintf(stderr, "\nMPI_ERROR(0): npes = %d is not equal to NPEX*NPEY = %d\n\n",
+ npes,NPEX*NPEY);
+ MPI_Finalize();
+ return(1);
+ }
+
+ /* Set local length */
+ local_N = NVARS*MXSUB*MYSUB;
+
+ /* Allocate and load user data block; allocate preconditioner block */
+ data = (UserData) malloc(sizeof *data);
+ if (check_flag((void *)data, "malloc", 2, my_pe)) MPI_Abort(comm, 1);
+ InitUserData(my_pe, comm, data);
+
+ /* Allocate u, and set initial values and tolerances */
+ u = N_VNew_Parallel(comm, local_N, neq);
+ if (check_flag((void *)u, "N_VNew", 0, my_pe)) MPI_Abort(comm, 1);
+ SetInitialProfiles(u, data);
+ abstol = ATOL; reltol = RTOL;
+
+ /* 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, my_pe)) MPI_Abort(comm, 1);
+
+ /* Set the pointer to user-defined data */
+ flag = CVodeSetUserData(cvode_mem, data);
+ if (check_flag(&flag, "CVodeSetUserData", 1, my_pe)) MPI_Abort(comm, 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
+ * the initial dependent variable vector u. */
+ flag = CVodeInit(cvode_mem, f, T0, u);
+ if(check_flag(&flag, "CVodeInit", 1, my_pe)) return(1);
+
+ /* Call CVodeSStolerances to specify the scalar relative tolerance
+ * and scalar absolute tolerances */
+ 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);
+
+ /* 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, my_pe)) MPI_Abort(comm, 1);
+
+ if (my_pe == 0)
+ printf("\n2-species diurnal advection-diffusion problem\n\n");
+
+ /* In loop over output points, call CVode, print results, test for error */
+ for (iout=1, tout = TWOHR; iout <= NOUT; iout++, tout += TWOHR) {
+ flag = CVode(cvode_mem, tout, u, &t, CV_NORMAL);
+ if (check_flag(&flag, "CVode", 1, my_pe)) break;
+ PrintOutput(cvode_mem, my_pe, comm, u, t);
+ }
+
+ /* Print final statistics */
+ if (my_pe == 0) PrintFinalStats(cvode_mem);
+
+ /* Free memory */
+ N_VDestroy_Parallel(u);
+ FreeUserData(data);
+ CVodeFree(&cvode_mem);
+
+ MPI_Finalize();
+
+ return(0);
+}
+
+
+/*********************** Private Helper Functions ************************/
+
+
+/* Load constants in data */
+
+static void InitUserData(int my_pe, MPI_Comm comm, UserData data)
+{
+ int isubx, isuby;
+ int lx, ly;
+
+ /* Set problem constants */
+ data->om = PI/HALFDAY;
+ data->dx = (XMAX-XMIN)/((realtype)(MX-1));
+ data->dy = (YMAX-YMIN)/((realtype)(MY-1));
+ data->hdco = KH/SQR(data->dx);
+ data->haco = VEL/(RCONST(2.0)*data->dx);
+ data->vdco = (RCONST(1.0)/SQR(data->dy))*KV0;
+
+ /* Set machine-related constants */
+ data->comm = comm;
+ data->my_pe = my_pe;
+
+ /* isubx and isuby are the PE grid indices corresponding to my_pe */
+ isuby = my_pe/NPEX;
+ isubx = my_pe - isuby*NPEX;
+ data->isubx = isubx;
+ data->isuby = isuby;
+
+ /* Set the sizes of a boundary x-line in u and uext */
+ data->nvmxsub = NVARS*MXSUB;
+ data->nvmxsub2 = NVARS*(MXSUB+2);
+
+ /* Preconditioner-related fields */
+ for (lx = 0; lx < MXSUB; lx++) {
+ 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);
+ }
+ }
+}
+
+/* Free user data memory */
+
+static void FreeUserData(UserData data)
+{
+ int lx, ly;
+
+ for (lx = 0; lx < MXSUB; lx++) {
+ for (ly = 0; ly < MYSUB; ly++) {
+ destroyMat((data->P)[lx][ly]);
+ destroyMat((data->Jbd)[lx][ly]);
+ destroyArray((data->pivot)[lx][ly]);
+ }
+ }
+
+ free(data);
+}
+
+/* Set initial conditions in u */
+
+static void SetInitialProfiles(N_Vector u, UserData data)
+{
+ int isubx, isuby, lx, ly, jx, jy;
+ long int offset;
+ realtype dx, dy, x, y, cx, cy, xmid, ymid;
+ realtype *udata;
+
+ /* Set pointer to data array in vector u */
+ udata = NV_DATA_P(u);
+
+ /* Get mesh spacings, and subgrid indices for this PE */
+ dx = data->dx; dy = data->dy;
+ isubx = data->isubx; isuby = data->isuby;
+
+ /* Load initial profiles of c1 and c2 into local u vector.
+ Here lx and ly are local mesh point indices on the local subgrid,
+ and jx and jy are the global mesh point indices. */
+ offset = 0;
+ xmid = RCONST(0.5)*(XMIN + XMAX);
+ ymid = RCONST(0.5)*(YMIN + YMAX);
+ for (ly = 0; ly < MYSUB; ly++) {
+ jy = ly + isuby*MYSUB;
+ y = YMIN + jy*dy;
+ cy = SQR(RCONST(0.1)*(y - ymid));
+ cy = RCONST(1.0) - cy + RCONST(0.5)*SQR(cy);
+ for (lx = 0; lx < MXSUB; lx++) {
+ jx = lx + isubx*MXSUB;
+ x = XMIN + jx*dx;
+ cx = SQR(RCONST(0.1)*(x - xmid));
+ cx = RCONST(1.0) - cx + RCONST(0.5)*SQR(cx);
+ udata[offset ] = C1_SCALE*cx*cy;
+ udata[offset+1] = C2_SCALE*cx*cy;
+ offset = offset + 2;
+ }
+ }
+}
+
+/* Print current t, step count, order, stepsize, and sampled c1,c2 values */
+
+static void PrintOutput(void *cvode_mem, int my_pe, MPI_Comm comm,
+ N_Vector u, realtype t)
+{
+ int qu, flag;
+ realtype hu, *udata, tempu[2];
+ int npelast;
+ long int i0, i1, nst;
+ MPI_Status status;
+
+ npelast = NPEX*NPEY - 1;
+ udata = NV_DATA_P(u);
+
+ /* Send c1,c2 at top right mesh point to PE 0 */
+ if (my_pe == npelast) {
+ i0 = NVARS*MXSUB*MYSUB - 2;
+ i1 = i0 + 1;
+ if (npelast != 0)
+ MPI_Send(&udata[i0], 2, PVEC_REAL_MPI_TYPE, 0, 0, comm);
+ else {
+ tempu[0] = udata[i0];
+ tempu[1] = udata[i1];
+ }
+ }
+
+ /* On PE 0, receive c1,c2 at top right, then print performance data
+ and sampled solution values */
+ if (my_pe == 0) {
+ if (npelast != 0)
+ MPI_Recv(&tempu[0], 2, PVEC_REAL_MPI_TYPE, npelast, 0, comm, &status);
+ flag = CVodeGetNumSteps(cvode_mem, &nst);
+ check_flag(&flag, "CVodeGetNumSteps", 1, my_pe);
+ flag = CVodeGetLastOrder(cvode_mem, &qu);
+ check_flag(&flag, "CVodeGetLastOrder", 1, my_pe);
+ flag = CVodeGetLastStep(cvode_mem, &hu);
+ check_flag(&flag, "CVodeGetLastStep", 1, my_pe);
+
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("t = %.2Le no. steps = %ld order = %d stepsize = %.2Le\n",
+ t, nst, qu, hu);
+ printf("At bottom left: c1, c2 = %12.3Le %12.3Le \n", udata[0], udata[1]);
+ printf("At top right: c1, c2 = %12.3Le %12.3Le \n\n", tempu[0], tempu[1]);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("t = %.2le no. steps = %ld order = %d stepsize = %.2le\n",
+ t, nst, qu, hu);
+ printf("At bottom left: c1, c2 = %12.3le %12.3le \n", udata[0], udata[1]);
+ printf("At top right: c1, c2 = %12.3le %12.3le \n\n", tempu[0], tempu[1]);
+#else
+ printf("t = %.2e no. steps = %ld order = %d stepsize = %.2e\n",
+ t, nst, qu, hu);
+ printf("At bottom left: c1, c2 = %12.3e %12.3e \n", udata[0], udata[1]);
+ printf("At top right: c1, c2 = %12.3e %12.3e \n\n", tempu[0], tempu[1]);
+#endif
+ }
+}
+
+/* Print final statistics contained in iopt */
+
+static void PrintFinalStats(void *cvode_mem)
+{
+ long int lenrw, leniw ;
+ long int 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, 0);
+ flag = CVodeGetNumSteps(cvode_mem, &nst);
+ check_flag(&flag, "CVodeGetNumSteps", 1, 0);
+ flag = CVodeGetNumRhsEvals(cvode_mem, &nfe);
+ check_flag(&flag, "CVodeGetNumRhsEvals", 1, 0);
+ flag = CVodeGetNumLinSolvSetups(cvode_mem, &nsetups);
+ check_flag(&flag, "CVodeGetNumLinSolvSetups", 1, 0);
+ flag = CVodeGetNumErrTestFails(cvode_mem, &netf);
+ check_flag(&flag, "CVodeGetNumErrTestFails", 1, 0);
+ flag = CVodeGetNumNonlinSolvIters(cvode_mem, &nni);
+ check_flag(&flag, "CVodeGetNumNonlinSolvIters", 1, 0);
+ flag = CVodeGetNumNonlinSolvConvFails(cvode_mem, &ncfn);
+ check_flag(&flag, "CVodeGetNumNonlinSolvConvFails", 1, 0);
+
+ flag = CVSpilsGetWorkSpace(cvode_mem, &lenrwLS, &leniwLS);
+ check_flag(&flag, "CVSpilsGetWorkSpace", 1, 0);
+ flag = CVSpilsGetNumLinIters(cvode_mem, &nli);
+ check_flag(&flag, "CVSpilsGetNumLinIters", 1, 0);
+ flag = CVSpilsGetNumPrecEvals(cvode_mem, &npe);
+ check_flag(&flag, "CVSpilsGetNumPrecEvals", 1, 0);
+ flag = CVSpilsGetNumPrecSolves(cvode_mem, &nps);
+ check_flag(&flag, "CVSpilsGetNumPrecSolves", 1, 0);
+ flag = CVSpilsGetNumConvFails(cvode_mem, &ncfl);
+ check_flag(&flag, "CVSpilsGetNumConvFails", 1, 0);
+ flag = CVSpilsGetNumRhsEvals(cvode_mem, &nfeLS);
+ 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("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);
+}
+
+/* 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[])
+{
+ int i, ly;
+ long int offsetu, offsetbuf;
+ realtype bufleft[NVARS*MYSUB], bufright[NVARS*MYSUB];
+
+ /* If isuby > 0, send data from bottom x-line of u */
+ if (isuby != 0)
+ MPI_Send(&udata[0], dsizex, PVEC_REAL_MPI_TYPE, my_pe-NPEX, 0, comm);
+
+ /* If isuby < NPEY-1, send data from top x-line of u */
+ if (isuby != NPEY-1) {
+ offsetu = (MYSUB-1)*dsizex;
+ MPI_Send(&udata[offsetu], dsizex, PVEC_REAL_MPI_TYPE, my_pe+NPEX, 0, comm);
+ }
+
+ /* If isubx > 0, send data from left y-line of u (via bufleft) */
+ if (isubx != 0) {
+ for (ly = 0; ly < MYSUB; ly++) {
+ offsetbuf = ly*NVARS;
+ offsetu = ly*dsizex;
+ for (i = 0; i < NVARS; i++)
+ bufleft[offsetbuf+i] = udata[offsetu+i];
+ }
+ MPI_Send(&bufleft[0], dsizey, PVEC_REAL_MPI_TYPE, my_pe-1, 0, comm);
+ }
+
+ /* If isubx < NPEX-1, send data from right y-line of u (via bufright) */
+ if (isubx != NPEX-1) {
+ for (ly = 0; ly < MYSUB; ly++) {
+ offsetbuf = ly*NVARS;
+ offsetu = offsetbuf*MXSUB + (MXSUB-1)*NVARS;
+ for (i = 0; i < NVARS; i++)
+ bufright[offsetbuf+i] = udata[offsetu+i];
+ }
+ MPI_Send(&bufright[0], dsizey, PVEC_REAL_MPI_TYPE, my_pe+1, 0, comm);
+ }
+}
+
+/* Routine to start receiving boundary data from neighboring PEs.
+ Notes:
+ 1) buffer should be able to hold 2*NVARS*MYSUB realtype entries, should be
+ passed to both the BRecvPost and BRecvWait functions, and should not
+ be manipulated between the two calls.
+ 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,
+ realtype uext[], realtype buffer[])
+{
+ long int offsetue;
+ /* Have bufleft and bufright use the same buffer */
+ realtype *bufleft = buffer, *bufright = buffer+NVARS*MYSUB;
+
+ /* If isuby > 0, receive data for bottom x-line of uext */
+ if (isuby != 0)
+ MPI_Irecv(&uext[NVARS], dsizex, PVEC_REAL_MPI_TYPE,
+ my_pe-NPEX, 0, comm, &request[0]);
+
+ /* If isuby < NPEY-1, receive data for top x-line of uext */
+ if (isuby != NPEY-1) {
+ offsetue = NVARS*(1 + (MYSUB+1)*(MXSUB+2));
+ MPI_Irecv(&uext[offsetue], dsizex, PVEC_REAL_MPI_TYPE,
+ my_pe+NPEX, 0, comm, &request[1]);
+ }
+
+ /* If isubx > 0, receive data for left y-line of uext (via bufleft) */
+ if (isubx != 0) {
+ MPI_Irecv(&bufleft[0], dsizey, PVEC_REAL_MPI_TYPE,
+ my_pe-1, 0, comm, &request[2]);
+ }
+
+ /* If isubx < NPEX-1, receive data for right y-line of uext (via bufright) */
+ if (isubx != NPEX-1) {
+ MPI_Irecv(&bufright[0], dsizey, PVEC_REAL_MPI_TYPE,
+ my_pe+1, 0, comm, &request[3]);
+ }
+}
+
+/* Routine to finish receiving boundary data from neighboring PEs.
+ Notes:
+ 1) buffer should be able to hold 2*NVARS*MYSUB realtype entries, should be
+ passed to both the BRecvPost and BRecvWait functions, and should not
+ be manipulated between the two calls.
+ 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[],
+ realtype buffer[])
+{
+ int i, ly;
+ long int dsizex2, offsetue, offsetbuf;
+ realtype *bufleft = buffer, *bufright = buffer+NVARS*MYSUB;
+ MPI_Status status;
+
+ dsizex2 = dsizex + 2*NVARS;
+
+ /* If isuby > 0, receive data for bottom x-line of uext */
+ if (isuby != 0)
+ MPI_Wait(&request[0],&status);
+
+ /* If isuby < NPEY-1, receive data for top x-line of uext */
+ if (isuby != NPEY-1)
+ MPI_Wait(&request[1],&status);
+
+ /* If isubx > 0, receive data for left y-line of uext (via bufleft) */
+ if (isubx != 0) {
+ MPI_Wait(&request[2],&status);
+
+ /* Copy the buffer to uext */
+ for (ly = 0; ly < MYSUB; ly++) {
+ offsetbuf = ly*NVARS;
+ offsetue = (ly+1)*dsizex2;
+ for (i = 0; i < NVARS; i++)
+ uext[offsetue+i] = bufleft[offsetbuf+i];
+ }
+ }
+
+ /* If isubx < NPEX-1, receive data for right y-line of uext (via bufright) */
+ if (isubx != NPEX-1) {
+ MPI_Wait(&request[3],&status);
+
+ /* Copy the buffer to uext */
+ for (ly = 0; ly < MYSUB; ly++) {
+ offsetbuf = ly*NVARS;
+ offsetue = (ly+2)*dsizex2 - NVARS;
+ for (i = 0; i < NVARS; i++)
+ uext[offsetue+i] = bufright[offsetbuf+i];
+ }
+ }
+}
+
+/* ucomm routine. This routine performs all communication
+ between processors of data needed to calculate f. */
+
+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;
+ MPI_Request request[4];
+
+ udata = NV_DATA_P(u);
+
+ /* Get comm, my_pe, subgrid indices, data sizes, extended array uext */
+ comm = data->comm; my_pe = data->my_pe;
+ isubx = data->isubx; isuby = data->isuby;
+ nvmxsub = data->nvmxsub;
+ nvmysub = NVARS*MYSUB;
+ uext = data->uext;
+
+ /* Start receiving boundary data from neighboring PEs */
+ BRecvPost(comm, request, my_pe, isubx, isuby, nvmxsub, nvmysub, uext, buffer);
+
+ /* Send data from boundary of local grid to neighboring PEs */
+ BSend(comm, my_pe, isubx, isuby, nvmxsub, nvmysub, udata);
+
+ /* Finish receiving boundary data from neighboring PEs */
+ BRecvWait(request, isubx, isuby, nvmxsub, uext, buffer);
+}
+
+/* fcalc routine. Compute f(t,y). This routine assumes that communication
+ between processors of data needed to calculate f has already been done,
+ and this data is in the work array uext. */
+
+static void fcalc(realtype t, realtype udata[],
+ realtype dudata[], UserData data)
+{
+ realtype *uext;
+ 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;
+ int i, lx, ly, jx, jy;
+ int isubx, isuby;
+ long int nvmxsub, nvmxsub2, offsetu, offsetue;
+
+ /* Get subgrid indices, data sizes, extended work array uext */
+ isubx = data->isubx; isuby = data->isuby;
+ nvmxsub = data->nvmxsub; nvmxsub2 = data->nvmxsub2;
+ uext = data->uext;
+
+ /* Copy local segment of u vector into the working extended array uext */
+ offsetu = 0;
+ offsetue = nvmxsub2 + NVARS;
+ for (ly = 0; ly < MYSUB; ly++) {
+ for (i = 0; i < nvmxsub; i++) uext[offsetue+i] = udata[offsetu+i];
+ offsetu = offsetu + nvmxsub;
+ offsetue = offsetue + nvmxsub2;
+ }
+
+ /* To facilitate homogeneous Neumann boundary conditions, when this is
+ a boundary PE, copy data from the first interior mesh line of u to uext */
+
+ /* If isuby = 0, copy x-line 2 of u to uext */
+ if (isuby == 0) {
+ for (i = 0; i < nvmxsub; i++) uext[NVARS+i] = udata[nvmxsub+i];
+ }
+
+ /* If isuby = NPEY-1, copy x-line MYSUB-1 of u to uext */
+ if (isuby == NPEY-1) {
+ offsetu = (MYSUB-2)*nvmxsub;
+ offsetue = (MYSUB+1)*nvmxsub2 + NVARS;
+ for (i = 0; i < nvmxsub; i++) uext[offsetue+i] = udata[offsetu+i];
+ }
+
+ /* If isubx = 0, copy y-line 2 of u to uext */
+ if (isubx == 0) {
+ for (ly = 0; ly < MYSUB; ly++) {
+ offsetu = ly*nvmxsub + NVARS;
+ offsetue = (ly+1)*nvmxsub2;
+ for (i = 0; i < NVARS; i++) uext[offsetue+i] = udata[offsetu+i];
+ }
+ }
+
+ /* If isubx = NPEX-1, copy y-line MXSUB-1 of u to uext */
+ if (isubx == NPEX-1) {
+ for (ly = 0; ly < MYSUB; ly++) {
+ offsetu = (ly+1)*nvmxsub - 2*NVARS;
+ offsetue = (ly+2)*nvmxsub2 - NVARS;
+ for (i = 0; i < NVARS; i++) uext[offsetue+i] = udata[offsetu+i];
+ }
+ }
+
+ /* Make local copies of problem variables, for efficiency */
+ dely = data->dy;
+ verdco = data->vdco;
+ hordco = data->hdco;
+ horaco = data->haco;
+
+ /* Set diurnal rate coefficients as functions of t, and save q4 in
+ data block for use by preconditioner evaluation routine */
+ s = sin((data->om)*t);
+ if (s > RCONST(0.0)) {
+ q3 = EXP(-A3/s);
+ q4coef = EXP(-A4/s);
+ } else {
+ q3 = RCONST(0.0);
+ q4coef = RCONST(0.0);
+ }
+ data->q4 = q4coef;
+
+ /* Loop over all grid points in local subgrid */
+ for (ly = 0; ly < MYSUB; ly++) {
+
+ jy = ly + isuby*MYSUB;
+
+ /* Set vertical diffusion coefficients at jy +- 1/2 */
+ ydn = YMIN + (jy - RCONST(0.5))*dely;
+ yup = ydn + dely;
+ cydn = verdco*EXP(RCONST(0.2)*ydn);
+ cyup = verdco*EXP(RCONST(0.2)*yup);
+ for (lx = 0; lx < MXSUB; lx++) {
+
+ jx = lx + isubx*MXSUB;
+
+ /* Extract c1 and c2, and set kinetic rate terms */
+ offsetue = (lx+1)*NVARS + (ly+1)*nvmxsub2;
+ c1 = uext[offsetue];
+ c2 = uext[offsetue+1];
+ qq1 = Q1*c1*C3;
+ qq2 = Q2*c1*c2;
+ qq3 = q3*C3;
+ qq4 = q4coef*c2;
+ rkin1 = -qq1 - qq2 + RCONST(2.0)*qq3 + qq4;
+ rkin2 = qq1 - qq2 - qq4;
+
+ /* Set vertical diffusion terms */
+ c1dn = uext[offsetue-nvmxsub2];
+ c2dn = uext[offsetue-nvmxsub2+1];
+ c1up = uext[offsetue+nvmxsub2];
+ c2up = uext[offsetue+nvmxsub2+1];
+ vertd1 = cyup*(c1up - c1) - cydn*(c1 - c1dn);
+ vertd2 = cyup*(c2up - c2) - cydn*(c2 - c2dn);
+
+ /* Set horizontal diffusion and advection terms */
+ c1lt = uext[offsetue-2];
+ c2lt = uext[offsetue-1];
+ c1rt = uext[offsetue+2];
+ c2rt = uext[offsetue+3];
+ hord1 = hordco*(c1rt - RCONST(2.0)*c1 + c1lt);
+ hord2 = hordco*(c2rt - RCONST(2.0)*c2 + c2lt);
+ horad1 = horaco*(c1rt - c1lt);
+ horad2 = horaco*(c2rt - c2lt);
+
+ /* Load all terms into dudata */
+ offsetu = lx*NVARS + ly*nvmxsub;
+ dudata[offsetu] = vertd1 + hord1 + horad1 + rkin1;
+ dudata[offsetu+1] = vertd2 + hord2 + horad2 + rkin2;
+ }
+ }
+}
+
+
+/***************** Functions Called by the Solver *************************/
+
+/* f routine. Evaluate f(t,y). First call ucomm to do communication of
+ subgrid boundary data into uext. Then calculate f by a call to fcalc. */
+
+static int f(realtype t, N_Vector u, N_Vector udot, void *user_data)
+{
+ realtype *udata, *dudata;
+ UserData data;
+
+ udata = NV_DATA_P(u);
+ dudata = NV_DATA_P(udot);
+ data = (UserData) user_data;
+
+ /* Call ucomm to do inter-processor communication */
+ ucomm(t, u, data);
+
+ /* Call fcalc to calculate all right-hand sides */
+ fcalc(t, udata, dudata, data);
+
+ return(0);
+}
+
+/* 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 c1, c2, cydn, cyup, diag, ydn, yup, q4coef, dely, verdco, hordco;
+ realtype **(*P)[MYSUB], **(*Jbd)[MYSUB];
+ int nvmxsub, ier, offset;
+ long int *(*pivot)[MYSUB];
+ int lx, ly, jx, jy, isubx, isuby;
+ realtype *udata, **a, **j;
+ UserData data;
+
+ /* Make local copies of pointers in user_data, pointer to u's data,
+ and PE index pair */
+ data = (UserData) user_data;
+ P = data->P;
+ Jbd = data->Jbd;
+ pivot = data->pivot;
+ udata = NV_DATA_P(u);
+ isubx = data->isubx; isuby = data->isuby;
+ nvmxsub = data->nvmxsub;
+
+ if (jok) {
+
+ /* jok = TRUE: 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;
+
+ }
+
+ else {
+
+ /* jok = FALSE: Generate Jbd from scratch and copy to P */
+
+ /* Make local copies of problem variables, for efficiency */
+ q4coef = data->q4;
+ dely = data->dy;
+ verdco = data->vdco;
+ hordco = data->hdco;
+
+ /* Compute 2x2 diagonal Jacobian blocks (using q4 values
+ computed on the last f call). Load into P. */
+ for (ly = 0; ly < MYSUB; ly++) {
+ jy = ly + isuby*MYSUB;
+ ydn = YMIN + (jy - RCONST(0.5))*dely;
+ yup = ydn + dely;
+ cydn = verdco*EXP(RCONST(0.2)*ydn);
+ cyup = verdco*EXP(RCONST(0.2)*yup);
+ diag = -(cydn + cyup + RCONST(2.0)*hordco);
+ for (lx = 0; lx < MXSUB; lx++) {
+ jx = lx + isubx*MXSUB;
+ offset = lx*NVARS + ly*nvmxsub;
+ c1 = udata[offset];
+ c2 = udata[offset+1];
+ j = Jbd[lx][ly];
+ a = P[lx][ly];
+ IJth(j,1,1) = (-Q1*C3 - Q2*c2) + diag;
+ IJth(j,1,2) = -Q2*c1 + q4coef;
+ IJth(j,2,1) = Q1*C3 - Q2*c2;
+ IJth(j,2,2) = (-Q2*c1 - q4coef) + diag;
+ denseCopy(j, a, NVARS, NVARS);
+ }
+ }
+
+ *jcurPtr = TRUE;
+
+ }
+
+ /* Scale by -gamma */
+ for (ly = 0; ly < MYSUB; ly++)
+ for (lx = 0; lx < MXSUB; lx++)
+ denseScale(-gamma, P[lx][ly], NVARS, NVARS);
+
+ /* Add identity matrix and do LU decompositions on blocks in place */
+ for (lx = 0; lx < MXSUB; lx++) {
+ for (ly = 0; ly < MYSUB; ly++) {
+ denseAddIdentity(P[lx][ly], NVARS);
+ ier = denseGETRF(P[lx][ly], NVARS, NVARS, pivot[lx][ly]);
+ if (ier != 0) return(1);
+ }
+ }
+
+ return(0);
+}
+
+/* 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)
+{
+ realtype **(*P)[MYSUB];
+ int nvmxsub;
+ long int *(*pivot)[MYSUB];
+ int lx, ly;
+ realtype *zdata, *v;
+ UserData data;
+
+ /* Extract the P and pivot arrays from user_data */
+ data = (UserData) user_data;
+ P = data->P;
+ pivot = data->pivot;
+
+ /* Solve the block-diagonal system Px = r using LU factors stored
+ 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 = NV_DATA_P(z);
+
+ for (lx = 0; lx < MXSUB; lx++) {
+ for (ly = 0; ly < MYSUB; ly++) {
+ v = &(zdata[lx*NVARS + ly*nvmxsub]);
+ denseGETRS(P[lx][ly], NVARS, pivot[lx][ly], v);
+ }
+ }
+
+ return(0);
+}
+
+
+/*********************** Private Helper Function ************************/
+
+/* 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, char *funcname, int opt, int id)
+{
+ int *errflag;
+
+ /* Check if SUNDIALS function returned NULL pointer - no memory allocated */
+ if (opt == 0 && flagvalue == NULL) {
+ fprintf(stderr, "\nSUNDIALS_ERROR(%d): %s() failed - returned NULL pointer\n\n",
+ id, funcname);
+ return(1); }
+
+ /* Check if flag < 0 */
+ else if (opt == 1) {
+ errflag = (int *) flagvalue;
+ if (*errflag < 0) {
+ fprintf(stderr, "\nSUNDIALS_ERROR(%d): %s() failed with flag = %d\n\n",
+ id, funcname, *errflag);
+ return(1); }}
+
+ /* Check if function returned NULL pointer - no memory allocated */
+ else if (opt == 2 && flagvalue == NULL) {
+ fprintf(stderr, "\nMEMORY_ERROR(%d): %s() failed - returned NULL pointer\n\n",
+ id, funcname);
+ return(1); }
+
+ return(0);
+}
diff --git a/examples/cvode/parallel/cvDiurnal_kry_p.out b/examples/cvode/parallel/cvDiurnal_kry_p.out
new file mode 100644
index 0000000..6705776
--- /dev/null
+++ b/examples/cvode/parallel/cvDiurnal_kry_p.out
@@ -0,0 +1,63 @@
+
+2-species diurnal advection-diffusion problem
+
+t = 7.20e+03 no. steps = 219 order = 5 stepsize = 1.59e+02
+At bottom left: c1, c2 = 1.047e+04 2.527e+11
+At top right: c1, c2 = 1.119e+04 2.700e+11
+
+t = 1.44e+04 no. steps = 251 order = 5 stepsize = 3.77e+02
+At bottom left: c1, c2 = 6.659e+06 2.582e+11
+At top right: c1, c2 = 7.301e+06 2.833e+11
+
+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
+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
+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 = 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.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 = 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 = 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.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 = 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
+
+
+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
+
diff --git a/examples/cvode/serial/CMakeLists.txt b/examples/cvode/serial/CMakeLists.txt
new file mode 100644
index 0000000..6c539b8
--- /dev/null
+++ b/examples/cvode/serial/CMakeLists.txt
@@ -0,0 +1,127 @@
+# ---------------------------------------------------------------
+# $Revision: 1.5 $
+# $Date: 2009/02/17 02:58:47 $
+# ---------------------------------------------------------------
+# Programmer: Radu Serban @ LLNL
+# ---------------------------------------------------------------
+# Copyright (c) 2007, The Regents of the University of California.
+# Produced at the Lawrence Livermore National Laboratory.
+# All rights reserved.
+# For details, see the LICENSE file.
+# ---------------------------------------------------------------
+# CMakeLists.txt file for CVODE serial examples
+
+# Add variable CVODE_examples with the names of the serial CVODE examples
+
+SET(CVODE_examples
+ cvAdvDiff_bnd
+ cvDirectDemo_ls
+ cvDiurnal_kry_bp
+ cvDiurnal_kry
+ cvKrylovDemo_ls
+ cvKrylovDemo_prec
+ cvRoberts_dns
+ cvRoberts_dns_uw
+ )
+
+# Add variable CVODE_examples_BL with the names of the serial CVODE examples
+# that use Lapack
+
+SET(CVODE_examples_BL
+ cvAdvDiff_bndL
+ cvRoberts_dnsL
+ )
+
+# 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")
+ SET(CVODE_LIB sundials_cvode_shared)
+ SET(NVECS_LIB sundials_nvecserial_shared)
+ENDIF(LINK_LIBRARY_TYPE MATCHES "static")
+
+# Set-up linker flags and link libraries
+
+SET(SUNDIALS_LIBS ${CVODE_LIB} ${NVECS_LIB} ${EXTRA_LINK_LIBS})
+IF(LAPACK_FOUND)
+ SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${LAPACK_LINKER_FLAGS}")
+ SET(SUNDIALS_LIBS "${SUNDIALS_LIBS} ${LAPACK_LIBRARIES}")
+ENDIF(LAPACK_FOUND)
+
+# Add the build and install targets for each CVODE example
+
+FOREACH(example ${CVODE_examples})
+ ADD_EXECUTABLE(${example} ${example}.c)
+ TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+ IF(EXAMPLES_INSTALL)
+ INSTALL(FILES ${example}.c ${example}.out DESTINATION ${EXAMPLES_INSTALL_PATH}/cvode/serial)
+ ENDIF(EXAMPLES_INSTALL)
+ENDFOREACH(example ${CVODE_examples})
+
+# Add the build and install targets for each Lapack CVODE example (if needed)
+
+IF(LAPACK_FOUND)
+ FOREACH(example ${CVODE_examples_BL})
+ ADD_EXECUTABLE(${example} ${example}.c)
+ TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+ IF(EXAMPLES_INSTALL)
+ INSTALL(FILES ${example}.c ${example}.out DESTINATION ${EXAMPLES_INSTALL_PATH}/cvode/serial)
+ ENDIF(EXAMPLES_INSTALL)
+ ENDFOREACH(example ${CVODE_examples_BL})
+ENDIF(LAPACK_FOUND)
+
+IF(EXAMPLES_INSTALL)
+
+ # Install the README file
+ INSTALL(FILES README DESTINATION ${EXAMPLES_INSTALL_PATH}/cvode/serial)
+
+ # Prepare substitution variables for Makefile and/or CMakeLists templates
+ SET(SOLVER "CVODE")
+ SET(SOLVER_LIB "sundials_cvode")
+ LIST2STRING(CVODE_examples EXAMPLES)
+ IF(LAPACK_FOUND)
+ LIST2STRING(CVODE_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
+ # 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/cvode/serial/CMakeLists.txt
+ @ONLY
+ )
+
+ # install CMakelists.txt
+ INSTALL(
+ FILES ${PROJECT_BINARY_DIR}/examples/cvode/serial/CMakeLists.txt
+ DESTINATION ${EXAMPLES_INSTALL_PATH}/cvode/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/cvode/serial/Makefile_ex
+ @ONLY
+ )
+ # install the configured Makefile_ex as Makefile
+ INSTALL(
+ FILES ${PROJECT_BINARY_DIR}/examples/cvode/serial/Makefile_ex
+ DESTINATION ${EXAMPLES_INSTALL_PATH}/cvode/serial
+ RENAME Makefile
+ )
+ ENDIF(UNIX)
+
+ENDIF(EXAMPLES_INSTALL)
diff --git a/examples/cvode/serial/Makefile.in b/examples/cvode/serial/Makefile.in
new file mode 100644
index 0000000..2b1b71f
--- /dev/null
+++ b/examples/cvode/serial/Makefile.in
@@ -0,0 +1,139 @@
+# -----------------------------------------------------------------
+# $Revision: 1.12 $
+# $Date: 2009/02/17 02:58:47 $
+# -----------------------------------------------------------------
+# Programmer(s): Radu Serban and Aaron Collier @ LLNL
+# -----------------------------------------------------------------
+# Copyright (c) 2002, The Regents of the University of California.
+# Produced at the Lawrence Livermore National Laboratory.
+# All rights reserved.
+# For details, see the LICENSE file.
+# -----------------------------------------------------------------
+# Makefile for CVODE serial examples
+#
+# @configure_input@
+# -----------------------------------------------------------------
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_builddir = @top_builddir@
+builddir = @builddir@
+abs_builddir = @abs_builddir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+includedir = @includedir@
+libdir = @libdir@
+
+INSTALL = @INSTALL@
+INSTALL_PROG = @INSTALL_PROGRAM@
+INSTALL_FILE = @INSTALL_DATA@
+
+LIBTOOL = @LIBTOOL@
+LIBTOOL_DEPS = @LIBTOOL_DEPS@
+
+SHARED_LIBS = @SHARED_LIBS@
+
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CC = @CC@
+CFLAGS = @CFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+
+LAPACK_ENABLED = @LAPACK_ENABLED@
+BLAS_LAPACK_LIBS = @BLAS_LAPACK_LIBS@
+
+OBJ_EXT = @OBJEXT@
+EXE_EXT = @EXEEXT@
+
+EXS_INSTDIR = @EXS_INSTDIR@
+
+top_srcdir = $(srcdir)/../../..
+
+SUNDIALS_INCS = -I$(top_srcdir)/include -I$(top_builddir)/include
+
+SUNDIALS_LIBS = $(top_builddir)/src/cvode/libsundials_cvode.la \
+ $(top_builddir)/src/nvec_ser/libsundials_nvecserial.la
+
+mkinstalldirs = $(SHELL) $(top_srcdir)/config/mkinstalldirs
+rminstalldirs = $(SHELL) $(top_srcdir)/config/rminstalldirs
+
+EXAMPLES = cvAdvDiff_bnd \
+ cvDirectDemo_ls \
+ cvDiurnal_kry_bp \
+ cvDiurnal_kry \
+ cvKrylovDemo_ls \
+ cvKrylovDemo_prec \
+ cvRoberts_dns \
+ cvRoberts_dns_uw
+
+EXAMPLES_BL = cvAdvDiff_bndL \
+ cvRoberts_dnsL
+
+OBJECTS = ${EXAMPLES:=${OBJ_EXT}}
+OBJECTS_BL = ${EXAMPLES_BL:=${OBJ_EXT}}
+EXECS = ${EXAMPLES:=${EXE_EXT}}
+EXECS_BL = ${EXAMPLES_BL:=${EXE_EXT}}
+
+# ----------------------------------------------------------------------------------------------------------------------
+
+all:
+ @for i in ${EXAMPLES} ; do \
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(SUNDIALS_INCS) $(CFLAGS) -c $(srcdir)/$${i}.c -o $${i}${OBJ_EXT} ; \
+ $(LIBTOOL) --mode=link $(CC) -o $(builddir)/$${i}$(EXE_EXT) $(builddir)/$${i}${OBJ_EXT} $(CFLAGS) $(LDFLAGS) $(SUNDIALS_LIBS) $(LIBS) $(BLAS_LAPACK_LIBS) ; \
+ done
+ @if test "X${LAPACK_ENABLED}" = "Xyes"; then \
+ for i in ${EXAMPLES_BL} ; do \
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(SUNDIALS_INCS) $(CFLAGS) -c $(srcdir)/$${i}.c -o $${i}${OBJ_EXT} ; \
+ $(LIBTOOL) --mode=link $(CC) -o $(builddir)/$${i}$(EXE_EXT) $(builddir)/$${i}${OBJ_EXT} $(CFLAGS) $(LDFLAGS) $(SUNDIALS_LIBS) $(LIBS) $(BLAS_LAPACK_LIBS) ; \
+ done ; \
+ fi
+
+install:
+ $(mkinstalldirs) $(EXS_INSTDIR)/cvode/serial
+ $(INSTALL_FILE) Makefile_ex $(EXS_INSTDIR)/cvode/serial/Makefile
+ $(INSTALL_FILE) $(top_srcdir)/examples/cvode/serial/README $(EXS_INSTDIR)/cvode/serial/
+ for i in ${EXAMPLES} ; do \
+ $(INSTALL_FILE) $(top_srcdir)/examples/cvode/serial/$${i}.c $(EXS_INSTDIR)/cvode/serial/ ; \
+ $(INSTALL_FILE) $(top_srcdir)/examples/cvode/serial/$${i}.out $(EXS_INSTDIR)/cvode/serial/ ; \
+ done
+ @if test "X${LAPACK_ENABLED}" = "Xyes"; then \
+ for i in ${EXAMPLES_BL} ; do \
+ $(INSTALL_FILE) $(top_srcdir)/examples/cvode/serial/$${i}.c $(EXS_INSTDIR)/cvode/serial/ ; \
+ $(INSTALL_FILE) $(top_srcdir)/examples/cvode/serial/$${i}.out $(EXS_INSTDIR)/cvode/serial/ ; \
+ done ; \
+ fi
+
+uninstall:
+ rm -f $(EXS_INSTDIR)/cvode/serial/Makefile
+ rm -f $(EXS_INSTDIR)/cvode/serial/README
+ for i in ${EXAMPLES} ; do \
+ rm -f $(EXS_INSTDIR)/cvode/serial/$${i}.c ; \
+ rm -f $(EXS_INSTDIR)/cvode/serial/$${i}.out ; \
+ done
+ @if test "X${LAPACK_ENABLED}" = "Xyes"; then \
+ for i in ${EXAMPLES_BL} ; do \
+ rm -f $(EXS_INSTDIR)/cvode/serial/$${i}.c ; \
+ rm -f $(EXS_INSTDIR)/cvode/serial/$${i}.out ; \
+ done ; \
+ fi
+ $(rminstalldirs) $(EXS_INSTDIR)/cvode/serial
+ $(rminstalldirs) $(EXS_INSTDIR)/cvode
+
+clean:
+ rm -rf .libs
+ rm -f *.lo *.o
+ rm -f ${OBJECTS} ${OBJECTS_BL}
+ rm -f $(EXECS) $(EXECS_BL)
+
+distclean: clean
+ rm -f Makefile
+ rm -f Makefile_ex
+
+# ----------------------------------------------------------------------------------------------------------------------
+
+libtool: $(top_builddir)/$(LIBTOOL_DEPS)
+ @cd ${top_builddir} ; \
+ ${SHELL} ./config.status --recheck ; \
+ cd ${abs_builddir}
diff --git a/examples/cvode/serial/README b/examples/cvode/serial/README
new file mode 100644
index 0000000..7423632
--- /dev/null
+++ b/examples/cvode/serial/README
@@ -0,0 +1,25 @@
+List of serial CVODE examples
+
+ cvAdvDiff_bnd : banded example
+ cvAdvDiff_bndL : banded example (Lapack)
+ cvDirectDemo_ls : demonstration program for direct methods
+ cvDiurnal_kry_bp : Krylov example with banded preconditioner
+ cvDiurnal_kry : Krylov example
+ cvKrylovDemo_ls : demonstration program with 3 Krylov solvers
+ cvKrylovDemo_prec : demonstration program for Krylov methods
+ cvRoberts_dns : dense example
+ cvRoberts_dnsL : dense example (Lapack)
+ cvRoberts_dns_uw : dense example with user ewt function
+
+Sample results:
+
+ SUNDIALS was built with the following options:
+
+ ./configure CC=gcc F77=g77 CFLAGS="-g3 -O0" FFLAGS="-g3 -O0" --with-blas-lapack-libs="-L/home/radu/apps/lib -lSimTKlapack" --enable-examples
+
+ System Architecture: IA-32
+ Processor Type: Intel Pentium 4 Xeon DP (i686)
+ Operating System: Red Hat Enterprise Linux WS 3 (Taroon Update 7)
+ C/Fortran Compilers: gcc/gfortran v4.1.0
+
+ The SimTKlapack library provides ATLAS-tunned Blas and Lapack functions
\ No newline at end of file
diff --git a/examples/cvode/serial/cvAdvDiff_bnd.c b/examples/cvode/serial/cvAdvDiff_bnd.c
new file mode 100644
index 0000000..e9e249f
--- /dev/null
+++ b/examples/cvode/serial/cvAdvDiff_bnd.c
@@ -0,0 +1,426 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.3 $
+ * $Date: 2010/12/01 22:51:32 $
+ * -----------------------------------------------------------------
+ * Programmer(s): 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>
+
+/* 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 */
+
+/* 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 */
+#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)
+
+/* 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 = NV_DATA_S(v),
+ where v is an N_Vector.
+ The variables are ordered by the y index j, then by the x index i. */
+
+#define IJth(vdata,i,j) (vdata[(j-1) + (i-1)*MY])
+
+/* Type : UserData (contains grid constants) */
+
+typedef struct {
+ realtype dx, dy, hdcoef, hacoef, vdcoef;
+} *UserData;
+
+/* Private Helper Functions */
+
+static void SetIC(N_Vector u, UserData data);
+static void PrintHeader(realtype reltol, realtype abstol, realtype umax);
+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, 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);
+
+/*
+ *-------------------------------
+ * Main Program
+ *-------------------------------
+ */
+
+int main(void)
+{
+ realtype dx, dy, reltol, abstol, t, tout, umax;
+ N_Vector u;
+ UserData data;
+ void *cvode_mem;
+ int iout, flag;
+ long int nst;
+
+ u = NULL;
+ data = 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);
+
+ reltol = ZERO; /* Set the tolerances */
+ 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);
+
+ 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 inital 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);
+
+ /* Call CVBand to specify the CVBAND band linear solver */
+ flag = CVBand(cvode_mem, NEQ, MY, MY);
+ if(check_flag(&flag, "CVBand", 1)) return(1);
+
+ /* Set the user-supplied Jacobian routine Jac */
+ flag = CVDlsSetBandJacFn(cvode_mem, Jac);
+ if(check_flag(&flag, "CVDlsSetBandJacFn", 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) {
+ 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_Serial(u); /* Free the u vector */
+ CVodeFree(&cvode_mem); /* Free the integrator memory */
+ free(data); /* Free the user data */
+
+ return(0);
+}
+
+/*
+ *-------------------------------
+ * 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)
+{
+ realtype uij, udn, uup, ult, urt, hordc, horac, verdc, hdiff, hadv, vdiff;
+ realtype *udata, *dudata;
+ int i, j;
+ UserData data;
+
+ udata = NV_DATA_S(u);
+ dudata = NV_DATA_S(udot);
+
+ /* Extract needed constants from data */
+
+ data = (UserData) user_data;
+ hordc = data->hdcoef;
+ horac = data->hacoef;
+ verdc = data->vdcoef;
+
+ /* Loop over all grid points. */
+
+ for (j=1; j <= MY; j++) {
+
+ for (i=1; i <= MX; i++) {
+
+ /* Extract u at x_i, y_j and four neighboring points */
+
+ 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);
+
+ /* 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);
+ IJth(dudata, i, j) = hdiff + hadv + vdiff;
+ }
+ }
+
+ return(0);
+}
+
+/* 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
+ *-------------------------------
+ */
+
+/* Set initial conditions in u vector */
+
+static void SetIC(N_Vector u, UserData data)
+{
+ int i, j;
+ realtype x, y, dx, dy;
+ realtype *udata;
+
+ /* Extract needed constants from data */
+
+ dx = data->dx;
+ dy = data->dy;
+
+ /* Set pointer to data array in vector u. */
+
+ udata = NV_DATA_S(u);
+
+ /* Load initial profile into u vector */
+
+ 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)*EXP(FIVE*x*y);
+ }
+ }
+}
+
+/* Print first lines of output (problem description) */
+
+static void PrintHeader(realtype reltol, realtype abstol, realtype umax)
+{
+ printf("\n2-D Advection-Diffusion Equation\n");
+ 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("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);
+#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.6le 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)
+{
+ int flag;
+ long int nst, nfe, nsetups, netf, nni, ncfn, nje, nfeLS;
+
+ 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 = 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);
+
+ 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, 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/serial/cvAdvDiff_bnd.out b/examples/cvode/serial/cvAdvDiff_bnd.out
new file mode 100644
index 0000000..c48de03
--- /dev/null
+++ b/examples/cvode/serial/cvAdvDiff_bnd.out
@@ -0,0 +1,22 @@
+
+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.132889e+00 nst = 85
+At t = 0.20 max.norm(u) = 1.039294e+00 nst = 103
+At t = 0.30 max.norm(u) = 2.979829e-01 nst = 113
+At t = 0.40 max.norm(u) = 8.765774e-02 nst = 120
+At t = 0.50 max.norm(u) = 2.625637e-02 nst = 126
+At t = 0.60 max.norm(u) = 7.830425e-03 nst = 130
+At t = 0.70 max.norm(u) = 2.329387e-03 nst = 134
+At t = 0.80 max.norm(u) = 6.953434e-04 nst = 137
+At t = 0.90 max.norm(u) = 2.115983e-04 nst = 140
+At t = 1.00 max.norm(u) = 6.556853e-05 nst = 142
+
+Final Statistics:
+nst = 142 nfe = 174 nsetups = 23 nfeLS = 0 nje = 3
+nni = 170 ncfn = 0 netf = 3
+
diff --git a/examples/cvode/serial/cvAdvDiff_bndL.c b/examples/cvode/serial/cvAdvDiff_bndL.c
new file mode 100644
index 0000000..35dfb86
--- /dev/null
+++ b/examples/cvode/serial/cvAdvDiff_bndL.c
@@ -0,0 +1,421 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.3 $
+ * $Date: 2010/12/01 22:51:32 $
+ * -----------------------------------------------------------------
+ * Programmer(s): 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 LAPACK 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>
+
+/* 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 */
+
+/* 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 */
+#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)
+
+/* 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 = NV_DATA_S(v),
+ where v is an N_Vector.
+ The variables are ordered by the y index j, then by the x index i. */
+
+#define IJth(vdata,i,j) (vdata[(j-1) + (i-1)*MY])
+
+/* Type : UserData (contains grid constants) */
+
+typedef struct {
+ realtype dx, dy, hdcoef, hacoef, vdcoef;
+} *UserData;
+
+/* Private Helper Functions */
+
+static void SetIC(N_Vector u, UserData data);
+static void PrintHeader(realtype reltol, realtype abstol, realtype umax);
+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, 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);
+
+/*
+ *-------------------------------
+ * Main Program
+ *-------------------------------
+ */
+
+int main(void)
+{
+ realtype dx, dy, reltol, abstol, t, tout, umax;
+ N_Vector u;
+ UserData data;
+ void *cvode_mem;
+ int iout, flag;
+ long int nst;
+
+ u = NULL;
+ data = 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);
+
+ reltol = ZERO; /* Set the tolerances */
+ 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);
+
+ 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 inital 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);
+
+ /* Call CVLapackBand to specify the CVBAND band linear solver */
+ flag = CVLapackBand(cvode_mem, NEQ, MY, MY);
+ if(check_flag(&flag, "CVLapackBand", 1)) return(1);
+
+ /* Set the user-supplied Jacobian routine Jac */
+ flag = CVDlsSetBandJacFn(cvode_mem, Jac);
+ if(check_flag(&flag, "CVDlsSetBandJacFn", 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) {
+ 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_Serial(u); /* Free the u vector */
+ CVodeFree(&cvode_mem); /* Free the integrator memory */
+ free(data); /* Free the user data */
+
+ return(0);
+}
+
+/*
+ *-------------------------------
+ * 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)
+{
+ realtype uij, udn, uup, ult, urt, hordc, horac, verdc, hdiff, hadv, vdiff;
+ realtype *udata, *dudata;
+ int i, j;
+ UserData data;
+
+ udata = NV_DATA_S(u);
+ dudata = NV_DATA_S(udot);
+
+ /* Extract needed constants from data */
+
+ data = (UserData) user_data;
+ hordc = data->hdcoef;
+ horac = data->hacoef;
+ verdc = data->vdcoef;
+
+ /* Loop over all grid points. */
+
+ for (j=1; j <= MY; j++) {
+
+ for (i=1; i <= MX; i++) {
+
+ /* Extract u at x_i, y_j and four neighboring points */
+
+ 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);
+
+ /* 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);
+ IJth(dudata, i, j) = hdiff + hadv + vdiff;
+ }
+ }
+
+ return(0);
+}
+
+/* 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)
+{
+ 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;
+
+ /* 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);
+
+ /* 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
+ *-------------------------------
+ */
+
+/* Set initial conditions in u vector */
+
+static void SetIC(N_Vector u, UserData data)
+{
+ int i, j;
+ realtype x, y, dx, dy;
+ realtype *udata;
+
+ /* Extract needed constants from data */
+
+ dx = data->dx;
+ dy = data->dy;
+
+ /* Set pointer to data array in vector u. */
+
+ udata = NV_DATA_S(u);
+
+ /* Load initial profile into u vector */
+
+ 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)*EXP(FIVE*x*y);
+ }
+ }
+}
+
+/* Print first lines of output (problem description) */
+
+static void PrintHeader(realtype reltol, realtype abstol, realtype umax)
+{
+ printf("\n2-D Advection-Diffusion Equation\n");
+ 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("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);
+#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.6le 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)
+{
+ int flag;
+ long int nst, nfe, nsetups, netf, nni, ncfn, nje, nfeLS;
+
+ 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 = 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);
+
+ 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, 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/serial/cvAdvDiff_bndL.out b/examples/cvode/serial/cvAdvDiff_bndL.out
new file mode 100644
index 0000000..c48de03
--- /dev/null
+++ b/examples/cvode/serial/cvAdvDiff_bndL.out
@@ -0,0 +1,22 @@
+
+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.132889e+00 nst = 85
+At t = 0.20 max.norm(u) = 1.039294e+00 nst = 103
+At t = 0.30 max.norm(u) = 2.979829e-01 nst = 113
+At t = 0.40 max.norm(u) = 8.765774e-02 nst = 120
+At t = 0.50 max.norm(u) = 2.625637e-02 nst = 126
+At t = 0.60 max.norm(u) = 7.830425e-03 nst = 130
+At t = 0.70 max.norm(u) = 2.329387e-03 nst = 134
+At t = 0.80 max.norm(u) = 6.953434e-04 nst = 137
+At t = 0.90 max.norm(u) = 2.115983e-04 nst = 140
+At t = 1.00 max.norm(u) = 6.556853e-05 nst = 142
+
+Final Statistics:
+nst = 142 nfe = 174 nsetups = 23 nfeLS = 0 nje = 3
+nni = 170 ncfn = 0 netf = 3
+
diff --git a/examples/cvode/serial/cvDirectDemo_ls.c b/examples/cvode/serial/cvDirectDemo_ls.c
new file mode 100644
index 0000000..756e854
--- /dev/null
+++ b/examples/cvode/serial/cvDirectDemo_ls.c
@@ -0,0 +1,789 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.3 $
+ * $Date: 2010/12/01 22:51:32 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh and
+ * Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Demonstration program for CVODE - direct linear solvers.
+ * Two separate problems are solved using both the CV_ADAMS and CV_BDF
+ * linear multistep methods in combination with CV_FUNCTIONAL and
+ * CV_NEWTON iterations:
+ *
+ * Problem 1: Van der Pol oscillator
+ * xdotdot - 3*(1 - x^2)*xdot + x = 0, x(0) = 2, xdot(0) = 0.
+ * This second-order ODE is converted to a first-order system by
+ * defining y0 = x and y1 = xdot.
+ * The NEWTON iteration cases use the following types of Jacobian
+ * approximation: (1) dense, user-supplied, (2) dense, difference
+ * quotient approximation, (3) diagonal approximation.
+ *
+ * Problem 2: ydot = A * y, where A is a banded lower triangular
+ * matrix derived from 2-D advection PDE.
+ * The NEWTON iteration cases use the following types of Jacobian
+ * approximation: (1) band, user-supplied, (2) band, difference
+ * quotient approximation, (3) diagonal approximation.
+ *
+ * For each problem, in the series of eight runs, CVodeInit is
+ * called only once, for the first run, whereas CVodeReInit is
+ * called for each of the remaining seven runs.
+ *
+ * Notes: This program demonstrates the usage of the sequential
+ * macros NV_Ith_S, NV_DATA_S, DENSE_ELEM, BAND_COL, and
+ * BAND_COL_ELEM. 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 NV_DATA_S
+ * macro 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 NV_DATA_S
+ * macro 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 NV_DATA_S macro. 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.
+ * -----------------------------------------------------------------
+ */
+
+#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, SQR, and EXP*/
+
+/* Shared Problem Constants */
+
+#define ATOL RCONST(1.0e-6)
+#define RTOL RCONST(0.0)
+
+#define ZERO RCONST(0.0)
+#define ONE RCONST(1.0)
+#define TWO RCONST(2.0)
+#define THIRTY RCONST(30.0)
+
+/* Problem #1 Constants */
+
+#define P1_NEQ 2
+#define P1_ETA RCONST(3.0)
+#define P1_NOUT 4
+#define P1_T0 RCONST(0.0)
+#define P1_T1 RCONST(1.39283880203)
+#define P1_DTOUT RCONST(2.214773875)
+#define P1_TOL_FACTOR RCONST(1.0e4)
+
+/* Problem #2 Constants */
+
+#define P2_MESHX 5
+#define P2_MESHY 5
+#define P2_NEQ P2_MESHX*P2_MESHY
+#define P2_ALPH1 RCONST(1.0)
+#define P2_ALPH2 RCONST(1.0)
+#define P2_NOUT 5
+#define P2_ML 5
+#define P2_MU 0
+#define P2_T0 RCONST(0.0)
+#define P2_T1 RCONST(0.01)
+#define P2_TOUT_MULT RCONST(10.0)
+#define P2_TOL_FACTOR RCONST(1.0e3)
+
+/* Linear Solver Options */
+
+enum {FUNC, DENSE_USER, DENSE_DQ, DIAG, BAND_USER, BAND_DQ};
+
+/* Private Helper Functions */
+
+static int Problem1(void);
+static void PrintIntro1(void);
+static void PrintHeader1(void);
+static void PrintOutput1(realtype t, realtype y0, realtype y1, int qu, realtype hu);
+static int Problem2(void);
+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 void PrintErrOutput(realtype tol_factor);
+static void PrintFinalStats(void *cvode_mem, int miter, realtype ero);
+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 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,
+ N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
+
+/* Private function to check function return values */
+
+static int check_flag(void *flagvalue, char *funcname, int opt);
+
+/* Implementation */
+
+int main(void)
+{
+ int nerr;
+
+ nerr = Problem1();
+ nerr += Problem2();
+ PrintErrInfo(nerr);
+
+ return(0);
+}
+
+static int Problem1(void)
+{
+ realtype reltol=RTOL, abstol=ATOL, t, tout, ero, er;
+ int miter, flag, temp_flag, iout, nerr=0;
+ N_Vector y;
+ void *cvode_mem;
+ booleantype firstrun;
+ int qu;
+ realtype hu;
+
+ y = NULL;
+ cvode_mem = NULL;
+
+ y = N_VNew_Serial(P1_NEQ);
+ if(check_flag((void *)y, "N_VNew_Serial", 0)) return(1);
+ PrintIntro1();
+
+ cvode_mem = CVodeCreate(CV_ADAMS, CV_FUNCTIONAL);
+ if(check_flag((void *)cvode_mem, "CVodeCreate", 0)) return(1);
+
+ for (miter=FUNC; miter <= DIAG; miter++) {
+ ero = ZERO;
+ NV_Ith_S(y,0) = TWO;
+ NV_Ith_S(y,1) = ZERO;
+
+ firstrun = (miter==FUNC);
+ if (firstrun) {
+ flag = CVodeInit(cvode_mem, f1, P1_T0, y);
+ if(check_flag(&flag, "CVodeInit", 1)) return(1);
+ flag = CVodeSStolerances(cvode_mem, reltol, abstol);
+ if(check_flag(&flag, "CVodeSStolerances", 1)) return(1);
+ } else {
+ flag = CVodeSetIterType(cvode_mem, CV_NEWTON);
+ if(check_flag(&flag, "CVodeSetIterType", 1)) ++nerr;
+ flag = CVodeReInit(cvode_mem, P1_T0, y);
+ if(check_flag(&flag, "CVodeReInit", 1)) return(1);
+ }
+
+ flag = PrepareNextRun(cvode_mem, CV_ADAMS, miter, 0, 0);
+ if(check_flag(&flag, "PrepareNextRun", 1)) return(1);
+
+ PrintHeader1();
+
+ for(iout=1, tout=P1_T1; iout <= P1_NOUT; iout++, tout += P1_DTOUT) {
+ flag = CVode(cvode_mem, tout, y, &t, CV_NORMAL);
+ check_flag(&flag, "CVode", 1);
+ temp_flag = CVodeGetLastOrder(cvode_mem, &qu);
+ if(check_flag(&temp_flag, "CVodeGetLastOrder", 1)) ++nerr;
+ temp_flag = CVodeGetLastStep(cvode_mem, &hu);
+ if(check_flag(&temp_flag, "CVodeGetLastStep", 1)) ++nerr;
+ PrintOutput1(t, NV_Ith_S(y,0), NV_Ith_S(y,1), qu, hu);
+ if (flag != CV_SUCCESS) {
+ nerr++;
+ break;
+ }
+ if (iout%2 == 0) {
+ er = ABS(NV_Ith_S(y,0)) / abstol;
+ if (er > ero) ero = er;
+ if (er > P1_TOL_FACTOR) {
+ nerr++;
+ PrintErrOutput(P1_TOL_FACTOR);
+ }
+ }
+ }
+
+ PrintFinalStats(cvode_mem, miter, ero);
+ }
+
+ CVodeFree(&cvode_mem);
+
+ cvode_mem = CVodeCreate(CV_BDF, CV_FUNCTIONAL);
+ if(check_flag((void *)cvode_mem, "CVodeCreate", 0)) return(1);
+
+ for (miter=FUNC; miter <= DIAG; miter++) {
+ ero = ZERO;
+ NV_Ith_S(y,0) = TWO;
+ NV_Ith_S(y,1) = ZERO;
+
+ firstrun = (miter==FUNC);
+ if (firstrun) {
+ flag = CVodeInit(cvode_mem, f1, P1_T0, y);
+ if(check_flag(&flag, "CVodeInit", 1)) return(1);
+ flag = CVodeSStolerances(cvode_mem, reltol, abstol);
+ if(check_flag(&flag, "CVodeSStolerances", 1)) return(1);
+ } else {
+ flag = CVodeSetIterType(cvode_mem, CV_NEWTON);
+ if(check_flag(&flag, "CVodeSetIterType", 1)) ++nerr;
+ flag = CVodeReInit(cvode_mem, P1_T0, y);
+ if(check_flag(&flag, "CVodeReInit", 1)) return(1);
+ }
+
+ flag = PrepareNextRun(cvode_mem, CV_BDF, miter, 0, 0);
+ if(check_flag(&flag, "PrepareNextRun", 1)) return(1);
+
+ PrintHeader1();
+
+ for(iout=1, tout=P1_T1; iout <= P1_NOUT; iout++, tout += P1_DTOUT) {
+ flag = CVode(cvode_mem, tout, y, &t, CV_NORMAL);
+ check_flag(&flag, "CVode", 1);
+ temp_flag = CVodeGetLastOrder(cvode_mem, &qu);
+ if(check_flag(&temp_flag, "CVodeGetLastOrder", 1)) ++nerr;
+ temp_flag = CVodeGetLastStep(cvode_mem, &hu);
+ if(check_flag(&temp_flag, "CVodeGetLastStep", 1)) ++nerr;
+ PrintOutput1(t, NV_Ith_S(y,0), NV_Ith_S(y,1), qu, hu);
+ if (flag != CV_SUCCESS) {
+ nerr++;
+ break;
+ }
+ if (iout%2 == 0) {
+ er = ABS(NV_Ith_S(y,0)) / abstol;
+ if (er > ero) ero = er;
+ if (er > P1_TOL_FACTOR) {
+ nerr++;
+ PrintErrOutput(P1_TOL_FACTOR);
+ }
+ }
+ }
+
+ PrintFinalStats(cvode_mem, miter, ero);
+ }
+
+ CVodeFree(&cvode_mem);
+ N_VDestroy_Serial(y);
+
+ return(nerr);
+}
+
+static void PrintIntro1(void)
+{
+ printf("Demonstration program for CVODE package - direct linear solvers\n");
+ printf("\n\n");
+ printf("Problem 1: Van der Pol oscillator\n");
+ printf(" xdotdot - 3*(1 - x^2)*xdot + x = 0, x(0) = 2, xdot(0) = 0\n");
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf(" neq = %d, reltol = %.2Lg, abstol = %.2Lg",
+ P1_NEQ, RTOL, ATOL);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf(" neq = %d, reltol = %.2lg, abstol = %.2lg",
+ P1_NEQ, RTOL, ATOL);
+#else
+ printf(" neq = %d, reltol = %.2g, abstol = %.2g",
+ P1_NEQ, RTOL, ATOL);
+#endif
+}
+
+static void PrintHeader1(void)
+{
+ printf("\n t x xdot qu hu \n");
+
+ return;
+}
+
+static void PrintOutput1(realtype t, realtype y0, realtype y1, int qu, realtype hu)
+{
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("%10.5Lf %12.5Le %12.5Le %2d %6.4Le\n", t, y0, y1, qu, hu);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("%10.5f %12.5le %12.5le %2d %6.4le\n", t, y0, y1, qu, hu);
+#else
+ printf("%10.5f %12.5e %12.5e %2d %6.4e\n", t, y0, y1, qu, hu);
+#endif
+
+ return;
+}
+
+static int f1(realtype t, N_Vector y, N_Vector ydot, void *user_data)
+{
+ realtype y0, y1;
+
+ y0 = NV_Ith_S(y,0);
+ y1 = NV_Ith_S(y,1);
+
+ NV_Ith_S(ydot,0) = y1;
+ NV_Ith_S(ydot,1) = (ONE - SQR(y0))* P1_ETA * y1 - y0;
+
+ 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)
+{
+ 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 - SQR(y0));
+
+ return(0);
+}
+
+static int Problem2(void)
+{
+ realtype reltol=RTOL, abstol=ATOL, t, tout, er, erm, ero;
+ int miter, flag, temp_flag, nerr=0;
+ N_Vector y;
+ void *cvode_mem;
+ booleantype firstrun;
+ int qu, iout;
+ realtype hu;
+
+ y = NULL;
+ cvode_mem = NULL;
+
+ y = N_VNew_Serial(P2_NEQ);
+ if(check_flag((void *)y, "N_VNew_Serial", 0)) return(1);
+
+ PrintIntro2();
+
+ cvode_mem = CVodeCreate(CV_ADAMS, CV_FUNCTIONAL);
+ if(check_flag((void *)cvode_mem, "CVodeCreate", 0)) return(1);
+
+ for (miter=FUNC; miter <= BAND_DQ; miter++) {
+ if ((miter==DENSE_USER) || (miter==DENSE_DQ)) continue;
+ ero = ZERO;
+ N_VConst(ZERO, y);
+ NV_Ith_S(y,0) = ONE;
+
+ firstrun = (miter==FUNC);
+ if (firstrun) {
+ flag = CVodeInit(cvode_mem, f2, P2_T0, y);
+ if(check_flag(&flag, "CVodeInit", 1)) return(1);
+ flag = CVodeSStolerances(cvode_mem, reltol, abstol);
+ if(check_flag(&flag, "CVodeSStolerances", 1)) return(1);
+ } else {
+ flag = CVodeSetIterType(cvode_mem, CV_NEWTON);
+ if(check_flag(&flag, "CVodeSetIterType", 1)) ++nerr;
+ flag = CVodeReInit(cvode_mem, P2_T0, y);
+ if(check_flag(&flag, "CVodeReInit", 1)) return(1);
+ }
+
+ flag = PrepareNextRun(cvode_mem, CV_ADAMS, miter, P2_MU, P2_ML);
+ if(check_flag(&flag, "PrepareNextRun", 1)) return(1);
+
+ PrintHeader2();
+
+ for(iout=1, tout=P2_T1; iout <= P2_NOUT; iout++, tout*=P2_TOUT_MULT) {
+ flag = CVode(cvode_mem, tout, y, &t, CV_NORMAL);
+ check_flag(&flag, "CVode", 1);
+ erm = MaxError(y, t);
+ temp_flag = CVodeGetLastOrder(cvode_mem, &qu);
+ if(check_flag(&temp_flag, "CVodeGetLastOrder", 1)) ++nerr;
+ temp_flag = CVodeGetLastStep(cvode_mem, &hu);
+ if(check_flag(&temp_flag, "CVodeGetLastStep", 1)) ++nerr;
+ PrintOutput2(t, erm, qu, hu);
+ if (flag != CV_SUCCESS) {
+ nerr++;
+ break;
+ }
+ er = erm / abstol;
+ if (er > ero) ero = er;
+ if (er > P2_TOL_FACTOR) {
+ nerr++;
+ PrintErrOutput(P2_TOL_FACTOR);
+ }
+ }
+
+ PrintFinalStats(cvode_mem, miter, ero);
+ }
+
+ CVodeFree(&cvode_mem);
+
+ cvode_mem = CVodeCreate(CV_BDF, CV_FUNCTIONAL);
+ if(check_flag((void *)cvode_mem, "CVodeCreate", 0)) return(1);
+
+ for (miter=FUNC; miter <= BAND_DQ; miter++) {
+ if ((miter==DENSE_USER) || (miter==DENSE_DQ)) continue;
+ ero = ZERO;
+ N_VConst(ZERO, y);
+ NV_Ith_S(y,0) = ONE;
+
+ firstrun = (miter==FUNC);
+ if (firstrun) {
+ flag = CVodeInit(cvode_mem, f2, P2_T0, y);
+ if(check_flag(&flag, "CVodeInit", 1)) return(1);
+ flag = CVodeSStolerances(cvode_mem, reltol, abstol);
+ if(check_flag(&flag, "CVodeSStolerances", 1)) return(1);
+ } else {
+ flag = CVodeSetIterType(cvode_mem, CV_NEWTON);
+ if(check_flag(&flag, "CVodeSetIterType", 1)) ++nerr;
+ flag = CVodeReInit(cvode_mem, P2_T0, y);
+ if(check_flag(&flag, "CVodeReInit", 1)) return(1);
+ }
+
+ flag = PrepareNextRun(cvode_mem, CV_BDF, miter, P2_MU, P2_ML);
+ if(check_flag(&flag, "PrepareNextRun", 1)) return(1);
+
+ PrintHeader2();
+
+ for(iout=1, tout=P2_T1; iout <= P2_NOUT; iout++, tout*=P2_TOUT_MULT) {
+ flag = CVode(cvode_mem, tout, y, &t, CV_NORMAL);
+ check_flag(&flag, "CVode", 1);
+ erm = MaxError(y, t);
+ temp_flag = CVodeGetLastOrder(cvode_mem, &qu);
+ if(check_flag(&temp_flag, "CVodeGetLastOrder", 1)) ++nerr;
+ temp_flag = CVodeGetLastStep(cvode_mem, &hu);
+ if(check_flag(&temp_flag, "CVodeGetLastStep", 1)) ++nerr;
+ PrintOutput2(t, erm, qu, hu);
+ if (flag != CV_SUCCESS) {
+ nerr++;
+ break;
+ }
+ er = erm / abstol;
+ if (er > ero) ero = er;
+ if (er > P2_TOL_FACTOR) {
+ nerr++;
+ PrintErrOutput(P2_TOL_FACTOR);
+ }
+ }
+
+ PrintFinalStats(cvode_mem, miter, ero);
+ }
+
+ CVodeFree(&cvode_mem);
+ N_VDestroy_Serial(y);
+
+ return(nerr);
+}
+
+static void PrintIntro2(void)
+{
+ printf("\n\n-------------------------------------------------------------");
+ printf("\n-------------------------------------------------------------");
+ printf("\n\nProblem 2: ydot = A * y, where A is a banded lower\n");
+ printf("triangular matrix derived from 2-D advection PDE\n\n");
+ printf(" neq = %d, ml = %d, mu = %d\n", P2_NEQ, P2_ML, P2_MU);
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf(" itol = %s, reltol = %.2Lg, abstol = %.2Lg", "CV_SS", RTOL, ATOL);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf(" itol = %s, reltol = %.2lg, abstol = %.2lg", "CV_SS", RTOL, ATOL);
+#else
+ printf(" itol = %s, reltol = %.2g, abstol = %.2g", "CV_SS", RTOL, ATOL);
+#endif
+ printf("\n t max.err qu hu \n");
+}
+
+static void PrintHeader2(void)
+{
+ printf("\n t max.err qu hu \n");
+
+ return;
+}
+
+static void PrintOutput2(realtype t, realtype erm, int qu, realtype hu)
+{
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("%10.3Lf %12.4Le %2d %12.4Le\n", t, erm, qu, hu);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("%10.3f %12.4le %2d %12.4le\n", t, erm, qu, hu);
+#else
+ printf("%10.3f %12.4e %2d %12.4e\n", t, erm, qu, hu);
+#endif
+
+ return;
+}
+
+static int f2(realtype t, N_Vector y, N_Vector ydot, void *user_data)
+{
+ long int i, j, k;
+ realtype d, *ydata, *dydata;
+
+ ydata = NV_DATA_S(y);
+ dydata = NV_DATA_S(ydot);
+
+ /*
+ Excluding boundaries,
+
+ ydot = f = -2 y + alpha1 * y + alpha2 * y
+ i,j i,j i,j i-1,j i,j-1
+ */
+
+ for (j=0; j < P2_MESHY; j++) {
+ for (i=0; i < P2_MESHX; i++) {
+ k = i + j * P2_MESHX;
+ d = -TWO*ydata[k];
+ if (i != 0) d += P2_ALPH1 * ydata[k-1];
+ if (j != 0) d += P2_ALPH2 * ydata[k-P2_MESHX];
+ dydata[k] = d;
+ }
+ }
+
+ 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)
+{
+ int i, j, k;
+ realtype *kthCol;
+
+ /*
+ The components of f(t,y) which depend on y are
+ i,j
+ f , f , and f :
+ i,j i+1,j i,j+1
+
+ f = -2 y + alpha1 * y + alpha2 * y
+ i,j i,j i-1,j i,j-1
+
+ f = -2 y + alpha1 * y + alpha2 * y
+ i+1,j i+1,j i,j i+1,j-1
+
+ f = -2 y + alpha1 * y + alpha2 * y
+ i,j+1 i,j+1 i-1,j+1 i,j
+ */
+
+ 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;
+ }
+ }
+
+ return(0);
+}
+
+static realtype MaxError(N_Vector y, realtype t)
+{
+ long int i, j, k;
+ realtype *ydata, er, ex=ZERO, yt, maxError=ZERO, ifact_inv, jfact_inv=ONE;
+
+ if (t == ZERO) return(ZERO);
+
+ ydata = NV_DATA_S(y);
+ if (t <= THIRTY) ex = EXP(-TWO*t);
+
+ for (j = 0; j < P2_MESHY; j++) {
+ ifact_inv = ONE;
+ for (i = 0; i < P2_MESHX; i++) {
+ k = i + j * P2_MESHX;
+ yt = RPowerI(t,i+j) * ex * ifact_inv * jfact_inv;
+ er = ABS(ydata[k] - yt);
+ if (er > maxError) maxError = er;
+ ifact_inv /= (i+1);
+ }
+ jfact_inv /= (j+1);
+ }
+ return(maxError);
+}
+
+static int PrepareNextRun(void *cvode_mem, int lmm, int miter,
+ long int mu, long int ml)
+{
+ int flag = CV_SUCCESS;
+
+ printf("\n\n-------------------------------------------------------------");
+
+ printf("\n\nLinear Multistep Method : ");
+ if (lmm == CV_ADAMS) {
+ printf("ADAMS\n");
+ } else {
+ printf("BDF\n");
+ }
+
+ printf("Iteration : ");
+ if (miter == FUNC) {
+ printf("FUNCTIONAL\n");
+ } 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);
+ break;
+ case DENSE_DQ :
+ printf("Dense, Difference Quotient Jacobian\n");
+ flag = CVDlsSetDenseJacFn(cvode_mem, NULL);
+ check_flag(&flag, "CVDlsSetDenseJacFn", 1);
+ break;
+ case DIAG :
+ printf("Diagonal Jacobian\n");
+ flag = CVDiag(cvode_mem);
+ check_flag(&flag, "CVDiag", 1);
+ break;
+ 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);
+ break;
+ case BAND_DQ :
+ printf("Band, Difference Quotient Jacobian\n");
+ flag = CVDlsSetBandJacFn(cvode_mem, NULL);
+ check_flag(&flag, "CVDlsSetBandJacFn", 1);
+ break;
+ }
+ }
+
+ return(flag);
+}
+
+static void PrintErrOutput(realtype tol_factor)
+{
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("\n\n Error exceeds %Lg * tolerance \n\n", tol_factor);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("\n\n Error exceeds %lg * tolerance \n\n", tol_factor);
+#else
+ printf("\n\n Error exceeds %g * tolerance \n\n", tol_factor);
+#endif
+
+ return;
+}
+
+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;
+ 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);
+
+ 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(" Number of steps = %4ld \n", nst);
+ printf(" Number of f-s = %4ld \n", nfe);
+ printf(" Number of setups = %4ld \n", nsetups);
+ printf(" Number of nonlinear iterations = %4ld \n", nni);
+ printf(" Number of nonlinear convergence failures = %4ld \n", ncfn);
+ printf(" Number of error test failures = %4ld \n\n",netf);
+
+ if (miter != FUNC) {
+ switch(miter) {
+ case DENSE_USER :
+ case DENSE_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 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 :
+ 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 f evals. in linear solver = %4ld \n\n", nfeLS);
+ }
+
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf(" Error overrun = %.3Lf \n", ero);
+#else
+ printf(" Error overrun = %.3f \n", ero);
+#endif
+}
+
+static void PrintErrInfo(int nerr)
+{
+ printf("\n\n-------------------------------------------------------------");
+ printf("\n-------------------------------------------------------------");
+ printf("\n\n Number of errors encountered = %d \n", nerr);
+
+ 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, 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/serial/cvDirectDemo_ls.out b/examples/cvode/serial/cvDirectDemo_ls.out
new file mode 100644
index 0000000..517e697
--- /dev/null
+++ b/examples/cvode/serial/cvDirectDemo_ls.out
@@ -0,0 +1,502 @@
+Demonstration program for CVODE package - direct linear solvers
+
+
+Problem 1: Van der Pol oscillator
+ xdotdot - 3*(1 - x^2)*xdot + x = 0, x(0) = 2, xdot(0) = 0
+ neq = 2, itol = CV_SS, reltol = 0, abstol = 1e-06
+
+-------------------------------------------------------------
+
+Linear Multistep Method : ADAMS
+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
+ 5.82239 -1.68010e+00 2.91060e-01 4 1.4079e-01
+ 8.03716 9.57611e-05 3.16900e+00 5 2.0348e-02
+
+ Final statistics for this run:
+
+ CVode real workspace length = 123
+ CVode integer workspace length = 57
+ Number of steps = 196
+ Number of f-s = 391
+ Number of setups = 0
+ Number of nonlinear iterations = 387
+ Number of nonlinear convergence failures = 0
+ Number of error test failures = 15
+
+ Error overrun = 95.761
+
+
+-------------------------------------------------------------
+
+Linear Multistep Method : ADAMS
+Iteration : NEWTON
+Linear Solver : Dense, User-Supplied Jacobian
+
+ t x xdot qu hu
+ 1.39284 1.68010e+00 -2.91056e-01 7 6.5178e-02
+ 3.60761 2.42943e-06 -3.16870e+00 7 2.0626e-02
+ 5.82239 -1.68010e+00 2.91062e-01 7 1.3038e-01
+ 8.03716 1.99078e-05 3.16879e+00 7 2.3923e-02
+
+ Final statistics for this run:
+
+ CVode real workspace length = 123
+ CVode integer workspace length = 57
+ Number of steps = 266
+ Number of f-s = 366
+ Number of setups = 46
+ Number of nonlinear iterations = 362
+ 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
+ Number of f evals. in linear solver = 0
+
+ Error overrun = 19.908
+
+
+-------------------------------------------------------------
+
+Linear Multistep Method : ADAMS
+Iteration : NEWTON
+Linear Solver : Dense, Difference Quotient Jacobian
+
+ t x xdot qu hu
+ 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
+
+ Final statistics for this run:
+
+ CVode real workspace length = 123
+ CVode integer workspace length = 57
+ Number of steps = 195
+ Number of f-s = 268
+ Number of setups = 34
+ Number of nonlinear iterations = 264
+ 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
+ Number of f evals. in linear solver = 8
+
+ Error overrun = 22.805
+
+
+-------------------------------------------------------------
+
+Linear Multistep Method : ADAMS
+Iteration : NEWTON
+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
+
+ 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 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
+
+ Error overrun = 82.136
+
+
+-------------------------------------------------------------
+
+Linear Multistep Method : BDF
+Iteration : FUNCTIONAL
+
+ t x xdot qu hu
+ 1.39284 1.68010e+00 -2.91056e-01 4 9.6100e-02
+ 3.60761 -1.35636e-04 -3.16912e+00 5 1.5675e-02
+ 5.82239 -1.68009e+00 2.91063e-01 5 1.1210e-01
+ 8.03716 2.20969e-04 3.16937e+00 5 1.4732e-02
+
+ Final statistics for this run:
+
+ CVode real workspace length = 109
+ CVode integer workspace length = 50
+ Number of steps = 262
+ Number of f-s = 498
+ Number of setups = 0
+ Number of nonlinear iterations = 494
+ Number of nonlinear convergence failures = 0
+ Number of error test failures = 22
+
+ Error overrun = 220.969
+
+
+-------------------------------------------------------------
+
+Linear Multistep Method : BDF
+Iteration : NEWTON
+Linear Solver : Dense, User-Supplied Jacobian
+
+ t x xdot qu hu
+ 1.39284 1.68010e+00 -2.91056e-01 5 1.1991e-01
+ 3.60761 -5.46907e-05 -3.16886e+00 5 1.6403e-02
+ 5.82239 -1.68010e+00 2.91061e-01 4 1.0146e-01
+ 8.03716 1.54312e-04 3.16917e+00 4 9.5378e-03
+
+ Final statistics for this run:
+
+ CVode real workspace length = 109
+ CVode integer workspace length = 50
+ Number of steps = 265
+ Number of f-s = 358
+ Number of setups = 40
+ Number of nonlinear iterations = 354
+ 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
+ Number of f evals. in linear solver = 0
+
+ Error overrun = 154.312
+
+
+-------------------------------------------------------------
+
+Linear Multistep Method : BDF
+Iteration : NEWTON
+Linear Solver : Dense, Difference Quotient Jacobian
+
+ t x xdot qu hu
+ 1.39284 1.68010e+00 -2.91058e-01 4 8.1067e-02
+ 3.60761 -5.84200e-05 -3.16886e+00 4 1.1360e-02
+ 5.82239 -1.68010e+00 2.91062e-01 5 6.4941e-02
+ 8.03716 9.61737e-05 3.16899e+00 5 1.5216e-02
+
+ Final statistics for this run:
+
+ CVode real workspace length = 109
+ CVode integer workspace length = 50
+ Number of steps = 276
+ Number of f-s = 367
+ Number of setups = 40
+ Number of nonlinear iterations = 363
+ 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
+ Number of f evals. in linear solver = 12
+
+ Error overrun = 96.174
+
+
+-------------------------------------------------------------
+
+Linear Multistep Method : BDF
+Iteration : NEWTON
+Linear Solver : Diagonal Jacobian
+
+ t x xdot qu hu
+ 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
+
+ Final statistics for this run:
+
+ CVode real workspace length = 109
+ CVode integer workspace length = 50
+ Number of steps = 266
+ Number of f-s = 360
+ Number of setups = 39
+ Number of nonlinear iterations = 356
+ Number of nonlinear convergence failures = 0
+ Number of error test failures = 17
+
+ Linear solver real workspace length = 6
+ Linear solver integer workspace length = 3
+ Number of Jacobian evaluations = 39
+ Number of f evals. in linear solver = 39
+
+ Error overrun = 166.644
+
+
+-------------------------------------------------------------
+-------------------------------------------------------------
+
+Problem 2: ydot = A * y, where A is a banded lower
+triangular matrix derived from 2-D advection PDE
+
+ neq = 25, ml = 5, mu = 0
+ itol = CV_SS, reltol = 0, abstol = 1e-06
+ t max.err qu hu
+
+
+-------------------------------------------------------------
+
+Linear Multistep Method : ADAMS
+Iteration : FUNCTIONAL
+
+ t max.err qu hu
+ 0.010 1.4690e-07 3 1.1459e-02
+ 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
+
+ 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 setups = 0
+ Number of nonlinear iterations = 597
+ Number of nonlinear convergence failures = 79
+ Number of error test failures = 0
+
+ Error overrun = 1.221
+
+
+-------------------------------------------------------------
+
+Linear Multistep Method : ADAMS
+Iteration : NEWTON
+Linear Solver : Diagonal Jacobian
+
+ t max.err qu hu
+ 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
+
+ Final statistics for this run:
+
+ CVode real workspace length = 514
+ CVode integer workspace length = 57
+ Number of steps = 154
+ Number of f-s = 219
+ Number of setups = 33
+ Number of nonlinear iterations = 215
+ Number of nonlinear convergence failures = 0
+ Number of error test failures = 5
+
+ Linear solver real workspace length = 75
+ Linear solver integer workspace length = 3
+ Number of Jacobian evaluations = 33
+ Number of f evals. in linear solver = 33
+
+ Error overrun = 4.233
+
+
+-------------------------------------------------------------
+
+Linear Multistep Method : ADAMS
+Iteration : NEWTON
+Linear Solver : Band, User-Supplied Jacobian
+
+ t max.err qu hu
+ 0.010 1.3670e-07 3 1.2164e-02
+ 0.100 4.7920e-07 4 4.2115e-02
+ 1.000 2.5077e-07 6 1.0365e-01
+ 10.000 6.0790e-07 4 4.7206e-01
+ 100.000 5.7390e-08 2 1.0750e+01
+
+ Final statistics for this run:
+
+ CVode real workspace length = 514
+ CVode integer workspace length = 57
+ Number of steps = 149
+ Number of f-s = 184
+ Number of setups = 32
+ Number of nonlinear iterations = 180
+ 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
+ Number of f evals. in linear solver = 0
+
+ Error overrun = 0.608
+
+
+-------------------------------------------------------------
+
+Linear Multistep Method : ADAMS
+Iteration : NEWTON
+Linear Solver : Band, Difference Quotient Jacobian
+
+ t max.err qu hu
+ 0.010 1.4285e-07 3 1.3840e-02
+ 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
+
+ Final statistics for this run:
+
+ CVode real workspace length = 514
+ CVode integer workspace length = 57
+ Number of steps = 124
+ Number of f-s = 142
+ Number of setups = 24
+ Number of nonlinear iterations = 138
+ 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
+ Number of f evals. in linear solver = 18
+
+ Error overrun = 0.733
+
+
+-------------------------------------------------------------
+
+Linear Multistep Method : BDF
+Iteration : FUNCTIONAL
+
+ t max.err qu hu
+ 0.010 5.5931e-07 2 8.1257e-03
+ 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
+
+ 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 setups = 0
+ Number of nonlinear iterations = 694
+ Number of nonlinear convergence failures = 56
+ Number of error test failures = 1
+
+ Error overrun = 5.290
+
+
+-------------------------------------------------------------
+
+Linear Multistep Method : BDF
+Iteration : NEWTON
+Linear Solver : Diagonal Jacobian
+
+ t max.err qu hu
+ 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
+
+ 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
+
+ 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
+
+ Error overrun = 11.253
+
+
+-------------------------------------------------------------
+
+Linear Multistep Method : BDF
+Iteration : NEWTON
+Linear Solver : Band, User-Supplied Jacobian
+
+ t max.err qu hu
+ 0.010 5.6372e-07 2 8.1246e-03
+ 0.100 5.2784e-06 3 1.7819e-02
+ 1.000 1.8169e-06 5 6.0110e-02
+ 10.000 5.4997e-07 5 4.1661e-01
+ 100.000 1.7764e-09 2 2.9748e+01
+
+ Final statistics for this run:
+
+ CVode real workspace length = 339
+ CVode integer workspace length = 50
+ Number of steps = 119
+ Number of f-s = 144
+ Number of setups = 25
+ Number of nonlinear iterations = 140
+ 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
+ Number of f evals. in linear solver = 0
+
+ Error overrun = 5.278
+
+
+-------------------------------------------------------------
+
+Linear Multistep Method : BDF
+Iteration : NEWTON
+Linear Solver : Band, Difference Quotient Jacobian
+
+ t max.err qu hu
+ 0.010 5.6492e-07 2 8.1361e-03
+ 0.100 5.9968e-06 3 1.7105e-02
+ 1.000 1.6902e-06 5 8.7628e-02
+ 10.000 5.2314e-07 5 3.1091e-01
+ 100.000 1.4380e-09 2 2.1635e+01
+
+ Final statistics for this run:
+
+ CVode real workspace length = 339
+ CVode integer workspace length = 50
+ Number of steps = 121
+ Number of f-s = 145
+ Number of setups = 24
+ Number of nonlinear iterations = 141
+ 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
+ Number of f evals. in linear solver = 18
+
+ Error overrun = 5.997
+
+
+-------------------------------------------------------------
+-------------------------------------------------------------
+
+ Number of errors encountered = 0
diff --git a/examples/cvode/serial/cvDiurnal_kry.c b/examples/cvode/serial/cvDiurnal_kry.c
new file mode 100644
index 0000000..4075d25
--- /dev/null
+++ b/examples/cvode/serial/cvDiurnal_kry.c
@@ -0,0 +1,801 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.4 $
+ * $Date: 2010/12/01 22:51:32 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh and
+ * Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Example problem:
+ *
+ * An ODE system is generated from the following 2-species diurnal
+ * kinetics advection-diffusion PDE system in 2 space dimensions:
+ *
+ * dc(i)/dt = Kh*(d/dx)^2 c(i) + V*dc(i)/dx + (d/dy)(Kv(y)*dc(i)/dy)
+ * + Ri(c1,c2,t) for i = 1,2, where
+ * R1(c1,c2,t) = -q1*c1*c3 - q2*c1*c2 + 2*q3(t)*c3 + q4(t)*c2 ,
+ * R2(c1,c2,t) = q1*c1*c3 - q2*c1*c2 - q4(t)*c2 ,
+ * Kv(y) = Kv0*exp(y/5) ,
+ * Kh, V, Kv0, q1, q2, and c3 are constants, and q3(t) and q4(t)
+ * vary diurnally. The problem is posed on the square
+ * 0 <= x <= 20, 30 <= y <= 50 (all in km),
+ * with homogeneous Neumann boundary conditions, and for time t in
+ * 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 CVODE, with the BDF/GMRES
+ * method (i.e. using the CVSPGMR 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, SQR, EXP */
+
+/* Problem Constants */
+
+#define ZERO RCONST(0.0)
+#define ONE RCONST(1.0)
+#define TWO RCONST(2.0)
+
+#define NUM_SPECIES 2 /* number of species */
+#define KH RCONST(4.0e-6) /* horizontal diffusivity Kh */
+#define VEL RCONST(0.001) /* advection velocity V */
+#define KV0 RCONST(1.0e-8) /* coefficient in Kv(y) */
+#define Q1 RCONST(1.63e-16) /* coefficients q1, q2, c3 */
+#define Q2 RCONST(4.66e-16)
+#define C3 RCONST(3.7e16)
+#define A3 RCONST(22.62) /* coefficient in expression for q3(t) */
+#define A4 RCONST(7.601) /* coefficient in expression for q4(t) */
+#define C1_SCALE RCONST(1.0e6) /* coefficients in initial profiles */
+#define C2_SCALE RCONST(1.0e12)
+
+#define T0 ZERO /* initial time */
+#define NOUT 12 /* number of output times */
+#define TWOHR RCONST(7200.0) /* number of seconds in two hours */
+#define HALFDAY RCONST(4.32e4) /* number of seconds in a half day */
+#define PI RCONST(3.1415926535898) /* pi */
+
+#define XMIN ZERO /* grid boundaries in x */
+#define XMAX RCONST(20.0)
+#define YMIN RCONST(30.0) /* grid boundaries in y */
+#define YMAX RCONST(50.0)
+#define XMID RCONST(10.0) /* grid midpoints in x,y */
+#define YMID RCONST(40.0)
+
+#define MX 10 /* MX = number of x mesh points */
+#define MY 10 /* MY = number of y mesh points */
+#define NSMX 20 /* NSMX = NUM_SPECIES*MX */
+#define MM (MX*MY) /* MM = MX*MY */
+
+/* CVodeInit Constants */
+
+#define RTOL RCONST(1.0e-5) /* scalar relative tolerance */
+#define FLOOR RCONST(100.0) /* value of C1 or C2 at which tolerances */
+ /* change from relative to absolute */
+#define ATOL (RTOL*FLOOR) /* scalar absolute tolerance */
+#define NEQ (NUM_SPECIES*MM) /* NEQ = number of equations */
+
+/* User-defined vector and matrix accessor macros: IJKth, IJth */
+
+/* IJKth is defined in order to isolate the translation from the
+ mathematical 3-dimensional structure of the dependent variable vector
+ to the underlying 1-dimensional storage. IJth is defined in order to
+ write code which indexes into small dense matrices with a (row,column)
+ pair, where 1 <= row, column <= NUM_SPECIES.
+
+ 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 = NV_DATA_S(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 sundials_dense.h
+ work with matrices stored by column in a 2-dimensional array. In C,
+ arrays are indexed starting at 0, not 1. */
+
+#define IJKth(vdata,i,j,k) (vdata[i-1 + (j)*NUM_SPECIES + (k)*NSMX])
+#define IJth(a,i,j) (a[j-1][i-1])
+
+/* Type : UserData
+ contains preconditioner blocks, pivot arrays, and problem constants */
+
+typedef struct {
+ realtype **P[MX][MY], **Jbd[MX][MY];
+ long int *pivot[MX][MY];
+ realtype q4, om, dx, dy, hdco, haco, vdco;
+} *UserData;
+
+/* Private Helper Functions */
+
+static UserData AllocUserData(void);
+static void InitUserData(UserData data);
+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);
+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 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 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);
+
+
+/*
+ *-------------------------------
+ * Main Program
+ *-------------------------------
+ */
+
+int main()
+{
+ realtype abstol, reltol, t, tout;
+ N_Vector u;
+ UserData data;
+ void *cvode_mem;
+ int iout, flag;
+
+ u = NULL;
+ data = NULL;
+ cvode_mem = NULL;
+
+ /* Allocate memory, and set problem data, initial values, tolerances */
+ u = N_VNew_Serial(NEQ);
+ if(check_flag((void *)u, "N_VNew_Serial", 0)) return(1);
+ data = AllocUserData();
+ if(check_flag((void *)data, "AllocUserData", 2)) return(1);
+ InitUserData(data);
+ SetInitialProfiles(u, data->dx, data->dy);
+ abstol=ATOL;
+ reltol=RTOL;
+
+ /* 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);
+
+ /* Set the pointer to user-defined data */
+ flag = CVodeSetUserData(cvode_mem, data);
+ if(check_flag(&flag, "CVodeSetUserData", 1)) 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
+ * 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 tolerances */
+ 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);
+
+ /* set the JAcobian-times-vector function */
+ flag = CVSpilsSetJacTimesVecFn(cvode_mem, jtv);
+ if(check_flag(&flag, "CVSpilsSetJacTimesVecFn", 1)) return(1);
+
+ /* Set modified Gram-Schmidt orthogonalization */
+ flag = CVSpilsSetGSType(cvode_mem, MODIFIED_GS);
+ if(check_flag(&flag, "CVSpilsSetGSType", 1)) return(1);
+
+ /* Set the preconditioner solve and setup functions */
+ flag = CVSpilsSetPreconditioner(cvode_mem, Precond, PSolve);
+ if(check_flag(&flag, "CVSpilsSetPreconditioner", 1)) return(1);
+
+ /* In loop over output points, call CVode, print results, test for error */
+ printf(" \n2-species diurnal advection-diffusion problem\n\n");
+ for (iout=1, tout = TWOHR; iout <= NOUT; iout++, tout += TWOHR) {
+ flag = CVode(cvode_mem, tout, u, &t, CV_NORMAL);
+ PrintOutput(cvode_mem, u, t);
+ if(check_flag(&flag, "CVode", 1)) break;
+ }
+
+ PrintFinalStats(cvode_mem);
+
+ /* Free memory */
+ N_VDestroy_Serial(u);
+ FreeUserData(data);
+ CVodeFree(&cvode_mem);
+
+ return(0);
+}
+
+/*
+ *-------------------------------
+ * Private helper functions
+ *-------------------------------
+ */
+
+/* Allocate memory for data structure of type UserData */
+
+static UserData AllocUserData(void)
+{
+ int jx, jy;
+ UserData data;
+
+ data = (UserData) malloc(sizeof *data);
+
+ for (jx=0; jx < MX; jx++) {
+ 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);
+ }
+ }
+
+ return(data);
+}
+
+/* Load problem constants in data */
+
+static void InitUserData(UserData data)
+{
+ data->om = PI/HALFDAY;
+ data->dx = (XMAX-XMIN)/(MX-1);
+ data->dy = (YMAX-YMIN)/(MY-1);
+ data->hdco = KH/SQR(data->dx);
+ data->haco = VEL/(TWO*data->dx);
+ data->vdco = (ONE/SQR(data->dy))*KV0;
+}
+
+/* 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]);
+ destroyMat((data->Jbd)[jx][jy]);
+ destroyArray((data->pivot)[jx][jy]);
+ }
+ }
+
+ free(data);
+}
+
+/* Set initial conditions in u */
+
+static void SetInitialProfiles(N_Vector u, realtype dx, realtype dy)
+{
+ int jx, jy;
+ realtype x, y, cx, cy;
+ realtype *udata;
+
+ /* Set pointer to data array in vector u. */
+
+ udata = NV_DATA_S(u);
+
+ /* Load initial profiles of c1 and c2 into u vector */
+
+ for (jy=0; jy < MY; jy++) {
+ y = YMIN + jy*dy;
+ cy = SQR(RCONST(0.1)*(y - YMID));
+ cy = ONE - cy + RCONST(0.5)*SQR(cy);
+ for (jx=0; jx < MX; jx++) {
+ x = XMIN + jx*dx;
+ cx = SQR(RCONST(0.1)*(x - XMID));
+ cx = ONE - cx + RCONST(0.5)*SQR(cx);
+ IJKth(udata,1,jx,jy) = C1_SCALE*cx*cy;
+ IJKth(udata,2,jx,jy) = C2_SCALE*cx*cy;
+ }
+ }
+}
+
+/* Print current t, step count, order, stepsize, and sampled c1,c2 values */
+
+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 = NV_DATA_S(u);
+
+ flag = CVodeGetNumSteps(cvode_mem, &nst);
+ check_flag(&flag, "CVodeGetNumSteps", 1);
+ flag = CVodeGetLastOrder(cvode_mem, &qu);
+ check_flag(&flag, "CVodeGetLastOrder", 1);
+ flag = CVodeGetLastStep(cvode_mem, &hu);
+ check_flag(&flag, "CVodeGetLastStep", 1);
+
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("t = %.2Le no. steps = %ld order = %d stepsize = %.2Le\n",
+ t, nst, qu, hu);
+ printf("c1 (bot.left/middle/top rt.) = %12.3Le %12.3Le %12.3Le\n",
+ IJKth(udata,1,0,0), IJKth(udata,1,mxh,myh), IJKth(udata,1,mx1,my1));
+ printf("c2 (bot.left/middle/top rt.) = %12.3Le %12.3Le %12.3Le\n\n",
+ IJKth(udata,2,0,0), IJKth(udata,2,mxh,myh), IJKth(udata,2,mx1,my1));
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("t = %.2le no. steps = %ld order = %d stepsize = %.2le\n",
+ t, nst, qu, hu);
+ printf("c1 (bot.left/middle/top rt.) = %12.3le %12.3le %12.3le\n",
+ IJKth(udata,1,0,0), IJKth(udata,1,mxh,myh), IJKth(udata,1,mx1,my1));
+ printf("c2 (bot.left/middle/top rt.) = %12.3le %12.3le %12.3le\n\n",
+ IJKth(udata,2,0,0), IJKth(udata,2,mxh,myh), IJKth(udata,2,mx1,my1));
+#else
+ printf("t = %.2e no. steps = %ld order = %d stepsize = %.2e\n",
+ t, nst, qu, hu);
+ printf("c1 (bot.left/middle/top rt.) = %12.3e %12.3e %12.3e\n",
+ IJKth(udata,1,0,0), IJKth(udata,1,mxh,myh), IJKth(udata,1,mx1,my1));
+ printf("c2 (bot.left/middle/top rt.) = %12.3e %12.3e %12.3e\n\n",
+ IJKth(udata,2,0,0), IJKth(udata,2,mxh,myh), IJKth(udata,2,mx1,my1));
+#endif
+}
+
+/* Get and print final statistics */
+
+static void PrintFinalStats(void *cvode_mem)
+{
+ long int lenrw, leniw ;
+ long int 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);
+}
+
+/* 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, 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);
+}
+
+/*
+ *-------------------------------
+ * Functions called by the solver
+ *-------------------------------
+ */
+
+/* f routine. Compute RHS function f(t,u). */
+
+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 jx, jy, idn, iup, ileft, iright;
+ UserData data;
+
+ data = (UserData) user_data;
+ udata = NV_DATA_S(u);
+ dudata = NV_DATA_S(udot);
+
+ /* Set diurnal rate coefficients. */
+
+ s = sin(data->om*t);
+ if (s > ZERO) {
+ q3 = EXP(-A3/s);
+ data->q4 = EXP(-A4/s);
+ } else {
+ q3 = ZERO;
+ data->q4 = ZERO;
+ }
+
+ /* Make local copies of problem variables, for efficiency. */
+
+ q4coef = data->q4;
+ dely = data->dy;
+ verdco = data->vdco;
+ hordco = data->hdco;
+ horaco = data->haco;
+
+ /* Loop over all grid points. */
+
+ for (jy=0; jy < MY; jy++) {
+
+ /* Set vertical diffusion coefficients at jy +- 1/2 */
+
+ ydn = YMIN + (jy - RCONST(0.5))*dely;
+ yup = ydn + dely;
+ cydn = verdco*EXP(RCONST(0.2)*ydn);
+ cyup = verdco*EXP(RCONST(0.2)*yup);
+ idn = (jy == 0) ? 1 : -1;
+ iup = (jy == MY-1) ? -1 : 1;
+ for (jx=0; jx < MX; jx++) {
+
+ /* Extract c1 and c2, and set kinetic rate terms. */
+
+ c1 = IJKth(udata,1,jx,jy);
+ c2 = IJKth(udata,2,jx,jy);
+ qq1 = Q1*c1*C3;
+ qq2 = Q2*c1*c2;
+ qq3 = q3*C3;
+ qq4 = q4coef*c2;
+ rkin1 = -qq1 - qq2 + TWO*qq3 + qq4;
+ rkin2 = qq1 - qq2 - qq4;
+
+ /* Set vertical diffusion terms. */
+
+ c1dn = IJKth(udata,1,jx,jy+idn);
+ c2dn = IJKth(udata,2,jx,jy+idn);
+ c1up = IJKth(udata,1,jx,jy+iup);
+ c2up = IJKth(udata,2,jx,jy+iup);
+ vertd1 = cyup*(c1up - c1) - cydn*(c1 - c1dn);
+ vertd2 = cyup*(c2up - c2) - cydn*(c2 - c2dn);
+
+ /* Set horizontal diffusion and advection terms. */
+
+ ileft = (jx == 0) ? 1 : -1;
+ iright =(jx == MX-1) ? -1 : 1;
+ c1lt = IJKth(udata,1,jx+ileft,jy);
+ c2lt = IJKth(udata,2,jx+ileft,jy);
+ c1rt = IJKth(udata,1,jx+iright,jy);
+ c2rt = IJKth(udata,2,jx+iright,jy);
+ hord1 = hordco*(c1rt - TWO*c1 + c1lt);
+ hord2 = hordco*(c2rt - TWO*c2 + c2lt);
+ horad1 = horaco*(c1rt - c1lt);
+ horad2 = horaco*(c2rt - c2lt);
+
+ /* Load all terms into udot. */
+
+ IJKth(dudata, 1, jx, jy) = vertd1 + hord1 + horad1 + rkin1;
+ IJKth(dudata, 2, jx, jy) = vertd2 + hord2 + horad2 + rkin2;
+ }
+ }
+
+ 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)
+{
+ realtype c1, c2, c1dn, c2dn, c1up, c2up, c1lt, c2lt, c1rt, c2rt;
+ realtype v1, v2, v1dn, v2dn, v1up, v2up, v1lt, v2lt, v1rt, v2rt;
+ realtype Jv1, Jv2;
+ realtype cydn, cyup;
+ realtype s, ydn, yup;
+ realtype q4coef, dely, verdco, hordco, horaco;
+ int jx, jy, idn, iup, ileft, iright;
+ realtype *udata, *vdata, *Jvdata;
+ UserData data;
+
+ data = (UserData) user_data;
+
+ udata = NV_DATA_S(u);
+ vdata = NV_DATA_S(v);
+ Jvdata = NV_DATA_S(Jv);
+
+ /* Set diurnal rate coefficients. */
+
+ s = sin(data->om*t);
+ if (s > ZERO) {
+ data->q4 = EXP(-A4/s);
+ } else {
+ data->q4 = ZERO;
+ }
+
+ /* Make local copies of problem variables, for efficiency. */
+
+ q4coef = data->q4;
+ dely = data->dy;
+ verdco = data->vdco;
+ hordco = data->hdco;
+ horaco = data->haco;
+
+ /* Loop over all grid points. */
+
+ for (jy=0; jy < MY; jy++) {
+
+ /* Set vertical diffusion coefficients at jy +- 1/2 */
+
+ ydn = YMIN + (jy - RCONST(0.5))*dely;
+ yup = ydn + dely;
+
+ cydn = verdco*EXP(RCONST(0.2)*ydn);
+ cyup = verdco*EXP(RCONST(0.2)*yup);
+
+ idn = (jy == 0) ? 1 : -1;
+ iup = (jy == MY-1) ? -1 : 1;
+
+ for (jx=0; jx < MX; jx++) {
+
+ Jv1 = ZERO;
+ Jv2 = ZERO;
+
+ /* Extract c1 and c2 at the current location and at neighbors */
+
+ c1 = IJKth(udata,1,jx,jy);
+ c2 = IJKth(udata,2,jx,jy);
+
+ v1 = IJKth(vdata,1,jx,jy);
+ v2 = IJKth(vdata,2,jx,jy);
+
+ c1dn = IJKth(udata,1,jx,jy+idn);
+ c2dn = IJKth(udata,2,jx,jy+idn);
+ c1up = IJKth(udata,1,jx,jy+iup);
+ c2up = IJKth(udata,2,jx,jy+iup);
+
+ v1dn = IJKth(vdata,1,jx,jy+idn);
+ v2dn = IJKth(vdata,2,jx,jy+idn);
+ v1up = IJKth(vdata,1,jx,jy+iup);
+ v2up = IJKth(vdata,2,jx,jy+iup);
+
+ ileft = (jx == 0) ? 1 : -1;
+ iright =(jx == MX-1) ? -1 : 1;
+
+ c1lt = IJKth(udata,1,jx+ileft,jy);
+ c2lt = IJKth(udata,2,jx+ileft,jy);
+ c1rt = IJKth(udata,1,jx+iright,jy);
+ c2rt = IJKth(udata,2,jx+iright,jy);
+
+ v1lt = IJKth(vdata,1,jx+ileft,jy);
+ v2lt = IJKth(vdata,2,jx+ileft,jy);
+ v1rt = IJKth(vdata,1,jx+iright,jy);
+ v2rt = IJKth(vdata,2,jx+iright,jy);
+
+ /* Set kinetic rate terms. */
+
+ //rkin1 = -Q1*C3 * c1 - Q2 * c1*c2 + q4coef * c2 + TWO*C3*q3;
+ //rkin2 = Q1*C3 * c1 - Q2 * c1*c2 - q4coef * c2;
+
+ Jv1 += -(Q1*C3 + Q2*c2) * v1 + (q4coef - Q2*c1) * v2;
+ Jv2 += (Q1*C3 - Q2*c2) * v1 - (q4coef + Q2*c1) * v2;
+
+ /* Set vertical diffusion terms. */
+
+ //vertd1 = -(cyup+cydn) * c1 + cyup * c1up + cydn * c1dn;
+ //vertd2 = -(cyup+cydn) * c2 + cyup * c2up + cydn * c2dn;
+
+ Jv1 += -(cyup+cydn) * v1 + cyup * v1up + cydn * v1dn;
+ Jv2 += -(cyup+cydn) * v2 + cyup * v2up + cydn * v2dn;
+
+ /* Set horizontal diffusion and advection terms. */
+
+ //hord1 = hordco*(c1rt - TWO*c1 + c1lt);
+ //hord2 = hordco*(c2rt - TWO*c2 + c2lt);
+
+ Jv1 += hordco*(v1rt - TWO*v1 + v1lt);
+ Jv2 += hordco*(v2rt - TWO*v2 + v2lt);
+
+ //horad1 = horaco*(c1rt - c1lt);
+ //horad2 = horaco*(c2rt - c2lt);
+
+ Jv1 += horaco*(v1rt - v1lt);
+ Jv2 += horaco*(v2rt - v2lt);
+
+ /* Load two components of J*v */
+
+ //IJKth(dudata, 1, jx, jy) = vertd1 + hord1 + horad1 + rkin1;
+ //IJKth(dudata, 2, jx, jy) = vertd2 + hord2 + horad2 + rkin2;
+
+ IJKth(Jvdata, 1, jx, jy) = Jv1;
+ IJKth(Jvdata, 2, jx, jy) = Jv2;
+
+ }
+
+ }
+
+ return(0);
+
+}
+
+
+/* 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 c1, c2, cydn, cyup, diag, ydn, yup, q4coef, dely, verdco, hordco;
+ realtype **(*P)[MY], **(*Jbd)[MY];
+ long int *(*pivot)[MY], ier;
+ int jx, jy;
+ realtype *udata, **a, **j;
+ UserData data;
+
+ /* Make local copies of pointers in user_data, and of pointer to u's data */
+
+ data = (UserData) user_data;
+ P = data->P;
+ Jbd = data->Jbd;
+ pivot = data->pivot;
+ udata = NV_DATA_S(u);
+
+ if (jok) {
+
+ /* jok = TRUE: 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;
+
+ }
+
+ else {
+ /* jok = FALSE: Generate Jbd from scratch and copy to P */
+
+ /* Make local copies of problem variables, for efficiency. */
+
+ q4coef = data->q4;
+ dely = data->dy;
+ verdco = data->vdco;
+ hordco = data->hdco;
+
+ /* Compute 2x2 diagonal Jacobian blocks (using q4 values
+ computed on the last f call). Load into P. */
+
+ for (jy=0; jy < MY; jy++) {
+ ydn = YMIN + (jy - RCONST(0.5))*dely;
+ yup = ydn + dely;
+ cydn = verdco*EXP(RCONST(0.2)*ydn);
+ cyup = verdco*EXP(RCONST(0.2)*yup);
+ diag = -(cydn + cyup + TWO*hordco);
+ for (jx=0; jx < MX; jx++) {
+ c1 = IJKth(udata,1,jx,jy);
+ c2 = IJKth(udata,2,jx,jy);
+ j = Jbd[jx][jy];
+ a = P[jx][jy];
+ IJth(j,1,1) = (-Q1*C3 - Q2*c2) + diag;
+ IJth(j,1,2) = -Q2*c1 + q4coef;
+ IJth(j,2,1) = Q1*C3 - Q2*c2;
+ IJth(j,2,2) = (-Q2*c1 - q4coef) + diag;
+ denseCopy(j, a, NUM_SPECIES, NUM_SPECIES);
+ }
+ }
+
+ *jcurPtr = TRUE;
+
+ }
+
+ /* Scale by -gamma */
+
+ for (jy=0; jy < MY; jy++)
+ for (jx=0; jx < MX; jx++)
+ denseScale(-gamma, P[jx][jy], NUM_SPECIES, NUM_SPECIES);
+
+ /* Add identity matrix and do LU decompositions on blocks in place. */
+
+ for (jx=0; jx < MX; jx++) {
+ for (jy=0; jy < MY; jy++) {
+ denseAddIdentity(P[jx][jy], NUM_SPECIES);
+ ier = denseGETRF(P[jx][jy], NUM_SPECIES, NUM_SPECIES, pivot[jx][jy]);
+ if (ier != 0) return(1);
+ }
+ }
+
+ return(0);
+}
+
+/* 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)
+{
+ realtype **(*P)[MY];
+ long int *(*pivot)[MY];
+ int jx, jy;
+ realtype *zdata, *v;
+ UserData data;
+
+ /* Extract the P and pivot arrays from user_data. */
+
+ data = (UserData) user_data;
+ P = data->P;
+ pivot = data->pivot;
+ zdata = NV_DATA_S(z);
+
+ N_VScale(ONE, r, z);
+
+ /* Solve the block-diagonal system Px = r using LU factors stored
+ in P and pivot data in pivot, and return the solution in z. */
+
+ for (jx=0; jx < MX; jx++) {
+ for (jy=0; jy < MY; jy++) {
+ v = &(IJKth(zdata, 1, jx, jy));
+ denseGETRS(P[jx][jy], NUM_SPECIES, pivot[jx][jy], v);
+ }
+ }
+
+ return(0);
+}
diff --git a/examples/cvode/serial/cvDiurnal_kry.out b/examples/cvode/serial/cvDiurnal_kry.out
new file mode 100644
index 0000000..8b02132
--- /dev/null
+++ b/examples/cvode/serial/cvDiurnal_kry.out
@@ -0,0 +1,63 @@
+
+2-species diurnal advection-diffusion problem
+
+t = 7.20e+03 no. steps = 219 order = 5 stepsize = 1.59e+02
+c1 (bot.left/middle/top rt.) = 1.047e+04 2.964e+04 1.119e+04
+c2 (bot.left/middle/top rt.) = 2.527e+11 7.154e+11 2.700e+11
+
+t = 1.44e+04 no. steps = 251 order = 5 stepsize = 3.77e+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 = 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
+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
+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
+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
+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
+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
+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
+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
+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
+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
+ncfn = 0 ncfl = 0
+
diff --git a/examples/cvode/serial/cvDiurnal_kry_bp.c b/examples/cvode/serial/cvDiurnal_kry_bp.c
new file mode 100644
index 0000000..d847dc4
--- /dev/null
+++ b/examples/cvode/serial/cvDiurnal_kry_bp.c
@@ -0,0 +1,530 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.2 $
+ * $Date: 2010/12/01 22:51:32 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh and
+ * Radu Serban @LLNL
+ * -----------------------------------------------------------------
+ * Example problem:
+ *
+ * An ODE system is generated from the following 2-species diurnal
+ * kinetics advection-diffusion PDE system in 2 space dimensions:
+ *
+ * dc(i)/dt = Kh*(d/dx)^2 c(i) + V*dc(i)/dx + (d/dy)(Kv(y)*dc(i)/dy)
+ * + Ri(c1,c2,t) for i = 1,2, where
+ * R1(c1,c2,t) = -q1*c1*c3 - q2*c1*c2 + 2*q3(t)*c3 + q4(t)*c2 ,
+ * R2(c1,c2,t) = q1*c1*c3 - q2*c1*c2 - q4(t)*c2 ,
+ * Kv(y) = Kv0*exp(y/5) ,
+ * Kh, V, Kv0, q1, q2, and c3 are constants, and q3(t) and q4(t)
+ * vary diurnally. The problem is posed on the square
+ * 0 <= x <= 20, 30 <= y <= 50 (all in km),
+ * with homogeneous Neumann boundary conditions, and for time t in
+ * 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 CVODE, with the BDF/GMRES
+ * method (i.e. using the CVSPGMR linear solver) and a banded
+ * 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, SQR, and EXP */
+
+/* Problem Constants */
+
+#define ZERO RCONST(0.0)
+#define ONE RCONST(1.0)
+#define TWO RCONST(2.0)
+
+#define NUM_SPECIES 2 /* number of species */
+#define KH RCONST(4.0e-6) /* horizontal diffusivity Kh */
+#define VEL RCONST(0.001) /* advection velocity V */
+#define KV0 RCONST(1.0e-8) /* coefficient in Kv(y) */
+#define Q1 RCONST(1.63e-16) /* coefficients q1, q2, c3 */
+#define Q2 RCONST(4.66e-16)
+#define C3 RCONST(3.7e16)
+#define A3 RCONST(22.62) /* coefficient in expression for q3(t) */
+#define A4 RCONST(7.601) /* coefficient in expression for q4(t) */
+#define C1_SCALE RCONST(1.0e6) /* coefficients in initial profiles */
+#define C2_SCALE RCONST(1.0e12)
+
+#define T0 ZERO /* initial time */
+#define NOUT 12 /* number of output times */
+#define TWOHR RCONST(7200.0) /* number of seconds in two hours */
+#define HALFDAY RCONST(4.32e4) /* number of seconds in a half day */
+#define PI RCONST(3.1415926535898) /* pi */
+
+#define XMIN ZERO /* grid boundaries in x */
+#define XMAX RCONST(20.0)
+#define YMIN RCONST(30.0) /* grid boundaries in y */
+#define YMAX RCONST(50.0)
+#define XMID RCONST(10.0) /* grid midpoints in x,y */
+#define YMID RCONST(40.0)
+
+#define MX 10 /* MX = number of x mesh points */
+#define MY 10 /* MY = number of y mesh points */
+#define NSMX 20 /* NSMX = NUM_SPECIES*MX */
+#define MM (MX*MY) /* MM = MX*MY */
+
+/* CVodeInit Constants */
+
+#define RTOL RCONST(1.0e-5) /* scalar relative tolerance */
+#define FLOOR RCONST(100.0) /* value of C1 or C2 at which tolerances */
+ /* change from relative to absolute */
+#define ATOL (RTOL*FLOOR) /* scalar absolute tolerance */
+#define NEQ (NUM_SPECIES*MM) /* NEQ = number of equations */
+
+/* User-defined vector and matrix accessor macros: IJKth, IJth */
+
+/* IJKth is defined in order to isolate the translation from the
+ mathematical 3-dimensional structure of the dependent variable vector
+ to the underlying 1-dimensional storage. IJth is defined in order to
+ write code which indexes into small dense matrices with a (row,column)
+ pair, where 1 <= row, column <= NUM_SPECIES.
+
+ 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 = NV_DATA_S(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
+ work with matrices stored by column in a 2-dimensional array. In C,
+ arrays are indexed starting at 0, not 1. */
+
+#define IJKth(vdata,i,j,k) (vdata[i-1 + (j)*NUM_SPECIES + (k)*NSMX])
+#define IJth(a,i,j) (a[j-1][i-1])
+
+/* Type : UserData
+ contains preconditioner blocks, pivot arrays, and problem constants */
+
+typedef struct {
+ realtype q4, om, dx, dy, hdco, haco, vdco;
+} *UserData;
+
+/* Private Helper Functions */
+
+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 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, char *funcname, int opt);
+
+/* Function Called by the Solver */
+
+static int f(realtype t, N_Vector u, N_Vector udot, void *user_data);
+
+/*
+ *-------------------------------
+ * Main Program
+ *-------------------------------
+ */
+
+int main()
+{
+ realtype abstol, reltol, t, tout;
+ N_Vector u;
+ UserData data;
+ void *cvode_mem;
+ int flag, iout, jpre;
+ long int ml, mu;
+
+ u = NULL;
+ data = NULL;
+ cvode_mem = NULL;
+
+ /* Allocate and initialize u, and set problem data and tolerances */
+ u = N_VNew_Serial(NEQ);
+ if(check_flag((void *)u, "N_VNew_Serial", 0)) return(1);
+ data = (UserData) malloc(sizeof *data);
+ if(check_flag((void *)data, "malloc", 2)) return(1);
+ InitUserData(data);
+ SetInitialProfiles(u, data->dx, data->dy);
+ abstol = ATOL;
+ reltol = RTOL;
+
+ /* 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);
+
+ /* Set the pointer to user-defined data */
+ flag = CVodeSetUserData(cvode_mem, data);
+ if(check_flag(&flag, "CVodeSetUserData", 1)) 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
+ * 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 tolerances */
+ 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 CVBandPreInit to initialize band preconditioner */
+ ml = mu = 2;
+ flag = CVBandPrecInit(cvode_mem, NEQ, mu, ml);
+ if(check_flag(&flag, "CVBandPrecInit", 0)) return(1);
+
+ PrintIntro(mu, ml);
+
+ /* 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 solver, and CVSPGMR */
+
+ if (jpre == PREC_RIGHT) {
+
+ SetInitialProfiles(u, data->dx, data->dy);
+
+ 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);
+
+ printf("\n\n-------------------------------------------------------");
+ printf("------------\n");
+ }
+
+ printf("\n\nPreconditioner type is: jpre = %s\n\n",
+ (jpre == PREC_LEFT) ? "PREC_LEFT" : "PREC_RIGHT");
+
+ /* In loop over output points, call CVode, print results, test for error */
+
+ for (iout = 1, tout = TWOHR; iout <= NOUT; iout++, tout += TWOHR) {
+ flag = CVode(cvode_mem, tout, u, &t, CV_NORMAL);
+ check_flag(&flag, "CVode", 1);
+ PrintOutput(cvode_mem, u, t);
+ if (flag != CV_SUCCESS) {
+ break;
+ }
+ }
+
+ /* Print final statistics */
+
+ PrintFinalStats(cvode_mem);
+
+ } /* End of jpre loop */
+
+ /* Free memory */
+ N_VDestroy_Serial(u);
+ free(data);
+ CVodeFree(&cvode_mem);
+
+ return(0);
+}
+
+/*
+ *-------------------------------
+ * Private helper functions
+ *-------------------------------
+ */
+
+/* Load problem constants in data */
+
+static void InitUserData(UserData data)
+{
+ data->om = PI/HALFDAY;
+ data->dx = (XMAX-XMIN)/(MX-1);
+ data->dy = (YMAX-YMIN)/(MY-1);
+ data->hdco = KH/SQR(data->dx);
+ data->haco = VEL/(TWO*data->dx);
+ data->vdco = (ONE/SQR(data->dy))*KV0;
+}
+
+/* Set initial conditions in u */
+
+static void SetInitialProfiles(N_Vector u, realtype dx, realtype dy)
+{
+ int jx, jy;
+ realtype x, y, cx, cy;
+ realtype *udata;
+
+ /* Set pointer to data array in vector u. */
+
+ udata = NV_DATA_S(u);
+
+ /* Load initial profiles of c1 and c2 into u vector */
+
+ for (jy = 0; jy < MY; jy++) {
+ y = YMIN + jy*dy;
+ cy = SQR(RCONST(0.1)*(y - YMID));
+ cy = ONE - cy + RCONST(0.5)*SQR(cy);
+ for (jx = 0; jx < MX; jx++) {
+ x = XMIN + jx*dx;
+ cx = SQR(RCONST(0.1)*(x - XMID));
+ cx = ONE - cx + RCONST(0.5)*SQR(cx);
+ IJKth(udata,1,jx,jy) = C1_SCALE*cx*cy;
+ IJKth(udata,2,jx,jy) = C2_SCALE*cx*cy;
+ }
+ }
+}
+
+static void PrintIntro(long int mu, long int ml)
+{
+ printf("2-species diurnal advection-diffusion problem, %d by %d mesh\n",
+ MX, MY);
+ printf("SPGMR solver; band preconditioner; mu = %d, ml = %d\n\n",
+ mu, 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)
+{
+ 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 = NV_DATA_S(u);
+
+ flag = CVodeGetNumSteps(cvode_mem, &nst);
+ check_flag(&flag, "CVodeGetNumSteps", 1);
+ flag = CVodeGetLastOrder(cvode_mem, &qu);
+ check_flag(&flag, "CVodeGetLastOrder", 1);
+ flag = CVodeGetLastStep(cvode_mem, &hu);
+ check_flag(&flag, "CVodeGetLastStep", 1);
+
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("t = %.2Le no. steps = %ld order = %d stepsize = %.2Le\n",
+ t, nst, qu, hu);
+ printf("c1 (bot.left/middle/top rt.) = %12.3Le %12.3Le %12.3Le\n",
+ IJKth(udata,1,0,0), IJKth(udata,1,mxh,myh), IJKth(udata,1,mx1,my1));
+ printf("c2 (bot.left/middle/top rt.) = %12.3Le %12.3Le %12.3Le\n\n",
+ IJKth(udata,2,0,0), IJKth(udata,2,mxh,myh), IJKth(udata,2,mx1,my1));
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("t = %.2le no. steps = %ld order = %d stepsize = %.2le\n",
+ t, nst, qu, hu);
+ printf("c1 (bot.left/middle/top rt.) = %12.3le %12.3le %12.3le\n",
+ IJKth(udata,1,0,0), IJKth(udata,1,mxh,myh), IJKth(udata,1,mx1,my1));
+ printf("c2 (bot.left/middle/top rt.) = %12.3le %12.3le %12.3le\n\n",
+ IJKth(udata,2,0,0), IJKth(udata,2,mxh,myh), IJKth(udata,2,mx1,my1));
+#else
+ printf("t = %.2e no. steps = %ld order = %d stepsize = %.2e\n",
+ t, nst, qu, hu);
+ printf("c1 (bot.left/middle/top rt.) = %12.3e %12.3e %12.3e\n",
+ IJKth(udata,1,0,0), IJKth(udata,1,mxh,myh), IJKth(udata,1,mx1,my1));
+ printf("c2 (bot.left/middle/top rt.) = %12.3e %12.3e %12.3e\n\n",
+ IJKth(udata,2,0,0), IJKth(udata,2,mxh,myh), IJKth(udata,2,mx1,my1));
+#endif
+}
+
+/* Get and print final statistics */
+
+static void PrintFinalStats(void *cvode_mem)
+{
+ long int lenrw, leniw ;
+ long int lenrwLS, leniwLS;
+ long int lenrwBP, leniwBP;
+ long int nst, nfe, nsetups, nni, ncfn, netf;
+ long int nli, npe, nps, ncfl, nfeLS;
+ long int nfeBP;
+ 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);
+
+ flag = CVBandPrecGetWorkSpace(cvode_mem, &lenrwBP, &leniwBP);
+ check_flag(&flag, "CVBandPrecGetWorkSpace", 1);
+ flag = CVBandPrecGetNumRhsEvals(cvode_mem, &nfeBP);
+ 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("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);
+ 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);
+}
+
+/* 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, 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);
+}
+
+/*
+ *-------------------------------
+ * Function called by the solver
+ *-------------------------------
+ */
+
+/* f routine. Compute f(t,u). */
+
+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;
+ UserData data;
+
+ data = (UserData) user_data;
+ udata = NV_DATA_S(u);
+ dudata = NV_DATA_S(udot);
+
+ /* Set diurnal rate coefficients. */
+
+ s = sin(data->om*t);
+ if (s > ZERO) {
+ q3 = EXP(-A3/s);
+ data->q4 = EXP(-A4/s);
+ } else {
+ q3 = ZERO;
+ data->q4 = ZERO;
+ }
+
+ /* Make local copies of problem variables, for efficiency. */
+
+ q4coef = data->q4;
+ dely = data->dy;
+ verdco = data->vdco;
+ hordco = data->hdco;
+ horaco = data->haco;
+
+ /* Loop over all grid points. */
+
+ for (jy = 0; jy < MY; jy++) {
+
+ /* Set vertical diffusion coefficients at jy +- 1/2 */
+
+ ydn = YMIN + (jy - RCONST(0.5))*dely;
+ yup = ydn + dely;
+ cydn = verdco*EXP(RCONST(0.2)*ydn);
+ cyup = verdco*EXP(RCONST(0.2)*yup);
+ idn = (jy == 0) ? 1 : -1;
+ iup = (jy == MY-1) ? -1 : 1;
+ for (jx = 0; jx < MX; jx++) {
+
+ /* Extract c1 and c2, and set kinetic rate terms. */
+
+ c1 = IJKth(udata,1,jx,jy);
+ c2 = IJKth(udata,2,jx,jy);
+ qq1 = Q1*c1*C3;
+ qq2 = Q2*c1*c2;
+ qq3 = q3*C3;
+ qq4 = q4coef*c2;
+ rkin1 = -qq1 - qq2 + TWO*qq3 + qq4;
+ rkin2 = qq1 - qq2 - qq4;
+
+ /* Set vertical diffusion terms. */
+
+ c1dn = IJKth(udata,1,jx,jy+idn);
+ c2dn = IJKth(udata,2,jx,jy+idn);
+ c1up = IJKth(udata,1,jx,jy+iup);
+ c2up = IJKth(udata,2,jx,jy+iup);
+ vertd1 = cyup*(c1up - c1) - cydn*(c1 - c1dn);
+ vertd2 = cyup*(c2up - c2) - cydn*(c2 - c2dn);
+
+ /* Set horizontal diffusion and advection terms. */
+
+ ileft = (jx == 0) ? 1 : -1;
+ iright =(jx == MX-1) ? -1 : 1;
+ c1lt = IJKth(udata,1,jx+ileft,jy);
+ c2lt = IJKth(udata,2,jx+ileft,jy);
+ c1rt = IJKth(udata,1,jx+iright,jy);
+ c2rt = IJKth(udata,2,jx+iright,jy);
+ hord1 = hordco*(c1rt - TWO*c1 + c1lt);
+ hord2 = hordco*(c2rt - TWO*c2 + c2lt);
+ horad1 = horaco*(c1rt - c1lt);
+ horad2 = horaco*(c2rt - c2lt);
+
+ /* Load all terms into udot. */
+
+ IJKth(dudata, 1, jx, jy) = vertd1 + hord1 + horad1 + rkin1;
+ IJKth(dudata, 2, jx, jy) = vertd2 + hord2 + horad2 + rkin2;
+ }
+ }
+
+ return(0);
+}
diff --git a/examples/cvode/serial/cvDiurnal_kry_bp.out b/examples/cvode/serial/cvDiurnal_kry_bp.out
new file mode 100644
index 0000000..8de1c7b
--- /dev/null
+++ b/examples/cvode/serial/cvDiurnal_kry_bp.out
@@ -0,0 +1,138 @@
+2-species diurnal advection-diffusion problem, 10 by 10 mesh
+SPGMR solver; band preconditioner; mu = 2, ml = 2
+
+
+
+Preconditioner type is: jpre = PREC_LEFT
+
+t = 7.20e+03 no. steps = 190 order = 5 stepsize = 1.61e+02
+c1 (bot.left/middle/top rt.) = 1.047e+04 2.964e+04 1.119e+04
+c2 (bot.left/middle/top rt.) = 2.527e+11 7.154e+11 2.700e+11
+
+t = 1.44e+04 no. steps = 221 order = 5 stepsize = 3.83e+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 = 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
+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
+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
+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
+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
+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
+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
+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
+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
+
+
+Final Statistics..
+
+lenrw = 2089 leniw = 50
+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
+ncfn = 0 ncfl = 0
+
+
+
+-------------------------------------------------------------------
+
+
+Preconditioner type is: jpre = PREC_RIGHT
+
+t = 7.20e+03 no. steps = 219 order = 5 stepsize = 1.55e+02
+c1 (bot.left/middle/top rt.) = 1.047e+04 2.964e+04 1.119e+04
+c2 (bot.left/middle/top rt.) = 2.527e+11 7.154e+11 2.700e+11
+
+t = 1.44e+04 no. steps = 251 order = 5 stepsize = 3.59e+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 = 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
+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
+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
+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
+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
+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
+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
+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
+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
+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 = 450
+nfe = 564 nfetot = 1319
+nfeLS = 670 nfeBP = 85
+nni = 560 nli = 670
+nsetups = 71 netf = 21
+npe = 8 nps = 1140
+ncfn = 0 ncfl = 0
+
diff --git a/examples/cvode/serial/cvKrylovDemo_ls.c b/examples/cvode/serial/cvKrylovDemo_ls.c
new file mode 100644
index 0000000..12fe020
--- /dev/null
+++ b/examples/cvode/serial/cvKrylovDemo_ls.c
@@ -0,0 +1,736 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.3 $
+ * $Date: 2010/12/01 22:51:32 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh and
+ * Radu Serban @ LLNL
+ *
+ * This example loops through the available iterative linear solvers:
+ * SPGMR, SPBCG and SPTFQMR.
+ *
+ * Example problem:
+ *
+ * An ODE system is generated from the following 2-species diurnal
+ * kinetics advection-diffusion PDE system in 2 space dimensions:
+ *
+ * dc(i)/dt = Kh*(d/dx)^2 c(i) + V*dc(i)/dx + (d/dy)(Kv(y)*dc(i)/dy)
+ * + Ri(c1,c2,t) for i = 1,2, where
+ * R1(c1,c2,t) = -q1*c1*c3 - q2*c1*c2 + 2*q3(t)*c3 + q4(t)*c2 ,
+ * R2(c1,c2,t) = q1*c1*c3 - q2*c1*c2 - q4(t)*c2 ,
+ * Kv(y) = Kv0*exp(y/5) ,
+ * Kh, V, Kv0, q1, q2, and c3 are constants, and q3(t) and q4(t)
+ * vary diurnally. The problem is posed on the square
+ * 0 <= x <= 20, 30 <= y <= 50 (all in km),
+ * with homogeneous Neumann boundary conditions, and for time t in
+ * 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 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
+ * 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, SQR, and EXP */
+
+/* Problem Constants */
+
+#define ZERO RCONST(0.0)
+#define ONE RCONST(1.0)
+#define TWO RCONST(2.0)
+
+#define NUM_SPECIES 2 /* number of species */
+#define KH RCONST(4.0e-6) /* horizontal diffusivity Kh */
+#define VEL RCONST(0.001) /* advection velocity V */
+#define KV0 RCONST(1.0e-8) /* coefficient in Kv(y) */
+#define Q1 RCONST(1.63e-16) /* coefficients q1, q2, c3 */
+#define Q2 RCONST(4.66e-16)
+#define C3 RCONST(3.7e16)
+#define A3 RCONST(22.62) /* coefficient in expression for q3(t) */
+#define A4 RCONST(7.601) /* coefficient in expression for q4(t) */
+#define C1_SCALE RCONST(1.0e6) /* coefficients in initial profiles */
+#define C2_SCALE RCONST(1.0e12)
+
+#define T0 ZERO /* initial time */
+#define NOUT 12 /* number of output times */
+#define TWOHR RCONST(7200.0) /* number of seconds in two hours */
+#define HALFDAY RCONST(4.32e4) /* number of seconds in a half day */
+#define PI RCONST(3.1415926535898) /* pi */
+
+#define XMIN ZERO /* grid boundaries in x */
+#define XMAX RCONST(20.0)
+#define YMIN RCONST(30.0) /* grid boundaries in y */
+#define YMAX RCONST(50.0)
+#define XMID RCONST(10.0) /* grid midpoints in x,y */
+#define YMID RCONST(40.0)
+
+#define MX 10 /* MX = number of x mesh points */
+#define MY 10 /* MY = number of y mesh points */
+#define NSMX 20 /* NSMX = NUM_SPECIES*MX */
+#define MM (MX*MY) /* MM = MX*MY */
+
+/* CVodeInit Constants */
+
+#define RTOL RCONST(1.0e-5) /* scalar relative tolerance */
+#define FLOOR RCONST(100.0) /* value of C1 or C2 at which tolerances */
+ /* change from relative to absolute */
+#define ATOL (RTOL*FLOOR) /* scalar absolute tolerance */
+#define NEQ (NUM_SPECIES*MM) /* NEQ = number of equations */
+
+/* Linear Solver Loop Constants */
+
+#define USE_SPGMR 0
+#define USE_SPBCG 1
+#define USE_SPTFQMR 2
+
+/* User-defined vector and matrix accessor macros: IJKth, IJth */
+
+/* IJKth is defined in order to isolate the translation from the
+ mathematical 3-dimensional structure of the dependent variable vector
+ to the underlying 1-dimensional storage. IJth is defined in order to
+ write code which indexes into dense matrices with a (row,column)
+ pair, where 1 <= row, column <= NUM_SPECIES.
+
+ 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 = NV_DATA_S(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 matrix realtype **a,
+ where 1 <= i,j <= NUM_SPECIES. The small matrix routines in
+ sundials_dense.h work with matrices stored by column in a 2-dimensional
+ array. In C, arrays are indexed starting at 0, not 1. */
+
+#define IJKth(vdata,i,j,k) (vdata[i-1 + (j)*NUM_SPECIES + (k)*NSMX])
+#define IJth(a,i,j) (a[j-1][i-1])
+
+/* Type : UserData
+ contains preconditioner blocks, pivot arrays, and problem constants */
+
+typedef struct {
+ realtype **P[MX][MY], **Jbd[MX][MY];
+ long int *pivot[MX][MY];
+ realtype q4, om, dx, dy, hdco, haco, vdco;
+} *UserData;
+
+/* Private Helper Functions */
+
+static UserData AllocUserData(void);
+static void InitUserData(UserData data);
+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, int linsolver);
+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 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 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);
+
+
+/*
+ *-------------------------------
+ * Main Program
+ *-------------------------------
+ */
+
+int main(void)
+{
+ realtype abstol, reltol, t, tout;
+ N_Vector u;
+ UserData data;
+ void *cvode_mem;
+ int linsolver, iout, flag;
+
+ u = NULL;
+ data = NULL;
+ cvode_mem = NULL;
+
+ /* Allocate memory, and set problem data, initial values, tolerances */
+ u = N_VNew_Serial(NEQ);
+ if(check_flag((void *)u, "N_VNew_Serial", 0)) return(1);
+ data = AllocUserData();
+ if(check_flag((void *)data, "AllocUserData", 2)) return(1);
+ InitUserData(data);
+ SetInitialProfiles(u, data->dx, data->dy);
+ abstol=ATOL;
+ reltol=RTOL;
+
+ /* 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);
+
+ /* Set the pointer to user-defined data */
+ flag = CVodeSetUserData(cvode_mem, data);
+ if(check_flag(&flag, "CVodeSetUserData", 1)) 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
+ * 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 tolerances */
+ flag = CVodeSStolerances(cvode_mem, reltol, abstol);
+ if (check_flag(&flag, "CVodeSStolerances", 1)) return(1);
+
+ /* START: Loop through SPGMR, SPBCG and SPTFQMR linear solver modules */
+ for (linsolver = 0; linsolver < 3; ++linsolver) {
+
+ if (linsolver != 0) {
+
+ /* Re-initialize user data */
+ InitUserData(data);
+ SetInitialProfiles(u, data->dx, data->dy);
+
+ /* Re-initialize CVode for the solution of the same problem, but
+ using a different linear solver module */
+ flag = CVodeReInit(cvode_mem, T0, u);
+ if (check_flag(&flag, "CVodeReInit", 1)) return(1);
+
+ }
+
+ /* Attach a linear solver module */
+ switch(linsolver) {
+
+ /* (a) SPGMR */
+ case(USE_SPGMR):
+
+ /* Print header */
+ printf(" -------");
+ 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);
+
+ /* Set modified Gram-Schmidt orthogonalization, preconditioner
+ setup and solve routines Precond and PSolve, and the pointer
+ to the user-defined block data */
+ flag = CVSpilsSetGSType(cvode_mem, MODIFIED_GS);
+ if(check_flag(&flag, "CVSpilsSetGSType", 1)) return(1);
+
+ break;
+
+ /* (b) SPBCG */
+ case(USE_SPBCG):
+
+ /* Print header */
+ printf(" -------");
+ printf(" \n| SPBCG |\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);
+
+ break;
+
+ /* (c) SPTFQMR */
+ case(USE_SPTFQMR):
+
+ /* Print header */
+ printf(" ---------");
+ 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);
+
+ break;
+
+ }
+
+
+ /* 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);
+
+ /* In loop over output points, call CVode, print results, test for error */
+ printf(" \n2-species diurnal advection-diffusion problem\n\n");
+ for (iout=1, tout = TWOHR; iout <= NOUT; iout++, tout += TWOHR) {
+ flag = CVode(cvode_mem, tout, u, &t, CV_NORMAL);
+ PrintOutput(cvode_mem, u, t);
+ if(check_flag(&flag, "CVode", 1)) break;
+ }
+
+ PrintFinalStats(cvode_mem, linsolver);
+
+ } /* END: Loop through SPGMR, SPBCG and SPTFQMR linear solver modules */
+
+ /* Free memory */
+ N_VDestroy_Serial(u);
+ FreeUserData(data);
+ CVodeFree(&cvode_mem);
+
+ return(0);
+}
+
+/*
+ *-------------------------------
+ * Private helper functions
+ *-------------------------------
+ */
+
+/* Allocate memory for data structure of type UserData */
+
+static UserData AllocUserData(void)
+{
+ int jx, jy;
+ UserData data;
+
+ data = (UserData) malloc(sizeof *data);
+
+ for (jx=0; jx < MX; jx++) {
+ 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);
+ }
+ }
+
+ return(data);
+}
+
+/* Load problem constants in data */
+
+static void InitUserData(UserData data)
+{
+ data->om = PI/HALFDAY;
+ data->dx = (XMAX-XMIN)/(MX-1);
+ data->dy = (YMAX-YMIN)/(MY-1);
+ data->hdco = KH/SQR(data->dx);
+ data->haco = VEL/(TWO*data->dx);
+ data->vdco = (ONE/SQR(data->dy))*KV0;
+}
+
+/* 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]);
+ destroyMat((data->Jbd)[jx][jy]);
+ destroyArray((data->pivot)[jx][jy]);
+ }
+ }
+
+ free(data);
+}
+
+/* Set initial conditions in u */
+
+static void SetInitialProfiles(N_Vector u, realtype dx, realtype dy)
+{
+ int jx, jy;
+ realtype x, y, cx, cy;
+ realtype *udata;
+
+ /* Set pointer to data array in vector u. */
+
+ udata = NV_DATA_S(u);
+
+ /* Load initial profiles of c1 and c2 into u vector */
+
+ for (jy=0; jy < MY; jy++) {
+ y = YMIN + jy*dy;
+ cy = SQR(RCONST(0.1)*(y - YMID));
+ cy = ONE - cy + RCONST(0.5)*SQR(cy);
+ for (jx=0; jx < MX; jx++) {
+ x = XMIN + jx*dx;
+ cx = SQR(RCONST(0.1)*(x - XMID));
+ cx = ONE - cx + RCONST(0.5)*SQR(cx);
+ IJKth(udata,1,jx,jy) = C1_SCALE*cx*cy;
+ IJKth(udata,2,jx,jy) = C2_SCALE*cx*cy;
+ }
+ }
+}
+
+/* Print current t, step count, order, stepsize, and sampled c1,c2 values */
+
+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 = NV_DATA_S(u);
+
+ flag = CVodeGetNumSteps(cvode_mem, &nst);
+ check_flag(&flag, "CVodeGetNumSteps", 1);
+ flag = CVodeGetLastOrder(cvode_mem, &qu);
+ check_flag(&flag, "CVodeGetLastOrder", 1);
+ flag = CVodeGetLastStep(cvode_mem, &hu);
+ check_flag(&flag, "CVodeGetLastStep", 1);
+
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("t = %.2Le no. steps = %ld order = %d stepsize = %.2Le\n",
+ t, nst, qu, hu);
+ printf("c1 (bot.left/middle/top rt.) = %12.3Le %12.3Le %12.3Le\n",
+ IJKth(udata,1,0,0), IJKth(udata,1,mxh,myh), IJKth(udata,1,mx1,my1));
+ printf("c2 (bot.left/middle/top rt.) = %12.3Le %12.3Le %12.3Le\n\n",
+ IJKth(udata,2,0,0), IJKth(udata,2,mxh,myh), IJKth(udata,2,mx1,my1));
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("t = %.2le no. steps = %ld order = %d stepsize = %.2le\n",
+ t, nst, qu, hu);
+ printf("c1 (bot.left/middle/top rt.) = %12.3le %12.3le %12.3le\n",
+ IJKth(udata,1,0,0), IJKth(udata,1,mxh,myh), IJKth(udata,1,mx1,my1));
+ printf("c2 (bot.left/middle/top rt.) = %12.3le %12.3le %12.3le\n\n",
+ IJKth(udata,2,0,0), IJKth(udata,2,mxh,myh), IJKth(udata,2,mx1,my1));
+#else
+ printf("t = %.2e no. steps = %ld order = %d stepsize = %.2e\n",
+ t, nst, qu, hu);
+ printf("c1 (bot.left/middle/top rt.) = %12.3e %12.3e %12.3e\n",
+ IJKth(udata,1,0,0), IJKth(udata,1,mxh,myh), IJKth(udata,1,mx1,my1));
+ printf("c2 (bot.left/middle/top rt.) = %12.3e %12.3e %12.3e\n\n",
+ IJKth(udata,2,0,0), IJKth(udata,2,mxh,myh), IJKth(udata,2,mx1,my1));
+#endif
+}
+
+/* Get and print final statistics */
+
+static void PrintFinalStats(void *cvode_mem, int linsolver)
+{
+ long int lenrw, leniw ;
+ long int 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);
+
+ if (linsolver < 2)
+ printf("======================================================================\n\n");
+}
+
+/* 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, 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);
+}
+
+/*
+ *-------------------------------
+ * Functions called by the solver
+ *-------------------------------
+ */
+
+/* f routine. Compute RHS function f(t,u). */
+
+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 jx, jy, idn, iup, ileft, iright;
+ UserData data;
+
+ data = (UserData) user_data;
+ udata = NV_DATA_S(u);
+ dudata = NV_DATA_S(udot);
+
+ /* Set diurnal rate coefficients. */
+
+ s = sin(data->om*t);
+ if (s > ZERO) {
+ q3 = EXP(-A3/s);
+ data->q4 = EXP(-A4/s);
+ } else {
+ q3 = ZERO;
+ data->q4 = ZERO;
+ }
+
+ /* Make local copies of problem variables, for efficiency. */
+
+ q4coef = data->q4;
+ dely = data->dy;
+ verdco = data->vdco;
+ hordco = data->hdco;
+ horaco = data->haco;
+
+ /* Loop over all grid points. */
+
+ for (jy=0; jy < MY; jy++) {
+
+ /* Set vertical diffusion coefficients at jy +- 1/2 */
+
+ ydn = YMIN + (jy - RCONST(0.5))*dely;
+ yup = ydn + dely;
+ cydn = verdco*EXP(RCONST(0.2)*ydn);
+ cyup = verdco*EXP(RCONST(0.2)*yup);
+ idn = (jy == 0) ? 1 : -1;
+ iup = (jy == MY-1) ? -1 : 1;
+ for (jx=0; jx < MX; jx++) {
+
+ /* Extract c1 and c2, and set kinetic rate terms. */
+
+ c1 = IJKth(udata,1,jx,jy);
+ c2 = IJKth(udata,2,jx,jy);
+ qq1 = Q1*c1*C3;
+ qq2 = Q2*c1*c2;
+ qq3 = q3*C3;
+ qq4 = q4coef*c2;
+ rkin1 = -qq1 - qq2 + TWO*qq3 + qq4;
+ rkin2 = qq1 - qq2 - qq4;
+
+ /* Set vertical diffusion terms. */
+
+ c1dn = IJKth(udata,1,jx,jy+idn);
+ c2dn = IJKth(udata,2,jx,jy+idn);
+ c1up = IJKth(udata,1,jx,jy+iup);
+ c2up = IJKth(udata,2,jx,jy+iup);
+ vertd1 = cyup*(c1up - c1) - cydn*(c1 - c1dn);
+ vertd2 = cyup*(c2up - c2) - cydn*(c2 - c2dn);
+
+ /* Set horizontal diffusion and advection terms. */
+
+ ileft = (jx == 0) ? 1 : -1;
+ iright =(jx == MX-1) ? -1 : 1;
+ c1lt = IJKth(udata,1,jx+ileft,jy);
+ c2lt = IJKth(udata,2,jx+ileft,jy);
+ c1rt = IJKth(udata,1,jx+iright,jy);
+ c2rt = IJKth(udata,2,jx+iright,jy);
+ hord1 = hordco*(c1rt - TWO*c1 + c1lt);
+ hord2 = hordco*(c2rt - TWO*c2 + c2lt);
+ horad1 = horaco*(c1rt - c1lt);
+ horad2 = horaco*(c2rt - c2lt);
+
+ /* Load all terms into udot. */
+
+ IJKth(dudata, 1, jx, jy) = vertd1 + hord1 + horad1 + rkin1;
+ IJKth(dudata, 2, jx, jy) = vertd2 + hord2 + horad2 + rkin2;
+ }
+ }
+
+ return(0);
+}
+
+/* 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 c1, c2, cydn, cyup, diag, ydn, yup, q4coef, dely, verdco, hordco;
+ realtype **(*P)[MY], **(*Jbd)[MY];
+ long int *(*pivot)[MY], ier;
+ int jx, jy;
+ realtype *udata, **a, **j;
+ UserData data;
+
+ /* Make local copies of pointers in user_data, and of pointer to u's data */
+
+ data = (UserData) user_data;
+ P = data->P;
+ Jbd = data->Jbd;
+ pivot = data->pivot;
+ udata = NV_DATA_S(u);
+
+ if (jok) {
+
+ /* jok = TRUE: 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;
+
+ }
+
+ else {
+ /* jok = FALSE: Generate Jbd from scratch and copy to P */
+
+ /* Make local copies of problem variables, for efficiency. */
+
+ q4coef = data->q4;
+ dely = data->dy;
+ verdco = data->vdco;
+ hordco = data->hdco;
+
+ /* Compute 2x2 diagonal Jacobian blocks (using q4 values
+ computed on the last f call). Load into P. */
+
+ for (jy=0; jy < MY; jy++) {
+ ydn = YMIN + (jy - RCONST(0.5))*dely;
+ yup = ydn + dely;
+ cydn = verdco*EXP(RCONST(0.2)*ydn);
+ cyup = verdco*EXP(RCONST(0.2)*yup);
+ diag = -(cydn + cyup + TWO*hordco);
+ for (jx=0; jx < MX; jx++) {
+ c1 = IJKth(udata,1,jx,jy);
+ c2 = IJKth(udata,2,jx,jy);
+ j = Jbd[jx][jy];
+ a = P[jx][jy];
+ IJth(j,1,1) = (-Q1*C3 - Q2*c2) + diag;
+ IJth(j,1,2) = -Q2*c1 + q4coef;
+ IJth(j,2,1) = Q1*C3 - Q2*c2;
+ IJth(j,2,2) = (-Q2*c1 - q4coef) + diag;
+ denseCopy(j, a, NUM_SPECIES, NUM_SPECIES);
+ }
+ }
+
+ *jcurPtr = TRUE;
+
+ }
+
+ /* Scale by -gamma */
+
+ for (jy=0; jy < MY; jy++)
+ for (jx=0; jx < MX; jx++)
+ denseScale(-gamma, P[jx][jy], NUM_SPECIES, NUM_SPECIES);
+
+ /* Add identity matrix and do LU decompositions on blocks in place. */
+
+ for (jx=0; jx < MX; jx++) {
+ for (jy=0; jy < MY; jy++) {
+ denseAddIdentity(P[jx][jy], NUM_SPECIES);
+ ier =denseGETRF(P[jx][jy], NUM_SPECIES, NUM_SPECIES, pivot[jx][jy]);
+ if (ier != 0) return(1);
+ }
+ }
+
+ return(0);
+}
+
+/* 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)
+{
+ realtype **(*P)[MY];
+ long int *(*pivot)[MY];
+ int jx, jy;
+ realtype *zdata, *v;
+ UserData data;
+
+ /* Extract the P and pivot arrays from user_data. */
+
+ data = (UserData) user_data;
+ P = data->P;
+ pivot = data->pivot;
+ zdata = NV_DATA_S(z);
+
+ N_VScale(ONE, r, z);
+
+ /* Solve the block-diagonal system Px = r using LU factors stored
+ in P and pivot data in pivot, and return the solution in z. */
+
+ for (jx=0; jx < MX; jx++) {
+ for (jy=0; jy < MY; jy++) {
+ v = &(IJKth(zdata, 1, jx, jy));
+ denseGETRS(P[jx][jy], NUM_SPECIES, pivot[jx][jy], v);
+ }
+ }
+
+ return(0);
+}
diff --git a/examples/cvode/serial/cvKrylovDemo_ls.out b/examples/cvode/serial/cvKrylovDemo_ls.out
new file mode 100644
index 0000000..54b2bf2
--- /dev/null
+++ b/examples/cvode/serial/cvKrylovDemo_ls.out
@@ -0,0 +1,202 @@
+ -------
+| SPGMR |
+ -------
+
+2-species diurnal advection-diffusion problem
+
+t = 7.20e+03 no. steps = 219 order = 5 stepsize = 1.59e+02
+c1 (bot.left/middle/top rt.) = 1.047e+04 2.964e+04 1.119e+04
+c2 (bot.left/middle/top rt.) = 2.527e+11 7.154e+11 2.700e+11
+
+t = 1.44e+04 no. steps = 251 order = 5 stepsize = 3.77e+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 = 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
+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
+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
+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
+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
+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
+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
+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
+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
+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
+ncfn = 0 ncfl = 0
+
+======================================================================
+
+ -------
+| SPBCG |
+ -------
+
+2-species diurnal advection-diffusion problem
+
+t = 7.20e+03 no. steps = 190 order = 5 stepsize = 1.58e+02
+c1 (bot.left/middle/top rt.) = 1.047e+04 2.964e+04 1.119e+04
+c2 (bot.left/middle/top rt.) = 2.527e+11 7.154e+11 2.700e+11
+
+t = 1.44e+04 no. steps = 222 order = 5 stepsize = 3.81e+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 = 246 order = 5 stepsize = 4.34e+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 = 282 order = 4 stepsize = 1.71e+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 = 317 order = 5 stepsize = 9.48e+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 = 369 order = 4 stepsize = 5.46e+02
+c1 (bot.left/middle/top rt.) = -1.286e-09 -1.138e-09 -1.297e-09
+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
+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
+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
+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
+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
+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
+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
+ncfn = 0 ncfl = 0
+
+======================================================================
+
+ ---------
+| SPTFQMR |
+ ---------
+
+2-species diurnal advection-diffusion problem
+
+t = 7.20e+03 no. steps = 218 order = 5 stepsize = 1.44e+02
+c1 (bot.left/middle/top rt.) = 1.047e+04 2.964e+04 1.119e+04
+c2 (bot.left/middle/top rt.) = 2.527e+11 7.154e+11 2.700e+11
+
+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
+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
+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
+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
+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
+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
+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
+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
+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
+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
+
+
+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
+ncfn = 0 ncfl = 0
+
diff --git a/examples/cvode/serial/cvKrylovDemo_prec.c b/examples/cvode/serial/cvKrylovDemo_prec.c
new file mode 100644
index 0000000..19ee71e
--- /dev/null
+++ b/examples/cvode/serial/cvKrylovDemo_prec.c
@@ -0,0 +1,1142 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.3 $
+ * $Date: 2010/12/01 22:51:32 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh and
+ * Radu Serban @ LLNL
+ * --------------------------------------------------------------------
+ * Demonstration program for CVODE - Krylov linear solver.
+ * ODE system from ns-species interaction PDE in 2 dimensions.
+ *
+ * This program solves a stiff ODE system that arises from a system
+ * of partial differential equations. The PDE system is a food web
+ * population model, with predator-prey interaction and diffusion on
+ * the unit square in two dimensions. The dependent variable vector is:
+ *
+ * 1 2 ns
+ * c = (c , c , ..., c )
+ *
+ * and the PDEs are as follows:
+ *
+ * i i i
+ * dc /dt = d(i)*(c + c ) + f (x,y,c) (i=1,...,ns)
+ * xx yy i
+ *
+ * where
+ *
+ * i ns j
+ * f (x,y,c) = c *(b(i) + sum a(i,j)*c )
+ * i j=1
+ *
+ * The number of species is ns = 2*np, with the first np being prey
+ * and the last np being predators. The coefficients a(i,j), b(i),
+ * d(i) are:
+ *
+ * a(i,i) = -a (all i)
+ * a(i,j) = -g (i <= np, j > np)
+ * a(i,j) = e (i > np, j <= np)
+ * b(i) = b*(1 + alpha*x*y) (i <= np)
+ * b(i) = -b*(1 + alpha*x*y) (i > np)
+ * d(i) = Dprey (i <= np)
+ * d(i) = Dpred (i > np)
+ *
+ * The spatial domain is the unit square. The final time is 10.
+ * The boundary conditions are: normal derivative = 0.
+ * A polynomial in x and y is used to set the initial conditions.
+ *
+ * The PDEs are discretized by central differencing on an MX by MY mesh.
+ *
+ * The resulting ODE system is stiff.
+ *
+ * The ODE system is solved using Newton iteration and the CVSPGMR
+ * 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
+ * of Gauss-Seidel iterations using the diffusion terms only.
+ * (2) A block-diagonal matrix based on the partial derivatives
+ * of the interaction terms f only, using block-grouping (computing
+ * only a subset of the ns by ns blocks).
+ *
+ * Four different runs are made for this problem.
+ * 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.
+ *
+ * A problem description, performance statistics at selected output
+ * times, and final statistics are written to standard output.
+ * On the first run, solution values are also printed at output
+ * times. Error and warning messages are written to standard error,
+ * but there should be no such messages.
+ *
+ * Note: This program requires the dense linear solver functions
+ * newDenseMat, newLintArray, denseAddIdentity, denseGETRF, denseGETRS,
+ * destroyMat and destroyArray.
+ *
+ * Note: This program assumes the sequential implementation for the
+ * type N_Vector and uses the NV_DATA_S macro 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 SQR */
+
+/* Constants */
+
+#define ZERO RCONST(0.0)
+#define ONE RCONST(1.0)
+
+/* Problem Specification Constants */
+
+#define AA ONE /* AA = a */
+#define EE RCONST(1.0e4) /* EE = e */
+#define GG RCONST(0.5e-6) /* GG = g */
+#define BB ONE /* BB = b */
+#define DPREY ONE
+#define DPRED RCONST(0.5)
+#define ALPH ONE
+#define NP 3
+#define NS (2*NP)
+
+/* Method Constants */
+
+#define MX 6
+#define MY 6
+#define MXNS (MX*NS)
+#define AX ONE
+#define AY ONE
+#define DX (AX/(realtype)(MX-1))
+#define DY (AY/(realtype)(MY-1))
+#define MP NS
+#define MQ (MX*MY)
+#define MXMP (MX*MP)
+#define NGX 2
+#define NGY 2
+#define NGRP (NGX*NGY)
+#define ITMAX 5
+
+/* CVodeInit Constants */
+
+#define NEQ (NS*MX*MY)
+#define T0 ZERO
+#define RTOL RCONST(1.0e-5)
+#define ATOL RCONST(1.0e-5)
+
+/* CVSpgmr Constants */
+
+#define MAXL 0 /* => use default = MIN(NEQ, 5) */
+#define DELT ZERO /* => use default = 0.05 */
+
+/* Output Constants */
+
+#define T1 RCONST(1.0e-8)
+#define TOUT_MULT RCONST(10.0)
+#define DTOUT ONE
+#define NOUT 18
+
+/* Note: The value for species i at mesh point (j,k) is stored in */
+/* component number (i-1) + j*NS + k*NS*MX of an N_Vector, */
+/* where 1 <= i <= NS, 0 <= j < MX, 0 <= k < MY. */
+
+/* Structure for user data */
+
+typedef struct {
+ realtype **P[NGRP];
+ long int *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];
+ int jxr[NGX], jyr[NGY];
+ realtype acoef[NS][NS], bcoef[NS], diff[NS];
+ realtype cox[NS], coy[NS], dx, dy, srur;
+ realtype fsave[NEQ];
+ N_Vector rewt;
+ void *cvode_mem;
+} *WebData;
+
+/* Private Helper Functions */
+
+static WebData AllocUserData(void);
+static void InitUserData(WebData wdata);
+static void SetGroups(int m, int ng, int jg[], int jig[], int jr[]);
+static void CInit(N_Vector c, WebData wdata);
+static void PrintIntro(void);
+static void PrintHeader(int jpre, int gstype);
+static void PrintAllSpecies(N_Vector c, int ns, int mxns, realtype t);
+static void PrintOutput(void *cvode_mem, realtype t);
+static void PrintFinalStats(void *cvode_mem);
+static void FreeUserData(WebData wdata);
+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);
+
+/* Small Vector Kernels */
+
+static void v_inc_by_prod(realtype u[], realtype v[], realtype w[], int n);
+static void v_sum_prods(realtype u[], realtype p[], realtype q[], realtype v[],
+ realtype w[], int n);
+static void v_prod(realtype u[], realtype v[], realtype w[], int n);
+static void v_zero(realtype u[], int n);
+
+/* Functions Called By The Solver */
+
+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 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);
+
+/* Private function to check function return values */
+
+static int check_flag(void *flagvalue, char *funcname, int opt);
+
+/* Implementation */
+
+int main()
+{
+ realtype abstol=ATOL, reltol=RTOL, t, tout;
+ N_Vector c;
+ WebData wdata;
+ void *cvode_mem;
+ booleantype firstrun;
+ int jpre, gstype, flag;
+ int ns, mxns, iout;
+
+ c = NULL;
+ wdata = NULL;
+ cvode_mem = NULL;
+
+ /* Initializations */
+ c = N_VNew_Serial(NEQ);
+ if(check_flag((void *)c, "N_VNew_Serial", 0)) return(1);
+ wdata = AllocUserData();
+ if(check_flag((void *)wdata, "AllocUserData", 2)) return(1);
+ InitUserData(wdata);
+ ns = wdata->ns;
+ mxns = wdata->mxns;
+
+ /* Print problem description */
+ PrintIntro();
+
+ /* Loop over jpre and gstype (four cases) */
+ for (jpre = PREC_LEFT; jpre <= PREC_RIGHT; jpre++) {
+ for (gstype = MODIFIED_GS; gstype <= CLASSICAL_GS; gstype++) {
+
+ /* Initialize c and print heading */
+ CInit(c, wdata);
+ PrintHeader(jpre, gstype);
+
+ /* Call CVodeInit or CVodeReInit, then CVSpgmr to set up problem */
+
+ firstrun = (jpre == PREC_LEFT) && (gstype == MODIFIED_GS);
+ if (firstrun) {
+ cvode_mem = CVodeCreate(CV_BDF, CV_NEWTON);
+ if(check_flag((void *)cvode_mem, "CVodeCreate", 0)) return(1);
+
+ wdata->cvode_mem = cvode_mem;
+
+ flag = CVodeSetUserData(cvode_mem, wdata);
+ if(check_flag(&flag, "CVodeSetUserData", 1)) return(1);
+
+ flag = CVodeInit(cvode_mem, f, T0, c);
+ if(check_flag(&flag, "CVodeInit", 1)) return(1);
+
+ flag = CVodeSStolerances(cvode_mem, reltol, abstol);
+ if (check_flag(&flag, "CVodeSStolerances", 1)) return(1);
+
+ flag = CVSpgmr(cvode_mem, jpre, MAXL);
+ if(check_flag(&flag, "CVSpgmr", 1)) return(1);
+
+ flag = CVSpilsSetGSType(cvode_mem, gstype);
+ if(check_flag(&flag, "CVSpilsSetGSType", 1)) return(1);
+
+ flag = CVSpilsSetEpsLin(cvode_mem, DELT);
+ if(check_flag(&flag, "CVSpilsSetEpsLin", 1)) return(1);
+
+ flag = CVSpilsSetPreconditioner(cvode_mem, Precond, PSolve);
+ if(check_flag(&flag, "CVSpilsSetPreconditioner", 1)) return(1);
+
+ } else {
+
+ 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);
+
+ }
+
+ /* Print initial values */
+ if (firstrun) PrintAllSpecies(c, ns, mxns, T0);
+
+ /* Loop over output points, call CVode, print sample solution values. */
+ tout = T1;
+ for (iout = 1; iout <= NOUT; iout++) {
+ flag = CVode(cvode_mem, tout, c, &t, CV_NORMAL);
+ PrintOutput(cvode_mem, t);
+ if (firstrun && (iout % 3 == 0)) PrintAllSpecies(c, ns, mxns, t);
+ if(check_flag(&flag, "CVode", 1)) break;
+ if (tout > RCONST(0.9)) tout += DTOUT; else tout *= TOUT_MULT;
+ }
+
+ /* Print final statistics, and loop for next case */
+ PrintFinalStats(cvode_mem);
+
+ }
+ }
+
+ /* Free all memory */
+ CVodeFree(&cvode_mem);
+ N_VDestroy_Serial(c);
+ FreeUserData(wdata);
+
+ return(0);
+}
+
+static WebData AllocUserData(void)
+{
+ int i, ngrp = NGRP;
+ long int 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->rewt = N_VNew_Serial(NEQ);
+ return(wdata);
+}
+
+static void InitUserData(WebData wdata)
+{
+ int i, j, ns;
+ realtype *bcoef, *diff, *cox, *coy, dx, dy;
+ realtype (*acoef)[NS];
+
+ acoef = wdata->acoef;
+ bcoef = wdata->bcoef;
+ diff = wdata->diff;
+ cox = wdata->cox;
+ coy = wdata->coy;
+ ns = wdata->ns = NS;
+
+ for (j = 0; j < NS; j++) { for (i = 0; i < NS; i++) acoef[i][j] = 0.; }
+ for (j = 0; j < NP; j++) {
+ for (i = 0; i < NP; i++) {
+ acoef[NP+i][j] = EE;
+ acoef[i][NP+j] = -GG;
+ }
+ acoef[j][j] = -AA;
+ acoef[NP+j][NP+j] = -AA;
+ bcoef[j] = BB;
+ bcoef[NP+j] = -BB;
+ diff[j] = DPREY;
+ diff[NP+j] = DPRED;
+ }
+
+ /* Set remaining problem parameters */
+
+ wdata->mxns = MXNS;
+ dx = wdata->dx = DX;
+ dy = wdata->dy = DY;
+ for (i = 0; i < ns; i++) {
+ cox[i] = diff[i]/SQR(dx);
+ coy[i] = diff[i]/SQR(dy);
+ }
+
+ /* Set remaining method parameters */
+
+ wdata->mp = MP;
+ wdata->mq = MQ;
+ wdata->mx = MX;
+ wdata->my = MY;
+ wdata->srur = SQRT(UNIT_ROUNDOFF);
+ wdata->mxmp = MXMP;
+ wdata->ngrp = NGRP;
+ wdata->ngx = NGX;
+ wdata->ngy = NGY;
+ SetGroups(MX, NGX, wdata->jgx, wdata->jigx, wdata->jxr);
+ SetGroups(MY, NGY, wdata->jgy, wdata->jigy, wdata->jyr);
+}
+
+/*
+ This routine sets arrays jg, jig, and jr describing
+ a uniform partition of (0,1,2,...,m-1) into ng groups.
+ The arrays set are:
+ jg = length ng+1 array of group boundaries.
+ Group ig has indices j = jg[ig],...,jg[ig+1]-1.
+ jig = length m array of group indices vs node index.
+ Node index j is in group jig[j].
+ jr = length ng array of indices representing the groups.
+ The index for group ig is j = jr[ig].
+*/
+static void SetGroups(int m, int ng, int jg[], int jig[], int jr[])
+{
+ int ig, j, len1, mper, ngm1;
+
+ mper = m/ng; /* does integer division */
+ for (ig=0; ig < ng; ig++) jg[ig] = ig*mper;
+ jg[ng] = m;
+
+ ngm1 = ng - 1;
+ len1 = ngm1*mper;
+ for (j = 0; j < len1; j++) jig[j] = j/mper;
+ for (j = len1; j < m; j++) jig[j] = ngm1;
+
+ for (ig = 0; ig < ngm1; ig++) jr[ig] = ((2*ig+1)*mper-1)/2;
+ jr[ngm1] = (ngm1*mper+m-1)/2;
+}
+
+/* This routine computes and loads the vector of initial values. */
+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 = NV_DATA_S(c);
+ ns = wdata->ns;
+ mxns = wdata->mxns;
+ dx = wdata->dx;
+ dy = wdata->dy;
+
+ x_factor = RCONST(4.0)/SQR(AX);
+ y_factor = RCONST(4.0)/SQR(AY);
+ for (jy = 0; jy < MY; jy++) {
+ y = jy*dy;
+ argy = SQR(y_factor*y*(AY-y));
+ iyoff = mxns*jy;
+ for (jx = 0; jx < MX; jx++) {
+ x = jx*dx;
+ argx = SQR(x_factor*x*(AX-x));
+ ioff = iyoff + ns*jx;
+ for (i = 1; i <= ns; i++) {
+ ici = ioff + i-1;
+ cdata[ici] = RCONST(10.0) + i*argx*argy;
+ }
+ }
+ }
+}
+
+static void PrintIntro(void)
+{
+ printf("\n\nDemonstration program for CVODE - CVSPGMR 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)
+ printf("Matrix parameters: a = %.2Lg e = %.2Lg g = %.2Lg\n",
+ AA, EE, GG);
+ printf("b parameter = %.2Lg\n", BB);
+ printf("Diffusion coefficients: Dprey = %.2Lg Dpred = %.2Lg\n",
+ DPREY, DPRED);
+ printf("Rate parameter alpha = %.2Lg\n\n", ALPH);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("Matrix parameters: a = %.2lg e = %.2lg g = %.2lg\n",
+ AA, EE, GG);
+ printf("b parameter = %.2lg\n", BB);
+ printf("Diffusion coefficients: Dprey = %.2lg Dpred = %.2lg\n",
+ DPREY, DPRED);
+ printf("Rate parameter alpha = %.2lg\n\n", ALPH);
+#else
+ printf("Matrix parameters: a = %.2g e = %.2g g = %.2g\n",
+ AA, EE, GG);
+ printf("b parameter = %.2g\n", BB);
+ printf("Diffusion coefficients: Dprey = %.2g Dpred = %.2g\n",
+ DPREY, DPRED);
+ printf("Rate parameter alpha = %.2g\n\n", ALPH);
+#endif
+ printf("Mesh dimensions (mx,my) are %d, %d. ", MX, MY);
+ printf("Total system size is neq = %d \n\n", NEQ);
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("Tolerances: reltol = %.2Lg, abstol = %.2Lg \n\n",
+ RTOL, ATOL);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("Tolerances: reltol = %.2lg, abstol = %.2lg \n\n",
+ RTOL, ATOL);
+#else
+ printf("Tolerances: reltol = %.2g, abstol = %.2g \n\n",
+ RTOL, ATOL);
+#endif
+ printf("Preconditioning uses a product of:\n");
+ printf(" (1) Gauss-Seidel iterations with ");
+ printf("itmax = %d iterations, and\n", ITMAX);
+ printf(" (2) interaction-only block-diagonal matrix ");
+ printf("with block-grouping\n");
+ printf(" Number of diagonal block groups = ngrp = %d", NGRP);
+ printf(" (ngx by ngy, ngx = %d, ngy = %d)\n", NGX, NGY);
+ printf("\n\n--------------------------------------------------------------");
+ printf("--------------\n");
+}
+
+static void PrintHeader(int jpre, int gstype)
+{
+ if(jpre == PREC_LEFT)
+ printf("\n\nPreconditioner type is jpre = %s\n", "PREC_LEFT");
+ else
+ printf("\n\nPreconditioner type is jpre = %s\n", "PREC_RIGHT");
+
+ if(gstype == MODIFIED_GS)
+ printf("\nGram-Schmidt method type is gstype = %s\n\n\n", "MODIFIED_GS");
+ else
+ printf("\nGram-Schmidt method type is gstype = %s\n\n\n", "CLASSICAL_GS");
+}
+
+static void PrintAllSpecies(N_Vector c, int ns, int mxns, realtype t)
+{
+ int i, jx ,jy;
+ realtype *cdata;
+
+ cdata = NV_DATA_S(c);
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("c values at t = %Lg:\n\n", t);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("c values at t = %lg:\n\n", t);
+#else
+ printf("c values at t = %g:\n\n", t);
+#endif
+ for (i=1; i <= ns; i++) {
+ printf("Species %d\n", i);
+ for (jy=MY-1; jy >= 0; jy--) {
+ for (jx=0; jx < MX; jx++) {
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("%-10.6Lg", cdata[(i-1) + jx*ns + jy*mxns]);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("%-10.6lg", cdata[(i-1) + jx*ns + jy*mxns]);
+#else
+ printf("%-10.6g", cdata[(i-1) + jx*ns + jy*mxns]);
+#endif
+ }
+ printf("\n");
+ }
+ printf("\n");
+ }
+}
+
+static void PrintOutput(void *cvode_mem, realtype t)
+{
+ long int nst, nfe, nni;
+ int qu, flag;
+ realtype hu;
+
+ flag = CVodeGetNumSteps(cvode_mem, &nst);
+ check_flag(&flag, "CVodeGetNumSteps", 1);
+ flag = CVodeGetNumRhsEvals(cvode_mem, &nfe);
+ check_flag(&flag, "CVodeGetNumRhsEvals", 1);
+ flag = CVodeGetNumNonlinSolvIters(cvode_mem, &nni);
+ check_flag(&flag, "CVodeGetNumNonlinSolvIters", 1);
+ flag = CVodeGetLastOrder(cvode_mem, &qu);
+ check_flag(&flag, "CVodeGetLastOrder", 1);
+ flag = CVodeGetLastStep(cvode_mem, &hu);
+ check_flag(&flag, "CVodeGetLastStep", 1);
+
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("t = %10.2Le nst = %ld nfe = %ld nni = %ld", t, nst, nfe, nni);
+ printf(" qu = %d hu = %11.2Le\n\n", qu, hu);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("t = %10.2le nst = %ld nfe = %ld nni = %ld", t, nst, nfe, nni);
+ printf(" qu = %d hu = %11.2le\n\n", qu, hu);
+#else
+ printf("t = %10.2e nst = %ld nfe = %ld nni = %ld", t, nst, nfe, nni);
+ printf(" qu = %d hu = %11.2e\n\n", qu, hu);
+#endif
+}
+
+static void PrintFinalStats(void *cvode_mem)
+{
+ long int lenrw, leniw ;
+ long int lenrwLS, leniwLS;
+ long int nst, nfe, nsetups, nni, ncfn, netf;
+ long int nli, npe, nps, ncfl, nfeLS;
+ int flag;
+ realtype avdim;
+
+ 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("\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(" Number of steps = %4ld \n", nst);
+ printf(" Number of f-s = %4ld \n", nfe);
+ printf(" Number of f-s (SPGMR) = %4ld \n", nfeLS);
+ printf(" Number of f-s (TOTAL) = %4ld \n", nfe + nfeLS);
+ printf(" Number of setups = %4ld \n", nsetups);
+ printf(" Number of nonlinear iterations = %4ld \n", nni);
+ printf(" Number of linear iterations = %4ld \n", nli);
+ printf(" Number of preconditioner evaluations = %4ld \n", npe);
+ printf(" Number of preconditioner solves = %4ld \n", nps);
+ printf(" Number of error test failures = %4ld \n", netf);
+ printf(" Number of nonlinear conv. failures = %4ld \n", ncfn);
+ printf(" Number of linear convergence failures = %4ld \n", ncfl);
+ avdim = (nni > 0) ? ((realtype)nli)/((realtype)nni) : ZERO;
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf(" Average Krylov subspace dimension = %.3Lf \n", avdim);
+#else
+ printf(" Average Krylov subspace dimension = %.3f \n", avdim);
+#endif
+ printf("\n\n--------------------------------------------------------------");
+ printf("--------------\n");
+ printf( "--------------------------------------------------------------");
+ printf("--------------\n");
+}
+
+static void FreeUserData(WebData wdata)
+{
+ int i, ngrp;
+
+ ngrp = wdata->ngrp;
+ for(i=0; i < ngrp; i++) {
+ destroyMat((wdata->P)[i]);
+ destroyArray((wdata->pivot)[i]);
+ }
+ N_VDestroy_Serial(wdata->rewt);
+ free(wdata);
+}
+
+/*
+ This routine computes the right-hand side of the ODE system and
+ returns it in cdot. The interaction rates are computed by calls to WebRates,
+ and these are saved in fsave for use in preconditioning.
+*/
+static int f(realtype t, N_Vector c, N_Vector cdot,void *user_data)
+{
+ int i, ic, ici, idxl, idxu, jx, ns, mxns, iyoff, jy, idyu, idyl;
+ realtype dcxli, dcxui, dcyli, dcyui, x, y, *cox, *coy, *fsave, dx, dy;
+ realtype *cdata, *cdotdata;
+ WebData wdata;
+
+ wdata = (WebData) user_data;
+ cdata = NV_DATA_S(c);
+ cdotdata = NV_DATA_S(cdot);
+
+ mxns = wdata->mxns;
+ ns = wdata->ns;
+ fsave = wdata->fsave;
+ cox = wdata->cox;
+ coy = wdata->coy;
+ mxns = wdata->mxns;
+ dx = wdata->dx;
+ dy = wdata->dy;
+
+ for (jy = 0; jy < MY; jy++) {
+ y = jy*dy;
+ iyoff = mxns*jy;
+ idyu = (jy == MY-1) ? -mxns : mxns;
+ idyl = (jy == 0) ? -mxns : mxns;
+ for (jx = 0; jx < MX; jx++) {
+ x = jx*dx;
+ ic = iyoff + ns*jx;
+ /* Get interaction rates at one point (x,y). */
+ WebRates(x, y, t, cdata+ic, fsave+ic, wdata);
+ idxu = (jx == MX-1) ? -ns : ns;
+ idxl = (jx == 0) ? -ns : ns;
+ for (i = 1; i <= ns; i++) {
+ ici = ic + i-1;
+ /* Do differencing in y. */
+ dcyli = cdata[ici] - cdata[ici-idyl];
+ dcyui = cdata[ici+idyu] - cdata[ici];
+ /* Do differencing in x. */
+ dcxli = cdata[ici] - cdata[ici-idxl];
+ dcxui = cdata[ici+idxu] - cdata[ici];
+ /* Collect terms and load cdot elements. */
+ cdotdata[ici] = coy[i-1]*(dcyui - dcyli) + cox[i-1]*(dcxui - dcxli) +
+ fsave[ici];
+ }
+ }
+ }
+
+ return(0);
+}
+
+/*
+ This routine computes the interaction rates for the species
+ c_1, ... ,c_ns (stored in c[0],...,c[ns-1]), at one spatial point
+ and at time t.
+*/
+static void WebRates(realtype x, realtype y, realtype t, realtype c[],
+ realtype rate[], WebData wdata)
+{
+ int i, j, ns;
+ realtype fac, *bcoef;
+ realtype (*acoef)[NS];
+
+ ns = wdata->ns;
+ acoef = wdata->acoef;
+ bcoef = wdata->bcoef;
+
+ for (i = 0; i < ns; i++)
+ rate[i] = ZERO;
+
+ for (j = 0; j < ns; j++)
+ for (i = 0; i < ns; i++)
+ rate[i] += c[j] * acoef[i][j];
+
+ fac = ONE + ALPH*x*y;
+ for (i = 0; i < ns; i++)
+ rate[i] = c[i]*(bcoef[i]*fac + rate[i]);
+}
+
+/*
+ This routine generates the block-diagonal part of the Jacobian
+ corresponding to the interaction rates, multiplies by -gamma, adds
+ the identity matrix, and calls denseGETRF to do the LU decomposition of
+ each diagonal block. The computation of the diagonal blocks uses
+ the preset block and grouping information. One block per group is
+ computed. The Jacobian elements are generated by difference
+ quotients using calls to the routine fblock.
+
+ This routine can be regarded as a prototype for the general case
+ 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)
+{
+ realtype ***P;
+ int ier;
+ long int **pivot;
+ int i, if0, if00, ig, igx, igy, j, jj, jx, jy;
+ int *jxr, *jyr, ngrp, ngx, ngy, mxmp, flag;
+ long int mp;
+ realtype uround, fac, r, r0, save, srur;
+ realtype *f1, *fsave, *cdata, *rewtdata;
+ WebData wdata;
+ void *cvode_mem;
+ N_Vector rewt;
+
+ wdata = (WebData) user_data;
+ cvode_mem = wdata->cvode_mem;
+ cdata = NV_DATA_S(c);
+ rewt = wdata->rewt;
+ flag = CVodeGetErrWeights(cvode_mem, rewt);
+ if(check_flag(&flag, "CVodeGetErrWeights", 1)) return(1);
+ rewtdata = NV_DATA_S(rewt);
+
+ uround = UNIT_ROUNDOFF;
+
+ P = wdata->P;
+ pivot = wdata->pivot;
+ jxr = wdata->jxr;
+ jyr = wdata->jyr;
+ mp = wdata->mp;
+ srur = wdata->srur;
+ ngrp = wdata->ngrp;
+ ngx = wdata->ngx;
+ ngy = wdata->ngy;
+ mxmp = wdata->mxmp;
+ fsave = wdata->fsave;
+
+ /* Make mp calls to fblock to approximate each diagonal block of Jacobian.
+ Here, fsave contains the base value of the rate vector and
+ r0 is a minimum increment factor for the difference quotient. */
+
+ f1 = NV_DATA_S(vtemp1);
+
+ fac = N_VWrmsNorm (fc, rewt);
+ r0 = RCONST(1000.0)*ABS(gamma)*uround*NEQ*fac;
+ if (r0 == ZERO) r0 = ONE;
+
+ for (igy = 0; igy < ngy; igy++) {
+ jy = jyr[igy];
+ if00 = jy*mxmp;
+ for (igx = 0; igx < ngx; igx++) {
+ jx = jxr[igx];
+ if0 = if00 + jx*mp;
+ ig = igx + igy*ngx;
+ /* Generate ig-th diagonal block */
+ for (j = 0; j < mp; j++) {
+ /* Generate the jth column as a difference quotient */
+ jj = if0 + j;
+ save = cdata[jj];
+ r = MAX(srur*ABS(save),r0/rewtdata[jj]);
+ cdata[jj] += r;
+ fac = -gamma/r;
+ fblock (t, cdata, jx, jy, f1, wdata);
+ for (i = 0; i < mp; i++) {
+ P[ig][j][i] = (f1[i] - fsave[if0+i])*fac;
+ }
+ cdata[jj] = save;
+ }
+ }
+ }
+
+ /* Add identity matrix and do LU decompositions on blocks. */
+
+ for (ig = 0; ig < ngrp; ig++) {
+ denseAddIdentity(P[ig], mp);
+ ier = denseGETRF(P[ig], mp, mp, pivot[ig]);
+ if (ier != 0) return(1);
+ }
+
+ *jcurPtr = TRUE;
+ return(0);
+}
+
+/*
+ This routine computes one block of the interaction terms of the
+ system, namely block (jx,jy), for use in preconditioning.
+ Here jx and jy count from 0.
+*/
+static void fblock(realtype t, realtype cdata[], int jx, int jy,
+ realtype cdotdata[], WebData wdata)
+{
+ int iblok, ic;
+ realtype x, y;
+
+ iblok = jx + jy*(wdata->mx);
+ y = jy*(wdata->dy);
+ x = jx*(wdata->dx);
+ ic = (wdata->ns)*(iblok);
+ WebRates(x, y, t, cdata+ic, cdotdata, wdata);
+}
+
+/*
+ This routine applies two inverse preconditioner matrices
+ to the vector r, using the interaction-only block-diagonal Jacobian
+ with block-grouping, denoted Jr, and Gauss-Seidel applied to the
+ diffusion contribution to the Jacobian, denoted Jd.
+ It first calls GSIter for a Gauss-Seidel approximation to
+ ((I - gamma*Jd)-inverse)*r, and stores the result in z.
+ 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)
+{
+ realtype ***P;
+ long int **pivot;
+ int jx, jy, igx, igy, iv, ig, *jigx, *jigy, mx, my, ngx;
+ long int mp;
+ WebData wdata;
+
+ wdata = (WebData) user_data;
+
+ N_VScale(ONE, r, z);
+
+ /* call GSIter for Gauss-Seidel iterations */
+
+ GSIter(gamma, z, vtemp, wdata);
+
+ /* Do backsolves for inverse of block-diagonal preconditioner factor */
+
+ P = wdata->P;
+ pivot = wdata->pivot;
+ mx = wdata->mx;
+ my = wdata->my;
+ ngx = wdata->ngx;
+ mp = wdata->mp;
+ jigx = wdata->jigx;
+ jigy = wdata->jigy;
+
+ iv = 0;
+ for (jy = 0; jy < my; jy++) {
+ igy = jigy[jy];
+ for (jx = 0; jx < mx; jx++) {
+ igx = jigx[jx];
+ ig = igx + igy*ngx;
+ denseGETRS(P[ig], mp, pivot[ig], &(NV_DATA_S(z)[iv]));
+ iv += mp;
+ }
+ }
+
+ return(0);
+}
+
+/*
+ This routine performs ITMAX=5 Gauss-Seidel iterations to compute an
+ approximation to (P-inverse)*z, where P = I - gamma*Jd, and
+ Jd represents the diffusion contributions to the Jacobian.
+ The answer is stored in z on return, and x is a temporary vector.
+ The dimensions below assume a global constant NS >= ns.
+ Some inner loops of length ns are implemented with the small
+ vector kernels v_sum_prods, v_prod, v_inc_by_prod.
+*/
+static void GSIter(realtype gamma, N_Vector z, N_Vector x, WebData wdata)
+{
+ int jx, jy, mx, my, x_loc, y_loc;
+ int ns, mxns, i, iyoff, ic, iter;
+ realtype beta[NS], beta2[NS], cof1[NS], gam[NS], gam2[NS];
+ realtype temp, *cox, *coy, *xd, *zd;
+
+ xd = NV_DATA_S(x);
+ zd = NV_DATA_S(z);
+ ns = wdata->ns;
+ mx = wdata->mx;
+ my = wdata->my;
+ mxns = wdata->mxns;
+ cox = wdata->cox;
+ coy = wdata->coy;
+
+ /* Write matrix as P = D - L - U.
+ Load local arrays beta, beta2, gam, gam2, and cof1. */
+
+ for (i = 0; i < ns; i++) {
+ temp = ONE/(ONE + RCONST(2.0)*gamma*(cox[i] + coy[i]));
+ beta[i] = gamma*cox[i]*temp;
+ beta2[i] = RCONST(2.0)*beta[i];
+ gam[i] = gamma*coy[i]*temp;
+ gam2[i] = RCONST(2.0)*gam[i];
+ cof1[i] = temp;
+ }
+
+ /* Begin iteration loop.
+ Load vector x with (D-inverse)*z for first iteration. */
+
+ for (jy = 0; jy < my; jy++) {
+ iyoff = mxns*jy;
+ for (jx = 0; jx < mx; jx++) {
+ ic = iyoff + ns*jx;
+ v_prod(xd+ic, cof1, zd+ic, ns); /* x[ic+i] = cof1[i]z[ic+i] */
+ }
+ }
+ N_VConst(ZERO, z);
+
+ /* Looping point for iterations. */
+
+ for (iter=1; iter <= ITMAX; iter++) {
+
+ /* Calculate (D-inverse)*U*x if not the first iteration. */
+
+ if (iter > 1) {
+ for (jy=0; jy < my; jy++) {
+ iyoff = mxns*jy;
+ for (jx=0; jx < mx; jx++) { /* order of loops matters */
+ ic = iyoff + ns*jx;
+ x_loc = (jx == 0) ? 0 : ((jx == mx-1) ? 2 : 1);
+ y_loc = (jy == 0) ? 0 : ((jy == my-1) ? 2 : 1);
+ switch (3*y_loc+x_loc) {
+ case 0 :
+ /* jx == 0, jy == 0 */
+ /* x[ic+i] = beta2[i]x[ic+ns+i] + gam2[i]x[ic+mxns+i] */
+ v_sum_prods(xd+ic, beta2, xd+ic+ns, gam2, xd+ic+mxns, ns);
+ break;
+ case 1 :
+ /* 1 <= jx <= mx-2, jy == 0 */
+ /* x[ic+i] = beta[i]x[ic+ns+i] + gam2[i]x[ic+mxns+i] */
+ v_sum_prods(xd+ic, beta, xd+ic+ns, gam2, xd+ic+mxns, ns);
+ break;
+ case 2 :
+ /* jx == mx-1, jy == 0 */
+ /* x[ic+i] = gam2[i]x[ic+mxns+i] */
+ v_prod(xd+ic, gam2, xd+ic+mxns, ns);
+ break;
+ case 3 :
+ /* jx == 0, 1 <= jy <= my-2 */
+ /* x[ic+i] = beta2[i]x[ic+ns+i] + gam[i]x[ic+mxns+i] */
+ v_sum_prods(xd+ic, beta2, xd+ic+ns, gam, xd+ic+mxns, ns);
+ break;
+ case 4 :
+ /* 1 <= jx <= mx-2, 1 <= jy <= my-2 */
+ /* x[ic+i] = beta[i]x[ic+ns+i] + gam[i]x[ic+mxns+i] */
+ v_sum_prods(xd+ic, beta, xd+ic+ns, gam, xd+ic+mxns, ns);
+ break;
+ case 5 :
+ /* jx == mx-1, 1 <= jy <= my-2 */
+ /* x[ic+i] = gam[i]x[ic+mxns+i] */
+ v_prod(xd+ic, gam, xd+ic+mxns, ns);
+ break;
+ case 6 :
+ /* jx == 0, jy == my-1 */
+ /* x[ic+i] = beta2[i]x[ic+ns+i] */
+ v_prod(xd+ic, beta2, xd+ic+ns, ns);
+ break;
+ case 7 :
+ /* 1 <= jx <= mx-2, jy == my-1 */
+ /* x[ic+i] = beta[i]x[ic+ns+i] */
+ v_prod(xd+ic, beta, xd+ic+ns, ns);
+ break;
+ case 8 :
+ /* jx == mx-1, jy == my-1 */
+ /* x[ic+i] = 0.0 */
+ v_zero(xd+ic, ns);
+ break;
+ }
+ }
+ }
+ } /* end if (iter > 1) */
+
+ /* Overwrite x with [(I - (D-inverse)*L)-inverse]*x. */
+
+ for (jy=0; jy < my; jy++) {
+ iyoff = mxns*jy;
+ for (jx=0; jx < mx; jx++) { /* order of loops matters */
+ ic = iyoff + ns*jx;
+ x_loc = (jx == 0) ? 0 : ((jx == mx-1) ? 2 : 1);
+ y_loc = (jy == 0) ? 0 : ((jy == my-1) ? 2 : 1);
+ switch (3*y_loc+x_loc) {
+ case 0 :
+ /* jx == 0, jy == 0 */
+ break;
+ case 1 :
+ /* 1 <= jx <= mx-2, jy == 0 */
+ /* x[ic+i] += beta[i]x[ic-ns+i] */
+ v_inc_by_prod(xd+ic, beta, xd+ic-ns, ns);
+ break;
+ case 2 :
+ /* jx == mx-1, jy == 0 */
+ /* x[ic+i] += beta2[i]x[ic-ns+i] */
+ v_inc_by_prod(xd+ic, beta2, xd+ic-ns, ns);
+ break;
+ case 3 :
+ /* jx == 0, 1 <= jy <= my-2 */
+ /* x[ic+i] += gam[i]x[ic-mxns+i] */
+ v_inc_by_prod(xd+ic, gam, xd+ic-mxns, ns);
+ break;
+ case 4 :
+ /* 1 <= jx <= mx-2, 1 <= jy <= my-2 */
+ /* x[ic+i] += beta[i]x[ic-ns+i] + gam[i]x[ic-mxns+i] */
+ v_inc_by_prod(xd+ic, beta, xd+ic-ns, ns);
+ v_inc_by_prod(xd+ic, gam, xd+ic-mxns, ns);
+ break;
+ case 5 :
+ /* jx == mx-1, 1 <= jy <= my-2 */
+ /* x[ic+i] += beta2[i]x[ic-ns+i] + gam[i]x[ic-mxns+i] */
+ v_inc_by_prod(xd+ic, beta2, xd+ic-ns, ns);
+ v_inc_by_prod(xd+ic, gam, xd+ic-mxns, ns);
+ break;
+ case 6 :
+ /* jx == 0, jy == my-1 */
+ /* x[ic+i] += gam2[i]x[ic-mxns+i] */
+ v_inc_by_prod(xd+ic, gam2, xd+ic-mxns, ns);
+ break;
+ case 7 :
+ /* 1 <= jx <= mx-2, jy == my-1 */
+ /* x[ic+i] += beta[i]x[ic-ns+i] + gam2[i]x[ic-mxns+i] */
+ v_inc_by_prod(xd+ic, beta, xd+ic-ns, ns);
+ v_inc_by_prod(xd+ic, gam2, xd+ic-mxns, ns);
+ break;
+ case 8 :
+ /* jx == mx-1, jy == my-1 */
+ /* x[ic+i] += beta2[i]x[ic-ns+i] + gam2[i]x[ic-mxns+i] */
+ v_inc_by_prod(xd+ic, beta2, xd+ic-ns, ns);
+ v_inc_by_prod(xd+ic, gam2, xd+ic-mxns, ns);
+ break;
+ }
+ }
+ }
+
+ /* Add increment x to z : z <- z+x */
+
+ N_VLinearSum(ONE, z, ONE, x, z);
+
+ }
+}
+
+static void v_inc_by_prod(realtype u[], realtype v[], realtype w[], int n)
+{
+ int i;
+ for (i=0; i < n; i++) u[i] += v[i]*w[i];
+}
+
+static void v_sum_prods(realtype u[], realtype p[], realtype q[],
+ realtype v[], realtype w[], int n)
+{
+ int i;
+ for (i=0; i < n; i++) u[i] = p[i]*q[i] + v[i]*w[i];
+}
+
+static void v_prod(realtype u[], realtype v[], realtype w[], int n)
+{
+ int i;
+ for (i=0; i < n; i++) u[i] = v[i]*w[i];
+}
+
+static void v_zero(realtype u[], int n)
+{
+ int i;
+ for (i=0; i < n; i++) u[i] = ZERO;
+}
+
+/* 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, 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/serial/cvKrylovDemo_prec.out b/examples/cvode/serial/cvKrylovDemo_prec.out
new file mode 100644
index 0000000..66c5396
--- /dev/null
+++ b/examples/cvode/serial/cvKrylovDemo_prec.out
@@ -0,0 +1,645 @@
+
+
+Demonstration program for CVODE - CVSPGMR linear solver
+
+Food web problem with ns species, ns = 6
+Predator-prey interaction and diffusion on a 2-D square
+
+Matrix parameters: a = 1 e = 1e+04 g = 5e-07
+b parameter = 1
+Diffusion coefficients: Dprey = 1 Dpred = 0.5
+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
+
+Preconditioning uses a product of:
+ (1) Gauss-Seidel iterations with itmax = 5 iterations, and
+ (2) interaction-only block-diagonal matrix with block-grouping
+ Number of diagonal block groups = ngrp = 4 (ngx by ngy, ngx = 2, ngy = 2)
+
+
+----------------------------------------------------------------------------
+
+
+Preconditioner type is jpre = PREC_LEFT
+
+Gram-Schmidt method type is gstype = MODIFIED_GS
+
+
+c values at t = 0:
+
+Species 1
+10 10 10 10 10 10
+10 10.1678 10.3775 10.3775 10.1678 10
+10 10.3775 10.8493 10.8493 10.3775 10
+10 10.3775 10.8493 10.8493 10.3775 10
+10 10.1678 10.3775 10.3775 10.1678 10
+10 10 10 10 10 10
+
+Species 2
+10 10 10 10 10 10
+10 10.3355 10.755 10.755 10.3355 10
+10 10.755 11.6987 11.6987 10.755 10
+10 10.755 11.6987 11.6987 10.755 10
+10 10.3355 10.755 10.755 10.3355 10
+10 10 10 10 10 10
+
+Species 3
+10 10 10 10 10 10
+10 10.5033 11.1325 11.1325 10.5033 10
+10 11.1325 12.548 12.548 11.1325 10
+10 11.1325 12.548 12.548 11.1325 10
+10 10.5033 11.1325 11.1325 10.5033 10
+10 10 10 10 10 10
+
+Species 4
+10 10 10 10 10 10
+10 10.6711 11.5099 11.5099 10.6711 10
+10 11.5099 13.3974 13.3974 11.5099 10
+10 11.5099 13.3974 13.3974 11.5099 10
+10 10.6711 11.5099 11.5099 10.6711 10
+10 10 10 10 10 10
+
+Species 5
+10 10 10 10 10 10
+10 10.8389 11.8874 11.8874 10.8389 10
+10 11.8874 14.2467 14.2467 11.8874 10
+10 11.8874 14.2467 14.2467 11.8874 10
+10 10.8389 11.8874 11.8874 10.8389 10
+10 10 10 10 10 10
+
+Species 6
+10 10 10 10 10 10
+10 11.0066 12.2649 12.2649 11.0066 10
+10 12.2649 15.0961 15.0961 12.2649 10
+10 12.2649 15.0961 15.0961 12.2649 10
+10 11.0066 12.2649 12.2649 11.0066 10
+10 10 10 10 10 10
+
+t = 1.00e-08 nst = 3 nfe = 10 nni = 6 qu = 2 hu = 1.76e-08
+
+t = 1.00e-07 nst = 7 nfe = 14 nni = 10 qu = 2 hu = 4.78e-08
+
+t = 1.00e-06 nst = 15 nfe = 24 nni = 20 qu = 3 hu = 1.50e-07
+
+c values at t = 1e-06:
+
+Species 1
+9.99991 9.99992 9.99993 9.99993 9.99993 9.99992
+9.99992 10.1677 10.3774 10.3774 10.1677 9.99993
+9.99993 10.3774 10.8492 10.8492 10.3774 9.99993
+9.99993 10.3774 10.8492 10.8492 10.3774 9.99993
+9.99992 10.1677 10.3774 10.3774 10.1677 9.99992
+9.99991 9.99992 9.99993 9.99993 9.99992 9.99991
+
+Species 2
+9.99991 9.99993 9.99995 9.99995 9.99993 9.99992
+9.99993 10.3355 10.7549 10.7549 10.3355 9.99993
+9.99995 10.7549 11.6985 11.6985 10.7549 9.99995
+9.99995 10.7549 11.6985 11.6985 10.7549 9.99995
+9.99993 10.3355 10.7549 10.7549 10.3355 9.99993
+9.99991 9.99993 9.99995 9.99995 9.99993 9.99991
+
+Species 3
+9.99991 9.99994 9.99997 9.99997 9.99994 9.99992
+9.99994 10.5032 11.1323 11.1323 10.5032 9.99994
+9.99997 11.1323 12.5478 12.5478 11.1323 9.99997
+9.99997 11.1323 12.5478 12.5478 11.1323 9.99997
+9.99994 10.5032 11.1323 11.1323 10.5032 9.99994
+9.99991 9.99994 9.99997 9.99997 9.99994 9.99991
+
+Species 4
+13.499 13.499 13.499 13.499 13.499 13.4989
+13.499 14.5506 15.8932 15.8932 14.5506 13.499
+13.499 15.8932 19.0308 19.0308 15.8932 13.499
+13.499 15.8932 19.0308 19.0308 15.8932 13.499
+13.499 14.5506 15.8932 15.8932 14.5506 13.499
+13.499 13.499 13.499 13.499 13.499 13.499
+
+Species 5
+13.499 13.499 13.499 13.499 13.499 13.4989
+13.499 14.7794 16.4145 16.4145 14.7794 13.499
+13.499 16.4145 20.2373 20.2373 16.4145 13.499
+13.499 16.4145 20.2373 20.2373 16.4145 13.499
+13.499 14.7794 16.4145 16.4145 14.7794 13.499
+13.499 13.499 13.499 13.499 13.499 13.499
+
+Species 6
+13.499 13.499 13.499 13.499 13.499 13.4989
+13.499 15.0082 16.9357 16.9357 15.0082 13.499
+13.499 16.9357 21.4437 21.4437 16.9357 13.499
+13.499 16.9357 21.4437 21.4437 16.9357 13.499
+13.499 15.0082 16.9357 16.9357 15.0082 13.499
+13.499 13.499 13.499 13.499 13.499 13.499
+
+t = 1.00e-05 nst = 34 nfe = 47 nni = 43 qu = 5 hu = 6.11e-07
+
+t = 1.00e-04 nst = 116 nfe = 137 nni = 133 qu = 5 hu = 5.51e-06
+
+t = 1.00e-03 nst = 135 nfe = 156 nni = 152 qu = 2 hu = 3.53e-04
+
+c values at t = 0.001:
+
+Species 1
+9.90702 9.91664 9.92836 9.93033 9.92253 9.91674
+9.91472 10.0746 10.2769 10.2785 10.0795 9.92253
+9.92446 10.2748 10.7181 10.7194 10.2785 9.93033
+9.92445 10.2744 10.7173 10.7181 10.2769 9.92836
+9.91469 10.0734 10.2744 10.2748 10.0746 9.91664
+9.90697 9.91469 9.92445 9.92446 9.91472 9.90702
+
+Species 2
+9.90741 9.92474 9.94623 9.9482 9.93064 9.91713
+9.92282 10.2412 10.644 10.6457 10.2461 9.93064
+9.94232 10.6419 11.5267 11.5281 10.6457 9.9482
+9.94231 10.6415 11.5258 11.5267 10.644 9.94623
+9.92279 10.24 10.6415 10.6419 10.2412 9.92474
+9.90737 9.92279 9.94231 9.94232 9.92282 9.90741
+
+Species 3
+9.90781 9.93284 9.96408 9.96606 9.93874 9.91752
+9.93092 10.4078 11.0109 11.0127 10.4127 9.93874
+9.96017 11.0088 12.3339 12.3354 11.0127 9.96606
+9.96016 11.0083 12.3329 12.3339 11.0109 9.96408
+9.93089 10.4065 11.0083 11.0088 10.4078 9.93284
+9.90776 9.93089 9.96016 9.96017 9.93092 9.90781
+
+Species 4
+297231 297749 298393 298451 297925 297520
+297692 307244 319327 319378 307390 297925
+298276 319264 345799 345840 319378 298451
+298276 319252 345771 345799 319327 298393
+297691 307208 319252 319264 307244 297749
+297229 297691 298276 298276 297692 297231
+
+Species 5
+297231 297749 298393 298451 297925 297520
+297692 307244 319327 319378 307390 297925
+298276 319264 345799 345840 319378 298451
+298276 319252 345771 345799 319327 298393
+297691 307208 319252 319264 307244 297749
+297229 297691 298276 298276 297692 297231
+
+Species 6
+297231 297749 298393 298451 297925 297520
+297692 307244 319327 319378 307390 297925
+298276 319264 345799 345840 319378 298451
+298276 319252 345771 345799 319327 298393
+297691 307208 319252 319264 307244 297749
+297229 297691 298276 298276 297692 297231
+
+t = 1.00e-02 nst = 143 nfe = 166 nni = 162 qu = 3 hu = 1.37e-03
+
+t = 1.00e-01 nst = 165 nfe = 191 nni = 187 qu = 5 hu = 6.02e-03
+
+t = 1.00e+00 nst = 235 nfe = 265 nni = 261 qu = 4 hu = 2.49e-02
+
+c values at t = 1:
+
+Species 1
+1.58853 1.59926 1.62153 1.64766 1.67038 1.68151
+1.58535 1.59505 1.61549 1.63954 1.66035 1.67038
+1.57758 1.58549 1.60241 1.62237 1.63954 1.64766
+1.56822 1.57414 1.58708 1.60241 1.61549 1.62153
+1.5605 1.56465 1.57414 1.58549 1.59505 1.59926
+1.55734 1.5605 1.56822 1.57758 1.58535 1.58853
+
+Species 2
+1.59068 1.60143 1.62373 1.64989 1.67263 1.68377
+1.5875 1.59721 1.61768 1.64175 1.66259 1.67263
+1.57973 1.58764 1.60458 1.62456 1.64175 1.64989
+1.57036 1.57628 1.58923 1.60458 1.61768 1.62373
+1.56263 1.56678 1.57628 1.58764 1.59721 1.60143
+1.55947 1.56263 1.57036 1.57973 1.5875 1.59068
+
+Species 3
+1.59272 1.60347 1.6258 1.65199 1.67476 1.68591
+1.58953 1.59926 1.61975 1.64384 1.6647 1.67476
+1.58175 1.58968 1.60664 1.62664 1.64384 1.65199
+1.57237 1.5783 1.59127 1.60664 1.61975 1.6258
+1.56464 1.56879 1.5783 1.58968 1.59926 1.60347
+1.56147 1.56464 1.57237 1.58175 1.58953 1.59272
+
+Species 4
+47718.9 48040.8 48709.6 49494 50176.1 50509.9
+47623.3 47914.5 48528.3 49250.2 49874.9 50176.1
+47390.2 47627.5 48135.5 48734.6 49250.2 49494
+47109 47286.6 47675.1 48135.5 48528.3 48709.6
+46877.1 47001.6 47286.6 47627.5 47914.5 48040.8
+46782.3 46877.1 47109 47390.2 47623.3 47718.9
+
+Species 5
+47718.9 48040.8 48709.6 49494 50176.1 50509.9
+47623.3 47914.5 48528.3 49250.2 49874.9 50176.1
+47390.2 47627.5 48135.5 48734.6 49250.2 49494
+47109 47286.6 47675.1 48135.5 48528.3 48709.6
+46877.1 47001.6 47286.6 47627.5 47914.5 48040.8
+46782.3 46877.1 47109 47390.2 47623.3 47718.9
+
+Species 6
+47718.9 48040.8 48709.6 49494 50176.1 50509.9
+47623.3 47914.5 48528.3 49250.2 49874.9 50176.1
+47390.2 47627.5 48135.5 48734.6 49250.2 49494
+47109 47286.6 47675.1 48135.5 48528.3 48709.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.81e-02
+
+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
+
+c values at t = 4:
+
+Species 1
+1.19535 1.20368 1.2211 1.24158 1.25935 1.268
+1.19281 1.20035 1.21636 1.23523 1.25154 1.25935
+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
+
+Species 2
+1.19539 1.20372 1.22113 1.24161 1.25939 1.26804
+1.19284 1.20039 1.2164 1.23527 1.25158 1.25939
+1.18661 1.19277 1.20606 1.22177 1.23527 1.24161
+1.17908 1.18372 1.19393 1.20606 1.2164 1.22113
+1.17288 1.17616 1.18372 1.19277 1.20039 1.20372
+1.17036 1.17288 1.17908 1.18661 1.19284 1.19539
+
+Species 3
+1.19542 1.20375 1.22117 1.24164 1.25942 1.26807
+1.19287 1.20042 1.21643 1.2353 1.25161 1.25942
+1.18664 1.1928 1.20609 1.2218 1.2353 1.24164
+1.17911 1.18375 1.19396 1.20609 1.21643 1.22117
+1.17291 1.17619 1.18375 1.1928 1.20042 1.20375
+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
+
+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
+
+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
+
+t = 5.00e+00 nst = 316 nfe = 351 nni = 347 qu = 3 hu = 1.10e-01
+
+t = 6.00e+00 nst = 325 nfe = 361 nni = 357 qu = 3 hu = 1.10e-01
+
+t = 7.00e+00 nst = 334 nfe = 371 nni = 367 qu = 3 hu = 1.10e-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.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
+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.17231 1.17692 1.18709 1.19916 1.20944 1.21415
+1.16614 1.1694 1.17692 1.18594 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
+
+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
+
+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
+
+t = 8.00e+00 nst = 342 nfe = 381 nni = 377 qu = 2 hu = 3.67e-01
+
+t = 9.00e+00 nst = 344 nfe = 383 nni = 379 qu = 2 hu = 3.67e-01
+
+t = 1.00e+01 nst = 346 nfe = 385 nni = 381 qu = 2 hu = 5.82e-01
+
+c values at t = 10:
+
+Species 1
+1.18838 1.19667 1.21399 1.23436 1.25205 1.26065
+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.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.18585 1.19335 1.20928 1.22805 1.24428 1.25205
+1.17964 1.18578 1.199 1.21463 1.22805 1.23436
+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.18585 1.19335 1.20928 1.22805 1.24428 1.25205
+1.17964 1.18578 1.199 1.21463 1.22805 1.23436
+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
+
+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
+
+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
+
+
+
+ Final statistics for this run:
+
+ 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
+ Number of error test failures = 1
+ Number of nonlinear conv. failures = 0
+ Number of linear convergence failures = 0
+ Average Krylov subspace dimension = 1.444
+
+
+----------------------------------------------------------------------------
+----------------------------------------------------------------------------
+
+
+Preconditioner type is jpre = PREC_LEFT
+
+Gram-Schmidt method type is gstype = CLASSICAL_GS
+
+
+t = 1.00e-08 nst = 3 nfe = 10 nni = 6 qu = 2 hu = 1.76e-08
+
+t = 1.00e-07 nst = 7 nfe = 14 nni = 10 qu = 2 hu = 4.78e-08
+
+t = 1.00e-06 nst = 15 nfe = 24 nni = 20 qu = 3 hu = 1.50e-07
+
+t = 1.00e-05 nst = 34 nfe = 47 nni = 43 qu = 5 hu = 6.11e-07
+
+t = 1.00e-04 nst = 116 nfe = 137 nni = 133 qu = 5 hu = 5.51e-06
+
+t = 1.00e-03 nst = 135 nfe = 156 nni = 152 qu = 2 hu = 3.53e-04
+
+t = 1.00e-02 nst = 143 nfe = 166 nni = 162 qu = 3 hu = 1.37e-03
+
+t = 1.00e-01 nst = 165 nfe = 191 nni = 187 qu = 5 hu = 6.02e-03
+
+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 = 4.00e+00 nst = 303 nfe = 337 nni = 333 qu = 3 hu = 6.59e-02
+
+t = 5.00e+00 nst = 313 nfe = 349 nni = 345 qu = 3 hu = 1.26e-01
+
+t = 6.00e+00 nst = 321 nfe = 357 nni = 353 qu = 3 hu = 1.26e-01
+
+t = 7.00e+00 nst = 329 nfe = 366 nni = 362 qu = 3 hu = 1.26e-01
+
+t = 8.00e+00 nst = 337 nfe = 374 nni = 370 qu = 3 hu = 1.26e-01
+
+t = 9.00e+00 nst = 345 nfe = 382 nni = 378 qu = 3 hu = 1.26e-01
+
+t = 1.00e+01 nst = 353 nfe = 391 nni = 387 qu = 3 hu = 1.26e-01
+
+
+
+ Final statistics for this run:
+
+ 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
+ Number of error test failures = 1
+ Number of nonlinear conv. failures = 0
+ Number of linear convergence failures = 0
+ Average Krylov subspace dimension = 1.501
+
+
+----------------------------------------------------------------------------
+----------------------------------------------------------------------------
+
+
+Preconditioner type is jpre = PREC_RIGHT
+
+Gram-Schmidt method type is gstype = MODIFIED_GS
+
+
+t = 1.00e-08 nst = 3 nfe = 10 nni = 6 qu = 2 hu = 1.76e-08
+
+t = 1.00e-07 nst = 7 nfe = 14 nni = 10 qu = 2 hu = 4.78e-08
+
+t = 1.00e-06 nst = 15 nfe = 24 nni = 20 qu = 3 hu = 1.50e-07
+
+t = 1.00e-05 nst = 34 nfe = 47 nni = 43 qu = 5 hu = 6.11e-07
+
+t = 1.00e-04 nst = 118 nfe = 138 nni = 134 qu = 5 hu = 6.64e-06
+
+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+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 = 3.00e+00 nst = 228 nfe = 271 nni = 267 qu = 5 hu = 1.32e-01
+
+t = 4.00e+00 nst = 235 nfe = 278 nni = 274 qu = 5 hu = 1.32e-01
+
+t = 5.00e+00 nst = 240 nfe = 284 nni = 280 qu = 4 hu = 2.06e-01
+
+t = 6.00e+00 nst = 246 nfe = 294 nni = 290 qu = 4 hu = 8.61e-02
+
+t = 7.00e+00 nst = 254 nfe = 306 nni = 302 qu = 2 hu = 2.67e-01
+
+t = 8.00e+00 nst = 257 nfe = 310 nni = 306 qu = 3 hu = 4.13e-01
+
+t = 9.00e+00 nst = 260 nfe = 315 nni = 311 qu = 3 hu = 4.61e-01
+
+t = 1.00e+01 nst = 262 nfe = 321 nni = 317 qu = 3 hu = 2.25e-01
+
+
+
+ Final statistics for this run:
+
+ 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
+ Number of error test failures = 3
+ Number of nonlinear conv. failures = 4
+ Number of linear convergence failures = 48
+ Average Krylov subspace dimension = 2.009
+
+
+----------------------------------------------------------------------------
+----------------------------------------------------------------------------
+
+
+Preconditioner type is jpre = PREC_RIGHT
+
+Gram-Schmidt method type is gstype = CLASSICAL_GS
+
+
+t = 1.00e-08 nst = 3 nfe = 10 nni = 6 qu = 2 hu = 1.76e-08
+
+t = 1.00e-07 nst = 7 nfe = 14 nni = 10 qu = 2 hu = 4.78e-08
+
+t = 1.00e-06 nst = 15 nfe = 24 nni = 20 qu = 3 hu = 1.50e-07
+
+t = 1.00e-05 nst = 34 nfe = 47 nni = 43 qu = 5 hu = 6.11e-07
+
+t = 1.00e-04 nst = 118 nfe = 138 nni = 134 qu = 5 hu = 6.64e-06
+
+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+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 = 3.00e+00 nst = 227 nfe = 271 nni = 267 qu = 5 hu = 1.23e-01
+
+t = 4.00e+00 nst = 234 nfe = 279 nni = 275 qu = 5 hu = 1.90e-01
+
+t = 5.00e+00 nst = 239 nfe = 284 nni = 280 qu = 5 hu = 1.90e-01
+
+t = 6.00e+00 nst = 244 nfe = 289 nni = 285 qu = 5 hu = 1.90e-01
+
+t = 7.00e+00 nst = 259 nfe = 311 nni = 307 qu = 4 hu = 1.53e-01
+
+t = 8.00e+00 nst = 265 nfe = 319 nni = 315 qu = 3 hu = 2.48e-01
+
+t = 9.00e+00 nst = 268 nfe = 322 nni = 318 qu = 3 hu = 3.76e-01
+
+t = 1.00e+01 nst = 270 nfe = 324 nni = 320 qu = 2 hu = 5.81e-01
+
+
+
+ Final statistics for this run:
+
+ 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
+ Number of error test failures = 3
+ Number of nonlinear conv. failures = 2
+ Number of linear convergence failures = 43
+ Average Krylov subspace dimension = 1.956
+
+
+----------------------------------------------------------------------------
+----------------------------------------------------------------------------
diff --git a/examples/cvode/serial/cvRoberts_dns.c b/examples/cvode/serial/cvRoberts_dns.c
new file mode 100644
index 0000000..8ee57fd
--- /dev/null
+++ b/examples/cvode/serial/cvRoberts_dns.c
@@ -0,0 +1,360 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.3 $
+ * $Date: 2010/12/01 22:51:32 $
+ * -----------------------------------------------------------------
+ * 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 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 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
+ * 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 */
+
+/* User-defined vector and matrix accessor macros: Ith, IJth */
+
+/* These macros are defined in order to write code which exactly matches
+ the mathematical problem description given above.
+
+ 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.
+
+ 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. */
+
+#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 */
+
+
+/* Problem Constants */
+
+#define NEQ 3 /* number of equations */
+#define Y1 RCONST(1.0) /* initial y components */
+#define Y2 RCONST(0.0)
+#define Y3 RCONST(0.0)
+#define RTOL RCONST(1.0e-4) /* scalar relative tolerance */
+#define ATOL1 RCONST(1.0e-8) /* vector absolute tolerance components */
+#define ATOL2 RCONST(1.0e-14)
+#define ATOL3 RCONST(1.0e-6)
+#define T0 RCONST(0.0) /* initial time */
+#define T1 RCONST(0.4) /* first output time */
+#define TMULT RCONST(10.0) /* output time factor */
+#define NOUT 12 /* number of output times */
+
+
+/* Functions Called by the Solver */
+
+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);
+
+/* Private functions to output results */
+
+static void PrintOutput(realtype t, realtype y1, realtype y2, realtype y3);
+static void PrintRootInfo(int root_f1, int root_f2);
+
+/* Private function to print final statistics */
+
+static void PrintFinalStats(void *cvode_mem);
+
+/* Private function to check function return values */
+
+static int check_flag(void *flagvalue, char *funcname, int opt);
+
+
+/*
+ *-------------------------------
+ * Main Program
+ *-------------------------------
+ */
+
+int main()
+{
+ realtype reltol, t, tout;
+ N_Vector y, abstol;
+ void *cvode_mem;
+ int flag, flagr, iout;
+ int rootsfound[2];
+
+ y = abstol = NULL;
+ cvode_mem = NULL;
+
+ /* Create serial vector of length NEQ for I.C. and abstol */
+ y = N_VNew_Serial(NEQ);
+ if (check_flag((void *)y, "N_VNew_Serial", 0)) return(1);
+ abstol = N_VNew_Serial(NEQ);
+ if (check_flag((void *)abstol, "N_VNew_Serial", 0)) return(1);
+
+ /* Initialize y */
+ Ith(y,1) = Y1;
+ Ith(y,2) = Y2;
+ Ith(y,3) = Y3;
+
+ /* Set the scalar relative tolerance */
+ reltol = RTOL;
+ /* Set the vector absolute tolerance */
+ Ith(abstol,1) = ATOL1;
+ Ith(abstol,2) = ATOL2;
+ Ith(abstol,3) = ATOL3;
+
+ /* 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 inital 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 CVodeSVtolerances to specify the scalar relative tolerance
+ * and vector absolute tolerances */
+ flag = CVodeSVtolerances(cvode_mem, reltol, abstol);
+ if (check_flag(&flag, "CVodeSVtolerances", 1)) return(1);
+
+ /* Call CVodeRootInit to specify the root function g with 2 components */
+ 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);
+
+ /* Set the Jacobian routine to Jac (user-supplied) */
+ flag = CVDlsSetDenseJacFn(cvode_mem, Jac);
+ if (check_flag(&flag, "CVDlsSetDenseJacFn", 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. */
+ printf(" \n3-species kinetics problem\n\n");
+
+ iout = 0; tout = T1;
+ while(1) {
+ flag = CVode(cvode_mem, tout, y, &t, CV_NORMAL);
+ PrintOutput(t, Ith(y,1), Ith(y,2), Ith(y,3));
+
+ if (flag == CV_ROOT_RETURN) {
+ flagr = CVodeGetRootInfo(cvode_mem, rootsfound);
+ if (check_flag(&flagr, "CVodeGetRootInfo", 1)) return(1);
+ PrintRootInfo(rootsfound[0],rootsfound[1]);
+ }
+
+ if (check_flag(&flag, "CVode", 1)) break;
+ if (flag == CV_SUCCESS) {
+ iout++;
+ tout *= TMULT;
+ }
+
+ if (iout == NOUT) break;
+ }
+
+ /* Print some final statistics */
+ PrintFinalStats(cvode_mem);
+
+ /* Free y and abstol vectors */
+ N_VDestroy_Serial(y);
+ N_VDestroy_Serial(abstol);
+
+ /* Free integrator memory */
+ CVodeFree(&cvode_mem);
+
+ return(0);
+}
+
+
+/*
+ *-------------------------------
+ * Functions called by the solver
+ *-------------------------------
+ */
+
+/*
+ * f routine. Compute function f(t,y).
+ */
+
+static int f(realtype t, N_Vector y, N_Vector ydot, void *user_data)
+{
+ realtype y1, y2, y3, yd1, yd3;
+
+ y1 = Ith(y,1); y2 = Ith(y,2); y3 = Ith(y,3);
+
+ yd1 = Ith(ydot,1) = RCONST(-0.04)*y1 + RCONST(1.0e4)*y2*y3;
+ yd3 = Ith(ydot,3) = RCONST(3.0e7)*y2*y2;
+ Ith(ydot,2) = -yd1 - yd3;
+
+ return(0);
+}
+
+/*
+ * g routine. Compute functions g_i(t,y) for i = 0,1.
+ */
+
+static int g(realtype t, N_Vector y, realtype *gout, void *user_data)
+{
+ realtype y1, y3;
+
+ y1 = Ith(y,1); y3 = Ith(y,3);
+ gout[0] = y1 - RCONST(0.0001);
+ gout[1] = y3 - RCONST(0.01);
+
+ return(0);
+}
+
+/*
+ * 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)
+{
+ realtype y1, y2, y3;
+
+ y1 = Ith(y,1); y2 = Ith(y,2); y3 = Ith(y,3);
+
+ 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,2) = RCONST(6.0e7)*y2;
+
+ return(0);
+}
+
+/*
+ *-------------------------------
+ * Private helper functions
+ *-------------------------------
+ */
+
+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);
+#else
+ printf("At t = %0.4e y =%14.6e %14.6e %14.6e\n", t, y1, y2, y3);
+#endif
+
+ return;
+}
+
+static void PrintRootInfo(int root_f1, int root_f2)
+{
+ printf(" rootsfound[] = %3d %3d\n", root_f1, root_f2);
+
+ return;
+}
+
+/*
+ * Get and print some final statistics
+ */
+
+static void PrintFinalStats(void *cvode_mem)
+{
+ long int nst, nfe, nsetups, nje, nfeLS, nni, ncfn, netf, nge;
+ int flag;
+
+ 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 = CVDlsGetNumJacEvals(cvode_mem, &nje);
+ check_flag(&flag, "CVDlsGetNumJacEvals", 1);
+ flag = CVDlsGetNumRhsEvals(cvode_mem, &nfeLS);
+ check_flag(&flag, "CVDlsGetNumRhsEvals", 1);
+
+ flag = CVodeGetNumGEvals(cvode_mem, &nge);
+ check_flag(&flag, "CVodeGetNumGEvals", 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 = %-6ld nge = %ld\n \n",
+ nni, ncfn, netf, nge);
+}
+
+/*
+ * 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, 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/serial/cvRoberts_dns.out b/examples/cvode/serial/cvRoberts_dns.out
new file mode 100644
index 0000000..c21cc40
--- /dev/null
+++ b/examples/cvode/serial/cvRoberts_dns.out
@@ -0,0 +1,24 @@
+
+3-species kinetics problem
+
+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
+ 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
+
+Final Statistics:
+nst = 579 nfe = 817 nsetups = 118 nfeLS = 0 nje = 12
+nni = 813 ncfn = 0 netf = 31 nge = 615
+
diff --git a/examples/cvode/serial/cvRoberts_dnsL.c b/examples/cvode/serial/cvRoberts_dnsL.c
new file mode 100644
index 0000000..f4379f2
--- /dev/null
+++ b/examples/cvode/serial/cvRoberts_dnsL.c
@@ -0,0 +1,363 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.2 $
+ * $Date: 2010/12/01 22:51:32 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Example problem:
+ *
+ * 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 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 LAPACK 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. and consts. */
+#include <cvode/cvode_lapack.h> /* prototype for CVLapackDense */
+#include <nvector/nvector_serial.h> /* serial N_Vector types, fcts., and macros */
+
+/* User-defined vector and matrix accessor macros: Ith, IJth */
+
+/* These macros are defined in order to write code which exactly matches
+ the mathematical problem description given above.
+
+ 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.
+
+ 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. */
+
+#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 */
+
+
+/* Problem Constants */
+
+#define NEQ 3 /* number of equations */
+#define Y1 RCONST(1.0) /* initial y components */
+#define Y2 RCONST(0.0)
+#define Y3 RCONST(0.0)
+#define RTOL RCONST(1.0e-4) /* scalar relative tolerance */
+#define ATOL1 RCONST(1.0e-8) /* vector absolute tolerance components */
+#define ATOL2 RCONST(1.0e-14)
+#define ATOL3 RCONST(1.0e-6)
+#define T0 RCONST(0.0) /* initial time */
+#define T1 RCONST(0.4) /* first output time */
+#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 */
+
+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);
+
+/* Private functions to output results */
+
+static void PrintOutput(realtype t, realtype y1, realtype y2, realtype y3);
+static void PrintRootInfo(int root_f1, int root_f2);
+
+/* Private function to print final statistics */
+
+static void PrintFinalStats(void *cvode_mem);
+
+/* Private function to check function return values */
+
+static int check_flag(void *flagvalue, char *funcname, int opt);
+
+
+/*
+ *-------------------------------
+ * Main Program
+ *-------------------------------
+ */
+
+int main()
+{
+ realtype reltol, t, tout;
+ N_Vector y, abstol;
+ void *cvode_mem;
+ int flag, flagr, iout;
+ int rootsfound[2];
+
+ y = abstol = NULL;
+ cvode_mem = NULL;
+
+ /* Create serial vector of length NEQ for I.C. and abstol */
+ y = N_VNew_Serial(NEQ);
+ if (check_flag((void *)y, "N_VNew_Serial", 0)) return(1);
+ abstol = N_VNew_Serial(NEQ);
+ if (check_flag((void *)abstol, "N_VNew_Serial", 0)) return(1);
+
+ /* Initialize y */
+ Ith(y,1) = Y1;
+ Ith(y,2) = Y2;
+ Ith(y,3) = Y3;
+
+ /* Set the scalar relative tolerance */
+ reltol = RTOL;
+ /* Set the vector absolute tolerance */
+ Ith(abstol,1) = ATOL1;
+ Ith(abstol,2) = ATOL2;
+ Ith(abstol,3) = ATOL3;
+
+ /* 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 inital 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 CVodeSVtolerances to specify the scalar relative tolerance
+ * and vector absolute tolerances */
+ flag = CVodeSVtolerances(cvode_mem, reltol, abstol);
+ if (check_flag(&flag, "CVodeSVtolerances", 1)) return(1);
+
+ /* Call CVodeRootInit to specify the root function g with 2 components */
+ 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);
+
+ /* Set the Jacobian routine to Jac (user-supplied) */
+ flag = CVDlsSetDenseJacFn(cvode_mem, Jac);
+ if (check_flag(&flag, "CVDlsSetDenseJacFn", 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. */
+ printf(" \n3-species kinetics problem\n\n");
+
+ iout = 0; tout = T1;
+ while(1) {
+ flag = CVode(cvode_mem, tout, y, &t, CV_NORMAL);
+ PrintOutput(t, Ith(y,1), Ith(y,2), Ith(y,3));
+
+ if (flag == CV_ROOT_RETURN) {
+ flagr = CVodeGetRootInfo(cvode_mem, rootsfound);
+ if (check_flag(&flagr, "CVodeGetRootInfo", 1)) return(1);
+ PrintRootInfo(rootsfound[0],rootsfound[1]);
+ }
+
+ if (check_flag(&flag, "CVode", 1)) break;
+ if (flag == CV_SUCCESS) {
+ iout++;
+ tout *= TMULT;
+ }
+
+ if (iout == NOUT) break;
+ }
+
+ /* Print some final statistics */
+ PrintFinalStats(cvode_mem);
+
+ /* Free y vector */
+ N_VDestroy_Serial(y);
+
+ /* Free integrator memory */
+ CVodeFree(&cvode_mem);
+
+ return(0);
+}
+
+
+/*
+ *-------------------------------
+ * Functions called by the solver
+ *-------------------------------
+ */
+
+/*
+ * f routine. Compute function f(t,y).
+ */
+
+static int f(realtype t, N_Vector y, N_Vector ydot, void *user_data)
+{
+ realtype y1, y2, y3, yd1, yd3;
+
+ y1 = Ith(y,1); y2 = Ith(y,2); y3 = Ith(y,3);
+
+ yd1 = Ith(ydot,1) = RCONST(-0.04)*y1 + RCONST(1.0e4)*y2*y3;
+ yd3 = Ith(ydot,3) = RCONST(3.0e7)*y2*y2;
+ Ith(ydot,2) = -yd1 - yd3;
+
+ return(0);
+}
+
+/*
+ * g routine. Compute functions g_i(t,y) for i = 0,1.
+ */
+
+static int g(realtype t, N_Vector y, realtype *gout, void *user_data)
+{
+ realtype y1, y3;
+
+ y1 = Ith(y,1); y3 = Ith(y,3);
+ gout[0] = y1 - RCONST(0.0001);
+ gout[1] = y3 - RCONST(0.01);
+
+ return(0);
+}
+
+/*
+ * 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)
+{
+ realtype y1, y2, y3;
+
+ y1 = Ith(y,1); y2 = Ith(y,2); y3 = Ith(y,3);
+
+ 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);
+}
+
+/*
+ *-------------------------------
+ * Private helper functions
+ *-------------------------------
+ */
+
+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);
+#else
+ printf("At t = %0.4e y =%14.6e %14.6e %14.6e\n", t, y1, y2, y3);
+#endif
+
+ return;
+}
+
+static void PrintRootInfo(int root_f1, int root_f2)
+{
+ printf(" rootsfound[] = %3d %3d\n", root_f1, root_f2);
+
+ return;
+}
+
+/*
+ * Get and print some final statistics
+ */
+
+static void PrintFinalStats(void *cvode_mem)
+{
+ long int nst, nfe, nsetups, nje, nfeLS, nni, ncfn, netf, nge;
+ int flag;
+
+ 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 = CVDlsGetNumJacEvals(cvode_mem, &nje);
+ check_flag(&flag, "CVDlsGetNumJacEvals", 1);
+ flag = CVDlsGetNumRhsEvals(cvode_mem, &nfeLS);
+ check_flag(&flag, "CVDlsGetNumRhsEvals", 1);
+
+ flag = CVodeGetNumGEvals(cvode_mem, &nge);
+ check_flag(&flag, "CVodeGetNumGEvals", 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 = %-6ld nge = %ld\n \n",
+ nni, ncfn, netf, nge);
+}
+
+/*
+ * 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, 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/serial/cvRoberts_dnsL.out b/examples/cvode/serial/cvRoberts_dnsL.out
new file mode 100644
index 0000000..747ed23
--- /dev/null
+++ b/examples/cvode/serial/cvRoberts_dnsL.out
@@ -0,0 +1,24 @@
+
+3-species kinetics problem
+
+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
+ 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
+
+Final Statistics:
+nst = 577 nfe = 838 nsetups = 125 nfeLS = 0 nje = 12
+nni = 834 ncfn = 0 netf = 33 nge = 612
+
diff --git a/examples/cvode/serial/cvRoberts_dns_uw.c b/examples/cvode/serial/cvRoberts_dns_uw.c
new file mode 100644
index 0000000..64f49c3
--- /dev/null
+++ b/examples/cvode/serial/cvRoberts_dns_uw.c
@@ -0,0 +1,377 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.2 $
+ * $Date: 2010/12/01 22:51:32 $
+ * -----------------------------------------------------------------
+ * 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 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 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
+ * 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 */
+
+/* User-defined vector and matrix accessor macros: Ith, IJth */
+
+/* These macros are defined in order to write code which exactly matches
+ the mathematical problem description given above.
+
+ 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.
+
+ 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. */
+
+#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 */
+
+
+/* Problem Constants */
+
+#define NEQ 3 /* number of equations */
+#define Y1 RCONST(1.0) /* initial y components */
+#define Y2 RCONST(0.0)
+#define Y3 RCONST(0.0)
+#define RTOL RCONST(1.0e-4) /* scalar relative tolerance */
+#define ATOL1 RCONST(1.0e-8) /* vector absolute tolerance components */
+#define ATOL2 RCONST(1.0e-14)
+#define ATOL3 RCONST(1.0e-6)
+#define T0 RCONST(0.0) /* initial time */
+#define T1 RCONST(0.4) /* first output time */
+#define TMULT RCONST(10.0) /* output time factor */
+#define NOUT 12 /* number of output times */
+
+
+/* Functions Called by the Solver */
+
+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 ewt(N_Vector y, N_Vector w, void *user_data);
+
+/* Private functions to output results */
+
+static void PrintOutput(realtype t, realtype y1, realtype y2, realtype y3);
+static void PrintRootInfo(int root_f1, int root_f2);
+
+/* Private function to print final statistics */
+
+static void PrintFinalStats(void *cvode_mem);
+
+/* Private function to check function return values */
+
+static int check_flag(void *flagvalue, char *funcname, int opt);
+
+
+/*
+ *-------------------------------
+ * Main Program
+ *-------------------------------
+ */
+
+int main()
+{
+ realtype t, tout;
+ N_Vector y;
+ void *cvode_mem;
+ int flag, flagr, iout;
+ int rootsfound[2];
+
+ y = NULL;
+ cvode_mem = NULL;
+
+ /* Create serial vector of length NEQ for I.C. */
+ y = N_VNew_Serial(NEQ);
+ if (check_flag((void *)y, "N_VNew_Serial", 0)) return(1);
+
+ /* Initialize y */
+ Ith(y,1) = Y1;
+ Ith(y,2) = Y2;
+ Ith(y,3) = Y3;
+
+ /* 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 inital time T0, and
+ * the initial dependent variable vector y. */
+ flag = CVodeInit(cvode_mem, f, T0, y);
+ if (check_flag(&flag, "CVodeInit", 1)) return(1);
+
+ /* Use private function to compute error weights */
+ flag = CVodeWFtolerances(cvode_mem, ewt);
+ if (check_flag(&flag, "CVodeSetEwtFn", 1)) return(1);
+
+ /* Call CVodeRootInit to specify the root function g with 2 components */
+ 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);
+
+ /* Set the Jacobian routine to Jac (user-supplied) */
+ flag = CVDlsSetDenseJacFn(cvode_mem, Jac);
+ if (check_flag(&flag, "CVDlsSetDenseJacFn", 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. */
+ printf(" \n3-species kinetics problem\n\n");
+
+ iout = 0; tout = T1;
+ while(1) {
+ flag = CVode(cvode_mem, tout, y, &t, CV_NORMAL);
+ PrintOutput(t, Ith(y,1), Ith(y,2), Ith(y,3));
+
+ if (flag == CV_ROOT_RETURN) {
+ flagr = CVodeGetRootInfo(cvode_mem, rootsfound);
+ check_flag(&flagr, "CVodeGetRootInfo", 1);
+ PrintRootInfo(rootsfound[0],rootsfound[1]);
+ }
+
+ if (check_flag(&flag, "CVode", 1)) break;
+ if (flag == CV_SUCCESS) {
+ iout++;
+ tout *= TMULT;
+ }
+
+ if (iout == NOUT) break;
+ }
+
+ /* Print some final statistics */
+ PrintFinalStats(cvode_mem);
+
+ /* Free y vector */
+ N_VDestroy_Serial(y);
+
+ /* Free integrator memory */
+ CVodeFree(&cvode_mem);
+
+ return(0);
+}
+
+
+/*
+ *-------------------------------
+ * Functions called by the solver
+ *-------------------------------
+ */
+
+/*
+ * f routine. Compute function f(t,y).
+ */
+
+static int f(realtype t, N_Vector y, N_Vector ydot, void *user_data)
+{
+ realtype y1, y2, y3, yd1, yd3;
+
+ y1 = Ith(y,1); y2 = Ith(y,2); y3 = Ith(y,3);
+
+ yd1 = Ith(ydot,1) = RCONST(-0.04)*y1 + RCONST(1.0e4)*y2*y3;
+ yd3 = Ith(ydot,3) = RCONST(3.0e7)*y2*y2;
+ Ith(ydot,2) = -yd1 - yd3;
+
+ return(0);
+}
+
+/*
+ * g routine. Compute functions g_i(t,y) for i = 0,1.
+ */
+
+static int g(realtype t, N_Vector y, realtype *gout, void *user_data)
+{
+ realtype y1, y3;
+
+ y1 = Ith(y,1); y3 = Ith(y,3);
+ gout[0] = y1 - RCONST(0.0001);
+ gout[1] = y3 - RCONST(0.01);
+
+ return(0);
+}
+
+/*
+ * 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)
+{
+ realtype y1, y2, y3;
+
+ y1 = Ith(y,1); y2 = Ith(y,2); y3 = Ith(y,3);
+
+ 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,2) = RCONST(6.0e7)*y2;
+
+ return(0);
+}
+
+/*
+ * EwtSet function. Computes the error weights at the current solution.
+ */
+
+static int ewt(N_Vector y, N_Vector w, void *user_data)
+{
+ int i;
+ realtype yy, ww, rtol, atol[3];
+
+ rtol = RTOL;
+ atol[0] = ATOL1;
+ atol[1] = ATOL2;
+ atol[2] = ATOL3;
+
+ for (i=1; i<=3; i++) {
+ yy = Ith(y,i);
+ ww = rtol * ABS(yy) + atol[i-1];
+ if (ww <= 0.0) return (-1);
+ Ith(w,i) = 1.0/ww;
+ }
+
+ return(0);
+}
+
+/*
+ *-------------------------------
+ * Private helper functions
+ *-------------------------------
+ */
+
+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);
+#else
+ printf("At t = %0.4e y =%14.6e %14.6e %14.6e\n", t, y1, y2, y3);
+#endif
+
+ return;
+}
+
+static void PrintRootInfo(int root_f1, int root_f2)
+{
+ printf(" rootsfound[] = %3d %3d\n", root_f1, root_f2);
+
+ return;
+}
+
+/*
+ * Get and print some final statistics
+ */
+
+static void PrintFinalStats(void *cvode_mem)
+{
+ long int nst, nfe, nsetups, nje, nfeLS, nni, ncfn, netf, nge;
+ int flag;
+
+ 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 = CVDlsGetNumJacEvals(cvode_mem, &nje);
+ check_flag(&flag, "CVDlsGetNumJacEvals", 1);
+ flag = CVDlsGetNumRhsEvals(cvode_mem, &nfeLS);
+ check_flag(&flag, "CVDlsGetNumRhsEvals", 1);
+
+ flag = CVodeGetNumGEvals(cvode_mem, &nge);
+ check_flag(&flag, "CVodeGetNumGEvals", 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 = %-6ld nge = %ld\n \n",
+ nni, ncfn, netf, nge);
+}
+
+/*
+ * 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, 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/serial/cvRoberts_dns_uw.out b/examples/cvode/serial/cvRoberts_dns_uw.out
new file mode 100644
index 0000000..ce633e3
--- /dev/null
+++ b/examples/cvode/serial/cvRoberts_dns_uw.out
@@ -0,0 +1,24 @@
+
+3-species kinetics problem
+
+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
+ 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
+
+Final Statistics:
+nst = 545 nfe = 773 nsetups = 117 nfeLS = 0 nje = 12
+nni = 769 ncfn = 0 netf = 30 nge = 573
+
diff --git a/examples/cvodes/parallel/CMakeLists.txt b/examples/cvodes/parallel/CMakeLists.txt
new file mode 100644
index 0000000..1c0e1a0
--- /dev/null
+++ b/examples/cvodes/parallel/CMakeLists.txt
@@ -0,0 +1,118 @@
+# ---------------------------------------------------------------
+# $Revision: 1.4 $
+# $Date: 2009/02/17 02:58:47 $
+# ---------------------------------------------------------------
+# Programmer: Radu Serban @ LLNL
+# ---------------------------------------------------------------
+# Copyright (c) 2007, The Regents of the University of California.
+# Produced at the Lawrence Livermore National Laboratory.
+# All rights reserved.
+# For details, see the LICENSE file.
+# ---------------------------------------------------------------
+# CMakeLists.txt file for the CVODES parallel examples
+
+
+# Add variable CVODES_examples with the names of the parallel CVODES examples
+
+SET(CVODES_examples
+ cvsAdvDiff_ASAp_non_p
+ cvsAdvDiff_FSA_non_p
+ cvsAdvDiff_non_p
+ cvsAtmDisp_ASAi_kry_bbd_p
+ cvsDiurnal_FSA_kry_p
+ cvsDiurnal_kry_bbd_p
+ cvsDiurnal_kry_p
+ )
+
+# 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)
+ # add MPI_INCLUDE_PATH to include directories
+ INCLUDE_DIRECTORIES(${MPI_INCLUDE_PATH})
+ENDIF(MPI_MPICC)
+
+# 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")
+ SET(CVODES_LIB sundials_cvodes_shared)
+ SET(NVECP_LIB sundials_nvecparallel_shared)
+ENDIF(LINK_LIBRARY_TYPE MATCHES "static")
+
+# Set-up linker flags and link libraries
+
+SET(SUNDIALS_LIBS ${CVODES_LIB} ${NVECP_LIB} ${EXTRA_LINK_LIBS})
+IF(LAPACK_FOUND)
+ SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${LAPACK_LINKER_FLAGS}")
+ SET(SUNDIALS_LIBS "${SUNDIALS_LIBS} ${LAPACK_LIBRARIES}")
+ENDIF(LAPACK_FOUND)
+
+# Add the build and install targets for each CVODES example
+
+FOREACH(example ${CVODES_examples})
+ ADD_EXECUTABLE(${example} ${example}.c)
+ TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+ IF(NOT MPI_MPICC)
+ TARGET_LINK_LIBRARIES(${example} ${MPI_LIBRARY} ${MPI_EXTRA_LIBRARIES})
+ ENDIF(NOT MPI_MPICC)
+ FILE(GLOB example_out ${example}.out*)
+ IF(EXAMPLES_INSTALL)
+ INSTALL(FILES ${example}.c ${example_out} DESTINATION ${EXAMPLES_INSTALL_PATH}/cvodes/parallel)
+ ENDIF(EXAMPLES_INSTALL)
+ENDFOREACH(example ${CVODES_examples})
+
+IF(EXAMPLES_INSTALL)
+
+ # Install the README file
+ INSTALL(FILES README DESTINATION ${EXAMPLES_INSTALL_PATH}/cvodes/parallel)
+
+ # Prepare substitution variables for Makefile and/or CMakeLists templates
+ SET(SOLVER "CVODES")
+ SET(SOLVER_LIB "sundials_cvodes")
+ LIST2STRING(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
+ # 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
+ )
+
+ # install CMakelists.txt
+ INSTALL(
+ FILES ${PROJECT_BINARY_DIR}/examples/cvodes/parallel/CMakeLists.txt
+ 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
+ # 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/cvodes/parallel/Makefile_ex
+ @ONLY
+ )
+ # install the configured Makefile_ex as Makefile
+ INSTALL(
+ FILES ${PROJECT_BINARY_DIR}/examples/cvodes/parallel/Makefile_ex
+ DESTINATION ${EXAMPLES_INSTALL_PATH}/cvodes/parallel
+ RENAME Makefile
+ )
+ ENDIF(UNIX)
+
+ENDIF(EXAMPLES_INSTALL)
diff --git a/examples/cvodes/parallel/Makefile.in b/examples/cvodes/parallel/Makefile.in
new file mode 100644
index 0000000..8cbd3d7
--- /dev/null
+++ b/examples/cvodes/parallel/Makefile.in
@@ -0,0 +1,116 @@
+# -----------------------------------------------------------------
+# $Revision: 1.9 $
+# $Date: 2009/02/17 02:58:47 $
+# -----------------------------------------------------------------
+# Programmer(s): Radu Serban and Aaron Collier @ LLNL
+# -----------------------------------------------------------------
+# Copyright (c) 2002, The Regents of the University of California.
+# Produced at the Lawrence Livermore National Laboratory.
+# All rights reserved.
+# For details, see the LICENSE file.
+# -----------------------------------------------------------------
+# Makefile for CVODES parallel examples
+#
+# @configure_input@
+# -----------------------------------------------------------------
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_builddir = @top_builddir@
+builddir = @builddir@
+abs_builddir = @abs_builddir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+includedir = @includedir@
+libdir = @libdir@
+
+INSTALL = @INSTALL@
+INSTALL_PROG = @INSTALL_PROGRAM@
+INSTALL_FILE = @INSTALL_DATA@
+
+LIBTOOL = @LIBTOOL@
+LIBTOOL_DEPS = @LIBTOOL_DEPS@
+
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CC = @CC@
+CFLAGS = @CFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+MPICC = @MPICC@
+MPI_INC_DIR = @MPI_INC_DIR@
+MPI_LIB_DIR = @MPI_LIB_DIR@
+MPI_LIBS = @MPI_LIBS@
+MPI_FLAGS = @MPI_FLAGS@
+
+BLAS_LAPACK_LIBS = @BLAS_LAPACK_LIBS@
+
+OBJ_EXT = @OBJEXT@
+EXE_EXT = @EXEEXT@
+
+EXS_INSTDIR = @EXS_INSTDIR@
+
+top_srcdir = $(srcdir)/../../..
+
+SUNDIALS_INCS = -I$(top_srcdir)/include -I$(top_builddir)/include
+
+SUNDIALS_LIBS = $(top_builddir)/src/cvodes/libsundials_cvodes.la $(top_builddir)/src/nvec_par/libsundials_nvecparallel.la
+
+mkinstalldirs = $(SHELL) $(top_srcdir)/config/mkinstalldirs
+rminstalldirs = $(SHELL) $(top_srcdir)/config/rminstalldirs
+
+EXAMPLES = cvsAdvDiff_ASAp_non_p \
+ cvsAdvDiff_FSA_non_p \
+ cvsAdvDiff_non_p \
+ cvsAtmDisp_ASAi_kry_bbd_p \
+ cvsDiurnal_FSA_kry_p \
+ cvsDiurnal_kry_bbd_p \
+ cvsDiurnal_kry_p
+
+OBJECTS = ${EXAMPLES:=${OBJ_EXT}}
+EXECS = ${EXAMPLES:=${EXE_EXT}}
+
+# ----------------------------------------------------------------------------------------------------------------------
+
+all:
+ @for i in ${EXAMPLES} ; do \
+ $(LIBTOOL) --mode=compile $(MPICC) $(CPPFLAGS) $(MPI_FLAGS) $(SUNDIALS_INCS) -I$(MPI_INC_DIR) $(CFLAGS) -c $(srcdir)/$${i}.c -o $${i}${OBJ_EXT} ; \
+ $(LIBTOOL) --mode=link $(MPICC) -o $(builddir)/$${i}$(EXE_EXT) $(builddir)/$${i}$(OBJ_EXT) $(MPI_FLAGS) $(CFLAGS) $(LDFLAGS) $(SUNDIALS_LIBS) -L$(MPI_LIB_DIR) $(MPI_LIBS) $(LIBS) $(BLAS_LAPACK_LIBS) ; \
+ done
+
+install:
+ $(mkinstalldirs) $(EXS_INSTDIR)/cvodes/parallel
+ $(INSTALL_FILE) Makefile_ex $(EXS_INSTDIR)/cvodes/parallel/Makefile
+ $(INSTALL_FILE) $(top_srcdir)/examples/cvodes/parallel/README $(EXS_INSTDIR)/cvodes/parallel/
+ for i in ${EXAMPLES} ; do \
+ $(INSTALL_FILE) $(top_srcdir)/examples/cvodes/parallel/$${i}.c $(EXS_INSTDIR)/cvodes/parallel/ ; \
+ $(INSTALL_FILE) $(top_srcdir)/examples/cvodes/parallel/$${i}.out $(EXS_INSTDIR)/cvodes/parallel/ ; \
+ done
+
+uninstall:
+ rm -f $(EXS_INSTDIR)/cvodes/parallel/Makefile
+ rm -f $(EXS_INSTDIR)/cvodes/parallel/README
+ for i in ${EXAMPLES} ; do \
+ rm -f $(EXS_INSTDIR)/cvodes/parallel/$${i}.c ; \
+ rm -f $(EXS_INSTDIR)/cvodes/parallel/$${i}.out ; \
+ done
+ $(rminstalldirs) $(EXS_INSTDIR)/cvodes/parallel
+ $(rminstalldirs) $(EXS_INSTDIR)/cvodes
+
+clean:
+ rm -rf .libs
+ rm -f *.lo *.o
+ rm -f ${OBJECTS}
+ rm -f $(EXECS)
+
+distclean: clean
+ rm -f Makefile
+ rm -f Makefile_ex
+
+# ----------------------------------------------------------------------------------------------------------------------
+
+libtool: $(top_builddir)/$(LIBTOOL_DEPS)
+ @cd ${top_builddir} ; \
+ ${SHELL} ./config.status --recheck ; \
+ cd ${abs_builddir}
diff --git a/examples/cvodes/parallel/README b/examples/cvodes/parallel/README
new file mode 100644
index 0000000..573f2e7
--- /dev/null
+++ b/examples/cvodes/parallel/README
@@ -0,0 +1,34 @@
+List of parallel CVODES examples
+
+(1) Simulation
+
+ cvsAdvDiff_non_p : 1-D advection-diffusion (nonstiff)
+ cvsDiurnal_kry_bbd_p : 2-D 2-species diurnal advection-diffusion
+ BBD preconditioner
+ cvsDiurnal_kry_p : 2-D 2-species diurnal advection-diffusion
+
+
+(2) Forward sensitivity
+
+ cvsAdvDiff_FSA_non_p : 1-D advection difusion PDE -
+ Adams with Functional iteration
+ cvsDiurnal_FSA_kry_p : 2-D 2-species diurnal advection-diffusion PDE -
+ BDF with Newton GMRES
+
+(3) Adjoint sensitivity
+
+ cvsAdvDiff_ASAp_non_p : 1-D advection-diffusion (nonstiff)
+ cvsAtmDisp_ASAi_kry_bbd_p : 2-D (or 3-D) advection-diffusion-reaction PDE
+ BDF/SPGMR/BBD
+
+Sample results:
+
+ SUNDIALS was built with the following options:
+
+ ./configure CC=gcc F77=gfortran CFLAGS="-g3 -O0" FFLAGS="-g3 -O0" --enable-examples
+
+ System Architecture: IA-32
+ Processor Type: Intel Pentium 4 Xeon DP (i686)
+ Operating System: Red Hat Enterprise Linux WS 3 (Taroon Update 7)
+ C/Fortran Compilers: gcc/gfortran v4.1.0
+ MPI Implementation: Open MPI v1.1
diff --git a/examples/cvodes/parallel/cvsAdvDiff_ASAp_non_p.c b/examples/cvodes/parallel/cvsAdvDiff_ASAp_non_p.c
new file mode 100644
index 0000000..399a6f6
--- /dev/null
+++ b/examples/cvodes/parallel/cvsAdvDiff_ASAp_non_p.c
@@ -0,0 +1,696 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.1 $
+ * $Date: 2007/10/25 20:03:30 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Example problem:
+ *
+ * The following is a simple example problem, with the program for
+ * its solution by CVODE. The problem is the semi-discrete form of
+ * the advection-diffusion equation in 1-D:
+ * du/dt = p1 * d^2u / dx^2 + p2 * du / dx
+ * on the interval 0 <= x <= 2, and the time interval 0 <= t <= 5.
+ * Homogeneous Dirichlet boundary conditions are posed, and the
+ * initial condition is:
+ * u(x,t=0) = x(2-x)exp(2x).
+ * The nominal values of the two parameters are: p1=1.0, p2=0.5
+ * 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 option for nonstiff
+ * systems: ADAMS method and functional iteration.
+ * It uses scalar relative and absolute tolerances.
+ *
+ * In addition to the solution, sensitivities with respect to p1
+ * and p2 as well as with respect to initial conditions are
+ * computed for the quantity:
+ * g(t, u, p) = int_x u(x,t) at t = 5
+ * These sensitivities are obtained by solving the adjoint system:
+ * dv/dt = -p1 * d^2 v / dx^2 + p2 * dv / dx
+ * with homogeneous Ditrichlet boundary conditions and the final
+ * condition:
+ * v(x,t=5) = 1.0
+ * Then, v(x, t=0) represents the sensitivity of g(5) with respect
+ * to u(x, t=0) and the gradient of g(5) with respect to p1, p2 is
+ * (dg/dp)^T = [ int_t int_x (v * d^2u / dx^2) dx dt ]
+ * [ int_t int_x (v * du / dx) dx dt ]
+ *
+ * This version uses MPI for user routines.
+ * Execute with Number of Processors = N, with 1 <= N <= MX.
+ * -----------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+
+#include <cvodes/cvodes.h>
+#include <nvector/nvector_parallel.h>
+#include <sundials/sundials_math.h>
+#include <sundials/sundials_types.h>
+
+#include <mpi.h>
+
+/* Problem Constants */
+
+#define XMAX RCONST(2.0) /* domain boundary */
+#define MX 20 /* mesh dimension */
+#define NEQ MX /* number of equations */
+#define ATOL RCONST(1.e-5) /* scalar absolute tolerance */
+#define T0 RCONST(0.0) /* initial time */
+#define TOUT RCONST(2.5) /* output time increment */
+
+/* Adjoint Problem Constants */
+
+#define NP 2 /* number of parameters */
+#define STEPS 200 /* steps between check points */
+
+#define ZERO RCONST(0.0)
+#define ONE RCONST(1.0)
+#define TWO RCONST(2.0)
+
+/* Type : UserData */
+
+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;
+ MPI_Comm comm; /* MPI communicator */
+ realtype *z1, *z2; /* work space */
+} *UserData;
+
+/* Prototypes of user-supplied funcitons */
+
+static int f(realtype t, N_Vector u, N_Vector udot, void *user_data);
+static int fB(realtype t, N_Vector u,
+ N_Vector uB, N_Vector uBdot, void *user_dataB);
+
+/* 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 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, char *funcname, int opt, int id);
+
+/*
+ *--------------------------------------------------------------------
+ * MAIN PROGRAM
+ *--------------------------------------------------------------------
+ */
+
+int main(int argc, char *argv[])
+{
+ UserData data;
+
+ void *cvode_mem;
+
+ N_Vector u;
+ realtype reltol, abstol;
+
+ int indexB;
+ N_Vector uB;
+
+ realtype dx, t, g_val;
+ int flag, my_pe, nprocs, npes, ncheck;
+ long int local_N=0, nperpe, nrem, my_base=-1;
+
+ MPI_Comm comm;
+
+ data = NULL;
+ cvode_mem = NULL;
+ u = uB = NULL;
+
+ /*------------------------------------------------------
+ Initialize MPI and get total number of pe's, and my_pe
+ ------------------------------------------------------*/
+ MPI_Init(&argc, &argv);
+ comm = MPI_COMM_WORLD;
+ MPI_Comm_size(comm, &nprocs);
+ MPI_Comm_rank(comm, &my_pe);
+
+ npes = nprocs - 1; /* pe's dedicated to PDE integration */
+
+ if ( npes <= 0 ) {
+ if (my_pe == npes)
+ fprintf(stderr, "\nMPI_ERROR(%d): number of processes must be >= 2\n\n",
+ my_pe);
+ MPI_Finalize();
+ return(1);
+ }
+
+ /*-----------------------
+ Set local vector length
+ -----------------------*/
+ nperpe = NEQ/npes;
+ nrem = NEQ - npes*nperpe;
+ if (my_pe < npes) {
+
+ /* PDE vars. distributed to this proccess */
+ local_N = (my_pe < nrem) ? nperpe+1 : nperpe;
+ my_base = (my_pe < nrem) ? my_pe*local_N : my_pe*nperpe + nrem;
+
+ } else {
+
+ /* Make last process inactive for forward phase */
+ local_N = 0;
+
+ }
+
+ /*-------------------------------------
+ Allocate and load user data structure
+ -------------------------------------*/
+ data = (UserData) malloc(sizeof *data);
+ if (check_flag((void *)data , "malloc", 2, my_pe)) MPI_Abort(comm, 1);
+ data->p[0] = ONE;
+ data->p[1] = RCONST(0.5);
+ dx = data->dx = XMAX/((realtype)(MX+1));
+ data->hdcoef = data->p[0]/(dx*dx);
+ data->hacoef = data->p[1]/(TWO*dx);
+ data->comm = comm;
+ data->npes = npes;
+ data->my_pe = my_pe;
+ data->nperpe = nperpe;
+ data->nrem = nrem;
+ data->local_N = local_N;
+
+ /*-------------------------
+ Forward integration phase
+ -------------------------*/
+
+ /* Set relative and absolute tolerances for forward phase */
+ reltol = ZERO;
+ abstol = ATOL;
+
+ /* Allocate and initialize forward variables */
+ u = N_VNew_Parallel(comm, local_N, NEQ);
+ if (check_flag((void *)u, "N_VNew_Parallel", 0, my_pe)) MPI_Abort(comm, 1);
+ SetIC(u, dx, local_N, my_base);
+
+ /* Allocate CVODES memory for forward integration */
+ cvode_mem = CVodeCreate(CV_ADAMS, CV_FUNCTIONAL);
+ if (check_flag((void *)cvode_mem, "CVodeCreate", 0, my_pe)) MPI_Abort(comm, 1);
+
+ flag = CVodeSetUserData(cvode_mem, data);
+ if (check_flag(&flag, "CVodeSetUserData", 1, my_pe)) MPI_Abort(comm, 1);
+
+ flag = CVodeInit(cvode_mem, f, T0, u);
+ if (check_flag(&flag, "CVodeInit", 1, my_pe)) MPI_Abort(comm, 1);
+
+ flag = CVodeSStolerances(cvode_mem, reltol, abstol);
+ if (check_flag(&flag, "CVodeSStolerances", 1, my_pe)) MPI_Abort(comm, 1);
+
+ /* Allocate combined forward/backward memory */
+ flag = CVodeAdjInit(cvode_mem, STEPS, CV_HERMITE);
+ if (check_flag(&flag, "CVadjInit", 1, my_pe)) MPI_Abort(comm, 1);
+
+ /* Integrate to TOUT and collect check point information */
+ flag = CVodeF(cvode_mem, TOUT, u, &t, CV_NORMAL, &ncheck);
+ if (check_flag(&flag, "CVodeF", 1, my_pe)) MPI_Abort(comm, 1);
+
+ /*---------------------------
+ Compute and value of g(t_f)
+ ---------------------------*/
+ g_val = Compute_g(u, data);
+
+ /*--------------------------
+ Backward integration phase
+ --------------------------*/
+
+ if (my_pe == npes) {
+
+ /* Activate last process for integration of the quadrature equations */
+ local_N = NP;
+
+ } else {
+
+ /* Allocate work space */
+ data->z1 = (realtype *)malloc(local_N*sizeof(realtype));
+ if (check_flag((void *)data->z1, "malloc", 2, my_pe)) MPI_Abort(comm, 1);
+ data->z2 = (realtype *)malloc(local_N*sizeof(realtype));
+ if (check_flag((void *)data->z2, "malloc", 2, my_pe)) MPI_Abort(comm, 1);
+
+ }
+
+ /* Allocate and initialize backward variables */
+ uB = N_VNew_Parallel(comm, local_N, NEQ+NP);
+ if (check_flag((void *)uB, "N_VNew_Parallel", 0, my_pe)) MPI_Abort(comm, 1);
+ SetICback(uB, my_base);
+
+ /* Allocate CVODES memory for the backward integration */
+ flag = CVodeCreateB(cvode_mem, CV_ADAMS, CV_FUNCTIONAL, &indexB);
+ if (check_flag(&flag, "CVodeCreateB", 1, my_pe)) MPI_Abort(comm, 1);
+ flag = CVodeSetUserDataB(cvode_mem, indexB, data);
+ if (check_flag(&flag, "CVodeSetUserDataB", 1, my_pe)) MPI_Abort(comm, 1);
+ flag = CVodeInitB(cvode_mem, indexB, fB, TOUT, uB);
+ if (check_flag(&flag, "CVodeInitB", 1, my_pe)) MPI_Abort(comm, 1);
+ flag = CVodeSStolerancesB(cvode_mem, indexB, reltol, abstol);
+ if (check_flag(&flag, "CVodeSStolerancesB", 1, my_pe)) MPI_Abort(comm, 1);
+
+ /* Integrate to T0 */
+ flag = CVodeB(cvode_mem, T0, CV_NORMAL);
+ if (check_flag(&flag, "CVodeB", 1, my_pe)) MPI_Abort(comm, 1);
+
+ flag = CVodeGetB(cvode_mem, indexB, &t, uB);
+ if (check_flag(&flag, "CVodeGetB", 1, my_pe)) MPI_Abort(comm, 1);
+
+ /* Print results (adjoint states and quadrature variables) */
+ PrintOutput(g_val, uB, data);
+
+
+ /* Free memory */
+ N_VDestroy_Parallel(u);
+ N_VDestroy_Parallel(uB);
+ CVodeFree(&cvode_mem);
+
+ if (my_pe != npes) {
+ free(data->z1);
+ free(data->z2);
+ }
+ free(data);
+
+ MPI_Finalize();
+
+ return(0);
+}
+
+/*
+ *--------------------------------------------------------------------
+ * FUNCTIONS CALLED BY CVODES
+ *--------------------------------------------------------------------
+ */
+
+/*
+ * f routine. Compute f(t,u) for forward phase.
+ */
+
+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;
+ int npes, my_pe, my_pe_m1, my_pe_p1, last_pe, my_last;
+ UserData data;
+ MPI_Status status;
+ MPI_Comm comm;
+
+ /* Extract MPI info. from data */
+ data = (UserData) user_data;
+ comm = data->comm;
+ npes = data->npes;
+ my_pe = data->my_pe;
+
+ /* If this process is inactive, return now */
+ if (my_pe == npes) return(0);
+
+ /* Extract problem constants from data */
+ hordc = data->hdcoef;
+ horac = data->hacoef;
+
+ /* Find related processes */
+ my_pe_m1 = my_pe - 1;
+ my_pe_p1 = my_pe + 1;
+ last_pe = npes - 1;
+
+ /* Obtain local arrays */
+ udata = NV_DATA_P(u);
+ dudata = NV_DATA_P(udot);
+ my_length = NV_LOCLENGTH_P(u);
+ my_last = my_length - 1;
+
+ /* Pass needed data to processes before and after current process. */
+ if (my_pe != 0)
+ MPI_Send(&udata[0], 1, PVEC_REAL_MPI_TYPE, my_pe_m1, 0, comm);
+ if (my_pe != last_pe)
+ MPI_Send(&udata[my_length-1], 1, PVEC_REAL_MPI_TYPE, my_pe_p1, 0, comm);
+
+ /* Receive needed data from processes before and after current process. */
+ if (my_pe != 0)
+ MPI_Recv(&uLeft, 1, PVEC_REAL_MPI_TYPE, my_pe_m1, 0, comm, &status);
+ else uLeft = ZERO;
+ if (my_pe != last_pe)
+ MPI_Recv(&uRight, 1, PVEC_REAL_MPI_TYPE, my_pe_p1, 0, comm,
+ &status);
+ else uRight = ZERO;
+
+ /* Loop over all grid points in current process. */
+ for (i=0; i<my_length; i++) {
+
+ /* Extract u at x_i and two neighboring points */
+ ui = udata[i];
+ ult = (i==0) ? uLeft: udata[i-1];
+ urt = (i==my_length-1) ? uRight : udata[i+1];
+
+ /* Set diffusion and advection terms and load into udot */
+ hdiff = hordc*(ult - TWO*ui + urt);
+ hadv = horac*(urt - ult);
+ dudata[i] = hdiff + hadv;
+ }
+
+ return(0);
+}
+
+/*
+ * fB routine. Compute right hand side of backward problem
+ */
+
+static int fB(realtype t, N_Vector u,
+ N_Vector uB, N_Vector uBdot, void *user_dataB)
+{
+ realtype *uBdata, *duBdata, *udata;
+ realtype uBLeft, uBRight, uBi, uBlt, uBrt;
+ realtype uLeft, uRight, ui, ult, urt;
+ realtype dx, hordc, horac, hdiff, hadv;
+ realtype *z1, *z2, intgr1, intgr2;
+ long int 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];
+ MPI_Status status;
+ MPI_Comm comm;
+
+ /* Extract MPI info. from data */
+ data = (UserData) user_dataB;
+ comm = data->comm;
+ npes = data->npes;
+ my_pe = data->my_pe;
+
+ if (my_pe == npes) { /* This process performs the quadratures */
+
+ /* Obtain local arrays */
+ duBdata = NV_DATA_P(uBdot);
+ my_length = NV_LOCLENGTH_P(uB);
+
+ /* Loop over all other processes and load right hand side of quadrature eqs. */
+ duBdata[0] = ZERO;
+ duBdata[1] = ZERO;
+ for (i=0; i<npes; i++) {
+ MPI_Recv(&intgr1, 1, PVEC_REAL_MPI_TYPE, i, 0, comm, &status);
+ duBdata[0] += intgr1;
+ MPI_Recv(&intgr2, 1, PVEC_REAL_MPI_TYPE, i, 0, comm, &status);
+ duBdata[1] += intgr2;
+ }
+
+ } else { /* This process integrates part of the PDE */
+
+ /* Extract problem constants and work arrays from data */
+ dx = data->dx;
+ hordc = data->hdcoef;
+ horac = data->hacoef;
+ z1 = data->z1;
+ z2 = data->z2;
+
+ /* Obtain local arrays */
+ uBdata = NV_DATA_P(uB);
+ duBdata = NV_DATA_P(uBdot);
+ udata = NV_DATA_P(u);
+ my_length = NV_LOCLENGTH_P(uB);
+
+ /* Compute related parameters. */
+ my_pe_m1 = my_pe - 1;
+ my_pe_p1 = my_pe + 1;
+ last_pe = npes - 1;
+ my_last = my_length - 1;
+
+ /* Pass needed data to processes before and after current process. */
+ if (my_pe != 0) {
+ data_out[0] = udata[0];
+ data_out[1] = uBdata[0];
+
+ MPI_Send(data_out, 2, PVEC_REAL_MPI_TYPE, my_pe_m1, 0, comm);
+ }
+ if (my_pe != last_pe) {
+ data_out[0] = udata[my_length-1];
+ data_out[1] = uBdata[my_length-1];
+
+ MPI_Send(data_out, 2, PVEC_REAL_MPI_TYPE, my_pe_p1, 0, comm);
+ }
+
+ /* Receive needed data from processes before and after current process. */
+ if (my_pe != 0) {
+ MPI_Recv(data_in, 2, PVEC_REAL_MPI_TYPE, my_pe_m1, 0, comm, &status);
+
+ uLeft = data_in[0];
+ uBLeft = data_in[1];
+ } else {
+ uLeft = ZERO;
+ uBLeft = ZERO;
+ }
+ if (my_pe != last_pe) {
+ MPI_Recv(data_in, 2, PVEC_REAL_MPI_TYPE, my_pe_p1, 0, comm, &status);
+
+ uRight = data_in[0];
+ uBRight = data_in[1];
+ } else {
+ uRight = ZERO;
+ uBRight = ZERO;
+ }
+
+ /* Loop over all grid points in current process. */
+ for (i=0; i<my_length; i++) {
+
+ /* Extract uB at x_i and two neighboring points */
+ uBi = uBdata[i];
+ uBlt = (i==0) ? uBLeft: uBdata[i-1];
+ uBrt = (i==my_length-1) ? uBRight : uBdata[i+1];
+
+ /* Set diffusion and advection terms and load into udot */
+ hdiff = hordc*(uBlt - TWO*uBi + uBrt);
+ hadv = horac*(uBrt - uBlt);
+ duBdata[i] = - hdiff + hadv;
+
+ /* Extract u at x_i and two neighboring points */
+ ui = udata[i];
+ ult = (i==0) ? uLeft: udata[i-1];
+ urt = (i==my_length-1) ? uRight : udata[i+1];
+
+ /* Load integrands of the two space integrals */
+ z1[i] = uBdata[i]*(ult - TWO*ui + urt)/(dx*dx);
+ z2[i] = uBdata[i]*(urt - ult)/(TWO*dx);
+ }
+
+ /* Compute local integrals */
+ intgr1 = Xintgr(z1, my_length, dx);
+ intgr2 = Xintgr(z2, my_length, dx);
+
+ /* Send local integrals to 'quadrature' process */
+ MPI_Send(&intgr1, 1, PVEC_REAL_MPI_TYPE, npes, 0, comm);
+ MPI_Send(&intgr2, 1, PVEC_REAL_MPI_TYPE, npes, 0, comm);
+
+ }
+
+
+ return(0);
+}
+
+/*
+ *--------------------------------------------------------------------
+ * PRIVATE FUNCTIONS
+ *--------------------------------------------------------------------
+ */
+
+/*
+ * Set initial conditions in u vector
+ */
+
+static void SetIC(N_Vector u, realtype dx, long int my_length, long int my_base)
+{
+ int i;
+ long int iglobal;
+ realtype x;
+ realtype *udata;
+
+ /* Set pointer to data array and get local length of u */
+ udata = NV_DATA_P(u);
+ my_length = NV_LOCLENGTH_P(u);
+
+ /* Load initial profile into u vector */
+ for (i=1; i<=my_length; i++) {
+ iglobal = my_base + i;
+ x = iglobal*dx;
+ udata[i-1] = x*(XMAX - x)*EXP(TWO*x);
+ }
+}
+
+/*
+ * Set final conditions in uB vector
+ */
+
+static void SetICback(N_Vector uB, long int my_base)
+{
+ int i;
+ realtype *uBdata;
+ long int my_length;
+
+ /* Set pointer to data array and get local length of uB */
+ uBdata = NV_DATA_P(uB);
+ my_length = NV_LOCLENGTH_P(uB);
+
+ /* Set adjoint states to 1.0 and quadrature variables to 0.0 */
+ if (my_base == -1) for (i=0; i<my_length; i++) uBdata[i] = ZERO;
+ else for (i=0; i<my_length; i++) uBdata[i] = ONE;
+}
+
+/*
+ * Compute local value of the space integral int_x z(x) dx
+ */
+
+static realtype Xintgr(realtype *z, long int l, realtype dx)
+{
+ realtype my_intgr;
+ long int i;
+
+ my_intgr = RCONST(0.5)*(z[0] + z[l-1]);
+ for (i = 1; i < l-1; i++)
+ my_intgr += z[i];
+ my_intgr *= dx;
+
+ return(my_intgr);
+}
+
+/*
+ * Compute value of g(u)
+ */
+
+static realtype Compute_g(N_Vector u, UserData data)
+{
+ realtype intgr, my_intgr, dx, *udata;
+ long int my_length;
+ int npes, my_pe, i;
+ MPI_Status status;
+ MPI_Comm comm;
+
+ /* Extract MPI info. from data */
+ comm = data->comm;
+ npes = data->npes;
+ my_pe = data->my_pe;
+
+ dx = data->dx;
+
+ if (my_pe == npes) { /* Loop over all other processes and sum */
+ intgr = ZERO;
+ for (i=0; i<npes; i++) {
+ MPI_Recv(&my_intgr, 1, PVEC_REAL_MPI_TYPE, i, 0, comm, &status);
+ intgr += my_intgr;
+ }
+ return(intgr);
+ } else { /* Compute local portion of the integral */
+ udata = NV_DATA_P(u);
+ my_length = NV_LOCLENGTH_P(u);
+ my_intgr = Xintgr(udata, my_length, dx);
+ MPI_Send(&my_intgr, 1, PVEC_REAL_MPI_TYPE, npes, 0, comm);
+ return(my_intgr);
+ }
+}
+
+/*
+ * Print output after backward integration
+ */
+
+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;
+ realtype *uBdata;
+ realtype *mu;
+
+ comm = data->comm;
+ npes = data->npes;
+ my_pe = data->my_pe;
+ local_N = data->local_N;
+ nperpe = data->nperpe;
+ nrem = data->nrem;
+
+ uBdata = NV_DATA_P(uB);
+
+ if (my_pe == npes) {
+
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("\ng(tf) = %8Le\n\n", g_val);
+ printf("dgdp(tf)\n [ 1]: %8Le\n [ 2]: %8Le\n\n", -uBdata[0], -uBdata[1]);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("\ng(tf) = %8le\n\n", g_val);
+ printf("dgdp(tf)\n [ 1]: %8le\n [ 2]: %8le\n\n", -uBdata[0], -uBdata[1]);
+#else
+ printf("\ng(tf) = %8e\n\n", g_val);
+ printf("dgdp(tf)\n [ 1]: %8e\n [ 2]: %8e\n\n", -uBdata[0], -uBdata[1]);
+#endif
+
+ mu = (realtype *)malloc(NEQ*sizeof(realtype));
+ if (check_flag((void *)mu, "malloc", 2, my_pe)) MPI_Abort(comm, 1);
+
+ indx = 0;
+ for ( i = 0; i < npes; i++) {
+ Ni = ( i < nrem ) ? nperpe+1 : nperpe;
+ MPI_Recv(&mu[indx], Ni, PVEC_REAL_MPI_TYPE, i, 0, comm, &status);
+ indx += Ni;
+ }
+
+ printf("mu(t0)\n");
+
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ for (i=0; i<NEQ; i++)
+ printf(" [%2ld]: %8Le\n", i+1, mu[i]);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ for (i=0; i<NEQ; i++)
+ printf(" [%2ld]: %8le\n", i+1, mu[i]);
+#else
+ for (i=0; i<NEQ; i++)
+ printf(" [%2ld]: %8e\n", i+1, mu[i]);
+#endif
+
+ free(mu);
+
+ } else {
+
+ MPI_Send(uBdata, local_N, PVEC_REAL_MPI_TYPE, npes, 0, comm);
+
+ }
+
+}
+
+/*
+ * 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, char *funcname, int opt, int id)
+{
+ int *errflag;
+
+ /* Check if SUNDIALS function returned NULL pointer - no memory allocated */
+ if (opt == 0 && flagvalue == NULL) {
+ fprintf(stderr, "\nSUNDIALS_ERROR(%d): %s() failed - returned NULL pointer\n\n",
+ id, funcname);
+ return(1); }
+
+ /* Check if flag < 0 */
+ else if (opt == 1) {
+ errflag = (int *) flagvalue;
+ if (*errflag < 0) {
+ fprintf(stderr, "\nSUNDIALS_ERROR(%d): %s() failed with flag = %d\n\n",
+ id, funcname, *errflag);
+ return(1); }}
+
+ /* Check if function returned NULL pointer - no memory allocated */
+ else if (opt == 2 && flagvalue == NULL) {
+ fprintf(stderr, "\nMEMORY_ERROR(%d): %s() failed - returned NULL pointer\n\n",
+ id, funcname);
+ return(1); }
+
+ return(0);
+}
diff --git a/examples/cvodes/parallel/cvsAdvDiff_ASAp_non_p.out b/examples/cvodes/parallel/cvsAdvDiff_ASAp_non_p.out
new file mode 100644
index 0000000..63bdf03
--- /dev/null
+++ b/examples/cvodes/parallel/cvsAdvDiff_ASAp_non_p.out
@@ -0,0 +1,27 @@
+g(tf) = 2.446335e-02
+
+dgdp(tf)
+ [ 1]: -1.502544e-01
+ [ 2]: -1.098456e-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
diff --git a/examples/cvodes/parallel/cvsAdvDiff_FSA_non_p.c b/examples/cvodes/parallel/cvsAdvDiff_FSA_non_p.c
new file mode 100644
index 0000000..1591740
--- /dev/null
+++ b/examples/cvodes/parallel/cvsAdvDiff_FSA_non_p.c
@@ -0,0 +1,612 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.1 $
+ * $Date: 2007/10/25 20:03:30 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh, George D. Byrne,
+ * and Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Example problem:
+ *
+ * The following is a simple example problem, with the program for
+ * its solution by CVODES. The problem is the semi-discrete form of
+ * the advection-diffusion equation in 1-D:
+ * du/dt = q1 * d^2 u / dx^2 + q2 * du/dx
+ * on the interval 0 <= x <= 2, and the time interval 0 <= t <= 5.
+ * Homogeneous Dirichlet boundary conditions are posed, and the
+ * initial condition is:
+ * u(x,y,t=0) = x(2-x)exp(2x).
+ * 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 option for nonstiff
+ * systems: ADAMS method and functional iteration.
+ * It uses scalar relative and absolute tolerances.
+ * Output is printed at t = .5, 1.0, ..., 5.
+ * Run statistics (optional outputs) are printed at the end.
+ *
+ * Optionally, CVODES can compute sensitivities with respect to the
+ * problem parameters q1 and q2.
+ * 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 FULL or PARTIAL,
+ * respectively).
+ *
+ * Execution:
+ *
+ * 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 parallel
+ * application.
+ * If no sensitivities are desired:
+ * % mpirun -np N cvsAdvDiff_FSA_non_p -nosensi
+ * If sensitivities are to be computed:
+ * % mpirun -np N cvsAdvDiff_FSA_non_p -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 <math.h>
+#include <string.h>
+
+#include <cvodes/cvodes.h>
+#include <nvector/nvector_parallel.h>
+#include <sundials/sundials_types.h>
+#include <sundials/sundials_math.h>
+
+#include <mpi.h>
+
+/* Problem Constants */
+#define XMAX RCONST(2.0) /* domain boundary */
+#define MX 10 /* mesh dimension */
+#define NEQ MX /* number of equations */
+#define ATOL RCONST(1.e-5) /* scalar absolute tolerance */
+#define T0 RCONST(0.0) /* initial time */
+#define T1 RCONST(0.5) /* first output time */
+#define DTOUT RCONST(0.5) /* output time increment */
+#define NOUT 10 /* number of output times */
+
+#define NP 2
+#define NS 2
+
+#define ZERO RCONST(0.0)
+
+/* Type : UserData
+ contains problem parameters, grid constants, work array. */
+
+typedef struct {
+ realtype *p;
+ realtype dx;
+ int npes, my_pe;
+ MPI_Comm comm;
+ realtype z[100];
+} *UserData;
+
+
+/* Prototypes of user-supplied functins */
+
+static int f(realtype t, N_Vector u, N_Vector udot, void *user_data);
+
+/* Prototypes of private functions */
+
+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 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);
+static int check_flag(void *flagvalue, char *funcname, int opt, int id);
+
+/*
+ *--------------------------------------------------------------------
+ * MAIN PROGRAM
+ *--------------------------------------------------------------------
+ */
+
+int main(int argc, char *argv[])
+{
+ realtype dx, reltol, abstol, t, tout;
+ N_Vector u;
+ UserData data;
+ void *cvode_mem;
+ int iout, flag, my_pe, npes;
+ long int local_N, nperpe, nrem, my_base;
+
+ realtype *pbar;
+ int is, *plist;
+ N_Vector *uS;
+ booleantype sensi, err_con;
+ int sensi_meth;
+
+ MPI_Comm comm;
+
+ u = NULL;
+ data = NULL;
+ cvode_mem = NULL;
+ pbar = NULL;
+ plist = NULL;
+ uS = NULL;
+
+ /* Get processor number, total number of pe's, and my_pe. */
+ MPI_Init(&argc, &argv);
+ comm = MPI_COMM_WORLD;
+ MPI_Comm_size(comm, &npes);
+ MPI_Comm_rank(comm, &my_pe);
+
+ /* Process arguments */
+ ProcessArgs(argc, argv, my_pe, &sensi, &sensi_meth, &err_con);
+
+ /* Set local vector length. */
+ nperpe = NEQ/npes;
+ nrem = NEQ - npes*nperpe;
+ local_N = (my_pe < nrem) ? nperpe+1 : nperpe;
+ my_base = (my_pe < nrem) ? my_pe*local_N : my_pe*nperpe + nrem;
+
+ /* USER DATA STRUCTURE */
+ data = (UserData) malloc(sizeof *data); /* Allocate data memory */
+ data->p = NULL;
+ if(check_flag((void *)data, "malloc", 2, my_pe)) MPI_Abort(comm, 1);
+ data->comm = comm;
+ data->npes = npes;
+ data->my_pe = my_pe;
+ data->p = (realtype *) malloc(NP * sizeof(realtype));
+ if(check_flag((void *)data->p, "malloc", 2, my_pe)) MPI_Abort(comm, 1);
+ dx = data->dx = XMAX/((realtype)(MX+1));
+ data->p[0] = RCONST(1.0);
+ data->p[1] = RCONST(0.5);
+
+ /* INITIAL STATES */
+ u = N_VNew_Parallel(comm, local_N, NEQ); /* Allocate u vector */
+ if(check_flag((void *)u, "N_VNew_Parallel", 0, my_pe)) MPI_Abort(comm, 1);
+ SetIC(u, dx, local_N, my_base); /* Initialize u vector */
+
+ /* TOLERANCES */
+ reltol = ZERO; /* Set the tolerances */
+ abstol = ATOL;
+
+ /* CVODE_CREATE & CVODE_MALLOC */
+ cvode_mem = CVodeCreate(CV_ADAMS, CV_FUNCTIONAL);
+ if(check_flag((void *)cvode_mem, "CVodeCreate", 0, my_pe)) MPI_Abort(comm, 1);
+
+ flag = CVodeSetUserData(cvode_mem, data);
+ if(check_flag(&flag, "CVodeSetUserData", 1, my_pe)) MPI_Abort(comm, 1);
+
+ flag = CVodeInit(cvode_mem, f, T0, u);
+ if(check_flag(&flag, "CVodeInit", 1, my_pe)) MPI_Abort(comm, 1);
+ flag = CVodeSStolerances(cvode_mem, reltol, abstol);
+ if(check_flag(&flag, "CVodeSStolerances", 1, my_pe)) MPI_Abort(comm, 1);
+
+
+ if (my_pe == 0) {
+ printf("\n1-D advection-diffusion equation, mesh size =%3d \n", MX);
+ printf("\nNumber of PEs = %3d \n",npes);
+ }
+
+ if(sensi) {
+
+ plist = (int *) malloc(NS * sizeof(int));
+ if(check_flag((void *)plist, "malloc", 2, my_pe)) MPI_Abort(comm, 1);
+ for(is=0; is<NS; is++)
+ plist[is] = is; /* sensitivity w.r.t. i-th parameter */
+
+ pbar = (realtype *) malloc(NS * sizeof(realtype));
+ if(check_flag((void *)pbar, "malloc", 2, my_pe)) MPI_Abort(comm, 1);
+ for(is=0; is<NS; is++) pbar[is] = data->p[plist[is]];
+
+ uS = N_VCloneVectorArray_Parallel(NS, u);
+ if(check_flag((void *)uS, "N_VCloneVectorArray_Parallel", 0, my_pe))
+ MPI_Abort(comm, 1);
+ for(is=0;is<NS;is++)
+ N_VConst(ZERO,uS[is]);
+
+ flag = CVodeSensInit1(cvode_mem, NS, sensi_meth, NULL, uS);
+ if(check_flag(&flag, "CVodeSensInit1", 1, my_pe)) MPI_Abort(comm, 1);
+
+ flag = CVodeSensEEtolerances(cvode_mem);
+ if(check_flag(&flag, "CVodeSensEEtolerances", 1, my_pe)) MPI_Abort(comm, 1);
+
+ flag = CVodeSetSensErrCon(cvode_mem, err_con);
+ if(check_flag(&flag, "CVodeSetSensErrCon", 1, my_pe)) MPI_Abort(comm, 1);
+
+ flag = CVodeSetSensDQMethod(cvode_mem, CV_CENTERED, ZERO);
+ if(check_flag(&flag, "CVodeSetSensDQMethod", 1, my_pe)) MPI_Abort(comm, 1);
+
+ flag = CVodeSetSensParams(cvode_mem, data->p, pbar, plist);
+ if(check_flag(&flag, "CVodeSetSensParams", 1, my_pe)) MPI_Abort(comm, 1);
+
+ if(my_pe == 0) {
+ printf("Sensitivity: YES ");
+ if(sensi_meth == CV_SIMULTANEOUS)
+ printf("( SIMULTANEOUS +");
+ else
+ if(sensi_meth == CV_STAGGERED) printf("( STAGGERED +");
+ else printf("( STAGGERED1 +");
+ if(err_con) printf(" FULL ERROR CONTROL )");
+ else printf(" PARTIAL ERROR CONTROL )");
+ }
+
+ } else {
+
+ if(my_pe == 0) printf("Sensitivity: NO ");
+
+ }
+
+ /* In loop over output points, call CVode, print results, test for error */
+
+ if(my_pe == 0) {
+ printf("\n\n");
+ printf("============================================================\n");
+ printf(" T Q H NST Max norm \n");
+ printf("============================================================\n");
+ }
+
+ 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, my_pe)) break;
+ PrintOutput(cvode_mem, my_pe, t, u);
+ if (sensi) {
+ flag = CVodeGetSens(cvode_mem, &t, uS);
+ if(check_flag(&flag, "CVodeGetSens", 1, my_pe)) break;
+ PrintOutputS(my_pe, uS);
+ }
+ if (my_pe == 0)
+ printf("------------------------------------------------------------\n");
+
+ }
+
+ /* Print final statistics */
+ if (my_pe == 0)
+ PrintFinalStats(cvode_mem, sensi);
+
+ /* Free memory */
+ N_VDestroy(u); /* Free the u vector */
+ if (sensi)
+ N_VDestroyVectorArray(uS, NS); /* Free the uS vectors */
+ free(data->p); /* Free the p vector */
+ free(data); /* Free block of UserData */
+ CVodeFree(&cvode_mem); /* Free the CVODES problem memory */
+ free(pbar);
+ if(sensi) free(plist);
+
+ MPI_Finalize();
+
+ return(0);
+}
+
+/*
+ *--------------------------------------------------------------------
+ * FUNCTIONS CALLED BY CVODES
+ *--------------------------------------------------------------------
+ */
+
+/*
+ * f routine. Compute f(t,u).
+ */
+
+static int f(realtype t, N_Vector u, N_Vector udot, void *user_data)
+{
+ realtype ui, ult, urt, hordc, horac, hdiff, hadv;
+ realtype *udata, *dudata, *z;
+ realtype dx;
+ int i;
+ int npes, my_pe, my_length, my_pe_m1, my_pe_p1, last_pe, my_last;
+ UserData data;
+ MPI_Status status;
+ MPI_Comm comm;
+
+ udata = NV_DATA_P(u);
+ dudata = NV_DATA_P(udot);
+
+ /* Extract needed problem constants from data */
+ data = (UserData) user_data;
+ dx = data->dx;
+ hordc = data->p[0]/(dx*dx);
+ horac = data->p[1]/(RCONST(2.0)*dx);
+
+ /* Extract parameters for parallel computation. */
+ comm = data->comm;
+ npes = data->npes; /* Number of processes. */
+ my_pe = data->my_pe; /* Current process number. */
+ my_length = NV_LOCLENGTH_P(u); /* Number of local elements of u. */
+ z = data->z;
+
+ /* Compute related parameters. */
+ my_pe_m1 = my_pe - 1;
+ my_pe_p1 = my_pe + 1;
+ last_pe = npes - 1;
+ my_last = my_length - 1;
+
+ /* Store local segment of u in the working array z. */
+ for (i = 1; i <= my_length; i++)
+ z[i] = udata[i - 1];
+
+ /* Pass needed data to processes before and after current process. */
+ 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);
+
+ /* Receive needed data from processes before and after current process. */
+ if (my_pe != 0)
+ MPI_Recv(&z[0], 1, PVEC_REAL_MPI_TYPE, my_pe_m1, 0, comm, &status);
+ 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);
+ else z[my_length + 1] = ZERO;
+
+ /* Loop over all grid points in current process. */
+ for (i=1; i<=my_length; i++) {
+
+ /* Extract u at x_i and two neighboring points */
+ ui = z[i];
+ ult = z[i-1];
+ urt = z[i+1];
+
+ /* Set diffusion and advection terms and load into udot */
+ hdiff = hordc*(ult - RCONST(2.0)*ui + urt);
+ hadv = horac*(urt - ult);
+ dudata[i-1] = hdiff + hadv;
+ }
+
+ return(0);
+}
+
+/*
+ *--------------------------------------------------------------------
+ * PRIVATE FUNCTIONS
+ *--------------------------------------------------------------------
+ */
+
+/*
+ * Process and verify arguments to cvsfwdnonx_p.
+ */
+
+static void ProcessArgs(int argc, char *argv[], int my_pe,
+ booleantype *sensi, int *sensi_meth, booleantype *err_con)
+{
+ *sensi = FALSE;
+ *sensi_meth = -1;
+ *err_con = FALSE;
+
+ if (argc < 2) WrongArgs(my_pe, argv[0]);
+
+ if (strcmp(argv[1],"-nosensi") == 0)
+ *sensi = FALSE;
+ else if (strcmp(argv[1],"-sensi") == 0)
+ *sensi = TRUE;
+ else
+ WrongArgs(my_pe, argv[0]);
+
+ if (*sensi) {
+
+ if (argc != 4)
+ WrongArgs(my_pe, argv[0]);
+
+ if (strcmp(argv[2],"sim") == 0)
+ *sensi_meth = CV_SIMULTANEOUS;
+ else if (strcmp(argv[2],"stg") == 0)
+ *sensi_meth = CV_STAGGERED;
+ else if (strcmp(argv[2],"stg1") == 0)
+ *sensi_meth = CV_STAGGERED1;
+ else
+ WrongArgs(my_pe, argv[0]);
+
+ if (strcmp(argv[3],"t") == 0)
+ *err_con = TRUE;
+ else if (strcmp(argv[3],"f") == 0)
+ *err_con = FALSE;
+ else
+ WrongArgs(my_pe, argv[0]);
+ }
+
+}
+
+static void WrongArgs(int my_pe, char *name)
+{
+ if (my_pe == 0) {
+ printf("\nUsage: %s [-nosensi] [-sensi sensi_meth err_con]\n",name);
+ printf(" sensi_meth = sim, stg, or stg1\n");
+ printf(" err_con = t or f\n");
+ }
+ MPI_Finalize();
+ exit(0);
+}
+
+/*
+ * Set initial conditions in u vector
+ */
+
+static void SetIC(N_Vector u, realtype dx, long int my_length,
+ long int my_base)
+{
+ int i;
+ long int iglobal;
+ realtype x;
+ realtype *udata;
+
+ /* Set pointer to data array and get local length of u. */
+ udata = NV_DATA_P(u);
+ my_length = NV_LOCLENGTH_P(u);
+
+ /* Load initial profile into u vector */
+ for (i=1; i<=my_length; i++) {
+ iglobal = my_base + i;
+ x = iglobal*dx;
+ udata[i-1] = x*(XMAX - x)*EXP(2.0*x);
+ }
+}
+
+/*
+ * Print current t, step count, order, stepsize, and max norm of solution
+ */
+
+static void PrintOutput(void *cvode_mem, int my_pe, realtype t, N_Vector u)
+{
+ long int nst;
+ int qu, flag;
+ realtype hu, umax;
+
+ flag = CVodeGetNumSteps(cvode_mem, &nst);
+ check_flag(&flag, "CVodeGetNumSteps", 1, my_pe);
+ flag = CVodeGetLastOrder(cvode_mem, &qu);
+ check_flag(&flag, "CVodeGetLastOrder", 1, my_pe);
+ flag = CVodeGetLastStep(cvode_mem, &hu);
+ check_flag(&flag, "CVodeGetLastStep", 1, my_pe);
+
+ umax = N_VMaxNorm(u);
+
+ if (my_pe == 0) {
+
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("%8.3Le %2d %8.3Le %5ld\n", t,qu,hu,nst);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("%8.3le %2d %8.3le %5ld\n", t,qu,hu,nst);
+#else
+ printf("%8.3e %2d %8.3e %5ld\n", t,qu,hu,nst);
+#endif
+
+ printf(" Solution ");
+
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("%12.4Le \n", umax);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("%12.4le \n", umax);
+#else
+ printf("%12.4e \n", umax);
+#endif
+
+ }
+
+}
+
+/*
+ * Print max norm of sensitivities
+ */
+
+static void PrintOutputS(int my_pe, N_Vector *uS)
+{
+ realtype smax;
+
+ smax = N_VMaxNorm(uS[0]);
+ if (my_pe == 0) {
+ printf(" Sensitivity 1 ");
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("%12.4Le \n", smax);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("%12.4le \n", smax);
+#else
+ printf("%12.4e \n", smax);
+#endif
+ }
+
+ smax = N_VMaxNorm(uS[1]);
+ if (my_pe == 0) {
+ printf(" Sensitivity 2 ");
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("%12.4Le \n", smax);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("%12.4le \n", smax);
+#else
+ printf("%12.4e \n", smax);
+#endif
+ }
+
+}
+
+/*
+ * Print some final statistics located in the iopt array
+ */
+
+static void PrintFinalStats(void *cvode_mem, booleantype sensi)
+{
+ long int nst;
+ long int nfe, nsetups, nni, ncfn, netf;
+ long int nfSe, nfeS, nsetupsS, nniS, ncfnS, netfS;
+ int flag;
+
+ flag = CVodeGetNumSteps(cvode_mem, &nst);
+ check_flag(&flag, "CVodeGetNumSteps", 1, 0);
+ flag = CVodeGetNumRhsEvals(cvode_mem, &nfe);
+ check_flag(&flag, "CVodeGetNumRhsEvals", 1, 0);
+ flag = CVodeGetNumLinSolvSetups(cvode_mem, &nsetups);
+ check_flag(&flag, "CVodeGetNumLinSolvSetups", 1, 0);
+ flag = CVodeGetNumErrTestFails(cvode_mem, &netf);
+ check_flag(&flag, "CVodeGetNumErrTestFails", 1, 0);
+ flag = CVodeGetNumNonlinSolvIters(cvode_mem, &nni);
+ check_flag(&flag, "CVodeGetNumNonlinSolvIters", 1, 0);
+ flag = CVodeGetNumNonlinSolvConvFails(cvode_mem, &ncfn);
+ check_flag(&flag, "CVodeGetNumNonlinSolvConvFails", 1, 0);
+
+ if (sensi) {
+ flag = CVodeGetSensNumRhsEvals(cvode_mem, &nfSe);
+ check_flag(&flag, "CVodeGetSensNumRhsEvals", 1, 0);
+ flag = CVodeGetNumRhsEvalsSens(cvode_mem, &nfeS);
+ check_flag(&flag, "CVodeGetNumRhsEvalsSens", 1, 0);
+ flag = CVodeGetSensNumLinSolvSetups(cvode_mem, &nsetupsS);
+ check_flag(&flag, "CVodeGetSensNumLinSolvSetups", 1, 0);
+ flag = CVodeGetSensNumErrTestFails(cvode_mem, &netfS);
+ check_flag(&flag, "CVodeGetSensNumErrTestFails", 1, 0);
+ flag = CVodeGetSensNumNonlinSolvIters(cvode_mem, &nniS);
+ check_flag(&flag, "CVodeGetSensNumNonlinSolvIters", 1, 0);
+ flag = CVodeGetSensNumNonlinSolvConvFails(cvode_mem, &ncfnS);
+ check_flag(&flag, "CVodeGetSensNumNonlinSolvConvFails", 1, 0);
+ }
+
+ printf("\nFinal Statistics\n\n");
+ printf("nst = %5ld\n\n", nst);
+ printf("nfe = %5ld\n", nfe);
+ printf("netf = %5ld nsetups = %5ld\n", netf, nsetups);
+ printf("nni = %5ld ncfn = %5ld\n", nni, ncfn);
+
+ if(sensi) {
+ printf("\n");
+ printf("nfSe = %5ld nfeS = %5ld\n", nfSe, nfeS);
+ printf("netfs = %5ld nsetupsS = %5ld\n", netfS, nsetupsS);
+ printf("nniS = %5ld ncfnS = %5ld\n", nniS, ncfnS);
+ }
+
+}
+
+/*
+ * 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, char *funcname, int opt, int id)
+{
+ int *errflag;
+
+ /* Check if SUNDIALS function returned NULL pointer - no memory allocated */
+ if (opt == 0 && flagvalue == NULL) {
+ fprintf(stderr, "\nSUNDIALS_ERROR(%d): %s() failed - returned NULL pointer\n\n",
+ id, funcname);
+ return(1); }
+
+ /* Check if flag < 0 */
+ else if (opt == 1) {
+ errflag = (int *) flagvalue;
+ if (*errflag < 0) {
+ fprintf(stderr, "\nSUNDIALS_ERROR(%d): %s() failed with flag = %d\n\n",
+ id, funcname, *errflag);
+ return(1); }}
+
+ /* Check if function returned NULL pointer - no memory allocated */
+ else if (opt == 2 && flagvalue == NULL) {
+ fprintf(stderr, "\nMEMORY_ERROR(%d): %s() failed - returned NULL pointer\n\n",
+ id, funcname);
+ return(1); }
+
+ return(0);
+}
diff --git a/examples/cvodes/parallel/cvsAdvDiff_FSA_non_p.out b/examples/cvodes/parallel/cvsAdvDiff_FSA_non_p.out
new file mode 100644
index 0000000..38f7830
--- /dev/null
+++ b/examples/cvodes/parallel/cvsAdvDiff_FSA_non_p.out
@@ -0,0 +1,71 @@
+
+1-D advection-diffusion equation, mesh size = 10
+
+Number of PEs = 4
+Sensitivity: YES ( SIMULTANEOUS + FULL ERROR CONTROL )
+
+============================================================
+ T Q H NST Max norm
+============================================================
+5.000e-01 4 7.656e-03 115
+ Solution 3.0529e+00
+ Sensitivity 1 3.8668e+00
+ Sensitivity 2 6.2020e-01
+------------------------------------------------------------
+1.000e+00 4 9.504e-03 182
+ Solution 8.7533e-01
+ Sensitivity 1 2.1743e+00
+ Sensitivity 2 1.8909e-01
+------------------------------------------------------------
+1.500e+00 3 4.221e-03 290
+ Solution 2.4949e-01
+ Sensitivity 1 9.1826e-01
+ Sensitivity 2 7.3922e-02
+------------------------------------------------------------
+2.000e+00 2 8.301e-03 375
+ Solution 7.1098e-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
+ Sensitivity 2 1.0085e-02
+------------------------------------------------------------
+3.000e+00 2 7.134e-03 514
+ Solution 5.7728e-03
+ Sensitivity 1 4.1956e-02
+ Sensitivity 2 3.4555e-03
+------------------------------------------------------------
+3.500e+00 2 1.657e-02 586
+ Solution 1.6450e-03
+ Sensitivity 1 1.3921e-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.500e+00 1 5.326e-03 732
+ Solution 1.3417e-04
+ Sensitivity 1 1.4551e-03
+ Sensitivity 2 1.2585e-04
+------------------------------------------------------------
+5.000e+00 2 9.973e-03 814
+ Solution 3.8672e-05
+ Sensitivity 1 4.6549e-04
+ Sensitivity 2 4.0632e-05
+------------------------------------------------------------
+
+Final Statistics
+
+nst = 814
+
+nfe = 1462
+netf = 2 nsetups = 0
+nni = 1458 ncfn = 134
+
+nfSe = 2924 nfeS = 5848
+netfs = 0 nsetupsS = 0
+nniS = 0 ncfnS = 0
diff --git a/examples/cvodes/parallel/cvsAdvDiff_non_p.c b/examples/cvodes/parallel/cvsAdvDiff_non_p.c
new file mode 100644
index 0000000..12e8704
--- /dev/null
+++ b/examples/cvodes/parallel/cvsAdvDiff_non_p.c
@@ -0,0 +1,362 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.1 $
+ * $Date: 2007/10/25 20:03:30 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh, George Byrne,
+ * and Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Example problem:
+ *
+ * The following is a simple example problem, with the program for
+ * its solution by CVODES. The problem is the semi-discrete
+ * form of the advection-diffusion equation in 1-D:
+ * du/dt = d^2 u / dx^2 + .5 du/dx
+ * on the interval 0 <= x <= 2, and the time interval 0 <= t <= 5.
+ * Homogeneous Dirichlet boundary conditions are posed, and the
+ * initial condition is the following:
+ * u(x,t=0) = x(2-x)exp(2x) .
+ * 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 option for nonstiff
+ * systems: ADAMS method and functional iteration.
+ * It uses scalar relative and absolute tolerances.
+ * Output is printed at t = .5, 1.0, ..., 5.
+ * Run statistics (optional outputs) are printed at the end.
+ *
+ * This version uses MPI for user routines.
+ * Execute with Number of Processors = N, with 1 <= N <= MX.
+ * -----------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+
+#include <cvodes/cvodes.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 <mpi.h> /* MPI constants and types */
+
+/* Problem Constants */
+
+#define ZERO RCONST(0.0)
+
+#define XMAX RCONST(2.0) /* domain boundary */
+#define MX 10 /* mesh dimension */
+#define NEQ MX /* number of equations */
+#define ATOL RCONST(1.0e-5) /* scalar absolute tolerance */
+#define T0 ZERO /* initial time */
+#define T1 RCONST(0.5) /* first output time */
+#define DTOUT RCONST(0.5) /* output time increment */
+#define NOUT 10 /* number of output times */
+
+/* Type : UserData
+ contains grid constants, parallel machine parameters, work array. */
+
+typedef struct {
+ realtype dx, hdcoef, hacoef;
+ int npes, my_pe;
+ MPI_Comm comm;
+ realtype z[100];
+} *UserData;
+
+/* Private Helper Functions */
+
+static void SetIC(N_Vector u, realtype dx, long int my_length,
+ long int my_base);
+
+static void PrintIntro(int npes);
+
+static void PrintData(realtype t, realtype umax, long int nst);
+
+static void PrintFinalStats(void *cvode_mem);
+
+/* Functions Called by the Solver */
+
+static int f(realtype t, N_Vector u, N_Vector udot, void *user_data);
+
+/* Private function to check function return values */
+
+static int check_flag(void *flagvalue, char *funcname, int opt, int id);
+
+/***************************** Main Program ******************************/
+
+int main(int argc, char *argv[])
+{
+ realtype dx, reltol, abstol, t, tout, umax;
+ N_Vector u;
+ UserData data;
+ void *cvode_mem;
+ int iout, flag, my_pe, npes;
+ long int local_N, nperpe, nrem, my_base, nst;
+
+ MPI_Comm comm;
+
+ u = NULL;
+ data = NULL;
+ cvode_mem = NULL;
+
+ /* Get processor number, total number of pe's, and my_pe. */
+ MPI_Init(&argc, &argv);
+ comm = MPI_COMM_WORLD;
+ MPI_Comm_size(comm, &npes);
+ MPI_Comm_rank(comm, &my_pe);
+
+ /* Set local vector length. */
+ nperpe = NEQ/npes;
+ nrem = NEQ - npes*nperpe;
+ local_N = (my_pe < nrem) ? nperpe+1 : nperpe;
+ my_base = (my_pe < nrem) ? my_pe*local_N : my_pe*nperpe + nrem;
+
+ data = (UserData) malloc(sizeof *data); /* Allocate data memory */
+ if(check_flag((void *)data, "malloc", 2, my_pe)) MPI_Abort(comm, 1);
+
+ data->comm = comm;
+ data->npes = npes;
+ data->my_pe = my_pe;
+
+ u = N_VNew_Parallel(comm, local_N, NEQ); /* Allocate u vector */
+ if(check_flag((void *)u, "N_VNew", 0, my_pe)) MPI_Abort(comm, 1);
+
+ reltol = ZERO; /* Set the tolerances */
+ abstol = ATOL;
+
+ dx = data->dx = XMAX/((realtype)(MX+1)); /* Set grid coefficients in data */
+ data->hdcoef = RCONST(1.0)/(dx*dx);
+ data->hacoef = RCONST(0.5)/(RCONST(2.0)*dx);
+
+ SetIC(u, dx, local_N, my_base); /* Initialize u vector */
+
+ /* 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);
+
+ flag = CVodeSetUserData(cvode_mem, data);
+ if(check_flag(&flag, "CVodeSetUserData", 1, my_pe)) MPI_Abort(comm, 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
+ * the initial dependent variable vector u. */
+ flag = CVodeInit(cvode_mem, f, T0, u);
+ if(check_flag(&flag, "CVodeInit", 1, my_pe)) return(1);
+
+ /* Call CVodeSStolerances to specify the scalar relative tolerance
+ * and scalar absolute tolerances */
+ flag = CVodeSStolerances(cvode_mem, reltol, abstol);
+ if (check_flag(&flag, "CVodeSStolerances", 1, my_pe)) return(1);
+
+ if (my_pe == 0) PrintIntro(npes);
+
+ umax = N_VMaxNorm(u);
+
+ if (my_pe == 0) {
+ t = T0;
+ PrintData(t, umax, 0);
+ }
+
+ /* In loop over output points, call CVode, print results, test for error */
+
+ 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, my_pe)) break;
+ umax = N_VMaxNorm(u);
+ flag = CVodeGetNumSteps(cvode_mem, &nst);
+ check_flag(&flag, "CVodeGetNumSteps", 1, my_pe);
+ if (my_pe == 0) PrintData(t, umax, nst);
+ }
+
+ if (my_pe == 0)
+ PrintFinalStats(cvode_mem); /* Print some final statistics */
+
+ N_VDestroy_Parallel(u); /* Free the u vector */
+ CVodeFree(&cvode_mem); /* Free the integrator memory */
+ free(data); /* Free user data */
+
+ MPI_Finalize();
+
+ return(0);
+}
+
+/************************ Private Helper Functions ***********************/
+
+/* Set initial conditions in u vector */
+
+static void SetIC(N_Vector u, realtype dx, long int my_length,
+ long int my_base)
+{
+ int i;
+ long int iglobal;
+ realtype x;
+ realtype *udata;
+
+ /* Set pointer to data array and get local length of u. */
+ udata = NV_DATA_P(u);
+ my_length = NV_LOCLENGTH_P(u);
+
+ /* Load initial profile into u vector */
+ for (i=1; i<=my_length; i++) {
+ iglobal = my_base + i;
+ x = iglobal*dx;
+ udata[i-1] = x*(XMAX - x)*EXP(RCONST(2.0)*x);
+ }
+}
+
+/* Print problem introduction */
+
+static void PrintIntro(int npes)
+{
+ printf("\n 1-D advection-diffusion equation, mesh size =%3d \n", MX);
+ printf("\n Number of PEs = %3d \n\n", npes);
+
+ return;
+}
+
+/* Print data */
+
+static void PrintData(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);
+#else
+ printf("At t = %4.2f max.norm(u) =%14.6e nst =%4ld \n", t, umax, nst);
+#endif
+
+ return;
+}
+
+/* Print some final statistics located in the iopt array */
+
+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);
+ check_flag(&flag, "CVodeGetNumRhsEvals", 1, 0);
+ flag = CVodeGetNumErrTestFails(cvode_mem, &netf);
+ check_flag(&flag, "CVodeGetNumErrTestFails", 1, 0);
+ flag = CVodeGetNumNonlinSolvIters(cvode_mem, &nni);
+ check_flag(&flag, "CVodeGetNumNonlinSolvIters", 1, 0);
+ flag = CVodeGetNumNonlinSolvConvFails(cvode_mem, &ncfn);
+ check_flag(&flag, "CVodeGetNumNonlinSolvConvFails", 1, 0);
+
+ printf("\nFinal Statistics: \n\n");
+ printf("nst = %-6ld nfe = %-6ld ", nst, nfe);
+ printf("nni = %-6ld ncfn = %-6ld netf = %ld\n \n", nni, ncfn, netf);
+}
+
+/***************** Function Called by the Solver ***********************/
+
+/* f routine. Compute f(t,u). */
+
+static int f(realtype t, N_Vector u, N_Vector udot, void *user_data)
+{
+ realtype ui, ult, urt, hordc, horac, hdiff, hadv;
+ realtype *udata, *dudata, *z;
+ int i;
+ int npes, my_pe, my_length, my_pe_m1, my_pe_p1, last_pe, my_last;
+ UserData data;
+ MPI_Status status;
+ MPI_Comm comm;
+
+ udata = NV_DATA_P(u);
+ dudata = NV_DATA_P(udot);
+
+ /* Extract needed problem constants from data */
+ data = (UserData) user_data;
+ hordc = data->hdcoef;
+ horac = data->hacoef;
+
+ /* Extract parameters for parallel computation. */
+ comm = data->comm;
+ npes = data->npes; /* Number of processes. */
+ my_pe = data->my_pe; /* Current process number. */
+ my_length = NV_LOCLENGTH_P(u); /* Number of local elements of u. */
+ z = data->z;
+
+ /* Compute related parameters. */
+ my_pe_m1 = my_pe - 1;
+ my_pe_p1 = my_pe + 1;
+ last_pe = npes - 1;
+ my_last = my_length - 1;
+
+ /* Store local segment of u in the working array z. */
+ for (i = 1; i <= my_length; i++)
+ z[i] = udata[i - 1];
+
+ /* Pass needed data to processes before and after current process. */
+ 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);
+
+ /* Receive needed data from processes before and after current process. */
+ if (my_pe != 0)
+ MPI_Recv(&z[0], 1, PVEC_REAL_MPI_TYPE, my_pe_m1, 0, comm, &status);
+ 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);
+ else z[my_length + 1] = ZERO;
+
+ /* Loop over all grid points in current process. */
+ for (i=1; i<=my_length; i++) {
+
+ /* Extract u at x_i and two neighboring points */
+ ui = z[i];
+ ult = z[i-1];
+ urt = z[i+1];
+
+ /* Set diffusion and advection terms and load into udot */
+ hdiff = hordc*(ult - RCONST(2.0)*ui + urt);
+ hadv = horac*(urt - ult);
+ dudata[i-1] = hdiff + hadv;
+ }
+
+ 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, char *funcname, int opt, int id)
+{
+ int *errflag;
+
+ /* Check if SUNDIALS function returned NULL pointer - no memory allocated */
+ if (opt == 0 && flagvalue == NULL) {
+ fprintf(stderr, "\nSUNDIALS_ERROR(%d): %s() failed - returned NULL pointer\n\n",
+ id, funcname);
+ return(1); }
+
+ /* Check if flag < 0 */
+ else if (opt == 1) {
+ errflag = (int *) flagvalue;
+ if (*errflag < 0) {
+ fprintf(stderr, "\nSUNDIALS_ERROR(%d): %s() failed with flag = %d\n\n",
+ id, funcname, *errflag);
+ return(1); }}
+
+ /* Check if function returned NULL pointer - no memory allocated */
+ else if (opt == 2 && flagvalue == NULL) {
+ fprintf(stderr, "\nMEMORY_ERROR(%d): %s() failed - returned NULL pointer\n\n",
+ id, funcname);
+ return(1); }
+
+ return(0);
+}
diff --git a/examples/cvodes/parallel/cvsAdvDiff_non_p.out b/examples/cvodes/parallel/cvsAdvDiff_non_p.out
new file mode 100644
index 0000000..be50625
--- /dev/null
+++ b/examples/cvodes/parallel/cvsAdvDiff_non_p.out
@@ -0,0 +1,21 @@
+
+ 1-D advection-diffusion equation, mesh size = 10
+
+ Number of PEs = 4
+
+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
+
+Final Statistics:
+
+nst = 795 nfe = 1465 nni = 1461 ncfn = 146 netf = 5
+
diff --git a/examples/cvodes/parallel/cvsAtmDisp_ASAi_kry_bbd_p.c b/examples/cvodes/parallel/cvsAtmDisp_ASAi_kry_bbd_p.c
new file mode 100644
index 0000000..c19d02f
--- /dev/null
+++ b/examples/cvodes/parallel/cvsAtmDisp_ASAi_kry_bbd_p.c
@@ -0,0 +1,1196 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.3 $
+ * $Date: 2010/12/14 22:15:31 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Lukas Jager and Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Parallel Krylov adjoint sensitivity example problem.
+ * -----------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <limits.h>
+
+#include <cvodes/cvodes.h>
+#include <cvodes/cvodes_spgmr.h>
+#include <cvodes/cvodes_bbdpre.h>
+#include <nvector/nvector_parallel.h>
+#include <sundials/sundials_types.h>
+#include <sundials/sundials_math.h>
+
+#include <mpi.h>
+
+/*
+ *------------------------------------------------------------------
+ * Constants
+ *------------------------------------------------------------------
+ */
+
+#ifdef USE3D
+#define DIM 3
+#else
+#define DIM 2
+#endif
+
+/* Domain definition */
+
+#define XMIN RCONST(0.0)
+#define XMAX RCONST(20.0)
+#define MX 20 /* no. of divisions in x dir. */
+#define NPX 2 /* no. of procs. in x dir. */
+
+#define YMIN RCONST(0.0)
+#define YMAX RCONST(20.0)
+#define MY 40 /* no. of divisions in y dir. */
+#define NPY 2 /* no. of procs. in y dir. */
+
+#ifdef USE3D
+#define ZMIN RCONST(0.0)
+#define ZMAX RCONST(20.0)
+#define MZ 20 /* no. of divisions in z dir. */
+#define NPZ 1 /* no. of procs. in z dir. */
+#endif
+
+/* Parameters for source Gaussians */
+
+#define G1_AMPL RCONST(1.0)
+#define G1_SIGMA RCONST(1.7)
+#define G1_X RCONST(4.0)
+#define G1_Y RCONST(8.0)
+#ifdef USE3D
+#define G1_Z RCONST(8.0)
+#endif
+
+#define G2_AMPL RCONST(0.8)
+#define G2_SIGMA RCONST(3.0)
+#define G2_X RCONST(16.0)
+#define G2_Y RCONST(12.0)
+#ifdef USE3D
+#define G2_Z RCONST(12.0)
+#endif
+
+#define G_MIN RCONST(1.0e-5)
+
+/* Diffusion coeff., max. velocity, domain width in y dir. */
+
+#define DIFF_COEF RCONST(1.0)
+#define V_MAX RCONST(1.0)
+#define L (YMAX-YMIN)/RCONST(2.0)
+#define V_COEFF V_MAX/L/L
+
+/* Initial and final times */
+
+#define ti RCONST(0.0)
+#define tf RCONST(10.0)
+
+/* Integration tolerances */
+
+#define RTOL RCONST(1.0e-8) /* states */
+#define ATOL RCONST(1.0e-6)
+
+#define RTOL_Q RCONST(1.0e-8) /* forward quadrature */
+#define ATOL_Q RCONST(1.0e-6)
+
+#define RTOL_B RCONST(1.0e-8) /* adjoint variables */
+#define ATOL_B RCONST(1.0e-6)
+
+#define RTOL_QB RCONST(1.0e-8) /* backward quadratures */
+#define ATOL_QB RCONST(1.0e-6)
+
+/* Steps between check points */
+
+#define STEPS 200
+
+#define ZERO RCONST(0.0)
+#define ONE RCONST(1.0)
+#define TWO RCONST(2.0)
+
+/*
+ *------------------------------------------------------------------
+ * Macros
+ *------------------------------------------------------------------
+ */
+
+#define FOR_DIM for(dim=0; dim<DIM; dim++)
+
+/* IJth: (i[0],i[1],i[2])-th vector component */
+/* IJth_ext: (i[0],i[1],i[2])-th vector component in the extended array */
+
+#ifdef USE3D
+#define IJth(y,i) ( y[(i[0])+(l_m[0]*((i[1])+(i[2])*l_m[1]))] )
+#define IJth_ext(y,i) ( y[(i[0]+1)+((l_m[0]+2)*((i[1]+1)+(i[2]+1)*(l_m[1]+2)))] )
+#else
+#define IJth(y,i) (y[i[0]+(i[1])*l_m[0]])
+#define IJth_ext(y,i) (y[ (i[0]+1) + (i[1]+1) * (l_m[0]+2)])
+#endif
+
+/*
+ *------------------------------------------------------------------
+ * Type definition: ProblemData
+ *------------------------------------------------------------------
+ */
+
+typedef struct {
+ /* Domain */
+ realtype xmin[DIM]; /* "left" boundaries */
+ realtype xmax[DIM]; /* "right" boundaries */
+ int m[DIM]; /* number of grid points */
+ realtype dx[DIM]; /* grid spacing */
+ realtype dOmega; /* differential volume */
+
+ /* Parallel stuff */
+ MPI_Comm comm; /* MPI communicator */
+ int myId; /* process id */
+ int npes; /* total number of processes */
+ int num_procs[DIM]; /* number of processes in each direction */
+ int nbr_left[DIM]; /* MPI ID of "left" neighbor */
+ int nbr_right[DIM]; /* MPI ID of "right" neighbor */
+ int m_start[DIM]; /* "left" index in the global domain */
+ int l_m[DIM]; /* number of local grid points */
+ realtype *y_ext; /* extended data array */
+ realtype *buf_send; /* Send buffer */
+ realtype *buf_recv; /* Receive buffer */
+ int buf_size; /* Buffer size */
+
+ /* Source */
+ N_Vector p; /* Source parameters */
+
+} *ProblemData;
+
+/*
+ *------------------------------------------------------------------
+ * Interface functions to CVODES
+ *------------------------------------------------------------------
+ */
+
+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,
+ N_Vector ydot, void *user_data);
+
+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,
+ N_Vector y, N_Vector yB, N_Vector yBdot,
+ void *user_dataB);
+
+static int fQB(realtype t, N_Vector y, N_Vector yB,
+ N_Vector qBdot, void *user_dataB);
+
+/*
+ *------------------------------------------------------------------
+ * Private functions
+ *------------------------------------------------------------------
+ */
+
+static void SetData(ProblemData d, MPI_Comm comm, int npes, int myId,
+ long int *neq, long int *l_neq);
+static void SetSource(ProblemData d);
+static void f_comm(long int 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);
+static void OutputGradient(int myId, N_Vector qB, ProblemData d);
+
+/*
+ *------------------------------------------------------------------
+ * Main program
+ *------------------------------------------------------------------
+ */
+
+int main(int argc, char *argv[])
+{
+ ProblemData d;
+
+ MPI_Comm comm;
+ int npes, npes_needed;
+ int myId;
+
+ long int neq, l_neq;
+
+ void *cvode_mem;
+ N_Vector y, q;
+ realtype abstol, reltol, abstolQ, reltolQ;
+ long int mudq, mldq, mukeep, mlkeep;
+
+ int indexB;
+ N_Vector yB, qB;
+ realtype abstolB, reltolB, abstolQB, reltolQB;
+ long int mudqB, mldqB, mukeepB, mlkeepB;
+
+ realtype tret, *qdata, G;
+
+ int ncheckpnt, flag;
+
+ booleantype output;
+
+ /* Initialize MPI and set Ids */
+ MPI_Init(&argc, &argv);
+ comm = MPI_COMM_WORLD;
+ MPI_Comm_rank(comm, &myId);
+
+ /* Check number of processes */
+ npes_needed = NPX * NPY;
+#ifdef USE3D
+ npes_needed *= NPZ;
+#endif
+ MPI_Comm_size(comm, &npes);
+ if (npes_needed != npes) {
+ if (myId == 0)
+ fprintf(stderr,"I need %d processes but I only got %d\n",
+ npes_needed, npes);
+ MPI_Abort(comm, EXIT_FAILURE);
+ }
+
+ /* Test if matlab output is requested */
+ if (argc > 1) output = TRUE;
+ else output = FALSE;
+
+ /* Allocate and set problem data structure */
+ d = (ProblemData) malloc(sizeof *d);
+ SetData(d, comm, npes, myId, &neq, &l_neq);
+
+ if (myId == 0) PrintHeader();
+
+ /*--------------------------
+ Forward integration phase
+ --------------------------*/
+
+ /* Allocate space for y and set it with the I.C. */
+ y = N_VNew_Parallel(comm, l_neq, neq);
+ N_VConst(ZERO, y);
+
+ /* Allocate and initialize qB (local contribution to cost) */
+ q = N_VNew_Parallel(comm, 1, npes);
+ N_VConst(ZERO, q);
+
+ /* Create CVODES object, attach user data, and allocate space */
+ cvode_mem = CVodeCreate(CV_BDF, CV_NEWTON);
+ flag = CVodeSetUserData(cvode_mem, d);
+ flag = CVodeInit(cvode_mem, f, ti, y);
+ abstol = ATOL;
+ reltol = RTOL;
+ flag = CVodeSStolerances(cvode_mem, reltol, abstol);
+
+ /* attach linear solver */
+ flag = CVSpgmr(cvode_mem, PREC_LEFT, 0);
+
+ /* Attach preconditioner and linear solver modules */
+ mudq = mldq = d->l_m[0]+1;
+ mukeep = mlkeep = 2;
+ flag = CVBBDPrecInit(cvode_mem, l_neq, mudq, mldq,
+ mukeep, mlkeep, ZERO,
+ f_local, NULL);
+
+ /* Initialize quadrature calculations */
+ abstolQ = ATOL_Q;
+ reltolQ = RTOL_Q;
+ flag = CVodeQuadInit(cvode_mem, fQ, q);
+ flag = CVodeQuadSStolerances(cvode_mem, reltolQ, abstolQ);
+ flag = CVodeSetQuadErrCon(cvode_mem, TRUE);
+
+ /* Allocate space for the adjoint calculation */
+ flag = CVodeAdjInit(cvode_mem, STEPS, CV_HERMITE);
+
+ /* Integrate forward in time while storing check points */
+ if (myId == 0) printf("Begin forward integration... ");
+ flag = CVodeF(cvode_mem, tf, y, &tret, CV_NORMAL, &ncheckpnt);
+ if (myId == 0) printf("done. ");
+
+ /* Extract quadratures */
+ flag = CVodeGetQuad(cvode_mem, &tret, q);
+ qdata = NV_DATA_P(q);
+ 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 = %le\n",G);
+#else
+ if (myId == 0) printf(" G = %e\n",G);
+#endif
+
+ /* Print statistics for forward run */
+ if (myId == 0) PrintFinalStats(cvode_mem);
+
+ /*--------------------------
+ Backward integration phase
+ --------------------------*/
+
+ /* Allocate and initialize yB */
+ yB = N_VNew_Parallel(comm, l_neq, neq);
+ N_VConst(ZERO, yB);
+
+ /* Allocate and initialize qB (gradient) */
+ qB = N_VNew_Parallel(comm, l_neq, neq);
+ N_VConst(ZERO, qB);
+
+ /* Create and allocate backward CVODE memory */
+ flag = CVodeCreateB(cvode_mem, CV_BDF, CV_NEWTON, &indexB);
+ flag = CVodeSetUserDataB(cvode_mem, indexB, d);
+ flag = CVodeInitB(cvode_mem, indexB, fB, tf, yB);
+ abstolB = ATOL_B;
+ reltolB = RTOL_B;
+ flag = CVodeSStolerancesB(cvode_mem, indexB, reltolB, abstolB);
+
+ /* Attach preconditioner and linear solver modules */
+ flag = CVSpgmrB(cvode_mem, indexB, PREC_LEFT, 0);
+ mudqB = mldqB = d->l_m[0]+1;
+ mukeepB = mlkeepB = 2;
+ flag = CVBBDPrecInitB(cvode_mem, indexB, l_neq, mudqB, mldqB,
+ mukeepB, mlkeepB, ZERO, fB_local, NULL);
+
+ /* Initialize quadrature calculations */
+ abstolQB = ATOL_QB;
+ reltolQB = RTOL_QB;
+ flag = CVodeQuadInitB(cvode_mem, indexB, fQB, qB);
+ flag = CVodeQuadSStolerancesB(cvode_mem, indexB, reltolQB, abstolQB);
+ flag = CVodeSetQuadErrConB(cvode_mem, indexB, TRUE);
+
+ /* Integrate backwards */
+ if (myId == 0) printf("Begin backward integration... ");
+ flag = CVodeB(cvode_mem, ti, CV_NORMAL);
+ if (myId == 0) printf("done.\n");
+
+ /* Extract solution */
+ flag = CVodeGetB(cvode_mem, indexB, &tret, yB);
+
+ /* Extract quadratures */
+ flag = CVodeGetQuadB(cvode_mem, indexB, &tret, qB);
+
+ /* Print statistics for backward run */
+ if (myId == 0) {
+ PrintFinalStats(CVodeGetAdjCVodeBmem(cvode_mem, indexB));
+ }
+
+ /* Process 0 collects the gradient components and prints them */
+ if (output) {
+ OutputGradient(myId, qB, d);
+ if (myId == 0) printf("Wrote matlab file 'grad.m'.\n");
+ }
+
+ /* Free memory */
+
+ N_VDestroy_Parallel(y);
+ N_VDestroy_Parallel(q);
+ N_VDestroy_Parallel(qB);
+ N_VDestroy_Parallel(yB);
+
+ CVodeFree(&cvode_mem);
+
+ MPI_Finalize();
+
+ return(0);
+}
+
+/*
+ *------------------------------------------------------------------
+ * SetData:
+ * Allocate space for the ProblemData structure.
+ * Set fields in the ProblemData structure.
+ * Return local and global problem dimensions.
+ *
+ * SetSource:
+ * Instantiates the source parameters for a combination of two
+ * Gaussian sources.
+ *------------------------------------------------------------------
+ */
+
+static void SetData(ProblemData d, MPI_Comm comm, int npes, int myId,
+ long int *neq, long int *l_neq)
+{
+ int n[DIM], nd[DIM];
+ int dim, size;
+
+ /* Set MPI communicator, id, and total number of processes */
+
+ d->comm = comm;
+ d->myId = myId;
+ d->npes = npes;
+
+ /* Set domain boundaries */
+
+ d->xmin[0] = XMIN;
+ d->xmax[0] = XMAX;
+ d->m[0] = MX;
+
+ d->xmin[1] = YMIN;
+ d->xmax[1] = YMAX;
+ d->m[1] = MY;
+
+#ifdef USE3D
+ d->xmin[2] = ZMIN;
+ d->xmax[2] = ZMAX;
+ d->m[2] = MZ;
+#endif
+
+ /* Calculate grid spacing and differential volume */
+
+ d->dOmega = ONE;
+ FOR_DIM {
+ d->dx[dim] = (d->xmax[dim] - d->xmin[dim]) / d->m[dim];
+ d->m[dim] +=1;
+ d->dOmega *= d->dx[dim];
+ }
+
+ /* Set partitioning */
+
+ d->num_procs[0] = NPX;
+ n[0] = NPX;
+ nd[0] = d->m[0] / NPX;
+
+ d->num_procs[1] = NPY;
+ n[1] = NPY;
+ nd[1] = d->m[1] / NPY;
+
+#ifdef USE3D
+ d->num_procs[2] = NPZ;
+ n[2] = NPZ;
+ nd[2] = d->m[2] / NPZ;
+#endif
+
+ /* Compute the neighbors */
+
+ d->nbr_left[0] = (myId%n[0]) == 0 ? myId : myId-1;
+ d->nbr_right[0] = (myId%n[0]) == n[0]-1 ? myId : myId+1;
+
+ d->nbr_left[1] = (myId/n[0])%n[1] == 0 ? myId : myId-n[0];
+ d->nbr_right[1] = (myId/n[0])%n[1] == n[1]-1 ? myId : myId+n[0];
+
+#ifdef USE3D
+ d->nbr_left[2] = (myId/n[0]/n[1])%n[2] == 0 ? myId : myId-n[0]*n[1];
+ d->nbr_right[2] = (myId/n[0]/n[1])%n[2] == n[2]-1 ? myId : myId+n[0]*n[1];
+#endif
+
+ /* Compute the local subdomains
+ m_start: left border in global index space
+ l_m: length of the subdomain */
+
+ d->m_start[0] = (myId%n[0])*nd[0];
+ d->l_m[0] = d->nbr_right[0] == myId ? d->m[0] - d->m_start[0] : nd[0];
+
+ d->m_start[1] = ((myId/n[0])%n[1])*nd[1];
+ d->l_m[1] = d->nbr_right[1] == myId ? d->m[1] - d->m_start[1] : nd[1];
+
+#ifdef USE3D
+ d->m_start[2] = (myId/n[0]/n[1])*nd[2];
+ d->l_m[2] = d->nbr_right[2] == myId ? d->m[2] - d->m_start[2] : nd[2];
+#endif
+
+ /* Allocate memory for the y_ext array
+ (local solution + data from neighbors) */
+
+ size = 1;
+ FOR_DIM size *= d->l_m[dim]+2;
+ d->y_ext = (realtype *) malloc( size*sizeof(realtype));
+
+ /* Initialize Buffer field.
+ Size of buffer is checked when needed */
+
+ d->buf_send = NULL;
+ d->buf_recv = NULL;
+ d->buf_size = 0;
+
+ /* Allocate space for the source parameters */
+
+ *neq = 1; *l_neq = 1;
+ FOR_DIM {*neq *= d->m[dim]; *l_neq *= d->l_m[dim];}
+ d->p = N_VNew_Parallel(comm, *l_neq, *neq);
+
+ /* Initialize the parameters for a source with Gaussian profile */
+
+ SetSource(d);
+
+}
+
+static void SetSource(ProblemData d)
+{
+ int *l_m, *m_start;
+ realtype *xmin, *xmax, *dx;
+ realtype x[DIM], g, *pdata;
+ int i[DIM];
+
+ l_m = d->l_m;
+ m_start = d->m_start;
+ xmin = d->xmin;
+ xmax = d->xmax;
+ dx = d->dx;
+
+
+ pdata = NV_DATA_P(d->p);
+
+ for(i[0]=0; i[0]<l_m[0]; i[0]++) {
+ x[0] = xmin[0] + (m_start[0]+i[0]) * dx[0];
+ for(i[1]=0; i[1]<l_m[1]; i[1]++) {
+ x[1] = xmin[1] + (m_start[1]+i[1]) * dx[1];
+#ifdef USE3D
+ for(i[2]=0; i[2]<l_m[2]; i[2]++) {
+ x[2] = xmin[2] + (m_start[2]+i[2]) * dx[2];
+
+ g = G1_AMPL
+ * EXP( -SQR(G1_X-x[0])/SQR(G1_SIGMA) )
+ * EXP( -SQR(G1_Y-x[1])/SQR(G1_SIGMA) )
+ * EXP( -SQR(G1_Z-x[2])/SQR(G1_SIGMA) );
+
+ g += G2_AMPL
+ * EXP( -SQR(G2_X-x[0])/SQR(G2_SIGMA) )
+ * EXP( -SQR(G2_Y-x[1])/SQR(G2_SIGMA) )
+ * EXP( -SQR(G2_Z-x[2])/SQR(G2_SIGMA) );
+
+ if( g < G_MIN ) g = ZERO;
+
+ IJth(pdata, i) = g;
+ }
+#else
+ g = G1_AMPL
+ * EXP( -SQR(G1_X-x[0])/SQR(G1_SIGMA) )
+ * EXP( -SQR(G1_Y-x[1])/SQR(G1_SIGMA) );
+
+ g += G2_AMPL
+ * EXP( -SQR(G2_X-x[0])/SQR(G2_SIGMA) )
+ * EXP( -SQR(G2_Y-x[1])/SQR(G2_SIGMA) );
+
+ if( g < G_MIN ) g = ZERO;
+
+ IJth(pdata, i) = g;
+#endif
+ }
+ }
+}
+
+/*
+ *------------------------------------------------------------------
+ * f_comm:
+ * Function for inter-process communication
+ * Used both for the forward and backward phase.
+ *------------------------------------------------------------------
+ */
+
+static void f_comm(long int N_local, realtype t, N_Vector y, void *user_data)
+{
+ int id, n[DIM], proc_cond[DIM], nbr[DIM][2];
+ ProblemData d;
+ realtype *yextdata, *ydata;
+ int l_m[DIM], dim;
+ int c, i[DIM], l[DIM-1];
+ realtype *buf_send, *buf_recv;
+ MPI_Status stat;
+ MPI_Comm comm;
+ int dir, size = 1, small = INT_MAX;
+
+ d = (ProblemData) user_data;
+ comm = d->comm;
+ id = d->myId;
+
+ /* extract data from domain*/
+ FOR_DIM {
+ n[dim] = d->num_procs[dim];
+ l_m[dim] = d->l_m[dim];
+ }
+ yextdata = d->y_ext;
+ ydata = NV_DATA_P(y);
+
+ /* Calculate required buffer size */
+ FOR_DIM {
+ size *= l_m[dim];
+ if( l_m[dim] < small) small = l_m[dim];
+ }
+ size /= small;
+
+ /* Adjust buffer size if necessary */
+ if( d->buf_size < size ) {
+ d->buf_send = (realtype*) realloc( d->buf_send, size * sizeof(realtype));
+ d->buf_recv = (realtype*) realloc( d->buf_recv, size * sizeof(realtype));
+ d->buf_size = size;
+ }
+
+ buf_send = d->buf_send;
+ buf_recv = d->buf_recv;
+
+ /* Compute the communication pattern; who sends first? */
+ /* if proc_cond==1 , process sends first in this dimension */
+ proc_cond[0] = (id%n[0])%2;
+ proc_cond[1] = ((id/n[0])%n[1])%2;
+#ifdef USE3D
+ proc_cond[2] = (id/n[0]/n[1])%2;
+#endif
+
+ /* Compute the actual communication pattern */
+ /* nbr[dim][0] is first proc to communicate with in dimension dim */
+ /* nbr[dim][1] the second one */
+ FOR_DIM {
+ nbr[dim][proc_cond[dim]] = d->nbr_left[dim];
+ nbr[dim][!proc_cond[dim]] = d->nbr_right[dim];
+ }
+
+ /* Communication: loop over dimension and direction (left/right) */
+ FOR_DIM {
+
+ for (dir=0; dir<=1; dir++) {
+
+ /* If subdomain at boundary, no communication in this direction */
+
+ if (id != nbr[dim][dir]) {
+ c=0;
+ /* Compute the index of the boundary (right or left) */
+ i[dim] = (dir ^ proc_cond[dim]) ? (l_m[dim]-1) : 0;
+ /* Loop over all other dimensions and copy data into buf_send */
+ l[0]=(dim+1)%DIM;
+#ifdef USE3D
+ l[1]=(dim+2)%DIM;
+ for(i[l[1]]=0; i[l[1]]<l_m[l[1]]; i[l[1]]++)
+#endif
+ for(i[l[0]]=0; i[l[0]]<l_m[l[0]]; i[l[0]]++)
+ buf_send[c++] = IJth(ydata, i);
+
+ if ( proc_cond[dim] ) {
+ /* Send buf_send and receive into buf_recv */
+ MPI_Send(buf_send, c, PVEC_REAL_MPI_TYPE, nbr[dim][dir], 0, comm);
+ MPI_Recv(buf_recv, c, PVEC_REAL_MPI_TYPE, nbr[dim][dir], 0, comm, &stat);
+ } else {
+ /* Receive into buf_recv and send buf_send*/
+ MPI_Recv(buf_recv, c, PVEC_REAL_MPI_TYPE, nbr[dim][dir], 0, comm, &stat);
+ MPI_Send(buf_send, c, PVEC_REAL_MPI_TYPE, nbr[dim][dir], 0, comm);
+ }
+
+ c=0;
+
+ /* Compute the index of the boundary (right or left) in yextdata */
+ i[dim] = (dir ^ proc_cond[dim]) ? l_m[dim] : -1;
+
+ /* Loop over all other dimensions and copy data into yextdata */
+#ifdef USE3D
+ for(i[l[1]]=0; i[l[1]]<l_m[l[1]]; i[l[1]]++)
+#endif
+ for(i[l[0]]=0; i[l[0]]<l_m[l[0]]; i[l[0]]++)
+ IJth_ext(yextdata, i) = buf_recv[c++];
+ }
+ } /* end loop over direction */
+ } /* end loop over dimension */
+}
+
+/*
+ *------------------------------------------------------------------
+ * f and f_local:
+ * Forward phase ODE right-hand side
+ *------------------------------------------------------------------
+ */
+
+static int f(realtype t, N_Vector y, N_Vector ydot, void *user_data)
+{
+ ProblemData d;
+ long int l_neq=1;
+ int dim;
+
+ d = (ProblemData) user_data;
+ FOR_DIM l_neq *= d->l_m[dim];
+
+ /* Do all inter-processor communication */
+ f_comm(l_neq, t, y, user_data);
+
+ /* Compute right-hand side locally */
+ f_local(l_neq, t, y, ydot, user_data);
+
+ return(0);
+}
+
+static int f_local(long int Nlocal, realtype t, N_Vector y,
+ N_Vector ydot, void *user_data)
+{
+ realtype *Ydata, *dydata, *pdata;
+ realtype dx[DIM], c, v[DIM], cl[DIM], cr[DIM];
+ realtype adv[DIM], diff[DIM];
+ realtype xmin[DIM], xmax[DIM], x[DIM], x1;
+ int i[DIM], l_m[DIM], m_start[DIM], nbr_left[DIM], nbr_right[DIM], id;
+ ProblemData d;
+ int dim;
+
+ d = (ProblemData) user_data;
+
+ /* Extract stuff from data structure */
+ id = d->myId;
+ FOR_DIM {
+ xmin[dim] = d->xmin[dim];
+ xmax[dim] = d->xmax[dim];
+ l_m[dim] = d->l_m[dim];
+ m_start[dim] = d->m_start[dim];
+ dx[dim] = d->dx[dim];
+ nbr_left[dim] = d->nbr_left[dim];
+ nbr_right[dim] = d->nbr_right[dim];
+ }
+
+ /* Get pointers to vector data */
+ dydata = NV_DATA_P(ydot);
+ pdata = NV_DATA_P(d->p);
+
+ /* Copy local segment of y to y_ext */
+ Load_yext(NV_DATA_P(y), d);
+ Ydata = d->y_ext;
+
+ /* Velocity components in x1 and x2 directions (Poiseuille profile) */
+ v[1] = ZERO;
+#ifdef USE3D
+ v[2] = ZERO;
+#endif
+
+ /* Local domain is [xmin+(m_start+1)*dx, xmin+(m_start+1+l_m-1)*dx] */
+#ifdef USE3D
+ for(i[2]=0; i[2]<l_m[2]; i[2]++) {
+
+ x[2] = xmin[2] + (m_start[2]+i[2])*dx[2];
+#endif
+ for(i[1]=0; i[1]<l_m[1]; i[1]++) {
+
+ x[1] = xmin[1] + (m_start[1]+i[1])*dx[1];
+
+ /* Velocity component in x0 direction (Poiseuille profile) */
+ x1 = x[1] - xmin[1] - L;
+ v[0] = V_COEFF * (L + x1) * (L - x1);
+
+ for(i[0]=0; i[0]<l_m[0]; i[0]++) {
+
+ x[0] = xmin[0] + (m_start[0]+i[0])*dx[0];
+
+ c = IJth_ext(Ydata, i);
+
+ /* Source term*/
+ IJth(dydata, i) = IJth(pdata, i);
+
+ FOR_DIM {
+ i[dim]+=1;
+ cr[dim] = IJth_ext(Ydata, i);
+ i[dim]-=2;
+ cl[dim] = IJth_ext(Ydata, i);
+ i[dim]+=1;
+
+ /* Boundary conditions for the state variables */
+ if( i[dim]==l_m[dim]-1 && nbr_right[dim]==id)
+ cr[dim] = cl[dim];
+ else if( i[dim]==0 && nbr_left[dim]==id )
+ cl[dim] = cr[dim];
+
+ adv[dim] = v[dim] * (cr[dim]-cl[dim]) / (TWO*dx[dim]);
+ diff[dim] = DIFF_COEF * (cr[dim]-TWO*c+cl[dim]) / SQR(dx[dim]);
+
+ IJth(dydata, i) += (diff[dim] - adv[dim]);
+ }
+ }
+ }
+#ifdef USE3D
+ }
+#endif
+
+ return(0);
+}
+
+/*
+ *------------------------------------------------------------------
+ * fQ:
+ * Right-hand side of quadrature equations on forward integration.
+ * The only quadrature on this phase computes the local contribution
+ * to the function G.
+ *------------------------------------------------------------------
+ */
+
+static int fQ(realtype t, N_Vector y, N_Vector qdot, void *user_data)
+{
+ ProblemData d;
+ realtype *dqdata;
+
+ d = (ProblemData) user_data;
+
+ dqdata = NV_DATA_P(qdot);
+
+ dqdata[0] = N_VDotProd_Parallel(y,y);
+ dqdata[0] *= RCONST(0.5) * (d->dOmega);
+
+ return(0);
+}
+
+/*
+ *------------------------------------------------------------------
+ * fB and fB_local:
+ * Backward phase ODE right-hand side (the discretized adjoint PDE)
+ *------------------------------------------------------------------
+ */
+
+static int fB(realtype t, N_Vector y, N_Vector yB, N_Vector yBdot,
+ void *user_dataB)
+{
+ ProblemData d;
+ long int l_neq=1;
+ int dim;
+
+ d = (ProblemData) user_dataB;
+ FOR_DIM l_neq *= d->l_m[dim];
+
+ /* Do all inter-processor communication */
+ f_comm(l_neq, t, yB, user_dataB);
+
+ /* Compute right-hand side locally */
+ fB_local(l_neq, t, y, yB, yBdot, user_dataB);
+
+ return(0);
+}
+
+static int fB_local(long int NlocalB, realtype t,
+ N_Vector y, N_Vector yB, N_Vector dyB,
+ void *user_dataB)
+{
+ realtype *YBdata, *dyBdata, *ydata;
+ realtype dx[DIM], c, v[DIM], cl[DIM], cr[DIM];
+ realtype adv[DIM], diff[DIM];
+ realtype xmin[DIM], xmax[DIM], x[DIM], x1;
+ int i[DIM], l_m[DIM], m_start[DIM], nbr_left[DIM], nbr_right[DIM], id;
+ ProblemData d;
+ int dim;
+
+ d = (ProblemData) user_dataB;
+
+ /* Extract stuff from data structure */
+ id = d->myId;
+ FOR_DIM {
+ xmin[dim] = d->xmin[dim];
+ xmax[dim] = d->xmax[dim];
+ l_m[dim] = d->l_m[dim];
+ m_start[dim] = d->m_start[dim];
+ dx[dim] = d->dx[dim];
+ nbr_left[dim] = d->nbr_left[dim];
+ nbr_right[dim] = d->nbr_right[dim];
+ }
+
+ dyBdata = NV_DATA_P(dyB);
+ ydata = NV_DATA_P(y);
+
+ /* Copy local segment of yB to y_ext */
+ Load_yext(NV_DATA_P(yB), d);
+ YBdata = d->y_ext;
+
+ /* Velocity components in x1 and x2 directions (Poiseuille profile) */
+ v[1] = ZERO;
+#ifdef USE3D
+ v[2] = ZERO;
+#endif
+
+ /* local domain is [xmin+(m_start)*dx, xmin+(m_start+l_m-1)*dx] */
+#ifdef USE3D
+ for(i[2]=0; i[2]<l_m[2]; i[2]++) {
+
+ x[2] = xmin[2] + (m_start[2]+i[2])*dx[2];
+#endif
+
+ for(i[1]=0; i[1]<l_m[1]; i[1]++) {
+
+ x[1] = xmin[1] + (m_start[1]+i[1])*dx[1];
+
+ /* Velocity component in x0 direction (Poiseuille profile) */
+ x1 = x[1] - xmin[1] - L;
+ v[0] = V_COEFF * (L + x1) * (L - x1);
+
+ for(i[0]=0; i[0]<l_m[0]; i[0]++) {
+
+ x[0] = xmin[0] + (m_start[0]+i[0])*dx[0];
+
+ c = IJth_ext(YBdata, i);
+
+ /* Source term for adjoint PDE */
+ IJth(dyBdata, i) = -IJth(ydata, i);
+
+ FOR_DIM {
+
+ i[dim]+=1;
+ cr[dim] = IJth_ext(YBdata, i);
+ i[dim]-=2;
+ cl[dim] = IJth_ext(YBdata, i);
+ i[dim]+=1;
+
+ /* Boundary conditions for the adjoint variables */
+ if( i[dim]==l_m[dim]-1 && nbr_right[dim]==id)
+ cr[dim] = cl[dim]-(TWO*dx[dim]*v[dim]/DIFF_COEF)*c;
+ else if( i[dim]==0 && nbr_left[dim]==id )
+ cl[dim] = cr[dim]+(TWO*dx[dim]*v[dim]/DIFF_COEF)*c;
+
+ adv[dim] = v[dim] * (cr[dim]-cl[dim]) / (TWO*dx[dim]);
+ diff[dim] = DIFF_COEF * (cr[dim]-TWO*c+cl[dim]) / SQR(dx[dim]);
+
+ IJth(dyBdata, i) -= (diff[dim] + adv[dim]);
+ }
+ }
+ }
+#ifdef USE3D
+ }
+#endif
+
+ return(0);
+}
+
+/*
+ *------------------------------------------------------------------
+ * fQB:
+ * Right-hand side of quadrature equations on backward integration
+ * The i-th component of the gradient is nothing but int_t yB_i dt
+ *------------------------------------------------------------------
+ */
+
+static int fQB(realtype t, N_Vector y, N_Vector yB, N_Vector qBdot,
+ void *user_dataB)
+{
+ ProblemData d;
+
+ d = (ProblemData) user_dataB;
+
+ N_VScale_Parallel(-(d->dOmega), yB, qBdot);
+
+ return(0);
+}
+
+/*
+ *------------------------------------------------------------------
+ * Load_yext:
+ * copies data from src (y or yB) into y_ext, which already contains
+ * data from neighboring processes.
+ *------------------------------------------------------------------
+ */
+
+static void Load_yext(realtype *src, ProblemData d)
+{
+ int i[DIM], l_m[DIM], dim;
+
+ FOR_DIM l_m[dim] = d->l_m[dim];
+
+ /* copy local segment */
+#ifdef USE3D
+ for (i[2]=0; i[2]<l_m[2]; i[2]++)
+#endif
+ for(i[1]=0; i[1]<l_m[1]; i[1]++)
+ for(i[0]=0; i[0]<l_m[0]; i[0]++)
+ IJth_ext(d->y_ext, i) = IJth(src, i);
+}
+
+/*
+ *------------------------------------------------------------------
+ * PrintHeader:
+ * Print first lins of output (problem description)
+ *------------------------------------------------------------------
+ */
+
+static void PrintHeader()
+{
+ printf("\nParallel Krylov adjoint sensitivity analysis example\n");
+ printf("%1dD Advection diffusion PDE with homogeneous Neumann B.C.\n",DIM);
+ printf("Computes gradient of G = int_t_Omega ( c_i^2 ) dt dOmega\n");
+ printf("with respect to the source values at each grid point.\n\n");
+
+ printf("Domain:\n");
+
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf(" %Lf < x < %Lf mx = %d npe_x = %d \n",XMIN,XMAX,MX,NPX);
+ printf(" %Lf < y < %Lf my = %d npe_y = %d \n",YMIN,YMAX,MY,NPY);
+#else
+ printf(" %f < x < %f mx = %d npe_x = %d \n",XMIN,XMAX,MX,NPX);
+ printf(" %f < y < %f my = %d npe_y = %d \n",YMIN,YMAX,MY,NPY);
+#endif
+
+#ifdef USE3D
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf(" %Lf < z < %Lf mz = %d npe_z = %d \n",ZMIN,ZMAX,MZ,NPZ);
+#else
+ printf(" %f < z < %f mz = %d npe_z = %d \n",ZMIN,ZMAX,MZ,NPZ);
+#endif
+#endif
+
+ printf("\n");
+ }
+
+/*
+ *------------------------------------------------------------------
+ * PrintFinalStats:
+ * Print final statistics contained in cvode_mem
+ *------------------------------------------------------------------
+ */
+
+static void PrintFinalStats(void *cvode_mem)
+{
+ long int lenrw, leniw ;
+ long int lenrwSPGMR, leniwSPGMR;
+ long int nst, nfe, nsetups, nni, ncfn, netf;
+ long int nli, npe, nps, ncfl, nfeSPGMR;
+ int flag;
+
+ flag = CVodeGetWorkSpace(cvode_mem, &lenrw, &leniw);
+ flag = CVodeGetNumSteps(cvode_mem, &nst);
+ flag = CVodeGetNumRhsEvals(cvode_mem, &nfe);
+ flag = CVodeGetNumLinSolvSetups(cvode_mem, &nsetups);
+ flag = CVodeGetNumErrTestFails(cvode_mem, &netf);
+ flag = CVodeGetNumNonlinSolvIters(cvode_mem, &nni);
+ flag = CVodeGetNumNonlinSolvConvFails(cvode_mem, &ncfn);
+
+ flag = CVSpilsGetWorkSpace(cvode_mem, &lenrwSPGMR, &leniwSPGMR);
+ 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);
+
+ printf("\nFinal Statistics.. \n\n");
+ printf("lenrw = %6ld leniw = %6ld\n", lenrw, leniw);
+ printf("llrw = %6ld lliw = %6ld\n", lenrwSPGMR, leniwSPGMR);
+ printf("nst = %6ld\n" , nst);
+ printf("nfe = %6ld nfel = %6ld\n" , nfe, nfeSPGMR);
+ printf("nni = %6ld nli = %6ld\n" , nni, nli);
+ printf("nsetups = %6ld netf = %6ld\n" , nsetups, netf);
+ printf("npe = %6ld nps = %6ld\n" , npe, nps);
+ printf("ncfn = %6ld ncfl = %6ld\n\n", ncfn, ncfl);
+}
+
+/*
+ *------------------------------------------------------------------
+ * OutputGradient:
+ * Generate matlab m files for visualization
+ * One file gradXXXX.m from each process + a driver grad.m
+ *------------------------------------------------------------------
+ */
+
+static void OutputGradient(int myId, N_Vector qB, ProblemData d)
+{
+ FILE *fid;
+ char filename[20];
+ int *l_m, *m_start, i[DIM],ip;
+ realtype *xmin, *xmax, *dx;
+ realtype x[DIM], *pdata, p, *qBdata, g;
+
+ sprintf(filename,"grad%03d.m",myId);
+ fid = fopen(filename,"w");
+
+ l_m = d->l_m;
+ m_start = d->m_start;
+ xmin = d->xmin;
+ xmax = d->xmax;
+ dx = d->dx;
+
+ qBdata = NV_DATA_P(qB);
+ pdata = NV_DATA_P(d->p);
+
+ /* Write matlab files with solutions from each process */
+
+ for(i[0]=0; i[0]<l_m[0]; i[0]++) {
+ x[0] = xmin[0] + (m_start[0]+i[0]) * dx[0];
+ for(i[1]=0; i[1]<l_m[1]; i[1]++) {
+ x[1] = xmin[1] + (m_start[1]+i[1]) * dx[1];
+#ifdef USE3D
+ for(i[2]=0; i[2]<l_m[2]; i[2]++) {
+ x[2] = xmin[2] + (m_start[2]+i[2]) * dx[2];
+ g = IJth(qBdata, i);
+ p = IJth(pdata, i);
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ fprintf(fid,"x%d(%d,1) = %Le; \n", myId, i[0]+1, x[0]);
+ fprintf(fid,"y%d(%d,1) = %Le; \n", myId, i[1]+1, x[1]);
+ fprintf(fid,"z%d(%d,1) = %Le; \n", myId, i[2]+1, x[2]);
+ 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,"x%d(%d,1) = %le; \n", myId, i[0]+1, x[0]);
+ fprintf(fid,"y%d(%d,1) = %le; \n", myId, i[1]+1, x[1]);
+ fprintf(fid,"z%d(%d,1) = %le; \n", myId, i[2]+1, x[2]);
+ 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,"x%d(%d,1) = %e; \n", myId, i[0]+1, x[0]);
+ fprintf(fid,"y%d(%d,1) = %e; \n", myId, i[1]+1, x[1]);
+ fprintf(fid,"z%d(%d,1) = %e; \n", myId, i[2]+1, x[2]);
+ 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);
+#endif
+ }
+#else
+ g = IJth(qBdata, i);
+ p = IJth(pdata, i);
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ fprintf(fid,"x%d(%d,1) = %Le; \n", myId, i[0]+1, x[0]);
+ fprintf(fid,"y%d(%d,1) = %Le; \n", myId, i[1]+1, x[1]);
+ 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,"x%d(%d,1) = %le; \n", myId, i[0]+1, x[0]);
+ fprintf(fid,"y%d(%d,1) = %le; \n", myId, i[1]+1, x[1]);
+ 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);
+#else
+ fprintf(fid,"x%d(%d,1) = %e; \n", myId, i[0]+1, x[0]);
+ fprintf(fid,"y%d(%d,1) = %e; \n", myId, i[1]+1, x[1]);
+ 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);
+#endif
+#endif
+ }
+ }
+ fclose(fid);
+
+ /* Write matlab driver */
+
+ if (myId == 0) {
+
+ fid = fopen("grad.m","w");
+
+#ifdef USE3D
+ fprintf(fid,"clear;\nfigure;\nhold on\n");
+ fprintf(fid,"trans = 0.7;\n");
+ fprintf(fid,"ecol = 'none';\n");
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ fprintf(fid,"xp=[%Lf %Lf];\n",G1_X,G2_X);
+ fprintf(fid,"yp=[%Lf %Lf];\n",G1_Y,G2_Y);
+ fprintf(fid,"zp=[%Lf %Lf];\n",G1_Z,G2_Z);
+#else
+ fprintf(fid,"xp=[%f %f];\n",G1_X,G2_X);
+ fprintf(fid,"yp=[%f %f];\n",G1_Y,G2_Y);
+ fprintf(fid,"zp=[%f %f];\n",G1_Z,G2_Z);
+#endif
+ fprintf(fid,"ns = length(xp)*length(yp)*length(zp);\n");
+
+ for (ip=0; ip<d->npes; ip++) {
+ fprintf(fid,"\ngrad%03d;\n",ip);
+ fprintf(fid,"[X,Y,Z]=meshgrid(x%d,y%d,z%d);\n",ip,ip,ip);
+ fprintf(fid,"s%d=slice(X,Y,Z,g%d,xp,yp,zp);\n",ip,ip);
+ fprintf(fid,"for i = 1:ns\n");
+ fprintf(fid," set(s%d(i),'FaceAlpha',trans);\n",ip);
+ fprintf(fid," set(s%d(i),'EdgeColor',ecol);\n",ip);
+ fprintf(fid,"end\n");
+ }
+
+ fprintf(fid,"view(3)\n");
+ fprintf(fid,"\nshading interp\naxis equal\n");
+#else
+ fprintf(fid,"clear;\nfigure;\n");
+ fprintf(fid,"trans = 0.7;\n");
+ fprintf(fid,"ecol = 'none';\n");
+
+ for (ip=0; ip<d->npes; ip++) {
+
+ fprintf(fid,"\ngrad%03d;\n",ip);
+
+ fprintf(fid,"\nsubplot(1,2,1)\n");
+ fprintf(fid,"s=surf(x%d,y%d,g%d);\n",ip,ip,ip);
+ fprintf(fid,"set(s,'FaceAlpha',trans);\n");
+ fprintf(fid,"set(s,'EdgeColor',ecol);\n");
+ fprintf(fid,"hold on\n");
+ fprintf(fid,"axis tight\n");
+ fprintf(fid,"box on\n");
+
+ fprintf(fid,"\nsubplot(1,2,2)\n");
+ fprintf(fid,"s=surf(x%d,y%d,p%d);\n",ip,ip,ip);
+ fprintf(fid,"set(s,'CData',g%d);\n",ip);
+ fprintf(fid,"set(s,'FaceAlpha',trans);\n");
+ fprintf(fid,"set(s,'EdgeColor',ecol);\n");
+ fprintf(fid,"hold on\n");
+ fprintf(fid,"axis tight\n");
+ fprintf(fid,"box on\n");
+
+ }
+#endif
+ fclose(fid);
+ }
+}
diff --git a/examples/cvodes/parallel/cvsAtmDisp_ASAi_kry_bbd_p.out b/examples/cvodes/parallel/cvsAtmDisp_ASAi_kry_bbd_p.out
new file mode 100644
index 0000000..f393689
--- /dev/null
+++ b/examples/cvodes/parallel/cvsAtmDisp_ASAi_kry_bbd_p.out
@@ -0,0 +1,37 @@
+
+Parallel Krylov adjoint sensitivity analysis example
+3D Advection diffusion PDE with homogeneous Neumann B.C.
+Computes gradient of G = int_t_Omega ( c_i^2 ) dt dOmega
+with respect to the source values at each grid point.
+
+Domain:
+ 0.000000 < x < 20.000000 mx = 20 npe_x = 2
+ 0.000000 < y < 20.000000 my = 40 npe_y = 2
+ 0.000000 < z < 20.000000 mz = 20 npe_z = 1
+
+Begin forward integration... done. G = 8.232843e+03
+
+Final Statistics..
+
+lenrw = 180946 leniw = 212
+llrw = 180856 lliw = 80
+nst = 118
+nfe = 125 nfel = 141
+nni = 121 nli = 141
+nsetups = 17 netf = 0
+npe = 2 nps = 234
+ncfn = 0 ncfl = 0
+
+Begin backward integration... done.
+
+Final Statistics..
+
+lenrw = 361716 leniw = 212
+llrw = 180856 lliw = 80
+nst = 70
+nfe = 80 nfel = 133
+nni = 76 nli = 133
+nsetups = 15 netf = 0
+npe = 2 nps = 204
+ncfn = 0 ncfl = 0
+
diff --git a/examples/cvodes/parallel/cvsDiurnal_FSA_kry_p.c b/examples/cvodes/parallel/cvsDiurnal_FSA_kry_p.c
new file mode 100644
index 0000000..c9d27a7
--- /dev/null
+++ b/examples/cvodes/parallel/cvsDiurnal_FSA_kry_p.c
@@ -0,0 +1,1286 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.4 $
+ * $Date: 2010/12/01 23:00:48 $
+ * -----------------------------------------------------------------
+ * Programmer(s): S. D. Cohen, A. C. Hindmarsh, Radu Serban,
+ * and M. R. Wittman @ LLNL
+ * -----------------------------------------------------------------
+ * Example problem:
+ *
+ * An ODE system is generated from the following 2-species diurnal
+ * kinetics advection-diffusion PDE system in 2 space dimensions:
+ *
+ * dc(i)/dt = Kh*(d/dx)^2 c(i) + V*dc(i)/dx + (d/dy)(Kv(y)*dc(i)/dy)
+ * + Ri(c1,c2,t) for i = 1,2, where
+ * R1(c1,c2,t) = -q1*c1*c3 - q2*c1*c2 + 2*q3(t)*c3 + q4(t)*c2 ,
+ * R2(c1,c2,t) = q1*c1*c3 - q2*c1*c2 - q4(t)*c2 ,
+ * Kv(y) = Kv0*exp(y/5) ,
+ * Kh, V, Kv0, q1, q2, and c3 are constants, and q3(t) and q4(t)
+ * vary diurnally. The problem is posed on the square
+ * 0 <= x <= 20, 30 <= y <= 50 (all in km),
+ * with homogeneous Neumann boundary conditions, and for time t in
+ * 0 <= t <= 86400 sec (1 day).
+ * The PDE system is treated by central differences on a uniform
+ * mesh, with simple polynomial initial profiles.
+ *
+ * The problem is solved by CVODES on NPE processors, treated
+ * as a rectangular process grid of size NPEX by NPEY, with
+ * NPE = NPEX*NPEY. Each processor contains a subgrid of size
+ * MXSUB by MYSUB of the (x,y) mesh. Thus the actual mesh sizes
+ * are MX = MXSUB*NPEX and MY = MYSUB*NPEY, and the ODE system size
+ * 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
+ * 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.
+ *
+ * Performance data and sampled solution values are printed at
+ * selected output times, and all performance counters are printed
+ * on completion.
+ *
+ * Optionally, CVODES can compute sensitivities with respect to the
+ * problem parameters q1 and q2.
+ * 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 FULL or PARTIAL,
+ * respectively).
+ *
+ * Execution:
+ *
+ * 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
+ * application.
+ * If no sensitivities are desired:
+ * % mpirun -np N cvsDiurnal_FSA_kry_p -nosensi
+ * If sensitivities are to be computed:
+ * % mpirun -np N cvsDiurnal_FSA_kry_p -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 <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 <mpi.h>
+
+
+/* Problem Constants */
+
+#define NVARS 2 /* number of species */
+#define C1_SCALE RCONST(1.0e6) /* coefficients in initial profiles */
+#define C2_SCALE RCONST(1.0e12)
+
+#define T0 RCONST(0.0) /* initial time */
+#define NOUT 12 /* number of output times */
+#define TWOHR RCONST(7200.0) /* number of seconds in two hours */
+#define HALFDAY RCONST(4.32e4) /* number of seconds in a half day */
+#define PI RCONST(3.1415926535898) /* pi */
+
+#define XMIN RCONST(0.0) /* grid boundaries in x */
+#define XMAX RCONST(20.0)
+#define YMIN RCONST(30.0) /* grid boundaries in y */
+#define YMAX RCONST(50.0)
+
+#define NPEX 2 /* no. PEs in x direction of PE array */
+#define NPEY 2 /* no. PEs in y direction of PE array */
+ /* Total no. PEs = NPEX*NPEY */
+#define MXSUB 5 /* no. x points per subgrid */
+#define MYSUB 5 /* no. y points per subgrid */
+
+#define MX (NPEX*MXSUB) /* MX = number of x mesh points */
+#define MY (NPEY*MYSUB) /* MY = number of y mesh points */
+ /* Spatial mesh is MX by MY */
+
+/* CVodeInit Constants */
+
+#define RTOL RCONST(1.0e-5) /* scalar relative tolerance */
+#define FLOOR RCONST(100.0) /* value of C1 or C2 at which tols. */
+ /* change from relative to absolute */
+#define ATOL (RTOL*FLOOR) /* scalar absolute tolerance */
+
+/* Sensitivity constants */
+#define NP 8 /* number of problem parameters */
+#define NS 2 /* number of sensitivities */
+
+#define ZERO RCONST(0.0)
+
+
+/* User-defined matrix accessor macro: IJth */
+
+/* IJth is defined in order to write code which indexes into small dense
+ matrices with a (row,column) pair, where 1 <= row,column <= NVARS.
+
+ IJth(a,i,j) references the (i,j)th entry of the small matrix realtype **a,
+ where 1 <= i,j <= NVARS. The small matrix routines in sundials_dense.h
+ work with matrices stored by column in a 2-dimensional array. In C,
+ arrays are indexed starting at 0, not 1. */
+
+#define IJth(a,i,j) (a[j-1][i-1])
+
+/* Types : UserData and PreconData
+ contain problem parameters, problem constants, preconditioner blocks,
+ pivot arrays, grid constants, and processor indices, as
+ well as data needed for preconditioning */
+
+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;
+ MPI_Comm comm;
+
+ /* For preconditioner */
+ realtype **P[MXSUB][MYSUB], **Jbd[MXSUB][MYSUB];
+ long int *pivot[MXSUB][MYSUB];
+
+} *UserData;
+
+/* Functions Called by the CVODES Solver */
+
+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 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);
+
+/* Private Helper Functions */
+
+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 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 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[]);
+static void ucomm(realtype t, N_Vector u, UserData data);
+static void fcalc(realtype t, realtype udata[], realtype dudata[], UserData data);
+
+static void PrintOutput(void *cvode_mem, int my_pe, MPI_Comm comm,
+ realtype t, N_Vector u);
+static void PrintOutputS(int my_pe, MPI_Comm comm, N_Vector *uS);
+static void PrintFinalStats(void *cvode_mem, booleantype sensi);
+static int check_flag(void *flagvalue, char *funcname, int opt, int id);
+
+/*
+ *--------------------------------------------------------------------
+ * MAIN PROGRAM
+ *--------------------------------------------------------------------
+ */
+
+int main(int argc, char *argv[])
+{
+ realtype abstol, reltol, t, tout;
+ N_Vector u;
+ UserData data;
+ void *cvode_mem;
+ int iout, flag, my_pe, npes;
+ long int neq, local_N;
+ MPI_Comm comm;
+
+ realtype *pbar;
+ int is, *plist;
+ N_Vector *uS;
+ booleantype sensi, err_con;
+ int sensi_meth;
+
+ u = NULL;
+ data = NULL;
+ cvode_mem = NULL;
+ pbar = NULL;
+ plist = NULL;
+ uS = 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;
+ MPI_Comm_size(comm, &npes);
+ MPI_Comm_rank(comm, &my_pe);
+
+ if (npes != NPEX*NPEY) {
+ if (my_pe == 0)
+ fprintf(stderr,
+ "\nMPI_ERROR(0): npes = %d is not equal to NPEX*NPEY = %d\n\n",
+ npes, NPEX*NPEY);
+ MPI_Finalize();
+ return(1);
+ }
+
+ /* Process arguments */
+ ProcessArgs(argc, argv, my_pe, &sensi, &sensi_meth, &err_con);
+
+ /* Set local length */
+ local_N = NVARS*MXSUB*MYSUB;
+
+ /* Allocate and load user data block; allocate preconditioner block */
+ data = (UserData) malloc(sizeof *data);
+ if (check_flag((void *)data, "malloc", 2, my_pe)) MPI_Abort(comm, 1);
+ data->p = NULL;
+ data->p = (realtype *) malloc(NP*sizeof(realtype));
+ if (check_flag((void *)data->p, "malloc", 2, my_pe)) MPI_Abort(comm, 1);
+ InitUserData(my_pe, comm, data);
+
+ /* Allocate u, and set initial values and tolerances */
+ u = N_VNew_Parallel(comm, local_N, neq);
+ if (check_flag((void *)u, "N_VNew_Parallel", 0, my_pe)) MPI_Abort(comm, 1);
+ SetInitialProfiles(u, data);
+ abstol = ATOL; reltol = RTOL;
+
+ /* Create CVODES object, set optional input, allocate memory */
+ cvode_mem = CVodeCreate(CV_BDF, CV_NEWTON);
+ if (check_flag((void *)cvode_mem, "CVodeCreate", 0, my_pe)) MPI_Abort(comm, 1);
+
+ flag = CVodeSetUserData(cvode_mem, data);
+ if (check_flag(&flag, "CVodeSetUserData", 1, my_pe)) MPI_Abort(comm, 1);
+
+ flag = CVodeSetMaxNumSteps(cvode_mem, 2000);
+ if (check_flag(&flag, "CVodeSetMaxNumSteps", 1, my_pe)) MPI_Abort(comm, 1);
+
+ flag = CVodeInit(cvode_mem, f, T0, u);
+ if (check_flag(&flag, "CVodeInit", 1, my_pe)) MPI_Abort(comm, 1);
+
+ 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);
+
+ flag = CVSpilsSetPreconditioner(cvode_mem, Precond, PSolve);
+ if (check_flag(&flag, "CVSpilsSetPreconditioner", 1, my_pe)) MPI_Abort(comm, 1);
+
+ if(my_pe == 0)
+ printf("\n2-species diurnal advection-diffusion problem\n");
+
+ /* Sensitivity-related settings */
+ if( sensi) {
+
+ plist = (int *) malloc(NS * sizeof(int));
+ if (check_flag((void *)plist, "malloc", 2, my_pe)) MPI_Abort(comm, 1);
+ for (is=0; is<NS; is++) plist[is] = is;
+
+ pbar = (realtype *) malloc(NS*sizeof(realtype));
+ if (check_flag((void *)pbar, "malloc", 2, my_pe)) MPI_Abort(comm, 1);
+ for (is=0; is<NS; is++) pbar[is] = data->p[plist[is]];
+
+ uS = N_VCloneVectorArray_Parallel(NS, u);
+ if (check_flag((void *)uS, "N_VCloneVectorArray_Parallel", 0, my_pe))
+ MPI_Abort(comm, 1);
+ for (is = 0; is < NS; is++)
+ N_VConst(ZERO,uS[is]);
+
+ flag = CVodeSensInit1(cvode_mem, NS, sensi_meth, NULL, uS);
+ if (check_flag(&flag, "CVodeSensInit1", 1, my_pe)) MPI_Abort(comm, 1);
+
+ flag = CVodeSensEEtolerances(cvode_mem);
+ if (check_flag(&flag, "CVodeSensEEtolerances", 1, my_pe)) MPI_Abort(comm, 1);
+
+ flag = CVodeSetSensErrCon(cvode_mem, err_con);
+ if (check_flag(&flag, "CVodeSetSensErrCon", 1, my_pe)) MPI_Abort(comm, 1);
+
+ flag = CVodeSetSensDQMethod(cvode_mem, CV_CENTERED, ZERO);
+ if (check_flag(&flag, "CVodeSetSensDQMethod", 1, my_pe)) MPI_Abort(comm, 1);
+
+ flag = CVodeSetSensParams(cvode_mem, data->p, pbar, plist);
+ if (check_flag(&flag, "CVodeSetSensParams", 1, my_pe)) MPI_Abort(comm, 1);
+
+ if(my_pe == 0) {
+ printf("Sensitivity: YES ");
+ if(sensi_meth == CV_SIMULTANEOUS)
+ printf("( SIMULTANEOUS +");
+ else
+ if(sensi_meth == CV_STAGGERED) printf("( STAGGERED +");
+ else printf("( STAGGERED1 +");
+ if(err_con) printf(" FULL ERROR CONTROL )");
+ else printf(" PARTIAL ERROR CONTROL )");
+ }
+
+ } else {
+
+ if(my_pe == 0) printf("Sensitivity: NO ");
+
+ }
+
+ if (my_pe == 0) {
+ printf("\n\n");
+ printf("========================================================================\n");
+ printf(" T Q H NST Bottom left Top right \n");
+ printf("========================================================================\n");
+ }
+
+ /* In loop over output points, call CVode, print results, test for error */
+ for (iout=1, tout = TWOHR; iout <= NOUT; iout++, tout += TWOHR) {
+ flag = CVode(cvode_mem, tout, u, &t, CV_NORMAL);
+ if (check_flag(&flag, "CVode", 1, my_pe)) break;
+ PrintOutput(cvode_mem, my_pe, comm, t, u);
+ if (sensi) {
+ flag = CVodeGetSens(cvode_mem, &t, uS);
+ if (check_flag(&flag, "CVodeGetSens", 1, my_pe)) break;
+ PrintOutputS(my_pe, comm, uS);
+ }
+ if (my_pe == 0)
+ printf("------------------------------------------------------------------------\n");
+ }
+
+ /* Print final statistics */
+ if (my_pe == 0) PrintFinalStats(cvode_mem, sensi);
+
+ /* Free memory */
+ N_VDestroy_Parallel(u);
+ if (sensi) {
+ N_VDestroyVectorArray_Parallel(uS, NS);
+ free(plist);
+ free(pbar);
+ }
+ FreeUserData(data);
+ CVodeFree(&cvode_mem);
+
+ MPI_Finalize();
+
+ return(0);
+}
+
+/*
+ *--------------------------------------------------------------------
+ * FUNCTIONS CALLED BY CVODES
+ *--------------------------------------------------------------------
+ */
+
+/*
+ * f routine. Evaluate f(t,y). First call ucomm to do communication of
+ * subgrid boundary data into uext. Then calculate f by a call to fcalc.
+ */
+
+static int f(realtype t, N_Vector u, N_Vector udot, void *user_data)
+{
+ realtype *udata, *dudata;
+ UserData data;
+
+ udata = NV_DATA_P(u);
+ dudata = NV_DATA_P(udot);
+ data = (UserData) user_data;
+
+ /* Call ucomm to do inter-processor communicaiton */
+ ucomm (t, u, data);
+
+ /* Call fcalc to calculate all right-hand sides */
+ fcalc (t, udata, dudata, data);
+
+ return(0);
+}
+
+/*
+ * 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 c1, c2, cydn, cyup, diag, ydn, yup, q4coef, dely, verdco, hordco;
+ realtype **(*P)[MYSUB], **(*Jbd)[MYSUB];
+ long int *(*pivot)[MYSUB], ier, nvmxsub, offset;
+ int lx, ly, jx, jy, isubx, isuby;
+ realtype *udata, **a, **j;
+ UserData data;
+ realtype Q1, Q2, C3, A3, A4, KH, VEL, KV0;
+
+ /* Make local copies of pointers in user_data, pointer to u's data,
+ and PE index pair */
+ data = (UserData) user_data;
+ P = data->P;
+ Jbd = data->Jbd;
+ pivot = data->pivot;
+ udata = NV_DATA_P(u);
+ isubx = data->isubx; isuby = data->isuby;
+ nvmxsub = data->nvmxsub;
+
+ /* Load problem coefficients and parameters */
+ Q1 = data->p[0];
+ Q2 = data->p[1];
+ C3 = data->p[2];
+ A3 = data->p[3];
+ A4 = data->p[4];
+ KH = data->p[5];
+ VEL = data->p[6];
+ KV0 = data->p[7];
+
+ if (jok) { /* jok = TRUE: 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;
+
+ } else { /* jok = FALSE: Generate Jbd from scratch and copy to P */
+
+ /* Make local copies of problem variables, for efficiency */
+ q4coef = data->q4;
+ dely = data->dy;
+ verdco = data->vdco;
+ hordco = data->hdco;
+
+ /* Compute 2x2 diagonal Jacobian blocks (using q4 values
+ computed on the last f call). Load into P. */
+ for (ly = 0; ly < MYSUB; ly++) {
+ jy = ly + isuby*MYSUB;
+ ydn = YMIN + (jy - RCONST(0.5))*dely;
+ yup = ydn + dely;
+ cydn = verdco*EXP(RCONST(0.2)*ydn);
+ cyup = verdco*EXP(RCONST(0.2)*yup);
+ diag = -(cydn + cyup + RCONST(2.0)*hordco);
+ for (lx = 0; lx < MXSUB; lx++) {
+ jx = lx + isubx*MXSUB;
+ offset = lx*NVARS + ly*nvmxsub;
+ c1 = udata[offset];
+ c2 = udata[offset+1];
+ j = Jbd[lx][ly];
+ a = P[lx][ly];
+ IJth(j,1,1) = (-Q1*C3 - Q2*c2) + diag;
+ IJth(j,1,2) = -Q2*c1 + q4coef;
+ IJth(j,2,1) = Q1*C3 - Q2*c2;
+ IJth(j,2,2) = (-Q2*c1 - q4coef) + diag;
+ denseCopy(j, a, NVARS, NVARS);
+ }
+ }
+
+ *jcurPtr = TRUE;
+
+ }
+
+ /* Scale by -gamma */
+ for (ly = 0; ly < MYSUB; ly++)
+ for (lx = 0; lx < MXSUB; lx++)
+ denseScale(-gamma, P[lx][ly], NVARS, NVARS);
+
+ /* Add identity matrix and do LU decompositions on blocks in place */
+ for (lx = 0; lx < MXSUB; lx++) {
+ for (ly = 0; ly < MYSUB; ly++) {
+ denseAddIdentity(P[lx][ly], NVARS);
+ ier = denseGETRF(P[lx][ly], NVARS, NVARS, pivot[lx][ly]);
+ if (ier != 0) return(1);
+ }
+ }
+
+ return(0);
+}
+
+/*
+ * 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)
+{
+ realtype **(*P)[MYSUB];
+ long int *(*pivot)[MYSUB], nvmxsub;
+ int lx, ly;
+ realtype *zdata, *v;
+ UserData data;
+
+ /* Extract the P and pivot arrays from user_data */
+ data = (UserData) user_data;
+ P = data->P;
+ pivot = data->pivot;
+
+ /* Solve the block-diagonal system Px = r using LU factors stored
+ 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 = NV_DATA_P(z);
+
+ for (lx = 0; lx < MXSUB; lx++) {
+ for (ly = 0; ly < MYSUB; ly++) {
+ v = &(zdata[lx*NVARS + ly*nvmxsub]);
+ denseGETRS(P[lx][ly], NVARS, pivot[lx][ly], v);
+ }
+ }
+
+ return(0);
+}
+
+/*
+ *--------------------------------------------------------------------
+ * PRIVATE FUNCTIONS
+ *--------------------------------------------------------------------
+ */
+
+/*
+ * Process and verify arguments to cvsfwdkryx_p.
+ */
+
+static void ProcessArgs(int argc, char *argv[], int my_pe,
+ booleantype *sensi, int *sensi_meth, booleantype *err_con)
+{
+ *sensi = FALSE;
+ *sensi_meth = -1;
+ *err_con = FALSE;
+
+ if (argc < 2) WrongArgs(my_pe, argv[0]);
+
+ if (strcmp(argv[1],"-nosensi") == 0)
+ *sensi = FALSE;
+ else if (strcmp(argv[1],"-sensi") == 0)
+ *sensi = TRUE;
+ else
+ WrongArgs(my_pe, argv[0]);
+
+ if (*sensi) {
+
+ if (argc != 4)
+ WrongArgs(my_pe, argv[0]);
+
+ if (strcmp(argv[2],"sim") == 0)
+ *sensi_meth = CV_SIMULTANEOUS;
+ else if (strcmp(argv[2],"stg") == 0)
+ *sensi_meth = CV_STAGGERED;
+ else if (strcmp(argv[2],"stg1") == 0)
+ *sensi_meth = CV_STAGGERED1;
+ else
+ WrongArgs(my_pe, argv[0]);
+
+ if (strcmp(argv[3],"t") == 0)
+ *err_con = TRUE;
+ else if (strcmp(argv[3],"f") == 0)
+ *err_con = FALSE;
+ else
+ WrongArgs(my_pe, argv[0]);
+ }
+
+}
+
+static void WrongArgs(int my_pe, char *name)
+{
+ if (my_pe == 0) {
+ printf("\nUsage: %s [-nosensi] [-sensi sensi_meth err_con]\n",name);
+ printf(" sensi_meth = sim, stg, or stg1\n");
+ printf(" err_con = t or f\n");
+ }
+ MPI_Finalize();
+ exit(0);
+}
+
+
+/*
+ * Set user data.
+ */
+
+static void InitUserData(int my_pe, MPI_Comm comm, UserData data)
+{
+ long int isubx, isuby;
+ int lx, ly;
+ realtype KH, VEL, KV0;
+
+ /* Set problem parameters */
+ data->p[0] = RCONST(1.63e-16); /* Q1 coeffs. q1, q2, c3 */
+ data->p[1] = RCONST(4.66e-16); /* Q2 */
+ data->p[2] = RCONST(3.7e16); /* C3 */
+ data->p[3] = RCONST(22.62); /* A3 coeff. in expression for q3(t) */
+ data->p[4] = RCONST(7.601); /* A4 coeff. in expression for q4(t) */
+ KH = data->p[5] = RCONST(4.0e-6); /* KH horizontal diffusivity Kh */
+ VEL = data->p[6] = RCONST(0.001); /* VEL advection velocity V */
+ KV0 = data->p[7] = RCONST(1.0e-8); /* KV0 coeff. in Kv(z) */
+
+ /* Set problem constants */
+ data->om = PI/HALFDAY;
+ data->dx = (XMAX-XMIN)/((realtype)(MX-1));
+ data->dy = (YMAX-YMIN)/((realtype)(MY-1));
+ data->hdco = KH/SQR(data->dx);
+ data->haco = VEL/(RCONST(2.0)*data->dx);
+ data->vdco = (RCONST(1.0)/SQR(data->dy))*KV0;
+
+ /* Set machine-related constants */
+ data->comm = comm;
+ data->my_pe = my_pe;
+
+ /* isubx and isuby are the PE grid indices corresponding to my_pe */
+ isuby = my_pe/NPEX;
+ isubx = my_pe - isuby*NPEX;
+ data->isubx = isubx;
+ data->isuby = isuby;
+
+ /* Set the sizes of a boundary x-line in u and uext */
+ data->nvmxsub = NVARS*MXSUB;
+ data->nvmxsub2 = NVARS*(MXSUB+2);
+
+ /* Preconditioner-related fields */
+ for (lx = 0; lx < MXSUB; lx++) {
+ 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);
+ }
+ }
+}
+
+/*
+ * Free user data memory.
+ */
+
+static void FreeUserData(UserData data)
+{
+ int lx, ly;
+
+ for (lx = 0; lx < MXSUB; lx++) {
+ for (ly = 0; ly < MYSUB; ly++) {
+ destroyMat((data->P)[lx][ly]);
+ destroyMat((data->Jbd)[lx][ly]);
+ destroyArray((data->pivot)[lx][ly]);
+ }
+ }
+
+ free(data->p);
+
+ free(data);
+}
+
+/*
+ * Set initial conditions in u.
+ */
+
+static void SetInitialProfiles(N_Vector u, UserData data)
+{
+ long int isubx, isuby, lx, ly, jx, jy, offset;
+ realtype dx, dy, x, y, cx, cy, xmid, ymid;
+ realtype *udata;
+
+ /* Set pointer to data array in vector u */
+ udata = NV_DATA_P(u);
+
+ /* Get mesh spacings, and subgrid indices for this PE */
+ dx = data->dx; dy = data->dy;
+ isubx = data->isubx; isuby = data->isuby;
+
+ /* Load initial profiles of c1 and c2 into local u vector.
+ Here lx and ly are local mesh point indices on the local subgrid,
+ and jx and jy are the global mesh point indices. */
+ offset = 0;
+ xmid = RCONST(0.5)*(XMIN + XMAX);
+ ymid = RCONST(0.5)*(YMIN + YMAX);
+ for (ly = 0; ly < MYSUB; ly++) {
+ jy = ly + isuby*MYSUB;
+ y = YMIN + jy*dy;
+ cy = SQR(RCONST(0.1)*(y - ymid));
+ cy = RCONST(1.0) - cy + RCONST(0.5)*SQR(cy);
+ for (lx = 0; lx < MXSUB; lx++) {
+ jx = lx + isubx*MXSUB;
+ x = XMIN + jx*dx;
+ cx = SQR(RCONST(0.1)*(x - xmid));
+ cx = RCONST(1.0) - cx + RCONST(0.5)*SQR(cx);
+ udata[offset ] = C1_SCALE*cx*cy;
+ udata[offset+1] = C2_SCALE*cx*cy;
+ offset = offset + 2;
+ }
+ }
+}
+
+/*
+ * 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,
+ realtype udata[])
+{
+ int i, ly;
+ long int offsetu, offsetbuf;
+ realtype bufleft[NVARS*MYSUB], bufright[NVARS*MYSUB];
+
+ /* If isuby > 0, send data from bottom x-line of u */
+ if (isuby != 0)
+ MPI_Send(&udata[0], dsizex, PVEC_REAL_MPI_TYPE, my_pe-NPEX, 0, comm);
+
+ /* If isuby < NPEY-1, send data from top x-line of u */
+ if (isuby != NPEY-1) {
+ offsetu = (MYSUB-1)*dsizex;
+ MPI_Send(&udata[offsetu], dsizex, PVEC_REAL_MPI_TYPE, my_pe+NPEX, 0, comm);
+ }
+
+ /* If isubx > 0, send data from left y-line of u (via bufleft) */
+ if (isubx != 0) {
+ for (ly = 0; ly < MYSUB; ly++) {
+ offsetbuf = ly*NVARS;
+ offsetu = ly*dsizex;
+ for (i = 0; i < NVARS; i++)
+ bufleft[offsetbuf+i] = udata[offsetu+i];
+ }
+ MPI_Send(&bufleft[0], dsizey, PVEC_REAL_MPI_TYPE, my_pe-1, 0, comm);
+ }
+
+ /* If isubx < NPEX-1, send data from right y-line of u (via bufright) */
+ if (isubx != NPEX-1) {
+ for (ly = 0; ly < MYSUB; ly++) {
+ offsetbuf = ly*NVARS;
+ offsetu = offsetbuf*MXSUB + (MXSUB-1)*NVARS;
+ for (i = 0; i < NVARS; i++)
+ bufright[offsetbuf+i] = udata[offsetu+i];
+ }
+ MPI_Send(&bufright[0], dsizey, PVEC_REAL_MPI_TYPE, my_pe+1, 0, comm);
+ }
+}
+
+/*
+ * Routine to start receiving boundary data from neighboring PEs.
+ * Notes:
+ * 1) buffer should be able to hold 2*NVARS*MYSUB realtype entries, should be
+ * passed to both the BRecvPost and BRecvWait functions, and should not
+ * be manipulated between the two calls.
+ * 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,
+ long int isubx, long int isuby,
+ long int dsizex, long int dsizey,
+ realtype uext[], realtype buffer[])
+{
+ long int offsetue;
+
+ /* Have bufleft and bufright use the same buffer */
+ realtype *bufleft = buffer, *bufright = buffer+NVARS*MYSUB;
+
+ /* If isuby > 0, receive data for bottom x-line of uext */
+ if (isuby != 0)
+ MPI_Irecv(&uext[NVARS], dsizex, PVEC_REAL_MPI_TYPE,
+ my_pe-NPEX, 0, comm, &request[0]);
+
+ /* If isuby < NPEY-1, receive data for top x-line of uext */
+ if (isuby != NPEY-1) {
+ offsetue = NVARS*(1 + (MYSUB+1)*(MXSUB+2));
+ MPI_Irecv(&uext[offsetue], dsizex, PVEC_REAL_MPI_TYPE,
+ my_pe+NPEX, 0, comm, &request[1]);
+ }
+
+ /* If isubx > 0, receive data for left y-line of uext (via bufleft) */
+ if (isubx != 0) {
+ MPI_Irecv(&bufleft[0], dsizey, PVEC_REAL_MPI_TYPE,
+ my_pe-1, 0, comm, &request[2]);
+ }
+
+ /* If isubx < NPEX-1, receive data for right y-line of uext (via bufright) */
+ if (isubx != NPEX-1) {
+ MPI_Irecv(&bufright[0], dsizey, PVEC_REAL_MPI_TYPE,
+ my_pe+1, 0, comm, &request[3]);
+ }
+}
+
+/*
+ * Routine to finish receiving boundary data from neighboring PEs.
+ * Notes:
+ * 1) buffer should be able to hold 2*NVARS*MYSUB realtype entries, should be
+ * passed to both the BRecvPost and BRecvWait functions, and should not
+ * be manipulated between the two calls.
+ * 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[])
+{
+ int i, ly;
+ long int dsizex2, offsetue, offsetbuf;
+ realtype *bufleft = buffer, *bufright = buffer+NVARS*MYSUB;
+ MPI_Status status;
+
+ dsizex2 = dsizex + 2*NVARS;
+
+ /* If isuby > 0, receive data for bottom x-line of uext */
+ if (isuby != 0)
+ MPI_Wait(&request[0],&status);
+
+ /* If isuby < NPEY-1, receive data for top x-line of uext */
+ if (isuby != NPEY-1)
+ MPI_Wait(&request[1],&status);
+
+ /* If isubx > 0, receive data for left y-line of uext (via bufleft) */
+ if (isubx != 0) {
+ MPI_Wait(&request[2],&status);
+
+ /* Copy the buffer to uext */
+ for (ly = 0; ly < MYSUB; ly++) {
+ offsetbuf = ly*NVARS;
+ offsetue = (ly+1)*dsizex2;
+ for (i = 0; i < NVARS; i++)
+ uext[offsetue+i] = bufleft[offsetbuf+i];
+ }
+ }
+
+ /* If isubx < NPEX-1, receive data for right y-line of uext (via bufright) */
+ if (isubx != NPEX-1) {
+ MPI_Wait(&request[3],&status);
+
+ /* Copy the buffer to uext */
+ for (ly = 0; ly < MYSUB; ly++) {
+ offsetbuf = ly*NVARS;
+ offsetue = (ly+2)*dsizex2 - NVARS;
+ for (i = 0; i < NVARS; i++)
+ uext[offsetue+i] = bufright[offsetbuf+i];
+ }
+ }
+
+}
+
+/*
+ * ucomm routine. This routine performs all communication
+ * between processors of data needed to calculate f.
+ */
+
+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;
+ MPI_Request request[4];
+
+ udata = NV_DATA_P(u);
+
+ /* Get comm, my_pe, subgrid indices, data sizes, extended array uext */
+ comm = data->comm; my_pe = data->my_pe;
+ isubx = data->isubx; isuby = data->isuby;
+ nvmxsub = data->nvmxsub;
+ nvmysub = NVARS*MYSUB;
+ uext = data->uext;
+
+ /* Start receiving boundary data from neighboring PEs */
+ BRecvPost(comm, request, my_pe, isubx, isuby, nvmxsub, nvmysub, uext, buffer);
+
+ /* Send data from boundary of local grid to neighboring PEs */
+ BSend(comm, my_pe, isubx, isuby, nvmxsub, nvmysub, udata);
+
+ /* Finish receiving boundary data from neighboring PEs */
+ BRecvWait(request, isubx, isuby, nvmxsub, uext, buffer);
+}
+
+/*
+ * fcalc routine. Compute f(t,y). This routine assumes that communication
+ * between processors of data needed to calculate f has already been done,
+ * and this data is in the work array uext.
+ */
+
+static void fcalc(realtype t, realtype udata[], realtype dudata[], UserData data)
+{
+ realtype *uext;
+ 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;
+ int i, lx, ly, jx, jy;
+ long int isubx, isuby, nvmxsub, nvmxsub2, offsetu, offsetue;
+ realtype Q1, Q2, C3, A3, A4, KH, VEL, KV0;
+
+ /* Get subgrid indices, data sizes, extended work array uext */
+ isubx = data->isubx; isuby = data->isuby;
+ nvmxsub = data->nvmxsub; nvmxsub2 = data->nvmxsub2;
+ uext = data->uext;
+
+ /* Load problem coefficients and parameters */
+ Q1 = data->p[0];
+ Q2 = data->p[1];
+ C3 = data->p[2];
+ A3 = data->p[3];
+ A4 = data->p[4];
+ KH = data->p[5];
+ VEL = data->p[6];
+ KV0 = data->p[7];
+
+ /* Copy local segment of u vector into the working extended array uext */
+ offsetu = 0;
+ offsetue = nvmxsub2 + NVARS;
+ for (ly = 0; ly < MYSUB; ly++) {
+ for (i = 0; i < nvmxsub; i++) uext[offsetue+i] = udata[offsetu+i];
+ offsetu = offsetu + nvmxsub;
+ offsetue = offsetue + nvmxsub2;
+ }
+
+ /* To facilitate homogeneous Neumann boundary conditions, when this is
+ a boundary PE, copy data from the first interior mesh line of u to uext */
+
+ /* If isuby = 0, copy x-line 2 of u to uext */
+ if (isuby == 0) {
+ for (i = 0; i < nvmxsub; i++) uext[NVARS+i] = udata[nvmxsub+i];
+ }
+
+ /* If isuby = NPEY-1, copy x-line MYSUB-1 of u to uext */
+ if (isuby == NPEY-1) {
+ offsetu = (MYSUB-2)*nvmxsub;
+ offsetue = (MYSUB+1)*nvmxsub2 + NVARS;
+ for (i = 0; i < nvmxsub; i++) uext[offsetue+i] = udata[offsetu+i];
+ }
+
+ /* If isubx = 0, copy y-line 2 of u to uext */
+ if (isubx == 0) {
+ for (ly = 0; ly < MYSUB; ly++) {
+ offsetu = ly*nvmxsub + NVARS;
+ offsetue = (ly+1)*nvmxsub2;
+ for (i = 0; i < NVARS; i++) uext[offsetue+i] = udata[offsetu+i];
+ }
+ }
+
+ /* If isubx = NPEX-1, copy y-line MXSUB-1 of u to uext */
+ if (isubx == NPEX-1) {
+ for (ly = 0; ly < MYSUB; ly++) {
+ offsetu = (ly+1)*nvmxsub - 2*NVARS;
+ offsetue = (ly+2)*nvmxsub2 - NVARS;
+ for (i = 0; i < NVARS; i++) uext[offsetue+i] = udata[offsetu+i];
+ }
+ }
+
+ /* Make local copies of problem variables, for efficiency */
+ dely = data->dy;
+ verdco = data->vdco;
+ hordco = data->hdco;
+ horaco = data->haco;
+
+ /* Set diurnal rate coefficients as functions of t, and save q4 in
+ data block for use by preconditioner evaluation routine */
+ s = sin((data->om)*t);
+ if (s > ZERO) {
+ q3 = EXP(-A3/s);
+ q4coef = EXP(-A4/s);
+ } else {
+ q3 = ZERO;
+ q4coef = ZERO;
+ }
+ data->q4 = q4coef;
+
+ /* Loop over all grid points in local subgrid */
+ for (ly = 0; ly < MYSUB; ly++) {
+ jy = ly + isuby*MYSUB;
+
+ /* Set vertical diffusion coefficients at jy +- 1/2 */
+ ydn = YMIN + (jy - .5)*dely;
+ yup = ydn + dely;
+ cydn = verdco*EXP(RCONST(0.2)*ydn);
+ cyup = verdco*EXP(RCONST(0.2)*yup);
+ for (lx = 0; lx < MXSUB; lx++) {
+ jx = lx + isubx*MXSUB;
+
+ /* Extract c1 and c2, and set kinetic rate terms */
+ offsetue = (lx+1)*NVARS + (ly+1)*nvmxsub2;
+ c1 = uext[offsetue];
+ c2 = uext[offsetue+1];
+ qq1 = Q1*c1*C3;
+ qq2 = Q2*c1*c2;
+ qq3 = q3*C3;
+ qq4 = q4coef*c2;
+ rkin1 = -qq1 - qq2 + RCONST(2.0)*qq3 + qq4;
+ rkin2 = qq1 - qq2 - qq4;
+
+ /* Set vertical diffusion terms */
+ c1dn = uext[offsetue-nvmxsub2];
+ c2dn = uext[offsetue-nvmxsub2+1];
+ c1up = uext[offsetue+nvmxsub2];
+ c2up = uext[offsetue+nvmxsub2+1];
+ vertd1 = cyup*(c1up - c1) - cydn*(c1 - c1dn);
+ vertd2 = cyup*(c2up - c2) - cydn*(c2 - c2dn);
+
+ /* Set horizontal diffusion and advection terms */
+ c1lt = uext[offsetue-2];
+ c2lt = uext[offsetue-1];
+ c1rt = uext[offsetue+2];
+ c2rt = uext[offsetue+3];
+ hord1 = hordco*(c1rt - 2.0*c1 + c1lt);
+ hord2 = hordco*(c2rt - 2.0*c2 + c2lt);
+ horad1 = horaco*(c1rt - c1lt);
+ horad2 = horaco*(c2rt - c2lt);
+
+ /* Load all terms into dudata */
+ offsetu = lx*NVARS + ly*nvmxsub;
+ dudata[offsetu] = vertd1 + hord1 + horad1 + rkin1;
+ dudata[offsetu+1] = vertd2 + hord2 + horad2 + rkin2;
+ }
+ }
+
+}
+
+/*
+ * Print current t, step count, order, stepsize, and sampled c1,c2 values.
+ */
+
+static void PrintOutput(void *cvode_mem, int my_pe, MPI_Comm comm,
+ realtype t, N_Vector u)
+{
+ long int nst;
+ int qu, flag;
+ realtype hu, *udata, tempu[2];
+ long int npelast, i0, i1;
+ MPI_Status status;
+
+ npelast = NPEX*NPEY - 1;
+ udata = NV_DATA_P(u);
+
+ /* Send c at top right mesh point to PE 0 */
+ if (my_pe == npelast) {
+ i0 = NVARS*MXSUB*MYSUB - 2;
+ i1 = i0 + 1;
+ if (npelast != 0)
+ MPI_Send(&udata[i0], 2, PVEC_REAL_MPI_TYPE, 0, 0, comm);
+ else {
+ tempu[0] = udata[i0];
+ tempu[1] = udata[i1];
+ }
+ }
+
+ /* On PE 0, receive c at top right, then print performance data
+ and sampled solution values */
+ if (my_pe == 0) {
+
+ if (npelast != 0)
+ MPI_Recv(&tempu[0], 2, PVEC_REAL_MPI_TYPE, npelast, 0, comm, &status);
+
+ flag = CVodeGetNumSteps(cvode_mem, &nst);
+ check_flag(&flag, "CVodeGetNumSteps", 1, my_pe);
+ flag = CVodeGetLastOrder(cvode_mem, &qu);
+ check_flag(&flag, "CVodeGetLastOrder", 1, my_pe);
+ flag = CVodeGetLastStep(cvode_mem, &hu);
+ check_flag(&flag, "CVodeGetLastStep", 1, my_pe);
+
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("%8.3Le %2d %8.3Le %5ld\n", t,qu,hu,nst);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("%8.3le %2d %8.3le %5ld\n", t,qu,hu,nst);
+#else
+ printf("%8.3e %2d %8.3e %5ld\n", t,qu,hu,nst);
+#endif
+
+ printf(" Solution ");
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("%12.4Le %12.4Le \n", udata[0], tempu[0]);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("%12.4le %12.4le \n", udata[0], tempu[0]);
+#else
+ printf("%12.4e %12.4e \n", udata[0], tempu[0]);
+#endif
+
+ printf(" ");
+
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("%12.4Le %12.4Le \n", udata[1], tempu[1]);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("%12.4le %12.4le \n", udata[1], tempu[1]);
+#else
+ printf("%12.4e %12.4e \n", udata[1], tempu[1]);
+#endif
+
+ }
+
+}
+
+/*
+ * Print sampled sensitivity values.
+ */
+
+static void PrintOutputS(int my_pe, MPI_Comm comm, N_Vector *uS)
+{
+ realtype *sdata, temps[2];
+ long int npelast, i0, i1;
+ MPI_Status status;
+
+ npelast = NPEX*NPEY - 1;
+
+ sdata = NV_DATA_P(uS[0]);
+
+ /* Send s1 at top right mesh point to PE 0 */
+ if (my_pe == npelast) {
+ i0 = NVARS*MXSUB*MYSUB - 2;
+ i1 = i0 + 1;
+ if (npelast != 0)
+ MPI_Send(&sdata[i0], 2, PVEC_REAL_MPI_TYPE, 0, 0, comm);
+ else {
+ temps[0] = sdata[i0];
+ temps[1] = sdata[i1];
+ }
+ }
+
+ /* On PE 0, receive s1 at top right, then print sampled sensitivity values */
+ if (my_pe == 0) {
+ if (npelast != 0)
+ MPI_Recv(&temps[0], 2, PVEC_REAL_MPI_TYPE, npelast, 0, comm, &status);
+ printf(" ----------------------------------------\n");
+ printf(" Sensitivity 1 ");
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("%12.4Le %12.4Le \n", sdata[0], temps[0]);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("%12.4le %12.4le \n", sdata[0], temps[0]);
+#else
+ printf("%12.4e %12.4e \n", sdata[0], temps[0]);
+#endif
+ printf(" ");
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("%12.4Le %12.4Le \n", sdata[1], temps[1]);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("%12.4le %12.4le \n", sdata[1], temps[1]);
+#else
+ printf("%12.4e %12.4e \n", sdata[1], temps[1]);
+#endif
+ }
+
+ sdata = NV_DATA_P(uS[1]);
+
+ /* Send s2 at top right mesh point to PE 0 */
+ if (my_pe == npelast) {
+ i0 = NVARS*MXSUB*MYSUB - 2;
+ i1 = i0 + 1;
+ if (npelast != 0)
+ MPI_Send(&sdata[i0], 2, PVEC_REAL_MPI_TYPE, 0, 0, comm);
+ else {
+ temps[0] = sdata[i0];
+ temps[1] = sdata[i1];
+ }
+ }
+
+ /* On PE 0, receive s2 at top right, then print sampled sensitivity values */
+ if (my_pe == 0) {
+ if (npelast != 0)
+ MPI_Recv(&temps[0], 2, PVEC_REAL_MPI_TYPE, npelast, 0, comm, &status);
+ printf(" ----------------------------------------\n");
+ printf(" Sensitivity 2 ");
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("%12.4Le %12.4Le \n", sdata[0], temps[0]);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("%12.4le %12.4le \n", sdata[0], temps[0]);
+#else
+ printf("%12.4e %12.4e \n", sdata[0], temps[0]);
+#endif
+ printf(" ");
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("%12.4Le %12.4Le \n", sdata[1], temps[1]);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("%12.4le %12.4le \n", sdata[1], temps[1]);
+#else
+ printf("%12.4e %12.4e \n", sdata[1], temps[1]);
+#endif
+ }
+}
+
+/*
+ * Print final statistics from the CVODES memory.
+ */
+
+static void PrintFinalStats(void *cvode_mem, booleantype sensi)
+{
+ long int nst;
+ long int nfe, nsetups, nni, ncfn, netf;
+ long int nfSe, nfeS, nsetupsS, nniS, ncfnS, netfS;
+ int flag;
+
+ flag = CVodeGetNumSteps(cvode_mem, &nst);
+ check_flag(&flag, "CVodeGetNumSteps", 1, 0);
+ flag = CVodeGetNumRhsEvals(cvode_mem, &nfe);
+ check_flag(&flag, "CVodeGetNumRhsEvals", 1, 0);
+ flag = CVodeGetNumLinSolvSetups(cvode_mem, &nsetups);
+ check_flag(&flag, "CVodeGetNumLinSolvSetups", 1, 0);
+ flag = CVodeGetNumErrTestFails(cvode_mem, &netf);
+ check_flag(&flag, "CVodeGetNumErrTestFails", 1, 0);
+ flag = CVodeGetNumNonlinSolvIters(cvode_mem, &nni);
+ check_flag(&flag, "CVodeGetNumNonlinSolvIters", 1, 0);
+ flag = CVodeGetNumNonlinSolvConvFails(cvode_mem, &ncfn);
+ check_flag(&flag, "CVodeGetNumNonlinSolvConvFails", 1, 0);
+
+ if (sensi) {
+ flag = CVodeGetSensNumRhsEvals(cvode_mem, &nfSe);
+ check_flag(&flag, "CVodeGetSensNumRhsEvals", 1, 0);
+ flag = CVodeGetNumRhsEvalsSens(cvode_mem, &nfeS);
+ check_flag(&flag, "CVodeGetNumRhsEvalsSens", 1, 0);
+ flag = CVodeGetSensNumLinSolvSetups(cvode_mem, &nsetupsS);
+ check_flag(&flag, "CVodeGetSensNumLinSolvSetups", 1, 0);
+ flag = CVodeGetSensNumErrTestFails(cvode_mem, &netfS);
+ check_flag(&flag, "CVodeGetSensNumErrTestFails", 1, 0);
+ flag = CVodeGetSensNumNonlinSolvIters(cvode_mem, &nniS);
+ check_flag(&flag, "CVodeGetSensNumNonlinSolvIters", 1, 0);
+ flag = CVodeGetSensNumNonlinSolvConvFails(cvode_mem, &ncfnS);
+ check_flag(&flag, "CVodeGetSensNumNonlinSolvConvFails", 1, 0);
+ }
+
+ printf("\nFinal Statistics\n\n");
+ printf("nst = %5ld\n\n", nst);
+ printf("nfe = %5ld\n", nfe);
+ printf("netf = %5ld nsetups = %5ld\n", netf, nsetups);
+ printf("nni = %5ld ncfn = %5ld\n", nni, ncfn);
+
+ if(sensi) {
+ printf("\n");
+ printf("nfSe = %5ld nfeS = %5ld\n", nfSe, nfeS);
+ printf("netfs = %5ld nsetupsS = %5ld\n", netfS, nsetupsS);
+ printf("nniS = %5ld ncfnS = %5ld\n", nniS, ncfnS);
+ }
+
+}
+
+/*
+ * 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, char *funcname, int opt, int id)
+{
+ int *errflag;
+
+ /* Check if SUNDIALS function returned NULL pointer - no memory allocated */
+ if (opt == 0 && flagvalue == NULL) {
+ fprintf(stderr,
+ "\nSUNDIALS_ERROR(%d): %s() failed - returned NULL pointer\n\n",
+ id, funcname);
+ return(1); }
+
+ /* Check if flag < 0 */
+ else if (opt == 1) {
+ errflag = (int *) flagvalue;
+ if (*errflag < 0) {
+ fprintf(stderr,
+ "\nSUNDIALS_ERROR(%d): %s() failed with flag = %d\n\n",
+ id, funcname, *errflag);
+ return(1); }}
+
+ /* Check if function returned NULL pointer - no memory allocated */
+ else if (opt == 2 && flagvalue == NULL) {
+ fprintf(stderr,
+ "\nMEMORY_ERROR(%d): %s() failed - returned NULL pointer\n\n",
+ id, funcname);
+ return(1); }
+
+ return(0);
+}
diff --git a/examples/cvodes/parallel/cvsDiurnal_FSA_kry_p.out b/examples/cvodes/parallel/cvsDiurnal_FSA_kry_p.out
new file mode 100644
index 0000000..6febb99
--- /dev/null
+++ b/examples/cvodes/parallel/cvsDiurnal_FSA_kry_p.out
@@ -0,0 +1,139 @@
+
+2-species diurnal advection-diffusion problem
+Sensitivity: YES ( SIMULTANEOUS + FULL ERROR CONTROL )
+
+========================================================================
+ T Q H NST Bottom left Top right
+========================================================================
+7.200e+03 3 3.544e+01 415
+ 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
+ ----------------------------------------
+ Sensitivity 2 -4.3853e+14 -5.0065e+14
+ -2.4407e+18 -2.7842e+18
+------------------------------------------------------------------------
+1.440e+04 3 4.903e+01 640
+ 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
+ ----------------------------------------
+ Sensitivity 2 -4.5235e+17 -5.4318e+17
+ -6.5419e+21 -7.8316e+21
+------------------------------------------------------------------------
+2.160e+04 2 2.948e+01 1198
+ Solution 2.6650e+07 2.9308e+07
+ 2.9928e+11 3.3134e+11
+ ----------------------------------------
+ Sensitivity 1 -1.6346e+23 -1.7976e+23
+ 3.8203e+23 4.4991e+23
+ ----------------------------------------
+ Sensitivity 2 -7.6601e+18 -9.4433e+18
+ -7.6459e+22 -9.4502e+22
+------------------------------------------------------------------------
+2.880e+04 3 4.499e+01 1542
+ Solution 8.7021e+06 9.6501e+06
+ 3.3804e+11 3.7510e+11
+ ----------------------------------------
+ Sensitivity 1 -5.3375e+22 -5.9188e+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
+ Solution 1.4040e+04 1.5609e+04
+ 3.3868e+11 3.7652e+11
+ ----------------------------------------
+ Sensitivity 1 -8.6141e+19 -9.5761e+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
+ 3.3823e+11 3.8035e+11
+ ----------------------------------------
+ Sensitivity 1 -3.4238e+08 -3.8876e+08
+ 5.2753e+23 6.7448e+23
+ ----------------------------------------
+ Sensitivity 2 5.4404e+03 6.6262e+03
+ -1.8454e+23 -2.3595e+23
+------------------------------------------------------------------------
+5.040e+04 4 2.431e+02 3194
+ Solution 8.0708e-08 7.0502e-08
+ 3.3582e+11 3.8645e+11
+ ----------------------------------------
+ Sensitivity 1 -4.5550e+10 -3.9697e+10
+ 5.2067e+23 6.9664e+23
+ ----------------------------------------
+ Sensitivity 2 -5.5727e+08 -5.5845e+08
+ -1.8214e+23 -2.4371e+23
+------------------------------------------------------------------------
+5.760e+04 4 2.523e+02 3216
+ Solution -1.8957e-11 -1.6762e-11
+ 3.3203e+11 3.9090e+11
+ ----------------------------------------
+ Sensitivity 1 -1.5940e+06 -1.4035e+06
+ 5.0825e+23 7.1205e+23
+ ----------------------------------------
+ Sensitivity 2 -2.2867e+02 -2.2722e+02
+ -1.7780e+23 -2.4910e+23
+------------------------------------------------------------------------
+6.480e+04 4 2.820e+02 3254
+ Solution -7.8717e-10 -6.7017e-10
+ 3.3130e+11 3.9634e+11
+ ----------------------------------------
+ Sensitivity 1 -3.4373e+07 -2.1671e+07
+ 5.0442e+23 7.3274e+23
+ ----------------------------------------
+ Sensitivity 2 1.3198e+08 1.3575e+08
+ -1.7646e+23 -2.5633e+23
+------------------------------------------------------------------------
+7.200e+04 4 3.810e+02 3276
+ Solution -4.4006e-09 -3.7463e-09
+ 3.3297e+11 4.0389e+11
+ ----------------------------------------
+ Sensitivity 1 4.5106e+09 3.8200e+09
+ 5.0783e+23 7.6382e+23
+ ----------------------------------------
+ Sensitivity 2 2.0264e+05 2.0791e+05
+ -1.7765e+23 -2.6721e+23
+------------------------------------------------------------------------
+7.920e+04 5 6.406e+02 3291
+ Solution -1.8328e-11 -1.5666e-11
+ 3.3344e+11 4.1203e+11
+ ----------------------------------------
+ Sensitivity 1 1.3650e+07 1.1729e+07
+ 5.0730e+23 7.9960e+23
+ ----------------------------------------
+ Sensitivity 2 6.1764e+01 6.8476e+01
+ -1.7747e+23 -2.7972e+23
+------------------------------------------------------------------------
+8.640e+04 5 6.406e+02 3302
+ Solution -2.0206e-13 -1.7557e-13
+ 3.3518e+11 4.1625e+11
+ ----------------------------------------
+ Sensitivity 1 1.1323e+06 9.7319e+05
+ 5.1171e+23 8.2142e+23
+ ----------------------------------------
+ Sensitivity 2 7.6632e+00 8.2818e+00
+ -1.7901e+23 -2.8736e+23
+------------------------------------------------------------------------
+
+Final Statistics
+
+nst = 3302
+
+nfe = 4387
+netf = 165 nsetups = 508
+nni = 4383 ncfn = 7
+
+nfSe = 8774 nfeS = 17548
+netfs = 0 nsetupsS = 0
+nniS = 0 ncfnS = 0
diff --git a/examples/cvodes/parallel/cvsDiurnal_kry_bbd_p.c b/examples/cvodes/parallel/cvsDiurnal_kry_bbd_p.c
new file mode 100644
index 0000000..93be293
--- /dev/null
+++ b/examples/cvodes/parallel/cvsDiurnal_kry_bbd_p.c
@@ -0,0 +1,891 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.3 $
+ * $Date: 2010/12/14 22:15:31 $
+ * -----------------------------------------------------------------
+ * Programmer(s): S. D. Cohen, A. C. Hindmarsh, M. R. Wittman, and
+ * Radu Serban @ LLNL
+ * --------------------------------------------------------------------
+ * Example problem:
+ *
+ * An ODE system is generated from the following 2-species diurnal
+ * kinetics advection-diffusion PDE system in 2 space dimensions:
+ *
+ * dc(i)/dt = Kh*(d/dx)^2 c(i) + V*dc(i)/dx + (d/dy)(Kv(y)*dc(i)/dy)
+ * + Ri(c1,c2,t) for i = 1,2, where
+ * R1(c1,c2,t) = -q1*c1*c3 - q2*c1*c2 + 2*q3(t)*c3 + q4(t)*c2 ,
+ * R2(c1,c2,t) = q1*c1*c3 - q2*c1*c2 - q4(t)*c2 ,
+ * Kv(y) = Kv0*exp(y/5) ,
+ * Kh, V, Kv0, q1, q2, and c3 are constants, and q3(t) and q4(t)
+ * vary diurnally. The problem is posed on the square
+ * 0 <= x <= 20, 30 <= y <= 50 (all in km),
+ * with homogeneous Neumann boundary conditions, and for time t in
+ * 0 <= t <= 86400 sec (1 day).
+ * The PDE system is treated by central differences on a uniform
+ * mesh, with simple polynomial initial profiles.
+ *
+ * The problem is solved by CVODES on NPE processors, treated
+ * as a rectangular process grid of size NPEX by NPEY, with
+ * NPE = NPEX*NPEY. Each processor contains a subgrid of size MXSUB
+ * by MYSUB of the (x,y) mesh. Thus the actual mesh sizes are
+ * MX = MXSUB*NPEX and MY = MYSUB*NPEY, and the ODE system size is
+ * 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
+ * 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
+ * blocks have half-bandwidths mukeep = mlkeep = 2.
+ * A copy of the approximate Jacobian is saved and conditionally
+ * reused within the preconditioner routine.
+ *
+ * The problem is solved twice -- with left and right preconditioning.
+ *
+ * Performance data and sampled solution values are printed at
+ * selected output times, and all performance counters are printed
+ * on completion.
+ *
+ * This version uses MPI for user routines.
+ * Execute with number of processors = NPEX*NPEY (see constants below).
+ * --------------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#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 SQR and EXP */
+
+#include <mpi.h> /* MPI constants and types */
+
+
+/* Problem Constants */
+
+#define ZERO RCONST(0.0)
+
+#define NVARS 2 /* number of species */
+#define KH RCONST(4.0e-6) /* horizontal diffusivity Kh */
+#define VEL RCONST(0.001) /* advection velocity V */
+#define KV0 RCONST(1.0e-8) /* coefficient in Kv(y) */
+#define Q1 RCONST(1.63e-16) /* coefficients q1, q2, c3 */
+#define Q2 RCONST(4.66e-16)
+#define C3 RCONST(3.7e16)
+#define A3 RCONST(22.62) /* coefficient in expression for q3(t) */
+#define A4 RCONST(7.601) /* coefficient in expression for q4(t) */
+#define C1_SCALE RCONST(1.0e6) /* coefficients in initial profiles */
+#define C2_SCALE RCONST(1.0e12)
+
+#define T0 ZERO /* initial time */
+#define NOUT 12 /* number of output times */
+#define TWOHR RCONST(7200.0) /* number of seconds in two hours */
+#define HALFDAY RCONST(4.32e4) /* number of seconds in a half day */
+#define PI RCONST(3.1415926535898) /* pi */
+
+#define XMIN ZERO /* grid boundaries in x */
+#define XMAX RCONST(20.0)
+#define YMIN RCONST(30.0) /* grid boundaries in y */
+#define YMAX RCONST(50.0)
+
+#define NPEX 2 /* no. PEs in x direction of PE array */
+#define NPEY 2 /* no. PEs in y direction of PE array */
+ /* Total no. PEs = NPEX*NPEY */
+#define MXSUB 5 /* no. x points per subgrid */
+#define MYSUB 5 /* no. y points per subgrid */
+
+#define MX (NPEX*MXSUB) /* MX = number of x mesh points */
+#define MY (NPEY*MYSUB) /* MY = number of y mesh points */
+ /* Spatial mesh is MX by MY */
+/* CVodeInit Constants */
+
+#define RTOL RCONST(1.0e-5) /* scalar relative tolerance */
+#define FLOOR RCONST(100.0) /* value of C1 or C2 at which tolerances */
+ /* change from relative to absolute */
+#define ATOL (RTOL*FLOOR) /* scalar absolute tolerance */
+
+/* Type : UserData
+ contains problem constants, extended dependent variable array,
+ grid constants, processor indices, MPI communicator */
+
+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;
+ MPI_Comm comm;
+} *UserData;
+
+/* Prototypes of private helper functions */
+
+static void InitUserData(int my_pe, long int 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 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,
+ realtype uarray[]);
+static void BRecvPost(MPI_Comm comm, MPI_Request request[],
+ int my_pe, int isubx, int isuby,
+ long int dsizex, long int dsizey,
+ realtype uext[], realtype buffer[]);
+static void BRecvWait(MPI_Request request[],
+ int isubx, int isuby,
+ long int dsizex, realtype uext[],
+ realtype buffer[]);
+
+static void fucomm(realtype t, N_Vector u, void *user_data);
+
+/* Prototype of function called by the solver */
+
+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,
+ N_Vector udot, void *user_data);
+
+/* Private function to check function return values */
+
+static int check_flag(void *flagvalue, char *funcname, int opt, int id);
+
+/***************************** Main Program ******************************/
+
+int main(int argc, char *argv[])
+{
+ UserData data;
+ 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;
+ MPI_Comm comm;
+
+ data = NULL;
+ cvode_mem = NULL;
+ u = 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;
+ MPI_Comm_size(comm, &npes);
+ MPI_Comm_rank(comm, &my_pe);
+
+ if (npes != NPEX*NPEY) {
+ if (my_pe == 0)
+ fprintf(stderr, "\nMPI_ERROR(0): npes = %d is not equal to NPEX*NPEY = %d\n\n",
+ npes, NPEX*NPEY);
+ MPI_Finalize();
+ return(1);
+ }
+
+ /* Set local length */
+ local_N = NVARS*MXSUB*MYSUB;
+
+ /* Allocate and load user data block */
+ data = (UserData) malloc(sizeof *data);
+ if(check_flag((void *)data, "malloc", 2, my_pe)) MPI_Abort(comm, 1);
+ InitUserData(my_pe, local_N, comm, data);
+
+ /* Allocate and initialize u, and set tolerances */
+ u = N_VNew_Parallel(comm, local_N, neq);
+ if(check_flag((void *)u, "N_VNew_Parallel", 0, my_pe)) MPI_Abort(comm, 1);
+ SetInitialProfiles(u, data);
+ abstol = ATOL;
+ reltol = RTOL;
+
+ /* 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, my_pe)) MPI_Abort(comm, 1);
+
+ /* Set the pointer to user-defined data */
+ flag = CVodeSetUserData(cvode_mem, data);
+ if(check_flag(&flag, "CVodeSetUserData", 1, my_pe)) MPI_Abort(comm, 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
+ * the initial dependent variable vector u. */
+ flag = CVodeInit(cvode_mem, f, T0, u);
+ if(check_flag(&flag, "CVodeInit", 1, my_pe)) return(1);
+
+ /* Call CVodeSStolerances to specify the scalar relative tolerance
+ * and scalar absolute tolerances */
+ 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);
+
+ /* 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);
+
+ /* Print heading */
+ if (my_pe == 0) PrintIntro(npes, mudq, mldq, mukeep, mlkeep);
+
+ /* 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 */
+
+ if (jpre == PREC_RIGHT) {
+
+ SetInitialProfiles(u, data);
+
+ flag = CVodeReInit(cvode_mem, T0, u);
+ if(check_flag(&flag, "CVodeReInit", 1, my_pe)) MPI_Abort(comm, 1);
+
+ 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);
+
+ if (my_pe == 0) {
+ printf("\n\n-------------------------------------------------------");
+ printf("------------\n");
+ }
+
+ }
+
+
+ if (my_pe == 0) {
+ printf("\n\nPreconditioner type is: jpre = %s\n\n",
+ (jpre == PREC_LEFT) ? "PREC_LEFT" : "PREC_RIGHT");
+ }
+
+ /* In loop over output points, call CVode, print results, test for error */
+
+ for (iout = 1, tout = TWOHR; iout <= NOUT; iout++, tout += TWOHR) {
+ flag = CVode(cvode_mem, tout, u, &t, CV_NORMAL);
+ if(check_flag(&flag, "CVode", 1, my_pe)) break;
+ PrintOutput(cvode_mem, my_pe, comm, u, t);
+ }
+
+ /* Print final statistics */
+
+ if (my_pe == 0) PrintFinalStats(cvode_mem);
+
+ } /* End of jpre loop */
+
+ /* Free memory */
+ N_VDestroy_Parallel(u);
+ free(data);
+ CVodeFree(&cvode_mem);
+
+ MPI_Finalize();
+
+ return(0);
+}
+
+/*********************** Private Helper Functions ************************/
+
+/* Load constants in data */
+
+static void InitUserData(int my_pe, long int local_N, MPI_Comm comm,
+ UserData data)
+{
+ int isubx, isuby;
+
+ /* Set problem constants */
+ data->om = PI/HALFDAY;
+ data->dx = (XMAX-XMIN)/((realtype)(MX-1));
+ data->dy = (YMAX-YMIN)/((realtype)(MY-1));
+ data->hdco = KH/SQR(data->dx);
+ data->haco = VEL/(RCONST(2.0)*data->dx);
+ data->vdco = (RCONST(1.0)/SQR(data->dy))*KV0;
+
+ /* Set machine-related constants */
+ data->comm = comm;
+ data->my_pe = my_pe;
+ data->Nlocal = local_N;
+ /* isubx and isuby are the PE grid indices corresponding to my_pe */
+ isuby = my_pe/NPEX;
+ isubx = my_pe - isuby*NPEX;
+ data->isubx = isubx;
+ data->isuby = isuby;
+ /* Set the sizes of a boundary x-line in u and uext */
+ data->nvmxsub = NVARS*MXSUB;
+ data->nvmxsub2 = NVARS*(MXSUB+2);
+}
+
+/* Set initial conditions in u */
+
+static void SetInitialProfiles(N_Vector u, UserData data)
+{
+ int isubx, isuby;
+ int lx, ly, jx, jy;
+ long int offset;
+ realtype dx, dy, x, y, cx, cy, xmid, ymid;
+ realtype *uarray;
+
+ /* Set pointer to data array in vector u */
+
+ uarray = NV_DATA_P(u);
+
+ /* Get mesh spacings, and subgrid indices for this PE */
+
+ dx = data->dx; dy = data->dy;
+ isubx = data->isubx; isuby = data->isuby;
+
+ /* Load initial profiles of c1 and c2 into local u vector.
+ Here lx and ly are local mesh point indices on the local subgrid,
+ and jx and jy are the global mesh point indices. */
+
+ offset = 0;
+ xmid = RCONST(0.5)*(XMIN + XMAX);
+ ymid = RCONST(0.5)*(YMIN + YMAX);
+ for (ly = 0; ly < MYSUB; ly++) {
+ jy = ly + isuby*MYSUB;
+ y = YMIN + jy*dy;
+ cy = SQR(RCONST(0.1)*(y - ymid));
+ cy = RCONST(1.0) - cy + RCONST(0.5)*SQR(cy);
+ for (lx = 0; lx < MXSUB; lx++) {
+ jx = lx + isubx*MXSUB;
+ x = XMIN + jx*dx;
+ cx = SQR(RCONST(0.1)*(x - xmid));
+ cx = RCONST(1.0) - cx + RCONST(0.5)*SQR(cx);
+ uarray[offset ] = C1_SCALE*cx*cy;
+ uarray[offset+1] = C2_SCALE*cx*cy;
+ offset = offset + 2;
+ }
+ }
+}
+
+/* Print problem introduction */
+
+static void PrintIntro(int npes, long int mudq, long int mldq,
+ long int mukeep, long int 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(" Retained band block half-bandwidths are");
+ printf(" mukeep = %ld, mlkeep = %ld", mukeep, mlkeep);
+
+ return;
+}
+
+/* Print current t, step count, order, stepsize, and sampled c1,c2 values */
+
+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;
+ realtype hu, *uarray, tempu[2];
+ MPI_Status status;
+
+ npelast = NPEX*NPEY - 1;
+ uarray = NV_DATA_P(u);
+
+ /* Send c1,c2 at top right mesh point to PE 0 */
+ if (my_pe == npelast) {
+ i0 = NVARS*MXSUB*MYSUB - 2;
+ i1 = i0 + 1;
+ if (npelast != 0)
+ MPI_Send(&uarray[i0], 2, PVEC_REAL_MPI_TYPE, 0, 0, comm);
+ else {
+ tempu[0] = uarray[i0];
+ tempu[1] = uarray[i1];
+ }
+ }
+
+ /* On PE 0, receive c1,c2 at top right, then print performance data
+ and sampled solution values */
+ if (my_pe == 0) {
+ if (npelast != 0)
+ MPI_Recv(&tempu[0], 2, PVEC_REAL_MPI_TYPE, npelast, 0, comm, &status);
+ flag = CVodeGetNumSteps(cvode_mem, &nst);
+ check_flag(&flag, "CVodeGetNumSteps", 1, my_pe);
+ flag = CVodeGetLastOrder(cvode_mem, &qu);
+ check_flag(&flag, "CVodeGetLastOrder", 1, my_pe);
+ flag = CVodeGetLastStep(cvode_mem, &hu);
+ check_flag(&flag, "CVodeGetLastStep", 1, my_pe);
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("t = %.2Le no. steps = %ld order = %d stepsize = %.2Le\n",
+ t, nst, qu, hu);
+ printf("At bottom left: c1, c2 = %12.3Le %12.3Le \n", uarray[0], uarray[1]);
+ printf("At top right: c1, c2 = %12.3Le %12.3Le \n\n", tempu[0], tempu[1]);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("t = %.2le no. steps = %ld order = %d stepsize = %.2le\n",
+ t, nst, qu, hu);
+ printf("At bottom left: c1, c2 = %12.3le %12.3le \n", uarray[0], uarray[1]);
+ printf("At top right: c1, c2 = %12.3le %12.3le \n\n", tempu[0], tempu[1]);
+#else
+ printf("t = %.2e no. steps = %ld order = %d stepsize = %.2e\n",
+ t, nst, qu, hu);
+ printf("At bottom left: c1, c2 = %12.3e %12.3e \n", uarray[0], uarray[1]);
+ printf("At top right: c1, c2 = %12.3e %12.3e \n\n", tempu[0], tempu[1]);
+#endif
+ }
+}
+
+/* Print final statistics contained in iopt */
+
+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 nli, npe, nps, ncfl, nfeLS;
+ int flag;
+
+ flag = CVodeGetWorkSpace(cvode_mem, &lenrw, &leniw);
+ check_flag(&flag, "CVodeGetWorkSpace", 1, 0);
+ flag = CVodeGetNumSteps(cvode_mem, &nst);
+ check_flag(&flag, "CVodeGetNumSteps", 1, 0);
+ flag = CVodeGetNumRhsEvals(cvode_mem, &nfe);
+ check_flag(&flag, "CVodeGetNumRhsEvals", 1, 0);
+ flag = CVodeGetNumLinSolvSetups(cvode_mem, &nsetups);
+ check_flag(&flag, "CVodeGetNumLinSolvSetups", 1, 0);
+ flag = CVodeGetNumErrTestFails(cvode_mem, &netf);
+ check_flag(&flag, "CVodeGetNumErrTestFails", 1, 0);
+ flag = CVodeGetNumNonlinSolvIters(cvode_mem, &nni);
+ check_flag(&flag, "CVodeGetNumNonlinSolvIters", 1, 0);
+ flag = CVodeGetNumNonlinSolvConvFails(cvode_mem, &ncfn);
+ check_flag(&flag, "CVodeGetNumNonlinSolvConvFails", 1, 0);
+
+ flag = CVSpilsGetWorkSpace(cvode_mem, &lenrwLS, &leniwLS);
+ check_flag(&flag, "CVSpilsGetWorkSpace", 1, 0);
+ flag = CVSpilsGetNumLinIters(cvode_mem, &nli);
+ check_flag(&flag, "CVSpilsGetNumLinIters", 1, 0);
+ flag = CVSpilsGetNumPrecEvals(cvode_mem, &npe);
+ check_flag(&flag, "CVSpilsGetNumPrecEvals", 1, 0);
+ flag = CVSpilsGetNumPrecSolves(cvode_mem, &nps);
+ check_flag(&flag, "CVSpilsGetNumPrecSolves", 1, 0);
+ flag = CVSpilsGetNumConvFails(cvode_mem, &ncfl);
+ check_flag(&flag, "CVSpilsGetNumConvFails", 1, 0);
+ flag = CVSpilsGetNumRhsEvals(cvode_mem, &nfeLS);
+ 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("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);
+
+ flag = CVBBDPrecGetWorkSpace(cvode_mem, &lenrwBBDP, &leniwBBDP);
+ check_flag(&flag, "CVBBDPrecGetWorkSpace", 1, 0);
+ 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);
+ 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,
+ realtype uarray[])
+{
+ int i, ly;
+ long int offsetu, offsetbuf;
+ realtype bufleft[NVARS*MYSUB], bufright[NVARS*MYSUB];
+
+ /* If isuby > 0, send data from bottom x-line of u */
+
+ if (isuby != 0)
+ MPI_Send(&uarray[0], dsizex, PVEC_REAL_MPI_TYPE, my_pe-NPEX, 0, comm);
+
+ /* If isuby < NPEY-1, send data from top x-line of u */
+
+ if (isuby != NPEY-1) {
+ offsetu = (MYSUB-1)*dsizex;
+ MPI_Send(&uarray[offsetu], dsizex, PVEC_REAL_MPI_TYPE, my_pe+NPEX, 0, comm);
+ }
+
+ /* If isubx > 0, send data from left y-line of u (via bufleft) */
+
+ if (isubx != 0) {
+ for (ly = 0; ly < MYSUB; ly++) {
+ offsetbuf = ly*NVARS;
+ offsetu = ly*dsizex;
+ for (i = 0; i < NVARS; i++)
+ bufleft[offsetbuf+i] = uarray[offsetu+i];
+ }
+ MPI_Send(&bufleft[0], dsizey, PVEC_REAL_MPI_TYPE, my_pe-1, 0, comm);
+ }
+
+ /* If isubx < NPEX-1, send data from right y-line of u (via bufright) */
+
+ if (isubx != NPEX-1) {
+ for (ly = 0; ly < MYSUB; ly++) {
+ offsetbuf = ly*NVARS;
+ offsetu = offsetbuf*MXSUB + (MXSUB-1)*NVARS;
+ for (i = 0; i < NVARS; i++)
+ bufright[offsetbuf+i] = uarray[offsetu+i];
+ }
+ MPI_Send(&bufright[0], dsizey, PVEC_REAL_MPI_TYPE, my_pe+1, 0, comm);
+ }
+
+}
+
+/* Routine to start receiving boundary data from neighboring PEs.
+ Notes:
+ 1) buffer should be able to hold 2*NVARS*MYSUB realtype entries, should be
+ passed to both the BRecvPost and BRecvWait functions, and should not
+ be manipulated between the two calls.
+ 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,
+ realtype uext[], realtype buffer[])
+{
+ long int offsetue;
+ /* Have bufleft and bufright use the same buffer */
+ realtype *bufleft = buffer, *bufright = buffer+NVARS*MYSUB;
+
+ /* If isuby > 0, receive data for bottom x-line of uext */
+ if (isuby != 0)
+ MPI_Irecv(&uext[NVARS], dsizex, PVEC_REAL_MPI_TYPE,
+ my_pe-NPEX, 0, comm, &request[0]);
+
+ /* If isuby < NPEY-1, receive data for top x-line of uext */
+ if (isuby != NPEY-1) {
+ offsetue = NVARS*(1 + (MYSUB+1)*(MXSUB+2));
+ MPI_Irecv(&uext[offsetue], dsizex, PVEC_REAL_MPI_TYPE,
+ my_pe+NPEX, 0, comm, &request[1]);
+ }
+
+ /* If isubx > 0, receive data for left y-line of uext (via bufleft) */
+ if (isubx != 0) {
+ MPI_Irecv(&bufleft[0], dsizey, PVEC_REAL_MPI_TYPE,
+ my_pe-1, 0, comm, &request[2]);
+ }
+
+ /* If isubx < NPEX-1, receive data for right y-line of uext (via bufright) */
+ if (isubx != NPEX-1) {
+ MPI_Irecv(&bufright[0], dsizey, PVEC_REAL_MPI_TYPE,
+ my_pe+1, 0, comm, &request[3]);
+ }
+
+}
+
+/* Routine to finish receiving boundary data from neighboring PEs.
+ Notes:
+ 1) buffer should be able to hold 2*NVARS*MYSUB realtype entries, should be
+ passed to both the BRecvPost and BRecvWait functions, and should not
+ be manipulated between the two calls.
+ 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[],
+ realtype buffer[])
+{
+ int i, ly;
+ long int dsizex2, offsetue, offsetbuf;
+ realtype *bufleft = buffer, *bufright = buffer+NVARS*MYSUB;
+ MPI_Status status;
+
+ dsizex2 = dsizex + 2*NVARS;
+
+ /* If isuby > 0, receive data for bottom x-line of uext */
+ if (isuby != 0)
+ MPI_Wait(&request[0],&status);
+
+ /* If isuby < NPEY-1, receive data for top x-line of uext */
+ if (isuby != NPEY-1)
+ MPI_Wait(&request[1],&status);
+
+ /* If isubx > 0, receive data for left y-line of uext (via bufleft) */
+ if (isubx != 0) {
+ MPI_Wait(&request[2],&status);
+
+ /* Copy the buffer to uext */
+ for (ly = 0; ly < MYSUB; ly++) {
+ offsetbuf = ly*NVARS;
+ offsetue = (ly+1)*dsizex2;
+ for (i = 0; i < NVARS; i++)
+ uext[offsetue+i] = bufleft[offsetbuf+i];
+ }
+ }
+
+ /* If isubx < NPEX-1, receive data for right y-line of uext (via bufright) */
+ if (isubx != NPEX-1) {
+ MPI_Wait(&request[3],&status);
+
+ /* Copy the buffer to uext */
+ for (ly = 0; ly < MYSUB; ly++) {
+ offsetbuf = ly*NVARS;
+ offsetue = (ly+2)*dsizex2 - NVARS;
+ for (i = 0; i < NVARS; i++)
+ uext[offsetue+i] = bufright[offsetbuf+i];
+ }
+ }
+}
+
+/* fucomm routine. This routine performs all inter-processor
+ communication of data in u needed to calculate f. */
+
+static void fucomm(realtype t, N_Vector u, void *user_data)
+{
+ UserData data;
+ realtype *uarray, *uext, buffer[2*NVARS*MYSUB];
+ MPI_Comm comm;
+ int my_pe, isubx, isuby;
+ long int nvmxsub, nvmysub;
+ MPI_Request request[4];
+
+ data = (UserData) user_data;
+ uarray = NV_DATA_P(u);
+
+ /* Get comm, my_pe, subgrid indices, data sizes, extended array uext */
+
+ comm = data->comm; my_pe = data->my_pe;
+ isubx = data->isubx; isuby = data->isuby;
+ nvmxsub = data->nvmxsub;
+ nvmysub = NVARS*MYSUB;
+ uext = data->uext;
+
+ /* Start receiving boundary data from neighboring PEs */
+
+ BRecvPost(comm, request, my_pe, isubx, isuby, nvmxsub, nvmysub, uext, buffer);
+
+ /* Send data from boundary of local grid to neighboring PEs */
+
+ BSend(comm, my_pe, isubx, isuby, nvmxsub, nvmysub, uarray);
+
+ /* Finish receiving boundary data from neighboring PEs */
+
+ BRecvWait(request, isubx, isuby, nvmxsub, uext, buffer);
+}
+
+/***************** Function called by the solver **************************/
+
+/* f routine. Evaluate f(t,y). First call fucomm to do communication of
+ subgrid boundary data into uext. Then calculate f by a call to flocal. */
+
+static int f(realtype t, N_Vector u, N_Vector udot, void *user_data)
+{
+ UserData data;
+
+ data = (UserData) user_data;
+
+ /* Call fucomm to do inter-processor communication */
+
+ fucomm (t, u, user_data);
+
+ /* Call flocal to calculate all right-hand sides */
+
+ flocal (data->Nlocal, t, u, udot, user_data);
+
+ return(0);
+}
+
+/***************** Functions called by the CVBBDPRE module ****************/
+
+/* 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,
+ N_Vector udot, void *user_data)
+{
+ realtype *uext;
+ 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;
+ int i, lx, ly, jx, jy;
+ int isubx, isuby;
+ long int nvmxsub, nvmxsub2, offsetu, offsetue;
+ UserData data;
+ realtype *uarray, *duarray;
+
+ uarray = NV_DATA_P(u);
+ duarray = NV_DATA_P(udot);
+
+ /* Get subgrid indices, array sizes, extended work array uext */
+
+ data = (UserData) user_data;
+ isubx = data->isubx; isuby = data->isuby;
+ nvmxsub = data->nvmxsub; nvmxsub2 = data->nvmxsub2;
+ uext = data->uext;
+
+ /* Copy local segment of u vector into the working extended array uext */
+
+ offsetu = 0;
+ offsetue = nvmxsub2 + NVARS;
+ for (ly = 0; ly < MYSUB; ly++) {
+ for (i = 0; i < nvmxsub; i++) uext[offsetue+i] = uarray[offsetu+i];
+ offsetu = offsetu + nvmxsub;
+ offsetue = offsetue + nvmxsub2;
+ }
+
+ /* To facilitate homogeneous Neumann boundary conditions, when this is
+ a boundary PE, copy data from the first interior mesh line of u to uext */
+
+ /* If isuby = 0, copy x-line 2 of u to uext */
+ if (isuby == 0) {
+ for (i = 0; i < nvmxsub; i++) uext[NVARS+i] = uarray[nvmxsub+i];
+ }
+
+ /* If isuby = NPEY-1, copy x-line MYSUB-1 of u to uext */
+ if (isuby == NPEY-1) {
+ offsetu = (MYSUB-2)*nvmxsub;
+ offsetue = (MYSUB+1)*nvmxsub2 + NVARS;
+ for (i = 0; i < nvmxsub; i++) uext[offsetue+i] = uarray[offsetu+i];
+ }
+
+ /* If isubx = 0, copy y-line 2 of u to uext */
+ if (isubx == 0) {
+ for (ly = 0; ly < MYSUB; ly++) {
+ offsetu = ly*nvmxsub + NVARS;
+ offsetue = (ly+1)*nvmxsub2;
+ for (i = 0; i < NVARS; i++) uext[offsetue+i] = uarray[offsetu+i];
+ }
+ }
+
+ /* If isubx = NPEX-1, copy y-line MXSUB-1 of u to uext */
+ if (isubx == NPEX-1) {
+ for (ly = 0; ly < MYSUB; ly++) {
+ offsetu = (ly+1)*nvmxsub - 2*NVARS;
+ offsetue = (ly+2)*nvmxsub2 - NVARS;
+ for (i = 0; i < NVARS; i++) uext[offsetue+i] = uarray[offsetu+i];
+ }
+ }
+
+ /* Make local copies of problem variables, for efficiency */
+
+ dely = data->dy;
+ verdco = data->vdco;
+ hordco = data->hdco;
+ horaco = data->haco;
+
+ /* Set diurnal rate coefficients as functions of t, and save q4 in
+ data block for use by preconditioner evaluation routine */
+
+ s = sin((data->om)*t);
+ if (s > ZERO) {
+ q3 = EXP(-A3/s);
+ q4coef = EXP(-A4/s);
+ } else {
+ q3 = ZERO;
+ q4coef = ZERO;
+ }
+ data->q4 = q4coef;
+
+
+ /* Loop over all grid points in local subgrid */
+
+ for (ly = 0; ly < MYSUB; ly++) {
+
+ jy = ly + isuby*MYSUB;
+
+ /* Set vertical diffusion coefficients at jy +- 1/2 */
+
+ ydn = YMIN + (jy - RCONST(0.5))*dely;
+ yup = ydn + dely;
+ cydn = verdco*EXP(RCONST(0.2)*ydn);
+ cyup = verdco*EXP(RCONST(0.2)*yup);
+ for (lx = 0; lx < MXSUB; lx++) {
+
+ jx = lx + isubx*MXSUB;
+
+ /* Extract c1 and c2, and set kinetic rate terms */
+
+ offsetue = (lx+1)*NVARS + (ly+1)*nvmxsub2;
+ c1 = uext[offsetue];
+ c2 = uext[offsetue+1];
+ qq1 = Q1*c1*C3;
+ qq2 = Q2*c1*c2;
+ qq3 = q3*C3;
+ qq4 = q4coef*c2;
+ rkin1 = -qq1 - qq2 + 2.0*qq3 + qq4;
+ rkin2 = qq1 - qq2 - qq4;
+
+ /* Set vertical diffusion terms */
+
+ c1dn = uext[offsetue-nvmxsub2];
+ c2dn = uext[offsetue-nvmxsub2+1];
+ c1up = uext[offsetue+nvmxsub2];
+ c2up = uext[offsetue+nvmxsub2+1];
+ vertd1 = cyup*(c1up - c1) - cydn*(c1 - c1dn);
+ vertd2 = cyup*(c2up - c2) - cydn*(c2 - c2dn);
+
+ /* Set horizontal diffusion and advection terms */
+
+ c1lt = uext[offsetue-2];
+ c2lt = uext[offsetue-1];
+ c1rt = uext[offsetue+2];
+ c2rt = uext[offsetue+3];
+ hord1 = hordco*(c1rt - RCONST(2.0)*c1 + c1lt);
+ hord2 = hordco*(c2rt - RCONST(2.0)*c2 + c2lt);
+ horad1 = horaco*(c1rt - c1lt);
+ horad2 = horaco*(c2rt - c2lt);
+
+ /* Load all terms into duarray */
+
+ offsetu = lx*NVARS + ly*nvmxsub;
+ duarray[offsetu] = vertd1 + hord1 + horad1 + rkin1;
+ duarray[offsetu+1] = vertd2 + hord2 + horad2 + rkin2;
+ }
+ }
+
+ 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, char *funcname, int opt, int id)
+{
+ int *errflag;
+
+ /* Check if SUNDIALS function returned NULL pointer - no memory allocated */
+ if (opt == 0 && flagvalue == NULL) {
+ fprintf(stderr, "\nSUNDIALS_ERROR(%d): %s() failed - returned NULL pointer\n\n",
+ id, funcname);
+ return(1); }
+
+ /* Check if flag < 0 */
+ else if (opt == 1) {
+ errflag = (int *) flagvalue;
+ if (*errflag < 0) {
+ fprintf(stderr, "\nSUNDIALS_ERROR(%d): %s() failed with flag = %d\n\n",
+ id, funcname, *errflag);
+ return(1); }}
+
+ /* Check if function returned NULL pointer - no memory allocated */
+ else if (opt == 2 && flagvalue == NULL) {
+ fprintf(stderr, "\nMEMORY_ERROR(%d): %s() failed - returned NULL pointer\n\n",
+ id, funcname);
+ return(1); }
+
+ return(0);
+}
diff --git a/examples/cvodes/parallel/cvsDiurnal_kry_bbd_p.out b/examples/cvodes/parallel/cvsDiurnal_kry_bbd_p.out
new file mode 100644
index 0000000..9388508
--- /dev/null
+++ b/examples/cvodes/parallel/cvsDiurnal_kry_bbd_p.out
@@ -0,0 +1,140 @@
+
+2-species diurnal advection-diffusion problem
+ 10 by 10 mesh on 4 processors
+ Using CVBBDPRE preconditioner module
+ Difference-quotient half-bandwidths are mudq = 10, mldq = 10
+ Retained band block half-bandwidths are mukeep = 2, mlkeep = 2
+
+Preconditioner type is: jpre = PREC_LEFT
+
+t = 7.20e+03 no. steps = 190 order = 5 stepsize = 1.61e+02
+At bottom left: c1, c2 = 1.047e+04 2.527e+11
+At top right: c1, c2 = 1.119e+04 2.700e+11
+
+t = 1.44e+04 no. steps = 221 order = 5 stepsize = 3.85e+02
+At bottom left: c1, c2 = 6.659e+06 2.582e+11
+At top right: c1, c2 = 7.301e+06 2.833e+11
+
+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
+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
+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 = 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.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 = 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 = 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.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 = 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
+
+
+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
+ncfn = 0 ncfl = 0
+
+In CVBBDPRE: real/integer local work space sizes = 600, 50
+ no. flocal evals. = 176
+
+
+-------------------------------------------------------------------
+
+
+Preconditioner type is: jpre = PREC_RIGHT
+
+t = 7.20e+03 no. steps = 191 order = 5 stepsize = 1.22e+02
+At bottom left: c1, c2 = 1.047e+04 2.527e+11
+At top right: c1, c2 = 1.119e+04 2.700e+11
+
+t = 1.44e+04 no. steps = 223 order = 5 stepsize = 2.79e+02
+At bottom left: c1, c2 = 6.659e+06 2.582e+11
+At top right: c1, c2 = 7.301e+06 2.833e+11
+
+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
+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
+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 = 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.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 = 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 = 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.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 = 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
+
+
+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
+ncfn = 0 ncfl = 0
+
+In CVBBDPRE: real/integer local work space sizes = 600, 50
+ no. flocal evals. = 198
diff --git a/examples/cvodes/parallel/cvsDiurnal_kry_p.c b/examples/cvodes/parallel/cvsDiurnal_kry_p.c
new file mode 100644
index 0000000..3f6ce0a
--- /dev/null
+++ b/examples/cvodes/parallel/cvsDiurnal_kry_p.c
@@ -0,0 +1,975 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.4 $
+ * $Date: 2010/12/01 23:00:48 $
+ * -----------------------------------------------------------------
+ * Programmer(s): S. D. Cohen, A. C. Hindmarsh, M. R. Wittman, and
+ * Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Example problem:
+ *
+ * An ODE system is generated from the following 2-species diurnal
+ * kinetics advection-diffusion PDE system in 2 space dimensions:
+ *
+ * dc(i)/dt = Kh*(d/dx)^2 c(i) + V*dc(i)/dx + (d/dy)(Kv(y)*dc(i)/dy)
+ * + Ri(c1,c2,t) for i = 1,2, where
+ * R1(c1,c2,t) = -q1*c1*c3 - q2*c1*c2 + 2*q3(t)*c3 + q4(t)*c2 ,
+ * R2(c1,c2,t) = q1*c1*c3 - q2*c1*c2 - q4(t)*c2 ,
+ * Kv(y) = Kv0*exp(y/5) ,
+ * Kh, V, Kv0, q1, q2, and c3 are constants, and q3(t) and q4(t)
+ * vary diurnally. The problem is posed on the square
+ * 0 <= x <= 20, 30 <= y <= 50 (all in km),
+ * with homogeneous Neumann boundary conditions, and for time t in
+ * 0 <= t <= 86400 sec (1 day).
+ * The PDE system is treated by central differences on a uniform
+ * mesh, with simple polynomial initial profiles.
+ *
+ * The problem is solved by CVODES on NPE processors, treated
+ * as a rectangular process grid of size NPEX by NPEY, with
+ * NPE = NPEX*NPEY. Each processor contains a subgrid of size MXSUB
+ * by MYSUB of the (x,y) mesh. Thus the actual mesh sizes are
+ * MX = MXSUB*NPEX and MY = MYSUB*NPEY, and the ODE system size is
+ * 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
+ * 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.
+ *
+ * Performance data and sampled solution values are printed at
+ * selected output times, and all performance counters are printed
+ * on completion.
+ *
+ * This version uses MPI for user routines.
+ *
+ * Execution: mpirun -np N cvsDiurnal_kry_p with N = NPEX*NPEY
+ * (see constants below).
+ * -----------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#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 SQR and EXP */
+
+#include <mpi.h> /* MPI constants and types */
+
+/* Problem Constants */
+
+#define NVARS 2 /* number of species */
+#define KH RCONST(4.0e-6) /* horizontal diffusivity Kh */
+#define VEL RCONST(0.001) /* advection velocity V */
+#define KV0 RCONST(1.0e-8) /* coefficient in Kv(y) */
+#define Q1 RCONST(1.63e-16) /* coefficients q1, q2, c3 */
+#define Q2 RCONST(4.66e-16)
+#define C3 RCONST(3.7e16)
+#define A3 RCONST(22.62) /* coefficient in expression for q3(t) */
+#define A4 RCONST(7.601) /* coefficient in expression for q4(t) */
+#define C1_SCALE RCONST(1.0e6) /* coefficients in initial profiles */
+#define C2_SCALE RCONST(1.0e12)
+
+#define T0 RCONST(0.0) /* initial time */
+#define NOUT 12 /* number of output times */
+#define TWOHR RCONST(7200.0) /* number of seconds in two hours */
+#define HALFDAY RCONST(4.32e4) /* number of seconds in a half day */
+#define PI RCONST(3.1415926535898) /* pi */
+
+#define XMIN RCONST(0.0) /* grid boundaries in x */
+#define XMAX RCONST(20.0)
+#define YMIN RCONST(30.0) /* grid boundaries in y */
+#define YMAX RCONST(50.0)
+
+#define NPEX 2 /* no. PEs in x direction of PE array */
+#define NPEY 2 /* no. PEs in y direction of PE array */
+ /* Total no. PEs = NPEX*NPEY */
+#define MXSUB 5 /* no. x points per subgrid */
+#define MYSUB 5 /* no. y points per subgrid */
+
+#define MX (NPEX*MXSUB) /* MX = number of x mesh points */
+#define MY (NPEY*MYSUB) /* MY = number of y mesh points */
+ /* Spatial mesh is MX by MY */
+/* CVodeMalloc Constants */
+
+#define RTOL RCONST(1.0e-5) /* scalar relative tolerance */
+#define FLOOR RCONST(100.0) /* value of C1 or C2 at which tolerances */
+ /* change from relative to absolute */
+#define ATOL (RTOL*FLOOR) /* scalar absolute tolerance */
+
+
+/* User-defined matrix accessor macro: IJth */
+
+/* IJth is defined in order to write code which indexes into dense
+ matrices with a (row,column) pair, where 1 <= row,column <= NVARS.
+
+ IJth(a,i,j) references the (i,j)th entry of the small matrix realtype **a,
+ where 1 <= i,j <= NVARS. The small matrix routines in sundials_dense.h
+ work with matrices stored by column in a 2-dimensional array. In C,
+ arrays are indexed starting at 0, not 1. */
+
+#define IJth(a,i,j) (a[j-1][i-1])
+
+/* Type : UserData
+ contains problem constants, preconditioner blocks, pivot arrays,
+ grid constants, and processor indices, as well as data needed
+ for the preconditiner */
+
+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;
+ MPI_Comm comm;
+
+ /* For preconditioner */
+ realtype **P[MXSUB][MYSUB], **Jbd[MXSUB][MYSUB];
+ long int *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(N_Vector u, UserData data);
+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,
+ realtype udata[]);
+static void BRecvPost(MPI_Comm comm, MPI_Request request[],
+ int my_pe, int isubx, int isuby,
+ long int dsizex, long int dsizey,
+ realtype uext[], realtype buffer[]);
+static void BRecvWait(MPI_Request request[],
+ int isubx, int isuby,
+ long int 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);
+
+
+/* Functions Called by the Solver */
+
+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 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);
+
+
+/* Private function to check function return values */
+
+static int check_flag(void *flagvalue, char *funcname, int opt, int id);
+
+
+/***************************** Main Program ******************************/
+
+int main(int argc, char *argv[])
+{
+ realtype abstol, reltol, t, tout;
+ N_Vector u;
+ UserData data;
+ void *cvode_mem;
+ int iout, flag, my_pe, npes;
+ long int neq, local_N;
+ MPI_Comm comm;
+
+ u = NULL;
+ data = NULL;
+ cvode_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;
+ MPI_Comm_size(comm, &npes);
+ MPI_Comm_rank(comm, &my_pe);
+
+ if (npes != NPEX*NPEY) {
+ if (my_pe == 0)
+ fprintf(stderr, "\nMPI_ERROR(0): npes = %d is not equal to NPEX*NPEY = %d\n\n",
+ npes,NPEX*NPEY);
+ MPI_Finalize();
+ return(1);
+ }
+
+ /* Set local length */
+ local_N = NVARS*MXSUB*MYSUB;
+
+ /* Allocate and load user data block; allocate preconditioner block */
+ data = (UserData) malloc(sizeof *data);
+ if (check_flag((void *)data, "malloc", 2, my_pe)) MPI_Abort(comm, 1);
+ InitUserData(my_pe, comm, data);
+
+ /* Allocate u, and set initial values and tolerances */
+ u = N_VNew_Parallel(comm, local_N, neq);
+ if (check_flag((void *)u, "N_VNew", 0, my_pe)) MPI_Abort(comm, 1);
+ SetInitialProfiles(u, data);
+ abstol = ATOL; reltol = RTOL;
+
+ /* 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, my_pe)) MPI_Abort(comm, 1);
+
+ /* Set the pointer to user-defined data */
+ flag = CVodeSetUserData(cvode_mem, data);
+ if (check_flag(&flag, "CVodeSetUserData", 1, my_pe)) MPI_Abort(comm, 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
+ * the initial dependent variable vector u. */
+ flag = CVodeInit(cvode_mem, f, T0, u);
+ if(check_flag(&flag, "CVodeInit", 1, my_pe)) return(1);
+
+ /* Call CVodeSStolerances to specify the scalar relative tolerance
+ * and scalar absolute tolerances */
+ 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);
+
+ /* 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, my_pe)) MPI_Abort(comm, 1);
+
+ if (my_pe == 0)
+ printf("\n2-species diurnal advection-diffusion problem\n\n");
+
+ /* In loop over output points, call CVode, print results, test for error */
+ for (iout=1, tout = TWOHR; iout <= NOUT; iout++, tout += TWOHR) {
+ flag = CVode(cvode_mem, tout, u, &t, CV_NORMAL);
+ if (check_flag(&flag, "CVode", 1, my_pe)) break;
+ PrintOutput(cvode_mem, my_pe, comm, u, t);
+ }
+
+ /* Print final statistics */
+ if (my_pe == 0) PrintFinalStats(cvode_mem);
+
+ /* Free memory */
+ N_VDestroy_Parallel(u);
+ FreeUserData(data);
+ CVodeFree(&cvode_mem);
+
+ MPI_Finalize();
+
+ return(0);
+}
+
+
+/*********************** Private Helper Functions ************************/
+
+
+/* Load constants in data */
+
+static void InitUserData(int my_pe, MPI_Comm comm, UserData data)
+{
+ int isubx, isuby;
+ int lx, ly;
+
+ /* Set problem constants */
+ data->om = PI/HALFDAY;
+ data->dx = (XMAX-XMIN)/((realtype)(MX-1));
+ data->dy = (YMAX-YMIN)/((realtype)(MY-1));
+ data->hdco = KH/SQR(data->dx);
+ data->haco = VEL/(RCONST(2.0)*data->dx);
+ data->vdco = (RCONST(1.0)/SQR(data->dy))*KV0;
+
+ /* Set machine-related constants */
+ data->comm = comm;
+ data->my_pe = my_pe;
+
+ /* isubx and isuby are the PE grid indices corresponding to my_pe */
+ isuby = my_pe/NPEX;
+ isubx = my_pe - isuby*NPEX;
+ data->isubx = isubx;
+ data->isuby = isuby;
+
+ /* Set the sizes of a boundary x-line in u and uext */
+ data->nvmxsub = NVARS*MXSUB;
+ data->nvmxsub2 = NVARS*(MXSUB+2);
+
+ /* Preconditioner-related fields */
+ for (lx = 0; lx < MXSUB; lx++) {
+ 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);
+ }
+ }
+}
+
+/* Free user data memory */
+
+static void FreeUserData(UserData data)
+{
+ int lx, ly;
+
+ for (lx = 0; lx < MXSUB; lx++) {
+ for (ly = 0; ly < MYSUB; ly++) {
+ destroyMat((data->P)[lx][ly]);
+ destroyMat((data->Jbd)[lx][ly]);
+ destroyArray((data->pivot)[lx][ly]);
+ }
+ }
+
+ free(data);
+}
+
+/* Set initial conditions in u */
+
+static void SetInitialProfiles(N_Vector u, UserData data)
+{
+ int isubx, isuby, lx, ly, jx, jy;
+ long int offset;
+ realtype dx, dy, x, y, cx, cy, xmid, ymid;
+ realtype *udata;
+
+ /* Set pointer to data array in vector u */
+ udata = NV_DATA_P(u);
+
+ /* Get mesh spacings, and subgrid indices for this PE */
+ dx = data->dx; dy = data->dy;
+ isubx = data->isubx; isuby = data->isuby;
+
+ /* Load initial profiles of c1 and c2 into local u vector.
+ Here lx and ly are local mesh point indices on the local subgrid,
+ and jx and jy are the global mesh point indices. */
+ offset = 0;
+ xmid = RCONST(0.5)*(XMIN + XMAX);
+ ymid = RCONST(0.5)*(YMIN + YMAX);
+ for (ly = 0; ly < MYSUB; ly++) {
+ jy = ly + isuby*MYSUB;
+ y = YMIN + jy*dy;
+ cy = SQR(RCONST(0.1)*(y - ymid));
+ cy = RCONST(1.0) - cy + RCONST(0.5)*SQR(cy);
+ for (lx = 0; lx < MXSUB; lx++) {
+ jx = lx + isubx*MXSUB;
+ x = XMIN + jx*dx;
+ cx = SQR(RCONST(0.1)*(x - xmid));
+ cx = RCONST(1.0) - cx + RCONST(0.5)*SQR(cx);
+ udata[offset ] = C1_SCALE*cx*cy;
+ udata[offset+1] = C2_SCALE*cx*cy;
+ offset = offset + 2;
+ }
+ }
+}
+
+/* Print current t, step count, order, stepsize, and sampled c1,c2 values */
+
+static void PrintOutput(void *cvode_mem, int my_pe, MPI_Comm comm,
+ N_Vector u, realtype t)
+{
+ int qu, flag;
+ realtype hu, *udata, tempu[2];
+ int npelast;
+ long int i0, i1, nst;
+ MPI_Status status;
+
+ npelast = NPEX*NPEY - 1;
+ udata = NV_DATA_P(u);
+
+ /* Send c1,c2 at top right mesh point to PE 0 */
+ if (my_pe == npelast) {
+ i0 = NVARS*MXSUB*MYSUB - 2;
+ i1 = i0 + 1;
+ if (npelast != 0)
+ MPI_Send(&udata[i0], 2, PVEC_REAL_MPI_TYPE, 0, 0, comm);
+ else {
+ tempu[0] = udata[i0];
+ tempu[1] = udata[i1];
+ }
+ }
+
+ /* On PE 0, receive c1,c2 at top right, then print performance data
+ and sampled solution values */
+ if (my_pe == 0) {
+ if (npelast != 0)
+ MPI_Recv(&tempu[0], 2, PVEC_REAL_MPI_TYPE, npelast, 0, comm, &status);
+ flag = CVodeGetNumSteps(cvode_mem, &nst);
+ check_flag(&flag, "CVodeGetNumSteps", 1, my_pe);
+ flag = CVodeGetLastOrder(cvode_mem, &qu);
+ check_flag(&flag, "CVodeGetLastOrder", 1, my_pe);
+ flag = CVodeGetLastStep(cvode_mem, &hu);
+ check_flag(&flag, "CVodeGetLastStep", 1, my_pe);
+
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("t = %.2Le no. steps = %ld order = %d stepsize = %.2Le\n",
+ t, nst, qu, hu);
+ printf("At bottom left: c1, c2 = %12.3Le %12.3Le \n", udata[0], udata[1]);
+ printf("At top right: c1, c2 = %12.3Le %12.3Le \n\n", tempu[0], tempu[1]);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("t = %.2le no. steps = %ld order = %d stepsize = %.2le\n",
+ t, nst, qu, hu);
+ printf("At bottom left: c1, c2 = %12.3le %12.3le \n", udata[0], udata[1]);
+ printf("At top right: c1, c2 = %12.3le %12.3le \n\n", tempu[0], tempu[1]);
+#else
+ printf("t = %.2e no. steps = %ld order = %d stepsize = %.2e\n",
+ t, nst, qu, hu);
+ printf("At bottom left: c1, c2 = %12.3e %12.3e \n", udata[0], udata[1]);
+ printf("At top right: c1, c2 = %12.3e %12.3e \n\n", tempu[0], tempu[1]);
+#endif
+ }
+}
+
+/* Print final statistics contained in iopt */
+
+static void PrintFinalStats(void *cvode_mem)
+{
+ long int lenrw, leniw ;
+ long int 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, 0);
+ flag = CVodeGetNumSteps(cvode_mem, &nst);
+ check_flag(&flag, "CVodeGetNumSteps", 1, 0);
+ flag = CVodeGetNumRhsEvals(cvode_mem, &nfe);
+ check_flag(&flag, "CVodeGetNumRhsEvals", 1, 0);
+ flag = CVodeGetNumLinSolvSetups(cvode_mem, &nsetups);
+ check_flag(&flag, "CVodeGetNumLinSolvSetups", 1, 0);
+ flag = CVodeGetNumErrTestFails(cvode_mem, &netf);
+ check_flag(&flag, "CVodeGetNumErrTestFails", 1, 0);
+ flag = CVodeGetNumNonlinSolvIters(cvode_mem, &nni);
+ check_flag(&flag, "CVodeGetNumNonlinSolvIters", 1, 0);
+ flag = CVodeGetNumNonlinSolvConvFails(cvode_mem, &ncfn);
+ check_flag(&flag, "CVodeGetNumNonlinSolvConvFails", 1, 0);
+
+ flag = CVSpilsGetWorkSpace(cvode_mem, &lenrwLS, &leniwLS);
+ check_flag(&flag, "CVSpilsGetWorkSpace", 1, 0);
+ flag = CVSpilsGetNumLinIters(cvode_mem, &nli);
+ check_flag(&flag, "CVSpilsGetNumLinIters", 1, 0);
+ flag = CVSpilsGetNumPrecEvals(cvode_mem, &npe);
+ check_flag(&flag, "CVSpilsGetNumPrecEvals", 1, 0);
+ flag = CVSpilsGetNumPrecSolves(cvode_mem, &nps);
+ check_flag(&flag, "CVSpilsGetNumPrecSolves", 1, 0);
+ flag = CVSpilsGetNumConvFails(cvode_mem, &ncfl);
+ check_flag(&flag, "CVSpilsGetNumConvFails", 1, 0);
+ flag = CVSpilsGetNumRhsEvals(cvode_mem, &nfeLS);
+ 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("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);
+}
+
+/* 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[])
+{
+ int i, ly;
+ long int offsetu, offsetbuf;
+ realtype bufleft[NVARS*MYSUB], bufright[NVARS*MYSUB];
+
+ /* If isuby > 0, send data from bottom x-line of u */
+ if (isuby != 0)
+ MPI_Send(&udata[0], dsizex, PVEC_REAL_MPI_TYPE, my_pe-NPEX, 0, comm);
+
+ /* If isuby < NPEY-1, send data from top x-line of u */
+ if (isuby != NPEY-1) {
+ offsetu = (MYSUB-1)*dsizex;
+ MPI_Send(&udata[offsetu], dsizex, PVEC_REAL_MPI_TYPE, my_pe+NPEX, 0, comm);
+ }
+
+ /* If isubx > 0, send data from left y-line of u (via bufleft) */
+ if (isubx != 0) {
+ for (ly = 0; ly < MYSUB; ly++) {
+ offsetbuf = ly*NVARS;
+ offsetu = ly*dsizex;
+ for (i = 0; i < NVARS; i++)
+ bufleft[offsetbuf+i] = udata[offsetu+i];
+ }
+ MPI_Send(&bufleft[0], dsizey, PVEC_REAL_MPI_TYPE, my_pe-1, 0, comm);
+ }
+
+ /* If isubx < NPEX-1, send data from right y-line of u (via bufright) */
+ if (isubx != NPEX-1) {
+ for (ly = 0; ly < MYSUB; ly++) {
+ offsetbuf = ly*NVARS;
+ offsetu = offsetbuf*MXSUB + (MXSUB-1)*NVARS;
+ for (i = 0; i < NVARS; i++)
+ bufright[offsetbuf+i] = udata[offsetu+i];
+ }
+ MPI_Send(&bufright[0], dsizey, PVEC_REAL_MPI_TYPE, my_pe+1, 0, comm);
+ }
+}
+
+/* Routine to start receiving boundary data from neighboring PEs.
+ Notes:
+ 1) buffer should be able to hold 2*NVARS*MYSUB realtype entries, should be
+ passed to both the BRecvPost and BRecvWait functions, and should not
+ be manipulated between the two calls.
+ 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,
+ realtype uext[], realtype buffer[])
+{
+ long int offsetue;
+ /* Have bufleft and bufright use the same buffer */
+ realtype *bufleft = buffer, *bufright = buffer+NVARS*MYSUB;
+
+ /* If isuby > 0, receive data for bottom x-line of uext */
+ if (isuby != 0)
+ MPI_Irecv(&uext[NVARS], dsizex, PVEC_REAL_MPI_TYPE,
+ my_pe-NPEX, 0, comm, &request[0]);
+
+ /* If isuby < NPEY-1, receive data for top x-line of uext */
+ if (isuby != NPEY-1) {
+ offsetue = NVARS*(1 + (MYSUB+1)*(MXSUB+2));
+ MPI_Irecv(&uext[offsetue], dsizex, PVEC_REAL_MPI_TYPE,
+ my_pe+NPEX, 0, comm, &request[1]);
+ }
+
+ /* If isubx > 0, receive data for left y-line of uext (via bufleft) */
+ if (isubx != 0) {
+ MPI_Irecv(&bufleft[0], dsizey, PVEC_REAL_MPI_TYPE,
+ my_pe-1, 0, comm, &request[2]);
+ }
+
+ /* If isubx < NPEX-1, receive data for right y-line of uext (via bufright) */
+ if (isubx != NPEX-1) {
+ MPI_Irecv(&bufright[0], dsizey, PVEC_REAL_MPI_TYPE,
+ my_pe+1, 0, comm, &request[3]);
+ }
+}
+
+/* Routine to finish receiving boundary data from neighboring PEs.
+ Notes:
+ 1) buffer should be able to hold 2*NVARS*MYSUB realtype entries, should be
+ passed to both the BRecvPost and BRecvWait functions, and should not
+ be manipulated between the two calls.
+ 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[],
+ realtype buffer[])
+{
+ int i, ly;
+ long int dsizex2, offsetue, offsetbuf;
+ realtype *bufleft = buffer, *bufright = buffer+NVARS*MYSUB;
+ MPI_Status status;
+
+ dsizex2 = dsizex + 2*NVARS;
+
+ /* If isuby > 0, receive data for bottom x-line of uext */
+ if (isuby != 0)
+ MPI_Wait(&request[0],&status);
+
+ /* If isuby < NPEY-1, receive data for top x-line of uext */
+ if (isuby != NPEY-1)
+ MPI_Wait(&request[1],&status);
+
+ /* If isubx > 0, receive data for left y-line of uext (via bufleft) */
+ if (isubx != 0) {
+ MPI_Wait(&request[2],&status);
+
+ /* Copy the buffer to uext */
+ for (ly = 0; ly < MYSUB; ly++) {
+ offsetbuf = ly*NVARS;
+ offsetue = (ly+1)*dsizex2;
+ for (i = 0; i < NVARS; i++)
+ uext[offsetue+i] = bufleft[offsetbuf+i];
+ }
+ }
+
+ /* If isubx < NPEX-1, receive data for right y-line of uext (via bufright) */
+ if (isubx != NPEX-1) {
+ MPI_Wait(&request[3],&status);
+
+ /* Copy the buffer to uext */
+ for (ly = 0; ly < MYSUB; ly++) {
+ offsetbuf = ly*NVARS;
+ offsetue = (ly+2)*dsizex2 - NVARS;
+ for (i = 0; i < NVARS; i++)
+ uext[offsetue+i] = bufright[offsetbuf+i];
+ }
+ }
+}
+
+/* ucomm routine. This routine performs all communication
+ between processors of data needed to calculate f. */
+
+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;
+ MPI_Request request[4];
+
+ udata = NV_DATA_P(u);
+
+ /* Get comm, my_pe, subgrid indices, data sizes, extended array uext */
+ comm = data->comm; my_pe = data->my_pe;
+ isubx = data->isubx; isuby = data->isuby;
+ nvmxsub = data->nvmxsub;
+ nvmysub = NVARS*MYSUB;
+ uext = data->uext;
+
+ /* Start receiving boundary data from neighboring PEs */
+ BRecvPost(comm, request, my_pe, isubx, isuby, nvmxsub, nvmysub, uext, buffer);
+
+ /* Send data from boundary of local grid to neighboring PEs */
+ BSend(comm, my_pe, isubx, isuby, nvmxsub, nvmysub, udata);
+
+ /* Finish receiving boundary data from neighboring PEs */
+ BRecvWait(request, isubx, isuby, nvmxsub, uext, buffer);
+}
+
+/* fcalc routine. Compute f(t,y). This routine assumes that communication
+ between processors of data needed to calculate f has already been done,
+ and this data is in the work array uext. */
+
+static void fcalc(realtype t, realtype udata[],
+ realtype dudata[], UserData data)
+{
+ realtype *uext;
+ 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;
+ int i, lx, ly, jx, jy;
+ int isubx, isuby;
+ long int nvmxsub, nvmxsub2, offsetu, offsetue;
+
+ /* Get subgrid indices, data sizes, extended work array uext */
+ isubx = data->isubx; isuby = data->isuby;
+ nvmxsub = data->nvmxsub; nvmxsub2 = data->nvmxsub2;
+ uext = data->uext;
+
+ /* Copy local segment of u vector into the working extended array uext */
+ offsetu = 0;
+ offsetue = nvmxsub2 + NVARS;
+ for (ly = 0; ly < MYSUB; ly++) {
+ for (i = 0; i < nvmxsub; i++) uext[offsetue+i] = udata[offsetu+i];
+ offsetu = offsetu + nvmxsub;
+ offsetue = offsetue + nvmxsub2;
+ }
+
+ /* To facilitate homogeneous Neumann boundary conditions, when this is
+ a boundary PE, copy data from the first interior mesh line of u to uext */
+
+ /* If isuby = 0, copy x-line 2 of u to uext */
+ if (isuby == 0) {
+ for (i = 0; i < nvmxsub; i++) uext[NVARS+i] = udata[nvmxsub+i];
+ }
+
+ /* If isuby = NPEY-1, copy x-line MYSUB-1 of u to uext */
+ if (isuby == NPEY-1) {
+ offsetu = (MYSUB-2)*nvmxsub;
+ offsetue = (MYSUB+1)*nvmxsub2 + NVARS;
+ for (i = 0; i < nvmxsub; i++) uext[offsetue+i] = udata[offsetu+i];
+ }
+
+ /* If isubx = 0, copy y-line 2 of u to uext */
+ if (isubx == 0) {
+ for (ly = 0; ly < MYSUB; ly++) {
+ offsetu = ly*nvmxsub + NVARS;
+ offsetue = (ly+1)*nvmxsub2;
+ for (i = 0; i < NVARS; i++) uext[offsetue+i] = udata[offsetu+i];
+ }
+ }
+
+ /* If isubx = NPEX-1, copy y-line MXSUB-1 of u to uext */
+ if (isubx == NPEX-1) {
+ for (ly = 0; ly < MYSUB; ly++) {
+ offsetu = (ly+1)*nvmxsub - 2*NVARS;
+ offsetue = (ly+2)*nvmxsub2 - NVARS;
+ for (i = 0; i < NVARS; i++) uext[offsetue+i] = udata[offsetu+i];
+ }
+ }
+
+ /* Make local copies of problem variables, for efficiency */
+ dely = data->dy;
+ verdco = data->vdco;
+ hordco = data->hdco;
+ horaco = data->haco;
+
+ /* Set diurnal rate coefficients as functions of t, and save q4 in
+ data block for use by preconditioner evaluation routine */
+ s = sin((data->om)*t);
+ if (s > RCONST(0.0)) {
+ q3 = EXP(-A3/s);
+ q4coef = EXP(-A4/s);
+ } else {
+ q3 = RCONST(0.0);
+ q4coef = RCONST(0.0);
+ }
+ data->q4 = q4coef;
+
+ /* Loop over all grid points in local subgrid */
+ for (ly = 0; ly < MYSUB; ly++) {
+
+ jy = ly + isuby*MYSUB;
+
+ /* Set vertical diffusion coefficients at jy +- 1/2 */
+ ydn = YMIN + (jy - RCONST(0.5))*dely;
+ yup = ydn + dely;
+ cydn = verdco*EXP(RCONST(0.2)*ydn);
+ cyup = verdco*EXP(RCONST(0.2)*yup);
+ for (lx = 0; lx < MXSUB; lx++) {
+
+ jx = lx + isubx*MXSUB;
+
+ /* Extract c1 and c2, and set kinetic rate terms */
+ offsetue = (lx+1)*NVARS + (ly+1)*nvmxsub2;
+ c1 = uext[offsetue];
+ c2 = uext[offsetue+1];
+ qq1 = Q1*c1*C3;
+ qq2 = Q2*c1*c2;
+ qq3 = q3*C3;
+ qq4 = q4coef*c2;
+ rkin1 = -qq1 - qq2 + RCONST(2.0)*qq3 + qq4;
+ rkin2 = qq1 - qq2 - qq4;
+
+ /* Set vertical diffusion terms */
+ c1dn = uext[offsetue-nvmxsub2];
+ c2dn = uext[offsetue-nvmxsub2+1];
+ c1up = uext[offsetue+nvmxsub2];
+ c2up = uext[offsetue+nvmxsub2+1];
+ vertd1 = cyup*(c1up - c1) - cydn*(c1 - c1dn);
+ vertd2 = cyup*(c2up - c2) - cydn*(c2 - c2dn);
+
+ /* Set horizontal diffusion and advection terms */
+ c1lt = uext[offsetue-2];
+ c2lt = uext[offsetue-1];
+ c1rt = uext[offsetue+2];
+ c2rt = uext[offsetue+3];
+ hord1 = hordco*(c1rt - RCONST(2.0)*c1 + c1lt);
+ hord2 = hordco*(c2rt - RCONST(2.0)*c2 + c2lt);
+ horad1 = horaco*(c1rt - c1lt);
+ horad2 = horaco*(c2rt - c2lt);
+
+ /* Load all terms into dudata */
+ offsetu = lx*NVARS + ly*nvmxsub;
+ dudata[offsetu] = vertd1 + hord1 + horad1 + rkin1;
+ dudata[offsetu+1] = vertd2 + hord2 + horad2 + rkin2;
+ }
+ }
+}
+
+
+/***************** Functions Called by the Solver *************************/
+
+/* f routine. Evaluate f(t,y). First call ucomm to do communication of
+ subgrid boundary data into uext. Then calculate f by a call to fcalc. */
+
+static int f(realtype t, N_Vector u, N_Vector udot, void *user_data)
+{
+ realtype *udata, *dudata;
+ UserData data;
+
+ udata = NV_DATA_P(u);
+ dudata = NV_DATA_P(udot);
+ data = (UserData) user_data;
+
+ /* Call ucomm to do inter-processor communication */
+ ucomm(t, u, data);
+
+ /* Call fcalc to calculate all right-hand sides */
+ fcalc(t, udata, dudata, data);
+
+ return(0);
+}
+
+/* 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 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;
+ int lx, ly, jx, jy, isubx, isuby;
+ realtype *udata, **a, **j;
+ UserData data;
+
+ /* Make local copies of pointers in user_data, pointer to u's data,
+ and PE index pair */
+ data = (UserData) user_data;
+ P = data->P;
+ Jbd = data->Jbd;
+ pivot = data->pivot;
+ udata = NV_DATA_P(u);
+ isubx = data->isubx; isuby = data->isuby;
+ nvmxsub = data->nvmxsub;
+
+ if (jok) {
+
+ /* jok = TRUE: 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;
+
+ }
+
+ else {
+
+ /* jok = FALSE: Generate Jbd from scratch and copy to P */
+
+ /* Make local copies of problem variables, for efficiency */
+ q4coef = data->q4;
+ dely = data->dy;
+ verdco = data->vdco;
+ hordco = data->hdco;
+
+ /* Compute 2x2 diagonal Jacobian blocks (using q4 values
+ computed on the last f call). Load into P. */
+ for (ly = 0; ly < MYSUB; ly++) {
+ jy = ly + isuby*MYSUB;
+ ydn = YMIN + (jy - RCONST(0.5))*dely;
+ yup = ydn + dely;
+ cydn = verdco*EXP(RCONST(0.2)*ydn);
+ cyup = verdco*EXP(RCONST(0.2)*yup);
+ diag = -(cydn + cyup + RCONST(2.0)*hordco);
+ for (lx = 0; lx < MXSUB; lx++) {
+ jx = lx + isubx*MXSUB;
+ offset = lx*NVARS + ly*nvmxsub;
+ c1 = udata[offset];
+ c2 = udata[offset+1];
+ j = Jbd[lx][ly];
+ a = P[lx][ly];
+ IJth(j,1,1) = (-Q1*C3 - Q2*c2) + diag;
+ IJth(j,1,2) = -Q2*c1 + q4coef;
+ IJth(j,2,1) = Q1*C3 - Q2*c2;
+ IJth(j,2,2) = (-Q2*c1 - q4coef) + diag;
+ denseCopy(j, a, NVARS, NVARS);
+ }
+ }
+
+ *jcurPtr = TRUE;
+
+ }
+
+ /* Scale by -gamma */
+ for (ly = 0; ly < MYSUB; ly++)
+ for (lx = 0; lx < MXSUB; lx++)
+ denseScale(-gamma, P[lx][ly], NVARS, NVARS);
+
+ /* Add identity matrix and do LU decompositions on blocks in place */
+ for (lx = 0; lx < MXSUB; lx++) {
+ for (ly = 0; ly < MYSUB; ly++) {
+ denseAddIdentity(P[lx][ly], NVARS);
+ ier = denseGETRF(P[lx][ly], NVARS, NVARS, pivot[lx][ly]);
+ if (ier != 0) return(1);
+ }
+ }
+
+ return(0);
+}
+
+/* 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)
+{
+ realtype **(*P)[MYSUB];
+ long int nvmxsub;
+ long int *(*pivot)[MYSUB];
+ int lx, ly;
+ realtype *zdata, *v;
+ UserData data;
+
+ /* Extract the P and pivot arrays from user_data */
+ data = (UserData) user_data;
+ P = data->P;
+ pivot = data->pivot;
+
+ /* Solve the block-diagonal system Px = r using LU factors stored
+ 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 = NV_DATA_P(z);
+
+ for (lx = 0; lx < MXSUB; lx++) {
+ for (ly = 0; ly < MYSUB; ly++) {
+ v = &(zdata[lx*NVARS + ly*nvmxsub]);
+ denseGETRS(P[lx][ly], NVARS, pivot[lx][ly], v);
+ }
+ }
+
+ return(0);
+}
+
+
+/*********************** Private Helper Function ************************/
+
+/* 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, char *funcname, int opt, int id)
+{
+ int *errflag;
+
+ /* Check if SUNDIALS function returned NULL pointer - no memory allocated */
+ if (opt == 0 && flagvalue == NULL) {
+ fprintf(stderr, "\nSUNDIALS_ERROR(%d): %s() failed - returned NULL pointer\n\n",
+ id, funcname);
+ return(1); }
+
+ /* Check if flag < 0 */
+ else if (opt == 1) {
+ errflag = (int *) flagvalue;
+ if (*errflag < 0) {
+ fprintf(stderr, "\nSUNDIALS_ERROR(%d): %s() failed with flag = %d\n\n",
+ id, funcname, *errflag);
+ return(1); }}
+
+ /* Check if function returned NULL pointer - no memory allocated */
+ else if (opt == 2 && flagvalue == NULL) {
+ fprintf(stderr, "\nMEMORY_ERROR(%d): %s() failed - returned NULL pointer\n\n",
+ id, funcname);
+ return(1); }
+
+ return(0);
+}
diff --git a/examples/cvodes/parallel/cvsDiurnal_kry_p.out b/examples/cvodes/parallel/cvsDiurnal_kry_p.out
new file mode 100644
index 0000000..484e635
--- /dev/null
+++ b/examples/cvodes/parallel/cvsDiurnal_kry_p.out
@@ -0,0 +1,63 @@
+
+2-species diurnal advection-diffusion problem
+
+t = 7.20e+03 no. steps = 219 order = 5 stepsize = 1.59e+02
+At bottom left: c1, c2 = 1.047e+04 2.527e+11
+At top right: c1, c2 = 1.119e+04 2.700e+11
+
+t = 1.44e+04 no. steps = 251 order = 5 stepsize = 3.77e+02
+At bottom left: c1, c2 = 6.659e+06 2.582e+11
+At top right: c1, c2 = 7.301e+06 2.833e+11
+
+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
+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
+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 = 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.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 = 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 = 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.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 = 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
+
+
+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
+
diff --git a/examples/cvodes/serial/CMakeLists.txt b/examples/cvodes/serial/CMakeLists.txt
new file mode 100644
index 0000000..1daa16c
--- /dev/null
+++ b/examples/cvodes/serial/CMakeLists.txt
@@ -0,0 +1,139 @@
+# ---------------------------------------------------------------
+# $Revision: 1.7 $
+# $Date: 2009/02/17 02:58:47 $
+# ---------------------------------------------------------------
+# Programmer: Radu Serban @ LLNL
+# ---------------------------------------------------------------
+# Copyright (c) 2007, The Regents of the University of California.
+# Produced at the Lawrence Livermore National Laboratory.
+# All rights reserved.
+# For details, see the LICENSE file.
+# ---------------------------------------------------------------
+# CMakeLists.txt file for CVODES serial examples
+
+
+# Add variable CVODES_examples with the names of the serial CVODES examples
+
+SET(CVODES_examples
+ cvsAdvDiff_ASAi_bnd
+ cvsAdvDiff_bnd
+ cvsAdvDiff_FSA_non
+ cvsDirectDemo_ls
+ cvsDiurnal_FSA_kry
+ 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
+ )
+
+# Add variable CVODES_examples_BL with the names of the serial CVODES examples
+# that use Lapack
+
+SET(CVODES_examples_BL
+ cvsAdvDiff_bndL
+ cvsRoberts_dnsL
+ )
+
+# 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")
+ SET(CVODES_LIB sundials_cvodes_shared)
+ SET(NVECS_LIB sundials_nvecserial_shared)
+ENDIF(LINK_LIBRARY_TYPE MATCHES "static")
+
+# Set-up linker flags and link libraries
+
+SET(SUNDIALS_LIBS ${CVODES_LIB} ${NVECS_LIB} ${EXTRA_LINK_LIBS})
+IF(LAPACK_FOUND)
+ SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${LAPACK_LINKER_FLAGS}")
+ SET(SUNDIALS_LIBS "${SUNDIALS_LIBS} ${LAPACK_LIBRARIES}")
+ENDIF(LAPACK_FOUND)
+
+# Add the build and install targets for each CVODES example
+
+FOREACH(example ${CVODES_examples})
+ ADD_EXECUTABLE(${example} ${example}.c)
+ TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+ FILE(GLOB example_out ${example}.out*)
+ IF(EXAMPLES_INSTALL)
+ INSTALL(FILES ${example}.c ${example_out} DESTINATION ${EXAMPLES_INSTALL_PATH}/cvodes/serial)
+ ENDIF(EXAMPLES_INSTALL)
+ENDFOREACH(example ${CVODES_examples})
+
+# If Lapack support is enabled, add the build and install targets for
+# the examples using Lapack
+
+IF(LAPACK_FOUND)
+ FOREACH(example ${CVODES_examples_BL})
+ ADD_EXECUTABLE(${example} ${example}.c)
+ TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+ FILE(GLOB example_out ${example}.out*)
+ IF(EXAMPLES_INSTALL)
+ INSTALL(FILES ${example}.c ${example_out} DESTINATION ${EXAMPLES_INSTALL_PATH}/cvodes/serial)
+ ENDIF(EXAMPLES_INSTALL)
+ ENDFOREACH(example ${CVODES_examples_BL})
+ENDIF(LAPACK_FOUND)
+
+IF(EXAMPLES_INSTALL)
+
+ # Install the README file
+ INSTALL(FILES README DESTINATION ${EXAMPLES_INSTALL_PATH}/cvodes/serial)
+
+ # Prepare substitution variables for Makefile and/or CMakeLists templates
+ SET(SOLVER "CVODES")
+ SET(SOLVER_LIB "sundials_cvodes")
+ LIST2STRING(CVODES_examples EXAMPLES)
+ IF(LAPACK_FOUND)
+ LIST2STRING(CVODES_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
+ # 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
+ )
+
+ # install CMakelists.txt
+ INSTALL(
+ FILES ${PROJECT_BINARY_DIR}/examples/cvodes/serial/CMakeLists.txt
+ 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
+ # 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/cvodes/serial/Makefile_ex
+ @ONLY
+ )
+ # install the configured Makefile_ex as Makefile
+ INSTALL(
+ FILES ${PROJECT_BINARY_DIR}/examples/cvodes/serial/Makefile_ex
+ DESTINATION ${EXAMPLES_INSTALL_PATH}/cvodes/serial
+ RENAME Makefile
+ )
+ ENDIF(UNIX)
+
+ENDIF(EXAMPLES_INSTALL)
diff --git a/examples/cvodes/serial/Makefile.in b/examples/cvodes/serial/Makefile.in
new file mode 100644
index 0000000..10f65a4
--- /dev/null
+++ b/examples/cvodes/serial/Makefile.in
@@ -0,0 +1,146 @@
+# -----------------------------------------------------------------
+# $Revision: 1.12 $
+# $Date: 2009/02/17 02:58:47 $
+# -----------------------------------------------------------------
+# Programmer(s): Radu Serban and Aaron Collier @ LLNL
+# -----------------------------------------------------------------
+# Copyright (c) 2002, The Regents of the University of California.
+# Produced at the Lawrence Livermore National Laboratory.
+# All rights reserved.
+# For details, see the LICENSE file.
+# -----------------------------------------------------------------
+# Makefile for CVODES serial examples
+#
+# @configure_input@
+# -----------------------------------------------------------------
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_builddir = @top_builddir@
+builddir = @builddir@
+abs_builddir = @abs_builddir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+includedir = @includedir@
+libdir = @libdir@
+
+INSTALL = @INSTALL@
+INSTALL_PROG = @INSTALL_PROGRAM@
+INSTALL_FILE = @INSTALL_DATA@
+
+LIBTOOL = @LIBTOOL@
+LIBTOOL_DEPS = @LIBTOOL_DEPS@
+
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CC = @CC@
+CFLAGS = @CFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+
+LAPACK_ENABLED = @LAPACK_ENABLED@
+BLAS_LAPACK_LIBS = @BLAS_LAPACK_LIBS@
+
+OBJ_EXT = @OBJEXT@
+EXE_EXT = @EXEEXT@
+
+EXS_INSTDIR = @EXS_INSTDIR@
+
+top_srcdir = $(srcdir)/../../..
+
+SUNDIALS_INCS = -I$(top_srcdir)/include -I$(top_builddir)/include
+
+SUNDIALS_LIBS = $(top_builddir)/src/cvodes/libsundials_cvodes.la \
+ $(top_builddir)/src/nvec_ser/libsundials_nvecserial.la
+
+mkinstalldirs = $(SHELL) $(top_srcdir)/config/mkinstalldirs
+rminstalldirs = $(SHELL) $(top_srcdir)/config/rminstalldirs
+
+EXAMPLES = cvsAdvDiff_ASAi_bnd \
+ cvsAdvDiff_bnd \
+ cvsAdvDiff_FSA_non \
+ cvsDirectDemo_ls \
+ cvsDiurnal_FSA_kry \
+ 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
+
+EXAMPLES_BL = cvsAdvDiff_bndL \
+ cvsRoberts_dnsL
+
+
+OBJECTS = ${EXAMPLES:=${OBJ_EXT}}
+OBJECTS_BL = ${EXAMPLES_BL:=${OBJ_EXT}}
+EXECS = ${EXAMPLES:=${EXE_EXT}}
+EXECS_BL = ${EXAMPLES_BL:=${EXE_EXT}}
+
+# ----------------------------------------------------------------------------------------------------------------------
+
+all:
+ @for i in ${EXAMPLES} ; do \
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(SUNDIALS_INCS) $(CFLAGS) -c $(srcdir)/$${i}.c -o $${i}${OBJ_EXT} ; \
+ $(LIBTOOL) --mode=link $(CC) -o $(builddir)/$${i}$(EXE_EXT) $(builddir)/$${i}${OBJ_EXT} $(CFLAGS) $(LDFLAGS) $(SUNDIALS_LIBS) $(LIBS) $(BLAS_LAPACK_LIBS) ; \
+ done
+ @if test "X${LAPACK_ENABLED}" = "Xyes"; then \
+ for i in ${EXAMPLES_BL} ; do \
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(SUNDIALS_INCS) $(CFLAGS) -c $(srcdir)/$${i}.c -o $${i}${OBJ_EXT} ; \
+ $(LIBTOOL) --mode=link $(CC) -o $(builddir)/$${i}$(EXE_EXT) $(builddir)/$${i}${OBJ_EXT} $(CFLAGS) $(LDFLAGS) $(SUNDIALS_LIBS) $(LIBS) $(BLAS_LAPACK_LIBS) ; \
+ done ; \
+ fi
+
+install:
+ $(mkinstalldirs) $(EXS_INSTDIR)/cvodes/serial
+ $(INSTALL_FILE) Makefile_ex $(EXS_INSTDIR)/cvodes/serial/Makefile
+ $(INSTALL_FILE) $(top_srcdir)/examples/cvodes/serial/README $(EXS_INSTDIR)/cvodes/serial/
+ for i in ${EXAMPLES} ; do \
+ $(INSTALL_FILE) $(top_srcdir)/examples/cvodes/serial/$${i}.c $(EXS_INSTDIR)/cvodes/serial/ ; \
+ $(INSTALL_FILE) $(top_srcdir)/examples/cvodes/serial/$${i}.out $(EXS_INSTDIR)/cvodes/serial/ ; \
+ done
+ @if test "X${LAPACK_ENABLED}" = "Xyes"; then \
+ for i in ${EXAMPLES_BL} ; do \
+ $(INSTALL_FILE) $(top_srcdir)/examples/cvodes/serial/$${i}.c $(EXS_INSTDIR)/cvodes/serial/ ; \
+ $(INSTALL_FILE) $(top_srcdir)/examples/cvodes/serial/$${i}.out $(EXS_INSTDIR)/cvodes/serial/ ; \
+ done ; \
+ fi
+
+uninstall:
+ rm -f $(EXS_INSTDIR)/cvodes/serial/Makefile
+ rm -f $(EXS_INSTDIR)/cvodes/serial/README
+ for i in ${EXAMPLES} ; do \
+ rm -f $(EXS_INSTDIR)/cvodes/serial/$${i}.c ; \
+ rm -f $(EXS_INSTDIR)/cvodes/serial/$${i}.out ; \
+ done
+ @if test "X${LAPACK_ENABLED}" = "Xyes"; then \
+ for i in ${EXAMPLES_BL} ; do \
+ rm -f $(EXS_INSTDIR)/cvodes/serial/$${i}.c ; \
+ rm -f $(EXS_INSTDIR)/cvodes/serial/$${i}.out ; \
+ done ; \
+ fi
+ $(rminstalldirs) $(EXS_INSTDIR)/cvodes/serial
+ $(rminstalldirs) $(EXS_INSTDIR)/cvodes
+
+clean:
+ rm -rf .libs
+ rm -f *.lo
+ rm -f ${OBJECTS} ${OBJECTS_BL}
+ rm -f $(EXECS) $(EXECS_BL)
+
+distclean: clean
+ rm -f Makefile
+ rm -f Makefile_ex
+
+# ----------------------------------------------------------------------------------------------------------------------
+
+libtool: $(top_builddir)/$(LIBTOOL_DEPS)
+ @cd ${top_builddir} ; \
+ ${SHELL} ./config.status --recheck ; \
+ cd ${abs_builddir}
diff --git a/examples/cvodes/serial/README b/examples/cvodes/serial/README
new file mode 100644
index 0000000..99d10a8
--- /dev/null
+++ b/examples/cvodes/serial/README
@@ -0,0 +1,44 @@
+List of serial CVODES examples
+
+(1) Simulation
+
+ cvsAdvDiff_bnd : banded example
+ cvsAdvDiff_bndL : banded example (Lapack)
+ cvsDirectDemo_ls : demonstration program for direct methods
+ cvsDiurnal_kry_bp : Krylov example with banded preconditioner
+ cvsDiurnal_kry : Krylov example
+ cvsKrylovDemo_ls : demonstration program with 3 Krylov solvers
+ cvsKrylovDemo_prec : demonstration program for Krylov methods
+ cvsRoberts_dns : dense example
+ cvsRoberts_dnsL : dense example (Lapack)
+ cvsRoberts_dns_uw : dense example with user ewt function
+
+(2) Forward sensitivity
+
+ cvsAdvDiff_FSA_non : 1-D advection difusion PDE -
+ 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
+
+(3) Adjoint sensitivity
+
+ cvsAdvDiff_ASAi_bnd : advection-diffusion - adjoint sensitivity
+ cvsFoodWeb_ASAi_kry : food web - adjoint sensitivity for G
+ cvsFoodWeb_ASAp_kry : food web - adjoint sensitivity for g
+ cvsHessian_ASA_FSA : ASA example for computing Hessian
+ cvsRoberts_ASAi_dns : chemical kinetics - adjoint sensitivity
+
+Sample results:
+
+ SUNDIALS was built with the following options:
+
+ ./configure CC=gcc F77=gfortran CFLAGS="-g3 -O0" FFLAGS="-g3 -O0" --with-blas-lapack-libs="-L/home/radu/apps/lib -lSimTKlapack" --enable-examples
+
+ System Architecture: IA-32
+ Processor Type: Intel Pentium 4 Xeon DP (i686)
+ Operating System: Red Hat Enterprise Linux WS 3 (Taroon Update 7)
+ C/Fortran Compilers: gcc/gfortran v4.1.0
+
+ The SimTKlapack library provides ATLAS-tunned Blas and Lapack functions
\ No newline at end of file
diff --git a/examples/cvodes/serial/cvsAdvDiff_ASAi_bnd.c b/examples/cvodes/serial/cvsAdvDiff_ASAi_bnd.c
new file mode 100644
index 0000000..641ee83
--- /dev/null
+++ b/examples/cvodes/serial/cvsAdvDiff_ASAi_bnd.c
@@ -0,0 +1,559 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.3 $
+ * $Date: 2011/11/23 23:53:02 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Adjoint sensitivity example problem:
+ *
+ * The following is a simple example problem with a banded Jacobian,
+ * with the program for its solution by 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
+ * 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 the following:
+ * 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 CVODE 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.
+ *
+ * Additionally, CVODES integrates backwards in time the
+ * the semi-discrete form of the adjoint PDE:
+ * d(lambda)/dt = - d^2(lambda) / dx^2 + 0.5 d(lambda) / dx
+ * - d^2(lambda) / dy^2 - 1.0
+ * with homogeneous Dirichlet boundary conditions and final
+ * conditions:
+ * lambda(x,y,t=t_final) = 0.0
+ * whose solution at t = 0 represents the sensitivity of
+ * G = int_0^t_final int_x int _y u(t,x,y) dx dy dt
+ * with respect to the initial conditions of the original problem.
+ * -----------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#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>
+
+/* Problem Constants */
+
+#define XMAX RCONST(2.0) /* domain boundaries */
+#define YMAX RCONST(1.0)
+#define MX 40 /* mesh dimensions */
+#define MY 20
+#define NEQ MX*MY /* number of equations */
+#define ATOL RCONST(1.e-5)
+#define RTOLB RCONST(1.e-6)
+#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 TOUT RCONST(1.0) /* final time */
+#define NSTEP 50 /* check point saved every NSTEP */
+
+#define ZERO RCONST(0.0)
+#define ONE RCONST(1.0)
+#define TWO RCONST(2.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_VDATA(v),
+ where v is an N_Vector.
+ The variables are ordered by the y index j, then by the x index i. */
+
+#define IJth(vdata,i,j) (vdata[(j-1) + (i-1)*MY])
+
+/* Type : UserData
+ contains grid constants */
+
+typedef struct {
+ realtype dx, dy, hdcoef, hacoef, vdcoef;
+} *UserData;
+
+/* Prototypes of user-supplied functions */
+
+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 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);
+
+/* Prototypes of private functions */
+
+static void SetIC(N_Vector u, UserData data);
+static void PrintOutput(N_Vector uB, UserData data);
+static int check_flag(void *flagvalue, char *funcname, int opt);
+
+/*
+ *--------------------------------------------------------------------
+ * MAIN PROGRAM
+ *--------------------------------------------------------------------
+ */
+
+int main(int argc, char *argv[])
+{
+ UserData data;
+
+ void *cvode_mem;
+
+ realtype dx, dy, reltol, abstol, t;
+ N_Vector u;
+
+ int indexB;
+
+ realtype reltolB, abstolB;
+ N_Vector uB;
+
+ int flag, ncheck;
+
+ data = NULL;
+ cvode_mem = NULL;
+ u = uB = NULL;
+
+ /* Allocate and initialize user data memory */
+
+ data = (UserData) malloc(sizeof *data);
+ if(check_flag((void *)data, "malloc", 2)) return(1);
+
+ dx = data->dx = XMAX/(MX+1);
+ dy = data->dy = YMAX/(MY+1);
+ data->hdcoef = ONE/(dx*dx);
+ data->hacoef = RCONST(1.5)/(TWO*dx);
+ data->vdcoef = ONE/(dy*dy);
+
+ /* Set the tolerances for the forward integration */
+ reltol = ZERO;
+ abstol = ATOL;
+
+ /* Allocate u vector */
+ u = N_VNew_Serial(NEQ);
+ if(check_flag((void *)u, "N_VNew", 0)) return(1);
+
+ /* Initialize u vector */
+ SetIC(u, data);
+
+ /* Create and allocate CVODES memory for forward run */
+
+ printf("\nCreate and allocate CVODES memory for forward runs\n");
+
+ cvode_mem = CVodeCreate(CV_BDF, CV_NEWTON);
+ if(check_flag((void *)cvode_mem, "CVodeCreate", 0)) return(1);
+
+ flag = CVodeSetUserData(cvode_mem, data);
+ if(check_flag(&flag, "CVodeSetUserData", 1)) return(1);
+
+ flag = CVodeInit(cvode_mem, f, T0, u);
+ if(check_flag(&flag, "CVodeInit", 1)) return(1);
+
+ flag = CVodeSStolerances(cvode_mem, reltol, abstol);
+ if(check_flag(&flag, "CVodeSStolerances", 1)) return(1);
+
+ /* Call CVBand with bandwidths ml = mu = MY, */
+
+ flag = CVBand(cvode_mem, NEQ, MY, MY);
+ if(check_flag(&flag, "CVBand", 1)) return(1);
+
+ flag = CVDlsSetBandJacFn(cvode_mem, Jac);
+ if(check_flag(&flag, "CVDlsSetBandJacFn", 1)) return(1);
+
+ /* Allocate global memory */
+
+ printf("\nAllocate global memory\n");
+
+ flag = CVodeAdjInit(cvode_mem, NSTEP, CV_HERMITE);
+ if(check_flag(&flag, "CVodeAdjInit", 1)) return(1);
+
+ /* Perform forward run */
+ printf("\nForward integration\n");
+ flag = CVodeF(cvode_mem, TOUT, u, &t, CV_NORMAL, &ncheck);
+ if(check_flag(&flag, "CVodeF", 1)) return(1);
+
+ printf("\nncheck = %d\n", ncheck);
+
+ /* Set the tolerances for the backward integration */
+ reltolB = RTOLB;
+ abstolB = ATOL;
+
+ /* Allocate uB */
+ uB = N_VNew_Serial(NEQ);
+ if(check_flag((void *)uB, "N_VNew", 0)) return(1);
+ /* Initialize uB = 0 */
+ N_VConst(ZERO, uB);
+
+ /* Create and allocate CVODES memory for backward run */
+
+ printf("\nCreate and allocate CVODES memory for backward run\n");
+
+ flag = CVodeCreateB(cvode_mem, CV_BDF, CV_NEWTON, &indexB);
+ if(check_flag(&flag, "CVodeCreateB", 1)) return(1);
+
+ flag = CVodeSetUserDataB(cvode_mem, indexB, data);
+ if(check_flag(&flag, "CVodeSetUserDataB", 1)) return(1);
+
+ flag = CVodeInitB(cvode_mem, indexB, fB, TOUT, uB);
+ if(check_flag(&flag, "CVodeInitB", 1)) return(1);
+
+ flag = CVodeSStolerancesB(cvode_mem, indexB, reltolB, abstolB);
+ if(check_flag(&flag, "CVodeSStolerancesB", 1)) 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);
+
+ /* Perform backward integration */
+ printf("\nBackward integration\n");
+ flag = CVodeB(cvode_mem, T0, CV_NORMAL);
+ if(check_flag(&flag, "CVodeB", 1)) return(1);
+
+ flag = CVodeGetB(cvode_mem, indexB, &t, uB);
+ if(check_flag(&flag, "CVodeGetB", 1)) return(1);
+
+ 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 */
+
+ free(data); /* Free the user data */
+
+ return(0);
+}
+
+/*
+ *--------------------------------------------------------------------
+ * FUNCTIONS CALLED BY CVODES
+ *--------------------------------------------------------------------
+ */
+
+/*
+ * f routine. right-hand side of forward ODE.
+ */
+
+static int f(realtype t, N_Vector u, N_Vector udot, void *user_data)
+{
+ realtype uij, udn, uup, ult, urt, hordc, horac, verdc, hdiff, hadv, vdiff;
+ realtype *udata, *dudata;
+ int i, j;
+ UserData data;
+
+ udata = NV_DATA_S(u);
+ dudata = NV_DATA_S(udot);
+
+ /* Extract needed constants from data */
+
+ data = (UserData) user_data;
+ hordc = data->hdcoef;
+ horac = data->hacoef;
+ verdc = data->vdcoef;
+
+ /* Loop over all grid points. */
+
+ for (j=1; j <= MY; j++) {
+
+ for (i=1; i <= MX; i++) {
+
+ /* Extract u at x_i, y_j and four neighboring points */
+
+ 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);
+
+ /* 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);
+ IJth(dudata, i, j) = hdiff + hadv + vdiff;
+ }
+ }
+
+ return(0);
+}
+
+/*
+ * 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)
+{
+ 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);
+}
+
+/*
+ * fB function. Right-hand side of backward ODE.
+ */
+
+static int fB(realtype tB, N_Vector u, N_Vector uB, N_Vector uBdot,
+ void *user_dataB)
+{
+ UserData data;
+ realtype *uBdata, *duBdata;
+ realtype hordc, horac, verdc;
+ realtype uBij, uBdn, uBup, uBlt, uBrt;
+ realtype hdiffB, hadvB, vdiffB;
+ int i, j;
+
+ uBdata = NV_DATA_S(uB);
+ duBdata = NV_DATA_S(uBdot);
+
+ /* Extract needed constants from data */
+
+ data = (UserData) user_dataB;
+ hordc = data->hdcoef;
+ horac = data->hacoef;
+ verdc = data->vdcoef;
+
+ /* Loop over all grid points. */
+
+ for (j=1; j <= MY; j++) {
+
+ for (i=1; i <= MX; i++) {
+
+ /* Extract u at x_i, y_j and four neighboring points */
+
+ uBij = IJth(uBdata, i, j);
+ uBdn = (j == 1) ? ZERO : IJth(uBdata, i, j-1);
+ uBup = (j == MY) ? ZERO : IJth(uBdata, i, j+1);
+ uBlt = (i == 1) ? ZERO : IJth(uBdata, i-1, j);
+ uBrt = (i == MX) ? ZERO : IJth(uBdata, i+1, j);
+
+ /* Set diffusion and advection terms and load into udot */
+
+ hdiffB = hordc*(- uBlt + TWO*uBij - uBrt);
+ hadvB = horac*(uBrt - uBlt);
+ vdiffB = verdc*(- uBup + TWO*uBij - uBdn);
+ IJth(duBdata, i, j) = hdiffB + hadvB + vdiffB - ONE;
+ }
+ }
+
+ return(0);
+}
+
+/*
+ * 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)
+{
+ int i, j, k;
+ realtype *kthCol, hordc, horac, verdc;
+ UserData data;
+
+ /* The Jacobian of the adjoint system is: JB = -J^T */
+
+ data = (UserData) user_dataB;
+ 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(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;
+ }
+ }
+
+ return(0);
+}
+
+/*
+ *--------------------------------------------------------------------
+ * PRIVATE FUNCTIONS
+ *--------------------------------------------------------------------
+ */
+
+/*
+ * Set initial conditions in u vector
+ */
+
+static void SetIC(N_Vector u, UserData data)
+{
+ int i, j;
+ realtype x, y, dx, dy;
+ realtype *udata;
+
+ /* Extract needed constants from data */
+
+ dx = data->dx;
+ dy = data->dy;
+
+ /* Set pointer to data array in vector u. */
+
+ udata = NV_DATA_S(u);
+
+ /* Load initial profile into u vector */
+
+ 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)*EXP(RCONST(5.0)*x*y);
+ }
+ }
+
+}
+
+/*
+ * Print results after backward integration
+ */
+
+static void PrintOutput(N_Vector uB, UserData data)
+{
+ realtype *uBdata, uBij, uBmax, x, y, dx, dy;
+ int i, j;
+
+ x = y = ZERO;
+
+ dx = data->dx;
+ dy = data->dy;
+
+ uBdata = NV_DATA_S(uB);
+
+ uBmax = ZERO;
+ for(j=1; j<= MY; j++) {
+ for(i=1; i<=MX; i++) {
+ uBij = IJth(uBdata, i, j);
+ if (ABS(uBij) > uBmax) {
+ uBmax = uBij;
+ x = i*dx;
+ y = j*dy;
+ }
+ }
+ }
+
+ printf("\nMaximum sensitivity\n");
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf(" lambda max = %Le\n", uBmax);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf(" lambda max = %le\n", uBmax);
+#else
+ printf(" lambda max = %e\n", uBmax);
+#endif
+ printf("at\n");
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf(" x = %Le\n y = %Le\n", x, y);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf(" x = %le\n y = %le\n", x, y);
+#else
+ printf(" x = %e\n y = %e\n", x, y);
+#endif
+
+}
+
+/*
+ * 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, 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/cvsAdvDiff_ASAi_bnd.out b/examples/cvodes/serial/cvsAdvDiff_ASAi_bnd.out
new file mode 100644
index 0000000..64b15df
--- /dev/null
+++ b/examples/cvodes/serial/cvsAdvDiff_ASAi_bnd.out
@@ -0,0 +1,18 @@
+
+Create and allocate CVODES memory for forward runs
+
+Allocate global memory
+
+Forward integration
+
+ncheck = 3
+
+Create and allocate CVODES memory for backward run
+
+Backward integration
+
+Maximum sensitivity
+ lambda max = 1.128855e-01
+at
+ x = 1.170732e+00
+ y = 4.761905e-01
diff --git a/examples/cvodes/serial/cvsAdvDiff_FSA_non.c b/examples/cvodes/serial/cvsAdvDiff_FSA_non.c
new file mode 100644
index 0000000..039e16e
--- /dev/null
+++ b/examples/cvodes/serial/cvsAdvDiff_FSA_non.c
@@ -0,0 +1,523 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.2 $
+ * $Date: 2008/12/31 00:04:42 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh, George D. Byrne,
+ * and Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Example problem:
+ *
+ * The following is a simple example problem, with the program for
+ * its solution by CVODES. The problem is the semi-discrete form of
+ * the advection-diffusion equation in 1-D:
+ * du/dt = q1 * d^2 u / dx^2 + q2 * du/dx
+ * on the interval 0 <= x <= 2, and the time interval 0 <= t <= 5.
+ * Homogeneous Dirichlet boundary conditions are posed, and the
+ * initial condition is:
+ * u(x,y,t=0) = x(2-x)exp(2x).
+ * 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 option for nonstiff
+ * systems: ADAMS method and functional iteration.
+ * It uses scalar relative and absolute tolerances.
+ * Output is printed at t = .5, 1.0, ..., 5.
+ * Run statistics (optional outputs) are printed at the end.
+ *
+ * Optionally, CVODES can compute sensitivities with respect to the
+ * problem parameters q1 and q2.
+ * 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 FULL or PARTIAL,
+ * respectively).
+ *
+ * Execution:
+ *
+ * If no sensitivities are desired:
+ * % cvsAdvDiff_FSA_non -nosensi
+ * If sensitivities are to be computed:
+ * % 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>
+#include <string.h>
+#include <math.h>
+
+#include <cvodes/cvodes.h>
+#include <nvector/nvector_serial.h>
+#include <sundials/sundials_types.h>
+#include <sundials/sundials_math.h>
+
+/* Problem Constants */
+#define XMAX RCONST(2.0) /* domain boundary */
+#define MX 10 /* mesh dimension */
+#define NEQ MX /* number of equations */
+#define ATOL RCONST(1.e-5) /* scalar absolute tolerance */
+#define T0 RCONST(0.0) /* initial time */
+#define T1 RCONST(0.5) /* first output time */
+#define DTOUT RCONST(0.5) /* output time increment */
+#define NOUT 10 /* number of output times */
+
+#define NP 2
+#define NS 2
+
+#define ZERO RCONST(0.0)
+
+/* Type : UserData
+ contains problem parameters, grid constants, work array. */
+
+typedef struct {
+ realtype *p;
+ realtype dx;
+} *UserData;
+
+/* Functions Called by the CVODES Solver */
+
+static int f(realtype t, N_Vector u, N_Vector udot, void *user_data);
+
+/* Private Helper Functions */
+
+static void ProcessArgs(int argc, char *argv[],
+ booleantype *sensi, int *sensi_meth,
+ booleantype *err_con);
+static void WrongArgs(char *name);
+static void SetIC(N_Vector u, realtype dx);
+static void PrintOutput(void *cvode_mem, realtype t, N_Vector u);
+static void PrintOutputS(N_Vector *uS);
+static void PrintFinalStats(void *cvode_mem, booleantype sensi);
+
+static int check_flag(void *flagvalue, char *funcname, int opt);
+
+/*
+ *--------------------------------------------------------------------
+ * MAIN PROGRAM
+ *--------------------------------------------------------------------
+ */
+
+int main(int argc, char *argv[])
+{
+ void *cvode_mem;
+ UserData data;
+ realtype dx, reltol, abstol, t, tout;
+ N_Vector u;
+ int iout, flag;
+
+ realtype *pbar;
+ int is, *plist;
+ N_Vector *uS;
+ booleantype sensi, err_con;
+ int sensi_meth;
+
+ cvode_mem = NULL;
+ data = NULL;
+ u = NULL;
+ pbar = NULL;
+ plist = NULL;
+ uS = NULL;
+
+ /* Process arguments */
+ ProcessArgs(argc, argv, &sensi, &sensi_meth, &err_con);
+
+ /* Set user data */
+ data = (UserData) malloc(sizeof *data); /* Allocate data memory */
+ if(check_flag((void *)data, "malloc", 2)) return(1);
+ data->p = (realtype *) malloc(NP * sizeof(realtype));
+ dx = data->dx = XMAX/((realtype)(MX+1));
+ data->p[0] = RCONST(1.0);
+ data->p[1] = RCONST(0.5);
+
+ /* Allocate and set initial states */
+ u = N_VNew_Serial(NEQ);
+ if(check_flag((void *)u, "N_VNew_Serial", 0)) return(1);
+ SetIC(u, dx);
+
+ /* Set integration tolerances */
+ reltol = ZERO;
+ abstol = ATOL;
+
+ /* Create CVODES object */
+ cvode_mem = CVodeCreate(CV_ADAMS, CV_FUNCTIONAL);
+ if(check_flag((void *)cvode_mem, "CVodeCreate", 0)) return(1);
+
+ flag = CVodeSetUserData(cvode_mem, data);
+ if(check_flag(&flag, "CVodeSetUserData", 1)) return(1);
+
+ /* Allocate CVODES memory */
+ flag = CVodeInit(cvode_mem, f, T0, u);
+ if(check_flag(&flag, "CVodeInit", 1)) return(1);
+
+ flag = CVodeSStolerances(cvode_mem, reltol, abstol);
+ if(check_flag(&flag, "CVodeSStolerances", 1)) return(1);
+
+ printf("\n1-D advection-diffusion equation, mesh size =%3d\n", MX);
+
+ /* Sensitivity-related settings */
+ if(sensi) {
+
+ plist = (int *) malloc(NS * sizeof(int));
+ if(check_flag((void *)plist, "malloc", 2)) return(1);
+ for(is=0; is<NS; is++) plist[is] = is;
+
+ pbar = (realtype *) malloc(NS * sizeof(realtype));
+ 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);
+ for(is=0;is<NS;is++)
+ N_VConst(ZERO, uS[is]);
+
+ flag = CVodeSensInit1(cvode_mem, NS, sensi_meth, NULL, uS);
+ if(check_flag(&flag, "CVodeSensInit1", 1)) return(1);
+
+ flag = CVodeSensEEtolerances(cvode_mem);
+ if(check_flag(&flag, "CVodeSensEEtolerances", 1)) return(1);
+
+ flag = CVodeSetSensErrCon(cvode_mem, err_con);
+ if(check_flag(&flag, "CVodeSetSensErrCon", 1)) return(1);
+
+ flag = CVodeSetSensDQMethod(cvode_mem, CV_CENTERED, ZERO);
+ if(check_flag(&flag, "CVodeSetSensDQMethod", 1)) return(1);
+
+ flag = CVodeSetSensParams(cvode_mem, data->p, pbar, plist);
+ if(check_flag(&flag, "CVodeSetSensParams", 1)) return(1);
+
+ printf("Sensitivity: YES ");
+ if(sensi_meth == CV_SIMULTANEOUS)
+ printf("( SIMULTANEOUS +");
+ else
+ if(sensi_meth == CV_STAGGERED) printf("( STAGGERED +");
+ else printf("( STAGGERED1 +");
+ if(err_con) printf(" FULL ERROR CONTROL )");
+ else printf(" PARTIAL ERROR CONTROL )");
+
+ } else {
+
+ printf("Sensitivity: NO ");
+
+ }
+
+ /* In loop over output points, call CVode, print results, test for error */
+
+ printf("\n\n");
+ printf("============================================================\n");
+ printf(" T Q H NST Max norm \n");
+ printf("============================================================\n");
+
+ 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;
+ PrintOutput(cvode_mem, t, u);
+ if (sensi) {
+ flag = CVodeGetSens(cvode_mem, &t, uS);
+ if(check_flag(&flag, "CVodeGetSens", 1)) break;
+ PrintOutputS(uS);
+ }
+ printf("------------------------------------------------------------\n");
+ }
+
+ /* Print final statistics */
+ PrintFinalStats(cvode_mem, sensi);
+
+ /* Free memory */
+ N_VDestroy_Serial(u);
+ if (sensi) {
+ N_VDestroyVectorArray_Serial(uS, NS);
+ free(plist);
+ free(pbar);
+ }
+ free(data);
+ CVodeFree(&cvode_mem);
+
+ return(0);
+}
+
+/*
+ *--------------------------------------------------------------------
+ * FUNCTIONS CALLED BY CVODES
+ *--------------------------------------------------------------------
+ */
+
+/*
+ * f routine. Compute f(t,u).
+ */
+
+static int f(realtype t, N_Vector u, N_Vector udot, void *user_data)
+{
+ realtype ui, ult, urt, hordc, horac, hdiff, hadv;
+ realtype dx;
+ realtype *udata, *dudata;
+ int i;
+ UserData data;
+
+ udata = NV_DATA_S(u);
+ dudata = NV_DATA_S(udot);
+
+ /* Extract needed problem constants from data */
+ data = (UserData) user_data;
+ dx = data->dx;
+ hordc = data->p[0]/(dx*dx);
+ horac = data->p[1]/(RCONST(2.0)*dx);
+
+ /* Loop over all grid points. */
+ for (i=0; i<NEQ; i++) {
+
+ /* Extract u at x_i and two neighboring points */
+ ui = udata[i];
+ if(i!=0)
+ ult = udata[i-1];
+ else
+ ult = ZERO;
+ if(i!=NEQ-1)
+ urt = udata[i+1];
+ else
+ urt = ZERO;
+
+ /* Set diffusion and advection terms and load into udot */
+ hdiff = hordc*(ult - RCONST(2.0)*ui + urt);
+ hadv = horac*(urt - ult);
+ dudata[i] = hdiff + hadv;
+ }
+
+ return(0);
+}
+
+/*
+ *--------------------------------------------------------------------
+ * PRIVATE FUNCTIONS
+ *--------------------------------------------------------------------
+ */
+
+/*
+ * Process and verify arguments.
+ */
+
+static void ProcessArgs(int argc, char *argv[],
+ booleantype *sensi, int *sensi_meth, booleantype *err_con)
+{
+ *sensi = FALSE;
+ *sensi_meth = -1;
+ *err_con = FALSE;
+
+ if (argc < 2) WrongArgs(argv[0]);
+
+ if (strcmp(argv[1],"-nosensi") == 0)
+ *sensi = FALSE;
+ else if (strcmp(argv[1],"-sensi") == 0)
+ *sensi = TRUE;
+ else
+ WrongArgs(argv[0]);
+
+ if (*sensi) {
+
+ if (argc != 4)
+ WrongArgs(argv[0]);
+
+ if (strcmp(argv[2],"sim") == 0)
+ *sensi_meth = CV_SIMULTANEOUS;
+ else if (strcmp(argv[2],"stg") == 0)
+ *sensi_meth = CV_STAGGERED;
+ else if (strcmp(argv[2],"stg1") == 0)
+ *sensi_meth = CV_STAGGERED1;
+ else
+ WrongArgs(argv[0]);
+
+ if (strcmp(argv[3],"t") == 0)
+ *err_con = TRUE;
+ else if (strcmp(argv[3],"f") == 0)
+ *err_con = FALSE;
+ else
+ WrongArgs(argv[0]);
+ }
+
+}
+
+static void WrongArgs(char *name)
+{
+ printf("\nUsage: %s [-nosensi] [-sensi sensi_meth err_con]\n",name);
+ printf(" sensi_meth = sim, stg, or stg1\n");
+ printf(" err_con = t or f\n");
+
+ exit(0);
+}
+
+/*
+ * Set initial conditions in u vector.
+ */
+
+static void SetIC(N_Vector u, realtype dx)
+{
+ int i;
+ realtype x;
+ realtype *udata;
+
+ /* Set pointer to data array and get local length of u. */
+ udata = NV_DATA_S(u);
+
+ /* Load initial profile into u vector */
+ for (i=0; i<NEQ; i++) {
+ x = (i+1)*dx;
+ udata[i] = x*(XMAX - x)*EXP(RCONST(2.0)*x);
+ }
+}
+
+/*
+ * Print current t, step count, order, stepsize, and max norm of solution
+ */
+
+static void PrintOutput(void *cvode_mem, realtype t, N_Vector u)
+{
+ long int nst;
+ int qu, flag;
+ realtype hu;
+
+ flag = CVodeGetNumSteps(cvode_mem, &nst);
+ check_flag(&flag, "CVodeGetNumSteps", 1);
+ flag = CVodeGetLastOrder(cvode_mem, &qu);
+ check_flag(&flag, "CVodeGetLastOrder", 1);
+ flag = CVodeGetLastStep(cvode_mem, &hu);
+ check_flag(&flag, "CVodeGetLastStep", 1);
+
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("%8.3Le %2d %8.3Le %5ld\n", t, qu, hu ,nst);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("%8.3le %2d %8.3le %5ld\n", t, qu, hu ,nst);
+#else
+ printf("%8.3e %2d %8.3e %5ld\n", t, qu, hu ,nst);
+#endif
+
+ printf(" Solution ");
+
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("%12.4Le \n", N_VMaxNorm(u));
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("%12.4le \n", N_VMaxNorm(u));
+#else
+ printf("%12.4e \n", N_VMaxNorm(u));
+#endif
+}
+
+/*
+ * Print max norm of sensitivities
+ */
+
+static void PrintOutputS(N_Vector *uS)
+{
+ printf(" Sensitivity 1 ");
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("%12.4Le \n", N_VMaxNorm(uS[0]));
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("%12.4le \n", N_VMaxNorm(uS[0]));
+#else
+ printf("%12.4e \n", N_VMaxNorm(uS[0]));
+#endif
+
+ printf(" Sensitivity 2 ");
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("%12.4Le \n", N_VMaxNorm(uS[1]));
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("%12.4le \n", N_VMaxNorm(uS[1]));
+#else
+ printf("%12.4e \n", N_VMaxNorm(uS[1]));
+#endif
+}
+
+
+/*
+ * Print some final statistics located in the CVODES memory
+ */
+
+static void PrintFinalStats(void *cvode_mem, booleantype sensi)
+{
+ long int nst;
+ long int nfe, nsetups, nni, ncfn, netf;
+ long int nfSe, nfeS, nsetupsS, nniS, ncfnS, netfS;
+ int flag;
+
+ 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);
+
+ if (sensi) {
+ flag = CVodeGetSensNumRhsEvals(cvode_mem, &nfSe);
+ check_flag(&flag, "CVodeGetSensNumRhsEvals", 1);
+ flag = CVodeGetNumRhsEvalsSens(cvode_mem, &nfeS);
+ check_flag(&flag, "CVodeGetNumRhsEvalsSens", 1);
+ flag = CVodeGetSensNumLinSolvSetups(cvode_mem, &nsetupsS);
+ check_flag(&flag, "CVodeGetSensNumLinSolvSetups", 1);
+ flag = CVodeGetSensNumErrTestFails(cvode_mem, &netfS);
+ check_flag(&flag, "CVodeGetSensNumErrTestFails", 1);
+ flag = CVodeGetSensNumNonlinSolvIters(cvode_mem, &nniS);
+ check_flag(&flag, "CVodeGetSensNumNonlinSolvIters", 1);
+ flag = CVodeGetSensNumNonlinSolvConvFails(cvode_mem, &ncfnS);
+ check_flag(&flag, "CVodeGetSensNumNonlinSolvConvFails", 1);
+ }
+
+ printf("\nFinal Statistics\n\n");
+ printf("nst = %5ld\n\n", nst);
+ printf("nfe = %5ld\n", nfe);
+ printf("netf = %5ld nsetups = %5ld\n", netf, nsetups);
+ printf("nni = %5ld ncfn = %5ld\n", nni, ncfn);
+
+ if(sensi) {
+ printf("\n");
+ printf("nfSe = %5ld nfeS = %5ld\n", nfSe, nfeS);
+ printf("netfs = %5ld nsetupsS = %5ld\n", netfS, nsetupsS);
+ printf("nniS = %5ld ncfnS = %5ld\n", nniS, ncfnS);
+ }
+
+}
+
+/*
+ * 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, 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/cvsAdvDiff_FSA_non.out b/examples/cvodes/serial/cvsAdvDiff_FSA_non.out
new file mode 100644
index 0000000..4cb83ad
--- /dev/null
+++ b/examples/cvodes/serial/cvsAdvDiff_FSA_non.out
@@ -0,0 +1,69 @@
+
+1-D advection-diffusion equation, mesh size = 10
+Sensitivity: YES ( SIMULTANEOUS + FULL ERROR CONTROL )
+
+============================================================
+ T Q H NST Max norm
+============================================================
+5.000e-01 4 7.656e-03 115
+ Solution 3.0529e+00
+ Sensitivity 1 3.8668e+00
+ Sensitivity 2 6.2020e-01
+------------------------------------------------------------
+1.000e+00 4 9.525e-03 182
+ 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
+ Sensitivity 1 9.1825e-01
+ Sensitivity 2 7.3922e-02
+------------------------------------------------------------
+2.000e+00 2 1.271e-02 330
+ Solution 7.1097e-02
+ Sensitivity 1 3.4667e-01
+ Sensitivity 2 2.8228e-02
+------------------------------------------------------------
+2.500e+00 2 1.629e-02 402
+ Solution 2.0260e-02
+ Sensitivity 1 1.2301e-01
+ Sensitivity 2 1.0085e-02
+------------------------------------------------------------
+3.000e+00 2 3.820e-03 473
+ Solution 5.7734e-03
+ Sensitivity 1 4.1956e-02
+ Sensitivity 2 3.4556e-03
+------------------------------------------------------------
+3.500e+00 2 8.988e-03 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.500e+00 3 4.744e-03 680
+ Solution 1.3422e-04
+ Sensitivity 1 1.4548e-03
+ Sensitivity 2 1.2589e-04
+------------------------------------------------------------
+5.000e+00 1 4.010e-03 757
+ Solution 3.8656e-05
+ Sensitivity 1 4.6451e-04
+ Sensitivity 2 4.0616e-05
+------------------------------------------------------------
+
+Final Statistics
+
+nst = 757
+
+nfe = 1373
+netf = 1 nsetups = 0
+nni = 1369 ncfn = 117
+
+nfSe = 2746 nfeS = 5492
+netfs = 0 nsetupsS = 0
+nniS = 0 ncfnS = 0
diff --git a/examples/cvodes/serial/cvsAdvDiff_bnd.c b/examples/cvodes/serial/cvsAdvDiff_bnd.c
new file mode 100644
index 0000000..2a8fba3
--- /dev/null
+++ b/examples/cvodes/serial/cvsAdvDiff_bnd.c
@@ -0,0 +1,424 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.2 $
+ * $Date: 2010/12/01 22:57:59 $
+ * -----------------------------------------------------------------
+ * Programmer(s): 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>
+
+/* 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 */
+
+/* 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 */
+#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)
+
+/* 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 = NV_DATA_S(v),
+ where v is an N_Vector.
+ The variables are ordered by the y index j, then by the x index i. */
+
+#define IJth(vdata,i,j) (vdata[(j-1) + (i-1)*MY])
+
+/* Type : UserData (contains grid constants) */
+
+typedef struct {
+ realtype dx, dy, hdcoef, hacoef, vdcoef;
+} *UserData;
+
+/* Private Helper Functions */
+
+static void SetIC(N_Vector u, UserData data);
+static void PrintHeader(realtype reltol, realtype abstol, realtype umax);
+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, 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);
+
+/*
+ *-------------------------------
+ * Main Program
+ *-------------------------------
+ */
+
+int main(void)
+{
+ realtype dx, dy, reltol, abstol, t, tout, umax;
+ N_Vector u;
+ UserData data;
+ void *cvode_mem;
+ int iout, flag;
+ long int nst;
+
+ u = NULL;
+ data = 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);
+
+ reltol = ZERO; /* Set the tolerances */
+ 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);
+
+ 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 inital 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);
+
+ /* Call CVBand to specify the CVBAND band linear solver */
+ flag = CVBand(cvode_mem, NEQ, MY, MY);
+ if(check_flag(&flag, "CVBand", 1)) return(1);
+
+ /* Set the user-supplied Jacobian routine Jac */
+ flag = CVDlsSetBandJacFn(cvode_mem, Jac);
+ if(check_flag(&flag, "CVDlsSetBandJacFn", 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) {
+ 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_Serial(u); /* Free the u vector */
+ CVodeFree(&cvode_mem); /* Free the integrator memory */
+ free(data); /* Free the user data */
+
+ return(0);
+}
+
+/*
+ *-------------------------------
+ * 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)
+{
+ realtype uij, udn, uup, ult, urt, hordc, horac, verdc, hdiff, hadv, vdiff;
+ realtype *udata, *dudata;
+ int i, j;
+ UserData data;
+
+ udata = NV_DATA_S(u);
+ dudata = NV_DATA_S(udot);
+
+ /* Extract needed constants from data */
+
+ data = (UserData) user_data;
+ hordc = data->hdcoef;
+ horac = data->hacoef;
+ verdc = data->vdcoef;
+
+ /* Loop over all grid points. */
+
+ for (j=1; j <= MY; j++) {
+
+ for (i=1; i <= MX; i++) {
+
+ /* Extract u at x_i, y_j and four neighboring points */
+
+ 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);
+
+ /* 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);
+ IJth(dudata, i, j) = hdiff + hadv + vdiff;
+ }
+ }
+
+ return(0);
+}
+
+/* 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
+ *-------------------------------
+ */
+
+/* Set initial conditions in u vector */
+
+static void SetIC(N_Vector u, UserData data)
+{
+ int i, j;
+ realtype x, y, dx, dy;
+ realtype *udata;
+
+ /* Extract needed constants from data */
+
+ dx = data->dx;
+ dy = data->dy;
+
+ /* Set pointer to data array in vector u. */
+
+ udata = NV_DATA_S(u);
+
+ /* Load initial profile into u vector */
+
+ 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)*EXP(FIVE*x*y);
+ }
+ }
+}
+
+/* Print first lines of output (problem description) */
+
+static void PrintHeader(realtype reltol, realtype abstol, realtype umax)
+{
+ printf("\n2-D Advection-Diffusion Equation\n");
+ 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("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);
+#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.6le 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)
+{
+ int flag;
+ long int nst, nfe, nsetups, netf, nni, ncfn, nje, nfeLS;
+
+ 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 = 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);
+
+ 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, 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/cvsAdvDiff_bnd.out b/examples/cvodes/serial/cvsAdvDiff_bnd.out
new file mode 100644
index 0000000..c48de03
--- /dev/null
+++ b/examples/cvodes/serial/cvsAdvDiff_bnd.out
@@ -0,0 +1,22 @@
+
+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.132889e+00 nst = 85
+At t = 0.20 max.norm(u) = 1.039294e+00 nst = 103
+At t = 0.30 max.norm(u) = 2.979829e-01 nst = 113
+At t = 0.40 max.norm(u) = 8.765774e-02 nst = 120
+At t = 0.50 max.norm(u) = 2.625637e-02 nst = 126
+At t = 0.60 max.norm(u) = 7.830425e-03 nst = 130
+At t = 0.70 max.norm(u) = 2.329387e-03 nst = 134
+At t = 0.80 max.norm(u) = 6.953434e-04 nst = 137
+At t = 0.90 max.norm(u) = 2.115983e-04 nst = 140
+At t = 1.00 max.norm(u) = 6.556853e-05 nst = 142
+
+Final Statistics:
+nst = 142 nfe = 174 nsetups = 23 nfeLS = 0 nje = 3
+nni = 170 ncfn = 0 netf = 3
+
diff --git a/examples/cvodes/serial/cvsAdvDiff_bndL.c b/examples/cvodes/serial/cvsAdvDiff_bndL.c
new file mode 100644
index 0000000..a592980
--- /dev/null
+++ b/examples/cvodes/serial/cvsAdvDiff_bndL.c
@@ -0,0 +1,421 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.3 $
+ * $Date: 2010/12/01 22:57:59 $
+ * -----------------------------------------------------------------
+ * Programmer(s): 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 LAPACK 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>
+
+/* 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 */
+
+/* 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 */
+#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)
+
+/* 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 = NV_DATA_S(v),
+ where v is an N_Vector.
+ The variables are ordered by the y index j, then by the x index i. */
+
+#define IJth(vdata,i,j) (vdata[(j-1) + (i-1)*MY])
+
+/* Type : UserData (contains grid constants) */
+
+typedef struct {
+ realtype dx, dy, hdcoef, hacoef, vdcoef;
+} *UserData;
+
+/* Private Helper Functions */
+
+static void SetIC(N_Vector u, UserData data);
+static void PrintHeader(realtype reltol, realtype abstol, realtype umax);
+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, 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);
+
+/*
+ *-------------------------------
+ * Main Program
+ *-------------------------------
+ */
+
+int main(void)
+{
+ realtype dx, dy, reltol, abstol, t, tout, umax;
+ N_Vector u;
+ UserData data;
+ void *cvode_mem;
+ int iout, flag;
+ long int nst;
+
+ u = NULL;
+ data = 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);
+
+ reltol = ZERO; /* Set the tolerances */
+ 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);
+
+ 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 inital 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);
+
+ /* Call CVLapackBand to specify the CVBAND band linear solver */
+ flag = CVLapackBand(cvode_mem, NEQ, MY, MY);
+ if(check_flag(&flag, "CVLapackBand", 1)) return(1);
+
+ /* Set the user-supplied Jacobian routine Jac */
+ flag = CVDlsSetBandJacFn(cvode_mem, Jac);
+ if(check_flag(&flag, "CVDlsSetBandJacFn", 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) {
+ 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_Serial(u); /* Free the u vector */
+ CVodeFree(&cvode_mem); /* Free the integrator memory */
+ free(data); /* Free the user data */
+
+ return(0);
+}
+
+/*
+ *-------------------------------
+ * 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)
+{
+ realtype uij, udn, uup, ult, urt, hordc, horac, verdc, hdiff, hadv, vdiff;
+ realtype *udata, *dudata;
+ int i, j;
+ UserData data;
+
+ udata = NV_DATA_S(u);
+ dudata = NV_DATA_S(udot);
+
+ /* Extract needed constants from data */
+
+ data = (UserData) user_data;
+ hordc = data->hdcoef;
+ horac = data->hacoef;
+ verdc = data->vdcoef;
+
+ /* Loop over all grid points. */
+
+ for (j=1; j <= MY; j++) {
+
+ for (i=1; i <= MX; i++) {
+
+ /* Extract u at x_i, y_j and four neighboring points */
+
+ 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);
+
+ /* 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);
+ IJth(dudata, i, j) = hdiff + hadv + vdiff;
+ }
+ }
+
+ return(0);
+}
+
+/* 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)
+{
+ 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;
+
+ /* 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);
+
+ /* 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
+ *-------------------------------
+ */
+
+/* Set initial conditions in u vector */
+
+static void SetIC(N_Vector u, UserData data)
+{
+ int i, j;
+ realtype x, y, dx, dy;
+ realtype *udata;
+
+ /* Extract needed constants from data */
+
+ dx = data->dx;
+ dy = data->dy;
+
+ /* Set pointer to data array in vector u. */
+
+ udata = NV_DATA_S(u);
+
+ /* Load initial profile into u vector */
+
+ 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)*EXP(FIVE*x*y);
+ }
+ }
+}
+
+/* Print first lines of output (problem description) */
+
+static void PrintHeader(realtype reltol, realtype abstol, realtype umax)
+{
+ printf("\n2-D Advection-Diffusion Equation\n");
+ 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("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);
+#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.6le 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)
+{
+ int flag;
+ long int nst, nfe, nsetups, netf, nni, ncfn, nje, nfeLS;
+
+ 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 = 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);
+
+ 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, 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/cvsAdvDiff_bndL.out b/examples/cvodes/serial/cvsAdvDiff_bndL.out
new file mode 100644
index 0000000..c48de03
--- /dev/null
+++ b/examples/cvodes/serial/cvsAdvDiff_bndL.out
@@ -0,0 +1,22 @@
+
+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.132889e+00 nst = 85
+At t = 0.20 max.norm(u) = 1.039294e+00 nst = 103
+At t = 0.30 max.norm(u) = 2.979829e-01 nst = 113
+At t = 0.40 max.norm(u) = 8.765774e-02 nst = 120
+At t = 0.50 max.norm(u) = 2.625637e-02 nst = 126
+At t = 0.60 max.norm(u) = 7.830425e-03 nst = 130
+At t = 0.70 max.norm(u) = 2.329387e-03 nst = 134
+At t = 0.80 max.norm(u) = 6.953434e-04 nst = 137
+At t = 0.90 max.norm(u) = 2.115983e-04 nst = 140
+At t = 1.00 max.norm(u) = 6.556853e-05 nst = 142
+
+Final Statistics:
+nst = 142 nfe = 174 nsetups = 23 nfeLS = 0 nje = 3
+nni = 170 ncfn = 0 netf = 3
+
diff --git a/examples/cvodes/serial/cvsDirectDemo_ls.c b/examples/cvodes/serial/cvsDirectDemo_ls.c
new file mode 100644
index 0000000..3de9d66
--- /dev/null
+++ b/examples/cvodes/serial/cvsDirectDemo_ls.c
@@ -0,0 +1,789 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.2 $
+ * $Date: 2010/12/01 22:57:59 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh and
+ * Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Demonstration program for CVODE - direct linear solvers.
+ * Two separate problems are solved using both the CV_ADAMS and CV_BDF
+ * linear multistep methods in combination with CV_FUNCTIONAL and
+ * CV_NEWTON iterations:
+ *
+ * Problem 1: Van der Pol oscillator
+ * xdotdot - 3*(1 - x^2)*xdot + x = 0, x(0) = 2, xdot(0) = 0.
+ * This second-order ODE is converted to a first-order system by
+ * defining y0 = x and y1 = xdot.
+ * The NEWTON iteration cases use the following types of Jacobian
+ * approximation: (1) dense, user-supplied, (2) dense, difference
+ * quotient approximation, (3) diagonal approximation.
+ *
+ * Problem 2: ydot = A * y, where A is a banded lower triangular
+ * matrix derived from 2-D advection PDE.
+ * The NEWTON iteration cases use the following types of Jacobian
+ * approximation: (1) band, user-supplied, (2) band, difference
+ * quotient approximation, (3) diagonal approximation.
+ *
+ * For each problem, in the series of eight runs, CVodeInit is
+ * called only once, for the first run, whereas CVodeReInit is
+ * called for each of the remaining seven runs.
+ *
+ * Notes: This program demonstrates the usage of the sequential
+ * macros NV_Ith_S, NV_DATA_S, DENSE_ELEM, BAND_COL, and
+ * BAND_COL_ELEM. 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 NV_DATA_S
+ * macro 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 NV_DATA_S
+ * macro 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 NV_DATA_S macro. 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.
+ * -----------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#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, SQR, and EXP*/
+
+/* Shared Problem Constants */
+
+#define ATOL RCONST(1.0e-6)
+#define RTOL RCONST(0.0)
+
+#define ZERO RCONST(0.0)
+#define ONE RCONST(1.0)
+#define TWO RCONST(2.0)
+#define THIRTY RCONST(30.0)
+
+/* Problem #1 Constants */
+
+#define P1_NEQ 2
+#define P1_ETA RCONST(3.0)
+#define P1_NOUT 4
+#define P1_T0 RCONST(0.0)
+#define P1_T1 RCONST(1.39283880203)
+#define P1_DTOUT RCONST(2.214773875)
+#define P1_TOL_FACTOR RCONST(1.0e4)
+
+/* Problem #2 Constants */
+
+#define P2_MESHX 5
+#define P2_MESHY 5
+#define P2_NEQ P2_MESHX*P2_MESHY
+#define P2_ALPH1 RCONST(1.0)
+#define P2_ALPH2 RCONST(1.0)
+#define P2_NOUT 5
+#define P2_ML 5
+#define P2_MU 0
+#define P2_T0 RCONST(0.0)
+#define P2_T1 RCONST(0.01)
+#define P2_TOUT_MULT RCONST(10.0)
+#define P2_TOL_FACTOR RCONST(1.0e3)
+
+/* Linear Solver Options */
+
+enum {FUNC, DENSE_USER, DENSE_DQ, DIAG, BAND_USER, BAND_DQ};
+
+/* Private Helper Functions */
+
+static int Problem1(void);
+static void PrintIntro1(void);
+static void PrintHeader1(void);
+static void PrintOutput1(realtype t, realtype y0, realtype y1, int qu, realtype hu);
+static int Problem2(void);
+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 void PrintErrOutput(realtype tol_factor);
+static void PrintFinalStats(void *cvode_mem, int miter, realtype ero);
+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 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,
+ N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
+
+/* Private function to check function return values */
+
+static int check_flag(void *flagvalue, char *funcname, int opt);
+
+/* Implementation */
+
+int main(void)
+{
+ int nerr;
+
+ nerr = Problem1();
+ nerr += Problem2();
+ PrintErrInfo(nerr);
+
+ return(0);
+}
+
+static int Problem1(void)
+{
+ realtype reltol=RTOL, abstol=ATOL, t, tout, ero, er;
+ int miter, flag, temp_flag, iout, nerr=0;
+ N_Vector y;
+ void *cvode_mem;
+ booleantype firstrun;
+ int qu;
+ realtype hu;
+
+ y = NULL;
+ cvode_mem = NULL;
+
+ y = N_VNew_Serial(P1_NEQ);
+ if(check_flag((void *)y, "N_VNew_Serial", 0)) return(1);
+ PrintIntro1();
+
+ cvode_mem = CVodeCreate(CV_ADAMS, CV_FUNCTIONAL);
+ if(check_flag((void *)cvode_mem, "CVodeCreate", 0)) return(1);
+
+ for (miter=FUNC; miter <= DIAG; miter++) {
+ ero = ZERO;
+ NV_Ith_S(y,0) = TWO;
+ NV_Ith_S(y,1) = ZERO;
+
+ firstrun = (miter==FUNC);
+ if (firstrun) {
+ flag = CVodeInit(cvode_mem, f1, P1_T0, y);
+ if(check_flag(&flag, "CVodeInit", 1)) return(1);
+ flag = CVodeSStolerances(cvode_mem, reltol, abstol);
+ if(check_flag(&flag, "CVodeSStolerances", 1)) return(1);
+ } else {
+ flag = CVodeSetIterType(cvode_mem, CV_NEWTON);
+ if(check_flag(&flag, "CVodeSetIterType", 1)) ++nerr;
+ flag = CVodeReInit(cvode_mem, P1_T0, y);
+ if(check_flag(&flag, "CVodeReInit", 1)) return(1);
+ }
+
+ flag = PrepareNextRun(cvode_mem, CV_ADAMS, miter, 0, 0);
+ if(check_flag(&flag, "PrepareNextRun", 1)) return(1);
+
+ PrintHeader1();
+
+ for(iout=1, tout=P1_T1; iout <= P1_NOUT; iout++, tout += P1_DTOUT) {
+ flag = CVode(cvode_mem, tout, y, &t, CV_NORMAL);
+ check_flag(&flag, "CVode", 1);
+ temp_flag = CVodeGetLastOrder(cvode_mem, &qu);
+ if(check_flag(&temp_flag, "CVodeGetLastOrder", 1)) ++nerr;
+ temp_flag = CVodeGetLastStep(cvode_mem, &hu);
+ if(check_flag(&temp_flag, "CVodeGetLastStep", 1)) ++nerr;
+ PrintOutput1(t, NV_Ith_S(y,0), NV_Ith_S(y,1), qu, hu);
+ if (flag != CV_SUCCESS) {
+ nerr++;
+ break;
+ }
+ if (iout%2 == 0) {
+ er = ABS(NV_Ith_S(y,0)) / abstol;
+ if (er > ero) ero = er;
+ if (er > P1_TOL_FACTOR) {
+ nerr++;
+ PrintErrOutput(P1_TOL_FACTOR);
+ }
+ }
+ }
+
+ PrintFinalStats(cvode_mem, miter, ero);
+ }
+
+ CVodeFree(&cvode_mem);
+
+ cvode_mem = CVodeCreate(CV_BDF, CV_FUNCTIONAL);
+ if(check_flag((void *)cvode_mem, "CVodeCreate", 0)) return(1);
+
+ for (miter=FUNC; miter <= DIAG; miter++) {
+ ero = ZERO;
+ NV_Ith_S(y,0) = TWO;
+ NV_Ith_S(y,1) = ZERO;
+
+ firstrun = (miter==FUNC);
+ if (firstrun) {
+ flag = CVodeInit(cvode_mem, f1, P1_T0, y);
+ if(check_flag(&flag, "CVodeInit", 1)) return(1);
+ flag = CVodeSStolerances(cvode_mem, reltol, abstol);
+ if(check_flag(&flag, "CVodeSStolerances", 1)) return(1);
+ } else {
+ flag = CVodeSetIterType(cvode_mem, CV_NEWTON);
+ if(check_flag(&flag, "CVodeSetIterType", 1)) ++nerr;
+ flag = CVodeReInit(cvode_mem, P1_T0, y);
+ if(check_flag(&flag, "CVodeReInit", 1)) return(1);
+ }
+
+ flag = PrepareNextRun(cvode_mem, CV_BDF, miter, 0, 0);
+ if(check_flag(&flag, "PrepareNextRun", 1)) return(1);
+
+ PrintHeader1();
+
+ for(iout=1, tout=P1_T1; iout <= P1_NOUT; iout++, tout += P1_DTOUT) {
+ flag = CVode(cvode_mem, tout, y, &t, CV_NORMAL);
+ check_flag(&flag, "CVode", 1);
+ temp_flag = CVodeGetLastOrder(cvode_mem, &qu);
+ if(check_flag(&temp_flag, "CVodeGetLastOrder", 1)) ++nerr;
+ temp_flag = CVodeGetLastStep(cvode_mem, &hu);
+ if(check_flag(&temp_flag, "CVodeGetLastStep", 1)) ++nerr;
+ PrintOutput1(t, NV_Ith_S(y,0), NV_Ith_S(y,1), qu, hu);
+ if (flag != CV_SUCCESS) {
+ nerr++;
+ break;
+ }
+ if (iout%2 == 0) {
+ er = ABS(NV_Ith_S(y,0)) / abstol;
+ if (er > ero) ero = er;
+ if (er > P1_TOL_FACTOR) {
+ nerr++;
+ PrintErrOutput(P1_TOL_FACTOR);
+ }
+ }
+ }
+
+ PrintFinalStats(cvode_mem, miter, ero);
+ }
+
+ CVodeFree(&cvode_mem);
+ N_VDestroy_Serial(y);
+
+ return(nerr);
+}
+
+static void PrintIntro1(void)
+{
+ printf("Demonstration program for CVODE package - direct linear solvers\n");
+ printf("\n\n");
+ printf("Problem 1: Van der Pol oscillator\n");
+ printf(" xdotdot - 3*(1 - x^2)*xdot + x = 0, x(0) = 2, xdot(0) = 0\n");
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf(" neq = %d, reltol = %.2Lg, abstol = %.2Lg",
+ P1_NEQ, RTOL, ATOL);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf(" neq = %d, reltol = %.2lg, abstol = %.2lg",
+ P1_NEQ, RTOL, ATOL);
+#else
+ printf(" neq = %d, reltol = %.2g, abstol = %.2g",
+ P1_NEQ, RTOL, ATOL);
+#endif
+}
+
+static void PrintHeader1(void)
+{
+ printf("\n t x xdot qu hu \n");
+
+ return;
+}
+
+static void PrintOutput1(realtype t, realtype y0, realtype y1, int qu, realtype hu)
+{
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("%10.5Lf %12.5Le %12.5Le %2d %6.4Le\n", t, y0, y1, qu, hu);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("%10.5f %12.5le %12.5le %2d %6.4le\n", t, y0, y1, qu, hu);
+#else
+ printf("%10.5f %12.5e %12.5e %2d %6.4e\n", t, y0, y1, qu, hu);
+#endif
+
+ return;
+}
+
+static int f1(realtype t, N_Vector y, N_Vector ydot, void *user_data)
+{
+ realtype y0, y1;
+
+ y0 = NV_Ith_S(y,0);
+ y1 = NV_Ith_S(y,1);
+
+ NV_Ith_S(ydot,0) = y1;
+ NV_Ith_S(ydot,1) = (ONE - SQR(y0))* P1_ETA * y1 - y0;
+
+ 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)
+{
+ 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 - SQR(y0));
+
+ return(0);
+}
+
+static int Problem2(void)
+{
+ realtype reltol=RTOL, abstol=ATOL, t, tout, er, erm, ero;
+ int miter, flag, temp_flag, nerr=0;
+ N_Vector y;
+ void *cvode_mem;
+ booleantype firstrun;
+ int qu, iout;
+ realtype hu;
+
+ y = NULL;
+ cvode_mem = NULL;
+
+ y = N_VNew_Serial(P2_NEQ);
+ if(check_flag((void *)y, "N_VNew", 0)) return(1);
+
+ PrintIntro2();
+
+ cvode_mem = CVodeCreate(CV_ADAMS, CV_FUNCTIONAL);
+ if(check_flag((void *)cvode_mem, "CVodeCreate", 0)) return(1);
+
+ for (miter=FUNC; miter <= BAND_DQ; miter++) {
+ if ((miter==DENSE_USER) || (miter==DENSE_DQ)) continue;
+ ero = ZERO;
+ N_VConst(ZERO, y);
+ NV_Ith_S(y,0) = ONE;
+
+ firstrun = (miter==FUNC);
+ if (firstrun) {
+ flag = CVodeInit(cvode_mem, f2, P2_T0, y);
+ if(check_flag(&flag, "CVodeInit", 1)) return(1);
+ flag = CVodeSStolerances(cvode_mem, reltol, abstol);
+ if(check_flag(&flag, "CVodeSStolerances", 1)) return(1);
+ } else {
+ flag = CVodeSetIterType(cvode_mem, CV_NEWTON);
+ if(check_flag(&flag, "CVodeSetIterType", 1)) ++nerr;
+ flag = CVodeReInit(cvode_mem, P2_T0, y);
+ if(check_flag(&flag, "CVodeReInit", 1)) return(1);
+ }
+
+ flag = PrepareNextRun(cvode_mem, CV_ADAMS, miter, P2_MU, P2_ML);
+ if(check_flag(&flag, "PrepareNextRun", 1)) return(1);
+
+ PrintHeader2();
+
+ for(iout=1, tout=P2_T1; iout <= P2_NOUT; iout++, tout*=P2_TOUT_MULT) {
+ flag = CVode(cvode_mem, tout, y, &t, CV_NORMAL);
+ check_flag(&flag, "CVode", 1);
+ erm = MaxError(y, t);
+ temp_flag = CVodeGetLastOrder(cvode_mem, &qu);
+ if(check_flag(&temp_flag, "CVodeGetLastOrder", 1)) ++nerr;
+ temp_flag = CVodeGetLastStep(cvode_mem, &hu);
+ if(check_flag(&temp_flag, "CVodeGetLastStep", 1)) ++nerr;
+ PrintOutput2(t, erm, qu, hu);
+ if (flag != CV_SUCCESS) {
+ nerr++;
+ break;
+ }
+ er = erm / abstol;
+ if (er > ero) ero = er;
+ if (er > P2_TOL_FACTOR) {
+ nerr++;
+ PrintErrOutput(P2_TOL_FACTOR);
+ }
+ }
+
+ PrintFinalStats(cvode_mem, miter, ero);
+ }
+
+ CVodeFree(&cvode_mem);
+
+ cvode_mem = CVodeCreate(CV_BDF, CV_FUNCTIONAL);
+ if(check_flag((void *)cvode_mem, "CVodeCreate", 0)) return(1);
+
+ for (miter=FUNC; miter <= BAND_DQ; miter++) {
+ if ((miter==DENSE_USER) || (miter==DENSE_DQ)) continue;
+ ero = ZERO;
+ N_VConst(ZERO, y);
+ NV_Ith_S(y,0) = ONE;
+
+ firstrun = (miter==FUNC);
+ if (firstrun) {
+ flag = CVodeInit(cvode_mem, f2, P2_T0, y);
+ if(check_flag(&flag, "CVodeInit", 1)) return(1);
+ flag = CVodeSStolerances(cvode_mem, reltol, abstol);
+ if(check_flag(&flag, "CVodeSStolerances", 1)) return(1);
+ } else {
+ flag = CVodeSetIterType(cvode_mem, CV_NEWTON);
+ if(check_flag(&flag, "CVodeSetIterType", 1)) ++nerr;
+ flag = CVodeReInit(cvode_mem, P2_T0, y);
+ if(check_flag(&flag, "CVodeReInit", 1)) return(1);
+ }
+
+ flag = PrepareNextRun(cvode_mem, CV_BDF, miter, P2_MU, P2_ML);
+ if(check_flag(&flag, "PrepareNextRun", 1)) return(1);
+
+ PrintHeader2();
+
+ for(iout=1, tout=P2_T1; iout <= P2_NOUT; iout++, tout*=P2_TOUT_MULT) {
+ flag = CVode(cvode_mem, tout, y, &t, CV_NORMAL);
+ check_flag(&flag, "CVode", 1);
+ erm = MaxError(y, t);
+ temp_flag = CVodeGetLastOrder(cvode_mem, &qu);
+ if(check_flag(&temp_flag, "CVodeGetLastOrder", 1)) ++nerr;
+ temp_flag = CVodeGetLastStep(cvode_mem, &hu);
+ if(check_flag(&temp_flag, "CVodeGetLastStep", 1)) ++nerr;
+ PrintOutput2(t, erm, qu, hu);
+ if (flag != CV_SUCCESS) {
+ nerr++;
+ break;
+ }
+ er = erm / abstol;
+ if (er > ero) ero = er;
+ if (er > P2_TOL_FACTOR) {
+ nerr++;
+ PrintErrOutput(P2_TOL_FACTOR);
+ }
+ }
+
+ PrintFinalStats(cvode_mem, miter, ero);
+ }
+
+ CVodeFree(&cvode_mem);
+ N_VDestroy_Serial(y);
+
+ return(nerr);
+}
+
+static void PrintIntro2(void)
+{
+ printf("\n\n-------------------------------------------------------------");
+ printf("\n-------------------------------------------------------------");
+ printf("\n\nProblem 2: ydot = A * y, where A is a banded lower\n");
+ printf("triangular matrix derived from 2-D advection PDE\n\n");
+ printf(" neq = %d, ml = %d, mu = %d\n", P2_NEQ, P2_ML, P2_MU);
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf(" itol = %s, reltol = %.2Lg, abstol = %.2Lg", "CV_SS", RTOL, ATOL);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf(" itol = %s, reltol = %.2lg, abstol = %.2lg", "CV_SS", RTOL, ATOL);
+#else
+ printf(" itol = %s, reltol = %.2g, abstol = %.2g", "CV_SS", RTOL, ATOL);
+#endif
+ printf("\n t max.err qu hu \n");
+}
+
+static void PrintHeader2(void)
+{
+ printf("\n t max.err qu hu \n");
+
+ return;
+}
+
+static void PrintOutput2(realtype t, realtype erm, int qu, realtype hu)
+{
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("%10.3Lf %12.4Le %2d %12.4Le\n", t, erm, qu, hu);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("%10.3f %12.4le %2d %12.4le\n", t, erm, qu, hu);
+#else
+ printf("%10.3f %12.4e %2d %12.4e\n", t, erm, qu, hu);
+#endif
+
+ return;
+}
+
+static int f2(realtype t, N_Vector y, N_Vector ydot, void *user_data)
+{
+ long int i, j, k;
+ realtype d, *ydata, *dydata;
+
+ ydata = NV_DATA_S(y);
+ dydata = NV_DATA_S(ydot);
+
+ /*
+ Excluding boundaries,
+
+ ydot = f = -2 y + alpha1 * y + alpha2 * y
+ i,j i,j i,j i-1,j i,j-1
+ */
+
+ for (j=0; j < P2_MESHY; j++) {
+ for (i=0; i < P2_MESHX; i++) {
+ k = i + j * P2_MESHX;
+ d = -TWO*ydata[k];
+ if (i != 0) d += P2_ALPH1 * ydata[k-1];
+ if (j != 0) d += P2_ALPH2 * ydata[k-P2_MESHX];
+ dydata[k] = d;
+ }
+ }
+
+ 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)
+{
+ int i, j, k;
+ realtype *kthCol;
+
+ /*
+ The components of f(t,y) which depend on y are
+ i,j
+ f , f , and f :
+ i,j i+1,j i,j+1
+
+ f = -2 y + alpha1 * y + alpha2 * y
+ i,j i,j i-1,j i,j-1
+
+ f = -2 y + alpha1 * y + alpha2 * y
+ i+1,j i+1,j i,j i+1,j-1
+
+ f = -2 y + alpha1 * y + alpha2 * y
+ i,j+1 i,j+1 i-1,j+1 i,j
+ */
+
+ 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;
+ }
+ }
+
+ return(0);
+}
+
+static realtype MaxError(N_Vector y, realtype t)
+{
+ long int i, j, k;
+ realtype *ydata, er, ex=ZERO, yt, maxError=ZERO, ifact_inv, jfact_inv=ONE;
+
+ if (t == ZERO) return(ZERO);
+
+ ydata = NV_DATA_S(y);
+ if (t <= THIRTY) ex = EXP(-TWO*t);
+
+ for (j = 0; j < P2_MESHY; j++) {
+ ifact_inv = ONE;
+ for (i = 0; i < P2_MESHX; i++) {
+ k = i + j * P2_MESHX;
+ yt = RPowerI(t,i+j) * ex * ifact_inv * jfact_inv;
+ er = ABS(ydata[k] - yt);
+ if (er > maxError) maxError = er;
+ ifact_inv /= (i+1);
+ }
+ jfact_inv /= (j+1);
+ }
+ return(maxError);
+}
+
+static int PrepareNextRun(void *cvode_mem, int lmm, int miter,
+ long int mu, long int ml)
+{
+ int flag = CV_SUCCESS;
+
+ printf("\n\n-------------------------------------------------------------");
+
+ printf("\n\nLinear Multistep Method : ");
+ if (lmm == CV_ADAMS) {
+ printf("ADAMS\n");
+ } else {
+ printf("BDF\n");
+ }
+
+ printf("Iteration : ");
+ if (miter == FUNC) {
+ printf("FUNCTIONAL\n");
+ } 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);
+ break;
+ case DENSE_DQ :
+ printf("Dense, Difference Quotient Jacobian\n");
+ flag = CVDlsSetDenseJacFn(cvode_mem, NULL);
+ check_flag(&flag, "CVDlsSetDenseJacFn", 1);
+ break;
+ case DIAG :
+ printf("Diagonal Jacobian\n");
+ flag = CVDiag(cvode_mem);
+ check_flag(&flag, "CVDiag", 1);
+ break;
+ 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);
+ break;
+ case BAND_DQ :
+ printf("Band, Difference Quotient Jacobian\n");
+ flag = CVDlsSetBandJacFn(cvode_mem, NULL);
+ check_flag(&flag, "CVDlsSetBandJacFn", 1);
+ break;
+ }
+ }
+
+ return(flag);
+}
+
+static void PrintErrOutput(realtype tol_factor)
+{
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("\n\n Error exceeds %Lg * tolerance \n\n", tol_factor);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("\n\n Error exceeds %lg * tolerance \n\n", tol_factor);
+#else
+ printf("\n\n Error exceeds %g * tolerance \n\n", tol_factor);
+#endif
+
+ return;
+}
+
+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;
+ 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);
+
+ 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(" Number of steps = %4ld \n", nst);
+ printf(" Number of f-s = %4ld \n", nfe);
+ printf(" Number of setups = %4ld \n", nsetups);
+ printf(" Number of nonlinear iterations = %4ld \n", nni);
+ printf(" Number of nonlinear convergence failures = %4ld \n", ncfn);
+ printf(" Number of error test failures = %4ld \n\n",netf);
+
+ if (miter != FUNC) {
+ switch(miter) {
+ case DENSE_USER :
+ case DENSE_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 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 :
+ 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 f evals. in linear solver = %4ld \n\n", nfeLS);
+ }
+
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf(" Error overrun = %.3Lf \n", ero);
+#else
+ printf(" Error overrun = %.3f \n", ero);
+#endif
+}
+
+static void PrintErrInfo(int nerr)
+{
+ printf("\n\n-------------------------------------------------------------");
+ printf("\n-------------------------------------------------------------");
+ printf("\n\n Number of errors encountered = %d \n", nerr);
+
+ 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, 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/cvsDirectDemo_ls.out b/examples/cvodes/serial/cvsDirectDemo_ls.out
new file mode 100644
index 0000000..9aa156f
--- /dev/null
+++ b/examples/cvodes/serial/cvsDirectDemo_ls.out
@@ -0,0 +1,502 @@
+Demonstration program for CVODE package - direct linear solvers
+
+
+Problem 1: Van der Pol oscillator
+ xdotdot - 3*(1 - x^2)*xdot + x = 0, x(0) = 2, xdot(0) = 0
+ neq = 2, reltol = 0, abstol = 1e-06
+
+-------------------------------------------------------------
+
+Linear Multistep Method : ADAMS
+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
+ 5.82239 -1.68010e+00 2.91060e-01 4 1.4079e-01
+ 8.03716 9.57612e-05 3.16900e+00 5 2.0348e-02
+
+ Final statistics for this run:
+
+ CVode real workspace length = 130
+ CVode integer workspace length = 69
+ Number of steps = 196
+ Number of f-s = 391
+ Number of setups = 0
+ Number of nonlinear iterations = 387
+ Number of nonlinear convergence failures = 0
+ Number of error test failures = 15
+
+ Error overrun = 95.761
+
+
+-------------------------------------------------------------
+
+Linear Multistep Method : ADAMS
+Iteration : NEWTON
+Linear Solver : Dense, User-Supplied Jacobian
+
+ t x xdot qu hu
+ 1.39284 1.68010e+00 -2.91056e-01 7 6.5178e-02
+ 3.60761 2.42943e-06 -3.16870e+00 7 2.0626e-02
+ 5.82239 -1.68010e+00 2.91062e-01 7 1.3038e-01
+ 8.03716 1.99078e-05 3.16879e+00 7 2.3923e-02
+
+ Final statistics for this run:
+
+ CVode real workspace length = 130
+ CVode integer workspace length = 69
+ Number of steps = 266
+ Number of f-s = 366
+ Number of setups = 46
+ Number of nonlinear iterations = 362
+ 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
+ Number of f evals. in linear solver = 0
+
+ Error overrun = 19.908
+
+
+-------------------------------------------------------------
+
+Linear Multistep Method : ADAMS
+Iteration : NEWTON
+Linear Solver : Dense, Difference Quotient Jacobian
+
+ t x xdot qu hu
+ 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
+
+ Final statistics for this run:
+
+ CVode real workspace length = 130
+ CVode integer workspace length = 69
+ Number of steps = 195
+ Number of f-s = 268
+ Number of setups = 34
+ Number of nonlinear iterations = 264
+ 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
+ Number of f evals. in linear solver = 8
+
+ Error overrun = 22.805
+
+
+-------------------------------------------------------------
+
+Linear Multistep Method : ADAMS
+Iteration : NEWTON
+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
+
+ 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 nonlinear convergence failures = 0
+ Number of error test failures = 21
+
+ 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
+
+ Error overrun = 63.607
+
+
+-------------------------------------------------------------
+
+Linear Multistep Method : BDF
+Iteration : FUNCTIONAL
+
+ t x xdot qu hu
+ 1.39284 1.68010e+00 -2.91056e-01 4 9.6100e-02
+ 3.60761 -1.35636e-04 -3.16912e+00 5 1.5675e-02
+ 5.82239 -1.68009e+00 2.91063e-01 5 1.1210e-01
+ 8.03716 2.20969e-04 3.16937e+00 5 1.4732e-02
+
+ Final statistics for this run:
+
+ CVode real workspace length = 116
+ CVode integer workspace length = 62
+ Number of steps = 262
+ Number of f-s = 498
+ Number of setups = 0
+ Number of nonlinear iterations = 494
+ Number of nonlinear convergence failures = 0
+ Number of error test failures = 22
+
+ Error overrun = 220.969
+
+
+-------------------------------------------------------------
+
+Linear Multistep Method : BDF
+Iteration : NEWTON
+Linear Solver : Dense, User-Supplied Jacobian
+
+ t x xdot qu hu
+ 1.39284 1.68010e+00 -2.91056e-01 5 1.1991e-01
+ 3.60761 -5.46907e-05 -3.16886e+00 5 1.6403e-02
+ 5.82239 -1.68010e+00 2.91061e-01 4 1.0146e-01
+ 8.03716 1.54312e-04 3.16917e+00 4 9.5378e-03
+
+ Final statistics for this run:
+
+ CVode real workspace length = 116
+ CVode integer workspace length = 62
+ Number of steps = 265
+ Number of f-s = 358
+ Number of setups = 40
+ Number of nonlinear iterations = 354
+ 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
+ Number of f evals. in linear solver = 0
+
+ Error overrun = 154.312
+
+
+-------------------------------------------------------------
+
+Linear Multistep Method : BDF
+Iteration : NEWTON
+Linear Solver : Dense, Difference Quotient Jacobian
+
+ t x xdot qu hu
+ 1.39284 1.68010e+00 -2.91058e-01 4 8.1067e-02
+ 3.60761 -5.84200e-05 -3.16886e+00 4 1.1360e-02
+ 5.82239 -1.68010e+00 2.91062e-01 5 6.4941e-02
+ 8.03716 9.61737e-05 3.16899e+00 5 1.5216e-02
+
+ Final statistics for this run:
+
+ CVode real workspace length = 116
+ CVode integer workspace length = 62
+ Number of steps = 276
+ Number of f-s = 367
+ Number of setups = 40
+ Number of nonlinear iterations = 363
+ 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
+ Number of f evals. in linear solver = 12
+
+ Error overrun = 96.174
+
+
+-------------------------------------------------------------
+
+Linear Multistep Method : BDF
+Iteration : NEWTON
+Linear Solver : Diagonal Jacobian
+
+ t x xdot qu hu
+ 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
+
+ Final statistics for this run:
+
+ CVode real workspace length = 116
+ CVode integer workspace length = 62
+ Number of steps = 266
+ Number of f-s = 360
+ Number of setups = 39
+ Number of nonlinear iterations = 356
+ Number of nonlinear convergence failures = 0
+ Number of error test failures = 17
+
+ Linear solver real workspace length = 6
+ Linear solver integer workspace length = 3
+ Number of Jacobian evaluations = 39
+ Number of f evals. in linear solver = 39
+
+ Error overrun = 166.641
+
+
+-------------------------------------------------------------
+-------------------------------------------------------------
+
+Problem 2: ydot = A * y, where A is a banded lower
+triangular matrix derived from 2-D advection PDE
+
+ neq = 25, ml = 5, mu = 0
+ itol = CV_SS, reltol = 0, abstol = 1e-06
+ t max.err qu hu
+
+
+-------------------------------------------------------------
+
+Linear Multistep Method : ADAMS
+Iteration : FUNCTIONAL
+
+ t max.err qu hu
+ 0.010 1.4690e-07 3 1.1459e-02
+ 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
+
+ Final statistics for this run:
+
+ CVode real workspace length = 521
+ CVode integer workspace length = 69
+ Number of steps = 339
+ Number of f-s = 602
+ Number of setups = 0
+ Number of nonlinear iterations = 598
+ Number of nonlinear convergence failures = 80
+ Number of error test failures = 0
+
+ Error overrun = 1.221
+
+
+-------------------------------------------------------------
+
+Linear Multistep Method : ADAMS
+Iteration : NEWTON
+Linear Solver : Diagonal Jacobian
+
+ t max.err qu hu
+ 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
+
+ Final statistics for this run:
+
+ CVode real workspace length = 521
+ CVode integer workspace length = 69
+ Number of steps = 154
+ Number of f-s = 219
+ Number of setups = 33
+ Number of nonlinear iterations = 215
+ Number of nonlinear convergence failures = 0
+ Number of error test failures = 5
+
+ Linear solver real workspace length = 75
+ Linear solver integer workspace length = 3
+ Number of Jacobian evaluations = 33
+ Number of f evals. in linear solver = 33
+
+ Error overrun = 4.233
+
+
+-------------------------------------------------------------
+
+Linear Multistep Method : ADAMS
+Iteration : NEWTON
+Linear Solver : Band, User-Supplied Jacobian
+
+ t max.err qu hu
+ 0.010 1.3670e-07 3 1.2164e-02
+ 0.100 4.7920e-07 4 4.2115e-02
+ 1.000 2.5077e-07 6 1.0365e-01
+ 10.000 6.0790e-07 4 4.7206e-01
+ 100.000 5.7390e-08 2 1.0750e+01
+
+ Final statistics for this run:
+
+ CVode real workspace length = 521
+ CVode integer workspace length = 69
+ Number of steps = 149
+ Number of f-s = 184
+ Number of setups = 32
+ Number of nonlinear iterations = 180
+ 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
+ Number of f evals. in linear solver = 0
+
+ Error overrun = 0.608
+
+
+-------------------------------------------------------------
+
+Linear Multistep Method : ADAMS
+Iteration : NEWTON
+Linear Solver : Band, Difference Quotient Jacobian
+
+ t max.err qu hu
+ 0.010 1.4285e-07 3 1.3840e-02
+ 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
+
+ Final statistics for this run:
+
+ CVode real workspace length = 521
+ CVode integer workspace length = 69
+ Number of steps = 124
+ Number of f-s = 142
+ Number of setups = 24
+ Number of nonlinear iterations = 138
+ 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
+ Number of f evals. in linear solver = 18
+
+ Error overrun = 0.733
+
+
+-------------------------------------------------------------
+
+Linear Multistep Method : BDF
+Iteration : FUNCTIONAL
+
+ t max.err qu hu
+ 0.010 5.5931e-07 2 8.1257e-03
+ 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
+
+ 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 setups = 0
+ Number of nonlinear iterations = 686
+ Number of nonlinear convergence failures = 55
+ Number of error test failures = 1
+
+ Error overrun = 5.290
+
+
+-------------------------------------------------------------
+
+Linear Multistep Method : BDF
+Iteration : NEWTON
+Linear Solver : Diagonal Jacobian
+
+ t max.err qu hu
+ 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
+
+ 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 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
+
+ Error overrun = 5.910
+
+
+-------------------------------------------------------------
+
+Linear Multistep Method : BDF
+Iteration : NEWTON
+Linear Solver : Band, User-Supplied Jacobian
+
+ t max.err qu hu
+ 0.010 5.6372e-07 2 8.1246e-03
+ 0.100 5.2784e-06 3 1.7819e-02
+ 1.000 1.8169e-06 5 6.0110e-02
+ 10.000 5.4997e-07 5 4.1661e-01
+ 100.000 1.7764e-09 2 2.9748e+01
+
+ Final statistics for this run:
+
+ CVode real workspace length = 346
+ CVode integer workspace length = 62
+ Number of steps = 119
+ Number of f-s = 144
+ Number of setups = 25
+ Number of nonlinear iterations = 140
+ 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
+ Number of f evals. in linear solver = 0
+
+ Error overrun = 5.278
+
+
+-------------------------------------------------------------
+
+Linear Multistep Method : BDF
+Iteration : NEWTON
+Linear Solver : Band, Difference Quotient Jacobian
+
+ t max.err qu hu
+ 0.010 5.6492e-07 2 8.1361e-03
+ 0.100 5.9968e-06 3 1.7105e-02
+ 1.000 1.6902e-06 5 8.7628e-02
+ 10.000 5.2314e-07 5 3.1091e-01
+ 100.000 1.4380e-09 2 2.1635e+01
+
+ Final statistics for this run:
+
+ CVode real workspace length = 346
+ CVode integer workspace length = 62
+ Number of steps = 121
+ Number of f-s = 145
+ Number of setups = 24
+ Number of nonlinear iterations = 141
+ 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
+ Number of f evals. in linear solver = 18
+
+ Error overrun = 5.997
+
+
+-------------------------------------------------------------
+-------------------------------------------------------------
+
+ Number of errors encountered = 0
diff --git a/examples/cvodes/serial/cvsDiurnal_FSA_kry.c b/examples/cvodes/serial/cvsDiurnal_FSA_kry.c
new file mode 100644
index 0000000..1a4195d
--- /dev/null
+++ b/examples/cvodes/serial/cvsDiurnal_FSA_kry.c
@@ -0,0 +1,928 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.3 $
+ * $Date: 2010/12/01 22:57:59 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Scott D. Cohen and Alan C. Hindmarsh and
+ * Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Example problem:
+ *
+ * An ODE system is generated from the following 2-species diurnal
+ * kinetics advection-diffusion PDE system in 2 space dimensions:
+ *
+ * dc(i)/dt = Kh*(d/dx)^2 c(i) + V*dc(i)/dx + (d/dz)(Kv(z)*dc(i)/dz)
+ * + Ri(c1,c2,t) for i = 1,2, where
+ * R1(c1,c2,t) = -q1*c1*c3 - q2*c1*c2 + 2*q3(t)*c3 + q4(t)*c2 ,
+ * R2(c1,c2,t) = q1*c1*c3 - q2*c1*c2 - q4(t)*c2 ,
+ * Kv(z) = Kv0*exp(z/5) ,
+ * Kh, V, Kv0, q1, q2, and c3 are constants, and q3(t) and q4(t)
+ * vary diurnally. The problem is posed on the square
+ * 0 <= x <= 20, 30 <= z <= 50 (all in km),
+ * with homogeneous Neumann boundary conditions, and for time t in
+ * 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 method
+ * (i.e. using the CVSPGMR 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.
+ *
+ * Optionally, CVODES can compute sensitivities with respect to the
+ * problem parameters q1 and q2.
+ * 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 FULL or PARTIAL,
+ * respectively).
+ *
+ * Execution:
+ *
+ * If no sensitivities are desired:
+ * % cvsDiurnal_FSA_kry -nosensi
+ * If sensitivities are to be computed:
+ * % 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, macro NV_DATA_S */
+#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 SQR and EXP */
+
+/* Problem Constants */
+
+#define NUM_SPECIES 2 /* number of species */
+#define C1_SCALE RCONST(1.0e6) /* coefficients in initial profiles */
+#define C2_SCALE RCONST(1.0e12)
+
+#define T0 RCONST(0.0) /* initial time */
+#define NOUT 12 /* number of output times */
+#define TWOHR RCONST(7200.0) /* number of seconds in two hours */
+#define HALFDAY RCONST(4.32e4) /* number of seconds in a half day */
+#define PI RCONST(3.1415926535898) /* pi */
+
+#define XMIN RCONST(0.0) /* grid boundaries in x */
+#define XMAX RCONST(20.0)
+#define ZMIN RCONST(30.0) /* grid boundaries in z */
+#define ZMAX RCONST(50.0)
+#define XMID RCONST(10.0) /* grid midpoints in x,z */
+#define ZMID RCONST(40.0)
+
+#define MX 15 /* MX = number of x mesh points */
+#define MZ 15 /* MZ = number of z mesh points */
+#define NSMX NUM_SPECIES*MX /* NSMX = NUM_SPECIES*MX */
+#define MM (MX*MZ) /* MM = MX*MZ */
+
+/* CVodeInit Constants */
+#define RTOL RCONST(1.0e-5) /* scalar relative tolerance */
+#define FLOOR RCONST(100.0) /* value of C1 or C2 at which tolerances */
+ /* change from relative to absolute */
+#define ATOL (RTOL*FLOOR) /* scalar absolute tolerance */
+#define NEQ (NUM_SPECIES*MM) /* NEQ = number of equations */
+
+/* Sensitivity Constants */
+#define NP 8
+#define NS 2
+
+#define ZERO RCONST(0.0)
+#define ONE RCONST(1.0)
+
+/* User-defined vector and matrix accessor macros: IJKth, IJth */
+
+/* IJKth is defined in order to isolate the translation from the
+ mathematical 3-dimensional structure of the dependent variable vector
+ to the underlying 1-dimensional storage. IJth is defined in order to
+ write code which indexes into small dense matrices with a (row,column)
+ pair, where 1 <= row, column <= NUM_SPECIES.
+
+ 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 = NV_DATA_S(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
+ work with matrices stored by column in a 2-dimensional array. In C,
+ arrays are indexed starting at 0, not 1. */
+
+#define IJKth(vdata,i,j,k) (vdata[i-1 + (j)*NUM_SPECIES + (k)*NSMX])
+#define IJth(a,i,j) (a[j-1][i-1])
+
+/* Type : UserData
+ contains preconditioner blocks, pivot arrays,
+ problem parameters, and problem constants */
+
+typedef struct {
+ realtype *p;
+ realtype **P[MX][MZ], **Jbd[MX][MZ];
+ long int *pivot[MX][MZ];
+ realtype q4, om, dx, dz, hdco, haco, vdco;
+} *UserData;
+
+
+/* Prototypes of user-supplied functions */
+
+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);
+
+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);
+
+/* Prototypes of private functions */
+
+static void ProcessArgs(int argc, char *argv[],
+ booleantype *sensi, int *sensi_meth, booleantype *err_con);
+static void WrongArgs(char *name);
+static UserData AllocUserData(void);
+static void InitUserData(UserData data);
+static void FreeUserData(UserData data);
+static void SetInitialProfiles(N_Vector y, realtype dx, realtype dz);
+static void PrintOutput(void *cvode_mem, realtype t, N_Vector y);
+static void PrintOutputS(N_Vector *uS);
+static void PrintFinalStats(void *cvode_mem, booleantype sensi);
+static int check_flag(void *flagvalue, char *funcname, int opt);
+
+/*
+ *--------------------------------------------------------------------
+ * MAIN PROGRAM
+ *--------------------------------------------------------------------
+ */
+
+int main(int argc, char *argv[])
+{
+ void *cvode_mem;
+ UserData data;
+ realtype abstol, reltol, t, tout;
+ N_Vector y;
+ int iout, flag;
+
+ realtype *pbar;
+ int is, *plist;
+ N_Vector *uS;
+ booleantype sensi, err_con;
+ int sensi_meth;
+
+ pbar = NULL;
+ plist = NULL;
+ uS = NULL;
+ y = NULL;
+ data = NULL;
+ cvode_mem = NULL;
+
+ /* Process arguments */
+ ProcessArgs(argc, argv, &sensi, &sensi_meth, &err_con);
+
+ /* Problem parameters */
+ data = AllocUserData();
+ if(check_flag((void *)data, "AllocUserData", 2)) return(1);
+ InitUserData(data);
+
+ /* Initial states */
+ y = N_VNew_Serial(NEQ);
+ if(check_flag((void *)y, "N_VNew_Serial", 0)) return(1);
+ SetInitialProfiles(y, data->dx, data->dz);
+
+ /* Tolerances */
+ abstol=ATOL;
+ reltol=RTOL;
+
+ /* Create CVODES object */
+ cvode_mem = CVodeCreate(CV_BDF, CV_NEWTON);
+ if(check_flag((void *)cvode_mem, "CVodeCreate", 0)) return(1);
+
+ flag = CVodeSetUserData(cvode_mem, data);
+ if(check_flag(&flag, "CVodeSetUserData", 1)) return(1);
+
+ flag = CVodeSetMaxNumSteps(cvode_mem, 2000);
+ if(check_flag(&flag, "CVodeSetMaxNumSteps", 1)) return(1);
+
+ /* Allocate CVODES memory */
+ 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);
+
+ /* Attach CVSPGMR linear solver */
+ flag = CVSpgmr(cvode_mem, PREC_LEFT, 0);
+ if(check_flag(&flag, "CVSpgmr", 1)) return(1);
+
+ flag = CVSpilsSetPreconditioner(cvode_mem, Precond, PSolve);
+ if(check_flag(&flag, "CVSpilsSetPreconditioner", 1)) return(1);
+
+ printf("\n2-species diurnal advection-diffusion problem\n");
+
+ /* Forward sensitivity analysis */
+ if(sensi) {
+
+ plist = (int *) malloc(NS * sizeof(int));
+ if(check_flag((void *)plist, "malloc", 2)) return(1);
+ for(is=0; is<NS; is++) plist[is] = is;
+
+ pbar = (realtype *) malloc(NS * sizeof(realtype));
+ 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);
+ for(is=0;is<NS;is++)
+ N_VConst(ZERO,uS[is]);
+
+ flag = CVodeSensInit1(cvode_mem, NS, sensi_meth, NULL, uS);
+ if(check_flag(&flag, "CVodeSensInit", 1)) return(1);
+
+ flag = CVodeSensEEtolerances(cvode_mem);
+ if(check_flag(&flag, "CVodeSensEEtolerances", 1)) return(1);
+
+ flag = CVodeSetSensErrCon(cvode_mem, err_con);
+ if(check_flag(&flag, "CVodeSetSensErrCon", 1)) return(1);
+
+ flag = CVodeSetSensDQMethod(cvode_mem, CV_CENTERED, ZERO);
+ if(check_flag(&flag, "CVodeSetSensDQMethod", 1)) return(1);
+
+ flag = CVodeSetSensParams(cvode_mem, data->p, pbar, plist);
+ if(check_flag(&flag, "CVodeSetSensParams", 1)) return(1);
+
+ printf("Sensitivity: YES ");
+ if(sensi_meth == CV_SIMULTANEOUS)
+ printf("( SIMULTANEOUS +");
+ else
+ if(sensi_meth == CV_STAGGERED) printf("( STAGGERED +");
+ else printf("( STAGGERED1 +");
+ if(err_con) printf(" FULL ERROR CONTROL )");
+ else printf(" PARTIAL ERROR CONTROL )");
+
+ } else {
+
+ printf("Sensitivity: NO ");
+
+ }
+
+ /* In loop over output points, call CVode, print results, test for error */
+
+ printf("\n\n");
+ printf("========================================================================\n");
+ printf(" T Q H NST Bottom left Top right \n");
+ printf("========================================================================\n");
+
+ for (iout=1, tout = TWOHR; iout <= NOUT; iout++, tout += TWOHR) {
+ flag = CVode(cvode_mem, tout, y, &t, CV_NORMAL);
+ if(check_flag(&flag, "CVode", 1)) break;
+ PrintOutput(cvode_mem, t, y);
+ if (sensi) {
+ flag = CVodeGetSens(cvode_mem, &t, uS);
+ if(check_flag(&flag, "CVodeGetSens", 1)) break;
+ PrintOutputS(uS);
+ }
+
+ printf("------------------------------------------------------------------------\n");
+
+ }
+
+ /* Print final statistics */
+ PrintFinalStats(cvode_mem, sensi);
+
+ /* Free memory */
+ N_VDestroy_Serial(y);
+ if (sensi) {
+ N_VDestroyVectorArray_Serial(uS, NS);
+ free(pbar);
+ free(plist);
+ }
+ FreeUserData(data);
+ CVodeFree(&cvode_mem);
+
+ return(0);
+}
+
+/*
+ *--------------------------------------------------------------------
+ * FUNCTIONS CALLED BY CVODES
+ *--------------------------------------------------------------------
+ */
+
+/*
+ * f routine. Compute f(t,y).
+ */
+
+static int f(realtype t, N_Vector y, N_Vector ydot, void *user_data)
+{
+ realtype q3, c1, c2, c1dn, c2dn, c1up, c2up, c1lt, c2lt;
+ realtype c1rt, c2rt, czdn, czup, hord1, hord2, horad1, horad2;
+ realtype qq1, qq2, qq3, qq4, rkin1, rkin2, s, vertd1, vertd2, zdn, zup;
+ realtype q4coef, delz, verdco, hordco, horaco;
+ realtype *ydata, *dydata;
+ int jx, jz, idn, iup, ileft, iright;
+ UserData data;
+ realtype Q1, Q2, C3, A3, A4, KH, VEL, KV0;
+
+ data = (UserData) user_data;
+ ydata = NV_DATA_S(y);
+ dydata = NV_DATA_S(ydot);
+
+ /* Load problem coefficients and parameters */
+
+ Q1 = data->p[0];
+ Q2 = data->p[1];
+ C3 = data->p[2];
+ A3 = data->p[3];
+ A4 = data->p[4];
+ KH = data->p[5];
+ VEL = data->p[6];
+ KV0 = data->p[7];
+
+ /* Set diurnal rate coefficients. */
+
+ s = sin(data->om*t);
+ if (s > ZERO) {
+ q3 = EXP(-A3/s);
+ data->q4 = EXP(-A4/s);
+ } else {
+ q3 = ZERO;
+ data->q4 = ZERO;
+ }
+
+ /* Make local copies of problem variables, for efficiency. */
+
+ q4coef = data->q4;
+ delz = data->dz;
+ verdco = data->vdco;
+ hordco = data->hdco;
+ horaco = data->haco;
+
+ /* Loop over all grid points. */
+
+ for (jz=0; jz < MZ; jz++) {
+
+ /* Set vertical diffusion coefficients at jz +- 1/2 */
+
+ zdn = ZMIN + (jz - RCONST(0.5))*delz;
+ zup = zdn + delz;
+ czdn = verdco*EXP(RCONST(0.2)*zdn);
+ czup = verdco*EXP(RCONST(0.2)*zup);
+ idn = (jz == 0) ? 1 : -1;
+ iup = (jz == MZ-1) ? -1 : 1;
+ for (jx=0; jx < MX; jx++) {
+
+ /* Extract c1 and c2, and set kinetic rate terms. */
+
+ c1 = IJKth(ydata,1,jx,jz);
+ c2 = IJKth(ydata,2,jx,jz);
+ qq1 = Q1*c1*C3;
+ qq2 = Q2*c1*c2;
+ qq3 = q3*C3;
+ qq4 = q4coef*c2;
+ rkin1 = -qq1 - qq2 + RCONST(2.0)*qq3 + qq4;
+ rkin2 = qq1 - qq2 - qq4;
+
+ /* Set vertical diffusion terms. */
+
+ c1dn = IJKth(ydata,1,jx,jz+idn);
+ c2dn = IJKth(ydata,2,jx,jz+idn);
+ c1up = IJKth(ydata,1,jx,jz+iup);
+ c2up = IJKth(ydata,2,jx,jz+iup);
+ vertd1 = czup*(c1up - c1) - czdn*(c1 - c1dn);
+ vertd2 = czup*(c2up - c2) - czdn*(c2 - c2dn);
+
+ /* Set horizontal diffusion and advection terms. */
+
+ ileft = (jx == 0) ? 1 : -1;
+ iright =(jx == MX-1) ? -1 : 1;
+ c1lt = IJKth(ydata,1,jx+ileft,jz);
+ c2lt = IJKth(ydata,2,jx+ileft,jz);
+ c1rt = IJKth(ydata,1,jx+iright,jz);
+ c2rt = IJKth(ydata,2,jx+iright,jz);
+ hord1 = hordco*(c1rt - RCONST(2.0)*c1 + c1lt);
+ hord2 = hordco*(c2rt - RCONST(2.0)*c2 + c2lt);
+ horad1 = horaco*(c1rt - c1lt);
+ horad2 = horaco*(c2rt - c2lt);
+
+ /* Load all terms into ydot. */
+
+ IJKth(dydata, 1, jx, jz) = vertd1 + hord1 + horad1 + rkin1;
+ IJKth(dydata, 2, jx, jz) = vertd2 + hord2 + horad2 + rkin2;
+ }
+ }
+
+ return(0);
+}
+
+/*
+ * Preconditioner setup routine. Generate and preprocess P.
+ */
+
+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)
+{
+ realtype c1, c2, czdn, czup, diag, zdn, zup, q4coef, delz, verdco, hordco;
+ realtype **(*P)[MZ], **(*Jbd)[MZ];
+ long int *(*pivot)[MZ];
+ int ier, jx, jz;
+ realtype *ydata, **a, **j;
+ UserData data;
+ realtype Q1, Q2, C3, A3, A4, KH, VEL, KV0;
+
+ /* Make local copies of pointers in user_data, and of pointer to y's data */
+ data = (UserData) user_data;
+ P = data->P;
+ Jbd = data->Jbd;
+ pivot = data->pivot;
+ ydata = NV_DATA_S(y);
+
+ /* Load problem coefficients and parameters */
+ Q1 = data->p[0];
+ Q2 = data->p[1];
+ C3 = data->p[2];
+ A3 = data->p[3];
+ A4 = data->p[4];
+ KH = data->p[5];
+ VEL = data->p[6];
+ KV0 = data->p[7];
+
+ if (jok) {
+
+ /* jok = TRUE: 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;
+
+ }
+
+ else {
+ /* jok = FALSE: Generate Jbd from scratch and copy to P */
+
+ /* Make local copies of problem variables, for efficiency. */
+
+ q4coef = data->q4;
+ delz = data->dz;
+ verdco = data->vdco;
+ hordco = data->hdco;
+
+ /* Compute 2x2 diagonal Jacobian blocks (using q4 values
+ computed on the last f call). Load into P. */
+
+ for (jz=0; jz < MZ; jz++) {
+ zdn = ZMIN + (jz - RCONST(0.5))*delz;
+ zup = zdn + delz;
+ czdn = verdco*EXP(RCONST(0.2)*zdn);
+ czup = verdco*EXP(RCONST(0.2)*zup);
+ diag = -(czdn + czup + RCONST(2.0)*hordco);
+ for (jx=0; jx < MX; jx++) {
+ c1 = IJKth(ydata,1,jx,jz);
+ c2 = IJKth(ydata,2,jx,jz);
+ j = Jbd[jx][jz];
+ a = P[jx][jz];
+ IJth(j,1,1) = (-Q1*C3 - Q2*c2) + diag;
+ IJth(j,1,2) = -Q2*c1 + q4coef;
+ IJth(j,2,1) = Q1*C3 - Q2*c2;
+ IJth(j,2,2) = (-Q2*c1 - q4coef) + diag;
+ denseCopy(j, a, NUM_SPECIES, NUM_SPECIES);
+ }
+ }
+
+ *jcurPtr = TRUE;
+
+ }
+
+ /* Scale by -gamma */
+
+ for (jz=0; jz < MZ; jz++)
+ for (jx=0; jx < MX; jx++)
+ denseScale(-gamma, P[jx][jz], NUM_SPECIES, NUM_SPECIES);
+
+ /* Add identity matrix and do LU decompositions on blocks in place. */
+
+ for (jx=0; jx < MX; jx++) {
+ for (jz=0; jz < MZ; jz++) {
+ denseAddIdentity(P[jx][jz], NUM_SPECIES);
+ ier = denseGETRF(P[jx][jz], NUM_SPECIES, NUM_SPECIES, pivot[jx][jz]);
+ if (ier != 0) return(1);
+ }
+ }
+
+ return(0);
+}
+
+/*
+ * Preconditioner solve routine
+ */
+
+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)
+{
+ realtype **(*P)[MZ];
+ long int *(*pivot)[MZ];
+ int jx, jz;
+ realtype *zdata, *v;
+ UserData data;
+
+ /* Extract the P and pivot arrays from user_data. */
+
+ data = (UserData) user_data;
+ P = data->P;
+ pivot = data->pivot;
+ zdata = NV_DATA_S(z);
+
+ N_VScale(ONE, r, z);
+
+ /* Solve the block-diagonal system Px = r using LU factors stored
+ in P and pivot data in pivot, and return the solution in z. */
+
+ for (jx=0; jx < MX; jx++) {
+ for (jz=0; jz < MZ; jz++) {
+ v = &(IJKth(zdata, 1, jx, jz));
+ denseGETRS(P[jx][jz], NUM_SPECIES, pivot[jx][jz], v);
+ }
+ }
+
+ return(0);
+}
+
+/*
+ *--------------------------------------------------------------------
+ * PRIVATE FUNCTIONS
+ *--------------------------------------------------------------------
+ */
+
+/*
+ * Process and verify arguments to cvsfwdkryx.
+ */
+
+static void ProcessArgs(int argc, char *argv[],
+ booleantype *sensi, int *sensi_meth, booleantype *err_con)
+{
+ *sensi = FALSE;
+ *sensi_meth = -1;
+ *err_con = FALSE;
+
+ if (argc < 2) WrongArgs(argv[0]);
+
+ if (strcmp(argv[1],"-nosensi") == 0)
+ *sensi = FALSE;
+ else if (strcmp(argv[1],"-sensi") == 0)
+ *sensi = TRUE;
+ else
+ WrongArgs(argv[0]);
+
+ if (*sensi) {
+
+ if (argc != 4)
+ WrongArgs(argv[0]);
+
+ if (strcmp(argv[2],"sim") == 0)
+ *sensi_meth = CV_SIMULTANEOUS;
+ else if (strcmp(argv[2],"stg") == 0)
+ *sensi_meth = CV_STAGGERED;
+ else if (strcmp(argv[2],"stg1") == 0)
+ *sensi_meth = CV_STAGGERED1;
+ else
+ WrongArgs(argv[0]);
+
+ if (strcmp(argv[3],"t") == 0)
+ *err_con = TRUE;
+ else if (strcmp(argv[3],"f") == 0)
+ *err_con = FALSE;
+ else
+ WrongArgs(argv[0]);
+ }
+
+}
+
+static void WrongArgs(char *name)
+{
+ printf("\nUsage: %s [-nosensi] [-sensi sensi_meth err_con]\n",name);
+ printf(" sensi_meth = sim, stg, or stg1\n");
+ printf(" err_con = t or f\n");
+
+ exit(0);
+}
+
+/*
+ * Allocate memory for data structure of type UserData
+ */
+
+static UserData AllocUserData(void)
+{
+ int jx, jz;
+ UserData data;
+
+ data = (UserData) malloc(sizeof *data);
+
+ for (jx=0; jx < MX; jx++) {
+ 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->p = (realtype *) malloc(NP*sizeof(realtype));
+
+ return(data);
+}
+
+/*
+ * Load problem constants in data
+ */
+
+static void InitUserData(UserData data)
+{
+ realtype Q1, Q2, C3, A3, A4, KH, VEL, KV0;
+
+ /* Set problem parameters */
+ Q1 = RCONST(1.63e-16); /* Q1 coefficients q1, q2, c3 */
+ Q2 = RCONST(4.66e-16); /* Q2 */
+ C3 = RCONST(3.7e16); /* C3 */
+ A3 = RCONST(22.62); /* A3 coefficient in expression for q3(t) */
+ A4 = RCONST(7.601); /* A4 coefficient in expression for q4(t) */
+ KH = RCONST(4.0e-6); /* KH horizontal diffusivity Kh */
+ VEL = RCONST(0.001); /* VEL advection velocity V */
+ KV0 = RCONST(1.0e-8); /* KV0 coefficient in Kv(z) */
+
+ data->om = PI/HALFDAY;
+ data->dx = (XMAX-XMIN)/(MX-1);
+ data->dz = (ZMAX-ZMIN)/(MZ-1);
+ data->hdco = KH/SQR(data->dx);
+ data->haco = VEL/(RCONST(2.0)*data->dx);
+ data->vdco = (ONE/SQR(data->dz))*KV0;
+
+ data->p[0] = Q1;
+ data->p[1] = Q2;
+ data->p[2] = C3;
+ data->p[3] = A3;
+ data->p[4] = A4;
+ data->p[5] = KH;
+ data->p[6] = VEL;
+ data->p[7] = KV0;
+}
+
+/*
+ * Free user data memory
+ */
+
+static void FreeUserData(UserData data)
+{
+ int jx, jz;
+
+ for (jx=0; jx < MX; jx++) {
+ for (jz=0; jz < MZ; jz++) {
+ destroyMat((data->P)[jx][jz]);
+ destroyMat((data->Jbd)[jx][jz]);
+ destroyArray((data->pivot)[jx][jz]);
+ }
+ }
+
+ free(data->p);
+
+ free(data);
+}
+
+/*
+ * Set initial conditions in y
+ */
+
+static void SetInitialProfiles(N_Vector y, realtype dx, realtype dz)
+{
+ int jx, jz;
+ realtype x, z, cx, cz;
+ realtype *ydata;
+
+ /* Set pointer to data array in vector y. */
+
+ ydata = NV_DATA_S(y);
+
+ /* Load initial profiles of c1 and c2 into y vector */
+
+ for (jz=0; jz < MZ; jz++) {
+ z = ZMIN + jz*dz;
+ cz = SQR(RCONST(0.1)*(z - ZMID));
+ cz = ONE - cz + RCONST(0.5)*SQR(cz);
+ for (jx=0; jx < MX; jx++) {
+ x = XMIN + jx*dx;
+ cx = SQR(RCONST(0.1)*(x - XMID));
+ cx = ONE - cx + RCONST(0.5)*SQR(cx);
+ IJKth(ydata,1,jx,jz) = C1_SCALE*cx*cz;
+ IJKth(ydata,2,jx,jz) = C2_SCALE*cx*cz;
+ }
+ }
+}
+
+/*
+ * Print current t, step count, order, stepsize, and sampled c1,c2 values
+ */
+
+static void PrintOutput(void *cvode_mem, realtype t, N_Vector y)
+{
+ long int nst;
+ int qu, flag;
+ realtype hu;
+ realtype *ydata;
+
+ ydata = NV_DATA_S(y);
+
+ flag = CVodeGetNumSteps(cvode_mem, &nst);
+ check_flag(&flag, "CVodeGetNumSteps", 1);
+ flag = CVodeGetLastOrder(cvode_mem, &qu);
+ check_flag(&flag, "CVodeGetLastOrder", 1);
+ flag = CVodeGetLastStep(cvode_mem, &hu);
+ check_flag(&flag, "CVodeGetLastStep", 1);
+
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("%8.3Le %2d %8.3Le %5ld\n", t,qu,hu,nst);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("%8.3le %2d %8.3le %5ld\n", t,qu,hu,nst);
+#else
+ printf("%8.3e %2d %8.3e %5ld\n", t,qu,hu,nst);
+#endif
+
+ printf(" Solution ");
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("%12.4Le %12.4Le \n", IJKth(ydata,1,0,0), IJKth(ydata,1,MX-1,MZ-1));
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("%12.4le %12.4le \n", IJKth(ydata,1,0,0), IJKth(ydata,1,MX-1,MZ-1));
+#else
+ printf("%12.4e %12.4e \n", IJKth(ydata,1,0,0), IJKth(ydata,1,MX-1,MZ-1));
+#endif
+ printf(" ");
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("%12.4Le %12.4Le \n", IJKth(ydata,2,0,0), IJKth(ydata,2,MX-1,MZ-1));
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("%12.4le %12.4le \n", IJKth(ydata,2,0,0), IJKth(ydata,2,MX-1,MZ-1));
+#else
+ printf("%12.4e %12.4e \n", IJKth(ydata,2,0,0), IJKth(ydata,2,MX-1,MZ-1));
+#endif
+}
+
+/*
+ * Print sampled sensitivities
+ */
+
+static void PrintOutputS(N_Vector *uS)
+{
+ realtype *sdata;
+
+ sdata = NV_DATA_S(uS[0]);
+
+ printf(" ----------------------------------------\n");
+ printf(" Sensitivity 1 ");
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("%12.4Le %12.4Le \n", IJKth(sdata,1,0,0), IJKth(sdata,1,MX-1,MZ-1));
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("%12.4le %12.4le \n", IJKth(sdata,1,0,0), IJKth(sdata,1,MX-1,MZ-1));
+#else
+ printf("%12.4e %12.4e \n", IJKth(sdata,1,0,0), IJKth(sdata,1,MX-1,MZ-1));
+#endif
+ printf(" ");
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("%12.4Le %12.4Le \n", IJKth(sdata,2,0,0), IJKth(sdata,2,MX-1,MZ-1));
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("%12.4le %12.4le \n", IJKth(sdata,2,0,0), IJKth(sdata,2,MX-1,MZ-1));
+#else
+ printf("%12.4e %12.4e \n", IJKth(sdata,2,0,0), IJKth(sdata,2,MX-1,MZ-1));
+#endif
+
+ sdata = NV_DATA_S(uS[1]);
+
+ printf(" ----------------------------------------\n");
+ printf(" Sensitivity 2 ");
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("%12.4Le %12.4Le \n", IJKth(sdata,1,0,0), IJKth(sdata,1,MX-1,MZ-1));
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("%12.4le %12.4le \n", IJKth(sdata,1,0,0), IJKth(sdata,1,MX-1,MZ-1));
+#else
+ printf("%12.4e %12.4e \n", IJKth(sdata,1,0,0), IJKth(sdata,1,MX-1,MZ-1));
+#endif
+ printf(" ");
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("%12.4Le %12.4Le \n", IJKth(sdata,2,0,0), IJKth(sdata,2,MX-1,MZ-1));
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("%12.4le %12.4le \n", IJKth(sdata,2,0,0), IJKth(sdata,2,MX-1,MZ-1));
+#else
+ printf("%12.4e %12.4e \n", IJKth(sdata,2,0,0), IJKth(sdata,2,MX-1,MZ-1));
+#endif
+}
+
+/*
+ * Print final statistics contained in iopt
+ */
+
+static void PrintFinalStats(void *cvode_mem, booleantype sensi)
+{
+ long int nst;
+ long int nfe, nsetups, nni, ncfn, netf;
+ long int nfSe, nfeS, nsetupsS, nniS, ncfnS, netfS;
+ long int nli, ncfl, npe, nps;
+ int flag;
+
+ 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);
+
+ if (sensi) {
+ flag = CVodeGetSensNumRhsEvals(cvode_mem, &nfSe);
+ check_flag(&flag, "CVodeGetSensNumRhsEvals", 1);
+ flag = CVodeGetNumRhsEvalsSens(cvode_mem, &nfeS);
+ check_flag(&flag, "CVodeGetNumRhsEvalsSens", 1);
+ flag = CVodeGetSensNumLinSolvSetups(cvode_mem, &nsetupsS);
+ check_flag(&flag, "CVodeGetSensNumLinSolvSetups", 1);
+ flag = CVodeGetSensNumErrTestFails(cvode_mem, &netfS);
+ check_flag(&flag, "CVodeGetSensNumErrTestFails", 1);
+ flag = CVodeGetSensNumNonlinSolvIters(cvode_mem, &nniS);
+ check_flag(&flag, "CVodeGetSensNumNonlinSolvIters", 1);
+ flag = CVodeGetSensNumNonlinSolvConvFails(cvode_mem, &ncfnS);
+ check_flag(&flag, "CVodeGetSensNumNonlinSolvConvFails", 1);
+ }
+
+ flag = CVSpilsGetNumLinIters(cvode_mem, &nli);
+ check_flag(&flag, "CVSpilsGetNumLinIters", 1);
+ flag = CVSpilsGetNumConvFails(cvode_mem, &ncfl);
+ check_flag(&flag, "CVSpilsGetNumConvFails", 1);
+ flag = CVSpilsGetNumPrecEvals(cvode_mem, &npe);
+ check_flag(&flag, "CVSpilsGetNumPrecEvals", 1);
+ flag = CVSpilsGetNumPrecSolves(cvode_mem, &nps);
+ check_flag(&flag, "CVSpilsGetNumPrecSolves", 1);
+
+ printf("\nFinal Statistics\n\n");
+ printf("nst = %5ld\n\n", nst);
+ printf("nfe = %5ld\n", nfe);
+ printf("netf = %5ld nsetups = %5ld\n", netf, nsetups);
+ printf("nni = %5ld ncfn = %5ld\n", nni, ncfn);
+
+ if(sensi) {
+ printf("\n");
+ printf("nfSe = %5ld nfeS = %5ld\n", nfSe, nfeS);
+ printf("netfs = %5ld nsetupsS = %5ld\n", netfS, nsetupsS);
+ printf("nniS = %5ld ncfnS = %5ld\n", nniS, ncfnS);
+ }
+
+ printf("\n");
+ printf("nli = %5ld ncfl = %5ld\n", nli, ncfl);
+ printf("npe = %5ld nps = %5ld\n", npe, nps);
+
+}
+
+/*
+ * 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, 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/cvsDiurnal_FSA_kry.out b/examples/cvodes/serial/cvsDiurnal_FSA_kry.out
new file mode 100644
index 0000000..ac1d121
--- /dev/null
+++ b/examples/cvodes/serial/cvsDiurnal_FSA_kry.out
@@ -0,0 +1,142 @@
+
+2-species diurnal advection-diffusion problem
+Sensitivity: YES ( SIMULTANEOUS + FULL ERROR CONTROL )
+
+========================================================================
+ T Q H NST Bottom left Top right
+========================================================================
+7.200e+03 3 3.039e+01 552
+ Solution 1.0593e+04 1.1152e+04
+ 2.5567e+11 2.6917e+11
+ ----------------------------------------
+ Sensitivity 1 -6.4963e+19 -6.8394e+19
+ 7.2120e+19 7.6304e+19
+ ----------------------------------------
+ Sensitivity 2 -4.4900e+14 -4.9768e+14
+ -2.5039e+18 -2.7672e+18
+------------------------------------------------------------------------
+1.440e+04 3 2.312e+01 1032
+ 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
+ ----------------------------------------
+ Sensitivity 2 -4.8955e+17 -5.3580e+17
+ -7.1116e+21 -7.7236e+21
+------------------------------------------------------------------------
+2.160e+04 3 4.952e+01 1884
+ 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
+ -8.2851e+22 -9.3662e+22
+------------------------------------------------------------------------
+2.880e+04 3 7.302e+01 2213
+ 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
+ ----------------------------------------
+ Sensitivity 2 -5.2367e+18 -6.4007e+18
+ -1.8450e+23 -2.2574e+23
+------------------------------------------------------------------------
+3.600e+04 4 3.366e+01 2302
+ 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
+ ----------------------------------------
+ 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
+ 3.4900e+11 4.0867e+11
+ ----------------------------------------
+ Sensitivity 1 1.1669e+08 -1.4148e+08
+ 5.7083e+23 7.9553e+23
+ ----------------------------------------
+ Sensitivity 2 1.0171e+05 1.1062e+05
+ -1.9969e+23 -2.7830e+23
+------------------------------------------------------------------------
+5.040e+04 4 4.497e+02 2538
+ Solution 2.7652e-09 2.9811e-09
+ 3.5570e+11 4.1225e+11
+ ----------------------------------------
+ Sensitivity 1 -1.7614e+07 -1.8570e+07
+ 5.9553e+23 8.1823e+23
+ ----------------------------------------
+ Sensitivity 2 -3.9136e+03 -4.6763e+03
+ -2.0833e+23 -2.8624e+23
+------------------------------------------------------------------------
+5.760e+04 3 3.862e+01 2580
+ Solution 4.0865e-09 1.2653e-08
+ 3.6425e+11 4.1628e+11
+ ----------------------------------------
+ Sensitivity 1 9.5471e+08 2.9501e+09
+ 6.2592e+23 8.4334e+23
+ ----------------------------------------
+ Sensitivity 2 -1.2170e+04 -2.7099e+04
+ -2.1896e+23 -2.9502e+23
+------------------------------------------------------------------------
+6.480e+04 4 1.536e+02 2636
+ Solution 3.6356e-08 1.1341e-07
+ 3.6334e+11 4.2182e+11
+ ----------------------------------------
+ Sensitivity 1 -2.9344e+09 -9.1186e+09
+ 6.2461e+23 8.7310e+23
+ ----------------------------------------
+ Sensitivity 2 -8.4752e+03 -3.0885e+04
+ -2.1850e+23 -3.0543e+23
+------------------------------------------------------------------------
+7.200e+04 4 1.536e+02 2683
+ Solution 4.3358e-09 1.5100e-08
+ 3.6192e+11 4.3354e+11
+ ----------------------------------------
+ Sensitivity 1 -2.7350e+08 -9.6001e+08
+ 6.2310e+23 9.2797e+23
+ ----------------------------------------
+ Sensitivity 2 3.7283e+07 1.2247e+08
+ -2.1798e+23 -3.2463e+23
+------------------------------------------------------------------------
+7.920e+04 4 4.008e+02 2711
+ Solution -2.1912e-15 -7.8117e-15
+ 3.6148e+11 4.4474e+11
+ ----------------------------------------
+ Sensitivity 1 1.0220e+04 3.6486e+04
+ 6.2481e+23 9.8067e+23
+ ----------------------------------------
+ Sensitivity 2 1.2136e+00 4.0255e+00
+ -2.1858e+23 -3.4307e+23
+------------------------------------------------------------------------
+8.640e+04 4 4.008e+02 2729
+ Solution 1.3608e-20 4.5805e-20
+ 3.6318e+11 4.4524e+11
+ ----------------------------------------
+ Sensitivity 1 1.2856e-02 5.0845e-02
+ 6.3248e+23 9.8819e+23
+ ----------------------------------------
+ Sensitivity 2 -3.1311e-05 -9.6668e-05
+ -2.2126e+23 -3.4570e+23
+------------------------------------------------------------------------
+
+Final Statistics
+
+nst = 2729
+
+nfe = 4101
+netf = 203 nsetups = 542
+nni = 4097 ncfn = 9
+
+nfSe = 8202 nfeS = 16404
+netfs = 0 nsetupsS = 0
+nniS = 0 ncfnS = 0
+
+nli = 8349 ncfl = 0
+npe = 63 nps = 17946
diff --git a/examples/cvodes/serial/cvsDiurnal_kry.c b/examples/cvodes/serial/cvsDiurnal_kry.c
new file mode 100644
index 0000000..60606b8
--- /dev/null
+++ b/examples/cvodes/serial/cvsDiurnal_kry.c
@@ -0,0 +1,801 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.3 $
+ * $Date: 2010/12/01 22:57:59 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh and
+ * Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Example problem:
+ *
+ * An ODE system is generated from the following 2-species diurnal
+ * kinetics advection-diffusion PDE system in 2 space dimensions:
+ *
+ * dc(i)/dt = Kh*(d/dx)^2 c(i) + V*dc(i)/dx + (d/dy)(Kv(y)*dc(i)/dy)
+ * + Ri(c1,c2,t) for i = 1,2, where
+ * R1(c1,c2,t) = -q1*c1*c3 - q2*c1*c2 + 2*q3(t)*c3 + q4(t)*c2 ,
+ * R2(c1,c2,t) = q1*c1*c3 - q2*c1*c2 - q4(t)*c2 ,
+ * Kv(y) = Kv0*exp(y/5) ,
+ * Kh, V, Kv0, q1, q2, and c3 are constants, and q3(t) and q4(t)
+ * vary diurnally. The problem is posed on the square
+ * 0 <= x <= 20, 30 <= y <= 50 (all in km),
+ * with homogeneous Neumann boundary conditions, and for time t in
+ * 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
+ * method (i.e. using the CVSPGMR 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, SQR, and EXP */
+
+/* Problem Constants */
+
+#define ZERO RCONST(0.0)
+#define ONE RCONST(1.0)
+#define TWO RCONST(2.0)
+
+#define NUM_SPECIES 2 /* number of species */
+#define KH RCONST(4.0e-6) /* horizontal diffusivity Kh */
+#define VEL RCONST(0.001) /* advection velocity V */
+#define KV0 RCONST(1.0e-8) /* coefficient in Kv(y) */
+#define Q1 RCONST(1.63e-16) /* coefficients q1, q2, c3 */
+#define Q2 RCONST(4.66e-16)
+#define C3 RCONST(3.7e16)
+#define A3 RCONST(22.62) /* coefficient in expression for q3(t) */
+#define A4 RCONST(7.601) /* coefficient in expression for q4(t) */
+#define C1_SCALE RCONST(1.0e6) /* coefficients in initial profiles */
+#define C2_SCALE RCONST(1.0e12)
+
+#define T0 ZERO /* initial time */
+#define NOUT 12 /* number of output times */
+#define TWOHR RCONST(7200.0) /* number of seconds in two hours */
+#define HALFDAY RCONST(4.32e4) /* number of seconds in a half day */
+#define PI RCONST(3.1415926535898) /* pi */
+
+#define XMIN ZERO /* grid boundaries in x */
+#define XMAX RCONST(20.0)
+#define YMIN RCONST(30.0) /* grid boundaries in y */
+#define YMAX RCONST(50.0)
+#define XMID RCONST(10.0) /* grid midpoints in x,y */
+#define YMID RCONST(40.0)
+
+#define MX 10 /* MX = number of x mesh points */
+#define MY 10 /* MY = number of y mesh points */
+#define NSMX 20 /* NSMX = NUM_SPECIES*MX */
+#define MM (MX*MY) /* MM = MX*MY */
+
+/* CVodeInit Constants */
+
+#define RTOL RCONST(1.0e-5) /* scalar relative tolerance */
+#define FLOOR RCONST(100.0) /* value of C1 or C2 at which tolerances */
+ /* change from relative to absolute */
+#define ATOL (RTOL*FLOOR) /* scalar absolute tolerance */
+#define NEQ (NUM_SPECIES*MM) /* NEQ = number of equations */
+
+/* User-defined vector and matrix accessor macros: IJKth, IJth */
+
+/* IJKth is defined in order to isolate the translation from the
+ mathematical 3-dimensional structure of the dependent variable vector
+ to the underlying 1-dimensional storage. IJth is defined in order to
+ write code which indexes into small dense matrices with a (row,column)
+ pair, where 1 <= row, column <= NUM_SPECIES.
+
+ 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 = NV_DATA_S(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 sundials_dense.h
+ work with matrices stored by column in a 2-dimensional array. In C,
+ arrays are indexed starting at 0, not 1. */
+
+#define IJKth(vdata,i,j,k) (vdata[i-1 + (j)*NUM_SPECIES + (k)*NSMX])
+#define IJth(a,i,j) (a[j-1][i-1])
+
+/* Type : UserData
+ contains preconditioner blocks, pivot arrays, and problem constants */
+
+typedef struct {
+ realtype **P[MX][MY], **Jbd[MX][MY];
+ long int *pivot[MX][MY];
+ realtype q4, om, dx, dy, hdco, haco, vdco;
+} *UserData;
+
+/* Private Helper Functions */
+
+static UserData AllocUserData(void);
+static void InitUserData(UserData data);
+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);
+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 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 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);
+
+
+/*
+ *-------------------------------
+ * Main Program
+ *-------------------------------
+ */
+
+int main()
+{
+ realtype abstol, reltol, t, tout;
+ N_Vector u;
+ UserData data;
+ void *cvode_mem;
+ int iout, flag;
+
+ u = NULL;
+ data = NULL;
+ cvode_mem = NULL;
+
+ /* Allocate memory, and set problem data, initial values, tolerances */
+ u = N_VNew_Serial(NEQ);
+ if(check_flag((void *)u, "N_VNew_Serial", 0)) return(1);
+ data = AllocUserData();
+ if(check_flag((void *)data, "AllocUserData", 2)) return(1);
+ InitUserData(data);
+ SetInitialProfiles(u, data->dx, data->dy);
+ abstol=ATOL;
+ reltol=RTOL;
+
+ /* 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);
+
+ /* Set the pointer to user-defined data */
+ flag = CVodeSetUserData(cvode_mem, data);
+ if(check_flag(&flag, "CVodeSetUserData", 1)) 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
+ * 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 tolerances */
+ 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);
+
+ /* set the JAcobian-times-vector function */
+ flag = CVSpilsSetJacTimesVecFn(cvode_mem, jtv);
+ if(check_flag(&flag, "CVSpilsSetJacTimesVecFn", 1)) return(1);
+
+ /* Set modified Gram-Schmidt orthogonalization */
+ flag = CVSpilsSetGSType(cvode_mem, MODIFIED_GS);
+ if(check_flag(&flag, "CVSpilsSetGSType", 1)) return(1);
+
+ /* Set the preconditioner solve and setup functions */
+ flag = CVSpilsSetPreconditioner(cvode_mem, Precond, PSolve);
+ if(check_flag(&flag, "CVSpilsSetPreconditioner", 1)) return(1);
+
+ /* In loop over output points, call CVode, print results, test for error */
+ printf(" \n2-species diurnal advection-diffusion problem\n\n");
+ for (iout=1, tout = TWOHR; iout <= NOUT; iout++, tout += TWOHR) {
+ flag = CVode(cvode_mem, tout, u, &t, CV_NORMAL);
+ PrintOutput(cvode_mem, u, t);
+ if(check_flag(&flag, "CVode", 1)) break;
+ }
+
+ PrintFinalStats(cvode_mem);
+
+ /* Free memory */
+ N_VDestroy_Serial(u);
+ FreeUserData(data);
+ CVodeFree(&cvode_mem);
+
+ return(0);
+}
+
+/*
+ *-------------------------------
+ * Private helper functions
+ *-------------------------------
+ */
+
+/* Allocate memory for data structure of type UserData */
+
+static UserData AllocUserData(void)
+{
+ int jx, jy;
+ UserData data;
+
+ data = (UserData) malloc(sizeof *data);
+
+ for (jx=0; jx < MX; jx++) {
+ 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);
+ }
+ }
+
+ return(data);
+}
+
+/* Load problem constants in data */
+
+static void InitUserData(UserData data)
+{
+ data->om = PI/HALFDAY;
+ data->dx = (XMAX-XMIN)/(MX-1);
+ data->dy = (YMAX-YMIN)/(MY-1);
+ data->hdco = KH/SQR(data->dx);
+ data->haco = VEL/(TWO*data->dx);
+ data->vdco = (ONE/SQR(data->dy))*KV0;
+}
+
+/* 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]);
+ destroyMat((data->Jbd)[jx][jy]);
+ destroyArray((data->pivot)[jx][jy]);
+ }
+ }
+
+ free(data);
+}
+
+/* Set initial conditions in u */
+
+static void SetInitialProfiles(N_Vector u, realtype dx, realtype dy)
+{
+ int jx, jy;
+ realtype x, y, cx, cy;
+ realtype *udata;
+
+ /* Set pointer to data array in vector u. */
+
+ udata = NV_DATA_S(u);
+
+ /* Load initial profiles of c1 and c2 into u vector */
+
+ for (jy=0; jy < MY; jy++) {
+ y = YMIN + jy*dy;
+ cy = SQR(RCONST(0.1)*(y - YMID));
+ cy = ONE - cy + RCONST(0.5)*SQR(cy);
+ for (jx=0; jx < MX; jx++) {
+ x = XMIN + jx*dx;
+ cx = SQR(RCONST(0.1)*(x - XMID));
+ cx = ONE - cx + RCONST(0.5)*SQR(cx);
+ IJKth(udata,1,jx,jy) = C1_SCALE*cx*cy;
+ IJKth(udata,2,jx,jy) = C2_SCALE*cx*cy;
+ }
+ }
+}
+
+/* Print current t, step count, order, stepsize, and sampled c1,c2 values */
+
+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 = NV_DATA_S(u);
+
+ flag = CVodeGetNumSteps(cvode_mem, &nst);
+ check_flag(&flag, "CVodeGetNumSteps", 1);
+ flag = CVodeGetLastOrder(cvode_mem, &qu);
+ check_flag(&flag, "CVodeGetLastOrder", 1);
+ flag = CVodeGetLastStep(cvode_mem, &hu);
+ check_flag(&flag, "CVodeGetLastStep", 1);
+
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("t = %.2Le no. steps = %ld order = %d stepsize = %.2Le\n",
+ t, nst, qu, hu);
+ printf("c1 (bot.left/middle/top rt.) = %12.3Le %12.3Le %12.3Le\n",
+ IJKth(udata,1,0,0), IJKth(udata,1,mxh,myh), IJKth(udata,1,mx1,my1));
+ printf("c2 (bot.left/middle/top rt.) = %12.3Le %12.3Le %12.3Le\n\n",
+ IJKth(udata,2,0,0), IJKth(udata,2,mxh,myh), IJKth(udata,2,mx1,my1));
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("t = %.2le no. steps = %ld order = %d stepsize = %.2le\n",
+ t, nst, qu, hu);
+ printf("c1 (bot.left/middle/top rt.) = %12.3le %12.3le %12.3le\n",
+ IJKth(udata,1,0,0), IJKth(udata,1,mxh,myh), IJKth(udata,1,mx1,my1));
+ printf("c2 (bot.left/middle/top rt.) = %12.3le %12.3le %12.3le\n\n",
+ IJKth(udata,2,0,0), IJKth(udata,2,mxh,myh), IJKth(udata,2,mx1,my1));
+#else
+ printf("t = %.2e no. steps = %ld order = %d stepsize = %.2e\n",
+ t, nst, qu, hu);
+ printf("c1 (bot.left/middle/top rt.) = %12.3e %12.3e %12.3e\n",
+ IJKth(udata,1,0,0), IJKth(udata,1,mxh,myh), IJKth(udata,1,mx1,my1));
+ printf("c2 (bot.left/middle/top rt.) = %12.3e %12.3e %12.3e\n\n",
+ IJKth(udata,2,0,0), IJKth(udata,2,mxh,myh), IJKth(udata,2,mx1,my1));
+#endif
+}
+
+/* Get and print final statistics */
+
+static void PrintFinalStats(void *cvode_mem)
+{
+ long int lenrw, leniw ;
+ long int 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);
+}
+
+/* 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, 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);
+}
+
+/*
+ *-------------------------------
+ * Functions called by the solver
+ *-------------------------------
+ */
+
+/* f routine. Compute RHS function f(t,u). */
+
+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 jx, jy, idn, iup, ileft, iright;
+ UserData data;
+
+ data = (UserData) user_data;
+ udata = NV_DATA_S(u);
+ dudata = NV_DATA_S(udot);
+
+ /* Set diurnal rate coefficients. */
+
+ s = sin(data->om*t);
+ if (s > ZERO) {
+ q3 = EXP(-A3/s);
+ data->q4 = EXP(-A4/s);
+ } else {
+ q3 = ZERO;
+ data->q4 = ZERO;
+ }
+
+ /* Make local copies of problem variables, for efficiency. */
+
+ q4coef = data->q4;
+ dely = data->dy;
+ verdco = data->vdco;
+ hordco = data->hdco;
+ horaco = data->haco;
+
+ /* Loop over all grid points. */
+
+ for (jy=0; jy < MY; jy++) {
+
+ /* Set vertical diffusion coefficients at jy +- 1/2 */
+
+ ydn = YMIN + (jy - RCONST(0.5))*dely;
+ yup = ydn + dely;
+ cydn = verdco*EXP(RCONST(0.2)*ydn);
+ cyup = verdco*EXP(RCONST(0.2)*yup);
+ idn = (jy == 0) ? 1 : -1;
+ iup = (jy == MY-1) ? -1 : 1;
+ for (jx=0; jx < MX; jx++) {
+
+ /* Extract c1 and c2, and set kinetic rate terms. */
+
+ c1 = IJKth(udata,1,jx,jy);
+ c2 = IJKth(udata,2,jx,jy);
+ qq1 = Q1*c1*C3;
+ qq2 = Q2*c1*c2;
+ qq3 = q3*C3;
+ qq4 = q4coef*c2;
+ rkin1 = -qq1 - qq2 + TWO*qq3 + qq4;
+ rkin2 = qq1 - qq2 - qq4;
+
+ /* Set vertical diffusion terms. */
+
+ c1dn = IJKth(udata,1,jx,jy+idn);
+ c2dn = IJKth(udata,2,jx,jy+idn);
+ c1up = IJKth(udata,1,jx,jy+iup);
+ c2up = IJKth(udata,2,jx,jy+iup);
+ vertd1 = cyup*(c1up - c1) - cydn*(c1 - c1dn);
+ vertd2 = cyup*(c2up - c2) - cydn*(c2 - c2dn);
+
+ /* Set horizontal diffusion and advection terms. */
+
+ ileft = (jx == 0) ? 1 : -1;
+ iright =(jx == MX-1) ? -1 : 1;
+ c1lt = IJKth(udata,1,jx+ileft,jy);
+ c2lt = IJKth(udata,2,jx+ileft,jy);
+ c1rt = IJKth(udata,1,jx+iright,jy);
+ c2rt = IJKth(udata,2,jx+iright,jy);
+ hord1 = hordco*(c1rt - TWO*c1 + c1lt);
+ hord2 = hordco*(c2rt - TWO*c2 + c2lt);
+ horad1 = horaco*(c1rt - c1lt);
+ horad2 = horaco*(c2rt - c2lt);
+
+ /* Load all terms into udot. */
+
+ IJKth(dudata, 1, jx, jy) = vertd1 + hord1 + horad1 + rkin1;
+ IJKth(dudata, 2, jx, jy) = vertd2 + hord2 + horad2 + rkin2;
+ }
+ }
+
+ 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)
+{
+ realtype c1, c2, c1dn, c2dn, c1up, c2up, c1lt, c2lt, c1rt, c2rt;
+ realtype v1, v2, v1dn, v2dn, v1up, v2up, v1lt, v2lt, v1rt, v2rt;
+ realtype Jv1, Jv2;
+ realtype cydn, cyup;
+ realtype s, ydn, yup;
+ realtype q4coef, dely, verdco, hordco, horaco;
+ int jx, jy, idn, iup, ileft, iright;
+ realtype *udata, *vdata, *Jvdata;
+ UserData data;
+
+ data = (UserData) user_data;
+
+ udata = NV_DATA_S(u);
+ vdata = NV_DATA_S(v);
+ Jvdata = NV_DATA_S(Jv);
+
+ /* Set diurnal rate coefficients. */
+
+ s = sin(data->om*t);
+ if (s > ZERO) {
+ data->q4 = EXP(-A4/s);
+ } else {
+ data->q4 = ZERO;
+ }
+
+ /* Make local copies of problem variables, for efficiency. */
+
+ q4coef = data->q4;
+ dely = data->dy;
+ verdco = data->vdco;
+ hordco = data->hdco;
+ horaco = data->haco;
+
+ /* Loop over all grid points. */
+
+ for (jy=0; jy < MY; jy++) {
+
+ /* Set vertical diffusion coefficients at jy +- 1/2 */
+
+ ydn = YMIN + (jy - RCONST(0.5))*dely;
+ yup = ydn + dely;
+
+ cydn = verdco*EXP(RCONST(0.2)*ydn);
+ cyup = verdco*EXP(RCONST(0.2)*yup);
+
+ idn = (jy == 0) ? 1 : -1;
+ iup = (jy == MY-1) ? -1 : 1;
+
+ for (jx=0; jx < MX; jx++) {
+
+ Jv1 = ZERO;
+ Jv2 = ZERO;
+
+ /* Extract c1 and c2 at the current location and at neighbors */
+
+ c1 = IJKth(udata,1,jx,jy);
+ c2 = IJKth(udata,2,jx,jy);
+
+ v1 = IJKth(vdata,1,jx,jy);
+ v2 = IJKth(vdata,2,jx,jy);
+
+ c1dn = IJKth(udata,1,jx,jy+idn);
+ c2dn = IJKth(udata,2,jx,jy+idn);
+ c1up = IJKth(udata,1,jx,jy+iup);
+ c2up = IJKth(udata,2,jx,jy+iup);
+
+ v1dn = IJKth(vdata,1,jx,jy+idn);
+ v2dn = IJKth(vdata,2,jx,jy+idn);
+ v1up = IJKth(vdata,1,jx,jy+iup);
+ v2up = IJKth(vdata,2,jx,jy+iup);
+
+ ileft = (jx == 0) ? 1 : -1;
+ iright =(jx == MX-1) ? -1 : 1;
+
+ c1lt = IJKth(udata,1,jx+ileft,jy);
+ c2lt = IJKth(udata,2,jx+ileft,jy);
+ c1rt = IJKth(udata,1,jx+iright,jy);
+ c2rt = IJKth(udata,2,jx+iright,jy);
+
+ v1lt = IJKth(vdata,1,jx+ileft,jy);
+ v2lt = IJKth(vdata,2,jx+ileft,jy);
+ v1rt = IJKth(vdata,1,jx+iright,jy);
+ v2rt = IJKth(vdata,2,jx+iright,jy);
+
+ /* Set kinetic rate terms. */
+
+ //rkin1 = -Q1*C3 * c1 - Q2 * c1*c2 + q4coef * c2 + TWO*C3*q3;
+ //rkin2 = Q1*C3 * c1 - Q2 * c1*c2 - q4coef * c2;
+
+ Jv1 += -(Q1*C3 + Q2*c2) * v1 + (q4coef - Q2*c1) * v2;
+ Jv2 += (Q1*C3 - Q2*c2) * v1 - (q4coef + Q2*c1) * v2;
+
+ /* Set vertical diffusion terms. */
+
+ //vertd1 = -(cyup+cydn) * c1 + cyup * c1up + cydn * c1dn;
+ //vertd2 = -(cyup+cydn) * c2 + cyup * c2up + cydn * c2dn;
+
+ Jv1 += -(cyup+cydn) * v1 + cyup * v1up + cydn * v1dn;
+ Jv2 += -(cyup+cydn) * v2 + cyup * v2up + cydn * v2dn;
+
+ /* Set horizontal diffusion and advection terms. */
+
+ //hord1 = hordco*(c1rt - TWO*c1 + c1lt);
+ //hord2 = hordco*(c2rt - TWO*c2 + c2lt);
+
+ Jv1 += hordco*(v1rt - TWO*v1 + v1lt);
+ Jv2 += hordco*(v2rt - TWO*v2 + v2lt);
+
+ //horad1 = horaco*(c1rt - c1lt);
+ //horad2 = horaco*(c2rt - c2lt);
+
+ Jv1 += horaco*(v1rt - v1lt);
+ Jv2 += horaco*(v2rt - v2lt);
+
+ /* Load two components of J*v */
+
+ //IJKth(dudata, 1, jx, jy) = vertd1 + hord1 + horad1 + rkin1;
+ //IJKth(dudata, 2, jx, jy) = vertd2 + hord2 + horad2 + rkin2;
+
+ IJKth(Jvdata, 1, jx, jy) = Jv1;
+ IJKth(Jvdata, 2, jx, jy) = Jv2;
+
+ }
+
+ }
+
+ return(0);
+
+}
+
+
+/* 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 c1, c2, cydn, cyup, diag, ydn, yup, q4coef, dely, verdco, hordco;
+ realtype **(*P)[MY], **(*Jbd)[MY];
+ long int *(*pivot)[MY], ier;
+ int jx, jy;
+ realtype *udata, **a, **j;
+ UserData data;
+
+ /* Make local copies of pointers in user_data, and of pointer to u's data */
+
+ data = (UserData) user_data;
+ P = data->P;
+ Jbd = data->Jbd;
+ pivot = data->pivot;
+ udata = NV_DATA_S(u);
+
+ if (jok) {
+
+ /* jok = TRUE: 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;
+
+ }
+
+ else {
+ /* jok = FALSE: Generate Jbd from scratch and copy to P */
+
+ /* Make local copies of problem variables, for efficiency. */
+
+ q4coef = data->q4;
+ dely = data->dy;
+ verdco = data->vdco;
+ hordco = data->hdco;
+
+ /* Compute 2x2 diagonal Jacobian blocks (using q4 values
+ computed on the last f call). Load into P. */
+
+ for (jy=0; jy < MY; jy++) {
+ ydn = YMIN + (jy - RCONST(0.5))*dely;
+ yup = ydn + dely;
+ cydn = verdco*EXP(RCONST(0.2)*ydn);
+ cyup = verdco*EXP(RCONST(0.2)*yup);
+ diag = -(cydn + cyup + TWO*hordco);
+ for (jx=0; jx < MX; jx++) {
+ c1 = IJKth(udata,1,jx,jy);
+ c2 = IJKth(udata,2,jx,jy);
+ j = Jbd[jx][jy];
+ a = P[jx][jy];
+ IJth(j,1,1) = (-Q1*C3 - Q2*c2) + diag;
+ IJth(j,1,2) = -Q2*c1 + q4coef;
+ IJth(j,2,1) = Q1*C3 - Q2*c2;
+ IJth(j,2,2) = (-Q2*c1 - q4coef) + diag;
+ denseCopy(j, a, NUM_SPECIES, NUM_SPECIES);
+ }
+ }
+
+ *jcurPtr = TRUE;
+
+ }
+
+ /* Scale by -gamma */
+
+ for (jy=0; jy < MY; jy++)
+ for (jx=0; jx < MX; jx++)
+ denseScale(-gamma, P[jx][jy], NUM_SPECIES, NUM_SPECIES);
+
+ /* Add identity matrix and do LU decompositions on blocks in place. */
+
+ for (jx=0; jx < MX; jx++) {
+ for (jy=0; jy < MY; jy++) {
+ denseAddIdentity(P[jx][jy], NUM_SPECIES);
+ ier = denseGETRF(P[jx][jy], NUM_SPECIES, NUM_SPECIES, pivot[jx][jy]);
+ if (ier != 0) return(1);
+ }
+ }
+
+ return(0);
+}
+
+/* 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)
+{
+ realtype **(*P)[MY];
+ long int *(*pivot)[MY];
+ int jx, jy;
+ realtype *zdata, *v;
+ UserData data;
+
+ /* Extract the P and pivot arrays from user_data. */
+
+ data = (UserData) user_data;
+ P = data->P;
+ pivot = data->pivot;
+ zdata = NV_DATA_S(z);
+
+ N_VScale(ONE, r, z);
+
+ /* Solve the block-diagonal system Px = r using LU factors stored
+ in P and pivot data in pivot, and return the solution in z. */
+
+ for (jx=0; jx < MX; jx++) {
+ for (jy=0; jy < MY; jy++) {
+ v = &(IJKth(zdata, 1, jx, jy));
+ denseGETRS(P[jx][jy], NUM_SPECIES, pivot[jx][jy], v);
+ }
+ }
+
+ return(0);
+}
diff --git a/examples/cvodes/serial/cvsDiurnal_kry.out b/examples/cvodes/serial/cvsDiurnal_kry.out
new file mode 100644
index 0000000..7edac66
--- /dev/null
+++ b/examples/cvodes/serial/cvsDiurnal_kry.out
@@ -0,0 +1,63 @@
+
+2-species diurnal advection-diffusion problem
+
+t = 7.20e+03 no. steps = 219 order = 5 stepsize = 1.59e+02
+c1 (bot.left/middle/top rt.) = 1.047e+04 2.964e+04 1.119e+04
+c2 (bot.left/middle/top rt.) = 2.527e+11 7.154e+11 2.700e+11
+
+t = 1.44e+04 no. steps = 251 order = 5 stepsize = 3.77e+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 = 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
+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
+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
+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
+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
+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
+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
+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
+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
+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
+ncfn = 0 ncfl = 0
+
diff --git a/examples/cvodes/serial/cvsDiurnal_kry_bp.c b/examples/cvodes/serial/cvsDiurnal_kry_bp.c
new file mode 100644
index 0000000..77fcec4
--- /dev/null
+++ b/examples/cvodes/serial/cvsDiurnal_kry_bp.c
@@ -0,0 +1,530 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.2 $
+ * $Date: 2010/12/01 22:57:59 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh and
+ * Radu Serban @LLNL
+ * -----------------------------------------------------------------
+ * Example problem:
+ *
+ * An ODE system is generated from the following 2-species diurnal
+ * kinetics advection-diffusion PDE system in 2 space dimensions:
+ *
+ * dc(i)/dt = Kh*(d/dx)^2 c(i) + V*dc(i)/dx + (d/dy)(Kv(y)*dc(i)/dy)
+ * + Ri(c1,c2,t) for i = 1,2, where
+ * R1(c1,c2,t) = -q1*c1*c3 - q2*c1*c2 + 2*q3(t)*c3 + q4(t)*c2 ,
+ * R2(c1,c2,t) = q1*c1*c3 - q2*c1*c2 - q4(t)*c2 ,
+ * Kv(y) = Kv0*exp(y/5) ,
+ * Kh, V, Kv0, q1, q2, and c3 are constants, and q3(t) and q4(t)
+ * vary diurnally. The problem is posed on the square
+ * 0 <= x <= 20, 30 <= y <= 50 (all in km),
+ * with homogeneous Neumann boundary conditions, and for time t in
+ * 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
+ * method (i.e. using the CVSPGMR linear solver) and a banded
+ * 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 <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, SQR, and EXP */
+
+/* Problem Constants */
+
+#define ZERO RCONST(0.0)
+#define ONE RCONST(1.0)
+#define TWO RCONST(2.0)
+
+#define NUM_SPECIES 2 /* number of species */
+#define KH RCONST(4.0e-6) /* horizontal diffusivity Kh */
+#define VEL RCONST(0.001) /* advection velocity V */
+#define KV0 RCONST(1.0e-8) /* coefficient in Kv(y) */
+#define Q1 RCONST(1.63e-16) /* coefficients q1, q2, c3 */
+#define Q2 RCONST(4.66e-16)
+#define C3 RCONST(3.7e16)
+#define A3 RCONST(22.62) /* coefficient in expression for q3(t) */
+#define A4 RCONST(7.601) /* coefficient in expression for q4(t) */
+#define C1_SCALE RCONST(1.0e6) /* coefficients in initial profiles */
+#define C2_SCALE RCONST(1.0e12)
+
+#define T0 ZERO /* initial time */
+#define NOUT 12 /* number of output times */
+#define TWOHR RCONST(7200.0) /* number of seconds in two hours */
+#define HALFDAY RCONST(4.32e4) /* number of seconds in a half day */
+#define PI RCONST(3.1415926535898) /* pi */
+
+#define XMIN ZERO /* grid boundaries in x */
+#define XMAX RCONST(20.0)
+#define YMIN RCONST(30.0) /* grid boundaries in y */
+#define YMAX RCONST(50.0)
+#define XMID RCONST(10.0) /* grid midpoints in x,y */
+#define YMID RCONST(40.0)
+
+#define MX 10 /* MX = number of x mesh points */
+#define MY 10 /* MY = number of y mesh points */
+#define NSMX 20 /* NSMX = NUM_SPECIES*MX */
+#define MM (MX*MY) /* MM = MX*MY */
+
+/* CVodeInit Constants */
+
+#define RTOL RCONST(1.0e-5) /* scalar relative tolerance */
+#define FLOOR RCONST(100.0) /* value of C1 or C2 at which tolerances */
+ /* change from relative to absolute */
+#define ATOL (RTOL*FLOOR) /* scalar absolute tolerance */
+#define NEQ (NUM_SPECIES*MM) /* NEQ = number of equations */
+
+/* User-defined vector and matrix accessor macros: IJKth, IJth */
+
+/* IJKth is defined in order to isolate the translation from the
+ mathematical 3-dimensional structure of the dependent variable vector
+ to the underlying 1-dimensional storage. IJth is defined in order to
+ write code which indexes into small dense matrices with a (row,column)
+ pair, where 1 <= row, column <= NUM_SPECIES.
+
+ 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 = NV_DATA_S(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
+ work with matrices stored by column in a 2-dimensional array. In C,
+ arrays are indexed starting at 0, not 1. */
+
+#define IJKth(vdata,i,j,k) (vdata[i-1 + (j)*NUM_SPECIES + (k)*NSMX])
+#define IJth(a,i,j) (a[j-1][i-1])
+
+/* Type : UserData
+ contains problem constants */
+
+typedef struct {
+ realtype q4, om, dx, dy, hdco, haco, vdco;
+} *UserData;
+
+/* Private Helper Functions */
+
+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 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, char *funcname, int opt);
+
+/* Function Called by the Solver */
+
+static int f(realtype t, N_Vector u, N_Vector udot, void *user_data);
+
+/*
+ *-------------------------------
+ * Main Program
+ *-------------------------------
+ */
+
+int main()
+{
+ realtype abstol, reltol, t, tout;
+ N_Vector u;
+ UserData data;
+ void *cvode_mem;
+ int flag, iout, jpre;
+ long int ml, mu;
+
+ u = NULL;
+ data = NULL;
+ cvode_mem = NULL;
+
+ /* Allocate and initialize u, and set problem data and tolerances */
+ u = N_VNew_Serial(NEQ);
+ if(check_flag((void *)u, "N_VNew_Serial", 0)) return(1);
+ data = (UserData) malloc(sizeof *data);
+ if(check_flag((void *)data, "malloc", 2)) return(1);
+ InitUserData(data);
+ SetInitialProfiles(u, data->dx, data->dy);
+ abstol = ATOL;
+ reltol = RTOL;
+
+ /* 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);
+
+ /* Set the pointer to user-defined data */
+ flag = CVodeSetUserData(cvode_mem, data);
+ if(check_flag(&flag, "CVodeSetUserData", 1)) 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
+ * 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 tolerances */
+ 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 CVBandPreInit to initialize band preconditioner */
+ ml = mu = 2;
+ flag = CVBandPrecInit(cvode_mem, NEQ, mu, ml);
+ if(check_flag(&flag, "CVBandPrecInit", 0)) return(1);
+
+ PrintIntro(mu, ml);
+
+ /* 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 solver, and CVSPGMR */
+
+ if (jpre == PREC_RIGHT) {
+
+ SetInitialProfiles(u, data->dx, data->dy);
+
+ 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);
+
+ printf("\n\n-------------------------------------------------------");
+ printf("------------\n");
+ }
+
+ printf("\n\nPreconditioner type is: jpre = %s\n\n",
+ (jpre == PREC_LEFT) ? "PREC_LEFT" : "PREC_RIGHT");
+
+ /* In loop over output points, call CVode, print results, test for error */
+
+ for (iout = 1, tout = TWOHR; iout <= NOUT; iout++, tout += TWOHR) {
+ flag = CVode(cvode_mem, tout, u, &t, CV_NORMAL);
+ check_flag(&flag, "CVode", 1);
+ PrintOutput(cvode_mem, u, t);
+ if (flag != CV_SUCCESS) {
+ break;
+ }
+ }
+
+ /* Print final statistics */
+
+ PrintFinalStats(cvode_mem);
+
+ } /* End of jpre loop */
+
+ /* Free memory */
+ N_VDestroy_Serial(u);
+ free(data);
+ CVodeFree(&cvode_mem);
+
+ return(0);
+}
+
+/*
+ *-------------------------------
+ * Private helper functions
+ *-------------------------------
+ */
+
+/* Load problem constants in data */
+
+static void InitUserData(UserData data)
+{
+ data->om = PI/HALFDAY;
+ data->dx = (XMAX-XMIN)/(MX-1);
+ data->dy = (YMAX-YMIN)/(MY-1);
+ data->hdco = KH/SQR(data->dx);
+ data->haco = VEL/(TWO*data->dx);
+ data->vdco = (ONE/SQR(data->dy))*KV0;
+}
+
+/* Set initial conditions in u */
+
+static void SetInitialProfiles(N_Vector u, realtype dx, realtype dy)
+{
+ int jx, jy;
+ realtype x, y, cx, cy;
+ realtype *udata;
+
+ /* Set pointer to data array in vector u. */
+
+ udata = NV_DATA_S(u);
+
+ /* Load initial profiles of c1 and c2 into u vector */
+
+ for (jy = 0; jy < MY; jy++) {
+ y = YMIN + jy*dy;
+ cy = SQR(RCONST(0.1)*(y - YMID));
+ cy = ONE - cy + RCONST(0.5)*SQR(cy);
+ for (jx = 0; jx < MX; jx++) {
+ x = XMIN + jx*dx;
+ cx = SQR(RCONST(0.1)*(x - XMID));
+ cx = ONE - cx + RCONST(0.5)*SQR(cx);
+ IJKth(udata,1,jx,jy) = C1_SCALE*cx*cy;
+ IJKth(udata,2,jx,jy) = C2_SCALE*cx*cy;
+ }
+ }
+}
+
+static void PrintIntro(long int mu, long int ml)
+{
+ printf("2-species diurnal advection-diffusion problem, %d by %d mesh\n",
+ MX, MY);
+ printf("SPGMR solver; band preconditioner; mu = %d, ml = %d\n\n",
+ mu, 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)
+{
+ 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 = NV_DATA_S(u);
+
+ flag = CVodeGetNumSteps(cvode_mem, &nst);
+ check_flag(&flag, "CVodeGetNumSteps", 1);
+ flag = CVodeGetLastOrder(cvode_mem, &qu);
+ check_flag(&flag, "CVodeGetLastOrder", 1);
+ flag = CVodeGetLastStep(cvode_mem, &hu);
+ check_flag(&flag, "CVodeGetLastStep", 1);
+
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("t = %.2Le no. steps = %ld order = %d stepsize = %.2Le\n",
+ t, nst, qu, hu);
+ printf("c1 (bot.left/middle/top rt.) = %12.3Le %12.3Le %12.3Le\n",
+ IJKth(udata,1,0,0), IJKth(udata,1,mxh,myh), IJKth(udata,1,mx1,my1));
+ printf("c2 (bot.left/middle/top rt.) = %12.3Le %12.3Le %12.3Le\n\n",
+ IJKth(udata,2,0,0), IJKth(udata,2,mxh,myh), IJKth(udata,2,mx1,my1));
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("t = %.2le no. steps = %ld order = %d stepsize = %.2le\n",
+ t, nst, qu, hu);
+ printf("c1 (bot.left/middle/top rt.) = %12.3le %12.3le %12.3le\n",
+ IJKth(udata,1,0,0), IJKth(udata,1,mxh,myh), IJKth(udata,1,mx1,my1));
+ printf("c2 (bot.left/middle/top rt.) = %12.3le %12.3le %12.3le\n\n",
+ IJKth(udata,2,0,0), IJKth(udata,2,mxh,myh), IJKth(udata,2,mx1,my1));
+#else
+ printf("t = %.2e no. steps = %ld order = %d stepsize = %.2e\n",
+ t, nst, qu, hu);
+ printf("c1 (bot.left/middle/top rt.) = %12.3e %12.3e %12.3e\n",
+ IJKth(udata,1,0,0), IJKth(udata,1,mxh,myh), IJKth(udata,1,mx1,my1));
+ printf("c2 (bot.left/middle/top rt.) = %12.3e %12.3e %12.3e\n\n",
+ IJKth(udata,2,0,0), IJKth(udata,2,mxh,myh), IJKth(udata,2,mx1,my1));
+#endif
+}
+
+/* Get and print final statistics */
+
+static void PrintFinalStats(void *cvode_mem)
+{
+ long int lenrw, leniw ;
+ long int lenrwLS, leniwLS;
+ long int lenrwBP, leniwBP;
+ long int nst, nfe, nsetups, nni, ncfn, netf;
+ long int nli, npe, nps, ncfl, nfeLS;
+ long int nfeBP;
+ 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);
+
+ flag = CVBandPrecGetWorkSpace(cvode_mem, &lenrwBP, &leniwBP);
+ check_flag(&flag, "CVBandPrecGetWorkSpace", 1);
+ flag = CVBandPrecGetNumRhsEvals(cvode_mem, &nfeBP);
+ 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("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);
+ 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);
+}
+
+/* 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, 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);
+}
+
+/*
+ *-------------------------------
+ * Function called by the solver
+ *-------------------------------
+ */
+
+/* f routine. Compute f(t,u). */
+
+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;
+ UserData data;
+
+ data = (UserData) user_data;
+ udata = NV_DATA_S(u);
+ dudata = NV_DATA_S(udot);
+
+ /* Set diurnal rate coefficients. */
+
+ s = sin(data->om*t);
+ if (s > ZERO) {
+ q3 = EXP(-A3/s);
+ data->q4 = EXP(-A4/s);
+ } else {
+ q3 = ZERO;
+ data->q4 = ZERO;
+ }
+
+ /* Make local copies of problem variables, for efficiency. */
+
+ q4coef = data->q4;
+ dely = data->dy;
+ verdco = data->vdco;
+ hordco = data->hdco;
+ horaco = data->haco;
+
+ /* Loop over all grid points. */
+
+ for (jy = 0; jy < MY; jy++) {
+
+ /* Set vertical diffusion coefficients at jy +- 1/2 */
+
+ ydn = YMIN + (jy - RCONST(0.5))*dely;
+ yup = ydn + dely;
+ cydn = verdco*EXP(RCONST(0.2)*ydn);
+ cyup = verdco*EXP(RCONST(0.2)*yup);
+ idn = (jy == 0) ? 1 : -1;
+ iup = (jy == MY-1) ? -1 : 1;
+ for (jx = 0; jx < MX; jx++) {
+
+ /* Extract c1 and c2, and set kinetic rate terms. */
+
+ c1 = IJKth(udata,1,jx,jy);
+ c2 = IJKth(udata,2,jx,jy);
+ qq1 = Q1*c1*C3;
+ qq2 = Q2*c1*c2;
+ qq3 = q3*C3;
+ qq4 = q4coef*c2;
+ rkin1 = -qq1 - qq2 + TWO*qq3 + qq4;
+ rkin2 = qq1 - qq2 - qq4;
+
+ /* Set vertical diffusion terms. */
+
+ c1dn = IJKth(udata,1,jx,jy+idn);
+ c2dn = IJKth(udata,2,jx,jy+idn);
+ c1up = IJKth(udata,1,jx,jy+iup);
+ c2up = IJKth(udata,2,jx,jy+iup);
+ vertd1 = cyup*(c1up - c1) - cydn*(c1 - c1dn);
+ vertd2 = cyup*(c2up - c2) - cydn*(c2 - c2dn);
+
+ /* Set horizontal diffusion and advection terms. */
+
+ ileft = (jx == 0) ? 1 : -1;
+ iright =(jx == MX-1) ? -1 : 1;
+ c1lt = IJKth(udata,1,jx+ileft,jy);
+ c2lt = IJKth(udata,2,jx+ileft,jy);
+ c1rt = IJKth(udata,1,jx+iright,jy);
+ c2rt = IJKth(udata,2,jx+iright,jy);
+ hord1 = hordco*(c1rt - TWO*c1 + c1lt);
+ hord2 = hordco*(c2rt - TWO*c2 + c2lt);
+ horad1 = horaco*(c1rt - c1lt);
+ horad2 = horaco*(c2rt - c2lt);
+
+ /* Load all terms into udot. */
+
+ IJKth(dudata, 1, jx, jy) = vertd1 + hord1 + horad1 + rkin1;
+ IJKth(dudata, 2, jx, jy) = vertd2 + hord2 + horad2 + rkin2;
+ }
+ }
+
+ return(0);
+}
diff --git a/examples/cvodes/serial/cvsDiurnal_kry_bp.out b/examples/cvodes/serial/cvsDiurnal_kry_bp.out
new file mode 100644
index 0000000..6a49f52
--- /dev/null
+++ b/examples/cvodes/serial/cvsDiurnal_kry_bp.out
@@ -0,0 +1,138 @@
+2-species diurnal advection-diffusion problem, 10 by 10 mesh
+SPGMR solver; band preconditioner; mu = 2, ml = 2
+
+
+
+Preconditioner type is: jpre = PREC_LEFT
+
+t = 7.20e+03 no. steps = 190 order = 5 stepsize = 1.61e+02
+c1 (bot.left/middle/top rt.) = 1.047e+04 2.964e+04 1.119e+04
+c2 (bot.left/middle/top rt.) = 2.527e+11 7.154e+11 2.700e+11
+
+t = 1.44e+04 no. steps = 221 order = 5 stepsize = 3.83e+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 = 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
+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
+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
+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
+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
+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
+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
+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
+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
+
+
+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
+ncfn = 0 ncfl = 0
+
+
+
+-------------------------------------------------------------------
+
+
+Preconditioner type is: jpre = PREC_RIGHT
+
+t = 7.20e+03 no. steps = 219 order = 5 stepsize = 1.55e+02
+c1 (bot.left/middle/top rt.) = 1.047e+04 2.964e+04 1.119e+04
+c2 (bot.left/middle/top rt.) = 2.527e+11 7.154e+11 2.700e+11
+
+t = 1.44e+04 no. steps = 251 order = 5 stepsize = 3.59e+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 = 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
+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
+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
+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
+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
+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
+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
+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
+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
+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
+ncfn = 0 ncfl = 0
+
diff --git a/examples/cvodes/serial/cvsFoodWeb_ASAi_kry.c b/examples/cvodes/serial/cvsFoodWeb_ASAi_kry.c
new file mode 100644
index 0000000..b665d1c
--- /dev/null
+++ b/examples/cvodes/serial/cvsFoodWeb_ASAi_kry.c
@@ -0,0 +1,1363 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.4 $
+ * $Date: 2011/11/23 23:53:02 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * This program solves a stiff ODE system that arises from a system
+ * of partial differential equations. The PDE system is a food web
+ * 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 )
+ *
+ * and the PDEs are as follows:
+ *
+ * i i i
+ * dc /dt = d(i)*(c + c ) + f (x,y,c) (i=1,...,ns)
+ * xx yy i
+ *
+ * where
+ *
+ * i ns j
+ * f (x,y,c) = c *(b(i) + sum a(i,j)*c ).
+ * i j=1
+ *
+ * The number of species is ns = 2*np, with the first np being prey
+ * and the last np being predators. The coefficients a(i,j), b(i),
+ * d(i) are:
+ *
+ * a(i,i) = -a (all i)
+ * a(i,j) = -g (i <= np, j > np)
+ * a(i,j) = e (i > np, j <= np)
+ * b(i) = b*(1 + alpha*x*y) (i <= np)
+ * b(i) = -b*(1 + alpha*x*y) (i > np)
+ * d(i) = Dprey (i <= np)
+ * d(i) = Dpred (i > np)
+ *
+ * The spatial domain is the unit square. The final time is 10.
+ * The boundary conditions are: normal derivative = 0.
+ * A polynomial in x and y is used to set the initial conditions.
+ *
+ * The PDEs are discretized by central differencing on an MX by 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 preconditioner matrix used is the product of two matrices:
+ * (1) A matrix, only defined implicitly, based on a fixed number
+ * of Gauss-Seidel iterations using the diffusion terms only.
+ * (2) A block-diagonal matrix based on the partial derivatives of
+ * the interaction terms f only, using block-grouping (computing
+ * only a subset of the ns by ns blocks).
+ *
+ * Additionally, CVODES integrates backwards in time the
+ * the semi-discrete form of the adjoint PDE:
+ * d(lambda)/dt = - D^T ( lambda_xx + lambda_yy )
+ * - F_c^T lambda - g_c^T
+ * with homogeneous Neumann boundary conditions and final
+ * conditions are the following:
+ * lambda(x,y,t=t_final) = 0.0
+ * whose solution at t = 0 represents the sensitivity of
+ * G = int_0^t_final int_x int _y g(t,c) dx dy dt
+ * with respect to the initial conditions of the original problem.
+ *
+ * In this example,
+ * g(t,c) = c(ISPEC), with ISPEC defined below.
+ *
+ * During the forward run, CVODES also computes G as
+ * G = phi(t_final)
+ * where
+ * d(phi)/dt = int_x int _y g(t,c) dx dy
+ * and the 2-D integral is evaluated with Simpson's rule.
+ * -----------------------------------------------------------------
+ * 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>
+#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>
+
+#define ZERO RCONST(0.0)
+#define ONE RCONST(1.0)
+
+/* Problem Specification Constants */
+
+#define AA ONE /* AA = a */
+#define EE RCONST(1e4) /* EE = e */
+#define GG RCONST(0.5e-6) /* GG = g */
+#define BB ONE /* BB = b */
+#define DPREY ONE
+#define DPRED RCONST(0.5)
+#define ALPH ONE
+#define NP 3
+#define NS (2*NP)
+
+/* Method Constants */
+
+#define MX 20
+#define MY 20
+#define MXNS (MX*NS)
+#define AX ONE
+#define AY ONE
+#define DX (AX/(realtype)(MX-1))
+#define DY (AY/(realtype)(MY-1))
+#define MP NS
+#define MQ (MX*MY)
+#define MXMP (MX*MP)
+#define NGX 2
+#define NGY 2
+#define NGRP (NGX*NGY)
+#define ITMAX 5
+
+/* CVodeInit Constants */
+
+#define NEQ (NS*MX*MY)
+#define T0 RCONST(0.0)
+#define RTOL RCONST(1e-5)
+#define ATOL RCONST(1e-5)
+
+/* Output Constants */
+
+#define TOUT RCONST(10.0)
+
+/* Note: The value for species i at mesh point (j,k) is stored in */
+/* component number (i-1) + j*NS + k*NS*MX of an N_Vector, */
+/* where 1 <= i <= NS, 0 <= j < MX, 0 <= k < MY. */
+
+/* Structure for user data */
+
+typedef struct {
+ realtype **P[NGRP];
+ long int *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];
+ realtype acoef[NS][NS], bcoef[NS], diff[NS];
+ realtype cox[NS], coy[NS], dx, dy, srur;
+ realtype fsave[NEQ];
+ realtype fBsave[NEQ];
+ N_Vector rewt;
+ void *cvode_mem;
+ int indexB;
+} *WebData;
+
+/* Adjoint calculation constants */
+/* G = int_t int_x int_y c(ISPEC) dy dx dt */
+
+#define NSTEPS 300 /* check points every NSTEPS steps */
+#define ISPEC 6 /* species # in objective */
+
+/* Prototypes for user-supplied functions */
+
+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);
+
+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);
+
+static int fB(realtype t, N_Vector c, N_Vector cB,
+ N_Vector cBdot, void *user_data);
+
+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);
+
+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);
+
+/* Prototypes for private functions */
+
+static WebData AllocUserData(void);
+static void InitUserData(WebData wdata);
+static void SetGroups(int m, int ng, int jg[], int jig[], int jr[]);
+static void CInit(N_Vector c, WebData wdata);
+static void PrintOutput(N_Vector c, int ns, int mxns, WebData wdata);
+static void FreeUserData(WebData wdata);
+static void WebRates(realtype x, realtype y, realtype t, realtype c[], realtype rate[],
+ WebData wdata);
+static void WebRatesB(realtype x, realtype y, realtype t, realtype c[], realtype cB[],
+ realtype rate[], realtype rateB[], 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 realtype doubleIntgr(N_Vector c, int i, WebData wdata);
+static int check_flag(void *flagvalue, char *funcname, int opt);
+
+/* Small Vector Kernels */
+
+static void v_inc_by_prod(realtype u[], realtype v[], realtype w[], int n);
+static void v_sum_prods(realtype u[], realtype p[], realtype q[], realtype v[], realtype w[],
+ int n);
+static void v_prod(realtype u[], realtype v[], realtype w[], int n);
+static void v_zero(realtype u[], int n);
+
+/*
+ *--------------------------------------------------------------------
+ * MAIN PROGRAM
+ *--------------------------------------------------------------------
+ */
+
+int main(int argc, char *argv[])
+{
+ realtype abstol=ATOL, reltol=RTOL, t;
+ N_Vector c;
+ WebData wdata;
+ void *cvode_mem;
+
+ int flag, ncheck;
+
+ int indexB;
+
+ realtype reltolB=RTOL, abstolB=ATOL;
+ N_Vector cB;
+
+ c = NULL;
+ cB = NULL;
+ wdata = NULL;
+ cvode_mem = NULL;
+
+ /* Allocate and initialize user data */
+
+ wdata = AllocUserData();
+ if(check_flag((void *)wdata, "AllocUserData", 2)) return(1);
+ InitUserData(wdata);
+
+ /* Set-up forward problem */
+
+ /* Initializations */
+ c = N_VNew_Serial(NEQ+1);
+ if(check_flag((void *)c, "N_VNew_Serial", 0)) return(1);
+ CInit(c, wdata);
+
+ /* Call CVodeCreate/CVodeInit for forward run */
+ printf("\nCreate and allocate CVODE memory for forward run\n");
+ cvode_mem = CVodeCreate(CV_BDF, CV_NEWTON);
+ if(check_flag((void *)cvode_mem, "CVodeCreate", 0)) return(1);
+ wdata->cvode_mem = cvode_mem; /* Used in Precond */
+ flag = CVodeSetUserData(cvode_mem, wdata);
+ if(check_flag(&flag, "CVodeSetUserData", 1)) return(1);
+ flag = CVodeInit(cvode_mem, f, T0, c);
+ if(check_flag(&flag, "CVodeInit", 1)) return(1);
+ 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);
+ flag = CVSpilsSetPreconditioner(cvode_mem, Precond, PSolve);
+ if(check_flag(&flag, "CVSpilsSetPreconditioner", 1)) return(1);
+
+ /* Set-up adjoint calculations */
+
+ printf("\nAllocate global memory\n");
+ flag = CVodeAdjInit(cvode_mem, NSTEPS, CV_HERMITE);
+ if(check_flag(&flag, "CVadjInit", 1)) return(1);
+
+ /* Perform forward run */
+
+ printf("\nForward integration\n");
+ flag = CVodeF(cvode_mem, TOUT, c, &t, CV_NORMAL, &ncheck);
+ if(check_flag(&flag, "CVodeF", 1)) return(1);
+
+ printf("\nncheck = %d\n", ncheck);
+
+
+#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, NV_DATA_S(c)[NEQ]);
+#else
+ printf("\n G = int_t int_x int_y c%d(t,x,y) dx dy dt = %f \n\n",
+ ISPEC, NV_DATA_S(c)[NEQ]);
+#endif
+
+ /* Set-up backward problem */
+
+ /* Allocate cB */
+ cB = N_VNew_Serial(NEQ);
+ if(check_flag((void *)cB, "N_VNew_Serial", 0)) return(1);
+ /* Initialize cB = 0 */
+ N_VConst(ZERO, cB);
+
+ /* Create and allocate CVODES memory for backward run */
+ printf("\nCreate and allocate CVODES memory for backward run\n");
+ flag = CVodeCreateB(cvode_mem, CV_BDF, CV_NEWTON, &indexB);
+ if(check_flag(&flag, "CVodeCreateB", 1)) return(1);
+ flag = CVodeSetUserDataB(cvode_mem, indexB, wdata);
+ if(check_flag(&flag, "CVodeSetUserDataB", 1)) return(1);
+ flag = CVodeSetMaxNumStepsB(cvode_mem, indexB, 1000);
+ if(check_flag(&flag, "CVodeSetMaxNumStepsB", 1)) return(1);
+ flag = CVodeInitB(cvode_mem, indexB, fB, TOUT, cB);
+ if(check_flag(&flag, "CVodeInitB", 1)) return(1);
+ flag = CVodeSStolerancesB(cvode_mem, indexB, reltolB, abstolB);
+ if(check_flag(&flag, "CVodeSStolerancesB", 1)) return(1);
+
+ wdata->indexB = indexB;
+
+ /* Call CVSpgmr */
+ flag = CVSpgmrB(cvode_mem, indexB, PREC_LEFT, 0);
+ if(check_flag(&flag, "CVSpgmrB", 1)) return(1);
+ flag = CVSpilsSetPreconditionerB(cvode_mem, indexB, PrecondB, PSolveB);
+ if(check_flag(&flag, "CVSpilsSetPreconditionerB", 1)) return(1);
+
+ /* Perform backward integration */
+
+ printf("\nBackward integration\n");
+ flag = CVodeB(cvode_mem, T0, CV_NORMAL);
+ if(check_flag(&flag, "CVodeB", 1)) return(1);
+
+ flag = CVodeGetB(cvode_mem, indexB, &t, cB);
+ if(check_flag(&flag, "CVodeGetB", 1)) return(1);
+
+ PrintOutput(cB, NS, MXNS, wdata);
+
+ /* Free all memory */
+ CVodeFree(&cvode_mem);
+
+ N_VDestroy_Serial(c);
+ N_VDestroy_Serial(cB);
+
+ FreeUserData(wdata);
+
+ return(0);
+}
+
+/*
+ *--------------------------------------------------------------------
+ * FUNCTIONS CALLED BY CVODES
+ *--------------------------------------------------------------------
+ */
+
+/*
+ * This routine computes the right-hand side of the ODE system and
+ * returns it in cdot. The interaction rates are computed by calls to WebRates,
+ * and these are saved in fsave for use in preconditioning.
+ */
+
+static int f(realtype t, N_Vector c, N_Vector cdot, void *user_data)
+{
+ int i, ic, ici, idxl, idxu, idyl, idyu, iyoff, jx, jy, ns, mxns;
+ realtype dcxli, dcxui, dcyli, dcyui, x, y, *cox, *coy, *fsave, dx, dy;
+ realtype *cdata, *cdotdata;
+ WebData wdata;
+
+ wdata = (WebData) user_data;
+ cdata = NV_DATA_S(c);
+ cdotdata = NV_DATA_S(cdot);
+
+ mxns = wdata->mxns;
+ ns = wdata->ns;
+ fsave = wdata->fsave;
+ cox = wdata->cox;
+ coy = wdata->coy;
+ mxns = wdata->mxns;
+ dx = wdata->dx;
+ dy = wdata->dy;
+
+ for (jy = 0; jy < MY; jy++) {
+ y = jy*dy;
+ iyoff = mxns*jy;
+ idyu = (jy == MY-1) ? -mxns : mxns;
+ idyl = (jy == 0) ? -mxns : mxns;
+ for (jx = 0; jx < MX; jx++) {
+ x = jx*dx;
+ ic = iyoff + ns*jx;
+ /* Get interaction rates at one point (x,y). */
+ WebRates(x, y, t, cdata+ic, fsave+ic, wdata);
+ idxu = (jx == MX-1) ? -ns : ns;
+ idxl = (jx == 0) ? -ns : ns;
+ for (i = 1; i <= ns; i++) {
+ ici = ic + i-1;
+ /* Do differencing in y. */
+ dcyli = cdata[ici] - cdata[ici-idyl];
+ dcyui = cdata[ici+idyu] - cdata[ici];
+ /* Do differencing in x. */
+ dcxli = cdata[ici] - cdata[ici-idxl];
+ dcxui = cdata[ici+idxu] - cdata[ici];
+ /* Collect terms and load cdot elements. */
+ cdotdata[ici] = coy[i-1]*(dcyui - dcyli) +
+ cox[i-1]*(dcxui - dcxli) +
+ fsave[ici];
+ }
+ }
+ }
+
+ /* Quadrature equation (species 1) */
+ cdotdata[NEQ] = doubleIntgr(c,ISPEC,wdata);
+
+ return(0);
+}
+
+/*
+ * This routine generates the block-diagonal part of the Jacobian
+ * corresponding to the interaction rates, multiplies by -gamma, adds
+ * the identity matrix, and calls denseGETRF to do the LU decomposition of
+ * each diagonal block. The computation of the diagonal blocks uses
+ * the preset block and grouping information. One block per group is
+ * computed. The Jacobian elements are generated by difference
+ * quotients using calls to the routine fblock.
+ *
+ * This routine can be regarded as a prototype for the general case
+ * 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)
+{
+ int N;
+ realtype ***P;
+ long int **pivot, ier;
+ int i, if0, if00, ig, igx, igy, j, jj, jx, jy;
+ int *jxr, *jyr, ngrp, ngx, ngy, mxmp, flag;
+ long int mp;
+ realtype uround, fac, r, r0, save, srur;
+ realtype *f1, *fsave, *cdata, *rewtdata;
+ void *cvode_mem;
+ WebData wdata;
+ N_Vector rewt;
+
+ wdata = (WebData) user_data;
+ cvode_mem = wdata->cvode_mem;
+ rewt = wdata->rewt;
+ flag = CVodeGetErrWeights(cvode_mem, rewt);
+ if(check_flag(&flag, "CVodeGetErrWeights", 1)) return(1);
+
+ cdata = NV_DATA_S(c);
+ rewtdata = NV_DATA_S(rewt);
+
+ uround = UNIT_ROUNDOFF;
+
+ P = wdata->P;
+ pivot = wdata->pivot;
+ jxr = wdata->jxr;
+ jyr = wdata->jyr;
+ mp = wdata->mp;
+ srur = wdata->srur;
+ ngrp = wdata->ngrp;
+ ngx = wdata->ngx;
+ ngy = wdata->ngy;
+ mxmp = wdata->mxmp;
+ fsave = wdata->fsave;
+
+ /* Make mp calls to fblock to approximate each diagonal block of Jacobian.
+ Here, fsave contains the base value of the rate vector and
+ r0 is a minimum increment factor for the difference quotient. */
+
+ f1 = NV_DATA_S(vtemp1);
+
+ fac = N_VWrmsNorm (fc, rewt);
+ N = NEQ+1;
+ r0 = RCONST(1000.0)*ABS(gamma)*uround*N*fac;
+ if (r0 == ZERO) r0 = ONE;
+
+ for (igy = 0; igy < ngy; igy++) {
+ jy = jyr[igy];
+ if00 = jy*mxmp;
+ for (igx = 0; igx < ngx; igx++) {
+ jx = jxr[igx];
+ if0 = if00 + jx*mp;
+ ig = igx + igy*ngx;
+ /* Generate ig-th diagonal block */
+ for (j = 0; j < mp; j++) {
+ /* Generate the jth column as a difference quotient */
+ jj = if0 + j;
+ save = cdata[jj];
+ r = MAX(srur*ABS(save),r0/rewtdata[jj]);
+ cdata[jj] += r;
+ fac = -gamma/r;
+ fblock (t, cdata, jx, jy, f1, wdata);
+ for (i = 0; i < mp; i++) {
+ P[ig][j][i] = (f1[i] - fsave[if0+i])*fac;
+ }
+ cdata[jj] = save;
+ }
+ }
+ }
+
+ /* Add identity matrix and do LU decompositions on blocks. */
+
+ for (ig = 0; ig < ngrp; ig++) {
+ denseAddIdentity(P[ig], mp);
+ ier = denseGETRF(P[ig], mp, mp, pivot[ig]);
+ if (ier != 0) return(1);
+ }
+
+ *jcurPtr = TRUE;
+ return(0);
+}
+
+/*
+ * This routine applies two inverse preconditioner matrices
+ * to the vector r, using the interaction-only block-diagonal Jacobian
+ * with block-grouping, denoted Jr, and Gauss-Seidel applied to the
+ * diffusion contribution to the Jacobian, denoted Jd.
+ * It first calls GSIter for a Gauss-Seidel approximation to
+ * ((I - gamma*Jd)-inverse)*r, and stores the result in z.
+ * 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 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)
+{
+ realtype ***P;
+ long int **pivot;
+ int jx, jy, igx, igy, iv, ig, *jigx, *jigy, mx, my, ngx;
+ long int mp;
+ WebData wdata;
+
+ wdata = (WebData) user_data;
+
+ N_VScale(ONE, r, z);
+
+ /* call GSIter for Gauss-Seidel iterations */
+
+ GSIter(gamma, z, vtemp, wdata);
+
+ /* Do backsolves for inverse of block-diagonal preconditioner factor */
+
+ P = wdata->P;
+ pivot = wdata->pivot;
+ mx = wdata->mx;
+ my = wdata->my;
+ ngx = wdata->ngx;
+ mp = wdata->mp;
+ jigx = wdata->jigx;
+ jigy = wdata->jigy;
+
+ iv = 0;
+ for (jy = 0; jy < my; jy++) {
+ igy = jigy[jy];
+ for (jx = 0; jx < mx; jx++) {
+ igx = jigx[jx];
+ ig = igx + igy*ngx;
+ denseGETRS(P[ig], mp, pivot[ig], &(NV_DATA_S(z)[iv]));
+ iv += mp;
+ }
+ }
+
+ /* Solve for the quadrature variable */
+ NV_DATA_S(z)[NEQ] = NV_DATA_S(r)[NEQ] + gamma*doubleIntgr(z,ISPEC,wdata);
+
+ return(0);
+}
+
+/*
+ * This routine computes the right-hand side of the adjoint ODE system and
+ * returns it in cBdot. The interaction rates are computed by calls to WebRates,
+ * and these are saved in fsave for use in preconditioning. The adjoint
+ * interaction rates are computed by calls to WebRatesB.
+ */
+
+static int fB(realtype t, N_Vector c, N_Vector cB,
+ N_Vector cBdot, void *user_data)
+{
+ int i, ic, ici, idxl, idxu, idyl, idyu, iyoff, jx, jy, ns, mxns;
+ realtype dcxli, dcxui, dcyli, dcyui, x, y, *cox, *coy, *fsave, *fBsave, dx, dy;
+ realtype *cdata, *cBdata, *cBdotdata;
+ WebData wdata;
+
+ realtype gu[NS];
+
+ wdata = (WebData) user_data;
+ cdata = NV_DATA_S(c);
+ cBdata = NV_DATA_S(cB);
+ cBdotdata = NV_DATA_S(cBdot);
+
+ mxns = wdata->mxns;
+ ns = wdata->ns;
+ fsave = wdata->fsave;
+ fBsave = wdata->fBsave;
+ cox = wdata->cox;
+ coy = wdata->coy;
+ mxns = wdata->mxns;
+ dx = wdata->dx;
+ dy = wdata->dy;
+
+ for ( i = 0; i < ns; i++ ) gu[i] = ZERO;
+ gu[ISPEC-1] = ONE;
+
+ for (jy = 0; jy < MY; jy++) {
+ y = jy*dy;
+ iyoff = mxns*jy;
+ idyu = (jy == MY-1) ? -mxns : mxns;
+ idyl = (jy == 0) ? -mxns : mxns;
+ for (jx = 0; jx < MX; jx++) {
+ x = jx*dx;
+ ic = iyoff + ns*jx;
+ /* Get interaction rates at one point (x,y). */
+ WebRatesB(x, y, t, cdata+ic, cBdata+ic, fsave+ic, fBsave+ic, wdata);
+ idxu = (jx == MX-1) ? -ns : ns;
+ idxl = (jx == 0) ? -ns : ns;
+ for (i = 1; i <= ns; i++) {
+ ici = ic + i-1;
+ /* Do differencing in y. */
+ dcyli = cBdata[ici] - cBdata[ici-idyl];
+ dcyui = cBdata[ici+idyu] - cBdata[ici];
+ /* Do differencing in x. */
+ dcxli = cBdata[ici] - cBdata[ici-idxl];
+ dcxui = cBdata[ici+idxu] - cBdata[ici];
+ /* Collect terms and load cdot elements. */
+ cBdotdata[ici] = - coy[i-1]*(dcyui - dcyli)
+ - cox[i-1]*(dcxui - dcxli)
+ - fBsave[ici]
+ - gu[i-1];
+ }
+ }
+ }
+
+ return(0);
+}
+
+/*
+ * Preconditioner setup function for the backward problem
+ */
+
+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)
+{
+ int N;
+ realtype ***P;
+ long int **pivot, ier;
+ int i, if0, if00, ig, igx, igy, j, jj, jx, jy;
+ int *jxr, *jyr, ngrp, ngx, ngy, mxmp, flag;
+ long int mp;
+ realtype uround, fac, r, r0, save, srur;
+ realtype *f1, *fsave, *cdata, *rewtdata;
+ void *cvode_mem;
+ WebData wdata;
+ N_Vector rewt;
+
+ wdata = (WebData) user_data;
+ cvode_mem = CVodeGetAdjCVodeBmem(wdata->cvode_mem, wdata->indexB);
+ if(check_flag((void *)cvode_mem, "CVadjGetCVodeBmem", 0)) return(1);
+ rewt = wdata->rewt;
+ flag = CVodeGetErrWeights(cvode_mem, rewt);
+ if(check_flag(&flag, "CVodeGetErrWeights", 1)) return(1);
+
+ cdata = NV_DATA_S(c);
+ rewtdata = NV_DATA_S(rewt);
+
+ uround = UNIT_ROUNDOFF;
+
+ P = wdata->P;
+ pivot = wdata->pivot;
+ jxr = wdata->jxr;
+ jyr = wdata->jyr;
+ mp = wdata->mp;
+ srur = wdata->srur;
+ ngrp = wdata->ngrp;
+ ngx = wdata->ngx;
+ ngy = wdata->ngy;
+ mxmp = wdata->mxmp;
+ fsave = wdata->fsave;
+
+ /* Make mp calls to fblock to approximate each diagonal block of Jacobian.
+ Here, fsave contains the base value of the rate vector and
+ r0 is a minimum increment factor for the difference quotient. */
+
+ f1 = NV_DATA_S(vtemp1);
+ fac = N_VWrmsNorm (fcB, rewt);
+ N = NEQ;
+ r0 = RCONST(1000.0)*ABS(gamma)*uround*N*fac;
+ if (r0 == ZERO) r0 = ONE;
+
+ for (igy = 0; igy < ngy; igy++) {
+ jy = jyr[igy];
+ if00 = jy*mxmp;
+ for (igx = 0; igx < ngx; igx++) {
+ jx = jxr[igx];
+ if0 = if00 + jx*mp;
+ ig = igx + igy*ngx;
+ /* Generate ig-th diagonal block */
+ for (j = 0; j < mp; j++) {
+ /* Generate the jth column as a difference quotient */
+ jj = if0 + j;
+ save = cdata[jj];
+ r = MAX(srur*ABS(save),r0/rewtdata[jj]);
+ cdata[jj] += r;
+ fac = gamma/r;
+ fblock (t, cdata, jx, jy, f1, wdata);
+ for (i = 0; i < mp; i++) {
+ P[ig][i][j] = (f1[i] - fsave[if0+i])*fac;
+ }
+ cdata[jj] = save;
+ }
+ }
+ }
+
+ /* Add identity matrix and do LU decompositions on blocks. */
+
+ for (ig = 0; ig < ngrp; ig++) {
+ denseAddIdentity(P[ig], mp);
+ ier = denseGETRF(P[ig], mp, mp, pivot[ig]);
+ if (ier != 0) return(1);
+ }
+
+ *jcurPtr = TRUE;
+ return(0);
+}
+
+/*
+ * Preconditioner solve function for the backward problem
+ */
+
+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)
+{
+ realtype ***P;
+ long int **pivot;
+ int jx, jy, igx, igy, iv, ig, *jigx, *jigy, mx, my, ngx;
+ long int mp;
+ WebData wdata;
+
+ wdata = (WebData) user_data;
+
+ N_VScale(ONE, r, z);
+
+ /* call GSIter for Gauss-Seidel iterations (same routine but with gamma=-gamma) */
+
+ GSIter(-gamma, z, vtemp, wdata);
+
+ /* Do backsolves for inverse of block-diagonal preconditioner factor */
+
+ P = wdata->P;
+ pivot = wdata->pivot;
+ mx = wdata->mx;
+ my = wdata->my;
+ ngx = wdata->ngx;
+ mp = wdata->mp;
+ jigx = wdata->jigx;
+ jigy = wdata->jigy;
+
+ iv = 0;
+ for (jy = 0; jy < my; jy++) {
+ igy = jigy[jy];
+ for (jx = 0; jx < mx; jx++) {
+ igx = jigx[jx];
+ ig = igx + igy*ngx;
+ denseGETRS(P[ig], mp, pivot[ig], &(NV_DATA_S(z)[iv]));
+ iv += mp;
+ }
+ }
+
+ return(0);
+}
+
+/*
+ *--------------------------------------------------------------------
+ * PRIVATE FUNCTIONS
+ *--------------------------------------------------------------------
+ */
+
+/*
+ * Allocate space for user data structure
+ */
+
+static WebData AllocUserData(void)
+{
+ int i, ngrp = NGRP, 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->rewt = N_VNew_Serial(NEQ+1);
+ return(wdata);
+}
+
+/*
+ * Initialize user data structure
+ */
+
+static void InitUserData(WebData wdata)
+{
+ int i, j, ns;
+ realtype *bcoef, *diff, *cox, *coy, dx, dy;
+ realtype (*acoef)[NS];
+
+ acoef = wdata->acoef;
+ bcoef = wdata->bcoef;
+ diff = wdata->diff;
+ cox = wdata->cox;
+ coy = wdata->coy;
+ ns = wdata->ns = NS;
+
+ for (j = 0; j < NS; j++) { for (i = 0; i < NS; i++) acoef[i][j] = ZERO; }
+ for (j = 0; j < NP; j++) {
+ for (i = 0; i < NP; i++) {
+ acoef[NP+i][j] = EE;
+ acoef[i][NP+j] = -GG;
+ }
+ acoef[j][j] = -AA;
+ acoef[NP+j][NP+j] = -AA;
+ bcoef[j] = BB;
+ bcoef[NP+j] = -BB;
+ diff[j] = DPREY;
+ diff[NP+j] = DPRED;
+ }
+
+ /* Set remaining problem parameters */
+
+ wdata->mxns = MXNS;
+ dx = wdata->dx = DX;
+ dy = wdata->dy = DY;
+ for (i = 0; i < ns; i++) {
+ cox[i] = diff[i]/SQR(dx);
+ coy[i] = diff[i]/SQR(dy);
+ }
+
+ /* Set remaining method parameters */
+
+ wdata->mp = MP;
+ wdata->mq = MQ;
+ wdata->mx = MX;
+ wdata->my = MY;
+ wdata->srur = SQRT(UNIT_ROUNDOFF);
+ wdata->mxmp = MXMP;
+ wdata->ngrp = NGRP;
+ wdata->ngx = NGX;
+ wdata->ngy = NGY;
+ SetGroups(MX, NGX, wdata->jgx, wdata->jigx, wdata->jxr);
+ SetGroups(MY, NGY, wdata->jgy, wdata->jigy, wdata->jyr);
+}
+
+/*
+ * This routine sets arrays jg, jig, and jr describing
+ * a uniform partition of (0,1,2,...,m-1) into ng groups.
+ * The arrays set are:
+ * jg = length ng+1 array of group boundaries.
+ * Group ig has indices j = jg[ig],...,jg[ig+1]-1.
+ * jig = length m array of group indices vs node index.
+ * Node index j is in group jig[j].
+ * jr = length ng array of indices representing the groups.
+ * The index for group ig is j = jr[ig].
+ */
+
+static void SetGroups(int m, int ng, int jg[], int jig[], int jr[])
+{
+ int ig, j, len1, mper, ngm1;
+
+ mper = m/ng; /* does integer division */
+ for (ig=0; ig < ng; ig++) jg[ig] = ig*mper;
+ jg[ng] = m;
+
+ ngm1 = ng - 1;
+ len1 = ngm1*mper;
+ for (j = 0; j < len1; j++) jig[j] = j/mper;
+ for (j = len1; j < m; j++) jig[j] = ngm1;
+
+ for (ig = 0; ig < ngm1; ig++) jr[ig] = ((2*ig+1)*mper-1)/2;
+ jr[ngm1] = (ngm1*mper+m-1)/2;
+}
+
+/*
+ * This routine computes and loads the vector of initial values.
+ */
+
+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 = NV_DATA_S(c);
+ ns = wdata->ns;
+ mxns = wdata->mxns;
+ dx = wdata->dx;
+ dy = wdata->dy;
+
+ x_factor = RCONST(4.0)/SQR(AX);
+ y_factor = RCONST(4.0)/SQR(AY);
+ for (jy = 0; jy < MY; jy++) {
+ y = jy*dy;
+ argy = SQR(y_factor*y*(AY-y));
+ iyoff = mxns*jy;
+ for (jx = 0; jx < MX; jx++) {
+ x = jx*dx;
+ argx = SQR(x_factor*x*(AX-x));
+ ioff = iyoff + ns*jx;
+ for (i = 1; i <= ns; i++) {
+ ici = ioff + i-1;
+ cdata[ici] = RCONST(10.0) + i*argx*argy;
+
+ /*if(i==1) cdata[ici] += ONE;*/
+
+ }
+ }
+ }
+
+ /* Initialize quadrature variable to zero */
+ cdata[NEQ] = ZERO;
+}
+
+/*
+ * This routine computes the interaction rates for the species
+ * c_1, ... ,c_ns (stored in c[0],...,c[ns-1]), at one spatial point
+ * and at time t.
+ */
+
+static void WebRates(realtype x, realtype y, realtype t, realtype c[],
+ realtype rate[], WebData wdata)
+{
+ int i, j, ns;
+ realtype fac, *bcoef;
+ realtype (*acoef)[NS];
+
+ ns = wdata->ns;
+ acoef = wdata->acoef;
+ bcoef = wdata->bcoef;
+
+ for (i = 0; i < ns; i++)
+ rate[i] = ZERO;
+
+ for (j = 0; j < ns; j++)
+ for (i = 0; i < ns; i++)
+ rate[i] += c[j] * acoef[i][j];
+
+ fac = ONE + ALPH*x*y;
+ for (i = 0; i < ns; i++)
+ rate[i] = c[i]*(bcoef[i]*fac + rate[i]);
+}
+
+/*
+ * This routine computes the interaction rates for the backward problem
+ */
+
+static void WebRatesB(realtype x, realtype y, realtype t, realtype c[], realtype cB[],
+ realtype rate[], realtype rateB[], WebData wdata)
+{
+ int i, j, ns;
+ realtype fac, *bcoef;
+ realtype (*acoef)[NS];
+
+ ns = wdata->ns;
+ acoef = wdata->acoef;
+ bcoef = wdata->bcoef;
+
+ fac = ONE + ALPH*x*y;
+
+ for (i = 0; i < ns; i++)
+ rate[i] = bcoef[i]*fac;
+
+ for (j = 0; j < ns; j++)
+ for (i = 0; i < ns; i++)
+ rate[i] += acoef[i][j]*c[j];
+
+ for (i = 0; i < ns; i++) {
+ rateB[i] = cB[i]*rate[i];
+ rate[i] = c[i]*rate[i];
+ }
+
+ for (j = 0; j < ns; j++)
+ for (i = 0; i < ns; i++)
+ rateB[i] += acoef[j][i]*c[j]*cB[j];
+}
+
+/*
+ * This routine computes one block of the interaction terms of the
+ * system, namely block (jx,jy), for use in preconditioning.
+ * Here jx and jy count from 0.
+ */
+
+static void fblock(realtype t, realtype cdata[], int jx, int jy,
+ realtype cdotdata[], WebData wdata)
+{
+ int iblok, ic;
+ realtype x, y;
+
+ iblok = jx + jy*(wdata->mx);
+ y = jy*(wdata->dy);
+ x = jx*(wdata->dx);
+ ic = (wdata->ns)*(iblok);
+ WebRates(x, y, t, cdata+ic, cdotdata, wdata);
+}
+
+
+/*
+ * This routine performs ITMAX=5 Gauss-Seidel iterations to compute an
+ * approximation to (P-inverse)*z, where P = I - gamma*Jd, and
+ * Jd represents the diffusion contributions to the Jacobian.
+ * The answer is stored in z on return, and x is a temporary vector.
+ * The dimensions below assume a global constant NS >= ns.
+ * Some inner loops of length ns are implemented with the small
+ * vector kernels v_sum_prods, v_prod, v_inc_by_prod.
+ */
+
+static void GSIter(realtype gamma, N_Vector z, N_Vector x,
+ WebData wdata)
+{
+ int i, ic, iter, iyoff, jx, jy, ns, mxns, mx, my, x_loc, y_loc;
+ realtype beta[NS], beta2[NS], cof1[NS], gam[NS], gam2[NS];
+ realtype temp, *cox, *coy, *xd, *zd;
+
+ xd = NV_DATA_S(x);
+ zd = NV_DATA_S(z);
+ ns = wdata->ns;
+ mx = wdata->mx;
+ my = wdata->my;
+ mxns = wdata->mxns;
+ cox = wdata->cox;
+ coy = wdata->coy;
+
+ /* Write matrix as P = D - L - U.
+ Load local arrays beta, beta2, gam, gam2, and cof1. */
+
+ for (i = 0; i < ns; i++) {
+ temp = ONE/(ONE + RCONST(2.0)*gamma*(cox[i] + coy[i]));
+ beta[i] = gamma*cox[i]*temp;
+ beta2[i] = RCONST(2.0)*beta[i];
+ gam[i] = gamma*coy[i]*temp;
+ gam2[i] = RCONST(2.0)*gam[i];
+ cof1[i] = temp;
+ }
+
+ /* Begin iteration loop.
+ Load vector x with (D-inverse)*z for first iteration. */
+
+ for (jy = 0; jy < my; jy++) {
+ iyoff = mxns*jy;
+ for (jx = 0; jx < mx; jx++) {
+ ic = iyoff + ns*jx;
+ v_prod(xd+ic, cof1, zd+ic, ns); /* x[ic+i] = cof1[i]z[ic+i] */
+ }
+ }
+ N_VConst(ZERO, z);
+
+ /* Looping point for iterations. */
+
+ for (iter=1; iter <= ITMAX; iter++) {
+
+ /* Calculate (D-inverse)*U*x if not the first iteration. */
+
+ if (iter > 1) {
+ for (jy=0; jy < my; jy++) {
+ iyoff = mxns*jy;
+ for (jx=0; jx < mx; jx++) { /* order of loops matters */
+ ic = iyoff + ns*jx;
+ x_loc = (jx == 0) ? 0 : ((jx == mx-1) ? 2 : 1);
+ y_loc = (jy == 0) ? 0 : ((jy == my-1) ? 2 : 1);
+ switch (3*y_loc+x_loc) {
+ case 0 : /* jx == 0, jy == 0 */
+ /* x[ic+i] = beta2[i]x[ic+ns+i] + gam2[i]x[ic+mxns+i] */
+ v_sum_prods(xd+ic, beta2, xd+ic+ns, gam2, xd+ic+mxns, ns);
+ break;
+ case 1 : /* 1 <= jx <= mx-2, jy == 0 */
+ /* x[ic+i] = beta[i]x[ic+ns+i] + gam2[i]x[ic+mxns+i] */
+ v_sum_prods(xd+ic, beta, xd+ic+ns, gam2, xd+ic+mxns, ns);
+ break;
+ case 2 : /* jx == mx-1, jy == 0 */
+ /* x[ic+i] = gam2[i]x[ic+mxns+i] */
+ v_prod(xd+ic, gam2, xd+ic+mxns, ns);
+ break;
+ case 3 : /* jx == 0, 1 <= jy <= my-2 */
+ /* x[ic+i] = beta2[i]x[ic+ns+i] + gam[i]x[ic+mxns+i] */
+ v_sum_prods(xd+ic, beta2, xd+ic+ns, gam, xd+ic+mxns, ns);
+ break;
+ case 4 : /* 1 <= jx <= mx-2, 1 <= jy <= my-2 */
+ /* x[ic+i] = beta[i]x[ic+ns+i] + gam[i]x[ic+mxns+i] */
+ v_sum_prods(xd+ic, beta, xd+ic+ns, gam, xd+ic+mxns, ns);
+ break;
+ case 5 : /* jx == mx-1, 1 <= jy <= my-2 */
+ /* x[ic+i] = gam[i]x[ic+mxns+i] */
+ v_prod(xd+ic, gam, xd+ic+mxns, ns);
+ break;
+ case 6 : /* jx == 0, jy == my-1 */
+ /* x[ic+i] = beta2[i]x[ic+ns+i] */
+ v_prod(xd+ic, beta2, xd+ic+ns, ns);
+ break;
+ case 7 : /* 1 <= jx <= mx-2, jy == my-1 */
+ /* x[ic+i] = beta[i]x[ic+ns+i] */
+ v_prod(xd+ic, beta, xd+ic+ns, ns);
+ break;
+ case 8 : /* jx == mx-1, jy == my-1 */
+ /* x[ic+i] = ZERO */
+ v_zero(xd+ic, ns);
+ break;
+ }
+ }
+ }
+ } /* end if (iter > 1) */
+
+ /* Overwrite x with [(I - (D-inverse)*L)-inverse]*x. */
+
+ for (jy=0; jy < my; jy++) {
+ iyoff = mxns*jy;
+ for (jx=0; jx < mx; jx++) { /* order of loops matters */
+ ic = iyoff + ns*jx;
+ x_loc = (jx == 0) ? 0 : ((jx == mx-1) ? 2 : 1);
+ y_loc = (jy == 0) ? 0 : ((jy == my-1) ? 2 : 1);
+ switch (3*y_loc+x_loc) {
+ case 0 : /* jx == 0, jy == 0 */
+ break;
+ case 1 : /* 1 <= jx <= mx-2, jy == 0 */
+ /* x[ic+i] += beta[i]x[ic-ns+i] */
+ v_inc_by_prod(xd+ic, beta, xd+ic-ns, ns);
+ break;
+ case 2 : /* jx == mx-1, jy == 0 */
+ /* x[ic+i] += beta2[i]x[ic-ns+i] */
+ v_inc_by_prod(xd+ic, beta2, xd+ic-ns, ns);
+ break;
+ case 3 : /* jx == 0, 1 <= jy <= my-2 */
+ /* x[ic+i] += gam[i]x[ic-mxns+i] */
+ v_inc_by_prod(xd+ic, gam, xd+ic-mxns, ns);
+ break;
+ case 4 : /* 1 <= jx <= mx-2, 1 <= jy <= my-2 */
+ /* x[ic+i] += beta[i]x[ic-ns+i] + gam[i]x[ic-mxns+i] */
+ v_inc_by_prod(xd+ic, beta, xd+ic-ns, ns);
+ v_inc_by_prod(xd+ic, gam, xd+ic-mxns, ns);
+ break;
+ case 5 : /* jx == mx-1, 1 <= jy <= my-2 */
+ /* x[ic+i] += beta2[i]x[ic-ns+i] + gam[i]x[ic-mxns+i] */
+ v_inc_by_prod(xd+ic, beta2, xd+ic-ns, ns);
+ v_inc_by_prod(xd+ic, gam, xd+ic-mxns, ns);
+ break;
+ case 6 : /* jx == 0, jy == my-1 */
+ /* x[ic+i] += gam2[i]x[ic-mxns+i] */
+ v_inc_by_prod(xd+ic, gam2, xd+ic-mxns, ns);
+ break;
+ case 7 : /* 1 <= jx <= mx-2, jy == my-1 */
+ /* x[ic+i] += beta[i]x[ic-ns+i] + gam2[i]x[ic-mxns+i] */
+ v_inc_by_prod(xd+ic, beta, xd+ic-ns, ns);
+ v_inc_by_prod(xd+ic, gam2, xd+ic-mxns, ns);
+ break;
+ case 8 : /* jx == mx-1, jy == my-1 */
+ /* x[ic+i] += beta2[i]x[ic-ns+i] + gam2[i]x[ic-mxns+i] */
+ v_inc_by_prod(xd+ic, beta2, xd+ic-ns, ns);
+ v_inc_by_prod(xd+ic, gam2, xd+ic-mxns, ns);
+ break;
+ }
+ }
+ }
+
+ /* Add increment x to z : z <- z+x */
+
+ N_VLinearSum(ONE, z, ONE, x, z);
+
+ }
+}
+
+static void v_inc_by_prod(realtype u[], realtype v[], realtype w[], int n)
+{
+ int i;
+ for (i=0; i < n; i++) u[i] += v[i]*w[i];
+}
+
+static void v_sum_prods(realtype u[], realtype p[], realtype q[],
+ realtype v[], realtype w[], int n)
+{
+ int i;
+ for (i=0; i < n; i++) u[i] = p[i]*q[i] + v[i]*w[i];
+}
+
+static void v_prod(realtype u[], realtype v[], realtype w[], int n)
+{
+ int i;
+ for (i=0; i < n; i++) u[i] = v[i]*w[i];
+}
+
+static void v_zero(realtype u[], int n)
+{
+ int i;
+ for (i=0; i < n; i++) u[i] = ZERO;
+}
+
+/*
+ * Print maximum sensitivity of G for each species
+ */
+
+static void PrintOutput(N_Vector cB, int ns, int mxns, WebData wdata)
+{
+ int i, jx, jy;
+ realtype *cdata, cij, cmax, x, y;
+
+ x = y = ZERO;
+
+ cdata = NV_DATA_S(cB);
+
+ for (i=1; i <= ns; i++) {
+
+ cmax = ZERO;
+
+ for (jy=MY-1; jy >= 0; jy--) {
+ for (jx=0; jx < MX; jx++) {
+ cij = cdata[(i-1) + jx*ns + jy*mxns];
+ if (ABS(cij) > cmax) {
+ cmax = cij;
+ x = jx * wdata->dx;
+ y = jy * wdata->dy;
+ }
+ }
+ }
+
+ printf("\nMaximum sensitivity with respect to I.C. of species %d\n", i);
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf(" lambda max = %Le\n",cmax);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf(" lambda max = %le\n",cmax);
+#else
+ printf(" lambda max = %e\n",cmax);
+#endif
+ printf("at\n");
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf(" x = %Le\n y = %Le\n", x, y);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf(" x = %le\n y = %le\n", x, y);
+#else
+ printf(" x = %e\n y = %e\n", x, y);
+#endif
+
+ }
+
+}
+
+/*
+ * Compute double space integral
+ */
+
+static realtype doubleIntgr(N_Vector c, int i, WebData wdata)
+{
+ realtype *cdata;
+ int ns, mx, my, mxns;
+ realtype dx, dy;
+ realtype intgr_xy, intgr_x;
+ int jx, jy;
+
+ cdata = NV_DATA_S(c);
+
+ ns = wdata->ns;
+ mx = wdata->mx;
+ my = wdata->my;
+ mxns = wdata->mxns;
+ dx = wdata->dx;
+ dy = wdata->dy;
+
+ jy = 0;
+ intgr_x = cdata[(i-1)+jy*mxns];
+ for (jx = 1; jx < mx-1; jx++) {
+ intgr_x += RCONST(2.0)*cdata[(i-1) + jx*ns + jy*mxns];
+ }
+ intgr_x += cdata[(i-1)+(mx-1)*ns+jy*mxns];
+ intgr_x *= RCONST(0.5)*dx;
+
+ intgr_xy = intgr_x;
+
+ for (jy = 1; jy < my-1; jy++) {
+
+ intgr_x = cdata[(i-1)+jy*mxns];
+ for (jx = 1; jx < mx-1; jx++) {
+ intgr_x += RCONST(2.0)*cdata[(i-1) + jx*ns + jy*mxns];
+ }
+ intgr_x += cdata[(i-1)+(mx-1)*ns+jy*mxns];
+ intgr_x *= RCONST(0.5)*dx;
+
+ intgr_xy += RCONST(2.0)*intgr_x;
+
+ }
+
+ jy = my-1;
+ intgr_x = cdata[(i-1)+jy*mxns];
+ for (jx = 1; jx < mx-1; jx++) {
+ intgr_x += RCONST(2.0)*cdata[(i-1) + jx*ns + jy*mxns];
+ }
+ intgr_x += cdata[(i-1)+(mx-1)*ns+jy*mxns];
+ intgr_x *= RCONST(0.5)*dx;
+
+ intgr_xy += intgr_x;
+
+ intgr_xy *= RCONST(0.5)*dy;
+
+ return(intgr_xy);
+}
+
+/*
+ * Free space allocated for the user data structure
+ */
+
+static void FreeUserData(WebData wdata)
+{
+ int i, ngrp;
+
+ ngrp = wdata->ngrp;
+ for(i=0; i < ngrp; i++) {
+ destroyMat((wdata->P)[i]);
+ destroyArray((wdata->pivot)[i]);
+ }
+ N_VDestroy_Serial(wdata->rewt);
+ free(wdata);
+}
+
+/*
+ * 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, 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/cvsFoodWeb_ASAi_kry.out b/examples/cvodes/serial/cvsFoodWeb_ASAi_kry.out
new file mode 100644
index 0000000..9855170
--- /dev/null
+++ b/examples/cvodes/serial/cvsFoodWeb_ASAi_kry.out
@@ -0,0 +1,51 @@
+
+Create and allocate CVODE memory for forward run
+
+Allocate global memory
+
+Forward integration
+
+ncheck = 2
+
+ G = int_t int_x int_y c6(t,x,y) dx dy dt = 422295.963896
+
+
+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
+at
+ x = 1.000000e+00
+ y = 1.000000e+00
+
+Maximum sensitivity with respect to I.C. of species 2
+ lambda max = 9.379464e+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
+at
+ x = 1.000000e+00
+ y = 1.000000e+00
+
+Maximum sensitivity with respect to I.C. of species 4
+ lambda max = -4.942530e-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
+at
+ x = 1.000000e+00
+ y = 0.000000e+00
+
+Maximum sensitivity with respect to I.C. of species 6
+ lambda max = 3.566293e-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
new file mode 100644
index 0000000..a65c3e5
--- /dev/null
+++ b/examples/cvodes/serial/cvsFoodWeb_ASAp_kry.c
@@ -0,0 +1,1359 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.4 $
+ * $Date: 2011/11/23 23:53:02 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * This program solves a stiff ODE system that arises from a system
+ * of partial differential equations. The PDE system is a food web
+ * 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 )
+ *
+ * and the PDEs are as follows:
+ *
+ * i i i
+ * dc /dt = d(i)*(c + c ) + f (x,y,c) (i=1,...,ns)
+ * xx yy i
+ *
+ * where
+ *
+ * i ns j
+ * f (x,y,c) = c *(b(i) + sum a(i,j)*c )
+ * i j=1
+ *
+ * The number of species is ns = 2*np, with the first np being prey
+ * and the last np being predators. The coefficients a(i,j), b(i),
+ * d(i) are:
+ *
+ * a(i,i) = -a (all i)
+ * a(i,j) = -g (i <= np, j > np)
+ * a(i,j) = e (i > np, j <= np)
+ * b(i) = b*(1 + alpha*x*y) (i <= np)
+ * b(i) = -b*(1 + alpha*x*y) (i > np)
+ * d(i) = Dprey (i <= np)
+ * d(i) = Dpred (i > np)
+ *
+ * The spatial domain is the unit square. The final time is 10.
+ * The boundary conditions are: normal derivative = 0.
+ * A polynomial in x and y is used to set the initial conditions.
+ *
+ * The PDEs are discretized by central differencing on an MX by
+ * 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 preconditioner matrix used is the product of two matrices:
+ * (1) A matrix, only defined implicitly, based on a fixed number
+ * of Gauss-Seidel iterations using the diffusion terms only.
+ * (2) A block-diagonal matrix based on the partial derivatives
+ * of the interaction terms f only, using block-grouping (computing
+ * only a subset of the ns by ns blocks).
+ *
+ * Additionally, CVODES can integrate backwards in time the
+ * the semi-discrete form of the adjoint PDE:
+ * d(lambda)/dt = - D^T ( lambda_xx + lambda_yy )
+ * - F_c^T lambda
+ * with homogeneous Neumann boundary conditions and final conditions
+ * lambda(x,y,t=t_final) = - g_c^T(t_final)
+ * whose solution at t = 0 represents the sensitivity of
+ * int_x int _y g(t_final,c) dx dy dt
+ * with respect to the initial conditions of the original problem.
+ *
+ * In this example,
+ * g(t,c) = c(ISPEC), with ISPEC defined below.
+ * -----------------------------------------------------------------
+ * 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>
+#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>
+
+#define ZERO RCONST(0.0)
+#define ONE RCONST(1.0)
+#define TWO RCONST(2.0)
+
+/* Problem Specification Constants */
+
+#define AA ONE /* AA = a */
+#define EE RCONST(1.0e4) /* EE = e */
+#define GG RCONST(0.5e-6) /* GG = g */
+#define BB ONE /* BB = b */
+#define DPREY ONE
+#define DPRED RCONST(0.5)
+#define ALPH ONE
+#define NP 3
+#define NS (2*NP)
+
+/* Method Constants */
+
+#define MX 20
+#define MY 20
+#define MXNS (MX*NS)
+#define AX ONE
+#define AY ONE
+#define DX (AX/(realtype)(MX-1))
+#define DY (AY/(realtype)(MY-1))
+#define MP NS
+#define MQ (MX*MY)
+#define MXMP (MX*MP)
+#define NGX 2
+#define NGY 2
+#define NGRP (NGX*NGY)
+#define ITMAX 5
+
+/* CVodeInit Constants */
+
+#define NEQ (NS*MX*MY)
+#define T0 ZERO
+#define RTOL RCONST(1.0e-5)
+#define ATOL RCONST(1.0e-5)
+
+/* Output Constants */
+
+#define TOUT RCONST(10.0)
+
+/* Note: The value for species i at mesh point (j,k) is stored in */
+/* component number (i-1) + j*NS + k*NS*MX of an N_Vector, */
+/* where 1 <= i <= NS, 0 <= j < MX, 0 <= k < MY. */
+
+/* Structure for user data */
+
+typedef struct {
+ realtype **P[NGRP];
+ long int *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];
+ realtype acoef[NS][NS], bcoef[NS], diff[NS];
+ realtype cox[NS], coy[NS], dx, dy, srur;
+ realtype fsave[NEQ];
+ realtype fBsave[NEQ];
+ N_Vector rewt;
+ void *cvode_mem;
+ int indexB;
+} *WebData;
+
+/* Adjoint calculation constants */
+/* g = int_x int_y c(ISPEC) dy dx at t = Tfinal */
+#define NSTEPS 80 /* check points every NSTEPS steps */
+#define ISPEC 6 /* species # in objective */
+
+/* Prototypes for user-supplied functions */
+
+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);
+
+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);
+
+static int fB(realtype t, N_Vector c, N_Vector cB,
+ N_Vector cBdot, void *user_data);
+
+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);
+
+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);
+
+/* Prototypes for private functions */
+
+static WebData AllocUserData(void);
+static void InitUserData(WebData wdata);
+static void SetGroups(int m, int ng, int jg[], int jig[], int jr[]);
+static void CInit(N_Vector c, WebData wdata);
+static void CbInit(N_Vector c, int is, WebData wdata);
+static void PrintOutput(N_Vector c, int ns, int mxns, WebData wdata);
+static void FreeUserData(WebData wdata);
+static void WebRates(realtype x, realtype y, realtype t, realtype c[], realtype rate[],
+ WebData wdata);
+static void WebRatesB(realtype x, realtype y, realtype t, realtype c[], realtype cB[],
+ realtype rate[], realtype rateB[], 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 realtype doubleIntgr(N_Vector c, int i, WebData wdata);
+static int check_flag(void *flagvalue, char *funcname, int opt);
+
+/* Small Vector Kernels */
+
+static void v_inc_by_prod(realtype u[], realtype v[], realtype w[], int n);
+static void v_sum_prods(realtype u[], realtype p[], realtype q[], realtype v[],
+ realtype w[], int n);
+static void v_prod(realtype u[], realtype v[], realtype w[], int n);
+static void v_zero(realtype u[], int n);
+
+/*
+ *--------------------------------------------------------------------
+ * MAIN PROGRAM
+ *--------------------------------------------------------------------
+ */
+
+int main(int argc, char *argv[])
+{
+ realtype abstol=ATOL, reltol=RTOL, t;
+ N_Vector c;
+ WebData wdata;
+ void *cvode_mem;
+
+ int flag, ncheck;
+
+ int indexB;
+
+ realtype reltolB=RTOL, abstolB=ATOL;
+ N_Vector cB;
+
+ c = cB = NULL;
+ wdata = NULL;
+ cvode_mem = NULL;
+
+ /* Allocate and initialize user data */
+
+ wdata = AllocUserData();
+ if(check_flag((void *)wdata, "AllocUserData", 2)) return(1);
+ InitUserData(wdata);
+
+ /* Set-up forward problem */
+
+ /* Initializations */
+ c = N_VNew_Serial(NEQ);
+ if(check_flag((void *)c, "N_VNew_Serial", 0)) return(1);
+ CInit(c, wdata);
+
+ /* Call CVodeCreate/CVodeInit for forward run */
+ printf("\nCreate and allocate CVODES memory for forward run\n");
+ cvode_mem = CVodeCreate(CV_BDF, CV_NEWTON);
+ if(check_flag((void *)cvode_mem, "CVodeCreate", 0)) return(1);
+ wdata->cvode_mem = cvode_mem; /* Used in Precond */
+ flag = CVodeSetUserData(cvode_mem, wdata);
+ if(check_flag(&flag, "CVodeSetUserData", 1)) return(1);
+ flag = CVodeInit(cvode_mem, f, T0, c);
+ if(check_flag(&flag, "CVodeInit", 1)) return(1);
+ 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);
+ flag = CVSpilsSetPreconditioner(cvode_mem, Precond, PSolve);
+ if(check_flag(&flag, "CVSpilsSetPreconditioner", 1)) return(1);
+
+ /* Set-up adjoint calculations */
+
+ printf("\nAllocate global memory\n");
+ flag = CVodeAdjInit(cvode_mem, NSTEPS, CV_HERMITE);
+ if(check_flag(&flag, "CVodeAdjInit", 1)) return(1);
+
+ /* Perform forward run */
+
+ printf("\nForward integration\n");
+ flag = CVodeF(cvode_mem, TOUT, c, &t, CV_NORMAL, &ncheck);
+ if(check_flag(&flag, "CVodeF", 1)) return(1);
+
+ printf("\nncheck = %d\n", ncheck);
+
+
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("\n g = int_x int_y c%d(Tfinal,x,y) dx dy = %Lf \n\n",
+ ISPEC, doubleIntgr(c,ISPEC,wdata));
+#else
+ printf("\n g = int_x int_y c%d(Tfinal,x,y) dx dy = %f \n\n",
+ ISPEC, doubleIntgr(c,ISPEC,wdata));
+#endif
+
+ /* Set-up backward problem */
+
+ /* Allocate cB */
+ cB = N_VNew_Serial(NEQ);
+ if(check_flag((void *)cB, "N_VNew_Serial", 0)) return(1);
+ /* Initialize cB = 0 */
+ CbInit(cB, ISPEC, wdata);
+
+ /* Create and allocate CVODES memory for backward run */
+ printf("\nCreate and allocate CVODES memory for backward run\n");
+ flag = CVodeCreateB(cvode_mem, CV_BDF, CV_NEWTON, &indexB);
+ if(check_flag(&flag, "CVodeCreateB", 1)) return(1);
+ flag = CVodeSetUserDataB(cvode_mem, indexB, wdata);
+ if(check_flag(&flag, "CVodeSetUserDataB", 1)) return(1);
+ flag = CVodeInitB(cvode_mem, indexB, fB, TOUT, cB);
+ if(check_flag(&flag, "CVodeInitB", 1)) return(1);
+ flag = CVodeSStolerancesB(cvode_mem, indexB, reltolB, abstolB);
+ if(check_flag(&flag, "CVodeSStolerancesB", 1)) return(1);
+
+ wdata->indexB = indexB;
+
+ /* Call CVSpgmr */
+ flag = CVSpgmrB(cvode_mem, indexB, PREC_LEFT, 0);
+ if(check_flag(&flag, "CVSpgmrB", 1)) return(1);
+ flag = CVSpilsSetPreconditionerB(cvode_mem, indexB, PrecondB, PSolveB);
+ if(check_flag(&flag, "CVSpilsSetPreconditionerB", 1)) return(1);
+
+ /* Perform backward integration */
+
+ printf("\nBackward integration\n");
+ flag = CVodeB(cvode_mem, T0, CV_NORMAL);
+ if(check_flag(&flag, "CVodeB", 1)) return(1);
+
+ flag = CVodeGetB(cvode_mem, indexB, &t, cB);
+ if(check_flag(&flag, "CVodeGetB", 1)) return(1);
+
+ PrintOutput(cB, NS, MXNS, wdata);
+
+ /* Free all memory */
+ CVodeFree(&cvode_mem);
+
+ N_VDestroy_Serial(c);
+ N_VDestroy_Serial(cB);
+
+ FreeUserData(wdata);
+
+ return(0);
+}
+
+/*
+ *--------------------------------------------------------------------
+ * FUNCTIONS CALLED BY CVODES
+ *--------------------------------------------------------------------
+ */
+
+/*
+ * This routine computes the right-hand side of the ODE system and
+ * returns it in cdot. The interaction rates are computed by calls to WebRates,
+ * and these are saved in fsave for use in preconditioning.
+ */
+
+static int f(realtype t, N_Vector c, N_Vector cdot, void *user_data)
+{
+ int i, ic, ici, idxl, idxu, idyl, idyu, iyoff, jx, jy, ns, mxns;
+ realtype dcxli, dcxui, dcyli, dcyui, x, y, *cox, *coy, *fsave, dx, dy;
+ realtype *cdata, *cdotdata;
+ WebData wdata;
+
+ wdata = (WebData) user_data;
+ cdata = NV_DATA_S(c);
+ cdotdata = NV_DATA_S(cdot);
+
+ mxns = wdata->mxns;
+ ns = wdata->ns;
+ fsave = wdata->fsave;
+ cox = wdata->cox;
+ coy = wdata->coy;
+ mxns = wdata->mxns;
+ dx = wdata->dx;
+ dy = wdata->dy;
+
+ for (jy = 0; jy < MY; jy++) {
+ y = jy*dy;
+ iyoff = mxns*jy;
+ idyu = (jy == MY-1) ? -mxns : mxns;
+ idyl = (jy == 0) ? -mxns : mxns;
+ for (jx = 0; jx < MX; jx++) {
+ x = jx*dx;
+ ic = iyoff + ns*jx;
+ /* Get interaction rates at one point (x,y). */
+ WebRates(x, y, t, cdata+ic, fsave+ic, wdata);
+ idxu = (jx == MX-1) ? -ns : ns;
+ idxl = (jx == 0) ? -ns : ns;
+ for (i = 1; i <= ns; i++) {
+ ici = ic + i-1;
+ /* Do differencing in y. */
+ dcyli = cdata[ici] - cdata[ici-idyl];
+ dcyui = cdata[ici+idyu] - cdata[ici];
+ /* Do differencing in x. */
+ dcxli = cdata[ici] - cdata[ici-idxl];
+ dcxui = cdata[ici+idxu] - cdata[ici];
+ /* Collect terms and load cdot elements. */
+ cdotdata[ici] = coy[i-1]*(dcyui - dcyli) +
+ cox[i-1]*(dcxui - dcxli) +
+ fsave[ici];
+ }
+ }
+ }
+
+ return(0);
+}
+
+/*
+ * This routine generates the block-diagonal part of the Jacobian
+ * corresponding to the interaction rates, multiplies by -gamma, adds
+ * the identity matrix, and calls denseGETRF to do the LU decomposition of
+ * each diagonal block. The computation of the diagonal blocks uses
+ * the preset block and grouping information. One block per group is
+ * computed. The Jacobian elements are generated by difference
+ * quotients using calls to the routine fblock.
+ *
+ * This routine can be regarded as a prototype for the general case
+ * 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)
+{
+ realtype ***P;
+ long int **pivot, ier;
+ int i, if0, if00, ig, igx, igy, j, jj, jx, jy;
+ int *jxr, *jyr, ngrp, ngx, ngy, mxmp, flag;
+ long int mp;
+ realtype uround, fac, r, r0, save, srur;
+ realtype *f1, *fsave, *cdata, *rewtdata;
+ WebData wdata;
+ N_Vector rewt;
+
+ wdata = (WebData) user_data;
+ rewt = wdata->rewt;
+ flag = CVodeGetErrWeights(wdata->cvode_mem, rewt);
+ if(check_flag(&flag, "CVodeGetErrWeights", 1)) return(1);
+
+ cdata = NV_DATA_S(c);
+ rewtdata = NV_DATA_S(rewt);
+
+ uround = UNIT_ROUNDOFF;
+
+ P = wdata->P;
+ pivot = wdata->pivot;
+ jxr = wdata->jxr;
+ jyr = wdata->jyr;
+ mp = wdata->mp;
+ srur = wdata->srur;
+ ngrp = wdata->ngrp;
+ ngx = wdata->ngx;
+ ngy = wdata->ngy;
+ mxmp = wdata->mxmp;
+ fsave = wdata->fsave;
+
+ /* Make mp calls to fblock to approximate each diagonal block of Jacobian.
+ Here, fsave contains the base value of the rate vector and
+ r0 is a minimum increment factor for the difference quotient. */
+
+ f1 = NV_DATA_S(vtemp1);
+
+ fac = N_VWrmsNorm (fc, rewt);
+ r0 = RCONST(1000.0)*ABS(gamma)*uround*NEQ*fac;
+ if (r0 == ZERO) r0 = ONE;
+
+ for (igy = 0; igy < ngy; igy++) {
+ jy = jyr[igy];
+ if00 = jy*mxmp;
+ for (igx = 0; igx < ngx; igx++) {
+ jx = jxr[igx];
+ if0 = if00 + jx*mp;
+ ig = igx + igy*ngx;
+ /* Generate ig-th diagonal block */
+ for (j = 0; j < mp; j++) {
+ /* Generate the jth column as a difference quotient */
+ jj = if0 + j;
+ save = cdata[jj];
+ r = MAX(srur*ABS(save),r0/rewtdata[jj]);
+ cdata[jj] += r;
+ fac = -gamma/r;
+ fblock (t, cdata, jx, jy, f1, wdata);
+ for (i = 0; i < mp; i++) {
+ P[ig][j][i] = (f1[i] - fsave[if0+i])*fac;
+ }
+ cdata[jj] = save;
+ }
+ }
+ }
+
+ /* Add identity matrix and do LU decompositions on blocks. */
+
+ for (ig = 0; ig < ngrp; ig++) {
+ denseAddIdentity(P[ig], mp);
+ ier = denseGETRF(P[ig], mp, mp, pivot[ig]);
+ if (ier != 0) return(1);
+ }
+
+ *jcurPtr = TRUE;
+ return(0);
+}
+
+/*
+ * This routine applies two inverse preconditioner matrices
+ * to the vector r, using the interaction-only block-diagonal Jacobian
+ * with block-grouping, denoted Jr, and Gauss-Seidel applied to the
+ * diffusion contribution to the Jacobian, denoted Jd.
+ * It first calls GSIter for a Gauss-Seidel approximation to
+ * ((I - gamma*Jd)-inverse)*r, and stores the result in z.
+ * 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 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)
+{
+ realtype ***P;
+ long int **pivot;
+ int jx, jy, igx, igy, iv, ig, *jigx, *jigy, mx, my, ngx, mp;
+ WebData wdata;
+
+ wdata = (WebData) user_data;
+
+ N_VScale(ONE, r, z);
+
+ /* call GSIter for Gauss-Seidel iterations */
+
+ GSIter(gamma, z, vtemp, wdata);
+
+ /* Do backsolves for inverse of block-diagonal preconditioner factor */
+
+ P = wdata->P;
+ pivot = wdata->pivot;
+ mx = wdata->mx;
+ my = wdata->my;
+ ngx = wdata->ngx;
+ mp = wdata->mp;
+ jigx = wdata->jigx;
+ jigy = wdata->jigy;
+
+ iv = 0;
+ for (jy = 0; jy < my; jy++) {
+ igy = jigy[jy];
+ for (jx = 0; jx < mx; jx++) {
+ igx = jigx[jx];
+ ig = igx + igy*ngx;
+ denseGETRS(P[ig], mp, pivot[ig], &(NV_DATA_S(z)[iv]));
+ iv += mp;
+ }
+ }
+
+ return(0);
+}
+
+/*
+ * This routine computes the right-hand side of the adjoint ODE system and
+ * returns it in cBdot. The interaction rates are computed by calls to WebRates,
+ * and these are saved in fsave for use in preconditioning. The adjoint
+ * interaction rates are computed by calls to WebRatesB.
+ */
+
+static int fB(realtype t, N_Vector c, N_Vector cB,
+ N_Vector cBdot, void *user_data)
+{
+ int i, ic, ici, idxl, idxu, idyl, idyu, iyoff, jx, jy, ns, mxns;
+ realtype dcxli, dcxui, dcyli, dcyui, x, y, *cox, *coy, *fsave, *fBsave, dx, dy;
+ realtype *cdata, *cBdata, *cBdotdata;
+ WebData wdata;
+
+ wdata = (WebData) user_data;
+ cdata = NV_DATA_S(c);
+ cBdata = NV_DATA_S(cB);
+ cBdotdata = NV_DATA_S(cBdot);
+
+ mxns = wdata->mxns;
+ ns = wdata->ns;
+ fsave = wdata->fsave;
+ fBsave = wdata->fBsave;
+ cox = wdata->cox;
+ coy = wdata->coy;
+ mxns = wdata->mxns;
+ dx = wdata->dx;
+ dy = wdata->dy;
+
+ for (jy = 0; jy < MY; jy++) {
+ y = jy*dy;
+ iyoff = mxns*jy;
+ idyu = (jy == MY-1) ? -mxns : mxns;
+ idyl = (jy == 0) ? -mxns : mxns;
+ for (jx = 0; jx < MX; jx++) {
+ x = jx*dx;
+ ic = iyoff + ns*jx;
+ /* Get interaction rates at one point (x,y). */
+ WebRatesB(x, y, t, cdata+ic, cBdata+ic, fsave+ic, fBsave+ic, wdata);
+ idxu = (jx == MX-1) ? -ns : ns;
+ idxl = (jx == 0) ? -ns : ns;
+ for (i = 1; i <= ns; i++) {
+ ici = ic + i-1;
+ /* Do differencing in y. */
+ dcyli = cBdata[ici] - cBdata[ici-idyl];
+ dcyui = cBdata[ici+idyu] - cBdata[ici];
+ /* Do differencing in x. */
+ dcxli = cBdata[ici] - cBdata[ici-idxl];
+ dcxui = cBdata[ici+idxu] - cBdata[ici];
+ /* Collect terms and load cdot elements. */
+ cBdotdata[ici] = - coy[i-1]*(dcyui - dcyli)
+ - cox[i-1]*(dcxui - dcxli)
+ - fBsave[ici];
+ }
+ }
+ }
+
+ return(0);
+}
+
+/*
+ * Preconditioner setup function for the backward problem
+ */
+
+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)
+{
+ realtype ***P;
+ long int **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;
+ realtype *f1, *fsave, *cdata, *rewtdata;
+ void *cvode_mem;
+ WebData wdata;
+ N_Vector rewt;
+
+ wdata = (WebData) user_data;
+ cvode_mem = CVodeGetAdjCVodeBmem(wdata->cvode_mem, wdata->indexB);
+ if(check_flag((void *)cvode_mem, "CVadjGetCVodeBmem", 0)) return(1);
+ rewt = wdata->rewt;
+ flag = CVodeGetErrWeights(cvode_mem, rewt);
+ if(check_flag(&flag, "CVodeGetErrWeights", 1)) return(1);
+
+ cdata = NV_DATA_S(c);
+ rewtdata = NV_DATA_S(rewt);
+
+ uround = UNIT_ROUNDOFF;
+
+ P = wdata->P;
+ pivot = wdata->pivot;
+ jxr = wdata->jxr;
+ jyr = wdata->jyr;
+ mp = wdata->mp;
+ srur = wdata->srur;
+ ngrp = wdata->ngrp;
+ ngx = wdata->ngx;
+ ngy = wdata->ngy;
+ mxmp = wdata->mxmp;
+ fsave = wdata->fsave;
+
+ /* Make mp calls to fblock to approximate each diagonal block of Jacobian.
+ Here, fsave contains the base value of the rate vector and
+ r0 is a minimum increment factor for the difference quotient. */
+
+ f1 = NV_DATA_S(vtemp1);
+
+ fac = N_VWrmsNorm (fcB, rewt);
+ r0 = RCONST(1000.0)*ABS(gamma)*uround*NEQ*fac;
+ if (r0 == ZERO) r0 = ONE;
+
+ for (igy = 0; igy < ngy; igy++) {
+ jy = jyr[igy];
+ if00 = jy*mxmp;
+ for (igx = 0; igx < ngx; igx++) {
+ jx = jxr[igx];
+ if0 = if00 + jx*mp;
+ ig = igx + igy*ngx;
+ /* Generate ig-th diagonal block */
+ for (j = 0; j < mp; j++) {
+ /* Generate the jth column as a difference quotient */
+ jj = if0 + j;
+ save = cdata[jj];
+ r = MAX(srur*ABS(save),r0/rewtdata[jj]);
+ cdata[jj] += r;
+ fac = gamma/r;
+ fblock (t, cdata, jx, jy, f1, wdata);
+ for (i = 0; i < mp; i++) {
+ P[ig][i][j] = (f1[i] - fsave[if0+i])*fac;
+ }
+ cdata[jj] = save;
+ }
+ }
+ }
+
+ /* Add identity matrix and do LU decompositions on blocks. */
+
+ for (ig = 0; ig < ngrp; ig++) {
+ denseAddIdentity(P[ig], mp);
+ ier = denseGETRF(P[ig], mp, mp, pivot[ig]);
+ if (ier != 0) return(1);
+ }
+
+ *jcurPtr = TRUE;
+ return(0);
+}
+
+/*
+ * Preconditioner solve function for the backward problem
+ */
+
+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)
+{
+ realtype ***P;
+ long int **pivot;
+ int jx, jy, igx, igy, iv, ig, *jigx, *jigy, mx, my, ngx;
+ long int mp;
+ WebData wdata;
+
+ wdata = (WebData) user_data;
+
+ N_VScale(ONE, r, z);
+
+ /* call GSIter for Gauss-Seidel iterations (same routine but with gamma=-gamma) */
+
+ GSIter(-gamma, z, vtemp, wdata);
+
+ /* Do backsolves for inverse of block-diagonal preconditioner factor */
+
+ P = wdata->P;
+ pivot = wdata->pivot;
+ mx = wdata->mx;
+ my = wdata->my;
+ ngx = wdata->ngx;
+ mp = wdata->mp;
+ jigx = wdata->jigx;
+ jigy = wdata->jigy;
+
+ iv = 0;
+ for (jy = 0; jy < my; jy++) {
+ igy = jigy[jy];
+ for (jx = 0; jx < mx; jx++) {
+ igx = jigx[jx];
+ ig = igx + igy*ngx;
+ denseGETRS(P[ig], mp, pivot[ig], &(NV_DATA_S(z)[iv]));
+ iv += mp;
+ }
+ }
+
+ return(0);
+}
+
+/*
+ *--------------------------------------------------------------------
+ * PRIVATE FUNCTIONS
+ *--------------------------------------------------------------------
+ */
+
+/*
+ * Allocate space for user data structure
+ */
+
+static WebData AllocUserData(void)
+{
+ int i, ngrp = NGRP;
+ long int 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->rewt = N_VNew_Serial(NEQ);
+ return(wdata);
+}
+
+/*
+ * Initialize user data structure
+ */
+
+static void InitUserData(WebData wdata)
+{
+ int i, j, ns;
+ realtype *bcoef, *diff, *cox, *coy, dx, dy;
+ realtype (*acoef)[NS];
+
+ acoef = wdata->acoef;
+ bcoef = wdata->bcoef;
+ diff = wdata->diff;
+ cox = wdata->cox;
+ coy = wdata->coy;
+ ns = wdata->ns = NS;
+
+ for (j = 0; j < NS; j++) { for (i = 0; i < NS; i++) acoef[i][j] = ZERO; }
+ for (j = 0; j < NP; j++) {
+ for (i = 0; i < NP; i++) {
+ acoef[NP+i][j] = EE;
+ acoef[i][NP+j] = -GG;
+ }
+ acoef[j][j] = -AA;
+ acoef[NP+j][NP+j] = -AA;
+ bcoef[j] = BB;
+ bcoef[NP+j] = -BB;
+ diff[j] = DPREY;
+ diff[NP+j] = DPRED;
+ }
+
+ /* Set remaining problem parameters */
+
+ wdata->mxns = MXNS;
+ dx = wdata->dx = DX;
+ dy = wdata->dy = DY;
+ for (i = 0; i < ns; i++) {
+ cox[i] = diff[i]/SQR(dx);
+ coy[i] = diff[i]/SQR(dy);
+ }
+
+ /* Set remaining method parameters */
+
+ wdata->mp = MP;
+ wdata->mq = MQ;
+ wdata->mx = MX;
+ wdata->my = MY;
+ wdata->srur = SQRT(UNIT_ROUNDOFF);
+ wdata->mxmp = MXMP;
+ wdata->ngrp = NGRP;
+ wdata->ngx = NGX;
+ wdata->ngy = NGY;
+ SetGroups(MX, NGX, wdata->jgx, wdata->jigx, wdata->jxr);
+ SetGroups(MY, NGY, wdata->jgy, wdata->jigy, wdata->jyr);
+}
+
+/*
+ * This routine sets arrays jg, jig, and jr describing
+ * a uniform partition of (0,1,2,...,m-1) into ng groups.
+ * The arrays set are:
+ * jg = length ng+1 array of group boundaries.
+ * Group ig has indices j = jg[ig],...,jg[ig+1]-1.
+ * jig = length m array of group indices vs node index.
+ * Node index j is in group jig[j].
+ * jr = length ng array of indices representing the groups.
+ * The index for group ig is j = jr[ig].
+ */
+
+static void SetGroups(int m, int ng, int jg[], int jig[], int jr[])
+{
+ int ig, j, len1, mper, ngm1;
+
+ mper = m/ng; /* does integer division */
+ for (ig=0; ig < ng; ig++) jg[ig] = ig*mper;
+ jg[ng] = m;
+
+ ngm1 = ng - 1;
+ len1 = ngm1*mper;
+ for (j = 0; j < len1; j++) jig[j] = j/mper;
+ for (j = len1; j < m; j++) jig[j] = ngm1;
+
+ for (ig = 0; ig < ngm1; ig++) jr[ig] = ((2*ig+1)*mper-1)/2;
+ jr[ngm1] = (ngm1*mper+m-1)/2;
+}
+
+/*
+ * This routine computes and loads the vector of initial values.
+ */
+
+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 = NV_DATA_S(c);
+ ns = wdata->ns;
+ mxns = wdata->mxns;
+ dx = wdata->dx;
+ dy = wdata->dy;
+
+ x_factor = RCONST(4.0)/SQR(AX);
+ y_factor = RCONST(4.0)/SQR(AY);
+ for (jy = 0; jy < MY; jy++) {
+ y = jy*dy;
+ argy = SQR(y_factor*y*(AY-y));
+ iyoff = mxns*jy;
+ for (jx = 0; jx < MX; jx++) {
+ x = jx*dx;
+ argx = SQR(x_factor*x*(AX-x));
+ ioff = iyoff + ns*jx;
+ for (i = 1; i <= ns; i++) {
+ ici = ioff + i-1;
+ cdata[ici] = RCONST(10.0) + i*argx*argy;
+ }
+ }
+ }
+}
+
+/*
+ * This function computes and loads the final values for the adjoint variables
+ */
+
+static void CbInit(N_Vector c, int is, WebData wdata)
+{
+ int i, ici, ioff, iyoff, jx, jy, ns, mxns;
+ realtype *cdata;
+
+ realtype gu[NS];
+
+ cdata = NV_DATA_S(c);
+ ns = wdata->ns;
+ mxns = wdata->mxns;
+
+ for ( i = 1; i <= ns; i++ ) gu[i-1] = ZERO;
+ gu[ISPEC-1] = ONE;
+
+ for (jy = 0; jy < MY; jy++) {
+ iyoff = mxns*jy;
+ for (jx = 0; jx < MX; jx++) {
+ ioff = iyoff + ns*jx;
+ for (i = 1; i <= ns; i++) {
+ ici = ioff + i-1;
+ cdata[ici] = gu[i-1];
+ }
+ }
+ }
+}
+
+/*
+ * This routine computes the interaction rates for the species
+ * c_1, ... ,c_ns (stored in c[0],...,c[ns-1]), at one spatial point
+ * and at time t.
+ */
+
+static void WebRates(realtype x, realtype y, realtype t, realtype c[],
+ realtype rate[], WebData wdata)
+{
+ int i, j, ns;
+ realtype fac, *bcoef;
+ realtype (*acoef)[NS];
+
+ ns = wdata->ns;
+ acoef = wdata->acoef;
+ bcoef = wdata->bcoef;
+
+ for (i = 0; i < ns; i++)
+ rate[i] = ZERO;
+
+ for (j = 0; j < ns; j++)
+ for (i = 0; i < ns; i++)
+ rate[i] += c[j] * acoef[i][j];
+
+ fac = ONE + ALPH*x*y;
+ for (i = 0; i < ns; i++)
+ rate[i] = c[i]*(bcoef[i]*fac + rate[i]);
+}
+
+/*
+ * This routine computes the interaction rates for the backward problem
+ */
+
+static void WebRatesB(realtype x, realtype y, realtype t, realtype c[], realtype cB[],
+ realtype rate[], realtype rateB[], WebData wdata)
+{
+ int i, j, ns;
+ realtype fac, *bcoef;
+ realtype (*acoef)[NS];
+
+ ns = wdata->ns;
+ acoef = wdata->acoef;
+ bcoef = wdata->bcoef;
+
+ fac = ONE + ALPH*x*y;
+
+ for (i = 0; i < ns; i++)
+ rate[i] = bcoef[i]*fac;
+
+ for (j = 0; j < ns; j++)
+ for (i = 0; i < ns; i++)
+ rate[i] += acoef[i][j]*c[j];
+
+ for (i = 0; i < ns; i++) {
+ rateB[i] = cB[i]*rate[i];
+ rate[i] = c[i]*rate[i];
+ }
+
+ for (j = 0; j < ns; j++)
+ for (i = 0; i < ns; i++)
+ rateB[i] += acoef[j][i]*c[j]*cB[j];
+
+}
+
+/*
+ * This routine computes one block of the interaction terms of the
+ * system, namely block (jx,jy), for use in preconditioning.
+ * Here jx and jy count from 0.
+ */
+
+static void fblock(realtype t, realtype cdata[], int jx, int jy,
+ realtype cdotdata[], WebData wdata)
+{
+ int iblok, ic;
+ realtype x, y;
+
+ iblok = jx + jy*(wdata->mx);
+ y = jy*(wdata->dy);
+ x = jx*(wdata->dx);
+ ic = (wdata->ns)*(iblok);
+ WebRates(x, y, t, cdata+ic, cdotdata, wdata);
+}
+
+/*
+ * This routine performs ITMAX=5 Gauss-Seidel iterations to compute an
+ * approximation to (P-inverse)*z, where P = I - gamma*Jd, and
+ * Jd represents the diffusion contributions to the Jacobian.
+ * The answer is stored in z on return, and x is a temporary vector.
+ * The dimensions below assume a global constant NS >= ns.
+ * Some inner loops of length ns are implemented with the small
+ * vector kernels v_sum_prods, v_prod, v_inc_by_prod.
+ */
+
+static void GSIter(realtype gamma, N_Vector z, N_Vector x, WebData wdata)
+{
+ int i, ic, iter, iyoff, jx, jy, ns, mxns, mx, my, x_loc, y_loc;
+ realtype beta[NS], beta2[NS], cof1[NS], gam[NS], gam2[NS];
+ realtype temp, *cox, *coy, *xd, *zd;
+
+ xd = NV_DATA_S(x);
+ zd = NV_DATA_S(z);
+ ns = wdata->ns;
+ mx = wdata->mx;
+ my = wdata->my;
+ mxns = wdata->mxns;
+ cox = wdata->cox;
+ coy = wdata->coy;
+
+ /* Write matrix as P = D - L - U.
+ Load local arrays beta, beta2, gam, gam2, and cof1. */
+
+ for (i = 0; i < ns; i++) {
+ temp = ONE/(ONE + TWO*gamma*(cox[i] + coy[i]));
+ beta[i] = gamma*cox[i]*temp;
+ beta2[i] = TWO*beta[i];
+ gam[i] = gamma*coy[i]*temp;
+ gam2[i] = TWO*gam[i];
+ cof1[i] = temp;
+ }
+
+ /* Begin iteration loop.
+ Load vector x with (D-inverse)*z for first iteration. */
+
+ for (jy = 0; jy < my; jy++) {
+ iyoff = mxns*jy;
+ for (jx = 0; jx < mx; jx++) {
+ ic = iyoff + ns*jx;
+ v_prod(xd+ic, cof1, zd+ic, ns); /* x[ic+i] = cof1[i]z[ic+i] */
+ }
+ }
+ N_VConst(ZERO, z);
+
+ /* Looping point for iterations. */
+
+ for (iter=1; iter <= ITMAX; iter++) {
+
+ /* Calculate (D-inverse)*U*x if not the first iteration. */
+
+ if (iter > 1) {
+ for (jy=0; jy < my; jy++) {
+ iyoff = mxns*jy;
+ for (jx=0; jx < mx; jx++) { /* order of loops matters */
+ ic = iyoff + ns*jx;
+ x_loc = (jx == 0) ? 0 : ((jx == mx-1) ? 2 : 1);
+ y_loc = (jy == 0) ? 0 : ((jy == my-1) ? 2 : 1);
+ switch (3*y_loc+x_loc) {
+ case 0 : /* jx == 0, jy == 0 */
+ /* x[ic+i] = beta2[i]x[ic+ns+i] + gam2[i]x[ic+mxns+i] */
+ v_sum_prods(xd+ic, beta2, xd+ic+ns, gam2, xd+ic+mxns, ns);
+ break;
+ case 1 : /* 1 <= jx <= mx-2, jy == 0 */
+ /* x[ic+i] = beta[i]x[ic+ns+i] + gam2[i]x[ic+mxns+i] */
+ v_sum_prods(xd+ic, beta, xd+ic+ns, gam2, xd+ic+mxns, ns);
+ break;
+ case 2 : /* jx == mx-1, jy == 0 */
+ /* x[ic+i] = gam2[i]x[ic+mxns+i] */
+ v_prod(xd+ic, gam2, xd+ic+mxns, ns);
+ break;
+ case 3 : /* jx == 0, 1 <= jy <= my-2 */
+ /* x[ic+i] = beta2[i]x[ic+ns+i] + gam[i]x[ic+mxns+i] */
+ v_sum_prods(xd+ic, beta2, xd+ic+ns, gam, xd+ic+mxns, ns);
+ break;
+ case 4 : /* 1 <= jx <= mx-2, 1 <= jy <= my-2 */
+ /* x[ic+i] = beta[i]x[ic+ns+i] + gam[i]x[ic+mxns+i] */
+ v_sum_prods(xd+ic, beta, xd+ic+ns, gam, xd+ic+mxns, ns);
+ break;
+ case 5 : /* jx == mx-1, 1 <= jy <= my-2 */
+ /* x[ic+i] = gam[i]x[ic+mxns+i] */
+ v_prod(xd+ic, gam, xd+ic+mxns, ns);
+ break;
+ case 6 : /* jx == 0, jy == my-1 */
+ /* x[ic+i] = beta2[i]x[ic+ns+i] */
+ v_prod(xd+ic, beta2, xd+ic+ns, ns);
+ break;
+ case 7 : /* 1 <= jx <= mx-2, jy == my-1 */
+ /* x[ic+i] = beta[i]x[ic+ns+i] */
+ v_prod(xd+ic, beta, xd+ic+ns, ns);
+ break;
+ case 8 : /* jx == mx-1, jy == my-1 */
+ /* x[ic+i] = ZERO */
+ v_zero(xd+ic, ns);
+ break;
+ }
+ }
+ }
+ } /* end if (iter > 1) */
+
+ /* Overwrite x with [(I - (D-inverse)*L)-inverse]*x. */
+
+ for (jy=0; jy < my; jy++) {
+ iyoff = mxns*jy;
+ for (jx=0; jx < mx; jx++) { /* order of loops matters */
+ ic = iyoff + ns*jx;
+ x_loc = (jx == 0) ? 0 : ((jx == mx-1) ? 2 : 1);
+ y_loc = (jy == 0) ? 0 : ((jy == my-1) ? 2 : 1);
+ switch (3*y_loc+x_loc) {
+ case 0 : /* jx == 0, jy == 0 */
+ break;
+ case 1 : /* 1 <= jx <= mx-2, jy == 0 */
+ /* x[ic+i] += beta[i]x[ic-ns+i] */
+ v_inc_by_prod(xd+ic, beta, xd+ic-ns, ns);
+ break;
+ case 2 : /* jx == mx-1, jy == 0 */
+ /* x[ic+i] += beta2[i]x[ic-ns+i] */
+ v_inc_by_prod(xd+ic, beta2, xd+ic-ns, ns);
+ break;
+ case 3 : /* jx == 0, 1 <= jy <= my-2 */
+ /* x[ic+i] += gam[i]x[ic-mxns+i] */
+ v_inc_by_prod(xd+ic, gam, xd+ic-mxns, ns);
+ break;
+ case 4 : /* 1 <= jx <= mx-2, 1 <= jy <= my-2 */
+ /* x[ic+i] += beta[i]x[ic-ns+i] + gam[i]x[ic-mxns+i] */
+ v_inc_by_prod(xd+ic, beta, xd+ic-ns, ns);
+ v_inc_by_prod(xd+ic, gam, xd+ic-mxns, ns);
+ break;
+ case 5 : /* jx == mx-1, 1 <= jy <= my-2 */
+ /* x[ic+i] += beta2[i]x[ic-ns+i] + gam[i]x[ic-mxns+i] */
+ v_inc_by_prod(xd+ic, beta2, xd+ic-ns, ns);
+ v_inc_by_prod(xd+ic, gam, xd+ic-mxns, ns);
+ break;
+ case 6 : /* jx == 0, jy == my-1 */
+ /* x[ic+i] += gam2[i]x[ic-mxns+i] */
+ v_inc_by_prod(xd+ic, gam2, xd+ic-mxns, ns);
+ break;
+ case 7 : /* 1 <= jx <= mx-2, jy == my-1 */
+ /* x[ic+i] += beta[i]x[ic-ns+i] + gam2[i]x[ic-mxns+i] */
+ v_inc_by_prod(xd+ic, beta, xd+ic-ns, ns);
+ v_inc_by_prod(xd+ic, gam2, xd+ic-mxns, ns);
+ break;
+ case 8 : /* jx == mx-1, jy == my-1 */
+ /* x[ic+i] += beta2[i]x[ic-ns+i] + gam2[i]x[ic-mxns+i] */
+ v_inc_by_prod(xd+ic, beta2, xd+ic-ns, ns);
+ v_inc_by_prod(xd+ic, gam2, xd+ic-mxns, ns);
+ break;
+ }
+ }
+ }
+
+ /* Add increment x to z : z <- z+x */
+
+ N_VLinearSum(ONE, z, ONE, x, z);
+
+ }
+}
+
+static void v_inc_by_prod(realtype u[], realtype v[], realtype w[], int n)
+{
+ int i;
+ for (i=0; i < n; i++) u[i] += v[i]*w[i];
+}
+
+static void v_sum_prods(realtype u[], realtype p[], realtype q[],
+ realtype v[], realtype w[], int n)
+{
+ int i;
+ for (i=0; i < n; i++) u[i] = p[i]*q[i] + v[i]*w[i];
+}
+
+static void v_prod(realtype u[], realtype v[], realtype w[], int n)
+{
+ int i;
+ for (i=0; i < n; i++) u[i] = v[i]*w[i];
+}
+
+static void v_zero(realtype u[], int n)
+{
+ int i;
+ for (i=0; i < n; i++) u[i] = ZERO;
+}
+
+/*
+ * Print maximum sensitivity of G for each species
+ */
+
+static void PrintOutput(N_Vector cB, int ns, int mxns, WebData wdata)
+{
+ int i, jx, jy;
+ realtype *cdata, cij, cmax, x, y;
+
+ x = y = ZERO;
+
+ cdata = NV_DATA_S(cB);
+
+ for (i=1; i <= ns; i++) {
+
+ cmax = ZERO;
+
+ for (jy=MY-1; jy >= 0; jy--) {
+ for (jx=0; jx < MX; jx++) {
+ cij = cdata[(i-1) + jx*ns + jy*mxns];
+ if (ABS(cij) > cmax) {
+ cmax = cij;
+ x = jx * wdata->dx;
+ y = jy * wdata->dy;
+ }
+ }
+ }
+
+ printf("\nMaximum sensitivity with respect to I.C. of species %d\n", i);
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf(" mu max = %Le\n",cmax);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf(" mu max = %le\n",cmax);
+#else
+ printf(" mu max = %e\n",cmax);
+#endif
+ printf("at\n");
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf(" x = %Le\n y = %Le\n", x, y);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf(" x = %le\n y = %le\n", x, y);
+#else
+ printf(" x = %e\n y = %e\n", x, y);
+#endif
+
+ }
+
+}
+
+/*
+ * Compute double space integral
+ */
+
+static realtype doubleIntgr(N_Vector c, int i, WebData wdata)
+{
+ realtype *cdata;
+ int ns, mx, my, mxns;
+ realtype dx, dy;
+ realtype intgr_xy, intgr_x;
+ int jx, jy;
+
+ cdata = NV_DATA_S(c);
+
+ ns = wdata->ns;
+ mx = wdata->mx;
+ my = wdata->my;
+ mxns = wdata->mxns;
+ dx = wdata->dx;
+ dy = wdata->dy;
+
+ jy = 0;
+ intgr_x = cdata[(i-1)+jy*mxns];
+ for (jx = 1; jx < mx-1; jx++) {
+ intgr_x += TWO*cdata[(i-1) + jx*ns + jy*mxns];
+ }
+ intgr_x += cdata[(i-1)+(mx-1)*ns+jy*mxns];
+ intgr_x *= RCONST(0.5)*dx;
+
+ intgr_xy = intgr_x;
+
+ for (jy = 1; jy < my-1; jy++) {
+
+ intgr_x = cdata[(i-1)+jy*mxns];
+ for (jx = 1; jx < mx-1; jx++) {
+ intgr_x += TWO*cdata[(i-1) + jx*ns + jy*mxns];
+ }
+ intgr_x += cdata[(i-1)+(mx-1)*ns+jy*mxns];
+ intgr_x *= RCONST(0.5)*dx;
+
+ intgr_xy += TWO*intgr_x;
+
+ }
+
+ jy = my-1;
+ intgr_x = cdata[(i-1)+jy*mxns];
+ for (jx = 1; jx < mx-1; jx++) {
+ intgr_x += TWO*cdata[(i-1) + jx*ns + jy*mxns];
+ }
+ intgr_x += cdata[(i-1)+(mx-1)*ns+jy*mxns];
+ intgr_x *= RCONST(0.5)*dx;
+
+ intgr_xy += intgr_x;
+
+ intgr_xy *= RCONST(0.5)*dy;
+
+ return(intgr_xy);
+}
+
+/*
+ * Free space allocated for the user data structure
+ */
+
+static void FreeUserData(WebData wdata)
+{
+ int i, ngrp;
+
+ ngrp = wdata->ngrp;
+ for(i=0; i < ngrp; i++) {
+ destroyMat((wdata->P)[i]);
+ destroyArray((wdata->pivot)[i]);
+ }
+ N_VDestroy_Serial(wdata->rewt);
+ free(wdata);
+}
+
+/*
+ * 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, 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/cvsFoodWeb_ASAp_kry.out b/examples/cvodes/serial/cvsFoodWeb_ASAp_kry.out
new file mode 100644
index 0000000..f822e64
--- /dev/null
+++ b/examples/cvodes/serial/cvsFoodWeb_ASAp_kry.out
@@ -0,0 +1,51 @@
+
+Create and allocate CVODES memory for forward run
+
+Allocate global memory
+
+Forward integration
+
+ncheck = 11
+
+ g = int_x int_y c6(Tfinal,x,y) dx dy = 35988.914996
+
+
+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
+at
+ x = 1.000000e+00
+ y = 1.000000e+00
+
+Maximum sensitivity with respect to I.C. of species 2
+ mu max = 4.865450e-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
+at
+ x = 1.000000e+00
+ y = 1.000000e+00
+
+Maximum sensitivity with respect to I.C. of species 4
+ mu max = 3.447561e-12
+at
+ x = 1.000000e+00
+ y = 8.421053e-01
+
+Maximum sensitivity with respect to I.C. of species 5
+ mu max = 3.434214e-12
+at
+ x = 1.000000e+00
+ y = 8.421053e-01
+
+Maximum sensitivity with respect to I.C. of species 6
+ mu max = 6.326559e-12
+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
new file mode 100644
index 0000000..7145a4c
--- /dev/null
+++ b/examples/cvodes/serial/cvsHessian_ASA_FSA.c
@@ -0,0 +1,779 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.2 $
+ * $Date: 2010/12/01 22:57:59 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ *
+ * Hessian through adjoint sensitivity example problem.
+ *
+ * [ - p1 * y1^2 - y3 ] [ 1 ]
+ * y' = [ - y2 ] y(0) = [ 1 ]
+ * [ -p2^2 * y2 * y3 ] [ 1 ]
+ *
+ * p1 = 1.0
+ * p2 = 2.0
+ *
+ * 2
+ * /
+ * G(p) = | 0.5 * ( y1^2 + y2^2 + y3^2 ) dt
+ * /
+ * 0
+ *
+ * Compute the gradient (ASA) and Hessian (FSA over ASA) of G(p).
+ *
+ * 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>
+
+#define Ith(v,i) NV_Ith_S(v,i-1)
+
+#define ZERO RCONST(0.0)
+#define ONE RCONST(1.0)
+
+typedef struct {
+ realtype p1, p2;
+} *UserData;
+
+static int f(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);
+static int fS(int Ns, realtype t,
+ N_Vector y, N_Vector ydot,
+ N_Vector *yS, N_Vector *ySdot,
+ void *user_data,
+ N_Vector tmp1, N_Vector tmp2);
+static int fQS(int Ns, realtype t,
+ N_Vector y, N_Vector *yS,
+ N_Vector yQdot, N_Vector *yQSdot,
+ void *user_data,
+ N_Vector tmp, N_Vector tmpQ);
+
+static int fB1(realtype t, N_Vector y, N_Vector *yS,
+ N_Vector yB, N_Vector yBdot, void *user_dataB);
+static int fQB1(realtype t, N_Vector y, N_Vector *yS,
+ N_Vector yB, N_Vector qBdot, void *user_dataB);
+
+
+static int fB2(realtype t, N_Vector y, N_Vector *yS,
+ N_Vector yB, N_Vector yBdot, void *user_dataB);
+static int fQB2(realtype t, N_Vector y, N_Vector *yS,
+ N_Vector yB, N_Vector qBdot, void *user_dataB);
+
+void PrintFwdStats(void *cvode_mem);
+void PrintBckStats(void *cvode_mem, int idx);
+
+/*
+ *--------------------------------------------------------------------
+ * MAIN PROGRAM
+ *--------------------------------------------------------------------
+ */
+
+int main(int argc, char *argv[])
+{
+ UserData data;
+
+ void *cvode_mem;
+
+ long int Neq, Np2;
+ int Np;
+
+ realtype t0, tf;
+
+ realtype reltol;
+ realtype abstol, abstolQ, abstolB, abstolQB;
+
+ N_Vector y, yQ;
+ N_Vector *yS, *yQS;
+ N_Vector yB1, yB2;
+ N_Vector yQB1, yQB2;
+
+ int steps, ncheck;
+ int indexB1, indexB2;
+
+ int flag;
+ realtype time;
+
+ realtype dp;
+ realtype G, Gp, Gm;
+ realtype grdG_fwd[2], grdG_bck[2], grdG_cntr[2];
+ realtype H11, H22;
+
+ /* User data structure */
+
+ data = (UserData) malloc(sizeof *data);
+ data->p1 = RCONST(1.0);
+ data->p2 = RCONST(2.0);
+
+ /* Problem size, integration interval, and tolerances */
+
+ Neq = 3;
+ Np = 2;
+ Np2 = 2*Np;
+
+ t0 = 0.0;
+ tf = 2.0;
+
+ reltol = 1.0e-8;
+
+ abstol = 1.0e-8;
+ abstolQ = 1.0e-8;
+
+ abstolB = 1.0e-8;
+ abstolQB = 1.0e-8;
+
+ /* Initializations for forward problem */
+
+ y = N_VNew_Serial(Neq);
+ N_VConst(ONE, y);
+
+ yQ = N_VNew_Serial(1);
+ N_VConst(ZERO, yQ);
+
+ yS = N_VCloneVectorArray_Serial(Np, y);
+ N_VConst(ZERO, yS[0]);
+ N_VConst(ZERO, yS[1]);
+
+ yQS = N_VCloneVectorArray_Serial(Np, yQ);
+ N_VConst(ZERO, yQS[0]);
+ N_VConst(ZERO, yQS[1]);
+
+ /* Create and initialize forward problem */
+
+ cvode_mem = CVodeCreate(CV_BDF, CV_NEWTON);
+
+ flag = CVodeInit(cvode_mem, f, t0, y);
+ flag = CVodeSStolerances(cvode_mem, reltol, abstol);
+ flag = CVodeSetUserData(cvode_mem, data);
+
+ flag = CVDense(cvode_mem, Neq);
+
+ flag = CVodeQuadInit(cvode_mem, fQ, yQ);
+ flag = CVodeQuadSStolerances(cvode_mem, reltol, abstolQ);
+ flag = CVodeSetQuadErrCon(cvode_mem, TRUE);
+
+ flag = CVodeSensInit(cvode_mem, Np, CV_SIMULTANEOUS, fS, yS);
+ flag = CVodeSensEEtolerances(cvode_mem);
+ flag = CVodeSetSensErrCon(cvode_mem, TRUE);
+
+ flag = CVodeQuadSensInit(cvode_mem, fQS, yQS);
+
+ flag = CVodeQuadSensEEtolerances(cvode_mem);
+ flag = CVodeSetQuadSensErrCon(cvode_mem, TRUE);
+
+ /* Initialize ASA */
+
+ steps = 100;
+ flag = CVodeAdjInit(cvode_mem, steps, CV_POLYNOMIAL);
+
+ /* Forward integration */
+
+ printf("-------------------\n");
+ printf("Forward integration\n");
+ printf("-------------------\n\n");
+
+ flag = CVodeF(cvode_mem, tf, y, &time, CV_NORMAL, &ncheck);
+
+ flag = CVodeGetQuad(cvode_mem, &time, yQ);
+ G = Ith(yQ,1);
+
+ flag = CVodeGetSens(cvode_mem, &time, yS);
+
+ flag = CVodeGetQuadSens(cvode_mem, &time, yQS);
+
+ printf("ncheck = %d\n", ncheck);
+ printf("\n");
+ 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));
+ printf("\n");
+
+ printf("Final Statistics for forward pb.\n");
+ printf("--------------------------------\n");
+ PrintFwdStats(cvode_mem);
+
+
+ /* Initializations for backward problems */
+
+ yB1 = N_VNew_Serial(2*Neq);
+ N_VConst(ZERO, yB1);
+
+ yQB1 = N_VNew_Serial(Np2);
+ N_VConst(ZERO, yQB1);
+
+ yB2 = N_VNew_Serial(2*Neq);
+ N_VConst(ZERO, yB1);
+
+ yQB2 = N_VNew_Serial(Np2);
+ N_VConst(ZERO, yQB2);
+
+ /* Create and initialize backward problems (one for each column of the Hessian) */
+
+ flag = CVodeCreateB(cvode_mem, CV_BDF, CV_NEWTON, &indexB1);
+ flag = CVodeInitBS(cvode_mem, indexB1, fB1, tf, yB1);
+ flag = CVodeSStolerancesB(cvode_mem, indexB1, reltol, abstolB);
+ flag = CVodeSetUserDataB(cvode_mem, indexB1, data);
+ flag = CVodeQuadInitBS(cvode_mem, indexB1, fQB1, yQB1);
+ flag = CVodeQuadSStolerancesB(cvode_mem, indexB1, reltol, abstolQB);
+ flag = CVodeSetQuadErrConB(cvode_mem, indexB1, TRUE);
+ flag = CVDenseB(cvode_mem, indexB1, 2*Neq);
+
+ flag = CVodeCreateB(cvode_mem, CV_BDF, CV_NEWTON, &indexB2);
+ flag = CVodeInitBS(cvode_mem, indexB2, fB2, tf, yB2);
+ flag = CVodeSStolerancesB(cvode_mem, indexB2, reltol, abstolB);
+ flag = CVodeSetUserDataB(cvode_mem, indexB2, data);
+ flag = CVodeQuadInitBS(cvode_mem, indexB2, fQB2, yQB2);
+ flag = CVodeQuadSStolerancesB(cvode_mem, indexB2, reltol, abstolQB);
+ flag = CVodeSetQuadErrConB(cvode_mem, indexB2, TRUE);
+ flag = CVDenseB(cvode_mem, indexB2, 2*Neq);
+
+ /* Backward integration */
+
+ printf("---------------------------------------------\n");
+ printf("Backward integration ... (2 adjoint problems)\n");
+ printf("---------------------------------------------\n\n");
+
+ flag = CVodeB(cvode_mem, t0, CV_NORMAL);
+
+ flag = CVodeGetB(cvode_mem, indexB1, &time, yB1);
+ flag = CVodeGetQuadB(cvode_mem, indexB1, &time, yQB1);
+
+ flag = CVodeGetB(cvode_mem, indexB2, &time, yB2);
+ flag = CVodeGetQuadB(cvode_mem, indexB2, &time, yQB2);
+
+ 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));
+ printf("\n");
+ printf(" H = d2G/dp2:\n");
+ printf(" (1) (2)\n");
+ printf(" %12.4le %12.4le\n", -Ith(yQB1,3) , -Ith(yQB2,3));
+ printf(" %12.4le %12.4le\n", -Ith(yQB1,4) , -Ith(yQB2,4));
+ printf("\n");
+
+ printf("Final Statistics for backward pb. 1\n");
+ printf("-----------------------------------\n");
+ PrintBckStats(cvode_mem, indexB1);
+
+ printf("Final Statistics for backward pb. 2\n");
+ printf("-----------------------------------\n");
+ PrintBckStats(cvode_mem, indexB2);
+
+ /* Free CVODES memory */
+
+ CVodeFree(&cvode_mem);
+
+ /* Finite difference tests */
+
+ dp = RCONST(1.0e-2);
+
+ printf("-----------------------\n");
+ printf("Finite Difference tests\n");
+ printf("-----------------------\n\n");
+
+ printf("del_p = %g\n\n",dp);
+
+ cvode_mem = CVodeCreate(CV_BDF, CV_NEWTON);
+
+ N_VConst(ONE, y);
+ N_VConst(ZERO, yQ);
+ flag = CVodeInit(cvode_mem, f, t0, y);
+ flag = CVodeSStolerances(cvode_mem, reltol, abstol);
+ flag = CVodeSetUserData(cvode_mem, data);
+ flag = CVDense(cvode_mem, Neq);
+ flag = CVodeQuadInit(cvode_mem, fQ, yQ);
+ flag = CVodeQuadSStolerances(cvode_mem, reltol, abstolQ);
+ flag = CVodeSetQuadErrCon(cvode_mem, TRUE);
+
+ data->p1 += dp;
+
+ flag = CVode(cvode_mem, tf, y, &time, CV_NORMAL);
+ flag = CVodeGetQuad(cvode_mem, &time, yQ);
+ Gp = Ith(yQ,1);
+ 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));
+
+ 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);
+ flag = CVodeGetQuad(cvode_mem, &time, yQ);
+ Gm = Ith(yQ,1);
+ 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));
+
+ data->p1 += dp;
+
+ grdG_fwd[0] = (Gp-G)/dp;
+ grdG_bck[0] = (G-Gm)/dp;
+ grdG_cntr[0] = (Gp-Gm)/(2.0*dp);
+ H11 = (Gp - 2.0*G + Gm) / (dp*dp);
+
+ data->p2 += 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);
+ flag = CVodeGetQuad(cvode_mem, &time, yQ);
+ Gp = Ith(yQ,1);
+ 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));
+
+ 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);
+ flag = CVodeGetQuad(cvode_mem, &time, yQ);
+ Gm = Ith(yQ,1);
+ 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));
+
+ data->p2 += dp;
+
+ grdG_fwd[1] = (Gp-G)/dp;
+ grdG_bck[1] = (G-Gm)/dp;
+ grdG_cntr[1] = (Gp-Gm)/(2.0*dp);
+ H22 = (Gp - 2.0*G + Gm) / (dp*dp);
+
+ printf("\n");
+
+ 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);
+
+
+ /* Free memory */
+
+ CVodeFree(&cvode_mem);
+
+ N_VDestroy_Serial(y);
+ N_VDestroy_Serial(yQ);
+
+ N_VDestroyVectorArray_Serial(yS, Np);
+ N_VDestroyVectorArray_Serial(yQS, 1);
+
+ N_VDestroy_Serial(yB1);
+ N_VDestroy_Serial(yQB1);
+ N_VDestroy_Serial(yB2);
+ N_VDestroy_Serial(yQB2);
+
+ free(data);
+
+ return(0);
+
+}
+
+/*
+ *--------------------------------------------------------------------
+ * FUNCTIONS CALLED BY CVODES
+ *--------------------------------------------------------------------
+ */
+
+
+static int f(realtype t, N_Vector y, N_Vector ydot, void *user_data)
+{
+ realtype y1, y2, y3;
+ UserData data;
+ realtype p1, p2;
+
+ data = (UserData) user_data;
+ p1 = data->p1;
+ p2 = data->p2;
+
+ y1 = Ith(y,1);
+ y2 = Ith(y,2);
+ y3 = Ith(y,3);
+
+ Ith(ydot,1) = -p1*y1*y1 - y3;
+ Ith(ydot,2) = -y2;
+ Ith(ydot,3) = -p2*p2*y2*y3;
+
+ return(0);
+}
+
+static int fQ(realtype t, N_Vector y, N_Vector qdot, void *user_data)
+{
+ realtype y1, y2, y3;
+
+ y1 = Ith(y,1);
+ y2 = Ith(y,2);
+ y3 = Ith(y,3);
+
+ Ith(qdot,1) = 0.5 * ( y1*y1 + y2*y2 + y3*y3 );
+
+ return(0);
+}
+
+static int fS(int Ns, realtype t,
+ N_Vector y, N_Vector ydot,
+ N_Vector *yS, N_Vector *ySdot,
+ void *user_data,
+ N_Vector tmp1, N_Vector tmp2)
+{
+ UserData data;
+ realtype y1, y2, y3;
+ realtype s1, s2, s3;
+ realtype fys1, fys2, fys3;
+ realtype p1, p2;
+
+ data = (UserData) user_data;
+ p1 = data->p1;
+ p2 = data->p2;
+
+ y1 = Ith(y,1);
+ y2 = Ith(y,2);
+ y3 = Ith(y,3);
+
+ /* 1st sensitivity RHS */
+
+ s1 = Ith(yS[0],1);
+ s2 = Ith(yS[0],2);
+ s3 = Ith(yS[0],3);
+
+ fys1 = - 2.0*p1*y1 * s1 - s3;
+ fys2 = - s2;
+ fys3 = - p2*p2*y3 * s2 - p2*p2*y2 * s3;
+
+ Ith(ySdot[0],1) = fys1 - y1*y1;
+ Ith(ySdot[0],2) = fys2;
+ Ith(ySdot[0],3) = fys3;
+
+ /* 2nd sensitivity RHS */
+
+ s1 = Ith(yS[1],1);
+ s2 = Ith(yS[1],2);
+ s3 = Ith(yS[1],3);
+
+ fys1 = - 2.0*p1*y1 * s1 - s3;
+ fys2 = - s2;
+ fys3 = - p2*p2*y3 * s2 - p2*p2*y2 * s3;
+
+ Ith(ySdot[1],1) = fys1;
+ Ith(ySdot[1],2) = fys2;
+ Ith(ySdot[1],3) = fys3 - 2.0*p2*y2*y3;
+
+ return(0);
+}
+
+static int fQS(int Ns, realtype t,
+ N_Vector y, N_Vector *yS,
+ N_Vector yQdot, N_Vector *yQSdot,
+ void *user_data,
+ N_Vector tmp, N_Vector tmpQ)
+{
+ realtype y1, y2, y3;
+ realtype s1, s2, s3;
+
+ y1 = Ith(y,1);
+ y2 = Ith(y,2);
+ y3 = Ith(y,3);
+
+
+ /* 1st sensitivity RHS */
+
+ s1 = Ith(yS[0],1);
+ s2 = Ith(yS[0],2);
+ s3 = Ith(yS[0],3);
+
+ Ith(yQSdot[0],1) = y1*s1 + y2*s2 + y3*s3;
+
+
+ /* 1st sensitivity RHS */
+
+ s1 = Ith(yS[1],1);
+ s2 = Ith(yS[1],2);
+ s3 = Ith(yS[1],3);
+
+ Ith(yQSdot[1],1) = y1*s1 + y2*s2 + y3*s3;
+
+ return(0);
+}
+
+static int fB1(realtype t, N_Vector y, N_Vector *yS,
+ N_Vector yB, N_Vector yBdot, void *user_dataB)
+{
+ UserData data;
+ realtype p1, p2;
+ realtype y1, y2, y3; /* solution */
+ realtype s1, s2, s3; /* sensitivity 1 */
+ realtype l1, l2, l3; /* lambda */
+ realtype m1, m2, m3; /* mu */
+
+ data = (UserData) user_dataB;
+ p1 = data->p1;
+ p2 = data->p2;
+
+ y1 = Ith(y,1);
+ y2 = Ith(y,2);
+ y3 = Ith(y,3);
+
+ s1 = Ith(yS[0],1);
+ s2 = Ith(yS[0],2);
+ s3 = Ith(yS[0],3);
+
+ l1 = Ith(yB,1);
+ l2 = Ith(yB,2);
+ l3 = Ith(yB,3);
+
+ m1 = Ith(yB,4);
+ m2 = Ith(yB,5);
+ m3 = Ith(yB,6);
+
+
+ Ith(yBdot,1) = 2.0*p1*y1 * l1 - y1;
+ Ith(yBdot,2) = l2 + p2*p2*y3 * l3 - y2;
+ Ith(yBdot,3) = l1 + p2*p2*y2 * l3 - y3;
+
+ Ith(yBdot,4) = 2.0*p1*y1 * m1 + l1 * 2.0*(y1 + p1*s1) - s1;
+ Ith(yBdot,5) = m2 + p2*p2*y3 * m3 + l3 * p2*p2*s3 - s2;
+ Ith(yBdot,6) = m1 + p2*p2*y2 * m3 + l3 * p2*p2*s2 - s3;
+
+ return(0);
+}
+
+static int fQB1(realtype t, N_Vector y, N_Vector *yS,
+ N_Vector yB, N_Vector qBdot, void *user_dataB)
+{
+ UserData data;
+ realtype p1, p2;
+ realtype y1, y2, y3; /* solution */
+ realtype s1, s2, s3; /* sensitivity 1 */
+ realtype l1, l2, l3; /* lambda */
+ realtype m1, m2, m3; /* mu */
+
+ data = (UserData) user_dataB;
+ p1 = data->p1;
+ p2 = data->p2;
+
+ y1 = Ith(y,1);
+ y2 = Ith(y,2);
+ y3 = Ith(y,3);
+
+ s1 = Ith(yS[0],1);
+ s2 = Ith(yS[0],2);
+ s3 = Ith(yS[0],3);
+
+ l1 = Ith(yB,1);
+ l2 = Ith(yB,2);
+ l3 = Ith(yB,3);
+
+ m1 = Ith(yB,4);
+ m2 = Ith(yB,5);
+ m3 = Ith(yB,6);
+
+ Ith(qBdot,1) = -y1*y1 * l1;
+ Ith(qBdot,2) = -2.0*p2*y2*y3 * l3;
+
+ Ith(qBdot,3) = -y1*y1 * m1 - l1 * 2.0*y1*s1;
+ Ith(qBdot,4) = -2.0*p2*y2*y3 * m3 - l3 * 2.0*(p2*y3*s2 + p2*y2*s3);
+
+ return(0);
+}
+
+
+
+
+static int fB2(realtype t, N_Vector y, N_Vector *yS,
+ N_Vector yB, N_Vector yBdot, void *user_dataB)
+{
+ UserData data;
+ realtype p1, p2;
+ realtype y1, y2, y3; /* solution */
+ realtype s1, s2, s3; /* sensitivity 2 */
+ realtype l1, l2, l3; /* lambda */
+ realtype m1, m2, m3; /* mu */
+
+ data = (UserData) user_dataB;
+ p1 = data->p1;
+ p2 = data->p2;
+
+ y1 = Ith(y,1);
+ y2 = Ith(y,2);
+ y3 = Ith(y,3);
+
+ s1 = Ith(yS[1],1);
+ s2 = Ith(yS[1],2);
+ s3 = Ith(yS[1],3);
+
+ l1 = Ith(yB,1);
+ l2 = Ith(yB,2);
+ l3 = Ith(yB,3);
+
+ m1 = Ith(yB,4);
+ m2 = Ith(yB,5);
+ m3 = Ith(yB,6);
+
+ Ith(yBdot,1) = 2.0*p1*y1 * l1 - y1;
+ Ith(yBdot,2) = l2 + p2*p2*y3 * l3 - y2;
+ Ith(yBdot,3) = l1 + p2*p2*y2 * l3 - y3;
+
+ Ith(yBdot,4) = 2.0*p1*y1 * m1 + l1 * 2.0*p1*s1 - s1;
+ Ith(yBdot,5) = m2 + p2*p2*y3 * m3 + l3 * (2.0*p2*y3 + p2*p2*s3) - s2;
+ Ith(yBdot,6) = m1 + p2*p2*y2 * m3 + l3 * (2.0*p2*y3 + p2*p2*s2) - s3;
+
+
+ return(0);
+}
+
+
+static int fQB2(realtype t, N_Vector y, N_Vector *yS,
+ N_Vector yB, N_Vector qBdot, void *user_dataB)
+{
+ UserData data;
+ realtype p1, p2;
+ realtype y1, y2, y3; /* solution */
+ realtype s1, s2, s3; /* sensitivity 2 */
+ realtype l1, l2, l3; /* lambda */
+ realtype m1, m2, m3; /* mu */
+
+ data = (UserData) user_dataB;
+ p1 = data->p1;
+ p2 = data->p2;
+
+ y1 = Ith(y,1);
+ y2 = Ith(y,2);
+ y3 = Ith(y,3);
+
+ s1 = Ith(yS[1],1);
+ s2 = Ith(yS[1],2);
+ s3 = Ith(yS[1],3);
+
+ l1 = Ith(yB,1);
+ l2 = Ith(yB,2);
+ l3 = Ith(yB,3);
+
+ m1 = Ith(yB,4);
+ m2 = Ith(yB,5);
+ m3 = Ith(yB,6);
+
+ Ith(qBdot,1) = -y1*y1 * l1;
+ Ith(qBdot,2) = -2.0*p2*y2*y3 * l3;
+
+ Ith(qBdot,3) = -y1*y1 * m1 - l1 * 2.0*y1*s1;
+ Ith(qBdot,4) = -2.0*p2*y2*y3 * m3 - l3 * 2.0*(p2*y3*s2 + p2*y2*s3 + y2*y3);
+
+ return(0);
+}
+
+
+/*
+ *--------------------------------------------------------------------
+ * PRIVATE FUNCTIONS
+ *--------------------------------------------------------------------
+ */
+
+void PrintFwdStats(void *cvode_mem)
+{
+ long int nst, nfe, nsetups, nni, ncfn, netf;
+ long int nfQe, netfQ;
+ long int nfSe, nfeS, nsetupsS, nniS, ncfnS, netfS;
+ long int nfQSe, netfQS;
+
+ int qlast, qcur;
+ realtype h0u, hlast, hcur, tcur;
+
+ int flag;
+
+
+ flag = CVodeGetIntegratorStats(cvode_mem, &nst, &nfe, &nsetups, &netf,
+ &qlast, &qcur,
+ &h0u, &hlast, &hcur,
+ &tcur);
+
+ flag = CVodeGetNonlinSolvStats(cvode_mem, &nni, &ncfn);
+
+ flag = CVodeGetQuadStats(cvode_mem, &nfQe, &netfQ);
+
+ flag = CVodeGetSensStats(cvode_mem, &nfSe, &nfeS, &netfS, &nsetupsS);
+
+ flag = CVodeGetSensNonlinSolvStats(cvode_mem, &nniS, &ncfnS);
+
+ flag = CVodeGetQuadSensStats(cvode_mem, &nfQSe, &netfQS);
+
+
+ printf(" Number steps: %5ld\n\n", nst);
+ printf(" Function evaluations:\n");
+ printf(" f: %5ld\n fQ: %5ld\n fS: %5ld\n fQS: %5ld\n",
+ nfe, nfQe, nfSe, nfQSe);
+ printf(" Error test failures:\n");
+ printf(" netf: %5ld\n netfQ: %5ld\n netfS: %5ld\n netfQS: %5ld\n",
+ netf, netfQ, netfS, netfQS);
+ printf(" Linear solver setups:\n");
+ printf(" nsetups: %5ld\n nsetupsS: %5ld\n", nsetups, nsetupsS);
+ printf(" Nonlinear iterations:\n");
+ printf(" nni: %5ld\n nniS: %5ld\n", nni, nniS);
+ printf(" Convergence failures:\n");
+ printf(" ncfn: %5ld\n ncfnS: %5ld\n", ncfn, ncfnS);
+
+ printf("\n");
+
+}
+
+
+void PrintBckStats(void *cvode_mem, int idx)
+{
+ void *cvode_mem_bck;
+
+ long int nst, nfe, nsetups, nni, ncfn, netf;
+ long int nfQe, netfQ;
+
+ int qlast, qcur;
+ realtype h0u, hlast, hcur, tcur;
+
+ int flag;
+
+ cvode_mem_bck = CVodeGetAdjCVodeBmem(cvode_mem, idx);
+
+ flag = CVodeGetIntegratorStats(cvode_mem_bck, &nst, &nfe, &nsetups, &netf,
+ &qlast, &qcur,
+ &h0u, &hlast, &hcur,
+ &tcur);
+
+ flag = CVodeGetNonlinSolvStats(cvode_mem_bck, &nni, &ncfn);
+
+ flag = CVodeGetQuadStats(cvode_mem_bck, &nfQe, &netfQ);
+
+ printf(" Number steps: %5ld\n\n", nst);
+ printf(" Function evaluations:\n");
+ printf(" f: %5ld\n fQ: %5ld\n", nfe, nfQe);
+ printf(" Error test failures:\n");
+ printf(" netf: %5ld\n netfQ: %5ld\n", netf, netfQ);
+ printf(" Linear solver setups:\n");
+ printf(" nsetups: %5ld\n", nsetups);
+ printf(" Nonlinear iterations:\n");
+ printf(" nni: %5ld\n", nni);
+ printf(" Convergence failures:\n");
+ printf(" ncfn: %5ld\n", ncfn);
+
+ printf("\n");
+
+
+}
diff --git a/examples/cvodes/serial/cvsHessian_ASA_FSA.out b/examples/cvodes/serial/cvsHessian_ASA_FSA.out
new file mode 100644
index 0000000..de73f5a
--- /dev/null
+++ b/examples/cvodes/serial/cvsHessian_ASA_FSA.out
@@ -0,0 +1,100 @@
+-------------------
+Forward integration
+-------------------
+
+ncheck = 1
+
+ y: 2.2732e-01 1.3534e-01 3.1472e-02 G: 5.3088e-01
+
+ yS1: -1.6714e-01 0.0000e+00 0.0000e+00
+ yS2: 2.1339e-01 0.0000e+00 -1.0885e-01
+
+ dG/dp: -1.2838e-01 1.8037e-02
+
+Final Statistics for forward pb.
+--------------------------------
+ Number steps: 142
+
+ Function evaluations:
+ f: 165
+ fQ: 147
+ fS: 165
+ fQS: 147
+ Error test failures:
+ netf: 1
+ netfQ: 0
+ netfS: 0
+ netfQS: 1
+ Linear solver setups:
+ nsetups: 27
+ nsetupsS: 0
+ Nonlinear iterations:
+ nni: 161
+ nniS: 0
+ Convergence failures:
+ ncfn: 0
+ ncfnS: 0
+
+---------------------------------------------
+Backward integration ... (2 adjoint problems)
+---------------------------------------------
+
+ dG/dp: -1.2838e-01 1.8036e-02 (from backward pb. 1)
+ -1.2838e-01 1.8036e-02 (from backward pb. 2)
+
+ H = d2G/dp2:
+ (1) (2)
+ 1.5628e-01 -7.8678e-02
+ -7.8678e-02 1.1093e-01
+
+Final Statistics for backward pb. 1
+-----------------------------------
+ Number steps: 100
+
+ Function evaluations:
+ f: 127
+ fQ: 108
+ Error test failures:
+ netf: 1
+ netfQ: 4
+ Linear solver setups:
+ nsetups: 22
+ Nonlinear iterations:
+ nni: 123
+ Convergence failures:
+ ncfn: 0
+
+Final Statistics for backward pb. 2
+-----------------------------------
+ Number steps: 85
+
+ Function evaluations:
+ f: 109
+ fQ: 92
+ Error test failures:
+ netf: 1
+ netfQ: 3
+ Linear solver setups:
+ nsetups: 18
+ Nonlinear iterations:
+ nni: 105
+ Convergence failures:
+ ncfn: 0
+
+-----------------------
+Finite Difference tests
+-----------------------
+
+del_p = 0.01
+
+p1+ y: 2.2566e-01 1.3534e-01 3.1472e-02 G: 5.2960e-01
+p1- y: 2.2900e-01 1.3534e-01 3.1472e-02 G: 5.3217e-01
+p2+ y: 2.2943e-01 1.3534e-01 3.0399e-02 G: 5.3106e-01
+p2- y: 2.2516e-01 1.3534e-01 3.2577e-02 G: 5.3070e-01
+
+ dG/dp: -1.2760e-01 1.8475e-02 (fwd FD)
+ -1.2916e-01 1.7581e-02 (bck FD)
+ -1.2838e-01 1.8028e-02 (cntr FD)
+
+ H(1,1): 1.5590e-01
+ H(2,2): 8.9446e-02
diff --git a/examples/cvodes/serial/cvsKrylovDemo_ls.c b/examples/cvodes/serial/cvsKrylovDemo_ls.c
new file mode 100644
index 0000000..6864513
--- /dev/null
+++ b/examples/cvodes/serial/cvsKrylovDemo_ls.c
@@ -0,0 +1,736 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.3 $
+ * $Date: 2010/12/01 22:57:59 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh and
+ * Radu Serban @ LLNL
+ *
+ * This example loops through the available iterative linear solvers:
+ * SPGMR, SPBCG and SPTFQMR.
+ *
+ * Example problem:
+ *
+ * An ODE system is generated from the following 2-species diurnal
+ * kinetics advection-diffusion PDE system in 2 space dimensions:
+ *
+ * dc(i)/dt = Kh*(d/dx)^2 c(i) + V*dc(i)/dx + (d/dy)(Kv(y)*dc(i)/dy)
+ * + Ri(c1,c2,t) for i = 1,2, where
+ * R1(c1,c2,t) = -q1*c1*c3 - q2*c1*c2 + 2*q3(t)*c3 + q4(t)*c2 ,
+ * R2(c1,c2,t) = q1*c1*c3 - q2*c1*c2 - q4(t)*c2 ,
+ * Kv(y) = Kv0*exp(y/5) ,
+ * Kh, V, Kv0, q1, q2, and c3 are constants, and q3(t) and q4(t)
+ * vary diurnally. The problem is posed on the square
+ * 0 <= x <= 20, 30 <= y <= 50 (all in km),
+ * with homogeneous Neumann boundary conditions, and for time t in
+ * 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
+ * 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, SQR, and EXP */
+
+/* Problem Constants */
+
+#define ZERO RCONST(0.0)
+#define ONE RCONST(1.0)
+#define TWO RCONST(2.0)
+
+#define NUM_SPECIES 2 /* number of species */
+#define KH RCONST(4.0e-6) /* horizontal diffusivity Kh */
+#define VEL RCONST(0.001) /* advection velocity V */
+#define KV0 RCONST(1.0e-8) /* coefficient in Kv(y) */
+#define Q1 RCONST(1.63e-16) /* coefficients q1, q2, c3 */
+#define Q2 RCONST(4.66e-16)
+#define C3 RCONST(3.7e16)
+#define A3 RCONST(22.62) /* coefficient in expression for q3(t) */
+#define A4 RCONST(7.601) /* coefficient in expression for q4(t) */
+#define C1_SCALE RCONST(1.0e6) /* coefficients in initial profiles */
+#define C2_SCALE RCONST(1.0e12)
+
+#define T0 ZERO /* initial time */
+#define NOUT 12 /* number of output times */
+#define TWOHR RCONST(7200.0) /* number of seconds in two hours */
+#define HALFDAY RCONST(4.32e4) /* number of seconds in a half day */
+#define PI RCONST(3.1415926535898) /* pi */
+
+#define XMIN ZERO /* grid boundaries in x */
+#define XMAX RCONST(20.0)
+#define YMIN RCONST(30.0) /* grid boundaries in y */
+#define YMAX RCONST(50.0)
+#define XMID RCONST(10.0) /* grid midpoints in x,y */
+#define YMID RCONST(40.0)
+
+#define MX 10 /* MX = number of x mesh points */
+#define MY 10 /* MY = number of y mesh points */
+#define NSMX 20 /* NSMX = NUM_SPECIES*MX */
+#define MM (MX*MY) /* MM = MX*MY */
+
+/* CVodeInit Constants */
+
+#define RTOL RCONST(1.0e-5) /* scalar relative tolerance */
+#define FLOOR RCONST(100.0) /* value of C1 or C2 at which tolerances */
+ /* change from relative to absolute */
+#define ATOL (RTOL*FLOOR) /* scalar absolute tolerance */
+#define NEQ (NUM_SPECIES*MM) /* NEQ = number of equations */
+
+/* Linear Solver Loop Constants */
+
+#define USE_SPGMR 0
+#define USE_SPBCG 1
+#define USE_SPTFQMR 2
+
+/* User-defined vector and matrix accessor macros: IJKth, IJth */
+
+/* IJKth is defined in order to isolate the translation from the
+ mathematical 3-dimensional structure of the dependent variable vector
+ to the underlying 1-dimensional storage. IJth is defined in order to
+ write code which indexes into dense matrices with a (row,column)
+ pair, where 1 <= row, column <= NUM_SPECIES.
+
+ 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 = NV_DATA_S(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 matrix realtype **a,
+ where 1 <= i,j <= NUM_SPECIES. The small matrix routines in
+ sundials_dense.h work with matrices stored by column in a 2-dimensional
+ array. In C, arrays are indexed starting at 0, not 1. */
+
+#define IJKth(vdata,i,j,k) (vdata[i-1 + (j)*NUM_SPECIES + (k)*NSMX])
+#define IJth(a,i,j) (a[j-1][i-1])
+
+/* Type : UserData
+ contains preconditioner blocks, pivot arrays, and problem constants */
+
+typedef struct {
+ realtype **P[MX][MY], **Jbd[MX][MY];
+ long int *pivot[MX][MY];
+ realtype q4, om, dx, dy, hdco, haco, vdco;
+} *UserData;
+
+/* Private Helper Functions */
+
+static UserData AllocUserData(void);
+static void InitUserData(UserData data);
+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, int linsolver);
+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 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 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);
+
+
+/*
+ *-------------------------------
+ * Main Program
+ *-------------------------------
+ */
+
+int main(void)
+{
+ realtype abstol, reltol, t, tout;
+ N_Vector u;
+ UserData data;
+ void *cvode_mem;
+ int linsolver, iout, flag;
+
+ u = NULL;
+ data = NULL;
+ cvode_mem = NULL;
+
+ /* Allocate memory, and set problem data, initial values, tolerances */
+ u = N_VNew_Serial(NEQ);
+ if(check_flag((void *)u, "N_VNew_Serial", 0)) return(1);
+ data = AllocUserData();
+ if(check_flag((void *)data, "AllocUserData", 2)) return(1);
+ InitUserData(data);
+ SetInitialProfiles(u, data->dx, data->dy);
+ abstol=ATOL;
+ reltol=RTOL;
+
+ /* 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);
+
+ /* Set the pointer to user-defined data */
+ flag = CVodeSetUserData(cvode_mem, data);
+ if(check_flag(&flag, "CVodeSetUserData", 1)) 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
+ * 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 tolerances */
+ flag = CVodeSStolerances(cvode_mem, reltol, abstol);
+ if (check_flag(&flag, "CVodeSStolerances", 1)) return(1);
+
+ /* START: Loop through SPGMR, SPBCG and SPTFQMR linear solver modules */
+ for (linsolver = 0; linsolver < 3; ++linsolver) {
+
+ if (linsolver != 0) {
+
+ /* Re-initialize user data */
+ InitUserData(data);
+ SetInitialProfiles(u, data->dx, data->dy);
+
+ /* Re-initialize CVode for the solution of the same problem, but
+ using a different linear solver module */
+ flag = CVodeReInit(cvode_mem, T0, u);
+ if (check_flag(&flag, "CVodeReInit", 1)) return(1);
+
+ }
+
+ /* Attach a linear solver module */
+ switch(linsolver) {
+
+ /* (a) SPGMR */
+ case(USE_SPGMR):
+
+ /* Print header */
+ printf(" -------");
+ 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);
+
+ /* Set modified Gram-Schmidt orthogonalization, preconditioner
+ setup and solve routines Precond and PSolve, and the pointer
+ to the user-defined block data */
+ flag = CVSpilsSetGSType(cvode_mem, MODIFIED_GS);
+ if(check_flag(&flag, "CVSpilsSetGSType", 1)) return(1);
+
+ break;
+
+ /* (b) SPBCG */
+ case(USE_SPBCG):
+
+ /* Print header */
+ printf(" -------");
+ printf(" \n| SPBCG |\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);
+
+ break;
+
+ /* (c) SPTFQMR */
+ case(USE_SPTFQMR):
+
+ /* Print header */
+ printf(" ---------");
+ 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);
+
+ break;
+
+ }
+
+
+ /* 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);
+
+ /* In loop over output points, call CVode, print results, test for error */
+ printf(" \n2-species diurnal advection-diffusion problem\n\n");
+ for (iout=1, tout = TWOHR; iout <= NOUT; iout++, tout += TWOHR) {
+ flag = CVode(cvode_mem, tout, u, &t, CV_NORMAL);
+ PrintOutput(cvode_mem, u, t);
+ if(check_flag(&flag, "CVode", 1)) break;
+ }
+
+ PrintFinalStats(cvode_mem, linsolver);
+
+ } /* END: Loop through SPGMR, SPBCG and SPTFQMR linear solver modules */
+
+ /* Free memory */
+ N_VDestroy_Serial(u);
+ FreeUserData(data);
+ CVodeFree(&cvode_mem);
+
+ return(0);
+}
+
+/*
+ *-------------------------------
+ * Private helper functions
+ *-------------------------------
+ */
+
+/* Allocate memory for data structure of type UserData */
+
+static UserData AllocUserData(void)
+{
+ int jx, jy;
+ UserData data;
+
+ data = (UserData) malloc(sizeof *data);
+
+ for (jx=0; jx < MX; jx++) {
+ 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);
+ }
+ }
+
+ return(data);
+}
+
+/* Load problem constants in data */
+
+static void InitUserData(UserData data)
+{
+ data->om = PI/HALFDAY;
+ data->dx = (XMAX-XMIN)/(MX-1);
+ data->dy = (YMAX-YMIN)/(MY-1);
+ data->hdco = KH/SQR(data->dx);
+ data->haco = VEL/(TWO*data->dx);
+ data->vdco = (ONE/SQR(data->dy))*KV0;
+}
+
+/* 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]);
+ destroyMat((data->Jbd)[jx][jy]);
+ destroyArray((data->pivot)[jx][jy]);
+ }
+ }
+
+ free(data);
+}
+
+/* Set initial conditions in u */
+
+static void SetInitialProfiles(N_Vector u, realtype dx, realtype dy)
+{
+ int jx, jy;
+ realtype x, y, cx, cy;
+ realtype *udata;
+
+ /* Set pointer to data array in vector u. */
+
+ udata = NV_DATA_S(u);
+
+ /* Load initial profiles of c1 and c2 into u vector */
+
+ for (jy=0; jy < MY; jy++) {
+ y = YMIN + jy*dy;
+ cy = SQR(RCONST(0.1)*(y - YMID));
+ cy = ONE - cy + RCONST(0.5)*SQR(cy);
+ for (jx=0; jx < MX; jx++) {
+ x = XMIN + jx*dx;
+ cx = SQR(RCONST(0.1)*(x - XMID));
+ cx = ONE - cx + RCONST(0.5)*SQR(cx);
+ IJKth(udata,1,jx,jy) = C1_SCALE*cx*cy;
+ IJKth(udata,2,jx,jy) = C2_SCALE*cx*cy;
+ }
+ }
+}
+
+/* Print current t, step count, order, stepsize, and sampled c1,c2 values */
+
+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 = NV_DATA_S(u);
+
+ flag = CVodeGetNumSteps(cvode_mem, &nst);
+ check_flag(&flag, "CVodeGetNumSteps", 1);
+ flag = CVodeGetLastOrder(cvode_mem, &qu);
+ check_flag(&flag, "CVodeGetLastOrder", 1);
+ flag = CVodeGetLastStep(cvode_mem, &hu);
+ check_flag(&flag, "CVodeGetLastStep", 1);
+
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("t = %.2Le no. steps = %ld order = %d stepsize = %.2Le\n",
+ t, nst, qu, hu);
+ printf("c1 (bot.left/middle/top rt.) = %12.3Le %12.3Le %12.3Le\n",
+ IJKth(udata,1,0,0), IJKth(udata,1,mxh,myh), IJKth(udata,1,mx1,my1));
+ printf("c2 (bot.left/middle/top rt.) = %12.3Le %12.3Le %12.3Le\n\n",
+ IJKth(udata,2,0,0), IJKth(udata,2,mxh,myh), IJKth(udata,2,mx1,my1));
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("t = %.2le no. steps = %ld order = %d stepsize = %.2le\n",
+ t, nst, qu, hu);
+ printf("c1 (bot.left/middle/top rt.) = %12.3le %12.3le %12.3le\n",
+ IJKth(udata,1,0,0), IJKth(udata,1,mxh,myh), IJKth(udata,1,mx1,my1));
+ printf("c2 (bot.left/middle/top rt.) = %12.3le %12.3le %12.3le\n\n",
+ IJKth(udata,2,0,0), IJKth(udata,2,mxh,myh), IJKth(udata,2,mx1,my1));
+#else
+ printf("t = %.2e no. steps = %ld order = %d stepsize = %.2e\n",
+ t, nst, qu, hu);
+ printf("c1 (bot.left/middle/top rt.) = %12.3e %12.3e %12.3e\n",
+ IJKth(udata,1,0,0), IJKth(udata,1,mxh,myh), IJKth(udata,1,mx1,my1));
+ printf("c2 (bot.left/middle/top rt.) = %12.3e %12.3e %12.3e\n\n",
+ IJKth(udata,2,0,0), IJKth(udata,2,mxh,myh), IJKth(udata,2,mx1,my1));
+#endif
+}
+
+/* Get and print final statistics */
+
+static void PrintFinalStats(void *cvode_mem, int linsolver)
+{
+ long int lenrw, leniw ;
+ long int 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);
+
+ if (linsolver < 2)
+ printf("======================================================================\n\n");
+}
+
+/* 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, 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);
+}
+
+/*
+ *-------------------------------
+ * Functions called by the solver
+ *-------------------------------
+ */
+
+/* f routine. Compute RHS function f(t,u). */
+
+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 jx, jy, idn, iup, ileft, iright;
+ UserData data;
+
+ data = (UserData) user_data;
+ udata = NV_DATA_S(u);
+ dudata = NV_DATA_S(udot);
+
+ /* Set diurnal rate coefficients. */
+
+ s = sin(data->om*t);
+ if (s > ZERO) {
+ q3 = EXP(-A3/s);
+ data->q4 = EXP(-A4/s);
+ } else {
+ q3 = ZERO;
+ data->q4 = ZERO;
+ }
+
+ /* Make local copies of problem variables, for efficiency. */
+
+ q4coef = data->q4;
+ dely = data->dy;
+ verdco = data->vdco;
+ hordco = data->hdco;
+ horaco = data->haco;
+
+ /* Loop over all grid points. */
+
+ for (jy=0; jy < MY; jy++) {
+
+ /* Set vertical diffusion coefficients at jy +- 1/2 */
+
+ ydn = YMIN + (jy - RCONST(0.5))*dely;
+ yup = ydn + dely;
+ cydn = verdco*EXP(RCONST(0.2)*ydn);
+ cyup = verdco*EXP(RCONST(0.2)*yup);
+ idn = (jy == 0) ? 1 : -1;
+ iup = (jy == MY-1) ? -1 : 1;
+ for (jx=0; jx < MX; jx++) {
+
+ /* Extract c1 and c2, and set kinetic rate terms. */
+
+ c1 = IJKth(udata,1,jx,jy);
+ c2 = IJKth(udata,2,jx,jy);
+ qq1 = Q1*c1*C3;
+ qq2 = Q2*c1*c2;
+ qq3 = q3*C3;
+ qq4 = q4coef*c2;
+ rkin1 = -qq1 - qq2 + TWO*qq3 + qq4;
+ rkin2 = qq1 - qq2 - qq4;
+
+ /* Set vertical diffusion terms. */
+
+ c1dn = IJKth(udata,1,jx,jy+idn);
+ c2dn = IJKth(udata,2,jx,jy+idn);
+ c1up = IJKth(udata,1,jx,jy+iup);
+ c2up = IJKth(udata,2,jx,jy+iup);
+ vertd1 = cyup*(c1up - c1) - cydn*(c1 - c1dn);
+ vertd2 = cyup*(c2up - c2) - cydn*(c2 - c2dn);
+
+ /* Set horizontal diffusion and advection terms. */
+
+ ileft = (jx == 0) ? 1 : -1;
+ iright =(jx == MX-1) ? -1 : 1;
+ c1lt = IJKth(udata,1,jx+ileft,jy);
+ c2lt = IJKth(udata,2,jx+ileft,jy);
+ c1rt = IJKth(udata,1,jx+iright,jy);
+ c2rt = IJKth(udata,2,jx+iright,jy);
+ hord1 = hordco*(c1rt - TWO*c1 + c1lt);
+ hord2 = hordco*(c2rt - TWO*c2 + c2lt);
+ horad1 = horaco*(c1rt - c1lt);
+ horad2 = horaco*(c2rt - c2lt);
+
+ /* Load all terms into udot. */
+
+ IJKth(dudata, 1, jx, jy) = vertd1 + hord1 + horad1 + rkin1;
+ IJKth(dudata, 2, jx, jy) = vertd2 + hord2 + horad2 + rkin2;
+ }
+ }
+
+ return(0);
+}
+
+/* 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 c1, c2, cydn, cyup, diag, ydn, yup, q4coef, dely, verdco, hordco;
+ realtype **(*P)[MY], **(*Jbd)[MY];
+ long int *(*pivot)[MY], ier;
+ int jx, jy;
+ realtype *udata, **a, **j;
+ UserData data;
+
+ /* Make local copies of pointers in user_data, and of pointer to u's data */
+
+ data = (UserData) user_data;
+ P = data->P;
+ Jbd = data->Jbd;
+ pivot = data->pivot;
+ udata = NV_DATA_S(u);
+
+ if (jok) {
+
+ /* jok = TRUE: 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;
+
+ }
+
+ else {
+ /* jok = FALSE: Generate Jbd from scratch and copy to P */
+
+ /* Make local copies of problem variables, for efficiency. */
+
+ q4coef = data->q4;
+ dely = data->dy;
+ verdco = data->vdco;
+ hordco = data->hdco;
+
+ /* Compute 2x2 diagonal Jacobian blocks (using q4 values
+ computed on the last f call). Load into P. */
+
+ for (jy=0; jy < MY; jy++) {
+ ydn = YMIN + (jy - RCONST(0.5))*dely;
+ yup = ydn + dely;
+ cydn = verdco*EXP(RCONST(0.2)*ydn);
+ cyup = verdco*EXP(RCONST(0.2)*yup);
+ diag = -(cydn + cyup + TWO*hordco);
+ for (jx=0; jx < MX; jx++) {
+ c1 = IJKth(udata,1,jx,jy);
+ c2 = IJKth(udata,2,jx,jy);
+ j = Jbd[jx][jy];
+ a = P[jx][jy];
+ IJth(j,1,1) = (-Q1*C3 - Q2*c2) + diag;
+ IJth(j,1,2) = -Q2*c1 + q4coef;
+ IJth(j,2,1) = Q1*C3 - Q2*c2;
+ IJth(j,2,2) = (-Q2*c1 - q4coef) + diag;
+ denseCopy(j, a, NUM_SPECIES, NUM_SPECIES);
+ }
+ }
+
+ *jcurPtr = TRUE;
+
+ }
+
+ /* Scale by -gamma */
+
+ for (jy=0; jy < MY; jy++)
+ for (jx=0; jx < MX; jx++)
+ denseScale(-gamma, P[jx][jy], NUM_SPECIES, NUM_SPECIES);
+
+ /* Add identity matrix and do LU decompositions on blocks in place. */
+
+ for (jx=0; jx < MX; jx++) {
+ for (jy=0; jy < MY; jy++) {
+ denseAddIdentity(P[jx][jy], NUM_SPECIES);
+ ier =denseGETRF(P[jx][jy], NUM_SPECIES, NUM_SPECIES, pivot[jx][jy]);
+ if (ier != 0) return(1);
+ }
+ }
+
+ return(0);
+}
+
+/* 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)
+{
+ realtype **(*P)[MY];
+ long int *(*pivot)[MY];
+ int jx, jy;
+ realtype *zdata, *v;
+ UserData data;
+
+ /* Extract the P and pivot arrays from user_data. */
+
+ data = (UserData) user_data;
+ P = data->P;
+ pivot = data->pivot;
+ zdata = NV_DATA_S(z);
+
+ N_VScale(ONE, r, z);
+
+ /* Solve the block-diagonal system Px = r using LU factors stored
+ in P and pivot data in pivot, and return the solution in z. */
+
+ for (jx=0; jx < MX; jx++) {
+ for (jy=0; jy < MY; jy++) {
+ v = &(IJKth(zdata, 1, jx, jy));
+ denseGETRS(P[jx][jy], NUM_SPECIES, pivot[jx][jy], v);
+ }
+ }
+
+ return(0);
+}
diff --git a/examples/cvodes/serial/cvsKrylovDemo_ls.out b/examples/cvodes/serial/cvsKrylovDemo_ls.out
new file mode 100644
index 0000000..5e386da
--- /dev/null
+++ b/examples/cvodes/serial/cvsKrylovDemo_ls.out
@@ -0,0 +1,202 @@
+ -------
+| SPGMR |
+ -------
+
+2-species diurnal advection-diffusion problem
+
+t = 7.20e+03 no. steps = 219 order = 5 stepsize = 1.59e+02
+c1 (bot.left/middle/top rt.) = 1.047e+04 2.964e+04 1.119e+04
+c2 (bot.left/middle/top rt.) = 2.527e+11 7.154e+11 2.700e+11
+
+t = 1.44e+04 no. steps = 251 order = 5 stepsize = 3.77e+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 = 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
+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
+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
+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
+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
+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
+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
+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
+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
+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
+ncfn = 0 ncfl = 0
+
+======================================================================
+
+ -------
+| SPBCG |
+ -------
+
+2-species diurnal advection-diffusion problem
+
+t = 7.20e+03 no. steps = 190 order = 5 stepsize = 1.58e+02
+c1 (bot.left/middle/top rt.) = 1.047e+04 2.964e+04 1.119e+04
+c2 (bot.left/middle/top rt.) = 2.527e+11 7.154e+11 2.700e+11
+
+t = 1.44e+04 no. steps = 222 order = 5 stepsize = 3.81e+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 = 246 order = 5 stepsize = 4.34e+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 = 282 order = 4 stepsize = 1.71e+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 = 317 order = 5 stepsize = 9.48e+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 = 369 order = 4 stepsize = 5.46e+02
+c1 (bot.left/middle/top rt.) = -1.286e-09 -1.138e-09 -1.297e-09
+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
+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
+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
+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
+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
+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
+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
+ncfn = 0 ncfl = 0
+
+======================================================================
+
+ ---------
+| SPTFQMR |
+ ---------
+
+2-species diurnal advection-diffusion problem
+
+t = 7.20e+03 no. steps = 218 order = 5 stepsize = 1.44e+02
+c1 (bot.left/middle/top rt.) = 1.047e+04 2.964e+04 1.119e+04
+c2 (bot.left/middle/top rt.) = 2.527e+11 7.154e+11 2.700e+11
+
+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
+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
+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
+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
+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
+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
+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
+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
+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
+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
+
+
+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
+ncfn = 0 ncfl = 0
+
diff --git a/examples/cvodes/serial/cvsKrylovDemo_prec.c b/examples/cvodes/serial/cvsKrylovDemo_prec.c
new file mode 100644
index 0000000..4cd2f16
--- /dev/null
+++ b/examples/cvodes/serial/cvsKrylovDemo_prec.c
@@ -0,0 +1,1141 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.5 $
+ * $Date: 2010/12/30 00:22:20 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh and
+ * Radu Serban @ LLNL
+ * --------------------------------------------------------------------
+ * Demonstration program for CVODES - Krylov linear solver.
+ * ODE system from ns-species interaction PDE in 2 dimensions.
+ *
+ * This program solves a stiff ODE system that arises from a system
+ * of partial differential equations. The PDE system is a food web
+ * population model, with predator-prey interaction and diffusion on
+ * the unit square in two dimensions. The dependent variable vector is:
+ *
+ * 1 2 ns
+ * c = (c , c , ..., c )
+ *
+ * and the PDEs are as follows:
+ *
+ * i i i
+ * dc /dt = d(i)*(c + c ) + f (x,y,c) (i=1,...,ns)
+ * xx yy i
+ *
+ * where
+ *
+ * i ns j
+ * f (x,y,c) = c *(b(i) + sum a(i,j)*c )
+ * i j=1
+ *
+ * The number of species is ns = 2*np, with the first np being prey
+ * and the last np being predators. The coefficients a(i,j), b(i),
+ * d(i) are:
+ *
+ * a(i,i) = -a (all i)
+ * a(i,j) = -g (i <= np, j > np)
+ * a(i,j) = e (i > np, j <= np)
+ * b(i) = b*(1 + alpha*x*y) (i <= np)
+ * b(i) = -b*(1 + alpha*x*y) (i > np)
+ * d(i) = Dprey (i <= np)
+ * d(i) = Dpred (i > np)
+ *
+ * The spatial domain is the unit square. The final time is 10.
+ * The boundary conditions are: normal derivative = 0.
+ * A polynomial in x and y is used to set the initial conditions.
+ *
+ * The PDEs are discretized by central differencing on an MX by MY mesh.
+ *
+ * The resulting ODE system is stiff.
+ *
+ * The ODE system is solved using Newton iteration and the CVSPGMR
+ * 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
+ * of Gauss-Seidel iterations using the diffusion terms only.
+ * (2) A block-diagonal matrix based on the partial derivatives
+ * of the interaction terms f only, using block-grouping (computing
+ * only a subset of the ns by ns blocks).
+ *
+ * Four different runs are made for this problem.
+ * 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.
+ *
+ * A problem description, performance statistics at selected output
+ * times, and final statistics are written to standard output.
+ * On the first run, solution values are also printed at output
+ * times. Error and warning messages are written to standard error,
+ * but there should be no such messages.
+ *
+ * Note: This program requires the dense linear solver functions
+ * newDenseMat, newLintArray, denseAddIdentity, denseGETRF, denseGETRS,
+ * destroyMat and destroyArray.
+ *
+ * Note: This program assumes the sequential implementation for the
+ * type N_Vector and uses the NV_DATA_S macro 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 SQR */
+
+/* Constants */
+
+#define ZERO RCONST(0.0)
+#define ONE RCONST(1.0)
+
+/* Problem Specification Constants */
+
+#define AA ONE /* AA = a */
+#define EE RCONST(1.0e4) /* EE = e */
+#define GG RCONST(0.5e-6) /* GG = g */
+#define BB ONE /* BB = b */
+#define DPREY ONE
+#define DPRED RCONST(0.5)
+#define ALPH ONE
+#define NP 3
+#define NS (2*NP)
+
+/* Method Constants */
+
+#define MX 6
+#define MY 6
+#define MXNS (MX*NS)
+#define AX ONE
+#define AY ONE
+#define DX (AX/(realtype)(MX-1))
+#define DY (AY/(realtype)(MY-1))
+#define MP NS
+#define MQ (MX*MY)
+#define MXMP (MX*MP)
+#define NGX 2
+#define NGY 2
+#define NGRP (NGX*NGY)
+#define ITMAX 5
+
+/* CVodeInit Constants */
+
+#define NEQ (NS*MX*MY)
+#define T0 ZERO
+#define RTOL RCONST(1.0e-5)
+#define ATOL RCONST(1.0e-5)
+
+/* CVSpgmr Constants */
+
+#define MAXL 0 /* => use default = MIN(NEQ, 5) */
+#define DELT ZERO /* => use default = 0.05 */
+
+/* Output Constants */
+
+#define T1 RCONST(1.0e-8)
+#define TOUT_MULT RCONST(10.0)
+#define DTOUT ONE
+#define NOUT 18
+
+/* Note: The value for species i at mesh point (j,k) is stored in */
+/* component number (i-1) + j*NS + k*NS*MX of an N_Vector, */
+/* where 1 <= i <= NS, 0 <= j < MX, 0 <= k < MY. */
+
+/* Structure for user data */
+
+typedef struct {
+ realtype **P[NGRP];
+ long int *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];
+ int jxr[NGX], jyr[NGY];
+ realtype acoef[NS][NS], bcoef[NS], diff[NS];
+ realtype cox[NS], coy[NS], dx, dy, srur;
+ realtype fsave[NEQ];
+ N_Vector rewt;
+ void *cvode_mem;
+} *WebData;
+
+/* Private Helper Functions */
+
+static WebData AllocUserData(void);
+static void InitUserData(WebData wdata);
+static void SetGroups(int m, int ng, int jg[], int jig[], int jr[]);
+static void CInit(N_Vector c, WebData wdata);
+static void PrintIntro(void);
+static void PrintHeader(int jpre, int gstype);
+static void PrintAllSpecies(N_Vector c, int ns, int mxns, realtype t);
+static void PrintOutput(void *cvode_mem, realtype t);
+static void PrintFinalStats(void *cvode_mem);
+static void FreeUserData(WebData wdata);
+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);
+
+/* Small Vector Kernels */
+
+static void v_inc_by_prod(realtype u[], realtype v[], realtype w[], int n);
+static void v_sum_prods(realtype u[], realtype p[], realtype q[], realtype v[],
+ realtype w[], int n);
+static void v_prod(realtype u[], realtype v[], realtype w[], int n);
+static void v_zero(realtype u[], int n);
+
+/* Functions Called By The Solver */
+
+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 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);
+
+/* Private function to check function return values */
+
+static int check_flag(void *flagvalue, char *funcname, int opt);
+
+/* Implementation */
+
+int main()
+{
+ realtype abstol=ATOL, reltol=RTOL, t, tout;
+ N_Vector c;
+ WebData wdata;
+ void *cvode_mem;
+ booleantype firstrun;
+ int jpre, gstype, flag;
+ int ns, mxns, iout;
+
+ c = NULL;
+ wdata = NULL;
+ cvode_mem = NULL;
+
+ /* Initializations */
+ c = N_VNew_Serial(NEQ);
+ if(check_flag((void *)c, "N_VNew_Serial", 0)) return(1);
+ wdata = AllocUserData();
+ if(check_flag((void *)wdata, "AllocUserData", 2)) return(1);
+ InitUserData(wdata);
+ ns = wdata->ns;
+ mxns = wdata->mxns;
+
+ /* Print problem description */
+ PrintIntro();
+
+ /* Loop over jpre and gstype (four cases) */
+ for (jpre = PREC_LEFT; jpre <= PREC_RIGHT; jpre++) {
+ for (gstype = MODIFIED_GS; gstype <= CLASSICAL_GS; gstype++) {
+
+ /* Initialize c and print heading */
+ CInit(c, wdata);
+ PrintHeader(jpre, gstype);
+
+ /* Call CVodeInit or CVodeReInit, then CVSpgmr to set up problem */
+
+ firstrun = (jpre == PREC_LEFT) && (gstype == MODIFIED_GS);
+ if (firstrun) {
+ cvode_mem = CVodeCreate(CV_BDF, CV_NEWTON);
+ if(check_flag((void *)cvode_mem, "CVodeCreate", 0)) return(1);
+
+ wdata->cvode_mem = cvode_mem;
+
+ flag = CVodeSetUserData(cvode_mem, wdata);
+ if(check_flag(&flag, "CVodeSetUserData", 1)) return(1);
+
+ flag = CVodeInit(cvode_mem, f, T0, c);
+ if(check_flag(&flag, "CVodeInit", 1)) return(1);
+
+ flag = CVodeSStolerances(cvode_mem, reltol, abstol);
+ if (check_flag(&flag, "CVodeSStolerances", 1)) return(1);
+
+ flag = CVSpgmr(cvode_mem, jpre, MAXL);
+ if(check_flag(&flag, "CVSpgmr", 1)) return(1);
+
+ flag = CVSpilsSetGSType(cvode_mem, gstype);
+ if(check_flag(&flag, "CVSpilsSetGSType", 1)) return(1);
+
+ flag = CVSpilsSetEpsLin(cvode_mem, DELT);
+ if(check_flag(&flag, "CVSpilsSetEpsLin", 1)) return(1);
+
+ flag = CVSpilsSetPreconditioner(cvode_mem, Precond, PSolve);
+ if(check_flag(&flag, "CVSpilsSetPreconditioner", 1)) return(1);
+
+ } else {
+
+ 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);
+
+ }
+
+ /* Print initial values */
+ if (firstrun) PrintAllSpecies(c, ns, mxns, T0);
+
+ /* Loop over output points, call CVode, print sample solution values. */
+ tout = T1;
+ for (iout = 1; iout <= NOUT; iout++) {
+ flag = CVode(cvode_mem, tout, c, &t, CV_NORMAL);
+ PrintOutput(cvode_mem, t);
+ if (firstrun && (iout % 3 == 0)) PrintAllSpecies(c, ns, mxns, t);
+ if(check_flag(&flag, "CVode", 1)) break;
+ if (tout > RCONST(0.9)) tout += DTOUT; else tout *= TOUT_MULT;
+ }
+
+ /* Print final statistics, and loop for next case */
+ PrintFinalStats(cvode_mem);
+
+ }
+ }
+
+ /* Free all memory */
+ CVodeFree(&cvode_mem);
+ N_VDestroy_Serial(c);
+ FreeUserData(wdata);
+
+ return(0);
+}
+
+static WebData AllocUserData(void)
+{
+ int i, ngrp = NGRP;
+ long int 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->rewt = N_VNew_Serial(NEQ);
+ return(wdata);
+}
+
+static void InitUserData(WebData wdata)
+{
+ int i, j, ns;
+ realtype *bcoef, *diff, *cox, *coy, dx, dy;
+ realtype (*acoef)[NS];
+
+ acoef = wdata->acoef;
+ bcoef = wdata->bcoef;
+ diff = wdata->diff;
+ cox = wdata->cox;
+ coy = wdata->coy;
+ ns = wdata->ns = NS;
+
+ for (j = 0; j < NS; j++) { for (i = 0; i < NS; i++) acoef[i][j] = 0.; }
+ for (j = 0; j < NP; j++) {
+ for (i = 0; i < NP; i++) {
+ acoef[NP+i][j] = EE;
+ acoef[i][NP+j] = -GG;
+ }
+ acoef[j][j] = -AA;
+ acoef[NP+j][NP+j] = -AA;
+ bcoef[j] = BB;
+ bcoef[NP+j] = -BB;
+ diff[j] = DPREY;
+ diff[NP+j] = DPRED;
+ }
+
+ /* Set remaining problem parameters */
+
+ wdata->mxns = MXNS;
+ dx = wdata->dx = DX;
+ dy = wdata->dy = DY;
+ for (i = 0; i < ns; i++) {
+ cox[i] = diff[i]/SQR(dx);
+ coy[i] = diff[i]/SQR(dy);
+ }
+
+ /* Set remaining method parameters */
+
+ wdata->mp = MP;
+ wdata->mq = MQ;
+ wdata->mx = MX;
+ wdata->my = MY;
+ wdata->srur = SQRT(UNIT_ROUNDOFF);
+ wdata->mxmp = MXMP;
+ wdata->ngrp = NGRP;
+ wdata->ngx = NGX;
+ wdata->ngy = NGY;
+ SetGroups(MX, NGX, wdata->jgx, wdata->jigx, wdata->jxr);
+ SetGroups(MY, NGY, wdata->jgy, wdata->jigy, wdata->jyr);
+}
+
+/*
+ This routine sets arrays jg, jig, and jr describing
+ a uniform partition of (0,1,2,...,m-1) into ng groups.
+ The arrays set are:
+ jg = length ng+1 array of group boundaries.
+ Group ig has indices j = jg[ig],...,jg[ig+1]-1.
+ jig = length m array of group indices vs node index.
+ Node index j is in group jig[j].
+ jr = length ng array of indices representing the groups.
+ The index for group ig is j = jr[ig].
+*/
+static void SetGroups(int m, int ng, int jg[], int jig[], int jr[])
+{
+ int ig, j, len1, mper, ngm1;
+
+ mper = m/ng; /* does integer division */
+ for (ig=0; ig < ng; ig++) jg[ig] = ig*mper;
+ jg[ng] = m;
+
+ ngm1 = ng - 1;
+ len1 = ngm1*mper;
+ for (j = 0; j < len1; j++) jig[j] = j/mper;
+ for (j = len1; j < m; j++) jig[j] = ngm1;
+
+ for (ig = 0; ig < ngm1; ig++) jr[ig] = ((2*ig+1)*mper-1)/2;
+ jr[ngm1] = (ngm1*mper+m-1)/2;
+}
+
+/* This routine computes and loads the vector of initial values. */
+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 = NV_DATA_S(c);
+ ns = wdata->ns;
+ mxns = wdata->mxns;
+ dx = wdata->dx;
+ dy = wdata->dy;
+
+ x_factor = RCONST(4.0)/SQR(AX);
+ y_factor = RCONST(4.0)/SQR(AY);
+ for (jy = 0; jy < MY; jy++) {
+ y = jy*dy;
+ argy = SQR(y_factor*y*(AY-y));
+ iyoff = mxns*jy;
+ for (jx = 0; jx < MX; jx++) {
+ x = jx*dx;
+ argx = SQR(x_factor*x*(AX-x));
+ ioff = iyoff + ns*jx;
+ for (i = 1; i <= ns; i++) {
+ ici = ioff + i-1;
+ cdata[ici] = RCONST(10.0) + i*argx*argy;
+ }
+ }
+ }
+}
+
+static void PrintIntro(void)
+{
+ printf("\n\nDemonstration program for CVODES - CVSPGMR 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)
+ printf("Matrix parameters: a = %.2Lg e = %.2Lg g = %.2Lg\n",
+ AA, EE, GG);
+ printf("b parameter = %.2Lg\n", BB);
+ printf("Diffusion coefficients: Dprey = %.2Lg Dpred = %.2Lg\n",
+ DPREY, DPRED);
+ printf("Rate parameter alpha = %.2Lg\n\n", ALPH);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("Matrix parameters: a = %.2lg e = %.2lg g = %.2lg\n",
+ AA, EE, GG);
+ printf("b parameter = %.2lg\n", BB);
+ printf("Diffusion coefficients: Dprey = %.2lg Dpred = %.2lg\n",
+ DPREY, DPRED);
+ printf("Rate parameter alpha = %.2lg\n\n", ALPH);
+#else
+ printf("Matrix parameters: a = %.2g e = %.2g g = %.2g\n",
+ AA, EE, GG);
+ printf("b parameter = %.2g\n", BB);
+ printf("Diffusion coefficients: Dprey = %.2g Dpred = %.2g\n",
+ DPREY, DPRED);
+ printf("Rate parameter alpha = %.2g\n\n", ALPH);
+#endif
+ printf("Mesh dimensions (mx,my) are %d, %d. ", MX, MY);
+ printf("Total system size is neq = %d \n\n", NEQ);
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("Tolerances: reltol = %.2Lg, abstol = %.2Lg \n\n",
+ RTOL, ATOL);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("Tolerances: reltol = %.2lg, abstol = %.2lg \n\n",
+ RTOL, ATOL);
+#else
+ printf("Tolerances: reltol = %.2g, abstol = %.2g \n\n",
+ RTOL, ATOL);
+#endif
+ printf("Preconditioning uses a product of:\n");
+ printf(" (1) Gauss-Seidel iterations with ");
+ printf("itmax = %d iterations, and\n", ITMAX);
+ printf(" (2) interaction-only block-diagonal matrix ");
+ printf("with block-grouping\n");
+ printf(" Number of diagonal block groups = ngrp = %d", NGRP);
+ printf(" (ngx by ngy, ngx = %d, ngy = %d)\n", NGX, NGY);
+ printf("\n\n--------------------------------------------------------------");
+ printf("--------------\n");
+}
+
+static void PrintHeader(int jpre, int gstype)
+{
+ if(jpre == PREC_LEFT)
+ printf("\n\nPreconditioner type is jpre = %s\n", "PREC_LEFT");
+ else
+ printf("\n\nPreconditioner type is jpre = %s\n", "PREC_RIGHT");
+
+ if(gstype == MODIFIED_GS)
+ printf("\nGram-Schmidt method type is gstype = %s\n\n\n", "MODIFIED_GS");
+ else
+ printf("\nGram-Schmidt method type is gstype = %s\n\n\n", "CLASSICAL_GS");
+}
+
+static void PrintAllSpecies(N_Vector c, int ns, int mxns, realtype t)
+{
+ int i, jx ,jy;
+ realtype *cdata;
+
+ cdata = NV_DATA_S(c);
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("c values at t = %Lg:\n\n", t);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("c values at t = %lg:\n\n", t);
+#else
+ printf("c values at t = %g:\n\n", t);
+#endif
+ for (i=1; i <= ns; i++) {
+ printf("Species %d\n", i);
+ for (jy=MY-1; jy >= 0; jy--) {
+ for (jx=0; jx < MX; jx++) {
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("%-10.6Lg", cdata[(i-1) + jx*ns + jy*mxns]);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("%-10.6lg", cdata[(i-1) + jx*ns + jy*mxns]);
+#else
+ printf("%-10.6g", cdata[(i-1) + jx*ns + jy*mxns]);
+#endif
+ }
+ printf("\n");
+ }
+ printf("\n");
+ }
+}
+
+static void PrintOutput(void *cvode_mem, realtype t)
+{
+ long int nst, nfe, nni;
+ int qu, flag;
+ realtype hu;
+
+ flag = CVodeGetNumSteps(cvode_mem, &nst);
+ check_flag(&flag, "CVodeGetNumSteps", 1);
+ flag = CVodeGetNumRhsEvals(cvode_mem, &nfe);
+ check_flag(&flag, "CVodeGetNumRhsEvals", 1);
+ flag = CVodeGetNumNonlinSolvIters(cvode_mem, &nni);
+ check_flag(&flag, "CVodeGetNumNonlinSolvIters", 1);
+ flag = CVodeGetLastOrder(cvode_mem, &qu);
+ check_flag(&flag, "CVodeGetLastOrder", 1);
+ flag = CVodeGetLastStep(cvode_mem, &hu);
+ check_flag(&flag, "CVodeGetLastStep", 1);
+
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("t = %10.2Le nst = %ld nfe = %ld nni = %ld", t, nst, nfe, nni);
+ printf(" qu = %d hu = %11.2Le\n\n", qu, hu);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("t = %10.2le nst = %ld nfe = %ld nni = %ld", t, nst, nfe, nni);
+ printf(" qu = %d hu = %11.2le\n\n", qu, hu);
+#else
+ printf("t = %10.2e nst = %ld nfe = %ld nni = %ld", t, nst, nfe, nni);
+ printf(" qu = %d hu = %11.2e\n\n", qu, hu);
+#endif
+}
+
+static void PrintFinalStats(void *cvode_mem)
+{
+ long int lenrw, leniw ;
+ long int lenrwLS, leniwLS;
+ long int nst, nfe, nsetups, nni, ncfn, netf;
+ long int nli, npe, nps, ncfl, nfeLS;
+ int flag;
+ realtype avdim;
+
+ 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("\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(" Number of steps = %4ld \n", nst);
+ printf(" Number of f-s = %4ld \n", nfe);
+ printf(" Number of f-s (SPGMR) = %4ld \n", nfeLS);
+ printf(" Number of f-s (TOTAL) = %4ld \n", nfe + nfeLS);
+ printf(" Number of setups = %4ld \n", nsetups);
+ printf(" Number of nonlinear iterations = %4ld \n", nni);
+ printf(" Number of linear iterations = %4ld \n", nli);
+ printf(" Number of preconditioner evaluations = %4ld \n", npe);
+ printf(" Number of preconditioner solves = %4ld \n", nps);
+ printf(" Number of error test failures = %4ld \n", netf);
+ printf(" Number of nonlinear conv. failures = %4ld \n", ncfn);
+ printf(" Number of linear convergence failures = %4ld \n", ncfl);
+ avdim = (nni > 0) ? ((realtype)nli)/((realtype)nni) : ZERO;
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf(" Average Krylov subspace dimension = %.3Lf \n", avdim);
+#else
+ printf(" Average Krylov subspace dimension = %.3f \n", avdim);
+#endif
+ printf("\n\n--------------------------------------------------------------");
+ printf("--------------\n");
+ printf( "--------------------------------------------------------------");
+ printf("--------------\n");
+}
+
+static void FreeUserData(WebData wdata)
+{
+ int i, ngrp;
+
+ ngrp = wdata->ngrp;
+ for(i=0; i < ngrp; i++) {
+ destroyMat((wdata->P)[i]);
+ destroyArray((wdata->pivot)[i]);
+ }
+ N_VDestroy_Serial(wdata->rewt);
+ free(wdata);
+}
+
+/*
+ This routine computes the right-hand side of the ODE system and
+ returns it in cdot. The interaction rates are computed by calls to WebRates,
+ and these are saved in fsave for use in preconditioning.
+*/
+static int f(realtype t, N_Vector c, N_Vector cdot,void *user_data)
+{
+ int i, ic, ici, idxl, idxu, jx, ns, mxns, iyoff, jy, idyu, idyl;
+ realtype dcxli, dcxui, dcyli, dcyui, x, y, *cox, *coy, *fsave, dx, dy;
+ realtype *cdata, *cdotdata;
+ WebData wdata;
+
+ wdata = (WebData) user_data;
+ cdata = NV_DATA_S(c);
+ cdotdata = NV_DATA_S(cdot);
+
+ mxns = wdata->mxns;
+ ns = wdata->ns;
+ fsave = wdata->fsave;
+ cox = wdata->cox;
+ coy = wdata->coy;
+ mxns = wdata->mxns;
+ dx = wdata->dx;
+ dy = wdata->dy;
+
+ for (jy = 0; jy < MY; jy++) {
+ y = jy*dy;
+ iyoff = mxns*jy;
+ idyu = (jy == MY-1) ? -mxns : mxns;
+ idyl = (jy == 0) ? -mxns : mxns;
+ for (jx = 0; jx < MX; jx++) {
+ x = jx*dx;
+ ic = iyoff + ns*jx;
+ /* Get interaction rates at one point (x,y). */
+ WebRates(x, y, t, cdata+ic, fsave+ic, wdata);
+ idxu = (jx == MX-1) ? -ns : ns;
+ idxl = (jx == 0) ? -ns : ns;
+ for (i = 1; i <= ns; i++) {
+ ici = ic + i-1;
+ /* Do differencing in y. */
+ dcyli = cdata[ici] - cdata[ici-idyl];
+ dcyui = cdata[ici+idyu] - cdata[ici];
+ /* Do differencing in x. */
+ dcxli = cdata[ici] - cdata[ici-idxl];
+ dcxui = cdata[ici+idxu] - cdata[ici];
+ /* Collect terms and load cdot elements. */
+ cdotdata[ici] = coy[i-1]*(dcyui - dcyli) + cox[i-1]*(dcxui - dcxli) +
+ fsave[ici];
+ }
+ }
+ }
+
+ return(0);
+}
+
+/*
+ This routine computes the interaction rates for the species
+ c_1, ... ,c_ns (stored in c[0],...,c[ns-1]), at one spatial point
+ and at time t.
+*/
+static void WebRates(realtype x, realtype y, realtype t, realtype c[],
+ realtype rate[], WebData wdata)
+{
+ int i, j, ns;
+ realtype fac, *bcoef;
+ realtype (*acoef)[NS];
+
+ ns = wdata->ns;
+ acoef = wdata->acoef;
+ bcoef = wdata->bcoef;
+
+ for (i = 0; i < ns; i++)
+ rate[i] = ZERO;
+
+ for (j = 0; j < ns; j++)
+ for (i = 0; i < ns; i++)
+ rate[i] += c[j] * acoef[i][j];
+
+ fac = ONE + ALPH*x*y;
+ for (i = 0; i < ns; i++)
+ rate[i] = c[i]*(bcoef[i]*fac + rate[i]);
+}
+
+/*
+ This routine generates the block-diagonal part of the Jacobian
+ corresponding to the interaction rates, multiplies by -gamma, adds
+ the identity matrix, and calls denseGETRF to do the LU decomposition of
+ each diagonal block. The computation of the diagonal blocks uses
+ the preset block and grouping information. One block per group is
+ computed. The Jacobian elements are generated by difference
+ quotients using calls to the routine fblock.
+
+ This routine can be regarded as a prototype for the general case
+ 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)
+{
+ realtype ***P;
+ long int **pivot, ier;
+ int i, if0, if00, ig, igx, igy, j, jj, jx, jy;
+ int *jxr, *jyr, ngrp, ngx, ngy, mxmp, flag;
+ long int mp;
+ realtype uround, fac, r, r0, save, srur;
+ realtype *f1, *fsave, *cdata, *rewtdata;
+ WebData wdata;
+ void *cvode_mem;
+ N_Vector rewt;
+
+ wdata = (WebData) user_data;
+ cvode_mem = wdata->cvode_mem;
+ cdata = NV_DATA_S(c);
+ rewt = wdata->rewt;
+ flag = CVodeGetErrWeights(cvode_mem, rewt);
+ if(check_flag(&flag, "CVodeGetErrWeights", 1)) return(1);
+ rewtdata = NV_DATA_S(rewt);
+
+ uround = UNIT_ROUNDOFF;
+
+ P = wdata->P;
+ pivot = wdata->pivot;
+ jxr = wdata->jxr;
+ jyr = wdata->jyr;
+ mp = wdata->mp;
+ srur = wdata->srur;
+ ngrp = wdata->ngrp;
+ ngx = wdata->ngx;
+ ngy = wdata->ngy;
+ mxmp = wdata->mxmp;
+ fsave = wdata->fsave;
+
+ /* Make mp calls to fblock to approximate each diagonal block of Jacobian.
+ Here, fsave contains the base value of the rate vector and
+ r0 is a minimum increment factor for the difference quotient. */
+
+ f1 = NV_DATA_S(vtemp1);
+
+ fac = N_VWrmsNorm (fc, rewt);
+ r0 = RCONST(1000.0)*ABS(gamma)*uround*NEQ*fac;
+ if (r0 == ZERO) r0 = ONE;
+
+ for (igy = 0; igy < ngy; igy++) {
+ jy = jyr[igy];
+ if00 = jy*mxmp;
+ for (igx = 0; igx < ngx; igx++) {
+ jx = jxr[igx];
+ if0 = if00 + jx*mp;
+ ig = igx + igy*ngx;
+ /* Generate ig-th diagonal block */
+ for (j = 0; j < mp; j++) {
+ /* Generate the jth column as a difference quotient */
+ jj = if0 + j;
+ save = cdata[jj];
+ r = MAX(srur*ABS(save),r0/rewtdata[jj]);
+ cdata[jj] += r;
+ fac = -gamma/r;
+ fblock (t, cdata, jx, jy, f1, wdata);
+ for (i = 0; i < mp; i++) {
+ P[ig][j][i] = (f1[i] - fsave[if0+i])*fac;
+ }
+ cdata[jj] = save;
+ }
+ }
+ }
+
+ /* Add identity matrix and do LU decompositions on blocks. */
+
+ for (ig = 0; ig < ngrp; ig++) {
+ denseAddIdentity(P[ig], mp);
+ ier = denseGETRF(P[ig], mp, mp, pivot[ig]);
+ if (ier != 0) return(1);
+ }
+
+ *jcurPtr = TRUE;
+ return(0);
+}
+
+/*
+ This routine computes one block of the interaction terms of the
+ system, namely block (jx,jy), for use in preconditioning.
+ Here jx and jy count from 0.
+*/
+static void fblock(realtype t, realtype cdata[], int jx, int jy,
+ realtype cdotdata[], WebData wdata)
+{
+ int iblok, ic;
+ realtype x, y;
+
+ iblok = jx + jy*(wdata->mx);
+ y = jy*(wdata->dy);
+ x = jx*(wdata->dx);
+ ic = (wdata->ns)*(iblok);
+ WebRates(x, y, t, cdata+ic, cdotdata, wdata);
+}
+
+/*
+ This routine applies two inverse preconditioner matrices
+ to the vector r, using the interaction-only block-diagonal Jacobian
+ with block-grouping, denoted Jr, and Gauss-Seidel applied to the
+ diffusion contribution to the Jacobian, denoted Jd.
+ It first calls GSIter for a Gauss-Seidel approximation to
+ ((I - gamma*Jd)-inverse)*r, and stores the result in z.
+ 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)
+{
+ realtype ***P;
+ long int **pivot;
+ int jx, jy, igx, igy, iv, ig, *jigx, *jigy, mx, my, ngx;
+ long int mp;
+ WebData wdata;
+
+ wdata = (WebData) user_data;
+
+ N_VScale(ONE, r, z);
+
+ /* call GSIter for Gauss-Seidel iterations */
+
+ GSIter(gamma, z, vtemp, wdata);
+
+ /* Do backsolves for inverse of block-diagonal preconditioner factor */
+
+ P = wdata->P;
+ pivot = wdata->pivot;
+ mx = wdata->mx;
+ my = wdata->my;
+ ngx = wdata->ngx;
+ mp = wdata->mp;
+ jigx = wdata->jigx;
+ jigy = wdata->jigy;
+
+ iv = 0;
+ for (jy = 0; jy < my; jy++) {
+ igy = jigy[jy];
+ for (jx = 0; jx < mx; jx++) {
+ igx = jigx[jx];
+ ig = igx + igy*ngx;
+ denseGETRS(P[ig], mp, pivot[ig], &(NV_DATA_S(z)[iv]));
+ iv += mp;
+ }
+ }
+
+ return(0);
+}
+
+/*
+ This routine performs ITMAX=5 Gauss-Seidel iterations to compute an
+ approximation to (P-inverse)*z, where P = I - gamma*Jd, and
+ Jd represents the diffusion contributions to the Jacobian.
+ The answer is stored in z on return, and x is a temporary vector.
+ The dimensions below assume a global constant NS >= ns.
+ Some inner loops of length ns are implemented with the small
+ vector kernels v_sum_prods, v_prod, v_inc_by_prod.
+*/
+static void GSIter(realtype gamma, N_Vector z, N_Vector x, WebData wdata)
+{
+ int jx, jy, mx, my, x_loc, y_loc;
+ int ns, mxns, i, iyoff, ic, iter;
+ realtype beta[NS], beta2[NS], cof1[NS], gam[NS], gam2[NS];
+ realtype temp, *cox, *coy, *xd, *zd;
+
+ xd = NV_DATA_S(x);
+ zd = NV_DATA_S(z);
+ ns = wdata->ns;
+ mx = wdata->mx;
+ my = wdata->my;
+ mxns = wdata->mxns;
+ cox = wdata->cox;
+ coy = wdata->coy;
+
+ /* Write matrix as P = D - L - U.
+ Load local arrays beta, beta2, gam, gam2, and cof1. */
+
+ for (i = 0; i < ns; i++) {
+ temp = ONE/(ONE + RCONST(2.0)*gamma*(cox[i] + coy[i]));
+ beta[i] = gamma*cox[i]*temp;
+ beta2[i] = RCONST(2.0)*beta[i];
+ gam[i] = gamma*coy[i]*temp;
+ gam2[i] = RCONST(2.0)*gam[i];
+ cof1[i] = temp;
+ }
+
+ /* Begin iteration loop.
+ Load vector x with (D-inverse)*z for first iteration. */
+
+ for (jy = 0; jy < my; jy++) {
+ iyoff = mxns*jy;
+ for (jx = 0; jx < mx; jx++) {
+ ic = iyoff + ns*jx;
+ v_prod(xd+ic, cof1, zd+ic, ns); /* x[ic+i] = cof1[i]z[ic+i] */
+ }
+ }
+ N_VConst(ZERO, z);
+
+ /* Looping point for iterations. */
+
+ for (iter=1; iter <= ITMAX; iter++) {
+
+ /* Calculate (D-inverse)*U*x if not the first iteration. */
+
+ if (iter > 1) {
+ for (jy=0; jy < my; jy++) {
+ iyoff = mxns*jy;
+ for (jx=0; jx < mx; jx++) { /* order of loops matters */
+ ic = iyoff + ns*jx;
+ x_loc = (jx == 0) ? 0 : ((jx == mx-1) ? 2 : 1);
+ y_loc = (jy == 0) ? 0 : ((jy == my-1) ? 2 : 1);
+ switch (3*y_loc+x_loc) {
+ case 0 :
+ /* jx == 0, jy == 0 */
+ /* x[ic+i] = beta2[i]x[ic+ns+i] + gam2[i]x[ic+mxns+i] */
+ v_sum_prods(xd+ic, beta2, xd+ic+ns, gam2, xd+ic+mxns, ns);
+ break;
+ case 1 :
+ /* 1 <= jx <= mx-2, jy == 0 */
+ /* x[ic+i] = beta[i]x[ic+ns+i] + gam2[i]x[ic+mxns+i] */
+ v_sum_prods(xd+ic, beta, xd+ic+ns, gam2, xd+ic+mxns, ns);
+ break;
+ case 2 :
+ /* jx == mx-1, jy == 0 */
+ /* x[ic+i] = gam2[i]x[ic+mxns+i] */
+ v_prod(xd+ic, gam2, xd+ic+mxns, ns);
+ break;
+ case 3 :
+ /* jx == 0, 1 <= jy <= my-2 */
+ /* x[ic+i] = beta2[i]x[ic+ns+i] + gam[i]x[ic+mxns+i] */
+ v_sum_prods(xd+ic, beta2, xd+ic+ns, gam, xd+ic+mxns, ns);
+ break;
+ case 4 :
+ /* 1 <= jx <= mx-2, 1 <= jy <= my-2 */
+ /* x[ic+i] = beta[i]x[ic+ns+i] + gam[i]x[ic+mxns+i] */
+ v_sum_prods(xd+ic, beta, xd+ic+ns, gam, xd+ic+mxns, ns);
+ break;
+ case 5 :
+ /* jx == mx-1, 1 <= jy <= my-2 */
+ /* x[ic+i] = gam[i]x[ic+mxns+i] */
+ v_prod(xd+ic, gam, xd+ic+mxns, ns);
+ break;
+ case 6 :
+ /* jx == 0, jy == my-1 */
+ /* x[ic+i] = beta2[i]x[ic+ns+i] */
+ v_prod(xd+ic, beta2, xd+ic+ns, ns);
+ break;
+ case 7 :
+ /* 1 <= jx <= mx-2, jy == my-1 */
+ /* x[ic+i] = beta[i]x[ic+ns+i] */
+ v_prod(xd+ic, beta, xd+ic+ns, ns);
+ break;
+ case 8 :
+ /* jx == mx-1, jy == my-1 */
+ /* x[ic+i] = 0.0 */
+ v_zero(xd+ic, ns);
+ break;
+ }
+ }
+ }
+ } /* end if (iter > 1) */
+
+ /* Overwrite x with [(I - (D-inverse)*L)-inverse]*x. */
+
+ for (jy=0; jy < my; jy++) {
+ iyoff = mxns*jy;
+ for (jx=0; jx < mx; jx++) { /* order of loops matters */
+ ic = iyoff + ns*jx;
+ x_loc = (jx == 0) ? 0 : ((jx == mx-1) ? 2 : 1);
+ y_loc = (jy == 0) ? 0 : ((jy == my-1) ? 2 : 1);
+ switch (3*y_loc+x_loc) {
+ case 0 :
+ /* jx == 0, jy == 0 */
+ break;
+ case 1 :
+ /* 1 <= jx <= mx-2, jy == 0 */
+ /* x[ic+i] += beta[i]x[ic-ns+i] */
+ v_inc_by_prod(xd+ic, beta, xd+ic-ns, ns);
+ break;
+ case 2 :
+ /* jx == mx-1, jy == 0 */
+ /* x[ic+i] += beta2[i]x[ic-ns+i] */
+ v_inc_by_prod(xd+ic, beta2, xd+ic-ns, ns);
+ break;
+ case 3 :
+ /* jx == 0, 1 <= jy <= my-2 */
+ /* x[ic+i] += gam[i]x[ic-mxns+i] */
+ v_inc_by_prod(xd+ic, gam, xd+ic-mxns, ns);
+ break;
+ case 4 :
+ /* 1 <= jx <= mx-2, 1 <= jy <= my-2 */
+ /* x[ic+i] += beta[i]x[ic-ns+i] + gam[i]x[ic-mxns+i] */
+ v_inc_by_prod(xd+ic, beta, xd+ic-ns, ns);
+ v_inc_by_prod(xd+ic, gam, xd+ic-mxns, ns);
+ break;
+ case 5 :
+ /* jx == mx-1, 1 <= jy <= my-2 */
+ /* x[ic+i] += beta2[i]x[ic-ns+i] + gam[i]x[ic-mxns+i] */
+ v_inc_by_prod(xd+ic, beta2, xd+ic-ns, ns);
+ v_inc_by_prod(xd+ic, gam, xd+ic-mxns, ns);
+ break;
+ case 6 :
+ /* jx == 0, jy == my-1 */
+ /* x[ic+i] += gam2[i]x[ic-mxns+i] */
+ v_inc_by_prod(xd+ic, gam2, xd+ic-mxns, ns);
+ break;
+ case 7 :
+ /* 1 <= jx <= mx-2, jy == my-1 */
+ /* x[ic+i] += beta[i]x[ic-ns+i] + gam2[i]x[ic-mxns+i] */
+ v_inc_by_prod(xd+ic, beta, xd+ic-ns, ns);
+ v_inc_by_prod(xd+ic, gam2, xd+ic-mxns, ns);
+ break;
+ case 8 :
+ /* jx == mx-1, jy == my-1 */
+ /* x[ic+i] += beta2[i]x[ic-ns+i] + gam2[i]x[ic-mxns+i] */
+ v_inc_by_prod(xd+ic, beta2, xd+ic-ns, ns);
+ v_inc_by_prod(xd+ic, gam2, xd+ic-mxns, ns);
+ break;
+ }
+ }
+ }
+
+ /* Add increment x to z : z <- z+x */
+
+ N_VLinearSum(ONE, z, ONE, x, z);
+
+ }
+}
+
+static void v_inc_by_prod(realtype u[], realtype v[], realtype w[], int n)
+{
+ int i;
+ for (i=0; i < n; i++) u[i] += v[i]*w[i];
+}
+
+static void v_sum_prods(realtype u[], realtype p[], realtype q[],
+ realtype v[], realtype w[], int n)
+{
+ int i;
+ for (i=0; i < n; i++) u[i] = p[i]*q[i] + v[i]*w[i];
+}
+
+static void v_prod(realtype u[], realtype v[], realtype w[], int n)
+{
+ int i;
+ for (i=0; i < n; i++) u[i] = v[i]*w[i];
+}
+
+static void v_zero(realtype u[], int n)
+{
+ int i;
+ for (i=0; i < n; i++) u[i] = ZERO;
+}
+
+/* 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, 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_prec.out b/examples/cvodes/serial/cvsKrylovDemo_prec.out
new file mode 100644
index 0000000..eee5b2b
--- /dev/null
+++ b/examples/cvodes/serial/cvsKrylovDemo_prec.out
@@ -0,0 +1,645 @@
+
+
+Demonstration program for CVODES - CVSPGMR linear solver
+
+Food web problem with ns species, ns = 6
+Predator-prey interaction and diffusion on a 2-D square
+
+Matrix parameters: a = 1 e = 1e+04 g = 5e-07
+b parameter = 1
+Diffusion coefficients: Dprey = 1 Dpred = 0.5
+Rate parameter alpha = 1
+
+Mesh dimensions (mx,my) are 6, 6. Total system size is neq = 216
+
+Tolerances: reltol = 1e-05, abstol = 1e-05
+
+Preconditioning uses a product of:
+ (1) Gauss-Seidel iterations with itmax = 5 iterations, and
+ (2) interaction-only block-diagonal matrix with block-grouping
+ Number of diagonal block groups = ngrp = 4 (ngx by ngy, ngx = 2, ngy = 2)
+
+
+----------------------------------------------------------------------------
+
+
+Preconditioner type is jpre = PREC_LEFT
+
+Gram-Schmidt method type is gstype = MODIFIED_GS
+
+
+c values at t = 0:
+
+Species 1
+10 10 10 10 10 10
+10 10.1678 10.3775 10.3775 10.1678 10
+10 10.3775 10.8493 10.8493 10.3775 10
+10 10.3775 10.8493 10.8493 10.3775 10
+10 10.1678 10.3775 10.3775 10.1678 10
+10 10 10 10 10 10
+
+Species 2
+10 10 10 10 10 10
+10 10.3355 10.755 10.755 10.3355 10
+10 10.755 11.6987 11.6987 10.755 10
+10 10.755 11.6987 11.6987 10.755 10
+10 10.3355 10.755 10.755 10.3355 10
+10 10 10 10 10 10
+
+Species 3
+10 10 10 10 10 10
+10 10.5033 11.1325 11.1325 10.5033 10
+10 11.1325 12.548 12.548 11.1325 10
+10 11.1325 12.548 12.548 11.1325 10
+10 10.5033 11.1325 11.1325 10.5033 10
+10 10 10 10 10 10
+
+Species 4
+10 10 10 10 10 10
+10 10.6711 11.5099 11.5099 10.6711 10
+10 11.5099 13.3974 13.3974 11.5099 10
+10 11.5099 13.3974 13.3974 11.5099 10
+10 10.6711 11.5099 11.5099 10.6711 10
+10 10 10 10 10 10
+
+Species 5
+10 10 10 10 10 10
+10 10.8389 11.8874 11.8874 10.8389 10
+10 11.8874 14.2467 14.2467 11.8874 10
+10 11.8874 14.2467 14.2467 11.8874 10
+10 10.8389 11.8874 11.8874 10.8389 10
+10 10 10 10 10 10
+
+Species 6
+10 10 10 10 10 10
+10 11.0066 12.2649 12.2649 11.0066 10
+10 12.2649 15.0961 15.0961 12.2649 10
+10 12.2649 15.0961 15.0961 12.2649 10
+10 11.0066 12.2649 12.2649 11.0066 10
+10 10 10 10 10 10
+
+t = 1.00e-08 nst = 3 nfe = 10 nni = 6 qu = 2 hu = 1.76e-08
+
+t = 1.00e-07 nst = 7 nfe = 14 nni = 10 qu = 2 hu = 4.78e-08
+
+t = 1.00e-06 nst = 15 nfe = 24 nni = 20 qu = 3 hu = 1.50e-07
+
+c values at t = 1e-06:
+
+Species 1
+9.99991 9.99992 9.99993 9.99993 9.99993 9.99992
+9.99992 10.1677 10.3774 10.3774 10.1677 9.99993
+9.99993 10.3774 10.8492 10.8492 10.3774 9.99993
+9.99993 10.3774 10.8492 10.8492 10.3774 9.99993
+9.99992 10.1677 10.3774 10.3774 10.1677 9.99992
+9.99991 9.99992 9.99993 9.99993 9.99992 9.99991
+
+Species 2
+9.99991 9.99993 9.99995 9.99995 9.99993 9.99992
+9.99993 10.3355 10.7549 10.7549 10.3355 9.99993
+9.99995 10.7549 11.6985 11.6985 10.7549 9.99995
+9.99995 10.7549 11.6985 11.6985 10.7549 9.99995
+9.99993 10.3355 10.7549 10.7549 10.3355 9.99993
+9.99991 9.99993 9.99995 9.99995 9.99993 9.99991
+
+Species 3
+9.99991 9.99994 9.99997 9.99997 9.99994 9.99992
+9.99994 10.5032 11.1323 11.1323 10.5032 9.99994
+9.99997 11.1323 12.5478 12.5478 11.1323 9.99997
+9.99997 11.1323 12.5478 12.5478 11.1323 9.99997
+9.99994 10.5032 11.1323 11.1323 10.5032 9.99994
+9.99991 9.99994 9.99997 9.99997 9.99994 9.99991
+
+Species 4
+13.499 13.499 13.499 13.499 13.499 13.4989
+13.499 14.5506 15.8932 15.8932 14.5506 13.499
+13.499 15.8932 19.0308 19.0308 15.8932 13.499
+13.499 15.8932 19.0308 19.0308 15.8932 13.499
+13.499 14.5506 15.8932 15.8932 14.5506 13.499
+13.499 13.499 13.499 13.499 13.499 13.499
+
+Species 5
+13.499 13.499 13.499 13.499 13.499 13.4989
+13.499 14.7794 16.4145 16.4145 14.7794 13.499
+13.499 16.4145 20.2373 20.2373 16.4145 13.499
+13.499 16.4145 20.2373 20.2373 16.4145 13.499
+13.499 14.7794 16.4145 16.4145 14.7794 13.499
+13.499 13.499 13.499 13.499 13.499 13.499
+
+Species 6
+13.499 13.499 13.499 13.499 13.499 13.4989
+13.499 15.0082 16.9357 16.9357 15.0082 13.499
+13.499 16.9357 21.4437 21.4437 16.9357 13.499
+13.499 16.9357 21.4437 21.4437 16.9357 13.499
+13.499 15.0082 16.9357 16.9357 15.0082 13.499
+13.499 13.499 13.499 13.499 13.499 13.499
+
+t = 1.00e-05 nst = 34 nfe = 47 nni = 43 qu = 5 hu = 6.11e-07
+
+t = 1.00e-04 nst = 116 nfe = 137 nni = 133 qu = 5 hu = 5.51e-06
+
+t = 1.00e-03 nst = 135 nfe = 156 nni = 152 qu = 2 hu = 3.53e-04
+
+c values at t = 0.001:
+
+Species 1
+9.90702 9.91664 9.92836 9.93033 9.92253 9.91674
+9.91472 10.0746 10.2769 10.2785 10.0795 9.92253
+9.92446 10.2748 10.7181 10.7194 10.2785 9.93033
+9.92445 10.2744 10.7173 10.7181 10.2769 9.92836
+9.91469 10.0734 10.2744 10.2748 10.0746 9.91664
+9.90697 9.91469 9.92445 9.92446 9.91472 9.90702
+
+Species 2
+9.90741 9.92474 9.94623 9.9482 9.93064 9.91713
+9.92282 10.2412 10.644 10.6457 10.2461 9.93064
+9.94232 10.6419 11.5267 11.5281 10.6457 9.9482
+9.94231 10.6415 11.5258 11.5267 10.644 9.94623
+9.92279 10.24 10.6415 10.6419 10.2412 9.92474
+9.90737 9.92279 9.94231 9.94232 9.92282 9.90741
+
+Species 3
+9.90781 9.93284 9.96408 9.96606 9.93874 9.91752
+9.93092 10.4078 11.0109 11.0127 10.4127 9.93874
+9.96017 11.0088 12.3339 12.3354 11.0127 9.96606
+9.96016 11.0083 12.3329 12.3339 11.0109 9.96408
+9.93089 10.4065 11.0083 11.0088 10.4078 9.93284
+9.90776 9.93089 9.96016 9.96017 9.93092 9.90781
+
+Species 4
+297231 297749 298393 298451 297925 297520
+297692 307244 319327 319378 307390 297925
+298276 319264 345799 345840 319378 298451
+298276 319252 345771 345799 319327 298393
+297691 307208 319252 319264 307244 297749
+297229 297691 298276 298276 297692 297231
+
+Species 5
+297231 297749 298393 298451 297925 297520
+297692 307244 319327 319378 307390 297925
+298276 319264 345799 345840 319378 298451
+298276 319252 345771 345799 319327 298393
+297691 307208 319252 319264 307244 297749
+297229 297691 298276 298276 297692 297231
+
+Species 6
+297231 297749 298393 298451 297925 297520
+297692 307244 319327 319378 307390 297925
+298276 319264 345799 345840 319378 298451
+298276 319252 345771 345799 319327 298393
+297691 307208 319252 319264 307244 297749
+297229 297691 298276 298276 297692 297231
+
+t = 1.00e-02 nst = 143 nfe = 166 nni = 162 qu = 3 hu = 1.37e-03
+
+t = 1.00e-01 nst = 165 nfe = 191 nni = 187 qu = 5 hu = 6.02e-03
+
+t = 1.00e+00 nst = 235 nfe = 265 nni = 261 qu = 4 hu = 2.49e-02
+
+c values at t = 1:
+
+Species 1
+1.58853 1.59926 1.62153 1.64766 1.67038 1.68151
+1.58535 1.59505 1.61549 1.63954 1.66035 1.67038
+1.57758 1.58549 1.60241 1.62237 1.63954 1.64766
+1.56822 1.57414 1.58708 1.60241 1.61549 1.62153
+1.5605 1.56465 1.57414 1.58549 1.59505 1.59926
+1.55734 1.5605 1.56822 1.57758 1.58535 1.58853
+
+Species 2
+1.59068 1.60143 1.62373 1.64989 1.67263 1.68377
+1.5875 1.59721 1.61768 1.64175 1.66259 1.67263
+1.57973 1.58764 1.60458 1.62456 1.64175 1.64989
+1.57036 1.57628 1.58923 1.60458 1.61768 1.62373
+1.56263 1.56678 1.57628 1.58764 1.59721 1.60143
+1.55947 1.56263 1.57036 1.57973 1.5875 1.59068
+
+Species 3
+1.59272 1.60347 1.6258 1.65199 1.67476 1.68591
+1.58953 1.59926 1.61975 1.64384 1.6647 1.67476
+1.58175 1.58968 1.60664 1.62664 1.64384 1.65199
+1.57237 1.5783 1.59127 1.60664 1.61975 1.6258
+1.56464 1.56879 1.5783 1.58968 1.59926 1.60347
+1.56147 1.56464 1.57237 1.58175 1.58953 1.59272
+
+Species 4
+47718.9 48040.8 48709.6 49494 50176.1 50509.9
+47623.3 47914.5 48528.3 49250.2 49874.9 50176.1
+47390.2 47627.5 48135.5 48734.6 49250.2 49494
+47109 47286.6 47675.1 48135.5 48528.3 48709.6
+46877.1 47001.6 47286.6 47627.5 47914.5 48040.8
+46782.3 46877.1 47109 47390.2 47623.3 47718.9
+
+Species 5
+47718.9 48040.8 48709.6 49494 50176.1 50509.9
+47623.3 47914.5 48528.3 49250.2 49874.9 50176.1
+47390.2 47627.5 48135.5 48734.6 49250.2 49494
+47109 47286.6 47675.1 48135.5 48528.3 48709.6
+46877.1 47001.6 47286.6 47627.5 47914.5 48040.8
+46782.3 46877.1 47109 47390.2 47623.3 47718.9
+
+Species 6
+47718.9 48040.8 48709.6 49494 50176.1 50509.9
+47623.3 47914.5 48528.3 49250.2 49874.9 50176.1
+47390.2 47627.5 48135.5 48734.6 49250.2 49494
+47109 47286.6 47675.1 48135.5 48528.3 48709.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 = 3.00e+00 nst = 288 nfe = 322 nni = 318 qu = 3 hu = 6.59e-02
+
+t = 4.00e+00 nst = 303 nfe = 337 nni = 333 qu = 3 hu = 6.59e-02
+
+c values at t = 4:
+
+Species 1
+1.19535 1.20368 1.2211 1.24158 1.25935 1.268
+1.19281 1.20035 1.21636 1.23523 1.25154 1.25935
+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.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
+1.19284 1.20039 1.2164 1.23527 1.25158 1.25939
+1.18661 1.19277 1.20606 1.22177 1.23527 1.24161
+1.17908 1.18372 1.19393 1.20606 1.2164 1.22113
+1.17288 1.17616 1.18372 1.19277 1.20039 1.20372
+1.17036 1.17288 1.17908 1.18661 1.19284 1.19539
+
+Species 3
+1.19542 1.20375 1.22117 1.24164 1.25942 1.26807
+1.19287 1.20042 1.21643 1.2353 1.25161 1.25942
+1.18664 1.1928 1.20609 1.2218 1.2353 1.24164
+1.17911 1.18375 1.19396 1.20609 1.21643 1.22117
+1.17291 1.17619 1.18375 1.1928 1.20042 1.20375
+1.17039 1.17291 1.17911 1.18664 1.19287 1.19542
+
+Species 4
+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.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.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 = 313 nfe = 349 nni = 345 qu = 3 hu = 1.26e-01
+
+t = 6.00e+00 nst = 321 nfe = 357 nni = 353 qu = 3 hu = 1.26e-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 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.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.18593 1.19351 1.19683
+1.16363 1.16614 1.17231 1.1798 1.186 1.18854
+
+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
+35393.1 35577 35973.5 36442.2 36844.9 37034.1
+35168.3 35306.6 35611.4 35973.5 36281.8 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.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.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 = 337 nfe = 374 nni = 370 qu = 3 hu = 1.26e-01
+
+t = 9.00e+00 nst = 345 nfe = 382 nni = 378 qu = 3 hu = 1.26e-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.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.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.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.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.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.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
+35650.5 35898.8 36418.4 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
+
+Species 5
+35650.5 35898.8 36418.4 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
+
+Species 6
+35650.5 35898.8 36418.4 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
+
+
+
+ Final statistics for this run:
+
+ CVode real workspace length = 2256
+ CVode integer workspace length = 62
+ CVSPGMR real workspace length = 2206
+ CVSPGMR integer workspace length = 10
+ Number of steps = 353
+ Number of f-s = 391
+ Number of f-s (SPGMR) = 585
+ Number of f-s (TOTAL) = 976
+ Number of setups = 43
+ Number of nonlinear iterations = 387
+ Number of linear iterations = 585
+ Number of preconditioner evaluations = 43
+ Number of preconditioner solves = 956
+ Number of error test failures = 1
+ Number of nonlinear conv. failures = 0
+ Number of linear convergence failures = 0
+ Average Krylov subspace dimension = 1.512
+
+
+----------------------------------------------------------------------------
+----------------------------------------------------------------------------
+
+
+Preconditioner type is jpre = PREC_LEFT
+
+Gram-Schmidt method type is gstype = CLASSICAL_GS
+
+
+t = 1.00e-08 nst = 3 nfe = 10 nni = 6 qu = 2 hu = 1.76e-08
+
+t = 1.00e-07 nst = 7 nfe = 14 nni = 10 qu = 2 hu = 4.78e-08
+
+t = 1.00e-06 nst = 15 nfe = 24 nni = 20 qu = 3 hu = 1.50e-07
+
+t = 1.00e-05 nst = 34 nfe = 47 nni = 43 qu = 5 hu = 6.11e-07
+
+t = 1.00e-04 nst = 116 nfe = 137 nni = 133 qu = 5 hu = 5.51e-06
+
+t = 1.00e-03 nst = 135 nfe = 156 nni = 152 qu = 2 hu = 3.53e-04
+
+t = 1.00e-02 nst = 143 nfe = 166 nni = 162 qu = 3 hu = 1.37e-03
+
+t = 1.00e-01 nst = 165 nfe = 191 nni = 187 qu = 5 hu = 6.02e-03
+
+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.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 = 6.00e+00 nst = 323 nfe = 359 nni = 355 qu = 3 hu = 1.94e-01
+
+t = 7.00e+00 nst = 326 nfe = 364 nni = 360 qu = 3 hu = 4.05e-01
+
+t = 8.00e+00 nst = 328 nfe = 366 nni = 362 qu = 3 hu = 4.05e-01
+
+t = 9.00e+00 nst = 331 nfe = 369 nni = 365 qu = 3 hu = 4.05e-01
+
+t = 1.00e+01 nst = 333 nfe = 371 nni = 367 qu = 3 hu = 4.05e-01
+
+
+
+ Final statistics for this run:
+
+ 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
+ Number of error test failures = 1
+ Number of nonlinear conv. failures = 0
+ Number of linear convergence failures = 4
+ Average Krylov subspace dimension = 1.455
+
+
+----------------------------------------------------------------------------
+----------------------------------------------------------------------------
+
+
+Preconditioner type is jpre = PREC_RIGHT
+
+Gram-Schmidt method type is gstype = MODIFIED_GS
+
+
+t = 1.00e-08 nst = 3 nfe = 10 nni = 6 qu = 2 hu = 1.76e-08
+
+t = 1.00e-07 nst = 7 nfe = 14 nni = 10 qu = 2 hu = 4.78e-08
+
+t = 1.00e-06 nst = 15 nfe = 24 nni = 20 qu = 3 hu = 1.50e-07
+
+t = 1.00e-05 nst = 34 nfe = 47 nni = 43 qu = 5 hu = 6.11e-07
+
+t = 1.00e-04 nst = 118 nfe = 138 nni = 134 qu = 5 hu = 6.64e-06
+
+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+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 = 3.00e+00 nst = 226 nfe = 270 nni = 266 qu = 5 hu = 1.36e-01
+
+t = 4.00e+00 nst = 233 nfe = 277 nni = 273 qu = 5 hu = 1.36e-01
+
+t = 5.00e+00 nst = 241 nfe = 285 nni = 281 qu = 5 hu = 1.36e-01
+
+t = 6.00e+00 nst = 248 nfe = 292 nni = 288 qu = 5 hu = 1.36e-01
+
+t = 7.00e+00 nst = 255 nfe = 299 nni = 295 qu = 5 hu = 1.36e-01
+
+t = 8.00e+00 nst = 260 nfe = 305 nni = 301 qu = 5 hu = 2.06e-01
+
+t = 9.00e+00 nst = 270 nfe = 319 nni = 315 qu = 5 hu = 5.14e-02
+
+t = 1.00e+01 nst = 278 nfe = 328 nni = 324 qu = 3 hu = 3.01e-01
+
+
+
+ Final statistics for this run:
+
+ 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
+ Number of error test failures = 3
+ Number of nonlinear conv. failures = 1
+ Number of linear convergence failures = 55
+ Average Krylov subspace dimension = 2.056
+
+
+----------------------------------------------------------------------------
+----------------------------------------------------------------------------
+
+
+Preconditioner type is jpre = PREC_RIGHT
+
+Gram-Schmidt method type is gstype = CLASSICAL_GS
+
+
+t = 1.00e-08 nst = 3 nfe = 10 nni = 6 qu = 2 hu = 1.76e-08
+
+t = 1.00e-07 nst = 7 nfe = 14 nni = 10 qu = 2 hu = 4.78e-08
+
+t = 1.00e-06 nst = 15 nfe = 24 nni = 20 qu = 3 hu = 1.50e-07
+
+t = 1.00e-05 nst = 34 nfe = 47 nni = 43 qu = 5 hu = 6.11e-07
+
+t = 1.00e-04 nst = 118 nfe = 138 nni = 134 qu = 5 hu = 6.64e-06
+
+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+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 = 3.00e+00 nst = 227 nfe = 271 nni = 267 qu = 5 hu = 1.21e-01
+
+t = 4.00e+00 nst = 233 nfe = 278 nni = 274 qu = 5 hu = 1.85e-01
+
+t = 5.00e+00 nst = 238 nfe = 283 nni = 279 qu = 5 hu = 1.85e-01
+
+t = 6.00e+00 nst = 248 nfe = 298 nni = 294 qu = 5 hu = 7.06e-02
+
+t = 7.00e+00 nst = 255 nfe = 305 nni = 301 qu = 4 hu = 2.07e-01
+
+t = 8.00e+00 nst = 258 nfe = 308 nni = 304 qu = 3 hu = 3.42e-01
+
+t = 9.00e+00 nst = 261 nfe = 311 nni = 307 qu = 3 hu = 3.42e-01
+
+t = 1.00e+01 nst = 263 nfe = 313 nni = 309 qu = 3 hu = 5.33e-01
+
+
+
+ Final statistics for this run:
+
+ 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
+ Number of error test failures = 3
+ Number of nonlinear conv. failures = 1
+ Number of linear convergence failures = 42
+ Average Krylov subspace dimension = 1.922
+
+
+----------------------------------------------------------------------------
+----------------------------------------------------------------------------
diff --git a/examples/cvodes/serial/cvsRoberts_ASAi_dns.c b/examples/cvodes/serial/cvsRoberts_ASAi_dns.c
new file mode 100644
index 0000000..2fd7888
--- /dev/null
+++ b/examples/cvodes/serial/cvsRoberts_ASAi_dns.c
@@ -0,0 +1,655 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.4 $
+ * $Date: 2011/11/23 23:53:02 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * 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.
+ * dy1/dt = -p1*y1 + p2*y2*y3
+ * dy2/dt = p1*y1 - p2*y2*y3 - p3*(y2)^2
+ * dy3/dt = p3*(y2)^2
+ * on the interval from t = 0.0 to t = 4.e10, with initial
+ * 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 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.
+ *
+ * Optionally, CVODES can compute sensitivities with respect to
+ * the problem parameters p1, p2, and p3 of the following quantity:
+ * G = int_t0^t1 g(t,p,y) dt
+ * where
+ * g(t,p,y) = y3
+ *
+ * The gradient dG/dp is obtained as:
+ * dG/dp = int_t0^t1 (g_p - lambda^T f_p ) dt - lambda^T(t0)*y0_p
+ * = - xi^T(t0) - lambda^T(t0)*y0_p
+ * where lambda and xi are solutions of:
+ * d(lambda)/dt = - (f_y)^T * lambda - (g_y)^T
+ * lambda(t1) = 0
+ * and
+ * d(xi)/dt = - (f_p)^T * lambda + (g_p)^T
+ * xi(t1) = 0
+ *
+ * During the backward integration, CVODES also evaluates G as
+ * G = - phi(t0)
+ * 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>
+
+/* 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 */
+
+/* Problem Constants */
+
+#define NEQ 3 /* number of equations */
+
+#define RTOL RCONST(1e-6) /* scalar relative tolerance */
+
+#define ATOL1 RCONST(1e-8) /* vector absolute tolerance components */
+#define ATOL2 RCONST(1e-14)
+#define ATOL3 RCONST(1e-6)
+
+#define ATOLl RCONST(1e-8) /* absolute tolerance for adjoint vars. */
+#define ATOLq RCONST(1e-6) /* absolute tolerance for quadratures */
+
+#define T0 RCONST(0.0) /* initial time */
+#define TOUT RCONST(4e7) /* final time */
+
+#define TB1 RCONST(4e7) /* starting point for adjoint problem */
+#define TB2 RCONST(50.0) /* starting point for adjoint problem */
+
+#define STEPS 150 /* number of steps between check points */
+
+#define NP 3 /* number of problem parameters */
+
+#define ZERO RCONST(0.0)
+
+
+/* Type : UserData */
+
+typedef struct {
+ realtype p[3];
+} *UserData;
+
+/* 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 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 fQB(realtype t, N_Vector y, N_Vector yB,
+ N_Vector qBdot, void *user_dataB);
+
+
+/* Prototypes of private functions */
+
+static void PrintOutput(realtype tfinal, N_Vector yB, N_Vector qB);
+static int check_flag(void *flagvalue, char *funcname, int opt);
+
+/*
+ *--------------------------------------------------------------------
+ * MAIN PROGRAM
+ *--------------------------------------------------------------------
+ */
+
+int main(int argc, char *argv[])
+{
+ UserData data;
+
+ void *cvode_mem;
+
+ realtype reltolQ, abstolQ;
+ N_Vector y, q;
+
+ int steps;
+
+ int indexB;
+
+ realtype reltolB, abstolB, abstolQB;
+ N_Vector yB, qB;
+
+ realtype time;
+ int flag, ncheck;
+
+ long int nst, nstB;
+
+ CVadjCheckPointRec *ckpnt;
+
+ data = NULL;
+ cvode_mem = NULL;
+ ckpnt = NULL;
+ y = yB = qB = NULL;
+
+ /* Print problem description */
+ printf("\nAdjoint Sensitivity Example for Chemical Kinetics\n");
+ printf("-------------------------------------------------\n\n");
+ printf("ODE: dy1/dt = -p1*y1 + p2*y2*y3\n");
+ printf(" dy2/dt = p1*y1 - p2*y2*y3 - p3*(y2)^2\n");
+ printf(" dy3/dt = p3*(y2)^2\n\n");
+ printf("Find dG/dp for\n");
+ printf(" G = int_t0^tB0 g(t,p,y) dt\n");
+ printf(" g(t,p,y) = y3\n\n\n");
+
+ /* User data structure */
+ data = (UserData) malloc(sizeof *data);
+ if (check_flag((void *)data, "malloc", 2)) return(1);
+ data->p[0] = RCONST(0.04);
+ data->p[1] = RCONST(1.0e4);
+ data->p[2] = RCONST(3.0e7);
+
+ /* Initialize y */
+ y = N_VNew_Serial(NEQ);
+ if (check_flag((void *)y, "N_VNew_Serial", 0)) return(1);
+ Ith(y,1) = RCONST(1.0);
+ Ith(y,2) = ZERO;
+ Ith(y,3) = ZERO;
+
+ /* Initialize q */
+ q = N_VNew_Serial(1);
+ if (check_flag((void *)q, "N_VNew_Serial", 0)) return(1);
+ Ith(q,1) = ZERO;
+
+ /* Set the scalar realtive and absolute tolerances reltolQ and abstolQ */
+ reltolQ = RTOL;
+ abstolQ = ATOLq;
+
+ /* Create and allocate CVODES memory for forward run */
+ printf("Create and allocate CVODES memory for forward runs\n");
+
+ 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 = CVodeWFtolerances(cvode_mem, ewt);
+ if (check_flag(&flag, "CVodeWFtolerances", 1)) return(1);
+
+ 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);
+
+ flag = CVDlsSetDenseJacFn(cvode_mem, Jac);
+ if (check_flag(&flag, "CVDlsSetDenseJacFn", 1)) return(1);
+
+ flag = CVodeQuadInit(cvode_mem, fQ, q);
+ if (check_flag(&flag, "CVodeQuadInit", 1)) return(1);
+
+ 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;
+ flag = CVodeAdjInit(cvode_mem, steps, CV_HERMITE);
+ /*
+ flag = CVodeAdjInit(cvode_mem, steps, CV_POLYNOMIAL);
+ */
+ if (check_flag(&flag, "CVodeAdjInit", 1)) return(1);
+
+ /* Perform forward run */
+ printf("Forward integration ... ");
+
+ flag = CVodeF(cvode_mem, TOUT, y, &time, CV_NORMAL, &ncheck);
+ if (check_flag(&flag, "CVodeF", 1)) return(1);
+ flag = CVodeGetNumSteps(cvode_mem, &nst);
+ if (check_flag(&flag, "CVodeGetNumSteps", 1)) return(1);
+
+ printf("done ( nst = %ld )\n",nst);
+ printf("\nncheck = %d\n\n", ncheck);
+
+ flag = CVodeGetQuad(cvode_mem, &time, q);
+ if (check_flag(&flag, "CVodeGetQuad", 1)) return(1);
+
+ printf("--------------------------------------------------------\n");
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("G: %12.4Le \n",Ith(q,1));
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("G: %12.4le \n",Ith(q,1));
+#else
+ printf("G: %12.4e \n",Ith(q,1));
+#endif
+ printf("--------------------------------------------------------\n\n");
+
+ /* Test check point linked list
+ (uncomment next block to print check point information) */
+
+ /*
+ {
+ int i;
+
+ printf("\nList of Check Points (ncheck = %d)\n\n", ncheck);
+ ckpnt = (CVadjCheckPointRec *) malloc ( (ncheck+1)*sizeof(CVadjCheckPointRec));
+ CVodeGetAdjCheckPointsInfo(cvode_mem, ckpnt);
+ for (i=0;i<=ncheck;i++) {
+ printf("Address: %p\n",ckpnt[i].my_addr);
+ printf("Next: %p\n",ckpnt[i].next_addr);
+ printf("Time interval: %le %le\n",ckpnt[i].t0, ckpnt[i].t1);
+ printf("Step number: %ld\n",ckpnt[i].nstep);
+ printf("Order: %d\n",ckpnt[i].order);
+ printf("Step size: %le\n",ckpnt[i].step);
+ printf("\n");
+ }
+
+ }
+ */
+
+ /* Initialize yB */
+ yB = N_VNew_Serial(NEQ);
+ if (check_flag((void *)yB, "N_VNew_Serial", 0)) return(1);
+ Ith(yB,1) = ZERO;
+ Ith(yB,2) = ZERO;
+ Ith(yB,3) = ZERO;
+
+ /* Initialize qB */
+ qB = N_VNew_Serial(NP);
+ if (check_flag((void *)qB, "N_VNew", 0)) return(1);
+ Ith(qB,1) = ZERO;
+ Ith(qB,2) = ZERO;
+ Ith(qB,3) = ZERO;
+
+ /* Set the scalar relative tolerance reltolB */
+ reltolB = RTOL;
+
+ /* Set the scalar absolute tolerance abstolB */
+ abstolB = ATOLl;
+
+ /* Set the scalar absolute tolerance abstolQB */
+ abstolQB = ATOLq;
+
+ /* Create and allocate CVODES memory for backward run */
+ printf("Create and allocate CVODES memory for backward run\n");
+
+ flag = CVodeCreateB(cvode_mem, CV_BDF, CV_NEWTON, &indexB);
+ if (check_flag(&flag, "CVodeCreateB", 1)) return(1);
+
+ flag = CVodeInitB(cvode_mem, indexB, fB, TB1, yB);
+ if (check_flag(&flag, "CVodeInitB", 1)) return(1);
+
+ flag = CVodeSStolerancesB(cvode_mem, indexB, reltolB, abstolB);
+ if (check_flag(&flag, "CVodeSStolerancesB", 1)) return(1);
+
+ 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);
+
+ flag = CVDlsSetDenseJacFnB(cvode_mem, indexB, JacB);
+ if (check_flag(&flag, "CVDlsSetDenseJacFnB", 1)) return(1);
+
+ flag = CVodeQuadInitB(cvode_mem, indexB, fQB, qB);
+ if (check_flag(&flag, "CVodeQuadInitB", 1)) return(1);
+
+ 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 */
+ printf("Backward integration ... ");
+
+ flag = CVodeB(cvode_mem, T0, CV_NORMAL);
+ if (check_flag(&flag, "CVodeB", 1)) return(1);
+ CVodeGetNumSteps(CVodeGetAdjCVodeBmem(cvode_mem, indexB), &nstB);
+ printf("done ( nst = %ld )\n", nstB);
+
+ flag = CVodeGetB(cvode_mem, indexB, &time, yB);
+ if (check_flag(&flag, "CVodeGetB", 1)) return(1);
+
+ flag = CVodeGetQuadB(cvode_mem, indexB, &time, qB);
+ if (check_flag(&flag, "CVodeGetQuadB", 1)) return(1);
+
+ PrintOutput(TB1, yB, qB);
+
+ /* Reinitialize backward phase (new tB0) */
+
+ Ith(yB,1) = ZERO;
+ Ith(yB,2) = ZERO;
+ Ith(yB,3) = ZERO;
+
+ Ith(qB,1) = ZERO;
+ Ith(qB,2) = ZERO;
+ Ith(qB,3) = ZERO;
+
+ printf("Re-initialize CVODES memory for backward run\n");
+
+ flag = CVodeReInitB(cvode_mem, indexB, TB2, yB);
+ if (check_flag(&flag, "CVodeReInitB", 1)) return(1);
+
+ flag = CVodeQuadReInitB(cvode_mem, indexB, qB);
+ if (check_flag(&flag, "CVodeQuadReInitB", 1)) return(1);
+
+ printf("Backward integration ... ");
+
+ flag = CVodeB(cvode_mem, T0, CV_NORMAL);
+ if (check_flag(&flag, "CVodeB", 1)) return(1);
+ CVodeGetNumSteps(CVodeGetAdjCVodeBmem(cvode_mem, indexB), &nstB);
+ printf("done ( nst = %ld )\n", nstB);
+
+ flag = CVodeGetB(cvode_mem, indexB, &time, yB);
+ if (check_flag(&flag, "CVodeGetB", 1)) return(1);
+
+ flag = CVodeGetQuadB(cvode_mem, indexB, &time, qB);
+ if (check_flag(&flag, "CVodeGetQuadB", 1)) return(1);
+
+ PrintOutput(TB2, yB, qB);
+
+ /* Free memory */
+ printf("Free memory\n\n");
+
+ CVodeFree(&cvode_mem);
+ N_VDestroy_Serial(y);
+ N_VDestroy_Serial(q);
+ N_VDestroy_Serial(yB);
+ N_VDestroy_Serial(qB);
+
+ if (ckpnt != NULL) free(ckpnt);
+ free(data);
+
+ return(0);
+
+}
+
+/*
+ *--------------------------------------------------------------------
+ * FUNCTIONS CALLED BY CVODES
+ *--------------------------------------------------------------------
+ */
+
+/*
+ * f routine. Compute f(t,y).
+*/
+
+static int f(realtype t, N_Vector y, N_Vector ydot, void *user_data)
+{
+ realtype y1, y2, y3, yd1, yd3;
+ UserData data;
+ realtype p1, p2, p3;
+
+ y1 = Ith(y,1); y2 = Ith(y,2); y3 = Ith(y,3);
+ data = (UserData) user_data;
+ p1 = data->p[0]; p2 = data->p[1]; p3 = data->p[2];
+
+ yd1 = Ith(ydot,1) = -p1*y1 + p2*y2*y3;
+ yd3 = Ith(ydot,3) = p3*y2*y2;
+ Ith(ydot,2) = -yd1 - yd3;
+
+ return(0);
+}
+
+/*
+ * 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)
+{
+ realtype y1, y2, y3;
+ UserData data;
+ realtype p1, p2, p3;
+
+ y1 = Ith(y,1); y2 = Ith(y,2); y3 = Ith(y,3);
+ data = (UserData) user_data;
+ p1 = data->p[0]; p2 = data->p[1]; p3 = data->p[2];
+
+ 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;
+
+ 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);
+
+ return(0);
+}
+
+/*
+ * EwtSet function. Computes the error weights at the current solution.
+ */
+
+static int ewt(N_Vector y, N_Vector w, void *user_data)
+{
+ int i;
+ realtype yy, ww, rtol, atol[3];
+
+ rtol = RTOL;
+ atol[0] = ATOL1;
+ atol[1] = ATOL2;
+ atol[2] = ATOL3;
+
+ for (i=1; i<=3; i++) {
+ yy = Ith(y,i);
+ ww = rtol * ABS(yy) + atol[i-1];
+ if (ww <= 0.0) return (-1);
+ Ith(w,i) = 1.0/ww;
+ }
+
+ return(0);
+}
+
+/*
+ * fB routine. Compute fB(t,y,yB).
+*/
+
+static int fB(realtype t, N_Vector y, N_Vector yB, N_Vector yBdot, 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);
+
+ /* The lambda vector */
+ l1 = Ith(yB,1); l2 = Ith(yB,2); l3 = Ith(yB,3);
+
+ /* Temporary variables */
+ l21 = l2-l1;
+ l32 = l3-l2;
+ y23 = y2*y3;
+
+ /* Load yBdot */
+ Ith(yBdot,1) = - p1*l21;
+ Ith(yBdot,2) = p2*y3*l21 - RCONST(2.0)*p3*y2*l32;
+ Ith(yBdot,3) = p2*y2*l21 - RCONST(1.0);
+
+ return(0);
+}
+
+/*
+ * 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)
+{
+ UserData data;
+ realtype y1, y2, y3;
+ realtype p1, p2, p3;
+
+ 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);
+
+ /* 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;
+
+ 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)
+{
+ 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);
+
+ /* The lambda vector */
+ l1 = Ith(yB,1); l2 = Ith(yB,2); l3 = Ith(yB,3);
+
+ /* Temporary variables */
+ l21 = l2-l1;
+ l32 = l3-l2;
+ y23 = y2*y3;
+
+ Ith(qBdot,1) = y1*l21;
+ Ith(qBdot,2) = - y23*l21;
+ Ith(qBdot,3) = y2*y2*l32;
+
+ return(0);
+}
+
+/*
+ *--------------------------------------------------------------------
+ * PRIVATE FUNCTIONS
+ *--------------------------------------------------------------------
+ */
+
+/*
+ * Print results after backward integration
+ */
+
+static void PrintOutput(realtype tfinal, N_Vector yB, N_Vector qB)
+{
+ printf("--------------------------------------------------------\n");
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("tB0: %12.4Le\n",tfinal);
+ printf("dG/dp: %12.4Le %12.4Le %12.4Le\n",
+ -Ith(qB,1), -Ith(qB,2), -Ith(qB,3));
+ printf("lambda(t0): %12.4Le %12.4Le %12.4Le\n",
+ Ith(yB,1), Ith(yB,2), Ith(yB,3));
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("tB0: %12.4le\n",tfinal);
+ printf("dG/dp: %12.4le %12.4le %12.4le\n",
+ -Ith(qB,1), -Ith(qB,2), -Ith(qB,3));
+ printf("lambda(t0): %12.4le %12.4le %12.4le\n",
+ Ith(yB,1), Ith(yB,2), Ith(yB,3));
+#else
+ printf("tB0: %12.4e\n",tfinal);
+ printf("dG/dp: %12.4e %12.4e %12.4e\n",
+ -Ith(qB,1), -Ith(qB,2), -Ith(qB,3));
+ printf("lambda(t0): %12.4e %12.4e %12.4e\n",
+ Ith(yB,1), Ith(yB,2), Ith(yB,3));
+#endif
+ printf("--------------------------------------------------------\n\n");
+}
+
+/*
+ * 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, 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/cvsRoberts_ASAi_dns.out b/examples/cvodes/serial/cvsRoberts_ASAi_dns.out
new file mode 100644
index 0000000..008a51c
--- /dev/null
+++ b/examples/cvodes/serial/cvsRoberts_ASAi_dns.out
@@ -0,0 +1,39 @@
+
+Adjoint Sensitivity Example for Chemical Kinetics
+-------------------------------------------------
+
+ODE: dy1/dt = -p1*y1 + p2*y2*y3
+ dy2/dt = p1*y1 - p2*y2*y3 - p3*(y2)^2
+ dy3/dt = p3*(y2)^2
+
+Find dG/dp for
+ G = int_t0^tB0 g(t,p,y) dt
+ g(t,p,y) = y3
+
+
+Create and allocate CVODES memory for forward runs
+Forward integration ... done ( nst = 851 )
+
+ncheck = 5
+--------------------------------------------------------
+G: 3.9983e+07
+--------------------------------------------------------
+
+Create and allocate CVODES memory for backward run
+Backward integration ... done ( nst = 260 )
+--------------------------------------------------------
+tB0: 4.0000e+07
+dG/dp: 7.6844e+05 -3.0691e+00 5.1152e-04
+lambda(t0): 3.9967e+07 3.9967e+07 3.9967e+07
+--------------------------------------------------------
+
+Re-initialize CVODES memory for backward run
+Backward integration ... done ( nst = 196 )
+--------------------------------------------------------
+tB0: 5.0000e+01
+dG/dp: 1.7341e+02 -5.0590e-04 8.4320e-08
+lambda(t0): 8.4190e+00 1.6097e+01 1.6097e+01
+--------------------------------------------------------
+
+Free memory
+
diff --git a/examples/cvodes/serial/cvsRoberts_FSA_dns.c b/examples/cvodes/serial/cvsRoberts_FSA_dns.c
new file mode 100644
index 0000000..27084ef
--- /dev/null
+++ b/examples/cvodes/serial/cvsRoberts_FSA_dns.c
@@ -0,0 +1,626 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.2 $
+ * $Date: 2010/12/01 22:58:00 $
+ * -----------------------------------------------------------------
+ * 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:
+ * dy1/dt = -p1*y1 + p2*y2*y3
+ * dy2/dt = p1*y1 - p2*y2*y3 - p3*(y2)^2
+ * dy3/dt = p3*(y2)^2
+ * on the interval from t = 0.0 to t = 4.e10, with initial
+ * 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 CVODES 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.
+ *
+ * Optionally, CVODES can compute sensitivities with respect to the
+ * problem parameters p1, p2, and p3.
+ * The sensitivity right hand side is given analytically through the
+ * 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,
+ * respectively).
+ *
+ * Execution:
+ *
+ * If no sensitivities are desired:
+ * % cvsRoberts_FSA_dns -nosensi
+ * If sensitivities are to be computed:
+ * % 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 */
+
+/* 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 */
+#define Y1 RCONST(1.0) /* initial y components */
+#define Y2 RCONST(0.0)
+#define Y3 RCONST(0.0)
+#define RTOL RCONST(1e-4) /* scalar relative tolerance */
+#define ATOL1 RCONST(1e-8) /* vector absolute tolerance components */
+#define ATOL2 RCONST(1e-14)
+#define ATOL3 RCONST(1e-6)
+#define T0 RCONST(0.0) /* initial time */
+#define T1 RCONST(0.4) /* first output time */
+#define TMULT RCONST(10.0) /* output time factor */
+#define NOUT 12 /* number of output times */
+
+#define NP 3 /* number of problem parameters */
+#define NS 3 /* number of sensitivities computed */
+
+#define ZERO RCONST(0.0)
+
+/* Type : UserData */
+
+typedef struct {
+ realtype p[3]; /* problem parameters */
+} *UserData;
+
+/* Prototypes of functions by CVODES */
+
+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 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);
+
+/* Prototypes of private functions */
+
+static void ProcessArgs(int argc, char *argv[],
+ booleantype *sensi, int *sensi_meth,
+ booleantype *err_con);
+static void WrongArgs(char *name);
+static void PrintOutput(void *cvode_mem, realtype t, N_Vector u);
+static void PrintOutputS(N_Vector *uS);
+static void PrintFinalStats(void *cvode_mem, booleantype sensi);
+static int check_flag(void *flagvalue, char *funcname, int opt);
+
+/*
+ *--------------------------------------------------------------------
+ * MAIN PROGRAM
+ *--------------------------------------------------------------------
+ */
+
+int main(int argc, char *argv[])
+{
+ void *cvode_mem;
+ UserData data;
+ realtype t, tout;
+ N_Vector y;
+ int iout, flag;
+
+ realtype pbar[NS];
+ int is;
+ N_Vector *yS;
+ booleantype sensi, err_con;
+ int sensi_meth;
+
+ cvode_mem = NULL;
+ data = NULL;
+ y = NULL;
+ yS = NULL;
+
+ /* Process arguments */
+ ProcessArgs(argc, argv, &sensi, &sensi_meth, &err_con);
+
+ /* User data structure */
+ data = (UserData) malloc(sizeof *data);
+ if (check_flag((void *)data, "malloc", 2)) return(1);
+ data->p[0] = RCONST(0.04);
+ data->p[1] = RCONST(1.0e4);
+ data->p[2] = RCONST(3.0e7);
+
+ /* Initial conditions */
+ y = N_VNew_Serial(NEQ);
+ if (check_flag((void *)y, "N_VNew_Serial", 0)) return(1);
+
+ Ith(y,1) = Y1;
+ Ith(y,2) = Y2;
+ Ith(y,3) = Y3;
+
+ /* Create CVODES object */
+ cvode_mem = CVodeCreate(CV_BDF, CV_NEWTON);
+ if (check_flag((void *)cvode_mem, "CVodeCreate", 0)) return(1);
+
+ /* Allocate space for CVODES */
+ flag = CVodeInit(cvode_mem, f, T0, y);
+ if (check_flag(&flag, "CVodeInit", 1)) return(1);
+
+ /* Use private function to compute error weights */
+ flag = CVodeWFtolerances(cvode_mem, ewt);
+ if (check_flag(&flag, "CVodeSetEwtFn", 1)) return(1);
+
+ /* Attach user data */
+ 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);
+
+ flag = CVDlsSetDenseJacFn(cvode_mem, Jac);
+ if (check_flag(&flag, "CVDlsSetDenseJacFn", 1)) return(1);
+
+ printf("\n3-species chemical kinetics problem\n");
+
+ /* Sensitivity-related settings */
+ if (sensi) {
+
+ 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);
+ for (is=0;is<NS;is++) N_VConst(ZERO, yS[is]);
+
+ flag = CVodeSensInit1(cvode_mem, NS, sensi_meth, fS, yS);
+ if(check_flag(&flag, "CVodeSensInit", 1)) return(1);
+
+ flag = CVodeSensEEtolerances(cvode_mem);
+ if(check_flag(&flag, "CVodeSensEEtolerances", 1)) return(1);
+
+ flag = CVodeSetSensErrCon(cvode_mem, err_con);
+ if (check_flag(&flag, "CVodeSetSensErrCon", 1)) return(1);
+
+ flag = CVodeSetSensParams(cvode_mem, NULL, pbar, NULL);
+ if (check_flag(&flag, "CVodeSetSensParams", 1)) return(1);
+
+ printf("Sensitivity: YES ");
+ if(sensi_meth == CV_SIMULTANEOUS)
+ printf("( SIMULTANEOUS +");
+ else
+ if(sensi_meth == CV_STAGGERED) printf("( STAGGERED +");
+ else printf("( STAGGERED1 +");
+ if(err_con) printf(" FULL ERROR CONTROL )");
+ else printf(" PARTIAL ERROR CONTROL )");
+
+ } else {
+
+ printf("Sensitivity: NO ");
+
+ }
+
+ /* In loop over output points, call CVode, print results, test for error */
+
+ printf("\n\n");
+ printf("===========================================");
+ printf("============================\n");
+ printf(" T Q H NST y1");
+ printf(" y2 y3 \n");
+ printf("===========================================");
+ printf("============================\n");
+
+ for (iout=1, tout=T1; iout <= NOUT; iout++, tout *= TMULT) {
+
+ flag = CVode(cvode_mem, tout, y, &t, CV_NORMAL);
+ if (check_flag(&flag, "CVode", 1)) break;
+
+ PrintOutput(cvode_mem, t, y);
+
+ if (sensi) {
+ flag = CVodeGetSens(cvode_mem, &t, yS);
+ if (check_flag(&flag, "CVodeGetSens", 1)) break;
+ PrintOutputS(yS);
+ }
+ printf("-----------------------------------------");
+ printf("------------------------------\n");
+
+ }
+
+ /* Print final statistics */
+ PrintFinalStats(cvode_mem, sensi);
+
+ /* Free memory */
+
+ N_VDestroy_Serial(y); /* Free y vector */
+ if (sensi) {
+ N_VDestroyVectorArray_Serial(yS, NS); /* Free yS vector */
+ }
+ free(data); /* Free user data */
+ CVodeFree(&cvode_mem); /* Free CVODES memory */
+
+ return(0);
+}
+
+/*
+ *--------------------------------------------------------------------
+ * FUNCTIONS CALLED BY CVODES
+ *--------------------------------------------------------------------
+ */
+
+/*
+ * f routine. Compute f(t,y).
+ */
+
+static int f(realtype t, N_Vector y, N_Vector ydot, void *user_data)
+{
+ realtype y1, y2, y3, yd1, yd3;
+ UserData data;
+ realtype p1, p2, p3;
+
+ y1 = Ith(y,1); y2 = Ith(y,2); y3 = Ith(y,3);
+ data = (UserData) user_data;
+ p1 = data->p[0]; p2 = data->p[1]; p3 = data->p[2];
+
+ yd1 = Ith(ydot,1) = -p1*y1 + p2*y2*y3;
+ yd3 = Ith(ydot,3) = p3*y2*y2;
+ Ith(ydot,2) = -yd1 - yd3;
+
+ return(0);
+}
+
+
+/*
+ * 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)
+{
+ realtype y1, y2, y3;
+ UserData data;
+ realtype p1, p2, p3;
+
+ y1 = Ith(y,1); y2 = Ith(y,2); y3 = Ith(y,3);
+ data = (UserData) user_data;
+ p1 = data->p[0]; p2 = data->p[1]; p3 = data->p[2];
+
+ 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;
+
+ return(0);
+}
+
+/*
+ * fS routine. Compute sensitivity r.h.s.
+ */
+
+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)
+{
+ UserData data;
+ realtype p1, p2, p3;
+ realtype y1, y2, y3;
+ realtype s1, s2, s3;
+ realtype sd1, sd2, sd3;
+
+ data = (UserData) user_data;
+ p1 = data->p[0]; p2 = data->p[1]; p3 = data->p[2];
+
+ y1 = Ith(y,1); y2 = Ith(y,2); y3 = Ith(y,3);
+ s1 = Ith(yS,1); s2 = Ith(yS,2); s3 = Ith(yS,3);
+
+ sd1 = -p1*s1 + p2*y3*s2 + p2*y2*s3;
+ sd3 = 2*p3*y2*s2;
+ sd2 = -sd1-sd3;
+
+ switch (iS) {
+ case 0:
+ sd1 += -y1;
+ sd2 += y1;
+ break;
+ case 1:
+ sd1 += y2*y3;
+ sd2 += -y2*y3;
+ break;
+ case 2:
+ sd2 += -y2*y2;
+ sd3 += y2*y2;
+ break;
+ }
+
+ Ith(ySdot,1) = sd1;
+ Ith(ySdot,2) = sd2;
+ Ith(ySdot,3) = sd3;
+
+ return(0);
+}
+
+/*
+ * EwtSet function. Computes the error weights at the current solution.
+ */
+
+static int ewt(N_Vector y, N_Vector w, void *user_data)
+{
+ int i;
+ realtype yy, ww, rtol, atol[3];
+
+ rtol = RTOL;
+ atol[0] = ATOL1;
+ atol[1] = ATOL2;
+ atol[2] = ATOL3;
+
+ for (i=1; i<=3; i++) {
+ yy = Ith(y,i);
+ ww = rtol * ABS(yy) + atol[i-1];
+ if (ww <= 0.0) return (-1);
+ Ith(w,i) = 1.0/ww;
+ }
+
+ return(0);
+}
+
+/*
+ *--------------------------------------------------------------------
+ * PRIVATE FUNCTIONS
+ *--------------------------------------------------------------------
+ */
+
+/*
+ * Process and verify arguments to cvsfwddenx.
+ */
+
+static void ProcessArgs(int argc, char *argv[],
+ booleantype *sensi, int *sensi_meth, booleantype *err_con)
+{
+ *sensi = FALSE;
+ *sensi_meth = -1;
+ *err_con = FALSE;
+
+ if (argc < 2) WrongArgs(argv[0]);
+
+ if (strcmp(argv[1],"-nosensi") == 0)
+ *sensi = FALSE;
+ else if (strcmp(argv[1],"-sensi") == 0)
+ *sensi = TRUE;
+ else
+ WrongArgs(argv[0]);
+
+ if (*sensi) {
+
+ if (argc != 4)
+ WrongArgs(argv[0]);
+
+ if (strcmp(argv[2],"sim") == 0)
+ *sensi_meth = CV_SIMULTANEOUS;
+ else if (strcmp(argv[2],"stg") == 0)
+ *sensi_meth = CV_STAGGERED;
+ else if (strcmp(argv[2],"stg1") == 0)
+ *sensi_meth = CV_STAGGERED1;
+ else
+ WrongArgs(argv[0]);
+
+ if (strcmp(argv[3],"t") == 0)
+ *err_con = TRUE;
+ else if (strcmp(argv[3],"f") == 0)
+ *err_con = FALSE;
+ else
+ WrongArgs(argv[0]);
+ }
+
+}
+
+static void WrongArgs(char *name)
+{
+ printf("\nUsage: %s [-nosensi] [-sensi sensi_meth err_con]\n",name);
+ printf(" sensi_meth = sim, stg, or stg1\n");
+ printf(" err_con = t or f\n");
+
+ exit(0);
+}
+
+/*
+ * Print current t, step count, order, stepsize, and solution.
+ */
+
+static void PrintOutput(void *cvode_mem, realtype t, N_Vector u)
+{
+ long int nst;
+ int qu, flag;
+ realtype hu, *udata;
+
+ udata = NV_DATA_S(u);
+
+ flag = CVodeGetNumSteps(cvode_mem, &nst);
+ check_flag(&flag, "CVodeGetNumSteps", 1);
+ flag = CVodeGetLastOrder(cvode_mem, &qu);
+ check_flag(&flag, "CVodeGetLastOrder", 1);
+ flag = CVodeGetLastStep(cvode_mem, &hu);
+ check_flag(&flag, "CVodeGetLastStep", 1);
+
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("%8.3Le %2d %8.3Le %5ld\n", t, qu, hu, nst);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("%8.3le %2d %8.3le %5ld\n", t, qu, hu, nst);
+#else
+ printf("%8.3e %2d %8.3e %5ld\n", t, qu, hu, nst);
+#endif
+
+ printf(" Solution ");
+
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("%12.4Le %12.4Le %12.4Le \n", udata[0], udata[1], udata[2]);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("%12.4le %12.4le %12.4le \n", udata[0], udata[1], udata[2]);
+#else
+ printf("%12.4e %12.4e %12.4e \n", udata[0], udata[1], udata[2]);
+#endif
+
+}
+
+/*
+ * Print sensitivities.
+*/
+
+static void PrintOutputS(N_Vector *uS)
+{
+ realtype *sdata;
+
+ sdata = NV_DATA_S(uS[0]);
+ printf(" Sensitivity 1 ");
+
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("%12.4Le %12.4Le %12.4Le \n", sdata[0], sdata[1], sdata[2]);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("%12.4le %12.4le %12.4le \n", sdata[0], sdata[1], sdata[2]);
+#else
+ printf("%12.4e %12.4e %12.4e \n", sdata[0], sdata[1], sdata[2]);
+#endif
+
+ sdata = NV_DATA_S(uS[1]);
+ printf(" Sensitivity 2 ");
+
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("%12.4Le %12.4Le %12.4Le \n", sdata[0], sdata[1], sdata[2]);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("%12.4le %12.4le %12.4le \n", sdata[0], sdata[1], sdata[2]);
+#else
+ printf("%12.4e %12.4e %12.4e \n", sdata[0], sdata[1], sdata[2]);
+#endif
+
+ sdata = NV_DATA_S(uS[2]);
+ printf(" Sensitivity 3 ");
+
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("%12.4Le %12.4Le %12.4Le \n", sdata[0], sdata[1], sdata[2]);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("%12.4le %12.4le %12.4le \n", sdata[0], sdata[1], sdata[2]);
+#else
+ printf("%12.4e %12.4e %12.4e \n", sdata[0], sdata[1], sdata[2]);
+#endif
+}
+
+/*
+ * Print some final statistics from the CVODES memory.
+ */
+
+static void PrintFinalStats(void *cvode_mem, booleantype sensi)
+{
+ long int nst;
+ long int nfe, nsetups, nni, ncfn, netf;
+ long int nfSe, nfeS, nsetupsS, nniS, ncfnS, netfS;
+ long int nje, nfeLS;
+ int flag;
+
+ 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);
+
+ if (sensi) {
+ flag = CVodeGetSensNumRhsEvals(cvode_mem, &nfSe);
+ check_flag(&flag, "CVodeGetSensNumRhsEvals", 1);
+ flag = CVodeGetNumRhsEvalsSens(cvode_mem, &nfeS);
+ check_flag(&flag, "CVodeGetNumRhsEvalsSens", 1);
+ flag = CVodeGetSensNumLinSolvSetups(cvode_mem, &nsetupsS);
+ check_flag(&flag, "CVodeGetSensNumLinSolvSetups", 1);
+ flag = CVodeGetSensNumErrTestFails(cvode_mem, &netfS);
+ check_flag(&flag, "CVodeGetSensNumErrTestFails", 1);
+ flag = CVodeGetSensNumNonlinSolvIters(cvode_mem, &nniS);
+ check_flag(&flag, "CVodeGetSensNumNonlinSolvIters", 1);
+ flag = CVodeGetSensNumNonlinSolvConvFails(cvode_mem, &ncfnS);
+ check_flag(&flag, "CVodeGetSensNumNonlinSolvConvFails", 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\n");
+ printf("nst = %5ld\n\n", nst);
+ printf("nfe = %5ld\n", nfe);
+ printf("netf = %5ld nsetups = %5ld\n", netf, nsetups);
+ printf("nni = %5ld ncfn = %5ld\n", nni, ncfn);
+
+ if(sensi) {
+ printf("\n");
+ printf("nfSe = %5ld nfeS = %5ld\n", nfSe, nfeS);
+ printf("netfs = %5ld nsetupsS = %5ld\n", netfS, nsetupsS);
+ printf("nniS = %5ld ncfnS = %5ld\n", nniS, ncfnS);
+ }
+
+ printf("\n");
+ printf("nje = %5ld nfeLS = %5ld\n", nje, nfeLS);
+
+}
+
+/*
+ * 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, 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/cvsRoberts_FSA_dns.out b/examples/cvodes/serial/cvsRoberts_FSA_dns.out
new file mode 100644
index 0000000..74a4952
--- /dev/null
+++ b/examples/cvodes/serial/cvsRoberts_FSA_dns.out
@@ -0,0 +1,93 @@
+
+3-species chemical kinetics problem
+Sensitivity: YES ( SIMULTANEOUS + FULL ERROR CONTROL )
+
+=======================================================================
+ T Q H NST y1 y2 y3
+=======================================================================
+4.000e-01 3 4.881e-02 115
+ Solution 9.8517e-01 3.3864e-05 1.4794e-02
+ Sensitivity 1 -3.5595e-01 3.9025e-04 3.5556e-01
+ Sensitivity 2 9.5431e-08 -2.1309e-10 -9.5218e-08
+ Sensitivity 3 -1.5833e-11 -5.2900e-13 1.6362e-11
+-----------------------------------------------------------------------
+4.000e+00 5 2.363e-01 138
+ 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.8305e-10 -2.9608e-06
+ Sensitivity 3 -4.9334e-10 -2.7626e-13 4.9362e-10
+-----------------------------------------------------------------------
+4.000e+01 3 1.485e+00 219
+ Solution 7.1583e-01 9.1856e-06 2.8416e-01
+ Sensitivity 1 -4.2475e+00 4.5913e-05 4.2475e+00
+ Sensitivity 2 1.3731e-05 -2.3573e-10 -1.3730e-05
+ Sensitivity 3 -2.2883e-09 -1.1380e-13 2.2884e-09
+-----------------------------------------------------------------------
+4.000e+02 3 8.882e+00 331
+ Solution 4.5052e-01 3.2229e-06 5.4947e-01
+ Sensitivity 1 -5.9584e+00 3.5431e-06 5.9584e+00
+ Sensitivity 2 2.2738e-05 -2.2605e-11 -2.2738e-05
+ Sensitivity 3 -3.7896e-09 -4.9948e-14 3.7897e-09
+-----------------------------------------------------------------------
+4.000e+03 2 1.090e+02 486
+ Solution 1.8317e-01 8.9403e-07 8.1683e-01
+ Sensitivity 1 -4.7500e+00 -5.9957e-06 4.7500e+00
+ Sensitivity 2 1.8809e-05 2.3136e-11 -1.8809e-05
+ Sensitivity 3 -3.1348e-09 -1.8757e-14 3.1348e-09
+-----------------------------------------------------------------------
+4.000e+04 3 1.178e+03 588
+ Solution 3.8977e-02 1.6215e-07 9.6102e-01
+ Sensitivity 1 -1.5748e+00 -2.7620e-06 1.5748e+00
+ Sensitivity 2 6.2869e-06 1.1002e-11 -6.2869e-06
+ Sensitivity 3 -1.0478e-09 -4.5362e-15 1.0478e-09
+-----------------------------------------------------------------------
+4.000e+05 3 1.514e+04 645
+ Solution 4.9387e-03 1.9852e-08 9.9506e-01
+ Sensitivity 1 -2.3639e-01 -4.5861e-07 2.3639e-01
+ Sensitivity 2 9.4525e-07 1.8334e-12 -9.4525e-07
+ Sensitivity 3 -1.5751e-10 -6.3629e-16 1.5751e-10
+-----------------------------------------------------------------------
+4.000e+06 4 2.323e+05 696
+ Solution 5.1684e-04 2.0684e-09 9.9948e-01
+ Sensitivity 1 -2.5667e-02 -5.1064e-08 2.5667e-02
+ Sensitivity 2 1.0266e-07 2.0424e-13 -1.0266e-07
+ Sensitivity 3 -1.7111e-11 -6.8513e-17 1.7111e-11
+-----------------------------------------------------------------------
+4.000e+07 4 1.776e+06 753
+ Solution 5.2039e-05 2.0817e-10 9.9995e-01
+ Sensitivity 1 -2.5991e-03 -5.1931e-09 2.5991e-03
+ Sensitivity 2 1.0396e-08 2.0772e-14 -1.0397e-08
+ Sensitivity 3 -1.7330e-12 -6.9328e-18 1.7330e-12
+-----------------------------------------------------------------------
+4.000e+08 4 2.766e+07 802
+ Solution 5.2106e-06 2.0842e-11 9.9999e-01
+ Sensitivity 1 -2.6063e-04 -5.2149e-10 2.6063e-04
+ Sensitivity 2 1.0425e-09 2.0859e-15 -1.0425e-09
+ Sensitivity 3 -1.7366e-13 -6.9467e-19 1.7367e-13
+-----------------------------------------------------------------------
+4.000e+09 2 4.183e+08 836
+ Solution 5.1881e-07 2.0752e-12 1.0000e-00
+ Sensitivity 1 -2.5907e-05 -5.1717e-11 2.5907e-05
+ Sensitivity 2 1.0363e-10 2.0687e-16 -1.0363e-10
+ Sensitivity 3 -1.7293e-14 -6.9174e-20 1.7293e-14
+-----------------------------------------------------------------------
+4.000e+10 2 3.799e+09 859
+ Solution 6.5181e-08 2.6072e-13 1.0000e-00
+ Sensitivity 1 -2.4884e-06 -3.3032e-12 2.4884e-06
+ Sensitivity 2 9.9534e-12 1.3213e-17 -9.9534e-12
+ Sensitivity 3 -2.1727e-15 -8.6908e-21 2.1727e-15
+-----------------------------------------------------------------------
+
+Final Statistics
+
+nst = 859
+
+nfe = 1222
+netf = 29 nsetups = 142
+nni = 1218 ncfn = 4
+
+nfSe = 3666 nfeS = 0
+netfs = 0 nsetupsS = 0
+nniS = 0 ncfnS = 0
+
+nje = 24 nfeLS = 0
diff --git a/examples/cvodes/serial/cvsRoberts_dns.c b/examples/cvodes/serial/cvsRoberts_dns.c
new file mode 100644
index 0000000..94698ce
--- /dev/null
+++ b/examples/cvodes/serial/cvsRoberts_dns.c
@@ -0,0 +1,359 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.2 $
+ * $Date: 2010/12/01 22:58:00 $
+ * -----------------------------------------------------------------
+ * 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 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 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
+ * 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 */
+
+/* User-defined vector and matrix accessor macros: Ith, IJth */
+
+/* These macros are defined in order to write code which exactly matches
+ the mathematical problem description given above.
+
+ 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.
+
+ 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. */
+
+#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 */
+
+
+/* Problem Constants */
+
+#define NEQ 3 /* number of equations */
+#define Y1 RCONST(1.0) /* initial y components */
+#define Y2 RCONST(0.0)
+#define Y3 RCONST(0.0)
+#define RTOL RCONST(1.0e-4) /* scalar relative tolerance */
+#define ATOL1 RCONST(1.0e-8) /* vector absolute tolerance components */
+#define ATOL2 RCONST(1.0e-14)
+#define ATOL3 RCONST(1.0e-6)
+#define T0 RCONST(0.0) /* initial time */
+#define T1 RCONST(0.4) /* first output time */
+#define TMULT RCONST(10.0) /* output time factor */
+#define NOUT 12 /* number of output times */
+
+
+/* Functions Called by the Solver */
+
+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);
+
+/* Private functions to output results */
+
+static void PrintOutput(realtype t, realtype y1, realtype y2, realtype y3);
+static void PrintRootInfo(int root_f1, int root_f2);
+
+/* Private function to print final statistics */
+
+static void PrintFinalStats(void *cvode_mem);
+
+/* Private function to check function return values */
+
+static int check_flag(void *flagvalue, char *funcname, int opt);
+
+
+/*
+ *-------------------------------
+ * Main Program
+ *-------------------------------
+ */
+
+int main()
+{
+ realtype reltol, t, tout;
+ N_Vector y, abstol;
+ void *cvode_mem;
+ int flag, flagr, iout;
+ int rootsfound[2];
+
+ y = abstol = NULL;
+ cvode_mem = NULL;
+
+ /* Create serial vector of length NEQ for I.C. and abstol */
+ y = N_VNew_Serial(NEQ);
+ if (check_flag((void *)y, "N_VNew_Serial", 0)) return(1);
+ abstol = N_VNew_Serial(NEQ);
+ if (check_flag((void *)abstol, "N_VNew_Serial", 0)) return(1);
+
+ /* Initialize y */
+ Ith(y,1) = Y1;
+ Ith(y,2) = Y2;
+ Ith(y,3) = Y3;
+
+ /* Set the scalar relative tolerance */
+ reltol = RTOL;
+ /* Set the vector absolute tolerance */
+ Ith(abstol,1) = ATOL1;
+ Ith(abstol,2) = ATOL2;
+ Ith(abstol,3) = ATOL3;
+
+ /* 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 inital 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 CVodeSVtolerances to specify the scalar relative tolerance
+ * and vector absolute tolerances */
+ flag = CVodeSVtolerances(cvode_mem, reltol, abstol);
+ if (check_flag(&flag, "CVodeSVtolerances", 1)) return(1);
+
+ /* Call CVodeRootInit to specify the root function g with 2 components */
+ 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);
+
+ /* Set the Jacobian routine to Jac (user-supplied) */
+ flag = CVDlsSetDenseJacFn(cvode_mem, Jac);
+ if (check_flag(&flag, "CVDlsSetDenseJacFn", 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. */
+ printf(" \n3-species kinetics problem\n\n");
+
+ iout = 0; tout = T1;
+ while(1) {
+ flag = CVode(cvode_mem, tout, y, &t, CV_NORMAL);
+ PrintOutput(t, Ith(y,1), Ith(y,2), Ith(y,3));
+
+ if (flag == CV_ROOT_RETURN) {
+ flagr = CVodeGetRootInfo(cvode_mem, rootsfound);
+ if (check_flag(&flagr, "CVodeGetRootInfo", 1)) return(1);
+ PrintRootInfo(rootsfound[0],rootsfound[1]);
+ }
+
+ if (check_flag(&flag, "CVode", 1)) break;
+ if (flag == CV_SUCCESS) {
+ iout++;
+ tout *= TMULT;
+ }
+
+ if (iout == NOUT) break;
+ }
+
+ /* Print some final statistics */
+ PrintFinalStats(cvode_mem);
+
+ /* Free y vector */
+ N_VDestroy_Serial(y);
+
+ /* Free integrator memory */
+ CVodeFree(&cvode_mem);
+
+ return(0);
+}
+
+
+/*
+ *-------------------------------
+ * Functions called by the solver
+ *-------------------------------
+ */
+
+/*
+ * f routine. Compute function f(t,y).
+ */
+
+static int f(realtype t, N_Vector y, N_Vector ydot, void *user_data)
+{
+ realtype y1, y2, y3, yd1, yd3;
+
+ y1 = Ith(y,1); y2 = Ith(y,2); y3 = Ith(y,3);
+
+ yd1 = Ith(ydot,1) = RCONST(-0.04)*y1 + RCONST(1.0e4)*y2*y3;
+ yd3 = Ith(ydot,3) = RCONST(3.0e7)*y2*y2;
+ Ith(ydot,2) = -yd1 - yd3;
+
+ return(0);
+}
+
+/*
+ * g routine. Compute functions g_i(t,y) for i = 0,1.
+ */
+
+static int g(realtype t, N_Vector y, realtype *gout, void *user_data)
+{
+ realtype y1, y3;
+
+ y1 = Ith(y,1); y3 = Ith(y,3);
+ gout[0] = y1 - RCONST(0.0001);
+ gout[1] = y3 - RCONST(0.01);
+
+ return(0);
+}
+
+/*
+ * 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)
+{
+ realtype y1, y2, y3;
+
+ y1 = Ith(y,1); y2 = Ith(y,2); y3 = Ith(y,3);
+
+ 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,2) = RCONST(6.0e7)*y2;
+
+ return(0);
+}
+
+/*
+ *-------------------------------
+ * Private helper functions
+ *-------------------------------
+ */
+
+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);
+#else
+ printf("At t = %0.4e y =%14.6e %14.6e %14.6e\n", t, y1, y2, y3);
+#endif
+
+ return;
+}
+
+static void PrintRootInfo(int root_f1, int root_f2)
+{
+ printf(" rootsfound[] = %3d %3d\n", root_f1, root_f2);
+
+ return;
+}
+
+/*
+ * Get and print some final statistics
+ */
+
+static void PrintFinalStats(void *cvode_mem)
+{
+ long int nst, nfe, nsetups, nje, nfeLS, nni, ncfn, netf, nge;
+ int flag;
+
+ 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 = CVDlsGetNumJacEvals(cvode_mem, &nje);
+ check_flag(&flag, "CVDlsGetNumJacEvals", 1);
+ flag = CVDlsGetNumRhsEvals(cvode_mem, &nfeLS);
+ check_flag(&flag, "CVDlsGetNumRhsEvals", 1);
+
+ flag = CVodeGetNumGEvals(cvode_mem, &nge);
+ check_flag(&flag, "CVodeGetNumGEvals", 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 = %-6ld nge = %ld\n \n",
+ nni, ncfn, netf, nge);
+}
+
+/*
+ * 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, 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/cvsRoberts_dns.out b/examples/cvodes/serial/cvsRoberts_dns.out
new file mode 100644
index 0000000..8ef3495
--- /dev/null
+++ b/examples/cvodes/serial/cvsRoberts_dns.out
@@ -0,0 +1,24 @@
+
+3-species kinetics problem
+
+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
+ 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
+
+Final Statistics:
+nst = 566 nfe = 817 nsetups = 119 nfeLS = 0 nje = 12
+nni = 813 ncfn = 0 netf = 32 nge = 600
+
diff --git a/examples/cvodes/serial/cvsRoberts_dnsL.c b/examples/cvodes/serial/cvsRoberts_dnsL.c
new file mode 100644
index 0000000..8715cfd
--- /dev/null
+++ b/examples/cvodes/serial/cvsRoberts_dnsL.c
@@ -0,0 +1,363 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.2 $
+ * $Date: 2010/12/01 22:58:00 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Example problem:
+ *
+ * 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 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 LAPACK 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 <cvodes/cvodes_lapack.h> /* prototype for CVLapackDense */
+#include <nvector/nvector_serial.h> /* serial N_Vector types, fcts., and macros */
+
+/* User-defined vector and matrix accessor macros: Ith, IJth */
+
+/* These macros are defined in order to write code which exactly matches
+ the mathematical problem description given above.
+
+ 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.
+
+ 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. */
+
+#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 */
+
+
+/* Problem Constants */
+
+#define NEQ 3 /* number of equations */
+#define Y1 RCONST(1.0) /* initial y components */
+#define Y2 RCONST(0.0)
+#define Y3 RCONST(0.0)
+#define RTOL RCONST(1.0e-4) /* scalar relative tolerance */
+#define ATOL1 RCONST(1.0e-8) /* vector absolute tolerance components */
+#define ATOL2 RCONST(1.0e-14)
+#define ATOL3 RCONST(1.0e-6)
+#define T0 RCONST(0.0) /* initial time */
+#define T1 RCONST(0.4) /* first output time */
+#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 */
+
+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);
+
+/* Private functions to output results */
+
+static void PrintOutput(realtype t, realtype y1, realtype y2, realtype y3);
+static void PrintRootInfo(int root_f1, int root_f2);
+
+/* Private function to print final statistics */
+
+static void PrintFinalStats(void *cvode_mem);
+
+/* Private function to check function return values */
+
+static int check_flag(void *flagvalue, char *funcname, int opt);
+
+
+/*
+ *-------------------------------
+ * Main Program
+ *-------------------------------
+ */
+
+int main()
+{
+ realtype reltol, t, tout;
+ N_Vector y, abstol;
+ void *cvode_mem;
+ int flag, flagr, iout;
+ int rootsfound[2];
+
+ y = abstol = NULL;
+ cvode_mem = NULL;
+
+ /* Create serial vector of length NEQ for I.C. and abstol */
+ y = N_VNew_Serial(NEQ);
+ if (check_flag((void *)y, "N_VNew_Serial", 0)) return(1);
+ abstol = N_VNew_Serial(NEQ);
+ if (check_flag((void *)abstol, "N_VNew_Serial", 0)) return(1);
+
+ /* Initialize y */
+ Ith(y,1) = Y1;
+ Ith(y,2) = Y2;
+ Ith(y,3) = Y3;
+
+ /* Set the scalar relative tolerance */
+ reltol = RTOL;
+ /* Set the vector absolute tolerance */
+ Ith(abstol,1) = ATOL1;
+ Ith(abstol,2) = ATOL2;
+ Ith(abstol,3) = ATOL3;
+
+ /* 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 inital 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 CVodeSVtolerances to specify the scalar relative tolerance
+ * and vector absolute tolerances */
+ flag = CVodeSVtolerances(cvode_mem, reltol, abstol);
+ if (check_flag(&flag, "CVodeSVtolerances", 1)) return(1);
+
+ /* Call CVodeRootInit to specify the root function g with 2 components */
+ 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);
+
+ /* Set the Jacobian routine to Jac (user-supplied) */
+ flag = CVDlsSetDenseJacFn(cvode_mem, Jac);
+ if (check_flag(&flag, "CVDlsSetDenseJacFn", 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. */
+ printf(" \n3-species kinetics problem\n\n");
+
+ iout = 0; tout = T1;
+ while(1) {
+ flag = CVode(cvode_mem, tout, y, &t, CV_NORMAL);
+ PrintOutput(t, Ith(y,1), Ith(y,2), Ith(y,3));
+
+ if (flag == CV_ROOT_RETURN) {
+ flagr = CVodeGetRootInfo(cvode_mem, rootsfound);
+ if (check_flag(&flagr, "CVodeGetRootInfo", 1)) return(1);
+ PrintRootInfo(rootsfound[0],rootsfound[1]);
+ }
+
+ if (check_flag(&flag, "CVode", 1)) break;
+ if (flag == CV_SUCCESS) {
+ iout++;
+ tout *= TMULT;
+ }
+
+ if (iout == NOUT) break;
+ }
+
+ /* Print some final statistics */
+ PrintFinalStats(cvode_mem);
+
+ /* Free y vector */
+ N_VDestroy_Serial(y);
+
+ /* Free integrator memory */
+ CVodeFree(&cvode_mem);
+
+ return(0);
+}
+
+
+/*
+ *-------------------------------
+ * Functions called by the solver
+ *-------------------------------
+ */
+
+/*
+ * f routine. Compute function f(t,y).
+ */
+
+static int f(realtype t, N_Vector y, N_Vector ydot, void *user_data)
+{
+ realtype y1, y2, y3, yd1, yd3;
+
+ y1 = Ith(y,1); y2 = Ith(y,2); y3 = Ith(y,3);
+
+ yd1 = Ith(ydot,1) = RCONST(-0.04)*y1 + RCONST(1.0e4)*y2*y3;
+ yd3 = Ith(ydot,3) = RCONST(3.0e7)*y2*y2;
+ Ith(ydot,2) = -yd1 - yd3;
+
+ return(0);
+}
+
+/*
+ * g routine. Compute functions g_i(t,y) for i = 0,1.
+ */
+
+static int g(realtype t, N_Vector y, realtype *gout, void *user_data)
+{
+ realtype y1, y3;
+
+ y1 = Ith(y,1); y3 = Ith(y,3);
+ gout[0] = y1 - RCONST(0.0001);
+ gout[1] = y3 - RCONST(0.01);
+
+ return(0);
+}
+
+/*
+ * 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)
+{
+ realtype y1, y2, y3;
+
+ y1 = Ith(y,1); y2 = Ith(y,2); y3 = Ith(y,3);
+
+ 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);
+}
+
+/*
+ *-------------------------------
+ * Private helper functions
+ *-------------------------------
+ */
+
+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);
+#else
+ printf("At t = %0.4e y =%14.6e %14.6e %14.6e\n", t, y1, y2, y3);
+#endif
+
+ return;
+}
+
+static void PrintRootInfo(int root_f1, int root_f2)
+{
+ printf(" rootsfound[] = %3d %3d\n", root_f1, root_f2);
+
+ return;
+}
+
+/*
+ * Get and print some final statistics
+ */
+
+static void PrintFinalStats(void *cvode_mem)
+{
+ long int nst, nfe, nsetups, nje, nfeLS, nni, ncfn, netf, nge;
+ int flag;
+
+ 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 = CVDlsGetNumJacEvals(cvode_mem, &nje);
+ check_flag(&flag, "CVDlsGetNumJacEvals", 1);
+ flag = CVDlsGetNumRhsEvals(cvode_mem, &nfeLS);
+ check_flag(&flag, "CVDlsGetNumRhsEvals", 1);
+
+ flag = CVodeGetNumGEvals(cvode_mem, &nge);
+ check_flag(&flag, "CVodeGetNumGEvals", 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 = %-6ld nge = %ld\n \n",
+ nni, ncfn, netf, nge);
+}
+
+/*
+ * 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, 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/cvsRoberts_dnsL.out b/examples/cvodes/serial/cvsRoberts_dnsL.out
new file mode 100644
index 0000000..0e27ff1
--- /dev/null
+++ b/examples/cvodes/serial/cvsRoberts_dnsL.out
@@ -0,0 +1,24 @@
+
+3-species kinetics problem
+
+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
+ 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
+
+Final Statistics:
+nst = 595 nfe = 857 nsetups = 125 nfeLS = 0 nje = 12
+nni = 853 ncfn = 0 netf = 34 nge = 629
+
diff --git a/examples/cvodes/serial/cvsRoberts_dns_uw.c b/examples/cvodes/serial/cvsRoberts_dns_uw.c
new file mode 100644
index 0000000..93651a4
--- /dev/null
+++ b/examples/cvodes/serial/cvsRoberts_dns_uw.c
@@ -0,0 +1,377 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.2 $
+ * $Date: 2010/12/01 22:58:00 $
+ * -----------------------------------------------------------------
+ * 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 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 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
+ * 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 */
+
+/* User-defined vector and matrix accessor macros: Ith, IJth */
+
+/* These macros are defined in order to write code which exactly matches
+ the mathematical problem description given above.
+
+ 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.
+
+ 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. */
+
+#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 */
+
+
+/* Problem Constants */
+
+#define NEQ 3 /* number of equations */
+#define Y1 RCONST(1.0) /* initial y components */
+#define Y2 RCONST(0.0)
+#define Y3 RCONST(0.0)
+#define RTOL RCONST(1.0e-4) /* scalar relative tolerance */
+#define ATOL1 RCONST(1.0e-8) /* vector absolute tolerance components */
+#define ATOL2 RCONST(1.0e-14)
+#define ATOL3 RCONST(1.0e-6)
+#define T0 RCONST(0.0) /* initial time */
+#define T1 RCONST(0.4) /* first output time */
+#define TMULT RCONST(10.0) /* output time factor */
+#define NOUT 12 /* number of output times */
+
+
+/* Functions Called by the Solver */
+
+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 ewt(N_Vector y, N_Vector w, void *user_data);
+
+/* Private functions to output results */
+
+static void PrintOutput(realtype t, realtype y1, realtype y2, realtype y3);
+static void PrintRootInfo(int root_f1, int root_f2);
+
+/* Private function to print final statistics */
+
+static void PrintFinalStats(void *cvode_mem);
+
+/* Private function to check function return values */
+
+static int check_flag(void *flagvalue, char *funcname, int opt);
+
+
+/*
+ *-------------------------------
+ * Main Program
+ *-------------------------------
+ */
+
+int main()
+{
+ realtype t, tout;
+ N_Vector y;
+ void *cvode_mem;
+ int flag, flagr, iout;
+ int rootsfound[2];
+
+ y = NULL;
+ cvode_mem = NULL;
+
+ /* Create serial vector of length NEQ for I.C. */
+ y = N_VNew_Serial(NEQ);
+ if (check_flag((void *)y, "N_VNew_Serial", 0)) return(1);
+
+ /* Initialize y */
+ Ith(y,1) = Y1;
+ Ith(y,2) = Y2;
+ Ith(y,3) = Y3;
+
+ /* 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 inital time T0, and
+ * the initial dependent variable vector y. */
+ flag = CVodeInit(cvode_mem, f, T0, y);
+ if (check_flag(&flag, "CVodeInit", 1)) return(1);
+
+ /* Use private function to compute error weights */
+ flag = CVodeWFtolerances(cvode_mem, ewt);
+ if (check_flag(&flag, "CVodeSetEwtFn", 1)) return(1);
+
+ /* Call CVodeRootInit to specify the root function g with 2 components */
+ 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);
+
+ /* Set the Jacobian routine to Jac (user-supplied) */
+ flag = CVDlsSetDenseJacFn(cvode_mem, Jac);
+ if (check_flag(&flag, "CVDlsSetDenseJacFn", 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. */
+ printf(" \n3-species kinetics problem\n\n");
+
+ iout = 0; tout = T1;
+ while(1) {
+ flag = CVode(cvode_mem, tout, y, &t, CV_NORMAL);
+ PrintOutput(t, Ith(y,1), Ith(y,2), Ith(y,3));
+
+ if (flag == CV_ROOT_RETURN) {
+ flagr = CVodeGetRootInfo(cvode_mem, rootsfound);
+ check_flag(&flagr, "CVodeGetRootInfo", 1);
+ PrintRootInfo(rootsfound[0],rootsfound[1]);
+ }
+
+ if (check_flag(&flag, "CVode", 1)) break;
+ if (flag == CV_SUCCESS) {
+ iout++;
+ tout *= TMULT;
+ }
+
+ if (iout == NOUT) break;
+ }
+
+ /* Print some final statistics */
+ PrintFinalStats(cvode_mem);
+
+ /* Free y vector */
+ N_VDestroy_Serial(y);
+
+ /* Free integrator memory */
+ CVodeFree(&cvode_mem);
+
+ return(0);
+}
+
+
+/*
+ *-------------------------------
+ * Functions called by the solver
+ *-------------------------------
+ */
+
+/*
+ * f routine. Compute function f(t,y).
+ */
+
+static int f(realtype t, N_Vector y, N_Vector ydot, void *user_data)
+{
+ realtype y1, y2, y3, yd1, yd3;
+
+ y1 = Ith(y,1); y2 = Ith(y,2); y3 = Ith(y,3);
+
+ yd1 = Ith(ydot,1) = RCONST(-0.04)*y1 + RCONST(1.0e4)*y2*y3;
+ yd3 = Ith(ydot,3) = RCONST(3.0e7)*y2*y2;
+ Ith(ydot,2) = -yd1 - yd3;
+
+ return(0);
+}
+
+/*
+ * g routine. Compute functions g_i(t,y) for i = 0,1.
+ */
+
+static int g(realtype t, N_Vector y, realtype *gout, void *user_data)
+{
+ realtype y1, y3;
+
+ y1 = Ith(y,1); y3 = Ith(y,3);
+ gout[0] = y1 - RCONST(0.0001);
+ gout[1] = y3 - RCONST(0.01);
+
+ return(0);
+}
+
+/*
+ * 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)
+{
+ realtype y1, y2, y3;
+
+ y1 = Ith(y,1); y2 = Ith(y,2); y3 = Ith(y,3);
+
+ 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,2) = RCONST(6.0e7)*y2;
+
+ return(0);
+}
+
+/*
+ * EwtSet function. Computes the error weights at the current solution.
+ */
+
+static int ewt(N_Vector y, N_Vector w, void *user_data)
+{
+ int i;
+ realtype yy, ww, rtol, atol[3];
+
+ rtol = RTOL;
+ atol[0] = ATOL1;
+ atol[1] = ATOL2;
+ atol[2] = ATOL3;
+
+ for (i=1; i<=3; i++) {
+ yy = Ith(y,i);
+ ww = rtol * ABS(yy) + atol[i-1];
+ if (ww <= 0.0) return (-1);
+ Ith(w,i) = 1.0/ww;
+ }
+
+ return(0);
+}
+
+/*
+ *-------------------------------
+ * Private helper functions
+ *-------------------------------
+ */
+
+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);
+#else
+ printf("At t = %0.4e y =%14.6e %14.6e %14.6e\n", t, y1, y2, y3);
+#endif
+
+ return;
+}
+
+static void PrintRootInfo(int root_f1, int root_f2)
+{
+ printf(" rootsfound[] = %3d %3d\n", root_f1, root_f2);
+
+ return;
+}
+
+/*
+ * Get and print some final statistics
+ */
+
+static void PrintFinalStats(void *cvode_mem)
+{
+ long int nst, nfe, nsetups, nje, nfeLS, nni, ncfn, netf, nge;
+ int flag;
+
+ 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 = CVDlsGetNumJacEvals(cvode_mem, &nje);
+ check_flag(&flag, "CVDlsGetNumJacEvals", 1);
+ flag = CVDlsGetNumRhsEvals(cvode_mem, &nfeLS);
+ check_flag(&flag, "CVDlsGetNumRhsEvals", 1);
+
+ flag = CVodeGetNumGEvals(cvode_mem, &nge);
+ check_flag(&flag, "CVodeGetNumGEvals", 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 = %-6ld nge = %ld\n \n",
+ nni, ncfn, netf, nge);
+}
+
+/*
+ * 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, 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/cvsRoberts_dns_uw.out b/examples/cvodes/serial/cvsRoberts_dns_uw.out
new file mode 100644
index 0000000..14add0b
--- /dev/null
+++ b/examples/cvodes/serial/cvsRoberts_dns_uw.out
@@ -0,0 +1,24 @@
+
+3-species kinetics problem
+
+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
+ 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
+
+Final Statistics:
+nst = 534 nfe = 796 nsetups = 127 nfeLS = 0 nje = 12
+nni = 792 ncfn = 0 netf = 35 nge = 564
+
diff --git a/examples/ida/fcmix_parallel/CMakeLists.txt b/examples/ida/fcmix_parallel/CMakeLists.txt
new file mode 100644
index 0000000..147c466
--- /dev/null
+++ b/examples/ida/fcmix_parallel/CMakeLists.txt
@@ -0,0 +1,118 @@
+# ---------------------------------------------------------------
+# $Revision: 1.4 $
+# $Date: 2009/02/17 02:58:47 $
+# ---------------------------------------------------------------
+# Programmer: Radu Serban @ LLNL
+# ---------------------------------------------------------------
+# Copyright (c) 2007, The Regents of the University of California.
+# Produced at the Lawrence Livermore National Laboratory.
+# All rights reserved.
+# For details, see the LICENSE file.
+# ---------------------------------------------------------------
+# CMakeLists.txt file for the FIDA parallel examples
+
+
+# Add variable ida_examples with the names of the parallel IDA examples
+
+SET(FIDA_examples
+ fidaHeat2D_kry_bbd_p
+ )
+
+# 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 )
+ # use MPI_MPIF77 as the compiler
+ SET(CMAKE_Fortran_COMPILER ${MPI_MPIF77})
+ELSE(MPI_MPIF77)
+ # add MPI_INCLUDE_PATH to include directories
+ INCLUDE_DIRECTORIES(${MPI_INCLUDE_PATH})
+ENDIF(MPI_MPIF77)
+
+# 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")
+ SET(IDA_LIB sundials_ida_shared)
+ SET(NVECP_LIB sundials_nvecparallel_shared)
+ SET(FNVECP_LIB sundials_fnvecparallel_shared)
+ENDIF(LINK_LIBRARY_TYPE MATCHES "static")
+
+# 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)
+ SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${LAPACK_LINKER_FLAGS}")
+ SET(SUNDIALS_LIBS "${SUNDIALS_LIBS} ${LAPACK_LIBRARIES}")
+ENDIF(LAPACK_FOUND)
+
+# Add the build and install targets for each IDA example
+
+FOREACH(example ${FIDA_examples})
+ ADD_EXECUTABLE(${example} ${example}.f)
+ TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+ IF(NOT MPI_MPIF77)
+ TARGET_LINK_LIBRARIES(${example} ${MPI_LIBRARY} ${MPI_EXTRA_LIBRARIES})
+ ENDIF(NOT MPI_MPIF77)
+ IF(EXAMPLES_INSTALL)
+ INSTALL(FILES ${example}.f ${example}.out DESTINATION ${EXAMPLES_INSTALL_PATH}/ida/fcmix_parallel)
+ ENDIF(EXAMPLES_INSTALL)
+ENDFOREACH(example ${FIDA_examples})
+
+IF(EXAMPLES_INSTALL)
+
+ # Install the README file
+ INSTALL(FILES README DESTINATION ${EXAMPLES_INSTALL_PATH}/ida/fcmix_parallel)
+
+ # Prepare substitution variables for Makefile and/or CMakeLists templates
+ SET(SOLVER "IDA")
+ SET(SOLVER_LIB "sundials_ida")
+ SET(SOLVER_FLIB "sundials_fida")
+ LIST2STRING(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
+ )
+
+ # install CMakelists.txt
+ INSTALL(
+ FILES ${PROJECT_BINARY_DIR}/examples/ida/fcmix_parallel/CMakeLists.txt
+ 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
+ # 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_F77_ex.in
+ ${PROJECT_BINARY_DIR}/examples/ida/fcmix_parallel/Makefile_ex
+ @ONLY
+ )
+ # 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
+ RENAME Makefile
+ )
+ ENDIF(UNIX)
+
+ENDIF(EXAMPLES_INSTALL)
diff --git a/examples/ida/fcmix_parallel/Makefile.in b/examples/ida/fcmix_parallel/Makefile.in
new file mode 100644
index 0000000..827ea68
--- /dev/null
+++ b/examples/ida/fcmix_parallel/Makefile.in
@@ -0,0 +1,114 @@
+# -----------------------------------------------------------------
+# $Revision: 1.9 $
+# $Date: 2009/02/17 02:58:47 $
+# -----------------------------------------------------------------
+# Programmer(s): Radu Serban and Aaron Collier @ 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.
+# -----------------------------------------------------------------
+# Makefile for FIDA parallel examples
+#
+# @configure_input@
+# -----------------------------------------------------------------
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_builddir = @top_builddir@
+builddir = @builddir@
+abs_builddir = @abs_builddir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+includedir = @includedir@
+libdir = @libdir@
+
+INSTALL = @INSTALL@
+INSTALL_PROG = @INSTALL_PROGRAM@
+INSTALL_FILE = @INSTALL_DATA@
+
+LIBTOOL = @LIBTOOL@
+LIBTOOL_DEPS = @LIBTOOL_DEPS@
+
+FFLAGS = @FFLAGS@
+F77_LDFLAGS = @F77_LDFLAGS@
+F77_LIBS = @F77_LIBS@
+
+MPIF77 = @MPIF77@
+MPI_INC_DIR = @MPI_INC_DIR@
+MPI_FLAGS = @MPI_FLAGS@
+MPIF77_LNKR = @MPIF77_LNKR@
+MPI_LIB_DIR = @MPI_LIB_DIR@
+MPI_LIBS = @MPI_LIBS@
+
+BLAS_LAPACK_LIBS = @BLAS_LAPACK_LIBS@
+
+OBJ_EXT = @OBJEXT@
+EXE_EXT = @EXEEXT@
+
+EXS_INSTDIR = @EXS_INSTDIR@
+
+top_srcdir = $(srcdir)/../../..
+
+SUNDIALS_LIBS = $(top_builddir)/src/ida/fcmix/libsundials_fida.la \
+ $(top_builddir)/src/ida/libsundials_ida.la \
+ $(top_builddir)/src/nvec_par/libsundials_fnvecparallel.la \
+ $(top_builddir)/src/nvec_par/libsundials_nvecparallel.la
+
+fortran-update = ${SHELL} ${top_builddir}/bin/fortran-update.sh
+
+mkinstalldirs = $(SHELL) $(top_srcdir)/config/mkinstalldirs
+rminstalldirs = $(SHELL) $(top_srcdir)/config/rminstalldirs
+
+EXAMPLES = fidaHeat2D_kry_bbd_p
+
+OBJECTS = ${EXAMPLES:=${OBJ_EXT}}
+EXECS = ${EXAMPLES:=${EXE_EXT}}
+
+# ----------------------------------------------------------------------------------------------------------------------
+
+all:
+ @for i in ${EXAMPLES} ; do \
+ ${fortran-update} ${srcdir} $${i}.f ; \
+ ${LIBTOOL} --mode=compile ${MPIF77} ${MPI_FLAGS} -I${MPI_INC_DIR} ${FFLAGS} -c ${builddir}/$${i}-updated.f ; \
+ ${LIBTOOL} --mode=link ${MPIF77_LNKR} -o ${builddir}/$${i}${EXE_EXT} ${builddir}/$${i}-updated${OBJ_EXT} ${MPI_FLAGS} ${F77_LDFLAGS} ${SUNDIALS_LIBS} -L${MPI_LIB_DIR} ${MPI_LIBS} ${F77_LIBS} $(BLAS_LAPACK_LIBS) ; \
+ done
+
+install:
+ $(mkinstalldirs) $(EXS_INSTDIR)/ida/fcmix_parallel
+ $(INSTALL_FILE) Makefile_ex $(EXS_INSTDIR)/ida/fcmix_parallel/Makefile
+ $(INSTALL_FILE) $(top_srcdir)/examples/ida/fcmix_parallel/README $(EXS_INSTDIR)/ida/fcmix_parallel/
+ for i in ${EXAMPLES} ; do \
+ $(INSTALL_FILE) $(top_srcdir)/examples/ida/fcmix_parallel/$${i}.f $(EXS_INSTDIR)/ida/fcmix_parallel/ ; \
+ $(INSTALL_FILE) $(top_srcdir)/examples/ida/fcmix_parallel/$${i}.out $(EXS_INSTDIR)/ida/fcmix_parallel/ ; \
+ done
+
+uninstall:
+ rm -f $(EXS_INSTDIR)/ida/fcmix_parallel/Makefile
+ rm -f $(EXS_INSTDIR)/ida/fcmix_parallel/README
+ for i in ${EXAMPLES} ; do \
+ rm -f $(EXS_INSTDIR)/ida/fcmix_parallel/$${i}.f ; \
+ rm -f $(EXS_INSTDIR)/ida/fcmix_parallel/$${i}.out ; \
+ done
+ $(rminstalldirs) $(EXS_INSTDIR)/ida/fcmix_parallel
+ $(rminstalldirs) $(EXS_INSTDIR)/ida
+
+clean:
+ rm -rf .libs
+ rm -f *.lo *.o
+ rm -f *-updated.f
+ rm -f ${OBJECTS}
+ rm -f $(EXECS)
+
+distclean: clean
+ rm -f Makefile
+ rm -f Makefile_ex
+
+# ----------------------------------------------------------------------------------------------------------------------
+
+libtool: $(top_builddir)/$(LIBTOOL_DEPS)
+ @cd ${top_builddir} ; \
+ ${SHELL} ./config.status --recheck ; \
+ cd ${abs_builddir}
diff --git a/examples/ida/fcmix_parallel/README b/examples/ida/fcmix_parallel/README
new file mode 100644
index 0000000..1e3a43d
--- /dev/null
+++ b/examples/ida/fcmix_parallel/README
@@ -0,0 +1,15 @@
+List of parallel IDA FCMIX examples
+
+ fidaHeat2D_kry_bbd_p : 2D heat equation (SPGMR w/FIDABBD preconditioner)
+
+Sample results:
+
+ SUNDIALS was built with the following options:
+
+ ./configure CC=gcc F77=gfortran CFLAGS="-g3 -O0" FFLAGS="-g3 -O0" --enable-examples
+
+ System Architecture: IA-32
+ Processor Type: Intel Pentium 4 Xeon DP (i686)
+ Operating System: Red Hat Enterprise Linux WS 3 (Taroon Update 7)
+ C/Fortran Compilers: gcc/gfortran v4.1.0
+ MPI Implementation: Open MPI v1.1
diff --git a/examples/ida/fcmix_parallel/fidaHeat2D_kry_bbd_p.f b/examples/ida/fcmix_parallel/fidaHeat2D_kry_bbd_p.f
new file mode 100644
index 0000000..901e47e
--- /dev/null
+++ b/examples/ida/fcmix_parallel/fidaHeat2D_kry_bbd_p.f
@@ -0,0 +1,830 @@
+c ----------------------------------------------------------------
+c $Revision: 1.3 $
+c $Date: 2009/09/30 23:29:59 $
+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 preconditioning.
+c
+c The DAE system solved is a spatial discretization of the PDE
+c du/dt = d^2u/dx^2 + d^2u/dy^2
+c on the unit square. The boundary condition is u = 0 on all edges.
+c Initial conditions are given by u = 16 x (1 - x) y (1 - y). The
+c PDE is treated with central differences on a uniform MX x MY
+c grid. The values of u at the interior points satisfy ODEs, and
+c equations u = 0 at the boundaries are appended, to form a DAE
+c system of size N = MX * MY. Here MX = MY = 10.
+c
+c The system is actually implemented on submeshes, processor by
+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 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
+c suppressed. Output is taken at t = 0, .01, .02, .04, ..., 10.24.
+c ----------------------------------------------------------------
+c
+ program fidaHeat2D_kry_bbd_p
+c
+ include "mpif.h"
+c
+c global variables
+c
+ integer*4 nlocal, neq, npex, npey, mxsub, mysub, mx, my
+ integer*4 ixsub, jysub
+ integer thispe
+ integer mxsubg, mysubg, nlocalg
+ parameter (mxsubg = 5, mysubg = 5)
+ parameter (nlocalg = mxsubg*mysubg)
+ double precision dx, dy, coeffx, coeffy, coeffxy
+ double precision uext((mxsubg+2)*(mysubg+2))
+c
+c local variables
+c
+ integer*4 mudq, mldq, mukeep, mlkeep
+ integer*4 iout(25), ipar
+ double precision rout(10), rpar
+ integer nout, ier
+ parameter (nout = 11)
+ integer npes, inopt, maxl, gstype, maxrs, itask, iatol
+ double precision t0, t1, tout, tret, dqrely, eplifac, dqincfac
+ double precision atol, rtol
+ double precision constr(nlocalg), uu(nlocalg), up(nlocalg)
+ double precision res(nlocalg), id(nlocalg)
+c
+ data atol/1.0d-3/, rtol/0.0d0/
+c
+ common /pcom/ dx, dy, coeffx, coeffy, coeffxy, uext,
+ & nlocal, neq, mx, my, mxsub, mysub, npey, npex,
+ & ixsub, jysub, thispe
+c
+c Initialize variables
+c
+ npex = 2
+ npey = 2
+ mxsub = 5
+ mysub = 5
+ mx = npex*mxsub
+ my = npey*mysub
+ neq = mx*my
+ nlocal = mxsub*mysub
+ inopt = 1
+ t0 = 0.0d0
+ t1 = 0.01d0
+ mudq = mxsub
+ mldq = mxsub
+ mukeep = 1
+ mlkeep = 1
+ dqrely = 0.0d0
+ maxl = 0
+ gstype = 0
+ maxrs = 0
+ eplifac = 0.0d0
+ dqincfac = 0.0d0
+ itask = 1
+ iatol = 1
+c
+c Initialize MPI environment
+c
+ call mpi_init(ier)
+ if (ier .ne. 0) then
+ write(*,2) ier
+ 2 format(///' MPI_ERROR: MPI_INIT returned IER = ', i5)
+ stop
+ endif
+c
+ call mpi_comm_size(mpi_comm_world, npes, ier)
+ if (ier .ne. 0) then
+ write(*,3) ier
+ 3 format(///' MPI_ERROR: MPI_COMM_SIZE returned IER = ', i5)
+ call mpi_abort(mpi_comm_world, 1, ier)
+ stop
+ endif
+c
+ call mpi_comm_rank(mpi_comm_world, thispe, ier)
+ if (ier .ne. 0) then
+ write(*,4) ier
+ 4 format(///' MPI_ERROR: MPI_COMM_RANK returned IER = ', i5)
+ call mpi_abort(mpi_comm_world, 1, ier)
+ stop
+ endif
+c
+ if (npes .ne. npex*npey) then
+ if (thispe .eq. 0) then
+ write(*,5) npes, npex*npey
+ 5 format(///' MPI_ERROR: npes = ', i5, ' is not equal to ',
+ & 'NPEX*NPEY = ', i5)
+ call mpi_finalize(ier)
+ stop
+ endif
+ endif
+c
+ call fnvinitp(mpi_comm_world, 2, nlocal, neq, ier)
+ if (ier .ne. 0) then
+ write(*,6) ier
+ 6 format(///' SUNDIALS_ERROR: FNVINITP returned IER = ', i5)
+ call mpi_finalize(ier)
+ stop
+ endif
+c
+ jysub = int(thispe/npex)
+ ixsub = thispe-jysub*npex
+c
+c Initialize problem data
+c
+ call setinitprofile(uu, up, id, res, constr, ipar, rpar)
+c
+c Initialize IDA environment
+c
+ call fidamalloc(t0, uu, up, iatol, rtol, atol,
+ & iout, rout, ipar, rpar, ier)
+ if (ier .ne. 0) then
+ write(*,7) ier
+ 7 format(///' SUNDIALS_ERROR: FIDAMALLOC returned IER = ', i5)
+ call mpi_abort(mpi_comm_world, 1, ier)
+ stop
+ endif
+c
+c Set optional inputs
+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
+ call fidaspgmr(maxl, gstype, maxrs, eplifac, dqincfac, ier)
+ if (ier .ne. 0) then
+ write(*,9) ier
+ 9 format(///' SUNDIALS_ERROR: FIDABBDSPGMR returned IER = ', i5)
+ call mpi_abort(mpi_comm_world, 1, ier)
+ stop
+ endif
+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)
+ call mpi_abort(mpi_comm_world, 1, ier)
+ stop
+ endif
+c
+c Print header
+c
+ if (thispe .eq. 0) then
+ call prntintro(rtol, atol)
+ call prntcase(1, mudq, mukeep)
+ endif
+c
+ tout = t1
+ do 10 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)
+ call fidafree
+ stop
+ endif
+c
+ tout = tout*2.0d0
+c
+ 10 continue
+c
+c Print statistics
+c
+ if (thispe .eq. 0) then
+ call prntfinalstats(iout)
+ endif
+c
+c Reinitialize variables and data for second problem
+c
+ mudq = 1
+ mldq = 1
+c
+ call setinitprofile(uu, up, id, res, constr, ipar, rpar)
+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)
+ 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)
+ call fidafree
+ stop
+ endif
+c
+c Print header
+c
+ if (thispe .eq. 0) then
+ call prntcase(2, mudq, mukeep)
+ endif
+c
+ tout = t1
+ 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(*,13) ier
+ 13 format(///' SUNDIALS_ERROR: FIDASOLVE returned IER = ', i5)
+ call fidafree
+ stop
+ endif
+c
+ tout = tout*2.0d0
+c
+ 12 continue
+c
+c Print statistics
+c
+ if (thispe .eq. 0) then
+ call prntfinalstats(iout)
+ endif
+c
+c Free memory
+c
+ call fidafree
+c
+ call mpi_finalize(ier)
+c
+ stop
+ end
+c
+c ==========
+c
+ subroutine setinitprofile(uu, up, id, res, constr, ipar, rpar)
+c
+c global variables
+c
+ integer*4 nlocal, neq, npex, npey, mxsub, mysub, mx, my
+ integer*4 ixsub, jysub, ipar(*)
+ integer thispe
+ integer mxsubg, mysubg, nlocalg
+ parameter (mxsubg = 5, mysubg = 5)
+ parameter (nlocalg = mxsubg*mysubg)
+ double precision dx, dy, coeffx, coeffy, coeffxy, rpar(*)
+ double precision uext((mxsubg+2)*(mysubg+2))
+c
+c local variables
+c
+ integer*4 i, iloc, j, jloc, offset, loc
+ integer*4 ixbegin, ixend, jybegin, jyend
+ integer reserr
+ double precision xfact, yfact
+ double precision uu(*), up(*), id(*), res(*), constr(*)
+c
+ common /pcom/ dx, dy, coeffx, coeffy, coeffxy, uext,
+ & nlocal, neq, mx, my, mxsub, mysub, npey, npex,
+ & ixsub, jysub, thispe
+c
+c Initialize variables
+c
+ dx = 1.0d0/dble(mx-1)
+ dy = 1.0d0/dble(my-1)
+ coeffx = 1.0d0/(dx*dx)
+ coeffy = 1.0d0/(dy*dy)
+ coeffxy = 2.0d0/(dx*dx)+2.0d0/(dy*dy)
+ ixbegin = mxsub*ixsub
+ ixend = mxsub*(ixsub+1)-1
+ jybegin = mysub*jysub
+ jyend = mysub*(jysub+1)-1
+c
+ do 14 i = 1, nlocal
+ id(i) = 1.0d0
+ 14 continue
+c
+ jloc = 0
+ do 15 j = jybegin, jyend
+ yfact = dy*dble(j)
+ offset = jloc*mxsub
+ iloc = 0
+ do 16 i = ixbegin, ixend
+ xfact = dx*dble(i)
+ loc = offset+iloc
+ uu(loc+1) = 16.0d0*xfact*(1.0d0-xfact)*yfact*(1.0d0-yfact)
+ if (i .eq. 0 .or. i .eq. mx-1) then
+ id(loc+1) = 0.0d0
+ endif
+ if (j .eq. 0 .or. j .eq. my-1) then
+ id(loc+1) = 0.0d0
+ endif
+ iloc = iloc+1
+ 16 continue
+ jloc = jloc+1
+ 15 continue
+c
+ do 17 i = 1, nlocal
+ up(i) = 0.0d0
+ constr(i) = 1.0d0
+ 17 continue
+c
+ call fidaresfun(0.0d0, uu, up, res, ipar, rpar, reserr)
+c
+ do 18 i = 1, nlocal
+ up(i) = -1.0d0*res(i)
+ 18 continue
+c
+ return
+ end
+c
+c ==========
+c
+ subroutine fidaresfun(tres, u, up, res, ipar, rpar, reserr)
+c
+c global variables
+c
+ integer*4 nlocal, neq, npex, npey, mxsub, mysub, mx, my
+ integer*4 ixsub, jysub, ipar(*)
+ integer thispe
+ integer mxsubg, mysubg, nlocalg
+ parameter (mxsubg = 5, mysubg = 5)
+ parameter (nlocalg = mxsubg*mysubg)
+ double precision dx, dy, coeffx, coeffy, coeffxy, rpar(*)
+ double precision uext((mxsubg+2)*(mysubg+2))
+c
+c local variables
+c
+ integer reserr
+ double precision tres
+ double precision u(*), up(*), res(*)
+c
+ common /pcom/ dx, dy, coeffx, coeffy, coeffxy, uext,
+ & nlocal, neq, mx, my, mxsub, mysub, npey, npex,
+ & ixsub, jysub, thispe
+c
+ call fidacommfn(nlocal, tres, u, up, ipar, rpar, reserr)
+c
+ call fidaglocfn(nlocal, tres, u, up, res, ipar, rpar, reserr)
+c
+ return
+ end
+c
+c ==========
+c
+ subroutine fidacommfn(nloc, tres, u, up, ipar, rpar, reserr)
+c
+ include "mpif.h"
+c
+c global variables
+c
+ integer*4 nlocal, neq, npex, npey, mxsub, mysub, mx, my
+ integer*4 ixsub, jysub, ipar(*)
+ integer thispe
+ integer mxsubg, mysubg, nlocalg
+ parameter (mxsubg = 5, mysubg = 5)
+ parameter (nlocalg = mxsubg*mysubg)
+ double precision dx, dy, coeffx, coeffy, coeffxy, rpar(*)
+ double precision uext((mxsubg+2)*(mysubg+2))
+c
+c local variables
+c
+ integer*4 nloc
+ integer reserr
+ double precision tres, u(*), up(*)
+c
+ integer request(mpi_status_size)
+ double precision buffer(2*mysub)
+c
+ common /pcom/ dx, dy, coeffx, coeffy, coeffxy, uext,
+ & nlocal, neq, mx, my, mxsub, mysub, npey, npex,
+ & ixsub, jysub, thispe
+c
+ call brecvpost(request, mxsub, mysub, buffer)
+c
+ call bsend(mxsub, mysub, u)
+c
+ call brecvwait(request, mxsub, buffer)
+c
+ return
+ end
+c
+c ==========
+c
+ subroutine fidaglocfn(nloc, tres, u, up, res, ipar, rpar, reserr)
+c
+c global variables
+c
+ integer*4 nlocal, neq, npex, npey, mxsub, mysub, mx, my
+ integer*4 ixsub, jysub, ipar(*)
+ integer thispe
+ integer mxsubg, mysubg, nlocalg
+ parameter (mxsubg = 5, mysubg = 5)
+ parameter (nlocalg = mxsubg*mysubg)
+ double precision dx, dy, coeffx, coeffy, coeffxy, rpar(*)
+ double precision uext((mxsubg+2)*(mysubg+2))
+c
+c local variables
+c
+ integer*4 nloc
+ integer reserr
+ double precision tres, u(*), up(*), res(*)
+c
+ integer*4 i, lx, ly, offsetu, offsetue, locu, locue
+ integer*4 ixbegin, ixend, jybegin, jyend, mxsub2
+ double precision termx, termy, termctr
+c
+ common /pcom/ dx, dy, coeffx, coeffy, coeffxy, uext,
+ & nlocal, neq, mx, my, mxsub, mysub, npey, npex,
+ & ixsub, jysub, thispe
+c
+ mxsub2 = mxsub+2
+c
+ do 19 i = 1, nlocal
+ res(i) = u(i)
+ 19 continue
+c
+ offsetu = 0
+ offsetue = mxsub2+1
+ do 20 ly = 0, mysub-1
+ do 21 lx = 0, mxsub-1
+ uext(offsetue+lx+1) = u(offsetu+lx+1)
+ 21 continue
+ offsetu = offsetu+mxsub
+ offsetue = offsetue+mxsub2
+ 20 continue
+c
+ ixbegin = 0
+ ixend = mxsub-1
+ jybegin = 0
+ jyend = mysub-1
+ if (ixsub .eq. 0) then
+ ixbegin = ixbegin+1
+ endif
+ if (ixsub .eq. npex-1) then
+ ixend = ixend-1
+ endif
+ if (jysub .eq. 0) then
+ jybegin = jybegin+1
+ endif
+ if (jysub .eq. npey-1) then
+ jyend = jyend-1
+ endif
+c
+ do 22 ly = jybegin, jyend
+ do 23 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
+c
+ return
+ end
+c
+c ==========
+c
+ subroutine bsend(dsizex, dsizey, uarray)
+c
+ include "mpif.h"
+c
+c global variables
+c
+ integer*4 nlocal, neq, npex, npey, mxsub, mysub, mx, my
+ integer*4 ixsub, jysub
+ integer thispe
+ integer mxsubg, mysubg, nlocalg
+ parameter (mxsubg = 5, mysubg = 5)
+ parameter (nlocalg = mxsubg*mysubg)
+ double precision dx, dy, coeffx, coeffy, coeffxy
+ double precision uext((mxsubg+2)*(mysubg+2))
+c
+c local variables
+c
+ integer*4 dsizex, dsizey
+ double precision uarray(*)
+c
+ integer ier, offsetu
+ double precision bufleft(mysub), bufright(mysub)
+c
+ common /pcom/ dx, dy, coeffx, coeffy, coeffxy, uext,
+ & nlocal, neq, mx, my, mxsub, mysub, npey, npex,
+ & ixsub, jysub, thispe
+c
+ if (jysub .ne. 0) then
+ call mpi_send(uarray(1), dsizex, mpi_double_precision,
+ & thispe-npex, 0, mpi_comm_world, ier)
+ endif
+c
+ if (jysub .ne. npey-1) then
+ offsetu = (mysub-1)*dsizex
+ call mpi_send(uarray(offsetu+1), dsizex, mpi_double_precision,
+ & thispe+npex, 0, mpi_comm_world, ier)
+ endif
+c
+ if (ixsub .ne. 0) then
+ do 24 ly = 0, mysub-1
+ offsetu = ly*dsizex
+ bufleft(ly+1) = uarray(offsetu+1)
+ 24 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
+ offsetu = ly*mxsub+(mxsub-1)
+ bufright(ly+1) = uarray(offsetu+1)
+ 25 continue
+ call mpi_send(bufright(1), dsizey, mpi_double_precision,
+ & thispe+1, 0, mpi_comm_world, ier)
+ endif
+c
+ return
+ end
+c
+c ==========
+c
+ subroutine brecvpost(request, dsizex, dsizey, buffer)
+c
+ include "mpif.h"
+c
+c global variables
+c
+ integer*4 nlocal, neq, npex, npey, mxsub, mysub, mx, my
+ integer*4 ixsub, jysub
+ integer thispe
+ integer mxsubg, mysubg, nlocalg
+ parameter (mxsubg = 5, mysubg = 5)
+ parameter (nlocalg = mxsubg*mysubg)
+ double precision dx, dy, coeffx, coeffy, coeffxy
+ double precision uext((mxsubg+2)*(mysubg+2))
+c
+c local variables
+c
+ integer*4 dsizex, dsizey
+ integer request(*)
+ double precision buffer(*)
+c
+ integer ier
+ integer*4 offsetue
+c
+ common /pcom/ dx, dy, coeffx, coeffy, coeffxy, uext,
+ & nlocal, neq, mx, my, mxsub, mysub, npey, npex,
+ & ixsub, jysub, thispe
+c
+ if (jysub .ne. 0) then
+ call mpi_irecv(uext(2), dsizex, mpi_double_precision,
+ & thispe-npex, 0, mpi_comm_world, request(1),
+ & ier)
+ endif
+c
+ if (jysub .ne. npey-1) then
+ offsetue = (1+(mysub+1)*(mxsub+2))
+ call mpi_irecv(uext(offsetue+1), dsizex, mpi_double_precision,
+ & thispe+npex, 0, mpi_comm_world, request(2),
+ & ier)
+ endif
+c
+ if (ixsub .ne. 0) then
+ call mpi_irecv(buffer(1), dsizey, mpi_double_precision,
+ & thispe-1, 0, mpi_comm_world, request(3),
+ & ier)
+ endif
+c
+ if (ixsub .ne. npex-1) then
+ call mpi_irecv(buffer(1+mysub), dsizey, mpi_double_precision,
+ & thispe+1, 0, mpi_comm_world, request(4),
+ & ier)
+ endif
+c
+ return
+ end
+c
+c ==========
+c
+ subroutine brecvwait(request, dsizex, buffer)
+c
+ include "mpif.h"
+c
+c global variables
+c
+ integer*4 nlocal, neq, npex, npey, mxsub, mysub, mx, my
+ integer*4 ixsub, jysub
+ integer thispe
+ integer mxsubg, mysubg, nlocalg
+ parameter (mxsubg = 5, mysubg = 5)
+ parameter (nlocalg = mxsubg*mysubg)
+ double precision dx, dy, coeffx, coeffy, coeffxy
+ double precision uext((mxsubg+2)*(mysubg+2))
+c
+c local variables
+c
+ integer request(*)
+ integer*4 dsizex
+ double precision buffer(*)
+c
+ integer*4 ly, dsizex2, offsetue
+ integer ier, status(mpi_status_size)
+c
+ common /pcom/ dx, dy, coeffx, coeffy, coeffxy, uext,
+ & nlocal, neq, mx, my, mxsub, mysub, npey, npex,
+ & ixsub, jysub, thispe
+c
+ dsizex2 = dsizex+2
+c
+ if (jysub .ne. 0) then
+ call mpi_wait(request(1), status, ier)
+ endif
+c
+ if (jysub .ne. npey-1) then
+ call mpi_wait(request(2), status, ier)
+ endif
+c
+ if (ixsub .ne. 0) then
+ call mpi_wait(request(3), status, ier)
+ do 26 ly = 0, mysub-1
+ offsetue = (ly+1)*dsizex2
+ uext(offsetue+1) = buffer(ly+1)
+ 26 continue
+ endif
+c
+ if (ixsub .ne. npex-1) then
+ call mpi_wait(request(4), status, ier)
+ do 27 ly = 0, mysub-1
+ offsetue = (ly+2)*dsizex2-1
+ uext(offsetue+1) = buffer(ly+mysub+1)
+ 27 continue
+ endif
+c
+ return
+ end
+c
+c ==========
+c
+ subroutine prntoutput(tret, u, iout, rout)
+c
+c global variables
+c
+ integer*4 nlocal, neq, npex, npey, mxsub, mysub, mx, my
+ integer*4 ixsub, jysub
+ integer thispe
+ integer mxsubg, mysubg, nlocalg
+ parameter (mxsubg = 5, mysubg = 5)
+ parameter (nlocalg = mxsubg*mysubg)
+ double precision dx, dy, coeffx, coeffy, coeffxy
+ double precision uext((mxsubg+2)*(mysubg+2))
+c
+c local variables
+c
+ integer*4 iout(*), lenrwbbd, leniwbbd, ngebbd
+ double precision tret, umax, u(*), rout(*)
+c
+ common /pcom/ dx, dy, coeffx, coeffy, coeffxy, uext,
+ & nlocal, neq, mx, my, mxsub, mysub, npey, npex,
+ & ixsub, jysub, thispe
+c
+ call maxnorm(u, umax)
+c
+ if (thispe .eq. 0) then
+ call fidabbdopt(lenrwbbd, leniwbbd, ngebbd)
+ write(*,28) 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,
+ & ' ', i3, ' ', i3, ' ', i2,'+',i2, ' ',
+ & i3, ' ', e9.2, ' ', i2, ' ', i3)
+ endif
+c
+ return
+ end
+c
+c ==========
+c
+ subroutine maxnorm(u, unorm)
+c
+ include "mpif.h"
+c
+c global variables
+c
+ integer*4 nlocal, neq, npex, npey, mxsub, mysub, mx, my
+ integer*4 ixsub, jysub
+ integer thispe
+ integer mxsubg, mysubg, nlocalg
+ parameter (mxsubg = 5, mysubg = 5)
+ parameter (nlocalg = mxsubg*mysubg)
+ double precision dx, dy, coeffx, coeffy, coeffxy
+ double precision uext((mxsubg+2)*(mysubg+2))
+c
+c local variables
+c
+ integer*4 i
+ integer ier
+ double precision temp, unorm, u(*)
+c
+ common /pcom/ dx, dy, coeffx, coeffy, coeffxy, uext,
+ & nlocal, neq, mx, my, mxsub, mysub, npey, npex,
+ & ixsub, jysub, thispe
+c
+ temp = 0.0d0
+c
+ do 29 i = 1, nlocal
+ temp = max(abs(u(i)), temp)
+ 29 continue
+c
+ call mpi_allreduce(temp, unorm, 1, mpi_double_precision,
+ & mpi_max, mpi_comm_world, ier)
+c
+c unorm = temp
+c
+ return
+ end
+c
+c ==========
+c
+ subroutine prntintro(rtol, atol)
+c
+c global variables
+c
+ integer*4 nlocal, neq, npex, npey, mxsub, mysub, mx, my
+ integer*4 ixsub, jysub
+ integer thispe
+ integer mxsubg, mysubg, nlocalg
+ parameter (mxsubg = 5, mysubg = 5)
+ parameter (nlocalg = mxsubg*mysubg)
+ double precision dx, dy, coeffx, coeffy, coeffxy
+ double precision uext((mxsubg+2)*(mysubg+2))
+c
+c local variables
+c
+ double precision rtol, atol
+c
+ common /pcom/ dx, dy, coeffx, coeffy, coeffxy, uext,
+ & nlocal, neq, mx, my, mxsub, mysub, npey, npex,
+ & 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',
+ & ' for FIDA', /, 16x,'Discretized heat equation',
+ & ' on 2D unit square.', /, 16x,'Zero boundary',
+ & ' conditions, polynomial conditions.', /,
+ & 16x,'Mesh dimensions: ', i2, ' x ', i2,
+ & ' Total system size: ', i3, //,
+ & 'Subgrid dimensions: ', i2, ' x ', i2,
+ & ' 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',
+ & ' boundary components from the error test.', /,
+ & 'Linear solver: SPGMR. Preconditioner: BBDPRE - ',
+ & 'Banded-block-diagonal.')
+c
+ return
+ end
+c
+c ==========
+c
+ subroutine prntcase(num, mudq, mukeep)
+c
+c local variables
+c
+ integer*4 mudq, mukeep
+ integer num
+c
+ write(*,31) num, mudq, mukeep
+ 31 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.)',
+ & //, ' time umax k nst nni nli nre',
+ & ' nge h npe nps', /,
+ & '-------------------------------------------------------',
+ & '-------------------')
+c
+ return
+ end
+c
+c ==========
+c
+ subroutine prntfinalstats(iout)
+c
+c local variables
+c
+ integer*4 iout(*)
+c
+ write(*,32) iout(5), iout(6), iout(21)
+ 32 format(/, 'Error test failures =', i3, /,
+ & 'Nonlinear convergence failures =', i3, /,
+ & 'Linear convergence failures =', i3)
+c
+ return
+ end
diff --git a/examples/ida/fcmix_parallel/fidaHeat2D_kry_bbd_p.out b/examples/ida/fcmix_parallel/fidaHeat2D_kry_bbd_p.out
new file mode 100644
index 0000000..45d222e
--- /dev/null
+++ b/examples/ida/fcmix_parallel/fidaHeat2D_kry_bbd_p.out
@@ -0,0 +1,65 @@
+
+fidaHeat2D_kry_bbd_p: Heat equation, parallel example problem for FIDA
+ Discretized heat equation on 2D unit square.
+ Zero boundary conditions, polynomial conditions.
+ Mesh dimensions: 10 x 10 Total system size: 100
+
+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.
+Linear solver: SPGMR. Preconditioner: BBDPRE - Banded-block-diagonal.
+
+
+Case 1
+ Difference quotient half-bandwidths = 5
+ Retained matrix half-bandwidths = 1
+
+Output Summary
+ umax = max-norm of solution
+ nre = nre + nreLS (total number of RES evals.)
+
+ time umax k nst nni nli nre nge h npe nps
+--------------------------------------------------------------------------
+ 0.1000E-01 0.82411E+00 2 12 14 7 14+ 7 96 0.26E-02 8 21
+ 0.2000E-01 0.68812E+00 3 15 18 12 18+12 96 0.51E-02 8 30
+ 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
+
+Error test failures = 1
+Nonlinear convergence failures = 0
+Linear convergence failures = 0
+
+
+Case 2
+ Difference quotient half-bandwidths = 1
+ Retained matrix half-bandwidths = 1
+
+Output Summary
+ umax = max-norm of solution
+ nre = nre + nreLS (total number of RES evals.)
+
+ time umax k nst nni nli nre nge h npe nps
+--------------------------------------------------------------------------
+ 0.1000E-01 0.82411E+00 2 12 14 7 14+ 7 32 0.26E-02 8 21
+ 0.2000E-01 0.68812E+00 3 15 18 12 18+12 32 0.51E-02 8 30
+ 0.4000E-01 0.47093E+00 3 19 23 20 23+20 36 0.10E-01 9 43
+ 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
+
+Error test failures = 0
+Nonlinear convergence failures = 0
+Linear convergence failures = 0
diff --git a/examples/ida/fcmix_serial/CMakeLists.txt b/examples/ida/fcmix_serial/CMakeLists.txt
new file mode 100644
index 0000000..96a083f
--- /dev/null
+++ b/examples/ida/fcmix_serial/CMakeLists.txt
@@ -0,0 +1,127 @@
+# ---------------------------------------------------------------
+# $Revision: 1.5 $
+# $Date: 2009/02/17 02:58:47 $
+# ---------------------------------------------------------------
+# Programmer: Radu Serban @ LLNL
+# ---------------------------------------------------------------
+# Copyright (c) 2007, The Regents of the University of California.
+# Produced at the Lawrence Livermore National Laboratory.
+# All rights reserved.
+# For details, see the LICENSE file.
+# ---------------------------------------------------------------
+# CMakeLists.txt file for the FIDA serial examples
+
+
+# Add variable ida_examples with the names of the serial FIDA examples
+
+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
+ )
+
+# 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")
+ SET(IDA_LIB sundials_ida_shared)
+ SET(NVECS_LIB sundials_nvecserial_shared)
+ SET(FNVECS_LIB sundials_fnvecserial_shared)
+ENDIF(LINK_LIBRARY_TYPE MATCHES "static")
+
+# 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)
+ SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${LAPACK_LINKER_FLAGS}")
+ SET(SUNDIALS_LIBS "${SUNDIALS_LIBS} ${LAPACK_LIBRARIES}")
+ENDIF(LAPACK_FOUND)
+
+# Add the build and install targets for each FIDA example
+
+FOREACH(example ${FIDA_examples})
+ ADD_EXECUTABLE(${example} ${example}.f)
+ 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})
+
+# 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)
+ 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)
+
+IF(EXAMPLES_INSTALL)
+
+ # Install the README file
+ INSTALL(FILES README DESTINATION ${EXAMPLES_INSTALL_PATH}/ida/fcmix_serial)
+
+ # Prepare substitution variables for Makefile and/or CMakeLists templates
+ 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
+ # 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
+ )
+
+ # install CMakelists.txt
+ INSTALL(
+ FILES ${PROJECT_BINARY_DIR}/examples/ida/fcmix_serial/CMakeLists.txt
+ 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
+ # 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_F77_ex.in
+ ${PROJECT_BINARY_DIR}/examples/ida/fcmix_serial/Makefile_ex
+ @ONLY
+ )
+ # 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
+ RENAME Makefile
+ )
+ ENDIF(UNIX)
+
+ENDIF(EXAMPLES_INSTALL)
diff --git a/examples/ida/fcmix_serial/Makefile.in b/examples/ida/fcmix_serial/Makefile.in
new file mode 100644
index 0000000..1539d2d
--- /dev/null
+++ b/examples/ida/fcmix_serial/Makefile.in
@@ -0,0 +1,134 @@
+# -----------------------------------------------------------------
+# $Revision: 1.10 $
+# $Date: 2009/02/17 02:58:47 $
+# -----------------------------------------------------------------
+# Programmer(s): Radu Serban and Aaron Collier @ 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.
+# -----------------------------------------------------------------
+# Makefile for FIDA serial examples
+#
+# @configure_input@
+# -----------------------------------------------------------------
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_builddir = @top_builddir@
+builddir = @builddir@
+abs_builddir = @abs_builddir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+includedir = @includedir@
+libdir = @libdir@
+
+INSTALL = @INSTALL@
+INSTALL_PROG = @INSTALL_PROGRAM@
+INSTALL_FILE = @INSTALL_DATA@
+
+LIBTOOL = @LIBTOOL@
+LIBTOOL_DEPS = @LIBTOOL_DEPS@
+
+F77 = @F77@
+FFLAGS = @FFLAGS@
+F77_LNKR = @F77_LNKR@
+F77_LDFLAGS = @F77_LDFLAGS@
+F77_LIBS = @F77_LIBS@
+
+LAPACK_ENABLED = @LAPACK_ENABLED@
+BLAS_LAPACK_LIBS = @BLAS_LAPACK_LIBS@
+
+OBJ_EXT = @OBJEXT@
+EXE_EXT = @EXEEXT@
+
+EXS_INSTDIR = @EXS_INSTDIR@
+
+top_srcdir = $(srcdir)/../../..
+
+SUNDIALS_LIBS = $(top_builddir)/src/ida/fcmix/libsundials_fida.la \
+ $(top_builddir)/src/ida/libsundials_ida.la \
+ $(top_builddir)/src/nvec_ser/libsundials_fnvecserial.la \
+ $(top_builddir)/src/nvec_ser/libsundials_nvecserial.la
+
+fortran-update = ${SHELL} ${top_builddir}/bin/fortran-update.sh
+
+mkinstalldirs = $(SHELL) $(top_srcdir)/config/mkinstalldirs
+rminstalldirs = $(SHELL) $(top_srcdir)/config/rminstalldirs
+
+EXAMPLES = fidaRoberts_dns
+
+EXAMPLES_BL =
+
+OBJECTS = ${EXAMPLES:=${OBJ_EXT}}
+OBJECTS_BL = ${EXAMPLES_BL:=${OBJ_EXT}}
+EXECS = ${EXAMPLES:=${EXE_EXT}}
+EXECS_BL = ${EXAMPLES_BL:=${EXE_EXT}}
+
+# ----------------------------------------------------------------------------------------------------------------------
+
+all:
+ @for i in ${EXAMPLES} ; do \
+ ${fortran-update} ${srcdir} $${i}.f ; \
+ ${LIBTOOL} --mode=compile ${F77} ${FFLAGS} -c ${builddir}/$${i}-updated.f ; \
+ ${LIBTOOL} --mode=link ${F77_LNKR} -o ${builddir}/$${i}${EXE_EXT} ${builddir}/$${i}-updated${OBJ_EXT} ${F77_LDFLAGS} ${SUNDIALS_LIBS} ${F77_LIBS} ${BLAS_LAPACK_LIBS} ; \
+ done
+ @if test "X${LAPACK_ENABLED}" = "Xyes"; then \
+ for i in ${EXAMPLES_BL} ; do \
+ ${fortran-update} ${srcdir} $${i}.f ; \
+ ${LIBTOOL} --mode=compile ${F77} ${FFLAGS} -c ${builddir}/$${i}-updated.f ; \
+ ${LIBTOOL} --mode=link ${F77_LNKR} -o ${builddir}/$${i}${EXE_EXT} ${builddir}/$${i}-updated${OBJ_EXT} ${F77_LDFLAGS} ${SUNDIALS_LIBS} ${F77_LIBS} ${BLAS_LAPACK_LIBS} ; \
+ done ; \
+ fi
+
+
+install:
+ $(mkinstalldirs) $(EXS_INSTDIR)/ida/fcmix_serial
+ $(INSTALL_FILE) Makefile_ex $(EXS_INSTDIR)/ida/fcmix_serial/Makefile
+ $(INSTALL_FILE) $(top_srcdir)/examples/ida/fcmix_serial/README $(EXS_INSTDIR)/ida/fcmix_serial/
+ for i in ${EXAMPLES} ; do \
+ $(INSTALL_FILE) $(top_srcdir)/examples/ida/fcmix_serial/$${i}.f $(EXS_INSTDIR)/ida/fcmix_serial/ ; \
+ $(INSTALL_FILE) $(top_srcdir)/examples/ida/fcmix_serial/$${i}.out $(EXS_INSTDIR)/ida/fcmix_serial/ ; \
+ done
+ @if test "X${LAPACK_ENABLED}" = "Xyes"; then \
+ for i in ${EXAMPLES_BL} ; do \
+ $(INSTALL_FILE) $(top_srcdir)/examples/ida/fcmix_serial/$${i}.f $(EXS_INSTDIR)/ida/fcmix_serial/ ; \
+ $(INSTALL_FILE) $(top_srcdir)/examples/ida/fcmix_serial/$${i}.out $(EXS_INSTDIR)/ida/fcmix_serial/ ; \
+ done ; \
+ fi
+
+uninstall:
+ rm -f $(EXS_INSTDIR)/ida/fcmix_serial/Makefile
+ rm -f $(EXS_INSTDIR)/ida/fcmix_serial/README
+ for i in ${EXAMPLES} ; do \
+ rm -f $(EXS_INSTDIR)/ida/fcmix_serial/$${i}.f ; \
+ rm -f $(EXS_INSTDIR)/ida/fcmix_serial/$${i}.out ; \
+ done
+ @if test "X${LAPACK_ENABLED}" = "Xyes"; then \
+ for i in ${EXAMPLES_BL} ; do \
+ rm -f $(EXS_INSTDIR)/ida/fcmix_serial/$${i}.f ; \
+ rm -f $(EXS_INSTDIR)/ida/fcmix_serial/$${i}.out ; \
+ done ; \
+ fi
+ $(rminstalldirs) $(EXS_INSTDIR)/ida/fcmix_serial
+ $(rminstalldirs) $(EXS_INSTDIR)/ida
+
+clean:
+ rm -rf .libs
+ rm -f *.lo *.o
+ rm -f *-updated.f
+ rm -f ${OBJECTS} ${OBJECTS_BL}
+ rm -f $(EXECS) $(EXECS_BL)
+
+distclean: clean
+ rm -f Makefile
+ rm -f Makefile_ex
+
+# ----------------------------------------------------------------------------------------------------------------------
+
+libtool: $(top_builddir)/$(LIBTOOL_DEPS)
+ @cd ${top_builddir} ; \
+ ${SHELL} ./config.status --recheck ; \
+ cd ${abs_builddir}
diff --git a/examples/ida/fcmix_serial/README b/examples/ida/fcmix_serial/README
new file mode 100644
index 0000000..cae0431
--- /dev/null
+++ b/examples/ida/fcmix_serial/README
@@ -0,0 +1,14 @@
+List of serial IDA FCMIX examples
+
+ fidaRoberts_dns : chemical kinetics example (DENSE)
+
+Sample results:
+
+ SUNDIALS was built with the following options:
+
+ ./configure CC=gcc F77=gfortran CFLAGS="-g3 -O0" FFLAGS="-g3 -O0" --enable-examples
+
+ System Architecture: IA-32
+ Processor Type: Intel Pentium 4 Xeon DP (i686)
+ Operating System: Red Hat Enterprise Linux WS 3 (Taroon Update 7)
+ C/Fortran Compilers: gcc/gfortran v4.1.0
diff --git a/examples/ida/fcmix_serial/fidaRoberts_dns.f b/examples/ida/fcmix_serial/fidaRoberts_dns.f
new file mode 100644
index 0000000..707852e
--- /dev/null
+++ b/examples/ida/fcmix_serial/fidaRoberts_dns.f
@@ -0,0 +1,264 @@
+c ----------------------------------------------------------------
+c $Revision: 1.3 $
+c $Date: 2010/12/01 23:04:14 $
+c ----------------------------------------------------------------
+c This simple example problem for FIDA, due to Robertson, is from
+c chemical kinetics, and consists of the following three 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 0 = y1 + y2 + y3 - 1
+c
+c on the interval from t = 0.0 to t = 4.e10, with initial
+c conditions: y1 = 1, y2 = y3 = 0.
+c
+c While integrating the system, we also employ the rootfinding feature
+c to find the points at which y1 = 1.e-4 or at which y3 = 0.01.
+c
+c The problem is solved using a dense linear solver, with a
+c user-supplied Jacobian. Output is printed at
+c t = .4, 4, 40, ..., 4e10.
+c ----------------------------------------------------------------
+c
+ program fidaRoberts_dns
+c
+ implicit none
+c
+ integer ier, ierroot, info(2)
+ integer*4 iout(25), ipar
+ double precision rout(10), rpar
+c
+ integer iatol, nout, jout, itask
+ integer nst, kused, hused
+ integer*4 neq, i
+ double precision t0, t1, rtol, tout, tret
+ double precision y(3), yp(3), atol(3)
+c
+ data nst/3/, kused/9/, hused/2/
+c
+c Initialize variables
+c
+ neq = 3
+ nout = 12
+ rtol = 1.0d-4
+ t0 = 0.0d0
+ t1 = 0.4d0
+ iatol = 2
+ itask = 1
+c
+ y(1) = 1.0d0
+ y(2) = 0.0d0
+ y(3) = 0.0d0
+c
+ yp(1) = -0.04d0
+ yp(2) = 0.04d0
+ yp(3) = 0.0d0
+c
+ atol(1) = 1.0d-6
+ atol(2) = 1.0d-10
+ atol(3) = 1.0d-6
+c
+c Initialize IDA vector environment
+c
+ call fnvinits(2, neq, ier)
+ if (ier .ne. 0) then
+ write(6,10) ier
+ 10 format(///' SUNDIALS_ERROR: FNVINITS returned IER = ', i5)
+ stop
+ endif
+c
+ call fidamalloc(t0, y, yp, iatol, rtol, atol,
+ & iout, rout, ipar, rpar, ier)
+ if (ier .ne. 0) then
+ write(6,20) ier
+ 20 format(///' SUNDIALS_ERROR: FIDAMALLOC returned IER = ', i5)
+ stop
+ endif
+c
+c Initialize rootfinding problem
+
+ call fidarootinit(2, ier)
+ if (ier .ne. 0) then
+ write(6,25) ier
+ 25 format(///' SUNDIALS_ERROR: FIDAROOTINIT returned IER = ', i5)
+ call fidafree
+ stop
+ endif
+c
+c Attach dense linear solver
+c
+ call fidadense(neq, ier)
+ call fidadensesetjac(1, ier)
+c
+c Print header
+c
+ call prntintro(rtol, atol, y)
+c
+ tout = t1
+c
+c
+ jout = 1
+ do while(jout .le. nout)
+c
+ call fidasolve(tout, tret, y, yp, itask, ier)
+c
+ write(6,40) tret, (y(i), i = 1,3), iout(nst), iout(kused),
+ & rout(hused)
+ 40 format(e10.4, 3(1x,e12.4), i5, i3, e12.4)
+c
+ if (ier .lt. 0) then
+ write(6,50) ier, iout(15)
+ 50 format(///' SUNDIALS_ERROR: FIDASOLVE returned IER = ',i5,/,
+ 1 ' Linear Solver returned IER = ',i5)
+ call fidarootfree
+ call fidafree
+ stop
+ endif
+c
+ if (ier .eq. 2) then
+ call fidarootinfo(2, info, ierroot)
+ if (ierroot .lt. 0) then
+ write(6,55) ier
+ 55 format(///' SUNDIALS_ERROR: FIDAROOTINFO returned IER = ',
+ 1 i5)
+ call fidarootfree
+ call fidafree
+ stop
+ endif
+ write(6,60) (info(i), i = 1,2)
+ 60 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
+c
+c Print final statistics
+c
+ call prntstats(iout)
+c
+c Free IDA memory
+c
+ call fidarootfree
+ call fidafree
+c
+ stop
+ end
+c
+c ==========
+c
+ subroutine fidaresfun(tres, y, yp, res, ipar, rpar, reserr)
+c
+ implicit none
+c
+ integer reserr
+ integer*4 ipar(*)
+ double precision tres, rpar(*)
+ double precision y(*), yp(*), res(*)
+c
+ res(1) = -0.04d0*y(1)+1.0d4*y(2)*y(3)
+ res(2) = -res(1)-3.0d7*y(2)*y(2)-yp(2)
+ res(1) = res(1)-yp(1)
+ res(3) = y(1)+y(2)+y(3)-1.0d0
+c
+ reserr = 0
+c
+ return
+ end
+c
+c ==========
+c
+ subroutine fidadjac(neq, t, y, yp, r, jac, cj, ewt, h,
+ 1 ipar, rpar, wk1, wk2, wk3, djacerr)
+c
+ implicit none
+c
+ integer*4 neq
+ integer*4 ipar(*)
+ integer djacerr
+ double precision t, h, cj, rpar(*)
+ double precision y(*), yp(*), r(*), ewt(*), jac(neq,neq)
+ double precision wk1(*), wk2(*), wk3(*)
+c
+ jac(1,1) = -0.04d0-cj
+ jac(2,1) = 0.04d0
+ jac(3,1) = 1.0d0
+ jac(1,2) = 1.0d4*y(3)
+ jac(2,2) = -1.0d4*y(3)-6.0d7*y(2)-cj
+ jac(3,2) = 1.0d0
+ jac(1,3) = 1.0d4*y(2)
+ jac(2,3) = -1.0d4*y(2)
+ jac(3,3) = 1.0d0
+c
+ djacerr = 0
+
+ return
+ end
+c
+c ==========
+c
+ subroutine fidarootfn(t, y, yp, g, ipar, rpar, ier)
+c Fortran routine for rootfinding
+ implicit none
+c
+ INTEGER*4 ipar(*), ier
+ double precision t, y(*), yp(*), g(*), rpar(*)
+c
+ g(1) = y(1) - 1.0d-4
+ g(2) = y(3) - 1.0d-2
+
+ ier = 0
+
+ return
+ end
+c
+c ==========
+c
+ subroutine prntintro(rtol, atol, y)
+c
+ implicit none
+c
+ integer*4 i
+ double precision rtol, atol(*), y(*)
+c
+ write(6,60) rtol, (atol(i), i = 1,3), (y(i), i = 1,3)
+ 60 format(/'fidaRoberts_dns: Robertson kinetics DAE serial example',
+ & 'problem for IDA', /,' Three equation chemical',
+ & 'kinetics problem.', //,
+ & 'Tolerance parameters: rtol = ', e8.2,
+ & ' atol = ', 3(1x,e8.2), /,
+ & 'Initial conditions y0 = (', 3(1x,e8.2), ')', //,
+ & ' t y1 y2 y3 nst',
+ & ' k h')
+c
+ return
+ end
+c
+c ==========
+c
+ subroutine prntstats(iout)
+c
+ implicit none
+c
+ integer*4 iout(25)
+ integer nst, reseval, jaceval, nni, ncf, netf, nge
+c
+ data nst/3/, reseval/4/, jaceval/17/, nni/7/, netf/5/,
+ & ncf/6/, nge/12/
+c
+ write(6,70) iout(nst), iout(reseval), iout(jaceval),
+ & iout(nni), iout(netf), iout(ncf), iout(nge)
+ 70 format(/'Final Run Statistics:', //,
+ & 'Number of steps = ', i3, /,
+ & 'Number of residual evaluations = ', i3, /,
+ & 'Number of Jacobian evaluations = ', i3, /,
+ & 'Number of nonlinear iterations = ', i3, /,
+ & 'Number of error test failures = ', i3, /,
+ & 'Number of nonlinear conv. failures = ', i3, /,
+ & 'Number of root function evals. = ', i3)
+c
+ return
+ end
diff --git a/examples/ida/fcmix_serial/fidaRoberts_dns.out b/examples/ida/fcmix_serial/fidaRoberts_dns.out
new file mode 100644
index 0000000..549e24f
--- /dev/null
+++ b/examples/ida/fcmix_serial/fidaRoberts_dns.out
@@ -0,0 +1,34 @@
+
+fidaRoberts_dns: Robertson kinetics DAE serial exampleproblem for IDA
+ Three equation chemicalkinetics problem.
+
+Tolerance parameters: rtol = 0.10E-03 atol = 0.10E-05 0.10E-09 0.10E-05
+Initial conditions y0 = ( 0.10E+01 0.00E+00 0.00E+00)
+
+ t y1 y2 y3 nst k h
+0.2640E+00 0.9900E+00 0.3471E-04 0.1000E-01 75 2 0.5716E-01
+ Above is a root, INFO() = 0 1
+0.4000E+00 0.9852E+00 0.3386E-04 0.1480E-01 77 3 0.1143E+00
+0.4000E+01 0.9055E+00 0.2240E-04 0.9447E-01 91 4 0.3704E+00
+0.4000E+02 0.7158E+00 0.9185E-05 0.2842E+00 127 4 0.2963E+01
+0.4000E+03 0.4505E+00 0.3223E-05 0.5495E+00 177 3 0.1241E+02
+0.4000E+04 0.1832E+00 0.8940E-06 0.8168E+00 228 3 0.2765E+03
+0.4000E+05 0.3899E-01 0.1622E-06 0.9610E+00 278 5 0.2614E+04
+0.4000E+06 0.4939E-02 0.1985E-07 0.9951E+00 324 5 0.2770E+05
+0.4000E+07 0.5176E-03 0.2072E-08 0.9995E+00 355 4 0.3979E+06
+0.2075E+08 0.1000E-03 0.4000E-09 0.9999E+00 374 4 0.1592E+07
+ Above is a root, INFO() = -1 0
+0.4000E+08 0.5191E-04 0.2076E-09 0.9999E+00 380 3 0.6366E+07
+0.4000E+09 0.5882E-05 0.2353E-10 0.1000E+01 394 1 0.9167E+08
+0.4000E+10 0.7054E-06 0.2822E-11 0.1000E+01 402 1 0.1467E+10
+0.4000E+11 -0.7300E-06 -0.2920E-11 0.1000E+01 407 1 0.2347E+11
+
+Final Run Statistics:
+
+Number of steps = 407
+Number of residual evaluations = 557
+Number of Jacobian evaluations = 65
+Number of nonlinear iterations = 557
+Number of error test failures = 6
+Number of nonlinear conv. failures = 0
+Number of root function evals. = 437
diff --git a/examples/ida/parallel/CMakeLists.txt b/examples/ida/parallel/CMakeLists.txt
new file mode 100644
index 0000000..621642f
--- /dev/null
+++ b/examples/ida/parallel/CMakeLists.txt
@@ -0,0 +1,114 @@
+# ---------------------------------------------------------------
+# $Revision: 1.4 $
+# $Date: 2009/02/17 02:58:47 $
+# ---------------------------------------------------------------
+# Programmer: Radu Serban @ LLNL
+# ---------------------------------------------------------------
+# Copyright (c) 2007, The Regents of the University of California.
+# Produced at the Lawrence Livermore National Laboratory.
+# All rights reserved.
+# For details, see the LICENSE file.
+# ---------------------------------------------------------------
+# CMakeLists.txt file for IDA parallel examples
+
+
+# Add variable IDA_examples with the names of the parallel IDA examples
+
+SET(IDA_examples
+ idaFoodWeb_kry_bbd_p
+ idaFoodWeb_kry_p
+ idaHeat2D_kry_bbd_p
+ idaHeat2D_kry_p
+ )
+
+# 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)
+ # add MPI_INCLUDE_PATH to include directories
+ INCLUDE_DIRECTORIES(${MPI_INCLUDE_PATH})
+ENDIF(MPI_MPICC)
+
+# 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")
+ SET(IDA_LIB sundials_ida_shared)
+ SET(NVECP_LIB sundials_nvecparallel_shared)
+ENDIF(LINK_LIBRARY_TYPE MATCHES "static")
+
+# Set-up linker flags and link libraries
+
+SET(SUNDIALS_LIBS ${IDA_LIB} ${NVECP_LIB} ${EXTRA_LINK_LIBS})
+IF(LAPACK_FOUND)
+ SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${LAPACK_LINKER_FLAGS}")
+ SET(SUNDIALS_LIBS "${SUNDIALS_LIBS} ${LAPACK_LIBRARIES}")
+ENDIF(LAPACK_FOUND)
+
+# Add the build and install targets for each IDA example
+
+FOREACH(example ${IDA_examples})
+ ADD_EXECUTABLE(${example} ${example}.c)
+ TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+ IF(NOT MPI_MPICC)
+ TARGET_LINK_LIBRARIES(${example} ${MPI_LIBRARY} ${MPI_EXTRA_LIBRARIES})
+ ENDIF(NOT MPI_MPICC)
+ IF(EXAMPLES_INSTALL)
+ INSTALL(FILES ${example}.c ${example}.out DESTINATION ${EXAMPLES_INSTALL_PATH}/ida/parallel)
+ ENDIF(EXAMPLES_INSTALL)
+ENDFOREACH(example ${IDA_examples})
+
+IF(EXAMPLES_INSTALL)
+
+ # Install the README file
+ INSTALL(FILES README DESTINATION ${EXAMPLES_INSTALL_PATH}/ida/parallel)
+
+ # Prepare substitution variables for Makefile and/or CMakeLists templates
+ SET(SOLVER "IDA")
+ SET(SOLVER_LIB "sundials_ida")
+ LIST2STRING(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
+ )
+
+ # install CMakelists.txt
+ INSTALL(
+ FILES ${PROJECT_BINARY_DIR}/examples/ida/parallel/CMakeLists.txt
+ 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
+ # 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/ida/parallel/Makefile_ex
+ @ONLY
+ )
+ # install the configured Makefile_ex as Makefile
+ INSTALL(
+ FILES ${PROJECT_BINARY_DIR}/examples/ida/parallel/Makefile_ex
+ DESTINATION ${EXAMPLES_INSTALL_PATH}/ida/parallel
+ RENAME Makefile
+ )
+ ENDIF(UNIX)
+
+ENDIF(EXAMPLES_INSTALL)
diff --git a/examples/ida/parallel/Makefile.in b/examples/ida/parallel/Makefile.in
new file mode 100644
index 0000000..a1cce55
--- /dev/null
+++ b/examples/ida/parallel/Makefile.in
@@ -0,0 +1,113 @@
+# -----------------------------------------------------------------
+# $Revision: 1.9 $
+# $Date: 2009/02/17 02:58:47 $
+# -----------------------------------------------------------------
+# Programmer(s): Radu Serban and Aaron Collier @ LLNL
+# -----------------------------------------------------------------
+# Copyright (c) 2002, The Regents of the University of California.
+# Produced at the Lawrence Livermore National Laboratory.
+# All rights reserved.
+# For details, see the LICENSE file.
+# -----------------------------------------------------------------
+# Makefile for IDA parallel examples
+#
+# @configure_input@
+# -----------------------------------------------------------------
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_builddir = @top_builddir@
+builddir = @builddir@
+abs_builddir = @abs_builddir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+includedir = @includedir@
+libdir = @libdir@
+
+INSTALL = @INSTALL@
+INSTALL_PROG = @INSTALL_PROGRAM@
+INSTALL_FILE = @INSTALL_DATA@
+
+LIBTOOL = @LIBTOOL@
+LIBTOOL_DEPS = @LIBTOOL_DEPS@
+
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CC = @CC@
+CFLAGS = @CFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+MPICC = @MPICC@
+MPI_INC_DIR = @MPI_INC_DIR@
+MPI_LIB_DIR = @MPI_LIB_DIR@
+MPI_LIBS = @MPI_LIBS@
+MPI_FLAGS = @MPI_FLAGS@
+
+BLAS_LAPACK_LIBS = @BLAS_LAPACK_LIBS@
+
+OBJ_EXT = @OBJEXT@
+EXE_EXT = @EXEEXT@
+
+EXS_INSTDIR = @EXS_INSTDIR@
+
+top_srcdir = $(srcdir)/../../..
+
+SUNDIALS_INCS = -I$(top_srcdir)/include -I$(top_builddir)/include
+
+SUNDIALS_LIBS = $(top_builddir)/src/ida/libsundials_ida.la $(top_builddir)/src/nvec_par/libsundials_nvecparallel.la
+
+mkinstalldirs = $(SHELL) $(top_srcdir)/config/mkinstalldirs
+rminstalldirs = $(SHELL) $(top_srcdir)/config/rminstalldirs
+
+EXAMPLES = idaFoodWeb_kry_bbd_p \
+ idaFoodWeb_kry_p \
+ idaHeat2D_kry_bbd_p \
+ idaHeat2D_kry_p
+
+OBJECTS = ${EXAMPLES:=${OBJ_EXT}}
+EXECS = ${EXAMPLES:=${EXE_EXT}}
+
+# ----------------------------------------------------------------------------------------------------------------------
+
+all:
+ @for i in ${EXAMPLES} ; do \
+ $(LIBTOOL) --mode=compile $(MPICC) $(CPPFLAGS) $(MPI_FLAGS) $(SUNDIALS_INCS) -I$(MPI_INC_DIR) $(CFLAGS) -c $(srcdir)/$${i}.c -o $${i}${OBJ_EXT} ; \
+ $(LIBTOOL) --mode=link $(MPICC) -o $(builddir)/$${i}$(EXE_EXT) $(builddir)/$${i}$(OBJ_EXT) $(MPI_FLAGS) $(CFLAGS) $(LDFLAGS) $(SUNDIALS_LIBS) -L$(MPI_LIB_DIR) $(MPI_LIBS) $(LIBS) $(BLAS_LAPACK_LIBS) ; \
+ done
+
+install:
+ $(mkinstalldirs) $(EXS_INSTDIR)/ida/parallel
+ $(INSTALL_FILE) Makefile_ex $(EXS_INSTDIR)/ida/parallel/Makefile
+ $(INSTALL_FILE) $(top_srcdir)/examples/ida/parallel/README $(EXS_INSTDIR)/ida/parallel/
+ for i in ${EXAMPLES} ; do \
+ $(INSTALL_FILE) $(top_srcdir)/examples/ida/parallel/$${i}.c $(EXS_INSTDIR)/ida/parallel/ ; \
+ $(INSTALL_FILE) $(top_srcdir)/examples/ida/parallel/$${i}.out $(EXS_INSTDIR)/ida/parallel/ ; \
+ done
+
+uninstall:
+ rm -f $(EXS_INSTDIR)/ida/parallel/Makefile
+ rm -f $(EXS_INSTDIR)/ida/parallel/README
+ for i in ${EXAMPLES} ; do \
+ rm -f $(EXS_INSTDIR)/ida/parallel/$${i}.c ; \
+ rm -f $(EXS_INSTDIR)/ida/parallel/$${i}.out ; \
+ done
+ $(rminstalldirs) $(EXS_INSTDIR)/ida/parallel
+ $(rminstalldirs) $(EXS_INSTDIR)/ida
+
+clean:
+ rm -rf .libs
+ rm -f *.lo *.o
+ rm -f ${OBJECTS}
+ rm -f $(EXECS)
+
+distclean: clean
+ rm -f Makefile
+ rm -f Makefile_ex
+
+# ----------------------------------------------------------------------------------------------------------------------
+
+libtool: $(top_builddir)/$(LIBTOOL_DEPS)
+ @cd ${top_builddir} ; \
+ ${SHELL} ./config.status --recheck ; \
+ cd ${abs_builddir}
diff --git a/examples/ida/parallel/README b/examples/ida/parallel/README
new file mode 100644
index 0000000..20d827e
--- /dev/null
+++ b/examples/ida/parallel/README
@@ -0,0 +1,18 @@
+List of parallel IDA examples
+
+ idaFoodWeb_kry_bbd_p : 2-D food web, BBD preconditioner
+ idaFoodWeb_kry_p : 2-D food web, block-diagonal preconditioner
+ idaHeat2D_kry_bbd_p : 2-D heat equation, BBD preconditioner
+ idaHeat2D_kry_p : 2-D heat equation, diagonal preconditioner
+
+Sample results:
+
+ SUNDIALS was built with the following options:
+
+ ./configure CC=gcc F77=gfortran CFLAGS="-g3 -O0" FFLAGS="-g3 -O0" --enable-examples
+
+ System Architecture: IA-32
+ Processor Type: Intel Pentium 4 Xeon DP (i686)
+ Operating System: Red Hat Enterprise Linux WS 3 (Taroon Update 7)
+ C/Fortran Compilers: gcc/gfortran v4.1.0
+ MPI Implementation: Open MPI v1.1
diff --git a/examples/ida/parallel/idaFoodWeb_kry_bbd_p.c b/examples/ida/parallel/idaFoodWeb_kry_bbd_p.c
new file mode 100644
index 0000000..f048c63
--- /dev/null
+++ b/examples/ida/parallel/idaFoodWeb_kry_bbd_p.c
@@ -0,0 +1,1091 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.4 $
+ * $Date: 2010/12/01 23:03:29 $
+ * -----------------------------------------------------------------
+ * Programmer(s): 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.
+ * 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.
+ *
+ * The mathematical problem solved in this example is a DAE system
+ * that arises from a system of partial differential equations after
+ * spatial discretization. The PDE system is a food web population
+ * model, with predator-prey interaction and diffusion on the unit
+ * square in two dimensions. The dependent variable vector is:
+ *
+ * 1 2 ns
+ * c = (c , c , ..., c ) , ns = 2 * np
+ *
+ * and the PDE's are as follows:
+ *
+ * i i i
+ * dc /dt = d(i)*(c + c ) + R (x,y,c) (i = 1,...,np)
+ * xx yy i
+ *
+ * i i
+ * 0 = d(i)*(c + c ) + R (x,y,c) (i = np+1,...,ns)
+ * xx yy i
+ *
+ * where the reaction terms R are:
+ *
+ * i ns j
+ * R (x,y,c) = c * (b(i) + sum a(i,j)*c )
+ * i j=1
+ *
+ * The number of species is ns = 2 * np, with the first np being
+ * prey and the last np being predators. The coefficients a(i,j),
+ * b(i), d(i) are:
+ *
+ * a(i,i) = -AA (all i)
+ * a(i,j) = -GG (i <= np , j > np)
+ * a(i,j) = EE (i > np, j <= np)
+ * all other a(i,j) = 0
+ * b(i) = BB*(1+ alpha * x*y + beta*sin(4 pi x)*sin(4 pi y)) (i <= np)
+ * b(i) =-BB*(1+ alpha * x*y + beta*sin(4 pi x)*sin(4 pi y)) (i > np)
+ * d(i) = DPREY (i <= np)
+ * d(i) = DPRED (i > np)
+ *
+ * Note: The above equations are written in 1-based indices,
+ * whereas the code has 0-based indices, being written in C.
+ *
+ * The various scalar parameters required are set using '#define'
+ * statements or directly in routine InitUserData. In this program,
+ * np = 1, ns = 2. The boundary conditions are homogeneous Neumann:
+ * normal derivative = 0.
+ *
+ * A polynomial in x and y is used to set the initial values of the
+ * first np variables (the prey variables) at each x,y location,
+ * while initial values for the remaining (predator) variables are
+ * set to a flat value, which is corrected by IDACalcIC.
+ *
+ * The PDEs are discretized by central differencing on a MX by MY
+ * mesh, and so the system size Neq is the product
+ * MX * MY * NUM_SPECIES. The system is actually implemented on
+ * 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,
+ * in conjunction with the preconditioner module IDABBDPRE. The
+ * preconditioner uses a 5-diagonal band-block-diagonal
+ * approximation (half-bandwidths = 2). Output is printed at
+ * t = 0, .001, .01, .1, .4, .7, 1.
+ * -----------------------------------------------------------------
+ * References:
+ * [1] Peter N. Brown and Alan C. Hindmarsh,
+ * Reduced Storage Matrix Methods in Stiff ODE systems,
+ * Journal of Applied Mathematics and Computation, Vol. 31
+ * (May 1989), pp. 40-91.
+ *
+ * [2] Peter N. Brown, Alan C. Hindmarsh, and Linda R. Petzold,
+ * Using Krylov Methods in the Solution of Large-Scale
+ * Differential-Algebraic Systems, SIAM J. Sci. Comput., 15
+ * (1994), pp. 1467-1488.
+ *
+ * [3] Peter N. Brown, Alan C. Hindmarsh, and Linda R. Petzold,
+ * 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 <ida/ida_bbdpre.h>
+#include <nvector/nvector_parallel.h>
+#include <sundials/sundials_dense.h>
+#include <sundials/sundials_types.h>
+#include <sundials/sundials_math.h>
+
+#include <mpi.h>
+
+/* Problem Constants */
+
+#define NPREY 1 /* Number of prey (= number of predators). */
+#define NUM_SPECIES 2*NPREY
+
+#define PI RCONST(3.1415926535898) /* pi */
+#define FOURPI (RCONST(4.0)*PI) /* 4 pi */
+
+#define MXSUB 10 /* Number of x mesh points per processor subgrid */
+#define MYSUB 10 /* Number of y mesh points per processor subgrid */
+#define NPEX 2 /* Number of subgrids in the x direction */
+#define NPEY 2 /* Number of subgrids in the y direction */
+#define MX (MXSUB*NPEX) /* MX = number of x mesh points */
+#define MY (MYSUB*NPEY) /* MY = number of y mesh points */
+#define NSMXSUB (NUM_SPECIES * MXSUB)
+#define NEQ (NUM_SPECIES*MX*MY) /* Number of equations in system */
+#define AA RCONST(1.0) /* Coefficient in above eqns. for a */
+#define EE RCONST(10000.) /* Coefficient in above eqns. for a */
+#define GG RCONST(0.5e-6) /* Coefficient in above eqns. for a */
+#define BB RCONST(1.0) /* Coefficient in above eqns. for b */
+#define DPREY RCONST(1.0) /* Coefficient in above eqns. for d */
+#define DPRED RCONST(0.05) /* Coefficient in above eqns. for d */
+#define ALPHA RCONST(50.) /* Coefficient alpha in above eqns. */
+#define BETA RCONST(1000.) /* Coefficient beta in above eqns. */
+#define AX RCONST(1.0) /* Total range of x variable */
+#define AY RCONST(1.0) /* Total range of y variable */
+#define RTOL RCONST(1.e-5) /* rtol tolerance */
+#define ATOL RCONST(1.e-5) /* atol tolerance */
+#define ZERO RCONST(0.) /* 0. */
+#define ONE RCONST(1.0) /* 1. */
+#define NOUT 6
+#define TMULT RCONST(10.0) /* Multiplier for tout values */
+#define TADD RCONST(0.3) /* Increment for tout values */
+
+/* User-defined vector accessor macro IJ_Vptr. */
+
+/*
+ * IJ_Vptr is defined in order to express the underlying 3-d structure of the
+ * dependent variable vector from its underlying 1-d storage (an N_Vector).
+ * IJ_Vptr(vv,i,j) returns a pointer to the location in vv corresponding to
+ * species index is = 0, x-index ix = i, and y-index jy = j.
+ */
+
+#define IJ_Vptr(vv,i,j) (&NV_Ith_P(vv, (i)*NUM_SPECIES + (j)*NSMXSUB ))
+
+/* Type: UserData. Contains problem constants, preconditioner data, etc. */
+
+typedef struct {
+ int ns, np, thispe, npes, ixsub, jysub, npex, npey;
+ int mxsub, mysub, nsmxsub, nsmxsub2;
+ realtype dx, dy, **acoef;
+ realtype cox[NUM_SPECIES], coy[NUM_SPECIES], bcoef[NUM_SPECIES],
+ rhs[NUM_SPECIES], cext[(MXSUB+2)*(MYSUB+2)*NUM_SPECIES];
+ MPI_Comm comm;
+ N_Vector rates;
+ long int 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 reslocal(long int Nlocal, realtype tt,
+ N_Vector cc, N_Vector cp, N_Vector res,
+ void *user_data);
+
+static int rescomm(long int Nlocal, realtype tt,
+ N_Vector cc, N_Vector cp,
+ 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,
+ realtype cext[], realtype buffer[]);
+
+static void BRecvWait(MPI_Request request[], int ixsub, int jysub,
+ int dsizex, realtype cext[], realtype buffer[]);
+
+static void WebRates(realtype xx, realtype yy, realtype *cxy, realtype *ratesxy,
+ UserData webdata);
+
+static realtype dotprod(int size, realtype *x1, realtype *x2);
+
+/* Prototypes for private functions */
+
+static void InitUserData(UserData webdata, int thispe, int npes,
+ MPI_Comm comm);
+
+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,
+ realtype rtol, realtype atol);
+
+static void PrintOutput(void *mem, N_Vector cc, realtype time,
+ UserData webdata, MPI_Comm comm);
+
+static void PrintFinalStats(void *mem);
+
+static int check_flag(void *flagvalue, char *funcname, int opt, int id);
+
+/*
+ *--------------------------------------------------------------------
+ * MAIN PROGRAM
+ *--------------------------------------------------------------------
+ */
+
+int main(int argc, char *argv[])
+{
+ MPI_Comm comm;
+ void *mem;
+ UserData webdata;
+ long int 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;
+
+ /* Set communicator, and get processor number and total number of PE's. */
+
+ MPI_Init(&argc, &argv);
+ comm = MPI_COMM_WORLD;
+ MPI_Comm_rank(comm, &thispe);
+ MPI_Comm_size(comm, &npes);
+
+ if (npes != NPEX*NPEY) {
+ if (thispe == 0)
+ fprintf(stderr,
+ "\nMPI_ERROR(0): npes = %d not equal to NPEX*NPEY = %d\n",
+ npes, NPEX*NPEY);
+ MPI_Finalize();
+ return(1);
+ }
+
+ /* Set local length (local_N) and global length (SystemSize). */
+
+ local_N = MXSUB*MYSUB*NUM_SPECIES;
+ SystemSize = NEQ;
+
+ /* Set up user data block webdata. */
+
+ webdata = (UserData) malloc(sizeof *webdata);
+ webdata->rates = N_VNew_Parallel(comm, local_N, SystemSize);
+ webdata->acoef = newDenseMat(NUM_SPECIES, NUM_SPECIES);
+
+ InitUserData(webdata, thispe, npes, comm);
+
+ /* Create needed vectors, and load initial values.
+ The vector res is used temporarily only. */
+
+ cc = N_VNew_Parallel(comm, local_N, SystemSize);
+ if(check_flag((void *)cc, "N_VNew_Parallel", 0, thispe)) MPI_Abort(comm, 1);
+
+ cp = N_VNew_Parallel(comm, local_N, SystemSize);
+ if(check_flag((void *)cp, "N_VNew_Parallel", 0, thispe)) MPI_Abort(comm, 1);
+
+ res = N_VNew_Parallel(comm, local_N, SystemSize);
+ if(check_flag((void *)res, "N_VNew_Parallel", 0, thispe)) MPI_Abort(comm, 1);
+
+ id = N_VNew_Parallel(comm, local_N, SystemSize);
+ if(check_flag((void *)id, "N_VNew_Parallel", 0, thispe)) MPI_Abort(comm, 1);
+
+ SetInitialProfiles(cc, cp, id, res, webdata);
+
+ N_VDestroy_Parallel(res);
+
+ /* Set remaining inputs to IDAMalloc. */
+
+ t0 = ZERO;
+ rtol = RTOL;
+ atol = ATOL;
+
+ /* Call IDACreate and IDAMalloc to initialize solution */
+
+ mem = IDACreate();
+ if(check_flag((void *)mem, "IDACreate", 0, thispe)) MPI_Abort(comm, 1);
+
+ retval = IDASetUserData(mem, webdata);
+ if(check_flag(&retval, "IDASetUserData", 1, thispe)) MPI_Abort(comm, 1);
+
+ retval = IDASetId(mem, id);
+ if(check_flag(&retval, "IDASetId", 1, thispe)) MPI_Abort(comm, 1);
+
+ retval = IDAInit(mem, resweb, t0, cc, cp);
+ if(check_flag(&retval, "IDAInit", 1, thispe)) MPI_Abort(comm, 1);
+
+ retval = IDASStolerances(mem, rtol, atol);
+ if(check_flag(&retval, "IDASStolerances", 1, thispe)) MPI_Abort(comm, 1);
+
+ /* Call IDASpgmr to specify the IDA linear solver IDASPGMR */
+
+ maxl = 16;
+ retval = IDASpgmr(mem, maxl);
+ if(check_flag(&retval, "IDASpgmr", 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,
+ 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);
+ 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, 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);
+ if(check_flag(&retval, "IDASolve", 1, thispe)) MPI_Abort(comm, 1);
+
+ PrintOutput(mem, cc, tret, webdata, comm);
+
+ if (iout < 3) tout *= TMULT;
+ else tout += TADD;
+
+ }
+
+ /* On PE 0, print final set of statistics. */
+
+ if (thispe == 0) PrintFinalStats(mem);
+
+ /* Free memory. */
+
+ N_VDestroy_Parallel(cc);
+ N_VDestroy_Parallel(cp);
+ N_VDestroy_Parallel(id);
+
+ IDAFree(&mem);
+
+ destroyMat(webdata->acoef);
+ N_VDestroy_Parallel(webdata->rates);
+ free(webdata);
+
+ MPI_Finalize();
+
+ return(0);
+}
+
+/*
+ *--------------------------------------------------------------------
+ * PRIVATE FUNCTIONS
+ *--------------------------------------------------------------------
+ */
+
+/*
+ * InitUserData: Load problem constants in webdata (of type UserData).
+ */
+
+static void InitUserData(UserData webdata, int thispe, int npes,
+ MPI_Comm comm)
+{
+ int i, j, np;
+ realtype *a1,*a2, *a3, *a4, dx2, dy2, **acoef, *bcoef, *cox, *coy;
+
+ webdata->jysub = thispe / NPEX;
+ webdata->ixsub = thispe - (webdata->jysub)*NPEX;
+ webdata->mxsub = MXSUB;
+ webdata->mysub = MYSUB;
+ webdata->npex = NPEX;
+ webdata->npey = NPEY;
+ webdata->ns = NUM_SPECIES;
+ webdata->np = NPREY;
+ webdata->dx = AX/(MX-1);
+ webdata->dy = AY/(MY-1);
+ webdata->thispe = thispe;
+ webdata->npes = npes;
+ webdata->nsmxsub = MXSUB * NUM_SPECIES;
+ webdata->nsmxsub2 = (MXSUB+2)*NUM_SPECIES;
+ webdata->comm = comm;
+ webdata->n_local = MXSUB*MYSUB*NUM_SPECIES;
+
+ /* Set up the coefficients a and b plus others found in the equations. */
+
+ np = webdata->np;
+ dx2 = (webdata->dx)*(webdata->dx);
+ dy2 = (webdata->dy)*(webdata->dy);
+
+ acoef = webdata->acoef;
+ bcoef = webdata->bcoef;
+ cox = webdata->cox;
+ coy = webdata->coy;
+
+ for (i = 0; i < np; i++) {
+ a1 = &(acoef[i][np]);
+ a2 = &(acoef[i+np][0]);
+ a3 = &(acoef[i][0]);
+ a4 = &(acoef[i+np][np]);
+ /* Fill in the portion of acoef in the four quadrants, row by row. */
+ for (j = 0; j < np; j++) {
+ *a1++ = -GG;
+ *a2++ = EE;
+ *a3++ = ZERO;
+ *a4++ = ZERO;
+ }
+
+ /* Reset the diagonal elements of acoef to -AA. */
+ acoef[i][i] = -AA; acoef[i+np][i+np] = -AA;
+
+ /* Set coefficients for b and diffusion terms. */
+ bcoef[i] = BB; bcoef[i+np] = -BB;
+ cox[i] = DPREY/dx2; cox[i+np] = DPRED/dx2;
+ coy[i] = DPREY/dy2; coy[i+np] = DPRED/dy2;
+ }
+
+}
+
+/*
+ * SetInitialProfiles: Set initial conditions in cc, cp, and id.
+ * A polynomial profile is used for the prey cc values, and a constant
+ * (1.0e5) is loaded as the initial guess for the predator cc values.
+ * The id values are set to 1 for the prey and 0 for the predators.
+ * The prey cp values are set according to the given system, and
+ * the predator cp values are set to zero.
+ */
+
+static void SetInitialProfiles(N_Vector cc, N_Vector cp, N_Vector id,
+ N_Vector res, UserData webdata)
+{
+ int ixsub, jysub, mxsub, mysub, nsmxsub, np, ix, jy, is;
+ realtype *cxy, *idxy, *cpxy, dx, dy, xx, yy, xyfactor;
+
+ ixsub = webdata->ixsub;
+ jysub = webdata->jysub;
+ mxsub = webdata->mxsub;
+ mysub = webdata->mxsub;
+ nsmxsub = webdata->nsmxsub;
+ dx = webdata->dx;
+ dy = webdata->dy;
+ np = webdata->np;
+
+ /* Loop over grid, load cc values and id values. */
+ for (jy = 0; jy < mysub; jy++) {
+ yy = (jy + jysub*mysub) * dy;
+ for (ix = 0; ix < mxsub; ix++) {
+ xx = (ix + ixsub*mxsub) * dx;
+ xyfactor = 16.*xx*(1. - xx)*yy*(1. - yy);
+ xyfactor *= xyfactor;
+
+ 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;}
+ else { cxy[is] = 1.0e5; idxy[is] = ZERO; }
+ }
+ }
+ }
+
+ /* Set c' for the prey by calling the residual function with cp = 0. */
+
+ N_VConst(ZERO, cp);
+ resweb(ZERO, cc, cp, res, webdata);
+ N_VScale(-ONE, res, cp);
+
+ /* Set c' for predators to 0. */
+
+ for (jy = 0; jy < mysub; jy++) {
+ for (ix = 0; ix < mxsub; ix++) {
+ cpxy = IJ_Vptr(cp,ix,jy);
+ for (is = np; is < NUM_SPECIES; is++) cpxy[is] = ZERO;
+ }
+ }
+}
+
+/*
+ * Print first lines of output (problem description)
+ * and table headerr
+ */
+
+static void PrintHeader(long int SystemSize, int maxl,
+ long int mudq, long int mldq,
+ long int mukeep, long int 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: %d\n",SystemSize);
+ printf("Subgrid dimensions: %d x %d", MXSUB, MYSUB);
+ printf(" Processor array: %d x %d\n", NPEX, NPEY);
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("Tolerance parameters: rtol = %Lg atol = %Lg\n", rtol, atol);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("Tolerance parameters: rtol = %lg atol = %lg\n", rtol, atol);
+#else
+ printf("Tolerance parameters: rtol = %g atol = %g\n", rtol, atol);
+#endif
+ printf("Linear solver: IDASPGMR 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("CalcIC called to correct initial predator concentrations \n\n");
+ printf("-----------------------------------------------------------\n");
+ printf(" t bottom-left top-right");
+ printf(" | nst k h\n");
+ printf("-----------------------------------------------------------\n\n");
+}
+
+
+/*
+ * PrintOutput: Print output values at output time t = tt.
+ * Selected run statistics are printed. Then values of c1 and c2
+ * are printed for the bottom left and top right grid points only.
+ */
+
+static void PrintOutput(void *mem, N_Vector cc, realtype tt,
+ UserData webdata, MPI_Comm comm)
+{
+ MPI_Status status;
+ realtype *cdata, clast[2], hused;
+ long int nst;
+ int i, kused, flag, thispe, npelast, ilast;;
+
+ thispe = webdata->thispe;
+ npelast = webdata->npes - 1;
+ cdata = NV_DATA_P(cc);
+
+ /* Send conc. at top right mesh point from PE npes-1 to PE 0. */
+ if (thispe == npelast) {
+ ilast = NUM_SPECIES*MXSUB*MYSUB - 2;
+ if (npelast != 0)
+ MPI_Send(&cdata[ilast], 2, PVEC_REAL_MPI_TYPE, 0, 0, comm);
+ else { clast[0] = cdata[ilast]; clast[1] = cdata[ilast+1]; }
+ }
+
+ /* On PE 0, receive conc. at top right from PE npes - 1.
+ Then print performance data and sampled solution values. */
+
+ if (thispe == 0) {
+
+ if (npelast != 0)
+ MPI_Recv(&clast[0], 2, PVEC_REAL_MPI_TYPE, npelast, 0, comm, &status);
+
+ flag = IDAGetLastOrder(mem, &kused);
+ check_flag(&flag, "IDAGetLastOrder", 1, thispe);
+ flag = IDAGetNumSteps(mem, &nst);
+ check_flag(&flag, "IDAGetNumSteps", 1, thispe);
+ flag = IDAGetLastStep(mem, &hused);
+ check_flag(&flag, "IDAGetLastStep", 1, thispe);
+
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("%8.2Le %12.4Le %12.4Le | %3ld %1d %12.4Le\n",
+ tt, cdata[0], clast[0], nst, kused, hused);
+ for (i=1;i<NUM_SPECIES;i++)
+ printf(" %12.4Le %12.4Le |\n",cdata[i],clast[i]);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("%8.2le %12.4le %12.4le | %3ld %1d %12.4le\n",
+ tt, cdata[0], clast[0], nst, kused, hused);
+ for (i=1;i<NUM_SPECIES;i++)
+ printf(" %12.4le %12.4le |\n",cdata[i],clast[i]);
+#else
+ printf("%8.2e %12.4e %12.4e | %3ld %1d %12.4e\n",
+ tt, cdata[0], clast[0], nst, kused, hused);
+ for (i=1;i<NUM_SPECIES;i++)
+ printf(" %12.4e %12.4e |\n",cdata[i],clast[i]);
+#endif
+ printf("\n");
+
+ }
+
+}
+
+/*
+ * PrintFinalStats: Print final run data contained in iopt.
+ */
+
+static void PrintFinalStats(void *mem)
+{
+ long int nst, nre, nreLS, netf, ncfn, nni, ncfl, nli, npe, nps, nge;
+ int flag;
+
+ flag = IDAGetNumSteps(mem, &nst);
+ check_flag(&flag, "IDAGetNumSteps", 1, 0);
+ flag = IDAGetNumResEvals(mem, &nre);
+ check_flag(&flag, "IDAGetNumResEvals", 1, 0);
+ flag = IDAGetNumErrTestFails(mem, &netf);
+ check_flag(&flag, "IDAGetNumErrTestFails", 1, 0);
+ flag = IDAGetNumNonlinSolvConvFails(mem, &ncfn);
+ check_flag(&flag, "IDAGetNumNonlinSolvConvFails", 1, 0);
+ flag = IDAGetNumNonlinSolvIters(mem, &nni);
+ check_flag(&flag, "IDAGetNumNonlinSolvIters", 1, 0);
+
+ flag = IDASpilsGetNumConvFails(mem, &ncfl);
+ check_flag(&flag, "IDASpilsGetNumConvFails", 1, 0);
+ flag = IDASpilsGetNumLinIters(mem, &nli);
+ check_flag(&flag, "IDASpilsGetNumLinIters", 1, 0);
+ flag = IDASpilsGetNumPrecEvals(mem, &npe);
+ check_flag(&flag, "IDASpilsGetNumPrecEvals", 1, 0);
+ flag = IDASpilsGetNumPrecSolves(mem, &nps);
+ check_flag(&flag, "IDASpilsGetNumPrecSolves", 1, 0);
+ flag = IDASpilsGetNumResEvals(mem, &nreLS);
+ check_flag(&flag, "IDASpilsGetNumResEvals", 1, 0);
+
+ flag = IDABBDPrecGetNumGfnEvals(mem, &nge);
+ check_flag(&flag, "IDABBDPrecGetNumGfnEvals", 1, 0);
+
+ printf("-----------------------------------------------------------\n");
+ printf("\nFinal statistics: \n\n");
+
+ printf("Number of steps = %ld\n", nst);
+ printf("Number of residual evaluations = %ld\n", nre+nreLS);
+ printf("Number of nonlinear iterations = %ld\n", nni);
+ printf("Number of error test failures = %ld\n", netf);
+ printf("Number of nonlinear conv. failures = %ld\n\n", ncfn);
+
+ printf("Number of linear iterations = %ld\n", nli);
+ printf("Number of linear conv. failures = %ld\n\n", ncfl);
+
+ printf("Number of preconditioner setups = %ld\n", npe);
+ printf("Number of preconditioner solves = %ld\n", nps);
+ printf("Number of local residual evals. = %ld\n", nge);
+
+}
+
+/*
+ * 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, char *funcname, int opt, int id)
+{
+ int *errflag;
+
+ if (opt == 0 && flagvalue == NULL) {
+ /* Check if SUNDIALS function returned NULL pointer - no memory allocated */
+ fprintf(stderr,
+ "\nSUNDIALS_ERROR(%d): %s() failed - returned NULL pointer\n\n",
+ id, funcname);
+ return(1);
+ } else if (opt == 1) {
+ /* Check if flag < 0 */
+ errflag = (int *) flagvalue;
+ if (*errflag < 0) {
+ fprintf(stderr,
+ "\nSUNDIALS_ERROR(%d): %s() failed with flag = %d\n\n",
+ id, funcname, *errflag);
+ return(1);
+ }
+ } else if (opt == 2 && flagvalue == NULL) {
+ /* Check if function returned NULL pointer - no memory allocated */
+ fprintf(stderr,
+ "\nMEMORY_ERROR(%d): %s() failed - returned NULL pointer\n\n",
+ id, funcname);
+ return(1);
+ }
+
+ return(0);
+}
+
+/*
+ *--------------------------------------------------------------------
+ * FUNCTIONS CALLED BY IDA & SUPPORTING FUNCTIONS
+ *--------------------------------------------------------------------
+ */
+
+/*
+ * resweb: System residual function for predator-prey system.
+ * To compute the residual function F, this routine calls:
+ * rescomm, for needed communication, and then
+ * reslocal, for computation of the residuals on this processor.
+ */
+
+static int resweb(realtype tt,
+ N_Vector cc, N_Vector cp, N_Vector rr,
+ void *user_data)
+{
+ int retval;
+ UserData webdata;
+ long int Nlocal;
+
+ webdata = (UserData) user_data;
+
+ Nlocal = webdata->n_local;
+
+ /* Call rescomm to do inter-processor communication. */
+ retval = rescomm(Nlocal, tt, cc, cp, user_data);
+
+ /* Call reslocal to calculate the local portion of residual vector. */
+ retval = reslocal(Nlocal, tt, cc, cp, rr, user_data);
+
+ return(0);
+}
+
+/*
+ * rescomm: Communication routine in support of resweb.
+ * This routine performs all inter-processor communication of components
+ * of the cc vector needed to calculate F, namely the components at all
+ * interior subgrid boundaries (ghost cell data). It loads this data
+ * into a work array cext (the local portion of c, extended).
+ * 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 cc, N_Vector cp,
+ void *user_data)
+{
+
+ UserData webdata;
+ realtype *cdata, *cext, buffer[2*NUM_SPECIES*MYSUB];
+ int thispe, ixsub, jysub, nsmxsub, nsmysub;
+ MPI_Comm comm;
+ MPI_Request request[4];
+
+ webdata = (UserData) user_data;
+ cdata = NV_DATA_P(cc);
+
+ /* Get comm, thispe, subgrid indices, data sizes, extended array cext. */
+
+ comm = webdata->comm;
+ thispe = webdata->thispe;
+
+ ixsub = webdata->ixsub;
+ jysub = webdata->jysub;
+ cext = webdata->cext;
+ nsmxsub = webdata->nsmxsub;
+ nsmysub = (webdata->ns)*(webdata->mysub);
+
+ /* Start receiving boundary data from neighboring PEs. */
+
+ BRecvPost(comm, request, thispe, ixsub, jysub, nsmxsub, nsmysub,
+ cext, buffer);
+
+ /* Send data from boundary of local grid to neighboring PEs. */
+
+ BSend(comm, thispe, ixsub, jysub, nsmxsub, nsmysub, cdata);
+
+ /* Finish receiving boundary data from neighboring PEs. */
+
+ BRecvWait(request, ixsub, jysub, nsmxsub, cext, buffer);
+
+ return(0);
+}
+
+/*
+ * BRecvPost: Start receiving boundary data from neighboring PEs.
+ * (1) buffer should be able to hold 2*NUM_SPECIES*MYSUB realtype entries,
+ * should be passed to both the BRecvPost and BRecvWait functions, and
+ * should not be manipulated between the two calls.
+ * (2) request should have 4 entries, and is also passed in both calls.
+ */
+
+static void BRecvPost(MPI_Comm comm, MPI_Request request[], int my_pe,
+ int ixsub, int jysub,
+ int dsizex, int dsizey,
+ realtype cext[], realtype buffer[])
+{
+ int offsetce;
+ /* Have bufleft and bufright use the same buffer. */
+ realtype *bufleft = buffer, *bufright = buffer+NUM_SPECIES*MYSUB;
+
+ /* If jysub > 0, receive data for bottom x-line of cext. */
+ if (jysub != 0)
+ MPI_Irecv(&cext[NUM_SPECIES], dsizex, PVEC_REAL_MPI_TYPE,
+ my_pe-NPEX, 0, comm, &request[0]);
+
+ /* If jysub < NPEY-1, receive data for top x-line of cext. */
+ if (jysub != NPEY-1) {
+ offsetce = NUM_SPECIES*(1 + (MYSUB+1)*(MXSUB+2));
+ MPI_Irecv(&cext[offsetce], dsizex, PVEC_REAL_MPI_TYPE,
+ my_pe+NPEX, 0, comm, &request[1]);
+ }
+
+ /* If ixsub > 0, receive data for left y-line of cext (via bufleft). */
+ if (ixsub != 0) {
+ MPI_Irecv(&bufleft[0], dsizey, PVEC_REAL_MPI_TYPE,
+ my_pe-1, 0, comm, &request[2]);
+ }
+
+ /* If ixsub < NPEX-1, receive data for right y-line of cext (via bufright). */
+ if (ixsub != NPEX-1) {
+ MPI_Irecv(&bufright[0], dsizey, PVEC_REAL_MPI_TYPE,
+ my_pe+1, 0, comm, &request[3]);
+ }
+
+}
+
+/*
+ * BRecvWait: Finish receiving boundary data from neighboring PEs.
+ * (1) buffer should be able to hold 2*NUM_SPECIES*MYSUB realtype entries,
+ * should be passed to both the BRecvPost and BRecvWait functions, and
+ * should not be manipulated between the two calls.
+ * (2) request should have 4 entries, and is also passed in both calls.
+ */
+
+static void BRecvWait(MPI_Request request[], int ixsub, int jysub,
+ int dsizex, realtype cext[], realtype buffer[])
+{
+ int i;
+ int ly, dsizex2, offsetce, offsetbuf;
+ realtype *bufleft = buffer, *bufright = buffer+NUM_SPECIES*MYSUB;
+ MPI_Status status;
+
+ dsizex2 = dsizex + 2*NUM_SPECIES;
+
+ /* If jysub > 0, receive data for bottom x-line of cext. */
+ if (jysub != 0)
+ MPI_Wait(&request[0],&status);
+
+ /* If jysub < NPEY-1, receive data for top x-line of cext. */
+ if (jysub != NPEY-1)
+ MPI_Wait(&request[1],&status);
+
+ /* If ixsub > 0, receive data for left y-line of cext (via bufleft). */
+ if (ixsub != 0) {
+ MPI_Wait(&request[2],&status);
+
+ /* Copy the buffer to cext */
+ for (ly = 0; ly < MYSUB; ly++) {
+ offsetbuf = ly*NUM_SPECIES;
+ offsetce = (ly+1)*dsizex2;
+ for (i = 0; i < NUM_SPECIES; i++)
+ cext[offsetce+i] = bufleft[offsetbuf+i];
+ }
+ }
+
+ /* If ixsub < NPEX-1, receive data for right y-line of cext (via bufright). */
+ if (ixsub != NPEX-1) {
+ MPI_Wait(&request[3],&status);
+
+ /* Copy the buffer to cext */
+ for (ly = 0; ly < MYSUB; ly++) {
+ offsetbuf = ly*NUM_SPECIES;
+ offsetce = (ly+2)*dsizex2 - NUM_SPECIES;
+ for (i = 0; i < NUM_SPECIES; i++)
+ cext[offsetce+i] = bufright[offsetbuf+i];
+ }
+ }
+}
+
+/*
+ * BSend: Send boundary data to neighboring PEs.
+ * This routine sends components of cc from internal subgrid boundaries
+ * to the appropriate neighbor PEs.
+ */
+
+static void BSend(MPI_Comm comm, int my_pe, int ixsub, int jysub,
+ int dsizex, int dsizey, realtype cdata[])
+{
+ int i;
+ int ly, offsetc, offsetbuf;
+ realtype bufleft[NUM_SPECIES*MYSUB], bufright[NUM_SPECIES*MYSUB];
+
+ /* If jysub > 0, send data from bottom x-line of cc. */
+
+ if (jysub != 0)
+ MPI_Send(&cdata[0], dsizex, PVEC_REAL_MPI_TYPE, my_pe-NPEX, 0, comm);
+
+ /* If jysub < NPEY-1, send data from top x-line of cc. */
+
+ if (jysub != NPEY-1) {
+ offsetc = (MYSUB-1)*dsizex;
+ MPI_Send(&cdata[offsetc], dsizex, PVEC_REAL_MPI_TYPE, my_pe+NPEX, 0, comm);
+ }
+
+ /* If ixsub > 0, send data from left y-line of cc (via bufleft). */
+
+ if (ixsub != 0) {
+ for (ly = 0; ly < MYSUB; ly++) {
+ offsetbuf = ly*NUM_SPECIES;
+ offsetc = ly*dsizex;
+ for (i = 0; i < NUM_SPECIES; i++)
+ bufleft[offsetbuf+i] = cdata[offsetc+i];
+ }
+ MPI_Send(&bufleft[0], dsizey, PVEC_REAL_MPI_TYPE, my_pe-1, 0, comm);
+ }
+
+ /* If ixsub < NPEX-1, send data from right y-line of cc (via bufright). */
+
+ if (ixsub != NPEX-1) {
+ for (ly = 0; ly < MYSUB; ly++) {
+ offsetbuf = ly*NUM_SPECIES;
+ offsetc = offsetbuf*MXSUB + (MXSUB-1)*NUM_SPECIES;
+ for (i = 0; i < NUM_SPECIES; i++)
+ bufright[offsetbuf+i] = cdata[offsetc+i];
+ }
+ MPI_Send(&bufright[0], dsizey, PVEC_REAL_MPI_TYPE, my_pe+1, 0, comm);
+ }
+}
+
+/* Define lines are for ease of readability in the following functions. */
+
+#define mxsub (webdata->mxsub)
+#define mysub (webdata->mysub)
+#define npex (webdata->npex)
+#define npey (webdata->npey)
+#define ixsub (webdata->ixsub)
+#define jysub (webdata->jysub)
+#define nsmxsub (webdata->nsmxsub)
+#define nsmxsub2 (webdata->nsmxsub2)
+#define np (webdata->np)
+#define dx (webdata->dx)
+#define dy (webdata->dy)
+#define cox (webdata->cox)
+#define coy (webdata->coy)
+#define rhs (webdata->rhs)
+#define cext (webdata->cext)
+#define rates (webdata->rates)
+#define ns (webdata->ns)
+#define acoef (webdata->acoef)
+#define bcoef (webdata->bcoef)
+
+/*
+ * reslocal: Compute res = F(t,cc,cp).
+ * This routine assumes that all inter-processor communication of data
+ * needed to calculate F has already been done. Components at interior
+ * subgrid boundaries are assumed to be in the work array cext.
+ * The local portion of the cc vector is first copied into cext.
+ * The exterior Neumann boundary conditions are explicitly handled here
+ * by copying data from the first interior mesh line to the ghost cell
+ * locations in cext. Then the reaction and diffusion terms are
+ * evaluated in terms of the cext array, and the residuals are formed.
+ * The reaction terms are saved separately in the vector webdata->rates
+ * for use by the preconditioner setup routine.
+ */
+
+static int reslocal(long int Nlocal, realtype tt,
+ N_Vector cc, N_Vector cp, N_Vector rr,
+ void *user_data)
+{
+ realtype *cdata, *ratesxy, *cpxy, *resxy,
+ xx, yy, dcyli, dcyui, dcxli, dcxui;
+ int ix, jy, is, i, locc, ylocce, locce;
+ UserData webdata;
+
+ webdata = (UserData) user_data;
+
+ /* Get data pointers, subgrid data, array sizes, work array cext. */
+
+ cdata = NV_DATA_P(cc);
+
+ /* Copy local segment of cc vector into the working extended array cext. */
+
+ locc = 0;
+ locce = nsmxsub2 + NUM_SPECIES;
+ for (jy = 0; jy < mysub; jy++) {
+ for (i = 0; i < nsmxsub; i++) cext[locce+i] = cdata[locc+i];
+ locc = locc + nsmxsub;
+ locce = locce + nsmxsub2;
+ }
+
+ /* To facilitate homogeneous Neumann boundary conditions, when this is
+ a boundary PE, copy data from the first interior mesh line of cc to cext. */
+
+ /* If jysub = 0, copy x-line 2 of cc to cext. */
+ if (jysub == 0)
+ { for (i = 0; i < nsmxsub; i++) cext[NUM_SPECIES+i] = cdata[nsmxsub+i]; }
+
+ /* If jysub = npey-1, copy x-line mysub-1 of cc to cext. */
+ if (jysub == npey-1) {
+ locc = (mysub-2)*nsmxsub;
+ locce = (mysub+1)*nsmxsub2 + NUM_SPECIES;
+ for (i = 0; i < nsmxsub; i++) cext[locce+i] = cdata[locc+i];
+ }
+
+ /* If ixsub = 0, copy y-line 2 of cc to cext. */
+ if (ixsub == 0) {
+ for (jy = 0; jy < mysub; jy++) {
+ locc = jy*nsmxsub + NUM_SPECIES;
+ locce = (jy+1)*nsmxsub2;
+ for (i = 0; i < NUM_SPECIES; i++) cext[locce+i] = cdata[locc+i];
+ }
+ }
+
+ /* If ixsub = npex-1, copy y-line mxsub-1 of cc to cext. */
+ if (ixsub == npex-1) {
+ for (jy = 0; jy < mysub; jy++) {
+ locc = (jy+1)*nsmxsub - 2*NUM_SPECIES;
+ locce = (jy+2)*nsmxsub2 - NUM_SPECIES;
+ for (i = 0; i < NUM_SPECIES; i++) cext[locce+i] = cdata[locc+i];
+ }
+ }
+
+ /* Loop over all grid points, setting local array rates to right-hand sides.
+ Then set rr values appropriately for prey/predator components of F. */
+
+ for (jy = 0; jy < mysub; jy++) {
+ ylocce = (jy+1)*nsmxsub2;
+ yy = (jy+jysub*mysub)*dy;
+
+ for (ix = 0; ix < mxsub; ix++) {
+ locce = ylocce + (ix+1)*NUM_SPECIES;
+ xx = (ix + ixsub*mxsub)*dx;
+
+ ratesxy = IJ_Vptr(rates,ix,jy);
+ WebRates(xx, yy, &(cext[locce]), ratesxy, webdata);
+
+ resxy = IJ_Vptr(rr,ix,jy);
+ cpxy = IJ_Vptr(cp,ix,jy);
+
+ for (is = 0; is < NUM_SPECIES; is++) {
+ dcyli = cext[locce+is] - cext[locce+is-nsmxsub2];
+ dcyui = cext[locce+is+nsmxsub2] - cext[locce+is];
+
+ dcxli = cext[locce+is] - cext[locce+is-NUM_SPECIES];
+ dcxui = cext[locce+is+NUM_SPECIES] - cext[locce+is];
+
+ rhs[is] = cox[is]*(dcxui-dcxli) + coy[is]*(dcyui-dcyli) + ratesxy[is];
+
+ if (is < np) resxy[is] = cpxy[is] - rhs[is];
+ else resxy[is] = - rhs[is];
+
+ }
+ }
+ }
+
+ return(0);
+}
+
+/*
+ * WebRates: Evaluate reaction rates at a given spatial point.
+ * At a given (x,y), evaluate the array of ns reaction terms R.
+ */
+
+static void WebRates(realtype xx, realtype yy, realtype *cxy, realtype *ratesxy,
+ UserData webdata)
+{
+ int is;
+ realtype fac;
+
+ for (is = 0; is < NUM_SPECIES; is++)
+ ratesxy[is] = dotprod(NUM_SPECIES, cxy, acoef[is]);
+
+ fac = ONE + ALPHA*xx*yy + BETA*sin(FOURPI*xx)*sin(FOURPI*yy);
+
+ for (is = 0; is < NUM_SPECIES; is++)
+ ratesxy[is] = cxy[is]*( bcoef[is]*fac + ratesxy[is] );
+
+}
+
+/*
+ * dotprod: dot product routine for realtype arrays, for use by WebRates.
+ */
+
+static realtype dotprod(int size, realtype *x1, realtype *x2)
+{
+ int i;
+ realtype *xx1, *xx2, temp = ZERO;
+
+ xx1 = x1;
+ xx2 = x2;
+ for (i = 0; i < size; i++)
+ temp += (*xx1++) * (*xx2++);
+
+ return(temp);
+}
+
diff --git a/examples/ida/parallel/idaFoodWeb_kry_bbd_p.out b/examples/ida/parallel/idaFoodWeb_kry_bbd_p.out
new file mode 100644
index 0000000..16b0f3c
--- /dev/null
+++ b/examples/ida/parallel/idaFoodWeb_kry_bbd_p.out
@@ -0,0 +1,58 @@
+
+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
+CalcIC called to correct initial predator concentrations
+
+-----------------------------------------------------------
+ t bottom-left top-right | nst k h
+-----------------------------------------------------------
+
+0.00e+00 1.0000e+01 1.0000e+01 | 0 0 1.6310e-08
+ 1.0000e+05 1.0000e+05 |
+
+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.6189e+06 1.9735e+06 |
+
+1.00e-01 2.4019e+02 2.7072e+02 | 197 1 4.0396e-02
+ 2.4019e+06 2.7072e+06 |
+
+4.00e-01 2.4019e+02 2.7072e+02 | 200 1 3.2316e-01
+ 2.4019e+06 2.7072e+06 |
+
+7.00e-01 2.4019e+02 2.7072e+02 | 200 1 3.2316e-01
+ 2.4019e+06 2.7072e+06 |
+
+1.00e+00 2.4019e+02 2.7072e+02 | 201 1 6.4633e-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 error test failures = 0
+Number of nonlinear conv. failures = 0
+
+Number of linear iterations = 863
+Number of linear conv. failures = 0
+
+Number of preconditioner setups = 26
+Number of preconditioner solves = 1110
+Number of local residual evals. = 1092
diff --git a/examples/ida/parallel/idaFoodWeb_kry_p.c b/examples/ida/parallel/idaFoodWeb_kry_p.c
new file mode 100644
index 0000000..2940b05
--- /dev/null
+++ b/examples/ida/parallel/idaFoodWeb_kry_p.c
@@ -0,0 +1,1231 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.3 $
+ * $Date: 2010/12/01 23:03:29 $
+ * -----------------------------------------------------------------
+ * Programmer(s): 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.
+ * 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.
+ *
+ * The mathematical problem solved in this example is a DAE system
+ * that arises from a system of partial differential equations after
+ * spatial discretization. The PDE system is a food web population
+ * model, with predator-prey interaction and diffusion on the unit
+ * square in two dimensions. The dependent variable vector is:
+ *
+ * 1 2 ns
+ * c = (c , c , ..., c ) , ns = 2 * np
+ *
+ * and the PDE's are as follows:
+ *
+ * i i i
+ * dc /dt = d(i)*(c + c ) + R (x,y,c) (i = 1,...,np)
+ * xx yy i
+ *
+ * i i
+ * 0 = d(i)*(c + c ) + R (x,y,c) (i = np+1,...,ns)
+ * xx yy i
+ *
+ * where the reaction terms R are:
+ *
+ * i ns j
+ * R (x,y,c) = c * (b(i) + sum a(i,j)*c )
+ * i j=1
+ *
+ * The number of species is ns = 2 * np, with the first np being
+ * prey and the last np being predators. The coefficients a(i,j),
+ * b(i), d(i) are:
+ *
+ * a(i,i) = -AA (all i)
+ * a(i,j) = -GG (i <= np , j > np)
+ * a(i,j) = EE (i > np, j <= np)
+ * all other a(i,j) = 0
+ * b(i) = BB*(1+ alpha * x*y + beta*sin(4 pi x)*sin(4 pi y)) (i <= np)
+ * b(i) =-BB*(1+ alpha * x*y + beta*sin(4 pi x)*sin(4 pi y)) (i > np)
+ * d(i) = DPREY (i <= np)
+ * d(i) = DPRED (i > np)
+ *
+ * Note: The above equations are written in 1-based indices,
+ * whereas the code has 0-based indices, being written in C.
+ *
+ * The various scalar parameters required are set using '#define'
+ * statements or directly in routine InitUserData. In this program,
+ * np = 1, ns = 2. The boundary conditions are homogeneous Neumann:
+ * normal derivative = 0.
+ *
+ * A polynomial in x and y is used to set the initial values of the
+ * first np variables (the prey variables) at each x,y location,
+ * while initial values for the remaining (predator) variables are
+ * set to a flat value, which is corrected by IDACalcIC.
+ *
+ * The PDEs are discretized by central differencing on a MX by MY
+ * mesh, and so the system size Neq is the product
+ * MX * MY * NUM_SPECIES. The system is actually implemented on
+ * 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, which uses the preconditioned GMRES iterative method to
+ * solve linear systems. The precondtioner supplied to IDASPGMR 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.
+ * -----------------------------------------------------------------
+ * References:
+ * [1] Peter N. Brown and Alan C. Hindmarsh,
+ * Reduced Storage Matrix Methods in Stiff ODE systems,
+ * Journal of Applied Mathematics and Computation, Vol. 31
+ * (May 1989), pp. 40-91.
+ *
+ * [2] Peter N. Brown, Alan C. Hindmarsh, and Linda R. Petzold,
+ * Using Krylov Methods in the Solution of Large-Scale
+ * Differential-Algebraic Systems, SIAM J. Sci. Comput., 15
+ * (1994), pp. 1467-1488.
+ *
+ * [3] Peter N. Brown, Alan C. Hindmarsh, and Linda R. Petzold,
+ * 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_parallel.h>
+#include <sundials/sundials_dense.h>
+#include <sundials/sundials_types.h>
+#include <sundials/sundials_math.h>
+
+#include <mpi.h>
+
+/* Problem Constants. */
+
+#define NPREY 1 /* Number of prey (= number of predators). */
+#define NUM_SPECIES 2*NPREY
+
+#define PI RCONST(3.1415926535898) /* pi */
+#define FOURPI (RCONST(4.0)*PI) /* 4 pi */
+
+#define MXSUB 10 /* Number of x mesh points per processor subgrid */
+#define MYSUB 10 /* Number of y mesh points per processor subgrid */
+#define NPEX 2 /* Number of subgrids in the x direction */
+#define NPEY 2 /* Number of subgrids in the y direction */
+#define MX (MXSUB*NPEX) /* MX = number of x mesh points */
+#define MY (MYSUB*NPEY) /* MY = number of y mesh points */
+#define NSMXSUB (NUM_SPECIES * MXSUB)
+#define NEQ (NUM_SPECIES*MX*MY) /* Number of equations in system */
+#define AA RCONST(1.0) /* Coefficient in above eqns. for a */
+#define EE RCONST(10000.) /* Coefficient in above eqns. for a */
+#define GG RCONST(0.5e-6) /* Coefficient in above eqns. for a */
+#define BB RCONST(1.0) /* Coefficient in above eqns. for b */
+#define DPREY RCONST(1.0) /* Coefficient in above eqns. for d */
+#define DPRED RCONST(0.05) /* Coefficient in above eqns. for d */
+#define ALPHA RCONST(50.) /* Coefficient alpha in above eqns. */
+#define BETA RCONST(1000.) /* Coefficient beta in above eqns. */
+#define AX RCONST(1.0) /* Total range of x variable */
+#define AY RCONST(1.0) /* Total range of y variable */
+#define RTOL RCONST(1.e-5) /* rtol tolerance */
+#define ATOL RCONST(1.e-5) /* atol tolerance */
+#define ZERO RCONST(0.) /* 0. */
+#define ONE RCONST(1.0) /* 1. */
+#define NOUT 6
+#define TMULT RCONST(10.0) /* Multiplier for tout values */
+#define TADD RCONST(0.3) /* Increment for tout values */
+
+
+/* User-defined vector accessor macro IJ_Vptr. */
+
+/* IJ_Vptr is defined in order to express the underlying 3-d structure of the
+ dependent variable vector from its underlying 1-d storage (an N_Vector).
+ IJ_Vptr(vv,i,j) returns a pointer to the location in vv corresponding to
+ species index is = 0, x-index ix = i, and y-index jy = j. */
+
+#define IJ_Vptr(vv,i,j) (&NV_Ith_P(vv, (i)*NUM_SPECIES + (j)*NSMXSUB ))
+
+/* Type: UserData. Contains problem constants, preconditioner data, etc. */
+
+typedef struct {
+ long int ns;
+ int np, thispe, npes, ixsub, jysub, npex, npey;
+ int mxsub, mysub, nsmxsub, nsmxsub2;
+ realtype dx, dy, **acoef;
+ realtype cox[NUM_SPECIES], coy[NUM_SPECIES], bcoef[NUM_SPECIES],
+ rhs[NUM_SPECIES], cext[(MXSUB+2)*(MYSUB+2)*NUM_SPECIES];
+ MPI_Comm comm;
+ N_Vector rates;
+ realtype **PP[MXSUB][MYSUB];
+ long int *pivot[MXSUB][MYSUB];
+ N_Vector ewt;
+ void *ida_mem;
+} *UserData;
+
+
+/* Prototypes for user-supplied and supporting functions. */
+
+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 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 rescomm(N_Vector cc, N_Vector cp, void *user_data);
+
+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,
+ realtype cext[], realtype buffer[]);
+
+static void BRecvWait(MPI_Request request[], int ixsub, int jysub,
+ int dsizex, realtype cext[], realtype buffer[]);
+
+static int reslocal(realtype tt, N_Vector cc, N_Vector cp, N_Vector res,
+ void *user_data);
+
+static void WebRates(realtype xx, realtype yy, realtype *cxy, realtype *ratesxy,
+ UserData webdata);
+
+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 void InitUserData(UserData webdata, int thispe, int npes,
+ MPI_Comm comm);
+
+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,
+ realtype rtol, realtype atol);
+
+static void PrintOutput(void *mem, N_Vector cc, realtype time,
+ UserData webdata, MPI_Comm comm);
+
+static void PrintFinalStats(void *mem);
+
+static int check_flag(void *flagvalue, char *funcname, int opt, int id);
+
+/*
+ *--------------------------------------------------------------------
+ * MAIN PROGRAM
+ *--------------------------------------------------------------------
+ */
+
+int main(int argc, char *argv[])
+{
+ MPI_Comm comm;
+ void *mem;
+ UserData webdata;
+ long int 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;
+
+ /* Set communicator, and get processor number and total number of PE's. */
+
+ MPI_Init(&argc, &argv);
+ comm = MPI_COMM_WORLD;
+ MPI_Comm_rank(comm, &thispe);
+ MPI_Comm_size(comm, &npes);
+
+ if (npes != NPEX*NPEY) {
+ if (thispe == 0)
+ fprintf(stderr,
+ "\nMPI_ERROR(0): npes = %d not equal to NPEX*NPEY = %d\n",
+ npes, NPEX*NPEY);
+ MPI_Finalize();
+ return(1);
+ }
+
+ /* Set local length (local_N) and global length (SystemSize). */
+
+ local_N = MXSUB*MYSUB*NUM_SPECIES;
+ SystemSize = NEQ;
+
+ /* Set up user data block webdata. */
+
+ webdata = AllocUserData(comm, local_N, SystemSize);
+ if (check_flag((void *)webdata, "AllocUserData", 0, thispe)) MPI_Abort(comm, 1);
+
+ InitUserData(webdata, thispe, npes, comm);
+
+ /* Create needed vectors, and load initial values.
+ The vector res is used temporarily only. */
+
+ cc = N_VNew_Parallel(comm, local_N, SystemSize);
+ if (check_flag((void *)cc, "N_VNew_Parallel", 0, thispe)) MPI_Abort(comm, 1);
+
+ cp = N_VNew_Parallel(comm, local_N, SystemSize);
+ if (check_flag((void *)cp, "N_VNew_Parallel", 0, thispe)) MPI_Abort(comm, 1);
+
+ res = N_VNew_Parallel(comm, local_N, SystemSize);
+ if (check_flag((void *)res, "N_VNew_Parallel", 0, thispe)) MPI_Abort(comm, 1);
+
+ id = N_VNew_Parallel(comm, local_N, SystemSize);
+ if (check_flag((void *)id, "N_VNew_Parallel", 0, thispe)) MPI_Abort(comm, 1);
+
+ SetInitialProfiles(cc, cp, id, res, webdata);
+
+ N_VDestroy(res);
+
+ /* Set remaining inputs to IDAMalloc. */
+
+ t0 = ZERO;
+ rtol = RTOL;
+ atol = ATOL;
+
+ /* 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);
+
+ flag = IDASetUserData(mem, webdata);
+ if (check_flag(&flag, "IDASetUserData", 1, thispe)) MPI_Abort(comm, 1);
+
+ flag = IDASetId(mem, id);
+ if (check_flag(&flag, "IDASetId", 1, thispe)) MPI_Abort(comm, 1);
+
+ flag = IDAInit(mem, resweb, t0, cc, cp);
+ if (check_flag(&flag, "IDAinit", 1, thispe)) MPI_Abort(comm, 1);
+
+ flag = IDASStolerances(mem, rtol, atol);
+ if (check_flag(&flag, "IDASStolerances", 1, thispe)) MPI_Abort(comm, 1);
+
+ webdata->ida_mem = 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. */
+
+ maxl = 16;
+ flag = IDASpgmr(mem, maxl);
+ if (check_flag(&flag, "IDASpgmr", 1, thispe))
+ MPI_Abort(comm, 1);
+
+ flag = IDASpilsSetPreconditioner(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);
+ 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);
+
+ /* 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);
+ if (check_flag(&flag, "IDASolve", 1, thispe)) MPI_Abort(comm, 1);
+
+ PrintOutput(mem, cc, tret, webdata, comm);
+
+ if (iout < 3) tout *= TMULT;
+ else tout += TADD;
+
+ }
+
+ /* On PE 0, print final set of statistics. */
+ if (thispe == 0) PrintFinalStats(mem);
+
+ /* Free memory. */
+
+ N_VDestroy_Parallel(cc);
+ N_VDestroy_Parallel(cp);
+ N_VDestroy_Parallel(id);
+
+ IDAFree(&mem);
+
+ FreeUserData(webdata);
+
+ MPI_Finalize();
+
+ return(0);
+
+}
+
+/*
+ *--------------------------------------------------------------------
+ * PRIVATE FUNCTIONS
+ *--------------------------------------------------------------------
+ */
+
+/*
+ * AllocUserData: Allocate memory for data structure of type UserData.
+ */
+
+static UserData AllocUserData(MPI_Comm comm, long int local_N, long int SystemSize)
+{
+ int ix, jy;
+ UserData webdata;
+
+ webdata = (UserData) malloc(sizeof *webdata);
+
+ webdata->rates = N_VNew_Parallel(comm, local_N, SystemSize);
+
+ 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->acoef = newDenseMat(NUM_SPECIES, NUM_SPECIES);
+ webdata->ewt = N_VNew_Parallel(comm, local_N, SystemSize);
+ return(webdata);
+
+}
+
+/*
+ * InitUserData: Load problem constants in webdata (of type UserData).
+ */
+
+static void InitUserData(UserData webdata, int thispe, int npes,
+ MPI_Comm comm)
+{
+ int i, j, np;
+ realtype *a1,*a2, *a3, *a4, dx2, dy2, **acoef, *bcoef, *cox, *coy;
+
+ webdata->jysub = thispe / NPEX;
+ webdata->ixsub = thispe - (webdata->jysub)*NPEX;
+ webdata->mxsub = MXSUB;
+ webdata->mysub = MYSUB;
+ webdata->npex = NPEX;
+ webdata->npey = NPEY;
+ webdata->ns = NUM_SPECIES;
+ webdata->np = NPREY;
+ webdata->dx = AX/(MX-1);
+ webdata->dy = AY/(MY-1);
+ webdata->thispe = thispe;
+ webdata->npes = npes;
+ webdata->nsmxsub = MXSUB * NUM_SPECIES;
+ webdata->nsmxsub2 = (MXSUB+2)*NUM_SPECIES;
+ webdata->comm = comm;
+
+ /* Set up the coefficients a and b plus others found in the equations. */
+ np = webdata->np;
+ dx2 = (webdata->dx)*(webdata->dx); dy2 = (webdata->dy)*(webdata->dy);
+
+ acoef = webdata->acoef;
+ bcoef = webdata->bcoef;
+ cox = webdata->cox;
+ coy = webdata->coy;
+
+ for (i = 0; i < np; i++) {
+ a1 = &(acoef[i][np]);
+ a2 = &(acoef[i+np][0]);
+ a3 = &(acoef[i][0]);
+ a4 = &(acoef[i+np][np]);
+
+ /* Fill in the portion of acoef in the four quadrants, row by row. */
+ for (j = 0; j < np; j++) {
+ *a1++ = -GG;
+ *a2++ = EE;
+ *a3++ = ZERO;
+ *a4++ = ZERO;
+ }
+
+ /* Reset the diagonal elements of acoef to -AA. */
+ acoef[i][i] = -AA; acoef[i+np][i+np] = -AA;
+
+ /* Set coefficients for b and diffusion terms. */
+ bcoef[i] = BB; bcoef[i+np] = -BB;
+ cox[i] = DPREY/dx2; cox[i+np] = DPRED/dx2;
+ coy[i] = DPREY/dy2; coy[i+np] = DPRED/dy2;
+ }
+
+}
+
+/*
+ * FreeUserData: Free webdata memory.
+ */
+
+static void FreeUserData(UserData webdata)
+{
+ int ix, jy;
+
+ for (ix = 0; ix < MXSUB; ix++) {
+ for (jy = 0; jy < MYSUB; jy++) {
+ destroyMat((webdata->PP)[ix][jy]);
+ destroyArray((webdata->pivot)[ix][jy]);
+ }
+ }
+
+ destroyMat(webdata->acoef);
+ N_VDestroy_Parallel(webdata->rates);
+ N_VDestroy_Parallel(webdata->ewt);
+ free(webdata);
+
+}
+
+/*
+ * SetInitialProfiles: Set initial conditions in cc, cp, and id.
+ * A polynomial profile is used for the prey cc values, and a constant
+ * (1.0e5) is loaded as the initial guess for the predator cc values.
+ * The id values are set to 1 for the prey and 0 for the predators.
+ * The prey cp values are set according to the given system, and
+ * the predator cp values are set to zero.
+ */
+
+static void SetInitialProfiles(N_Vector cc, N_Vector cp, N_Vector id,
+ N_Vector res, UserData webdata)
+{
+ int ixsub, jysub, mxsub, mysub, nsmxsub, np, ix, jy, is;
+ realtype *cxy, *idxy, *cpxy, dx, dy, xx, yy, xyfactor;
+
+ ixsub = webdata->ixsub;
+ jysub = webdata->jysub;
+ mxsub = webdata->mxsub;
+ mysub = webdata->mxsub;
+ nsmxsub = webdata->nsmxsub;
+ dx = webdata->dx;
+ dy = webdata->dy;
+ np = webdata->np;
+
+ /* Loop over grid, load cc values and id values. */
+ for (jy = 0; jy < mysub; jy++) {
+ yy = (jy + jysub*mysub) * dy;
+ for (ix = 0; ix < mxsub; ix++) {
+ xx = (ix + ixsub*mxsub) * dx;
+ xyfactor = RCONST(16.0)*xx*(ONE - xx)*yy*(ONE - yy);
+ xyfactor *= xyfactor;
+
+ 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; }
+ else { cxy[is] = 1.0e5; idxy[is] = ZERO; }
+ }
+ }
+ }
+
+ /* Set c' for the prey by calling the residual function with cp = 0. */
+ N_VConst(ZERO, cp);
+ resweb(ZERO, cc, cp, res, webdata);
+ N_VScale(-ONE, res, cp);
+
+ /* Set c' for predators to 0. */
+ for (jy = 0; jy < mysub; jy++) {
+ for (ix = 0; ix < mxsub; ix++) {
+ cpxy = IJ_Vptr(cp,ix,jy);
+ for (is = np; is < NUM_SPECIES; is++) cpxy[is] = ZERO;
+ }
+ }
+}
+
+/*
+ * Print first lines of output (problem description)
+ */
+
+static void PrintHeader(long int 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: %d\n",SystemSize);
+ printf("Subgrid dimensions: %d x %d", MXSUB, MYSUB);
+ printf(" Processor array: %d x %d\n", NPEX, NPEY);
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("Tolerance parameters: rtol = %Lg atol = %Lg\n", rtol, atol);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("Tolerance parameters: rtol = %lg atol = %lg\n", rtol, atol);
+#else
+ printf("Tolerance parameters: rtol = %g atol = %g\n", rtol, atol);
+#endif
+ printf("Linear solver: IDASPGMR 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");
+
+ printf("-----------------------------------------------------------\n");
+ printf(" t bottom-left top-right");
+ printf(" | nst k h\n");
+ printf("-----------------------------------------------------------\n\n");
+}
+
+/*
+ * PrintOutput: Print output values at output time t = tt.
+ * Selected run statistics are printed. Then values of c1 and c2
+ * are printed for the bottom left and top right grid points only.
+ * (NOTE: This routine is specific to the case NUM_SPECIES = 2.)
+ */
+
+static void PrintOutput(void *mem, N_Vector cc, realtype tt,
+ UserData webdata, MPI_Comm comm)
+{
+ MPI_Status status;
+ realtype *cdata, clast[2], hused;
+ long int nst;
+ int i, kused, flag, thispe, npelast, ilast;;
+
+ thispe = webdata->thispe;
+ npelast = webdata->npes - 1;
+ cdata = NV_DATA_P(cc);
+
+ /* Send conc. at top right mesh point from PE npes-1 to PE 0. */
+ if (thispe == npelast) {
+ ilast = NUM_SPECIES*MXSUB*MYSUB - 2;
+ if (npelast != 0)
+ MPI_Send(&cdata[ilast], 2, PVEC_REAL_MPI_TYPE, 0, 0, comm);
+ else { clast[0] = cdata[ilast]; clast[1] = cdata[ilast+1]; }
+ }
+
+ /* On PE 0, receive conc. at top right from PE npes - 1.
+ Then print performance data and sampled solution values. */
+
+ if (thispe == 0) {
+
+ if (npelast != 0)
+ MPI_Recv(&clast[0], 2, PVEC_REAL_MPI_TYPE, npelast, 0, comm, &status);
+
+ flag = IDAGetLastOrder(mem, &kused);
+ check_flag(&flag, "IDAGetLastOrder", 1, thispe);
+ flag = IDAGetNumSteps(mem, &nst);
+ check_flag(&flag, "IDAGetNumSteps", 1, thispe);
+ flag = IDAGetLastStep(mem, &hused);
+ check_flag(&flag, "IDAGetLastStep", 1, thispe);
+
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("%8.2Le %12.4Le %12.4Le | %3ld %1d %12.4Le\n",
+ tt, cdata[0], clast[0], nst, kused, hused);
+ for (i=1;i<NUM_SPECIES;i++)
+ printf(" %12.4Le %12.4Le |\n",cdata[i],clast[i]);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("%8.2le %12.4le %12.4le | %3ld %1d %12.4le\n",
+ tt, cdata[0], clast[0], nst, kused, hused);
+ for (i=1;i<NUM_SPECIES;i++)
+ printf(" %12.4le %12.4le |\n",cdata[i],clast[i]);
+#else
+ printf("%8.2e %12.4e %12.4e | %3ld %1d %12.4e\n",
+ tt, cdata[0], clast[0], nst, kused, hused);
+ for (i=1;i<NUM_SPECIES;i++)
+ printf(" %12.4e %12.4e |\n",cdata[i],clast[i]);
+#endif
+ printf("\n");
+
+ }
+}
+
+/*
+ * PrintFinalStats: Print final run data contained in iopt.
+ */
+
+static void PrintFinalStats(void *mem)
+{
+ long int nst, nre, nreLS, netf, ncfn, nni, ncfl, nli, npe, nps;
+ int flag;
+
+ flag = IDAGetNumSteps(mem, &nst);
+ check_flag(&flag, "IDAGetNumSteps", 1, 0);
+ flag = IDAGetNumResEvals(mem, &nre);
+ check_flag(&flag, "IDAGetNumResEvals", 1, 0);
+ flag = IDAGetNumErrTestFails(mem, &netf);
+ check_flag(&flag, "IDAGetNumErrTestFails", 1, 0);
+ flag = IDAGetNumNonlinSolvConvFails(mem, &ncfn);
+ check_flag(&flag, "IDAGetNumNonlinSolvConvFails", 1, 0);
+ flag = IDAGetNumNonlinSolvIters(mem, &nni);
+ check_flag(&flag, "IDAGetNumNonlinSolvIters", 1, 0);
+
+ flag = IDASpilsGetNumConvFails(mem, &ncfl);
+ check_flag(&flag, "IDASpilsGetNumConvFails", 1, 0);
+ flag = IDASpilsGetNumLinIters(mem, &nli);
+ check_flag(&flag, "IDASpilsGetNumLinIters", 1, 0);
+ flag = IDASpilsGetNumPrecEvals(mem, &npe);
+ check_flag(&flag, "IDASpilsGetNumPrecEvals", 1, 0);
+ flag = IDASpilsGetNumPrecSolves(mem, &nps);
+ check_flag(&flag, "IDASpilsGetNumPrecSolves", 1, 0);
+ flag = IDASpilsGetNumResEvals(mem, &nreLS);
+ check_flag(&flag, "IDASpilsGetNumResEvals", 1, 0);
+
+ printf("-----------------------------------------------------------\n");
+ printf("\nFinal statistics: \n\n");
+
+ printf("Number of steps = %ld\n", nst);
+ printf("Number of residual evaluations = %ld\n", nre+nreLS);
+ printf("Number of nonlinear iterations = %ld\n", nni);
+ printf("Number of error test failures = %ld\n", netf);
+ printf("Number of nonlinear conv. failures = %ld\n\n", ncfn);
+
+ printf("Number of linear iterations = %ld\n", nli);
+ printf("Number of linear conv. failures = %ld\n\n", ncfl);
+
+ printf("Number of preconditioner setups = %ld\n", npe);
+ printf("Number of preconditioner solves = %ld\n", nps);
+
+}
+
+/*
+ * 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, char *funcname, int opt, int id)
+{
+ int *errflag;
+
+ if (opt == 0 && flagvalue == NULL) {
+ /* Check if SUNDIALS function returned NULL pointer - no memory allocated */
+ fprintf(stderr,
+ "\nSUNDIALS_ERROR(%d): %s() failed - returned NULL pointer\n\n",
+ id, funcname);
+ return(1);
+ } else if (opt == 1) {
+ /* Check if flag < 0 */
+ errflag = (int *) flagvalue;
+ if (*errflag < 0) {
+ fprintf(stderr,
+ "\nSUNDIALS_ERROR(%d): %s() failed with flag = %d\n\n",
+ id, funcname, *errflag);
+ return(1);
+ }
+ } else if (opt == 2 && flagvalue == NULL) {
+ /* Check if function returned NULL pointer - no memory allocated */
+ fprintf(stderr,
+ "\nMEMORY_ERROR(%d): %s() failed - returned NULL pointer\n\n",
+ id, funcname);
+ return(1);
+ }
+
+ return(0);
+}
+
+/*
+ *--------------------------------------------------------------------
+ * FUNCTIONS CALLED BY IDA & SUPPORTING FUNCTIONS
+ *--------------------------------------------------------------------
+ */
+
+/*
+ * resweb: System residual function for predator-prey system.
+ * To compute the residual function F, this routine calls:
+ * rescomm, for needed communication, and then
+ * reslocal, for computation of the residuals on this processor.
+ */
+
+static int resweb(realtype tt, N_Vector cc, N_Vector cp,
+ N_Vector res, void *user_data)
+{
+ int flag;
+ UserData webdata;
+
+ webdata = (UserData)user_data;
+
+ /* Call rescomm to do inter-processor communication. */
+ flag = rescomm(cc, cp, webdata);
+
+ /* Call reslocal to calculate the local portion of residual vector. */
+ flag = reslocal(tt, cc, cp, res, webdata);
+
+ return(0);
+
+}
+
+/*
+ * rescomm: Communication routine in support of resweb.
+ * This routine performs all inter-processor communication of components
+ * of the cc vector needed to calculate F, namely the components at all
+ * interior subgrid boundaries (ghost cell data). It loads this data
+ * into a work array cext (the local portion of c, extended).
+ * The message-passing uses blocking sends, non-blocking receives,
+ * and receive-waiting, in routines BRecvPost, BSend, BRecvWait.
+ */
+
+static int rescomm(N_Vector cc, N_Vector cp, void *user_data)
+{
+
+ UserData webdata;
+ realtype *cdata, *cext, buffer[2*NUM_SPECIES*MYSUB];
+ int thispe, ixsub, jysub, nsmxsub, nsmysub;
+ MPI_Comm comm;
+ MPI_Request request[4];
+
+ webdata = (UserData) user_data;
+ cdata = NV_DATA_P(cc);
+
+ /* Get comm, thispe, subgrid indices, data sizes, extended array cext. */
+ comm = webdata->comm; thispe = webdata->thispe;
+ ixsub = webdata->ixsub; jysub = webdata->jysub;
+ cext = webdata->cext;
+ nsmxsub = webdata->nsmxsub; nsmysub = (webdata->ns)*(webdata->mysub);
+
+ /* Start receiving boundary data from neighboring PEs. */
+ BRecvPost(comm, request, thispe, ixsub, jysub, nsmxsub, nsmysub,
+ cext, buffer);
+
+ /* Send data from boundary of local grid to neighboring PEs. */
+ BSend(comm, thispe, ixsub, jysub, nsmxsub, nsmysub, cdata);
+
+ /* Finish receiving boundary data from neighboring PEs. */
+ BRecvWait(request, ixsub, jysub, nsmxsub, cext, buffer);
+
+ return(0);
+
+}
+
+/*
+ * BSend: Send boundary data to neighboring PEs.
+ * This routine sends components of cc from internal subgrid boundaries
+ * to the appropriate neighbor PEs.
+ */
+
+static void BSend(MPI_Comm comm, int my_pe, int ixsub, int jysub,
+ int dsizex, int dsizey, realtype cdata[])
+{
+ int i;
+ int ly, offsetc, offsetbuf;
+ realtype bufleft[NUM_SPECIES*MYSUB], bufright[NUM_SPECIES*MYSUB];
+
+ /* If jysub > 0, send data from bottom x-line of cc. */
+ if (jysub != 0)
+ MPI_Send(&cdata[0], dsizex, PVEC_REAL_MPI_TYPE, my_pe-NPEX, 0, comm);
+
+ /* If jysub < NPEY-1, send data from top x-line of cc. */
+ if (jysub != NPEY-1) {
+ offsetc = (MYSUB-1)*dsizex;
+ MPI_Send(&cdata[offsetc], dsizex, PVEC_REAL_MPI_TYPE, my_pe+NPEX, 0, comm);
+ }
+
+ /* If ixsub > 0, send data from left y-line of cc (via bufleft). */
+ if (ixsub != 0) {
+ for (ly = 0; ly < MYSUB; ly++) {
+ offsetbuf = ly*NUM_SPECIES;
+ offsetc = ly*dsizex;
+ for (i = 0; i < NUM_SPECIES; i++)
+ bufleft[offsetbuf+i] = cdata[offsetc+i];
+ }
+ MPI_Send(&bufleft[0], dsizey, PVEC_REAL_MPI_TYPE, my_pe-1, 0, comm);
+ }
+
+ /* If ixsub < NPEX-1, send data from right y-line of cc (via bufright). */
+ if (ixsub != NPEX-1) {
+ for (ly = 0; ly < MYSUB; ly++) {
+ offsetbuf = ly*NUM_SPECIES;
+ offsetc = offsetbuf*MXSUB + (MXSUB-1)*NUM_SPECIES;
+ for (i = 0; i < NUM_SPECIES; i++)
+ bufright[offsetbuf+i] = cdata[offsetc+i];
+ }
+ MPI_Send(&bufright[0], dsizey, PVEC_REAL_MPI_TYPE, my_pe+1, 0, comm);
+ }
+
+}
+
+/*
+ * BRecvPost: Start receiving boundary data from neighboring PEs.
+ * (1) buffer should be able to hold 2*NUM_SPECIES*MYSUB realtype entries,
+ * should be passed to both the BRecvPost and BRecvWait functions, and
+ * should not be manipulated between the two calls.
+ * (2) request should have 4 entries, and is also passed in both calls.
+ */
+
+static void BRecvPost(MPI_Comm comm, MPI_Request request[], int my_pe,
+ int ixsub, int jysub,
+ int dsizex, int dsizey,
+ realtype cext[], realtype buffer[])
+{
+ int offsetce;
+ /* Have bufleft and bufright use the same buffer. */
+ realtype *bufleft = buffer, *bufright = buffer+NUM_SPECIES*MYSUB;
+
+ /* If jysub > 0, receive data for bottom x-line of cext. */
+ if (jysub != 0)
+ MPI_Irecv(&cext[NUM_SPECIES], dsizex, PVEC_REAL_MPI_TYPE,
+ my_pe-NPEX, 0, comm, &request[0]);
+
+ /* If jysub < NPEY-1, receive data for top x-line of cext. */
+ if (jysub != NPEY-1) {
+ offsetce = NUM_SPECIES*(1 + (MYSUB+1)*(MXSUB+2));
+ MPI_Irecv(&cext[offsetce], dsizex, PVEC_REAL_MPI_TYPE,
+ my_pe+NPEX, 0, comm, &request[1]);
+ }
+
+ /* If ixsub > 0, receive data for left y-line of cext (via bufleft). */
+ if (ixsub != 0) {
+ MPI_Irecv(&bufleft[0], dsizey, PVEC_REAL_MPI_TYPE,
+ my_pe-1, 0, comm, &request[2]);
+ }
+
+ /* If ixsub < NPEX-1, receive data for right y-line of cext (via bufright). */
+ if (ixsub != NPEX-1) {
+ MPI_Irecv(&bufright[0], dsizey, PVEC_REAL_MPI_TYPE,
+ my_pe+1, 0, comm, &request[3]);
+ }
+
+}
+
+/*
+ * BRecvWait: Finish receiving boundary data from neighboring PEs.
+ * (1) buffer should be able to hold 2*NUM_SPECIES*MYSUB realtype entries,
+ * should be passed to both the BRecvPost and BRecvWait functions, and
+ * should not be manipulated between the two calls.
+ * (2) request should have 4 entries, and is also passed in both calls.
+ */
+
+static void BRecvWait(MPI_Request request[], int ixsub, int jysub,
+ int dsizex, realtype cext[], realtype buffer[])
+{
+ int i;
+ int ly, dsizex2, offsetce, offsetbuf;
+ realtype *bufleft = buffer, *bufright = buffer+NUM_SPECIES*MYSUB;
+ MPI_Status status;
+
+ dsizex2 = dsizex + 2*NUM_SPECIES;
+
+ /* If jysub > 0, receive data for bottom x-line of cext. */
+ if (jysub != 0)
+ MPI_Wait(&request[0],&status);
+
+ /* If jysub < NPEY-1, receive data for top x-line of cext. */
+ if (jysub != NPEY-1)
+ MPI_Wait(&request[1],&status);
+
+ /* If ixsub > 0, receive data for left y-line of cext (via bufleft). */
+ if (ixsub != 0) {
+ MPI_Wait(&request[2],&status);
+
+ /* Copy the buffer to cext */
+ for (ly = 0; ly < MYSUB; ly++) {
+ offsetbuf = ly*NUM_SPECIES;
+ offsetce = (ly+1)*dsizex2;
+ for (i = 0; i < NUM_SPECIES; i++)
+ cext[offsetce+i] = bufleft[offsetbuf+i];
+ }
+ }
+
+ /* If ixsub < NPEX-1, receive data for right y-line of cext (via bufright). */
+ if (ixsub != NPEX-1) {
+ MPI_Wait(&request[3],&status);
+
+ /* Copy the buffer to cext */
+ for (ly = 0; ly < MYSUB; ly++) {
+ offsetbuf = ly*NUM_SPECIES;
+ offsetce = (ly+2)*dsizex2 - NUM_SPECIES;
+ for (i = 0; i < NUM_SPECIES; i++)
+ cext[offsetce+i] = bufright[offsetbuf+i];
+ }
+ }
+}
+
+/* Define lines are for ease of readability in the following functions. */
+
+#define mxsub (webdata->mxsub)
+#define mysub (webdata->mysub)
+#define npex (webdata->npex)
+#define npey (webdata->npey)
+#define ixsub (webdata->ixsub)
+#define jysub (webdata->jysub)
+#define nsmxsub (webdata->nsmxsub)
+#define nsmxsub2 (webdata->nsmxsub2)
+#define np (webdata->np)
+#define dx (webdata->dx)
+#define dy (webdata->dy)
+#define cox (webdata->cox)
+#define coy (webdata->coy)
+#define rhs (webdata->rhs)
+#define cext (webdata->cext)
+#define rates (webdata->rates)
+#define ns (webdata->ns)
+#define acoef (webdata->acoef)
+#define bcoef (webdata->bcoef)
+
+/*
+ * reslocal: Compute res = F(t,cc,cp).
+ * This routine assumes that all inter-processor communication of data
+ * needed to calculate F has already been done. Components at interior
+ * subgrid boundaries are assumed to be in the work array cext.
+ * The local portion of the cc vector is first copied into cext.
+ * The exterior Neumann boundary conditions are explicitly handled here
+ * by copying data from the first interior mesh line to the ghost cell
+ * locations in cext. Then the reaction and diffusion terms are
+ * evaluated in terms of the cext array, and the residuals are formed.
+ * The reaction terms are saved separately in the vector webdata->rates
+ * for use by the preconditioner setup routine.
+ */
+
+static int reslocal(realtype tt, N_Vector cc, N_Vector cp, N_Vector res,
+ void *user_data)
+{
+ realtype *cdata, *ratesxy, *cpxy, *resxy,
+ xx, yy, dcyli, dcyui, dcxli, dcxui;
+ int ix, jy, is, i, locc, ylocce, locce;
+ UserData webdata;
+
+ webdata = (UserData) user_data;
+
+ /* Get data pointers, subgrid data, array sizes, work array cext. */
+ cdata = NV_DATA_P(cc);
+
+ /* Copy local segment of cc vector into the working extended array cext. */
+ locc = 0;
+ locce = nsmxsub2 + NUM_SPECIES;
+ for (jy = 0; jy < mysub; jy++) {
+ for (i = 0; i < nsmxsub; i++) cext[locce+i] = cdata[locc+i];
+ locc = locc + nsmxsub;
+ locce = locce + nsmxsub2;
+ }
+
+ /* To facilitate homogeneous Neumann boundary conditions, when this is
+ a boundary PE, copy data from the first interior mesh line of cc to cext. */
+
+ /* If jysub = 0, copy x-line 2 of cc to cext. */
+ if (jysub == 0)
+ { for (i = 0; i < nsmxsub; i++) cext[NUM_SPECIES+i] = cdata[nsmxsub+i]; }
+
+ /* If jysub = npey-1, copy x-line mysub-1 of cc to cext. */
+ if (jysub == npey-1) {
+ locc = (mysub-2)*nsmxsub;
+ locce = (mysub+1)*nsmxsub2 + NUM_SPECIES;
+ for (i = 0; i < nsmxsub; i++) cext[locce+i] = cdata[locc+i];
+ }
+
+ /* If ixsub = 0, copy y-line 2 of cc to cext. */
+ if (ixsub == 0) {
+ for (jy = 0; jy < mysub; jy++) {
+ locc = jy*nsmxsub + NUM_SPECIES;
+ locce = (jy+1)*nsmxsub2;
+ for (i = 0; i < NUM_SPECIES; i++) cext[locce+i] = cdata[locc+i];
+ }
+ }
+
+ /* If ixsub = npex-1, copy y-line mxsub-1 of cc to cext. */
+ if (ixsub == npex-1) {
+ for (jy = 0; jy < mysub; jy++) {
+ locc = (jy+1)*nsmxsub - 2*NUM_SPECIES;
+ locce = (jy+2)*nsmxsub2 - NUM_SPECIES;
+ for (i = 0; i < NUM_SPECIES; i++) cext[locce+i] = cdata[locc+i];
+ }
+ }
+
+ /* Loop over all grid points, setting local array rates to right-hand sides.
+ Then set res values appropriately for prey/predator components of F. */
+ for (jy = 0; jy < mysub; jy++) {
+ ylocce = (jy+1)*nsmxsub2;
+ yy = (jy+jysub*mysub)*dy;
+
+ for (ix = 0; ix < mxsub; ix++) {
+ locce = ylocce + (ix+1)*NUM_SPECIES;
+ xx = (ix + ixsub*mxsub)*dx;
+
+ ratesxy = IJ_Vptr(rates,ix,jy);
+ WebRates(xx, yy, &(cext[locce]), ratesxy, webdata);
+
+ resxy = IJ_Vptr(res,ix,jy);
+ cpxy = IJ_Vptr(cp,ix,jy);
+
+ for (is = 0; is < NUM_SPECIES; is++) {
+ dcyli = cext[locce+is] - cext[locce+is-nsmxsub2];
+ dcyui = cext[locce+is+nsmxsub2] - cext[locce+is];
+
+ dcxli = cext[locce+is] - cext[locce+is-NUM_SPECIES];
+ dcxui = cext[locce+is+NUM_SPECIES] - cext[locce+is];
+
+ rhs[is] = cox[is]*(dcxui-dcxli) + coy[is]*(dcyui-dcyli) + ratesxy[is];
+
+ if (is < np) resxy[is] = cpxy[is] - rhs[is];
+ else resxy[is] = - rhs[is];
+
+ } /* End of is (species) loop. */
+ } /* End of ix loop. */
+ } /* End of jy loop. */
+
+ return(0);
+
+}
+
+/*
+ * WebRates: Evaluate reaction rates at a given spatial point.
+ * At a given (x,y), evaluate the array of ns reaction terms R.
+ */
+
+static void WebRates(realtype xx, realtype yy, realtype *cxy, realtype *ratesxy,
+ UserData webdata)
+{
+ int is;
+ realtype fac;
+
+ for (is = 0; is < NUM_SPECIES; is++)
+ ratesxy[is] = dotprod(NUM_SPECIES, cxy, acoef[is]);
+
+ fac = ONE + ALPHA*xx*yy + BETA*sin(FOURPI*xx)*sin(FOURPI*yy);
+
+ for (is = 0; is < NUM_SPECIES; is++)
+ ratesxy[is] = cxy[is]*( bcoef[is]*fac + ratesxy[is] );
+
+}
+
+/*
+ * dotprod: dot product routine for realtype arrays, for use by WebRates.
+ */
+
+static realtype dotprod(int size, realtype *x1, realtype *x2)
+{
+ int i;
+ realtype *xx1, *xx2, temp = ZERO;
+
+ xx1 = x1; xx2 = x2;
+ for (i = 0; i < size; i++) temp += (*xx1++) * (*xx2++);
+ return(temp);
+
+}
+
+/*
+ * Preconbd: Preconditioner setup routine.
+ * This routine generates and preprocesses the block-diagonal
+ * preconditoner PP. At each spatial point, a block of PP is computed
+ * by way of difference quotients on the reaction rates R.
+ * The base value of R are taken from webdata->rates, as set by webres.
+ * 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)
+{
+ int flag, thispe;
+ realtype uround;
+ realtype xx, yy, *cxy, *ewtxy, cctemp, **Pxy, *ratesxy, *Pxycol, *cpxy;
+ realtype inc, sqru, fac, perturb_rates[NUM_SPECIES];
+ int is, js, ix, jy, ret;
+ UserData webdata;
+ void *mem;
+ N_Vector ewt;
+ realtype hh;
+
+ webdata = (UserData)user_data;
+ uround = UNIT_ROUNDOFF;
+ sqru = SQRT(uround);
+ thispe = webdata->thispe;
+
+ mem = webdata->ida_mem;
+ ewt = webdata->ewt;
+ flag = IDAGetErrWeights(mem, ewt);
+ check_flag(&flag, "IDAGetErrWeights", 1, thispe);
+ flag = IDAGetCurrentStep(mem, &hh);
+ check_flag(&flag, "IDAGetCurrentStep", 1, thispe);
+
+ for (jy = 0; jy < mysub; jy++) {
+ yy = (jy + jysub*mysub)*dy;
+
+ for (ix = 0; ix < mxsub; ix++) {
+ xx = (ix+ ixsub*mxsub)*dx;
+ Pxy = (webdata->PP)[ix][jy];
+ cxy = IJ_Vptr(cc,ix,jy);
+ cpxy = IJ_Vptr(cp,ix,jy);
+ ewtxy= IJ_Vptr(ewt,ix,jy);
+ ratesxy = IJ_Vptr(rates,ix,jy);
+
+ for (js = 0; js < ns; js++) {
+ inc = sqru*(MAX(ABS(cxy[js]), MAX(hh*ABS(cpxy[js]), ONE/ewtxy[js])));
+ cctemp = cxy[js]; /* Save the (js,ix,jy) element of cc. */
+ cxy[js] += inc; /* Perturb the (js,ix,jy) element of cc. */
+ fac = -ONE/inc;
+
+ WebRates(xx, yy, cxy, perturb_rates, webdata);
+
+ Pxycol = Pxy[js];
+
+ for (is = 0; is < ns; is++)
+ Pxycol[is] = (perturb_rates[is] - ratesxy[is])*fac;
+
+ if (js < np) Pxycol[js] += cj; /* Add partial with respect to cp. */
+
+ cxy[js] = cctemp; /* Restore (js,ix,jy) element of cc. */
+
+ } /* End of js loop. */
+
+ /* Do LU decomposition of matrix block for grid point (ix,jy). */
+ ret = denseGETRF(Pxy, ns, ns, (webdata->pivot)[ix][jy]);
+
+ if (ret != 0) return(1);
+
+ } /* End of ix loop. */
+ } /* End of jy loop. */
+
+ return(0);
+
+}
+
+/*
+ * PSolvebd: Preconditioner solve routine.
+ * This routine applies the LU factorization of the blocks of the
+ * 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)
+{
+ realtype **Pxy, *zxy;
+ long int *pivot, ix, jy;
+ UserData webdata;
+
+ webdata = (UserData)user_data;
+
+ N_VScale(ONE, rvec, zvec);
+
+ /* Loop through subgrid and apply preconditioner factors at each point. */
+ for (ix = 0; ix < mxsub; ix++) {
+ for (jy = 0; jy < mysub; jy++) {
+
+ /* For grid point (ix,jy), do backsolve on local vector.
+ zxy is the address of the local portion of zvec, and
+ Pxy is the address of the corresponding block of PP. */
+ zxy = IJ_Vptr(zvec,ix,jy);
+ Pxy = (webdata->PP)[ix][jy];
+ pivot = (webdata->pivot)[ix][jy];
+ denseGETRS(Pxy, ns, pivot, zxy);
+
+ } /* End of jy loop. */
+ } /* End of ix loop. */
+
+ return(0);
+
+}
diff --git a/examples/ida/parallel/idaFoodWeb_kry_p.out b/examples/ida/parallel/idaFoodWeb_kry_p.out
new file mode 100644
index 0000000..ee07f6f
--- /dev/null
+++ b/examples/ida/parallel/idaFoodWeb_kry_p.out
@@ -0,0 +1,50 @@
+
+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
+Preconditioner: block diagonal, block size ns, via difference quotients
+CalcIC called to correct initial predator concentrations
+
+-----------------------------------------------------------
+ t bottom-left top-right | nst k h
+-----------------------------------------------------------
+
+0.00e+00 1.0000e+01 1.0000e+01 | 0 0 1.6310e-08
+ 1.0000e+05 1.0000e+05 |
+
+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 | 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
+ 2.4019e+06 2.7072e+06 |
+
+4.00e-01 2.4019e+02 2.7072e+02 | 165 1 3.2316e-01
+ 2.4019e+06 2.7072e+06 |
+
+7.00e-01 2.4019e+02 2.7072e+02 | 166 1 6.4633e-01
+ 2.4019e+06 2.7072e+06 |
+
+1.00e+00 2.4019e+02 2.7072e+02 | 166 1 6.4633e-01
+ 2.4019e+06 2.7072e+06 |
+
+-----------------------------------------------------------
+
+Final statistics:
+
+Number of steps = 166
+Number of residual evaluations = 1257
+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 conv. failures = 0
+
+Number of preconditioner setups = 25
+Number of preconditioner solves = 1257
diff --git a/examples/ida/parallel/idaHeat2D_kry_bbd_p.c b/examples/ida/parallel/idaHeat2D_kry_bbd_p.c
new file mode 100644
index 0000000..b65b333
--- /dev/null
+++ b/examples/ida/parallel/idaHeat2D_kry_bbd_p.c
@@ -0,0 +1,840 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.3 $
+ * $Date: 2010/12/01 23:03:29 $
+ * -----------------------------------------------------------------
+ * Programmer(s): 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
+ * preconditioning.
+ *
+ * The DAE system solved is a spatial discretization of the PDE
+ * du/dt = d^2u/dx^2 + d^2u/dy^2
+ * on the unit square. The boundary condition is u = 0 on all edges.
+ * Initial conditions are given by u = 16 x (1 - x) y (1 - y). The
+ * PDE is treated with central differences on a uniform MX x MY
+ * grid. The values of u at the interior points satisfy ODEs, and
+ * equations u = 0 at the boundaries are appended, to form a DAE
+ * system of size N = MX * MY. Here MX = MY = 10.
+ *
+ * The system is actually implemented on submeshes, processor by
+ * processor, with an MXSUB by MYSUB mesh on each of NPEX * NPEY
+ * processors.
+ *
+ * The system is solved with IDA using the Krylov linear solver
+ * IDASPGMR 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
+ * suppressed. 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_bbdpre.h>
+#include <nvector/nvector_parallel.h>
+#include <sundials/sundials_types.h>
+#include <sundials/sundials_math.h>
+
+#include <mpi.h>
+
+#define ZERO RCONST(0.0)
+#define ONE RCONST(1.0)
+#define TWO RCONST(2.0)
+
+#define NOUT 11 /* Number of output times */
+
+#define NPEX 2 /* No. PEs in x direction of PE array */
+#define NPEY 2 /* No. PEs in y direction of PE array */
+ /* Total no. PEs = NPEX*NPEY */
+#define MXSUB 5 /* No. x points per subgrid */
+#define MYSUB 5 /* No. y points per subgrid */
+
+#define MX (NPEX*MXSUB) /* MX = number of x mesh points */
+#define MY (NPEY*MYSUB) /* MY = number of y mesh points */
+ /* Spatial mesh is MX by MY */
+
+typedef struct {
+ int thispe, mx, my, ixsub, jysub, npex, npey, mxsub, mysub;
+ long int n_local;
+ realtype dx, dy, coeffx, coeffy, coeffxy;
+ realtype uext[(MXSUB+2)*(MYSUB+2)];
+ MPI_Comm comm;
+} *UserData;
+
+/* 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,
+ N_Vector uu, N_Vector up, N_Vector res,
+ void *user_data);
+
+static int BSend(MPI_Comm comm, int thispe, int ixsub,
+ int jysub, int dsizex, int dsizey,
+ realtype uarray[]);
+
+static int BRecvPost(MPI_Comm comm, MPI_Request request[], int thispe,
+ int ixsub, int jysub,
+ int dsizex, int dsizey,
+ realtype uext[], realtype buffer[]);
+
+static int BRecvWait(MPI_Request request[], int ixsub, int jysub,
+ int dsizex, realtype uext[], realtype buffer[]);
+
+/* Prototypes of private functions */
+
+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 PrintCase(int case_number, int mudq, int mukeep);
+
+static void PrintOutput(int id, void *mem, realtype t, N_Vector uu);
+
+static void PrintFinalStats(void *mem);
+
+static int check_flag(void *flagvalue, char *funcname, int opt, int id);
+
+/*
+ *--------------------------------------------------------------------
+ * MAIN PROGRAM
+ *--------------------------------------------------------------------
+ */
+
+int main(int argc, char *argv[])
+{
+ MPI_Comm comm;
+ void *mem;
+ UserData data;
+ int thispe, iout, ier, npes;
+ long int Neq, local_N, mudq, mldq, mukeep, mlkeep;
+ realtype rtol, atol, t0, t1, tout, tret;
+ N_Vector uu, up, constraints, id, res;
+
+ mem = NULL;
+ data = NULL;
+ uu = up = constraints = id = res = NULL;
+
+ /* Get processor number and total number of pe's. */
+
+ MPI_Init(&argc, &argv);
+ comm = MPI_COMM_WORLD;
+ MPI_Comm_size(comm, &npes);
+ MPI_Comm_rank(comm, &thispe);
+
+ if (npes != NPEX*NPEY) {
+ if (thispe == 0)
+ fprintf(stderr,
+ "\nMPI_ERROR(0): npes = %d is not equal to NPEX*NPEY = %d\n",
+ npes,NPEX*NPEY);
+ MPI_Finalize();
+ return(1);
+ }
+
+ /* Set local length local_N and global length Neq. */
+
+ local_N = MXSUB*MYSUB;
+ Neq = MX * MY;
+
+ /* Allocate N-vectors. */
+
+ uu = N_VNew_Parallel(comm, local_N, Neq);
+ if(check_flag((void *)uu, "N_VNew_Parallel", 0, thispe)) MPI_Abort(comm, 1);
+
+ up = N_VNew_Parallel(comm, local_N, Neq);
+ if(check_flag((void *)up, "N_VNew_Parallel", 0, thispe)) MPI_Abort(comm, 1);
+
+ res = N_VNew_Parallel(comm, local_N, Neq);
+ if(check_flag((void *)res, "N_VNew_Parallel", 0, thispe)) MPI_Abort(comm, 1);
+
+ constraints = N_VNew_Parallel(comm, local_N, Neq);
+ if(check_flag((void *)constraints, "N_VNew_Parallel", 0, thispe)) MPI_Abort(comm, 1);
+
+ id = N_VNew_Parallel(comm, local_N, Neq);
+ if(check_flag((void *)id, "N_VNew_Parallel", 0, thispe)) MPI_Abort(comm, 1);
+
+ /* Allocate and initialize the data structure. */
+
+ data = (UserData) malloc(sizeof *data);
+ if(check_flag((void *)data, "malloc", 2, thispe)) MPI_Abort(comm, 1);
+
+ InitUserData(thispe, comm, data);
+
+ /* Initialize the uu, up, id, and constraints profiles. */
+
+ SetInitialProfile(uu, up, id, res, data);
+ N_VConst(ONE, constraints);
+
+ t0 = ZERO; t1 = RCONST(0.01);
+
+ /* Scalar relative and absolute tolerance. */
+
+ rtol = ZERO;
+ atol = RCONST(1.0e-3);
+
+ /* Call IDACreate and IDAMalloc to initialize solution */
+
+ mem = IDACreate();
+ if(check_flag((void *)mem, "IDACreate", 0, thispe)) MPI_Abort(comm, 1);
+
+ ier = IDASetUserData(mem, data);
+ if(check_flag(&ier, "IDASetUserData", 1, thispe)) MPI_Abort(comm, 1);
+
+ ier = IDASetSuppressAlg(mem, TRUE);
+ if(check_flag(&ier, "IDASetSuppressAlg", 1, thispe)) MPI_Abort(comm, 1);
+
+ ier = IDASetId(mem, id);
+ if(check_flag(&ier, "IDASetId", 1, thispe)) MPI_Abort(comm, 1);
+
+ ier = IDASetConstraints(mem, constraints);
+ if(check_flag(&ier, "IDASetConstraints", 1, thispe)) MPI_Abort(comm, 1);
+ N_VDestroy_Parallel(constraints);
+
+ ier = IDAInit(mem, heatres, t0, uu, up);
+ if(check_flag(&ier, "IDAInit", 1, thispe)) MPI_Abort(comm, 1);
+
+ ier = IDASStolerances(mem, rtol, atol);
+ if(check_flag(&ier, "IDASStolerances", 1, thispe)) MPI_Abort(comm, 1);
+
+ mudq = MXSUB;
+ mldq = MXSUB;
+ mukeep = 1;
+ mlkeep = 1;
+
+ /* Print problem description */
+
+ if (thispe == 0 ) PrintHeader(Neq, rtol, atol);
+
+ /*
+ * -----------------------------
+ * Case 1 -- mldq = mudq = MXSUB
+ * -----------------------------
+ */
+
+ /* Call IDASpgmr to specify the linear solver. */
+ ier = IDASpgmr(mem, 0);
+ if(check_flag(&ier, "IDASpgmr", 1, thispe)) MPI_Abort(comm, 1);
+
+ /* Call IDABBDPrecInit to initialize BBD preconditioner. */
+ ier = IDABBDPrecInit(mem, local_N, mudq, mldq, mukeep, mlkeep,
+ ZERO, reslocal, NULL);
+ if(check_flag(&ier, "IDABBDPrecAlloc", 1, thispe)) MPI_Abort(comm, 1);
+
+ /* Print output heading (on processor 0 only) and initial solution. */
+ if (thispe == 0) PrintCase(1, mudq, mukeep);
+
+ /* 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);
+ if(check_flag(&ier, "IDASolve", 1, thispe)) MPI_Abort(comm, 1);
+
+ PrintOutput(thispe, mem, tret, uu);
+
+ }
+
+ /* Print final statistics */
+ if (thispe == 0) PrintFinalStats(mem);
+
+ /*
+ * -----------------------------
+ * Case 2 -- mldq = mudq = 1
+ * -----------------------------
+ */
+
+ mudq = 1;
+ mldq = 1;
+
+ /* Re-initialize the uu and up profiles. */
+ SetInitialProfile(uu, up, id, res, data);
+
+ /* Call IDAReInit to re-initialize IDA. */
+ ier = IDAReInit(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);
+ if(check_flag(&ier, "IDABBDPrecReInit", 1, thispe)) MPI_Abort(comm, 1);
+
+ /* Print output heading (on processor 0 only). */
+ if (thispe == 0) PrintCase(2, mudq, mukeep);
+
+ /* 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);
+ if(check_flag(&ier, "IDASolve", 1, thispe)) MPI_Abort(comm, 1);
+
+ PrintOutput(thispe, mem, tret, uu);
+
+ }
+
+ /* Print final statistics */
+ if (thispe == 0) PrintFinalStats(mem);
+
+ /* Free Memory */
+ IDAFree(&mem);
+ free(data);
+ N_VDestroy_Parallel(id);
+ N_VDestroy_Parallel(res);
+ N_VDestroy_Parallel(up);
+ N_VDestroy_Parallel(uu);
+
+ MPI_Finalize();
+
+ return(0);
+
+}
+/*
+ *--------------------------------------------------------------------
+ * FUNCTIONS CALLED BY IDA
+ *--------------------------------------------------------------------
+ */
+
+/*
+ * heatres: heat equation system residual function
+ * This uses 5-point central differencing on the interior points, and
+ * includes algebraic equations for the boundary values.
+ * So for each interior point, the residual component has the form
+ * res_i = u'_i - (central difference)_i
+ * while for each boundary point, it is res_i = u_i.
+ *
+ * This parallel implementation uses several supporting routines.
+ * First a call is made to rescomm to do communication of subgrid boundary
+ * data into array uext. Then reslocal is called to compute the residual
+ * on individual processors and their corresponding domains. The routines
+ * BSend, BRecvPost, and BREcvWait handle interprocessor communication
+ * of uu required to calculate the residual.
+ */
+
+static int heatres(realtype tres, N_Vector uu, N_Vector up,
+ N_Vector res, void *user_data)
+{
+ int retval;
+ UserData data;
+ long int Nlocal;
+
+ data = (UserData) user_data;
+
+ Nlocal = data->n_local;
+
+ /* Call rescomm to do inter-processor communication. */
+ retval = rescomm(Nlocal, tres, uu, up, data);
+
+ /* Call reslocal to calculate res. */
+ retval = reslocal(Nlocal, tres, uu, up, res, data);
+
+ return(0);
+
+}
+
+/*
+ * rescomm routine. This routine performs all inter-processor
+ * communication of data in u needed to calculate G.
+ */
+
+static int rescomm(long int Nlocal, realtype tt,
+ N_Vector uu, N_Vector up, void *user_data)
+{
+ UserData data;
+ realtype *uarray, *uext, buffer[2*MYSUB];
+ MPI_Comm comm;
+ int thispe, ixsub, jysub, mxsub, mysub;
+ MPI_Request request[4];
+
+ data = (UserData) user_data;
+ uarray = NV_DATA_P(uu);
+
+ /* Get comm, thispe, subgrid indices, data sizes, extended array uext. */
+ comm = data->comm; thispe = data->thispe;
+ ixsub = data->ixsub; jysub = data->jysub;
+ mxsub = data->mxsub; mysub = data->mysub;
+ uext = data->uext;
+
+ /* Start receiving boundary data from neighboring PEs. */
+ BRecvPost(comm, request, thispe, ixsub, jysub, mxsub, mysub, uext, buffer);
+
+ /* Send data from boundary of local grid to neighboring PEs. */
+ BSend(comm, thispe, ixsub, jysub, mxsub, mysub, uarray);
+
+ /* Finish receiving boundary data from neighboring PEs. */
+ BRecvWait(request, ixsub, jysub, mxsub, uext, buffer);
+
+ return(0);
+
+}
+
+/*
+ * reslocal routine. Compute res = F(t, uu, up). This routine assumes
+ * that all inter-processor communication of data needed to calculate F
+ * has already been done, and that this data is in the work array uext.
+ */
+
+static int reslocal(long int Nlocal, realtype tres,
+ N_Vector uu, N_Vector up, N_Vector res,
+ void *user_data)
+{
+ realtype *uext, *uuv, *upv, *resv;
+ realtype termx, termy, termctr;
+ int lx, ly, offsetu, offsetue, locu, locue;
+ int ixsub, jysub, mxsub, mxsub2, mysub, npex, npey;
+ int ixbegin, ixend, jybegin, jyend;
+ UserData data;
+
+ /* Get subgrid indices, array sizes, extended work array uext. */
+
+ data = (UserData) user_data;
+ uext = data->uext;
+ uuv = NV_DATA_P(uu);
+ upv = NV_DATA_P(up);
+ resv = NV_DATA_P(res);
+ ixsub = data->ixsub; jysub = data->jysub;
+ mxsub = data->mxsub; mxsub2 = data->mxsub + 2;
+ mysub = data->mysub; npex = data->npex; npey = data->npey;
+
+ /* Initialize all elements of res to uu. This sets the boundary
+ elements simply without indexing hassles. */
+
+ N_VScale(ONE, uu, res);
+
+ /* Copy local segment of u vector into the working extended array uext.
+ This completes uext prior to the computation of the res vector. */
+
+ offsetu = 0;
+ offsetue = mxsub2 + 1;
+ for (ly = 0; ly < mysub; ly++) {
+ for (lx = 0; lx < mxsub; lx++) uext[offsetue+lx] = uuv[offsetu+lx];
+ offsetu = offsetu + mxsub;
+ offsetue = offsetue + mxsub2;
+ }
+
+ /* Set loop limits for the interior of the local subgrid. */
+
+ ixbegin = 0;
+ ixend = mxsub-1;
+ jybegin = 0;
+ jyend = mysub-1;
+ if (ixsub == 0) ixbegin++; if (ixsub == npex-1) ixend--;
+ if (jysub == 0) jybegin++; if (jysub == npey-1) jyend--;
+
+ /* Loop over all grid points in local subgrid. */
+
+ for (ly = jybegin; ly <=jyend; ly++) {
+ for (lx = ixbegin; lx <= ixend; lx++) {
+ locu = lx + ly*mxsub;
+ locue = (lx+1) + (ly+1)*mxsub2;
+ termx = data->coeffx *(uext[locue-1] + uext[locue+1]);
+ termy = data->coeffy *(uext[locue-mxsub2] + uext[locue+mxsub2]);
+ termctr = data->coeffxy*uext[locue];
+ resv[locu] = upv[locu] - (termx + termy - termctr);
+ }
+ }
+ return(0);
+
+}
+
+/*
+ * Routine to send boundary data to neighboring PEs.
+ */
+
+static int BSend(MPI_Comm comm, int thispe, int ixsub,
+ int jysub, int dsizex, int dsizey,
+ realtype uarray[])
+{
+ int ly, offsetu;
+ realtype bufleft[MYSUB], bufright[MYSUB];
+
+ /* If jysub > 0, send data from bottom x-line of u. */
+
+ if (jysub != 0)
+ MPI_Send(&uarray[0], dsizex, PVEC_REAL_MPI_TYPE, thispe-NPEX, 0, comm);
+
+ /* If jysub < NPEY-1, send data from top x-line of u. */
+
+ if (jysub != NPEY-1) {
+ offsetu = (MYSUB-1)*dsizex;
+ MPI_Send(&uarray[offsetu], dsizex, PVEC_REAL_MPI_TYPE,
+ thispe+NPEX, 0, comm);
+ }
+
+ /* If ixsub > 0, send data from left y-line of u (via bufleft). */
+
+ if (ixsub != 0) {
+ for (ly = 0; ly < MYSUB; ly++) {
+ offsetu = ly*dsizex;
+ bufleft[ly] = uarray[offsetu];
+ }
+ MPI_Send(&bufleft[0], dsizey, PVEC_REAL_MPI_TYPE, thispe-1, 0, comm);
+ }
+
+ /* If ixsub < NPEX-1, send data from right y-line of u (via bufright). */
+
+ if (ixsub != NPEX-1) {
+ for (ly = 0; ly < MYSUB; ly++) {
+ offsetu = ly*MXSUB + (MXSUB-1);
+ bufright[ly] = uarray[offsetu];
+ }
+ MPI_Send(&bufright[0], dsizey, PVEC_REAL_MPI_TYPE, thispe+1, 0, comm);
+ }
+
+ return(0);
+
+}
+
+/*
+ * Routine to start receiving boundary data from neighboring PEs.
+ * Notes:
+ * 1) buffer should be able to hold 2*MYSUB realtype entries, should be
+ * passed to both the BRecvPost and BRecvWait functions, and should not
+ * be manipulated between the two calls.
+ * 2) request should have 4 entries, and should be passed in
+ * both calls also.
+ */
+
+static int BRecvPost(MPI_Comm comm, MPI_Request request[], int thispe,
+ int ixsub, int jysub,
+ int dsizex, int dsizey,
+ realtype uext[], realtype buffer[])
+{
+ int offsetue;
+ /* Have bufleft and bufright use the same buffer. */
+ realtype *bufleft = buffer, *bufright = buffer+MYSUB;
+
+ /* If jysub > 0, receive data for bottom x-line of uext. */
+ if (jysub != 0)
+ MPI_Irecv(&uext[1], dsizex, PVEC_REAL_MPI_TYPE,
+ thispe-NPEX, 0, comm, &request[0]);
+
+ /* If jysub < NPEY-1, receive data for top x-line of uext. */
+ if (jysub != NPEY-1) {
+ offsetue = (1 + (MYSUB+1)*(MXSUB+2));
+ MPI_Irecv(&uext[offsetue], dsizex, PVEC_REAL_MPI_TYPE,
+ thispe+NPEX, 0, comm, &request[1]);
+ }
+
+ /* If ixsub > 0, receive data for left y-line of uext (via bufleft). */
+ if (ixsub != 0) {
+ MPI_Irecv(&bufleft[0], dsizey, PVEC_REAL_MPI_TYPE,
+ thispe-1, 0, comm, &request[2]);
+ }
+
+ /* If ixsub < NPEX-1, receive data for right y-line of uext (via bufright). */
+ if (ixsub != NPEX-1) {
+ MPI_Irecv(&bufright[0], dsizey, PVEC_REAL_MPI_TYPE,
+ thispe+1, 0, comm, &request[3]);
+ }
+
+ return(0);
+
+}
+
+/*
+ * Routine to finish receiving boundary data from neighboring PEs.
+ * Notes:
+ * 1) buffer should be able to hold 2*MYSUB realtype entries, should be
+ * passed to both the BRecvPost and BRecvWait functions, and should not
+ * be manipulated between the two calls.
+ * 2) request should have four entries, and should be passed in both
+ * calls also.
+ */
+
+static int BRecvWait(MPI_Request request[], int ixsub,
+ int jysub, int dsizex, realtype uext[],
+ realtype buffer[])
+{
+ int ly, dsizex2, offsetue;
+ realtype *bufleft = buffer, *bufright = buffer+MYSUB;
+ MPI_Status status;
+
+ dsizex2 = dsizex + 2;
+
+ /* If jysub > 0, receive data for bottom x-line of uext. */
+ if (jysub != 0)
+ MPI_Wait(&request[0],&status);
+
+ /* If jysub < NPEY-1, receive data for top x-line of uext. */
+ if (jysub != NPEY-1)
+ MPI_Wait(&request[1],&status);
+
+ /* If ixsub > 0, receive data for left y-line of uext (via bufleft). */
+ if (ixsub != 0) {
+ MPI_Wait(&request[2],&status);
+
+ /* Copy the buffer to uext. */
+ for (ly = 0; ly < MYSUB; ly++) {
+ offsetue = (ly+1)*dsizex2;
+ uext[offsetue] = bufleft[ly];
+ }
+ }
+
+ /* If ixsub < NPEX-1, receive data for right y-line of uext (via bufright). */
+ if (ixsub != NPEX-1) {
+ MPI_Wait(&request[3],&status);
+
+ /* Copy the buffer to uext */
+ for (ly = 0; ly < MYSUB; ly++) {
+ offsetue = (ly+2)*dsizex2 - 1;
+ uext[offsetue] = bufright[ly];
+ }
+ }
+
+ return(0);
+}
+
+/*
+ *--------------------------------------------------------------------
+ * PRIVATE FUNCTIONS
+ *--------------------------------------------------------------------
+ */
+
+/*
+ * InitUserData initializes the user's data block data.
+ */
+
+static int InitUserData(int thispe, MPI_Comm comm, UserData data)
+{
+ data->thispe = thispe;
+ data->dx = ONE/(MX-ONE); /* Assumes a [0,1] interval in x. */
+ data->dy = ONE/(MY-ONE); /* Assumes a [0,1] interval in y. */
+ data->coeffx = ONE/(data->dx * data->dx);
+ data->coeffy = ONE/(data->dy * data->dy);
+ data->coeffxy = TWO/(data->dx * data->dx) + TWO/(data->dy * data->dy) ;
+ data->jysub = thispe/NPEX;
+ data->ixsub = thispe - data->jysub * NPEX;
+ data->npex = NPEX;
+ data->npey = NPEY;
+ data->mx = MX;
+ data->my = MY;
+ data->mxsub = MXSUB;
+ data->mysub = MYSUB;
+ data->comm = comm;
+ data->n_local = MXSUB*MYSUB;
+ return(0);
+
+}
+
+/*
+ * SetInitialProfile sets the initial values for the problem.
+ */
+
+static int SetInitialProfile(N_Vector uu, N_Vector up, N_Vector id,
+ N_Vector res, UserData data)
+{
+ int i, iloc, j, jloc, offset, loc, ixsub, jysub;
+ int ixbegin, ixend, jybegin, jyend;
+ realtype xfact, yfact, *udata, *iddata, dx, dy;
+
+ /* Initialize uu. */
+
+ udata = NV_DATA_P(uu);
+ iddata = NV_DATA_P(id);
+
+ /* Set mesh spacings and subgrid indices for this PE. */
+ dx = data->dx;
+ dy = data->dy;
+ ixsub = data->ixsub;
+ jysub = data->jysub;
+
+ /* Set beginning and ending locations in the global array corresponding
+ to the portion of that array assigned to this processor. */
+ ixbegin = MXSUB*ixsub;
+ ixend = MXSUB*(ixsub+1) - 1;
+ jybegin = MYSUB*jysub;
+ jyend = MYSUB*(jysub+1) - 1;
+
+ /* Loop over the local array, computing the initial profile value.
+ The global indices are (i,j) and the local indices are (iloc,jloc).
+ Also set the id vector to zero for boundary points, one otherwise. */
+
+ N_VConst(ONE,id);
+ for (j = jybegin, jloc = 0; j <= jyend; j++, jloc++) {
+ yfact = data->dy*j;
+ offset= jloc*MXSUB;
+ for (i = ixbegin, iloc = 0; i <= ixend; i++, iloc++) {
+ xfact = data->dx * i;
+ loc = offset + iloc;
+ udata[loc] = RCONST(16.0) * xfact * (ONE - xfact) * yfact * (ONE - yfact);
+ if (i == 0 || i == MX-1 || j == 0 || j == MY-1) iddata[loc] = ZERO;
+ }
+ }
+
+ /* Initialize up. */
+
+ N_VConst(ZERO, up); /* Initially set up = 0. */
+
+ /* heatres sets res to negative of ODE RHS values at interior points. */
+ heatres(ZERO, uu, up, res, data);
+
+ /* Copy -res into up to get correct initial up values. */
+ N_VScale(-ONE, res, up);
+
+ return(0);
+
+}
+
+/*
+ * Print first lines of output (problem description)
+ * and table heading
+ */
+
+static void PrintHeader(long int 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: %d\n\n", Neq);
+
+ printf("Subgrid dimensions: %d x %d", MXSUB, MYSUB);
+ printf(" Processor array: %d x %d\n", NPEX, NPEY);
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("Tolerance parameters: rtol = %Lg atol = %Lg\n", rtol, atol);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("Tolerance parameters: rtol = %lg atol = %lg\n", rtol, atol);
+#else
+ 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(" all boundary components. \n");
+ printf("Linear solver: IDASPGMR. ");
+ printf("Preconditioner: IDABBDPRE - Banded-block-diagonal.\n");
+
+}
+
+/*
+ * Print case and table header
+ */
+
+static void PrintCase(int case_number, int mudq, int mukeep)
+{
+ printf("\n\nCase %1d. \n", case_number);
+ printf(" Difference quotient half-bandwidths = %d",mudq);
+ printf(" Retained matrix half-bandwidths = %d \n",mukeep);
+
+ /* Print output table heading and initial line of table. */
+ printf("\n Output Summary (umax = max-norm of solution) \n\n");
+ printf(" time umax k nst nni nli nre nreLS nge h npe nps\n");
+ printf(" . . . . . . . . . . . . . . . . . . . . . . . .\n");
+}
+
+/*
+ * Print integrator statistics and max-norm of solution
+ */
+
+static void PrintOutput(int id, void *mem, realtype t, N_Vector uu)
+{
+ realtype umax, hused;
+ int kused, ier;
+ long int nst, nni, nre, nli, npe, nps, nreLS, nge;
+
+ umax = N_VMaxNorm(uu);
+
+ if (id == 0) {
+
+ ier = IDAGetLastOrder(mem, &kused);
+ check_flag(&ier, "IDAGetLastOrder", 1, id);
+ ier = IDAGetNumSteps(mem, &nst);
+ check_flag(&ier, "IDAGetNumSteps", 1, id);
+ ier = IDAGetNumNonlinSolvIters(mem, &nni);
+ check_flag(&ier, "IDAGetNumNonlinSolvIters", 1, id);
+ ier = IDAGetNumResEvals(mem, &nre);
+ check_flag(&ier, "IDAGetNumResEvals", 1, id);
+ ier = IDAGetLastStep(mem, &hused);
+ check_flag(&ier, "IDAGetLastStep", 1, id);
+ ier = IDASpilsGetNumLinIters(mem, &nli);
+ check_flag(&ier, "IDASpilsGetNumLinIters", 1, id);
+ ier = IDASpilsGetNumResEvals(mem, &nreLS);
+ check_flag(&ier, "IDASpilsGetNumResEvals", 1, id);
+ ier = IDABBDPrecGetNumGfnEvals(mem, &nge);
+ check_flag(&ier, "IDABBDPrecGetNumGfnEvals", 1, id);
+ ier = IDASpilsGetNumPrecEvals(mem, &npe);
+ check_flag(&ier, "IDASpilsGetPrecEvals", 1, id);
+ ier = IDASpilsGetNumPrecSolves(mem, &nps);
+ check_flag(&ier, "IDASpilsGetNumPrecSolves", 1, id);
+
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf(" %5.2Lf %13.5Le %d %3ld %3ld %3ld %4ld %4ld %4ld %9.2Le %3ld %3ld\n",
+ t, umax, kused, nst, nni, nli, nre, nreLS, nge, hused, npe, nps);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf(" %5.2f %13.5le %d %3ld %3ld %3ld %4ld %4ld %4ld %9.2le %3ld %3ld\n",
+ t, umax, kused, nst, nni, nli, nre, nreLS, nge, hused, npe, nps);
+#else
+ printf(" %5.2f %13.5e %d %3ld %3ld %3ld %4ld %4ld %4ld %9.2e %3ld %3ld\n",
+ t, umax, kused, nst, nni, nli, nre, nreLS, nge, hused, npe, nps);
+#endif
+
+ }
+}
+
+/*
+ * Print some final integrator statistics
+ */
+
+static void PrintFinalStats(void *mem)
+{
+ long int netf, ncfn, ncfl;
+
+ IDAGetNumErrTestFails(mem, &netf);
+ IDAGetNumNonlinSolvConvFails(mem, &ncfn);
+ IDASpilsGetNumConvFails(mem, &ncfl);
+
+ printf("\nError test failures = %ld\n", netf);
+ printf("Nonlinear convergence failures = %ld\n", ncfn);
+ printf("Linear convergence failures = %ld\n", ncfl);
+}
+
+/*
+ * 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, char *funcname, int opt, int id)
+{
+ int *errflag;
+
+ /* Check if SUNDIALS function returned NULL pointer - no memory allocated */
+ if (opt == 0 && flagvalue == NULL) {
+ fprintf(stderr, "\nSUNDIALS_ERROR(%d): %s() failed - returned NULL pointer\n\n", id, funcname);
+ return(1); }
+
+ /* Check if flag < 0 */
+ else if (opt == 1) {
+ errflag = (int *) flagvalue;
+ if (*errflag < 0) {
+ fprintf(stderr, "\nSUNDIALS_ERROR(%d): %s() failed with flag = %d\n\n", id, funcname, *errflag);
+ return(1); }}
+
+ /* Check if function returned NULL pointer - no memory allocated */
+ else if (opt == 2 && flagvalue == NULL) {
+ fprintf(stderr, "\nMEMORY_ERROR(%d): %s() failed - returned NULL pointer\n\n", id, funcname);
+ return(1); }
+
+ return(0);
+}
diff --git a/examples/ida/parallel/idaHeat2D_kry_bbd_p.out b/examples/ida/parallel/idaHeat2D_kry_bbd_p.out
new file mode 100644
index 0000000..388faeb
--- /dev/null
+++ b/examples/ida/parallel/idaHeat2D_kry_bbd_p.out
@@ -0,0 +1,58 @@
+idaHeat2D_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.
+
+
+Case 1.
+ Difference quotient half-bandwidths = 5 Retained matrix half-bandwidths = 1
+
+ Output Summary (umax = max-norm of solution)
+
+ 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
+
+Error test failures = 1
+Nonlinear convergence failures = 0
+Linear convergence failures = 0
+
+
+Case 2.
+ Difference quotient half-bandwidths = 1 Retained matrix half-bandwidths = 1
+
+ Output Summary (umax = max-norm of solution)
+
+ 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
+ 0.04 4.70932e-01 3 19 23 20 23 20 36 1.02e-02 9 43
+ 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
+
+Error test failures = 0
+Nonlinear convergence failures = 0
+Linear convergence failures = 0
diff --git a/examples/ida/parallel/idaHeat2D_kry_p.c b/examples/ida/parallel/idaHeat2D_kry_p.c
new file mode 100644
index 0000000..ee99671
--- /dev/null
+++ b/examples/ida/parallel/idaHeat2D_kry_p.c
@@ -0,0 +1,892 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.3 $
+ * $Date: 2009/09/30 23:28:00 $
+ * -----------------------------------------------------------------
+ * Programmer(s): 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.
+ *
+ * The DAE system solved is a spatial discretization of the PDE
+ * du/dt = d^2u/dx^2 + d^2u/dy^2
+ * on the unit square. The boundary condition is u = 0 on all edges.
+ * Initial conditions are given by u = 16 x (1 - x) y (1 - y).
+ * The PDE is treated with central differences on a uniform MX x MY
+ * grid. The values of u at the interior points satisfy ODEs, and
+ * equations u = 0 at the boundaries are appended, to form a DAE
+ * system of size N = MX * MY. Here MX = MY = 10.
+ *
+ * The system is actually implemented on submeshes, processor by
+ * processor, with an MXSUB by MYSUB mesh on each of NPEX * NPEY
+ * processors.
+ *
+ * The system is solved with IDA using the Krylov linear solver
+ * IDASPGMR. 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
+ * for all components. Local error testing on the boundary values
+ * is suppressed. 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 <nvector/nvector_parallel.h>
+#include <sundials/sundials_types.h>
+#include <sundials/sundials_math.h>
+
+#include <mpi.h>
+
+#define ZERO RCONST(0.0)
+#define ONE RCONST(1.0)
+#define TWO RCONST(2.0)
+
+#define NOUT 11 /* Number of output times */
+
+#define NPEX 2 /* No. PEs in x direction of PE array */
+#define NPEY 2 /* No. PEs in y direction of PE array */
+ /* Total no. PEs = NPEX*NPEY */
+#define MXSUB 5 /* No. x points per subgrid */
+#define MYSUB 5 /* No. y points per subgrid */
+
+#define MX (NPEX*MXSUB) /* MX = number of x mesh points */
+#define MY (NPEY*MYSUB) /* MY = number of y mesh points */
+ /* Spatial mesh is MX by MY */
+
+typedef struct {
+ long int thispe, mx, my, ixsub, jysub, npex, npey, mxsub, mysub;
+ realtype dx, dy, coeffx, coeffy, coeffxy;
+ realtype uext[(MXSUB+2)*(MYSUB+2)];
+ N_Vector pp; /* vector of diagonal preconditioner elements */
+ MPI_Comm comm;
+} *UserData;
+
+/* User-supplied residual function and supporting routines */
+
+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 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 BRecvWait(MPI_Request request[], long int ixsub, long int jysub,
+ long int 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 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);
+
+/* Private function to check function return values */
+
+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 PrintOutput(int id, void *mem, realtype t, N_Vector uu);
+
+static void PrintFinalStats(void *mem);
+
+static int check_flag(void *flagvalue, char *funcname, int opt, int id);
+
+/*
+ *--------------------------------------------------------------------
+ * MAIN PROGRAM
+ *--------------------------------------------------------------------
+ */
+
+int main(int argc, char *argv[])
+{
+ MPI_Comm comm;
+ void *mem;
+ UserData data;
+ int iout, thispe, ier, npes;
+ long int Neq, local_N;
+ realtype rtol, atol, t0, t1, tout, tret;
+ N_Vector uu, up, constraints, id, res;
+
+ mem = NULL;
+ data = NULL;
+ uu = up = constraints = id = res = NULL;
+
+ /* Get processor number and total number of pe's. */
+
+ MPI_Init(&argc, &argv);
+ comm = MPI_COMM_WORLD;
+ MPI_Comm_size(comm, &npes);
+ MPI_Comm_rank(comm, &thispe);
+
+ if (npes != NPEX*NPEY) {
+ if (thispe == 0)
+ fprintf(stderr,
+ "\nMPI_ERROR(0): npes = %d is not equal to NPEX*NPEY = %d\n",
+ npes,NPEX*NPEY);
+ MPI_Finalize();
+ return(1);
+ }
+
+ /* Set local length local_N and global length Neq. */
+
+ local_N = MXSUB*MYSUB;
+ Neq = MX * MY;
+
+ /* Allocate and initialize the data structure and N-vectors. */
+
+ data = (UserData) malloc(sizeof *data);
+ if(check_flag((void *)data, "malloc", 2, thispe))
+ MPI_Abort(comm, 1);
+ data->pp = NULL;
+
+ uu = N_VNew_Parallel(comm, local_N, Neq);
+ if(check_flag((void *)uu, "N_VNew_Parallel", 0, thispe))
+ MPI_Abort(comm, 1);
+
+ up = N_VNew_Parallel(comm, local_N, Neq);
+ if(check_flag((void *)up, "N_VNew_Parallel", 0, thispe))
+ MPI_Abort(comm, 1);
+
+ res = N_VNew_Parallel(comm, local_N, Neq);
+ if(check_flag((void *)res, "N_VNew_Parallel", 0, thispe))
+ MPI_Abort(comm, 1);
+
+ constraints = N_VNew_Parallel(comm, local_N, Neq);
+ if(check_flag((void *)constraints, "N_VNew_Parallel", 0, thispe))
+ MPI_Abort(comm, 1);
+
+ id = N_VNew_Parallel(comm, local_N, Neq);
+ if(check_flag((void *)id, "N_VNew_Parallel", 0, thispe))
+ MPI_Abort(comm, 1);
+
+ /* An N-vector to hold preconditioner. */
+ data->pp = N_VNew_Parallel(comm, local_N, Neq);
+ if(check_flag((void *)data->pp, "N_VNew_Parallel", 0, thispe))
+ MPI_Abort(comm, 1);
+
+ InitUserData(thispe, comm, data);
+
+ /* Initialize the uu, up, id, and res profiles. */
+
+ SetInitialProfile(uu, up, id, res, data);
+
+ /* Set constraints to all 1's for nonnegative solution values. */
+
+ N_VConst(ONE, constraints);
+
+ t0 = ZERO; t1 = RCONST(0.01);
+
+ /* Scalar relative and absolute tolerance. */
+
+ rtol = ZERO;
+ atol = RCONST(1.0e-3);
+
+ /* Call IDACreate and IDAMalloc to initialize solution. */
+
+ mem = IDACreate();
+ if(check_flag((void *)mem, "IDACreate", 0, thispe)) MPI_Abort(comm, 1);
+
+ ier = IDASetUserData(mem, data);
+ if(check_flag(&ier, "IDASetUserData", 1, thispe)) MPI_Abort(comm, 1);
+
+ ier = IDASetSuppressAlg(mem, TRUE);
+ if(check_flag(&ier, "IDASetSuppressAlg", 1, thispe)) MPI_Abort(comm, 1);
+
+ ier = IDASetId(mem, id);
+ if(check_flag(&ier, "IDASetId", 1, thispe)) MPI_Abort(comm, 1);
+
+ ier = IDASetConstraints(mem, constraints);
+ if(check_flag(&ier, "IDASetConstraints", 1, thispe)) MPI_Abort(comm, 1);
+ N_VDestroy_Parallel(constraints);
+
+ ier = IDAInit(mem, resHeat, t0, uu, up);
+ if(check_flag(&ier, "IDAInit", 1, thispe)) MPI_Abort(comm, 1);
+
+ ier = IDASStolerances(mem, rtol, atol);
+ if(check_flag(&ier, "IDASStolerances", 1, thispe)) MPI_Abort(comm, 1);
+
+ /* Call IDASpgmr to specify the linear solver. */
+
+ ier = IDASpgmr(mem, 0);
+ if(check_flag(&ier, "IDASpgmr", 1, thispe)) MPI_Abort(comm, 1);
+
+ ier = IDASpilsSetPreconditioner(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);
+
+ /* 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);
+ if(check_flag(&ier, "IDASolve", 1, thispe)) MPI_Abort(comm, 1);
+
+ PrintOutput(thispe, mem, tret, uu);
+
+ }
+
+ /* Print remaining counters. */
+
+ if (thispe == 0) PrintFinalStats(mem);
+
+ /* Free memory */
+
+ IDAFree(&mem);
+
+ N_VDestroy_Parallel(id);
+ N_VDestroy_Parallel(res);
+ N_VDestroy_Parallel(up);
+ N_VDestroy_Parallel(uu);
+
+ N_VDestroy_Parallel(data->pp);
+ free(data);
+
+ MPI_Finalize();
+
+ return(0);
+
+}
+
+/*
+ *--------------------------------------------------------------------
+ * FUNCTIONS CALLED BY IDA
+ *--------------------------------------------------------------------
+ */
+
+/*
+ * resHeat: heat equation system residual function
+ * This uses 5-point central differencing on the interior points, and
+ * includes algebraic equations for the boundary values.
+ * So for each interior point, the residual component has the form
+ * res_i = u'_i - (central difference)_i
+ * while for each boundary point, it is res_i = u_i.
+ *
+ * This parallel implementation uses several supporting routines.
+ * First a call is made to rescomm to do communication of subgrid boundary
+ * data into array uext. Then reslocal is called to compute the residual
+ * on individual processors and their corresponding domains. The routines
+ * BSend, BRecvPost, and BREcvWait handle interprocessor communication
+ * of uu required to calculate the residual.
+ */
+
+int resHeat(realtype tt,
+ N_Vector uu, N_Vector up, N_Vector rr,
+ void *user_data)
+{
+ int retval;
+
+ /* Call rescomm to do inter-processor communication. */
+ retval = rescomm(uu, up, user_data);
+
+ /* Call reslocal to calculate res. */
+ retval = reslocal(tt, uu, up, rr, user_data);
+
+ return(0);
+
+}
+
+/*
+ * PsetupHeat: setup for diagonal preconditioner for heatsk.
+ *
+ * The optional user-supplied functions PsetupHeat and
+ * PsolveHeat together must define the left preconditoner
+ * matrix P approximating the system Jacobian matrix
+ * J = dF/du + cj*dF/du'
+ * (where the DAE system is F(t,u,u') = 0), and solve the linear
+ * systems P z = r. This is done in this case by keeping only
+ * the diagonal elements of the J matrix above, storing them as
+ * inverses in a vector pp, when computed in PsetupHeat, for
+ * subsequent use in PsolveHeat.
+ *
+ * In this instance, only cj and data (user data structure, with
+ * pp etc.) are used from the PsetupHeat argument list.
+ *
+ */
+
+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)
+{
+ realtype *ppv, pelinv;
+ long int lx, ly, ixbegin, ixend, jybegin, jyend, locu, mxsub, mysub;
+ long int ixsub, jysub, npex, npey;
+ UserData data;
+
+ data = (UserData) user_data;
+
+ ppv = NV_DATA_P(data->pp);
+ ixsub = data->ixsub;
+ jysub = data->jysub;
+ mxsub = data->mxsub;
+ mysub = data->mysub;
+ npex = data->npex;
+ npey = data->npey;
+
+ /* Initially set all pp elements to one. */
+ N_VConst(ONE, data->pp);
+
+ /* Prepare to loop over subgrid. */
+ ixbegin = 0;
+ ixend = mxsub-1;
+ jybegin = 0;
+ jyend = mysub-1;
+ if (ixsub == 0) ixbegin++; if (ixsub == npex-1) ixend--;
+ if (jysub == 0) jybegin++; if (jysub == npey-1) jyend--;
+ pelinv = ONE/(c_j + data->coeffxy);
+
+ /* Load the inverse of the preconditioner diagonal elements
+ in loop over all the local subgrid. */
+
+ for (ly = jybegin; ly <=jyend; ly++) {
+ for (lx = ixbegin; lx <= ixend; lx++) {
+ locu = lx + ly*mxsub;
+ ppv[locu] = pelinv;
+ }
+ }
+
+ return(0);
+
+}
+
+/*
+ * PsolveHeat: solve preconditioner linear system.
+ * This routine multiplies the input vector rvec by the vector pp
+ * containing the inverse diagonal Jacobian elements (previously
+ * 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)
+{
+ UserData data;
+
+ data = (UserData) user_data;
+
+ N_VProd(data->pp, rvec, zvec);
+
+ return(0);
+
+}
+
+/*
+ *--------------------------------------------------------------------
+ * SUPPORTING FUNCTIONS
+ *--------------------------------------------------------------------
+ */
+
+
+/*
+ * rescomm routine. This routine performs all inter-processor
+ * communication of data in u needed to calculate G.
+ */
+
+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;
+ MPI_Request request[4];
+
+ data = (UserData) user_data;
+ uarray = NV_DATA_P(uu);
+
+ /* Get comm, thispe, subgrid indices, data sizes, extended array uext. */
+ comm = data->comm; thispe = data->thispe;
+ ixsub = data->ixsub; jysub = data->jysub;
+ mxsub = data->mxsub; mysub = data->mysub;
+ uext = data->uext;
+
+ /* Start receiving boundary data from neighboring PEs. */
+ BRecvPost(comm, request, thispe, ixsub, jysub, mxsub, mysub, uext, buffer);
+
+ /* Send data from boundary of local grid to neighboring PEs. */
+ BSend(comm, thispe, ixsub, jysub, mxsub, mysub, uarray);
+
+ /* Finish receiving boundary data from neighboring PEs. */
+ BRecvWait(request, ixsub, jysub, mxsub, uext, buffer);
+
+ return(0);
+
+}
+
+/*
+ * reslocal routine. Compute res = F(t, uu, up). This routine assumes
+ * that all inter-processor communication of data needed to calculate F
+ * 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,
+ 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;
+ UserData data;
+
+ /* Get subgrid indices, array sizes, extended work array uext. */
+
+ data = (UserData) user_data;
+ uext = data->uext;
+ uuv = NV_DATA_P(uu);
+ upv = NV_DATA_P(up);
+ resv = NV_DATA_P(rr);
+ ixsub = data->ixsub; jysub = data->jysub;
+ mxsub = data->mxsub; mxsub2 = data->mxsub + 2;
+ mysub = data->mysub; npex = data->npex; npey = data->npey;
+
+ /* Initialize all elements of rr to uu. This sets the boundary
+ elements simply without indexing hassles. */
+
+ N_VScale(ONE, uu, rr);
+
+ /* Copy local segment of u vector into the working extended array uext.
+ This completes uext prior to the computation of the rr vector. */
+
+ offsetu = 0;
+ offsetue = mxsub2 + 1;
+ for (ly = 0; ly < mysub; ly++) {
+ for (lx = 0; lx < mxsub; lx++) uext[offsetue+lx] = uuv[offsetu+lx];
+ offsetu = offsetu + mxsub;
+ offsetue = offsetue + mxsub2;
+ }
+
+ /* Set loop limits for the interior of the local subgrid. */
+
+ ixbegin = 0;
+ ixend = mxsub-1;
+ jybegin = 0;
+ jyend = mysub-1;
+ if (ixsub == 0) ixbegin++; if (ixsub == npex-1) ixend--;
+ if (jysub == 0) jybegin++; if (jysub == npey-1) jyend--;
+
+ /* Loop over all grid points in local subgrid. */
+
+ for (ly = jybegin; ly <=jyend; ly++) {
+ for (lx = ixbegin; lx <= ixend; lx++) {
+ locu = lx + ly*mxsub;
+ locue = (lx+1) + (ly+1)*mxsub2;
+ termx = data->coeffx *(uext[locue-1] + uext[locue+1]);
+ termy = data->coeffy *(uext[locue-mxsub2] + uext[locue+mxsub2]);
+ termctr = data->coeffxy*uext[locue];
+ resv[locu] = upv[locu] - (termx + termy - termctr);
+ }
+ }
+ return(0);
+
+}
+
+/*
+ * 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[])
+{
+ long int ly, offsetu;
+ realtype bufleft[MYSUB], bufright[MYSUB];
+
+ /* If jysub > 0, send data from bottom x-line of u. */
+
+ if (jysub != 0)
+ MPI_Send(&uarray[0], dsizex, PVEC_REAL_MPI_TYPE, thispe-NPEX, 0, comm);
+
+ /* If jysub < NPEY-1, send data from top x-line of u. */
+
+ if (jysub != NPEY-1) {
+ offsetu = (MYSUB-1)*dsizex;
+ MPI_Send(&uarray[offsetu], dsizex, PVEC_REAL_MPI_TYPE,
+ thispe+NPEX, 0, comm);
+ }
+
+ /* If ixsub > 0, send data from left y-line of u (via bufleft). */
+
+ if (ixsub != 0) {
+ for (ly = 0; ly < MYSUB; ly++) {
+ offsetu = ly*dsizex;
+ bufleft[ly] = uarray[offsetu];
+ }
+ MPI_Send(&bufleft[0], dsizey, PVEC_REAL_MPI_TYPE, thispe-1, 0, comm);
+ }
+
+ /* If ixsub < NPEX-1, send data from right y-line of u (via bufright). */
+
+ if (ixsub != NPEX-1) {
+ for (ly = 0; ly < MYSUB; ly++) {
+ offsetu = ly*MXSUB + (MXSUB-1);
+ bufright[ly] = uarray[offsetu];
+ }
+ MPI_Send(&bufright[0], dsizey, PVEC_REAL_MPI_TYPE, thispe+1, 0, comm);
+ }
+
+ return(0);
+
+}
+
+/*
+ * Routine to start receiving boundary data from neighboring PEs.
+ * Notes:
+ * 1) buffer should be able to hold 2*MYSUB realtype entries, should be
+ * passed to both the BRecvPost and BRecvWait functions, and should not
+ * be manipulated between the two calls.
+ * 2) request should have 4 entries, and should be passed in
+ * 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[])
+{
+ long int offsetue;
+ /* Have bufleft and bufright use the same buffer. */
+ realtype *bufleft = buffer, *bufright = buffer+MYSUB;
+
+ /* If jysub > 0, receive data for bottom x-line of uext. */
+ if (jysub != 0)
+ MPI_Irecv(&uext[1], dsizex, PVEC_REAL_MPI_TYPE,
+ thispe-NPEX, 0, comm, &request[0]);
+
+ /* If jysub < NPEY-1, receive data for top x-line of uext. */
+ if (jysub != NPEY-1) {
+ offsetue = (1 + (MYSUB+1)*(MXSUB+2));
+ MPI_Irecv(&uext[offsetue], dsizex, PVEC_REAL_MPI_TYPE,
+ thispe+NPEX, 0, comm, &request[1]);
+ }
+
+ /* If ixsub > 0, receive data for left y-line of uext (via bufleft). */
+ if (ixsub != 0) {
+ MPI_Irecv(&bufleft[0], dsizey, PVEC_REAL_MPI_TYPE,
+ thispe-1, 0, comm, &request[2]);
+ }
+
+ /* If ixsub < NPEX-1, receive data for right y-line of uext (via bufright). */
+ if (ixsub != NPEX-1) {
+ MPI_Irecv(&bufright[0], dsizey, PVEC_REAL_MPI_TYPE,
+ thispe+1, 0, comm, &request[3]);
+ }
+
+ return(0);
+
+}
+
+/*
+ * Routine to finish receiving boundary data from neighboring PEs.
+ * Notes:
+ * 1) buffer should be able to hold 2*MYSUB realtype entries, should be
+ * passed to both the BRecvPost and BRecvWait functions, and should not
+ * be manipulated between the two calls.
+ * 2) request should have four entries, and should be passed in both
+ * calls also.
+ */
+
+static int BRecvWait(MPI_Request request[], long int ixsub, long int jysub,
+ long int dsizex, realtype uext[], realtype buffer[])
+{
+ long int ly, dsizex2, offsetue;
+ realtype *bufleft = buffer, *bufright = buffer+MYSUB;
+ MPI_Status status;
+
+ dsizex2 = dsizex + 2;
+
+ /* If jysub > 0, receive data for bottom x-line of uext. */
+ if (jysub != 0)
+ MPI_Wait(&request[0],&status);
+
+ /* If jysub < NPEY-1, receive data for top x-line of uext. */
+ if (jysub != NPEY-1)
+ MPI_Wait(&request[1],&status);
+
+ /* If ixsub > 0, receive data for left y-line of uext (via bufleft). */
+ if (ixsub != 0) {
+ MPI_Wait(&request[2],&status);
+
+ /* Copy the buffer to uext. */
+ for (ly = 0; ly < MYSUB; ly++) {
+ offsetue = (ly+1)*dsizex2;
+ uext[offsetue] = bufleft[ly];
+ }
+ }
+
+ /* If ixsub < NPEX-1, receive data for right y-line of uext (via bufright). */
+ if (ixsub != NPEX-1) {
+ MPI_Wait(&request[3],&status);
+
+ /* Copy the buffer to uext */
+ for (ly = 0; ly < MYSUB; ly++) {
+ offsetue = (ly+2)*dsizex2 - 1;
+ uext[offsetue] = bufright[ly];
+ }
+ }
+
+ return(0);
+
+}
+
+/*
+ *--------------------------------------------------------------------
+ * PRIVATE FUNCTIONS
+ *--------------------------------------------------------------------
+ */
+
+/*
+ * InitUserData initializes the user's data block data.
+ */
+
+static int InitUserData(int thispe, MPI_Comm comm, UserData data)
+{
+ data->thispe = thispe;
+ data->dx = ONE/(MX-ONE); /* Assumes a [0,1] interval in x. */
+ data->dy = ONE/(MY-ONE); /* Assumes a [0,1] interval in y. */
+ data->coeffx = ONE/(data->dx * data->dx);
+ data->coeffy = ONE/(data->dy * data->dy);
+ data->coeffxy = TWO/(data->dx * data->dx) + TWO/(data->dy * data->dy) ;
+ data->jysub = thispe/NPEX;
+ data->ixsub = thispe - data->jysub * NPEX;
+ data->npex = NPEX;
+ data->npey = NPEY;
+ data->mx = MX;
+ data->my = MY;
+ data->mxsub = MXSUB;
+ data->mysub = MYSUB;
+ data->comm = comm;
+ return(0);
+
+}
+
+/*
+ * SetInitialProfile sets the initial values for the problem.
+ */
+
+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;
+ realtype xfact, yfact, *udata, *iddata, dx, dy;
+
+ /* Initialize uu. */
+
+ udata = NV_DATA_P(uu);
+ iddata = NV_DATA_P(id);
+
+ /* Set mesh spacings and subgrid indices for this PE. */
+ dx = data->dx;
+ dy = data->dy;
+ ixsub = data->ixsub;
+ jysub = data->jysub;
+
+ /* Set beginning and ending locations in the global array corresponding
+ to the portion of that array assigned to this processor. */
+ ixbegin = MXSUB*ixsub;
+ ixend = MXSUB*(ixsub+1) - 1;
+ jybegin = MYSUB*jysub;
+ jyend = MYSUB*(jysub+1) - 1;
+
+ /* Loop over the local array, computing the initial profile value.
+ The global indices are (i,j) and the local indices are (iloc,jloc).
+ Also set the id vector to zero for boundary points, one otherwise. */
+
+ N_VConst(ONE,id);
+ for (j = jybegin, jloc = 0; j <= jyend; j++, jloc++) {
+ yfact = data->dy*j;
+ offset= jloc*MXSUB;
+ for (i = ixbegin, iloc = 0; i <= ixend; i++, iloc++) {
+ xfact = data->dx * i;
+ loc = offset + iloc;
+ udata[loc] = RCONST(16.0) * xfact * (ONE - xfact) * yfact * (ONE - yfact);
+ if (i == 0 || i == MX-1 || j == 0 || j == MY-1) iddata[loc] = ZERO;
+ }
+ }
+
+ /* Initialize up. */
+
+ N_VConst(ZERO, up); /* Initially set up = 0. */
+
+ /* resHeat sets res to negative of ODE RHS values at interior points. */
+ resHeat(ZERO, uu, up, res, data);
+
+ /* Copy -res into up to get correct initial up values. */
+ N_VScale(-ONE, res, up);
+
+ return(0);
+}
+
+/*
+ * Print first lines of output and table heading
+ */
+
+static void PrintHeader(long int 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("Subgrid dimensions: %d x %d", MXSUB, MYSUB);
+ printf(" Processor array: %d x %d\n", NPEX, NPEY);
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("Tolerance parameters: rtol = %Lg atol = %Lg\n", rtol, atol);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("Tolerance parameters: rtol = %lg atol = %lg\n", rtol, atol);
+#else
+ 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("all boundary components. \n");
+ printf("Linear solver: IDASPGMR ");
+ printf("Preconditioner: diagonal elements only.\n");
+
+ /* Print output table heading and initial line of table. */
+ printf("\n Output Summary (umax = max-norm of solution) \n\n");
+ printf(" time umax k nst nni nli nre nreLS h npe nps\n");
+ printf("----------------------------------------------------------------------\n");
+}
+
+/*
+ * PrintOutput: print max norm of solution and current solver statistics
+ */
+
+static void PrintOutput(int id, void *mem, realtype t, N_Vector uu)
+{
+ realtype hused, umax;
+ long int nst, nni, nje, nre, nreLS, nli, npe, nps;
+ int kused, ier;
+
+ umax = N_VMaxNorm(uu);
+
+ if (id == 0) {
+
+ ier = IDAGetLastOrder(mem, &kused);
+ check_flag(&ier, "IDAGetLastOrder", 1, id);
+ ier = IDAGetNumSteps(mem, &nst);
+ check_flag(&ier, "IDAGetNumSteps", 1, id);
+ ier = IDAGetNumNonlinSolvIters(mem, &nni);
+ check_flag(&ier, "IDAGetNumNonlinSolvIters", 1, id);
+ ier = IDAGetNumResEvals(mem, &nre);
+ check_flag(&ier, "IDAGetNumResEvals", 1, id);
+ ier = IDAGetLastStep(mem, &hused);
+ check_flag(&ier, "IDAGetLastStep", 1, id);
+ ier = IDASpilsGetNumJtimesEvals(mem, &nje);
+ check_flag(&ier, "IDASpilsGetNumJtimesEvals", 1, id);
+ ier = IDASpilsGetNumLinIters(mem, &nli);
+ check_flag(&ier, "IDASpilsGetNumLinIters", 1, id);
+ ier = IDASpilsGetNumResEvals(mem, &nreLS);
+ check_flag(&ier, "IDASpilsGetNumResEvals", 1, id);
+ ier = IDASpilsGetNumPrecEvals(mem, &npe);
+ check_flag(&ier, "IDASpilsGetPrecEvals", 1, id);
+ ier = IDASpilsGetNumPrecSolves(mem, &nps);
+ check_flag(&ier, "IDASpilsGetNumPrecSolves", 1, id);
+
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf(" %5.2Lf %13.5Le %d %3ld %3ld %3ld %4ld %4ld %9.2Le %3ld %3ld\n",
+ t, umax, kused, nst, nni, nje, nre, nreLS, hused, npe, nps);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf(" %5.2f %13.5le %d %3ld %3ld %3ld %4ld %4ld %9.2le %3ld %3ld\n",
+ t, umax, kused, nst, nni, nje, nre, nreLS, hused, npe, nps);
+#else
+ printf(" %5.2f %13.5e %d %3ld %3ld %3ld %4ld %4ld %9.2e %3ld %3ld\n",
+ t, umax, kused, nst, nni, nje, nre, nreLS, hused, npe, nps);
+#endif
+
+ }
+}
+
+/*
+ * Print some final integrator statistics
+ */
+
+static void PrintFinalStats(void *mem)
+{
+ long int netf, ncfn, ncfl;
+
+ IDAGetNumErrTestFails(mem, &netf);
+ IDAGetNumNonlinSolvConvFails(mem, &ncfn);
+ IDASpilsGetNumConvFails(mem, &ncfl);
+
+ printf("\nError test failures = %ld\n", netf);
+ printf("Nonlinear convergence failures = %ld\n", ncfn);
+ printf("Linear convergence failures = %ld\n", ncfl);
+}
+
+/*
+ * 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, char *funcname, int opt, int id)
+{
+ int *errflag;
+
+ if (opt == 0 && flagvalue == NULL) {
+ /* Check if SUNDIALS function returned NULL pointer - no memory allocated */
+ fprintf(stderr,
+ "\nSUNDIALS_ERROR(%d): %s() failed - returned NULL pointer\n\n",
+ id, funcname);
+ return(1);
+ } else if (opt == 1) {
+ /* Check if flag < 0 */
+ errflag = (int *) flagvalue;
+ if (*errflag < 0) {
+ fprintf(stderr,
+ "\nSUNDIALS_ERROR(%d): %s() failed with flag = %d\n\n",
+ id, funcname, *errflag);
+ return(1);
+ }
+ } else if (opt == 2 && flagvalue == NULL) {
+ /* Check if function returned NULL pointer - no memory allocated */
+ fprintf(stderr,
+ "\nMEMORY_ERROR(%d): %s() failed - returned NULL pointer\n\n",
+ id, funcname);
+ return(1);
+ }
+
+ return(0);
+}
diff --git a/examples/ida/parallel/idaHeat2D_kry_p.out b/examples/ida/parallel/idaHeat2D_kry_p.out
new file mode 100644
index 0000000..12e1b95
--- /dev/null
+++ b/examples/ida/parallel/idaHeat2D_kry_p.out
@@ -0,0 +1,32 @@
+
+idaHeat2D_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
+
+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.
+
+ Output Summary (umax = max-norm of solution)
+
+ time umax k nst nni nli nre nreLS h npe nps
+----------------------------------------------------------------------
+ 0.00 9.75461e-01 0 0 0 0 0 0 0.00e+00 0 0
+ 0.01 8.24106e-01 2 12 14 7 14 7 2.56e-03 8 21
+ 0.02 6.88134e-01 3 15 18 12 18 12 5.12e-03 8 30
+ 0.04 4.70711e-01 3 18 24 21 24 21 6.58e-03 9 45
+ 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 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
+
+Error test failures = 1
+Nonlinear convergence failures = 0
+Linear convergence failures = 0
diff --git a/examples/ida/serial/CMakeLists.txt b/examples/ida/serial/CMakeLists.txt
new file mode 100644
index 0000000..720f6ee
--- /dev/null
+++ b/examples/ida/serial/CMakeLists.txt
@@ -0,0 +1,125 @@
+# ---------------------------------------------------------------
+# $Revision: 1.6 $
+# $Date: 2009/02/17 02:58:47 $
+# ---------------------------------------------------------------
+# Programmer: Radu Serban @ LLNL
+# ---------------------------------------------------------------
+# Copyright (c) 2007, The Regents of the University of California.
+# Produced at the Lawrence Livermore National Laboratory.
+# All rights reserved.
+# For details, see the LICENSE file.
+# ---------------------------------------------------------------
+# CMakeLists.txt file for IDA serial examples
+
+
+# Add variable IDA_examples with the names of the serial IDA examples
+
+SET(IDA_examples
+ idaFoodWeb_bnd
+ idaHeat2D_bnd
+ idaHeat2D_kry
+ idaKrylovDemo_ls
+ idaRoberts_dns
+ idaSlCrank_dns
+ )
+
+# Add variable IDA_examples_BL with the names of the serial IDA examples
+# that use Lapack
+
+SET(IDA_examples_BL
+ )
+
+# 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")
+ SET(IDA_LIB sundials_ida_shared)
+ SET(NVECS_LIB sundials_nvecserial_shared)
+ENDIF(LINK_LIBRARY_TYPE MATCHES "static")
+
+# Set-up linker flags and link libraries
+
+SET(SUNDIALS_LIBS ${IDA_LIB} ${NVECS_LIB} ${EXTRA_LINK_LIBS})
+IF(LAPACK_FOUND)
+ SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${LAPACK_LINKER_FLAGS}")
+ SET(SUNDIALS_LIBS "${SUNDIALS_LIBS} ${LAPACK_LIBRARIES}")
+ENDIF(LAPACK_FOUND)
+
+# Add the build and install targets for each IDA example
+
+FOREACH(example ${IDA_examples})
+ ADD_EXECUTABLE(${example} ${example}.c)
+ TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS} ${NVECS_LIB} ${EXTRA_LINK_LIBS})
+ IF(EXAMPLES_INSTALL)
+ INSTALL(FILES ${example}.c ${example}.out DESTINATION ${EXAMPLES_INSTALL_PATH}/ida/serial)
+ 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)
+ TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+ IF(EXAMPLES_INSTALL)
+ INSTALL(FILES ${example}.c ${example}.out DESTINATION ${EXAMPLES_INSTALL_PATH}/ida/serial)
+ ENDIF(EXAMPLES_INSTALL)
+ ENDFOREACH(example ${IDA_examples_BL})
+ENDIF(LAPACK_FOUND)
+
+IF(EXAMPLES_INSTALL)
+
+ # Install the README file
+ INSTALL(FILES README DESTINATION ${EXAMPLES_INSTALL_PATH}/ida/serial)
+
+ # 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)
+
+ # 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
+ )
+
+ # install CMakelists.txt
+ INSTALL(
+ FILES ${PROJECT_BINARY_DIR}/examples/ida/serial/CMakeLists.txt
+ 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
+ # 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/ida/serial/Makefile_ex
+ @ONLY
+ )
+ # install the configured Makefile_ex as Makefile
+ INSTALL(
+ FILES ${PROJECT_BINARY_DIR}/examples/ida/serial/Makefile_ex
+ DESTINATION ${EXAMPLES_INSTALL_PATH}/ida/serial
+ RENAME Makefile
+ )
+ ENDIF(UNIX)
+
+ENDIF(EXAMPLES_INSTALL)
diff --git a/examples/ida/serial/Makefile.in b/examples/ida/serial/Makefile.in
new file mode 100644
index 0000000..597e735
--- /dev/null
+++ b/examples/ida/serial/Makefile.in
@@ -0,0 +1,134 @@
+# -----------------------------------------------------------------
+# $Revision: 1.11 $
+# $Date: 2009/02/17 02:58:47 $
+# -----------------------------------------------------------------
+# Programmer(s): Radu Serban and Aaron Collier @ LLNL
+# -----------------------------------------------------------------
+# Copyright (c) 2002, The Regents of the University of California.
+# Produced at the Lawrence Livermore National Laboratory.
+# All rights reserved.
+# For details, see the LICENSE file.
+# -----------------------------------------------------------------
+# Makefile for IDA serial examples
+#
+# @configure_input@
+# -----------------------------------------------------------------
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_builddir = @top_builddir@
+builddir = @builddir@
+abs_builddir = @abs_builddir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+includedir = @includedir@
+libdir = @libdir@
+
+INSTALL = @INSTALL@
+INSTALL_PROG = @INSTALL_PROGRAM@
+INSTALL_FILE = @INSTALL_DATA@
+
+LIBTOOL = @LIBTOOL@
+LIBTOOL_DEPS = @LIBTOOL_DEPS@
+
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CC = @CC@
+CFLAGS = @CFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+
+LAPACK_ENABLED = @LAPACK_ENABLED@
+BLAS_LAPACK_LIBS = @BLAS_LAPACK_LIBS@
+
+OBJ_EXT = @OBJEXT@
+EXE_EXT = @EXEEXT@
+
+EXS_INSTDIR = @EXS_INSTDIR@
+
+top_srcdir = $(srcdir)/../../..
+
+SUNDIALS_INCS = -I$(top_srcdir)/include -I$(top_builddir)/include
+
+SUNDIALS_LIBS = $(top_builddir)/src/ida/libsundials_ida.la \
+ $(top_builddir)/src/nvec_ser/libsundials_nvecserial.la
+
+mkinstalldirs = $(SHELL) $(top_srcdir)/config/mkinstalldirs
+rminstalldirs = $(SHELL) $(top_srcdir)/config/rminstalldirs
+
+EXAMPLES = idaFoodWeb_bnd \
+ idaHeat2D_bnd \
+ idaHeat2D_kry \
+ idaKrylovDemo_ls \
+ idaRoberts_dns \
+ idaSlCrank_dns
+
+EXAMPLES_BL =
+
+OBJECTS = ${EXAMPLES:=${OBJ_EXT}}
+OBJECTS_BL = ${EXAMPLES_BL:=${OBJ_EXT}}
+EXECS = ${EXAMPLES:=${EXE_EXT}}
+EXECS_BL = ${EXAMPLES_BL:=${EXE_EXT}}
+
+# ----------------------------------------------------------------------------------------------------------------------
+
+all:
+ @for i in ${EXAMPLES} ; do \
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(SUNDIALS_INCS) $(CFLAGS) -c $(srcdir)/$${i}.c -o $${i}${OBJ_EXT} ; \
+ $(LIBTOOL) --mode=link $(CC) -o $(builddir)/$${i}$(EXE_EXT) $(builddir)/$${i}${OBJ_EXT} $(CFLAGS) $(LDFLAGS) $(SUNDIALS_LIBS) $(LIBS) $(BLAS_LAPACK_LIBS) ; \
+ done
+ @if test "X${LAPACK_ENABLED}" = "Xyes"; then \
+ for i in ${EXAMPLES_BL} ; do \
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(SUNDIALS_INCS) $(CFLAGS) -c $(srcdir)/$${i}.c -o $${i}${OBJ_EXT} ; \
+ $(LIBTOOL) --mode=link $(CC) -o $(builddir)/$${i}$(EXE_EXT) $(builddir)/$${i}${OBJ_EXT} $(CFLAGS) $(LDFLAGS) $(SUNDIALS_LIBS) $(LIBS) $(BLAS_LAPACK_LIBS) ; \
+ done ; \
+ fi
+
+install:
+ $(mkinstalldirs) $(EXS_INSTDIR)/ida/serial
+ $(INSTALL_FILE) Makefile_ex $(EXS_INSTDIR)/ida/serial/Makefile
+ $(INSTALL_FILE) $(top_srcdir)/examples/ida/serial/README $(EXS_INSTDIR)/ida/serial/
+ for i in ${EXAMPLES} ; do \
+ $(INSTALL_FILE) $(top_srcdir)/examples/ida/serial/$${i}.c $(EXS_INSTDIR)/ida/serial/ ; \
+ $(INSTALL_FILE) $(top_srcdir)/examples/ida/serial/$${i}.out $(EXS_INSTDIR)/ida/serial/ ; \
+ done
+ @if test "X${LAPACK_ENABLED}" = "Xyes"; then \
+ for i in ${EXAMPLES_BL} ; do \
+ $(INSTALL_FILE) $(top_srcdir)/examples/ida/serial/$${i}.c $(EXS_INSTDIR)/ida/serial/ ; \
+ $(INSTALL_FILE) $(top_srcdir)/examples/ida/serial/$${i}.out $(EXS_INSTDIR)/ida/serial/ ; \
+ done ; \
+ fi
+
+uninstall:
+ rm -f $(EXS_INSTDIR)/ida/serial/Makefile
+ rm -f $(EXS_INSTDIR)/ida/serial/README
+ for i in ${EXAMPLES} ; do \
+ rm -f $(EXS_INSTDIR)/ida/serial/$${i}.c ; \
+ rm -f $(EXS_INSTDIR)/ida/serial/$${i}.out ; \
+ done
+ @if test "X${LAPACK_ENABLED}" = "Xyes"; then \
+ for i in ${EXAMPLES_BL} ; do \
+ rm -f $(EXS_INSTDIR)/ida/serial/$${i}.c ; \
+ rm -f $(EXS_INSTDIR)/ida/serial/$${i}.out ; \
+ done ; \
+ fi
+ $(rminstalldirs) $(EXS_INSTDIR)/ida/serial
+ $(rminstalldirs) $(EXS_INSTDIR)/ida
+
+clean:
+ rm -rf .libs
+ rm -f *.lo
+ rm -f ${OBJECTS} ${OBJECTS_BL}
+ rm -f $(EXECS) $(EXECS_BL)
+
+distclean: clean
+ rm -f Makefile
+ rm -f Makefile_ex
+
+# ----------------------------------------------------------------------------------------------------------------------
+
+libtool: $(top_builddir)/$(LIBTOOL_DEPS)
+ @cd ${top_builddir} ; \
+ ${SHELL} ./config.status --recheck ; \
+ cd ${abs_builddir}
diff --git a/examples/ida/serial/README b/examples/ida/serial/README
new file mode 100644
index 0000000..c86d0b4
--- /dev/null
+++ b/examples/ida/serial/README
@@ -0,0 +1,19 @@
+List of serial IDA examples
+
+ idaFoodWeb_bnd : 2-D food web system, banded Jacobian
+ idaHeat2D_bnd : 2-D heat equation, banded Jacobian
+ idaHeat2D_kry : 2-D heat equation, diagonal preconditioner
+ idaKrylovDemo_ls : demonstration program with 3 Krylov solvers
+ idaRoberts_dns : 3-species Robertson kinetics system
+ idaSlCrank_dns : slider-crank example (stabilized index-2 DAE)
+
+Sample results:
+
+ SUNDIALS was built with the following options:
+
+ ./configure CC=gcc F77=gfortran CFLAGS="-g3 -O0" FFLAGS="-g3 -O0" --enable-examples
+
+ System Architecture: IA-32
+ Processor Type: Intel Pentium 4 Xeon DP (i686)
+ Operating System: Red Hat Enterprise Linux WS 3 (Taroon Update 7)
+ C/Fortran Compilers: gcc/gfortran v4.1.0
diff --git a/examples/ida/serial/idaFoodWeb_bnd.c b/examples/ida/serial/idaFoodWeb_bnd.c
new file mode 100644
index 0000000..35b83fe
--- /dev/null
+++ b/examples/ida/serial/idaFoodWeb_bnd.c
@@ -0,0 +1,674 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.2 $
+ * $Date: 2009/09/30 23:25:59 $
+ * -----------------------------------------------------------------
+ * 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
+ * solver, and IDACalcIC for initial condition calculation.
+ *
+ * The mathematical problem solved in this example is a DAE system
+ * that arises from a system of partial differential equations after
+ * spatial discretization. The PDE system is a food web population
+ * model, with predator-prey interaction and diffusion on the unit
+ * square in two dimensions. The dependent variable vector is:
+ *
+ * 1 2 ns
+ * c = (c , c , ..., c ) , ns = 2 * np
+ *
+ * and the PDE's are as follows:
+ *
+ * i i i
+ * dc /dt = d(i)*(c + c ) + R (x,y,c) (i = 1,...,np)
+ * xx yy i
+ *
+ * i i
+ * 0 = d(i)*(c + c ) + R (x,y,c) (i = np+1,...,ns)
+ * xx yy i
+ *
+ * where the reaction terms R are:
+ *
+ * i ns j
+ * R (x,y,c) = c * (b(i) + sum a(i,j)*c )
+ * i j=1
+ *
+ * The number of species is ns = 2 * np, with the first np being
+ * prey and the last np being predators. The coefficients a(i,j),
+ * b(i), d(i) are:
+ *
+ * a(i,i) = -AA (all i)
+ * a(i,j) = -GG (i <= np , j > np)
+ * a(i,j) = EE (i > np, j <= np)
+ * all other a(i,j) = 0
+ * b(i) = BB*(1+ alpha * x*y + beta*sin(4 pi x)*sin(4 pi y)) (i <= np)
+ * b(i) =-BB*(1+ alpha * x*y + beta*sin(4 pi x)*sin(4 pi y)) (i > np)
+ * d(i) = DPREY (i <= np)
+ * d(i) = DPRED (i > np)
+ *
+ * The various scalar parameters required are set using '#define'
+ * statements or directly in routine InitUserData. In this program,
+ * np = 1, ns = 2. The boundary conditions are homogeneous Neumann:
+ * normal derivative = 0.
+ *
+ * A polynomial in x and y is used to set the initial values of the
+ * first np variables (the prey variables) at each x,y location,
+ * while initial values for the remaining (predator) variables are
+ * set to a flat value, which is corrected by IDACalcIC.
+ *
+ * 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.
+ * Output is printed at t = 0, .001, .01, .1, .4, .7, 1.
+ * -----------------------------------------------------------------
+ * References:
+ * [1] Peter N. Brown and Alan C. Hindmarsh,
+ * Reduced Storage Matrix Methods in Stiff ODE systems, Journal
+ * of Applied Mathematics and Computation, Vol. 31 (May 1989),
+ * pp. 40-91.
+ *
+ * [2] Peter N. Brown, Alan C. Hindmarsh, and Linda R. Petzold,
+ * Using Krylov Methods in the Solution of Large-Scale
+ * Differential-Algebraic Systems, SIAM J. Sci. Comput., 15
+ * (1994), pp. 1467-1488.
+ *
+ * [3] Peter N. Brown, Alan C. Hindmarsh, and Linda R. Petzold,
+ * 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>
+
+/* Problem Constants. */
+
+#define NPREY 1 /* No. of prey (= no. of predators). */
+#define NUM_SPECIES 2*NPREY
+
+#define PI RCONST(3.1415926535898)
+#define FOURPI (RCONST(4.0)*PI)
+
+#define MX 20 /* MX = number of x mesh points */
+#define MY 20 /* MY = number of y mesh points */
+#define NSMX (NUM_SPECIES * MX)
+#define NEQ (NUM_SPECIES*MX*MY)
+#define AA RCONST(1.0) /* Coefficient in above eqns. for a */
+#define EE RCONST(10000.) /* Coefficient in above eqns. for a */
+#define GG RCONST(0.5e-6) /* Coefficient in above eqns. for a */
+#define BB RCONST(1.0) /* Coefficient in above eqns. for b */
+#define DPREY RCONST(1.0) /* Coefficient in above eqns. for d */
+#define DPRED RCONST(0.05) /* Coefficient in above eqns. for d */
+#define ALPHA RCONST(50.) /* Coefficient alpha in above eqns. */
+#define BETA RCONST(1000.) /* Coefficient beta in above eqns. */
+#define AX RCONST(1.0) /* Total range of x variable */
+#define AY RCONST(1.0) /* Total range of y variable */
+#define RTOL RCONST(1.e-5) /* Relative tolerance */
+#define ATOL RCONST(1.e-5) /* Absolute tolerance */
+#define NOUT 6 /* Number of output times */
+#define TMULT RCONST(10.0) /* Multiplier for tout values */
+#define TADD RCONST(0.3) /* Increment for tout values */
+#define ZERO RCONST(0.)
+#define ONE RCONST(1.0)
+
+/*
+ * User-defined vector and accessor macro: IJ_Vptr.
+ * IJ_Vptr is defined in order to express the underlying 3-D structure of
+ * the dependent variable vector from its underlying 1-D storage (an N_Vector).
+ * IJ_Vptr(vv,i,j) returns a pointer to the location in vv corresponding to
+ * species index is = 0, x-index ix = i, and y-index jy = j.
+ */
+
+#define IJ_Vptr(vv,i,j) (&NV_Ith_S(vv, (i)*NUM_SPECIES + (j)*NSMX))
+
+/* Type: UserData. Contains problem constants, etc. */
+
+typedef struct {
+ long int Neq, ns, np, mx, my;
+ realtype dx, dy, **acoef;
+ realtype cox[NUM_SPECIES], coy[NUM_SPECIES], bcoef[NUM_SPECIES];
+ N_Vector rates;
+} *UserData;
+
+/* Prototypes for functions called by the IDA Solver. */
+
+static int resweb(realtype time, N_Vector cc, N_Vector cp, N_Vector resval,
+ 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 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 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 int check_flag(void *flagvalue, char *funcname, int opt);
+
+/*
+ *--------------------------------------------------------------------
+ * MAIN PROGRAM
+ *--------------------------------------------------------------------
+ */
+
+int main()
+{
+ void *mem;
+ UserData webdata;
+ N_Vector cc, cp, id;
+ int iout, retval;
+ long int mu, ml;
+ realtype rtol, atol, t0, tout, tret;
+
+ mem = NULL;
+ webdata = NULL;
+ cc = cp = id = NULL;
+
+ /* Allocate and initialize user data block webdata. */
+
+ webdata = (UserData) malloc(sizeof *webdata);
+ webdata->rates = N_VNew_Serial(NEQ);
+ webdata->acoef = newDenseMat(NUM_SPECIES, NUM_SPECIES);
+
+ InitUserData(webdata);
+
+ /* Allocate N-vectors and initialize cc, cp, and id. */
+
+ cc = N_VNew_Serial(NEQ);
+ if(check_flag((void *)cc, "N_VNew_Serial", 0)) return(1);
+
+ cp = N_VNew_Serial(NEQ);
+ if(check_flag((void *)cp, "N_VNew_Serial", 0)) return(1);
+
+ id = N_VNew_Serial(NEQ);
+ if(check_flag((void *)id, "N_VNew_Serial", 0)) return(1);
+
+ SetInitialProfiles(cc, cp, id, webdata);
+
+ /* Set remaining inputs to IDAMalloc. */
+
+ t0 = ZERO;
+ rtol = RTOL;
+ atol = ATOL;
+
+ /* Call IDACreate and IDAMalloc to initialize IDA. */
+
+ mem = IDACreate();
+ if(check_flag((void *)mem, "IDACreate", 0)) return(1);
+
+ retval = IDASetUserData(mem, webdata);
+ if(check_flag(&retval, "IDASetUserData", 1)) return(1);
+
+ retval = IDASetId(mem, id);
+ if(check_flag(&retval, "IDASetId", 1)) return(1);
+
+ retval = IDAInit(mem, resweb, t0, cc, cp);
+ if(check_flag(&retval, "IDAInit", 1)) return(1);
+
+ retval = IDASStolerances(mem, rtol, atol);
+ if(check_flag(&retval, "IDASStolerances", 1)) return(1);
+
+ /* Call IDABand to specify the IDA linear solver. */
+
+ mu = ml = NSMX;
+ retval = IDABand(mem, NEQ, mu, ml);
+ if(check_flag(&retval, "IDABand", 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);
+ if(check_flag(&retval, "IDACalcIC", 1)) return(1);
+
+ /* Print heading, basic parameters, and initial values. */
+
+ PrintHeader(mu, ml, rtol, atol);
+ PrintOutput(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);
+ if(check_flag(&retval, "IDASolve", 1)) return(retval);
+
+ PrintOutput(mem, cc, tret);
+
+ if (iout < 3) tout *= TMULT; else tout += TADD;
+
+ }
+
+ /* Print final statistics and free memory. */
+
+ PrintFinalStats(mem);
+
+ /* Free memory */
+
+ IDAFree(&mem);
+
+ N_VDestroy_Serial(cc);
+ N_VDestroy_Serial(cp);
+ N_VDestroy_Serial(id);
+
+
+ destroyMat(webdata->acoef);
+ N_VDestroy_Serial(webdata->rates);
+ free(webdata);
+
+ return(0);
+}
+
+/* Define lines for readability in later routines */
+
+#define acoef (webdata->acoef)
+#define bcoef (webdata->bcoef)
+#define cox (webdata->cox)
+#define coy (webdata->coy)
+
+/*
+ *--------------------------------------------------------------------
+ * FUNCTIONS CALLED BY IDA
+ *--------------------------------------------------------------------
+ */
+
+/*
+ * resweb: System residual function for predator-prey system.
+ * This routine calls Fweb to get all the right-hand sides of the
+ * equations, then loads the residual vector accordingly,
+ * using cp in the case of prey species.
+ */
+
+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;
+ realtype *resv, *cpv;
+ UserData webdata;
+
+ webdata = (UserData)user_data;
+
+ cpv = NV_DATA_S(cp);
+ resv = NV_DATA_S(res);
+ np = webdata->np;
+
+ /* Call Fweb to set res to vector of right-hand sides. */
+ Fweb(tt, cc, res, webdata);
+
+ /* Loop over all grid points, setting residual values appropriately
+ for differential or algebraic components. */
+
+ for (jy = 0; jy < MY; jy++) {
+ yloc = NSMX * jy;
+ for (jx = 0; jx < MX; jx++) {
+ loc = yloc + NUM_SPECIES * jx;
+ for (is = 0; is < NUM_SPECIES; is++) {
+ if (is < np)
+ resv[loc+is] = cpv[loc+is] - resv[loc+is];
+ else
+ resv[loc+is] = -resv[loc+is];
+ }
+ }
+ }
+
+ return(0);
+
+}
+
+/*
+ *--------------------------------------------------------------------
+ * PRIVATE FUNCTIONS
+ *--------------------------------------------------------------------
+ */
+
+/*
+ * InitUserData: Load problem constants in webdata (of type UserData).
+ */
+
+static void InitUserData(UserData webdata)
+{
+ int i, j, np;
+ realtype *a1,*a2, *a3, *a4, dx2, dy2;
+
+ webdata->mx = MX;
+ webdata->my = MY;
+ webdata->ns = NUM_SPECIES;
+ webdata->np = NPREY;
+ webdata->dx = AX/(MX-1);
+ webdata->dy = AY/(MY-1);
+ webdata->Neq= NEQ;
+
+ /* Set up the coefficients a and b, and others found in the equations. */
+ np = webdata->np;
+ dx2 = (webdata->dx)*(webdata->dx); dy2 = (webdata->dy)*(webdata->dy);
+
+ for (i = 0; i < np; i++) {
+ a1 = &(acoef[i][np]);
+ a2 = &(acoef[i+np][0]);
+ a3 = &(acoef[i][0]);
+ a4 = &(acoef[i+np][np]);
+ /* Fill in the portion of acoef in the four quadrants, row by row. */
+ for (j = 0; j < np; j++) {
+ *a1++ = -GG;
+ *a2++ = EE;
+ *a3++ = ZERO;
+ *a4++ = ZERO;
+ }
+
+ /* Reset the diagonal elements of acoef to -AA. */
+ acoef[i][i] = -AA; acoef[i+np][i+np] = -AA;
+
+ /* Set coefficients for b and diffusion terms. */
+ bcoef[i] = BB; bcoef[i+np] = -BB;
+ cox[i] = DPREY/dx2; cox[i+np] = DPRED/dx2;
+ coy[i] = DPREY/dy2; coy[i+np] = DPRED/dy2;
+ }
+
+}
+
+/*
+ * SetInitialProfiles: Set initial conditions in cc, cp, and id.
+ * A polynomial profile is used for the prey cc values, and a constant
+ * (1.0e5) is loaded as the initial guess for the predator cc values.
+ * The id values are set to 1 for the prey and 0 for the predators.
+ * The prey cp values are set according to the given system, and
+ * the predator cp values are set to zero.
+ */
+
+static void SetInitialProfiles(N_Vector cc, N_Vector cp, N_Vector id,
+ UserData webdata)
+{
+ long int loc, yloc, is, jx, jy, np;
+ realtype xx, yy, xyfactor, fac;
+ realtype *ccv, *cpv, *idv;
+
+ ccv = NV_DATA_S(cc);
+ cpv = NV_DATA_S(cp);
+ idv = NV_DATA_S(id);
+ np = webdata->np;
+
+ /* Loop over grid, load cc values and id values. */
+ for (jy = 0; jy < MY; jy++) {
+ yy = jy * webdata->dy;
+ yloc = NSMX * jy;
+ for (jx = 0; jx < MX; jx++) {
+ xx = jx * webdata->dx;
+ xyfactor = RCONST(16.0)*xx*(ONE-xx)*yy*(ONE-yy);
+ 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;
+ idv[loc+is] = ONE;
+ }
+ else {
+ ccv[loc+is] = RCONST(1.0e5);
+ idv[loc+is] = ZERO;
+ }
+ }
+ }
+ }
+
+ /* Set c' for the prey by calling the function Fweb. */
+ Fweb(ZERO, cc, cp, webdata);
+
+ /* Set c' for predators to 0. */
+ for (jy = 0; jy < MY; jy++) {
+ yloc = NSMX * jy;
+ for (jx = 0; jx < MX; jx++) {
+ loc = yloc + NUM_SPECIES * jx;
+ for (is = np; is < NUM_SPECIES; is++) {
+ cpv[loc+is] = ZERO;
+ }
+ }
+ }
+}
+
+/*
+ * Print first lines of output (problem description)
+ */
+
+static void PrintHeader(long int mu, long int 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);
+ printf(" Mesh dimensions: %d x %d", MX, MY);
+ printf(" System size: %d\n", NEQ);
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("Tolerance parameters: rtol = %Lg atol = %Lg\n", rtol, atol);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("Tolerance parameters: rtol = %lg atol = %lg\n", rtol, 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("CalcIC called to correct initial predator concentrations.\n\n");
+ printf("-----------------------------------------------------------\n");
+ printf(" t bottom-left top-right");
+ printf(" | nst k h\n");
+ printf("-----------------------------------------------------------\n\n");
+
+}
+
+/*
+ * PrintOutput: Print output values at output time t = tt.
+ * Selected run statistics are printed. Then values of the concentrations
+ * are printed for the bottom left and top right grid points only.
+ */
+
+static void PrintOutput(void *mem, N_Vector c, realtype t)
+{
+ int i, kused, flag;
+ long int nst;
+ realtype *c_bl, *c_tr, hused;
+
+ flag = IDAGetLastOrder(mem, &kused);
+ check_flag(&flag, "IDAGetLastOrder", 1);
+ flag = IDAGetNumSteps(mem, &nst);
+ check_flag(&flag, "IDAGetNumSteps", 1);
+ flag = IDAGetLastStep(mem, &hused);
+ check_flag(&flag, "IDAGetLastStep", 1);
+
+ c_bl = IJ_Vptr(c,0,0);
+ c_tr = IJ_Vptr(c,MX-1,MY-1);
+
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("%8.2Le %12.4Le %12.4Le | %3ld %1d %12.4Le\n",
+ t, c_bl[0], c_tr[1], nst, kused, hused);
+ for (i=1;i<NUM_SPECIES;i++)
+ printf(" %12.4Le %12.4Le |\n",c_bl[i],c_tr[i]);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("%8.2le %12.4le %12.4le | %3ld %1d %12.4le\n",
+ t, c_bl[0], c_tr[1], nst, kused, hused);
+ for (i=1;i<NUM_SPECIES;i++)
+ printf(" %12.4le %12.4le |\n",c_bl[i],c_tr[i]);
+#else
+ printf("%8.2e %12.4e %12.4e | %3ld %1d %12.4e\n",
+ t, c_bl[0], c_tr[1], nst, kused, hused);
+ for (i=1;i<NUM_SPECIES;i++)
+ printf(" %12.4e %12.4e |\n",c_bl[i],c_tr[i]);
+#endif
+
+ printf("\n");
+}
+
+/*
+ * PrintFinalStats: Print final run data contained in iopt.
+ */
+
+static void PrintFinalStats(void *mem)
+{
+ long int nst, nre, nreLS, nni, nje, netf, ncfn;
+ int flag;
+
+ flag = IDAGetNumSteps(mem, &nst);
+ check_flag(&flag, "IDAGetNumSteps", 1);
+ flag = IDAGetNumNonlinSolvIters(mem, &nni);
+ check_flag(&flag, "IDAGetNumNonlinSolvIters", 1);
+ flag = IDAGetNumResEvals(mem, &nre);
+ check_flag(&flag, "IDAGetNumResEvals", 1);
+ flag = IDAGetNumErrTestFails(mem, &netf);
+ check_flag(&flag, "IDAGetNumErrTestFails", 1);
+ flag = IDAGetNumNonlinSolvConvFails(mem, &ncfn);
+ check_flag(&flag, "IDAGetNumNonlinSolvConvFails", 1);
+ flag = IDADlsGetNumJacEvals(mem, &nje);
+ check_flag(&flag, "IDADlsGetNumJacEvals", 1);
+ flag = IDADlsGetNumResEvals(mem, &nreLS);
+ check_flag(&flag, "IDADlsGetNumResEvals", 1);
+
+ printf("-----------------------------------------------------------\n");
+ printf("Final run statistics: \n\n");
+ printf("Number of steps = %ld\n", nst);
+ printf("Number of residual evaluations = %ld\n", nre+nreLS);
+ 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);
+ printf("Number of nonlinear conv. failures = %ld\n", ncfn);
+
+}
+
+/*
+ * Fweb: Rate function for the food-web problem.
+ * This routine computes the right-hand sides of the system equations,
+ * consisting of the diffusion term and interaction term.
+ * The interaction term is computed by the function WebRates.
+ */
+
+static void Fweb(realtype tcalc, N_Vector cc, N_Vector crate,
+ UserData webdata)
+{
+ long int 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),
+ form diffusion difference terms, and load crate. */
+
+ for (jy = 0; jy < MY; jy++) {
+ yy = (webdata->dy) * jy ;
+ idyu = (jy!=MY-1) ? NSMX : -NSMX;
+ idyl = (jy!= 0 ) ? NSMX : -NSMX;
+
+ for (jx = 0; jx < MX; jx++) {
+ xx = (webdata->dx) * jx;
+ idxu = (jx!= MX-1) ? NUM_SPECIES : -NUM_SPECIES;
+ idxl = (jx!= 0 ) ? NUM_SPECIES : -NUM_SPECIES;
+ cxy = IJ_Vptr(cc,jx,jy);
+ ratesxy = IJ_Vptr(webdata->rates,jx,jy);
+ cratexy = IJ_Vptr(crate,jx,jy);
+
+ /* Get interaction vector at this grid point. */
+ WebRates(xx, yy, cxy, ratesxy, webdata);
+
+ /* Loop over species, do differencing, load crate segment. */
+ for (is = 0; is < NUM_SPECIES; is++) {
+
+ /* Differencing in y. */
+ dcyli = *(cxy+is) - *(cxy - idyl + is) ;
+ dcyui = *(cxy + idyu + is) - *(cxy+is);
+
+ /* Differencing in x. */
+ dcxli = *(cxy+is) - *(cxy - idxl + is);
+ dcxui = *(cxy + idxu +is) - *(cxy+is);
+
+ /* Compute the crate values at (xx,yy). */
+ cratexy[is] = coy[is] * (dcyui - dcyli) +
+ cox[is] * (dcxui - dcxli) + ratesxy[is];
+
+ } /* End is loop */
+ } /* End of jx loop */
+ } /* End of jy loop */
+
+}
+
+/*
+ * WebRates: Evaluate reaction rates at a given spatial point.
+ * At a given (x,y), evaluate the array of ns reaction terms R.
+ */
+
+static void WebRates(realtype xx, realtype yy, realtype *cxy, realtype *ratesxy,
+ UserData webdata)
+{
+ int is;
+ realtype fac;
+
+ for (is = 0; is < NUM_SPECIES; is++)
+ ratesxy[is] = dotprod(NUM_SPECIES, cxy, acoef[is]);
+
+ fac = ONE + ALPHA*xx*yy + BETA*sin(FOURPI*xx)*sin(FOURPI*yy);
+
+ for (is = 0; is < NUM_SPECIES; is++)
+ ratesxy[is] = cxy[is]*( bcoef[is]*fac + ratesxy[is] );
+
+}
+
+/*
+ * dotprod: dot product routine for realtype arrays, for use by WebRates.
+ */
+
+static realtype dotprod(long int size, realtype *x1, realtype *x2)
+{
+ long int i;
+ realtype *xx1, *xx2, temp = ZERO;
+
+ xx1 = x1; xx2 = x2;
+ for (i = 0; i < size; i++) temp += (*xx1++) * (*xx2++);
+ return(temp);
+
+}
+
+/*
+ * 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, char *funcname, int opt)
+{
+ int *errflag;
+
+ if (opt == 0 && flagvalue == NULL) {
+ /* Check if SUNDIALS function returned NULL pointer - no memory allocated */
+ 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/idaFoodWeb_bnd.out b/examples/ida/serial/idaFoodWeb_bnd.out
new file mode 100644
index 0000000..293c68d
--- /dev/null
+++ b/examples/ida/serial/idaFoodWeb_bnd.out
@@ -0,0 +1,42 @@
+
+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
+CalcIC called to correct initial predator concentrations.
+
+-----------------------------------------------------------
+ t bottom-left top-right | nst k h
+-----------------------------------------------------------
+
+0.00e+00 1.0000e+01 1.0000e+05 | 0 0 1.6310e-08
+ 1.0000e+05 1.0000e+05 |
+
+1.00e-03 1.0318e+01 1.0822e+05 | 32 4 1.0823e-04
+ 1.0319e+05 1.0822e+05 |
+
+1.00e-02 1.6188e+02 1.9734e+06 | 127 4 1.4203e-04
+ 1.6189e+06 1.9734e+06 |
+
+1.00e-01 2.4019e+02 2.7072e+06 | 235 1 3.9160e-02
+ 2.4019e+06 2.7072e+06 |
+
+4.00e-01 2.4019e+02 2.7072e+06 | 238 1 3.1328e-01
+ 2.4019e+06 2.7072e+06 |
+
+7.00e-01 2.4019e+02 2.7072e+06 | 239 1 6.2657e-01
+ 2.4019e+06 2.7072e+06 |
+
+1.00e+00 2.4019e+02 2.7072e+06 | 239 1 6.2657e-01
+ 2.4019e+06 2.7072e+06 |
+
+-----------------------------------------------------------
+Final run statistics:
+
+Number of steps = 239
+Number of residual evaluations = 3339
+Number of Jacobian evaluations = 36
+Number of nonlinear iterations = 421
+Number of error test failures = 3
+Number of nonlinear conv. failures = 0
diff --git a/examples/ida/serial/idaHeat2D_bnd.c b/examples/ida/serial/idaHeat2D_bnd.c
new file mode 100644
index 0000000..7167d73
--- /dev/null
+++ b/examples/ida/serial/idaHeat2D_bnd.c
@@ -0,0 +1,407 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.2 $
+ * $Date: 2009/09/30 23:25:59 $
+ * -----------------------------------------------------------------
+ * 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.
+ *
+ * The DAE system solved is a spatial discretization of the PDE
+ * du/dt = d^2u/dx^2 + d^2u/dy^2
+ * on the unit square. The boundary condition is u = 0 on all edges.
+ * Initial conditions are given by u = 16 x (1 - x) y (1 - y).
+ * The PDE is treated with central differences on a uniform M x M
+ * grid. The values of u at the interior points satisfy ODEs, and
+ * equations u = 0 at the boundaries are appended, to form a DAE
+ * system of size N = M^2. Here M = 10.
+ *
+ * The system is solved with IDA using the banded linear system
+ * solver, half-bandwidths equal to M, and default
+ * difference-quotient 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_band.h>
+#include <nvector/nvector_serial.h>
+#include <sundials/sundials_types.h>
+
+/* Problem Constants */
+
+#define NOUT 11
+#define MGRID 10
+#define NEQ MGRID*MGRID
+#define ZERO RCONST(0.0)
+#define ONE RCONST(1.0)
+#define TWO RCONST(2.0)
+#define BVAL RCONST(0.1)
+
+/* Type: UserData */
+
+typedef struct {
+ long int 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);
+
+/* Prototypes of private functions */
+
+static void PrintHeader(realtype rtol, realtype atol);
+static void PrintOutput(void *mem, realtype t, N_Vector u);
+static int SetInitialProfile(UserData data, N_Vector uu, N_Vector up,
+ N_Vector id, N_Vector res);
+
+static int check_flag(void *flagvalue, char *funcname, int opt);
+
+/*
+ *--------------------------------------------------------------------
+ * MAIN PROGRAM
+ *--------------------------------------------------------------------
+ */
+
+int main(void)
+{
+ void *mem;
+ UserData data;
+ N_Vector uu, up, constraints, id, res;
+ int ier, iout;
+ long int mu, ml, netf, ncfn;
+ realtype rtol, atol, t0, t1, tout, tret;
+
+ mem = NULL;
+ data = NULL;
+ uu = up = constraints = id = res = NULL;
+
+ /* Create vectors uu, up, res, constraints, id. */
+ uu = N_VNew_Serial(NEQ);
+ if(check_flag((void *)uu, "N_VNew_Serial", 0)) return(1);
+ up = N_VNew_Serial(NEQ);
+ if(check_flag((void *)up, "N_VNew_Serial", 0)) return(1);
+ res = N_VNew_Serial(NEQ);
+ 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);
+ if(check_flag((void *)id, "N_VNew_Serial", 0)) return(1);
+
+ /* Create and load problem data block. */
+ data = (UserData) malloc(sizeof *data);
+ if(check_flag((void *)data, "malloc", 2)) return(1);
+ data->mm = MGRID;
+ data->dx = ONE/(MGRID - ONE);
+ data->coeff = ONE/( (data->dx) * (data->dx) );
+
+ /* Initialize uu, up, id. */
+ SetInitialProfile(data, uu, up, id, res);
+
+ /* Set constraints to all 1's for nonnegative solution values. */
+ N_VConst(ONE, constraints);
+
+ /* Set remaining input parameters. */
+ t0 = ZERO;
+ t1 = RCONST(0.01);
+ rtol = ZERO;
+ atol = RCONST(1.0e-3);
+
+ /* Call IDACreate and IDAMalloc to initialize solution */
+ mem = IDACreate();
+ if(check_flag((void *)mem, "IDACreate", 0)) return(1);
+
+ ier = IDASetUserData(mem, data);
+ if(check_flag(&ier, "IDASetUserData", 1)) return(1);
+
+ 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);
+
+ ier = IDAInit(mem, heatres, t0, uu, up);
+ if(check_flag(&ier, "IDAInit", 1)) return(1);
+
+ ier = IDASStolerances(mem, rtol, atol);
+ if(check_flag(&ier, "IDASStolerances", 1)) return(1);
+
+ /* Call IDABand to specify the linear solver. */
+ mu = MGRID; ml = MGRID;
+ ier = IDABand(mem, NEQ, mu, ml);
+ if(check_flag(&ier, "IDABand", 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);
+
+ /* Print output heading. */
+ PrintHeader(rtol, atol);
+
+ PrintOutput(mem, t0, uu);
+
+
+ /* Loop over output times, call IDASolve, and print results. */
+
+ for (tout = t1, iout = 1; iout <= NOUT; iout++, tout *= TWO) {
+
+ ier = IDASolve(mem, tout, &tret, uu, up, IDA_NORMAL);
+ if(check_flag(&ier, "IDASolve", 1)) return(1);
+
+ PrintOutput(mem, tret, uu);
+
+ }
+
+ /* Print remaining counters and free memory. */
+ ier = IDAGetNumErrTestFails(mem, &netf);
+ check_flag(&ier, "IDAGetNumErrTestFails", 1);
+ ier = IDAGetNumNonlinSolvConvFails(mem, &ncfn);
+ check_flag(&ier, "IDAGetNumNonlinSolvConvFails", 1);
+ 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);
+ free(data);
+
+ return(0);
+}
+
+/*
+ *--------------------------------------------------------------------
+ * FUNCTIONS CALLED BY KINSOL
+ *--------------------------------------------------------------------
+ */
+
+/*
+ * heatres: heat equation system residual function
+ * This uses 5-point central differencing on the interior points, and
+ * includes algebraic equations for the boundary values.
+ * So for each interior point, the residual component has the form
+ * res_i = u'_i - (central difference)_i
+ * while for each boundary point, it is res_i = u_i.
+ */
+
+int heatres(realtype tres, N_Vector uu, N_Vector up, N_Vector resval,
+ void *user_data)
+{
+ long int mm, i, j, offset, loc;
+ realtype *uv, *upv, *resv, coeff;
+ UserData data;
+
+ uv = NV_DATA_S(uu); upv = NV_DATA_S(up); resv = NV_DATA_S(resval);
+
+ data = (UserData)user_data;
+ mm = data->mm;
+ coeff = data->coeff;
+
+ /* Initialize resval to uu, to take care of boundary equations. */
+ N_VScale(ONE, uu, resval);
+
+ /* Loop over interior points; set res = up - (central difference). */
+ for (j = 1; j < mm-1; j++) {
+ offset = mm*j;
+ for (i = 1; i < mm-1; i++) {
+ loc = offset + i;
+ resv[loc] = upv[loc] - coeff *
+ (uv[loc-1] + uv[loc+1] + uv[loc-mm] + uv[loc+mm] - RCONST(4.0)*uv[loc]);
+ }
+ }
+
+ return(0);
+
+}
+
+/*
+ *--------------------------------------------------------------------
+ * PRIVATE FUNCTIONS
+ *--------------------------------------------------------------------
+ */
+
+/*
+ * SetInitialProfile: routine to initialize u, up, and id vectors.
+ */
+
+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;
+
+ mm = data->mm;
+ mm1 = mm - 1;
+
+ udata = NV_DATA_S(uu);
+ updata = NV_DATA_S(up);
+ iddata = NV_DATA_S(id);
+
+ /* Initialize id to 1's. */
+ N_VConst(ONE, id);
+
+ /* Initialize uu on all grid points. */
+ for (j = 0; j < mm; j++) {
+ yfact = data->dx * j;
+ offset = mm*j;
+ for (i = 0;i < mm; i++) {
+ xfact = data->dx * i;
+ loc = offset + i;
+ udata[loc] = RCONST(16.0) * xfact * (ONE - xfact) * yfact * (ONE - yfact);
+ }
+ }
+
+ /* Initialize up vector to 0. */
+ N_VConst(ZERO, up);
+
+ /* heatres sets res to negative of ODE RHS values at interior points. */
+ heatres(ZERO, uu, up, res, data);
+
+ /* Copy -res into up to get correct interior initial up values. */
+ N_VScale(-ONE, res, up);
+
+ /* Finally, set values of u, up, and id at boundary points. */
+ for (j = 0; j < mm; j++) {
+ offset = mm*j;
+ for (i = 0;i < mm; i++) {
+ loc = offset + i;
+ if (j == 0 || j == mm1 || i == 0 || i == mm1 ) {
+ udata[loc] = BVAL; updata[loc] = ZERO; iddata[loc] = ZERO; }
+ }
+ }
+
+ return(0);
+
+}
+
+/*
+ * Print first lines of output (problem description)
+ */
+
+static void PrintHeader(realtype rtol, realtype atol)
+{
+ printf("\nidaHeat2D_bnd: Heat equation, serial 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", MGRID, MGRID);
+ printf(" Total system size: %d\n\n", NEQ);
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("Tolerance parameters: rtol = %Lg atol = %Lg\n", rtol, atol);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("Tolerance parameters: rtol = %lg atol = %lg\n", rtol, atol);
+#else
+ 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(" difference quotient Jacobian, half-bandwidths = %d \n",MGRID);
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("IDACalcIC called with input boundary values = %Lg \n",BVAL);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("IDACalcIC called with input boundary values = %lg \n",BVAL);
+#else
+ printf("IDACalcIC called with input boundary values = %g \n",BVAL);
+#endif
+ /* Print output table heading and initial line of table. */
+ printf("\n Output Summary (umax = max-norm of solution) \n\n");
+ printf(" time umax k nst nni nje nre nreLS h \n" );
+ printf(" . . . . . . . . . . . . . . . . . . . . . \n");
+}
+
+/*
+ * Print Output
+ */
+
+static void PrintOutput(void *mem, realtype t, N_Vector uu)
+{
+ int ier;
+ realtype umax, hused;
+ long int nst, nni, nje, nre, nreLS;
+ int kused;
+
+ umax = N_VMaxNorm(uu);
+
+ ier = IDAGetLastOrder(mem, &kused);
+ check_flag(&ier, "IDAGetLastOrder", 1);
+ ier = IDAGetNumSteps(mem, &nst);
+ check_flag(&ier, "IDAGetNumSteps", 1);
+ ier = IDAGetNumNonlinSolvIters(mem, &nni);
+ check_flag(&ier, "IDAGetNumNonlinSolvIters", 1);
+ ier = IDAGetNumResEvals(mem, &nre);
+ check_flag(&ier, "IDAGetNumResEvals", 1);
+ ier = IDAGetLastStep(mem, &hused);
+ check_flag(&ier, "IDAGetLastStep", 1);
+ ier = IDADlsGetNumJacEvals(mem, &nje);
+ check_flag(&ier, "IDADlsGetNumJacEvals", 1);
+ ier = IDADlsGetNumResEvals(mem, &nreLS);
+ check_flag(&ier, "IDADlsGetNumResEvals", 1);
+
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf(" %5.2Lf %13.5Le %d %3ld %3ld %3ld %4ld %4ld %9.2Le \n",
+ t, umax, kused, nst, nni, nje, nre, nreLS, hused);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf(" %5.2f %13.5le %d %3ld %3ld %3ld %4ld %4ld %9.2le \n",
+ t, umax, kused, nst, nni, nje, nre, nreLS, hused);
+#else
+ printf(" %5.2f %13.5e %d %3ld %3ld %3ld %4ld %4ld %9.2e \n",
+ t, umax, kused, nst, nni, nje, nre, nreLS, hused);
+#endif
+
+}
+
+/*
+ * 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, 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/idaHeat2D_bnd.out b/examples/ida/serial/idaHeat2D_bnd.out
new file mode 100644
index 0000000..0d98fae
--- /dev/null
+++ b/examples/ida/serial/idaHeat2D_bnd.out
@@ -0,0 +1,30 @@
+
+idaHeat2D_bnd: Heat equation, serial 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
+
+Tolerance parameters: rtol = 0 atol = 0.001
+Constraints set to force all solution components >= 0.
+Linear solver: IDABAND, banded direct solver
+ difference quotient Jacobian, half-bandwidths = 10
+IDACalcIC called with input boundary values = 0.1
+
+ Output Summary (umax = max-norm of solution)
+
+ 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
+
+ netf = 0, ncfn = 0
diff --git a/examples/ida/serial/idaHeat2D_kry.c b/examples/ida/serial/idaHeat2D_kry.c
new file mode 100644
index 0000000..72cd9a2
--- /dev/null
+++ b/examples/ida/serial/idaHeat2D_kry.c
@@ -0,0 +1,550 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.2 $
+ * $Date: 2009/09/30 23:25:59 $
+ * -----------------------------------------------------------------
+ * 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.
+ *
+ * The DAE system solved is a spatial discretization of the PDE
+ * du/dt = d^2u/dx^2 + d^2u/dy^2
+ * on the unit square. The boundary condition is u = 0 on all edges.
+ * Initial conditions are given by u = 16 x (1 - x) y (1 - y). The
+ * PDE is treated with central differences on a uniform M x M grid.
+ * The values of u at the interior points satisfy ODEs, and
+ * equations u = 0 at the boundaries are appended, to form a DAE
+ * 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
+ * Jacobian only. Routines for preconditioning, required by
+ * IDASPGMR, 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.
+ * -----------------------------------------------------------------
+ */
+
+#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>
+
+/* Problem Constants */
+
+#define NOUT 11
+#define MGRID 10
+#define NEQ MGRID*MGRID
+#define ZERO RCONST(0.0)
+#define ONE RCONST(1.0)
+#define TWO RCONST(2.0)
+#define FOUR RCONST(4.0)
+
+/* User data type */
+
+typedef struct {
+ long int mm; /* number of grid points */
+ realtype dx;
+ realtype coeff;
+ N_Vector pp; /* vector of prec. diag. elements */
+} *UserData;
+
+/* Prototypes for functions called by IDA */
+
+int resHeat(realtype tres, N_Vector uu, N_Vector up,
+ N_Vector resval, void *user_data);
+
+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);
+
+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);
+
+/* Prototypes for private functions */
+
+static int SetInitialProfile(UserData data, N_Vector uu, N_Vector up,
+ N_Vector res);
+static void PrintHeader(realtype rtol, realtype atol);
+static void PrintOutput(void *mem, realtype t, N_Vector uu);
+static int check_flag(void *flagvalue, char *funcname, int opt);
+
+/*
+ *--------------------------------------------------------------------
+ * MAIN PROGRAM
+ *--------------------------------------------------------------------
+ */
+
+int main()
+{
+ void *mem;
+ UserData data;
+ N_Vector uu, up, constraints, res;
+ int ier, iout;
+ realtype rtol, atol, t0, t1, tout, tret;
+ long int netf, ncfn, ncfl;
+
+ mem = NULL;
+ data = NULL;
+ uu = up = constraints = res = NULL;
+
+ /* Allocate N-vectors and the user data structure. */
+
+ uu = N_VNew_Serial(NEQ);
+ if(check_flag((void *)uu, "N_VNew_Serial", 0)) return(1);
+
+ up = N_VNew_Serial(NEQ);
+ if(check_flag((void *)up, "N_VNew_Serial", 0)) return(1);
+
+ res = N_VNew_Serial(NEQ);
+ 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);
+
+ data = (UserData) malloc(sizeof *data);
+ data->pp = NULL;
+ if(check_flag((void *)data, "malloc", 2)) return(1);
+
+ /* Assign parameters in the user data structure. */
+
+ data->mm = MGRID;
+ data->dx = ONE/(MGRID-ONE);
+ data->coeff = ONE/(data->dx * data->dx);
+ data->pp = N_VNew_Serial(NEQ);
+ if(check_flag((void *)data->pp, "N_VNew_Serial", 0)) return(1);
+
+ /* Initialize uu, up. */
+
+ SetInitialProfile(data, uu, up, res);
+
+ /* Set constraints to all 1's for nonnegative solution values. */
+
+ N_VConst(ONE, constraints);
+
+ /* Assign various parameters. */
+
+ t0 = ZERO;
+ t1 = RCONST(0.01);
+ rtol = ZERO;
+ atol = RCONST(1.0e-3);
+
+ /* Call IDACreate and IDAMalloc to initialize solution */
+
+ mem = IDACreate();
+ if(check_flag((void *)mem, "IDACreate", 0)) return(1);
+
+ ier = IDASetUserData(mem, data);
+ if(check_flag(&ier, "IDASetUserData", 1)) return(1);
+
+ ier = IDASetConstraints(mem, constraints);
+ if(check_flag(&ier, "IDASetConstraints", 1)) return(1);
+ N_VDestroy_Serial(constraints);
+
+ ier = IDAInit(mem, resHeat, t0, uu, up);
+ if(check_flag(&ier, "IDAInit", 1)) return(1);
+
+ ier = IDASStolerances(mem, rtol, atol);
+ if(check_flag(&ier, "IDASStolerances", 1)) return(1);
+
+ /* Call IDASpgmr to specify the linear solver. */
+
+ ier = IDASpgmr(mem, 0);
+ if(check_flag(&ier, "IDASpgmr", 1)) return(1);
+
+ ier = IDASpilsSetPreconditioner(mem, PsetupHeat, PsolveHeat);
+ if(check_flag(&ier, "IDASpilsSetPreconditioner", 1)) return(1);
+
+ /* Print output heading. */
+ PrintHeader(rtol, atol);
+
+ /*
+ * -------------------------------------------------------------------------
+ * CASE I
+ * -------------------------------------------------------------------------
+ */
+
+ /* Print case number, output table heading, and initial line of table. */
+
+ printf("\n\nCase 1: gsytpe = MODIFIED_GS\n");
+ printf("\n Output Summary (umax = max-norm of solution) \n\n");
+ printf(" time umax k nst nni nje nre nreLS h npe nps\n" );
+ printf("----------------------------------------------------------------------\n");
+
+ /* Loop over output times, call IDASolve, and print results. */
+
+ for (tout = t1,iout = 1; iout <= NOUT ; iout++, tout *= TWO) {
+ ier = IDASolve(mem, tout, &tret, uu, up, IDA_NORMAL);
+ if(check_flag(&ier, "IDASolve", 1)) return(1);
+ PrintOutput(mem, tret, uu);
+ }
+
+ /* Print remaining counters. */
+
+ ier = IDAGetNumErrTestFails(mem, &netf);
+ check_flag(&ier, "IDAGetNumErrTestFails", 1);
+
+ ier = IDAGetNumNonlinSolvConvFails(mem, &ncfn);
+ check_flag(&ier, "IDAGetNumNonlinSolvConvFails", 1);
+
+ ier = IDASpilsGetNumConvFails(mem, &ncfl);
+ check_flag(&ier, "IDASpilsGetNumConvFails", 1);
+
+ printf("\nError test failures = %ld\n", netf);
+ printf("Nonlinear convergence failures = %ld\n", ncfn);
+ printf("Linear convergence failures = %ld\n", ncfl);
+
+ /*
+ * -------------------------------------------------------------------------
+ * CASE II
+ * -------------------------------------------------------------------------
+ */
+
+ /* Re-initialize uu, up. */
+
+ SetInitialProfile(data, uu, up, res);
+
+ /* Re-initialize IDA and IDASPGMR */
+
+ 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);
+
+ /* Print case number, output table heading, and initial line of table. */
+
+ printf("\n\nCase 2: gstype = CLASSICAL_GS\n");
+ printf("\n Output Summary (umax = max-norm of solution) \n\n");
+ printf(" time umax k nst nni nje nre nreLS h npe nps\n" );
+ printf("----------------------------------------------------------------------\n");
+
+ /* Loop over output times, call IDASolve, and print results. */
+
+ for (tout = t1,iout = 1; iout <= NOUT ; iout++, tout *= TWO) {
+ ier = IDASolve(mem, tout, &tret, uu, up, IDA_NORMAL);
+ if(check_flag(&ier, "IDASolve", 1)) return(1);
+ PrintOutput(mem, tret, uu);
+ }
+
+ /* Print remaining counters. */
+
+ ier = IDAGetNumErrTestFails(mem, &netf);
+ check_flag(&ier, "IDAGetNumErrTestFails", 1);
+
+ ier = IDAGetNumNonlinSolvConvFails(mem, &ncfn);
+ check_flag(&ier, "IDAGetNumNonlinSolvConvFails", 1);
+
+ ier = IDASpilsGetNumConvFails(mem, &ncfl);
+ check_flag(&ier, "IDASpilsGetNumConvFails", 1);
+
+ printf("\nError test failures = %ld\n", netf);
+ printf("Nonlinear convergence failures = %ld\n", ncfn);
+ printf("Linear convergence failures = %ld\n", ncfl);
+
+ /* Free Memory */
+
+ IDAFree(&mem);
+
+ N_VDestroy_Serial(uu);
+ N_VDestroy_Serial(up);
+ N_VDestroy_Serial(res);
+
+ N_VDestroy_Serial(data->pp);
+ free(data);
+
+ return(0);
+}
+
+/*
+ *--------------------------------------------------------------------
+ * FUNCTIONS CALLED BY IDA
+ *--------------------------------------------------------------------
+ */
+
+/*
+ * resHeat: heat equation system residual function (user-supplied)
+ * This uses 5-point central differencing on the interior points, and
+ * includes algebraic equations for the boundary values.
+ * So for each interior point, the residual component has the form
+ * res_i = u'_i - (central difference)_i
+ * while for each boundary point, it is res_i = u_i.
+ */
+
+int resHeat(realtype tt,
+ N_Vector uu, N_Vector up, N_Vector rr,
+ void *user_data)
+{
+ long int i, j, offset, loc, mm;
+ realtype *uu_data, *up_data, *rr_data, coeff, dif1, dif2;
+ UserData data;
+
+ uu_data = NV_DATA_S(uu);
+ up_data = NV_DATA_S(up);
+ rr_data = NV_DATA_S(rr);
+
+ data = (UserData) user_data;
+
+ coeff = data->coeff;
+ mm = data->mm;
+
+ /* Initialize rr to uu, to take care of boundary equations. */
+ N_VScale(ONE, uu, rr);
+
+ /* Loop over interior points; set res = up - (central difference). */
+ for (j = 1; j < MGRID-1; j++) {
+ offset = mm*j;
+ for (i = 1; i < mm-1; i++) {
+ loc = offset + i;
+ dif1 = uu_data[loc-1] + uu_data[loc+1] - TWO * uu_data[loc];
+ dif2 = uu_data[loc-mm] + uu_data[loc+mm] - TWO * uu_data[loc];
+ rr_data[loc]= up_data[loc] - coeff * ( dif1 + dif2 );
+ }
+ }
+
+ return(0);
+}
+
+/*
+ * PsetupHeat: setup for diagonal preconditioner for idaHeat2D_kry.
+ *
+ * The optional user-supplied functions PsetupHeat and
+ * PsolveHeat together must define the left preconditoner
+ * matrix P approximating the system Jacobian matrix
+ * J = dF/du + cj*dF/du'
+ * (where the DAE system is F(t,u,u') = 0), and solve the linear
+ * systems P z = r. This is done in this case by keeping only
+ * the diagonal elements of the J matrix above, storing them as
+ * inverses in a vector pp, when computed in PsetupHeat, for
+ * subsequent use in PsolveHeat.
+ *
+ * In this instance, only cj and data (user data structure, with
+ * pp etc.) are used from the PsetupdHeat argument list.
+ */
+
+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)
+{
+
+ long int i, j, offset, loc, mm;
+ realtype *ppv, pelinv;
+ UserData data;
+
+ data = (UserData) prec_data;
+ ppv = NV_DATA_S(data->pp);
+ mm = data->mm;
+
+ /* Initialize the entire vector to 1., then set the interior points to the
+ correct value for preconditioning. */
+ N_VConst(ONE,data->pp);
+
+ /* Compute the inverse of the preconditioner diagonal elements. */
+ pelinv = ONE/(c_j + FOUR*data->coeff);
+
+ for (j = 1; j < mm-1; j++) {
+ offset = mm * j;
+ for (i = 1; i < mm-1; i++) {
+ loc = offset + i;
+ ppv[loc] = pelinv;
+ }
+ }
+
+ return(0);
+}
+
+/*
+ * PsolveHeat: solve preconditioner linear system.
+ * This routine multiplies the input vector rvec by the vector pp
+ * containing the inverse diagonal Jacobian elements (previously
+ * computed in PrecondHeateq), 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 *prec_data,
+ N_Vector tmp)
+{
+ UserData data;
+ data = (UserData) prec_data;
+ N_VProd(data->pp, rvec, zvec);
+ return(0);
+}
+
+/*
+ *--------------------------------------------------------------------
+ * PRIVATE FUNCTIONS
+ *--------------------------------------------------------------------
+ */
+
+/*
+ * SetInitialProfile: routine to initialize u and up vectors.
+ */
+
+static int SetInitialProfile(UserData data, N_Vector uu, N_Vector up,
+ N_Vector res)
+{
+ long int mm, mm1, i, j, offset, loc;
+ realtype xfact, yfact, *udata, *updata;
+
+ mm = data->mm;
+
+ udata = NV_DATA_S(uu);
+ updata = NV_DATA_S(up);
+
+ /* Initialize uu on all grid points. */
+ mm1 = mm - 1;
+ for (j = 0; j < mm; j++) {
+ yfact = data->dx * j;
+ offset = mm*j;
+ for (i = 0;i < mm; i++) {
+ xfact = data->dx * i;
+ loc = offset + i;
+ udata[loc] = RCONST(16.0) * xfact * (ONE - xfact) * yfact * (ONE - yfact);
+ }
+ }
+
+ /* Initialize up vector to 0. */
+ N_VConst(ZERO, up);
+
+ /* resHeat sets res to negative of ODE RHS values at interior points. */
+ resHeat(ZERO, uu, up, res, data);
+
+ /* Copy -res into up to get correct interior initial up values. */
+ N_VScale(-ONE, res, up);
+
+ /* Set up at boundary points to zero. */
+ for (j = 0; j < mm; j++) {
+ offset = mm*j;
+ for (i = 0; i < mm; i++) {
+ loc = offset + i;
+ if (j == 0 || j == mm1 || i == 0 || i == mm1 ) updata[loc] = ZERO;
+ }
+ }
+
+ return(0);
+ }
+
+/*
+ * Print first lines of output (problem description)
+ */
+
+static void PrintHeader(realtype rtol, realtype atol)
+{
+ printf("\nidaHeat2D_kry: Heat equation, serial 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", MGRID, MGRID);
+ printf(" Total system size: %d\n\n", NEQ);
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("Tolerance parameters: rtol = %Lg atol = %Lg\n", rtol, atol);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("Tolerance parameters: rtol = %lg atol = %lg\n", rtol, atol);
+#else
+ 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");
+}
+
+/*
+ * PrintOutput: print max norm of solution and current solver statistics
+ */
+
+static void PrintOutput(void *mem, realtype t, N_Vector uu)
+{
+ realtype hused, umax;
+ long int nst, nni, nje, nre, nreLS, nli, npe, nps;
+ int kused, ier;
+
+ umax = N_VMaxNorm(uu);
+
+ ier = IDAGetLastOrder(mem, &kused);
+ check_flag(&ier, "IDAGetLastOrder", 1);
+ ier = IDAGetNumSteps(mem, &nst);
+ check_flag(&ier, "IDAGetNumSteps", 1);
+ ier = IDAGetNumNonlinSolvIters(mem, &nni);
+ check_flag(&ier, "IDAGetNumNonlinSolvIters", 1);
+ ier = IDAGetNumResEvals(mem, &nre);
+ check_flag(&ier, "IDAGetNumResEvals", 1);
+ ier = IDAGetLastStep(mem, &hused);
+ check_flag(&ier, "IDAGetLastStep", 1);
+ ier = IDASpilsGetNumJtimesEvals(mem, &nje);
+ check_flag(&ier, "IDASpilsGetNumJtimesEvals", 1);
+ ier = IDASpilsGetNumLinIters(mem, &nli);
+ check_flag(&ier, "IDASpilsGetNumLinIters", 1);
+ ier = IDASpilsGetNumResEvals(mem, &nreLS);
+ check_flag(&ier, "IDASpilsGetNumResEvals", 1);
+ ier = IDASpilsGetNumPrecEvals(mem, &npe);
+ check_flag(&ier, "IDASpilsGetPrecEvals", 1);
+ ier = IDASpilsGetNumPrecSolves(mem, &nps);
+ check_flag(&ier, "IDASpilsGetNumPrecSolves", 1);
+
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf(" %5.2Lf %13.5Le %d %3ld %3ld %3ld %4ld %4ld %9.2Le %3ld %3ld\n",
+ t, umax, kused, nst, nni, nje, nre, nreLS, hused, npe, nps);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf(" %5.2f %13.5le %d %3ld %3ld %3ld %4ld %4ld %9.2le %3ld %3ld\n",
+ t, umax, kused, nst, nni, nje, nre, nreLS, hused, npe, nps);
+#else
+ printf(" %5.2f %13.5e %d %3ld %3ld %3ld %4ld %4ld %9.2e %3ld %3ld\n",
+ t, umax, kused, nst, nni, nje, nre, nreLS, hused, npe, nps);
+#endif
+}
+
+/*
+ * 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, 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/idaHeat2D_kry.out b/examples/ida/serial/idaHeat2D_kry.out
new file mode 100644
index 0000000..fe7bde0
--- /dev/null
+++ b/examples/ida/serial/idaHeat2D_kry.out
@@ -0,0 +1,55 @@
+
+idaHeat2D_kry: Heat equation, serial 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
+
+Tolerance parameters: rtol = 0 atol = 0.001
+Constraints set to force all solution components >= 0.
+Linear solver: IDASPGMR, preconditioner using diagonal elements.
+
+
+Case 1: gsytpe = MODIFIED_GS
+
+ Output Summary (umax = max-norm of solution)
+
+ time umax k nst nni nje nre nreLS h npe nps
+----------------------------------------------------------------------
+ 0.01 8.24106e-01 2 12 14 7 14 7 2.56e-03 8 21
+ 0.02 6.88134e-01 3 15 18 12 18 12 5.12e-03 8 30
+ 0.04 4.70711e-01 3 18 24 21 24 21 6.58e-03 9 45
+ 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
+
+Error test failures = 1
+Nonlinear convergence failures = 0
+Linear convergence failures = 0
+
+
+Case 2: gstype = CLASSICAL_GS
+
+ Output Summary (umax = max-norm of solution)
+
+ time umax k nst nni nje nre nreLS h npe nps
+----------------------------------------------------------------------
+ 0.01 8.24106e-01 2 12 14 7 14 7 2.56e-03 8 21
+ 0.02 6.88134e-01 3 15 18 12 18 12 5.12e-03 8 30
+ 0.04 4.70711e-01 3 18 24 21 24 21 6.58e-03 9 45
+ 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 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
+
+Error test failures = 1
+Nonlinear convergence failures = 0
+Linear convergence failures = 0
diff --git a/examples/ida/serial/idaKrylovDemo_ls.c b/examples/ida/serial/idaKrylovDemo_ls.c
new file mode 100644
index 0000000..496b7f8
--- /dev/null
+++ b/examples/ida/serial/idaKrylovDemo_ls.c
@@ -0,0 +1,582 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.2 $
+ * $Date: 2009/09/30 23:25:59 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Allan Taylor, Alan Hindmarsh and
+ * Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ *
+ * This example loops through the available iterative linear solvers:
+ * SPGMR, SPBCG and SPTFQMR.
+ *
+ * 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.
+ *
+ * The DAE system solved is a spatial discretization of the PDE
+ * du/dt = d^2u/dx^2 + d^2u/dy^2
+ * on the unit square. The boundary condition is u = 0 on all edges.
+ * Initial conditions are given by u = 16 x (1 - x) y (1 - y). The
+ * PDE is treated with central differences on a uniform M x M grid.
+ * The values of u at the interior points satisfy ODEs, and
+ * equations u = 0 at the boundaries are appended, to form a DAE
+ * 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
+ * preconditioner uses the diagonal elements of the Jacobian only.
+ * Routines for preconditioning, required by IDASP*, 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>
+
+/* Problem Constants */
+
+#define NOUT 11
+#define MGRID 10
+#define NEQ MGRID*MGRID
+#define ZERO RCONST(0.0)
+#define ONE RCONST(1.0)
+#define TWO RCONST(2.0)
+#define FOUR RCONST(4.0)
+
+/* Linear Solver Loop Constants */
+
+#define USE_SPGMR 0
+#define USE_SPBCG 1
+#define USE_SPTFQMR 2
+
+/* User data type */
+
+typedef struct {
+ long int mm; /* number of grid points */
+ realtype dx;
+ realtype coeff;
+ N_Vector pp; /* vector of prec. diag. elements */
+} *UserData;
+
+/* Prototypes for functions called by IDA */
+
+int resHeat(realtype tres, N_Vector uu, N_Vector up,
+ N_Vector resval, void *user_data);
+
+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);
+
+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);
+
+/* Prototypes for private functions */
+
+static int SetInitialProfile(UserData data, N_Vector uu, N_Vector up,
+ N_Vector res);
+static void PrintHeader(realtype rtol, realtype atol, int linsolver);
+static void PrintOutput(void *mem, realtype t, N_Vector uu, int linsolver);
+static int check_flag(void *flagvalue, char *funcname, int opt);
+
+/*
+ *--------------------------------------------------------------------
+ * MAIN PROGRAM
+ *--------------------------------------------------------------------
+ */
+
+int main(void)
+{
+ void *mem;
+ UserData data;
+ N_Vector uu, up, constraints, res;
+ int ier, iout, linsolver;
+ realtype rtol, atol, t0, t1, tout, tret;
+ long int netf, ncfn, ncfl;
+
+ mem = NULL;
+ data = NULL;
+ uu = up = constraints = res = NULL;
+
+ /* Allocate N-vectors and the user data structure. */
+
+ uu = N_VNew_Serial(NEQ);
+ if(check_flag((void *)uu, "N_VNew_Serial", 0)) return(1);
+
+ up = N_VNew_Serial(NEQ);
+ if(check_flag((void *)up, "N_VNew_Serial", 0)) return(1);
+
+ res = N_VNew_Serial(NEQ);
+ 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);
+
+ data = (UserData) malloc(sizeof *data);
+ data->pp = NULL;
+ if(check_flag((void *)data, "malloc", 2)) return(1);
+
+ /* Assign parameters in the user data structure. */
+
+ data->mm = MGRID;
+ data->dx = ONE/(MGRID-ONE);
+ data->coeff = ONE/(data->dx * data->dx);
+ data->pp = N_VNew_Serial(NEQ);
+ if(check_flag((void *)data->pp, "N_VNew_Serial", 0)) return(1);
+
+ /* Initialize uu, up. */
+
+ SetInitialProfile(data, uu, up, res);
+
+ /* Set constraints to all 1's for nonnegative solution values. */
+
+ N_VConst(ONE, constraints);
+
+ /* Assign various parameters. */
+
+ t0 = ZERO;
+ t1 = RCONST(0.01);
+ rtol = ZERO;
+ atol = RCONST(1.0e-3);
+
+ /* Call IDACreate and IDAMalloc to initialize solution */
+
+ mem = IDACreate();
+ if(check_flag((void *)mem, "IDACreate", 0)) return(1);
+
+ ier = IDASetUserData(mem, data);
+ if(check_flag(&ier, "IDASetUserData", 1)) return(1);
+
+ ier = IDASetConstraints(mem, constraints);
+ if(check_flag(&ier, "IDASetConstraints", 1)) return(1);
+ N_VDestroy_Serial(constraints);
+
+ ier = IDAInit(mem, resHeat, t0, uu, up);
+ if(check_flag(&ier, "IDAInit", 1)) return(1);
+
+ ier = IDASStolerances(mem, rtol, atol);
+ if(check_flag(&ier, "IDASStolerances", 1)) return(1);
+
+ /* START: Loop through SPGMR, SPBCG and SPTFQMR linear solver modules */
+ for (linsolver = 0; linsolver < 3; ++linsolver) {
+
+ if (linsolver != 0) {
+
+ /* Re-initialize uu, up. */
+ SetInitialProfile(data, uu, up, res);
+
+ /* Re-initialize IDA */
+ ier = IDAReInit(mem, t0, uu, up);
+ if (check_flag(&ier, "IDAReInit", 1)) return(1);
+
+ }
+
+ /* Attach a linear solver module */
+ switch(linsolver) {
+
+ /* (a) SPGMR */
+ case(USE_SPGMR):
+
+ /* Print header */
+ printf(" -------");
+ 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);
+
+ break;
+
+ /* (b) SPBCG */
+ case(USE_SPBCG):
+
+ /* Print header */
+ printf(" -------");
+ printf(" \n| SPBCG |\n");
+ printf(" -------\n");
+
+ /* Call IDASpbcg to specify the linear solver. */
+ ier = IDASpbcg(mem, 0);
+ if(check_flag(&ier, "IDASpbcg", 1)) return(1);
+
+ break;
+
+ /* (c) SPTFQMR */
+ case(USE_SPTFQMR):
+
+ /* Print header */
+ printf(" ---------");
+ 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);
+
+ break;
+
+ }
+
+ /* Specify preconditioner */
+ ier = IDASpilsSetPreconditioner(mem, PsetupHeat, PsolveHeat);
+ if(check_flag(&ier, "IDASpilsSetPreconditioner", 1)) return(1);
+
+ /* Print output heading. */
+ PrintHeader(rtol, atol, linsolver);
+
+ /* Print output table heading, and initial line of table. */
+
+ printf("\n Output Summary (umax = max-norm of solution) \n\n");
+ printf(" time umax k nst nni nje nre nreLS h npe nps\n" );
+ printf("----------------------------------------------------------------------\n");
+
+ /* Loop over output times, call IDASolve, and print results. */
+
+ for (tout = t1,iout = 1; iout <= NOUT ; iout++, tout *= TWO) {
+ ier = IDASolve(mem, tout, &tret, uu, up, IDA_NORMAL);
+ if(check_flag(&ier, "IDASolve", 1)) return(1);
+ PrintOutput(mem, tret, uu, linsolver);
+ }
+
+ /* Print remaining counters. */
+ ier = IDAGetNumErrTestFails(mem, &netf);
+ check_flag(&ier, "IDAGetNumErrTestFails", 1);
+
+ ier = IDAGetNumNonlinSolvConvFails(mem, &ncfn);
+ check_flag(&ier, "IDAGetNumNonlinSolvConvFails", 1);
+
+ ier = IDASpilsGetNumConvFails(mem, &ncfl);
+ check_flag(&ier, "IDASpilsGetNumConvFails", 1);
+
+ printf("\nError test failures = %ld\n", netf);
+ printf("Nonlinear convergence failures = %ld\n", ncfn);
+ printf("Linear convergence failures = %ld\n", ncfl);
+
+ if (linsolver < 2)
+ printf("\n======================================================================\n\n");
+
+ } /* END: Loop through SPGMR, SPBCG and SPTFQMR linear solver modules */
+
+ /* Free Memory */
+
+ IDAFree(&mem);
+
+ N_VDestroy_Serial(uu);
+ N_VDestroy_Serial(up);
+ N_VDestroy_Serial(res);
+
+ N_VDestroy_Serial(data->pp);
+ free(data);
+
+ return(0);
+}
+
+/*
+ *--------------------------------------------------------------------
+ * FUNCTIONS CALLED BY IDA
+ *--------------------------------------------------------------------
+ */
+
+/*
+ * resHeat: heat equation system residual function (user-supplied)
+ * This uses 5-point central differencing on the interior points, and
+ * includes algebraic equations for the boundary values.
+ * So for each interior point, the residual component has the form
+ * res_i = u'_i - (central difference)_i
+ * while for each boundary point, it is res_i = u_i.
+ */
+
+int resHeat(realtype tt,
+ N_Vector uu, N_Vector up, N_Vector rr,
+ void *user_data)
+{
+ long int i, j, offset, loc, mm;
+ realtype *uu_data, *up_data, *rr_data, coeff, dif1, dif2;
+ UserData data;
+
+ uu_data = NV_DATA_S(uu);
+ up_data = NV_DATA_S(up);
+ rr_data = NV_DATA_S(rr);
+
+ data = (UserData) user_data;
+
+ coeff = data->coeff;
+ mm = data->mm;
+
+ /* Initialize rr to uu, to take care of boundary equations. */
+ N_VScale(ONE, uu, rr);
+
+ /* Loop over interior points; set res = up - (central difference). */
+ for (j = 1; j < MGRID-1; j++) {
+ offset = mm*j;
+ for (i = 1; i < mm-1; i++) {
+ loc = offset + i;
+ dif1 = uu_data[loc-1] + uu_data[loc+1] - TWO * uu_data[loc];
+ dif2 = uu_data[loc-mm] + uu_data[loc+mm] - TWO * uu_data[loc];
+ rr_data[loc]= up_data[loc] - coeff * ( dif1 + dif2 );
+ }
+ }
+
+ return(0);
+}
+
+/*
+ * PsetupHeat: setup for diagonal preconditioner.
+ *
+ * The optional user-supplied functions PsetupHeat and
+ * PsolveHeat together must define the left preconditoner
+ * matrix P approximating the system Jacobian matrix
+ * J = dF/du + cj*dF/du'
+ * (where the DAE system is F(t,u,u') = 0), and solve the linear
+ * systems P z = r. This is done in this case by keeping only
+ * the diagonal elements of the J matrix above, storing them as
+ * inverses in a vector pp, when computed in PsetupHeat, for
+ * subsequent use in PsolveHeat.
+ *
+ * In this instance, only cj and data (user data structure, with
+ * pp etc.) are used from the PsetupdHeat argument list.
+ */
+
+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)
+{
+
+ long int i, j, offset, loc, mm;
+ realtype *ppv, pelinv;
+ UserData data;
+
+ data = (UserData) user_data;
+ ppv = NV_DATA_S(data->pp);
+ mm = data->mm;
+
+ /* Initialize the entire vector to 1., then set the interior points to the
+ correct value for preconditioning. */
+ N_VConst(ONE,data->pp);
+
+ /* Compute the inverse of the preconditioner diagonal elements. */
+ pelinv = ONE/(c_j + FOUR*data->coeff);
+
+ for (j = 1; j < mm-1; j++) {
+ offset = mm * j;
+ for (i = 1; i < mm-1; i++) {
+ loc = offset + i;
+ ppv[loc] = pelinv;
+ }
+ }
+
+ return(0);
+}
+
+/*
+ * PsolveHeat: solve preconditioner linear system.
+ * This routine multiplies the input vector rvec by the vector pp
+ * containing the inverse diagonal Jacobian elements (previously
+ * computed in PrecondHeateq), 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)
+{
+ UserData data;
+ data = (UserData) user_data;
+ N_VProd(data->pp, rvec, zvec);
+ return(0);
+}
+
+/*
+ *--------------------------------------------------------------------
+ * PRIVATE FUNCTIONS
+ *--------------------------------------------------------------------
+ */
+
+/*
+ * SetInitialProfile: routine to initialize u and up vectors.
+ */
+
+static int SetInitialProfile(UserData data, N_Vector uu, N_Vector up,
+ N_Vector res)
+{
+ long int mm, mm1, i, j, offset, loc;
+ realtype xfact, yfact, *udata, *updata;
+
+ mm = data->mm;
+
+ udata = NV_DATA_S(uu);
+ updata = NV_DATA_S(up);
+
+ /* Initialize uu on all grid points. */
+ mm1 = mm - 1;
+ for (j = 0; j < mm; j++) {
+ yfact = data->dx * j;
+ offset = mm*j;
+ for (i = 0;i < mm; i++) {
+ xfact = data->dx * i;
+ loc = offset + i;
+ udata[loc] = RCONST(16.0) * xfact * (ONE - xfact) * yfact * (ONE - yfact);
+ }
+ }
+
+ /* Initialize up vector to 0. */
+ N_VConst(ZERO, up);
+
+ /* resHeat sets res to negative of ODE RHS values at interior points. */
+ resHeat(ZERO, uu, up, res, data);
+
+ /* Copy -res into up to get correct interior initial up values. */
+ N_VScale(-ONE, res, up);
+
+ /* Set up at boundary points to zero. */
+ for (j = 0; j < mm; j++) {
+ offset = mm*j;
+ for (i = 0; i < mm; i++) {
+ loc = offset + i;
+ if (j == 0 || j == mm1 || i == 0 || i == mm1 ) updata[loc] = ZERO;
+ }
+ }
+
+ return(0);
+ }
+
+/*
+ * Print first lines of output (problem description)
+ */
+
+static void PrintHeader(realtype rtol, realtype atol, int linsolver)
+{
+ printf("\nidaKrylovDemo_ls: Heat equation, serial 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", MGRID, MGRID);
+ printf(" Total system size: %d\n\n", NEQ);
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("Tolerance parameters: rtol = %Lg atol = %Lg\n", rtol, atol);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("Tolerance parameters: rtol = %lg atol = %lg\n", rtol, atol);
+#else
+ printf("Tolerance parameters: rtol = %g atol = %g\n", rtol, atol);
+#endif
+ printf("Constraints set to force all solution components >= 0. \n");
+
+ switch(linsolver) {
+
+ case(USE_SPGMR):
+ printf("Linear solver: IDASPGMR, preconditioner using diagonal elements. \n");
+ break;
+
+ case(USE_SPBCG):
+ printf("Linear solver: IDASPBCG, preconditioner using diagonal elements. \n");
+ break;
+
+ case(USE_SPTFQMR):
+ printf("Linear solver: IDASPTFQMR, preconditioner using diagonal elements. \n");
+ break;
+ }
+}
+
+/*
+ * PrintOutput: print max norm of solution and current solver statistics
+ */
+
+static void PrintOutput(void *mem, realtype t, N_Vector uu, int linsolver)
+{
+ realtype hused, umax;
+ long int nst, nni, nje, nre, nreLS, nli, npe, nps;
+ int kused, ier;
+
+ umax = N_VMaxNorm(uu);
+
+ ier = IDAGetLastOrder(mem, &kused);
+ check_flag(&ier, "IDAGetLastOrder", 1);
+ ier = IDAGetNumSteps(mem, &nst);
+ check_flag(&ier, "IDAGetNumSteps", 1);
+ ier = IDAGetNumNonlinSolvIters(mem, &nni);
+ check_flag(&ier, "IDAGetNumNonlinSolvIters", 1);
+ ier = IDAGetNumResEvals(mem, &nre);
+ check_flag(&ier, "IDAGetNumResEvals", 1);
+ ier = IDAGetLastStep(mem, &hused);
+ check_flag(&ier, "IDAGetLastStep", 1);
+
+ ier = IDASpilsGetNumJtimesEvals(mem, &nje);
+ check_flag(&ier, "IDASpilsGetNumJtimesEvals", 1);
+ ier = IDASpilsGetNumLinIters(mem, &nli);
+ check_flag(&ier, "IDASpilsGetNumLinIters", 1);
+ ier = IDASpilsGetNumResEvals(mem, &nreLS);
+ check_flag(&ier, "IDASpilsGetNumResEvals", 1);
+ ier = IDASpilsGetNumPrecEvals(mem, &npe);
+ check_flag(&ier, "IDASpilsGetPrecEvals", 1);
+ ier = IDASpilsGetNumPrecSolves(mem, &nps);
+ check_flag(&ier, "IDASpilsGetNumPrecSolves", 1);
+
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf(" %5.2Lf %13.5Le %d %3ld %3ld %3ld %4ld %4ld %9.2Le %3ld %3ld\n",
+ t, umax, kused, nst, nni, nje, nre, nreLS, hused, npe, nps);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf(" %5.2f %13.5le %d %3ld %3ld %3ld %4ld %4ld %9.2le %3ld %3ld\n",
+ t, umax, kused, nst, nni, nje, nre, nreLS, hused, npe, nps);
+#else
+ printf(" %5.2f %13.5e %d %3ld %3ld %3ld %4ld %4ld %9.2e %3ld %3ld\n",
+ t, umax, kused, nst, nni, nje, nre, nreLS, hused, npe, nps);
+#endif
+}
+
+/*
+ * 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, 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/idaKrylovDemo_ls.out b/examples/ida/serial/idaKrylovDemo_ls.out
new file mode 100644
index 0000000..01ad81a
--- /dev/null
+++ b/examples/ida/serial/idaKrylovDemo_ls.out
@@ -0,0 +1,102 @@
+ -------
+| SPGMR |
+ -------
+
+idaKrylovDemo_ls: Heat equation, serial 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
+
+Tolerance parameters: rtol = 0 atol = 0.001
+Constraints set to force all solution components >= 0.
+Linear solver: IDASPGMR, preconditioner using diagonal elements.
+
+ Output Summary (umax = max-norm of solution)
+
+ time umax k nst nni nje nre nreLS h npe nps
+----------------------------------------------------------------------
+ 0.01 8.24106e-01 2 12 14 7 14 7 2.56e-03 8 21
+ 0.02 6.88134e-01 3 15 18 12 18 12 5.12e-03 8 30
+ 0.04 4.70711e-01 3 18 24 21 24 21 6.58e-03 9 45
+ 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
+
+Error test failures = 1
+Nonlinear convergence failures = 0
+Linear convergence failures = 0
+
+======================================================================
+
+ -------
+| SPBCG |
+ -------
+
+idaKrylovDemo_ls: Heat equation, serial 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
+
+Tolerance parameters: rtol = 0 atol = 0.001
+Constraints set to force all solution components >= 0.
+Linear solver: IDASPBCG, preconditioner using diagonal elements.
+
+ Output Summary (umax = max-norm of solution)
+
+ time umax k nst nni nje nre nreLS h npe nps
+----------------------------------------------------------------------
+ 0.01 8.24105e-01 2 12 14 8 14 8 2.56e-03 8 22
+ 0.02 6.88129e-01 3 15 18 14 18 14 5.12e-03 8 32
+ 0.04 4.70820e-01 3 19 23 22 23 22 1.02e-02 9 45
+ 0.08 2.16332e-01 3 23 27 32 27 32 1.02e-02 9 59
+ 0.16 4.48774e-02 4 27 33 44 33 44 2.05e-02 10 77
+ 0.32 1.75557e-03 3 33 41 70 41 70 4.10e-02 11 111
+ 0.64 2.47770e-05 1 38 48 82 48 82 1.64e-01 13 130
+ 1.28 2.57209e-22 1 40 50 82 50 82 6.55e-01 15 132
+ 2.56 3.19445e-22 1 41 51 82 51 82 1.31e+00 16 133
+ 5.12 7.19965e-22 1 42 52 82 52 82 2.62e+00 17 134
+ 10.24 1.87591e-21 1 43 53 82 53 82 5.24e+00 18 135
+
+Error test failures = 0
+Nonlinear convergence failures = 0
+Linear convergence failures = 0
+
+======================================================================
+
+ ---------
+| SPTFQMR |
+ ---------
+
+idaKrylovDemo_ls: Heat equation, serial 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
+
+Tolerance parameters: rtol = 0 atol = 0.001
+Constraints set to force all solution components >= 0.
+Linear solver: IDASPTFQMR, preconditioner using diagonal elements.
+
+ Output Summary (umax = max-norm of solution)
+
+ time umax k nst nni nje nre nreLS h npe nps
+----------------------------------------------------------------------
+ 0.01 8.24104e-01 2 12 14 11 14 11 2.56e-03 8 28
+ 0.02 6.88133e-01 3 15 18 19 18 19 5.12e-03 8 42
+ 0.04 4.70857e-01 3 19 23 33 23 33 1.02e-02 9 64
+ 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
+
+Error test failures = 0
+Nonlinear convergence failures = 0
+Linear convergence failures = 0
diff --git a/examples/ida/serial/idaRoberts_dns.c b/examples/ida/serial/idaRoberts_dns.c
new file mode 100644
index 0000000..6cd1670
--- /dev/null
+++ b/examples/ida/serial/idaRoberts_dns.c
@@ -0,0 +1,404 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.4 $
+ * $Date: 2010/12/01 23:02:23 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Allan Taylor, Alan Hindmarsh and
+ * Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * This simple example problem for IDA, due to Robertson,
+ * is from chemical kinetics, and consists of the following three
+ * equations:
+ *
+ * dy1/dt = -.04*y1 + 1.e4*y2*y3
+ * dy2/dt = .04*y1 - 1.e4*y2*y3 - 3.e7*y2**2
+ * 0 = y1 + y2 + y3 - 1
+ *
+ * on the interval from t = 0.0 to t = 4.e10, with initial
+ * conditions: y1 = 1, y2 = y3 = 0.
+ *
+ * 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.
+ *
+ * The problem is solved with IDA using IDADENSE for the 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>
+
+/* Problem Constants */
+
+#define NEQ 3
+#define NOUT 12
+
+#define ZERO RCONST(0.0);
+#define ONE RCONST(1.0);
+
+/* Macro to define dense matrix elements, indexed from 1. */
+
+#define IJth(A,i,j) DENSE_ELEM(A,i-1,j-1)
+
+/* Prototypes of functions called by IDA */
+
+int resrob(realtype tres, N_Vector yy, N_Vector yp,
+ N_Vector resval, void *user_data);
+
+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,
+ N_Vector yy, N_Vector yp, N_Vector resvec,
+ DlsMat JJ, void *user_data,
+ N_Vector tempv1, N_Vector tempv2, N_Vector tempv3);
+
+/* Prototypes of private functions */
+static void PrintHeader(realtype rtol, N_Vector avtol, N_Vector y);
+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, char *funcname, int opt);
+
+/*
+ *--------------------------------------------------------------------
+ * Main Program
+ *--------------------------------------------------------------------
+ */
+
+int main(void)
+{
+ void *mem;
+ N_Vector yy, yp, avtol;
+ realtype rtol, *yval, *ypval, *atval;
+ realtype t0, tout1, tout, tret;
+ int iout, retval, retvalr;
+ int rootsfound[2];
+
+ mem = NULL;
+ yy = yp = avtol = NULL;
+ yval = ypval = atval = NULL;
+
+ /* Allocate N-vectors. */
+ yy = N_VNew_Serial(NEQ);
+ if(check_flag((void *)yy, "N_VNew_Serial", 0)) return(1);
+ yp = N_VNew_Serial(NEQ);
+ if(check_flag((void *)yp, "N_VNew_Serial", 0)) return(1);
+ avtol = N_VNew_Serial(NEQ);
+ if(check_flag((void *)avtol, "N_VNew_Serial", 0)) return(1);
+
+ /* Create and initialize y, y', and absolute tolerance vectors. */
+ yval = NV_DATA_S(yy);
+ yval[0] = ONE;
+ yval[1] = ZERO;
+ yval[2] = ZERO;
+
+ ypval = NV_DATA_S(yp);
+ ypval[0] = RCONST(-0.04);
+ ypval[1] = RCONST(0.04);
+ ypval[2] = ZERO;
+
+ rtol = RCONST(1.0e-4);
+
+ atval = NV_DATA_S(avtol);
+ atval[0] = RCONST(1.0e-8);
+ atval[1] = RCONST(1.0e-14);
+ atval[2] = RCONST(1.0e-6);
+
+ /* Integration limits */
+ t0 = ZERO;
+ tout1 = RCONST(0.4);
+
+ PrintHeader(rtol, avtol, yy);
+
+ /* 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);
+
+ /* 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) {
+
+ retval = IDASolve(mem, tout, &tret, yy, yp, IDA_NORMAL);
+
+ PrintOutput(mem,tret,yy);
+
+ if(check_flag(&retval, "IDASolve", 1)) return(1);
+
+ if (retval == IDA_ROOT_RETURN) {
+ retvalr = IDAGetRootInfo(mem, rootsfound);
+ check_flag(&retvalr, "IDAGetRootInfo", 1);
+ PrintRootInfo(rootsfound[0],rootsfound[1]);
+ }
+
+ if (retval == IDA_SUCCESS) {
+ iout++;
+ tout *= RCONST(10.0);
+ }
+
+ if (iout == NOUT) break;
+ }
+
+ PrintFinalStats(mem);
+
+ /* Free memory */
+
+ IDAFree(&mem);
+ N_VDestroy_Serial(yy);
+ N_VDestroy_Serial(yp);
+
+ return(0);
+
+}
+
+/*
+ *--------------------------------------------------------------------
+ * Functions called by IDA
+ *--------------------------------------------------------------------
+ */
+
+/*
+ * Define the system residual function.
+ */
+
+int resrob(realtype tres, N_Vector yy, N_Vector yp, N_Vector rr, void *user_data)
+{
+ realtype *yval, *ypval, *rval;
+
+ yval = NV_DATA_S(yy);
+ ypval = NV_DATA_S(yp);
+ rval = NV_DATA_S(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];
+ rval[0] -= ypval[0];
+ rval[2] = yval[0] + yval[1] + yval[2] - ONE;
+
+ return(0);
+}
+
+/*
+ * Root function routine. Compute functions g_i(t,y) for i = 0,1.
+ */
+
+static int grob(realtype t, N_Vector yy, N_Vector yp, realtype *gout,
+ void *user_data)
+{
+ realtype *yval, y1, y3;
+
+ yval = NV_DATA_S(yy);
+ y1 = yval[0]; y3 = yval[2];
+ gout[0] = y1 - RCONST(0.0001);
+ gout[1] = y3 - RCONST(0.01);
+
+ return(0);
+}
+
+/*
+ * Define the Jacobian function.
+ */
+
+int jacrob(long int Neq, realtype tt, realtype cj,
+ N_Vector yy, N_Vector yp, N_Vector resvec,
+ DlsMat JJ, void *user_data,
+ N_Vector tempv1, N_Vector tempv2, N_Vector tempv3)
+{
+ realtype *yval;
+
+ yval = NV_DATA_S(yy);
+
+ IJth(JJ,1,1) = RCONST(-0.04) - cj;
+ IJth(JJ,2,1) = RCONST(0.04);
+ IJth(JJ,3,1) = ONE;
+ IJth(JJ,1,2) = RCONST(1.0e4)*yval[2];
+ IJth(JJ,2,2) = RCONST(-1.0e4)*yval[2] - RCONST(6.0e7)*yval[1] - cj;
+ IJth(JJ,3,2) = ONE;
+ IJth(JJ,1,3) = RCONST(1.0e4)*yval[1];
+ IJth(JJ,2,3) = RCONST(-1.0e4)*yval[1];
+ IJth(JJ,3,3) = ONE;
+
+ return(0);
+}
+
+/*
+ *--------------------------------------------------------------------
+ * Private functions
+ *--------------------------------------------------------------------
+ */
+
+/*
+ * Print first lines of output (problem description)
+ */
+
+static void PrintHeader(realtype rtol, N_Vector avtol, N_Vector y)
+{
+ realtype *atval, *yval;
+
+ atval = NV_DATA_S(avtol);
+ yval = NV_DATA_S(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");
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("Tolerance parameters: rtol = %Lg atol = %Lg %Lg %Lg \n",
+ rtol, atval[0],atval[1],atval[2]);
+ printf("Initial conditions y0 = (%Lg %Lg %Lg)\n",
+ yval[0], yval[1], yval[2]);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("Tolerance parameters: rtol = %lg atol = %lg %lg %lg \n",
+ rtol, atval[0],atval[1],atval[2]);
+ printf("Initial conditions y0 = (%lg %lg %lg)\n",
+ yval[0], yval[1], yval[2]);
+#else
+ printf("Tolerance parameters: rtol = %g atol = %g %g %g \n",
+ rtol, atval[0],atval[1],atval[2]);
+ printf("Initial conditions y0 = (%g %g %g)\n",
+ yval[0], yval[1], yval[2]);
+#endif
+ printf("Constraints and id not used.\n\n");
+ printf("-----------------------------------------------------------------------\n");
+ printf(" t y1 y2 y3");
+ printf(" | nst k h\n");
+ printf("-----------------------------------------------------------------------\n");
+}
+
+/*
+ * Print Output
+ */
+
+static void PrintOutput(void *mem, realtype t, N_Vector y)
+{
+ realtype *yval;
+ int retval, kused;
+ long int nst;
+ realtype hused;
+
+ yval = NV_DATA_S(y);
+
+ retval = IDAGetLastOrder(mem, &kused);
+ check_flag(&retval, "IDAGetLastOrder", 1);
+ retval = IDAGetNumSteps(mem, &nst);
+ check_flag(&retval, "IDAGetNumSteps", 1);
+ retval = IDAGetLastStep(mem, &hused);
+ check_flag(&retval, "IDAGetLastStep", 1);
+#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);
+#elif defined(SUNDIALS_DOUBLE_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
+}
+
+static void PrintRootInfo(int root_f1, int root_f2)
+{
+ printf(" rootsfound[] = %3d %3d\n", root_f1, root_f2);
+ return;
+}
+
+/*
+ * Print final integrator statistics
+ */
+
+static void PrintFinalStats(void *mem)
+{
+ int retval;
+ long int nst, nni, nje, nre, nreLS, netf, ncfn, nge;
+
+ retval = IDAGetNumSteps(mem, &nst);
+ check_flag(&retval, "IDAGetNumSteps", 1);
+ retval = IDAGetNumResEvals(mem, &nre);
+ check_flag(&retval, "IDAGetNumResEvals", 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 = IDADlsGetNumResEvals(mem, &nreLS);
+ check_flag(&retval, "IDADlsGetNumResEvals", 1);
+ 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 Jacobian evaluations = %ld\n", nje);
+ printf("Number of nonlinear iterations = %ld\n", nni);
+ printf("Number of error test failures = %ld\n", netf);
+ printf("Number of nonlinear conv. failures = %ld\n", ncfn);
+ printf("Number of root fn. evaluations = %ld\n", nge);
+}
+
+/*
+ * 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, 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/idaRoberts_dns.out b/examples/ida/serial/idaRoberts_dns.out
new file mode 100644
index 0000000..04c1d91
--- /dev/null
+++ b/examples/ida/serial/idaRoberts_dns.out
@@ -0,0 +1,38 @@
+
+idaRoberts_dns: Robertson kinetics DAE serial example problem for IDA
+ Three equation chemical kinetics problem.
+
+Linear solver: IDADENSE, 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.
+
+-----------------------------------------------------------------------
+ t y1 y2 y3 | nst k h
+-----------------------------------------------------------------------
+2.6403e-01 9.8997e-01 3.4706e-05 1.0000e-02 | 85 2 6.4537e-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
+ 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
+
+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 nonlinear conv. failures = 0
+Number of root fn. evaluations = 624
diff --git a/examples/ida/serial/idaSlCrank_dns.c b/examples/ida/serial/idaSlCrank_dns.c
new file mode 100644
index 0000000..d379597
--- /dev/null
+++ b/examples/ida/serial/idaSlCrank_dns.c
@@ -0,0 +1,349 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.2 $
+ * $Date: 2009/09/30 23:25:59 $
+ * -----------------------------------------------------------------
+ * Programmer: Radu Serban @ 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 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>
+
+/* Problem Constants */
+
+#define NEQ 10
+
+#define TEND RCONST(10.0)
+#define NOUT 41
+
+
+#define ZERO RCONST(0.0)
+#define HALF RCONST(0.5)
+#define ONE RCONST(1.0)
+#define TWO RCONST(2.0)
+#define FOUR RCONST(4.0)
+
+typedef struct {
+ realtype a;
+ realtype J1, J2, m2;
+ realtype k, c, l0;
+ realtype F;
+} *UserData;
+
+int ressc(realtype tres, N_Vector yy, N_Vector yp,
+ N_Vector resval, void *user_data);
+
+void setIC(N_Vector yy, N_Vector yp, UserData data);
+void force(N_Vector yy, realtype *Q, UserData data);
+
+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);
+
+/*
+ *--------------------------------------------------------------------
+ * Main Program
+ *--------------------------------------------------------------------
+ */
+
+int main(void)
+{
+ UserData data;
+
+ void *mem;
+ N_Vector yy, yp, id;
+ realtype rtol, atol;
+ realtype t0, tf, tout, dt, tret;
+ int flag, iout;
+
+ /* User data */
+
+ data = (UserData) malloc(sizeof *data);
+
+ data->a = 0.5; /* half-length of crank */
+ data->J1 = 1.0; /* crank moment of inertia */
+ data->m2 = 1.0; /* mass of connecting rod */
+ data->J2 = 2.0; /* moment of inertia of connecting rod */
+ data->k = 1.0; /* spring constant */
+ data->c = 1.0; /* damper constant */
+ data->l0 = 1.0; /* spring free length */
+ data->F = 1.0; /* external constant force */
+
+ /* Create N_Vectors */
+ yy = N_VNew_Serial(NEQ);
+ yp = N_VNew_Serial(NEQ);
+ id = N_VNew_Serial(NEQ);
+
+ /* Consistent IC */
+ setIC(yy, yp, data);
+
+ /* ID array */
+ N_VConst(ONE, id);
+ NV_Ith_S(id,6) = ZERO;
+ NV_Ith_S(id,7) = ZERO;
+ NV_Ith_S(id,8) = ZERO;
+ NV_Ith_S(id,9) = ZERO;
+
+ /* Tolerances */
+ rtol = RCONST(1.0e-6);
+ atol = RCONST(1.0e-6);
+
+ /* Integration limits */
+ t0 = ZERO;
+ tf = TEND;
+ dt = (tf-t0)/(NOUT-1);
+
+ /* IDA initialization */
+ mem = IDACreate();
+ flag = IDAInit(mem, ressc, t0, yy, yp);
+ flag = IDASStolerances(mem, rtol, atol);
+ flag = IDASetUserData(mem, data);
+ flag = IDASetId(mem, id);
+ flag = IDASetSuppressAlg(mem, TRUE);
+
+ /* Call IDADense and set up the linear solver. */
+ flag = IDADense(mem, NEQ);
+
+ PrintHeader(rtol, atol, yy);
+
+ /* In loop, call IDASolve, print results, and test for error. */
+
+ PrintOutput(mem,t0,yy);
+
+ tout = dt;
+ for (iout=1; iout<NOUT; iout++) {
+ tout = iout*dt;
+ flag = IDASolve(mem, tout, &tret, yy, yp, IDA_NORMAL);
+ if (flag < 0) break;
+
+ PrintOutput(mem,tret,yy);
+
+ }
+
+ PrintFinalStats(mem);
+
+ /* Free memory */
+
+ free(data);
+ IDAFree(&mem);
+ N_VDestroy_Serial(yy);
+ N_VDestroy_Serial(yp);
+
+ return(0);
+
+}
+
+void setIC(N_Vector yy, N_Vector yp, UserData data)
+{
+ realtype pi;
+ realtype a, J1, m2, J2;
+ realtype q, p, x;
+ realtype Q[3];
+
+ N_VConst(ZERO, yy);
+ N_VConst(ZERO, yp);
+
+ pi = FOUR*atan(ONE);
+
+ a = data->a;
+ J1 = data->J1;
+ m2 = data->m2;
+ J2 = data->J2;
+
+ q = pi/TWO;
+ p = asin(-a);
+ x = cos(p);
+
+ NV_Ith_S(yy,0) = q;
+ NV_Ith_S(yy,1) = x;
+ NV_Ith_S(yy,2) = p;
+
+ force(yy, Q, data);
+
+ NV_Ith_S(yp,3) = Q[0]/J1;
+ NV_Ith_S(yp,4) = Q[1]/m2;
+ NV_Ith_S(yp,5) = Q[2]/J2;
+
+}
+
+void force(N_Vector yy, realtype *Q, UserData data)
+{
+ realtype a, k, c, l0, F;
+ realtype q, x, p;
+ realtype qd, xd, pd;
+ realtype s1, c1, s2, c2, s21, c21;
+ realtype l2, l, ld;
+ realtype f, fl;
+
+ a = data->a;
+ k = data->k;
+ c = data->c;
+ l0 = data->l0;
+ F = data->F;
+
+ q = NV_Ith_S(yy,0);
+ x = NV_Ith_S(yy,1);
+ p = NV_Ith_S(yy,2);
+
+ qd = NV_Ith_S(yy,3);
+ xd = NV_Ith_S(yy,4);
+ pd = NV_Ith_S(yy,5);
+
+ s1 = sin(q);
+ c1 = cos(q);
+ s2 = sin(p);
+ c2 = cos(p);
+ s21 = s2*c1 - c2*s1;
+ c21 = c2*c1 + s2*s1;
+
+ l2 = x*x - x*(c2+a*c1) + (ONE + a*a)/FOUR + a*c21/TWO;
+ l = RSqrt(l2);
+ ld = TWO*x*xd - xd*(c2+a*c1) + x*(s2*pd+a*s1*qd) - a*s21*(pd-qd)/TWO;
+ ld /= TWO*l;
+
+ f = k*(l-l0) + c*ld;
+ fl = f/l;
+
+ Q[0] = - fl * a * (s21/TWO + x*s1) / TWO;
+ Q[1] = fl * (c2/TWO - x + a*c1/TWO) + F;
+ Q[2] = - fl * (x*s2 - a*s21/TWO) / TWO - F*s2;
+
+}
+
+int ressc(realtype tres, N_Vector yy, N_Vector yp, N_Vector rr, void *user_data)
+{
+ UserData data;
+ realtype Q[3];
+ realtype a, J1, m2, J2;
+ realtype *yval, *ypval, *rval;
+ realtype q, x, p;
+ realtype qd, xd, pd;
+ realtype lam1, lam2, mu1, mu2;
+ realtype s1, c1, s2, c2;
+
+ data = (UserData) user_data;
+
+ a = data->a;
+ J1 = data->J1;
+ m2 = data->m2;
+ J2 = data->J2;
+
+ yval = NV_DATA_S(yy);
+ ypval = NV_DATA_S(yp);
+ rval = NV_DATA_S(rr);
+
+ q = yval[0];
+ x = yval[1];
+ p = yval[2];
+
+ qd = yval[3];
+ xd = yval[4];
+ pd = yval[5];
+
+ lam1 = yval[6];
+ lam2 = yval[7];
+
+ mu1 = yval[8];
+ mu2 = yval[9];
+
+ s1 = sin(q);
+ c1 = cos(q);
+ s2 = sin(p);
+ c2 = cos(p);
+
+ force(yy, Q, data);
+
+ rval[0] = ypval[0] - qd + a*s1*mu1 - a*c1*mu2;
+ rval[1] = ypval[1] - xd + mu1;
+ rval[2] = ypval[2] - pd + s2*mu1 - c2*mu2;
+
+ rval[3] = J1*ypval[3] - Q[0] + a*s1*lam1 - a*c1*lam2;
+ rval[4] = m2*ypval[4] - Q[1] + lam1;
+ rval[5] = J2*ypval[5] - Q[2] + s2*lam1 - c2*lam2;
+
+ rval[6] = x - c2 - a*c1;
+ rval[7] = -s2 - a*s1;
+
+ rval[8] = a*s1*qd + xd + s2*pd;
+ rval[9] = -a*c1*qd - c2*pd;
+
+ return(0);
+}
+
+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");
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("Tolerance parameters: rtol = %Lg atol = %Lg\n",
+ rtol, atol);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("Tolerance parameters: rtol = %lg atol = %lg\n",
+ rtol, atol);
+#else
+ printf("Tolerance parameters: rtol = %g atol = %g\n",
+ rtol, atol);
+#endif
+ printf("-----------------------------------------------------------------------\n");
+ printf(" t y1 y2 y3");
+ printf(" | nst k h\n");
+ printf("-----------------------------------------------------------------------\n");
+}
+
+static void PrintOutput(void *mem, realtype t, N_Vector y)
+{
+ realtype *yval;
+ int flag, kused;
+ long int nst;
+ realtype hused;
+
+ yval = NV_DATA_S(y);
+
+ flag = IDAGetLastOrder(mem, &kused);
+ flag = IDAGetNumSteps(mem, &nst);
+ flag = IDAGetLastStep(mem, &hused);
+
+ printf("%10.4le %12.4le %12.4le %12.4le %3ld %1d %12.4le\n",
+ t, yval[0], yval[1], yval[2], nst, kused, hused);
+}
+
+
+static void PrintFinalStats(void *mem)
+{
+ int flag;
+ long int nst, nni, nje, nre, nreLS, netf, ncfn;
+
+ flag = IDAGetNumSteps(mem, &nst);
+ flag = IDAGetNumResEvals(mem, &nre);
+ flag = IDADlsGetNumJacEvals(mem, &nje);
+ flag = IDAGetNumNonlinSolvIters(mem, &nni);
+ flag = IDAGetNumErrTestFails(mem, &netf);
+ flag = IDAGetNumNonlinSolvConvFails(mem, &ncfn);
+ flag = IDADlsGetNumResEvals(mem, &nreLS);
+
+ 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 Jacobian evaluations = %ld\n", nje);
+ printf("Number of nonlinear iterations = %ld\n", nni);
+ printf("Number of error test failures = %ld\n", netf);
+ printf("Number of nonlinear conv. failures = %ld\n", ncfn);
+}
+
diff --git a/examples/ida/serial/idaSlCrank_dns.out b/examples/ida/serial/idaSlCrank_dns.out
new file mode 100644
index 0000000..b79ec57
--- /dev/null
+++ b/examples/ida/serial/idaSlCrank_dns.out
@@ -0,0 +1,57 @@
+
+idaSlCrank_dns: Slider-Crank DAE serial example problem for IDAS
+Linear solver: IDADENSE, Jacobian is computed by IDAS.
+Tolerance parameters: rtol = 1e-06 atol = 1e-06
+-----------------------------------------------------------------------
+ t y1 y2 y3 | nst k h
+-----------------------------------------------------------------------
+0.0000e+00 1.5708e+00 8.6603e-01 -5.2360e-01 0 0 0.0000e+00
+2.5000e-01 1.5548e+00 8.7406e-01 -5.2352e-01 25 4 6.5436e-02
+5.0000e-01 1.5069e+00 8.9855e-01 -5.2242e-01 28 4 6.5436e-02
+7.5000e-01 1.4270e+00 9.4063e-01 -5.1765e-01 32 5 6.5436e-02
+1.0000e+00 1.3154e+00 1.0015e+00 -5.0497e-01 36 5 6.5436e-02
+1.2500e+00 1.1731e+00 1.0811e+00 -4.7909e-01 40 5 6.5436e-02
+1.5000e+00 1.0016e+00 1.1765e+00 -4.3472e-01 44 5 5.8893e-02
+1.7500e+00 8.0288e-01 1.2804e+00 -3.6792e-01 48 4 5.3003e-02
+2.0000e+00 5.7904e-01 1.3803e+00 -2.7715e-01 53 4 4.7703e-02
+2.2500e+00 3.3326e-01 1.4590e+00 -1.6430e-01 58 5 4.7703e-02
+2.5000e+00 7.2238e-02 1.4980e+00 -3.6096e-02 64 5 4.7703e-02
+2.7500e+00 -1.9245e-01 1.4862e+00 9.5777e-02 70 5 3.6885e-02
+3.0000e+00 -4.4711e-01 1.4272e+00 2.1790e-01 79 4 2.4398e-02
+3.2500e+00 -6.8090e-01 1.3377e+00 3.2019e-01 89 4 2.4398e-02
+3.5000e+00 -8.8750e-01 1.2374e+00 3.9819e-01 97 4 4.8796e-02
+3.7500e+00 -1.0634e+00 1.1424e+00 4.5228e-01 102 5 4.8796e-02
+4.0000e+00 -1.2064e+00 1.0623e+00 4.8609e-01 107 5 4.8796e-02
+4.2500e+00 -1.3150e+00 1.0017e+00 5.0491e-01 112 5 4.8796e-02
+4.5000e+00 -1.3883e+00 9.6149e-01 5.1404e-01 117 5 4.8796e-02
+4.7500e+00 -1.4265e+00 9.4088e-01 5.1761e-01 123 4 4.8796e-02
+5.0000e+00 -1.4300e+00 9.3903e-01 5.1790e-01 128 4 4.3916e-02
+5.2500e+00 -1.3992e+00 9.5560e-01 5.1514e-01 134 5 4.3916e-02
+5.5000e+00 -1.3346e+00 9.9087e-01 5.0765e-01 138 5 8.7832e-02
+5.7500e+00 -1.2371e+00 1.0451e+00 4.9204e-01 140 5 8.7832e-02
+6.0000e+00 -1.1080e+00 1.1176e+00 4.6386e-01 143 5 7.9049e-02
+6.2500e+00 -9.4916e-01 1.2048e+00 4.1858e-01 146 5 7.9049e-02
+6.5000e+00 -7.6277e-01 1.2999e+00 3.5273e-01 150 5 6.4030e-02
+6.7500e+00 -5.5125e-01 1.3910e+00 2.6497e-01 154 5 6.4030e-02
+7.0000e+00 -3.1828e-01 1.4626e+00 1.5711e-01 158 5 5.1864e-02
+7.2500e+00 -7.0713e-02 1.4981e+00 3.5334e-02 164 5 4.6678e-02
+7.5000e+00 1.8041e-01 1.4879e+00 -8.9839e-02 169 5 4.6678e-02
+7.7500e+00 4.2223e-01 1.4349e+00 -2.0636e-01 175 4 3.3481e-02
+8.0000e+00 6.4422e-01 1.3536e+00 -3.0500e-01 183 3 3.0133e-02
+8.2500e+00 8.3984e-01 1.2619e+00 -3.8145e-01 189 4 5.2811e-02
+8.5000e+00 1.0053e+00 1.1745e+00 -4.3582e-01 194 4 5.2811e-02
+8.7500e+00 1.1380e+00 1.1008e+00 -4.7113e-01 199 5 5.2811e-02
+9.0000e+00 1.2363e+00 1.0456e+00 -4.9189e-01 203 5 5.2811e-02
+9.2500e+00 1.2992e+00 1.0105e+00 -5.0257e-01 208 5 5.2811e-02
+9.5000e+00 1.3266e+00 9.9533e-01 -5.0655e-01 213 5 5.2811e-02
+9.7500e+00 1.3185e+00 9.9977e-01 -5.0542e-01 218 5 5.2811e-02
+1.0000e+01 1.2757e+00 1.0236e+00 -4.9881e-01 222 5 5.2811e-02
+
+Final Run Statistics:
+
+Number of steps = 222
+Number of residual evaluations = 874
+Number of Jacobian evaluations = 32
+Number of nonlinear iterations = 554
+Number of error test failures = 3
+Number of nonlinear conv. failures = 0
diff --git a/examples/idas/parallel/CMakeLists.txt b/examples/idas/parallel/CMakeLists.txt
new file mode 100644
index 0000000..b5d7d86
--- /dev/null
+++ b/examples/idas/parallel/CMakeLists.txt
@@ -0,0 +1,118 @@
+# ---------------------------------------------------------------
+# $Revision: 1.5 $
+# $Date: 2009/02/17 02:58:47 $
+# ---------------------------------------------------------------
+# Programmer: Radu Serban @ LLNL
+# ---------------------------------------------------------------
+# Copyright (c) 2007, The Regents of the University of California.
+# Produced at the Lawrence Livermore National Laboratory.
+# All rights reserved.
+# For details, see the LICENSE file.
+# ---------------------------------------------------------------
+# CMakeLists.txt file for IDAS parallel examples
+
+
+# Add variable IDAS_examples with the names of the parallel IDAS examples
+
+SET(IDAS_examples
+ idasBruss_ASAp_kry_bbd_p
+ idasBruss_FSA_kry_bbd_p
+ idasBruss_kry_bbd_p
+ idasFoodWeb_kry_bbd_p
+ idasFoodWeb_kry_p
+ idasHeat2D_FSA_kry_bbd_p
+ idasHeat2D_kry_bbd_p
+ idasHeat2D_kry_p
+ )
+
+# 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)
+ # add MPI_INCLUDE_PATH to include directories
+ INCLUDE_DIRECTORIES(${MPI_INCLUDE_PATH})
+ENDIF(MPI_MPICC)
+
+# 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")
+ SET(IDAS_LIB sundials_idas_shared)
+ SET(NVECP_LIB sundials_nvecparallel_shared)
+ENDIF(LINK_LIBRARY_TYPE MATCHES "static")
+
+# Set-up linker flags and link libraries
+
+SET(SUNDIALS_LIBS ${IDAS_LIB} ${NVECP_LIB} ${EXTRA_LINK_LIBS})
+IF(LAPACK_FOUND)
+ SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${LAPACK_LINKER_FLAGS}")
+ SET(SUNDIALS_LIBS "${SUNDIALS_LIBS} ${LAPACK_LIBRARIES}")
+ENDIF(LAPACK_FOUND)
+
+# Add the build and install targets for each IDAS example
+
+FOREACH(example ${IDAS_examples})
+ ADD_EXECUTABLE(${example} ${example}.c)
+ TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+ IF(NOT MPI_MPICC)
+ TARGET_LINK_LIBRARIES(${example} ${MPI_LIBRARY} ${MPI_EXTRA_LIBRARIES})
+ ENDIF(NOT MPI_MPICC)
+ IF(EXAMPLES_INSTALL)
+ INSTALL(FILES ${example}.c ${example}.out DESTINATION ${EXAMPLES_INSTALL_PATH}/idas/parallel)
+ ENDIF(EXAMPLES_INSTALL)
+ENDFOREACH(example ${IDAS_examples})
+
+IF(EXAMPLES_INSTALL)
+
+ # Install the README file
+ INSTALL(FILES README DESTINATION ${EXAMPLES_INSTALL_PATH}/idas/parallel)
+
+ # Prepare substitution variables for Makefile and/or CMakeLists templates
+ SET(SOLVER "IDAS")
+ SET(SOLVER_LIB "sundials_idas")
+ LIST2STRING(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
+ )
+
+ # install CMakelists.txt
+ INSTALL(
+ FILES ${PROJECT_BINARY_DIR}/examples/idas/parallel/CMakeLists.txt
+ 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
+ # 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/idas/parallel/Makefile_ex
+ @ONLY
+ )
+ # install the configured Makefile_ex as Makefile
+ INSTALL(
+ FILES ${PROJECT_BINARY_DIR}/examples/idas/parallel/Makefile_ex
+ DESTINATION ${EXAMPLES_INSTALL_PATH}/idas/parallel
+ RENAME Makefile
+ )
+ ENDIF(UNIX)
+
+ENDIF(EXAMPLES_INSTALL)
diff --git a/examples/idas/parallel/Makefile.in b/examples/idas/parallel/Makefile.in
new file mode 100644
index 0000000..1e4098b
--- /dev/null
+++ b/examples/idas/parallel/Makefile.in
@@ -0,0 +1,117 @@
+# -----------------------------------------------------------------
+# $Revision: 1.11 $
+# $Date: 2009/02/17 02:58:47 $
+# -----------------------------------------------------------------
+# Programmer(s): Radu Serban and Aaron Collier @ LLNL
+# -----------------------------------------------------------------
+# Copyright (c) 2002, The Regents of the University of California.
+# Produced at the Lawrence Livermore National Laboratory.
+# All rights reserved.
+# For details, see the LICENSE file.
+# -----------------------------------------------------------------
+# Makefile for IDA parallel examples
+#
+# @configure_input@
+# -----------------------------------------------------------------
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_builddir = @top_builddir@
+builddir = @builddir@
+abs_builddir = @abs_builddir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+includedir = @includedir@
+libdir = @libdir@
+
+INSTALL = @INSTALL@
+INSTALL_PROG = @INSTALL_PROGRAM@
+INSTALL_FILE = @INSTALL_DATA@
+
+LIBTOOL = @LIBTOOL@
+LIBTOOL_DEPS = @LIBTOOL_DEPS@
+
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CC = @CC@
+CFLAGS = @CFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+MPICC = @MPICC@
+MPI_INC_DIR = @MPI_INC_DIR@
+MPI_LIB_DIR = @MPI_LIB_DIR@
+MPI_LIBS = @MPI_LIBS@
+MPI_FLAGS = @MPI_FLAGS@
+
+BLAS_LAPACK_LIBS = @BLAS_LAPACK_LIBS@
+
+OBJ_EXT = @OBJEXT@
+EXE_EXT = @EXEEXT@
+
+EXS_INSTDIR = @EXS_INSTDIR@
+
+top_srcdir = $(srcdir)/../../..
+
+SUNDIALS_INCS = -I$(top_srcdir)/include -I$(top_builddir)/include
+
+SUNDIALS_LIBS = $(top_builddir)/src/idas/libsundials_idas.la $(top_builddir)/src/nvec_par/libsundials_nvecparallel.la
+
+mkinstalldirs = $(SHELL) $(top_srcdir)/config/mkinstalldirs
+rminstalldirs = $(SHELL) $(top_srcdir)/config/rminstalldirs
+
+EXAMPLES = idasBruss_ASAp_kry_bbd_p \
+ idasBruss_FSA_kry_bbd_p \
+ idasBruss_kry_bbd_p \
+ idasFoodWeb_kry_bbd_p \
+ idasFoodWeb_kry_p \
+ idasHeat2D_FSA_kry_bbd_p \
+ idasHeat2D_kry_bbd_p \
+ idasHeat2D_kry_p
+
+OBJECTS = ${EXAMPLES:=${OBJ_EXT}}
+EXECS = ${EXAMPLES:=${EXE_EXT}}
+
+# ----------------------------------------------------------------------------------------------------------------------
+
+all:
+ @for i in ${EXAMPLES} ; do \
+ $(LIBTOOL) --mode=compile $(MPICC) $(CPPFLAGS) $(MPI_FLAGS) $(SUNDIALS_INCS) -I$(MPI_INC_DIR) $(CFLAGS) -c $(srcdir)/$${i}.c -o $${i}${OBJ_EXT} ; \
+ $(LIBTOOL) --mode=link $(MPICC) -o $(builddir)/$${i}$(EXE_EXT) $(builddir)/$${i}$(OBJ_EXT) $(MPI_FLAGS) $(CFLAGS) $(LDFLAGS) $(SUNDIALS_LIBS) -L$(MPI_LIB_DIR) $(MPI_LIBS) $(LIBS) $(BLAS_LAPACK_LIBS) ; \
+ done
+
+install:
+ $(mkinstalldirs) $(EXS_INSTDIR)/idas/parallel
+ $(INSTALL_FILE) Makefile_ex $(EXS_INSTDIR)/idas/parallel/Makefile
+ $(INSTALL_FILE) $(top_srcdir)/examples/idas/parallel/README $(EXS_INSTDIR)/idas/parallel/
+ for i in ${EXAMPLES} ; do \
+ $(INSTALL_FILE) $(top_srcdir)/examples/idas/parallel/$${i}.c $(EXS_INSTDIR)/idas/parallel/ ; \
+ $(INSTALL_FILE) $(top_srcdir)/examples/idas/parallel/$${i}.out $(EXS_INSTDIR)/idas/parallel/ ; \
+ done
+
+uninstall:
+ rm -f $(EXS_INSTDIR)/idas/parallel/Makefile
+ rm -f $(EXS_INSTDIR)/idas/parallel/README
+ for i in ${EXAMPLES} ; do \
+ rm -f $(EXS_INSTDIR)/idas/parallel/$${i}.c ; \
+ rm -f $(EXS_INSTDIR)/idas/parallel/$${i}.out ; \
+ done
+ $(rminstalldirs) $(EXS_INSTDIR)/idas/parallel
+ $(rminstalldirs) $(EXS_INSTDIR)/idas
+
+clean:
+ rm -rf .libs
+ rm -f *.lo *.o
+ rm -f ${OBJECTS}
+ rm -f $(EXECS)
+
+distclean: clean
+ rm -f Makefile
+ rm -f Makefile_ex
+
+# ----------------------------------------------------------------------------------------------------------------------
+
+libtool: $(top_builddir)/$(LIBTOOL_DEPS)
+ @cd ${top_builddir} ; \
+ ${SHELL} ./config.status --recheck ; \
+ cd ${abs_builddir}
diff --git a/examples/idas/parallel/README b/examples/idas/parallel/README
new file mode 100644
index 0000000..ad6dc83
--- /dev/null
+++ b/examples/idas/parallel/README
@@ -0,0 +1,22 @@
+List of parallel IDAS examples
+
+ idasBruss_ASAp_kry_bbd_p : 2-D chemically reacting system, BBD preconditioner, ASA
+ idasBruss_FSA_kry_bbd_p : 2-D chemically reacting system, BBD preconditioner, FSA
+ idasBruss_kry_bbd_p : 2-D chemically reacting system, BBD preconditioner
+ idasFoodWeb_kry_bbd_p : 2-D food web, BBD preconditioner
+ idasFoodWeb_kry_p : 2-D food web, block-diagonal preconditioner
+ idasHeat2D_FSA_kry_bbd_p : 2-D heat equation, BBD preconditioner, FSA
+ idasHeat2D_kry_bbd_p : 2-D heat equation, BBD preconditioner
+ idasHeat2D_kry_p : 2-D heat equation, diagonal preconditioner
+
+Sample results:
+
+ SUNDIALS was built with the following options:
+
+ ./configure CC=gcc F77=gfortran CFLAGS="-g3 -O0" FFLAGS="-g3 -O0" --enable-examples
+
+ System Architecture: IA-32
+ Processor Type: Intel Pentium 4 Xeon DP (i686)
+ Operating System: Red Hat Enterprise Linux WS 3 (Taroon Update 7)
+ C/Fortran Compilers: gcc/gfortran v4.1.0
+ MPI Implementation: Open MPI v1.1
diff --git a/examples/idas/parallel/idasBruss_ASAp_kry_bbd_p.c b/examples/idas/parallel/idasBruss_ASAp_kry_bbd_p.c
new file mode 100644
index 0000000..f2d162a
--- /dev/null
+++ b/examples/idas/parallel/idasBruss_ASAp_kry_bbd_p.c
@@ -0,0 +1,1484 @@
+/* * -----------------------------------------------------------------
+ * $Revision:
+ * $Date:
+ * -----------------------------------------------------------------
+ * Programmer(s): 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.
+ * It is written for a parallel computer system and uses the
+ * IDABBDPRE band-block-diagonal preconditioner module for the
+ * IDASPGMR package.
+ *
+ * The mathematical problem solved in this example is a DAE system
+ * that arises from a system of partial differential equations after
+ * spatial discretization.
+ *
+ * The PDE system is a two-species time-dependent PDE known as
+ * Brusselator PDE and models a chemically reacting system.
+ *
+ *
+ * du/dt = eps(u + u) + u^2 v -(B+1)u + A
+ * xx yy
+ * domain Omega = [0,L]X[0,L]
+ * dv/dt = eps(v + v) - u^2 v + Bu
+ * xx yy
+ *
+ * B.C. : Neumann
+ * I.C : u(x,y,t0) = u0(x,y) = 1 - 0.5*cos(pi*y/L)
+ * v(x,y,t0) = v0(x,y) = 3.5 - 2.5*cos(pi*x/L)
+ *
+ * The PDEs are discretized by central differencing on a MX by MY
+ * mesh, and so the system size Neq is the product MX*MY*NUM_SPECIES.
+ * The system is actually implemented on submeshes, processor by
+ * processor, with an MXSUB by MYSUB mesh on each of NPEX * NPEY
+ * processors.
+ *
+ *
+ * The sensitivity of the output functional
+ * 1 /
+ * g(t) = ----- | u(x,y,t) ,
+ * |L^2| /
+ * Omega
+ * with respect to initial conditions u0 and v0 is also computed.
+ * Given the perturbations du0 and dv0 in the IC, the sensitivity of
+ * of g at final time tf is
+ * 1 /
+ * dg(tf) = ----- | ( lambda(0,x,y) du0(x,y) + mu(0,x,y) dv0(x,y) ),
+ * |L^2| /
+ * Omega
+ * where lambda and mu are the solutions of the adjoint PDEs:
+ *
+ * dl/dt = - eps(l + l) - (2uv - B - 1)l + (2uv - B)m
+ * xx yy
+ * domain Omega = [0,L]X[0,L]
+ * dm/dt = - eps(m + m) - u^2 l + u^2 m
+ * xx yy
+ * B.C. : Neumann
+ * I.C. : l(x,y,tf) = 1
+ * m(x,y,tf) = 0
+ *
+ * The adjoint PDEs are discretized and solved in the same way as
+ * the Brusselator PDEs.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+
+#include <idas/idas.h>
+#include <idas/idas_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>
+
+#include <mpi.h>
+
+/* Problem Constants */
+#define NUM_SPECIES 2
+#define ctL RCONST(1.0) /* Domain =[0,L]^2 */
+#define ctA RCONST(1.0)
+#define ctB RCONST(3.4)
+#define ctEps RCONST(2.0e-3)
+
+#define PI RCONST(3.1415926535898) /* pi */
+
+#define MXSUB 21 /* Number of x mesh points per processor subgrid */
+#define MYSUB 21 /* Number of y mesh points per processor subgrid */
+#define NPEX 2 /* Number of subgrids in the x direction */
+#define NPEY 2 /* Number of subgrids in the y direction */
+#define MX (MXSUB*NPEX) /* MX = number of x mesh points */
+#define MY (MYSUB*NPEY) /* MY = number of y mesh points */
+#define NSMXSUB (NUM_SPECIES * MXSUB)
+#define NEQ (NUM_SPECIES*MX*MY) /* Number of equations in system */
+
+#define RTOL RCONST(1.e-5) /* rtol tolerance */
+#define ATOL RCONST(1.e-5) /* atol tolerance */
+
+#define TBEGIN RCONST(0.0) /* Multiplier for tout values */
+#define TEND RCONST(1.0) /* Increment for tout values */
+
+#define STEPS 50
+
+#define ZERO RCONST(0.0)
+#define HALF RCONST(0.5)
+#define ONE RCONST(1.0)
+#define TWO RCONST(2.0)
+
+/* User-defined vector accessor macro IJ_Vptr. */
+
+/*
+ * IJ_Vptr is defined in order to express the underlying 3-d structure of the
+ * dependent variable vector from its underlying 1-d storage (an N_Vector).
+ * IJ_Vptr(vv,i,j) returns a pointer to the location in vv corresponding to
+ * species index is = 0, x-index ix = i, and y-index jy = j.
+ */
+
+#define IJ_Vptr(vv,i,j) (&NV_Ith_P(vv, (i)*NUM_SPECIES + (j)*NSMXSUB ))
+
+/* Type: UserData. Contains problem constants, preconditioner data, etc. */
+typedef struct {
+ int ns, thispe, npes, ixsub, jysub, npex, npey;
+ int mxsub, mysub, nsmxsub, nsmxsub2;
+ realtype A, B, L, eps[NUM_SPECIES];
+ realtype dx, dy;
+ realtype cox[NUM_SPECIES], coy[NUM_SPECIES];
+ realtype gridext[(MXSUB+2)*(MYSUB+2)*NUM_SPECIES];
+ realtype rhs[NUM_SPECIES];
+ MPI_Comm comm;
+ realtype rates[2];
+ long int 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 reslocal(long int 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);
+
+/* 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,
+ 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);
+
+/* ADJOINT */
+
+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,
+ N_Vector uv, N_Vector uvp,
+ N_Vector yyB, N_Vector ypB,
+ N_Vector res, void *user_dataB);
+
+/* Prototypes for private functions */
+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 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,
+ realtype rtol, realtype atol);
+
+static void PrintOutput(void *mem, N_Vector uv, realtype time,
+ UserData data, MPI_Comm comm);
+
+static void PrintSol(void* mem, N_Vector uv, N_Vector uvp, UserData data,
+ MPI_Comm comm);
+
+static void PrintAdjSol(N_Vector uvB, N_Vector uvpB, UserData data);
+
+static void PrintFinalStats(void *mem);
+
+static int check_flag(void *flagvalue, char *funcname, int opt, int id);
+
+/*
+ *--------------------------------------------------------------------
+ * MAIN PROGRAM
+ *--------------------------------------------------------------------
+ */
+
+int main(int argc, char *argv[])
+{
+ MPI_Comm comm;
+ void *mem;
+ UserData data;
+ long int 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;
+
+ int nckpnt, indexB;
+
+ uv = uvp = resid = id = NULL;
+ data = NULL;
+ mem = NULL;
+
+ /* Set communicator, and get processor number and total number of PE's. */
+
+ MPI_Init(&argc, &argv);
+ comm = MPI_COMM_WORLD;
+ MPI_Comm_rank(comm, &thispe);
+ MPI_Comm_size(comm, &npes);
+
+ if (npes != NPEX*NPEY) {
+ if (thispe == 0)
+ fprintf(stderr,
+ "\nMPI_ERROR(0): npes = %d not equal to NPEX*NPEY = %d\n",
+ npes, NPEX*NPEY);
+ MPI_Finalize();
+ return(1);
+ }
+
+ /* Set local length (local_N) and global length (SystemSize). */
+ local_N = MXSUB*MYSUB*NUM_SPECIES;
+ SystemSize = NEQ;
+
+ /* Set up user data block data. */
+ data = (UserData) malloc(sizeof *data);
+
+ InitUserData(data, thispe, npes, comm);
+
+ /* Create needed vectors, and load initial values.
+ The vector resid is used temporarily only. */
+ uv = N_VNew_Parallel(comm, local_N, SystemSize);
+ if(check_flag((void *)uv, "N_VNew_Parallel", 0, thispe)) MPI_Abort(comm, 1);
+
+ uvp = N_VNew_Parallel(comm, local_N, SystemSize);
+ if(check_flag((void *)uvp, "N_VNew_Parallel", 0, thispe)) MPI_Abort(comm, 1);
+
+ resid = N_VNew_Parallel(comm, local_N, SystemSize);
+ if(check_flag((void *)resid, "N_VNew_Parallel", 0, thispe)) MPI_Abort(comm, 1);
+
+ id = N_VNew_Parallel(comm, local_N, SystemSize);
+ if(check_flag((void *)id, "N_VNew_Parallel", 0, thispe)) MPI_Abort(comm, 1);
+
+ SetInitialProfiles(uv, uvp, id, resid, data);
+
+ res(ZERO, uv, uvp, resid, data);
+
+ /* Set remaining inputs to IDAS. */
+ t0 = ZERO;
+ rtol = RTOL;
+ atol = ATOL;
+
+ /* Call IDACreate and IDAInit to initialize solution */
+ mem = IDACreate();
+ if(check_flag((void *)mem, "IDACreate", 0, thispe)) MPI_Abort(comm, 1);
+
+ retval = IDASetUserData(mem, data);
+ if(check_flag(&retval, "IDASetUserData", 1, thispe)) MPI_Abort(comm, 1);
+
+ retval = IDASetId(mem, id);
+ if(check_flag(&retval, "IDASetId", 1, thispe)) MPI_Abort(comm, 1);
+
+ retval = IDAInit(mem, res, t0, uv, uvp);
+ if(check_flag(&retval, "IDAInit", 1, thispe)) MPI_Abort(comm, 1);
+
+ retval = IDASStolerances(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 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,
+ ZERO, reslocal, NULL);
+ if(check_flag(&retval, "IDABBDPrecInit", 1, thispe)) MPI_Abort(comm, 1);
+
+ /* Initialize adjoint module. */
+ retval = IDAAdjInit(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);
+ if(check_flag(&retval, "IDACalcIC", 1, thispe)) MPI_Abort(comm, 1);
+
+ if (thispe == 0) printf("\nStarting integration of the FORWARD problem\n\n");
+
+ /* On PE 0, print heading, basic parameters, initial values. */
+ if (thispe == 0) PrintHeader(SystemSize, maxl,
+ 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);
+ if(check_flag(&retval, "IDASolveF", 1, thispe)) MPI_Abort(comm, 1);
+
+
+ PrintOutput(mem, uv, tret, data, comm);
+
+ /* Print each PE's portion of the solution in a separate file. */
+ //PrintSol(mem, uv, uvp, data, comm);
+
+ /* On PE 0, print final set of statistics. */
+ if (thispe == 0) {
+ PrintFinalStats(mem);
+ }
+
+ /*******************************************************
+ * ADJOINT *
+ *******************************************************/
+ if (thispe == 0) printf("\n\t\t BACKWARD problem\n");
+
+ uvB = N_VNew_Parallel(comm, local_N, SystemSize);
+ uvpB = N_VNew_Parallel(comm, local_N, SystemSize);
+ residB = N_VNew_Parallel(comm, local_N, SystemSize);
+ qB = N_VNew_Parallel(comm, local_N, SystemSize);
+
+
+ retval = IDACreateB(mem, &indexB);
+
+ /*Get consistent IC */
+ SetInitialProfilesB(uv, uvp, uvB, uvpB, residB, data);
+
+ retval = IDAInitB(mem, indexB, resB, TEND, uvB, uvpB);
+ if(check_flag(&retval, "IDAInitB", 1, thispe)) MPI_Abort(comm, 1);
+
+ retval = IDASetUserDataB(mem, indexB, data);
+ if(check_flag(&retval, "IDASetUserDataB", 1, thispe)) MPI_Abort(comm, 1);
+
+ retval = IDASetIdB(mem, indexB, id);
+ if(check_flag(&retval, "IDASetIdBIDAInitB", 1, thispe)) MPI_Abort(comm, 1);
+
+ retval = IDASStolerancesB(mem, indexB, rtol, atol);
+ if(check_flag(&retval, "IDASStolerancesB", 1, thispe)) MPI_Abort(comm, 1);
+
+ /* Call IDASpgmr to specify the IDAS LINEAR SOLVER IDASPGMR */
+ maxl = 16;
+ retval = IDASpgmrB(mem, indexB, maxl);
+
+ mudq = mldq = NSMXSUB;
+ mukeep = mlkeep = 2;
+ retval = IDABBDPrecInitB(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);
+ if(check_flag(&retval, "IDASolveB", 1, thispe)) MPI_Abort(comm, 1);
+
+ retval = IDAGetB(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. */
+ /* PrintAdjSol(uvB, uvpB, data); */
+
+ /* On PE 0, print final set of statistics. */
+ if (thispe == 0) {
+ PrintFinalStats(IDAGetAdjIDABmem(mem, indexB));
+ }
+
+
+ /* Free memory. */
+ N_VDestroy_Parallel(uv);
+ N_VDestroy_Parallel(uvp);
+ N_VDestroy_Parallel(id);
+ N_VDestroy_Parallel(resid);
+ N_VDestroy_Parallel(uvB);
+ N_VDestroy_Parallel(uvpB);
+ N_VDestroy_Parallel(residB);
+
+ IDAFree(&mem);
+
+ free(data);
+
+ MPI_Finalize();
+
+ return(0);
+}
+
+/*
+ *--------------------------------------------------------------------
+ * PRIVATE FUNCTIONS
+ *--------------------------------------------------------------------
+ */
+
+/*
+ * InitUserData: Load problem constants in data (of type UserData).
+ */
+
+static void InitUserData(UserData data, int thispe, int npes,
+ MPI_Comm comm)
+{
+ data->jysub = thispe / NPEX;
+ data->ixsub = thispe - (data->jysub)*NPEX;
+ data->mxsub = MXSUB;
+ data->mysub = MYSUB;
+ data->npex = NPEX;
+ data->npey = NPEY;
+ data->ns = NUM_SPECIES;
+ data->dx = ctL/(MX-1);
+ data->dy = ctL/(MY-1);
+ data->thispe = thispe;
+ data->npes = npes;
+ data->nsmxsub = MXSUB * NUM_SPECIES;
+ 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;
+}
+
+/*
+ * SetInitialProfiles: Set initial conditions in uv, uvp, and id.
+ */
+
+static void SetInitialProfiles(N_Vector uv, N_Vector uvp, N_Vector id,
+ N_Vector resid, UserData data)
+{
+ int ixsub, jysub, mxsub, mysub, nsmxsub, ix, jy;
+ realtype *idxy, dx, dy, x, y, *uvxy, *uvxy1, L, npex, npey;
+
+ ixsub = data->ixsub;
+ jysub = data->jysub;
+ mxsub = data->mxsub;
+ mysub = data->mysub;
+ nsmxsub = data->nsmxsub;
+ npex = data->npex;
+ npey = data->npey;
+ dx = data->dx;
+ dy = data->dy;
+ L = data->L;
+
+ /* Loop over grid, load uv values and id values. */
+ for (jy = 0; jy < mysub; jy++) {
+ y = (jy + jysub*mysub) * dy;
+ for (ix = 0; ix < mxsub; ix++) {
+ x = (ix + ixsub*mxsub) * dx;
+ uvxy = IJ_Vptr(uv,ix,jy);
+
+ uvxy[0] = RCONST(1.0) - HALF*cos(PI*y/L);
+ uvxy[1] = RCONST(3.5) - RCONST(2.5)*cos(PI*x/L);
+ }
+ }
+
+ N_VConst(ONE, id);
+
+ if (jysub == 0) {
+ for (ix=0; ix<mxsub; ix++) {
+ idxy = IJ_Vptr(id,ix,0);
+ idxy[0] = idxy[1] = ZERO;
+
+ uvxy = IJ_Vptr(uv,ix,0);
+ uvxy1 = IJ_Vptr(uv,ix,1);
+ uvxy[0] = uvxy1[0];
+ uvxy[1] = uvxy1[1];
+ }
+ }
+
+ if (ixsub == npex-1) {
+ for (jy = 0; jy < mysub; jy++) {
+ idxy = IJ_Vptr(id,mxsub-1,jy);
+ idxy[0] = idxy[1] = ZERO;
+
+ uvxy = IJ_Vptr(uv,mxsub-1,jy);
+ uvxy1 = IJ_Vptr(uv,mxsub-2,jy);
+ uvxy[0] = uvxy1[0];
+ uvxy[1] = uvxy1[1];
+ }
+ }
+
+ if (ixsub == 0) {
+ for (jy = 0; jy < mysub; jy++) {
+ idxy = IJ_Vptr(id,0,jy);
+ idxy[0] = idxy[1] = ZERO;
+
+ uvxy = IJ_Vptr(uv,0,jy);
+ uvxy1 = IJ_Vptr(uv,1,jy);
+ uvxy[0] = uvxy1[0];
+ uvxy[1] = uvxy1[1];
+ }
+ }
+
+ if (jysub == npey-1) {
+ for (ix=0; ix<mxsub; ix++) {
+ idxy = IJ_Vptr(id,ix,jysub);
+ idxy[0] = idxy[1] = ZERO;
+
+ uvxy = IJ_Vptr(uv,ix,mysub-1);
+ uvxy1 = IJ_Vptr(uv,ix,mysub-2);
+ uvxy[0] = uvxy1[0];
+ uvxy[1] = uvxy1[1];
+ }
+ }
+
+ /* Derivative found by calling the residual function with uvp = 0. */
+ N_VConst(ZERO, uvp);
+ res(ZERO, uv, uvp, resid, data);
+ N_VScale(-ONE, resid, uvp);
+}
+
+/*
+ * SetInitialProfilesB: Set initial conditions in uvB, uvpB
+ */
+
+static void SetInitialProfilesB(N_Vector uv, N_Vector uvp,
+ N_Vector uvB, N_Vector uvpB,
+ N_Vector residB, UserData data)
+{
+ int ixsub, jysub, mxsub, mysub, nsmxsub, ix, jy;
+ realtype dx, dy, *uvxy, *uvBxy, *uvpBxy, npex, npey;
+ realtype B;
+
+ ixsub = data->ixsub;
+ jysub = data->jysub;
+ mxsub = data->mxsub;
+ mysub = data->mxsub;
+ nsmxsub = data->nsmxsub;
+ npex = data->npex;
+ npey = data->npey;
+ dx = data->dx;
+ dy = data->dy;
+ B = data->B;
+
+ /* Loop over grid, load (lambda, mu) values. */
+ for (jy = 0; jy < mysub; jy++) {
+ for (ix = 0; ix < mxsub; ix++) {
+ uvBxy = IJ_Vptr(uvB, ix,jy);
+ uvpBxy = IJ_Vptr(uvpB,ix,jy);
+
+ uvxy = IJ_Vptr(uv,ix,jy);
+
+ uvBxy[0] = ONE;
+ uvBxy[1] = ZERO;
+
+ uvpBxy[0] = -TWO*uvxy[0]*uvxy[1]+(B+1);
+ uvpBxy[1] = -uvxy[0]*uvxy[0];
+ }
+ }
+
+ if (jysub == 0) {
+ for (ix=0; ix<mxsub; ix++) {
+
+ uvBxy = IJ_Vptr(uvB,ix,0);
+ uvpBxy = IJ_Vptr(uvpB,ix,0);
+
+ uvpBxy[0] = uvpBxy[1] = ZERO;
+ }
+ }
+
+ if (ixsub == npex-1) {
+ for (jy = 0; jy < mysub; jy++) {
+
+ uvBxy = IJ_Vptr(uvB,mxsub-1,jy);
+ uvpBxy = IJ_Vptr(uvpB,mxsub-1,jy);
+
+ uvpBxy[0] = uvpBxy[1] = ZERO;
+ }
+ }
+
+ if (ixsub == 0) {
+ for (jy = 0; jy < mysub; jy++) {
+
+ uvBxy = IJ_Vptr(uvB,0,jy);
+ uvpBxy = IJ_Vptr(uvpB,0,jy);
+
+ uvpBxy[0] = uvpBxy[1] = ZERO;
+ }
+ }
+
+ if (jysub == npey-1) {
+ for (ix=0; ix<mxsub; ix++) {
+
+ uvBxy = IJ_Vptr(uvB,ix,mysub-1);
+ uvpBxy = IJ_Vptr(uvpB,ix,mysub-1);
+
+ uvpBxy[0] = uvpBxy[1] = ZERO;
+ }
+ }
+}
+
+
+/*
+ * Print first lines of output (problem description)
+ * and table headerr
+ */
+
+static void PrintHeader(int SystemSize, int maxl,
+ long int mudq, long int mldq,
+ long int mukeep, long int 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("Subgrid dimensions: %d x %d", MXSUB, MYSUB);
+ printf(" Processor array: %d x %d\n", NPEX, NPEY);
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("Tolerance parameters: rtol = %Lg atol = %Lg\n", rtol, atol);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("Tolerance parameters: rtol = %lg atol = %lg\n", rtol, atol);
+#else
+ printf("Tolerance parameters: rtol = %g atol = %g\n", rtol, atol);
+#endif
+ printf("Linear solver: IDASPGMR 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("-----------------------------------------------------------\n");
+ printf(" t bottom-left top-right");
+ printf(" | nst k h\n");
+ printf("-----------------------------------------------------------\n\n");
+}
+
+
+/*
+ * PrintOutput: Print output values at output time t = tt.
+ * Selected run statistics are printed. Then values of c1 and c2
+ * are printed for the bottom left and top right grid points only.
+ */
+
+static void PrintOutput(void *mem, N_Vector uv, realtype tt,
+ UserData data, MPI_Comm comm)
+{
+ MPI_Status status;
+ realtype *cdata, clast[2], hused;
+ long int nst;
+ int i, kused, flag, thispe, npelast, ilast;;
+
+ thispe = data->thispe;
+ npelast = data->npes - 1;
+ cdata = NV_DATA_P(uv);
+
+ /* Send conc. at top right mesh point from PE npes-1 to PE 0. */
+ if (thispe == npelast) {
+ ilast = NUM_SPECIES*MXSUB*MYSUB - 2;
+ if (npelast != 0)
+ MPI_Send(&cdata[ilast], 2, PVEC_REAL_MPI_TYPE, 0, 0, comm);
+ else { clast[0] = cdata[ilast]; clast[1] = cdata[ilast+1]; }
+ }
+
+ /* On PE 0, receive conc. at top right from PE npes - 1.
+ Then print performance data and sampled solution values. */
+
+ if (thispe == 0) {
+
+ if (npelast != 0)
+ MPI_Recv(&clast[0], 2, PVEC_REAL_MPI_TYPE, npelast, 0, comm, &status);
+
+ flag = IDAGetLastOrder(mem, &kused);
+ check_flag(&flag, "IDAGetLastOrder", 1, thispe);
+ flag = IDAGetNumSteps(mem, &nst);
+ check_flag(&flag, "IDAGetNumSteps", 1, thispe);
+ flag = IDAGetLastStep(mem, &hused);
+ check_flag(&flag, "IDAGetLastStep", 1, thispe);
+
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("%8.2Le %12.4Le %12.4Le | %3ld %1d %12.4Le\n",
+ tt, cdata[0], clast[0], nst, kused, hused);
+ for (i=1;i<NUM_SPECIES;i++)
+ printf(" %12.4Le %12.4Le |\n",cdata[i],clast[i]);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("%8.2le %12.4le %12.4le | %3ld %1d %12.4le\n",
+ tt, cdata[0], clast[0], nst, kused, hused);
+ for (i=1;i<NUM_SPECIES;i++)
+ printf(" %12.4le %12.4le |\n",cdata[i],clast[i]);
+#else
+ printf("%8.2e %12.4e %12.4e | %3ld %1d %12.4e\n",
+ tt, cdata[0], clast[0], nst, kused, hused);
+ for (i=1;i<NUM_SPECIES;i++)
+ printf(" %12.4e %12.4e |\n",cdata[i],clast[i]);
+#endif
+ printf("\n");
+
+ }
+
+}
+
+static void PrintSol(void* mem, N_Vector uv, N_Vector uvp,
+ UserData data, MPI_Comm comm)
+{
+ FILE* fout;
+ realtype *uvxy;
+ int ix, jy, mxsub, mysub, npex, npey, ixsub, jysub, nsmxsub, thispe, i, j;
+ char szFilename[128];
+
+ thispe = data->thispe;
+
+ sprintf(szFilename, "ysol%da.txt", thispe);
+
+ fout = fopen(szFilename, "w+");
+ if (fout==NULL) {
+ printf("PE[% 2d] is unable to write solution to disk!\n", thispe);
+ return;
+ }
+
+ npex = data->npex;
+ npey = data->npey;
+
+ mxsub = data->mxsub;
+ mysub = data->mysub;
+
+ ixsub = data->ixsub;
+ jysub = data->jysub;
+
+ nsmxsub = data->nsmxsub;
+
+ for (jy=0; jy<mysub; jy++) {
+
+ j = jysub*mysub+jy;
+
+ for (ix=0; ix<mxsub; ix++) {
+
+ i = ix + mxsub*ixsub;
+ if(MXSUB<5 && MYSUB<5)
+ printf("PE 2D[% 2d][% 2d] -- 1D[% 2d] subgrid[%d][%d] uv[%d][%d] uv[[%d]]\n",
+ ixsub, jysub, thispe, ix, jy, i, j,
+ (i)*NUM_SPECIES + (j)*NSMXSUB*npex);
+
+ uvxy = IJ_Vptr(uv, ix, jy);
+ //uvxy = (&NV_Ith_P(uv, (i)*NUM_SPECIES + (j)*NSMXSUB*npex ));
+ fprintf(fout, "%g\n%g\n", uvxy[0], uvxy[1]);
+ }
+ }
+ fclose(fout);
+}
+
+static void PrintAdjSol(N_Vector uvB, N_Vector uvpB, UserData data)
+{
+ FILE* fout;
+ realtype *uvxy;
+ int ix, jy, mxsub, mysub, npex, npey, ixsub, jysub, nsmxsub, thispe;
+ char szFilename[128];
+
+ thispe = data->thispe;
+
+ sprintf(szFilename, "ysol%dadj.txt", thispe);
+
+ fout = fopen(szFilename, "w+");
+ if (fout==NULL) {
+ printf("PE[% 2d] is unable to write adj solution to disk!\n", thispe);
+ return;
+ }
+
+ npex = data->npex;
+ npey = data->npey;
+
+ mxsub = data->mxsub;
+ mysub = data->mysub;
+
+ ixsub = data->ixsub;
+ jysub = data->jysub;
+
+ nsmxsub = data->nsmxsub;
+
+ for (jy=0; jy<mysub; jy++) {
+ for (ix=0; ix<mxsub; ix++) {
+
+ uvxy = IJ_Vptr(uvB, ix, jy);
+ fprintf(fout, "%g\n%g\n", uvxy[0], uvxy[1]);
+ }
+ }
+ fclose(fout);
+}
+
+
+
+/*
+ * PrintFinalStats: Print final run data contained in iopt.
+ */
+
+static void PrintFinalStats(void *mem)
+{
+ long int nst, nre, nreLS, netf, ncfn, nni, ncfl, nli, npe, nps, nge;
+ int flag;
+
+ flag = IDAGetNumSteps(mem, &nst);
+ check_flag(&flag, "IDAGetNumSteps", 1, 0);
+ flag = IDAGetNumResEvals(mem, &nre);
+ check_flag(&flag, "IDAGetNumResEvals", 1, 0);
+ flag = IDAGetNumErrTestFails(mem, &netf);
+ check_flag(&flag, "IDAGetNumErrTestFails", 1, 0);
+ flag = IDAGetNumNonlinSolvConvFails(mem, &ncfn);
+ check_flag(&flag, "IDAGetNumNonlinSolvConvFails", 1, 0);
+ flag = IDAGetNumNonlinSolvIters(mem, &nni);
+ check_flag(&flag, "IDAGetNumNonlinSolvIters", 1, 0);
+
+ flag = IDASpilsGetNumConvFails(mem, &ncfl);
+ check_flag(&flag, "IDASpilsGetNumConvFails", 1, 0);
+ flag = IDASpilsGetNumLinIters(mem, &nli);
+ check_flag(&flag, "IDASpilsGetNumLinIters", 1, 0);
+ flag = IDASpilsGetNumPrecEvals(mem, &npe);
+ check_flag(&flag, "IDASpilsGetNumPrecEvals", 1, 0);
+ flag = IDASpilsGetNumPrecSolves(mem, &nps);
+ check_flag(&flag, "IDASpilsGetNumPrecSolves", 1, 0);
+ flag = IDASpilsGetNumResEvals(mem, &nreLS);
+ check_flag(&flag, "IDASpilsGetNumResEvals", 1, 0);
+
+ flag = IDABBDPrecGetNumGfnEvals(mem, &nge);
+ check_flag(&flag, "IDABBDPrecGetNumGfnEvals", 1, 0);
+
+ printf("-----------------------------------------------------------\n");
+ printf("\nFinal statistics: \n\n");
+
+ printf("Number of steps = %ld\n", nst);
+ printf("Number of residual evaluations = %ld\n", nre+nreLS);
+ printf("Number of nonlinear iterations = %ld\n", nni);
+ printf("Number of error test failures = %ld\n", netf);
+ printf("Number of nonlinear conv. failures = %ld\n\n", ncfn);
+
+ printf("Number of linear iterations = %ld\n", nli);
+ printf("Number of linear conv. failures = %ld\n\n", ncfl);
+
+ printf("Number of preconditioner setups = %ld\n", npe);
+ printf("Number of preconditioner solves = %ld\n", nps);
+ printf("Number of local residual evals. = %ld\n", nge);
+
+}
+
+/*
+ * 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, char *funcname, int opt, int id)
+{
+ int *errflag;
+
+ if (opt == 0 && flagvalue == NULL) {
+ /* Check if SUNDIALS function returned NULL pointer - no memory allocated */
+ fprintf(stderr,
+ "\nSUNDIALS_ERROR(%d): %s() failed - returned NULL pointer\n\n",
+ id, funcname);
+ return(1);
+ } else if (opt == 1) {
+ /* Check if flag < 0 */
+ errflag = (int *) flagvalue;
+ if (*errflag < 0) {
+ fprintf(stderr,
+ "\nSUNDIALS_ERROR(%d): %s() failed with flag = %d\n\n",
+ id, funcname, *errflag);
+ return(1);
+ }
+ } else if (opt == 2 && flagvalue == NULL) {
+ /* Check if function returned NULL pointer - no memory allocated */
+ fprintf(stderr,
+ "\nMEMORY_ERROR(%d): %s() failed - returned NULL pointer\n\n",
+ id, funcname);
+ return(1);
+ }
+
+ return(0);
+}
+
+/*
+ *--------------------------------------------------------------------
+ * FUNCTIONS CALLED BY IDA & SUPPORTING FUNCTIONS
+ *--------------------------------------------------------------------
+ */
+
+/*
+ * res: System residual function
+ *
+ * To compute the residual function F, this routine calls:
+ * rescomm, for needed communication, and then
+ * 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)
+{
+ int retval;
+ UserData data;
+ long int Nlocal;
+
+ data = (UserData) user_data;
+
+ Nlocal = data->n_local;
+
+ /* Call rescomm to do inter-processor communication. */
+ retval = rescomm(Nlocal, tt, uv, uvp, user_data);
+
+ /* Call reslocal to calculate the local portion of residual vector. */
+ retval = reslocal(Nlocal, tt, uv, uvp, rr, user_data);
+
+ return(0);
+}
+
+/*
+ * rescomm: Communication routine in support of resweb.
+ * This routine performs all inter-processor communication of components
+ * of the uv vector needed to calculate F, namely the components at all
+ * interior subgrid boundaries (ghost cell data). It loads this data
+ * into a work array cext (the local portion of c, extended).
+ * 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)
+{
+
+ UserData data;
+ realtype *cdata, *gridext, buffer[2*NUM_SPECIES*MYSUB];
+ int thispe, ixsub, jysub, nsmxsub, nsmysub;
+ MPI_Comm comm;
+ MPI_Request request[4];
+
+ data = (UserData) user_data;
+ cdata = NV_DATA_P(uv);
+
+ /* Get comm, thispe, subgrid indices, data sizes, extended array cext. */
+
+ comm = data->comm;
+ thispe = data->thispe;
+
+ ixsub = data->ixsub;
+ jysub = data->jysub;
+ gridext = data->gridext;
+ nsmxsub = data->nsmxsub;
+ nsmysub = (data->ns)*(data->mysub);
+
+ /* Start receiving boundary data from neighboring PEs. */
+ BRecvPost(comm, request, thispe, ixsub, jysub, nsmxsub, nsmysub,
+ gridext, buffer);
+
+ /* Send data from boundary of local grid to neighboring PEs. */
+ BSend(comm, thispe, ixsub, jysub, nsmxsub, nsmysub, cdata);
+
+ /* Finish receiving boundary data from neighboring PEs. */
+ BRecvWait(request, ixsub, jysub, nsmxsub, gridext, buffer);
+
+ return(0);
+}
+
+/*
+ * BRecvPost: Start receiving boundary data from neighboring PEs.
+ * (1) buffer should be able to hold 2*NUM_SPECIES*MYSUB realtype entries,
+ * should be passed to both the BRecvPost and BRecvWait functions, and
+ * should not be manipulated between the two calls.
+ * (2) request should have 4 entries, and is also passed in both calls.
+ */
+
+static void BRecvPost(MPI_Comm comm, MPI_Request request[], int my_pe,
+ int ixsub, int jysub,
+ int dsizex, int dsizey,
+ realtype cext[], realtype buffer[])
+{
+ int offsetce;
+ /* Have bufleft and bufright use the same buffer. */
+ realtype *bufleft = buffer, *bufright = buffer+NUM_SPECIES*MYSUB;
+
+ /* If jysub > 0, receive data for bottom x-line of cext. */
+ if (jysub != 0)
+ MPI_Irecv(&cext[NUM_SPECIES], dsizex, PVEC_REAL_MPI_TYPE,
+ my_pe-NPEX, 0, comm, &request[0]);
+
+ /* If jysub < NPEY-1, receive data for top x-line of cext. */
+ if (jysub != NPEY-1) {
+ offsetce = NUM_SPECIES*(1 + (MYSUB+1)*(MXSUB+2));
+ MPI_Irecv(&cext[offsetce], dsizex, PVEC_REAL_MPI_TYPE,
+ my_pe+NPEX, 0, comm, &request[1]);
+ }
+
+ /* If ixsub > 0, receive data for left y-line of cext (via bufleft). */
+ if (ixsub != 0) {
+ MPI_Irecv(&bufleft[0], dsizey, PVEC_REAL_MPI_TYPE,
+ my_pe-1, 0, comm, &request[2]);
+ }
+
+ /* If ixsub < NPEX-1, receive data for right y-line of cext (via bufright). */
+ if (ixsub != NPEX-1) {
+ MPI_Irecv(&bufright[0], dsizey, PVEC_REAL_MPI_TYPE,
+ my_pe+1, 0, comm, &request[3]);
+ }
+
+}
+
+/*
+ * BRecvWait: Finish receiving boundary data from neighboring PEs.
+ * (1) buffer should be able to hold 2*NUM_SPECIES*MYSUB realtype entries,
+ * should be passed to both the BRecvPost and BRecvWait functions, and
+ * should not be manipulated between the two calls.
+ * (2) request should have 4 entries, and is also passed in both calls.
+ */
+
+static void BRecvWait(MPI_Request request[], int ixsub, int jysub,
+ int dsizex, realtype cext[], realtype buffer[])
+{
+ int i;
+ int ly, dsizex2, offsetce, offsetbuf;
+ realtype *bufleft = buffer, *bufright = buffer+NUM_SPECIES*MYSUB;
+ MPI_Status status;
+
+ dsizex2 = dsizex + 2*NUM_SPECIES;
+
+ /* If jysub > 0, receive data for bottom x-line of cext. */
+ if (jysub != 0)
+ MPI_Wait(&request[0],&status);
+
+ /* If jysub < NPEY-1, receive data for top x-line of cext. */
+ if (jysub != NPEY-1)
+ MPI_Wait(&request[1],&status);
+
+ /* If ixsub > 0, receive data for left y-line of cext (via bufleft). */
+ if (ixsub != 0) {
+ MPI_Wait(&request[2],&status);
+
+ /* Copy the buffer to cext */
+ for (ly = 0; ly < MYSUB; ly++) {
+ offsetbuf = ly*NUM_SPECIES;
+ offsetce = (ly+1)*dsizex2;
+ for (i = 0; i < NUM_SPECIES; i++)
+ cext[offsetce+i] = bufleft[offsetbuf+i];
+ }
+ }
+
+ /* If ixsub < NPEX-1, receive data for right y-line of cext (via bufright). */
+ if (ixsub != NPEX-1) {
+ MPI_Wait(&request[3],&status);
+
+ /* Copy the buffer to cext */
+ for (ly = 0; ly < MYSUB; ly++) {
+ offsetbuf = ly*NUM_SPECIES;
+ offsetce = (ly+2)*dsizex2 - NUM_SPECIES;
+ for (i = 0; i < NUM_SPECIES; i++)
+ cext[offsetce+i] = bufright[offsetbuf+i];
+ }
+ }
+}
+
+/*
+ * BSend: Send boundary data to neighboring PEs.
+ * This routine sends components of uv from internal subgrid boundaries
+ * to the appropriate neighbor PEs.
+ */
+
+static void BSend(MPI_Comm comm, int my_pe, int ixsub, int jysub,
+ int dsizex, int dsizey, realtype cdata[])
+{
+ int i;
+ int ly, offsetc, offsetbuf;
+ realtype bufleft[NUM_SPECIES*MYSUB], bufright[NUM_SPECIES*MYSUB];
+
+ /* If jysub > 0, send data from bottom x-line of uv. */
+
+ if (jysub != 0)
+ MPI_Send(&cdata[0], dsizex, PVEC_REAL_MPI_TYPE, my_pe-NPEX, 0, comm);
+
+ /* If jysub < NPEY-1, send data from top x-line of uv. */
+
+ if (jysub != NPEY-1) {
+ offsetc = (MYSUB-1)*dsizex;
+ MPI_Send(&cdata[offsetc], dsizex, PVEC_REAL_MPI_TYPE, my_pe+NPEX, 0, comm);
+ }
+
+ /* If ixsub > 0, send data from left y-line of uv (via bufleft). */
+
+ if (ixsub != 0) {
+ for (ly = 0; ly < MYSUB; ly++) {
+ offsetbuf = ly*NUM_SPECIES;
+ offsetc = ly*dsizex;
+ for (i = 0; i < NUM_SPECIES; i++)
+ bufleft[offsetbuf+i] = cdata[offsetc+i];
+ }
+ MPI_Send(&bufleft[0], dsizey, PVEC_REAL_MPI_TYPE, my_pe-1, 0, comm);
+ }
+
+ /* If ixsub < NPEX-1, send data from right y-line of uv (via bufright). */
+
+ if (ixsub != NPEX-1) {
+ for (ly = 0; ly < MYSUB; ly++) {
+ offsetbuf = ly*NUM_SPECIES;
+ offsetc = offsetbuf*MXSUB + (MXSUB-1)*NUM_SPECIES;
+ for (i = 0; i < NUM_SPECIES; i++)
+ bufright[offsetbuf+i] = cdata[offsetc+i];
+ }
+ MPI_Send(&bufright[0], dsizey, PVEC_REAL_MPI_TYPE, my_pe+1, 0, comm);
+ }
+}
+
+/* Define lines are for ease of readability in the following functions. */
+
+#define mxsub (data->mxsub)
+#define mysub (data->mysub)
+#define npex (data->npex)
+#define npey (data->npey)
+#define ixsub (data->ixsub)
+#define jysub (data->jysub)
+#define nsmxsub (data->nsmxsub)
+#define nsmxsub2 (data->nsmxsub2)
+#define dx (data->dx)
+#define dy (data->dy)
+#define cox (data->cox)
+#define coy (data->coy)
+#define gridext (data->gridext)
+#define eps (data->eps)
+#define ns (data->ns)
+
+/*
+ * reslocal: Compute res = F(t,uv,uvp).
+ * This routine assumes that all inter-processor communication of data
+ * needed to calculate F has already been done. Components at interior
+ * subgrid boundaries are assumed to be in the work array cext.
+ * The local portion of the uv vector is first copied into cext.
+ * The exterior Neumann boundary conditions are explicitly handled here
+ * by copying data from the first interior mesh line to the ghost cell
+ * locations in cext. Then the reaction and diffusion terms are
+ * evaluated in terms of the cext array, and the residuals are formed.
+ * The reaction terms are saved separately in the vector data->rates
+ * 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)
+{
+ realtype *uvdata, *uvpxy, *resxy, xx, yy, dcyli, dcyui, dcxli, dcxui, dx2, dy2;
+ realtype ixend, ixstart, jystart, jyend;
+ int ix, jy, is, i, locc, ylocce, locce;
+ realtype rates[2];
+ UserData data;
+
+ data = (UserData) user_data;
+
+ /* Get data pointers, subgrid data, array sizes, work array cext. */
+ uvdata = NV_DATA_P(uv);
+
+ dx2 = dx * dx;
+ dy2 = dy * dy;
+
+
+ /* Copy local segment of uv vector into the working extended array gridext. */
+ locc = 0;
+ locce = nsmxsub2 + NUM_SPECIES;
+ for (jy = 0; jy < mysub; jy++) {
+ for (i = 0; i < nsmxsub; i++) gridext[locce+i] = uvdata[locc+i];
+ locc = locc + nsmxsub;
+ locce = locce + nsmxsub2;
+ }
+
+ /* To facilitate homogeneous Neumann boundary conditions, when this is
+ a boundary PE, copy data from the first interior mesh line of uv to gridext. */
+
+ /* If jysub = 0, copy x-line 2 of uv to gridext. */
+ if (jysub == 0)
+ { for (i = 0; i < nsmxsub; i++) gridext[NUM_SPECIES+i] = uvdata[nsmxsub+i]; }
+
+
+ /* If jysub = npey-1, copy x-line mysub-1 of uv to gridext. */
+ if (jysub == npey-1) {
+ locc = (mysub-2)*nsmxsub;
+ locce = (mysub+1)*nsmxsub2 + NUM_SPECIES;
+ for (i = 0; i < nsmxsub; i++) gridext[locce+i] = uvdata[locc+i];
+ }
+
+
+ /* If ixsub = 0, copy y-line 2 of uv to gridext. */
+ if (ixsub == 0) {
+ for (jy = 0; jy < mysub; jy++) {
+ locc = jy*nsmxsub + NUM_SPECIES;
+ locce = (jy+1)*nsmxsub2;
+ for (i = 0; i < NUM_SPECIES; i++) gridext[locce+i] = uvdata[locc+i];
+ }
+ }
+
+
+ /* If ixsub = npex-1, copy y-line mxsub-1 of uv to gridext. */
+ if (ixsub == npex-1) {
+ for (jy = 0; jy < mysub; jy++) {
+ locc = (jy+1)*nsmxsub - 2*NUM_SPECIES;
+ locce = (jy+2)*nsmxsub2 - NUM_SPECIES;
+ for (i = 0; i < NUM_SPECIES; i++) gridext[locce+i] = uvdata[locc+i];
+ }
+ }
+
+ /* Loop over all grid points, setting local array rates to right-hand sides.
+ Then set rr values appropriately (ODE in the interior and DAE on the boundary)*/
+ ixend = ixstart = jystart = jyend = 0;
+
+ if (jysub==0) jystart = 1;
+ if (jysub==npey-1) jyend = 1;
+ if (ixsub==0) ixstart = 1;
+ if (ixsub==npex-1) ixend = 1;
+
+ for (jy = jystart; jy < mysub-jyend; jy++) {
+ ylocce = (jy+1)*nsmxsub2;
+ yy = (jy+jysub*mysub)*dy;
+
+ for (ix = ixstart; ix < mxsub-ixend; ix++) {
+ locce = ylocce + (ix+1)*NUM_SPECIES;
+ xx = (ix + ixsub*mxsub)*dx;
+
+ ReactRates(xx, yy, &(gridext[locce]), rates, data);
+
+ resxy = IJ_Vptr(rr,ix,jy);
+ uvpxy = IJ_Vptr(uvp,ix,jy);
+
+ for (is = 0; is < NUM_SPECIES; is++) {
+ dcyli = gridext[locce+is] - gridext[locce+is-nsmxsub2];
+ dcyui = gridext[locce+is+nsmxsub2] - gridext[locce+is];
+
+ dcxli = gridext[locce+is] - gridext[locce+is-NUM_SPECIES];
+ dcxui = gridext[locce+is+NUM_SPECIES] - gridext[locce+is];
+
+ resxy[is] = uvpxy[is]-eps[is]*((dcxui-dcxli)/dx2+(dcyui-dcyli)/dy2)-rates[is];
+ }
+ }
+ }
+
+ if (jysub==0) {
+ for (ix=0; ix<mxsub; ix++) {
+
+ locce = nsmxsub2 + NUM_SPECIES * (ix+1);
+ resxy = IJ_Vptr(rr,ix,0);
+
+ for (is=0; is<NUM_SPECIES; is++)
+ resxy[is] = gridext[locce+is+nsmxsub2] - gridext[locce+is];
+ }
+ }
+
+ if (ixsub==npex-1) {
+ for(jy=0; jy<mysub; jy++) {
+ locce = (jy+1)*nsmxsub2 + nsmxsub2-NUM_SPECIES;
+ resxy = IJ_Vptr(rr,mxsub-1,jy);
+
+ for (is=0; is<NUM_SPECIES; is++)
+ resxy[is] = gridext[locce+is-NUM_SPECIES] - gridext[locce+is];
+ }
+ }
+
+ if (ixsub==0) {
+ for (jy=0; jy<mysub; jy++) {
+ locce = (jy+1)*nsmxsub2 + NUM_SPECIES;
+ resxy = IJ_Vptr(rr,0,jy);
+
+ for (is=0; is<NUM_SPECIES; is++)
+ resxy[is] = gridext[locce+is-NUM_SPECIES] - gridext[locce+is];
+ }
+ }
+
+ if (jysub==npey-1) {
+ for(ix=0; ix<mxsub; ix++) {
+ locce = nsmxsub2*mysub + (ix+1)*NUM_SPECIES;
+ resxy = IJ_Vptr(rr,ix, mysub-1);
+
+ for (is=0; is<NUM_SPECIES; is++)
+ resxy[is] = gridext[locce+is-nsmxsub2] - gridext[locce+is];
+ }
+ }
+ return(0);
+}
+
+/*
+ * ReactRates: Evaluate reaction rates at a given spatial point.
+ * 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)
+{
+ realtype A, B;
+
+ A = data->A; B = data->B;
+
+ rates[0] = uvval[0]*uvval[0]*uvval[1];
+ rates[1] = - rates[0];
+
+ rates[0] += A-(B+1)*uvval[0];
+ rates[1] += B*uvval[0];
+}
+
+
+
+static int resB(realtype tt, N_Vector yy, N_Vector yp,
+ N_Vector yyB, N_Vector ypB, N_Vector rrB,
+ void *user_dataB)
+{
+ UserData data;
+ int retval;
+ long int Nlocal;
+
+ data = (UserData) user_dataB;
+
+ Nlocal = data->n_local;
+
+ /* Call rescomm to do inter-processor communication. */
+ retval = rescomm(Nlocal, tt, yyB, ypB, data);
+
+ /* Call reslocal to calculate the local portion of residual vector. */
+ retval = resBlocal(Nlocal, tt, yy, yp, yyB, ypB, rrB, user_dataB);
+
+ return(0);
+}
+
+
+
+static int resBlocal(long int Nlocal, realtype tt,
+ N_Vector uv, N_Vector uvp,
+ N_Vector uvB, N_Vector uvpB, N_Vector rrB,
+ void *user_dataB)
+{
+ realtype *uvBdata, *uvBxy, *uvpBxy, *uvxy, *rrBxy;
+ realtype dx2, dy2, xx, yy;
+ realtype dcxli, dcxui, dcyli, dcyui;
+ int locc, locce, ylocce;
+ int ix, jy, i, ixstart, ixend, jystart, jyend, is;
+ UserData data;
+ realtype A, B;
+
+ data = (UserData) user_dataB;
+
+ A = data->A; B = data->B;
+
+
+ /* Get data pointers, subgrid data, array sizes, work array cext. */
+ uvBdata = NV_DATA_P(uvB);
+
+ dx2 = dx * dx;
+ dy2 = dy * dy;
+
+
+ /* Copy local segment of uv vector into the working extended array gridext. */
+ locc = 0;
+ locce = nsmxsub2 + NUM_SPECIES;
+ for (jy = 0; jy < mysub; jy++) {
+ for (i = 0; i < nsmxsub; i++) gridext[locce+i] = uvBdata[locc+i];
+ locc = locc + nsmxsub;
+ locce = locce + nsmxsub2;
+ }
+
+ /* If jysub = 0, copy x-line 2 of uv to gridext. */
+ if (jysub == 0)
+ { for (i = 0; i < nsmxsub; i++) gridext[NUM_SPECIES+i] = uvBdata[nsmxsub+i]; }
+
+
+ /* If jysub = npey-1, copy x-line mysub-1 of uv to gridext. */
+ if (jysub == npey-1) {
+ locc = (mysub-2)*nsmxsub;
+ locce = (mysub+1)*nsmxsub2 + NUM_SPECIES;
+ for (i = 0; i < nsmxsub; i++) gridext[locce+i] = uvBdata[locc+i];
+ }
+
+
+ /* If ixsub = 0, copy y-line 2 of uv to gridext. */
+ if (ixsub == 0) {
+ for (jy = 0; jy < mysub; jy++) {
+ locc = jy*nsmxsub + NUM_SPECIES;
+ locce = (jy+1)*nsmxsub2;
+ for (i = 0; i < NUM_SPECIES; i++) gridext[locce+i] = uvBdata[locc+i];
+ }
+ }
+
+
+ /* If ixsub = npex-1, copy y-line mxsub-1 of uv to gridext. */
+ if (ixsub == npex-1) {
+ for (jy = 0; jy < mysub; jy++) {
+ locc = (jy+1)*nsmxsub - 2*NUM_SPECIES;
+ locce = (jy+2)*nsmxsub2 - NUM_SPECIES;
+ for (i = 0; i < NUM_SPECIES; i++) gridext[locce+i] = uvBdata[locc+i];
+ }
+ }
+
+ /* Loop over all grid points, setting local array rates to right-hand sides.
+ Then set rr values appropriately (ODE in the interior and DAE on the boundary)*/
+ ixend = ixstart = jystart = jyend = 0;
+
+ if (jysub==0) jystart = 1;
+ if (jysub==npey-1) jyend = 1;
+ if (ixsub==0) ixstart = 1;
+ if (ixsub==npex-1) ixend = 1;
+
+ for (jy = jystart; jy < mysub-jyend; jy++) {
+ ylocce = (jy+1)*nsmxsub2;
+ yy = (jy+jysub*mysub)*dy;
+
+ for (ix = ixstart; ix < mxsub-ixend; ix++) {
+ locce = ylocce + (ix+1)*NUM_SPECIES;
+ xx = (ix + ixsub*mxsub)*dx;
+
+
+ uvxy = IJ_Vptr(uv ,ix,jy);
+ uvBxy = IJ_Vptr(uvB ,ix,jy);
+ uvpBxy= IJ_Vptr(uvpB,ix,jy);
+ rrBxy = IJ_Vptr(rrB ,ix,jy);
+
+ for (is = 0; is < NUM_SPECIES; is++) {
+ dcyli = gridext[locce+is] - gridext[locce+is-nsmxsub2];
+ dcyui = gridext[locce+is+nsmxsub2] - gridext[locce+is];
+
+ dcxli = gridext[locce+is] - gridext[locce+is-NUM_SPECIES];
+ dcxui = gridext[locce+is+NUM_SPECIES] - gridext[locce+is];
+
+ rrBxy[is] = uvpBxy[is] + eps[is]*( (dcxui-dcxli)/dx2 + (dcyui-dcyli)/dy2 );
+ }
+
+ //now add rates
+ rrBxy[0] += (uvBxy[0]-uvBxy[1])*(2*uvxy[0]*uvxy[1] - B) - uvBxy[0];
+ rrBxy[1] += uvxy[0]*uvxy[0]*(uvBxy[0]-uvBxy[1]);
+ }
+ }
+
+ if (jysub==0) {
+ for (ix=0; ix<mxsub; ix++) {
+
+ locce = nsmxsub2 + NUM_SPECIES * (ix+1);
+ rrBxy = IJ_Vptr(rrB,ix,0);
+
+ for (is=0; is<NUM_SPECIES; is++)
+ rrBxy[is] = gridext[locce+is+nsmxsub2] - gridext[locce+is];
+ }
+ }
+
+ if (ixsub==npex-1) {
+ for(jy=0; jy<mysub; jy++) {
+ locce = (jy+1)*nsmxsub2 + nsmxsub2-NUM_SPECIES;
+ rrBxy = IJ_Vptr(rrB,mxsub-1,jy);
+
+ for (is=0; is<NUM_SPECIES; is++)
+ rrBxy[is] = gridext[locce+is-NUM_SPECIES] - gridext[locce+is];
+ }
+ }
+
+ if (ixsub==0) {
+ for (jy=0; jy<mysub; jy++) {
+ locce = (jy+1)*nsmxsub2 + NUM_SPECIES;
+ rrBxy = IJ_Vptr(rrB,0,jy);
+
+ for (is=0; is<NUM_SPECIES; is++)
+ rrBxy[is] = gridext[locce+is-NUM_SPECIES] - gridext[locce+is];
+ }
+ }
+
+ if (jysub==npey-1) {
+ for(ix=0; ix<mxsub; ix++) {
+ locce = nsmxsub2*mysub + (ix+1)*NUM_SPECIES;
+ rrBxy = IJ_Vptr(rrB,ix, mysub-1);
+
+ for (is=0; is<NUM_SPECIES; is++)
+ rrBxy[is] = gridext[locce+is-nsmxsub2] - gridext[locce+is];
+ }
+ }
+
+ return(0);
+}
+
diff --git a/examples/idas/parallel/idasBruss_ASAp_kry_bbd_p.out b/examples/idas/parallel/idasBruss_ASAp_kry_bbd_p.out
new file mode 100644
index 0000000..15a5385
--- /dev/null
+++ b/examples/idas/parallel/idasBruss_ASAp_kry_bbd_p.out
@@ -0,0 +1,50 @@
+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
+Preconditioner: band-block-diagonal (IDABBDPRE), with parameters
+ mudq = 42, mldq = 42, mukeep = 2, mlkeep = 2
+-----------------------------------------------------------
+ t bottom-left top-right | nst k h
+-----------------------------------------------------------
+
+1.00e+00 2.6132e-01 3.0982e+00 | 154 5 1.1112e-02
+ 1.9993e+00 1.0125e+00 |
+
+-----------------------------------------------------------
+
+Final statistics:
+
+Number of steps = 154
+Number of residual evaluations = 392
+Number of nonlinear iterations = 174
+Number of error test failures = 2
+Number of nonlinear conv. failures = 0
+
+Number of linear iterations = 216
+Number of linear conv. failures = 0
+
+Number of preconditioner setups = 17
+Number of preconditioner solves = 392
+Number of local residual evals. = 1462
+
+ BACKWARD problem
+-----------------------------------------------------------
+
+Final statistics:
+
+Number of steps = 99
+Number of residual evaluations = 268
+Number of nonlinear iterations = 118
+Number of error test failures = 0
+Number of nonlinear conv. failures = 0
+
+Number of linear iterations = 150
+Number of linear conv. failures = 0
+
+Number of preconditioner setups = 16
+Number of preconditioner solves = 268
+Number of local residual evals. = 1376
diff --git a/examples/idas/parallel/idasBruss_FSA_kry_bbd_p.c b/examples/idas/parallel/idasBruss_FSA_kry_bbd_p.c
new file mode 100644
index 0000000..91b37c1
--- /dev/null
+++ b/examples/idas/parallel/idasBruss_FSA_kry_bbd_p.c
@@ -0,0 +1,1169 @@
+/* * -----------------------------------------------------------------
+ * $Revision:
+ * $Date:
+ * -----------------------------------------------------------------
+ * Programmer(s): 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.
+ * It is written for a parallel computer system and uses the
+ * IDABBDPRE band-block-diagonal preconditioner module for the
+ * IDASPGMR package.
+ *
+ * The mathematical problem solved in this example is a DAE system
+ * that arises from a system of partial differential equations after
+ * spatial discretization.
+ *
+ * The PDE system is a two-species time-dependent PDE known as
+ * Brusselator PDE and models a chemically reacting system.
+ *
+ *
+ * du/dt = eps1(u + u ) + u^2 v -(B+1)u + A
+ * xx yy
+ * domain [0,L]X[0,L]
+ * dv/dt = eps2(v + v ) - u^2 v + Bu
+ * xx yy
+ *
+ * B.C. Neumann
+ * I.C u(x,y,t0) = u0(x,y) = 1 - 0.5*cos(pi*y/L)
+ * v(x,y,t0) = v0(x,y) = 3.5 - 2.5*cos(pi*x/L)
+ *
+ * The PDEs are discretized by central differencing on a MX by MY
+ * mesh, and so the system size Neq is the product MX*MY*NUM_SPECIES.
+ * The system is actually implemented on submeshes, processor by
+ * processor, with an MXSUB by MYSUB mesh on each of NPEX * NPEY
+ * processors.
+ *
+ * The average of the solution u at final time is also computed.
+ * / /
+ * g = | | u(x,y,tf) dx dy
+ * / /
+ * Also the sensitivities of g with respect to parameters eps1 and
+ * eps2 are computed.
+ * / /
+ * dg/d eps = | | u (x,y,tf) dx dy
+ * / / eps
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+
+#include <idas/idas.h>
+#include <idas/idas_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>
+
+#include <mpi.h>
+
+/* Problem Constants */
+#define NUM_SPECIES 2
+#define ctL RCONST(1.0) /* Domain =[0,L]^2 */
+#define ctA RCONST(1.0)
+#define ctB RCONST(3.4)
+#define ctEps RCONST(2.0e-3)
+
+#define NS 2
+
+#define PI RCONST(3.1415926535898) /* pi */
+
+#define MXSUB 41 /* Number of x mesh points per processor subgrid */
+#define MYSUB 41 /* Number of y mesh points per processor subgrid */
+#define NPEX 2 /* Number of subgrids in the x direction */
+#define NPEY 2 /* Number of subgrids in the y direction */
+#define MX (MXSUB*NPEX) /* MX = number of x mesh points */
+#define MY (MYSUB*NPEY) /* MY = number of y mesh points */
+#define NSMXSUB (NUM_SPECIES * MXSUB)
+#define NEQ (NUM_SPECIES*MX*MY) /* Number of equations in system */
+
+
+#define RTOL RCONST(1.e-5) /* rtol tolerance */
+#define ATOL RCONST(1.e-5) /* atol tolerance */
+#define NOUT 6
+#define TMULT RCONST(10.0) /* Multiplier for tout values */
+#define TADD RCONST(0.3) /* Increment for tout values */
+
+#define ZERO RCONST(0.0)
+#define HALF RCONST(0.5)
+#define ONE RCONST(1.0)
+
+
+/* User-defined vector accessor macro IJ_Vptr. */
+
+/*
+ * IJ_Vptr is defined in order to express the underlying 3-d structure of the
+ * dependent variable vector from its underlying 1-d storage (an N_Vector).
+ * IJ_Vptr(vv,i,j) returns a pointer to the location in vv corresponding to
+ * species index is = 0, x-index ix = i, and y-index jy = j.
+ */
+
+#define IJ_Vptr(vv,i,j) (&NV_Ith_P(vv, (i)*NUM_SPECIES + (j)*NSMXSUB ))
+
+/* Type: UserData. Contains problem constants, preconditioner data, etc. */
+typedef struct {
+ int ns, thispe, npes, ixsub, jysub, npex, npey;
+ int mxsub, mysub, nsmxsub, nsmxsub2;
+ realtype A, B, L, eps[NUM_SPECIES];
+ realtype dx, dy;
+ realtype cox[NUM_SPECIES], coy[NUM_SPECIES];
+ realtype gridext[(MXSUB+2)*(MYSUB+2)*NUM_SPECIES];
+ realtype rhs[NUM_SPECIES];
+ MPI_Comm comm;
+ realtype rates[2];
+ long int 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 reslocal(long int 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);
+
+/* Integrate over spatial domain. */
+static int integr(MPI_Comm comm, N_Vector uv, void *user_data, realtype *intval);
+
+/* 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,
+ 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);
+
+/* Prototypes for private functions */
+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,
+ realtype rtol, realtype atol);
+
+static void PrintOutput(void *mem, N_Vector uv, realtype time,
+ UserData data, MPI_Comm comm);
+
+static void PrintSol(void* mem, N_Vector uv, N_Vector uvp, UserData data,
+ MPI_Comm comm);
+
+static void PrintFinalStats(void *mem);
+
+static int check_flag(void *flagvalue, char *funcname, int opt, int id);
+
+/*
+ *--------------------------------------------------------------------
+ * MAIN PROGRAM
+ *--------------------------------------------------------------------
+ */
+
+int main(int argc, char *argv[])
+{
+ MPI_Comm comm;
+ void *mem;
+ UserData data;
+ long int 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;
+ realtype pbar[NS];
+ int is;
+ realtype intval;
+
+ uv = uvp = resid = id = NULL;
+ uvS = uvpS = NULL;
+ data = NULL;
+ mem = NULL;
+
+ /* Set communicator, and get processor number and total number of PE's. */
+ MPI_Init(&argc, &argv);
+ comm = MPI_COMM_WORLD;
+ MPI_Comm_rank(comm, &thispe);
+ MPI_Comm_size(comm, &npes);
+
+ if (npes != NPEX*NPEY) {
+ if (thispe == 0)
+ fprintf(stderr,
+ "\nMPI_ERROR(0): npes = %d not equal to NPEX*NPEY = %d\n",
+ npes, NPEX*NPEY);
+ MPI_Finalize();
+ return(1);
+ }
+
+ /* Set local length (local_N) and global length (SystemSize). */
+ local_N = MXSUB*MYSUB*NUM_SPECIES;
+ SystemSize = NEQ;
+
+ /* Set up user data block data. */
+ data = (UserData) malloc(sizeof *data);
+
+ InitUserData(data, thispe, npes, comm);
+
+ /* Create needed vectors, and load initial values.
+ The vector resid is used temporarily only. */
+
+ uv = N_VNew_Parallel(comm, local_N, SystemSize);
+ if(check_flag((void *)uv, "N_VNew_Parallel", 0, thispe)) MPI_Abort(comm, 1);
+
+ uvp = N_VNew_Parallel(comm, local_N, SystemSize);
+ if(check_flag((void *)uvp, "N_VNew_Parallel", 0, thispe)) MPI_Abort(comm, 1);
+
+ resid = N_VNew_Parallel(comm, local_N, SystemSize);
+ if(check_flag((void *)resid, "N_VNew_Parallel", 0, thispe)) MPI_Abort(comm, 1);
+
+ id = N_VNew_Parallel(comm, local_N, SystemSize);
+ if(check_flag((void *)id, "N_VNew_Parallel", 0, thispe)) MPI_Abort(comm, 1);
+
+ uvS = N_VCloneVectorArray_Parallel(NS, uv);
+ if (check_flag((void *)uvS, "N_VCloneVectorArray_Parallel", 0, thispe))
+ MPI_Abort(comm, 1);
+ for (is=0;is<NS;is++) N_VConst(ZERO, uvS[is]);
+
+ uvpS = N_VCloneVectorArray_Parallel(NS, uv);
+ if (check_flag((void *)uvpS, "N_VCloneVectorArray_Parallel", 0, thispe))
+ MPI_Abort(comm, 1);
+ for (is=0;is<NS;is++) N_VConst(ZERO, uvpS[is]);
+
+ SetInitialProfiles(uv, uvp, id, resid, data);
+
+ /* Set remaining inputs to IDAS. */
+ t0 = ZERO;
+ rtol = RTOL;
+ atol = ATOL;
+
+ /* Call IDACreate and IDAInit to initialize solution */
+ mem = IDACreate();
+ if(check_flag((void *)mem, "IDACreate", 0, thispe)) MPI_Abort(comm, 1);
+
+ retval = IDASetUserData(mem, data);
+ if(check_flag(&retval, "IDASetUserData", 1, thispe)) MPI_Abort(comm, 1);
+
+ retval = IDASetId(mem, id);
+ if(check_flag(&retval, "IDASetId", 1, thispe)) MPI_Abort(comm, 1);
+
+ retval = IDAInit(mem, res, t0, uv, uvp);
+ if(check_flag(&retval, "IDAInit", 1, thispe)) MPI_Abort(comm, 1);
+
+ retval = IDASStolerances(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);
+ if(check_flag(&retval, "IDASensInit", 1, thispe)) MPI_Abort(comm, 1);
+
+ retval = IDASensEEtolerances(mem);
+ if(check_flag(&retval, "IDASensEEtolerances", 1, thispe)) MPI_Abort(comm, 1);
+
+ retval = IDASetSensErrCon(mem, TRUE);
+ 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);
+ 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 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,
+ 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);
+ 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);
+
+
+ /* 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);
+ if(check_flag(&retval, "IDASolve", 1, thispe)) MPI_Abort(comm, 1);
+
+ PrintOutput(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); */
+
+
+ /* On PE 0, print final set of statistics. */
+ if (thispe == 0) {
+ PrintFinalStats(mem);
+ }
+
+ /* calculate integral of u over domain. */
+ integr(comm, uv, data, &intval);
+ if (thispe == 0) {
+ printf("\n\nThe average of u on the domain:\ng = %g\n", intval);
+ }
+
+ /* integrate the sensitivities of u over domain. */
+ IDAGetSens(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) {
+ printf("w.r.t. eps%d = %14.10f\n", is, intval);
+ }
+ }
+
+ /* Free memory. */
+ N_VDestroy_Parallel(uv);
+ N_VDestroy_Parallel(uvp);
+ N_VDestroy_Parallel(id);
+ N_VDestroy_Parallel(resid);
+ N_VDestroyVectorArray_Parallel(uvS, NS);
+ N_VDestroyVectorArray_Parallel(uvpS, NS);
+ IDAFree(&mem);
+
+ free(data);
+
+ MPI_Finalize();
+
+ return(0);
+}
+
+/*
+ *--------------------------------------------------------------------
+ * PRIVATE FUNCTIONS
+ *--------------------------------------------------------------------
+ */
+
+/*
+ * InitUserData: Load problem constants in data (of type UserData).
+ */
+
+static void InitUserData(UserData data, int thispe, int npes,
+ MPI_Comm comm)
+{
+ data->jysub = thispe / NPEX;
+ data->ixsub = thispe - (data->jysub)*NPEX;
+ data->mxsub = MXSUB;
+ data->mysub = MYSUB;
+ data->npex = NPEX;
+ data->npey = NPEY;
+ data->ns = NUM_SPECIES;
+ data->dx = ctL/(MX-1);
+ data->dy = ctL/(MY-1);
+ data->thispe = thispe;
+ data->npes = npes;
+ data->nsmxsub = MXSUB * NUM_SPECIES;
+ 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;
+}
+
+/*
+ * SetInitialProfiles: Set initial conditions in uv, uvp, and id.
+ */
+
+static void SetInitialProfiles(N_Vector uv, N_Vector uvp, N_Vector id,
+ N_Vector resid, UserData data)
+{
+ int ixsub, jysub, mxsub, mysub, nsmxsub, ix, jy;
+ realtype *idxy, dx, dy, x, y, *uvxy, *uvxy1, L, npex, npey;
+
+ ixsub = data->ixsub;
+ jysub = data->jysub;
+ mxsub = data->mxsub;
+ mysub = data->mysub;
+ nsmxsub = data->nsmxsub;
+ npex = data->npex;
+ npey = data->npey;
+ dx = data->dx;
+ dy = data->dy;
+ L = data->L;
+
+ /* Loop over grid, load uv values and id values. */
+ for (jy = 0; jy < mysub; jy++) {
+ y = (jy + jysub*mysub) * dy;
+ for (ix = 0; ix < mxsub; ix++) {
+
+ x = (ix + ixsub*mxsub) * dx;
+ uvxy = IJ_Vptr(uv,ix,jy);
+
+ uvxy[0] = RCONST(1.0) - HALF*cos(PI*y/L);
+ uvxy[1] = RCONST(3.5) - RCONST(2.5)*cos(PI*x/L);
+ }
+ }
+
+ N_VConst(ONE, id);
+
+ if (jysub == 0) {
+ for (ix=0; ix<mxsub; ix++) {
+ idxy = IJ_Vptr(id,ix,0);
+ idxy[0] = idxy[1] = ZERO;
+
+ uvxy = IJ_Vptr(uv,ix,0);
+ uvxy1 = IJ_Vptr(uv,ix,1);
+ uvxy[0] = uvxy1[0];
+ uvxy[1] = uvxy1[1];
+ }
+ }
+
+ if (ixsub == npex-1) {
+ for (jy = 0; jy < mysub; jy++) {
+ idxy = IJ_Vptr(id,mxsub-1,jy);
+ idxy[0] = idxy[1] = ZERO;
+
+ uvxy = IJ_Vptr(uv,mxsub-1,jy);
+ uvxy1 = IJ_Vptr(uv,mxsub-2,jy);
+ uvxy[0] = uvxy1[0];
+ uvxy[1] = uvxy1[1];
+
+ }
+ }
+
+
+ if (ixsub == 0) {
+ for (jy = 0; jy < mysub; jy++) {
+ idxy = IJ_Vptr(id,0,jy);
+ idxy[0] = idxy[1] = ZERO;
+
+ uvxy = IJ_Vptr(uv,0,jy);
+ uvxy1 = IJ_Vptr(uv,1,jy);
+ uvxy[0] = uvxy1[0];
+ uvxy[1] = uvxy1[1];
+
+ }
+ }
+
+ if (jysub == npey-1) {
+ for (ix=0; ix<mxsub; ix++) {
+ idxy = IJ_Vptr(id,ix,jysub);
+ idxy[0] = idxy[1] = ZERO;
+
+ uvxy = IJ_Vptr(uv,ix,mysub-1);
+ uvxy1 = IJ_Vptr(uv,ix,mysub-2);
+ uvxy[0] = uvxy1[0];
+ uvxy[1] = uvxy1[1];
+
+ }
+ }
+
+ /* Derivative found by calling the residual function with uvp = 0. */
+ N_VConst(ZERO, uvp);
+ res(ZERO, uv, uvp, resid, data);
+ N_VScale(-ONE, resid, uvp);
+
+
+}
+
+/*
+ * Print first lines of output (problem description)
+ * and table headerr
+ */
+
+static void PrintHeader(int SystemSize, int maxl,
+ long int mudq, long int mldq,
+ long int mukeep, long int 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("Subgrid dimensions: %d x %d", MXSUB, MYSUB);
+ printf(" Processor array: %d x %d\n", NPEX, NPEY);
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("Tolerance parameters: rtol = %Lg atol = %Lg\n", rtol, atol);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("Tolerance parameters: rtol = %lg atol = %lg\n", rtol, atol);
+#else
+ printf("Tolerance parameters: rtol = %g atol = %g\n", rtol, atol);
+#endif
+ printf("Linear solver: IDASPGMR 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("CalcIC called to correct initial concentrations \n\n");
+ printf("-----------------------------------------------------------\n");
+ printf(" t bottom-left top-right");
+ printf(" | nst k h\n");
+ printf("-----------------------------------------------------------\n\n");
+}
+
+
+/*
+ * PrintOutput: Print output values at output time t = tt.
+ * Selected run statistics are printed. Then values of c1 and c2
+ * are printed for the bottom left and top right grid points only.
+ */
+
+static void PrintOutput(void *mem, N_Vector uv, realtype tt,
+ UserData data, MPI_Comm comm)
+{
+ MPI_Status status;
+ realtype *cdata, clast[2], hused;
+ long int nst;
+ int i, kused, flag, thispe, npelast, ilast;;
+
+ thispe = data->thispe;
+ npelast = data->npes - 1;
+ cdata = NV_DATA_P(uv);
+
+ /* Send conc. at top right mesh point from PE npes-1 to PE 0. */
+ if (thispe == npelast) {
+ ilast = NUM_SPECIES*MXSUB*MYSUB - 2;
+ if (npelast != 0)
+ MPI_Send(&cdata[ilast], 2, PVEC_REAL_MPI_TYPE, 0, 0, comm);
+ else { clast[0] = cdata[ilast]; clast[1] = cdata[ilast+1]; }
+ }
+
+ /* On PE 0, receive conc. at top right from PE npes - 1.
+ Then print performance data and sampled solution values. */
+ if (thispe == 0) {
+
+ if (npelast != 0)
+ MPI_Recv(&clast[0], 2, PVEC_REAL_MPI_TYPE, npelast, 0, comm, &status);
+
+ flag = IDAGetLastOrder(mem, &kused);
+ check_flag(&flag, "IDAGetLastOrder", 1, thispe);
+ flag = IDAGetNumSteps(mem, &nst);
+ check_flag(&flag, "IDAGetNumSteps", 1, thispe);
+ flag = IDAGetLastStep(mem, &hused);
+ check_flag(&flag, "IDAGetLastStep", 1, thispe);
+
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("%8.2Le %12.4Le %12.4Le | %3ld %1d %12.4Le\n",
+ tt, cdata[0], clast[0], nst, kused, hused);
+ for (i=1;i<NUM_SPECIES;i++)
+ printf(" %12.4Le %12.4Le |\n",cdata[i],clast[i]);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("%8.2le %12.4le %12.4le | %3ld %1d %12.4le\n",
+ tt, cdata[0], clast[0], nst, kused, hused);
+ for (i=1;i<NUM_SPECIES;i++)
+ printf(" %12.4le %12.4le |\n",cdata[i],clast[i]);
+#else
+ printf("%8.2e %12.4e %12.4e | %3ld %1d %12.4e\n",
+ tt, cdata[0], clast[0], nst, kused, hused);
+ for (i=1;i<NUM_SPECIES;i++)
+ printf(" %12.4e %12.4e |\n",cdata[i],clast[i]);
+#endif
+ printf("\n");
+
+ }
+
+}
+
+/*
+ * PrintSol the PE's portion of the solution to a file.
+ */
+static void PrintSol(void* mem, N_Vector uv, N_Vector uvp,
+ UserData data, MPI_Comm comm)
+{
+ FILE* fout;
+ realtype *uvxy;
+ int ix, jy, mxsub, mysub, thispe;
+ char szFilename[128];
+
+ thispe = data->thispe;
+ sprintf(szFilename, "ysol%d.txt", thispe);
+
+ fout = fopen(szFilename, "w+");
+ if (fout==NULL) {
+ printf("PE[% 2d] is unable to write solution to disk!\n", thispe);
+ return;
+ }
+
+ mxsub = data->mxsub;
+ mysub = data->mysub;
+
+ for (jy=0; jy<mysub; jy++) {
+ for (ix=0; ix<mxsub; ix++) {
+
+ uvxy = IJ_Vptr(uv, ix, jy);
+ fprintf(fout, "%g\n%g\n", uvxy[0], uvxy[1]);
+ }
+ }
+ fclose(fout);
+}
+
+
+
+/*
+ * PrintFinalStats: Print final run data contained in iopt.
+ */
+
+static void PrintFinalStats(void *mem)
+{
+ long int nst, nre, nreLS, netf, ncfn, nni, ncfl, nli, npe, nps, nge;
+ int flag;
+
+ flag = IDAGetNumSteps(mem, &nst);
+ check_flag(&flag, "IDAGetNumSteps", 1, 0);
+ flag = IDAGetNumResEvals(mem, &nre);
+ check_flag(&flag, "IDAGetNumResEvals", 1, 0);
+ flag = IDAGetNumErrTestFails(mem, &netf);
+ check_flag(&flag, "IDAGetNumErrTestFails", 1, 0);
+ flag = IDAGetNumNonlinSolvConvFails(mem, &ncfn);
+ check_flag(&flag, "IDAGetNumNonlinSolvConvFails", 1, 0);
+ flag = IDAGetNumNonlinSolvIters(mem, &nni);
+ check_flag(&flag, "IDAGetNumNonlinSolvIters", 1, 0);
+
+ flag = IDASpilsGetNumConvFails(mem, &ncfl);
+ check_flag(&flag, "IDASpilsGetNumConvFails", 1, 0);
+ flag = IDASpilsGetNumLinIters(mem, &nli);
+ check_flag(&flag, "IDASpilsGetNumLinIters", 1, 0);
+ flag = IDASpilsGetNumPrecEvals(mem, &npe);
+ check_flag(&flag, "IDASpilsGetNumPrecEvals", 1, 0);
+ flag = IDASpilsGetNumPrecSolves(mem, &nps);
+ check_flag(&flag, "IDASpilsGetNumPrecSolves", 1, 0);
+ flag = IDASpilsGetNumResEvals(mem, &nreLS);
+ check_flag(&flag, "IDASpilsGetNumResEvals", 1, 0);
+
+ flag = IDABBDPrecGetNumGfnEvals(mem, &nge);
+ check_flag(&flag, "IDABBDPrecGetNumGfnEvals", 1, 0);
+
+ printf("-----------------------------------------------------------\n");
+ printf("\nFinal statistics: \n\n");
+
+ printf("Number of steps = %ld\n", nst);
+ printf("Number of residual evaluations = %ld\n", nre+nreLS);
+ printf("Number of nonlinear iterations = %ld\n", nni);
+ printf("Number of error test failures = %ld\n", netf);
+ printf("Number of nonlinear conv. failures = %ld\n\n", ncfn);
+
+ printf("Number of linear iterations = %ld\n", nli);
+ printf("Number of linear conv. failures = %ld\n\n", ncfl);
+
+ printf("Number of preconditioner setups = %ld\n", npe);
+ printf("Number of preconditioner solves = %ld\n", nps);
+ printf("Number of local residual evals. = %ld\n", nge);
+
+}
+
+/*
+ * 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, char *funcname, int opt, int id)
+{
+ int *errflag;
+
+ if (opt == 0 && flagvalue == NULL) {
+ /* Check if SUNDIALS function returned NULL pointer - no memory allocated */
+ fprintf(stderr,
+ "\nSUNDIALS_ERROR(%d): %s() failed - returned NULL pointer\n\n",
+ id, funcname);
+ return(1);
+ } else if (opt == 1) {
+ /* Check if flag < 0 */
+ errflag = (int *) flagvalue;
+ if (*errflag < 0) {
+ fprintf(stderr,
+ "\nSUNDIALS_ERROR(%d): %s() failed with flag = %d\n\n",
+ id, funcname, *errflag);
+ return(1);
+ }
+ } else if (opt == 2 && flagvalue == NULL) {
+ /* Check if function returned NULL pointer - no memory allocated */
+ fprintf(stderr,
+ "\nMEMORY_ERROR(%d): %s() failed - returned NULL pointer\n\n",
+ id, funcname);
+ return(1);
+ }
+
+ return(0);
+}
+
+/*
+ *--------------------------------------------------------------------
+ * FUNCTIONS CALLED BY IDA & SUPPORTING FUNCTIONS
+ *--------------------------------------------------------------------
+ */
+
+/*
+ * res: System residual function
+ *
+ * To compute the residual function F, this routine calls:
+ * rescomm, for needed communication, and then
+ * 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)
+{
+ int retval;
+ UserData data;
+ long int Nlocal;
+
+ data = (UserData) user_data;
+
+ Nlocal = data->n_local;
+
+ /* Call rescomm to do inter-processor communication. */
+ retval = rescomm(Nlocal, tt, uv, uvp, user_data);
+
+ /* Call reslocal to calculate the local portion of residual vector. */
+ retval = reslocal(Nlocal, tt, uv, uvp, rr, user_data);
+
+ return(0);
+}
+
+/*
+ * rescomm: Communication routine in support of resweb.
+ * This routine performs all inter-processor communication of components
+ * of the uv vector needed to calculate F, namely the components at all
+ * interior subgrid boundaries (ghost cell data). It loads this data
+ * into a work array cext (the local portion of c, extended).
+ * 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)
+{
+
+ UserData data;
+ realtype *cdata, *gridext, buffer[2*NUM_SPECIES*MYSUB];
+ int thispe, ixsub, jysub, nsmxsub, nsmysub;
+ MPI_Comm comm;
+ MPI_Request request[4];
+
+ data = (UserData) user_data;
+ cdata = NV_DATA_P(uv);
+
+ /* Get comm, thispe, subgrid indices, data sizes, extended array cext. */
+ comm = data->comm;
+ thispe = data->thispe;
+
+ ixsub = data->ixsub;
+ jysub = data->jysub;
+ gridext = data->gridext;
+ nsmxsub = data->nsmxsub;
+ nsmysub = (data->ns)*(data->mysub);
+
+ /* Start receiving boundary data from neighboring PEs. */
+ BRecvPost(comm, request, thispe, ixsub, jysub, nsmxsub, nsmysub,
+ gridext, buffer);
+
+ /* Send data from boundary of local grid to neighboring PEs. */
+ BSend(comm, thispe, ixsub, jysub, nsmxsub, nsmysub, cdata);
+
+ /* Finish receiving boundary data from neighboring PEs. */
+ BRecvWait(request, ixsub, jysub, nsmxsub, gridext, buffer);
+
+ return(0);
+}
+
+/*
+ * BRecvPost: Start receiving boundary data from neighboring PEs.
+ * (1) buffer should be able to hold 2*NUM_SPECIES*MYSUB realtype entries,
+ * should be passed to both the BRecvPost and BRecvWait functions, and
+ * should not be manipulated between the two calls.
+ * (2) request should have 4 entries, and is also passed in both calls.
+ */
+
+static void BRecvPost(MPI_Comm comm, MPI_Request request[], int my_pe,
+ int ixsub, int jysub,
+ int dsizex, int dsizey,
+ realtype cext[], realtype buffer[])
+{
+ int offsetce;
+ /* Have bufleft and bufright use the same buffer. */
+ realtype *bufleft = buffer, *bufright = buffer+NUM_SPECIES*MYSUB;
+
+ /* If jysub > 0, receive data for bottom x-line of cext. */
+ if (jysub != 0)
+ MPI_Irecv(&cext[NUM_SPECIES], dsizex, PVEC_REAL_MPI_TYPE,
+ my_pe-NPEX, 0, comm, &request[0]);
+
+ /* If jysub < NPEY-1, receive data for top x-line of cext. */
+ if (jysub != NPEY-1) {
+ offsetce = NUM_SPECIES*(1 + (MYSUB+1)*(MXSUB+2));
+ MPI_Irecv(&cext[offsetce], dsizex, PVEC_REAL_MPI_TYPE,
+ my_pe+NPEX, 0, comm, &request[1]);
+ }
+
+ /* If ixsub > 0, receive data for left y-line of cext (via bufleft). */
+ if (ixsub != 0) {
+ MPI_Irecv(&bufleft[0], dsizey, PVEC_REAL_MPI_TYPE,
+ my_pe-1, 0, comm, &request[2]);
+ }
+
+ /* If ixsub < NPEX-1, receive data for right y-line of cext (via bufright). */
+ if (ixsub != NPEX-1) {
+ MPI_Irecv(&bufright[0], dsizey, PVEC_REAL_MPI_TYPE,
+ my_pe+1, 0, comm, &request[3]);
+ }
+}
+
+/*
+ * BRecvWait: Finish receiving boundary data from neighboring PEs.
+ * (1) buffer should be able to hold 2*NUM_SPECIES*MYSUB realtype entries,
+ * should be passed to both the BRecvPost and BRecvWait functions, and
+ * should not be manipulated between the two calls.
+ * (2) request should have 4 entries, and is also passed in both calls.
+ */
+
+static void BRecvWait(MPI_Request request[], int ixsub, int jysub,
+ int dsizex, realtype cext[], realtype buffer[])
+{
+ int i;
+ int ly, dsizex2, offsetce, offsetbuf;
+ realtype *bufleft = buffer, *bufright = buffer+NUM_SPECIES*MYSUB;
+ MPI_Status status;
+
+ dsizex2 = dsizex + 2*NUM_SPECIES;
+
+ /* If jysub > 0, receive data for bottom x-line of cext. */
+ if (jysub != 0)
+ MPI_Wait(&request[0],&status);
+
+ /* If jysub < NPEY-1, receive data for top x-line of cext. */
+ if (jysub != NPEY-1)
+ MPI_Wait(&request[1],&status);
+
+ /* If ixsub > 0, receive data for left y-line of cext (via bufleft). */
+ if (ixsub != 0) {
+ MPI_Wait(&request[2],&status);
+
+ /* Copy the buffer to cext */
+ for (ly = 0; ly < MYSUB; ly++) {
+ offsetbuf = ly*NUM_SPECIES;
+ offsetce = (ly+1)*dsizex2;
+ for (i = 0; i < NUM_SPECIES; i++)
+ cext[offsetce+i] = bufleft[offsetbuf+i];
+ }
+ }
+
+ /* If ixsub < NPEX-1, receive data for right y-line of cext (via bufright). */
+ if (ixsub != NPEX-1) {
+ MPI_Wait(&request[3],&status);
+
+ /* Copy the buffer to cext */
+ for (ly = 0; ly < MYSUB; ly++) {
+ offsetbuf = ly*NUM_SPECIES;
+ offsetce = (ly+2)*dsizex2 - NUM_SPECIES;
+ for (i = 0; i < NUM_SPECIES; i++)
+ cext[offsetce+i] = bufright[offsetbuf+i];
+ }
+ }
+}
+
+/*
+ * BSend: Send boundary data to neighboring PEs.
+ * This routine sends components of uv from internal subgrid boundaries
+ * to the appropriate neighbor PEs.
+ */
+
+static void BSend(MPI_Comm comm, int my_pe, int ixsub, int jysub,
+ int dsizex, int dsizey, realtype cdata[])
+{
+ int i;
+ int ly, offsetc, offsetbuf;
+ realtype bufleft[NUM_SPECIES*MYSUB], bufright[NUM_SPECIES*MYSUB];
+
+ /* If jysub > 0, send data from bottom x-line of uv. */
+
+ if (jysub != 0)
+ MPI_Send(&cdata[0], dsizex, PVEC_REAL_MPI_TYPE, my_pe-NPEX, 0, comm);
+
+ /* If jysub < NPEY-1, send data from top x-line of uv. */
+
+ if (jysub != NPEY-1) {
+ offsetc = (MYSUB-1)*dsizex;
+ MPI_Send(&cdata[offsetc], dsizex, PVEC_REAL_MPI_TYPE, my_pe+NPEX, 0, comm);
+ }
+
+ /* If ixsub > 0, send data from left y-line of uv (via bufleft). */
+
+ if (ixsub != 0) {
+ for (ly = 0; ly < MYSUB; ly++) {
+ offsetbuf = ly*NUM_SPECIES;
+ offsetc = ly*dsizex;
+ for (i = 0; i < NUM_SPECIES; i++)
+ bufleft[offsetbuf+i] = cdata[offsetc+i];
+ }
+ MPI_Send(&bufleft[0], dsizey, PVEC_REAL_MPI_TYPE, my_pe-1, 0, comm);
+ }
+
+ /* If ixsub < NPEX-1, send data from right y-line of uv (via bufright). */
+
+ if (ixsub != NPEX-1) {
+ for (ly = 0; ly < MYSUB; ly++) {
+ offsetbuf = ly*NUM_SPECIES;
+ offsetc = offsetbuf*MXSUB + (MXSUB-1)*NUM_SPECIES;
+ for (i = 0; i < NUM_SPECIES; i++)
+ bufright[offsetbuf+i] = cdata[offsetc+i];
+ }
+ MPI_Send(&bufright[0], dsizey, PVEC_REAL_MPI_TYPE, my_pe+1, 0, comm);
+ }
+}
+
+/* Define lines are for ease of readability in the following functions. */
+
+#define mxsub (data->mxsub)
+#define mysub (data->mysub)
+#define npex (data->npex)
+#define npey (data->npey)
+#define ixsub (data->ixsub)
+#define jysub (data->jysub)
+#define nsmxsub (data->nsmxsub)
+#define nsmxsub2 (data->nsmxsub2)
+#define dx (data->dx)
+#define dy (data->dy)
+#define cox (data->cox)
+#define coy (data->coy)
+#define gridext (data->gridext)
+#define eps (data->eps)
+#define ns (data->ns)
+
+/*
+ * reslocal: Compute res = F(t,uv,uvp).
+ * This routine assumes that all inter-processor communication of data
+ * needed to calculate F has already been done. Components at interior
+ * subgrid boundaries are assumed to be in the work array cext.
+ * The local portion of the uv vector is first copied into cext.
+ * The exterior Neumann boundary conditions are explicitly handled here
+ * by copying data from the first interior mesh line to the ghost cell
+ * locations in cext. Then the reaction and diffusion terms are
+ * evaluated in terms of the cext array, and the residuals are formed.
+ * The reaction terms are saved separately in the vector data->rates
+ * 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)
+{
+ realtype *uvdata, *uvpxy, *resxy, xx, yy, dcyli, dcyui, dcxli, dcxui, dx2, dy2;
+ realtype ixend, ixstart, jystart, jyend;
+ int ix, jy, is, i, locc, ylocce, locce;
+ realtype rates[2];
+ UserData data;
+
+ data = (UserData) user_data;
+
+ /* Get data pointers, subgrid data, array sizes, work array cext. */
+ uvdata = NV_DATA_P(uv);
+
+ dx2 = dx * dx;
+ dy2 = dy * dy;
+
+ /* Copy local segment of uv vector into the working extended array gridext. */
+ locc = 0;
+ locce = nsmxsub2 + NUM_SPECIES;
+ for (jy = 0; jy < mysub; jy++) {
+ for (i = 0; i < nsmxsub; i++) gridext[locce+i] = uvdata[locc+i];
+ locc = locc + nsmxsub;
+ locce = locce + nsmxsub2;
+ }
+
+ /* To facilitate homogeneous Neumann boundary conditions, when this is
+ a boundary PE, copy data from the first interior mesh line of uv to gridext. */
+
+ /* If jysub = 0, copy x-line 2 of uv to gridext. */
+ if (jysub == 0)
+ { for (i = 0; i < nsmxsub; i++) gridext[NUM_SPECIES+i] = uvdata[nsmxsub+i]; }
+
+
+ /* If jysub = npey-1, copy x-line mysub-1 of uv to gridext. */
+ if (jysub == npey-1) {
+ locc = (mysub-2)*nsmxsub;
+ locce = (mysub+1)*nsmxsub2 + NUM_SPECIES;
+ for (i = 0; i < nsmxsub; i++) gridext[locce+i] = uvdata[locc+i];
+ }
+
+
+ /* If ixsub = 0, copy y-line 2 of uv to gridext. */
+ if (ixsub == 0) {
+ for (jy = 0; jy < mysub; jy++) {
+ locc = jy*nsmxsub + NUM_SPECIES;
+ locce = (jy+1)*nsmxsub2;
+ for (i = 0; i < NUM_SPECIES; i++) gridext[locce+i] = uvdata[locc+i];
+ }
+ }
+
+
+ /* If ixsub = npex-1, copy y-line mxsub-1 of uv to gridext. */
+ if (ixsub == npex-1) {
+ for (jy = 0; jy < mysub; jy++) {
+ locc = (jy+1)*nsmxsub - 2*NUM_SPECIES;
+ locce = (jy+2)*nsmxsub2 - NUM_SPECIES;
+ for (i = 0; i < NUM_SPECIES; i++) gridext[locce+i] = uvdata[locc+i];
+ }
+ }
+
+ /* Loop over all grid points, setting local array rates to right-hand sides.
+ Then set rr values appropriately (ODE in the interior and DAE on the boundary)*/
+ ixend = ixstart = jystart = jyend = 0;
+
+ if (jysub==0) jystart = 1;
+ if (jysub==npey-1) jyend = 1;
+ if (ixsub==0) ixstart = 1;
+ if (ixsub==npex-1) ixend = 1;
+
+ for (jy = jystart; jy < mysub-jyend; jy++) {
+ ylocce = (jy+1)*nsmxsub2;
+ yy = (jy+jysub*mysub)*dy;
+
+ for (ix = ixstart; ix < mxsub-ixend; ix++) {
+ locce = ylocce + (ix+1)*NUM_SPECIES;
+ xx = (ix + ixsub*mxsub)*dx;
+
+ ReactRates(xx, yy, &(gridext[locce]), rates, data);
+
+ resxy = IJ_Vptr(rr,ix,jy);
+ uvpxy = IJ_Vptr(uvp,ix,jy);
+
+ for (is = 0; is < NUM_SPECIES; is++) {
+ dcyli = gridext[locce+is] - gridext[locce+is-nsmxsub2];
+ dcyui = gridext[locce+is+nsmxsub2] - gridext[locce+is];
+
+ dcxli = gridext[locce+is] - gridext[locce+is-NUM_SPECIES];
+ dcxui = gridext[locce+is+NUM_SPECIES] - gridext[locce+is];
+
+ resxy[is] = uvpxy[is]-eps[is]*((dcxui-dcxli)/dx2+(dcyui-dcyli)/dy2)-rates[is];
+ }
+ }
+ }
+
+ /* Algebraic equation correspoding to boundary mesh point. */
+ if (jysub==0) {
+ for (ix=0; ix<mxsub; ix++) {
+
+ locce = nsmxsub2 + NUM_SPECIES * (ix+1);
+ resxy = IJ_Vptr(rr,ix,0);
+
+ for (is=0; is<NUM_SPECIES; is++)
+ resxy[is] = gridext[locce+is+nsmxsub2] - gridext[locce+is];
+ }
+ }
+
+ if (ixsub==npex-1) {
+ for(jy=0; jy<mysub; jy++) {
+ locce = (jy+1)*nsmxsub2 + nsmxsub2-NUM_SPECIES;
+ resxy = IJ_Vptr(rr,mxsub-1,jy);
+
+ for (is=0; is<NUM_SPECIES; is++)
+ resxy[is] = gridext[locce+is-NUM_SPECIES] - gridext[locce+is];
+ }
+ }
+
+ if (ixsub==0) {
+ for (jy=0; jy<mysub; jy++) {
+ locce = (jy+1)*nsmxsub2 + NUM_SPECIES;
+ resxy = IJ_Vptr(rr,0,jy);
+
+ for (is=0; is<NUM_SPECIES; is++)
+ resxy[is] = gridext[locce+is-NUM_SPECIES] - gridext[locce+is];
+ }
+ }
+
+ if (jysub==npey-1) {
+ for(ix=0; ix<mxsub; ix++) {
+ locce = nsmxsub2*mysub + (ix+1)*NUM_SPECIES;
+ resxy = IJ_Vptr(rr,ix, mysub-1);
+
+ for (is=0; is<NUM_SPECIES; is++)
+ resxy[is] = gridext[locce+is-nsmxsub2] - gridext[locce+is];
+ }
+ }
+ return(0);
+}
+
+/*
+ * ReactRates: Evaluate reaction rates at a given spatial point.
+ * 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)
+{
+ realtype A, B;
+
+ A = data->A; B = data->B;
+
+ rates[0] = uvval[0]*uvval[0]*uvval[1];
+ rates[1] = - rates[0];
+
+ rates[0] += A-(B+1)*uvval[0];
+ rates[1] += B*uvval[0];
+}
+
+/* Integrate over the spatial domain. Each process computes the integral on its
+ grid. Then processes call MPI_REDUCE to compute sum of the local values. */
+static int integr(MPI_Comm comm, N_Vector uv, void *user_data, realtype *intval)
+{
+ int ix, jy;
+ int retval;
+ realtype *uvdata;
+ UserData data;
+
+ realtype buf[2];
+
+ data = (UserData) user_data;
+
+ /* compute the integral on the (local) grid */
+ uvdata = NV_DATA_P(uv);
+
+ *intval = 0;
+
+ for (jy=1; jy<mysub; jy++)
+ for (ix=1; ix<mxsub; ix++)
+ //consider only u
+ *intval += uvdata[ix*NUM_SPECIES + jy*NSMXSUB];
+ *intval *= (dx*dy);
+
+ buf[0] = *intval;
+
+ /* Sum local values and get the result on all processors. */
+ retval = MPI_Allreduce(buf, buf+1, 1, MPI_DOUBLE, MPI_SUM, comm);
+
+ *intval = buf[1];
+ return(0);
+}
diff --git a/examples/idas/parallel/idasBruss_FSA_kry_bbd_p.out b/examples/idas/parallel/idasBruss_FSA_kry_bbd_p.out
new file mode 100644
index 0000000..a3165f8
--- /dev/null
+++ b/examples/idas/parallel/idasBruss_FSA_kry_bbd_p.out
@@ -0,0 +1,60 @@
+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
+Preconditioner: band-block-diagonal (IDABBDPRE), with parameters
+ mudq = 82, mldq = 82, mukeep = 2, mlkeep = 2
+CalcIC called to correct initial concentrations
+
+-----------------------------------------------------------
+ t bottom-left top-right | nst k h
+-----------------------------------------------------------
+
+0.00e+00 5.0038e-01 1.4996e+00 | 0 0 1.0000e-07
+ 1.0019e+00 5.9981e+00 |
+
+1.00e-03 4.9944e-01 1.5076e+00 | 11 1 5.1200e-04
+ 1.0034e+00 5.9896e+00 |
+
+1.00e-02 4.9119e-01 1.5832e+00 | 17 2 2.0480e-03
+ 1.0170e+00 5.9082e+00 |
+
+1.00e-01 4.2223e-01 3.0684e+00 | 31 4 7.4353e-03
+ 1.1419e+00 4.3097e+00 |
+
+4.00e-01 3.0652e-01 5.4104e+00 | 72 5 7.4353e-03
+ 1.4714e+00 6.1133e-01 |
+
+7.00e-01 2.7048e-01 4.1053e+00 | 112 5 7.4353e-03
+ 1.7403e+00 7.8907e-01 |
+
+1.00e+00 2.6100e-01 3.1024e+00 | 152 5 7.4353e-03
+ 1.9881e+00 1.0113e+00 |
+
+-----------------------------------------------------------
+
+Final statistics:
+
+Number of steps = 152
+Number of residual evaluations = 1243
+Number of nonlinear iterations = 165
+Number of error test failures = 1
+Number of nonlinear conv. failures = 1
+
+Number of linear iterations = 1047
+Number of linear conv. failures = 0
+
+Number of preconditioner setups = 16
+Number of preconditioner solves = 1635
+Number of local residual evals. = 2656
+
+
+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
diff --git a/examples/idas/parallel/idasBruss_kry_bbd_p.c b/examples/idas/parallel/idasBruss_kry_bbd_p.c
new file mode 100644
index 0000000..79b5666
--- /dev/null
+++ b/examples/idas/parallel/idasBruss_kry_bbd_p.c
@@ -0,0 +1,1081 @@
+/* * -----------------------------------------------------------------
+ * $Revision:
+ * $Date:
+ * -----------------------------------------------------------------
+ * Programmer(s): 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.
+ * It is written for a parallel computer system and uses the
+ * IDABBDPRE band-block-diagonal preconditioner module for the
+ * IDASPGMR package.
+ *
+ * The mathematical problem solved in this example is a DAE system
+ * that arises from a system of partial differential equations after
+ * spatial discretization.
+ *
+ * The PDE system is a two-species time-dependent PDE known as
+ * Brusselator PDE and models a chemically reacting system.
+ *
+ *
+ * du/dt = eps(u + u) + u^2 v -(B+1)u + A
+ * xx yy
+ * domain [0,L]X[0,L]
+ * dv/dt = eps(v + v) - u^2 v + Bu
+ * xx yy
+ *
+ * B.C. : Neumann
+ * I.C. : u(x,y,t0) = u0(x,y) = 1 - 0.5*cos(pi*y/L)
+ * v(x,y,t0) = v0(x,y) = 3.5 - 2.5*cos(pi*x/L)
+ *
+ * The PDEs are discretized by central differencing on a MX by MY
+ * mesh, and so the system size Neq is the product MX*MY*NUM_SPECIES.
+ * The system is actually implemented on submeshes, processor by
+ * processor, with an MXSUB by MYSUB mesh on each of NPEX * NPEY
+ * processors.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+
+#include <idas/idas.h>
+#include <idas/idas_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>
+
+#include <mpi.h>
+
+/* Problem Constants */
+#define NUM_SPECIES 2
+#define ctL RCONST(1.0) /* Domain =[0,L]^2 */
+#define ctA RCONST(1.0)
+#define ctB RCONST(3.4)
+#define ctEps RCONST(2.0e-3)
+
+
+#define PI RCONST(3.1415926535898) /* pi */
+
+#define MXSUB 21 /* Number of x mesh points per processor subgrid */
+#define MYSUB 21 /* Number of y mesh points per processor subgrid */
+#define NPEX 2 /* Number of subgrids in the x direction */
+#define NPEY 2 /* Number of subgrids in the y direction */
+#define MX (MXSUB*NPEX) /* MX = number of x mesh points */
+#define MY (MYSUB*NPEY) /* MY = number of y mesh points */
+#define NSMXSUB (NUM_SPECIES * MXSUB)
+#define NEQ (NUM_SPECIES*MX*MY) /* Number of equations in system */
+
+
+#define RTOL RCONST(1.e-5) /* rtol tolerance */
+#define ATOL RCONST(1.e-5) /* atol tolerance */
+#define NOUT 6
+#define TMULT RCONST(10.0) /* Multiplier for tout values */
+#define TADD RCONST(0.3) /* Increment for tout values */
+
+#define ZERO RCONST(0.0)
+#define HALF RCONST(0.5)
+#define ONE RCONST(1.0)
+
+
+/* User-defined vector accessor macro IJ_Vptr. */
+
+/*
+ * IJ_Vptr is defined in order to express the underlying 3-d structure of the
+ * dependent variable vector from its underlying 1-d storage (an N_Vector).
+ * IJ_Vptr(vv,i,j) returns a pointer to the location in vv corresponding to
+ * species index is = 0, x-index ix = i, and y-index jy = j.
+ */
+
+#define IJ_Vptr(vv,i,j) (&NV_Ith_P(vv, (i)*NUM_SPECIES + (j)*NSMXSUB ))
+
+/* Type: UserData. Contains problem constants, preconditioner data, etc. */
+typedef struct {
+ int ns, thispe, npes, ixsub, jysub, npex, npey;
+ int mxsub, mysub, nsmxsub, nsmxsub2;
+ realtype A, B, L, eps[NUM_SPECIES];
+ realtype dx, dy;
+ realtype cox[NUM_SPECIES], coy[NUM_SPECIES];
+ realtype gridext[(MXSUB+2)*(MYSUB+2)*NUM_SPECIES];
+ realtype rhs[NUM_SPECIES];
+ MPI_Comm comm;
+ realtype rates[2];
+ long int 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 reslocal(long int 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);
+
+/* 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,
+ 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);
+
+/* Prototypes for private functions */
+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,
+ realtype rtol, realtype atol);
+
+static void PrintOutput(void *mem, N_Vector uv, realtype time,
+ UserData data, MPI_Comm comm);
+
+static void PrintSol(void* mem, N_Vector uv, N_Vector uvp, UserData data,
+ MPI_Comm comm);
+
+static void PrintFinalStats(void *mem);
+
+static int check_flag(void *flagvalue, char *funcname, int opt, int id);
+
+/*
+ *--------------------------------------------------------------------
+ * MAIN PROGRAM
+ *--------------------------------------------------------------------
+ */
+
+int main(int argc, char *argv[])
+{
+ MPI_Comm comm;
+ void *mem;
+ UserData data;
+ long int 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;
+
+ /* Set communicator, and get processor number and total number of PE's. */
+ MPI_Init(&argc, &argv);
+ comm = MPI_COMM_WORLD;
+ MPI_Comm_rank(comm, &thispe);
+ MPI_Comm_size(comm, &npes);
+
+ if (npes != NPEX*NPEY) {
+ if (thispe == 0)
+ fprintf(stderr,
+ "\nMPI_ERROR(0): npes = %d not equal to NPEX*NPEY = %d\n",
+ npes, NPEX*NPEY);
+ MPI_Finalize();
+ return(1);
+ }
+
+ /* Set local length (local_N) and global length (SystemSize). */
+ local_N = MXSUB*MYSUB*NUM_SPECIES;
+ SystemSize = NEQ;
+
+ /* Set up user data block data. */
+ data = (UserData) malloc(sizeof *data);
+
+ InitUserData(data, thispe, npes, comm);
+
+ /* Create needed vectors, and load initial values.
+ The vector resid is used temporarily only. */
+
+ uv = N_VNew_Parallel(comm, local_N, SystemSize);
+ if(check_flag((void *)uv, "N_VNew_Parallel", 0, thispe)) MPI_Abort(comm, 1);
+
+ uvp = N_VNew_Parallel(comm, local_N, SystemSize);
+ if(check_flag((void *)uvp, "N_VNew_Parallel", 0, thispe)) MPI_Abort(comm, 1);
+
+ resid = N_VNew_Parallel(comm, local_N, SystemSize);
+ if(check_flag((void *)resid, "N_VNew_Parallel", 0, thispe)) MPI_Abort(comm, 1);
+
+ id = N_VNew_Parallel(comm, local_N, SystemSize);
+ if(check_flag((void *)id, "N_VNew_Parallel", 0, thispe)) MPI_Abort(comm, 1);
+
+ SetInitialProfiles(uv, uvp, id, resid, data);
+
+ /* Set remaining inputs to IDAS. */
+ t0 = ZERO;
+ rtol = RTOL;
+ atol = ATOL;
+
+ /* Call IDACreate and IDAInit to initialize solution */
+
+ mem = IDACreate();
+ if(check_flag((void *)mem, "IDACreate", 0, thispe)) MPI_Abort(comm, 1);
+
+ retval = IDASetUserData(mem, data);
+ if(check_flag(&retval, "IDASetUserData", 1, thispe)) MPI_Abort(comm, 1);
+
+ retval = IDASetId(mem, id);
+ if(check_flag(&retval, "IDASetId", 1, thispe)) MPI_Abort(comm, 1);
+
+ retval = IDAInit(mem, res, t0, uv, uvp);
+ if(check_flag(&retval, "IDAInit", 1, thispe)) MPI_Abort(comm, 1);
+
+ retval = IDASStolerances(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 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,
+ 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);
+ if(check_flag(&retval, "IDACalcIC", 1, thispe)) MPI_Abort(comm, 1);
+
+ retval = IDAGetConsistentIC(mem, uv, uvp);
+ if(check_flag(&retval, "IDAGetConsistentIC", 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);
+
+
+ /* 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);
+ if(check_flag(&retval, "IDASolve", 1, thispe)) MPI_Abort(comm, 1);
+
+ PrintOutput(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); */
+
+
+ /* On PE 0, print final set of statistics. */
+ if (thispe == 0) {
+ PrintFinalStats(mem);
+ }
+
+ /* Free memory. */
+ N_VDestroy_Parallel(uv);
+ N_VDestroy_Parallel(uvp);
+ N_VDestroy_Parallel(id);
+ N_VDestroy_Parallel(resid);
+ IDAFree(&mem);
+
+ free(data);
+
+ MPI_Finalize();
+
+ return(0);
+}
+
+/*
+ *--------------------------------------------------------------------
+ * PRIVATE FUNCTIONS
+ *--------------------------------------------------------------------
+ */
+
+/*
+ * InitUserData: Load problem constants in data (of type UserData).
+ */
+
+static void InitUserData(UserData data, int thispe, int npes,
+ MPI_Comm comm)
+{
+ data->jysub = thispe / NPEX;
+ data->ixsub = thispe - (data->jysub)*NPEX;
+ data->mxsub = MXSUB;
+ data->mysub = MYSUB;
+ data->npex = NPEX;
+ data->npey = NPEY;
+ data->ns = NUM_SPECIES;
+ data->dx = ctL/(MX-1);
+ data->dy = ctL/(MY-1);
+ data->thispe = thispe;
+ data->npes = npes;
+ data->nsmxsub = MXSUB * NUM_SPECIES;
+ 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;
+
+
+}
+
+/*
+ * SetInitialProfiles: Set initial conditions in uv, uvp, and id.
+ */
+
+static void SetInitialProfiles(N_Vector uv, N_Vector uvp, N_Vector id,
+ N_Vector resid, UserData data)
+{
+ int ixsub, jysub, mxsub, mysub, nsmxsub, ix, jy;
+ realtype *idxy, dx, dy, x, y, *uvxy, *uvxy1, L, npex, npey;
+
+ ixsub = data->ixsub;
+ jysub = data->jysub;
+ mxsub = data->mxsub;
+ mysub = data->mysub;
+ nsmxsub = data->nsmxsub;
+ npex = data->npex;
+ npey = data->npey;
+ dx = data->dx;
+ dy = data->dy;
+ L = data->L;
+
+ /* Loop over grid, load uv values and id values. */
+ for (jy = 0; jy < mysub; jy++) {
+ y = (jy + jysub*mysub) * dy;
+ for (ix = 0; ix < mxsub; ix++) {
+
+ x = (ix + ixsub*mxsub) * dx;
+ uvxy = IJ_Vptr(uv,ix,jy);
+
+ uvxy[0] = RCONST(1.0) - HALF*cos(PI*y/L);
+ uvxy[1] = RCONST(3.5) - RCONST(2.5)*cos(PI*x/L);
+ }
+ }
+
+ N_VConst(ONE, id);
+
+ if (jysub == 0) {
+ for (ix=0; ix<mxsub; ix++) {
+ idxy = IJ_Vptr(id,ix,0);
+ idxy[0] = idxy[1] = ZERO;
+
+ uvxy = IJ_Vptr(uv,ix,0);
+ uvxy1 = IJ_Vptr(uv,ix,1);
+ uvxy[0] = uvxy1[0];
+ uvxy[1] = uvxy1[1];
+ }
+ }
+
+ if (ixsub == npex-1) {
+ for (jy = 0; jy < mysub; jy++) {
+ idxy = IJ_Vptr(id,mxsub-1,jy);
+ idxy[0] = idxy[1] = ZERO;
+
+ uvxy = IJ_Vptr(uv,mxsub-1,jy);
+ uvxy1 = IJ_Vptr(uv,mxsub-2,jy);
+ uvxy[0] = uvxy1[0];
+ uvxy[1] = uvxy1[1];
+
+ }
+ }
+
+
+ if (ixsub == 0) {
+ for (jy = 0; jy < mysub; jy++) {
+ idxy = IJ_Vptr(id,0,jy);
+ idxy[0] = idxy[1] = ZERO;
+
+ uvxy = IJ_Vptr(uv,0,jy);
+ uvxy1 = IJ_Vptr(uv,1,jy);
+ uvxy[0] = uvxy1[0];
+ uvxy[1] = uvxy1[1];
+
+ }
+ }
+
+ if (jysub == npey-1) {
+ for (ix=0; ix<mxsub; ix++) {
+ idxy = IJ_Vptr(id,ix,jysub);
+ idxy[0] = idxy[1] = ZERO;
+
+ uvxy = IJ_Vptr(uv,ix,mysub-1);
+ uvxy1 = IJ_Vptr(uv,ix,mysub-2);
+ uvxy[0] = uvxy1[0];
+ uvxy[1] = uvxy1[1];
+
+ }
+ }
+
+ /* Derivative found by calling the residual function with uvp = 0. */
+ N_VConst(ZERO, uvp);
+ res(ZERO, uv, uvp, resid, data);
+ N_VScale(-ONE, resid, uvp);
+
+
+}
+
+/*
+ * Print first lines of output (problem description)
+ * and table headerr
+ */
+
+static void PrintHeader(int SystemSize, int maxl,
+ long int mudq, long int mldq,
+ long int mukeep, long int 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("Subgrid dimensions: %d x %d", MXSUB, MYSUB);
+ printf(" Processor array: %d x %d\n", NPEX, NPEY);
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("Tolerance parameters: rtol = %Lg atol = %Lg\n", rtol, atol);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("Tolerance parameters: rtol = %lg atol = %lg\n", rtol, atol);
+#else
+ printf("Tolerance parameters: rtol = %g atol = %g\n", rtol, atol);
+#endif
+ printf("Linear solver: IDASPGMR 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("CalcIC called to correct initial guesses \n\n");
+ printf("-----------------------------------------------------------\n");
+ printf(" t bottom-left top-right");
+ printf(" | nst k h\n");
+ printf("-----------------------------------------------------------\n\n");
+}
+
+
+/*
+ * PrintOutput: Print output values at output time t = tt.
+ * Selected run statistics are printed. Then values of c1 and c2
+ * are printed for the bottom left and top right grid points only.
+ */
+
+static void PrintOutput(void *mem, N_Vector uv, realtype tt,
+ UserData data, MPI_Comm comm)
+{
+ MPI_Status status;
+ realtype *cdata, clast[2], hused;
+ long int nst;
+ int i, kused, flag, thispe, npelast, ilast;;
+
+ thispe = data->thispe;
+ npelast = data->npes - 1;
+ cdata = NV_DATA_P(uv);
+
+ /* Send conc. at top right mesh point from PE npes-1 to PE 0. */
+ if (thispe == npelast) {
+ ilast = NUM_SPECIES*MXSUB*MYSUB - 2;
+ if (npelast != 0)
+ MPI_Send(&cdata[ilast], 2, PVEC_REAL_MPI_TYPE, 0, 0, comm);
+ else { clast[0] = cdata[ilast]; clast[1] = cdata[ilast+1]; }
+ }
+
+ /* On PE 0, receive conc. at top right from PE npes - 1.
+ Then print performance data and sampled solution values. */
+ if (thispe == 0) {
+
+ if (npelast != 0)
+ MPI_Recv(&clast[0], 2, PVEC_REAL_MPI_TYPE, npelast, 0, comm, &status);
+
+ flag = IDAGetLastOrder(mem, &kused);
+ check_flag(&flag, "IDAGetLastOrder", 1, thispe);
+ flag = IDAGetNumSteps(mem, &nst);
+ check_flag(&flag, "IDAGetNumSteps", 1, thispe);
+ flag = IDAGetLastStep(mem, &hused);
+ check_flag(&flag, "IDAGetLastStep", 1, thispe);
+
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("%8.2Le %12.4Le %12.4Le | %3ld %1d %12.4Le\n",
+ tt, cdata[0], clast[0], nst, kused, hused);
+ for (i=1;i<NUM_SPECIES;i++)
+ printf(" %12.4Le %12.4Le |\n",cdata[i],clast[i]);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("%8.2le %12.4le %12.4le | %3ld %1d %12.4le\n",
+ tt, cdata[0], clast[0], nst, kused, hused);
+ for (i=1;i<NUM_SPECIES;i++)
+ printf(" %12.4le %12.4le |\n",cdata[i],clast[i]);
+#else
+ printf("%8.2e %12.4e %12.4e | %3ld %1d %12.4e\n",
+ tt, cdata[0], clast[0], nst, kused, hused);
+ for (i=1;i<NUM_SPECIES;i++)
+ printf(" %12.4e %12.4e |\n",cdata[i],clast[i]);
+#endif
+ printf("\n");
+
+ }
+
+}
+
+/*
+ * PrintSol the PE's portion of the solution to a file.
+ */
+static void PrintSol(void* mem, N_Vector uv, N_Vector uvp,
+ UserData data, MPI_Comm comm)
+{
+ FILE* fout;
+ realtype *uvxy;
+ int ix, jy, mxsub, mysub, thispe;
+ char szFilename[128];
+
+ thispe = data->thispe;
+ sprintf(szFilename, "ysol%d.txt", thispe);
+
+ fout = fopen(szFilename, "w+");
+ if (fout==NULL) {
+ printf("PE[% 2d] is unable to write solution to disk!\n", thispe);
+ return;
+ }
+
+ mxsub = data->mxsub;
+ mysub = data->mysub;
+
+ for (jy=0; jy<mysub; jy++) {
+ for (ix=0; ix<mxsub; ix++) {
+
+ uvxy = IJ_Vptr(uv, ix, jy);
+ fprintf(fout, "%g\n%g\n", uvxy[0], uvxy[1]);
+ }
+ }
+ fclose(fout);
+}
+
+
+
+/*
+ * PrintFinalStats: Print final run data contained in iopt.
+ */
+
+static void PrintFinalStats(void *mem)
+{
+ long int nst, nre, nreLS, netf, ncfn, nni, ncfl, nli, npe, nps, nge;
+ int flag;
+
+ flag = IDAGetNumSteps(mem, &nst);
+ check_flag(&flag, "IDAGetNumSteps", 1, 0);
+ flag = IDAGetNumResEvals(mem, &nre);
+ check_flag(&flag, "IDAGetNumResEvals", 1, 0);
+ flag = IDAGetNumErrTestFails(mem, &netf);
+ check_flag(&flag, "IDAGetNumErrTestFails", 1, 0);
+ flag = IDAGetNumNonlinSolvConvFails(mem, &ncfn);
+ check_flag(&flag, "IDAGetNumNonlinSolvConvFails", 1, 0);
+ flag = IDAGetNumNonlinSolvIters(mem, &nni);
+ check_flag(&flag, "IDAGetNumNonlinSolvIters", 1, 0);
+
+ flag = IDASpilsGetNumConvFails(mem, &ncfl);
+ check_flag(&flag, "IDASpilsGetNumConvFails", 1, 0);
+ flag = IDASpilsGetNumLinIters(mem, &nli);
+ check_flag(&flag, "IDASpilsGetNumLinIters", 1, 0);
+ flag = IDASpilsGetNumPrecEvals(mem, &npe);
+ check_flag(&flag, "IDASpilsGetNumPrecEvals", 1, 0);
+ flag = IDASpilsGetNumPrecSolves(mem, &nps);
+ check_flag(&flag, "IDASpilsGetNumPrecSolves", 1, 0);
+ flag = IDASpilsGetNumResEvals(mem, &nreLS);
+ check_flag(&flag, "IDASpilsGetNumResEvals", 1, 0);
+
+ flag = IDABBDPrecGetNumGfnEvals(mem, &nge);
+ check_flag(&flag, "IDABBDPrecGetNumGfnEvals", 1, 0);
+
+ printf("-----------------------------------------------------------\n");
+ printf("\nFinal statistics: \n\n");
+
+ printf("Number of steps = %ld\n", nst);
+ printf("Number of residual evaluations = %ld\n", nre+nreLS);
+ printf("Number of nonlinear iterations = %ld\n", nni);
+ printf("Number of error test failures = %ld\n", netf);
+ printf("Number of nonlinear conv. failures = %ld\n\n", ncfn);
+
+ printf("Number of linear iterations = %ld\n", nli);
+ printf("Number of linear conv. failures = %ld\n\n", ncfl);
+
+ printf("Number of preconditioner setups = %ld\n", npe);
+ printf("Number of preconditioner solves = %ld\n", nps);
+ printf("Number of local residual evals. = %ld\n", nge);
+
+}
+
+/*
+ * 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, char *funcname, int opt, int id)
+{
+ int *errflag;
+
+ if (opt == 0 && flagvalue == NULL) {
+ /* Check if SUNDIALS function returned NULL pointer - no memory allocated */
+ fprintf(stderr,
+ "\nSUNDIALS_ERROR(%d): %s() failed - returned NULL pointer\n\n",
+ id, funcname);
+ return(1);
+ } else if (opt == 1) {
+ /* Check if flag < 0 */
+ errflag = (int *) flagvalue;
+ if (*errflag < 0) {
+ fprintf(stderr,
+ "\nSUNDIALS_ERROR(%d): %s() failed with flag = %d\n\n",
+ id, funcname, *errflag);
+ return(1);
+ }
+ } else if (opt == 2 && flagvalue == NULL) {
+ /* Check if function returned NULL pointer - no memory allocated */
+ fprintf(stderr,
+ "\nMEMORY_ERROR(%d): %s() failed - returned NULL pointer\n\n",
+ id, funcname);
+ return(1);
+ }
+
+ return(0);
+}
+
+/*
+ *--------------------------------------------------------------------
+ * FUNCTIONS CALLED BY IDA & SUPPORTING FUNCTIONS
+ *--------------------------------------------------------------------
+ */
+
+/*
+ * res: System residual function
+ *
+ * To compute the residual function F, this routine calls:
+ * rescomm, for needed communication, and then
+ * 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)
+{
+ int retval;
+ UserData data;
+ long int Nlocal;
+
+ data = (UserData) user_data;
+
+ Nlocal = data->n_local;
+
+ /* Call rescomm to do inter-processor communication. */
+ retval = rescomm(Nlocal, tt, uv, uvp, user_data);
+
+ /* Call reslocal to calculate the local portion of residual vector. */
+ retval = reslocal(Nlocal, tt, uv, uvp, rr, user_data);
+
+ return(0);
+}
+
+/*
+ * rescomm: Communication routine in support of resweb.
+ * This routine performs all inter-processor communication of components
+ * of the uv vector needed to calculate F, namely the components at all
+ * interior subgrid boundaries (ghost cell data). It loads this data
+ * into a work array cext (the local portion of c, extended).
+ * 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)
+{
+
+ UserData data;
+ realtype *cdata, *gridext, buffer[2*NUM_SPECIES*MYSUB];
+ int thispe, ixsub, jysub, nsmxsub, nsmysub;
+ MPI_Comm comm;
+ MPI_Request request[4];
+
+ data = (UserData) user_data;
+ cdata = NV_DATA_P(uv);
+
+ /* Get comm, thispe, subgrid indices, data sizes, extended array cext. */
+ comm = data->comm;
+ thispe = data->thispe;
+
+ ixsub = data->ixsub;
+ jysub = data->jysub;
+ gridext = data->gridext;
+ nsmxsub = data->nsmxsub;
+ nsmysub = (data->ns)*(data->mysub);
+
+ /* Start receiving boundary data from neighboring PEs. */
+ BRecvPost(comm, request, thispe, ixsub, jysub, nsmxsub, nsmysub,
+ gridext, buffer);
+
+ /* Send data from boundary of local grid to neighboring PEs. */
+ BSend(comm, thispe, ixsub, jysub, nsmxsub, nsmysub, cdata);
+
+ /* Finish receiving boundary data from neighboring PEs. */
+ BRecvWait(request, ixsub, jysub, nsmxsub, gridext, buffer);
+
+ return(0);
+}
+
+/*
+ * BRecvPost: Start receiving boundary data from neighboring PEs.
+ * (1) buffer should be able to hold 2*NUM_SPECIES*MYSUB realtype entries,
+ * should be passed to both the BRecvPost and BRecvWait functions, and
+ * should not be manipulated between the two calls.
+ * (2) request should have 4 entries, and is also passed in both calls.
+ */
+
+static void BRecvPost(MPI_Comm comm, MPI_Request request[], int my_pe,
+ int ixsub, int jysub,
+ int dsizex, int dsizey,
+ realtype cext[], realtype buffer[])
+{
+ int offsetce;
+ /* Have bufleft and bufright use the same buffer. */
+ realtype *bufleft = buffer, *bufright = buffer+NUM_SPECIES*MYSUB;
+
+ /* If jysub > 0, receive data for bottom x-line of cext. */
+ if (jysub != 0)
+ MPI_Irecv(&cext[NUM_SPECIES], dsizex, PVEC_REAL_MPI_TYPE,
+ my_pe-NPEX, 0, comm, &request[0]);
+
+ /* If jysub < NPEY-1, receive data for top x-line of cext. */
+ if (jysub != NPEY-1) {
+ offsetce = NUM_SPECIES*(1 + (MYSUB+1)*(MXSUB+2));
+ MPI_Irecv(&cext[offsetce], dsizex, PVEC_REAL_MPI_TYPE,
+ my_pe+NPEX, 0, comm, &request[1]);
+ }
+
+ /* If ixsub > 0, receive data for left y-line of cext (via bufleft). */
+ if (ixsub != 0) {
+ MPI_Irecv(&bufleft[0], dsizey, PVEC_REAL_MPI_TYPE,
+ my_pe-1, 0, comm, &request[2]);
+ }
+
+ /* If ixsub < NPEX-1, receive data for right y-line of cext (via bufright). */
+ if (ixsub != NPEX-1) {
+ MPI_Irecv(&bufright[0], dsizey, PVEC_REAL_MPI_TYPE,
+ my_pe+1, 0, comm, &request[3]);
+ }
+}
+
+/*
+ * BRecvWait: Finish receiving boundary data from neighboring PEs.
+ * (1) buffer should be able to hold 2*NUM_SPECIES*MYSUB realtype entries,
+ * should be passed to both the BRecvPost and BRecvWait functions, and
+ * should not be manipulated between the two calls.
+ * (2) request should have 4 entries, and is also passed in both calls.
+ */
+
+static void BRecvWait(MPI_Request request[], int ixsub, int jysub,
+ int dsizex, realtype cext[], realtype buffer[])
+{
+ int i;
+ int ly, dsizex2, offsetce, offsetbuf;
+ realtype *bufleft = buffer, *bufright = buffer+NUM_SPECIES*MYSUB;
+ MPI_Status status;
+
+ dsizex2 = dsizex + 2*NUM_SPECIES;
+
+ /* If jysub > 0, receive data for bottom x-line of cext. */
+ if (jysub != 0)
+ MPI_Wait(&request[0],&status);
+
+ /* If jysub < NPEY-1, receive data for top x-line of cext. */
+ if (jysub != NPEY-1)
+ MPI_Wait(&request[1],&status);
+
+ /* If ixsub > 0, receive data for left y-line of cext (via bufleft). */
+ if (ixsub != 0) {
+ MPI_Wait(&request[2],&status);
+
+ /* Copy the buffer to cext */
+ for (ly = 0; ly < MYSUB; ly++) {
+ offsetbuf = ly*NUM_SPECIES;
+ offsetce = (ly+1)*dsizex2;
+ for (i = 0; i < NUM_SPECIES; i++)
+ cext[offsetce+i] = bufleft[offsetbuf+i];
+ }
+ }
+
+ /* If ixsub < NPEX-1, receive data for right y-line of cext (via bufright). */
+ if (ixsub != NPEX-1) {
+ MPI_Wait(&request[3],&status);
+
+ /* Copy the buffer to cext */
+ for (ly = 0; ly < MYSUB; ly++) {
+ offsetbuf = ly*NUM_SPECIES;
+ offsetce = (ly+2)*dsizex2 - NUM_SPECIES;
+ for (i = 0; i < NUM_SPECIES; i++)
+ cext[offsetce+i] = bufright[offsetbuf+i];
+ }
+ }
+}
+
+/*
+ * BSend: Send boundary data to neighboring PEs.
+ * This routine sends components of uv from internal subgrid boundaries
+ * to the appropriate neighbor PEs.
+ */
+
+static void BSend(MPI_Comm comm, int my_pe, int ixsub, int jysub,
+ int dsizex, int dsizey, realtype cdata[])
+{
+ int i;
+ int ly, offsetc, offsetbuf;
+ realtype bufleft[NUM_SPECIES*MYSUB], bufright[NUM_SPECIES*MYSUB];
+
+ /* If jysub > 0, send data from bottom x-line of uv. */
+
+ if (jysub != 0)
+ MPI_Send(&cdata[0], dsizex, PVEC_REAL_MPI_TYPE, my_pe-NPEX, 0, comm);
+
+ /* If jysub < NPEY-1, send data from top x-line of uv. */
+
+ if (jysub != NPEY-1) {
+ offsetc = (MYSUB-1)*dsizex;
+ MPI_Send(&cdata[offsetc], dsizex, PVEC_REAL_MPI_TYPE, my_pe+NPEX, 0, comm);
+ }
+
+ /* If ixsub > 0, send data from left y-line of uv (via bufleft). */
+
+ if (ixsub != 0) {
+ for (ly = 0; ly < MYSUB; ly++) {
+ offsetbuf = ly*NUM_SPECIES;
+ offsetc = ly*dsizex;
+ for (i = 0; i < NUM_SPECIES; i++)
+ bufleft[offsetbuf+i] = cdata[offsetc+i];
+ }
+ MPI_Send(&bufleft[0], dsizey, PVEC_REAL_MPI_TYPE, my_pe-1, 0, comm);
+ }
+
+ /* If ixsub < NPEX-1, send data from right y-line of uv (via bufright). */
+
+ if (ixsub != NPEX-1) {
+ for (ly = 0; ly < MYSUB; ly++) {
+ offsetbuf = ly*NUM_SPECIES;
+ offsetc = offsetbuf*MXSUB + (MXSUB-1)*NUM_SPECIES;
+ for (i = 0; i < NUM_SPECIES; i++)
+ bufright[offsetbuf+i] = cdata[offsetc+i];
+ }
+ MPI_Send(&bufright[0], dsizey, PVEC_REAL_MPI_TYPE, my_pe+1, 0, comm);
+ }
+}
+
+/* Define lines are for ease of readability in the following functions. */
+
+#define mxsub (data->mxsub)
+#define mysub (data->mysub)
+#define npex (data->npex)
+#define npey (data->npey)
+#define ixsub (data->ixsub)
+#define jysub (data->jysub)
+#define nsmxsub (data->nsmxsub)
+#define nsmxsub2 (data->nsmxsub2)
+#define dx (data->dx)
+#define dy (data->dy)
+#define cox (data->cox)
+#define coy (data->coy)
+#define gridext (data->gridext)
+#define eps (data->eps)
+#define ns (data->ns)
+
+/*
+ * reslocal: Compute res = F(t,uv,uvp).
+ * This routine assumes that all inter-processor communication of data
+ * needed to calculate F has already been done. Components at interior
+ * subgrid boundaries are assumed to be in the work array cext.
+ * The local portion of the uv vector is first copied into cext.
+ * The exterior Neumann boundary conditions are explicitly handled here
+ * by copying data from the first interior mesh line to the ghost cell
+ * locations in cext. Then the reaction and diffusion terms are
+ * evaluated in terms of the cext array, and the residuals are formed.
+ * The reaction terms are saved separately in the vector data->rates
+ * 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)
+{
+ realtype *uvdata, *uvpxy, *resxy, xx, yy, dcyli, dcyui, dcxli, dcxui, dx2, dy2;
+ realtype ixend, ixstart, jystart, jyend;
+ int ix, jy, is, i, locc, ylocce, locce;
+ realtype rates[2];
+ UserData data;
+
+ data = (UserData) user_data;
+
+ /* Get data pointers, subgrid data, array sizes, work array cext. */
+ uvdata = NV_DATA_P(uv);
+
+ dx2 = dx * dx;
+ dy2 = dy * dy;
+
+ /* Copy local segment of uv vector into the working extended array gridext. */
+ locc = 0;
+ locce = nsmxsub2 + NUM_SPECIES;
+ for (jy = 0; jy < mysub; jy++) {
+ for (i = 0; i < nsmxsub; i++) gridext[locce+i] = uvdata[locc+i];
+ locc = locc + nsmxsub;
+ locce = locce + nsmxsub2;
+ }
+
+ /* To facilitate homogeneous Neumann boundary conditions, when this is
+ a boundary PE, copy data from the first interior mesh line of uv to gridext. */
+
+ /* If jysub = 0, copy x-line 2 of uv to gridext. */
+ if (jysub == 0)
+ { for (i = 0; i < nsmxsub; i++) gridext[NUM_SPECIES+i] = uvdata[nsmxsub+i]; }
+
+
+ /* If jysub = npey-1, copy x-line mysub-1 of uv to gridext. */
+ if (jysub == npey-1) {
+ locc = (mysub-2)*nsmxsub;
+ locce = (mysub+1)*nsmxsub2 + NUM_SPECIES;
+ for (i = 0; i < nsmxsub; i++) gridext[locce+i] = uvdata[locc+i];
+ }
+
+
+ /* If ixsub = 0, copy y-line 2 of uv to gridext. */
+ if (ixsub == 0) {
+ for (jy = 0; jy < mysub; jy++) {
+ locc = jy*nsmxsub + NUM_SPECIES;
+ locce = (jy+1)*nsmxsub2;
+ for (i = 0; i < NUM_SPECIES; i++) gridext[locce+i] = uvdata[locc+i];
+ }
+ }
+
+
+ /* If ixsub = npex-1, copy y-line mxsub-1 of uv to gridext. */
+ if (ixsub == npex-1) {
+ for (jy = 0; jy < mysub; jy++) {
+ locc = (jy+1)*nsmxsub - 2*NUM_SPECIES;
+ locce = (jy+2)*nsmxsub2 - NUM_SPECIES;
+ for (i = 0; i < NUM_SPECIES; i++) gridext[locce+i] = uvdata[locc+i];
+ }
+ }
+
+ /* Loop over all grid points, setting local array rates to right-hand sides.
+ Then set rr values appropriately (ODE in the interior and DAE on the boundary)*/
+ ixend = ixstart = jystart = jyend = 0;
+
+ if (jysub==0) jystart = 1;
+ if (jysub==npey-1) jyend = 1;
+ if (ixsub==0) ixstart = 1;
+ if (ixsub==npex-1) ixend = 1;
+
+ for (jy = jystart; jy < mysub-jyend; jy++) {
+ ylocce = (jy+1)*nsmxsub2;
+ yy = (jy+jysub*mysub)*dy;
+
+ for (ix = ixstart; ix < mxsub-ixend; ix++) {
+ locce = ylocce + (ix+1)*NUM_SPECIES;
+ xx = (ix + ixsub*mxsub)*dx;
+
+ ReactRates(xx, yy, &(gridext[locce]), rates, data);
+
+ resxy = IJ_Vptr(rr,ix,jy);
+ uvpxy = IJ_Vptr(uvp,ix,jy);
+
+ for (is = 0; is < NUM_SPECIES; is++) {
+ dcyli = gridext[locce+is] - gridext[locce+is-nsmxsub2];
+ dcyui = gridext[locce+is+nsmxsub2] - gridext[locce+is];
+
+ dcxli = gridext[locce+is] - gridext[locce+is-NUM_SPECIES];
+ dcxui = gridext[locce+is+NUM_SPECIES] - gridext[locce+is];
+
+ resxy[is] = uvpxy[is]- eps[is]*( (dcxui-dcxli)/dx2 + (dcyui-dcyli)/dy2 ) - rates[is];
+ }
+ }
+ }
+
+ /* Algebraic equation correspoding to boundary mesh point. */
+ if (jysub==0) {
+ for (ix=0; ix<mxsub; ix++) {
+
+ locce = nsmxsub2 + NUM_SPECIES * (ix+1);
+ resxy = IJ_Vptr(rr,ix,0);
+
+ for (is=0; is<NUM_SPECIES; is++)
+ resxy[is] = gridext[locce+is+nsmxsub2] - gridext[locce+is];
+ }
+ }
+
+ if (ixsub==npex-1) {
+ for(jy=0; jy<mysub; jy++) {
+ locce = (jy+1)*nsmxsub2 + nsmxsub2-NUM_SPECIES;
+ resxy = IJ_Vptr(rr,mxsub-1,jy);
+
+ for (is=0; is<NUM_SPECIES; is++)
+ resxy[is] = gridext[locce+is-NUM_SPECIES] - gridext[locce+is];
+ }
+ }
+
+ if (ixsub==0) {
+ for (jy=0; jy<mysub; jy++) {
+ locce = (jy+1)*nsmxsub2 + NUM_SPECIES;
+ resxy = IJ_Vptr(rr,0,jy);
+
+ for (is=0; is<NUM_SPECIES; is++)
+ resxy[is] = gridext[locce+is-NUM_SPECIES] - gridext[locce+is];
+ }
+ }
+
+ if (jysub==npey-1) {
+ for(ix=0; ix<mxsub; ix++) {
+ locce = nsmxsub2*mysub + (ix+1)*NUM_SPECIES;
+ resxy = IJ_Vptr(rr,ix, mysub-1);
+
+ for (is=0; is<NUM_SPECIES; is++)
+ resxy[is] = gridext[locce+is-nsmxsub2] - gridext[locce+is];
+ }
+ }
+ return(0);
+}
+
+/*
+ * ReactRates: Evaluate reaction rates at a given spatial point.
+ * 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)
+{
+ realtype A, B;
+
+ A = data->A; B = data->B;
+
+ rates[0] = uvval[0]*uvval[0]*uvval[1];
+ rates[1] = - rates[0];
+
+ rates[0] += A-(B+1)*uvval[0];
+ rates[1] += B*uvval[0];
+}
diff --git a/examples/idas/parallel/idasBruss_kry_bbd_p.out b/examples/idas/parallel/idasBruss_kry_bbd_p.out
new file mode 100644
index 0000000..3afac54
--- /dev/null
+++ b/examples/idas/parallel/idasBruss_kry_bbd_p.out
@@ -0,0 +1,51 @@
+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
+Preconditioner: band-block-diagonal (IDABBDPRE), with parameters
+ mudq = 42, mldq = 42, mukeep = 2, mlkeep = 2
+CalcIC called to correct initial guesses
+
+-----------------------------------------------------------
+ t bottom-left top-right | nst k h
+-----------------------------------------------------------
+
+0.00e+00 5.0147e-01 1.4985e+00 | 0 0 1.0000e-06
+ 1.0073e+00 5.9927e+00 |
+
+1.00e-03 5.0053e-01 1.5064e+00 | 11 1 5.1200e-04
+ 1.0089e+00 5.9842e+00 |
+
+1.00e-02 4.9226e-01 1.5818e+00 | 17 2 2.0480e-03
+ 1.0225e+00 5.9031e+00 |
+
+1.00e-01 4.2319e-01 3.0579e+00 | 29 4 1.1822e-02
+ 1.1480e+00 4.3135e+00 |
+
+4.00e-01 3.0714e-01 5.4048e+00 | 74 5 6.2824e-03
+ 1.4797e+00 6.1197e-01 |
+
+7.00e-01 2.7089e-01 4.1003e+00 | 122 5 6.2824e-03
+ 1.7503e+00 7.8994e-01 |
+
+1.00e+00 2.6132e-01 3.0981e+00 | 169 5 1.2565e-02
+ 1.9993e+00 1.0125e+00 |
+
+-----------------------------------------------------------
+
+Final statistics:
+
+Number of steps = 169
+Number of residual evaluations = 423
+Number of nonlinear iterations = 188
+Number of error test failures = 1
+Number of nonlinear conv. failures = 0
+
+Number of linear iterations = 233
+Number of linear conv. failures = 0
+
+Number of preconditioner setups = 17
+Number of preconditioner solves = 423
+Number of local residual evals. = 1462
diff --git a/examples/idas/parallel/idasFoodWeb_kry_bbd_p.c b/examples/idas/parallel/idasFoodWeb_kry_bbd_p.c
new file mode 100644
index 0000000..2b7ee32
--- /dev/null
+++ b/examples/idas/parallel/idasFoodWeb_kry_bbd_p.c
@@ -0,0 +1,1090 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.2 $
+ * $Date: 2010/12/01 23:06:37 $
+ * -----------------------------------------------------------------
+ * Programmer(s): 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.
+ * 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.
+ *
+ * The mathematical problem solved in this example is a DAE system
+ * that arises from a system of partial differential equations after
+ * spatial discretization. The PDE system is a food web population
+ * model, with predator-prey interaction and diffusion on the unit
+ * square in two dimensions. The dependent variable vector is:
+ *
+ * 1 2 ns
+ * c = (c , c , ..., c ) , ns = 2 * np
+ *
+ * and the PDE's are as follows:
+ *
+ * i i i
+ * dc /dt = d(i)*(c + c ) + R (x,y,c) (i = 1,...,np)
+ * xx yy i
+ *
+ * i i
+ * 0 = d(i)*(c + c ) + R (x,y,c) (i = np+1,...,ns)
+ * xx yy i
+ *
+ * where the reaction terms R are:
+ *
+ * i ns j
+ * R (x,y,c) = c * (b(i) + sum a(i,j)*c )
+ * i j=1
+ *
+ * The number of species is ns = 2 * np, with the first np being
+ * prey and the last np being predators. The coefficients a(i,j),
+ * b(i), d(i) are:
+ *
+ * a(i,i) = -AA (all i)
+ * a(i,j) = -GG (i <= np , j > np)
+ * a(i,j) = EE (i > np, j <= np)
+ * all other a(i,j) = 0
+ * b(i) = BB*(1+ alpha * x*y + beta*sin(4 pi x)*sin(4 pi y)) (i <= np)
+ * b(i) =-BB*(1+ alpha * x*y + beta*sin(4 pi x)*sin(4 pi y)) (i > np)
+ * d(i) = DPREY (i <= np)
+ * d(i) = DPRED (i > np)
+ *
+ * Note: The above equations are written in 1-based indices,
+ * whereas the code has 0-based indices, being written in C.
+ *
+ * The various scalar parameters required are set using '#define'
+ * statements or directly in routine InitUserData. In this program,
+ * np = 1, ns = 2. The boundary conditions are homogeneous Neumann:
+ * normal derivative = 0.
+ *
+ * A polynomial in x and y is used to set the initial values of the
+ * first np variables (the prey variables) at each x,y location,
+ * while initial values for the remaining (predator) variables are
+ * set to a flat value, which is corrected by IDACalcIC.
+ *
+ * The PDEs are discretized by central differencing on a MX by MY
+ * mesh, and so the system size Neq is the product
+ * MX * MY * NUM_SPECIES. The system is actually implemented on
+ * 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,
+ * in conjunction with the preconditioner module IDABBDPRE. The
+ * preconditioner uses a 5-diagonal band-block-diagonal
+ * approximation (half-bandwidths = 2). Output is printed at
+ * t = 0, .001, .01, .1, .4, .7, 1.
+ * -----------------------------------------------------------------
+ * References:
+ * [1] Peter N. Brown and Alan C. Hindmarsh,
+ * Reduced Storage Matrix Methods in Stiff ODE systems,
+ * Journal of Applied Mathematics and Computation, Vol. 31
+ * (May 1989), pp. 40-91.
+ *
+ * [2] Peter N. Brown, Alan C. Hindmarsh, and Linda R. Petzold,
+ * Using Krylov Methods in the Solution of Large-Scale
+ * Differential-Algebraic Systems, SIAM J. Sci. Comput., 15
+ * (1994), pp. 1467-1488.
+ *
+ * [3] Peter N. Brown, Alan C. Hindmarsh, and Linda R. Petzold,
+ * 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_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>
+
+#include <mpi.h>
+
+/* Problem Constants */
+
+#define NPREY 1 /* Number of prey (= number of predators). */
+#define NUM_SPECIES 2*NPREY
+
+#define PI RCONST(3.1415926535898) /* pi */
+#define FOURPI (RCONST(4.0)*PI) /* 4 pi */
+
+#define MXSUB 10 /* Number of x mesh points per processor subgrid */
+#define MYSUB 10 /* Number of y mesh points per processor subgrid */
+#define NPEX 2 /* Number of subgrids in the x direction */
+#define NPEY 2 /* Number of subgrids in the y direction */
+#define MX (MXSUB*NPEX) /* MX = number of x mesh points */
+#define MY (MYSUB*NPEY) /* MY = number of y mesh points */
+#define NSMXSUB (NUM_SPECIES * MXSUB)
+#define NEQ (NUM_SPECIES*MX*MY) /* Number of equations in system */
+#define AA RCONST(1.0) /* Coefficient in above eqns. for a */
+#define EE RCONST(10000.) /* Coefficient in above eqns. for a */
+#define GG RCONST(0.5e-6) /* Coefficient in above eqns. for a */
+#define BB RCONST(1.0) /* Coefficient in above eqns. for b */
+#define DPREY RCONST(1.0) /* Coefficient in above eqns. for d */
+#define DPRED RCONST(0.05) /* Coefficient in above eqns. for d */
+#define ALPHA RCONST(50.) /* Coefficient alpha in above eqns. */
+#define BETA RCONST(1000.) /* Coefficient beta in above eqns. */
+#define AX RCONST(1.0) /* Total range of x variable */
+#define AY RCONST(1.0) /* Total range of y variable */
+#define RTOL RCONST(1.e-5) /* rtol tolerance */
+#define ATOL RCONST(1.e-5) /* atol tolerance */
+#define ZERO RCONST(0.) /* 0. */
+#define ONE RCONST(1.0) /* 1. */
+#define NOUT 6
+#define TMULT RCONST(10.0) /* Multiplier for tout values */
+#define TADD RCONST(0.3) /* Increment for tout values */
+
+/* User-defined vector accessor macro IJ_Vptr. */
+
+/*
+ * IJ_Vptr is defined in order to express the underlying 3-d structure of the
+ * dependent variable vector from its underlying 1-d storage (an N_Vector).
+ * IJ_Vptr(vv,i,j) returns a pointer to the location in vv corresponding to
+ * species index is = 0, x-index ix = i, and y-index jy = j.
+ */
+
+#define IJ_Vptr(vv,i,j) (&NV_Ith_P(vv, (i)*NUM_SPECIES + (j)*NSMXSUB ))
+
+/* Type: UserData. Contains problem constants, preconditioner data, etc. */
+
+typedef struct {
+ int ns, np, thispe, npes, ixsub, jysub, npex, npey;
+ int mxsub, mysub, nsmxsub, nsmxsub2;
+ realtype dx, dy, **acoef;
+ realtype cox[NUM_SPECIES], coy[NUM_SPECIES], bcoef[NUM_SPECIES],
+ rhs[NUM_SPECIES], cext[(MXSUB+2)*(MYSUB+2)*NUM_SPECIES];
+ MPI_Comm comm;
+ N_Vector rates;
+ long int 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 reslocal(long int Nlocal, realtype tt,
+ N_Vector cc, N_Vector cp, N_Vector res,
+ void *user_data);
+
+static int rescomm(long int Nlocal, realtype tt,
+ N_Vector cc, N_Vector cp,
+ 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,
+ realtype cext[], realtype buffer[]);
+
+static void BRecvWait(MPI_Request request[], int ixsub, int jysub,
+ int dsizex, realtype cext[], realtype buffer[]);
+
+static void WebRates(realtype xx, realtype yy, realtype *cxy, realtype *ratesxy,
+ UserData webdata);
+
+static realtype dotprod(int size, realtype *x1, realtype *x2);
+
+/* Prototypes for private functions */
+
+static void InitUserData(UserData webdata, int thispe, int npes,
+ MPI_Comm comm);
+
+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,
+ realtype rtol, realtype atol);
+
+static void PrintOutput(void *mem, N_Vector cc, realtype time,
+ UserData webdata, MPI_Comm comm);
+
+static void PrintFinalStats(void *mem);
+
+static int check_flag(void *flagvalue, char *funcname, int opt, int id);
+
+/*
+ *--------------------------------------------------------------------
+ * MAIN PROGRAM
+ *--------------------------------------------------------------------
+ */
+
+int main(int argc, char *argv[])
+{
+ MPI_Comm comm;
+ void *mem;
+ UserData webdata;
+ long int 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;
+
+ /* Set communicator, and get processor number and total number of PE's. */
+
+ MPI_Init(&argc, &argv);
+ comm = MPI_COMM_WORLD;
+ MPI_Comm_rank(comm, &thispe);
+ MPI_Comm_size(comm, &npes);
+
+ if (npes != NPEX*NPEY) {
+ if (thispe == 0)
+ fprintf(stderr,
+ "\nMPI_ERROR(0): npes = %d not equal to NPEX*NPEY = %d\n",
+ npes, NPEX*NPEY);
+ MPI_Finalize();
+ return(1);
+ }
+
+ /* Set local length (local_N) and global length (SystemSize). */
+
+ local_N = MXSUB*MYSUB*NUM_SPECIES;
+ SystemSize = NEQ;
+
+ /* Set up user data block webdata. */
+
+ webdata = (UserData) malloc(sizeof *webdata);
+ webdata->rates = N_VNew_Parallel(comm, local_N, SystemSize);
+ webdata->acoef = newDenseMat(NUM_SPECIES, NUM_SPECIES);
+
+ InitUserData(webdata, thispe, npes, comm);
+
+ /* Create needed vectors, and load initial values.
+ The vector res is used temporarily only. */
+
+ cc = N_VNew_Parallel(comm, local_N, SystemSize);
+ if(check_flag((void *)cc, "N_VNew_Parallel", 0, thispe)) MPI_Abort(comm, 1);
+
+ cp = N_VNew_Parallel(comm, local_N, SystemSize);
+ if(check_flag((void *)cp, "N_VNew_Parallel", 0, thispe)) MPI_Abort(comm, 1);
+
+ res = N_VNew_Parallel(comm, local_N, SystemSize);
+ if(check_flag((void *)res, "N_VNew_Parallel", 0, thispe)) MPI_Abort(comm, 1);
+
+ id = N_VNew_Parallel(comm, local_N, SystemSize);
+ if(check_flag((void *)id, "N_VNew_Parallel", 0, thispe)) MPI_Abort(comm, 1);
+
+ SetInitialProfiles(cc, cp, id, res, webdata);
+
+ N_VDestroy_Parallel(res);
+
+ /* Set remaining inputs to IDAMalloc. */
+
+ t0 = ZERO;
+ rtol = RTOL;
+ atol = ATOL;
+
+ /* Call IDACreate and IDAMalloc to initialize solution */
+
+ mem = IDACreate();
+ if(check_flag((void *)mem, "IDACreate", 0, thispe)) MPI_Abort(comm, 1);
+
+ retval = IDASetUserData(mem, webdata);
+ if(check_flag(&retval, "IDASetUserData", 1, thispe)) MPI_Abort(comm, 1);
+
+ retval = IDASetId(mem, id);
+ if(check_flag(&retval, "IDASetId", 1, thispe)) MPI_Abort(comm, 1);
+
+ retval = IDAInit(mem, resweb, t0, cc, cp);
+ if(check_flag(&retval, "IDAInit", 1, thispe)) MPI_Abort(comm, 1);
+
+ retval = IDASStolerances(mem, rtol, atol);
+ if(check_flag(&retval, "IDASStolerances", 1, thispe)) MPI_Abort(comm, 1);
+
+ /* Call IDASpgmr to specify the IDA linear solver IDASPGMR */
+
+ maxl = 16;
+ retval = IDASpgmr(mem, maxl);
+ if(check_flag(&retval, "IDASpgmr", 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,
+ 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);
+ 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, 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);
+ if(check_flag(&retval, "IDASolve", 1, thispe)) MPI_Abort(comm, 1);
+
+ PrintOutput(mem, cc, tret, webdata, comm);
+
+ if (iout < 3) tout *= TMULT;
+ else tout += TADD;
+
+ }
+
+ /* On PE 0, print final set of statistics. */
+
+ if (thispe == 0) PrintFinalStats(mem);
+
+ /* Free memory. */
+
+ N_VDestroy_Parallel(cc);
+ N_VDestroy_Parallel(cp);
+ N_VDestroy_Parallel(id);
+
+ IDAFree(&mem);
+
+ destroyMat(webdata->acoef);
+ N_VDestroy_Parallel(webdata->rates);
+ free(webdata);
+
+ MPI_Finalize();
+
+ return(0);
+}
+
+/*
+ *--------------------------------------------------------------------
+ * PRIVATE FUNCTIONS
+ *--------------------------------------------------------------------
+ */
+
+/*
+ * InitUserData: Load problem constants in webdata (of type UserData).
+ */
+
+static void InitUserData(UserData webdata, int thispe, int npes,
+ MPI_Comm comm)
+{
+ int i, j, np;
+ realtype *a1,*a2, *a3, *a4, dx2, dy2, **acoef, *bcoef, *cox, *coy;
+
+ webdata->jysub = thispe / NPEX;
+ webdata->ixsub = thispe - (webdata->jysub)*NPEX;
+ webdata->mxsub = MXSUB;
+ webdata->mysub = MYSUB;
+ webdata->npex = NPEX;
+ webdata->npey = NPEY;
+ webdata->ns = NUM_SPECIES;
+ webdata->np = NPREY;
+ webdata->dx = AX/(MX-1);
+ webdata->dy = AY/(MY-1);
+ webdata->thispe = thispe;
+ webdata->npes = npes;
+ webdata->nsmxsub = MXSUB * NUM_SPECIES;
+ webdata->nsmxsub2 = (MXSUB+2)*NUM_SPECIES;
+ webdata->comm = comm;
+ webdata->n_local = MXSUB*MYSUB*NUM_SPECIES;
+
+ /* Set up the coefficients a and b plus others found in the equations. */
+
+ np = webdata->np;
+ dx2 = (webdata->dx)*(webdata->dx);
+ dy2 = (webdata->dy)*(webdata->dy);
+
+ acoef = webdata->acoef;
+ bcoef = webdata->bcoef;
+ cox = webdata->cox;
+ coy = webdata->coy;
+
+ for (i = 0; i < np; i++) {
+ a1 = &(acoef[i][np]);
+ a2 = &(acoef[i+np][0]);
+ a3 = &(acoef[i][0]);
+ a4 = &(acoef[i+np][np]);
+ /* Fill in the portion of acoef in the four quadrants, row by row. */
+ for (j = 0; j < np; j++) {
+ *a1++ = -GG;
+ *a2++ = EE;
+ *a3++ = ZERO;
+ *a4++ = ZERO;
+ }
+
+ /* Reset the diagonal elements of acoef to -AA. */
+ acoef[i][i] = -AA; acoef[i+np][i+np] = -AA;
+
+ /* Set coefficients for b and diffusion terms. */
+ bcoef[i] = BB; bcoef[i+np] = -BB;
+ cox[i] = DPREY/dx2; cox[i+np] = DPRED/dx2;
+ coy[i] = DPREY/dy2; coy[i+np] = DPRED/dy2;
+ }
+
+}
+
+/*
+ * SetInitialProfiles: Set initial conditions in cc, cp, and id.
+ * A polynomial profile is used for the prey cc values, and a constant
+ * (1.0e5) is loaded as the initial guess for the predator cc values.
+ * The id values are set to 1 for the prey and 0 for the predators.
+ * The prey cp values are set according to the given system, and
+ * the predator cp values are set to zero.
+ */
+
+static void SetInitialProfiles(N_Vector cc, N_Vector cp, N_Vector id,
+ N_Vector res, UserData webdata)
+{
+ int ixsub, jysub, mxsub, mysub, nsmxsub, np, ix, jy, is;
+ realtype *cxy, *idxy, *cpxy, dx, dy, xx, yy, xyfactor;
+
+ ixsub = webdata->ixsub;
+ jysub = webdata->jysub;
+ mxsub = webdata->mxsub;
+ mysub = webdata->mxsub;
+ nsmxsub = webdata->nsmxsub;
+ dx = webdata->dx;
+ dy = webdata->dy;
+ np = webdata->np;
+
+ /* Loop over grid, load cc values and id values. */
+ for (jy = 0; jy < mysub; jy++) {
+ yy = (jy + jysub*mysub) * dy;
+ for (ix = 0; ix < mxsub; ix++) {
+ xx = (ix + ixsub*mxsub) * dx;
+ xyfactor = 16.*xx*(1. - xx)*yy*(1. - yy);
+ xyfactor *= xyfactor;
+
+ 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; }
+ else { cxy[is] = 1.0e5; idxy[is] = ZERO; }
+ }
+ }
+ }
+
+ /* Set c' for the prey by calling the residual function with cp = 0. */
+
+ N_VConst(ZERO, cp);
+ resweb(ZERO, cc, cp, res, webdata);
+ N_VScale(-ONE, res, cp);
+
+ /* Set c' for predators to 0. */
+
+ for (jy = 0; jy < mysub; jy++) {
+ for (ix = 0; ix < mxsub; ix++) {
+ cpxy = IJ_Vptr(cp,ix,jy);
+ for (is = np; is < NUM_SPECIES; is++) cpxy[is] = ZERO;
+ }
+ }
+}
+
+/*
+ * Print first lines of output (problem description)
+ * and table headerr
+ */
+
+static void PrintHeader(int SystemSize, int maxl,
+ int mudq, int mldq,
+ int mukeep, int 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("Subgrid dimensions: %d x %d", MXSUB, MYSUB);
+ printf(" Processor array: %d x %d\n", NPEX, NPEY);
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("Tolerance parameters: rtol = %Lg atol = %Lg\n", rtol, atol);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("Tolerance parameters: rtol = %lg atol = %lg\n", rtol, atol);
+#else
+ printf("Tolerance parameters: rtol = %g atol = %g\n", rtol, atol);
+#endif
+ printf("Linear solver: IDASPGMR 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("CalcIC called to correct initial predator concentrations \n\n");
+ printf("-----------------------------------------------------------\n");
+ printf(" t bottom-left top-right");
+ printf(" | nst k h\n");
+ printf("-----------------------------------------------------------\n\n");
+}
+
+
+/*
+ * PrintOutput: Print output values at output time t = tt.
+ * Selected run statistics are printed. Then values of c1 and c2
+ * are printed for the bottom left and top right grid points only.
+ */
+
+static void PrintOutput(void *mem, N_Vector cc, realtype tt,
+ UserData webdata, MPI_Comm comm)
+{
+ MPI_Status status;
+ realtype *cdata, clast[2], hused;
+ long int nst;
+ int i, kused, flag, thispe, npelast, ilast;;
+
+ thispe = webdata->thispe;
+ npelast = webdata->npes - 1;
+ cdata = NV_DATA_P(cc);
+
+ /* Send conc. at top right mesh point from PE npes-1 to PE 0. */
+ if (thispe == npelast) {
+ ilast = NUM_SPECIES*MXSUB*MYSUB - 2;
+ if (npelast != 0)
+ MPI_Send(&cdata[ilast], 2, PVEC_REAL_MPI_TYPE, 0, 0, comm);
+ else { clast[0] = cdata[ilast]; clast[1] = cdata[ilast+1]; }
+ }
+
+ /* On PE 0, receive conc. at top right from PE npes - 1.
+ Then print performance data and sampled solution values. */
+
+ if (thispe == 0) {
+
+ if (npelast != 0)
+ MPI_Recv(&clast[0], 2, PVEC_REAL_MPI_TYPE, npelast, 0, comm, &status);
+
+ flag = IDAGetLastOrder(mem, &kused);
+ check_flag(&flag, "IDAGetLastOrder", 1, thispe);
+ flag = IDAGetNumSteps(mem, &nst);
+ check_flag(&flag, "IDAGetNumSteps", 1, thispe);
+ flag = IDAGetLastStep(mem, &hused);
+ check_flag(&flag, "IDAGetLastStep", 1, thispe);
+
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("%8.2Le %12.4Le %12.4Le | %3ld %1d %12.4Le\n",
+ tt, cdata[0], clast[0], nst, kused, hused);
+ for (i=1;i<NUM_SPECIES;i++)
+ printf(" %12.4Le %12.4Le |\n",cdata[i],clast[i]);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("%8.2le %12.4le %12.4le | %3ld %1d %12.4le\n",
+ tt, cdata[0], clast[0], nst, kused, hused);
+ for (i=1;i<NUM_SPECIES;i++)
+ printf(" %12.4le %12.4le |\n",cdata[i],clast[i]);
+#else
+ printf("%8.2e %12.4e %12.4e | %3ld %1d %12.4e\n",
+ tt, cdata[0], clast[0], nst, kused, hused);
+ for (i=1;i<NUM_SPECIES;i++)
+ printf(" %12.4e %12.4e |\n",cdata[i],clast[i]);
+#endif
+ printf("\n");
+
+ }
+
+}
+
+/*
+ * PrintFinalStats: Print final run data contained in iopt.
+ */
+
+static void PrintFinalStats(void *mem)
+{
+ long int nst, nre, nreLS, netf, ncfn, nni, ncfl, nli, npe, nps, nge;
+ int flag;
+
+ flag = IDAGetNumSteps(mem, &nst);
+ check_flag(&flag, "IDAGetNumSteps", 1, 0);
+ flag = IDAGetNumResEvals(mem, &nre);
+ check_flag(&flag, "IDAGetNumResEvals", 1, 0);
+ flag = IDAGetNumErrTestFails(mem, &netf);
+ check_flag(&flag, "IDAGetNumErrTestFails", 1, 0);
+ flag = IDAGetNumNonlinSolvConvFails(mem, &ncfn);
+ check_flag(&flag, "IDAGetNumNonlinSolvConvFails", 1, 0);
+ flag = IDAGetNumNonlinSolvIters(mem, &nni);
+ check_flag(&flag, "IDAGetNumNonlinSolvIters", 1, 0);
+
+ flag = IDASpilsGetNumConvFails(mem, &ncfl);
+ check_flag(&flag, "IDASpilsGetNumConvFails", 1, 0);
+ flag = IDASpilsGetNumLinIters(mem, &nli);
+ check_flag(&flag, "IDASpilsGetNumLinIters", 1, 0);
+ flag = IDASpilsGetNumPrecEvals(mem, &npe);
+ check_flag(&flag, "IDASpilsGetNumPrecEvals", 1, 0);
+ flag = IDASpilsGetNumPrecSolves(mem, &nps);
+ check_flag(&flag, "IDASpilsGetNumPrecSolves", 1, 0);
+ flag = IDASpilsGetNumResEvals(mem, &nreLS);
+ check_flag(&flag, "IDASpilsGetNumResEvals", 1, 0);
+
+ flag = IDABBDPrecGetNumGfnEvals(mem, &nge);
+ check_flag(&flag, "IDABBDPrecGetNumGfnEvals", 1, 0);
+
+ printf("-----------------------------------------------------------\n");
+ printf("\nFinal statistics: \n\n");
+
+ printf("Number of steps = %ld\n", nst);
+ printf("Number of residual evaluations = %ld\n", nre+nreLS);
+ printf("Number of nonlinear iterations = %ld\n", nni);
+ printf("Number of error test failures = %ld\n", netf);
+ printf("Number of nonlinear conv. failures = %ld\n\n", ncfn);
+
+ printf("Number of linear iterations = %ld\n", nli);
+ printf("Number of linear conv. failures = %ld\n\n", ncfl);
+
+ printf("Number of preconditioner setups = %ld\n", npe);
+ printf("Number of preconditioner solves = %ld\n", nps);
+ printf("Number of local residual evals. = %ld\n", nge);
+
+}
+
+/*
+ * 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, char *funcname, int opt, int id)
+{
+ int *errflag;
+
+ if (opt == 0 && flagvalue == NULL) {
+ /* Check if SUNDIALS function returned NULL pointer - no memory allocated */
+ fprintf(stderr,
+ "\nSUNDIALS_ERROR(%d): %s() failed - returned NULL pointer\n\n",
+ id, funcname);
+ return(1);
+ } else if (opt == 1) {
+ /* Check if flag < 0 */
+ errflag = (int *) flagvalue;
+ if (*errflag < 0) {
+ fprintf(stderr,
+ "\nSUNDIALS_ERROR(%d): %s() failed with flag = %d\n\n",
+ id, funcname, *errflag);
+ return(1);
+ }
+ } else if (opt == 2 && flagvalue == NULL) {
+ /* Check if function returned NULL pointer - no memory allocated */
+ fprintf(stderr,
+ "\nMEMORY_ERROR(%d): %s() failed - returned NULL pointer\n\n",
+ id, funcname);
+ return(1);
+ }
+
+ return(0);
+}
+
+/*
+ *--------------------------------------------------------------------
+ * FUNCTIONS CALLED BY IDA & SUPPORTING FUNCTIONS
+ *--------------------------------------------------------------------
+ */
+
+/*
+ * resweb: System residual function for predator-prey system.
+ * To compute the residual function F, this routine calls:
+ * rescomm, for needed communication, and then
+ * reslocal, for computation of the residuals on this processor.
+ */
+
+static int resweb(realtype tt,
+ N_Vector cc, N_Vector cp, N_Vector rr,
+ void *user_data)
+{
+ int retval;
+ UserData webdata;
+ long int Nlocal;
+
+ webdata = (UserData) user_data;
+
+ Nlocal = webdata->n_local;
+
+ /* Call rescomm to do inter-processor communication. */
+ retval = rescomm(Nlocal, tt, cc, cp, user_data);
+
+ /* Call reslocal to calculate the local portion of residual vector. */
+ retval = reslocal(Nlocal, tt, cc, cp, rr, user_data);
+
+ return(0);
+}
+
+/*
+ * rescomm: Communication routine in support of resweb.
+ * This routine performs all inter-processor communication of components
+ * of the cc vector needed to calculate F, namely the components at all
+ * interior subgrid boundaries (ghost cell data). It loads this data
+ * into a work array cext (the local portion of c, extended).
+ * 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 cc, N_Vector cp,
+ void *user_data)
+{
+
+ UserData webdata;
+ realtype *cdata, *cext, buffer[2*NUM_SPECIES*MYSUB];
+ int thispe, ixsub, jysub, nsmxsub, nsmysub;
+ MPI_Comm comm;
+ MPI_Request request[4];
+
+ webdata = (UserData) user_data;
+ cdata = NV_DATA_P(cc);
+
+ /* Get comm, thispe, subgrid indices, data sizes, extended array cext. */
+
+ comm = webdata->comm;
+ thispe = webdata->thispe;
+
+ ixsub = webdata->ixsub;
+ jysub = webdata->jysub;
+ cext = webdata->cext;
+ nsmxsub = webdata->nsmxsub;
+ nsmysub = (webdata->ns)*(webdata->mysub);
+
+ /* Start receiving boundary data from neighboring PEs. */
+
+ BRecvPost(comm, request, thispe, ixsub, jysub, nsmxsub, nsmysub,
+ cext, buffer);
+
+ /* Send data from boundary of local grid to neighboring PEs. */
+
+ BSend(comm, thispe, ixsub, jysub, nsmxsub, nsmysub, cdata);
+
+ /* Finish receiving boundary data from neighboring PEs. */
+
+ BRecvWait(request, ixsub, jysub, nsmxsub, cext, buffer);
+
+ return(0);
+}
+
+/*
+ * BRecvPost: Start receiving boundary data from neighboring PEs.
+ * (1) buffer should be able to hold 2*NUM_SPECIES*MYSUB realtype entries,
+ * should be passed to both the BRecvPost and BRecvWait functions, and
+ * should not be manipulated between the two calls.
+ * (2) request should have 4 entries, and is also passed in both calls.
+ */
+
+static void BRecvPost(MPI_Comm comm, MPI_Request request[], int my_pe,
+ int ixsub, int jysub,
+ int dsizex, int dsizey,
+ realtype cext[], realtype buffer[])
+{
+ int offsetce;
+ /* Have bufleft and bufright use the same buffer. */
+ realtype *bufleft = buffer, *bufright = buffer+NUM_SPECIES*MYSUB;
+
+ /* If jysub > 0, receive data for bottom x-line of cext. */
+ if (jysub != 0)
+ MPI_Irecv(&cext[NUM_SPECIES], dsizex, PVEC_REAL_MPI_TYPE,
+ my_pe-NPEX, 0, comm, &request[0]);
+
+ /* If jysub < NPEY-1, receive data for top x-line of cext. */
+ if (jysub != NPEY-1) {
+ offsetce = NUM_SPECIES*(1 + (MYSUB+1)*(MXSUB+2));
+ MPI_Irecv(&cext[offsetce], dsizex, PVEC_REAL_MPI_TYPE,
+ my_pe+NPEX, 0, comm, &request[1]);
+ }
+
+ /* If ixsub > 0, receive data for left y-line of cext (via bufleft). */
+ if (ixsub != 0) {
+ MPI_Irecv(&bufleft[0], dsizey, PVEC_REAL_MPI_TYPE,
+ my_pe-1, 0, comm, &request[2]);
+ }
+
+ /* If ixsub < NPEX-1, receive data for right y-line of cext (via bufright). */
+ if (ixsub != NPEX-1) {
+ MPI_Irecv(&bufright[0], dsizey, PVEC_REAL_MPI_TYPE,
+ my_pe+1, 0, comm, &request[3]);
+ }
+
+}
+
+/*
+ * BRecvWait: Finish receiving boundary data from neighboring PEs.
+ * (1) buffer should be able to hold 2*NUM_SPECIES*MYSUB realtype entries,
+ * should be passed to both the BRecvPost and BRecvWait functions, and
+ * should not be manipulated between the two calls.
+ * (2) request should have 4 entries, and is also passed in both calls.
+ */
+
+static void BRecvWait(MPI_Request request[], int ixsub, int jysub,
+ int dsizex, realtype cext[], realtype buffer[])
+{
+ int i;
+ int ly, dsizex2, offsetce, offsetbuf;
+ realtype *bufleft = buffer, *bufright = buffer+NUM_SPECIES*MYSUB;
+ MPI_Status status;
+
+ dsizex2 = dsizex + 2*NUM_SPECIES;
+
+ /* If jysub > 0, receive data for bottom x-line of cext. */
+ if (jysub != 0)
+ MPI_Wait(&request[0],&status);
+
+ /* If jysub < NPEY-1, receive data for top x-line of cext. */
+ if (jysub != NPEY-1)
+ MPI_Wait(&request[1],&status);
+
+ /* If ixsub > 0, receive data for left y-line of cext (via bufleft). */
+ if (ixsub != 0) {
+ MPI_Wait(&request[2],&status);
+
+ /* Copy the buffer to cext */
+ for (ly = 0; ly < MYSUB; ly++) {
+ offsetbuf = ly*NUM_SPECIES;
+ offsetce = (ly+1)*dsizex2;
+ for (i = 0; i < NUM_SPECIES; i++)
+ cext[offsetce+i] = bufleft[offsetbuf+i];
+ }
+ }
+
+ /* If ixsub < NPEX-1, receive data for right y-line of cext (via bufright). */
+ if (ixsub != NPEX-1) {
+ MPI_Wait(&request[3],&status);
+
+ /* Copy the buffer to cext */
+ for (ly = 0; ly < MYSUB; ly++) {
+ offsetbuf = ly*NUM_SPECIES;
+ offsetce = (ly+2)*dsizex2 - NUM_SPECIES;
+ for (i = 0; i < NUM_SPECIES; i++)
+ cext[offsetce+i] = bufright[offsetbuf+i];
+ }
+ }
+}
+
+/*
+ * BSend: Send boundary data to neighboring PEs.
+ * This routine sends components of cc from internal subgrid boundaries
+ * to the appropriate neighbor PEs.
+ */
+
+static void BSend(MPI_Comm comm, int my_pe, int ixsub, int jysub,
+ int dsizex, int dsizey, realtype cdata[])
+{
+ int i;
+ int ly, offsetc, offsetbuf;
+ realtype bufleft[NUM_SPECIES*MYSUB], bufright[NUM_SPECIES*MYSUB];
+
+ /* If jysub > 0, send data from bottom x-line of cc. */
+
+ if (jysub != 0)
+ MPI_Send(&cdata[0], dsizex, PVEC_REAL_MPI_TYPE, my_pe-NPEX, 0, comm);
+
+ /* If jysub < NPEY-1, send data from top x-line of cc. */
+
+ if (jysub != NPEY-1) {
+ offsetc = (MYSUB-1)*dsizex;
+ MPI_Send(&cdata[offsetc], dsizex, PVEC_REAL_MPI_TYPE, my_pe+NPEX, 0, comm);
+ }
+
+ /* If ixsub > 0, send data from left y-line of cc (via bufleft). */
+
+ if (ixsub != 0) {
+ for (ly = 0; ly < MYSUB; ly++) {
+ offsetbuf = ly*NUM_SPECIES;
+ offsetc = ly*dsizex;
+ for (i = 0; i < NUM_SPECIES; i++)
+ bufleft[offsetbuf+i] = cdata[offsetc+i];
+ }
+ MPI_Send(&bufleft[0], dsizey, PVEC_REAL_MPI_TYPE, my_pe-1, 0, comm);
+ }
+
+ /* If ixsub < NPEX-1, send data from right y-line of cc (via bufright). */
+
+ if (ixsub != NPEX-1) {
+ for (ly = 0; ly < MYSUB; ly++) {
+ offsetbuf = ly*NUM_SPECIES;
+ offsetc = offsetbuf*MXSUB + (MXSUB-1)*NUM_SPECIES;
+ for (i = 0; i < NUM_SPECIES; i++)
+ bufright[offsetbuf+i] = cdata[offsetc+i];
+ }
+ MPI_Send(&bufright[0], dsizey, PVEC_REAL_MPI_TYPE, my_pe+1, 0, comm);
+ }
+}
+
+/* Define lines are for ease of readability in the following functions. */
+
+#define mxsub (webdata->mxsub)
+#define mysub (webdata->mysub)
+#define npex (webdata->npex)
+#define npey (webdata->npey)
+#define ixsub (webdata->ixsub)
+#define jysub (webdata->jysub)
+#define nsmxsub (webdata->nsmxsub)
+#define nsmxsub2 (webdata->nsmxsub2)
+#define np (webdata->np)
+#define dx (webdata->dx)
+#define dy (webdata->dy)
+#define cox (webdata->cox)
+#define coy (webdata->coy)
+#define rhs (webdata->rhs)
+#define cext (webdata->cext)
+#define rates (webdata->rates)
+#define ns (webdata->ns)
+#define acoef (webdata->acoef)
+#define bcoef (webdata->bcoef)
+
+/*
+ * reslocal: Compute res = F(t,cc,cp).
+ * This routine assumes that all inter-processor communication of data
+ * needed to calculate F has already been done. Components at interior
+ * subgrid boundaries are assumed to be in the work array cext.
+ * The local portion of the cc vector is first copied into cext.
+ * The exterior Neumann boundary conditions are explicitly handled here
+ * by copying data from the first interior mesh line to the ghost cell
+ * locations in cext. Then the reaction and diffusion terms are
+ * evaluated in terms of the cext array, and the residuals are formed.
+ * The reaction terms are saved separately in the vector webdata->rates
+ * for use by the preconditioner setup routine.
+ */
+
+static int reslocal(long int Nlocal, realtype tt,
+ N_Vector cc, N_Vector cp, N_Vector rr,
+ void *user_data)
+{
+ realtype *cdata, *ratesxy, *cpxy, *resxy,
+ xx, yy, dcyli, dcyui, dcxli, dcxui;
+ int ix, jy, is, i, locc, ylocce, locce;
+ UserData webdata;
+
+ webdata = (UserData) user_data;
+
+ /* Get data pointers, subgrid data, array sizes, work array cext. */
+
+ cdata = NV_DATA_P(cc);
+
+ /* Copy local segment of cc vector into the working extended array cext. */
+
+ locc = 0;
+ locce = nsmxsub2 + NUM_SPECIES;
+ for (jy = 0; jy < mysub; jy++) {
+ for (i = 0; i < nsmxsub; i++) cext[locce+i] = cdata[locc+i];
+ locc = locc + nsmxsub;
+ locce = locce + nsmxsub2;
+ }
+
+ /* To facilitate homogeneous Neumann boundary conditions, when this is
+ a boundary PE, copy data from the first interior mesh line of cc to cext. */
+
+ /* If jysub = 0, copy x-line 2 of cc to cext. */
+ if (jysub == 0)
+ { for (i = 0; i < nsmxsub; i++) cext[NUM_SPECIES+i] = cdata[nsmxsub+i]; }
+
+ /* If jysub = npey-1, copy x-line mysub-1 of cc to cext. */
+ if (jysub == npey-1) {
+ locc = (mysub-2)*nsmxsub;
+ locce = (mysub+1)*nsmxsub2 + NUM_SPECIES;
+ for (i = 0; i < nsmxsub; i++) cext[locce+i] = cdata[locc+i];
+ }
+
+ /* If ixsub = 0, copy y-line 2 of cc to cext. */
+ if (ixsub == 0) {
+ for (jy = 0; jy < mysub; jy++) {
+ locc = jy*nsmxsub + NUM_SPECIES;
+ locce = (jy+1)*nsmxsub2;
+ for (i = 0; i < NUM_SPECIES; i++) cext[locce+i] = cdata[locc+i];
+ }
+ }
+
+ /* If ixsub = npex-1, copy y-line mxsub-1 of cc to cext. */
+ if (ixsub == npex-1) {
+ for (jy = 0; jy < mysub; jy++) {
+ locc = (jy+1)*nsmxsub - 2*NUM_SPECIES;
+ locce = (jy+2)*nsmxsub2 - NUM_SPECIES;
+ for (i = 0; i < NUM_SPECIES; i++) cext[locce+i] = cdata[locc+i];
+ }
+ }
+
+ /* Loop over all grid points, setting local array rates to right-hand sides.
+ Then set rr values appropriately for prey/predator components of F. */
+
+ for (jy = 0; jy < mysub; jy++) {
+ ylocce = (jy+1)*nsmxsub2;
+ yy = (jy+jysub*mysub)*dy;
+
+ for (ix = 0; ix < mxsub; ix++) {
+ locce = ylocce + (ix+1)*NUM_SPECIES;
+ xx = (ix + ixsub*mxsub)*dx;
+
+ ratesxy = IJ_Vptr(rates,ix,jy);
+ WebRates(xx, yy, &(cext[locce]), ratesxy, webdata);
+
+ resxy = IJ_Vptr(rr,ix,jy);
+ cpxy = IJ_Vptr(cp,ix,jy);
+
+ for (is = 0; is < NUM_SPECIES; is++) {
+ dcyli = cext[locce+is] - cext[locce+is-nsmxsub2];
+ dcyui = cext[locce+is+nsmxsub2] - cext[locce+is];
+
+ dcxli = cext[locce+is] - cext[locce+is-NUM_SPECIES];
+ dcxui = cext[locce+is+NUM_SPECIES] - cext[locce+is];
+
+ rhs[is] = cox[is]*(dcxui-dcxli) + coy[is]*(dcyui-dcyli) + ratesxy[is];
+
+ if (is < np) resxy[is] = cpxy[is] - rhs[is];
+ else resxy[is] = - rhs[is];
+
+ }
+ }
+ }
+
+ return(0);
+}
+
+/*
+ * WebRates: Evaluate reaction rates at a given spatial point.
+ * At a given (x,y), evaluate the array of ns reaction terms R.
+ */
+
+static void WebRates(realtype xx, realtype yy, realtype *cxy, realtype *ratesxy,
+ UserData webdata)
+{
+ int is;
+ realtype fac;
+
+ for (is = 0; is < NUM_SPECIES; is++)
+ ratesxy[is] = dotprod(NUM_SPECIES, cxy, acoef[is]);
+
+ fac = ONE + ALPHA*xx*yy + BETA*sin(FOURPI*xx)*sin(FOURPI*yy);
+
+ for (is = 0; is < NUM_SPECIES; is++)
+ ratesxy[is] = cxy[is]*( bcoef[is]*fac + ratesxy[is] );
+
+}
+
+/*
+ * dotprod: dot product routine for realtype arrays, for use by WebRates.
+ */
+
+static realtype dotprod(int size, realtype *x1, realtype *x2)
+{
+ int i;
+ realtype *xx1, *xx2, temp = ZERO;
+
+ xx1 = x1;
+ xx2 = x2;
+ for (i = 0; i < size; i++)
+ temp += (*xx1++) * (*xx2++);
+
+ return(temp);
+}
+
diff --git a/examples/idas/parallel/idasFoodWeb_kry_bbd_p.out b/examples/idas/parallel/idasFoodWeb_kry_bbd_p.out
new file mode 100644
index 0000000..da6066b
--- /dev/null
+++ b/examples/idas/parallel/idasFoodWeb_kry_bbd_p.out
@@ -0,0 +1,51 @@
+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
+Preconditioner: band-block-diagonal (IDABBDPRE), with parameters
+ mudq = 20, mldq = 20, mukeep = 2, mlkeep = 2
+CalcIC called to correct initial predator concentrations
+
+-----------------------------------------------------------
+ t bottom-left top-right | nst k h
+-----------------------------------------------------------
+
+0.00e+00 1.0000e+01 1.0000e+01 | 0 0 1.6310e-08
+ 1.0000e+05 1.0000e+05 |
+
+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.6189e+06 1.9735e+06 |
+
+1.00e-01 2.4019e+02 2.7072e+02 | 197 1 4.0396e-02
+ 2.4019e+06 2.7072e+06 |
+
+4.00e-01 2.4019e+02 2.7072e+02 | 200 1 3.2316e-01
+ 2.4019e+06 2.7072e+06 |
+
+7.00e-01 2.4019e+02 2.7072e+02 | 200 1 3.2316e-01
+ 2.4019e+06 2.7072e+06 |
+
+1.00e+00 2.4019e+02 2.7072e+02 | 201 1 6.4633e-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 error test failures = 0
+Number of nonlinear conv. failures = 0
+
+Number of linear iterations = 863
+Number of linear conv. failures = 0
+
+Number of preconditioner setups = 26
+Number of preconditioner solves = 1110
+Number of local residual evals. = 1092
diff --git a/examples/idas/parallel/idasFoodWeb_kry_p.c b/examples/idas/parallel/idasFoodWeb_kry_p.c
new file mode 100644
index 0000000..250a4cc
--- /dev/null
+++ b/examples/idas/parallel/idasFoodWeb_kry_p.c
@@ -0,0 +1,1231 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.2 $
+ * $Date: 2010/12/01 23:06:38 $
+ * -----------------------------------------------------------------
+ * Programmer(s): 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.
+ * 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.
+ *
+ * The mathematical problem solved in this example is a DAE system
+ * that arises from a system of partial differential equations after
+ * spatial discretization. The PDE system is a food web population
+ * model, with predator-prey interaction and diffusion on the unit
+ * square in two dimensions. The dependent variable vector is:
+ *
+ * 1 2 ns
+ * c = (c , c , ..., c ) , ns = 2 * np
+ *
+ * and the PDE's are as follows:
+ *
+ * i i i
+ * dc /dt = d(i)*(c + c ) + R (x,y,c) (i = 1,...,np)
+ * xx yy i
+ *
+ * i i
+ * 0 = d(i)*(c + c ) + R (x,y,c) (i = np+1,...,ns)
+ * xx yy i
+ *
+ * where the reaction terms R are:
+ *
+ * i ns j
+ * R (x,y,c) = c * (b(i) + sum a(i,j)*c )
+ * i j=1
+ *
+ * The number of species is ns = 2 * np, with the first np being
+ * prey and the last np being predators. The coefficients a(i,j),
+ * b(i), d(i) are:
+ *
+ * a(i,i) = -AA (all i)
+ * a(i,j) = -GG (i <= np , j > np)
+ * a(i,j) = EE (i > np, j <= np)
+ * all other a(i,j) = 0
+ * b(i) = BB*(1+ alpha * x*y + beta*sin(4 pi x)*sin(4 pi y)) (i <= np)
+ * b(i) =-BB*(1+ alpha * x*y + beta*sin(4 pi x)*sin(4 pi y)) (i > np)
+ * d(i) = DPREY (i <= np)
+ * d(i) = DPRED (i > np)
+ *
+ * Note: The above equations are written in 1-based indices,
+ * whereas the code has 0-based indices, being written in C.
+ *
+ * The various scalar parameters required are set using '#define'
+ * statements or directly in routine InitUserData. In this program,
+ * np = 1, ns = 2. The boundary conditions are homogeneous Neumann:
+ * normal derivative = 0.
+ *
+ * A polynomial in x and y is used to set the initial values of the
+ * first np variables (the prey variables) at each x,y location,
+ * while initial values for the remaining (predator) variables are
+ * set to a flat value, which is corrected by IDACalcIC.
+ *
+ * The PDEs are discretized by central differencing on a MX by MY
+ * mesh, and so the system size Neq is the product
+ * MX * MY * NUM_SPECIES. The system is actually implemented on
+ * 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, which uses the preconditioned GMRES iterative method to
+ * solve linear systems. The precondtioner supplied to IDASPGMR 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.
+ * -----------------------------------------------------------------
+ * References:
+ * [1] Peter N. Brown and Alan C. Hindmarsh,
+ * Reduced Storage Matrix Methods in Stiff ODE systems,
+ * Journal of Applied Mathematics and Computation, Vol. 31
+ * (May 1989), pp. 40-91.
+ *
+ * [2] Peter N. Brown, Alan C. Hindmarsh, and Linda R. Petzold,
+ * Using Krylov Methods in the Solution of Large-Scale
+ * Differential-Algebraic Systems, SIAM J. Sci. Comput., 15
+ * (1994), pp. 1467-1488.
+ *
+ * [3] Peter N. Brown, Alan C. Hindmarsh, and Linda R. Petzold,
+ * 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_spgmr.h>
+#include <nvector/nvector_parallel.h>
+#include <sundials/sundials_dense.h>
+#include <sundials/sundials_types.h>
+#include <sundials/sundials_math.h>
+
+#include <mpi.h>
+
+/* Problem Constants. */
+
+#define NPREY 1 /* Number of prey (= number of predators). */
+#define NUM_SPECIES 2*NPREY
+
+#define PI RCONST(3.1415926535898) /* pi */
+#define FOURPI (RCONST(4.0)*PI) /* 4 pi */
+
+#define MXSUB 10 /* Number of x mesh points per processor subgrid */
+#define MYSUB 10 /* Number of y mesh points per processor subgrid */
+#define NPEX 2 /* Number of subgrids in the x direction */
+#define NPEY 2 /* Number of subgrids in the y direction */
+#define MX (MXSUB*NPEX) /* MX = number of x mesh points */
+#define MY (MYSUB*NPEY) /* MY = number of y mesh points */
+#define NSMXSUB (NUM_SPECIES * MXSUB)
+#define NEQ (NUM_SPECIES*MX*MY) /* Number of equations in system */
+#define AA RCONST(1.0) /* Coefficient in above eqns. for a */
+#define EE RCONST(10000.) /* Coefficient in above eqns. for a */
+#define GG RCONST(0.5e-6) /* Coefficient in above eqns. for a */
+#define BB RCONST(1.0) /* Coefficient in above eqns. for b */
+#define DPREY RCONST(1.0) /* Coefficient in above eqns. for d */
+#define DPRED RCONST(0.05) /* Coefficient in above eqns. for d */
+#define ALPHA RCONST(50.) /* Coefficient alpha in above eqns. */
+#define BETA RCONST(1000.) /* Coefficient beta in above eqns. */
+#define AX RCONST(1.0) /* Total range of x variable */
+#define AY RCONST(1.0) /* Total range of y variable */
+#define RTOL RCONST(1.e-5) /* rtol tolerance */
+#define ATOL RCONST(1.e-5) /* atol tolerance */
+#define ZERO RCONST(0.) /* 0. */
+#define ONE RCONST(1.0) /* 1. */
+#define NOUT 6
+#define TMULT RCONST(10.0) /* Multiplier for tout values */
+#define TADD RCONST(0.3) /* Increment for tout values */
+
+
+/* User-defined vector accessor macro IJ_Vptr. */
+
+/* IJ_Vptr is defined in order to express the underlying 3-d structure of the
+ dependent variable vector from its underlying 1-d storage (an N_Vector).
+ IJ_Vptr(vv,i,j) returns a pointer to the location in vv corresponding to
+ species index is = 0, x-index ix = i, and y-index jy = j. */
+
+#define IJ_Vptr(vv,i,j) (&NV_Ith_P(vv, (i)*NUM_SPECIES + (j)*NSMXSUB ))
+
+/* Type: UserData. Contains problem constants, preconditioner data, etc. */
+
+typedef struct {
+ long int ns;
+ int np, thispe, npes, ixsub, jysub, npex, npey;
+ int mxsub, mysub, nsmxsub, nsmxsub2;
+ realtype dx, dy, **acoef;
+ realtype cox[NUM_SPECIES], coy[NUM_SPECIES], bcoef[NUM_SPECIES],
+ rhs[NUM_SPECIES], cext[(MXSUB+2)*(MYSUB+2)*NUM_SPECIES];
+ MPI_Comm comm;
+ N_Vector rates;
+ realtype **PP[MXSUB][MYSUB];
+ long int *pivot[MXSUB][MYSUB];
+ N_Vector ewt;
+ void *ida_mem;
+} *UserData;
+
+
+/* Prototypes for user-supplied and supporting functions. */
+
+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 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 rescomm(N_Vector cc, N_Vector cp, void *user_data);
+
+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,
+ realtype cext[], realtype buffer[]);
+
+static void BRecvWait(MPI_Request request[], int ixsub, int jysub,
+ int dsizex, realtype cext[], realtype buffer[]);
+
+static int reslocal(realtype tt, N_Vector cc, N_Vector cp, N_Vector res,
+ void *user_data);
+
+static void WebRates(realtype xx, realtype yy, realtype *cxy, realtype *ratesxy,
+ UserData webdata);
+
+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 void InitUserData(UserData webdata, int thispe, int npes,
+ MPI_Comm comm);
+
+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,
+ realtype rtol, realtype atol);
+
+static void PrintOutput(void *mem, N_Vector cc, realtype time,
+ UserData webdata, MPI_Comm comm);
+
+static void PrintFinalStats(void *mem);
+
+static int check_flag(void *flagvalue, char *funcname, int opt, int id);
+
+/*
+ *--------------------------------------------------------------------
+ * MAIN PROGRAM
+ *--------------------------------------------------------------------
+ */
+
+int main(int argc, char *argv[])
+{
+ MPI_Comm comm;
+ void *mem;
+ UserData webdata;
+ long int 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;
+
+ /* Set communicator, and get processor number and total number of PE's. */
+
+ MPI_Init(&argc, &argv);
+ comm = MPI_COMM_WORLD;
+ MPI_Comm_rank(comm, &thispe);
+ MPI_Comm_size(comm, &npes);
+
+ if (npes != NPEX*NPEY) {
+ if (thispe == 0)
+ fprintf(stderr,
+ "\nMPI_ERROR(0): npes = %d not equal to NPEX*NPEY = %d\n",
+ npes, NPEX*NPEY);
+ MPI_Finalize();
+ return(1);
+ }
+
+ /* Set local length (local_N) and global length (SystemSize). */
+
+ local_N = MXSUB*MYSUB*NUM_SPECIES;
+ SystemSize = NEQ;
+
+ /* Set up user data block webdata. */
+
+ webdata = AllocUserData(comm, local_N, SystemSize);
+ if (check_flag((void *)webdata, "AllocUserData", 0, thispe)) MPI_Abort(comm, 1);
+
+ InitUserData(webdata, thispe, npes, comm);
+
+ /* Create needed vectors, and load initial values.
+ The vector res is used temporarily only. */
+
+ cc = N_VNew_Parallel(comm, local_N, SystemSize);
+ if (check_flag((void *)cc, "N_VNew_Parallel", 0, thispe)) MPI_Abort(comm, 1);
+
+ cp = N_VNew_Parallel(comm, local_N, SystemSize);
+ if (check_flag((void *)cp, "N_VNew_Parallel", 0, thispe)) MPI_Abort(comm, 1);
+
+ res = N_VNew_Parallel(comm, local_N, SystemSize);
+ if (check_flag((void *)res, "N_VNew_Parallel", 0, thispe)) MPI_Abort(comm, 1);
+
+ id = N_VNew_Parallel(comm, local_N, SystemSize);
+ if (check_flag((void *)id, "N_VNew_Parallel", 0, thispe)) MPI_Abort(comm, 1);
+
+ SetInitialProfiles(cc, cp, id, res, webdata);
+
+ N_VDestroy(res);
+
+ /* Set remaining inputs to IDAMalloc. */
+
+ t0 = ZERO;
+ rtol = RTOL;
+ atol = ATOL;
+
+ /* 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);
+
+ flag = IDASetUserData(mem, webdata);
+ if (check_flag(&flag, "IDASetUserData", 1, thispe)) MPI_Abort(comm, 1);
+
+ flag = IDASetId(mem, id);
+ if (check_flag(&flag, "IDASetId", 1, thispe)) MPI_Abort(comm, 1);
+
+ flag = IDAInit(mem, resweb, t0, cc, cp);
+ if (check_flag(&flag, "IDAinit", 1, thispe)) MPI_Abort(comm, 1);
+
+ flag = IDASStolerances(mem, rtol, atol);
+ if (check_flag(&flag, "IDASStolerances", 1, thispe)) MPI_Abort(comm, 1);
+
+ webdata->ida_mem = 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. */
+
+ maxl = 16;
+ flag = IDASpgmr(mem, maxl);
+ if (check_flag(&flag, "IDASpgmr", 1, thispe))
+ MPI_Abort(comm, 1);
+
+ flag = IDASpilsSetPreconditioner(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);
+ 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);
+
+ /* 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);
+ if (check_flag(&flag, "IDASolve", 1, thispe)) MPI_Abort(comm, 1);
+
+ PrintOutput(mem, cc, tret, webdata, comm);
+
+ if (iout < 3) tout *= TMULT;
+ else tout += TADD;
+
+ }
+
+ /* On PE 0, print final set of statistics. */
+ if (thispe == 0) PrintFinalStats(mem);
+
+ /* Free memory. */
+
+ N_VDestroy_Parallel(cc);
+ N_VDestroy_Parallel(cp);
+ N_VDestroy_Parallel(id);
+
+ IDAFree(&mem);
+
+ FreeUserData(webdata);
+
+ MPI_Finalize();
+
+ return(0);
+
+}
+
+/*
+ *--------------------------------------------------------------------
+ * PRIVATE FUNCTIONS
+ *--------------------------------------------------------------------
+ */
+
+/*
+ * AllocUserData: Allocate memory for data structure of type UserData.
+ */
+
+static UserData AllocUserData(MPI_Comm comm, long int local_N, long int SystemSize)
+{
+ int ix, jy;
+ UserData webdata;
+
+ webdata = (UserData) malloc(sizeof *webdata);
+
+ webdata->rates = N_VNew_Parallel(comm, local_N, SystemSize);
+
+ 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->acoef = newDenseMat(NUM_SPECIES, NUM_SPECIES);
+ webdata->ewt = N_VNew_Parallel(comm, local_N, SystemSize);
+ return(webdata);
+
+}
+
+/*
+ * InitUserData: Load problem constants in webdata (of type UserData).
+ */
+
+static void InitUserData(UserData webdata, int thispe, int npes,
+ MPI_Comm comm)
+{
+ int i, j, np;
+ realtype *a1,*a2, *a3, *a4, dx2, dy2, **acoef, *bcoef, *cox, *coy;
+
+ webdata->jysub = thispe / NPEX;
+ webdata->ixsub = thispe - (webdata->jysub)*NPEX;
+ webdata->mxsub = MXSUB;
+ webdata->mysub = MYSUB;
+ webdata->npex = NPEX;
+ webdata->npey = NPEY;
+ webdata->ns = NUM_SPECIES;
+ webdata->np = NPREY;
+ webdata->dx = AX/(MX-1);
+ webdata->dy = AY/(MY-1);
+ webdata->thispe = thispe;
+ webdata->npes = npes;
+ webdata->nsmxsub = MXSUB * NUM_SPECIES;
+ webdata->nsmxsub2 = (MXSUB+2)*NUM_SPECIES;
+ webdata->comm = comm;
+
+ /* Set up the coefficients a and b plus others found in the equations. */
+ np = webdata->np;
+ dx2 = (webdata->dx)*(webdata->dx); dy2 = (webdata->dy)*(webdata->dy);
+
+ acoef = webdata->acoef;
+ bcoef = webdata->bcoef;
+ cox = webdata->cox;
+ coy = webdata->coy;
+
+ for (i = 0; i < np; i++) {
+ a1 = &(acoef[i][np]);
+ a2 = &(acoef[i+np][0]);
+ a3 = &(acoef[i][0]);
+ a4 = &(acoef[i+np][np]);
+
+ /* Fill in the portion of acoef in the four quadrants, row by row. */
+ for (j = 0; j < np; j++) {
+ *a1++ = -GG;
+ *a2++ = EE;
+ *a3++ = ZERO;
+ *a4++ = ZERO;
+ }
+
+ /* Reset the diagonal elements of acoef to -AA. */
+ acoef[i][i] = -AA; acoef[i+np][i+np] = -AA;
+
+ /* Set coefficients for b and diffusion terms. */
+ bcoef[i] = BB; bcoef[i+np] = -BB;
+ cox[i] = DPREY/dx2; cox[i+np] = DPRED/dx2;
+ coy[i] = DPREY/dy2; coy[i+np] = DPRED/dy2;
+ }
+
+}
+
+/*
+ * FreeUserData: Free webdata memory.
+ */
+
+static void FreeUserData(UserData webdata)
+{
+ int ix, jy;
+
+ for (ix = 0; ix < MXSUB; ix++) {
+ for (jy = 0; jy < MYSUB; jy++) {
+ destroyMat((webdata->PP)[ix][jy]);
+ destroyArray((webdata->pivot)[ix][jy]);
+ }
+ }
+
+ destroyMat(webdata->acoef);
+ N_VDestroy_Parallel(webdata->rates);
+ N_VDestroy_Parallel(webdata->ewt);
+ free(webdata);
+
+}
+
+/*
+ * SetInitialProfiles: Set initial conditions in cc, cp, and id.
+ * A polynomial profile is used for the prey cc values, and a constant
+ * (1.0e5) is loaded as the initial guess for the predator cc values.
+ * The id values are set to 1 for the prey and 0 for the predators.
+ * The prey cp values are set according to the given system, and
+ * the predator cp values are set to zero.
+ */
+
+static void SetInitialProfiles(N_Vector cc, N_Vector cp, N_Vector id,
+ N_Vector res, UserData webdata)
+{
+ int ixsub, jysub, mxsub, mysub, nsmxsub, np, ix, jy, is;
+ realtype *cxy, *idxy, *cpxy, dx, dy, xx, yy, xyfactor;
+
+ ixsub = webdata->ixsub;
+ jysub = webdata->jysub;
+ mxsub = webdata->mxsub;
+ mysub = webdata->mxsub;
+ nsmxsub = webdata->nsmxsub;
+ dx = webdata->dx;
+ dy = webdata->dy;
+ np = webdata->np;
+
+ /* Loop over grid, load cc values and id values. */
+ for (jy = 0; jy < mysub; jy++) {
+ yy = (jy + jysub*mysub) * dy;
+ for (ix = 0; ix < mxsub; ix++) {
+ xx = (ix + ixsub*mxsub) * dx;
+ xyfactor = RCONST(16.0)*xx*(ONE - xx)*yy*(ONE - yy);
+ xyfactor *= xyfactor;
+
+ 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; }
+ else { cxy[is] = 1.0e5; idxy[is] = ZERO; }
+ }
+ }
+ }
+
+ /* Set c' for the prey by calling the residual function with cp = 0. */
+ N_VConst(ZERO, cp);
+ resweb(ZERO, cc, cp, res, webdata);
+ N_VScale(-ONE, res, cp);
+
+ /* Set c' for predators to 0. */
+ for (jy = 0; jy < mysub; jy++) {
+ for (ix = 0; ix < mxsub; ix++) {
+ cpxy = IJ_Vptr(cp,ix,jy);
+ for (is = np; is < NUM_SPECIES; is++) cpxy[is] = ZERO;
+ }
+ }
+}
+
+/*
+ * Print first lines of output (problem description)
+ */
+
+static void PrintHeader(long int 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: %d\n",SystemSize);
+ printf("Subgrid dimensions: %d x %d", MXSUB, MYSUB);
+ printf(" Processor array: %d x %d\n", NPEX, NPEY);
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("Tolerance parameters: rtol = %Lg atol = %Lg\n", rtol, atol);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("Tolerance parameters: rtol = %lg atol = %lg\n", rtol, atol);
+#else
+ printf("Tolerance parameters: rtol = %g atol = %g\n", rtol, atol);
+#endif
+ printf("Linear solver: IDASPGMR 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");
+
+ printf("-----------------------------------------------------------\n");
+ printf(" t bottom-left top-right");
+ printf(" | nst k h\n");
+ printf("-----------------------------------------------------------\n\n");
+}
+
+/*
+ * PrintOutput: Print output values at output time t = tt.
+ * Selected run statistics are printed. Then values of c1 and c2
+ * are printed for the bottom left and top right grid points only.
+ * (NOTE: This routine is specific to the case NUM_SPECIES = 2.)
+ */
+
+static void PrintOutput(void *mem, N_Vector cc, realtype tt,
+ UserData webdata, MPI_Comm comm)
+{
+ MPI_Status status;
+ realtype *cdata, clast[2], hused;
+ long int nst;
+ int i, kused, flag, thispe, npelast, ilast;;
+
+ thispe = webdata->thispe;
+ npelast = webdata->npes - 1;
+ cdata = NV_DATA_P(cc);
+
+ /* Send conc. at top right mesh point from PE npes-1 to PE 0. */
+ if (thispe == npelast) {
+ ilast = NUM_SPECIES*MXSUB*MYSUB - 2;
+ if (npelast != 0)
+ MPI_Send(&cdata[ilast], 2, PVEC_REAL_MPI_TYPE, 0, 0, comm);
+ else { clast[0] = cdata[ilast]; clast[1] = cdata[ilast+1]; }
+ }
+
+ /* On PE 0, receive conc. at top right from PE npes - 1.
+ Then print performance data and sampled solution values. */
+
+ if (thispe == 0) {
+
+ if (npelast != 0)
+ MPI_Recv(&clast[0], 2, PVEC_REAL_MPI_TYPE, npelast, 0, comm, &status);
+
+ flag = IDAGetLastOrder(mem, &kused);
+ check_flag(&flag, "IDAGetLastOrder", 1, thispe);
+ flag = IDAGetNumSteps(mem, &nst);
+ check_flag(&flag, "IDAGetNumSteps", 1, thispe);
+ flag = IDAGetLastStep(mem, &hused);
+ check_flag(&flag, "IDAGetLastStep", 1, thispe);
+
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("%8.2Le %12.4Le %12.4Le | %3ld %1d %12.4Le\n",
+ tt, cdata[0], clast[0], nst, kused, hused);
+ for (i=1;i<NUM_SPECIES;i++)
+ printf(" %12.4Le %12.4Le |\n",cdata[i],clast[i]);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("%8.2le %12.4le %12.4le | %3ld %1d %12.4le\n",
+ tt, cdata[0], clast[0], nst, kused, hused);
+ for (i=1;i<NUM_SPECIES;i++)
+ printf(" %12.4le %12.4le |\n",cdata[i],clast[i]);
+#else
+ printf("%8.2e %12.4e %12.4e | %3ld %1d %12.4e\n",
+ tt, cdata[0], clast[0], nst, kused, hused);
+ for (i=1;i<NUM_SPECIES;i++)
+ printf(" %12.4e %12.4e |\n",cdata[i],clast[i]);
+#endif
+ printf("\n");
+
+ }
+}
+
+/*
+ * PrintFinalStats: Print final run data contained in iopt.
+ */
+
+static void PrintFinalStats(void *mem)
+{
+ long int nst, nre, nreLS, netf, ncfn, nni, ncfl, nli, npe, nps;
+ int flag;
+
+ flag = IDAGetNumSteps(mem, &nst);
+ check_flag(&flag, "IDAGetNumSteps", 1, 0);
+ flag = IDAGetNumResEvals(mem, &nre);
+ check_flag(&flag, "IDAGetNumResEvals", 1, 0);
+ flag = IDAGetNumErrTestFails(mem, &netf);
+ check_flag(&flag, "IDAGetNumErrTestFails", 1, 0);
+ flag = IDAGetNumNonlinSolvConvFails(mem, &ncfn);
+ check_flag(&flag, "IDAGetNumNonlinSolvConvFails", 1, 0);
+ flag = IDAGetNumNonlinSolvIters(mem, &nni);
+ check_flag(&flag, "IDAGetNumNonlinSolvIters", 1, 0);
+
+ flag = IDASpilsGetNumConvFails(mem, &ncfl);
+ check_flag(&flag, "IDASpilsGetNumConvFails", 1, 0);
+ flag = IDASpilsGetNumLinIters(mem, &nli);
+ check_flag(&flag, "IDASpilsGetNumLinIters", 1, 0);
+ flag = IDASpilsGetNumPrecEvals(mem, &npe);
+ check_flag(&flag, "IDASpilsGetNumPrecEvals", 1, 0);
+ flag = IDASpilsGetNumPrecSolves(mem, &nps);
+ check_flag(&flag, "IDASpilsGetNumPrecSolves", 1, 0);
+ flag = IDASpilsGetNumResEvals(mem, &nreLS);
+ check_flag(&flag, "IDASpilsGetNumResEvals", 1, 0);
+
+ printf("-----------------------------------------------------------\n");
+ printf("\nFinal statistics: \n\n");
+
+ printf("Number of steps = %ld\n", nst);
+ printf("Number of residual evaluations = %ld\n", nre+nreLS);
+ printf("Number of nonlinear iterations = %ld\n", nni);
+ printf("Number of error test failures = %ld\n", netf);
+ printf("Number of nonlinear conv. failures = %ld\n\n", ncfn);
+
+ printf("Number of linear iterations = %ld\n", nli);
+ printf("Number of linear conv. failures = %ld\n\n", ncfl);
+
+ printf("Number of preconditioner setups = %ld\n", npe);
+ printf("Number of preconditioner solves = %ld\n", nps);
+
+}
+
+/*
+ * 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, char *funcname, int opt, int id)
+{
+ int *errflag;
+
+ if (opt == 0 && flagvalue == NULL) {
+ /* Check if SUNDIALS function returned NULL pointer - no memory allocated */
+ fprintf(stderr,
+ "\nSUNDIALS_ERROR(%d): %s() failed - returned NULL pointer\n\n",
+ id, funcname);
+ return(1);
+ } else if (opt == 1) {
+ /* Check if flag < 0 */
+ errflag = (int *) flagvalue;
+ if (*errflag < 0) {
+ fprintf(stderr,
+ "\nSUNDIALS_ERROR(%d): %s() failed with flag = %d\n\n",
+ id, funcname, *errflag);
+ return(1);
+ }
+ } else if (opt == 2 && flagvalue == NULL) {
+ /* Check if function returned NULL pointer - no memory allocated */
+ fprintf(stderr,
+ "\nMEMORY_ERROR(%d): %s() failed - returned NULL pointer\n\n",
+ id, funcname);
+ return(1);
+ }
+
+ return(0);
+}
+
+/*
+ *--------------------------------------------------------------------
+ * FUNCTIONS CALLED BY IDA & SUPPORTING FUNCTIONS
+ *--------------------------------------------------------------------
+ */
+
+/*
+ * resweb: System residual function for predator-prey system.
+ * To compute the residual function F, this routine calls:
+ * rescomm, for needed communication, and then
+ * reslocal, for computation of the residuals on this processor.
+ */
+
+static int resweb(realtype tt, N_Vector cc, N_Vector cp,
+ N_Vector res, void *user_data)
+{
+ int flag;
+ UserData webdata;
+
+ webdata = (UserData)user_data;
+
+ /* Call rescomm to do inter-processor communication. */
+ flag = rescomm(cc, cp, webdata);
+
+ /* Call reslocal to calculate the local portion of residual vector. */
+ flag = reslocal(tt, cc, cp, res, webdata);
+
+ return(0);
+
+}
+
+/*
+ * rescomm: Communication routine in support of resweb.
+ * This routine performs all inter-processor communication of components
+ * of the cc vector needed to calculate F, namely the components at all
+ * interior subgrid boundaries (ghost cell data). It loads this data
+ * into a work array cext (the local portion of c, extended).
+ * The message-passing uses blocking sends, non-blocking receives,
+ * and receive-waiting, in routines BRecvPost, BSend, BRecvWait.
+ */
+
+static int rescomm(N_Vector cc, N_Vector cp, void *user_data)
+{
+
+ UserData webdata;
+ realtype *cdata, *cext, buffer[2*NUM_SPECIES*MYSUB];
+ int thispe, ixsub, jysub, nsmxsub, nsmysub;
+ MPI_Comm comm;
+ MPI_Request request[4];
+
+ webdata = (UserData) user_data;
+ cdata = NV_DATA_P(cc);
+
+ /* Get comm, thispe, subgrid indices, data sizes, extended array cext. */
+ comm = webdata->comm; thispe = webdata->thispe;
+ ixsub = webdata->ixsub; jysub = webdata->jysub;
+ cext = webdata->cext;
+ nsmxsub = webdata->nsmxsub; nsmysub = (webdata->ns)*(webdata->mysub);
+
+ /* Start receiving boundary data from neighboring PEs. */
+ BRecvPost(comm, request, thispe, ixsub, jysub, nsmxsub, nsmysub,
+ cext, buffer);
+
+ /* Send data from boundary of local grid to neighboring PEs. */
+ BSend(comm, thispe, ixsub, jysub, nsmxsub, nsmysub, cdata);
+
+ /* Finish receiving boundary data from neighboring PEs. */
+ BRecvWait(request, ixsub, jysub, nsmxsub, cext, buffer);
+
+ return(0);
+
+}
+
+/*
+ * BSend: Send boundary data to neighboring PEs.
+ * This routine sends components of cc from internal subgrid boundaries
+ * to the appropriate neighbor PEs.
+ */
+
+static void BSend(MPI_Comm comm, int my_pe, int ixsub, int jysub,
+ int dsizex, int dsizey, realtype cdata[])
+{
+ int i;
+ int ly, offsetc, offsetbuf;
+ realtype bufleft[NUM_SPECIES*MYSUB], bufright[NUM_SPECIES*MYSUB];
+
+ /* If jysub > 0, send data from bottom x-line of cc. */
+ if (jysub != 0)
+ MPI_Send(&cdata[0], dsizex, PVEC_REAL_MPI_TYPE, my_pe-NPEX, 0, comm);
+
+ /* If jysub < NPEY-1, send data from top x-line of cc. */
+ if (jysub != NPEY-1) {
+ offsetc = (MYSUB-1)*dsizex;
+ MPI_Send(&cdata[offsetc], dsizex, PVEC_REAL_MPI_TYPE, my_pe+NPEX, 0, comm);
+ }
+
+ /* If ixsub > 0, send data from left y-line of cc (via bufleft). */
+ if (ixsub != 0) {
+ for (ly = 0; ly < MYSUB; ly++) {
+ offsetbuf = ly*NUM_SPECIES;
+ offsetc = ly*dsizex;
+ for (i = 0; i < NUM_SPECIES; i++)
+ bufleft[offsetbuf+i] = cdata[offsetc+i];
+ }
+ MPI_Send(&bufleft[0], dsizey, PVEC_REAL_MPI_TYPE, my_pe-1, 0, comm);
+ }
+
+ /* If ixsub < NPEX-1, send data from right y-line of cc (via bufright). */
+ if (ixsub != NPEX-1) {
+ for (ly = 0; ly < MYSUB; ly++) {
+ offsetbuf = ly*NUM_SPECIES;
+ offsetc = offsetbuf*MXSUB + (MXSUB-1)*NUM_SPECIES;
+ for (i = 0; i < NUM_SPECIES; i++)
+ bufright[offsetbuf+i] = cdata[offsetc+i];
+ }
+ MPI_Send(&bufright[0], dsizey, PVEC_REAL_MPI_TYPE, my_pe+1, 0, comm);
+ }
+
+}
+
+/*
+ * BRecvPost: Start receiving boundary data from neighboring PEs.
+ * (1) buffer should be able to hold 2*NUM_SPECIES*MYSUB realtype entries,
+ * should be passed to both the BRecvPost and BRecvWait functions, and
+ * should not be manipulated between the two calls.
+ * (2) request should have 4 entries, and is also passed in both calls.
+ */
+
+static void BRecvPost(MPI_Comm comm, MPI_Request request[], int my_pe,
+ int ixsub, int jysub,
+ int dsizex, int dsizey,
+ realtype cext[], realtype buffer[])
+{
+ int offsetce;
+ /* Have bufleft and bufright use the same buffer. */
+ realtype *bufleft = buffer, *bufright = buffer+NUM_SPECIES*MYSUB;
+
+ /* If jysub > 0, receive data for bottom x-line of cext. */
+ if (jysub != 0)
+ MPI_Irecv(&cext[NUM_SPECIES], dsizex, PVEC_REAL_MPI_TYPE,
+ my_pe-NPEX, 0, comm, &request[0]);
+
+ /* If jysub < NPEY-1, receive data for top x-line of cext. */
+ if (jysub != NPEY-1) {
+ offsetce = NUM_SPECIES*(1 + (MYSUB+1)*(MXSUB+2));
+ MPI_Irecv(&cext[offsetce], dsizex, PVEC_REAL_MPI_TYPE,
+ my_pe+NPEX, 0, comm, &request[1]);
+ }
+
+ /* If ixsub > 0, receive data for left y-line of cext (via bufleft). */
+ if (ixsub != 0) {
+ MPI_Irecv(&bufleft[0], dsizey, PVEC_REAL_MPI_TYPE,
+ my_pe-1, 0, comm, &request[2]);
+ }
+
+ /* If ixsub < NPEX-1, receive data for right y-line of cext (via bufright). */
+ if (ixsub != NPEX-1) {
+ MPI_Irecv(&bufright[0], dsizey, PVEC_REAL_MPI_TYPE,
+ my_pe+1, 0, comm, &request[3]);
+ }
+
+}
+
+/*
+ * BRecvWait: Finish receiving boundary data from neighboring PEs.
+ * (1) buffer should be able to hold 2*NUM_SPECIES*MYSUB realtype entries,
+ * should be passed to both the BRecvPost and BRecvWait functions, and
+ * should not be manipulated between the two calls.
+ * (2) request should have 4 entries, and is also passed in both calls.
+ */
+
+static void BRecvWait(MPI_Request request[], int ixsub, int jysub,
+ int dsizex, realtype cext[], realtype buffer[])
+{
+ int i;
+ int ly, dsizex2, offsetce, offsetbuf;
+ realtype *bufleft = buffer, *bufright = buffer+NUM_SPECIES*MYSUB;
+ MPI_Status status;
+
+ dsizex2 = dsizex + 2*NUM_SPECIES;
+
+ /* If jysub > 0, receive data for bottom x-line of cext. */
+ if (jysub != 0)
+ MPI_Wait(&request[0],&status);
+
+ /* If jysub < NPEY-1, receive data for top x-line of cext. */
+ if (jysub != NPEY-1)
+ MPI_Wait(&request[1],&status);
+
+ /* If ixsub > 0, receive data for left y-line of cext (via bufleft). */
+ if (ixsub != 0) {
+ MPI_Wait(&request[2],&status);
+
+ /* Copy the buffer to cext */
+ for (ly = 0; ly < MYSUB; ly++) {
+ offsetbuf = ly*NUM_SPECIES;
+ offsetce = (ly+1)*dsizex2;
+ for (i = 0; i < NUM_SPECIES; i++)
+ cext[offsetce+i] = bufleft[offsetbuf+i];
+ }
+ }
+
+ /* If ixsub < NPEX-1, receive data for right y-line of cext (via bufright). */
+ if (ixsub != NPEX-1) {
+ MPI_Wait(&request[3],&status);
+
+ /* Copy the buffer to cext */
+ for (ly = 0; ly < MYSUB; ly++) {
+ offsetbuf = ly*NUM_SPECIES;
+ offsetce = (ly+2)*dsizex2 - NUM_SPECIES;
+ for (i = 0; i < NUM_SPECIES; i++)
+ cext[offsetce+i] = bufright[offsetbuf+i];
+ }
+ }
+}
+
+/* Define lines are for ease of readability in the following functions. */
+
+#define mxsub (webdata->mxsub)
+#define mysub (webdata->mysub)
+#define npex (webdata->npex)
+#define npey (webdata->npey)
+#define ixsub (webdata->ixsub)
+#define jysub (webdata->jysub)
+#define nsmxsub (webdata->nsmxsub)
+#define nsmxsub2 (webdata->nsmxsub2)
+#define np (webdata->np)
+#define dx (webdata->dx)
+#define dy (webdata->dy)
+#define cox (webdata->cox)
+#define coy (webdata->coy)
+#define rhs (webdata->rhs)
+#define cext (webdata->cext)
+#define rates (webdata->rates)
+#define ns (webdata->ns)
+#define acoef (webdata->acoef)
+#define bcoef (webdata->bcoef)
+
+/*
+ * reslocal: Compute res = F(t,cc,cp).
+ * This routine assumes that all inter-processor communication of data
+ * needed to calculate F has already been done. Components at interior
+ * subgrid boundaries are assumed to be in the work array cext.
+ * The local portion of the cc vector is first copied into cext.
+ * The exterior Neumann boundary conditions are explicitly handled here
+ * by copying data from the first interior mesh line to the ghost cell
+ * locations in cext. Then the reaction and diffusion terms are
+ * evaluated in terms of the cext array, and the residuals are formed.
+ * The reaction terms are saved separately in the vector webdata->rates
+ * for use by the preconditioner setup routine.
+ */
+
+static int reslocal(realtype tt, N_Vector cc, N_Vector cp, N_Vector res,
+ void *user_data)
+{
+ realtype *cdata, *ratesxy, *cpxy, *resxy,
+ xx, yy, dcyli, dcyui, dcxli, dcxui;
+ int ix, jy, is, i, locc, ylocce, locce;
+ UserData webdata;
+
+ webdata = (UserData) user_data;
+
+ /* Get data pointers, subgrid data, array sizes, work array cext. */
+ cdata = NV_DATA_P(cc);
+
+ /* Copy local segment of cc vector into the working extended array cext. */
+ locc = 0;
+ locce = nsmxsub2 + NUM_SPECIES;
+ for (jy = 0; jy < mysub; jy++) {
+ for (i = 0; i < nsmxsub; i++) cext[locce+i] = cdata[locc+i];
+ locc = locc + nsmxsub;
+ locce = locce + nsmxsub2;
+ }
+
+ /* To facilitate homogeneous Neumann boundary conditions, when this is
+ a boundary PE, copy data from the first interior mesh line of cc to cext. */
+
+ /* If jysub = 0, copy x-line 2 of cc to cext. */
+ if (jysub == 0)
+ { for (i = 0; i < nsmxsub; i++) cext[NUM_SPECIES+i] = cdata[nsmxsub+i]; }
+
+ /* If jysub = npey-1, copy x-line mysub-1 of cc to cext. */
+ if (jysub == npey-1) {
+ locc = (mysub-2)*nsmxsub;
+ locce = (mysub+1)*nsmxsub2 + NUM_SPECIES;
+ for (i = 0; i < nsmxsub; i++) cext[locce+i] = cdata[locc+i];
+ }
+
+ /* If ixsub = 0, copy y-line 2 of cc to cext. */
+ if (ixsub == 0) {
+ for (jy = 0; jy < mysub; jy++) {
+ locc = jy*nsmxsub + NUM_SPECIES;
+ locce = (jy+1)*nsmxsub2;
+ for (i = 0; i < NUM_SPECIES; i++) cext[locce+i] = cdata[locc+i];
+ }
+ }
+
+ /* If ixsub = npex-1, copy y-line mxsub-1 of cc to cext. */
+ if (ixsub == npex-1) {
+ for (jy = 0; jy < mysub; jy++) {
+ locc = (jy+1)*nsmxsub - 2*NUM_SPECIES;
+ locce = (jy+2)*nsmxsub2 - NUM_SPECIES;
+ for (i = 0; i < NUM_SPECIES; i++) cext[locce+i] = cdata[locc+i];
+ }
+ }
+
+ /* Loop over all grid points, setting local array rates to right-hand sides.
+ Then set res values appropriately for prey/predator components of F. */
+ for (jy = 0; jy < mysub; jy++) {
+ ylocce = (jy+1)*nsmxsub2;
+ yy = (jy+jysub*mysub)*dy;
+
+ for (ix = 0; ix < mxsub; ix++) {
+ locce = ylocce + (ix+1)*NUM_SPECIES;
+ xx = (ix + ixsub*mxsub)*dx;
+
+ ratesxy = IJ_Vptr(rates,ix,jy);
+ WebRates(xx, yy, &(cext[locce]), ratesxy, webdata);
+
+ resxy = IJ_Vptr(res,ix,jy);
+ cpxy = IJ_Vptr(cp,ix,jy);
+
+ for (is = 0; is < NUM_SPECIES; is++) {
+ dcyli = cext[locce+is] - cext[locce+is-nsmxsub2];
+ dcyui = cext[locce+is+nsmxsub2] - cext[locce+is];
+
+ dcxli = cext[locce+is] - cext[locce+is-NUM_SPECIES];
+ dcxui = cext[locce+is+NUM_SPECIES] - cext[locce+is];
+
+ rhs[is] = cox[is]*(dcxui-dcxli) + coy[is]*(dcyui-dcyli) + ratesxy[is];
+
+ if (is < np) resxy[is] = cpxy[is] - rhs[is];
+ else resxy[is] = - rhs[is];
+
+ } /* End of is (species) loop. */
+ } /* End of ix loop. */
+ } /* End of jy loop. */
+
+ return(0);
+
+}
+
+/*
+ * WebRates: Evaluate reaction rates at a given spatial point.
+ * At a given (x,y), evaluate the array of ns reaction terms R.
+ */
+
+static void WebRates(realtype xx, realtype yy, realtype *cxy, realtype *ratesxy,
+ UserData webdata)
+{
+ int is;
+ realtype fac;
+
+ for (is = 0; is < NUM_SPECIES; is++)
+ ratesxy[is] = dotprod(NUM_SPECIES, cxy, acoef[is]);
+
+ fac = ONE + ALPHA*xx*yy + BETA*sin(FOURPI*xx)*sin(FOURPI*yy);
+
+ for (is = 0; is < NUM_SPECIES; is++)
+ ratesxy[is] = cxy[is]*( bcoef[is]*fac + ratesxy[is] );
+
+}
+
+/*
+ * dotprod: dot product routine for realtype arrays, for use by WebRates.
+ */
+
+static realtype dotprod(int size, realtype *x1, realtype *x2)
+{
+ int i;
+ realtype *xx1, *xx2, temp = ZERO;
+
+ xx1 = x1; xx2 = x2;
+ for (i = 0; i < size; i++) temp += (*xx1++) * (*xx2++);
+ return(temp);
+
+}
+
+/*
+ * Preconbd: Preconditioner setup routine.
+ * This routine generates and preprocesses the block-diagonal
+ * preconditoner PP. At each spatial point, a block of PP is computed
+ * by way of difference quotients on the reaction rates R.
+ * The base value of R are taken from webdata->rates, as set by webres.
+ * 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)
+{
+ int flag, thispe;
+ realtype uround;
+ realtype xx, yy, *cxy, *ewtxy, cctemp, **Pxy, *ratesxy, *Pxycol, *cpxy;
+ realtype inc, sqru, fac, perturb_rates[NUM_SPECIES];
+ int is, js, ix, jy, ret;
+ UserData webdata;
+ void *mem;
+ N_Vector ewt;
+ realtype hh;
+
+ webdata = (UserData)user_data;
+ uround = UNIT_ROUNDOFF;
+ sqru = SQRT(uround);
+ thispe = webdata->thispe;
+
+ mem = webdata->ida_mem;
+ ewt = webdata->ewt;
+ flag = IDAGetErrWeights(mem, ewt);
+ check_flag(&flag, "IDAGetErrWeights", 1, thispe);
+ flag = IDAGetCurrentStep(mem, &hh);
+ check_flag(&flag, "IDAGetCurrentStep", 1, thispe);
+
+ for (jy = 0; jy < mysub; jy++) {
+ yy = (jy + jysub*mysub)*dy;
+
+ for (ix = 0; ix < mxsub; ix++) {
+ xx = (ix+ ixsub*mxsub)*dx;
+ Pxy = (webdata->PP)[ix][jy];
+ cxy = IJ_Vptr(cc,ix,jy);
+ cpxy = IJ_Vptr(cp,ix,jy);
+ ewtxy= IJ_Vptr(ewt,ix,jy);
+ ratesxy = IJ_Vptr(rates,ix,jy);
+
+ for (js = 0; js < ns; js++) {
+ inc = sqru*(MAX(ABS(cxy[js]), MAX(hh*ABS(cpxy[js]), ONE/ewtxy[js])));
+ cctemp = cxy[js]; /* Save the (js,ix,jy) element of cc. */
+ cxy[js] += inc; /* Perturb the (js,ix,jy) element of cc. */
+ fac = -ONE/inc;
+
+ WebRates(xx, yy, cxy, perturb_rates, webdata);
+
+ Pxycol = Pxy[js];
+
+ for (is = 0; is < ns; is++)
+ Pxycol[is] = (perturb_rates[is] - ratesxy[is])*fac;
+
+ if (js < np) Pxycol[js] += cj; /* Add partial with respect to cp. */
+
+ cxy[js] = cctemp; /* Restore (js,ix,jy) element of cc. */
+
+ } /* End of js loop. */
+
+ /* Do LU decomposition of matrix block for grid point (ix,jy). */
+ ret = denseGETRF(Pxy, ns, ns, (webdata->pivot)[ix][jy]);
+
+ if (ret != 0) return(1);
+
+ } /* End of ix loop. */
+ } /* End of jy loop. */
+
+ return(0);
+
+}
+
+/*
+ * PSolvebd: Preconditioner solve routine.
+ * This routine applies the LU factorization of the blocks of the
+ * 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)
+{
+ realtype **Pxy, *zxy;
+ long int *pivot, ix, jy;
+ UserData webdata;
+
+ webdata = (UserData)user_data;
+
+ N_VScale(ONE, rvec, zvec);
+
+ /* Loop through subgrid and apply preconditioner factors at each point. */
+ for (ix = 0; ix < mxsub; ix++) {
+ for (jy = 0; jy < mysub; jy++) {
+
+ /* For grid point (ix,jy), do backsolve on local vector.
+ zxy is the address of the local portion of zvec, and
+ Pxy is the address of the corresponding block of PP. */
+ zxy = IJ_Vptr(zvec,ix,jy);
+ Pxy = (webdata->PP)[ix][jy];
+ pivot = (webdata->pivot)[ix][jy];
+ denseGETRS(Pxy, ns, pivot, zxy);
+
+ } /* End of jy loop. */
+ } /* End of ix loop. */
+
+ return(0);
+
+}
diff --git a/examples/idas/parallel/idasFoodWeb_kry_p.out b/examples/idas/parallel/idasFoodWeb_kry_p.out
new file mode 100644
index 0000000..85cfd22
--- /dev/null
+++ b/examples/idas/parallel/idasFoodWeb_kry_p.out
@@ -0,0 +1,49 @@
+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
+Preconditioner: block diagonal, block size ns, via difference quotients
+CalcIC called to correct initial predator concentrations
+
+-----------------------------------------------------------
+ t bottom-left top-right | nst k h
+-----------------------------------------------------------
+
+0.00e+00 1.0000e+01 1.0000e+01 | 0 0 1.6310e-08
+ 1.0000e+05 1.0000e+05 |
+
+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 | 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
+ 2.4019e+06 2.7072e+06 |
+
+4.00e-01 2.4019e+02 2.7072e+02 | 165 1 3.2316e-01
+ 2.4019e+06 2.7072e+06 |
+
+7.00e-01 2.4019e+02 2.7072e+02 | 166 1 6.4633e-01
+ 2.4019e+06 2.7072e+06 |
+
+1.00e+00 2.4019e+02 2.7072e+02 | 166 1 6.4633e-01
+ 2.4019e+06 2.7072e+06 |
+
+-----------------------------------------------------------
+
+Final statistics:
+
+Number of steps = 166
+Number of residual evaluations = 1257
+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 conv. failures = 0
+
+Number of preconditioner setups = 25
+Number of preconditioner solves = 1257
diff --git a/examples/idas/parallel/idasHeat2D_FSA_kry_bbd_p.c b/examples/idas/parallel/idasHeat2D_FSA_kry_bbd_p.c
new file mode 100644
index 0000000..d2c882c
--- /dev/null
+++ b/examples/idas/parallel/idasHeat2D_FSA_kry_bbd_p.c
@@ -0,0 +1,969 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.2 $
+ * $Date: 2010/12/01 23:06:38 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Example problem for IDAS: FSA for 2D heat equation, parallel,
+ * GMRES, IDABBDPRE.
+ *
+ * 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.
+ *
+ * The DAE system solved is a spatial discretization of the PDE
+ * du/dt = p1 * d^2u/dx^2 + p2 * d^2u/dy^2
+ * on the unit square. The nominal values of the parameters are
+ * p1 = p2 = 1.0. The boundary condition is u = 0 on all edges.
+ * Initial conditions are given by u = 16 x (1 - x) y (1 - y).
+ * The PDE is treated with central differences on a uniform
+ * MX x MY grid. The values of u at the interior points satisfy
+ * ODEs, and equations u = 0 at the boundaries are appended,\
+ * to form a DAE system of size N = MX * MY. Here MX = MY = 10.
+ *
+ * The system is actually implemented on submeshes, processor by
+ * processor, with an MXSUB by MYSUB mesh on each of NPEX * NPEY
+ * processors.
+ *
+ * The system is solved with IDA using the Krylov linear solver
+ * IDASPGMR 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
+ * suppressed. Output is taken at t = 0, .01, .02, .04, ..., 10.24.
+ * -----------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include <idas/idas.h>
+#include <idas/idas_spgmr.h>
+#include <idas/idas_bbdpre.h>
+#include <nvector/nvector_parallel.h>
+#include <sundials/sundials_math.h>
+
+#include <mpi.h>
+
+#define ZERO RCONST(0.0)
+#define ONE RCONST(1.0)
+#define TWO RCONST(2.0)
+
+#define NOUT 11 /* Number of output times */
+
+#define NPEX 2 /* No. PEs in x direction of PE array */
+#define NPEY 2 /* No. PEs in y direction of PE array */
+ /* Total no. PEs = NPEX*NPEY */
+#define MXSUB 5 /* No. x points per subgrid */
+#define MYSUB 5 /* No. y points per subgrid */
+
+#define MX (NPEX*MXSUB) /* MX = number of x mesh points */
+#define MY (NPEY*MYSUB) /* MY = number of y mesh points */
+ /* Spatial mesh is MX by MY */
+
+#define NS 2 /* Number of sensitivities (NS<=2) */
+
+typedef struct {
+ realtype p[2];
+ int thispe, mx, my, ixsub, jysub, npex, npey, mxsub, mysub;
+ long int n_local;
+ realtype dx, dy, coeffx, coeffy, coeffxy;
+ realtype uext[(MXSUB+2)*(MYSUB+2)];
+ MPI_Comm comm;
+} *UserData;
+
+/* 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,
+ N_Vector uu, N_Vector up, N_Vector res,
+ void *user_data);
+static int BSend(MPI_Comm comm, int thispe, int ixsub,
+ int jysub, int dsizex, int dsizey,
+ realtype uarray[]);
+static int BRecvPost(MPI_Comm comm, MPI_Request request[], int thispe,
+ int ixsub, int jysub,
+ int dsizex, int dsizey,
+ realtype uext[], realtype buffer[]);
+static int BRecvWait(MPI_Request request[], int ixsub, int jysub,
+ int dsizex, realtype uext[], realtype buffer[]);
+
+/* Prototypes of private functions */
+
+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,
+ booleantype sensi, int sensi_meth, int err_con);
+static void PrintOutput(int id, void *mem, realtype t, N_Vector uu,
+ booleantype sensi, N_Vector *uuS);
+static void PrintFinalStats(void *mem);
+
+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 int check_flag(void *flagvalue, char *funcname, int opt, int id);
+
+/*
+ *--------------------------------------------------------------------
+ * MAIN PROGRAM
+ *--------------------------------------------------------------------
+ */
+
+int main(int argc, char *argv[])
+{
+ MPI_Comm comm;
+ void *mem;
+ UserData data;
+ int thispe, iout, ier, npes;
+ long int Neq, local_N, mudq, mldq, mukeep, mlkeep;
+ realtype rtol, atol, t0, t1, tout, tret;
+ N_Vector uu, up, constraints, id, res;
+
+ realtype *pbar;
+ int is;
+ N_Vector *uuS, *upS;
+ booleantype sensi, err_con;
+ int sensi_meth;
+
+ mem = NULL;
+ data = NULL;
+ uu = up = constraints = id = res = NULL;
+ uuS = upS = NULL;
+
+ /* Get processor number and total number of pe's. */
+
+ MPI_Init(&argc, &argv);
+ comm = MPI_COMM_WORLD;
+ MPI_Comm_size(comm, &npes);
+ MPI_Comm_rank(comm, &thispe);
+
+ if (npes != NPEX*NPEY) {
+ if (thispe == 0)
+ fprintf(stderr,
+ "\nMPI_ERROR(0): npes = %d is not equal to NPEX*NPEY = %d\n",
+ npes,NPEX*NPEY);
+ MPI_Finalize();
+ return(1);
+ }
+
+ /* Process arguments */
+
+ ProcessArgs(argc, argv, thispe, &sensi, &sensi_meth, &err_con);
+
+ /* Set local length local_N and global length Neq. */
+
+ local_N = MXSUB*MYSUB;
+ Neq = MX * MY;
+
+ /* Allocate N-vectors. */
+
+ uu = N_VNew_Parallel(comm, local_N, Neq);
+ if(check_flag((void *)uu, "N_VNew_Parallel", 0, thispe)) MPI_Abort(comm, 1);
+
+ up = N_VNew_Parallel(comm, local_N, Neq);
+ if(check_flag((void *)up, "N_VNew_Parallel", 0, thispe)) MPI_Abort(comm, 1);
+
+ res = N_VNew_Parallel(comm, local_N, Neq);
+ if(check_flag((void *)res, "N_VNew_Parallel", 0, thispe)) MPI_Abort(comm, 1);
+
+ constraints = N_VNew_Parallel(comm, local_N, Neq);
+ if(check_flag((void *)constraints, "N_VNew_Parallel", 0, thispe)) MPI_Abort(comm, 1);
+
+ id = N_VNew_Parallel(comm, local_N, Neq);
+ if(check_flag((void *)id, "N_VNew_Parallel", 0, thispe)) MPI_Abort(comm, 1);
+
+ /* Allocate and initialize the data structure. */
+
+ data = (UserData) malloc(sizeof *data);
+ if(check_flag((void *)data, "malloc", 2, thispe)) MPI_Abort(comm, 1);
+
+ InitUserData(thispe, comm, data);
+
+ /* Initialize the uu, up, id, and constraints profiles. */
+
+ SetInitialProfile(uu, up, id, res, data);
+ N_VConst(ONE, constraints);
+
+ t0 = ZERO; t1 = RCONST(0.01);
+
+ /* Scalar relative and absolute tolerance. */
+
+ rtol = ZERO;
+ atol = RCONST(1.0e-3);
+
+ /* Call IDACreate and IDAInit to initialize solution and various
+ IDASet*** functions to specify optional inputs:
+ - indicate which variables are differential and which are algebraic
+ - 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);
+
+ ier = IDASetUserData(mem, data);
+ if(check_flag(&ier, "IDASetUserData", 1, thispe)) MPI_Abort(comm, 1);
+
+ ier = IDASetSuppressAlg(mem, TRUE);
+ if(check_flag(&ier, "IDASetSuppressAlg", 1, thispe)) MPI_Abort(comm, 1);
+
+ ier = IDASetId(mem, id);
+ if(check_flag(&ier, "IDASetId", 1, thispe)) MPI_Abort(comm, 1);
+
+ ier = IDASetConstraints(mem, constraints);
+ if(check_flag(&ier, "IDASetConstraints", 1, thispe)) MPI_Abort(comm, 1);
+ N_VDestroy_Parallel(constraints);
+
+ ier = IDAInit(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);
+ if(check_flag(&ier, "IDASStolerances", 1, thispe)) MPI_Abort(comm, 1);
+
+ /* Call IDASpgmr to specify the linear solver. */
+
+ ier = IDASpgmr(mem, 12);
+ if(check_flag(&ier, "IDASpgmr", 1, thispe)) MPI_Abort(comm, 1);
+
+ /* Call IDABBDPrecInit to initialize BBD preconditioner. */
+
+ mudq = MXSUB;
+ mldq = MXSUB;
+ mukeep = 1;
+ mlkeep = 1;
+ ier = IDABBDPrecInit(mem, local_N, mudq, mldq, mukeep, mlkeep,
+ ZERO, reslocal, NULL);
+ if(check_flag(&ier, "IDABBDPrecInit", 1, thispe)) MPI_Abort(comm, 1);
+
+ /* Sensitivity-related settings */
+
+ if( sensi) {
+
+ /* Allocate and set pbar, the vector with order of magnitude
+ information for the problem parameters. (Note: this is
+ done here as an illustration only, as the default values
+ for pbar, if pbar is not supplied, are anyway 1.0) */
+
+ pbar = (realtype *) malloc(NS*sizeof(realtype));
+ if (check_flag((void *)pbar, "malloc", 2, thispe)) MPI_Abort(comm, 1);
+ for (is=0; is<NS; is++) pbar[is] = data->p[is];
+
+ /* Allocate sensitivity solution vectors uuS and upS and set them
+ to an initial guess for the sensitivity ICs (the IC for uuS are
+ 0.0 since the state IC do not depend on the porblem parameters;
+ however, the derivatives upS may not and therefore we will have
+ to call IDACalcIC to find them) */
+
+ uuS = N_VCloneVectorArray_Parallel(NS, uu);
+ if (check_flag((void *)uuS, "N_VCloneVectorArray_Parallel", 0, thispe)) MPI_Abort(comm, 1);
+ for (is = 0; is < NS; is++) N_VConst(ZERO,uuS[is]);
+
+ upS = N_VCloneVectorArray_Parallel(NS, uu);
+ if (check_flag((void *)upS, "N_VCloneVectorArray_Parallel", 0, thispe)) MPI_Abort(comm, 1);
+ for (is = 0; is < NS; is++) N_VConst(ZERO,upS[is]);
+
+ /* 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);
+ 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);
+ 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);
+ 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);
+ 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);
+ if(check_flag(&ier, "IDACalcIC", 1, thispe)) MPI_Abort(comm, 1);
+
+ }
+
+ /* Print problem description */
+
+ if (thispe == 0 ) PrintHeader(Neq, rtol, atol, mudq, mukeep,
+ sensi, sensi_meth, err_con);
+
+ /* 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);
+ if(check_flag(&ier, "IDASolve", 1, thispe)) MPI_Abort(comm, 1);
+
+ if (sensi) {
+ ier = IDAGetSens(mem, &tret, uuS);
+ if(check_flag(&ier, "IDAGetSens", 1, thispe)) MPI_Abort(comm, 1);
+ }
+
+ PrintOutput(thispe, mem, tret, uu, sensi, uuS);
+
+ }
+
+ /* Print final statistics */
+
+ if (thispe == 0) PrintFinalStats(mem);
+
+ /* Free Memory */
+ IDAFree(&mem);
+ free(data);
+ N_VDestroy_Parallel(id);
+ N_VDestroy_Parallel(res);
+ N_VDestroy_Parallel(up);
+ N_VDestroy_Parallel(uu);
+
+ MPI_Finalize();
+
+ return(0);
+
+}
+/*
+ *--------------------------------------------------------------------
+ * FUNCTIONS CALLED BY IDA
+ *--------------------------------------------------------------------
+ */
+
+/*
+ * heatres: heat equation system residual function
+ * This uses 5-point central differencing on the interior points, and
+ * includes algebraic equations for the boundary values.
+ * So for each interior point, the residual component has the form
+ * res_i = u'_i - (central difference)_i
+ * while for each boundary point, it is res_i = u_i.
+ *
+ * This parallel implementation uses several supporting routines.
+ * First a call is made to rescomm to do communication of subgrid boundary
+ * data into array uext. Then reslocal is called to compute the residual
+ * on individual processors and their corresponding domains. The routines
+ * BSend, BRecvPost, and BREcvWait handle interprocessor communication
+ * of uu required to calculate the residual.
+ */
+
+static int heatres(realtype tres, N_Vector uu, N_Vector up,
+ N_Vector res, void *user_data)
+{
+ int retval;
+ UserData data;
+ long int Nlocal;
+
+ data = (UserData) user_data;
+
+ Nlocal = data->n_local;
+
+ /* Call rescomm to do inter-processor communication. */
+ retval = rescomm(Nlocal, tres, uu, up, data);
+
+ /* Call reslocal to calculate res. */
+ retval = reslocal(Nlocal, tres, uu, up, res, data);
+
+ return(0);
+
+}
+
+/*
+ * rescomm routine. This routine performs all inter-processor
+ * communication of data in u needed to calculate G.
+ */
+
+static int rescomm(long int Nlocal, realtype tt,
+ N_Vector uu, N_Vector up, void *user_data)
+{
+ UserData data;
+ realtype *uarray, *uext, buffer[2*MYSUB];
+ MPI_Comm comm;
+ int thispe, ixsub, jysub, mxsub, mysub;
+ MPI_Request request[4];
+
+ data = (UserData) user_data;
+ uarray = NV_DATA_P(uu);
+
+ /* Get comm, thispe, subgrid indices, data sizes, extended array uext. */
+ comm = data->comm; thispe = data->thispe;
+ ixsub = data->ixsub; jysub = data->jysub;
+ mxsub = data->mxsub; mysub = data->mysub;
+ uext = data->uext;
+
+ /* Start receiving boundary data from neighboring PEs. */
+ BRecvPost(comm, request, thispe, ixsub, jysub, mxsub, mysub, uext, buffer);
+
+ /* Send data from boundary of local grid to neighboring PEs. */
+ BSend(comm, thispe, ixsub, jysub, mxsub, mysub, uarray);
+
+ /* Finish receiving boundary data from neighboring PEs. */
+ BRecvWait(request, ixsub, jysub, mxsub, uext, buffer);
+
+ return(0);
+
+}
+
+/*
+ * reslocal routine. Compute res = F(t, uu, up). This routine assumes
+ * that all inter-processor communication of data needed to calculate F
+ * has already been done, and that this data is in the work array uext.
+ */
+
+static int reslocal(long int Nlocal, realtype tres,
+ N_Vector uu, N_Vector up, N_Vector res,
+ void *user_data)
+{
+ realtype *uext, *uuv, *upv, *resv;
+ realtype termx, termy;
+ int lx, ly, offsetu, offsetue, locu, locue;
+ int ixsub, jysub, mxsub, mxsub2, mysub, npex, npey;
+ int ixbegin, ixend, jybegin, jyend;
+ UserData data;
+ realtype p1, p2;
+
+ /* Get subgrid indices, array sizes, extended work array uext. */
+
+ data = (UserData) user_data;
+
+ uext = data->uext;
+ uuv = NV_DATA_P(uu);
+ upv = NV_DATA_P(up);
+ resv = NV_DATA_P(res);
+ ixsub = data->ixsub; jysub = data->jysub;
+ mxsub = data->mxsub; mxsub2 = data->mxsub + 2;
+ mysub = data->mysub; npex = data->npex; npey = data->npey;
+
+ p1 = data->p[0];
+ p2 = data->p[1];
+
+ /* Initialize all elements of res to uu. This sets the boundary
+ elements simply without indexing hassles. */
+
+ N_VScale(ONE, uu, res);
+
+ /* Copy local segment of u vector into the working extended array uext.
+ This completes uext prior to the computation of the res vector. */
+
+ offsetu = 0;
+ offsetue = mxsub2 + 1;
+ for (ly = 0; ly < mysub; ly++) {
+ for (lx = 0; lx < mxsub; lx++) uext[offsetue+lx] = uuv[offsetu+lx];
+ offsetu = offsetu + mxsub;
+ offsetue = offsetue + mxsub2;
+ }
+
+ /* Set loop limits for the interior of the local subgrid. */
+
+ ixbegin = 0;
+ ixend = mxsub-1;
+ jybegin = 0;
+ jyend = mysub-1;
+ if (ixsub == 0) ixbegin++; if (ixsub == npex-1) ixend--;
+ if (jysub == 0) jybegin++; if (jysub == npey-1) jyend--;
+
+ /* Loop over all grid points in local subgrid. */
+
+ for (ly = jybegin; ly <=jyend; ly++) {
+ for (lx = ixbegin; lx <= ixend; lx++) {
+ locu = lx + ly*mxsub;
+ locue = (lx+1) + (ly+1)*mxsub2;
+ termx = p1 * data->coeffx *(uext[locue-1] - TWO*uext[locue] + uext[locue+1]);
+ termy = p2 * data->coeffy *(uext[locue-mxsub2] - TWO*uext[locue] + uext[locue+mxsub2]);
+ resv[locu] = upv[locu] - (termx + termy);
+ }
+ }
+ return(0);
+
+}
+
+/*
+ * Routine to send boundary data to neighboring PEs.
+ */
+
+static int BSend(MPI_Comm comm, int thispe, int ixsub,
+ int jysub, int dsizex, int dsizey,
+ realtype uarray[])
+{
+ int ly, offsetu;
+ realtype bufleft[MYSUB], bufright[MYSUB];
+
+ /* If jysub > 0, send data from bottom x-line of u. */
+
+ if (jysub != 0)
+ MPI_Send(&uarray[0], dsizex, PVEC_REAL_MPI_TYPE, thispe-NPEX, 0, comm);
+
+ /* If jysub < NPEY-1, send data from top x-line of u. */
+
+ if (jysub != NPEY-1) {
+ offsetu = (MYSUB-1)*dsizex;
+ MPI_Send(&uarray[offsetu], dsizex, PVEC_REAL_MPI_TYPE,
+ thispe+NPEX, 0, comm);
+ }
+
+ /* If ixsub > 0, send data from left y-line of u (via bufleft). */
+
+ if (ixsub != 0) {
+ for (ly = 0; ly < MYSUB; ly++) {
+ offsetu = ly*dsizex;
+ bufleft[ly] = uarray[offsetu];
+ }
+ MPI_Send(&bufleft[0], dsizey, PVEC_REAL_MPI_TYPE, thispe-1, 0, comm);
+ }
+
+ /* If ixsub < NPEX-1, send data from right y-line of u (via bufright). */
+
+ if (ixsub != NPEX-1) {
+ for (ly = 0; ly < MYSUB; ly++) {
+ offsetu = ly*MXSUB + (MXSUB-1);
+ bufright[ly] = uarray[offsetu];
+ }
+ MPI_Send(&bufright[0], dsizey, PVEC_REAL_MPI_TYPE, thispe+1, 0, comm);
+ }
+
+ return(0);
+
+}
+
+/*
+ * Routine to start receiving boundary data from neighboring PEs.
+ * Notes:
+ * 1) buffer should be able to hold 2*MYSUB realtype entries, should be
+ * passed to both the BRecvPost and BRecvWait functions, and should not
+ * be manipulated between the two calls.
+ * 2) request should have 4 entries, and should be passed in
+ * both calls also.
+ */
+
+static int BRecvPost(MPI_Comm comm, MPI_Request request[], int thispe,
+ int ixsub, int jysub,
+ int dsizex, int dsizey,
+ realtype uext[], realtype buffer[])
+{
+ int offsetue;
+ /* Have bufleft and bufright use the same buffer. */
+ realtype *bufleft = buffer, *bufright = buffer+MYSUB;
+
+ /* If jysub > 0, receive data for bottom x-line of uext. */
+ if (jysub != 0)
+ MPI_Irecv(&uext[1], dsizex, PVEC_REAL_MPI_TYPE,
+ thispe-NPEX, 0, comm, &request[0]);
+
+ /* If jysub < NPEY-1, receive data for top x-line of uext. */
+ if (jysub != NPEY-1) {
+ offsetue = (1 + (MYSUB+1)*(MXSUB+2));
+ MPI_Irecv(&uext[offsetue], dsizex, PVEC_REAL_MPI_TYPE,
+ thispe+NPEX, 0, comm, &request[1]);
+ }
+
+ /* If ixsub > 0, receive data for left y-line of uext (via bufleft). */
+ if (ixsub != 0) {
+ MPI_Irecv(&bufleft[0], dsizey, PVEC_REAL_MPI_TYPE,
+ thispe-1, 0, comm, &request[2]);
+ }
+
+ /* If ixsub < NPEX-1, receive data for right y-line of uext (via bufright). */
+ if (ixsub != NPEX-1) {
+ MPI_Irecv(&bufright[0], dsizey, PVEC_REAL_MPI_TYPE,
+ thispe+1, 0, comm, &request[3]);
+ }
+
+ return(0);
+
+}
+
+/*
+ * Routine to finish receiving boundary data from neighboring PEs.
+ * Notes:
+ * 1) buffer should be able to hold 2*MYSUB realtype entries, should be
+ * passed to both the BRecvPost and BRecvWait functions, and should not
+ * be manipulated between the two calls.
+ * 2) request should have four entries, and should be passed in both
+ * calls also.
+ */
+
+static int BRecvWait(MPI_Request request[], int ixsub,
+ int jysub, int dsizex, realtype uext[],
+ realtype buffer[])
+{
+ int ly, dsizex2, offsetue;
+ realtype *bufleft = buffer, *bufright = buffer+MYSUB;
+ MPI_Status status;
+
+ dsizex2 = dsizex + 2;
+
+ /* If jysub > 0, receive data for bottom x-line of uext. */
+ if (jysub != 0)
+ MPI_Wait(&request[0],&status);
+
+ /* If jysub < NPEY-1, receive data for top x-line of uext. */
+ if (jysub != NPEY-1)
+ MPI_Wait(&request[1],&status);
+
+ /* If ixsub > 0, receive data for left y-line of uext (via bufleft). */
+ if (ixsub != 0) {
+ MPI_Wait(&request[2],&status);
+
+ /* Copy the buffer to uext. */
+ for (ly = 0; ly < MYSUB; ly++) {
+ offsetue = (ly+1)*dsizex2;
+ uext[offsetue] = bufleft[ly];
+ }
+ }
+
+ /* If ixsub < NPEX-1, receive data for right y-line of uext (via bufright). */
+ if (ixsub != NPEX-1) {
+ MPI_Wait(&request[3],&status);
+
+ /* Copy the buffer to uext */
+ for (ly = 0; ly < MYSUB; ly++) {
+ offsetue = (ly+2)*dsizex2 - 1;
+ uext[offsetue] = bufright[ly];
+ }
+ }
+
+ return(0);
+}
+
+/*
+ *--------------------------------------------------------------------
+ * PRIVATE FUNCTIONS
+ *--------------------------------------------------------------------
+ */
+
+/*
+ * InitUserData initializes the user's data block data.
+ */
+
+static int InitUserData(int thispe, MPI_Comm comm, UserData data)
+{
+ data->thispe = thispe;
+ data->dx = ONE/(MX-ONE); /* Assumes a [0,1] interval in x. */
+ data->dy = ONE/(MY-ONE); /* Assumes a [0,1] interval in y. */
+ data->coeffx = ONE/(data->dx * data->dx);
+ data->coeffy = ONE/(data->dy * data->dy);
+ data->coeffxy = TWO/(data->dx * data->dx) + TWO/(data->dy * data->dy) ;
+ data->jysub = thispe/NPEX;
+ data->ixsub = thispe - data->jysub * NPEX;
+ data->npex = NPEX;
+ data->npey = NPEY;
+ data->mx = MX;
+ data->my = MY;
+ data->mxsub = MXSUB;
+ data->mysub = MYSUB;
+ data->comm = comm;
+ data->n_local = MXSUB*MYSUB;
+
+ data->p[0] = ONE;
+ data->p[1] = ONE;
+
+ return(0);
+
+}
+
+/*
+ * SetInitialProfile sets the initial values for the problem.
+ */
+
+static int SetInitialProfile(N_Vector uu, N_Vector up, N_Vector id,
+ N_Vector res, UserData data)
+{
+ int i, iloc, j, jloc, offset, loc, ixsub, jysub;
+ int ixbegin, ixend, jybegin, jyend;
+ realtype xfact, yfact, *udata, *iddata, dx, dy;
+
+ /* Initialize uu. */
+
+ udata = NV_DATA_P(uu);
+ iddata = NV_DATA_P(id);
+
+ /* Set mesh spacings and subgrid indices for this PE. */
+ dx = data->dx;
+ dy = data->dy;
+ ixsub = data->ixsub;
+ jysub = data->jysub;
+
+ /* Set beginning and ending locations in the global array corresponding
+ to the portion of that array assigned to this processor. */
+ ixbegin = MXSUB*ixsub;
+ ixend = MXSUB*(ixsub+1) - 1;
+ jybegin = MYSUB*jysub;
+ jyend = MYSUB*(jysub+1) - 1;
+
+ /* Loop over the local array, computing the initial profile value.
+ The global indices are (i,j) and the local indices are (iloc,jloc).
+ Also set the id vector to zero for boundary points, one otherwise. */
+
+ N_VConst(ONE,id);
+ for (j = jybegin, jloc = 0; j <= jyend; j++, jloc++) {
+ yfact = data->dy*j;
+ offset= jloc*MXSUB;
+ for (i = ixbegin, iloc = 0; i <= ixend; i++, iloc++) {
+ xfact = data->dx * i;
+ loc = offset + iloc;
+ udata[loc] = RCONST(16.0) * xfact * (ONE - xfact) * yfact * (ONE - yfact);
+ if (i == 0 || i == MX-1 || j == 0 || j == MY-1) iddata[loc] = ZERO;
+ }
+ }
+
+ /* Initialize up. */
+
+ N_VConst(ZERO, up); /* Initially set up = 0. */
+
+ /* heatres sets res to negative of ODE RHS values at interior points. */
+ heatres(ZERO, uu, up, res, data);
+
+ /* Copy -res into up to get correct initial up values. */
+ N_VScale(-ONE, res, up);
+
+ return(0);
+
+}
+
+/*
+ * Print first lines of output (problem description)
+ * and table heading
+ */
+
+static void PrintHeader(int Neq, realtype rtol, realtype atol,
+ int mudq, int 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("Subgrid dimensions: %d x %d", MXSUB, MYSUB);
+ printf(" Processor array: %d x %d\n", NPEX, NPEY);
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("Tolerance parameters: rtol = %Lg atol = %Lg\n", rtol, atol);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("Tolerance parameters: rtol = %lg atol = %lg\n", rtol, atol);
+#else
+ 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(" all boundary components. \n");
+ printf("Linear solver: IDASPGMR. ");
+ printf("Preconditioner: IDABBDPRE - Banded-block-diagonal.\n");
+ printf("Difference quotient half-bandwidths = %d",mudq);
+ printf("Retained matrix half-bandwidths = %d \n\n",mukeep);
+
+ if (sensi) {
+ printf("Sensitivity: YES ");
+ if(sensi_meth == IDA_SIMULTANEOUS)
+ printf("( SIMULTANEOUS +");
+ else
+ printf("( STAGGERED +");
+ if(err_con) printf(" FULL ERROR CONTROL )");
+ else printf(" PARTIAL ERROR CONTROL )");
+
+ } else {
+
+ printf("Sensitivity: NO ");
+
+ }
+
+ printf("\n\nOutput Summary: umax = max-norm of solution\n");
+ printf(" max-norm of sensitivity 1\n");
+ printf(" max-norm of sensitivity 2\n\n");
+ printf(" time umax k nst nni nli nre nreLS nge h npe nps\n");
+ printf(" . . . . . . . . . . . . . . . . . . . . . . . .\n");
+
+
+}
+
+/*
+ * Print integrator statistics and max-norm of solution
+ */
+static void PrintOutput(int id, void *mem, realtype t, N_Vector uu,
+ booleantype sensi, N_Vector *uuS)
+{
+ realtype umax, hused;
+ int kused, ier, is;
+ long int nst, nni, nre, nli, npe, nps, nreLS, nge;
+
+ umax = N_VMaxNorm(uu);
+
+ if (id == 0) {
+
+ ier = IDAGetLastOrder(mem, &kused);
+ check_flag(&ier, "IDAGetLastOrder", 1, id);
+ ier = IDAGetNumSteps(mem, &nst);
+ check_flag(&ier, "IDAGetNumSteps", 1, id);
+ ier = IDAGetNumNonlinSolvIters(mem, &nni);
+ check_flag(&ier, "IDAGetNumNonlinSolvIters", 1, id);
+ ier = IDAGetNumResEvals(mem, &nre);
+ check_flag(&ier, "IDAGetNumResEvals", 1, id);
+ ier = IDAGetLastStep(mem, &hused);
+ check_flag(&ier, "IDAGetLastStep", 1, id);
+ ier = IDASpilsGetNumLinIters(mem, &nli);
+ check_flag(&ier, "IDASpilsGetNumLinIters", 1, id);
+ ier = IDASpilsGetNumResEvals(mem, &nreLS);
+ check_flag(&ier, "IDASpilsGetNumResEvals", 1, id);
+ ier = IDABBDPrecGetNumGfnEvals(mem, &nge);
+ check_flag(&ier, "IDABBDPrecGetNumGfnEvals", 1, id);
+ ier = IDASpilsGetNumPrecEvals(mem, &npe);
+ check_flag(&ier, "IDASpilsGetPrecEvals", 1, id);
+ ier = IDASpilsGetNumPrecSolves(mem, &nps);
+ check_flag(&ier, "IDASpilsGetNumPrecSolves", 1, id);
+
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf(" %5.2Lf %13.5Le %d %3ld %3ld %3ld %4ld %4ld %4ld %9.2Le %3ld %3ld\n",
+ t, umax, kused, nst, nni, nli, nre, nreLS, nge, hused, npe, nps);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf(" %5.2f %13.5le %d %3ld %3ld %3ld %4ld %4ld %4ld %9.2le %3ld %3ld\n",
+ t, umax, kused, nst, nni, nli, nre, nreLS, nge, hused, npe, nps);
+#else
+ printf(" %5.2f %13.5e %d %3ld %3ld %3ld %4ld %4ld %4ld %9.2e %3ld %3ld\n",
+ t, umax, kused, nst, nni, nli, nre, nreLS, nge, hused, npe, nps);
+#endif
+
+ }
+
+ if (sensi) {
+ for (is=0; is<NS; is++) {
+ umax = N_VMaxNorm(uuS[is]);
+ if (id == 0) {
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf(" %13.5Le\n", umax);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf(" %13.5le\n", umax);
+#else
+ printf(" %13.5e\n", umax);
+#endif
+ }
+ }
+
+ }
+
+}
+
+/*
+ * Print some final integrator statistics
+ */
+
+static void PrintFinalStats(void *mem)
+{
+ long int netf, ncfn, ncfl;
+
+ IDAGetNumErrTestFails(mem, &netf);
+ IDAGetNumNonlinSolvConvFails(mem, &ncfn);
+ IDASpilsGetNumConvFails(mem, &ncfl);
+
+ printf("\nError test failures = %ld\n", netf);
+ printf("Nonlinear convergence failures = %ld\n", ncfn);
+ printf("Linear convergence failures = %ld\n", ncfl);
+}
+
+/*
+ * Process and verify command line arguments
+ */
+
+static void ProcessArgs(int argc, char *argv[], int my_pe,
+ booleantype *sensi, int *sensi_meth, booleantype *err_con)
+{
+ *sensi = FALSE;
+ *sensi_meth = -1;
+ *err_con = FALSE;
+
+ if (argc < 2) WrongArgs(my_pe, argv[0]);
+
+ if (strcmp(argv[1],"-nosensi") == 0)
+ *sensi = FALSE;
+ else if (strcmp(argv[1],"-sensi") == 0)
+ *sensi = TRUE;
+ else
+ WrongArgs(my_pe, argv[0]);
+
+ if (*sensi) {
+
+ if (argc != 4)
+ WrongArgs(my_pe, argv[0]);
+
+ if (strcmp(argv[2],"sim") == 0)
+ *sensi_meth = IDA_SIMULTANEOUS;
+ else if (strcmp(argv[2],"stg") == 0)
+ *sensi_meth = IDA_STAGGERED;
+ else
+ WrongArgs(my_pe, argv[0]);
+
+ if (strcmp(argv[3],"t") == 0)
+ *err_con = TRUE;
+ else if (strcmp(argv[3],"f") == 0)
+ *err_con = FALSE;
+ else
+ WrongArgs(my_pe, argv[0]);
+ }
+
+}
+
+static void WrongArgs(int my_pe, char *name)
+{
+ if (my_pe == 0) {
+ printf("\nUsage: %s [-nosensi] [-sensi sensi_meth err_con]\n",name);
+ printf(" sensi_meth = sim, stg, or stg1\n");
+ printf(" err_con = t or f\n");
+ }
+ MPI_Finalize();
+ exit(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, char *funcname, int opt, int id)
+{
+ int *errflag;
+
+ /* Check if SUNDIALS function returned NULL pointer - no memory allocated */
+ if (opt == 0 && flagvalue == NULL) {
+ fprintf(stderr, "\nSUNDIALS_ERROR(%d): %s() failed - returned NULL pointer\n\n", id, funcname);
+ return(1); }
+
+ /* Check if flag < 0 */
+ else if (opt == 1) {
+ errflag = (int *) flagvalue;
+ if (*errflag < 0) {
+ fprintf(stderr, "\nSUNDIALS_ERROR(%d): %s() failed with flag = %d\n\n", id, funcname, *errflag);
+ return(1); }}
+
+ /* Check if function returned NULL pointer - no memory allocated */
+ else if (opt == 2 && flagvalue == NULL) {
+ fprintf(stderr, "\nMEMORY_ERROR(%d): %s() failed - returned NULL pointer\n\n", id, funcname);
+ return(1); }
+
+ return(0);
+}
diff --git a/examples/idas/parallel/idasHeat2D_FSA_kry_bbd_p.out b/examples/idas/parallel/idasHeat2D_FSA_kry_bbd_p.out
new file mode 100644
index 0000000..d2038ae
--- /dev/null
+++ b/examples/idas/parallel/idasHeat2D_FSA_kry_bbd_p.out
@@ -0,0 +1,57 @@
+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_kry_bbd_p.c b/examples/idas/parallel/idasHeat2D_kry_bbd_p.c
new file mode 100644
index 0000000..a6145b7
--- /dev/null
+++ b/examples/idas/parallel/idasHeat2D_kry_bbd_p.c
@@ -0,0 +1,840 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.2 $
+ * $Date: 2010/12/01 23:06:38 $
+ * -----------------------------------------------------------------
+ * Programmer(s): 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
+ * preconditioning.
+ *
+ * The DAE system solved is a spatial discretization of the PDE
+ * du/dt = d^2u/dx^2 + d^2u/dy^2
+ * on the unit square. The boundary condition is u = 0 on all edges.
+ * Initial conditions are given by u = 16 x (1 - x) y (1 - y). The
+ * PDE is treated with central differences on a uniform MX x MY
+ * grid. The values of u at the interior points satisfy ODEs, and
+ * equations u = 0 at the boundaries are appended, to form a DAE
+ * system of size N = MX * MY. Here MX = MY = 10.
+ *
+ * The system is actually implemented on submeshes, processor by
+ * processor, with an MXSUB by MYSUB mesh on each of NPEX * NPEY
+ * processors.
+ *
+ * The system is solved with IDA using the Krylov linear solver
+ * IDASPGMR 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
+ * suppressed. 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_bbdpre.h>
+#include <nvector/nvector_parallel.h>
+#include <sundials/sundials_types.h>
+#include <sundials/sundials_math.h>
+
+#include <mpi.h>
+
+#define ZERO RCONST(0.0)
+#define ONE RCONST(1.0)
+#define TWO RCONST(2.0)
+
+#define NOUT 11 /* Number of output times */
+
+#define NPEX 2 /* No. PEs in x direction of PE array */
+#define NPEY 2 /* No. PEs in y direction of PE array */
+ /* Total no. PEs = NPEX*NPEY */
+#define MXSUB 5 /* No. x points per subgrid */
+#define MYSUB 5 /* No. y points per subgrid */
+
+#define MX (NPEX*MXSUB) /* MX = number of x mesh points */
+#define MY (NPEY*MYSUB) /* MY = number of y mesh points */
+ /* Spatial mesh is MX by MY */
+
+typedef struct {
+ int thispe, mx, my, ixsub, jysub, npex, npey, mxsub, mysub;
+ int n_local;
+ realtype dx, dy, coeffx, coeffy, coeffxy;
+ realtype uext[(MXSUB+2)*(MYSUB+2)];
+ MPI_Comm comm;
+} *UserData;
+
+/* 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,
+ N_Vector uu, N_Vector up, N_Vector res,
+ void *user_data);
+
+static int BSend(MPI_Comm comm, int thispe, int ixsub,
+ int jysub, int dsizex, int dsizey,
+ realtype uarray[]);
+
+static int BRecvPost(MPI_Comm comm, MPI_Request request[], int thispe,
+ int ixsub, int jysub,
+ int dsizex, int dsizey,
+ realtype uext[], realtype buffer[]);
+
+static int BRecvWait(MPI_Request request[], int ixsub, int jysub,
+ int dsizex, realtype uext[], realtype buffer[]);
+
+/* Prototypes of private functions */
+
+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 PrintCase(int case_number, int mudq, int mukeep);
+
+static void PrintOutput(int id, void *mem, realtype t, N_Vector uu);
+
+static void PrintFinalStats(void *mem);
+
+static int check_flag(void *flagvalue, char *funcname, int opt, int id);
+
+/*
+ *--------------------------------------------------------------------
+ * MAIN PROGRAM
+ *--------------------------------------------------------------------
+ */
+
+int main(int argc, char *argv[])
+{
+ MPI_Comm comm;
+ void *mem;
+ UserData data;
+ int thispe, iout, ier, npes;
+ long int Neq, local_N, mudq, mldq, mukeep, mlkeep;
+ realtype rtol, atol, t0, t1, tout, tret;
+ N_Vector uu, up, constraints, id, res;
+
+ mem = NULL;
+ data = NULL;
+ uu = up = constraints = id = res = NULL;
+
+ /* Get processor number and total number of pe's. */
+
+ MPI_Init(&argc, &argv);
+ comm = MPI_COMM_WORLD;
+ MPI_Comm_size(comm, &npes);
+ MPI_Comm_rank(comm, &thispe);
+
+ if (npes != NPEX*NPEY) {
+ if (thispe == 0)
+ fprintf(stderr,
+ "\nMPI_ERROR(0): npes = %d is not equal to NPEX*NPEY = %d\n",
+ npes,NPEX*NPEY);
+ MPI_Finalize();
+ return(1);
+ }
+
+ /* Set local length local_N and global length Neq. */
+
+ local_N = MXSUB*MYSUB;
+ Neq = MX * MY;
+
+ /* Allocate N-vectors. */
+
+ uu = N_VNew_Parallel(comm, local_N, Neq);
+ if(check_flag((void *)uu, "N_VNew_Parallel", 0, thispe)) MPI_Abort(comm, 1);
+
+ up = N_VNew_Parallel(comm, local_N, Neq);
+ if(check_flag((void *)up, "N_VNew_Parallel", 0, thispe)) MPI_Abort(comm, 1);
+
+ res = N_VNew_Parallel(comm, local_N, Neq);
+ if(check_flag((void *)res, "N_VNew_Parallel", 0, thispe)) MPI_Abort(comm, 1);
+
+ constraints = N_VNew_Parallel(comm, local_N, Neq);
+ if(check_flag((void *)constraints, "N_VNew_Parallel", 0, thispe)) MPI_Abort(comm, 1);
+
+ id = N_VNew_Parallel(comm, local_N, Neq);
+ if(check_flag((void *)id, "N_VNew_Parallel", 0, thispe)) MPI_Abort(comm, 1);
+
+ /* Allocate and initialize the data structure. */
+
+ data = (UserData) malloc(sizeof *data);
+ if(check_flag((void *)data, "malloc", 2, thispe)) MPI_Abort(comm, 1);
+
+ InitUserData(thispe, comm, data);
+
+ /* Initialize the uu, up, id, and constraints profiles. */
+
+ SetInitialProfile(uu, up, id, res, data);
+ N_VConst(ONE, constraints);
+
+ t0 = ZERO; t1 = RCONST(0.01);
+
+ /* Scalar relative and absolute tolerance. */
+
+ rtol = ZERO;
+ atol = RCONST(1.0e-3);
+
+ /* Call IDACreate and IDAMalloc to initialize solution */
+
+ mem = IDACreate();
+ if(check_flag((void *)mem, "IDACreate", 0, thispe)) MPI_Abort(comm, 1);
+
+ ier = IDASetUserData(mem, data);
+ if(check_flag(&ier, "IDASetUserData", 1, thispe)) MPI_Abort(comm, 1);
+
+ ier = IDASetSuppressAlg(mem, TRUE);
+ if(check_flag(&ier, "IDASetSuppressAlg", 1, thispe)) MPI_Abort(comm, 1);
+
+ ier = IDASetId(mem, id);
+ if(check_flag(&ier, "IDASetId", 1, thispe)) MPI_Abort(comm, 1);
+
+ ier = IDASetConstraints(mem, constraints);
+ if(check_flag(&ier, "IDASetConstraints", 1, thispe)) MPI_Abort(comm, 1);
+ N_VDestroy_Parallel(constraints);
+
+ ier = IDAInit(mem, heatres, t0, uu, up);
+ if(check_flag(&ier, "IDAInit", 1, thispe)) MPI_Abort(comm, 1);
+
+ ier = IDASStolerances(mem, rtol, atol);
+ if(check_flag(&ier, "IDASStolerances", 1, thispe)) MPI_Abort(comm, 1);
+
+ mudq = MXSUB;
+ mldq = MXSUB;
+ mukeep = 1;
+ mlkeep = 1;
+
+ /* Print problem description */
+
+ if (thispe == 0 ) PrintHeader(Neq, rtol, atol);
+
+ /*
+ * -----------------------------
+ * Case 1 -- mldq = mudq = MXSUB
+ * -----------------------------
+ */
+
+ /* Call IDASpgmr to specify the linear solver. */
+ ier = IDASpgmr(mem, 0);
+ if(check_flag(&ier, "IDASpgmr", 1, thispe)) MPI_Abort(comm, 1);
+
+ /* Call IDABBDPrecInit to initialize BBD preconditioner. */
+ ier = IDABBDPrecInit(mem, local_N, mudq, mldq, mukeep, mlkeep,
+ ZERO, reslocal, NULL);
+ if(check_flag(&ier, "IDABBDPrecAlloc", 1, thispe)) MPI_Abort(comm, 1);
+
+ /* Print output heading (on processor 0 only) and initial solution. */
+ if (thispe == 0) PrintCase(1, mudq, mukeep);
+
+ /* 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);
+ if(check_flag(&ier, "IDASolve", 1, thispe)) MPI_Abort(comm, 1);
+
+ PrintOutput(thispe, mem, tret, uu);
+
+ }
+
+ /* Print final statistics */
+ if (thispe == 0) PrintFinalStats(mem);
+
+ /*
+ * -----------------------------
+ * Case 2 -- mldq = mudq = 1
+ * -----------------------------
+ */
+
+ mudq = 1;
+ mldq = 1;
+
+ /* Re-initialize the uu and up profiles. */
+ SetInitialProfile(uu, up, id, res, data);
+
+ /* Call IDAReInit to re-initialize IDA. */
+ ier = IDAReInit(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);
+ if(check_flag(&ier, "IDABBDPrecReInit", 1, thispe)) MPI_Abort(comm, 1);
+
+ /* Print output heading (on processor 0 only). */
+ if (thispe == 0) PrintCase(2, mudq, mukeep);
+
+ /* 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);
+ if(check_flag(&ier, "IDASolve", 1, thispe)) MPI_Abort(comm, 1);
+
+ PrintOutput(thispe, mem, tret, uu);
+
+ }
+
+ /* Print final statistics */
+ if (thispe == 0) PrintFinalStats(mem);
+
+ /* Free Memory */
+ IDAFree(&mem);
+ free(data);
+ N_VDestroy_Parallel(id);
+ N_VDestroy_Parallel(res);
+ N_VDestroy_Parallel(up);
+ N_VDestroy_Parallel(uu);
+
+ MPI_Finalize();
+
+ return(0);
+
+}
+/*
+ *--------------------------------------------------------------------
+ * FUNCTIONS CALLED BY IDA
+ *--------------------------------------------------------------------
+ */
+
+/*
+ * heatres: heat equation system residual function
+ * This uses 5-point central differencing on the interior points, and
+ * includes algebraic equations for the boundary values.
+ * So for each interior point, the residual component has the form
+ * res_i = u'_i - (central difference)_i
+ * while for each boundary point, it is res_i = u_i.
+ *
+ * This parallel implementation uses several supporting routines.
+ * First a call is made to rescomm to do communication of subgrid boundary
+ * data into array uext. Then reslocal is called to compute the residual
+ * on individual processors and their corresponding domains. The routines
+ * BSend, BRecvPost, and BREcvWait handle interprocessor communication
+ * of uu required to calculate the residual.
+ */
+
+static int heatres(realtype tres, N_Vector uu, N_Vector up,
+ N_Vector res, void *user_data)
+{
+ int retval;
+ UserData data;
+ long int Nlocal;
+
+ data = (UserData) user_data;
+
+ Nlocal = data->n_local;
+
+ /* Call rescomm to do inter-processor communication. */
+ retval = rescomm(Nlocal, tres, uu, up, data);
+
+ /* Call reslocal to calculate res. */
+ retval = reslocal(Nlocal, tres, uu, up, res, data);
+
+ return(0);
+
+}
+
+/*
+ * rescomm routine. This routine performs all inter-processor
+ * communication of data in u needed to calculate G.
+ */
+
+static int rescomm(long int Nlocal, realtype tt,
+ N_Vector uu, N_Vector up, void *user_data)
+{
+ UserData data;
+ realtype *uarray, *uext, buffer[2*MYSUB];
+ MPI_Comm comm;
+ int thispe, ixsub, jysub, mxsub, mysub;
+ MPI_Request request[4];
+
+ data = (UserData) user_data;
+ uarray = NV_DATA_P(uu);
+
+ /* Get comm, thispe, subgrid indices, data sizes, extended array uext. */
+ comm = data->comm; thispe = data->thispe;
+ ixsub = data->ixsub; jysub = data->jysub;
+ mxsub = data->mxsub; mysub = data->mysub;
+ uext = data->uext;
+
+ /* Start receiving boundary data from neighboring PEs. */
+ BRecvPost(comm, request, thispe, ixsub, jysub, mxsub, mysub, uext, buffer);
+
+ /* Send data from boundary of local grid to neighboring PEs. */
+ BSend(comm, thispe, ixsub, jysub, mxsub, mysub, uarray);
+
+ /* Finish receiving boundary data from neighboring PEs. */
+ BRecvWait(request, ixsub, jysub, mxsub, uext, buffer);
+
+ return(0);
+
+}
+
+/*
+ * reslocal routine. Compute res = F(t, uu, up). This routine assumes
+ * that all inter-processor communication of data needed to calculate F
+ * has already been done, and that this data is in the work array uext.
+ */
+
+static int reslocal(long int Nlocal, realtype tres,
+ N_Vector uu, N_Vector up, N_Vector res,
+ void *user_data)
+{
+ realtype *uext, *uuv, *upv, *resv;
+ realtype termx, termy, termctr;
+ int lx, ly, offsetu, offsetue, locu, locue;
+ int ixsub, jysub, mxsub, mxsub2, mysub, npex, npey;
+ int ixbegin, ixend, jybegin, jyend;
+ UserData data;
+
+ /* Get subgrid indices, array sizes, extended work array uext. */
+
+ data = (UserData) user_data;
+ uext = data->uext;
+ uuv = NV_DATA_P(uu);
+ upv = NV_DATA_P(up);
+ resv = NV_DATA_P(res);
+ ixsub = data->ixsub; jysub = data->jysub;
+ mxsub = data->mxsub; mxsub2 = data->mxsub + 2;
+ mysub = data->mysub; npex = data->npex; npey = data->npey;
+
+ /* Initialize all elements of res to uu. This sets the boundary
+ elements simply without indexing hassles. */
+
+ N_VScale(ONE, uu, res);
+
+ /* Copy local segment of u vector into the working extended array uext.
+ This completes uext prior to the computation of the res vector. */
+
+ offsetu = 0;
+ offsetue = mxsub2 + 1;
+ for (ly = 0; ly < mysub; ly++) {
+ for (lx = 0; lx < mxsub; lx++) uext[offsetue+lx] = uuv[offsetu+lx];
+ offsetu = offsetu + mxsub;
+ offsetue = offsetue + mxsub2;
+ }
+
+ /* Set loop limits for the interior of the local subgrid. */
+
+ ixbegin = 0;
+ ixend = mxsub-1;
+ jybegin = 0;
+ jyend = mysub-1;
+ if (ixsub == 0) ixbegin++; if (ixsub == npex-1) ixend--;
+ if (jysub == 0) jybegin++; if (jysub == npey-1) jyend--;
+
+ /* Loop over all grid points in local subgrid. */
+
+ for (ly = jybegin; ly <=jyend; ly++) {
+ for (lx = ixbegin; lx <= ixend; lx++) {
+ locu = lx + ly*mxsub;
+ locue = (lx+1) + (ly+1)*mxsub2;
+ termx = data->coeffx *(uext[locue-1] + uext[locue+1]);
+ termy = data->coeffy *(uext[locue-mxsub2] + uext[locue+mxsub2]);
+ termctr = data->coeffxy*uext[locue];
+ resv[locu] = upv[locu] - (termx + termy - termctr);
+ }
+ }
+ return(0);
+
+}
+
+/*
+ * Routine to send boundary data to neighboring PEs.
+ */
+
+static int BSend(MPI_Comm comm, int thispe, int ixsub,
+ int jysub, int dsizex, int dsizey,
+ realtype uarray[])
+{
+ int ly, offsetu;
+ realtype bufleft[MYSUB], bufright[MYSUB];
+
+ /* If jysub > 0, send data from bottom x-line of u. */
+
+ if (jysub != 0)
+ MPI_Send(&uarray[0], dsizex, PVEC_REAL_MPI_TYPE, thispe-NPEX, 0, comm);
+
+ /* If jysub < NPEY-1, send data from top x-line of u. */
+
+ if (jysub != NPEY-1) {
+ offsetu = (MYSUB-1)*dsizex;
+ MPI_Send(&uarray[offsetu], dsizex, PVEC_REAL_MPI_TYPE,
+ thispe+NPEX, 0, comm);
+ }
+
+ /* If ixsub > 0, send data from left y-line of u (via bufleft). */
+
+ if (ixsub != 0) {
+ for (ly = 0; ly < MYSUB; ly++) {
+ offsetu = ly*dsizex;
+ bufleft[ly] = uarray[offsetu];
+ }
+ MPI_Send(&bufleft[0], dsizey, PVEC_REAL_MPI_TYPE, thispe-1, 0, comm);
+ }
+
+ /* If ixsub < NPEX-1, send data from right y-line of u (via bufright). */
+
+ if (ixsub != NPEX-1) {
+ for (ly = 0; ly < MYSUB; ly++) {
+ offsetu = ly*MXSUB + (MXSUB-1);
+ bufright[ly] = uarray[offsetu];
+ }
+ MPI_Send(&bufright[0], dsizey, PVEC_REAL_MPI_TYPE, thispe+1, 0, comm);
+ }
+
+ return(0);
+
+}
+
+/*
+ * Routine to start receiving boundary data from neighboring PEs.
+ * Notes:
+ * 1) buffer should be able to hold 2*MYSUB realtype entries, should be
+ * passed to both the BRecvPost and BRecvWait functions, and should not
+ * be manipulated between the two calls.
+ * 2) request should have 4 entries, and should be passed in
+ * both calls also.
+ */
+
+static int BRecvPost(MPI_Comm comm, MPI_Request request[], int thispe,
+ int ixsub, int jysub,
+ int dsizex, int dsizey,
+ realtype uext[], realtype buffer[])
+{
+ int offsetue;
+ /* Have bufleft and bufright use the same buffer. */
+ realtype *bufleft = buffer, *bufright = buffer+MYSUB;
+
+ /* If jysub > 0, receive data for bottom x-line of uext. */
+ if (jysub != 0)
+ MPI_Irecv(&uext[1], dsizex, PVEC_REAL_MPI_TYPE,
+ thispe-NPEX, 0, comm, &request[0]);
+
+ /* If jysub < NPEY-1, receive data for top x-line of uext. */
+ if (jysub != NPEY-1) {
+ offsetue = (1 + (MYSUB+1)*(MXSUB+2));
+ MPI_Irecv(&uext[offsetue], dsizex, PVEC_REAL_MPI_TYPE,
+ thispe+NPEX, 0, comm, &request[1]);
+ }
+
+ /* If ixsub > 0, receive data for left y-line of uext (via bufleft). */
+ if (ixsub != 0) {
+ MPI_Irecv(&bufleft[0], dsizey, PVEC_REAL_MPI_TYPE,
+ thispe-1, 0, comm, &request[2]);
+ }
+
+ /* If ixsub < NPEX-1, receive data for right y-line of uext (via bufright). */
+ if (ixsub != NPEX-1) {
+ MPI_Irecv(&bufright[0], dsizey, PVEC_REAL_MPI_TYPE,
+ thispe+1, 0, comm, &request[3]);
+ }
+
+ return(0);
+
+}
+
+/*
+ * Routine to finish receiving boundary data from neighboring PEs.
+ * Notes:
+ * 1) buffer should be able to hold 2*MYSUB realtype entries, should be
+ * passed to both the BRecvPost and BRecvWait functions, and should not
+ * be manipulated between the two calls.
+ * 2) request should have four entries, and should be passed in both
+ * calls also.
+ */
+
+static int BRecvWait(MPI_Request request[], int ixsub,
+ int jysub, int dsizex, realtype uext[],
+ realtype buffer[])
+{
+ int ly, dsizex2, offsetue;
+ realtype *bufleft = buffer, *bufright = buffer+MYSUB;
+ MPI_Status status;
+
+ dsizex2 = dsizex + 2;
+
+ /* If jysub > 0, receive data for bottom x-line of uext. */
+ if (jysub != 0)
+ MPI_Wait(&request[0],&status);
+
+ /* If jysub < NPEY-1, receive data for top x-line of uext. */
+ if (jysub != NPEY-1)
+ MPI_Wait(&request[1],&status);
+
+ /* If ixsub > 0, receive data for left y-line of uext (via bufleft). */
+ if (ixsub != 0) {
+ MPI_Wait(&request[2],&status);
+
+ /* Copy the buffer to uext. */
+ for (ly = 0; ly < MYSUB; ly++) {
+ offsetue = (ly+1)*dsizex2;
+ uext[offsetue] = bufleft[ly];
+ }
+ }
+
+ /* If ixsub < NPEX-1, receive data for right y-line of uext (via bufright). */
+ if (ixsub != NPEX-1) {
+ MPI_Wait(&request[3],&status);
+
+ /* Copy the buffer to uext */
+ for (ly = 0; ly < MYSUB; ly++) {
+ offsetue = (ly+2)*dsizex2 - 1;
+ uext[offsetue] = bufright[ly];
+ }
+ }
+
+ return(0);
+}
+
+/*
+ *--------------------------------------------------------------------
+ * PRIVATE FUNCTIONS
+ *--------------------------------------------------------------------
+ */
+
+/*
+ * InitUserData initializes the user's data block data.
+ */
+
+static int InitUserData(int thispe, MPI_Comm comm, UserData data)
+{
+ data->thispe = thispe;
+ data->dx = ONE/(MX-ONE); /* Assumes a [0,1] interval in x. */
+ data->dy = ONE/(MY-ONE); /* Assumes a [0,1] interval in y. */
+ data->coeffx = ONE/(data->dx * data->dx);
+ data->coeffy = ONE/(data->dy * data->dy);
+ data->coeffxy = TWO/(data->dx * data->dx) + TWO/(data->dy * data->dy) ;
+ data->jysub = thispe/NPEX;
+ data->ixsub = thispe - data->jysub * NPEX;
+ data->npex = NPEX;
+ data->npey = NPEY;
+ data->mx = MX;
+ data->my = MY;
+ data->mxsub = MXSUB;
+ data->mysub = MYSUB;
+ data->comm = comm;
+ data->n_local = MXSUB*MYSUB;
+ return(0);
+
+}
+
+/*
+ * SetInitialProfile sets the initial values for the problem.
+ */
+
+static int SetInitialProfile(N_Vector uu, N_Vector up, N_Vector id,
+ N_Vector res, UserData data)
+{
+ int i, iloc, j, jloc, offset, loc, ixsub, jysub;
+ int ixbegin, ixend, jybegin, jyend;
+ realtype xfact, yfact, *udata, *iddata, dx, dy;
+
+ /* Initialize uu. */
+
+ udata = NV_DATA_P(uu);
+ iddata = NV_DATA_P(id);
+
+ /* Set mesh spacings and subgrid indices for this PE. */
+ dx = data->dx;
+ dy = data->dy;
+ ixsub = data->ixsub;
+ jysub = data->jysub;
+
+ /* Set beginning and ending locations in the global array corresponding
+ to the portion of that array assigned to this processor. */
+ ixbegin = MXSUB*ixsub;
+ ixend = MXSUB*(ixsub+1) - 1;
+ jybegin = MYSUB*jysub;
+ jyend = MYSUB*(jysub+1) - 1;
+
+ /* Loop over the local array, computing the initial profile value.
+ The global indices are (i,j) and the local indices are (iloc,jloc).
+ Also set the id vector to zero for boundary points, one otherwise. */
+
+ N_VConst(ONE,id);
+ for (j = jybegin, jloc = 0; j <= jyend; j++, jloc++) {
+ yfact = data->dy*j;
+ offset= jloc*MXSUB;
+ for (i = ixbegin, iloc = 0; i <= ixend; i++, iloc++) {
+ xfact = data->dx * i;
+ loc = offset + iloc;
+ udata[loc] = RCONST(16.0) * xfact * (ONE - xfact) * yfact * (ONE - yfact);
+ if (i == 0 || i == MX-1 || j == 0 || j == MY-1) iddata[loc] = ZERO;
+ }
+ }
+
+ /* Initialize up. */
+
+ N_VConst(ZERO, up); /* Initially set up = 0. */
+
+ /* heatres sets res to negative of ODE RHS values at interior points. */
+ heatres(ZERO, uu, up, res, data);
+
+ /* Copy -res into up to get correct initial up values. */
+ N_VScale(-ONE, res, up);
+
+ return(0);
+
+}
+
+/*
+ * Print first lines of output (problem description)
+ * and table heading
+ */
+
+static void PrintHeader(long int 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: %d\n\n", Neq);
+
+ printf("Subgrid dimensions: %d x %d", MXSUB, MYSUB);
+ printf(" Processor array: %d x %d\n", NPEX, NPEY);
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("Tolerance parameters: rtol = %Lg atol = %Lg\n", rtol, atol);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("Tolerance parameters: rtol = %lg atol = %lg\n", rtol, atol);
+#else
+ 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(" all boundary components. \n");
+ printf("Linear solver: IDASPGMR. ");
+ printf("Preconditioner: IDABBDPRE - Banded-block-diagonal.\n");
+
+}
+
+/*
+ * Print case and table header
+ */
+
+static void PrintCase(int case_number, int mudq, int mukeep)
+{
+ printf("\n\nCase %1d. \n", case_number);
+ printf(" Difference quotient half-bandwidths = %d",mudq);
+ printf(" Retained matrix half-bandwidths = %d \n",mukeep);
+
+ /* Print output table heading and initial line of table. */
+ printf("\n Output Summary (umax = max-norm of solution) \n\n");
+ printf(" time umax k nst nni nli nre nreLS nge h npe nps\n");
+ printf(" . . . . . . . . . . . . . . . . . . . . . . . .\n");
+}
+
+/*
+ * Print integrator statistics and max-norm of solution
+ */
+
+static void PrintOutput(int id, void *mem, realtype t, N_Vector uu)
+{
+ realtype umax, hused;
+ int kused, ier;
+ long int nst, nni, nre, nli, npe, nps, nreLS, nge;
+
+ umax = N_VMaxNorm(uu);
+
+ if (id == 0) {
+
+ ier = IDAGetLastOrder(mem, &kused);
+ check_flag(&ier, "IDAGetLastOrder", 1, id);
+ ier = IDAGetNumSteps(mem, &nst);
+ check_flag(&ier, "IDAGetNumSteps", 1, id);
+ ier = IDAGetNumNonlinSolvIters(mem, &nni);
+ check_flag(&ier, "IDAGetNumNonlinSolvIters", 1, id);
+ ier = IDAGetNumResEvals(mem, &nre);
+ check_flag(&ier, "IDAGetNumResEvals", 1, id);
+ ier = IDAGetLastStep(mem, &hused);
+ check_flag(&ier, "IDAGetLastStep", 1, id);
+ ier = IDASpilsGetNumLinIters(mem, &nli);
+ check_flag(&ier, "IDASpilsGetNumLinIters", 1, id);
+ ier = IDASpilsGetNumResEvals(mem, &nreLS);
+ check_flag(&ier, "IDASpilsGetNumResEvals", 1, id);
+ ier = IDABBDPrecGetNumGfnEvals(mem, &nge);
+ check_flag(&ier, "IDABBDPrecGetNumGfnEvals", 1, id);
+ ier = IDASpilsGetNumPrecEvals(mem, &npe);
+ check_flag(&ier, "IDASpilsGetPrecEvals", 1, id);
+ ier = IDASpilsGetNumPrecSolves(mem, &nps);
+ check_flag(&ier, "IDASpilsGetNumPrecSolves", 1, id);
+
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf(" %5.2Lf %13.5Le %d %3ld %3ld %3ld %4ld %4ld %4ld %9.2Le %3ld %3ld\n",
+ t, umax, kused, nst, nni, nli, nre, nreLS, nge, hused, npe, nps);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf(" %5.2f %13.5le %d %3ld %3ld %3ld %4ld %4ld %4ld %9.2le %3ld %3ld\n",
+ t, umax, kused, nst, nni, nli, nre, nreLS, nge, hused, npe, nps);
+#else
+ printf(" %5.2f %13.5e %d %3ld %3ld %3ld %4ld %4ld %4ld %9.2e %3ld %3ld\n",
+ t, umax, kused, nst, nni, nli, nre, nreLS, nge, hused, npe, nps);
+#endif
+
+ }
+}
+
+/*
+ * Print some final integrator statistics
+ */
+
+static void PrintFinalStats(void *mem)
+{
+ long int netf, ncfn, ncfl;
+
+ IDAGetNumErrTestFails(mem, &netf);
+ IDAGetNumNonlinSolvConvFails(mem, &ncfn);
+ IDASpilsGetNumConvFails(mem, &ncfl);
+
+ printf("\nError test failures = %ld\n", netf);
+ printf("Nonlinear convergence failures = %ld\n", ncfn);
+ printf("Linear convergence failures = %ld\n", ncfl);
+}
+
+/*
+ * 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, char *funcname, int opt, int id)
+{
+ int *errflag;
+
+ /* Check if SUNDIALS function returned NULL pointer - no memory allocated */
+ if (opt == 0 && flagvalue == NULL) {
+ fprintf(stderr, "\nSUNDIALS_ERROR(%d): %s() failed - returned NULL pointer\n\n", id, funcname);
+ return(1); }
+
+ /* Check if flag < 0 */
+ else if (opt == 1) {
+ errflag = (int *) flagvalue;
+ if (*errflag < 0) {
+ fprintf(stderr, "\nSUNDIALS_ERROR(%d): %s() failed with flag = %d\n\n", id, funcname, *errflag);
+ return(1); }}
+
+ /* Check if function returned NULL pointer - no memory allocated */
+ else if (opt == 2 && flagvalue == NULL) {
+ fprintf(stderr, "\nMEMORY_ERROR(%d): %s() failed - returned NULL pointer\n\n", id, funcname);
+ return(1); }
+
+ return(0);
+}
diff --git a/examples/idas/parallel/idasHeat2D_kry_bbd_p.out b/examples/idas/parallel/idasHeat2D_kry_bbd_p.out
new file mode 100644
index 0000000..8315b95
--- /dev/null
+++ b/examples/idas/parallel/idasHeat2D_kry_bbd_p.out
@@ -0,0 +1,58 @@
+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
+
+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.
+
+
+Case 1.
+ Difference quotient half-bandwidths = 5 Retained matrix half-bandwidths = 1
+
+ Output Summary (umax = max-norm of solution)
+
+ 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
+
+Error test failures = 1
+Nonlinear convergence failures = 0
+Linear convergence failures = 0
+
+
+Case 2.
+ Difference quotient half-bandwidths = 1 Retained matrix half-bandwidths = 1
+
+ Output Summary (umax = max-norm of solution)
+
+ 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
+ 0.04 4.70932e-01 3 19 23 20 23 20 36 1.02e-02 9 43
+ 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
+
+Error test failures = 0
+Nonlinear convergence failures = 0
+Linear convergence failures = 0
diff --git a/examples/idas/parallel/idasHeat2D_kry_p.c b/examples/idas/parallel/idasHeat2D_kry_p.c
new file mode 100644
index 0000000..9aeb14a
--- /dev/null
+++ b/examples/idas/parallel/idasHeat2D_kry_p.c
@@ -0,0 +1,892 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.1 $
+ * $Date: 2007/10/25 20:03:38 $
+ * -----------------------------------------------------------------
+ * Programmer(s): 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.
+ *
+ * The DAE system solved is a spatial discretization of the PDE
+ * du/dt = d^2u/dx^2 + d^2u/dy^2
+ * on the unit square. The boundary condition is u = 0 on all edges.
+ * Initial conditions are given by u = 16 x (1 - x) y (1 - y).
+ * The PDE is treated with central differences on a uniform MX x MY
+ * grid. The values of u at the interior points satisfy ODEs, and
+ * equations u = 0 at the boundaries are appended, to form a DAE
+ * system of size N = MX * MY. Here MX = MY = 10.
+ *
+ * The system is actually implemented on submeshes, processor by
+ * processor, with an MXSUB by MYSUB mesh on each of NPEX * NPEY
+ * processors.
+ *
+ * The system is solved with IDA using the Krylov linear solver
+ * IDASPGMR. 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
+ * for all components. Local error testing on the boundary values
+ * is suppressed. 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 <nvector/nvector_parallel.h>
+#include <sundials/sundials_types.h>
+#include <sundials/sundials_math.h>
+
+#include <mpi.h>
+
+#define ZERO RCONST(0.0)
+#define ONE RCONST(1.0)
+#define TWO RCONST(2.0)
+
+#define NOUT 11 /* Number of output times */
+
+#define NPEX 2 /* No. PEs in x direction of PE array */
+#define NPEY 2 /* No. PEs in y direction of PE array */
+ /* Total no. PEs = NPEX*NPEY */
+#define MXSUB 5 /* No. x points per subgrid */
+#define MYSUB 5 /* No. y points per subgrid */
+
+#define MX (NPEX*MXSUB) /* MX = number of x mesh points */
+#define MY (NPEY*MYSUB) /* MY = number of y mesh points */
+ /* Spatial mesh is MX by MY */
+
+typedef struct {
+ long int thispe, mx, my, ixsub, jysub, npex, npey, mxsub, mysub;
+ realtype dx, dy, coeffx, coeffy, coeffxy;
+ realtype uext[(MXSUB+2)*(MYSUB+2)];
+ N_Vector pp; /* vector of diagonal preconditioner elements */
+ MPI_Comm comm;
+} *UserData;
+
+/* User-supplied residual function and supporting routines */
+
+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 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 BRecvWait(MPI_Request request[], long int ixsub, long int jysub,
+ long int 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 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);
+
+/* Private function to check function return values */
+
+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 PrintOutput(int id, void *mem, realtype t, N_Vector uu);
+
+static void PrintFinalStats(void *mem);
+
+static int check_flag(void *flagvalue, char *funcname, int opt, int id);
+
+/*
+ *--------------------------------------------------------------------
+ * MAIN PROGRAM
+ *--------------------------------------------------------------------
+ */
+
+int main(int argc, char *argv[])
+{
+ MPI_Comm comm;
+ void *mem;
+ UserData data;
+ int iout, thispe, ier, npes;
+ long int Neq, local_N;
+ realtype rtol, atol, t0, t1, tout, tret;
+ N_Vector uu, up, constraints, id, res;
+
+ mem = NULL;
+ data = NULL;
+ uu = up = constraints = id = res = NULL;
+
+ /* Get processor number and total number of pe's. */
+
+ MPI_Init(&argc, &argv);
+ comm = MPI_COMM_WORLD;
+ MPI_Comm_size(comm, &npes);
+ MPI_Comm_rank(comm, &thispe);
+
+ if (npes != NPEX*NPEY) {
+ if (thispe == 0)
+ fprintf(stderr,
+ "\nMPI_ERROR(0): npes = %d is not equal to NPEX*NPEY = %d\n",
+ npes,NPEX*NPEY);
+ MPI_Finalize();
+ return(1);
+ }
+
+ /* Set local length local_N and global length Neq. */
+
+ local_N = MXSUB*MYSUB;
+ Neq = MX * MY;
+
+ /* Allocate and initialize the data structure and N-vectors. */
+
+ data = (UserData) malloc(sizeof *data);
+ data->pp = NULL;
+ if(check_flag((void *)data, "malloc", 2, thispe))
+ MPI_Abort(comm, 1);
+
+ uu = N_VNew_Parallel(comm, local_N, Neq);
+ if(check_flag((void *)uu, "N_VNew_Parallel", 0, thispe))
+ MPI_Abort(comm, 1);
+
+ up = N_VNew_Parallel(comm, local_N, Neq);
+ if(check_flag((void *)up, "N_VNew_Parallel", 0, thispe))
+ MPI_Abort(comm, 1);
+
+ res = N_VNew_Parallel(comm, local_N, Neq);
+ if(check_flag((void *)res, "N_VNew_Parallel", 0, thispe))
+ MPI_Abort(comm, 1);
+
+ constraints = N_VNew_Parallel(comm, local_N, Neq);
+ if(check_flag((void *)constraints, "N_VNew_Parallel", 0, thispe))
+ MPI_Abort(comm, 1);
+
+ id = N_VNew_Parallel(comm, local_N, Neq);
+ if(check_flag((void *)id, "N_VNew_Parallel", 0, thispe))
+ MPI_Abort(comm, 1);
+
+ /* An N-vector to hold preconditioner. */
+ data->pp = N_VNew_Parallel(comm, local_N, Neq);
+ if(check_flag((void *)data->pp, "N_VNew_Parallel", 0, thispe))
+ MPI_Abort(comm, 1);
+
+ InitUserData(thispe, comm, data);
+
+ /* Initialize the uu, up, id, and res profiles. */
+
+ SetInitialProfile(uu, up, id, res, data);
+
+ /* Set constraints to all 1's for nonnegative solution values. */
+
+ N_VConst(ONE, constraints);
+
+ t0 = ZERO; t1 = RCONST(0.01);
+
+ /* Scalar relative and absolute tolerance. */
+
+ rtol = ZERO;
+ atol = RCONST(1.0e-3);
+
+ /* Call IDACreate and IDAMalloc to initialize solution. */
+
+ mem = IDACreate();
+ if(check_flag((void *)mem, "IDACreate", 0, thispe)) MPI_Abort(comm, 1);
+
+ ier = IDASetUserData(mem, data);
+ if(check_flag(&ier, "IDASetUserData", 1, thispe)) MPI_Abort(comm, 1);
+
+ ier = IDASetSuppressAlg(mem, TRUE);
+ if(check_flag(&ier, "IDASetSuppressAlg", 1, thispe)) MPI_Abort(comm, 1);
+
+ ier = IDASetId(mem, id);
+ if(check_flag(&ier, "IDASetId", 1, thispe)) MPI_Abort(comm, 1);
+
+ ier = IDASetConstraints(mem, constraints);
+ if(check_flag(&ier, "IDASetConstraints", 1, thispe)) MPI_Abort(comm, 1);
+ N_VDestroy_Parallel(constraints);
+
+ ier = IDAInit(mem, resHeat, t0, uu, up);
+ if(check_flag(&ier, "IDAInit", 1, thispe)) MPI_Abort(comm, 1);
+
+ ier = IDASStolerances(mem, rtol, atol);
+ if(check_flag(&ier, "IDASStolerances", 1, thispe)) MPI_Abort(comm, 1);
+
+ /* Call IDASpgmr to specify the linear solver. */
+
+ ier = IDASpgmr(mem, 0);
+ if(check_flag(&ier, "IDASpgmr", 1, thispe)) MPI_Abort(comm, 1);
+
+ ier = IDASpilsSetPreconditioner(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);
+
+ /* 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);
+ if(check_flag(&ier, "IDASolve", 1, thispe)) MPI_Abort(comm, 1);
+
+ PrintOutput(thispe, mem, tret, uu);
+
+ }
+
+ /* Print remaining counters. */
+
+ if (thispe == 0) PrintFinalStats(mem);
+
+ /* Free memory */
+
+ IDAFree(&mem);
+
+ N_VDestroy_Parallel(id);
+ N_VDestroy_Parallel(res);
+ N_VDestroy_Parallel(up);
+ N_VDestroy_Parallel(uu);
+
+ N_VDestroy_Parallel(data->pp);
+ free(data);
+
+ MPI_Finalize();
+
+ return(0);
+
+}
+
+/*
+ *--------------------------------------------------------------------
+ * FUNCTIONS CALLED BY IDA
+ *--------------------------------------------------------------------
+ */
+
+/*
+ * resHeat: heat equation system residual function
+ * This uses 5-point central differencing on the interior points, and
+ * includes algebraic equations for the boundary values.
+ * So for each interior point, the residual component has the form
+ * res_i = u'_i - (central difference)_i
+ * while for each boundary point, it is res_i = u_i.
+ *
+ * This parallel implementation uses several supporting routines.
+ * First a call is made to rescomm to do communication of subgrid boundary
+ * data into array uext. Then reslocal is called to compute the residual
+ * on individual processors and their corresponding domains. The routines
+ * BSend, BRecvPost, and BREcvWait handle interprocessor communication
+ * of uu required to calculate the residual.
+ */
+
+int resHeat(realtype tt,
+ N_Vector uu, N_Vector up, N_Vector rr,
+ void *user_data)
+{
+ int retval;
+
+ /* Call rescomm to do inter-processor communication. */
+ retval = rescomm(uu, up, user_data);
+
+ /* Call reslocal to calculate res. */
+ retval = reslocal(tt, uu, up, rr, user_data);
+
+ return(0);
+
+}
+
+/*
+ * PsetupHeat: setup for diagonal preconditioner for heatsk.
+ *
+ * The optional user-supplied functions PsetupHeat and
+ * PsolveHeat together must define the left preconditoner
+ * matrix P approximating the system Jacobian matrix
+ * J = dF/du + cj*dF/du'
+ * (where the DAE system is F(t,u,u') = 0), and solve the linear
+ * systems P z = r. This is done in this case by keeping only
+ * the diagonal elements of the J matrix above, storing them as
+ * inverses in a vector pp, when computed in PsetupHeat, for
+ * subsequent use in PsolveHeat.
+ *
+ * In this instance, only cj and data (user data structure, with
+ * pp etc.) are used from the PsetupHeat argument list.
+ *
+ */
+
+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)
+{
+ realtype *ppv, pelinv;
+ long int lx, ly, ixbegin, ixend, jybegin, jyend, locu, mxsub, mysub;
+ long int ixsub, jysub, npex, npey;
+ UserData data;
+
+ data = (UserData) user_data;
+
+ ppv = NV_DATA_P(data->pp);
+ ixsub = data->ixsub;
+ jysub = data->jysub;
+ mxsub = data->mxsub;
+ mysub = data->mysub;
+ npex = data->npex;
+ npey = data->npey;
+
+ /* Initially set all pp elements to one. */
+ N_VConst(ONE, data->pp);
+
+ /* Prepare to loop over subgrid. */
+ ixbegin = 0;
+ ixend = mxsub-1;
+ jybegin = 0;
+ jyend = mysub-1;
+ if (ixsub == 0) ixbegin++; if (ixsub == npex-1) ixend--;
+ if (jysub == 0) jybegin++; if (jysub == npey-1) jyend--;
+ pelinv = ONE/(c_j + data->coeffxy);
+
+ /* Load the inverse of the preconditioner diagonal elements
+ in loop over all the local subgrid. */
+
+ for (ly = jybegin; ly <=jyend; ly++) {
+ for (lx = ixbegin; lx <= ixend; lx++) {
+ locu = lx + ly*mxsub;
+ ppv[locu] = pelinv;
+ }
+ }
+
+ return(0);
+
+}
+
+/*
+ * PsolveHeat: solve preconditioner linear system.
+ * This routine multiplies the input vector rvec by the vector pp
+ * containing the inverse diagonal Jacobian elements (previously
+ * 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)
+{
+ UserData data;
+
+ data = (UserData) user_data;
+
+ N_VProd(data->pp, rvec, zvec);
+
+ return(0);
+
+}
+
+/*
+ *--------------------------------------------------------------------
+ * SUPPORTING FUNCTIONS
+ *--------------------------------------------------------------------
+ */
+
+
+/*
+ * rescomm routine. This routine performs all inter-processor
+ * communication of data in u needed to calculate G.
+ */
+
+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;
+ MPI_Request request[4];
+
+ data = (UserData) user_data;
+ uarray = NV_DATA_P(uu);
+
+ /* Get comm, thispe, subgrid indices, data sizes, extended array uext. */
+ comm = data->comm; thispe = data->thispe;
+ ixsub = data->ixsub; jysub = data->jysub;
+ mxsub = data->mxsub; mysub = data->mysub;
+ uext = data->uext;
+
+ /* Start receiving boundary data from neighboring PEs. */
+ BRecvPost(comm, request, thispe, ixsub, jysub, mxsub, mysub, uext, buffer);
+
+ /* Send data from boundary of local grid to neighboring PEs. */
+ BSend(comm, thispe, ixsub, jysub, mxsub, mysub, uarray);
+
+ /* Finish receiving boundary data from neighboring PEs. */
+ BRecvWait(request, ixsub, jysub, mxsub, uext, buffer);
+
+ return(0);
+
+}
+
+/*
+ * reslocal routine. Compute res = F(t, uu, up). This routine assumes
+ * that all inter-processor communication of data needed to calculate F
+ * 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,
+ 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;
+ UserData data;
+
+ /* Get subgrid indices, array sizes, extended work array uext. */
+
+ data = (UserData) user_data;
+ uext = data->uext;
+ uuv = NV_DATA_P(uu);
+ upv = NV_DATA_P(up);
+ resv = NV_DATA_P(rr);
+ ixsub = data->ixsub; jysub = data->jysub;
+ mxsub = data->mxsub; mxsub2 = data->mxsub + 2;
+ mysub = data->mysub; npex = data->npex; npey = data->npey;
+
+ /* Initialize all elements of rr to uu. This sets the boundary
+ elements simply without indexing hassles. */
+
+ N_VScale(ONE, uu, rr);
+
+ /* Copy local segment of u vector into the working extended array uext.
+ This completes uext prior to the computation of the rr vector. */
+
+ offsetu = 0;
+ offsetue = mxsub2 + 1;
+ for (ly = 0; ly < mysub; ly++) {
+ for (lx = 0; lx < mxsub; lx++) uext[offsetue+lx] = uuv[offsetu+lx];
+ offsetu = offsetu + mxsub;
+ offsetue = offsetue + mxsub2;
+ }
+
+ /* Set loop limits for the interior of the local subgrid. */
+
+ ixbegin = 0;
+ ixend = mxsub-1;
+ jybegin = 0;
+ jyend = mysub-1;
+ if (ixsub == 0) ixbegin++; if (ixsub == npex-1) ixend--;
+ if (jysub == 0) jybegin++; if (jysub == npey-1) jyend--;
+
+ /* Loop over all grid points in local subgrid. */
+
+ for (ly = jybegin; ly <=jyend; ly++) {
+ for (lx = ixbegin; lx <= ixend; lx++) {
+ locu = lx + ly*mxsub;
+ locue = (lx+1) + (ly+1)*mxsub2;
+ termx = data->coeffx *(uext[locue-1] + uext[locue+1]);
+ termy = data->coeffy *(uext[locue-mxsub2] + uext[locue+mxsub2]);
+ termctr = data->coeffxy*uext[locue];
+ resv[locu] = upv[locu] - (termx + termy - termctr);
+ }
+ }
+ return(0);
+
+}
+
+/*
+ * 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[])
+{
+ long int ly, offsetu;
+ realtype bufleft[MYSUB], bufright[MYSUB];
+
+ /* If jysub > 0, send data from bottom x-line of u. */
+
+ if (jysub != 0)
+ MPI_Send(&uarray[0], dsizex, PVEC_REAL_MPI_TYPE, thispe-NPEX, 0, comm);
+
+ /* If jysub < NPEY-1, send data from top x-line of u. */
+
+ if (jysub != NPEY-1) {
+ offsetu = (MYSUB-1)*dsizex;
+ MPI_Send(&uarray[offsetu], dsizex, PVEC_REAL_MPI_TYPE,
+ thispe+NPEX, 0, comm);
+ }
+
+ /* If ixsub > 0, send data from left y-line of u (via bufleft). */
+
+ if (ixsub != 0) {
+ for (ly = 0; ly < MYSUB; ly++) {
+ offsetu = ly*dsizex;
+ bufleft[ly] = uarray[offsetu];
+ }
+ MPI_Send(&bufleft[0], dsizey, PVEC_REAL_MPI_TYPE, thispe-1, 0, comm);
+ }
+
+ /* If ixsub < NPEX-1, send data from right y-line of u (via bufright). */
+
+ if (ixsub != NPEX-1) {
+ for (ly = 0; ly < MYSUB; ly++) {
+ offsetu = ly*MXSUB + (MXSUB-1);
+ bufright[ly] = uarray[offsetu];
+ }
+ MPI_Send(&bufright[0], dsizey, PVEC_REAL_MPI_TYPE, thispe+1, 0, comm);
+ }
+
+ return(0);
+
+}
+
+/*
+ * Routine to start receiving boundary data from neighboring PEs.
+ * Notes:
+ * 1) buffer should be able to hold 2*MYSUB realtype entries, should be
+ * passed to both the BRecvPost and BRecvWait functions, and should not
+ * be manipulated between the two calls.
+ * 2) request should have 4 entries, and should be passed in
+ * 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[])
+{
+ long int offsetue;
+ /* Have bufleft and bufright use the same buffer. */
+ realtype *bufleft = buffer, *bufright = buffer+MYSUB;
+
+ /* If jysub > 0, receive data for bottom x-line of uext. */
+ if (jysub != 0)
+ MPI_Irecv(&uext[1], dsizex, PVEC_REAL_MPI_TYPE,
+ thispe-NPEX, 0, comm, &request[0]);
+
+ /* If jysub < NPEY-1, receive data for top x-line of uext. */
+ if (jysub != NPEY-1) {
+ offsetue = (1 + (MYSUB+1)*(MXSUB+2));
+ MPI_Irecv(&uext[offsetue], dsizex, PVEC_REAL_MPI_TYPE,
+ thispe+NPEX, 0, comm, &request[1]);
+ }
+
+ /* If ixsub > 0, receive data for left y-line of uext (via bufleft). */
+ if (ixsub != 0) {
+ MPI_Irecv(&bufleft[0], dsizey, PVEC_REAL_MPI_TYPE,
+ thispe-1, 0, comm, &request[2]);
+ }
+
+ /* If ixsub < NPEX-1, receive data for right y-line of uext (via bufright). */
+ if (ixsub != NPEX-1) {
+ MPI_Irecv(&bufright[0], dsizey, PVEC_REAL_MPI_TYPE,
+ thispe+1, 0, comm, &request[3]);
+ }
+
+ return(0);
+
+}
+
+/*
+ * Routine to finish receiving boundary data from neighboring PEs.
+ * Notes:
+ * 1) buffer should be able to hold 2*MYSUB realtype entries, should be
+ * passed to both the BRecvPost and BRecvWait functions, and should not
+ * be manipulated between the two calls.
+ * 2) request should have four entries, and should be passed in both
+ * calls also.
+ */
+
+static int BRecvWait(MPI_Request request[], long int ixsub, long int jysub,
+ long int dsizex, realtype uext[], realtype buffer[])
+{
+ long int ly, dsizex2, offsetue;
+ realtype *bufleft = buffer, *bufright = buffer+MYSUB;
+ MPI_Status status;
+
+ dsizex2 = dsizex + 2;
+
+ /* If jysub > 0, receive data for bottom x-line of uext. */
+ if (jysub != 0)
+ MPI_Wait(&request[0],&status);
+
+ /* If jysub < NPEY-1, receive data for top x-line of uext. */
+ if (jysub != NPEY-1)
+ MPI_Wait(&request[1],&status);
+
+ /* If ixsub > 0, receive data for left y-line of uext (via bufleft). */
+ if (ixsub != 0) {
+ MPI_Wait(&request[2],&status);
+
+ /* Copy the buffer to uext. */
+ for (ly = 0; ly < MYSUB; ly++) {
+ offsetue = (ly+1)*dsizex2;
+ uext[offsetue] = bufleft[ly];
+ }
+ }
+
+ /* If ixsub < NPEX-1, receive data for right y-line of uext (via bufright). */
+ if (ixsub != NPEX-1) {
+ MPI_Wait(&request[3],&status);
+
+ /* Copy the buffer to uext */
+ for (ly = 0; ly < MYSUB; ly++) {
+ offsetue = (ly+2)*dsizex2 - 1;
+ uext[offsetue] = bufright[ly];
+ }
+ }
+
+ return(0);
+
+}
+
+/*
+ *--------------------------------------------------------------------
+ * PRIVATE FUNCTIONS
+ *--------------------------------------------------------------------
+ */
+
+/*
+ * InitUserData initializes the user's data block data.
+ */
+
+static int InitUserData(int thispe, MPI_Comm comm, UserData data)
+{
+ data->thispe = thispe;
+ data->dx = ONE/(MX-ONE); /* Assumes a [0,1] interval in x. */
+ data->dy = ONE/(MY-ONE); /* Assumes a [0,1] interval in y. */
+ data->coeffx = ONE/(data->dx * data->dx);
+ data->coeffy = ONE/(data->dy * data->dy);
+ data->coeffxy = TWO/(data->dx * data->dx) + TWO/(data->dy * data->dy) ;
+ data->jysub = thispe/NPEX;
+ data->ixsub = thispe - data->jysub * NPEX;
+ data->npex = NPEX;
+ data->npey = NPEY;
+ data->mx = MX;
+ data->my = MY;
+ data->mxsub = MXSUB;
+ data->mysub = MYSUB;
+ data->comm = comm;
+ return(0);
+
+}
+
+/*
+ * SetInitialProfile sets the initial values for the problem.
+ */
+
+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;
+ realtype xfact, yfact, *udata, *iddata, dx, dy;
+
+ /* Initialize uu. */
+
+ udata = NV_DATA_P(uu);
+ iddata = NV_DATA_P(id);
+
+ /* Set mesh spacings and subgrid indices for this PE. */
+ dx = data->dx;
+ dy = data->dy;
+ ixsub = data->ixsub;
+ jysub = data->jysub;
+
+ /* Set beginning and ending locations in the global array corresponding
+ to the portion of that array assigned to this processor. */
+ ixbegin = MXSUB*ixsub;
+ ixend = MXSUB*(ixsub+1) - 1;
+ jybegin = MYSUB*jysub;
+ jyend = MYSUB*(jysub+1) - 1;
+
+ /* Loop over the local array, computing the initial profile value.
+ The global indices are (i,j) and the local indices are (iloc,jloc).
+ Also set the id vector to zero for boundary points, one otherwise. */
+
+ N_VConst(ONE,id);
+ for (j = jybegin, jloc = 0; j <= jyend; j++, jloc++) {
+ yfact = data->dy*j;
+ offset= jloc*MXSUB;
+ for (i = ixbegin, iloc = 0; i <= ixend; i++, iloc++) {
+ xfact = data->dx * i;
+ loc = offset + iloc;
+ udata[loc] = RCONST(16.0) * xfact * (ONE - xfact) * yfact * (ONE - yfact);
+ if (i == 0 || i == MX-1 || j == 0 || j == MY-1) iddata[loc] = ZERO;
+ }
+ }
+
+ /* Initialize up. */
+
+ N_VConst(ZERO, up); /* Initially set up = 0. */
+
+ /* resHeat sets res to negative of ODE RHS values at interior points. */
+ resHeat(ZERO, uu, up, res, data);
+
+ /* Copy -res into up to get correct initial up values. */
+ N_VScale(-ONE, res, up);
+
+ return(0);
+}
+
+/*
+ * Print first lines of output and table heading
+ */
+
+static void PrintHeader(long int 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("Subgrid dimensions: %d x %d", MXSUB, MYSUB);
+ printf(" Processor array: %d x %d\n", NPEX, NPEY);
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("Tolerance parameters: rtol = %Lg atol = %Lg\n", rtol, atol);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("Tolerance parameters: rtol = %lg atol = %lg\n", rtol, atol);
+#else
+ 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("all boundary components. \n");
+ printf("Linear solver: IDASPGMR ");
+ printf("Preconditioner: diagonal elements only.\n");
+
+ /* Print output table heading and initial line of table. */
+ printf("\n Output Summary (umax = max-norm of solution) \n\n");
+ printf(" time umax k nst nni nli nre nreLS h npe nps\n");
+ printf("----------------------------------------------------------------------\n");
+}
+
+/*
+ * PrintOutput: print max norm of solution and current solver statistics
+ */
+
+static void PrintOutput(int id, void *mem, realtype t, N_Vector uu)
+{
+ realtype hused, umax;
+ long int nst, nni, nje, nre, nreLS, nli, npe, nps;
+ int kused, ier;
+
+ umax = N_VMaxNorm(uu);
+
+ if (id == 0) {
+
+ ier = IDAGetLastOrder(mem, &kused);
+ check_flag(&ier, "IDAGetLastOrder", 1, id);
+ ier = IDAGetNumSteps(mem, &nst);
+ check_flag(&ier, "IDAGetNumSteps", 1, id);
+ ier = IDAGetNumNonlinSolvIters(mem, &nni);
+ check_flag(&ier, "IDAGetNumNonlinSolvIters", 1, id);
+ ier = IDAGetNumResEvals(mem, &nre);
+ check_flag(&ier, "IDAGetNumResEvals", 1, id);
+ ier = IDAGetLastStep(mem, &hused);
+ check_flag(&ier, "IDAGetLastStep", 1, id);
+ ier = IDASpilsGetNumJtimesEvals(mem, &nje);
+ check_flag(&ier, "IDASpilsGetNumJtimesEvals", 1, id);
+ ier = IDASpilsGetNumLinIters(mem, &nli);
+ check_flag(&ier, "IDASpilsGetNumLinIters", 1, id);
+ ier = IDASpilsGetNumResEvals(mem, &nreLS);
+ check_flag(&ier, "IDASpilsGetNumResEvals", 1, id);
+ ier = IDASpilsGetNumPrecEvals(mem, &npe);
+ check_flag(&ier, "IDASpilsGetPrecEvals", 1, id);
+ ier = IDASpilsGetNumPrecSolves(mem, &nps);
+ check_flag(&ier, "IDASpilsGetNumPrecSolves", 1, id);
+
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf(" %5.2Lf %13.5Le %d %3ld %3ld %3ld %4ld %4ld %9.2Le %3ld %3ld\n",
+ t, umax, kused, nst, nni, nje, nre, nreLS, hused, npe, nps);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf(" %5.2f %13.5le %d %3ld %3ld %3ld %4ld %4ld %9.2le %3ld %3ld\n",
+ t, umax, kused, nst, nni, nje, nre, nreLS, hused, npe, nps);
+#else
+ printf(" %5.2f %13.5e %d %3ld %3ld %3ld %4ld %4ld %9.2e %3ld %3ld\n",
+ t, umax, kused, nst, nni, nje, nre, nreLS, hused, npe, nps);
+#endif
+
+ }
+}
+
+/*
+ * Print some final integrator statistics
+ */
+
+static void PrintFinalStats(void *mem)
+{
+ long int netf, ncfn, ncfl;
+
+ IDAGetNumErrTestFails(mem, &netf);
+ IDAGetNumNonlinSolvConvFails(mem, &ncfn);
+ IDASpilsGetNumConvFails(mem, &ncfl);
+
+ printf("\nError test failures = %ld\n", netf);
+ printf("Nonlinear convergence failures = %ld\n", ncfn);
+ printf("Linear convergence failures = %ld\n", ncfl);
+}
+
+/*
+ * 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, char *funcname, int opt, int id)
+{
+ int *errflag;
+
+ if (opt == 0 && flagvalue == NULL) {
+ /* Check if SUNDIALS function returned NULL pointer - no memory allocated */
+ fprintf(stderr,
+ "\nSUNDIALS_ERROR(%d): %s() failed - returned NULL pointer\n\n",
+ id, funcname);
+ return(1);
+ } else if (opt == 1) {
+ /* Check if flag < 0 */
+ errflag = (int *) flagvalue;
+ if (*errflag < 0) {
+ fprintf(stderr,
+ "\nSUNDIALS_ERROR(%d): %s() failed with flag = %d\n\n",
+ id, funcname, *errflag);
+ return(1);
+ }
+ } else if (opt == 2 && flagvalue == NULL) {
+ /* Check if function returned NULL pointer - no memory allocated */
+ fprintf(stderr,
+ "\nMEMORY_ERROR(%d): %s() failed - returned NULL pointer\n\n",
+ id, funcname);
+ return(1);
+ }
+
+ return(0);
+}
diff --git a/examples/idas/parallel/idasHeat2D_kry_p.out b/examples/idas/parallel/idasHeat2D_kry_p.out
new file mode 100644
index 0000000..b513617
--- /dev/null
+++ b/examples/idas/parallel/idasHeat2D_kry_p.out
@@ -0,0 +1,32 @@
+
+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
+
+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.
+
+ Output Summary (umax = max-norm of solution)
+
+ time umax k nst nni nli nre nreLS h npe nps
+----------------------------------------------------------------------
+ 0.00 9.75461e-01 0 0 0 0 0 0 0.00e+00 0 0
+ 0.01 8.24106e-01 2 12 14 7 14 7 2.56e-03 8 21
+ 0.02 6.88134e-01 3 15 18 12 18 12 5.12e-03 8 30
+ 0.04 4.70711e-01 3 18 24 21 24 21 6.58e-03 9 45
+ 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 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
+
+Error test failures = 1
+Nonlinear convergence failures = 0
+Linear convergence failures = 0
diff --git a/examples/idas/serial/CMakeLists.txt b/examples/idas/serial/CMakeLists.txt
new file mode 100644
index 0000000..68502c0
--- /dev/null
+++ b/examples/idas/serial/CMakeLists.txt
@@ -0,0 +1,131 @@
+# ---------------------------------------------------------------
+# $Revision: 1.10 $
+# $Date: 2009/02/17 02:58:47 $
+# ---------------------------------------------------------------
+# Programmer: Radu Serban @ LLNL
+# ---------------------------------------------------------------
+# Copyright (c) 2007, The Regents of the University of California.
+# Produced at the Lawrence Livermore National Laboratory.
+# All rights reserved.
+# For details, see the LICENSE file.
+# ---------------------------------------------------------------
+# CMakeLists.txt file for IDAS serial examples
+
+
+# Add variable IDAS_examples with the names of the serial IDAS examples
+
+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
+ idasSlCrank_dns
+ idasSlCrank_FSA_dns
+ )
+
+# Add variable IDAS_examples_BL with the names of the serial IDAS examples
+# that use Lapack
+
+SET(IDAS_examples_BL
+ )
+
+# 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")
+ SET(IDAS_LIB sundials_idas_shared)
+ SET(NVECS_LIB sundials_nvecserial_shared)
+ENDIF(LINK_LIBRARY_TYPE MATCHES "static")
+
+# Set-up linker flags and link libraries
+
+SET(SUNDIALS_LIBS ${IDAS_LIB} ${NVECS_LIB} ${EXTRA_LINK_LIBS})
+IF(LAPACK_FOUND)
+ SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${LAPACK_LINKER_FLAGS}")
+ SET(SUNDIALS_LIBS "${SUNDIALS_LIBS} ${LAPACK_LIBRARIES}")
+ENDIF(LAPACK_FOUND)
+
+# Add the build and install targets for each IDAS example
+
+FOREACH(example ${IDAS_examples})
+ ADD_EXECUTABLE(${example} ${example}.c)
+ 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})
+
+# If Lapack support is enabled, add the build and install targets for
+# the examples using Lapack
+
+IF(LAPACK_FOUND)
+ FOREACH(example ${IDAS_examples_BL})
+ ADD_EXECUTABLE(${example} ${example}.c)
+ 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_BL})
+ENDIF(LAPACK_FOUND)
+
+IF(EXAMPLES_INSTALL)
+
+ # Install the README file
+ INSTALL(FILES README DESTINATION ${EXAMPLES_INSTALL_PATH}/idas/serial)
+
+ # Prepare substitution variables for Makefile and/or CMakeLists templates
+ SET(SOLVER "IDAS")
+ SET(SOLVER_LIB "sundials_idas")
+ LIST2STRING(IDAS_examples EXAMPLES)
+ IF(LAPACK_FOUND)
+ LIST2STRING(IDAS_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
+ # 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
+ )
+
+ # install CMakelists.txt
+ INSTALL(
+ FILES ${PROJECT_BINARY_DIR}/examples/idas/serial/CMakeLists.txt
+ 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
+ # 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/idas/serial/Makefile_ex
+ @ONLY
+ )
+ # install the configured Makefile_ex as Makefile
+ INSTALL(
+ FILES ${PROJECT_BINARY_DIR}/examples/idas/serial/Makefile_ex
+ DESTINATION ${EXAMPLES_INSTALL_PATH}/idas/serial
+ RENAME Makefile
+ )
+ ENDIF(UNIX)
+
+ENDIF(EXAMPLES_INSTALL)
diff --git a/examples/idas/serial/Makefile.in b/examples/idas/serial/Makefile.in
new file mode 100644
index 0000000..aa67968
--- /dev/null
+++ b/examples/idas/serial/Makefile.in
@@ -0,0 +1,142 @@
+# -----------------------------------------------------------------
+# $Revision: 1.16 $
+# $Date: 2009/02/17 02:58:47 $
+# -----------------------------------------------------------------
+# Programmer(s): Radu Serban @ LLNL
+# -----------------------------------------------------------------
+# Copyright (c) 2002, The Regents of the University of California.
+# Produced at the Lawrence Livermore National Laboratory.
+# All rights reserved.
+# For details, see the LICENSE file.
+# -----------------------------------------------------------------
+# Makefile for IDAS serial examples
+#
+# @configure_input@
+# -----------------------------------------------------------------
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_builddir = @top_builddir@
+builddir = @builddir@
+abs_builddir = @abs_builddir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+includedir = @includedir@
+libdir = @libdir@
+
+INSTALL = @INSTALL@
+INSTALL_PROG = @INSTALL_PROGRAM@
+INSTALL_FILE = @INSTALL_DATA@
+
+LIBTOOL = @LIBTOOL@
+LIBTOOL_DEPS = @LIBTOOL_DEPS@
+
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CC = @CC@
+CFLAGS = @CFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+
+LAPACK_ENABLED = @LAPACK_ENABLED@
+BLAS_LAPACK_LIBS = @BLAS_LAPACK_LIBS@
+
+OBJ_EXT = @OBJEXT@
+EXE_EXT = @EXEEXT@
+
+EXS_INSTDIR = @EXS_INSTDIR@
+
+top_srcdir = $(srcdir)/../../..
+
+SUNDIALS_INCS = -I$(top_srcdir)/include -I$(top_builddir)/include
+
+SUNDIALS_LIBS = $(top_builddir)/src/idas/libsundials_idas.la \
+ $(top_builddir)/src/nvec_ser/libsundials_nvecserial.la
+
+mkinstalldirs = $(SHELL) $(top_srcdir)/config/mkinstalldirs
+rminstalldirs = $(SHELL) $(top_srcdir)/config/rminstalldirs
+
+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 \
+ idasSlCrank_dns \
+ idasSlCrank_FSA_dns
+
+EXAMPLES_BL =
+
+OBJECTS = ${EXAMPLES:=${OBJ_EXT}}
+OBJECTS_BL = ${EXAMPLES_BL:=${OBJ_EXT}}
+EXECS = ${EXAMPLES:=${EXE_EXT}}
+EXECS_BL = ${EXAMPLES_BL:=${EXE_EXT}}
+
+# ----------------------------------------------------------------------------------------------------------------------
+
+all:
+ @for i in ${EXAMPLES} ; do \
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(SUNDIALS_INCS) $(CFLAGS) -c $(srcdir)/$${i}.c -o $${i}${OBJ_EXT} ; \
+ $(LIBTOOL) --mode=link $(CC) -o $(builddir)/$${i}$(EXE_EXT) $(builddir)/$${i}${OBJ_EXT} $(CFLAGS) $(LDFLAGS) $(SUNDIALS_LIBS) $(LIBS) $(BLAS_LAPACK_LIBS) ; \
+ done
+ @if test "X${LAPACK_ENABLED}" = "Xyes"; then \
+ for i in ${EXAMPLES_BL} ; do \
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(SUNDIALS_INCS) $(CFLAGS) -c $(srcdir)/$${i}.c -o $${i}${OBJ_EXT} ; \
+ $(LIBTOOL) --mode=link $(CC) -o $(builddir)/$${i}$(EXE_EXT) $(builddir)/$${i}${OBJ_EXT} $(CFLAGS) $(LDFLAGS) $(SUNDIALS_LIBS) $(LIBS) $(BLAS_LAPACK_LIBS) ; \
+ done ; \
+ fi
+
+install:
+ $(mkinstalldirs) $(EXS_INSTDIR)/idas/serial
+ $(INSTALL_FILE) Makefile_ex $(EXS_INSTDIR)/idas/serial/Makefile
+ $(INSTALL_FILE) $(top_srcdir)/examples/idas/serial/README $(EXS_INSTDIR)/idas/serial/
+ for i in ${EXAMPLES} ; do \
+ $(INSTALL_FILE) $(top_srcdir)/examples/idas/serial/$${i}.c $(EXS_INSTDIR)/idas/serial/ ; \
+ $(INSTALL_FILE) $(top_srcdir)/examples/idas/serial/$${i}.out $(EXS_INSTDIR)/idas/serial/ ; \
+ done
+ @if test "X${LAPACK_ENABLED}" = "Xyes"; then \
+ for i in ${EXAMPLES_BL} ; do \
+ $(INSTALL_FILE) $(top_srcdir)/examples/idas/serial/$${i}.c $(EXS_INSTDIR)/idas/serial/ ; \
+ $(INSTALL_FILE) $(top_srcdir)/examples/idas/serial/$${i}.out $(EXS_INSTDIR)/idas/serial/ ; \
+ done ; \
+ fi
+
+uninstall:
+ rm -f $(EXS_INSTDIR)/idas/serial/Makefile
+ rm -f $(EXS_INSTDIR)/idas/serial/README
+ for i in ${EXAMPLES} ; do \
+ rm -f $(EXS_INSTDIR)/idas/serial/$${i}.c ; \
+ rm -f $(EXS_INSTDIR)/idas/serial/$${i}.out ; \
+ done
+ @if test "X${LAPACK_ENABLED}" = "Xyes"; then \
+ for i in ${EXAMPLES_BL} ; do \
+ rm -f $(EXS_INSTDIR)/idas/serial/$${i}.c ; \
+ rm -f $(EXS_INSTDIR)/idas/serial/$${i}.out ; \
+ done ; \
+ fi
+ $(rminstalldirs) $(EXS_INSTDIR)/idas/serial
+ $(rminstalldirs) $(EXS_INSTDIR)/idas
+
+clean:
+ rm -rf .libs
+ rm -f *.lo
+ rm -f ${OBJECTS} ${OBJECTS_BL}
+ rm -f $(EXECS) $(EXECS_BL)
+
+distclean: clean
+ rm -f Makefile
+ rm -f Makefile_ex
+
+# ----------------------------------------------------------------------------------------------------------------------
+
+libtool: $(top_builddir)/$(LIBTOOL_DEPS)
+ @cd ${top_builddir} ; \
+ ${SHELL} ./config.status --recheck ; \
+ cd ${abs_builddir}
+
+
diff --git a/examples/idas/serial/README b/examples/idas/serial/README
new file mode 100644
index 0000000..07f5d18
--- /dev/null
+++ b/examples/idas/serial/README
@@ -0,0 +1,26 @@
+List of serial IDAS examples
+
+ idasAkzoNob_ASAi_dns : adjoint sensitivity for the chemical Akzo-Nobel problem
+ idasAkzoNob_dns : chemical Akzo-Nobel problem
+ idasFoodWeb_bnd : 2-D food web system, banded Jacobian
+ idasHeat2D_bnd : 2-D heat equation, banded Jacobian
+ 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 a user-supplied Jacobian
+ idasRoberts_FSA_dns : forward sensitivity for Robertson kinetics system
+ idasSlCrank_dns : slider-crank simulation
+ idasSlCrank_FSA_dns : forward sensitivity for slider-crank
+
+
+Sample results:
+
+ SUNDIALS was built with the following options:
+
+ ./configure CC=gcc F77=gfortran CFLAGS="-g3 -O0" FFLAGS="-g3 -O0" --enable-examples
+
+ System Architecture: IA-32
+ Processor Type: Intel Pentium 4 Xeon DP (i686)
+ Operating System: Red Hat Enterprise Linux WS 3 (Taroon Update 7)
+ C/Fortran Compilers: gcc/gfortran v4.1.0
diff --git a/examples/idas/serial/idasAkzoNob_ASAi_dns.c b/examples/idas/serial/idasAkzoNob_ASAi_dns.c
new file mode 100644
index 0000000..82b8a32
--- /dev/null
+++ b/examples/idas/serial/idasAkzoNob_ASAi_dns.c
@@ -0,0 +1,441 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.2 $
+ * $Date: 2008/04/17 20:12:55 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Radu Serban and Cosmin Petra @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2007, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * Adjoint sensitivity example problem
+ *
+ * This IVP is a stiff system of 6 non-linear DAEs of index 1. The
+ * problem originates from Akzo Nobel Central research in Arnhern,
+ * 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
+ *
+ * IDAS also computes the sensitivities with respect to initial
+ * 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>
+
+/* 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 RTOL RCONST(1.0e-08)
+#define ATOL RCONST(1.0e-10)
+#define RTOLB RCONST(1.0e-06)
+#define ATOLB RCONST(1.0e-08)
+#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)
+#define TWO RCONST(2.0)
+
+#define STEPS 150
+
+typedef struct {
+ realtype k1, k2, k3, k4;
+ realtype K, klA, Ks, pCO2, H;
+} *UserData;
+
+static int res(realtype t, N_Vector yy, N_Vector yd, N_Vector res, void *userdata);
+
+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 rhsQ(realtype t, N_Vector yy, N_Vector yp,
+ N_Vector qdot, void *user_data);
+
+static void PrintOutput(realtype tfinal, N_Vector yB, N_Vector ypB);
+static int check_flag(void *flagvalue, char *funcname, int opt);
+
+
+/* Main program */
+int main()
+{
+ UserData data;
+ void *mem;
+ N_Vector yy, yp, rr, q;
+ N_Vector yB, ypB;
+ int ncheck, flag;
+ realtype time;
+ long int nst, nstB;
+ int indexB;
+
+
+ mem = NULL;
+ yy = yp = NULL;
+
+ printf("\nAdjoint Sensitivity Example for Akzo-Nobel Chemical Kinetics\n");
+ printf("-------------------------------------------------------------\n");
+ printf("Sensitivity of G = int_t0^tf (y1) dt with respect to IC.\n");
+ printf("-------------------------------------------------------------\n\n");
+ /* Allocate user data. */
+ data = (UserData) malloc(sizeof(*data));
+
+ /* Fill user's data with the appropriate values for coefficients. */
+ data->k1 = RCONST(18.7);
+ data->k2 = RCONST(0.58);
+ data->k3 = RCONST(0.09);
+ data->k4 = RCONST(0.42);
+ data->K = RCONST(34.4);
+ data->klA = RCONST(3.3);
+ data->Ks = RCONST(115.83);
+ data->pCO2 = RCONST(0.9);
+ data->H = RCONST(737.0);
+
+ /* Allocate N-vectors. */
+ yy = N_VNew_Serial(NEQ);
+ if (check_flag((void *)yy, "N_VNew_Serial", 0)) return(1);
+ 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);
+
+ /* Get y' = - res(t0, y, 0) */
+ N_VConst(ZERO, yp);
+
+ rr = N_VNew_Serial(NEQ);
+ res(T0, yy, yp, rr, data);
+ N_VScale(-ONE, rr, yp);
+ N_VDestroy_Serial(rr);
+
+ /* Create and initialize q0 for quadratures. */
+ q = N_VNew_Serial(1);
+ if (check_flag((void *)q, "N_VNew_Serial", 0)) return(1);
+ Ith(q,1) = ZERO;
+
+ /* Call IDACreate and IDAInit to initialize IDA memory */
+ mem = IDACreate();
+ if(check_flag((void *)mem, "IDACreate", 0)) return(1);
+
+ flag = IDAInit(mem, res, T0, yy, yp);
+ if(check_flag(&flag, "IDAInit", 1)) return(1);
+
+
+ /* Set tolerances. */
+ flag = IDASStolerances(mem, RTOL, ATOL);
+ if(check_flag(&flag, "IDASStolerances", 1)) return(1);
+
+ /* Attach user data. */
+ flag = IDASetUserData(mem, data);
+ if(check_flag(&flag, "IDASetUser", 1)) return(1);
+
+ /* Attach linear solver. */
+ flag = IDADense(mem, NEQ);
+
+ /* Initialize QUADRATURE(S). */
+ flag = IDAQuadInit(mem, rhsQ, q);
+ if (check_flag(&flag, "IDAQuadInit", 1)) return(1);
+
+ /* Set tolerances and error control for quadratures. */
+ flag = IDAQuadSStolerances(mem, RTOLQ, ATOLQ);
+ if (check_flag(&flag, "IDAQuadSStolerances", 1)) return(1);
+
+ flag = IDASetQuadErrCon(mem, TRUE);
+ if (check_flag(&flag, "IDASetQuadErrCon", 1)) return(1);
+
+ /* Prepare ADJOINT. */
+ flag = IDAAdjInit(mem, STEPS, IDA_HERMITE);
+ if (check_flag(&flag, "IDAAdjInit", 1)) return(1);
+
+ /* FORWARD run. */
+ printf("Forward integration ... ");
+ flag = IDASolveF(mem, TF, &time, yy, yp, IDA_NORMAL, &ncheck);
+ if (check_flag(&flag, "IDASolveF", 1)) return(1);
+
+ flag = IDAGetNumSteps(mem, &nst);
+ if (check_flag(&flag, "IDAGetNumSteps", 1)) return(1);
+
+ printf("done ( nst = %ld )\n",nst);
+
+ flag = IDAGetQuad(mem, &time, q);
+ if (check_flag(&flag, "IDAGetQuad", 1)) return(1);
+
+ printf("G: %24.16f \n",Ith(q,1));
+ printf("--------------------------------------------------------\n\n");
+
+
+ /* BACKWARD run */
+
+ /* Initialize yB */
+ yB = N_VNew_Serial(NEQ);
+ if (check_flag((void *)yB, "N_VNew_Serial", 0)) return(1);
+ N_VConst(ZERO, yB);
+
+ ypB = N_VNew_Serial(NEQ);
+ if (check_flag((void *)ypB, "N_VNew_Serial", 0)) return(1);
+ N_VConst(ZERO, ypB);
+ Ith(ypB,1) = - ONE;
+
+ flag = IDACreateB(mem, &indexB);
+ if (check_flag(&flag, "IDACreateB", 1)) return(1);
+
+ flag = IDAInitB(mem, indexB, resB, TF, yB, ypB);
+ if (check_flag(&flag, "IDAInitB", 1)) return(1);
+
+ flag = IDASStolerancesB(mem, indexB, RTOLB, ATOLB);
+ if (check_flag(&flag, "IDASStolerancesB", 1)) return(1);
+
+ flag = IDASetUserDataB(mem, indexB, data);
+ if (check_flag(&flag, "IDASetUserDataB", 1)) return(1);
+
+ flag = IDASetMaxNumStepsB(mem, indexB, 1000);
+
+ flag = IDADenseB(mem, indexB, NEQ);
+ if (check_flag(&flag, "IDADenseB", 1)) return(1);
+
+ printf("Backward integration ... ");
+
+ flag = IDASolveB(mem, T0, IDA_NORMAL);
+ if (check_flag(&flag, "IDASolveB", 1)) return(1);
+
+ IDAGetNumSteps(IDAGetAdjIDABmem(mem, indexB), &nstB);
+ printf("done ( nst = %ld )\n", nstB);
+
+ flag = IDAGetB(mem, indexB, &time, yB, ypB);
+ if (check_flag(&flag, "IDAGetB", 1)) return(1);
+
+ 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);
+
+ return(0);
+}
+
+
+static int res(realtype t, N_Vector yy, N_Vector yd, N_Vector res, void *userdata)
+{
+ UserData data;
+ realtype k1, k2, k3, k4;
+ realtype K, klA, Ks, pCO2, H;
+
+ realtype y1, y2, y3, y4, y5, y6;
+ realtype yd1, yd2, yd3, yd4, yd5;
+
+ realtype r1, r2, r3, r4, r5, Fin;
+
+ data = (UserData) userdata;
+ k1 = data->k1;
+ k2 = data->k2;
+ k3 = data->k3;
+ k4 = data->k4;
+ K = data->K;
+ klA = data->klA;
+ Ks = data->Ks;
+ pCO2 = data->pCO2;
+ H = data->H;
+
+ y1 = Ith(yy,1);
+ y2 = Ith(yy,2);
+ y3 = Ith(yy,3);
+ y4 = Ith(yy,4);
+ y5 = Ith(yy,5);
+ y6 = Ith(yy,6);
+
+ yd1 = Ith(yd,1);
+ yd2 = Ith(yd,2);
+ yd3 = Ith(yd,3);
+ yd4 = Ith(yd,4);
+ yd5 = Ith(yd,5);
+
+ r1 = k1 * RPowerI(y1,4) * RSqrt(y2);
+ r2 = k2 * y3 * y4;
+ r3 = k2/K * y1 * y5;
+ r4 = k3 * y1 * y4 * y4;
+ r5 = k4 * y6 * y6 * RSqrt(y2);
+ Fin = klA * ( pCO2/H - y2 );
+
+ Ith(res,1) = yd1 + TWO*r1 - r2 + r3 + r4;
+ Ith(res,2) = yd2 + HALF*r1 + r4 + HALF*r5 - Fin;
+ Ith(res,3) = yd3 - r1 + r2 - r3;
+ Ith(res,4) = yd4 + r2 - r3 + TWO*r4;
+ Ith(res,5) = yd5 - r2 + r3 - r5;
+ Ith(res,6) = Ks*y1*y4 - y6;
+
+ return(0);
+}
+
+/*
+ * rhsQ routine. Computes quadrature(t,y).
+ */
+
+static int rhsQ(realtype t, N_Vector yy, N_Vector yp, N_Vector qdot, void *user_data)
+{
+ Ith(qdot,1) = Ith(yy,1);
+
+ return(0);
+}
+
+#define QUARTER RCONST(0.25)
+#define FOUR RCONST(4.0)
+#define EIGHT RCONST(8.0)
+
+/*
+ * resB routine. Residual for adjoint system.
+ */
+static int resB(realtype tt,
+ N_Vector yy, N_Vector yp,
+ N_Vector yyB, N_Vector ypB, N_Vector rrB,
+ void *user_dataB)
+{
+ UserData data;
+
+ realtype y1, y2, y3, y4, y5, y6;
+
+ realtype yB1, yB2, yB3, yB4, yB5, yB6;
+ realtype ypB1, ypB2, ypB3, ypB4, ypB5;
+
+ realtype k1, k2, k3, k4;
+ realtype K, klA, Ks, pCO2, H;
+
+ realtype y2tohalf, y1to3, k2overK, tmp1, tmp2;
+
+ data = (UserData) user_dataB;
+ k1 = data->k1;
+ k2 = data->k2;
+ k3 = data->k3;
+ k4 = data->k4;
+ K = data->K;
+ klA = data->klA;
+ Ks = data->Ks;
+ pCO2 = data->pCO2;
+ H = data->H;
+
+ y1 = Ith(yy,1);
+ y2 = Ith(yy,2);
+ y3 = Ith(yy,3);
+ y4 = Ith(yy,4);
+ y5 = Ith(yy,5);
+ y6 = Ith(yy,6);
+
+ yB1 = Ith(yyB,1);
+ yB2 = Ith(yyB,2);
+ yB3 = Ith(yyB,3);
+ yB4 = Ith(yyB,4);
+ yB5 = Ith(yyB,5);
+ yB6 = Ith(yyB,6);
+
+ ypB1 = Ith(ypB,1);
+ ypB2 = Ith(ypB,2);
+ ypB3 = Ith(ypB,3);
+ ypB4 = Ith(ypB,4);
+ ypB5 = Ith(ypB,5);
+
+ y2tohalf = sqrt(y2);
+ y1to3 = y1*y1*y1;
+ k2overK = k2/K;
+
+ tmp1 = k1* y1to3 * y2tohalf; tmp2 = k3*y4*y4;
+ Ith(rrB,1) = 1 + ypB1 - (EIGHT*tmp1 + k2overK*y5 + tmp2)*yB1
+ - (TWO*tmp1+tmp2)*yB2 + (FOUR*tmp1+k2overK*y5)*yB3
+ + k2overK*y5*(yB4-yB5) - TWO*tmp2*yB4 + Ks*y4*yB6;
+
+ tmp1 = k1 * y1*y1to3 * (y2tohalf/y2); tmp2 = k4 * y6*y6 * (y2tohalf/y2);
+ Ith(rrB,2) = ypB2 - tmp1*yB1 - (QUARTER*tmp1 + QUARTER*tmp2 + klA)*yB2
+ + HALF*tmp1*yB3 + HALF*tmp2*yB5;
+
+ Ith(rrB,3) = ypB3 + k2*y4*(yB1-yB3-yB4+yB5);
+
+ tmp1 = k3*y1*y4; tmp2 = k2*y3;
+ Ith(rrB,4) = ypB4 + (tmp2-TWO*tmp1)*yB1 - TWO*tmp1*yB2 - tmp2*yB3
+ - (tmp2+FOUR*tmp1)*yB4 + tmp2*yB5 + Ks*y1*yB6;
+
+ Ith(rrB,5) = ypB5 - k2overK*y1*(yB1-yB3-yB4+yB5);
+
+ Ith(rrB,6) = k4*y6*y2tohalf*(2*yB5-yB2) - yB6;
+
+
+ return 0;
+}
+
+
+/*
+ * Print results after backward integration
+ */
+static void PrintOutput(realtype tfinal, N_Vector yB, N_Vector ypB)
+{
+ 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",
+ Ith(yB,1), Ith(yB,2), Ith(yB,3), Ith(yB,4), Ith(yB,5), Ith(yB,6));
+ printf("--------------------------------------------------------\n\n");
+}
+
+/*
+ * 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, 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/idasAkzoNob_ASAi_dns.out b/examples/idas/serial/idasAkzoNob_ASAi_dns.out
new file mode 100644
index 0000000..273d53d
--- /dev/null
+++ b/examples/idas/serial/idasAkzoNob_ASAi_dns.out
@@ -0,0 +1,19 @@
+
+Adjoint Sensitivity Example for Akzo-Nobel Chemical Kinetics
+-------------------------------------------------------------
+Sensitivity of G = int_t0^tf (y1) dt with respect to IC.
+-------------------------------------------------------------
+
+Forward integration ... done ( nst = 457 )
+G: 31.2642162580311549
+--------------------------------------------------------
+
+Backward integration ... done ( nst = 274 )
+dG/dy0: 2.2207e+01
+ -6.2695e+01
+ -2.5115e+00
+ 9.1837e+01
+ 3.5176e+00
+ 3.6976e-01
+--------------------------------------------------------
+
diff --git a/examples/idas/serial/idasAkzoNob_dns.c b/examples/idas/serial/idasAkzoNob_dns.c
new file mode 100644
index 0000000..63174b9
--- /dev/null
+++ b/examples/idas/serial/idasAkzoNob_dns.c
@@ -0,0 +1,371 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.2 $
+ * $Date: 2009/09/30 23:33:29 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Radu Serban and Cosmin Petra @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2007, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * Adjoint sensitivity example problem
+ *
+ * This IVP is a stiff system of 6 non-linear DAEs of index 1. The
+ * problem originates from Akzo Nobel Central research in Arnhern,
+ * 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>
+
+/* 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 T1 RCONST(1e-8) /* first time for output */
+
+#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)
+#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)
+#define TWO RCONST(2.0)
+
+
+typedef struct {
+ realtype k1, k2, k3, k4;
+ realtype K, klA, Ks, pCO2, H;
+} *UserData;
+
+static int res(realtype t, N_Vector yy, N_Vector yd, N_Vector res, void *userdata);
+
+static int rhsQ(realtype t, N_Vector yy, N_Vector yp,
+ N_Vector qdot, void *user_data);
+
+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, char *funcname, int opt);
+
+/* Main program */
+int main()
+{
+ UserData data;
+ void *mem;
+ N_Vector yy, yp, rr, q;
+ int flag;
+ realtype time, tout, incr;
+ int nout;
+
+ mem = NULL;
+ yy = yp = NULL;
+
+ /* Allocate user data. */
+ data = (UserData) malloc(sizeof(*data));
+
+ /* Fill user's data with the appropriate values for coefficients. */
+ data->k1 = RCONST(18.7);
+ data->k2 = RCONST(0.58);
+ data->k3 = RCONST(0.09);
+ data->k4 = RCONST(0.42);
+ data->K = RCONST(34.4);
+ data->klA = RCONST(3.3);
+ data->Ks = RCONST(115.83);
+ data->pCO2 = RCONST(0.9);
+ data->H = RCONST(737.0);
+
+ /* Allocate N-vectors. */
+ yy = N_VNew_Serial(NEQ);
+ if (check_flag((void *)yy, "N_VNew_Serial", 0)) return(1);
+ 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);
+
+ /* Get y' = - res(t0, y, 0) */
+ N_VConst(ZERO, yp);
+
+ rr = N_VNew_Serial(NEQ);
+ res(T0, yy, yp, rr, data);
+ N_VScale(-ONE, rr, yp);
+ N_VDestroy_Serial(rr);
+
+ /* Create and initialize q0 for quadratures. */
+ q = N_VNew_Serial(1);
+ if (check_flag((void *)q, "N_VNew_Serial", 0)) return(1);
+ Ith(q,1) = ZERO;
+
+ /* Call IDACreate and IDAInit to initialize IDA memory */
+ mem = IDACreate();
+ if(check_flag((void *)mem, "IDACreate", 0)) return(1);
+
+ flag = IDAInit(mem, res, T0, yy, yp);
+ if(check_flag(&flag, "IDAInit", 1)) return(1);
+
+
+ /* Set tolerances. */
+ flag = IDASStolerances(mem, RTOL, ATOL);
+ if(check_flag(&flag, "IDASStolerances", 1)) return(1);
+
+ /* Attach user data. */
+ flag = IDASetUserData(mem, data);
+ if(check_flag(&flag, "IDASetUserData", 1)) return(1);
+
+ /* Attach linear solver. */
+ flag = IDADense(mem, NEQ);
+
+ /* Initialize QUADRATURE(S). */
+ flag = IDAQuadInit(mem, rhsQ, q);
+ if (check_flag(&flag, "IDAQuadInit", 1)) return(1);
+
+ /* Set tolerances and error control for quadratures. */
+ flag = IDAQuadSStolerances(mem, RTOLQ, ATOLQ);
+ if (check_flag(&flag, "IDAQuadSStolerances", 1)) return(1);
+
+ flag = IDASetQuadErrCon(mem, TRUE);
+ if (check_flag(&flag, "IDASetQuadErrCon", 1)) return(1);
+
+ PrintHeader(RTOL, ATOL, yy);
+ /* Print initial states */
+ PrintOutput(mem,0.0,yy);
+
+ tout = T1; nout = 0;
+ incr = RPowerR(TF/T1,ONE/NF);
+
+ /* FORWARD run. */
+ while (1) {
+
+ flag = IDASolve(mem, tout, &time, yy, yp, IDA_NORMAL);
+ if (check_flag(&flag, "IDASolve", 1)) return(1);
+
+ PrintOutput(mem, time, yy);
+
+ nout++;
+ tout *= incr;
+
+ if (nout>NF) break;
+ }
+
+ flag = IDAGetQuad(mem, &time, q);
+ if (check_flag(&flag, "IDAGetQuad", 1)) return(1);
+
+ printf("\n--------------------------------------------------------\n");
+ printf("G: %24.16f \n",Ith(q,1));
+ printf("--------------------------------------------------------\n\n");
+
+ PrintFinalStats(mem);
+
+ IDAFree(&mem);
+
+ N_VDestroy_Serial(yy);
+ N_VDestroy_Serial(yp);
+ N_VDestroy_Serial(q);
+
+ return(0);
+}
+
+
+static int res(realtype t, N_Vector yy, N_Vector yd, N_Vector res, void *userdata)
+{
+ UserData data;
+ realtype k1, k2, k3, k4;
+ realtype K, klA, Ks, pCO2, H;
+
+ realtype y1, y2, y3, y4, y5, y6;
+ realtype yd1, yd2, yd3, yd4, yd5;
+
+ realtype r1, r2, r3, r4, r5, Fin;
+
+ data = (UserData) userdata;
+ k1 = data->k1;
+ k2 = data->k2;
+ k3 = data->k3;
+ k4 = data->k4;
+ K = data->K;
+ klA = data->klA;
+ Ks = data->Ks;
+ pCO2 = data->pCO2;
+ H = data->H;
+
+ y1 = Ith(yy,1);
+ y2 = Ith(yy,2);
+ y3 = Ith(yy,3);
+ y4 = Ith(yy,4);
+ y5 = Ith(yy,5);
+ y6 = Ith(yy,6);
+
+ yd1 = Ith(yd,1);
+ yd2 = Ith(yd,2);
+ yd3 = Ith(yd,3);
+ yd4 = Ith(yd,4);
+ yd5 = Ith(yd,5);
+
+ r1 = k1 * RPowerI(y1,4) * RSqrt(y2);
+ r2 = k2 * y3 * y4;
+ r3 = k2/K * y1 * y5;
+ r4 = k3 * y1 * y4 * y4;
+ r5 = k4 * y6 * y6 * RSqrt(y2);
+ Fin = klA * ( pCO2/H - y2 );
+
+ Ith(res,1) = yd1 + TWO*r1 - r2 + r3 + r4;
+ Ith(res,2) = yd2 + HALF*r1 + r4 + HALF*r5 - Fin;
+ Ith(res,3) = yd3 - r1 + r2 - r3;
+ Ith(res,4) = yd4 + r2 - r3 + TWO*r4;
+ Ith(res,5) = yd5 - r2 + r3 - r5;
+ Ith(res,6) = Ks*y1*y4 - y6;
+
+ return(0);
+}
+
+/*
+ * rhsQ routine. Computes quadrature(t,y).
+ */
+
+static int rhsQ(realtype t, N_Vector yy, N_Vector yp, N_Vector qdot, void *user_data)
+{
+ Ith(qdot,1) = Ith(yy,1);
+
+ return(0);
+}
+
+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");
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("Tolerance parameters: rtol = %Lg atol = %Lg\n",
+ rtol, avtol);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("Tolerance parameters: rtol = %lg atol = %lg\n",
+ rtol, avtol);
+#else
+ printf("Tolerance parameters: rtol = %g atol = %g\n",
+ rtol, avtol);
+#endif
+ printf("---------------------------------------------------------------------------------\n");
+ printf(" t y1 y2 y3 y4 y5");
+ printf(" y6 | nst k h\n");
+ printf("---------------------------------------------------------------------------------\n");
+}
+
+
+static void PrintOutput(void *mem, realtype t, N_Vector y)
+{
+ realtype *yval;
+ int retval, kused;
+ long int nst;
+ realtype hused;
+
+ yval = NV_DATA_S(y);
+
+ retval = IDAGetLastOrder(mem, &kused);
+ check_flag(&retval, "IDAGetLastOrder", 1);
+ retval = IDAGetNumSteps(mem, &nst);
+ check_flag(&retval, "IDAGetNumSteps", 1);
+ retval = IDAGetLastStep(mem, &hused);
+ check_flag(&retval, "IDAGetLastStep", 1);
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("%8.2Le %8.2Le %8.2Le %8.2Le %8.2Le %8.2Le %8.2Le | %3ld %1d %8.2Le\n",
+ t, yval[0], yval[1], yval[2], yval[3], yval[4], yval[5], nst, kused, hused);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("%8.2le %8.2le %8.2le %8.2le %8.2le %8.2le %8.2le | %3ld %1d %8.2le\n",
+ t, yval[0], yval[1], yval[2], yval[3], yval[4], yval[5], nst, kused, hused);
+#else
+ printf("%8.2e %8.2e %8.2e %8.2e %8.2e %8.2e %8.2e | %3ld %1d %8.2e\n",
+ t, yval[0], yval[1], yval[2], yval[3], yval[4], yval[5], nst, kused, hused);
+#endif
+}
+
+
+static void PrintFinalStats(void *mem)
+{
+ int flag;
+ long int nst, nni, nje, nre, nreLS, netf, ncfn;
+
+ flag = IDAGetNumSteps(mem, &nst);
+ flag = IDAGetNumResEvals(mem, &nre);
+ flag = IDADlsGetNumJacEvals(mem, &nje);
+ flag = IDAGetNumNonlinSolvIters(mem, &nni);
+ flag = IDAGetNumErrTestFails(mem, &netf);
+ flag = IDAGetNumNonlinSolvConvFails(mem, &ncfn);
+ flag = IDADlsGetNumResEvals(mem, &nreLS);
+
+ 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 Jacobian evaluations = %ld\n", nje);
+ printf("Number of nonlinear iterations = %ld\n", nni);
+ printf("Number of error test failures = %ld\n", netf);
+ 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, 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/idasAkzoNob_dns.out b/examples/idas/serial/idasAkzoNob_dns.out
new file mode 100644
index 0000000..f965973
--- /dev/null
+++ b/examples/idas/serial/idasAkzoNob_dns.out
@@ -0,0 +1,48 @@
+
+idasAkzoNob_dns: Akzo Nobel chemical kinetics DAE serial example problem for IDAS
+Linear solver: IDADENSE, Jacobian is computed by IDAS.
+Tolerance parameters: rtol = 1e-08 atol = 1e-10
+---------------------------------------------------------------------------------
+ t y1 y2 y3 y4 y5 y6 | nst k h
+---------------------------------------------------------------------------------
+0.00e+00 4.44e-01 1.23e-03 0.00e+00 7.00e-03 0.00e+00 3.60e-01 | 0 0 0.00e+00
+1.00e-08 4.44e-01 1.23e-03 2.55e-10 7.00e-03 1.91e-11 3.60e-01 | 15 1 9.23e-09
+2.57e-08 4.44e-01 1.23e-03 6.55e-10 7.00e-03 4.91e-11 3.60e-01 | 16 1 1.85e-08
+6.61e-08 4.44e-01 1.23e-03 1.69e-09 7.00e-03 1.26e-10 3.60e-01 | 17 1 3.69e-08
+1.70e-07 4.44e-01 1.23e-03 4.33e-09 7.00e-03 3.25e-10 3.60e-01 | 19 1 1.48e-07
+4.37e-07 4.44e-01 1.23e-03 1.11e-08 7.00e-03 8.35e-10 3.60e-01 | 20 1 2.95e-07
+1.12e-06 4.44e-01 1.23e-03 2.87e-08 7.00e-03 2.15e-09 3.60e-01 | 21 1 5.90e-07
+2.89e-06 4.44e-01 1.23e-03 7.37e-08 7.00e-03 5.52e-09 3.60e-01 | 23 1 2.36e-06
+7.44e-06 4.44e-01 1.23e-03 1.90e-07 7.00e-03 1.42e-08 3.60e-01 | 25 1 2.36e-06
+1.91e-05 4.44e-01 1.23e-03 4.88e-07 7.00e-03 3.65e-08 3.60e-01 | 28 2 4.72e-06
+4.92e-05 4.44e-01 1.23e-03 1.25e-06 7.00e-03 9.39e-08 3.60e-01 | 30 2 1.89e-05
+1.27e-04 4.44e-01 1.23e-03 3.22e-06 7.00e-03 2.41e-07 3.60e-01 | 32 2 7.56e-05
+3.25e-04 4.44e-01 1.23e-03 8.28e-06 7.00e-03 6.20e-07 3.60e-01 | 34 2 1.51e-04
+8.37e-04 4.44e-01 1.22e-03 2.13e-05 7.00e-03 1.59e-06 3.60e-01 | 37 3 3.02e-04
+2.15e-03 4.44e-01 1.20e-03 5.45e-05 7.00e-03 4.08e-06 3.60e-01 | 41 3 6.05e-04
+5.53e-03 4.44e-01 1.16e-03 1.39e-04 7.00e-03 1.04e-05 3.60e-01 | 45 3 8.45e-04
+1.42e-02 4.43e-01 1.05e-03 3.47e-04 7.00e-03 2.61e-05 3.59e-01 | 52 4 3.38e-03
+3.66e-02 4.42e-01 8.07e-04 8.35e-04 7.00e-03 6.29e-05 3.59e-01 | 58 5 3.38e-03
+9.41e-02 4.40e-01 4.01e-04 1.81e-03 7.00e-03 1.37e-04 3.57e-01 | 69 5 6.76e-03
+2.42e-01 4.37e-01 1.18e-04 3.26e-03 7.00e-03 2.50e-04 3.55e-01 | 91 5 6.76e-03
+6.22e-01 4.32e-01 1.08e-04 5.87e-03 6.99e-03 4.59e-04 3.50e-01 | 132 5 1.35e-02
+1.60e+00 4.19e-01 1.30e-04 1.24e-02 6.96e-03 1.02e-03 3.38e-01 | 150 4 1.08e-01
+4.12e+00 3.87e-01 2.07e-04 2.81e-02 6.77e-03 2.59e-03 3.04e-01 | 165 4 1.42e-01
+1.06e+01 3.21e-01 4.82e-04 6.10e-02 5.86e-03 6.80e-03 2.18e-01 | 194 5 2.84e-01
+2.72e+01 2.32e-01 9.50e-04 1.04e-01 3.07e-03 1.34e-02 8.27e-02 | 279 4 1.52e-01
+7.00e+01 1.62e-01 1.15e-03 1.38e-01 7.40e-04 1.66e-02 1.39e-02 | 375 4 3.60e-01
+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
+--------------------------------------------------------
+
+
+Final Run Statistics:
+
+Number of steps = 500
+Number of residual evaluations = 846
+Number of Jacobian evaluations = 43
+Number of nonlinear iterations = 588
+Number of error test failures = 2
+Number of nonlinear conv. failures = 0
diff --git a/examples/idas/serial/idasFoodWeb_bnd.c b/examples/idas/serial/idasFoodWeb_bnd.c
new file mode 100644
index 0000000..7a59c3a
--- /dev/null
+++ b/examples/idas/serial/idasFoodWeb_bnd.c
@@ -0,0 +1,674 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.2 $
+ * $Date: 2009/09/30 23:33:29 $
+ * -----------------------------------------------------------------
+ * 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
+ * solver, and IDACalcIC for initial condition calculation.
+ *
+ * The mathematical problem solved in this example is a DAE system
+ * that arises from a system of partial differential equations after
+ * spatial discretization. The PDE system is a food web population
+ * model, with predator-prey interaction and diffusion on the unit
+ * square in two dimensions. The dependent variable vector is:
+ *
+ * 1 2 ns
+ * c = (c , c , ..., c ) , ns = 2 * np
+ *
+ * and the PDE's are as follows:
+ *
+ * i i i
+ * dc /dt = d(i)*(c + c ) + R (x,y,c) (i = 1,...,np)
+ * xx yy i
+ *
+ * i i
+ * 0 = d(i)*(c + c ) + R (x,y,c) (i = np+1,...,ns)
+ * xx yy i
+ *
+ * where the reaction terms R are:
+ *
+ * i ns j
+ * R (x,y,c) = c * (b(i) + sum a(i,j)*c )
+ * i j=1
+ *
+ * The number of species is ns = 2 * np, with the first np being
+ * prey and the last np being predators. The coefficients a(i,j),
+ * b(i), d(i) are:
+ *
+ * a(i,i) = -AA (all i)
+ * a(i,j) = -GG (i <= np , j > np)
+ * a(i,j) = EE (i > np, j <= np)
+ * all other a(i,j) = 0
+ * b(i) = BB*(1+ alpha * x*y + beta*sin(4 pi x)*sin(4 pi y)) (i <= np)
+ * b(i) =-BB*(1+ alpha * x*y + beta*sin(4 pi x)*sin(4 pi y)) (i > np)
+ * d(i) = DPREY (i <= np)
+ * d(i) = DPRED (i > np)
+ *
+ * The various scalar parameters required are set using '#define'
+ * statements or directly in routine InitUserData. In this program,
+ * np = 1, ns = 2. The boundary conditions are homogeneous Neumann:
+ * normal derivative = 0.
+ *
+ * A polynomial in x and y is used to set the initial values of the
+ * first np variables (the prey variables) at each x,y location,
+ * while initial values for the remaining (predator) variables are
+ * set to a flat value, which is corrected by IDACalcIC.
+ *
+ * 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.
+ * Output is printed at t = 0, .001, .01, .1, .4, .7, 1.
+ * -----------------------------------------------------------------
+ * References:
+ * [1] Peter N. Brown and Alan C. Hindmarsh,
+ * Reduced Storage Matrix Methods in Stiff ODE systems, Journal
+ * of Applied Mathematics and Computation, Vol. 31 (May 1989),
+ * pp. 40-91.
+ *
+ * [2] Peter N. Brown, Alan C. Hindmarsh, and Linda R. Petzold,
+ * Using Krylov Methods in the Solution of Large-Scale
+ * Differential-Algebraic Systems, SIAM J. Sci. Comput., 15
+ * (1994), pp. 1467-1488.
+ *
+ * [3] Peter N. Brown, Alan C. Hindmarsh, and Linda R. Petzold,
+ * 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>
+
+/* Problem Constants. */
+
+#define NPREY 1 /* No. of prey (= no. of predators). */
+#define NUM_SPECIES 2*NPREY
+
+#define PI RCONST(3.1415926535898)
+#define FOURPI (RCONST(4.0)*PI)
+
+#define MX 20 /* MX = number of x mesh points */
+#define MY 20 /* MY = number of y mesh points */
+#define NSMX (NUM_SPECIES * MX)
+#define NEQ (NUM_SPECIES*MX*MY)
+#define AA RCONST(1.0) /* Coefficient in above eqns. for a */
+#define EE RCONST(10000.) /* Coefficient in above eqns. for a */
+#define GG RCONST(0.5e-6) /* Coefficient in above eqns. for a */
+#define BB RCONST(1.0) /* Coefficient in above eqns. for b */
+#define DPREY RCONST(1.0) /* Coefficient in above eqns. for d */
+#define DPRED RCONST(0.05) /* Coefficient in above eqns. for d */
+#define ALPHA RCONST(50.) /* Coefficient alpha in above eqns. */
+#define BETA RCONST(1000.) /* Coefficient beta in above eqns. */
+#define AX RCONST(1.0) /* Total range of x variable */
+#define AY RCONST(1.0) /* Total range of y variable */
+#define RTOL RCONST(1.e-5) /* Relative tolerance */
+#define ATOL RCONST(1.e-5) /* Absolute tolerance */
+#define NOUT 6 /* Number of output times */
+#define TMULT RCONST(10.0) /* Multiplier for tout values */
+#define TADD RCONST(0.3) /* Increment for tout values */
+#define ZERO RCONST(0.)
+#define ONE RCONST(1.0)
+
+/*
+ * User-defined vector and accessor macro: IJ_Vptr.
+ * IJ_Vptr is defined in order to express the underlying 3-D structure of
+ * the dependent variable vector from its underlying 1-D storage (an N_Vector).
+ * IJ_Vptr(vv,i,j) returns a pointer to the location in vv corresponding to
+ * species index is = 0, x-index ix = i, and y-index jy = j.
+ */
+
+#define IJ_Vptr(vv,i,j) (&NV_Ith_S(vv, (i)*NUM_SPECIES + (j)*NSMX))
+
+/* Type: UserData. Contains problem constants, etc. */
+
+typedef struct {
+ long int Neq, ns, np, mx, my;
+ realtype dx, dy, **acoef;
+ realtype cox[NUM_SPECIES], coy[NUM_SPECIES], bcoef[NUM_SPECIES];
+ N_Vector rates;
+} *UserData;
+
+/* Prototypes for functions called by the IDA Solver. */
+
+static int resweb(realtype time, N_Vector cc, N_Vector cp, N_Vector resval,
+ 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 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 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 int check_flag(void *flagvalue, char *funcname, int opt);
+
+/*
+ *--------------------------------------------------------------------
+ * MAIN PROGRAM
+ *--------------------------------------------------------------------
+ */
+
+int main()
+{
+ void *mem;
+ UserData webdata;
+ N_Vector cc, cp, id;
+ int iout, retval;
+ long int mu, ml;
+ realtype rtol, atol, t0, tout, tret;
+
+ mem = NULL;
+ webdata = NULL;
+ cc = cp = id = NULL;
+
+ /* Allocate and initialize user data block webdata. */
+
+ webdata = (UserData) malloc(sizeof *webdata);
+ webdata->rates = N_VNew_Serial(NEQ);
+ webdata->acoef = newDenseMat(NUM_SPECIES, NUM_SPECIES);
+
+ InitUserData(webdata);
+
+ /* Allocate N-vectors and initialize cc, cp, and id. */
+
+ cc = N_VNew_Serial(NEQ);
+ if(check_flag((void *)cc, "N_VNew_Serial", 0)) return(1);
+
+ cp = N_VNew_Serial(NEQ);
+ if(check_flag((void *)cp, "N_VNew_Serial", 0)) return(1);
+
+ id = N_VNew_Serial(NEQ);
+ if(check_flag((void *)id, "N_VNew_Serial", 0)) return(1);
+
+ SetInitialProfiles(cc, cp, id, webdata);
+
+ /* Set remaining inputs to IDAMalloc. */
+
+ t0 = ZERO;
+ rtol = RTOL;
+ atol = ATOL;
+
+ /* Call IDACreate and IDAMalloc to initialize IDA. */
+
+ mem = IDACreate();
+ if(check_flag((void *)mem, "IDACreate", 0)) return(1);
+
+ retval = IDASetUserData(mem, webdata);
+ if(check_flag(&retval, "IDASetUserData", 1)) return(1);
+
+ retval = IDASetId(mem, id);
+ if(check_flag(&retval, "IDASetId", 1)) return(1);
+
+ retval = IDAInit(mem, resweb, t0, cc, cp);
+ if(check_flag(&retval, "IDAInit", 1)) return(1);
+
+ retval = IDASStolerances(mem, rtol, atol);
+ if(check_flag(&retval, "IDASStolerances", 1)) return(1);
+
+ /* Call IDABand to specify the IDA linear solver. */
+
+ mu = ml = NSMX;
+ retval = IDABand(mem, NEQ, mu, ml);
+ if(check_flag(&retval, "IDABand", 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);
+ if(check_flag(&retval, "IDACalcIC", 1)) return(1);
+
+ /* Print heading, basic parameters, and initial values. */
+
+ PrintHeader(mu, ml, rtol, atol);
+ PrintOutput(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);
+ if(check_flag(&retval, "IDASolve", 1)) return(retval);
+
+ PrintOutput(mem, cc, tret);
+
+ if (iout < 3) tout *= TMULT; else tout += TADD;
+
+ }
+
+ /* Print final statistics and free memory. */
+
+ PrintFinalStats(mem);
+
+ /* Free memory */
+
+ IDAFree(&mem);
+
+ N_VDestroy_Serial(cc);
+ N_VDestroy_Serial(cp);
+ N_VDestroy_Serial(id);
+
+
+ destroyMat(webdata->acoef);
+ N_VDestroy_Serial(webdata->rates);
+ free(webdata);
+
+ return(0);
+}
+
+/* Define lines for readability in later routines */
+
+#define acoef (webdata->acoef)
+#define bcoef (webdata->bcoef)
+#define cox (webdata->cox)
+#define coy (webdata->coy)
+
+/*
+ *--------------------------------------------------------------------
+ * FUNCTIONS CALLED BY IDA
+ *--------------------------------------------------------------------
+ */
+
+/*
+ * resweb: System residual function for predator-prey system.
+ * This routine calls Fweb to get all the right-hand sides of the
+ * equations, then loads the residual vector accordingly,
+ * using cp in the case of prey species.
+ */
+
+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;
+ realtype *resv, *cpv;
+ UserData webdata;
+
+ webdata = (UserData)user_data;
+
+ cpv = NV_DATA_S(cp);
+ resv = NV_DATA_S(res);
+ np = webdata->np;
+
+ /* Call Fweb to set res to vector of right-hand sides. */
+ Fweb(tt, cc, res, webdata);
+
+ /* Loop over all grid points, setting residual values appropriately
+ for differential or algebraic components. */
+
+ for (jy = 0; jy < MY; jy++) {
+ yloc = NSMX * jy;
+ for (jx = 0; jx < MX; jx++) {
+ loc = yloc + NUM_SPECIES * jx;
+ for (is = 0; is < NUM_SPECIES; is++) {
+ if (is < np)
+ resv[loc+is] = cpv[loc+is] - resv[loc+is];
+ else
+ resv[loc+is] = -resv[loc+is];
+ }
+ }
+ }
+
+ return(0);
+
+}
+
+/*
+ *--------------------------------------------------------------------
+ * PRIVATE FUNCTIONS
+ *--------------------------------------------------------------------
+ */
+
+/*
+ * InitUserData: Load problem constants in webdata (of type UserData).
+ */
+
+static void InitUserData(UserData webdata)
+{
+ int i, j, np;
+ realtype *a1,*a2, *a3, *a4, dx2, dy2;
+
+ webdata->mx = MX;
+ webdata->my = MY;
+ webdata->ns = NUM_SPECIES;
+ webdata->np = NPREY;
+ webdata->dx = AX/(MX-1);
+ webdata->dy = AY/(MY-1);
+ webdata->Neq= NEQ;
+
+ /* Set up the coefficients a and b, and others found in the equations. */
+ np = webdata->np;
+ dx2 = (webdata->dx)*(webdata->dx); dy2 = (webdata->dy)*(webdata->dy);
+
+ for (i = 0; i < np; i++) {
+ a1 = &(acoef[i][np]);
+ a2 = &(acoef[i+np][0]);
+ a3 = &(acoef[i][0]);
+ a4 = &(acoef[i+np][np]);
+ /* Fill in the portion of acoef in the four quadrants, row by row. */
+ for (j = 0; j < np; j++) {
+ *a1++ = -GG;
+ *a2++ = EE;
+ *a3++ = ZERO;
+ *a4++ = ZERO;
+ }
+
+ /* Reset the diagonal elements of acoef to -AA. */
+ acoef[i][i] = -AA; acoef[i+np][i+np] = -AA;
+
+ /* Set coefficients for b and diffusion terms. */
+ bcoef[i] = BB; bcoef[i+np] = -BB;
+ cox[i] = DPREY/dx2; cox[i+np] = DPRED/dx2;
+ coy[i] = DPREY/dy2; coy[i+np] = DPRED/dy2;
+ }
+
+}
+
+/*
+ * SetInitialProfiles: Set initial conditions in cc, cp, and id.
+ * A polynomial profile is used for the prey cc values, and a constant
+ * (1.0e5) is loaded as the initial guess for the predator cc values.
+ * The id values are set to 1 for the prey and 0 for the predators.
+ * The prey cp values are set according to the given system, and
+ * the predator cp values are set to zero.
+ */
+
+static void SetInitialProfiles(N_Vector cc, N_Vector cp, N_Vector id,
+ UserData webdata)
+{
+ long int loc, yloc, is, jx, jy, np;
+ realtype xx, yy, xyfactor, fac;
+ realtype *ccv, *cpv, *idv;
+
+ ccv = NV_DATA_S(cc);
+ cpv = NV_DATA_S(cp);
+ idv = NV_DATA_S(id);
+ np = webdata->np;
+
+ /* Loop over grid, load cc values and id values. */
+ for (jy = 0; jy < MY; jy++) {
+ yy = jy * webdata->dy;
+ yloc = NSMX * jy;
+ for (jx = 0; jx < MX; jx++) {
+ xx = jx * webdata->dx;
+ xyfactor = RCONST(16.0)*xx*(ONE-xx)*yy*(ONE-yy);
+ 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;
+ idv[loc+is] = ONE;
+ }
+ else {
+ ccv[loc+is] = RCONST(1.0e5);
+ idv[loc+is] = ZERO;
+ }
+ }
+ }
+ }
+
+ /* Set c' for the prey by calling the function Fweb. */
+ Fweb(ZERO, cc, cp, webdata);
+
+ /* Set c' for predators to 0. */
+ for (jy = 0; jy < MY; jy++) {
+ yloc = NSMX * jy;
+ for (jx = 0; jx < MX; jx++) {
+ loc = yloc + NUM_SPECIES * jx;
+ for (is = np; is < NUM_SPECIES; is++) {
+ cpv[loc+is] = ZERO;
+ }
+ }
+ }
+}
+
+/*
+ * Print first lines of output (problem description)
+ */
+
+static void PrintHeader(long int mu, long int 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);
+ printf(" Mesh dimensions: %d x %d", MX, MY);
+ printf(" System size: %d\n", NEQ);
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("Tolerance parameters: rtol = %Lg atol = %Lg\n", rtol, atol);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("Tolerance parameters: rtol = %lg atol = %lg\n", rtol, 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("CalcIC called to correct initial predator concentrations.\n\n");
+ printf("-----------------------------------------------------------\n");
+ printf(" t bottom-left top-right");
+ printf(" | nst k h\n");
+ printf("-----------------------------------------------------------\n\n");
+
+}
+
+/*
+ * PrintOutput: Print output values at output time t = tt.
+ * Selected run statistics are printed. Then values of the concentrations
+ * are printed for the bottom left and top right grid points only.
+ */
+
+static void PrintOutput(void *mem, N_Vector c, realtype t)
+{
+ int i, kused, flag;
+ long int nst;
+ realtype *c_bl, *c_tr, hused;
+
+ flag = IDAGetLastOrder(mem, &kused);
+ check_flag(&flag, "IDAGetLastOrder", 1);
+ flag = IDAGetNumSteps(mem, &nst);
+ check_flag(&flag, "IDAGetNumSteps", 1);
+ flag = IDAGetLastStep(mem, &hused);
+ check_flag(&flag, "IDAGetLastStep", 1);
+
+ c_bl = IJ_Vptr(c,0,0);
+ c_tr = IJ_Vptr(c,MX-1,MY-1);
+
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("%8.2Le %12.4Le %12.4Le | %3ld %1d %12.4Le\n",
+ t, c_bl[0], c_tr[1], nst, kused, hused);
+ for (i=1;i<NUM_SPECIES;i++)
+ printf(" %12.4Le %12.4Le |\n",c_bl[i],c_tr[i]);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("%8.2le %12.4le %12.4le | %3ld %1d %12.4le\n",
+ t, c_bl[0], c_tr[1], nst, kused, hused);
+ for (i=1;i<NUM_SPECIES;i++)
+ printf(" %12.4le %12.4le |\n",c_bl[i],c_tr[i]);
+#else
+ printf("%8.2e %12.4e %12.4e | %3ld %1d %12.4e\n",
+ t, c_bl[0], c_tr[1], nst, kused, hused);
+ for (i=1;i<NUM_SPECIES;i++)
+ printf(" %12.4e %12.4e |\n",c_bl[i],c_tr[i]);
+#endif
+
+ printf("\n");
+}
+
+/*
+ * PrintFinalStats: Print final run data contained in iopt.
+ */
+
+static void PrintFinalStats(void *mem)
+{
+ long int nst, nre, nreLS, nni, nje, netf, ncfn;
+ int flag;
+
+ flag = IDAGetNumSteps(mem, &nst);
+ check_flag(&flag, "IDAGetNumSteps", 1);
+ flag = IDAGetNumNonlinSolvIters(mem, &nni);
+ check_flag(&flag, "IDAGetNumNonlinSolvIters", 1);
+ flag = IDAGetNumResEvals(mem, &nre);
+ check_flag(&flag, "IDAGetNumResEvals", 1);
+ flag = IDAGetNumErrTestFails(mem, &netf);
+ check_flag(&flag, "IDAGetNumErrTestFails", 1);
+ flag = IDAGetNumNonlinSolvConvFails(mem, &ncfn);
+ check_flag(&flag, "IDAGetNumNonlinSolvConvFails", 1);
+ flag = IDADlsGetNumJacEvals(mem, &nje);
+ check_flag(&flag, "IDADlsGetNumJacEvals", 1);
+ flag = IDADlsGetNumResEvals(mem, &nreLS);
+ check_flag(&flag, "IDADlsGetNumResEvals", 1);
+
+ printf("-----------------------------------------------------------\n");
+ printf("Final run statistics: \n\n");
+ printf("Number of steps = %ld\n", nst);
+ printf("Number of residual evaluations = %ld\n", nre+nreLS);
+ 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);
+ printf("Number of nonlinear conv. failures = %ld\n", ncfn);
+
+}
+
+/*
+ * Fweb: Rate function for the food-web problem.
+ * This routine computes the right-hand sides of the system equations,
+ * consisting of the diffusion term and interaction term.
+ * The interaction term is computed by the function WebRates.
+ */
+
+static void Fweb(realtype tcalc, N_Vector cc, N_Vector crate,
+ UserData webdata)
+{
+ long int 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),
+ form diffusion difference terms, and load crate. */
+
+ for (jy = 0; jy < MY; jy++) {
+ yy = (webdata->dy) * jy ;
+ idyu = (jy!=MY-1) ? NSMX : -NSMX;
+ idyl = (jy!= 0 ) ? NSMX : -NSMX;
+
+ for (jx = 0; jx < MX; jx++) {
+ xx = (webdata->dx) * jx;
+ idxu = (jx!= MX-1) ? NUM_SPECIES : -NUM_SPECIES;
+ idxl = (jx!= 0 ) ? NUM_SPECIES : -NUM_SPECIES;
+ cxy = IJ_Vptr(cc,jx,jy);
+ ratesxy = IJ_Vptr(webdata->rates,jx,jy);
+ cratexy = IJ_Vptr(crate,jx,jy);
+
+ /* Get interaction vector at this grid point. */
+ WebRates(xx, yy, cxy, ratesxy, webdata);
+
+ /* Loop over species, do differencing, load crate segment. */
+ for (is = 0; is < NUM_SPECIES; is++) {
+
+ /* Differencing in y. */
+ dcyli = *(cxy+is) - *(cxy - idyl + is) ;
+ dcyui = *(cxy + idyu + is) - *(cxy+is);
+
+ /* Differencing in x. */
+ dcxli = *(cxy+is) - *(cxy - idxl + is);
+ dcxui = *(cxy + idxu +is) - *(cxy+is);
+
+ /* Compute the crate values at (xx,yy). */
+ cratexy[is] = coy[is] * (dcyui - dcyli) +
+ cox[is] * (dcxui - dcxli) + ratesxy[is];
+
+ } /* End is loop */
+ } /* End of jx loop */
+ } /* End of jy loop */
+
+}
+
+/*
+ * WebRates: Evaluate reaction rates at a given spatial point.
+ * At a given (x,y), evaluate the array of ns reaction terms R.
+ */
+
+static void WebRates(realtype xx, realtype yy, realtype *cxy, realtype *ratesxy,
+ UserData webdata)
+{
+ int is;
+ realtype fac;
+
+ for (is = 0; is < NUM_SPECIES; is++)
+ ratesxy[is] = dotprod(NUM_SPECIES, cxy, acoef[is]);
+
+ fac = ONE + ALPHA*xx*yy + BETA*sin(FOURPI*xx)*sin(FOURPI*yy);
+
+ for (is = 0; is < NUM_SPECIES; is++)
+ ratesxy[is] = cxy[is]*( bcoef[is]*fac + ratesxy[is] );
+
+}
+
+/*
+ * dotprod: dot product routine for realtype arrays, for use by WebRates.
+ */
+
+static realtype dotprod(long int size, realtype *x1, realtype *x2)
+{
+ long int i;
+ realtype *xx1, *xx2, temp = ZERO;
+
+ xx1 = x1; xx2 = x2;
+ for (i = 0; i < size; i++) temp += (*xx1++) * (*xx2++);
+ return(temp);
+
+}
+
+/*
+ * 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, char *funcname, int opt)
+{
+ int *errflag;
+
+ if (opt == 0 && flagvalue == NULL) {
+ /* Check if SUNDIALS function returned NULL pointer - no memory allocated */
+ 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/idas/serial/idasFoodWeb_bnd.out b/examples/idas/serial/idasFoodWeb_bnd.out
new file mode 100644
index 0000000..ed33113
--- /dev/null
+++ b/examples/idas/serial/idasFoodWeb_bnd.out
@@ -0,0 +1,42 @@
+
+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
+CalcIC called to correct initial predator concentrations.
+
+-----------------------------------------------------------
+ t bottom-left top-right | nst k h
+-----------------------------------------------------------
+
+0.00e+00 1.0000e+01 1.0000e+05 | 0 0 1.6310e-08
+ 1.0000e+05 1.0000e+05 |
+
+1.00e-03 1.0318e+01 1.0822e+05 | 32 4 1.0823e-04
+ 1.0319e+05 1.0822e+05 |
+
+1.00e-02 1.6188e+02 1.9734e+06 | 127 4 1.4203e-04
+ 1.6189e+06 1.9734e+06 |
+
+1.00e-01 2.4019e+02 2.7072e+06 | 235 1 3.9160e-02
+ 2.4019e+06 2.7072e+06 |
+
+4.00e-01 2.4019e+02 2.7072e+06 | 238 1 3.1328e-01
+ 2.4019e+06 2.7072e+06 |
+
+7.00e-01 2.4019e+02 2.7072e+06 | 239 1 6.2657e-01
+ 2.4019e+06 2.7072e+06 |
+
+1.00e+00 2.4019e+02 2.7072e+06 | 239 1 6.2657e-01
+ 2.4019e+06 2.7072e+06 |
+
+-----------------------------------------------------------
+Final run statistics:
+
+Number of steps = 239
+Number of residual evaluations = 3339
+Number of Jacobian evaluations = 36
+Number of nonlinear iterations = 421
+Number of error test failures = 3
+Number of nonlinear conv. failures = 0
diff --git a/examples/idas/serial/idasHeat2D_bnd.c b/examples/idas/serial/idasHeat2D_bnd.c
new file mode 100644
index 0000000..c3f29c6
--- /dev/null
+++ b/examples/idas/serial/idasHeat2D_bnd.c
@@ -0,0 +1,407 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.2 $
+ * $Date: 2009/09/30 23:33:29 $
+ * -----------------------------------------------------------------
+ * 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.
+ *
+ * The DAE system solved is a spatial discretization of the PDE
+ * du/dt = d^2u/dx^2 + d^2u/dy^2
+ * on the unit square. The boundary condition is u = 0 on all edges.
+ * Initial conditions are given by u = 16 x (1 - x) y (1 - y).
+ * The PDE is treated with central differences on a uniform M x M
+ * grid. The values of u at the interior points satisfy ODEs, and
+ * equations u = 0 at the boundaries are appended, to form a DAE
+ * system of size N = M^2. Here M = 10.
+ *
+ * The system is solved with IDA using the banded linear system
+ * solver, half-bandwidths equal to M, and default
+ * difference-quotient 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 <idas/idas.h>
+#include <idas/idas_band.h>
+#include <nvector/nvector_serial.h>
+#include <sundials/sundials_types.h>
+
+/* Problem Constants */
+
+#define NOUT 11
+#define MGRID 10
+#define NEQ MGRID*MGRID
+#define ZERO RCONST(0.0)
+#define ONE RCONST(1.0)
+#define TWO RCONST(2.0)
+#define BVAL RCONST(0.1)
+
+/* Type: UserData */
+
+typedef struct {
+ long int 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);
+
+/* Prototypes of private functions */
+
+static void PrintHeader(realtype rtol, realtype atol);
+static void PrintOutput(void *mem, realtype t, N_Vector u);
+static int SetInitialProfile(UserData data, N_Vector uu, N_Vector up,
+ N_Vector id, N_Vector res);
+
+static int check_flag(void *flagvalue, char *funcname, int opt);
+
+/*
+ *--------------------------------------------------------------------
+ * MAIN PROGRAM
+ *--------------------------------------------------------------------
+ */
+
+int main(void)
+{
+ void *mem;
+ UserData data;
+ N_Vector uu, up, constraints, id, res;
+ int ier, iout;
+ long int mu, ml, netf, ncfn;
+ realtype rtol, atol, t0, t1, tout, tret;
+
+ mem = NULL;
+ data = NULL;
+ uu = up = constraints = id = res = NULL;
+
+ /* Create vectors uu, up, res, constraints, id. */
+ uu = N_VNew_Serial(NEQ);
+ if(check_flag((void *)uu, "N_VNew_Serial", 0)) return(1);
+ up = N_VNew_Serial(NEQ);
+ if(check_flag((void *)up, "N_VNew_Serial", 0)) return(1);
+ res = N_VNew_Serial(NEQ);
+ 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);
+ if(check_flag((void *)id, "N_VNew_Serial", 0)) return(1);
+
+ /* Create and load problem data block. */
+ data = (UserData) malloc(sizeof *data);
+ if(check_flag((void *)data, "malloc", 2)) return(1);
+ data->mm = MGRID;
+ data->dx = ONE/(MGRID - ONE);
+ data->coeff = ONE/( (data->dx) * (data->dx) );
+
+ /* Initialize uu, up, id. */
+ SetInitialProfile(data, uu, up, id, res);
+
+ /* Set constraints to all 1's for nonnegative solution values. */
+ N_VConst(ONE, constraints);
+
+ /* Set remaining input parameters. */
+ t0 = ZERO;
+ t1 = RCONST(0.01);
+ rtol = ZERO;
+ atol = RCONST(1.0e-3);
+
+ /* Call IDACreate and IDAMalloc to initialize solution */
+ mem = IDACreate();
+ if(check_flag((void *)mem, "IDACreate", 0)) return(1);
+
+ ier = IDASetUserData(mem, data);
+ if(check_flag(&ier, "IDASetUserData", 1)) return(1);
+
+ 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);
+
+ ier = IDAInit(mem, heatres, t0, uu, up);
+ if(check_flag(&ier, "IDAInit", 1)) return(1);
+
+ ier = IDASStolerances(mem, rtol, atol);
+ if(check_flag(&ier, "IDASStolerances", 1)) return(1);
+
+ /* Call IDABand to specify the linear solver. */
+ mu = MGRID; ml = MGRID;
+ ier = IDABand(mem, NEQ, mu, ml);
+ if(check_flag(&ier, "IDABand", 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);
+
+ /* Print output heading. */
+ PrintHeader(rtol, atol);
+
+ PrintOutput(mem, t0, uu);
+
+
+ /* Loop over output times, call IDASolve, and print results. */
+
+ for (tout = t1, iout = 1; iout <= NOUT; iout++, tout *= TWO) {
+
+ ier = IDASolve(mem, tout, &tret, uu, up, IDA_NORMAL);
+ if(check_flag(&ier, "IDASolve", 1)) return(1);
+
+ PrintOutput(mem, tret, uu);
+
+ }
+
+ /* Print remaining counters and free memory. */
+ ier = IDAGetNumErrTestFails(mem, &netf);
+ check_flag(&ier, "IDAGetNumErrTestFails", 1);
+ ier = IDAGetNumNonlinSolvConvFails(mem, &ncfn);
+ check_flag(&ier, "IDAGetNumNonlinSolvConvFails", 1);
+ 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);
+ free(data);
+
+ return(0);
+}
+
+/*
+ *--------------------------------------------------------------------
+ * FUNCTIONS CALLED BY KINSOL
+ *--------------------------------------------------------------------
+ */
+
+/*
+ * heatres: heat equation system residual function
+ * This uses 5-point central differencing on the interior points, and
+ * includes algebraic equations for the boundary values.
+ * So for each interior point, the residual component has the form
+ * res_i = u'_i - (central difference)_i
+ * while for each boundary point, it is res_i = u_i.
+ */
+
+int heatres(realtype tres, N_Vector uu, N_Vector up, N_Vector resval,
+ void *user_data)
+{
+ long int mm, i, j, offset, loc;
+ realtype *uv, *upv, *resv, coeff;
+ UserData data;
+
+ uv = NV_DATA_S(uu); upv = NV_DATA_S(up); resv = NV_DATA_S(resval);
+
+ data = (UserData)user_data;
+ mm = data->mm;
+ coeff = data->coeff;
+
+ /* Initialize resval to uu, to take care of boundary equations. */
+ N_VScale(ONE, uu, resval);
+
+ /* Loop over interior points; set res = up - (central difference). */
+ for (j = 1; j < mm-1; j++) {
+ offset = mm*j;
+ for (i = 1; i < mm-1; i++) {
+ loc = offset + i;
+ resv[loc] = upv[loc] - coeff *
+ (uv[loc-1] + uv[loc+1] + uv[loc-mm] + uv[loc+mm] - RCONST(4.0)*uv[loc]);
+ }
+ }
+
+ return(0);
+
+}
+
+/*
+ *--------------------------------------------------------------------
+ * PRIVATE FUNCTIONS
+ *--------------------------------------------------------------------
+ */
+
+/*
+ * SetInitialProfile: routine to initialize u, up, and id vectors.
+ */
+
+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;
+
+ mm = data->mm;
+ mm1 = mm - 1;
+
+ udata = NV_DATA_S(uu);
+ updata = NV_DATA_S(up);
+ iddata = NV_DATA_S(id);
+
+ /* Initialize id to 1's. */
+ N_VConst(ONE, id);
+
+ /* Initialize uu on all grid points. */
+ for (j = 0; j < mm; j++) {
+ yfact = data->dx * j;
+ offset = mm*j;
+ for (i = 0;i < mm; i++) {
+ xfact = data->dx * i;
+ loc = offset + i;
+ udata[loc] = RCONST(16.0) * xfact * (ONE - xfact) * yfact * (ONE - yfact);
+ }
+ }
+
+ /* Initialize up vector to 0. */
+ N_VConst(ZERO, up);
+
+ /* heatres sets res to negative of ODE RHS values at interior points. */
+ heatres(ZERO, uu, up, res, data);
+
+ /* Copy -res into up to get correct interior initial up values. */
+ N_VScale(-ONE, res, up);
+
+ /* Finally, set values of u, up, and id at boundary points. */
+ for (j = 0; j < mm; j++) {
+ offset = mm*j;
+ for (i = 0;i < mm; i++) {
+ loc = offset + i;
+ if (j == 0 || j == mm1 || i == 0 || i == mm1 ) {
+ udata[loc] = BVAL; updata[loc] = ZERO; iddata[loc] = ZERO; }
+ }
+ }
+
+ return(0);
+
+}
+
+/*
+ * Print first lines of output (problem description)
+ */
+
+static void PrintHeader(realtype rtol, realtype atol)
+{
+ printf("\nidasHeat2D_bnd: Heat equation, serial 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", MGRID, MGRID);
+ printf(" Total system size: %d\n\n", NEQ);
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("Tolerance parameters: rtol = %Lg atol = %Lg\n", rtol, atol);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("Tolerance parameters: rtol = %lg atol = %lg\n", rtol, atol);
+#else
+ 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(" difference quotient Jacobian, half-bandwidths = %d \n",MGRID);
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("IDACalcIC called with input boundary values = %Lg \n",BVAL);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("IDACalcIC called with input boundary values = %lg \n",BVAL);
+#else
+ printf("IDACalcIC called with input boundary values = %g \n",BVAL);
+#endif
+ /* Print output table heading and initial line of table. */
+ printf("\n Output Summary (umax = max-norm of solution) \n\n");
+ printf(" time umax k nst nni nje nre nreLS h \n" );
+ printf(" . . . . . . . . . . . . . . . . . . . . . \n");
+}
+
+/*
+ * Print Output
+ */
+
+static void PrintOutput(void *mem, realtype t, N_Vector uu)
+{
+ int ier;
+ realtype umax, hused;
+ long int nst, nni, nje, nre, nreLS;
+ int kused;
+
+ umax = N_VMaxNorm(uu);
+
+ ier = IDAGetLastOrder(mem, &kused);
+ check_flag(&ier, "IDAGetLastOrder", 1);
+ ier = IDAGetNumSteps(mem, &nst);
+ check_flag(&ier, "IDAGetNumSteps", 1);
+ ier = IDAGetNumNonlinSolvIters(mem, &nni);
+ check_flag(&ier, "IDAGetNumNonlinSolvIters", 1);
+ ier = IDAGetNumResEvals(mem, &nre);
+ check_flag(&ier, "IDAGetNumResEvals", 1);
+ ier = IDAGetLastStep(mem, &hused);
+ check_flag(&ier, "IDAGetLastStep", 1);
+ ier = IDADlsGetNumJacEvals(mem, &nje);
+ check_flag(&ier, "IDADlsGetNumJacEvals", 1);
+ ier = IDADlsGetNumResEvals(mem, &nreLS);
+ check_flag(&ier, "IDADlsGetNumResEvals", 1);
+
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf(" %5.2Lf %13.5Le %d %3ld %3ld %3ld %4ld %4ld %9.2Le \n",
+ t, umax, kused, nst, nni, nje, nre, nreLS, hused);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf(" %5.2f %13.5le %d %3ld %3ld %3ld %4ld %4ld %9.2le \n",
+ t, umax, kused, nst, nni, nje, nre, nreLS, hused);
+#else
+ printf(" %5.2f %13.5e %d %3ld %3ld %3ld %4ld %4ld %9.2e \n",
+ t, umax, kused, nst, nni, nje, nre, nreLS, hused);
+#endif
+
+}
+
+/*
+ * 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, 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/idas/serial/idasHeat2D_bnd.out b/examples/idas/serial/idasHeat2D_bnd.out
new file mode 100644
index 0000000..368673a
--- /dev/null
+++ b/examples/idas/serial/idasHeat2D_bnd.out
@@ -0,0 +1,30 @@
+
+idasHeat2D_bnd: Heat equation, serial 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
+
+Tolerance parameters: rtol = 0 atol = 0.001
+Constraints set to force all solution components >= 0.
+Linear solver: IDABAND, banded direct solver
+ difference quotient Jacobian, half-bandwidths = 10
+IDACalcIC called with input boundary values = 0.1
+
+ Output Summary (umax = max-norm of solution)
+
+ 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
+
+ netf = 0, ncfn = 0
diff --git a/examples/idas/serial/idasHeat2D_kry.c b/examples/idas/serial/idasHeat2D_kry.c
new file mode 100644
index 0000000..986e0d9
--- /dev/null
+++ b/examples/idas/serial/idasHeat2D_kry.c
@@ -0,0 +1,550 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.2 $
+ * $Date: 2009/09/30 23:33:29 $
+ * -----------------------------------------------------------------
+ * 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.
+ *
+ * The DAE system solved is a spatial discretization of the PDE
+ * du/dt = d^2u/dx^2 + d^2u/dy^2
+ * on the unit square. The boundary condition is u = 0 on all edges.
+ * Initial conditions are given by u = 16 x (1 - x) y (1 - y). The
+ * PDE is treated with central differences on a uniform M x M grid.
+ * The values of u at the interior points satisfy ODEs, and
+ * equations u = 0 at the boundaries are appended, to form a DAE
+ * 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
+ * Jacobian only. Routines for preconditioning, required by
+ * IDASPGMR, 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.
+ * -----------------------------------------------------------------
+ */
+
+#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>
+
+/* Problem Constants */
+
+#define NOUT 11
+#define MGRID 10
+#define NEQ MGRID*MGRID
+#define ZERO RCONST(0.0)
+#define ONE RCONST(1.0)
+#define TWO RCONST(2.0)
+#define FOUR RCONST(4.0)
+
+/* User data type */
+
+typedef struct {
+ long int mm; /* number of grid points */
+ realtype dx;
+ realtype coeff;
+ N_Vector pp; /* vector of prec. diag. elements */
+} *UserData;
+
+/* Prototypes for functions called by IDA */
+
+int resHeat(realtype tres, N_Vector uu, N_Vector up,
+ N_Vector resval, void *user_data);
+
+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);
+
+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);
+
+/* Prototypes for private functions */
+
+static int SetInitialProfile(UserData data, N_Vector uu, N_Vector up,
+ N_Vector res);
+static void PrintHeader(realtype rtol, realtype atol);
+static void PrintOutput(void *mem, realtype t, N_Vector uu);
+static int check_flag(void *flagvalue, char *funcname, int opt);
+
+/*
+ *--------------------------------------------------------------------
+ * MAIN PROGRAM
+ *--------------------------------------------------------------------
+ */
+
+int main()
+{
+ void *mem;
+ UserData data;
+ N_Vector uu, up, constraints, res;
+ int ier, iout;
+ realtype rtol, atol, t0, t1, tout, tret;
+ long int netf, ncfn, ncfl;
+
+ mem = NULL;
+ data = NULL;
+ uu = up = constraints = res = NULL;
+
+ /* Allocate N-vectors and the user data structure. */
+
+ uu = N_VNew_Serial(NEQ);
+ if(check_flag((void *)uu, "N_VNew_Serial", 0)) return(1);
+
+ up = N_VNew_Serial(NEQ);
+ if(check_flag((void *)up, "N_VNew_Serial", 0)) return(1);
+
+ res = N_VNew_Serial(NEQ);
+ 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);
+
+ data = (UserData) malloc(sizeof *data);
+ data->pp = NULL;
+ if(check_flag((void *)data, "malloc", 2)) return(1);
+
+ /* Assign parameters in the user data structure. */
+
+ data->mm = MGRID;
+ data->dx = ONE/(MGRID-ONE);
+ data->coeff = ONE/(data->dx * data->dx);
+ data->pp = N_VNew_Serial(NEQ);
+ if(check_flag((void *)data->pp, "N_VNew_Serial", 0)) return(1);
+
+ /* Initialize uu, up. */
+
+ SetInitialProfile(data, uu, up, res);
+
+ /* Set constraints to all 1's for nonnegative solution values. */
+
+ N_VConst(ONE, constraints);
+
+ /* Assign various parameters. */
+
+ t0 = ZERO;
+ t1 = RCONST(0.01);
+ rtol = ZERO;
+ atol = RCONST(1.0e-3);
+
+ /* Call IDACreate and IDAMalloc to initialize solution */
+
+ mem = IDACreate();
+ if(check_flag((void *)mem, "IDACreate", 0)) return(1);
+
+ ier = IDASetUserData(mem, data);
+ if(check_flag(&ier, "IDASetUserData", 1)) return(1);
+
+ ier = IDASetConstraints(mem, constraints);
+ if(check_flag(&ier, "IDASetConstraints", 1)) return(1);
+ N_VDestroy_Serial(constraints);
+
+ ier = IDAInit(mem, resHeat, t0, uu, up);
+ if(check_flag(&ier, "IDAInit", 1)) return(1);
+
+ ier = IDASStolerances(mem, rtol, atol);
+ if(check_flag(&ier, "IDASStolerances", 1)) return(1);
+
+ /* Call IDASpgmr to specify the linear solver. */
+
+ ier = IDASpgmr(mem, 0);
+ if(check_flag(&ier, "IDASpgmr", 1)) return(1);
+
+ ier = IDASpilsSetPreconditioner(mem, PsetupHeat, PsolveHeat);
+ if(check_flag(&ier, "IDASpilsSetPreconditioner", 1)) return(1);
+
+ /* Print output heading. */
+ PrintHeader(rtol, atol);
+
+ /*
+ * -------------------------------------------------------------------------
+ * CASE I
+ * -------------------------------------------------------------------------
+ */
+
+ /* Print case number, output table heading, and initial line of table. */
+
+ printf("\n\nCase 1: gsytpe = MODIFIED_GS\n");
+ printf("\n Output Summary (umax = max-norm of solution) \n\n");
+ printf(" time umax k nst nni nje nre nreLS h npe nps\n" );
+ printf("----------------------------------------------------------------------\n");
+
+ /* Loop over output times, call IDASolve, and print results. */
+
+ for (tout = t1,iout = 1; iout <= NOUT ; iout++, tout *= TWO) {
+ ier = IDASolve(mem, tout, &tret, uu, up, IDA_NORMAL);
+ if(check_flag(&ier, "IDASolve", 1)) return(1);
+ PrintOutput(mem, tret, uu);
+ }
+
+ /* Print remaining counters. */
+
+ ier = IDAGetNumErrTestFails(mem, &netf);
+ check_flag(&ier, "IDAGetNumErrTestFails", 1);
+
+ ier = IDAGetNumNonlinSolvConvFails(mem, &ncfn);
+ check_flag(&ier, "IDAGetNumNonlinSolvConvFails", 1);
+
+ ier = IDASpilsGetNumConvFails(mem, &ncfl);
+ check_flag(&ier, "IDASpilsGetNumConvFails", 1);
+
+ printf("\nError test failures = %ld\n", netf);
+ printf("Nonlinear convergence failures = %ld\n", ncfn);
+ printf("Linear convergence failures = %ld\n", ncfl);
+
+ /*
+ * -------------------------------------------------------------------------
+ * CASE II
+ * -------------------------------------------------------------------------
+ */
+
+ /* Re-initialize uu, up. */
+
+ SetInitialProfile(data, uu, up, res);
+
+ /* Re-initialize IDA and IDASPGMR */
+
+ 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);
+
+ /* Print case number, output table heading, and initial line of table. */
+
+ printf("\n\nCase 2: gstype = CLASSICAL_GS\n");
+ printf("\n Output Summary (umax = max-norm of solution) \n\n");
+ printf(" time umax k nst nni nje nre nreLS h npe nps\n" );
+ printf("----------------------------------------------------------------------\n");
+
+ /* Loop over output times, call IDASolve, and print results. */
+
+ for (tout = t1,iout = 1; iout <= NOUT ; iout++, tout *= TWO) {
+ ier = IDASolve(mem, tout, &tret, uu, up, IDA_NORMAL);
+ if(check_flag(&ier, "IDASolve", 1)) return(1);
+ PrintOutput(mem, tret, uu);
+ }
+
+ /* Print remaining counters. */
+
+ ier = IDAGetNumErrTestFails(mem, &netf);
+ check_flag(&ier, "IDAGetNumErrTestFails", 1);
+
+ ier = IDAGetNumNonlinSolvConvFails(mem, &ncfn);
+ check_flag(&ier, "IDAGetNumNonlinSolvConvFails", 1);
+
+ ier = IDASpilsGetNumConvFails(mem, &ncfl);
+ check_flag(&ier, "IDASpilsGetNumConvFails", 1);
+
+ printf("\nError test failures = %ld\n", netf);
+ printf("Nonlinear convergence failures = %ld\n", ncfn);
+ printf("Linear convergence failures = %ld\n", ncfl);
+
+ /* Free Memory */
+
+ IDAFree(&mem);
+
+ N_VDestroy_Serial(uu);
+ N_VDestroy_Serial(up);
+ N_VDestroy_Serial(res);
+
+ N_VDestroy_Serial(data->pp);
+ free(data);
+
+ return(0);
+}
+
+/*
+ *--------------------------------------------------------------------
+ * FUNCTIONS CALLED BY IDA
+ *--------------------------------------------------------------------
+ */
+
+/*
+ * resHeat: heat equation system residual function (user-supplied)
+ * This uses 5-point central differencing on the interior points, and
+ * includes algebraic equations for the boundary values.
+ * So for each interior point, the residual component has the form
+ * res_i = u'_i - (central difference)_i
+ * while for each boundary point, it is res_i = u_i.
+ */
+
+int resHeat(realtype tt,
+ N_Vector uu, N_Vector up, N_Vector rr,
+ void *user_data)
+{
+ long int i, j, offset, loc, mm;
+ realtype *uu_data, *up_data, *rr_data, coeff, dif1, dif2;
+ UserData data;
+
+ uu_data = NV_DATA_S(uu);
+ up_data = NV_DATA_S(up);
+ rr_data = NV_DATA_S(rr);
+
+ data = (UserData) user_data;
+
+ coeff = data->coeff;
+ mm = data->mm;
+
+ /* Initialize rr to uu, to take care of boundary equations. */
+ N_VScale(ONE, uu, rr);
+
+ /* Loop over interior points; set res = up - (central difference). */
+ for (j = 1; j < MGRID-1; j++) {
+ offset = mm*j;
+ for (i = 1; i < mm-1; i++) {
+ loc = offset + i;
+ dif1 = uu_data[loc-1] + uu_data[loc+1] - TWO * uu_data[loc];
+ dif2 = uu_data[loc-mm] + uu_data[loc+mm] - TWO * uu_data[loc];
+ rr_data[loc]= up_data[loc] - coeff * ( dif1 + dif2 );
+ }
+ }
+
+ return(0);
+}
+
+/*
+ * PsetupHeat: setup for diagonal preconditioner.
+ *
+ * The optional user-supplied functions PsetupHeat and
+ * PsolveHeat together must define the left preconditoner
+ * matrix P approximating the system Jacobian matrix
+ * J = dF/du + cj*dF/du'
+ * (where the DAE system is F(t,u,u') = 0), and solve the linear
+ * systems P z = r. This is done in this case by keeping only
+ * the diagonal elements of the J matrix above, storing them as
+ * inverses in a vector pp, when computed in PsetupHeat, for
+ * subsequent use in PsolveHeat.
+ *
+ * In this instance, only cj and data (user data structure, with
+ * pp etc.) are used from the PsetupdHeat argument list.
+ */
+
+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)
+{
+
+ long int i, j, offset, loc, mm;
+ realtype *ppv, pelinv;
+ UserData data;
+
+ data = (UserData) user_data;
+ ppv = NV_DATA_S(data->pp);
+ mm = data->mm;
+
+ /* Initialize the entire vector to 1., then set the interior points to the
+ correct value for preconditioning. */
+ N_VConst(ONE,data->pp);
+
+ /* Compute the inverse of the preconditioner diagonal elements. */
+ pelinv = ONE/(c_j + FOUR*data->coeff);
+
+ for (j = 1; j < mm-1; j++) {
+ offset = mm * j;
+ for (i = 1; i < mm-1; i++) {
+ loc = offset + i;
+ ppv[loc] = pelinv;
+ }
+ }
+
+ return(0);
+}
+
+/*
+ * PsolveHeat: solve preconditioner linear system.
+ * This routine multiplies the input vector rvec by the vector pp
+ * containing the inverse diagonal Jacobian elements (previously
+ * computed in PrecondHeateq), 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)
+{
+ UserData data;
+ data = (UserData) user_data;
+ N_VProd(data->pp, rvec, zvec);
+ return(0);
+}
+
+/*
+ *--------------------------------------------------------------------
+ * PRIVATE FUNCTIONS
+ *--------------------------------------------------------------------
+ */
+
+/*
+ * SetInitialProfile: routine to initialize u and up vectors.
+ */
+
+static int SetInitialProfile(UserData data, N_Vector uu, N_Vector up,
+ N_Vector res)
+{
+ long int mm, mm1, i, j, offset, loc;
+ realtype xfact, yfact, *udata, *updata;
+
+ mm = data->mm;
+
+ udata = NV_DATA_S(uu);
+ updata = NV_DATA_S(up);
+
+ /* Initialize uu on all grid points. */
+ mm1 = mm - 1;
+ for (j = 0; j < mm; j++) {
+ yfact = data->dx * j;
+ offset = mm*j;
+ for (i = 0;i < mm; i++) {
+ xfact = data->dx * i;
+ loc = offset + i;
+ udata[loc] = RCONST(16.0) * xfact * (ONE - xfact) * yfact * (ONE - yfact);
+ }
+ }
+
+ /* Initialize up vector to 0. */
+ N_VConst(ZERO, up);
+
+ /* resHeat sets res to negative of ODE RHS values at interior points. */
+ resHeat(ZERO, uu, up, res, data);
+
+ /* Copy -res into up to get correct interior initial up values. */
+ N_VScale(-ONE, res, up);
+
+ /* Set up at boundary points to zero. */
+ for (j = 0; j < mm; j++) {
+ offset = mm*j;
+ for (i = 0; i < mm; i++) {
+ loc = offset + i;
+ if (j == 0 || j == mm1 || i == 0 || i == mm1 ) updata[loc] = ZERO;
+ }
+ }
+
+ return(0);
+ }
+
+/*
+ * Print first lines of output (problem description)
+ */
+
+static void PrintHeader(realtype rtol, realtype atol)
+{
+ printf("\nidasHeat2D_kry: Heat equation, serial 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", MGRID, MGRID);
+ printf(" Total system size: %d\n\n", NEQ);
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("Tolerance parameters: rtol = %Lg atol = %Lg\n", rtol, atol);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("Tolerance parameters: rtol = %lg atol = %lg\n", rtol, atol);
+#else
+ 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");
+}
+
+/*
+ * PrintOutput: print max norm of solution and current solver statistics
+ */
+
+static void PrintOutput(void *mem, realtype t, N_Vector uu)
+{
+ realtype hused, umax;
+ long int nst, nni, nje, nre, nreLS, nli, npe, nps;
+ int kused, ier;
+
+ umax = N_VMaxNorm(uu);
+
+ ier = IDAGetLastOrder(mem, &kused);
+ check_flag(&ier, "IDAGetLastOrder", 1);
+ ier = IDAGetNumSteps(mem, &nst);
+ check_flag(&ier, "IDAGetNumSteps", 1);
+ ier = IDAGetNumNonlinSolvIters(mem, &nni);
+ check_flag(&ier, "IDAGetNumNonlinSolvIters", 1);
+ ier = IDAGetNumResEvals(mem, &nre);
+ check_flag(&ier, "IDAGetNumResEvals", 1);
+ ier = IDAGetLastStep(mem, &hused);
+ check_flag(&ier, "IDAGetLastStep", 1);
+ ier = IDASpilsGetNumJtimesEvals(mem, &nje);
+ check_flag(&ier, "IDASpilsGetNumJtimesEvals", 1);
+ ier = IDASpilsGetNumLinIters(mem, &nli);
+ check_flag(&ier, "IDASpilsGetNumLinIters", 1);
+ ier = IDASpilsGetNumResEvals(mem, &nreLS);
+ check_flag(&ier, "IDASpilsGetNumResEvals", 1);
+ ier = IDASpilsGetNumPrecEvals(mem, &npe);
+ check_flag(&ier, "IDASpilsGetPrecEvals", 1);
+ ier = IDASpilsGetNumPrecSolves(mem, &nps);
+ check_flag(&ier, "IDASpilsGetNumPrecSolves", 1);
+
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf(" %5.2Lf %13.5Le %d %3ld %3ld %3ld %4ld %4ld %9.2Le %3ld %3ld\n",
+ t, umax, kused, nst, nni, nje, nre, nreLS, hused, npe, nps);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf(" %5.2f %13.5le %d %3ld %3ld %3ld %4ld %4ld %9.2le %3ld %3ld\n",
+ t, umax, kused, nst, nni, nje, nre, nreLS, hused, npe, nps);
+#else
+ printf(" %5.2f %13.5e %d %3ld %3ld %3ld %4ld %4ld %9.2e %3ld %3ld\n",
+ t, umax, kused, nst, nni, nje, nre, nreLS, hused, npe, nps);
+#endif
+}
+
+/*
+ * 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, 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/idas/serial/idasHeat2D_kry.out b/examples/idas/serial/idasHeat2D_kry.out
new file mode 100644
index 0000000..74602d7
--- /dev/null
+++ b/examples/idas/serial/idasHeat2D_kry.out
@@ -0,0 +1,55 @@
+
+idasHeat2D_kry: Heat equation, serial 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
+
+Tolerance parameters: rtol = 0 atol = 0.001
+Constraints set to force all solution components >= 0.
+Linear solver: IDASPGMR, preconditioner using diagonal elements.
+
+
+Case 1: gsytpe = MODIFIED_GS
+
+ Output Summary (umax = max-norm of solution)
+
+ time umax k nst nni nje nre nreLS h npe nps
+----------------------------------------------------------------------
+ 0.01 8.24106e-01 2 12 14 7 14 7 2.56e-03 8 21
+ 0.02 6.88134e-01 3 15 18 12 18 12 5.12e-03 8 30
+ 0.04 4.70711e-01 3 18 24 21 24 21 6.58e-03 9 45
+ 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
+
+Error test failures = 1
+Nonlinear convergence failures = 0
+Linear convergence failures = 0
+
+
+Case 2: gstype = CLASSICAL_GS
+
+ Output Summary (umax = max-norm of solution)
+
+ time umax k nst nni nje nre nreLS h npe nps
+----------------------------------------------------------------------
+ 0.01 8.24106e-01 2 12 14 7 14 7 2.56e-03 8 21
+ 0.02 6.88134e-01 3 15 18 12 18 12 5.12e-03 8 30
+ 0.04 4.70711e-01 3 18 24 21 24 21 6.58e-03 9 45
+ 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 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
+
+Error test failures = 1
+Nonlinear convergence failures = 0
+Linear convergence failures = 0
diff --git a/examples/idas/serial/idasHessian_ASA_FSA.c b/examples/idas/serial/idasHessian_ASA_FSA.c
new file mode 100644
index 0000000..85d3c37
--- /dev/null
+++ b/examples/idas/serial/idasHessian_ASA_FSA.c
@@ -0,0 +1,734 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.1 $
+ * $Date: 2007/10/25 20:03:39 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Radu Serban and Cosmin Petra @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2007, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ *
+ * Hessian using adjoint sensitivity example problem.
+ *
+ * This simple example problem for IDAS, due to Robertson,
+ * is from chemical kinetics, and consists of the following three
+ * equations:
+ *
+ * [ y1' + p1 * y1 - p2 * y2 * y3 = 0
+ * [ y2' - p1 * y1 + p2 * y2 * y3 + p3 * y2^2 = 0
+ * [ y1 + y2 + y3 -1 = 0
+ *
+ * [1] [-p1]
+ * y(0)=[0] y'(0)=[ p1] p1 = 0.04 p2 = 1e4 p3 = 1e07
+ * [0] [ 0 ]
+ *
+ * 80
+ * /
+ * G = | 0.5 * (y1^2 + y2^2 + y3^2) dt
+ * /
+ * 0
+ * Compute the gradient (using FSA and ASA) and Hessian (FSA over ASA)
+ * of G with respect to parameters p1 and p2.
+ *
+ * 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>
+
+/* 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 */
+#define NP 2 /* number of sensitivities */
+
+#define T0 RCONST(0.0) /* Initial time. */
+#define TF RCONST(80.0) /* Final time. */
+
+/* Tolerances */
+#define RTOL RCONST(1e-08) /* scalar relative tolerance */
+#define ATOL RCONST(1e-10) /* vector absolute tolerance components */
+#define RTOLA RCONST(1e-08) /* for adjoint integration */
+#define ATOLA RCONST(1e-08) /* for adjoint integration */
+
+/* Parameters */
+#define P1 RCONST(0.04)
+#define P2 RCONST(1.0e4)
+#define P3 RCONST(3.0e7)
+
+/* Predefined consts */
+#define HALF RCONST(0.5)
+#define ZERO RCONST(0.0)
+#define ONE RCONST(1.0)
+#define TWO RCONST(2.0)
+
+/* User defined struct */
+typedef struct {
+ realtype p[3];
+} *UserData;
+
+/* residual for forward problem */
+static int res(realtype t, N_Vector yy, N_Vector yp,
+ N_Vector resval, void *user_data);
+
+static int resS(int Ns, realtype t,
+ N_Vector yy, N_Vector yp, N_Vector resval,
+ N_Vector *yyS, N_Vector *ypS, N_Vector *resvalS,
+ 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);
+
+static int rhsQS(int Ns, realtype t, N_Vector yy, N_Vector yp,
+ N_Vector *yyS, N_Vector *ypS, N_Vector rrQ, N_Vector *rhsQS,
+ void *user_data, N_Vector yytmp, N_Vector yptmp, N_Vector tmpQS);
+
+static int resBS1(realtype tt, N_Vector yy, N_Vector yp, N_Vector *yyS, N_Vector *ypS,
+ N_Vector yyB, N_Vector ypB, N_Vector resvalBQ, void *user_dataB);
+
+
+static int rhsQBS1(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 resBS2(realtype tt, N_Vector yy, N_Vector yp, N_Vector *yyS, N_Vector *ypS,
+ N_Vector yyB, N_Vector ypB, N_Vector resvalBQ, void *user_dataB);
+
+
+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);
+
+
+int main(int argc, char *argv[])
+{
+ N_Vector yy, yp, q, *yyS, *ypS, *qS;
+ N_Vector yyB1, ypB1, qB1, yyB2, ypB2, qB2;
+ void *ida_mem;
+ UserData data;
+ realtype time, ti, tf;
+ 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;
+
+
+ /* Print problem description */
+ printf("\nAdjoint Sensitivity Example for Chemical Kinetics\n");
+ printf("---------------------------------------------------------\n");
+ printf("DAE: dy1/dt + p1*y1 - p2*y2*y3 = 0\n");
+ printf(" dy2/dt - p1*y1 + p2*y2*y3 + p3*(y2)^2 = 0\n");
+ printf(" y1 + y2 + y3 = 0\n\n");
+ printf("Find dG/dp and d^2G/dp^2, where p=[p1,p2] for\n");
+ printf(" G = int_t0^tB0 g(t,p,y) dt\n");
+ printf(" g(t,p,y) = y3\n\n\n");
+
+ /* Alocate and initialize user data. */
+ data = (UserData) malloc(sizeof(*data));
+ data->p[0] = P1; data->p[1] = P2; data->p[2] = P3;
+
+ /* Consistent IC */
+ yy = N_VNew_Serial(NEQ);
+ yp = N_VNew_Serial(NEQ);
+ Ith(yy,1) = ONE; Ith(yy,2) = ZERO; Ith(yy,3) = ZERO;
+ Ith(yp,1) = -P1; Ith(yp,2) = P1; Ith(yp,3) = 0;
+
+ q = N_VNew_Serial(1);
+ N_VConst(ZERO, q);
+
+ yyS = N_VCloneVectorArray_Serial(NP, yy);
+ ypS = N_VCloneVectorArray_Serial(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);
+ N_VConst(ZERO, qS[0]);
+
+ ida_mem = IDACreate();
+
+ ti = T0;
+ flag = IDAInit(ida_mem, res, ti, yy, yp);
+
+ /* Forward problem's setup. */
+ flag = IDASStolerances(ida_mem, RTOL, ATOL);
+ flag = IDADense(ida_mem, NEQ);
+ 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);
+
+ /* Sensitivity's setup. */
+ flag = IDASensInit(ida_mem, NP, IDA_SIMULTANEOUS, resS, yyS, ypS);
+ flag = IDASensEEtolerances(ida_mem);
+ flag = IDASetSensErrCon(ida_mem, TRUE);
+
+ /* Setup of quadrature's sensitivities */
+ flag = IDAQuadSensInit(ida_mem, rhsQS, qS);
+ flag = IDAQuadSensEEtolerances(ida_mem);
+ flag = IDASetQuadSensErrCon(ida_mem, TRUE);
+
+ /* Initialize ASA. */
+ flag = IDAAdjInit(ida_mem, 100, IDA_HERMITE);
+
+ printf("---------------------------------------------------------\n");
+ printf("Forward integration\n");
+ printf("---------------------------------------------------------\n\n");
+
+ tf = TF;
+ flag = IDASolveF(ida_mem, tf, &time, yy, yp, IDA_NORMAL, &nckp);
+
+ IDAGetQuad(ida_mem, &time, q);
+ G = Ith(q,1);
+ printf(" G: %12.4le\n", G);
+
+ /* 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);
+ printf(" dG/dp: %12.4le %12.4le\n", Ith(qS[0],1), Ith(qS[1],1));
+ printf("\n");
+ /******************************
+ * BACKWARD PROBLEM #1
+ *******************************/
+
+ /* Consistent IC. */
+ yyB1 = N_VNew_Serial(2*NEQ);
+ ypB1 = N_VNew_Serial(2*NEQ);
+
+ N_VConst(ZERO, yyB1);
+ Ith(yyB1,3) = Ith(yy,3);
+ Ith(yyB1,6) = Ith(yyS[0], 3);
+
+ N_VConst(ZERO, ypB1);
+ Ith(ypB1,1) = Ith(yy,3)-Ith(yy,1);
+ Ith(ypB1,2) = Ith(yy,3)-Ith(yy,2);
+ Ith(ypB1,4) = Ith(yyS[0],3) - Ith(yyS[0],1);
+ Ith(ypB1,5) = Ith(yyS[0],3) - Ith(yyS[0],2);
+
+ qB1 = N_VNew_Serial(2*NP);
+ N_VConst(ZERO, qB1);
+
+ flag = IDACreateB(ida_mem, &indexB1);
+ flag = IDAInitBS(ida_mem, indexB1, resBS1, tf, yyB1, ypB1);
+ 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);
+ flag = IDAQuadInitBS(ida_mem, indexB1, rhsQBS1, qB1);
+
+ /******************************
+ * BACKWARD PROBLEM #2
+ *******************************/
+
+ /* Consistent IC. */
+ yyB2 = N_VNew_Serial(2*NEQ);
+ ypB2 = N_VNew_Serial(2*NEQ);
+
+ N_VConst(ZERO, yyB2);
+ Ith(yyB2,3) = Ith(yy,3);
+ Ith(yyB2,6) = Ith(yyS[1],3);
+
+ N_VConst(ZERO, ypB2);
+ Ith(ypB2,1) = Ith(yy,3)-Ith(yy,1);
+ Ith(ypB2,2) = Ith(yy,3)-Ith(yy,2);
+ Ith(ypB2,4) = Ith(yyS[1],3) - Ith(yyS[1],1);
+ Ith(ypB2,5) = Ith(yyS[1],3) - Ith(yyS[1],2);
+
+ qB2 = N_VNew_Serial(2*NP);
+ N_VConst(ZERO, qB2);
+
+ flag = IDACreateB(ida_mem, &indexB2);
+ flag = IDAInitBS(ida_mem, indexB2, resBS2, tf, yyB2, ypB2);
+ 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);
+ flag = IDAQuadInitBS(ida_mem, indexB2, rhsQBS2, qB2);
+
+ /* Integrate backward problems. */
+ printf("---------------------------------------------------------\n");
+ printf("Backward integration \n");
+ printf("---------------------------------------------------------\n\n");
+
+ flag = IDASolveB(ida_mem, ti, IDA_NORMAL);
+
+ flag = IDAGetB(ida_mem, indexB1, &time, yyB1, ypB1);
+ //flag = IDAGetNumSteps(IDAGetAdjIDABmem(ida_mem, indexB1), &nst);
+ //printf("at time=%g \tpb 1 Num steps:%d\n", time, nst);
+ //flag = IDAGetNumSteps(IDAGetAdjIDABmem(ida_mem, indexB2), &nst);
+ //printf("at time=%g \tpb 2 Num steps:%d\n\n", time, nst);
+
+ flag = IDAGetQuadB(ida_mem, indexB1, &time, qB1);
+ flag = IDAGetQuadB(ida_mem, indexB2, &time, qB2);
+ 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));
+
+ printf("\n");
+ printf(" H = d2G/dp2:\n");
+ printf(" (1) (2)\n");
+ printf(" %12.4le %12.4le\n", Ith(qB1,3), Ith(qB2,3));
+ printf(" %12.4le %12.4le\n", Ith(qB1,4), Ith(qB2,4));
+
+ IDAFree(&ida_mem);
+
+ /*********************************
+ * Use Finite Differences to verify
+ **********************************/
+
+ /* Perturbations are of different magnitudes as p1 and p2 are. */
+ dp1 = RCONST(1.0e-3);
+ dp2 = RCONST(2.5e+2);
+
+ printf("\n");
+ printf("---------------------------------------------------------\n");
+ printf("Finite Differences ( dp1=%6.1e and dp2 = %6.1e )\n", dp1, dp2);
+ printf("---------------------------------------------------------\n\n");
+
+ ida_mem = IDACreate();
+
+ /********************
+ * Forward FD for p1
+ ********************/
+ data->p[0] += dp1;
+
+ Ith(yy,1) = ONE; Ith(yy,2) = ZERO; Ith(yy,3) = ZERO;
+ Ith(yp,1) = -data->p[0]; Ith(yp,2) = -Ith(yp,1); Ith(yp,3) = 0;
+ N_VConst(ZERO, q);
+ ti = T0;
+ tf = TF;
+
+ flag = IDAInit(ida_mem, res, ti, yy, yp);
+
+ rtolFD = RCONST(1.0e-12);
+ atolFD = RCONST(1.0e-14);
+
+ flag = IDASStolerances(ida_mem, rtolFD, atolFD);
+ flag = IDADense(ida_mem, NEQ);
+ 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 = IDASolve(ida_mem, tf, &time, yy, yp, IDA_NORMAL);
+ flag = IDAGetQuad(ida_mem, &time, q);
+ Gp = Ith(q,1);
+
+ /********************
+ * Backward FD for p1
+ ********************/
+ data->p[0] -= 2*dp1;
+
+ Ith(yy,1) = ONE; Ith(yy,2) = ZERO; Ith(yy,3) = ZERO;
+ Ith(yp,1) = -data->p[0]; Ith(yp,2) = -Ith(yp,1); Ith(yp,3) = 0;
+ N_VConst(ZERO, q);
+
+ flag = IDAReInit(ida_mem, ti, yy, yp);
+ flag = IDAQuadReInit(ida_mem, q);
+
+ flag = IDASolve(ida_mem, tf, &time, yy, yp, IDA_NORMAL);
+ flag = IDAGetQuad(ida_mem, &time, q);
+ Gm = Ith(q,1);
+
+ /* Compute FD for p1. */
+ grdG_fwd[0] = (Gp-G)/dp1;
+ grdG_bck[0] = (G-Gm)/dp1;
+ grdG_cntr[0] = (Gp-Gm)/(2.0*dp1);
+ H11 = (Gp - 2.0*G + Gm) / (dp1*dp1);
+
+ /********************
+ * Forward FD for p2
+ ********************/
+ /*restore p1*/
+ data->p[0] += dp1;
+ data->p[1] += dp2;
+
+ Ith(yy,1) = ONE; Ith(yy,2) = ZERO; Ith(yy,3) = ZERO;
+ Ith(yp,1) = -data->p[0]; Ith(yp,2) = -Ith(yp,1); Ith(yp,3) = 0;
+ N_VConst(ZERO, q);
+
+ flag = IDAReInit(ida_mem, ti, yy, yp);
+ flag = IDAQuadReInit(ida_mem, q);
+
+ flag = IDASolve(ida_mem, tf, &time, yy, yp, IDA_NORMAL);
+ flag = IDAGetQuad(ida_mem, &time, q);
+ Gp = Ith(q,1);
+
+ /********************
+ * Backward FD for p2
+ ********************/
+ data->p[1] -= 2*dp2;
+
+ Ith(yy,1) = ONE; Ith(yy,2) = ZERO; Ith(yy,3) = ZERO;
+ Ith(yp,1) = -data->p[0]; Ith(yp,2) = -Ith(yp,1); Ith(yp,3) = 0;
+ N_VConst(ZERO, q);
+
+ flag = IDAReInit(ida_mem, ti, yy, yp);
+ flag = IDAQuadReInit(ida_mem, q);
+
+ flag = IDASolve(ida_mem, tf, &time, yy, yp, IDA_NORMAL);
+ flag = IDAGetQuad(ida_mem, &time, q);
+ Gm = Ith(q,1);
+
+ /* Compute FD for p2. */
+ grdG_fwd[1] = (Gp-G)/dp2;
+ grdG_bck[1] = (G-Gm)/dp2;
+ grdG_cntr[1] = (Gp-Gm)/(2.0*dp2);
+ H22 = (Gp - 2.0*G + Gm) / (dp2*dp2);
+
+
+ printf("\n");
+ 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);
+
+ IDAFree(&ida_mem);
+
+ N_VDestroy_Serial(yyB1);
+ N_VDestroy_Serial(ypB1);
+ N_VDestroy_Serial(qB1);
+
+ N_VDestroy_Serial(yyB2);
+ N_VDestroy_Serial(ypB2);
+ N_VDestroy_Serial(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);
+
+ free(data);
+ return 0;
+}
+
+
+
+static int res(realtype tres, N_Vector yy, N_Vector yp, N_Vector rr, void *user_data)
+{
+ realtype y1, y2, y3, yp1, yp2, yp3, *rval;
+ UserData data;
+ realtype p1, p2, p3;
+
+ 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 = NV_DATA_S(rr);
+
+ data = (UserData) user_data;
+ p1 = data->p[0]; p2 = data->p[1]; p3 = data->p[2];
+
+ rval[0] = p1*y1-p2*y2*y3;
+ rval[1] = -rval[0] + p3*y2*y2 + yp2;
+ rval[0]+= yp1;
+ rval[2] = y1+y2+y3-1;
+
+ return(0);
+}
+
+static int resS(int Ns, realtype t,
+ N_Vector yy, N_Vector yp, N_Vector resval,
+ N_Vector *yyS, N_Vector *ypS, N_Vector *resvalS,
+ void *user_data,
+ N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
+{
+ UserData data;
+ realtype p1, p2, p3;
+ realtype y1, y2, y3;
+ realtype yp1, yp2, yp3;
+ realtype s1, s2, s3;
+ realtype sd1, sd2, sd3;
+ realtype rs1, rs2, rs3;
+ int is;
+
+ data = (UserData) user_data;
+ p1 = data->p[0];
+ p2 = data->p[1];
+ p3 = data->p[2];
+
+ y1 = Ith(yy,1);
+ y2 = Ith(yy,2);
+ y3 = Ith(yy,3);
+
+ yp1 = Ith(yp,1);
+ yp2 = Ith(yp,2);
+ yp3 = Ith(yp,3);
+
+ for (is=0; is<NP; is++) {
+
+ s1 = Ith(yyS[is],1);
+ s2 = Ith(yyS[is],2);
+ s3 = Ith(yyS[is],3);
+
+ sd1 = Ith(ypS[is],1);
+ sd2 = Ith(ypS[is],2);
+ sd3 = Ith(ypS[is],3);
+
+ rs1 = sd1 + p1*s1 - p2*y3*s2 - p2*y2*s3;
+ rs2 = sd2 - p1*s1 + p2*y3*s2 + p2*y2*s3 + TWO*p3*y2*s2;
+ rs3 = s1 + s2 + s3;
+
+ switch (is) {
+ case 0:
+ rs1 += y1;
+ rs2 -= y1;
+ break;
+ case 1:
+ rs1 -= y2*y3;
+ rs2 += y2*y3;
+ break;
+ }
+
+ Ith(resvalS[is],1) = rs1;
+ Ith(resvalS[is],2) = rs2;
+ Ith(resvalS[is],3) = rs3;
+
+ }
+
+ return(0);
+}
+
+static int rhsQ(realtype t, N_Vector yy, N_Vector yp, N_Vector qdot, void *user_data)
+{
+
+ realtype y1, y2, y3;
+
+ y1 = Ith(yy,1); y2 = Ith(yy,2); y3 = Ith(yy,3);
+ Ith(qdot,1) = HALF*(y1*y1+y2*y2+y3*y3);
+
+ return(0);
+}
+
+static int rhsQS(int Ns, realtype t,
+ N_Vector yy, N_Vector yp,
+ N_Vector *yyS, N_Vector *ypS,
+ N_Vector rrQ, N_Vector *rhsQS,
+ void *user_data,
+ N_Vector yytmp, N_Vector yptmp, N_Vector tmpQS)
+{
+
+ realtype y1, y2, y3;
+ realtype s1, s2, s3;
+
+ y1 = Ith(yy,1);
+ y2 = Ith(yy,2);
+ y3 = Ith(yy,3);
+
+ /* 1st sensitivity RHS */
+ s1 = Ith(yyS[0],1);
+ s2 = Ith(yyS[0],2);
+ s3 = Ith(yyS[0],3);
+ Ith(rhsQS[0],1) = y1*s1 + y2*s2 + y3*s3;
+
+ /* 2nd sensitivity RHS */
+ s1 = Ith(yyS[1],1);
+ s2 = Ith(yyS[1],2);
+ s3 = Ith(yyS[1],3);
+ Ith(rhsQS[1],1) = y1*s1 + y2*s2 + y3*s3;
+
+ return(0);
+}
+
+/* Residuals for adjoint model. */
+static int resBS1(realtype tt,
+ N_Vector yy, N_Vector yp,
+ N_Vector *yyS, N_Vector *ypS,
+ N_Vector yyB, N_Vector ypB,
+ N_Vector rrBS, void *user_dataB)
+
+{
+ UserData data;
+ realtype y1, y2, y3;
+ realtype p1, p2, p3;
+ realtype l1, l2, l3, m1, m2, m3;
+ realtype lp1, lp2, mp1, mp2;
+ realtype s1, s2, s3;
+ realtype l21;
+
+ data = (UserData) user_dataB;
+
+ /* The parameters. */
+ p1 = data->p[0]; p2 = data->p[1]; p3 = data->p[2];
+
+ /* The y vector. */
+ y1 = Ith(yy,1); y2 = Ith(yy,2); y3 = Ith(yy,3);
+
+ /* The lambda vector. */
+ l1 = Ith(yyB,1); l2 = Ith(yyB,2); l3 = Ith(yyB,3);
+ /* The mu vector. */
+ m1 = Ith(yyB,4); m2 = Ith(yyB,5); m3 = Ith(yyB,6);
+
+ /* The lambda dot vector. */
+ lp1 = Ith(ypB,1); lp2 = Ith(ypB,2);
+ /* The mu dot vector. */
+ mp1 = Ith(ypB,4); mp2 = Ith(ypB,5);
+
+ /* The sensitivity with respect to p1 */
+ s1 = Ith(yyS[0],1); s2 = Ith(yyS[0],2); s3 = Ith(yyS[0],3);
+
+ /* Temporary variables */
+ l21 = l2-l1;
+
+ Ith(rrBS,1) = lp1 + p1*l21 - l3 + y1;
+ Ith(rrBS,2) = lp2 - p2*y3*l21 - TWO*p3*y2*l2 - l3 + y2;
+ Ith(rrBS,3) = -p2*y2*l21 - l3 + y3;
+
+ Ith(rrBS,4) = mp1 + p1*(-m1+m2) - m3 + l21 + s1;
+ Ith(rrBS,5) = mp2 + p2*y3*m1 - (p2*y3+TWO*p3*y2)*m2 - m3 + p2*s3*l1 - (TWO*p3*s2+p2*s3)*l2 + s2;
+ Ith(rrBS,6) = p2*y2*(m1-m2) - m3 - p2*s2*l21 + s3;
+
+ return(0);
+}
+
+static int rhsQBS1(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)
+{
+ UserData data;
+ realtype y1, y2, y3;
+ realtype p1, p2, p3;
+ realtype l1, l2, l3, m1, m2, m3;
+ realtype s1, s2, s3;
+ realtype l21;
+
+ data = (UserData) user_dataB;
+
+ /* The p vector */
+ p1 = data->p[0]; p2 = data->p[1]; p3 = data->p[2];
+
+ /* The y vector */
+ y1 = Ith(yy,1); y2 = Ith(yy,2); y3 = Ith(yy,3);
+
+ /* The lambda vector. */
+ l1 = Ith(yyB,1); l2 = Ith(yyB,2); l3 = Ith(yyB,3);
+ /* The mu vector. */
+ m1 = Ith(yyB,4); m2 = Ith(yyB,5); m3 = Ith(yyB,6);
+
+ /* The sensitivity with respect to p1 */
+ s1 = Ith(yyS[0],1); s2 = Ith(yyS[0],2); s3 = Ith(yyS[0],3);
+
+ /* Temporary variables */
+ l21 = l2-l1;
+
+ Ith(rhsBQS,1) = -y1*l21;
+ Ith(rhsBQS,2) = y2*y3*l21;
+
+ Ith(rhsBQS,3) = y1*(m1-m2) - s1*l21;
+ Ith(rhsBQS,4) = y2*y3*(m2-m1) + (y3*s2+y2*s3)*l21;
+
+ return(0);
+}
+
+static int resBS2(realtype tt,
+ N_Vector yy, N_Vector yp,
+ N_Vector *yyS, N_Vector *ypS,
+ N_Vector yyB, N_Vector ypB,
+ N_Vector rrBS, void *user_dataB)
+
+{
+ UserData data;
+ realtype y1, y2, y3;
+ realtype p1, p2, p3;
+ realtype l1, l2, l3, m1, m2, m3;
+ realtype lp1, lp2, mp1, mp2;
+ realtype s1, s2, s3;
+ realtype l21;
+
+ data = (UserData) user_dataB;
+
+ /* The parameters. */
+ p1 = data->p[0]; p2 = data->p[1]; p3 = data->p[2];
+
+ /* The y vector. */
+ y1 = Ith(yy,1); y2 = Ith(yy,2); y3 = Ith(yy,3);
+
+ /* The lambda vector. */
+ l1 = Ith(yyB,1); l2 = Ith(yyB,2); l3 = Ith(yyB,3);
+ /* The mu vector. */
+ m1 = Ith(yyB,4); m2 = Ith(yyB,5); m3 = Ith(yyB,6);
+
+ /* The lambda dot vector. */
+ lp1 = Ith(ypB,1); lp2 = Ith(ypB,2);
+ /* The mu dot vector. */
+ mp1 = Ith(ypB,4); mp2 = Ith(ypB,5);
+
+ /* The sensitivity with respect to p2 */
+ s1 = Ith(yyS[1],1); s2 = Ith(yyS[1],2); s3 = Ith(yyS[1],3);
+
+ /* Temporary variables */
+ l21 = l2-l1;
+
+ Ith(rrBS,1) = lp1 + p1*l21 - l3 + y1;
+ Ith(rrBS,2) = lp2 - p2*y3*l21 - TWO*p3*y2*l2 - l3 + y2;
+ Ith(rrBS,3) = -p2*y2*l21 - l3 + y3;
+
+ Ith(rrBS,4) = mp1 + p1*(-m1+m2) - m3 + s1;
+ Ith(rrBS,5) = mp2 + p2*y3*m1 - (p2*y3+TWO*p3*y2)*m2 - m3 + (y3+p2*s3)*l1 - (y3+TWO*p3*s2+p2*s3)*l2 + s2;
+ Ith(rrBS,6) = p2*y2*(m1-m2) - m3 - (y2+p2*s2)*l21 + s3;
+
+ return(0);
+}
+
+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)
+{
+ UserData data;
+ realtype y1, y2, y3;
+ realtype p1, p2, p3;
+ realtype l1, l2, l3, m1, m2, m3;
+ realtype s1, s2, s3;
+ realtype l21;
+
+ data = (UserData) user_dataB;
+
+ /* The p vector */
+ p1 = data->p[0]; p2 = data->p[1]; p3 = data->p[2];
+
+ /* The y vector */
+ y1 = Ith(yy,1); y2 = Ith(yy,2); y3 = Ith(yy,3);
+
+ /* The lambda vector. */
+ l1 = Ith(yyB,1); l2 = Ith(yyB,2); l3 = Ith(yyB,3);
+ /* The mu vector. */
+ m1 = Ith(yyB,4); m2 = Ith(yyB,5); m3 = Ith(yyB,6);
+
+ /* The sensitivity with respect to p2 */
+ s1 = Ith(yyS[1],1); s2 = Ith(yyS[1],2); s3 = Ith(yyS[1],3);
+
+ /* Temporary variables */
+ l21 = l2-l1;
+
+ Ith(rhsBQS,1) = -y1*l21;
+ Ith(rhsBQS,2) = y2*y3*l21;
+
+ Ith(rhsBQS,3) = y1*(m1-m2) - s1*l21;
+ Ith(rhsBQS,4) = y2*y3*(m2-m1) + (y3*s2+y2*s3)*l21;
+
+ return(0);
+}
diff --git a/examples/idas/serial/idasHessian_ASA_FSA.out b/examples/idas/serial/idasHessian_ASA_FSA.out
new file mode 100644
index 0000000..0bfa44a
--- /dev/null
+++ b/examples/idas/serial/idasHessian_ASA_FSA.out
@@ -0,0 +1,42 @@
+
+Adjoint Sensitivity Example for Chemical Kinetics
+---------------------------------------------------------
+DAE: dy1/dt + p1*y1 - p2*y2*y3 = 0
+ dy2/dt - p1*y1 + p2*y2*y3 + p3*(y2)^2 = 0
+ y1 + y2 + y3 = 0
+
+Find dG/dp and d^2G/dp^2, where p=[p1,p2] for
+ G = int_t0^tB0 g(t,p,y) dt
+ g(t,p,y) = y3
+
+
+---------------------------------------------------------
+Forward integration
+---------------------------------------------------------
+
+ G: 2.5042e+01
+ dG/dp: -1.3753e+02 4.1552e-04
+
+---------------------------------------------------------
+Backward integration
+---------------------------------------------------------
+
+ dG/dp: -1.3753e+02 4.1552e-04 (from backward pb. 1)
+ dG/dp: -1.3753e+02 4.1552e-04 (from backward pb. 2)
+
+ H = d2G/dp2:
+ (1) (2)
+ 4.4243e+03 -2.7779e-03
+ -2.7779e-03 -2.4173e-08
+
+---------------------------------------------------------
+Finite Differences ( dp1=1.0e-03 and dp2 = 2.5e+02 )
+---------------------------------------------------------
+
+
+ dG/dp: -1.3534e+02 4.1250e-04 (fwd FD)
+ -1.3977e+02 4.1855e-04 (bck FD)
+ -1.3755e+02 4.1552e-04 (cntr FD)
+
+ H(1,1): 4.4247e+03
+ H(2,2): -2.4174e-08
diff --git a/examples/idas/serial/idasKrylovDemo_ls.c b/examples/idas/serial/idasKrylovDemo_ls.c
new file mode 100644
index 0000000..06cd3fe
--- /dev/null
+++ b/examples/idas/serial/idasKrylovDemo_ls.c
@@ -0,0 +1,581 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.2 $
+ * $Date: 2009/09/30 23:33:29 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Allan Taylor, Alan Hindmarsh and Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ *
+ * This example loops through the available iterative linear solvers:
+ * SPGMR, SPBCG and SPTFQMR.
+ *
+ * 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.
+ *
+ * The DAE system solved is a spatial discretization of the PDE
+ * du/dt = d^2u/dx^2 + d^2u/dy^2
+ * on the unit square. The boundary condition is u = 0 on all edges.
+ * Initial conditions are given by u = 16 x (1 - x) y (1 - y). The
+ * PDE is treated with central differences on a uniform M x M grid.
+ * The values of u at the interior points satisfy ODEs, and
+ * equations u = 0 at the boundaries are appended, to form a DAE
+ * 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
+ * preconditioner uses the diagonal elements of the Jacobian only.
+ * Routines for preconditioning, required by IDASP*, 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>
+
+/* Problem Constants */
+
+#define NOUT 11
+#define MGRID 10
+#define NEQ MGRID*MGRID
+#define ZERO RCONST(0.0)
+#define ONE RCONST(1.0)
+#define TWO RCONST(2.0)
+#define FOUR RCONST(4.0)
+
+/* Linear Solver Loop Constants */
+
+#define USE_SPGMR 0
+#define USE_SPBCG 1
+#define USE_SPTFQMR 2
+
+/* User data type */
+
+typedef struct {
+ long int mm; /* number of grid points */
+ realtype dx;
+ realtype coeff;
+ N_Vector pp; /* vector of prec. diag. elements */
+} *UserData;
+
+/* Prototypes for functions called by IDA */
+
+int resHeat(realtype tres, N_Vector uu, N_Vector up,
+ N_Vector resval, void *user_data);
+
+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);
+
+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);
+
+/* Prototypes for private functions */
+
+static int SetInitialProfile(UserData data, N_Vector uu, N_Vector up,
+ N_Vector res);
+static void PrintHeader(realtype rtol, realtype atol, int linsolver);
+static void PrintOutput(void *mem, realtype t, N_Vector uu, int linsolver);
+static int check_flag(void *flagvalue, char *funcname, int opt);
+
+/*
+ *--------------------------------------------------------------------
+ * MAIN PROGRAM
+ *--------------------------------------------------------------------
+ */
+
+int main(void)
+{
+ void *mem;
+ UserData data;
+ N_Vector uu, up, constraints, res;
+ int ier, iout, linsolver;
+ realtype rtol, atol, t0, t1, tout, tret;
+ long int netf, ncfn, ncfl;
+
+ mem = NULL;
+ data = NULL;
+ uu = up = constraints = res = NULL;
+
+ /* Allocate N-vectors and the user data structure. */
+
+ uu = N_VNew_Serial(NEQ);
+ if(check_flag((void *)uu, "N_VNew_Serial", 0)) return(1);
+
+ up = N_VNew_Serial(NEQ);
+ if(check_flag((void *)up, "N_VNew_Serial", 0)) return(1);
+
+ res = N_VNew_Serial(NEQ);
+ 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);
+
+ data = (UserData) malloc(sizeof *data);
+ data->pp = NULL;
+ if(check_flag((void *)data, "malloc", 2)) return(1);
+
+ /* Assign parameters in the user data structure. */
+
+ data->mm = MGRID;
+ data->dx = ONE/(MGRID-ONE);
+ data->coeff = ONE/(data->dx * data->dx);
+ data->pp = N_VNew_Serial(NEQ);
+ if(check_flag((void *)data->pp, "N_VNew_Serial", 0)) return(1);
+
+ /* Initialize uu, up. */
+
+ SetInitialProfile(data, uu, up, res);
+
+ /* Set constraints to all 1's for nonnegative solution values. */
+
+ N_VConst(ONE, constraints);
+
+ /* Assign various parameters. */
+
+ t0 = ZERO;
+ t1 = RCONST(0.01);
+ rtol = ZERO;
+ atol = RCONST(1.0e-3);
+
+ /* Call IDACreate and IDAMalloc to initialize solution */
+
+ mem = IDACreate();
+ if(check_flag((void *)mem, "IDACreate", 0)) return(1);
+
+ ier = IDASetUserData(mem, data);
+ if(check_flag(&ier, "IDASetUserData", 1)) return(1);
+
+ ier = IDASetConstraints(mem, constraints);
+ if(check_flag(&ier, "IDASetConstraints", 1)) return(1);
+ N_VDestroy_Serial(constraints);
+
+ ier = IDAInit(mem, resHeat, t0, uu, up);
+ if(check_flag(&ier, "IDAInit", 1)) return(1);
+
+ ier = IDASStolerances(mem, rtol, atol);
+ if(check_flag(&ier, "IDASStolerances", 1)) return(1);
+
+ /* START: Loop through SPGMR, SPBCG and SPTFQMR linear solver modules */
+ for (linsolver = 0; linsolver < 3; ++linsolver) {
+
+ if (linsolver != 0) {
+
+ /* Re-initialize uu, up. */
+ SetInitialProfile(data, uu, up, res);
+
+ /* Re-initialize IDA */
+ ier = IDAReInit(mem, t0, uu, up);
+ if (check_flag(&ier, "IDAReInit", 1)) return(1);
+
+ }
+
+ /* Attach a linear solver module */
+ switch(linsolver) {
+
+ /* (a) SPGMR */
+ case(USE_SPGMR):
+
+ /* Print header */
+ printf(" -------");
+ 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);
+
+ break;
+
+ /* (b) SPBCG */
+ case(USE_SPBCG):
+
+ /* Print header */
+ printf(" -------");
+ printf(" \n| SPBCG |\n");
+ printf(" -------\n");
+
+ /* Call IDASpbcg to specify the linear solver. */
+ ier = IDASpbcg(mem, 0);
+ if(check_flag(&ier, "IDASpbcg", 1)) return(1);
+
+ break;
+
+ /* (c) SPTFQMR */
+ case(USE_SPTFQMR):
+
+ /* Print header */
+ printf(" ---------");
+ 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);
+
+ break;
+
+ }
+
+ /* Specify preconditioner */
+ ier = IDASpilsSetPreconditioner(mem, PsetupHeat, PsolveHeat);
+ if(check_flag(&ier, "IDASpilsSetPreconditioner", 1)) return(1);
+
+ /* Print output heading. */
+ PrintHeader(rtol, atol, linsolver);
+
+ /* Print output table heading, and initial line of table. */
+
+ printf("\n Output Summary (umax = max-norm of solution) \n\n");
+ printf(" time umax k nst nni nje nre nreLS h npe nps\n" );
+ printf("----------------------------------------------------------------------\n");
+
+ /* Loop over output times, call IDASolve, and print results. */
+
+ for (tout = t1,iout = 1; iout <= NOUT ; iout++, tout *= TWO) {
+ ier = IDASolve(mem, tout, &tret, uu, up, IDA_NORMAL);
+ if(check_flag(&ier, "IDASolve", 1)) return(1);
+ PrintOutput(mem, tret, uu, linsolver);
+ }
+
+ /* Print remaining counters. */
+ ier = IDAGetNumErrTestFails(mem, &netf);
+ check_flag(&ier, "IDAGetNumErrTestFails", 1);
+
+ ier = IDAGetNumNonlinSolvConvFails(mem, &ncfn);
+ check_flag(&ier, "IDAGetNumNonlinSolvConvFails", 1);
+
+ ier = IDASpilsGetNumConvFails(mem, &ncfl);
+ check_flag(&ier, "IDASpilsGetNumConvFails", 1);
+
+ printf("\nError test failures = %ld\n", netf);
+ printf("Nonlinear convergence failures = %ld\n", ncfn);
+ printf("Linear convergence failures = %ld\n", ncfl);
+
+ if (linsolver < 2)
+ printf("\n======================================================================\n\n");
+
+ } /* END: Loop through SPGMR, SPBCG and SPTFQMR linear solver modules */
+
+ /* Free Memory */
+
+ IDAFree(&mem);
+
+ N_VDestroy_Serial(uu);
+ N_VDestroy_Serial(up);
+ N_VDestroy_Serial(res);
+
+ N_VDestroy_Serial(data->pp);
+ free(data);
+
+ return(0);
+}
+
+/*
+ *--------------------------------------------------------------------
+ * FUNCTIONS CALLED BY IDA
+ *--------------------------------------------------------------------
+ */
+
+/*
+ * resHeat: heat equation system residual function (user-supplied)
+ * This uses 5-point central differencing on the interior points, and
+ * includes algebraic equations for the boundary values.
+ * So for each interior point, the residual component has the form
+ * res_i = u'_i - (central difference)_i
+ * while for each boundary point, it is res_i = u_i.
+ */
+
+int resHeat(realtype tt,
+ N_Vector uu, N_Vector up, N_Vector rr,
+ void *user_data)
+{
+ long int i, j, offset, loc, mm;
+ realtype *uu_data, *up_data, *rr_data, coeff, dif1, dif2;
+ UserData data;
+
+ uu_data = NV_DATA_S(uu);
+ up_data = NV_DATA_S(up);
+ rr_data = NV_DATA_S(rr);
+
+ data = (UserData) user_data;
+
+ coeff = data->coeff;
+ mm = data->mm;
+
+ /* Initialize rr to uu, to take care of boundary equations. */
+ N_VScale(ONE, uu, rr);
+
+ /* Loop over interior points; set res = up - (central difference). */
+ for (j = 1; j < MGRID-1; j++) {
+ offset = mm*j;
+ for (i = 1; i < mm-1; i++) {
+ loc = offset + i;
+ dif1 = uu_data[loc-1] + uu_data[loc+1] - TWO * uu_data[loc];
+ dif2 = uu_data[loc-mm] + uu_data[loc+mm] - TWO * uu_data[loc];
+ rr_data[loc]= up_data[loc] - coeff * ( dif1 + dif2 );
+ }
+ }
+
+ return(0);
+}
+
+/*
+ * PsetupHeat: setup for diagonal preconditioner.
+ *
+ * The optional user-supplied functions PsetupHeat and
+ * PsolveHeat together must define the left preconditoner
+ * matrix P approximating the system Jacobian matrix
+ * J = dF/du + cj*dF/du'
+ * (where the DAE system is F(t,u,u') = 0), and solve the linear
+ * systems P z = r. This is done in this case by keeping only
+ * the diagonal elements of the J matrix above, storing them as
+ * inverses in a vector pp, when computed in PsetupHeat, for
+ * subsequent use in PsolveHeat.
+ *
+ * In this instance, only cj and data (user data structure, with
+ * pp etc.) are used from the PsetupdHeat argument list.
+ */
+
+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)
+{
+
+ long int i, j, offset, loc, mm;
+ realtype *ppv, pelinv;
+ UserData data;
+
+ data = (UserData) user_data;
+ ppv = NV_DATA_S(data->pp);
+ mm = data->mm;
+
+ /* Initialize the entire vector to 1., then set the interior points to the
+ correct value for preconditioning. */
+ N_VConst(ONE,data->pp);
+
+ /* Compute the inverse of the preconditioner diagonal elements. */
+ pelinv = ONE/(c_j + FOUR*data->coeff);
+
+ for (j = 1; j < mm-1; j++) {
+ offset = mm * j;
+ for (i = 1; i < mm-1; i++) {
+ loc = offset + i;
+ ppv[loc] = pelinv;
+ }
+ }
+
+ return(0);
+}
+
+/*
+ * PsolveHeat: solve preconditioner linear system.
+ * This routine multiplies the input vector rvec by the vector pp
+ * containing the inverse diagonal Jacobian elements (previously
+ * computed in PrecondHeateq), 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)
+{
+ UserData data;
+ data = (UserData) user_data;
+ N_VProd(data->pp, rvec, zvec);
+ return(0);
+}
+
+/*
+ *--------------------------------------------------------------------
+ * PRIVATE FUNCTIONS
+ *--------------------------------------------------------------------
+ */
+
+/*
+ * SetInitialProfile: routine to initialize u and up vectors.
+ */
+
+static int SetInitialProfile(UserData data, N_Vector uu, N_Vector up,
+ N_Vector res)
+{
+ long int mm, mm1, i, j, offset, loc;
+ realtype xfact, yfact, *udata, *updata;
+
+ mm = data->mm;
+
+ udata = NV_DATA_S(uu);
+ updata = NV_DATA_S(up);
+
+ /* Initialize uu on all grid points. */
+ mm1 = mm - 1;
+ for (j = 0; j < mm; j++) {
+ yfact = data->dx * j;
+ offset = mm*j;
+ for (i = 0;i < mm; i++) {
+ xfact = data->dx * i;
+ loc = offset + i;
+ udata[loc] = RCONST(16.0) * xfact * (ONE - xfact) * yfact * (ONE - yfact);
+ }
+ }
+
+ /* Initialize up vector to 0. */
+ N_VConst(ZERO, up);
+
+ /* resHeat sets res to negative of ODE RHS values at interior points. */
+ resHeat(ZERO, uu, up, res, data);
+
+ /* Copy -res into up to get correct interior initial up values. */
+ N_VScale(-ONE, res, up);
+
+ /* Set up at boundary points to zero. */
+ for (j = 0; j < mm; j++) {
+ offset = mm*j;
+ for (i = 0; i < mm; i++) {
+ loc = offset + i;
+ if (j == 0 || j == mm1 || i == 0 || i == mm1 ) updata[loc] = ZERO;
+ }
+ }
+
+ return(0);
+ }
+
+/*
+ * Print first lines of output (problem description)
+ */
+
+static void PrintHeader(realtype rtol, realtype atol, int linsolver)
+{
+ printf("\nidasKrylovDemo_ls: Heat equation, serial 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", MGRID, MGRID);
+ printf(" Total system size: %d\n\n", NEQ);
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("Tolerance parameters: rtol = %Lg atol = %Lg\n", rtol, atol);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("Tolerance parameters: rtol = %lg atol = %lg\n", rtol, atol);
+#else
+ printf("Tolerance parameters: rtol = %g atol = %g\n", rtol, atol);
+#endif
+ printf("Constraints set to force all solution components >= 0. \n");
+
+ switch(linsolver) {
+
+ case(USE_SPGMR):
+ printf("Linear solver: IDASPGMR, preconditioner using diagonal elements. \n");
+ break;
+
+ case(USE_SPBCG):
+ printf("Linear solver: IDASPBCG, preconditioner using diagonal elements. \n");
+ break;
+
+ case(USE_SPTFQMR):
+ printf("Linear solver: IDASPTFQMR, preconditioner using diagonal elements. \n");
+ break;
+ }
+}
+
+/*
+ * PrintOutput: print max norm of solution and current solver statistics
+ */
+
+static void PrintOutput(void *mem, realtype t, N_Vector uu, int linsolver)
+{
+ realtype hused, umax;
+ long int nst, nni, nje, nre, nreLS, nli, npe, nps;
+ int kused, ier;
+
+ umax = N_VMaxNorm(uu);
+
+ ier = IDAGetLastOrder(mem, &kused);
+ check_flag(&ier, "IDAGetLastOrder", 1);
+ ier = IDAGetNumSteps(mem, &nst);
+ check_flag(&ier, "IDAGetNumSteps", 1);
+ ier = IDAGetNumNonlinSolvIters(mem, &nni);
+ check_flag(&ier, "IDAGetNumNonlinSolvIters", 1);
+ ier = IDAGetNumResEvals(mem, &nre);
+ check_flag(&ier, "IDAGetNumResEvals", 1);
+ ier = IDAGetLastStep(mem, &hused);
+ check_flag(&ier, "IDAGetLastStep", 1);
+
+ ier = IDASpilsGetNumJtimesEvals(mem, &nje);
+ check_flag(&ier, "IDASpilsGetNumJtimesEvals", 1);
+ ier = IDASpilsGetNumLinIters(mem, &nli);
+ check_flag(&ier, "IDASpilsGetNumLinIters", 1);
+ ier = IDASpilsGetNumResEvals(mem, &nreLS);
+ check_flag(&ier, "IDASpilsGetNumResEvals", 1);
+ ier = IDASpilsGetNumPrecEvals(mem, &npe);
+ check_flag(&ier, "IDASpilsGetPrecEvals", 1);
+ ier = IDASpilsGetNumPrecSolves(mem, &nps);
+ check_flag(&ier, "IDASpilsGetNumPrecSolves", 1);
+
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf(" %5.2Lf %13.5Le %d %3ld %3ld %3ld %4ld %4ld %9.2Le %3ld %3ld\n",
+ t, umax, kused, nst, nni, nje, nre, nreLS, hused, npe, nps);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf(" %5.2f %13.5le %d %3ld %3ld %3ld %4ld %4ld %9.2le %3ld %3ld\n",
+ t, umax, kused, nst, nni, nje, nre, nreLS, hused, npe, nps);
+#else
+ printf(" %5.2f %13.5e %d %3ld %3ld %3ld %4ld %4ld %9.2e %3ld %3ld\n",
+ t, umax, kused, nst, nni, nje, nre, nreLS, hused, npe, nps);
+#endif
+}
+
+/*
+ * 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, 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/idas/serial/idasKrylovDemo_ls.out b/examples/idas/serial/idasKrylovDemo_ls.out
new file mode 100644
index 0000000..ecdb3b8
--- /dev/null
+++ b/examples/idas/serial/idasKrylovDemo_ls.out
@@ -0,0 +1,102 @@
+ -------
+| SPGMR |
+ -------
+
+idasKrylovDemo_ls: Heat equation, serial 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
+
+Tolerance parameters: rtol = 0 atol = 0.001
+Constraints set to force all solution components >= 0.
+Linear solver: IDASPGMR, preconditioner using diagonal elements.
+
+ Output Summary (umax = max-norm of solution)
+
+ time umax k nst nni nje nre nreLS h npe nps
+----------------------------------------------------------------------
+ 0.01 8.24106e-01 2 12 14 7 14 7 2.56e-03 8 21
+ 0.02 6.88134e-01 3 15 18 12 18 12 5.12e-03 8 30
+ 0.04 4.70711e-01 3 18 24 21 24 21 6.58e-03 9 45
+ 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
+
+Error test failures = 1
+Nonlinear convergence failures = 0
+Linear convergence failures = 0
+
+======================================================================
+
+ -------
+| SPBCG |
+ -------
+
+idasKrylovDemo_ls: Heat equation, serial 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
+
+Tolerance parameters: rtol = 0 atol = 0.001
+Constraints set to force all solution components >= 0.
+Linear solver: IDASPBCG, preconditioner using diagonal elements.
+
+ Output Summary (umax = max-norm of solution)
+
+ time umax k nst nni nje nre nreLS h npe nps
+----------------------------------------------------------------------
+ 0.01 8.24105e-01 2 12 14 8 14 8 2.56e-03 8 22
+ 0.02 6.88129e-01 3 15 18 14 18 14 5.12e-03 8 32
+ 0.04 4.70820e-01 3 19 23 22 23 22 1.02e-02 9 45
+ 0.08 2.16332e-01 3 23 27 32 27 32 1.02e-02 9 59
+ 0.16 4.48774e-02 4 27 33 44 33 44 2.05e-02 10 77
+ 0.32 1.75557e-03 3 33 41 70 41 70 4.10e-02 11 111
+ 0.64 2.47770e-05 1 38 48 82 48 82 1.64e-01 13 130
+ 1.28 2.57209e-22 1 40 50 82 50 82 6.55e-01 15 132
+ 2.56 3.19445e-22 1 41 51 82 51 82 1.31e+00 16 133
+ 5.12 7.19965e-22 1 42 52 82 52 82 2.62e+00 17 134
+ 10.24 1.87591e-21 1 43 53 82 53 82 5.24e+00 18 135
+
+Error test failures = 0
+Nonlinear convergence failures = 0
+Linear convergence failures = 0
+
+======================================================================
+
+ ---------
+| SPTFQMR |
+ ---------
+
+idasKrylovDemo_ls: Heat equation, serial 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
+
+Tolerance parameters: rtol = 0 atol = 0.001
+Constraints set to force all solution components >= 0.
+Linear solver: IDASPTFQMR, preconditioner using diagonal elements.
+
+ Output Summary (umax = max-norm of solution)
+
+ time umax k nst nni nje nre nreLS h npe nps
+----------------------------------------------------------------------
+ 0.01 8.24104e-01 2 12 14 11 14 11 2.56e-03 8 28
+ 0.02 6.88133e-01 3 15 18 19 18 19 5.12e-03 8 42
+ 0.04 4.70857e-01 3 19 23 33 23 33 1.02e-02 9 64
+ 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
+
+Error test failures = 0
+Nonlinear convergence failures = 0
+Linear convergence failures = 0
diff --git a/examples/idas/serial/idasRoberts_ASAi_dns.c b/examples/idas/serial/idasRoberts_ASAi_dns.c
new file mode 100644
index 0000000..2b3d8ad
--- /dev/null
+++ b/examples/idas/serial/idasRoberts_ASAi_dns.c
@@ -0,0 +1,757 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.2 $
+ * $Date: 2010/12/01 23:05:10 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Radu Serban and Cosmin Petra @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2007, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * Adjoint sensitivity example problem.
+ *
+ * This simple example problem for IDAS, due to Robertson,
+ * is from chemical kinetics, and consists of the following three
+ * equations:
+ *
+ * dy1/dt + p1*y1 - p2*y2*y3 = 0
+ * dy2/dt - p1*y1 + p2*y2*y3 + p3*y2**2 = 0
+ * y1 + y2 + y3 - 1 = 0
+ *
+ * on the interval from t = 0.0 to t = 4.e10, with initial
+ * conditions: y1 = 1, y2 = y3 = 0.The reaction rates are: p1=0.04,
+ * p2=1e4, and p3=3e7
+ *
+ * It uses a scalar relative tolerance and a vector absolute
+ * tolerance.
+ *
+ * IDAS can also compute sensitivities with respect to
+ * the problem parameters p1, p2, and p3 of the following quantity:
+ * G = int_t0^t1 g(t,p,y) dt
+ * where
+ * g(t,p,y) = y3
+ *
+ * The gradient dG/dp is obtained as:
+ * dG/dp = int_t0^t1 (g_p - lambda^T F_p ) dt -
+ * lambda^T*F_y'*y_p | _t0^t1
+ * = int_t0^t1 (lambda^T*F_p) dt
+ * where lambda and are solutions of the adjoint system:
+ * d(lambda^T * F_y' )/dt -lambda^T F_y = -g_y
+ *
+ * During the backward integration, IDAS also evaluates G as
+ * G = - phi(t0)
+ * 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>
+
+/* 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 */
+
+#define RTOL RCONST(1e-06) /* scalar relative tolerance */
+
+#define ATOL1 RCONST(1e-08) /* vector absolute tolerance components */
+#define ATOL2 RCONST(1e-12)
+#define ATOL3 RCONST(1e-08)
+
+#define ATOLA RCONST(1e-08) /* absolute tolerance for adjoint vars. */
+#define ATOLQ RCONST(1e-06) /* absolute tolerance for quadratures */
+
+#define T0 RCONST(0.0) /* initial time */
+#define TOUT RCONST(4e10) /* final time */
+
+#define TB1 RCONST(50.0) /* starting point for adjoint problem */
+#define TB2 TOUT /* starting point for adjoint problem */
+
+#define T1B RCONST(49.0) /* for IDACalcICB */
+
+#define STEPS 100 /* number of steps between check points */
+
+#define NP 3 /* number of problem parameters */
+
+#define ONE RCONST(1.0)
+#define ZERO RCONST(0.0)
+
+
+/* Type : UserData */
+
+typedef struct {
+ realtype p[3];
+} *UserData;
+
+/* Prototypes of user-supplied functions */
+
+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,
+ N_Vector yy, N_Vector yp, N_Vector resvec,
+ DlsMat 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);
+static int ewt(N_Vector y, N_Vector w, void *user_data);
+
+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 JacB(long int NeqB, realtype tt, realtype cjB,
+ N_Vector yy, N_Vector yp,
+ N_Vector yyB, N_Vector ypB, N_Vector rrB,
+ DlsMat JacB, void *user_data,
+ N_Vector tmp1B, N_Vector tmp2B, N_Vector tmp3B);
+
+
+static int rhsQB(realtype tt,
+ N_Vector yy, N_Vector yp,
+ N_Vector yyB, N_Vector ypB,
+ N_Vector rrQB, void *user_dataB);
+
+/* Prototypes of private functions */
+static void PrintOutput(realtype tfinal, N_Vector yB, N_Vector ypB, N_Vector qB);
+static int check_flag(void *flagvalue, char *funcname, int opt);
+
+/*
+ *--------------------------------------------------------------------
+ * MAIN PROGRAM
+ *--------------------------------------------------------------------
+ */
+
+int main(int argc, char *argv[])
+{
+ UserData data;
+
+ void *ida_mem;
+
+ realtype reltolQ, abstolQ;
+ N_Vector yy, yp, q;
+ N_Vector yyTB1, ypTB1;
+ N_Vector id;
+
+ int steps;
+
+ int indexB;
+
+ realtype reltolB, abstolB, abstolQB;
+ N_Vector yB, ypB, qB;
+ realtype time;
+ int flag, ncheck;
+
+ IDAadjCheckPointRec *ckpnt;
+
+ long int nst, nstB;
+
+ data = NULL;
+ ckpnt = NULL;
+ ida_mem = NULL;
+ yy = yp = yB = qB = NULL;
+
+ /* Print problem description */
+ printf("\nAdjoint Sensitivity Example for Chemical Kinetics\n");
+ printf("-------------------------------------------------\n\n");
+ printf("DAE: dy1/dt + p1*y1 - p2*y2*y3 = 0\n");
+ printf(" dy2/dt - p1*y1 + p2*y2*y3 + p3*(y2)^2 = 0\n");
+ printf(" y1 + y2 + y3 = 0\n\n");
+ printf("Find dG/dp for\n");
+ printf(" G = int_t0^tB0 g(t,p,y) dt\n");
+ printf(" g(t,p,y) = y3\n\n\n");
+
+ /* User data structure */
+ data = (UserData) malloc(sizeof *data);
+ if (check_flag((void *)data, "malloc", 2)) return(1);
+ data->p[0] = RCONST(0.04);
+ data->p[1] = RCONST(1.0e4);
+ data->p[2] = RCONST(3.0e7);
+
+ /* Initialize y */
+ yy = N_VNew_Serial(NEQ);
+ if (check_flag((void *)yy, "N_VNew_Serial", 0)) return(1);
+ Ith(yy,1) = ONE;
+ Ith(yy,2) = ZERO;
+ Ith(yy,3) = ZERO;
+
+ /* Initialize yprime */
+ yp = N_VNew_Serial(NEQ);
+ if (check_flag((void *)yp, "N_VNew_Serial", 0)) return(1);
+ Ith(yp,1) = RCONST(-0.04);
+ Ith(yp,2) = RCONST( 0.04);
+ Ith(yp,3) = ZERO;
+
+ /* Initialize q */
+ q = N_VNew_Serial(1);
+ if (check_flag((void *)q, "N_VNew_Serial", 0)) return(1);
+ Ith(q,1) = ZERO;
+
+ /* Set the scalar realtive and absolute tolerances reltolQ and abstolQ */
+ reltolQ = RTOL;
+ abstolQ = ATOLQ;
+
+ /* Create and allocate IDAS memory for forward run */
+ printf("Create and allocate IDAS memory for forward runs\n");
+
+ ida_mem = IDACreate();
+ if (check_flag((void *)ida_mem, "IDACreate", 0)) return(1);
+
+ flag = IDAInit(ida_mem, res, T0, yy, yp);
+ if (check_flag(&flag, "IDAInit", 1)) return(1);
+
+ flag = IDAWFtolerances(ida_mem, ewt);
+ if (check_flag(&flag, "IDAWFtolerances", 1)) return(1);
+
+ 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);
+
+ flag = IDADlsSetDenseJacFn(ida_mem, Jac);
+ if (check_flag(&flag, "IDADlsSetDenseJacFn", 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);
+ if (check_flag(&flag, "IDASetQuadErrCon", 1)) return(1);
+
+ /* Allocate global memory */
+
+ steps = STEPS;
+ flag = IDAAdjInit(ida_mem, steps, IDA_HERMITE);
+ /*flag = IDAAdjInit(ida_mem, steps, IDA_POLYNOMIAL);*/
+ if (check_flag(&flag, "IDAAdjInit", 1)) return(1);
+
+ /* Perform forward run */
+ printf("Forward integration ... ");
+
+ /* Integrate till TB1 and get the solution (y, y') at that time. */
+ flag = IDASolveF(ida_mem, TB1, &time, yy, yp, IDA_NORMAL, &ncheck);
+ if (check_flag(&flag, "IDASolveF", 1)) return(1);
+
+ yyTB1 = N_VClone(yy);
+ ypTB1 = N_VClone(yp);
+ /* Save the states at t=TB1. */
+ N_VScale(ONE, yy, yyTB1);
+ N_VScale(ONE, yp, ypTB1);
+
+ /* Continue integrating till TOUT is reached. */
+ flag = IDASolveF(ida_mem, TOUT, &time, yy, yp, IDA_NORMAL, &ncheck);
+ if (check_flag(&flag, "IDASolveF", 1)) return(1);
+
+ flag = IDAGetNumSteps(ida_mem, &nst);
+ if (check_flag(&flag, "IDAGetNumSteps", 1)) return(1);
+
+ printf("done ( nst = %ld )\n",nst);
+
+ flag = IDAGetQuad(ida_mem, &time, q);
+ if (check_flag(&flag, "IDAGetQuad", 1)) return(1);
+
+ printf("--------------------------------------------------------\n");
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("G: %12.4Le \n",Ith(q,1));
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("G: %12.4le \n",Ith(q,1));
+#else
+ printf("G: %12.4e \n",Ith(q,1));
+#endif
+ printf("--------------------------------------------------------\n\n");
+
+ /* Test check point linked list
+ (uncomment next block to print check point information) */
+
+ /*
+ {
+ int i;
+
+ printf("\nList of Check Points (ncheck = %d)\n\n", ncheck);
+ ckpnt = (IDAadjCheckPointRec *) malloc ( (ncheck+1)*sizeof(IDAadjCheckPointRec));
+ IDAGetAdjCheckPointsInfo(ida_mem, ckpnt);
+ for (i=0;i<=ncheck;i++) {
+ printf("Address: %p\n",ckpnt[i].my_addr);
+ printf("Next: %p\n",ckpnt[i].next_addr);
+ printf("Time interval: %le %le\n",ckpnt[i].t0, ckpnt[i].t1);
+ printf("Step number: %ld\n",ckpnt[i].nstep);
+ printf("Order: %d\n",ckpnt[i].order);
+ printf("Step size: %le\n",ckpnt[i].step);
+ printf("\n");
+ }
+
+ }
+ */
+
+
+ /* Create BACKWARD problem. */
+
+ /* Allocate yB (i.e. lambda_0). */
+ yB = N_VNew_Serial(NEQ);
+ if (check_flag((void *)yB, "N_VNew_Serial", 0)) return(1);
+
+ /* Consistently initialize yB. */
+ Ith(yB,1) = ZERO;
+ Ith(yB,2) = ZERO;
+ Ith(yB,3) = ONE;
+
+
+ /* Allocate ypB (i.e. lambda'_0). */
+ ypB = N_VNew_Serial(NEQ);
+ if (check_flag((void *)ypB, "N_VNew_Serial", 0)) return(1);
+
+ /* Consistently initialize ypB. */
+ Ith(ypB,1) = ONE;
+ Ith(ypB,2) = ONE;
+ Ith(ypB,3) = ZERO;
+
+
+ /* Set the scalar relative tolerance reltolB */
+ reltolB = RTOL;
+
+ /* Set the scalar absolute tolerance abstolB */
+ abstolB = ATOLA;
+
+ /* Set the scalar absolute tolerance abstolQB */
+ abstolQB = ATOLQ;
+
+ /* Create and allocate IDAS memory for backward run */
+ printf("Create and allocate IDAS memory for backward run\n");
+
+ flag = IDACreateB(ida_mem, &indexB);
+ if (check_flag(&flag, "IDACreateB", 1)) return(1);
+
+ flag = IDAInitB(ida_mem, indexB, resB, TB2, yB, ypB);
+ if (check_flag(&flag, "IDAInitB", 1)) return(1);
+
+ flag = IDASStolerancesB(ida_mem, indexB, reltolB, abstolB);
+ if (check_flag(&flag, "IDASStolerancesB", 1)) return(1);
+
+ flag = IDASetUserDataB(ida_mem, indexB, data);
+ if (check_flag(&flag, "IDASetUserDataB", 1)) return(1);
+
+ flag = IDASetMaxNumStepsB(ida_mem, indexB, 1000);
+
+ flag = IDADenseB(ida_mem, indexB, NEQ);
+ if (check_flag(&flag, "IDADenseB", 1)) return(1);
+
+ flag = IDADlsSetDenseJacFnB(ida_mem, indexB, JacB);
+ if (check_flag(&flag, "IDASetDenseJacB", 1)) return(1);
+
+
+ /* Quadrature for backward problem. */
+
+ /* Initialize qB */
+ qB = N_VNew_Serial(NP);
+ if (check_flag((void *)qB, "N_VNew", 0)) return(1);
+ Ith(qB,1) = ZERO;
+ Ith(qB,2) = ZERO;
+ Ith(qB,3) = ZERO;
+
+ flag = IDAQuadInitB(ida_mem, indexB, rhsQB, qB);
+ if (check_flag(&flag, "IDAQuadInitB", 1)) return(1);
+
+ flag = IDAQuadSStolerancesB(ida_mem, indexB, reltolB, abstolQB);
+ if (check_flag(&flag, "IDAQuadSStolerancesB", 1)) return(1);
+
+ /* Include quadratures in error control. */
+ flag = IDASetQuadErrConB(ida_mem, indexB, TRUE);
+ if (check_flag(&flag, "IDASetQuadErrConB", 1)) return(1);
+
+
+ /* Backward Integration */
+ printf("Backward integration ... ");
+
+ flag = IDASolveB(ida_mem, T0, IDA_NORMAL);
+ if (check_flag(&flag, "IDASolveB", 1)) return(1);
+
+ IDAGetNumSteps(IDAGetAdjIDABmem(ida_mem, indexB), &nstB);
+ printf("done ( nst = %ld )\n", nstB);
+
+ flag = IDAGetB(ida_mem, indexB, &time, yB, ypB);
+ if (check_flag(&flag, "IDAGetB", 1)) return(1);
+
+ flag = IDAGetQuadB(ida_mem, indexB, &time, qB);
+ if (check_flag(&flag, "IDAGetB", 1)) return(1);
+
+ PrintOutput(TB2, yB, ypB, qB);
+
+
+ /* Reinitialize backward phase and start from a different time (TB1). */
+ printf("Re-initialize IDAS memory for backward run\n");
+
+ /* Both algebraic part from y and the entire y' are computed by IDACalcIC. */
+ Ith(yB,1) = ZERO;
+ Ith(yB,2) = ZERO;
+ Ith(yB,3) = RCONST(0.50); /* not consistent */
+
+ /* Rough guess for ypB. */
+ Ith(ypB,1) = RCONST(0.80);
+ Ith(ypB,2) = RCONST(0.75);
+ Ith(ypB,3) = ZERO;
+
+ /* Initialize qB */
+ Ith(qB,1) = ZERO;
+ Ith(qB,2) = ZERO;
+ Ith(qB,3) = ZERO;
+
+ flag = IDAReInitB(ida_mem, indexB, TB1, yB, ypB);
+ if (check_flag(&flag, "IDAReInitB", 1)) return(1);
+
+ /* Also reinitialize quadratures. */
+ flag = IDAQuadInitB(ida_mem, indexB, rhsQB, qB);
+ if (check_flag(&flag, "IDAQuadInitB", 1)) return(1);
+
+ /* Use IDACalcICB to compute consistent initial conditions
+ for this backward problem. */
+
+ id = N_VNew_Serial(NEQ);
+ Ith(id,1) = 1.0;
+ Ith(id,2) = 1.0;
+ Ith(id,3) = 0.0;
+
+ /* Specify which variables are differential (1) and which algebraic (0).*/
+ flag = IDASetIdB(ida_mem, indexB, id);
+ if (check_flag(&flag, "IDASetId", 1)) return(1);
+
+ flag = IDACalcICB(ida_mem, indexB, T1B, yyTB1, ypTB1);
+ if (check_flag(&flag, "IDACalcICB", 1)) return(1);
+
+ /* Get the consistent IC found by IDAS. */
+ flag = IDAGetConsistentICB(ida_mem, indexB, yB, ypB);
+ if (check_flag(&flag, "IDAGetConsistentICB", 1)) return(1);
+
+ printf("Backward integration ... ");
+
+ flag = IDASolveB(ida_mem, T0, IDA_NORMAL);
+ if (check_flag(&flag, "IDASolveB", 1)) return(1);
+
+ IDAGetNumSteps(IDAGetAdjIDABmem(ida_mem, indexB), &nstB);
+ printf("done ( nst = %ld )\n", nstB);
+
+ flag = IDAGetB(ida_mem, indexB, &time, yB, ypB);
+ if (check_flag(&flag, "IDAGetB", 1)) return(1);
+
+ flag = IDAGetQuadB(ida_mem, indexB, &time, qB);
+ if (check_flag(&flag, "IDAGetQuadB", 1)) return(1);
+
+ PrintOutput(TB1, yB, ypB, qB);
+
+ /* Free any memory used.*/
+
+ 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);
+
+ if (ckpnt != NULL) free(ckpnt);
+ free(data);
+
+ return(0);
+
+}
+
+/*
+ *--------------------------------------------------------------------
+ * FUNCTIONS CALLED BY IDAS
+ *--------------------------------------------------------------------
+ */
+
+/*
+ * f routine. Compute f(t,y).
+*/
+
+static int res(realtype t, N_Vector yy, N_Vector yp, N_Vector resval, void *user_data)
+{
+ realtype y1, y2, y3,yp1, yp2, yp3, *rval;
+ UserData data;
+ realtype p1, p2, p3;
+
+ 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 = NV_DATA_S(resval);
+
+ data = (UserData) user_data;
+ p1 = data->p[0]; p2 = data->p[1]; p3 = data->p[2];
+
+ rval[0] = p1*y1-p2*y2*y3;
+ rval[1] = -rval[0] + p3*y2*y2 + yp2;
+ rval[0]+= yp1;
+ rval[2] = y1+y2+y3-1;
+
+ return(0);
+}
+
+/*
+ * Jacobian routine. Compute J(t,y).
+*/
+
+static int Jac(long int Neq, realtype t, realtype cj,
+ N_Vector yy, N_Vector yp, N_Vector resvec,
+ DlsMat J, void *user_data,
+ N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
+{
+ realtype y1, y2, y3;
+ UserData data;
+ realtype p1, p2, p3;
+
+ y1 = Ith(yy,1); y2 = Ith(yy,2); y3 = Ith(yy,3);
+
+ data = (UserData) user_data;
+ p1 = data->p[0]; p2 = data->p[1]; p3 = data->p[2];
+
+ IJth(J,1,1) = p1+cj;
+ IJth(J,2,1) = -p1;
+ IJth(J,3,1) = ONE;
+
+ IJth(J,1,2) = -p2*y3;
+ IJth(J,2,2) = p2*y3+2*p3*y2+cj;
+ IJth(J,3,2) = ONE;
+
+ IJth(J,1,3) = -p2*y2;
+ IJth(J,2,3) = p2*y2;
+ IJth(J,3,3) = ONE;
+
+ return(0);
+}
+
+/*
+ * rhsQ routine. Compute fQ(t,y).
+*/
+
+static int rhsQ(realtype t, N_Vector yy, N_Vector yp, N_Vector qdot, void *user_data)
+{
+ Ith(qdot,1) = Ith(yy,3);
+ return(0);
+}
+
+/*
+ * EwtSet function. Computes the error weights at the current solution.
+ */
+
+static int ewt(N_Vector y, N_Vector w, void *user_data)
+{
+ int i;
+ realtype yy, ww, rtol, atol[3];
+
+ rtol = RTOL;
+ atol[0] = ATOL1;
+ atol[1] = ATOL2;
+ atol[2] = ATOL3;
+
+ for (i=1; i<=3; i++) {
+ yy = Ith(y,i);
+ ww = rtol * ABS(yy) + atol[i-1];
+ if (ww <= 0.0) return (-1);
+ Ith(w,i) = 1.0/ww;
+ }
+
+ return(0);
+}
+
+
+/*
+ * resB routine.
+*/
+
+static int resB(realtype tt,
+ N_Vector yy, N_Vector yp,
+ N_Vector yyB, N_Vector ypB, N_Vector rrB,
+ void *user_dataB)
+{
+ UserData data;
+ realtype y1, y2, y3;
+ realtype p1, p2, p3;
+ realtype l1, l2, l3;
+ realtype lp1, lp2, lp3;
+ 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(yy,1); y2 = Ith(yy,2); y3 = Ith(yy,3);
+
+ /* The lambda vector */
+ l1 = Ith(yyB,1); l2 = Ith(yyB,2); l3 = Ith(yyB,3);
+
+ /* The lambda dot vector */
+ lp1 = Ith(ypB,1); lp2 = Ith(ypB,2); lp3 = Ith(ypB,3);
+
+ /* Temporary variables */
+ l21 = l2-l1;
+ l32 = l3-l2;
+ y23 = y2*y3;
+
+ /* Load residual. */
+ Ith(rrB,1) = lp1 + p1*l21 - l3;
+ Ith(rrB,2) = lp2 - p2*y3*l21 - RCONST(2.0)*p3*y2*l2-l3;
+ Ith(rrB,3) = - p2*y2*l21 -l3 + RCONST(1.0);
+
+ return(0);
+}
+
+/*Jacobian for backward problem. */
+static int JacB(long int NeqB, realtype tt, realtype cj,
+ N_Vector yy, N_Vector yp,
+ N_Vector yyB, N_Vector ypB, N_Vector rrB,
+ DlsMat JB, void *user_data,
+ N_Vector tmp1B, N_Vector tmp2B, N_Vector tmp3B)
+{
+ realtype y1, y2, y3, l1, l2, l3;
+ UserData data;
+ realtype p1, p2, p3;
+
+ y1 = Ith(yy,1); y2 = Ith(yy,2); y3 = Ith(yy,3);
+ l1 = Ith(yyB,1); l2 = Ith(yyB,2); l3 = Ith(yyB,3);
+
+ data = (UserData) user_data;
+ p1 = data->p[0]; p2 = data->p[1]; p3 = data->p[2];
+
+ IJth(JB,1,1) = -p1+cj;
+ IJth(JB,1,2) = p1;
+ IJth(JB,1,3) = -ONE;
+
+ IJth(JB,2,1) = p2*y3;
+ IJth(JB,2,2) = -(p2*y3+RCONST(2.0)*p3*y2)+cj;
+ IJth(JB,2,3) = -ONE;
+
+ IJth(JB,3,1) = p2*y2;
+ IJth(JB,3,2) = -p2*y2;
+ IJth(JB,3,3) = -ONE;
+
+
+ return(0);
+}
+
+static int rhsQB(realtype tt,
+ N_Vector yy, N_Vector yp,
+ N_Vector yyB, N_Vector ypB,
+ N_Vector rrQB, void *user_dataB)
+{
+ UserData data;
+ realtype y1, y2, y3;
+ realtype p1, p2, p3;
+ realtype l1, l2, l3;
+ realtype l21;
+
+ data = (UserData) user_dataB;
+
+ /* The p vector */
+ p1 = data->p[0]; p2 = data->p[1]; p3 = data->p[2];
+
+ /* The y vector */
+ y1 = Ith(yy,1); y2 = Ith(yy,2); y3 = Ith(yy,3);
+
+ /* The lambda vector */
+ l1 = Ith(yyB,1); l2 = Ith(yyB,2); l3 = Ith(yyB,3);
+
+ /* Temporary variables */
+ l21 = l2-l1;
+
+ Ith(rrQB,1) = y1*l21;
+ Ith(rrQB,2) = -y3*y2*l21;
+ Ith(rrQB,3) = -y2*y2*l2;
+
+ return(0);
+}
+
+
+/*
+ *--------------------------------------------------------------------
+ * PRIVATE FUNCTIONS
+ *--------------------------------------------------------------------
+ */
+
+/*
+ * Print results after backward integration
+ */
+
+static void PrintOutput(realtype tfinal, N_Vector yB, N_Vector ypB, N_Vector qB)
+{
+ printf("--------------------------------------------------------\n");
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("tB0: %12.4Le\n",tfinal);
+ printf("dG/dp: %12.4Le %12.4Le %12.4Le\n",
+ -Ith(qB,1), -Ith(qB,2), -Ith(qB,3));
+ printf("lambda(t0): %12.4Le %12.4Le %12.4Le\n",
+ Ith(yB,1), Ith(yB,2), Ith(yB,3));
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("tB0: %12.4le\n",tfinal);
+ printf("dG/dp: %12.4le %12.4le %12.4le\n",
+ -Ith(qB,1), -Ith(qB,2), -Ith(qB,3));
+ printf("lambda(t0): %12.4le %12.4le %12.4le\n",
+ Ith(yB,1), Ith(yB,2), Ith(yB,3));
+#else
+ printf("tB0: %12.4e\n",tfinal);
+ printf("dG/dp: %12.4e %12.4e %12.4e\n",
+ -Ith(qB,1), -Ith(qB,2), -Ith(qB,3));
+ printf("lambda(t0): %12.4e %12.4e %12.4e\n",
+ Ith(yB,1), Ith(yB,2), Ith(yB,3));
+#endif
+ printf("--------------------------------------------------------\n\n");
+}
+
+/*
+ * 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, 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/idasRoberts_ASAi_dns.out b/examples/idas/serial/idasRoberts_ASAi_dns.out
new file mode 100644
index 0000000..3e2a801
--- /dev/null
+++ b/examples/idas/serial/idasRoberts_ASAi_dns.out
@@ -0,0 +1,37 @@
+
+Adjoint Sensitivity Example for Chemical Kinetics
+-------------------------------------------------
+
+DAE: dy1/dt + p1*y1 - p2*y2*y3 = 0
+ dy2/dt - p1*y1 + p2*y2*y3 + p3*(y2)^2 = 0
+ y1 + y2 + y3 = 0
+
+Find dG/dp for
+ G = int_t0^tB0 g(t,p,y) dt
+ g(t,p,y) = y3
+
+
+Create and allocate IDAS memory for forward runs
+Forward integration ... done ( nst = 816 )
+--------------------------------------------------------
+G: 4.0000e+10
+--------------------------------------------------------
+
+Create and allocate IDAS memory for backward run
+Backward integration ... done ( nst = 1272 )
+--------------------------------------------------------
+tB0: 4.0000e+10
+dG/dp: 1.4879e+06 -5.9470e+00 9.9117e-04
+lambda(t0): -2.4998e+01 1.6442e-03 1.0000e+00
+--------------------------------------------------------
+
+Re-initialize IDAS memory for backward run
+Backward integration ... done ( nst = 399 )
+--------------------------------------------------------
+tB0: 5.0000e+01
+dG/dp: 1.7341e+02 -5.0592e-04 8.4323e-08
+lambda(t0): -7.6780e+00 -1.2758e-04 1.0000e+00
+--------------------------------------------------------
+
+Free memory
+
diff --git a/examples/idas/serial/idasRoberts_FSA_dns.c b/examples/idas/serial/idasRoberts_FSA_dns.c
new file mode 100644
index 0000000..68b487c
--- /dev/null
+++ b/examples/idas/serial/idasRoberts_FSA_dns.c
@@ -0,0 +1,788 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.2 $
+ * $Date: 2008/04/15 16:37:37 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Cosmin Petra and Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Example problem:
+ *
+ * This simple example problem for IDA, due to Robertson,
+ * is from chemical kinetics, and consists of the following three
+ * equations:
+ *
+ * dy1/dt = -p1*y1 + p2*y2*y3
+ * dy2/dt = p1*y1 - p2*y2*y3 - p3*y2**2
+ * 0 = y1 + y2 + y3 - 1
+ *
+ * on the interval from t = 0.0 to t = 4.e10, with initial
+ * conditions: y1 = 1, y2 = y3 = 0.The reaction rates are: p1=0.04,
+ * p2=1e4, and p3=3e7
+ *
+ * Optionally, IDAS can compute sensitivities with respect to the
+ * problem parameters p1, p2, and p3.
+ * The sensitivity right hand side is given analytically through the
+ * 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).
+ *
+ * Execution:
+ *
+ * If no sensitivities are desired:
+ * % idasRoberts_FSA_dns -nosensi
+ * If sensitivities are to be computed:
+ * % 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 */
+
+/* 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 */
+#define T0 RCONST(0.0) /* initial time */
+#define T1 RCONST(0.4) /* first output time */
+#define TMULT RCONST(10.0) /* output time factor */
+#define NOUT 12 /* number of output times */
+
+#define NP 3 /* number of problem parameters */
+#define NS 3 /* number of sensitivities computed */
+
+#define ZERO RCONST(0.0)
+#define ONE RCONST(1.0)
+
+/* Type : UserData */
+
+typedef struct {
+ realtype p[3]; /* problem parameters */
+ realtype coef;
+} *UserData;
+
+/* Prototypes of functions by IDAS */
+
+static int res(realtype t, N_Vector y, N_Vector yp, N_Vector resval, void *user_data);
+
+static int resS(int Ns, realtype t,
+ N_Vector y, N_Vector yp, N_Vector resval,
+ N_Vector *yyS, N_Vector *ypS, N_Vector *resvalS,
+ void *user_data,
+ N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
+
+static int rhsQ(realtype tres, N_Vector yy, N_Vector yp,
+ N_Vector rrQ, void *user_data);
+
+/* Prototypes of private functions */
+
+static void ProcessArgs(int argc, char *argv[],
+ booleantype *sensi, int *sensi_meth,
+ booleantype *err_con);
+static void WrongArgs(char *name);
+
+static void PrintIC(N_Vector y, N_Vector yp);
+static void PrintSensIC(N_Vector y, N_Vector yp, N_Vector* yS, N_Vector* ypS);
+
+static void PrintOutput(void *ida_mem, realtype t, N_Vector u);
+static void PrintSensOutput(N_Vector *uS);
+
+static void PrintFinalStats(void *ida_mem, booleantype sensi);
+
+static int check_flag(void *flagvalue, char *funcname, int opt);
+/*
+ *--------------------------------------------------------------------
+ * MAIN PROGRAM
+ *--------------------------------------------------------------------
+ */
+
+int main(int argc, char *argv[])
+{
+ void *ida_mem;
+ UserData data;
+ realtype reltol, t, tout;
+ N_Vector y, yp, abstol, id;
+ int iout, flag;
+
+ realtype pbar[NS];
+ int is;
+ N_Vector *yS, *ypS;
+ booleantype sensi, err_con;
+ int sensi_meth;
+
+ ida_mem = NULL;
+ data = NULL;
+ y = NULL;
+ yS = NULL;
+ ypS = NULL;
+
+ /* Process arguments */
+ ProcessArgs(argc, argv, &sensi, &sensi_meth, &err_con);
+
+ /* User data structure */
+ data = (UserData) malloc(sizeof *data);
+ if (check_flag((void *)data, "malloc", 2)) return(1);
+ data->p[0] = RCONST(0.040);
+ data->p[1] = RCONST(1.0e4);
+ data->p[2] = RCONST(3.0e7);
+ data->coef = 0.5;
+
+ /* Initial conditions */
+ y = N_VNew_Serial(NEQ);
+ if (check_flag((void *)y, "N_VNew_Serial", 0)) return(1);
+
+ Ith(y,1) = ONE;
+ Ith(y,2) = ZERO;
+ Ith(y,3) = ZERO;
+
+ yp = N_VNew_Serial(NEQ);
+ if(check_flag((void *)yp, "N_VNew_Serial", 0)) return(1);
+
+ /* These initial conditions are NOT consistent. See IDACalcIC below. */
+ Ith(yp,1) = RCONST(0.1);
+ Ith(yp,2) = ZERO;
+ Ith(yp,3) = ZERO;
+
+ /* Create IDAS object */
+ ida_mem = IDACreate();
+ if (check_flag((void *)ida_mem, "IDACreate", 0)) return(1);
+
+ /* Allocate space for IDAS */
+ flag = IDAInit(ida_mem, res, T0, y, yp);
+ if (check_flag(&flag, "IDAInit", 1)) return(1);
+
+ /* Specify scalar relative tol. and vector absolute tol. */
+ reltol = RCONST(1.0e-6);
+ abstol = N_VNew_Serial(NEQ);
+ Ith(abstol,1) = RCONST(1.0e-8);
+ Ith(abstol,2) = RCONST(1.0e-14);
+ Ith(abstol,3) = RCONST(1.0e-6);
+ flag = IDASVtolerances(ida_mem, reltol, abstol);
+ if (check_flag(&flag, "IDASVtolerances", 1)) return(1);
+
+ /* Set ID vector */
+ id = N_VNew_Serial(NEQ);
+ Ith(id,1) = 1.0;
+ Ith(id,2) = 1.0;
+ Ith(id,3) = 0.0;
+ flag = IDASetId(ida_mem, id);
+ if (check_flag(&flag, "IDASetId", 1)) return(1);
+
+ /* Attach user data */
+ 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);
+
+ printf("\n3-species chemical kinetics problem\n");
+
+ /* Sensitivity-related settings */
+ if (sensi) {
+
+ 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);
+ 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);
+ for (is=0;is<NS;is++) N_VConst(ZERO, ypS[is]);
+
+ /*
+ * Only non-zero sensitivity I.C. are ypS[0]:
+ * - Ith(ypS[0],1) = -ONE;
+ * - Ith(ypS[0],2) = ONE;
+ *
+ * They are not set. IDACalcIC also computes consistent IC for sensitivities.
+ */
+
+ flag = IDASensInit(ida_mem, NS, sensi_meth, resS, yS, ypS);
+ if(check_flag(&flag, "IDASensInit", 1)) return(1);
+
+ flag = IDASensEEtolerances(ida_mem);
+ if(check_flag(&flag, "IDASensEEtolerances", 1)) return(1);
+
+ flag = IDASetSensErrCon(ida_mem, err_con);
+ if (check_flag(&flag, "IDASetSensErrCon", 1)) return(1);
+
+ flag = IDASetSensParams(ida_mem, data->p, pbar, NULL);
+ if (check_flag(&flag, "IDASetSensParams", 1)) return(1);
+
+ printf("Sensitivity: YES ");
+ if(sensi_meth == IDA_SIMULTANEOUS)
+ printf("( SIMULTANEOUS +");
+ else
+ printf("( STAGGERED +");
+ if(err_con) printf(" FULL ERROR CONTROL )");
+ else printf(" PARTIAL ERROR CONTROL )");
+
+ } else {
+
+ printf("Sensitivity: NO ");
+
+ }
+
+ /*----------------------------------------------------------
+ * Q U A D R A T U R E S
+ * ---------------------------------------------------------*/
+ N_Vector yQ, *yQS;
+ yQ = N_VNew_Serial(2);
+
+ Ith(yQ,1) = 0;
+ Ith(yQ,2) = 0;
+
+ IDAQuadInit(ida_mem, rhsQ, yQ);
+
+ yQS = N_VCloneVectorArray_Serial(NS, yQ);
+ for (is=0;is<NS;is++) N_VConst(ZERO, yQS[is]);
+
+ IDAQuadSensInit(ida_mem, NULL, yQS);
+
+ /* Call IDACalcIC to compute consistent initial conditions. If sensitivity is
+ enabled, this function also try to find consistent IC for the sensitivities. */
+
+ flag = IDACalcIC(ida_mem, IDA_YA_YDP_INIT, T1);;
+ if (check_flag(&flag, "IDACalcIC", 1)) return(1);
+
+ flag = IDAGetConsistentIC(ida_mem, y, yp);
+ if (check_flag(&flag, "IDAGetConsistentIC", 1)) return(1);
+
+ PrintIC(y, yp);
+
+ if(sensi) {
+ IDAGetSensConsistentIC(ida_mem, yS, ypS);
+ PrintSensIC(y, yp, yS, ypS);
+ }
+
+ /* In loop over output points, call IDA, print results, test for error */
+
+ printf("\n\n");
+ printf("===========================================");
+ printf("============================\n");
+ printf(" T Q H NST y1");
+ printf(" y2 y3 \n");
+ printf("===========================================");
+ printf("============================\n");
+
+ for (iout=1, tout=T1; iout <= NOUT; iout++, tout *= TMULT) {
+
+ flag = IDASolve(ida_mem, tout, &t, y, yp, IDA_NORMAL);
+ if (check_flag(&flag, "IDASolve", 1)) break;
+
+ PrintOutput(ida_mem, t, y);
+
+ if (sensi) {
+ flag = IDAGetSens(ida_mem, &t, yS);
+ if (check_flag(&flag, "IDAGetSens", 1)) break;
+ PrintSensOutput(yS);
+ }
+ printf("-----------------------------------------");
+ printf("------------------------------\n");
+
+ }
+
+ printf("\nQuadrature:\n");
+ IDAGetQuad(ida_mem, &t, yQ);
+ printf("G: %10.4e\n", Ith(yQ,1));
+
+ if(sensi) {
+ IDAGetQuadSens(ida_mem, &t, yQS);
+ 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));
+ }
+
+ /* Print final statistics */
+ PrintFinalStats(ida_mem, sensi);
+
+ /* Free memory */
+ N_VDestroy_Serial(y);
+ if (sensi) {
+ N_VDestroyVectorArray_Serial(yS, NS);
+ }
+ free(data);
+ IDAFree(&ida_mem);
+ N_VDestroy_Serial(yQ);
+
+ return(0);
+}
+
+/*
+ *--------------------------------------------------------------------
+ * FUNCTIONS CALLED BY IDAS
+ *--------------------------------------------------------------------
+ */
+
+/*
+ * Residual routine. Compute F(t,y,y',p).
+ */
+static int res(realtype t, N_Vector yy, N_Vector yp, N_Vector resval, void *user_data)
+{
+ UserData data;
+ realtype p1, p2, p3;
+ realtype y1, y2, y3;
+ realtype yp1, yp2, yp3;
+
+ data = (UserData) user_data;
+ p1 = data->p[0];
+ p2 = data->p[1];
+ p3 = data->p[2];
+
+ y1 = Ith(yy,1);
+ y2 = Ith(yy,2);
+ y3 = Ith(yy,3);
+
+ yp1 = Ith(yp,1);
+ yp2 = Ith(yp,2);
+ yp3 = Ith(yp,3);
+
+ Ith(resval,1) = yp1 + p1*y1 - p2*y2*y3;
+ Ith(resval,2) = yp2 - p1*y1 + p2*y2*y3 + p3*y2*y2;
+ Ith(resval,3) = y1 + y2 + y3 - ONE;
+
+ return(0);
+}
+
+
+/*
+ * resS routine. Compute sensitivity r.h.s.
+ */
+
+static int resS(int Ns, realtype t,
+ N_Vector yy, N_Vector yp, N_Vector resval,
+ N_Vector *yyS, N_Vector *ypS, N_Vector *resvalS,
+ void *user_data,
+ N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
+{
+ UserData data;
+ realtype p1, p2, p3;
+ realtype y1, y2, y3;
+ realtype yp1, yp2, yp3;
+ realtype s1, s2, s3;
+ realtype sd1, sd2, sd3;
+ realtype rs1, rs2, rs3;
+ int is;
+
+ data = (UserData) user_data;
+ p1 = data->p[0];
+ p2 = data->p[1];
+ p3 = data->p[2];
+
+ y1 = Ith(yy,1);
+ y2 = Ith(yy,2);
+ y3 = Ith(yy,3);
+
+ yp1 = Ith(yp,1);
+ yp2 = Ith(yp,2);
+ yp3 = Ith(yp,3);
+
+ for (is=0; is<NS; is++) {
+
+ s1 = Ith(yyS[is],1);
+ s2 = Ith(yyS[is],2);
+ s3 = Ith(yyS[is],3);
+
+ sd1 = Ith(ypS[is],1);
+ sd2 = Ith(ypS[is],2);
+ sd3 = Ith(ypS[is],3);
+
+ rs1 = sd1 + p1*s1 - p2*y3*s2 - p2*y2*s3;
+ rs2 = sd2 - p1*s1 + p2*y3*s2 + p2*y2*s3 + 2*p3*y2*s2;
+ rs3 = s1 + s2 + s3;
+
+ switch (is) {
+ case 0:
+ rs1 += y1;
+ rs2 -= y1;
+ break;
+ case 1:
+ rs1 -= y2*y3;
+ rs2 += y2*y3;
+ break;
+ case 2:
+ rs2 += y2*y2;
+ break;
+ }
+
+ Ith(resvalS[is],1) = rs1;
+ Ith(resvalS[is],2) = rs2;
+ Ith(resvalS[is],3) = rs3;
+
+ }
+
+ return(0);
+}
+
+static int rhsQ(realtype t, N_Vector y, N_Vector yp,
+ N_Vector ypQ, void* user_data)
+{
+ UserData data;
+
+ data = (UserData) user_data;
+
+ Ith(ypQ,1) = Ith(y,3);
+
+ Ith(ypQ,2) = data->coef*( Ith(y,1)*Ith(y,1)+
+ Ith(y,2)*Ith(y,2)+
+ Ith(y,3)*Ith(y,3) );
+
+ return(0);
+}
+
+
+/*
+ *--------------------------------------------------------------------
+ * PRIVATE FUNCTIONS
+ *--------------------------------------------------------------------
+ */
+
+/*
+ * Process and verify arguments to idasfwddenx.
+ */
+
+static void ProcessArgs(int argc, char *argv[],
+ booleantype *sensi, int *sensi_meth, booleantype *err_con)
+{
+ *sensi = FALSE;
+ *sensi_meth = -1;
+ *err_con = FALSE;
+
+ if (argc < 2) WrongArgs(argv[0]);
+
+ if (strcmp(argv[1],"-nosensi") == 0)
+ *sensi = FALSE;
+ else if (strcmp(argv[1],"-sensi") == 0)
+ *sensi = TRUE;
+ else
+ WrongArgs(argv[0]);
+
+ if (*sensi) {
+
+ if (argc != 4)
+ WrongArgs(argv[0]);
+
+ if (strcmp(argv[2],"sim") == 0)
+ *sensi_meth = IDA_SIMULTANEOUS;
+ else if (strcmp(argv[2],"stg") == 0)
+ *sensi_meth = IDA_STAGGERED;
+ else
+ WrongArgs(argv[0]);
+
+ if (strcmp(argv[3],"t") == 0)
+ *err_con = TRUE;
+ else if (strcmp(argv[3],"f") == 0)
+ *err_con = FALSE;
+ else
+ WrongArgs(argv[0]);
+ }
+
+}
+
+static void WrongArgs(char *name)
+{
+ printf("\nUsage: %s [-nosensi] [-sensi sensi_meth err_con]\n",name);
+ printf(" sensi_meth = sim or stg\n");
+ printf(" err_con = t or f\n");
+
+ exit(0);
+}
+
+
+static void PrintIC(N_Vector y, N_Vector yp)
+{
+ realtype* data;
+
+ data = NV_DATA_S(y);
+ printf("\n\nConsistent IC:\n");
+ printf("\ty = ");
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("%12.4Le %12.4Le %12.4Le \n", data[0], data[1], data[2]);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("%12.4le %12.4le %12.4le \n", data[0], data[1], data[2]);
+#else
+ printf("%12.4e %12.4e %12.4e \n", data[0], data[1], data[2]);
+#endif
+
+ data = NV_DATA_S(yp);
+ printf("\typ= ");
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("%12.4Le %12.4Le %12.4Le \n", data[0], data[1], data[2]);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("%12.4le %12.4le %12.4le \n", data[0], data[1], data[2]);
+#else
+ printf("%12.4e %12.4e %12.4e \n", data[0], data[1], data[2]);
+#endif
+
+}
+static void PrintSensIC(N_Vector y, N_Vector yp, N_Vector* yS, N_Vector* ypS)
+{
+ realtype *sdata;
+
+ sdata = NV_DATA_S(yS[0]);
+ printf(" Sensitivity 1 ");
+
+ printf("\n\ts1 = ");
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("%12.4Le %12.4Le %12.4Le \n", sdata[0], sdata[1], sdata[2]);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("%12.4le %12.4le %12.4le \n", sdata[0], sdata[1], sdata[2]);
+#else
+ printf("%12.4e %12.4e %12.4e \n", sdata[0], sdata[1], sdata[2]);
+#endif
+ sdata = NV_DATA_S(ypS[0]);
+ printf("\ts1'= ");
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("%12.4Le %12.4Le %12.4Le \n", sdata[0], sdata[1], sdata[2]);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("%12.4le %12.4le %12.4le \n", sdata[0], sdata[1], sdata[2]);
+#else
+ printf("%12.4e %12.4e %12.4e \n", sdata[0], sdata[1], sdata[2]);
+#endif
+
+
+ printf(" Sensitivity 2 ");
+ sdata = NV_DATA_S(yS[1]);
+ printf("\n\ts2 = ");
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("%12.4Le %12.4Le %12.4Le \n", sdata[0], sdata[1], sdata[2]);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("%12.4le %12.4le %12.4le \n", sdata[0], sdata[1], sdata[2]);
+#else
+ printf("%12.4e %12.4e %12.4e \n", sdata[0], sdata[1], sdata[2]);
+#endif
+ sdata = NV_DATA_S(ypS[1]);
+ printf("\ts2'= ");
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("%12.4Le %12.4Le %12.4Le \n", sdata[0], sdata[1], sdata[2]);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("%12.4le %12.4le %12.4le \n", sdata[0], sdata[1], sdata[2]);
+#else
+ printf("%12.4e %12.4e %12.4e \n", sdata[0], sdata[1], sdata[2]);
+#endif
+
+
+ printf(" Sensitivity 3 ");
+ sdata = NV_DATA_S(yS[2]);
+ printf("\n\ts3 = ");
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("%12.4Le %12.4Le %12.4Le \n", sdata[0], sdata[1], sdata[2]);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("%12.4le %12.4le %12.4le \n", sdata[0], sdata[1], sdata[2]);
+#else
+ printf("%12.4e %12.4e %12.4e \n", sdata[0], sdata[1], sdata[2]);
+#endif
+ sdata = NV_DATA_S(ypS[2]);
+ printf("\ts3'= ");
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("%12.4Le %12.4Le %12.4Le \n", sdata[0], sdata[1], sdata[2]);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("%12.4le %12.4le %12.4le \n", sdata[0], sdata[1], sdata[2]);
+#else
+ printf("%12.4e %12.4e %12.4e \n", sdata[0], sdata[1], sdata[2]);
+#endif
+
+
+}
+
+/*
+ * Print current t, step count, order, stepsize, and solution.
+ */
+
+static void PrintOutput(void *ida_mem, realtype t, N_Vector u)
+{
+ long int nst;
+ int qu, flag;
+ realtype hu, *udata;
+
+ udata = NV_DATA_S(u);
+
+ flag = IDAGetNumSteps(ida_mem, &nst);
+ check_flag(&flag, "IDAGetNumSteps", 1);
+ flag = IDAGetLastOrder(ida_mem, &qu);
+ check_flag(&flag, "IDAGetLastOrder", 1);
+ flag = IDAGetLastStep(ida_mem, &hu);
+ check_flag(&flag, "IDAGetLastStep", 1);
+
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("%8.3Le %2d %8.3Le %5ld\n", t, qu, hu, nst);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("%8.3le %2d %8.3le %5ld\n", t, qu, hu, nst);
+#else
+ printf("%8.3e %2d %8.3e %5ld\n", t, qu, hu, nst);
+#endif
+
+ printf(" Solution ");
+
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("%12.4Le %12.4Le %12.4Le \n", udata[0], udata[1], udata[2]);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("%12.4le %12.4le %12.4le \n", udata[0], udata[1], udata[2]);
+#else
+ printf("%12.4e %12.4e %12.4e \n", udata[0], udata[1], udata[2]);
+#endif
+
+}
+
+/*
+ * Print sensitivities.
+*/
+
+static void PrintSensOutput(N_Vector *uS)
+{
+ realtype *sdata;
+
+ sdata = NV_DATA_S(uS[0]);
+ printf(" Sensitivity 1 ");
+
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("%12.4Le %12.4Le %12.4Le \n", sdata[0], sdata[1], sdata[2]);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("%12.4le %12.4le %12.4le \n", sdata[0], sdata[1], sdata[2]);
+#else
+ printf("%12.4e %12.4e %12.4e \n", sdata[0], sdata[1], sdata[2]);
+#endif
+
+ sdata = NV_DATA_S(uS[1]);
+ printf(" Sensitivity 2 ");
+
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("%12.4Le %12.4Le %12.4Le \n", sdata[0], sdata[1], sdata[2]);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("%12.4le %12.4le %12.4le \n", sdata[0], sdata[1], sdata[2]);
+#else
+ printf("%12.4e %12.4e %12.4e \n", sdata[0], sdata[1], sdata[2]);
+#endif
+
+ sdata = NV_DATA_S(uS[2]);
+ printf(" Sensitivity 3 ");
+
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("%12.4Le %12.4Le %12.4Le \n", sdata[0], sdata[1], sdata[2]);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("%12.4le %12.4le %12.4le \n", sdata[0], sdata[1], sdata[2]);
+#else
+ printf("%12.4e %12.4e %12.4e \n", sdata[0], sdata[1], sdata[2]);
+#endif
+}
+
+/*
+ * Print some final statistics from the IDAS memory.
+ */
+
+static void PrintFinalStats(void *ida_mem, booleantype sensi)
+{
+ long int nst;
+ long int nfe, nsetups, nni, ncfn, netf;
+ long int nfSe, nfeS, nsetupsS, nniS, ncfnS, netfS;
+ long int nje, nfeLS;
+ int flag;
+
+ flag = IDAGetNumSteps(ida_mem, &nst);
+ check_flag(&flag, "IDAGetNumSteps", 1);
+ flag = IDAGetNumResEvals(ida_mem, &nfe);
+ check_flag(&flag, "IDAGetNumRhsEvals", 1);
+ flag = IDAGetNumLinSolvSetups(ida_mem, &nsetups);
+ check_flag(&flag, "IDAGetNumLinSolvSetups", 1);
+ flag = IDAGetNumErrTestFails(ida_mem, &netf);
+ check_flag(&flag, "IDAGetNumErrTestFails", 1);
+ flag = IDAGetNumNonlinSolvIters(ida_mem, &nni);
+ check_flag(&flag, "IDAGetNumNonlinSolvIters", 1);
+ flag = IDAGetNumNonlinSolvConvFails(ida_mem, &ncfn);
+ check_flag(&flag, "IDAGetNumNonlinSolvConvFails", 1);
+
+ if (sensi) {
+ flag = IDAGetSensNumResEvals(ida_mem, &nfSe);
+ check_flag(&flag, "IDAGetSensNumRhsEvals", 1);
+ flag = IDAGetNumResEvalsSens(ida_mem, &nfeS);
+ check_flag(&flag, "IDAGetNumResEvalsSens", 1);
+ flag = IDAGetSensNumLinSolvSetups(ida_mem, &nsetupsS);
+ check_flag(&flag, "IDAGetSensNumLinSolvSetups", 1);
+ flag = IDAGetSensNumErrTestFails(ida_mem, &netfS);
+ check_flag(&flag, "IDAGetSensNumErrTestFails", 1);
+ flag = IDAGetSensNumNonlinSolvIters(ida_mem, &nniS);
+ check_flag(&flag, "IDAGetSensNumNonlinSolvIters", 1);
+ flag = IDAGetSensNumNonlinSolvConvFails(ida_mem, &ncfnS);
+ check_flag(&flag, "IDAGetSensNumNonlinSolvConvFails", 1);
+ }
+
+ flag = IDADlsGetNumJacEvals(ida_mem, &nje);
+ check_flag(&flag, "IDADlsGetNumJacEvals", 1);
+ flag = IDADlsGetNumResEvals(ida_mem, &nfeLS);
+ check_flag(&flag, "IDADlsGetNumResEvals", 1);
+
+ printf("\nFinal Statistics\n\n");
+ printf("nst = %5ld\n\n", nst);
+ printf("nfe = %5ld\n", nfe);
+ printf("netf = %5ld nsetups = %5ld\n", netf, nsetups);
+ printf("nni = %5ld ncfn = %5ld\n", nni, ncfn);
+
+ if(sensi) {
+ printf("\n");
+ printf("nfSe = %5ld nfeS = %5ld\n", nfSe, nfeS);
+ printf("netfs = %5ld nsetupsS = %5ld\n", netfS, nsetupsS);
+ printf("nniS = %5ld ncfnS = %5ld\n", nniS, ncfnS);
+ }
+
+ printf("\n");
+ printf("nje = %5ld nfeLS = %5ld\n", nje, nfeLS);
+
+}
+
+/*
+ * 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, 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/idasRoberts_FSA_dns.out b/examples/idas/serial/idasRoberts_FSA_dns.out
new file mode 100644
index 0000000..cb70bb8
--- /dev/null
+++ b/examples/idas/serial/idasRoberts_FSA_dns.out
@@ -0,0 +1,115 @@
+
+3-species chemical kinetics problem
+Sensitivity: YES ( SIMULTANEOUS + FULL ERROR CONTROL )
+
+Consistent IC:
+ y = 1.0000e+00 0.0000e+00 -7.7954e-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
+ Sensitivity 2
+ s2 = 0.0000e+00 0.0000e+00 0.0000e+00
+ s2'= 0.0000e+00 0.0000e+00 0.0000e+00
+ Sensitivity 3
+ s3 = 0.0000e+00 0.0000e+00 0.0000e+00
+ s3'= 0.0000e+00 0.0000e+00 0.0000e+00
+
+
+=======================================================================
+ 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+00 4 1.544e-01 452
+ Solution 9.0552e-01 2.2405e-05 9.4458e-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
+-----------------------------------------------------------------------
+4.000e+01 4 1.280e+00 511
+ 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
+ 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
+ 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
+ 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
+ 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
+ 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
+-----------------------------------------------------------------------
+4.000e+07 5 1.793e+06 974
+ Solution 5.2033e-05 2.0814e-10 9.9995e-01
+ Sensitivity 1 -2.5993e-03 -5.1947e-09 2.5993e-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+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+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
+-----------------------------------------------------------------------
+
+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
+
+Final Statistics
+
+nst = 1064
+
+nfe = 1702
+netf = 19 nsetups = 129
+nni = 1700 ncfn = 12
+
+nfSe = 1702 nfeS = 0
+netfs = 0 nsetupsS = 0
+nniS = 0 ncfnS = 0
+
+nje = 129 nfeLS = 387
diff --git a/examples/idas/serial/idasRoberts_dns.c b/examples/idas/serial/idasRoberts_dns.c
new file mode 100644
index 0000000..b43dac7
--- /dev/null
+++ b/examples/idas/serial/idasRoberts_dns.c
@@ -0,0 +1,402 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.3 $
+ * $Date: 2010/12/01 23:05:10 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Allan Taylor, Alan Hindmarsh and
+ * Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * This simple example problem for IDA, due to Robertson,
+ * is from chemical kinetics, and consists of the following three
+ * equations:
+ *
+ * dy1/dt = -.04*y1 + 1.e4*y2*y3
+ * dy2/dt = .04*y1 - 1.e4*y2*y3 - 3.e7*y2**2
+ * 0 = y1 + y2 + y3 - 1
+ *
+ * on the interval from t = 0.0 to t = 4.e10, with initial
+ * conditions: y1 = 1, y2 = y3 = 0.
+ *
+ * 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.
+ *
+ * The problem is solved with IDA using IDADENSE for the 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>
+
+/* Problem Constants */
+
+#define NEQ 3
+#define NOUT 12
+
+#define ZERO RCONST(0.0);
+#define ONE RCONST(1.0);
+
+/* Macro to define dense matrix elements, indexed from 1. */
+
+#define IJth(A,i,j) DENSE_ELEM(A,i-1,j-1)
+
+/* Prototypes of functions called by IDA */
+
+int resrob(realtype tres, N_Vector yy, N_Vector yp,
+ N_Vector resval, void *user_data);
+
+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,
+ N_Vector yy, N_Vector yp, N_Vector resvec,
+ DlsMat JJ, void *user_data,
+ N_Vector tempv1, N_Vector tempv2, N_Vector tempv3);
+
+/* Prototypes of private functions */
+static void PrintHeader(realtype rtol, N_Vector avtol, N_Vector y);
+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, char *funcname, int opt);
+
+/*
+ *--------------------------------------------------------------------
+ * Main Program
+ *--------------------------------------------------------------------
+ */
+
+int main(void)
+{
+ void *mem;
+ N_Vector yy, yp, avtol;
+ realtype rtol, *yval, *ypval, *atval;
+ realtype t0, tout1, tout, tret;
+ int iout, retval, retvalr;
+ int rootsfound[2];
+
+ mem = NULL;
+ yy = yp = avtol = NULL;
+ yval = ypval = atval = NULL;
+
+ /* Allocate N-vectors. */
+ yy = N_VNew_Serial(NEQ);
+ if(check_flag((void *)yy, "N_VNew_Serial", 0)) return(1);
+ yp = N_VNew_Serial(NEQ);
+ if(check_flag((void *)yp, "N_VNew_Serial", 0)) return(1);
+ avtol = N_VNew_Serial(NEQ);
+ if(check_flag((void *)avtol, "N_VNew_Serial", 0)) return(1);
+
+ /* Create and initialize y, y', and absolute tolerance vectors. */
+ yval = NV_DATA_S(yy);
+ yval[0] = ONE;
+ yval[1] = ZERO;
+ yval[2] = ZERO;
+
+ ypval = NV_DATA_S(yp);
+ ypval[0] = RCONST(-0.04);
+ ypval[1] = RCONST(0.04);
+ ypval[2] = ZERO;
+
+ rtol = RCONST(1.0e-4);
+
+ atval = NV_DATA_S(avtol);
+ atval[0] = RCONST(1.0e-8);
+ atval[1] = RCONST(1.0e-6);
+ atval[2] = RCONST(1.0e-6);
+
+ /* Integration limits */
+ t0 = ZERO;
+ tout1 = RCONST(0.4);
+
+ PrintHeader(rtol, avtol, yy);
+
+ /* Call IDACreate and IDAMalloc 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);
+ 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);
+
+ /* 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) {
+
+ retval = IDASolve(mem, tout, &tret, yy, yp, IDA_NORMAL);
+
+ PrintOutput(mem,tret,yy);
+
+ if(check_flag(&retval, "IDASolve", 1)) return(1);
+
+ if (retval == IDA_ROOT_RETURN) {
+ retvalr = IDAGetRootInfo(mem, rootsfound);
+ check_flag(&retvalr, "IDAGetRootInfo", 1);
+ PrintRootInfo(rootsfound[0],rootsfound[1]);
+ }
+
+ if (retval == IDA_SUCCESS) {
+ iout++;
+ tout *= RCONST(10.0);
+ }
+
+ if (iout == NOUT) break;
+ }
+
+ PrintFinalStats(mem);
+
+ /* Free memory */
+
+ IDAFree(&mem);
+ N_VDestroy_Serial(yy);
+ N_VDestroy_Serial(yp);
+
+ return(0);
+
+}
+
+/*
+ *--------------------------------------------------------------------
+ * Functions called by IDA
+ *--------------------------------------------------------------------
+ */
+
+/*
+ * Define the system residual function.
+ */
+
+int resrob(realtype tres, N_Vector yy, N_Vector yp, N_Vector rr, void *user_data)
+{
+ realtype *yval, *ypval, *rval;
+
+ yval = NV_DATA_S(yy);
+ ypval = NV_DATA_S(yp);
+ rval = NV_DATA_S(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];
+ rval[0] -= ypval[0];
+ rval[2] = yval[0] + yval[1] + yval[2] - ONE;
+
+ return(0);
+}
+
+/*
+ * Root function routine. Compute functions g_i(t,y) for i = 0,1.
+ */
+
+static int grob(realtype t, N_Vector yy, N_Vector yp, realtype *gout,
+ void *user_data)
+{
+ realtype *yval, y1, y3;
+
+ yval = NV_DATA_S(yy);
+ y1 = yval[0]; y3 = yval[2];
+ gout[0] = y1 - RCONST(0.0001);
+ gout[1] = y3 - RCONST(0.01);
+
+ return(0);
+}
+
+/*
+ * Define the Jacobian function.
+ */
+
+int jacrob(long int Neq, realtype tt, realtype cj,
+ N_Vector yy, N_Vector yp, N_Vector resvec,
+ DlsMat JJ, void *user_data,
+ N_Vector tempv1, N_Vector tempv2, N_Vector tempv3)
+{
+ realtype *yval;
+
+ yval = NV_DATA_S(yy);
+
+ IJth(JJ,1,1) = RCONST(-0.04) - cj;
+ IJth(JJ,2,1) = RCONST(0.04);
+ IJth(JJ,3,1) = ONE;
+ IJth(JJ,1,2) = RCONST(1.0e4)*yval[2];
+ IJth(JJ,2,2) = RCONST(-1.0e4)*yval[2] - RCONST(6.0e7)*yval[1] - cj;
+ IJth(JJ,3,2) = ONE;
+ IJth(JJ,1,3) = RCONST(1.0e4)*yval[1];
+ IJth(JJ,2,3) = RCONST(-1.0e4)*yval[1];
+ IJth(JJ,3,3) = ONE;
+
+ return(0);
+}
+
+/*
+ *--------------------------------------------------------------------
+ * Private functions
+ *--------------------------------------------------------------------
+ */
+
+/*
+ * Print first lines of output (problem description)
+ */
+
+static void PrintHeader(realtype rtol, N_Vector avtol, N_Vector y)
+{
+ realtype *atval, *yval;
+
+ atval = NV_DATA_S(avtol);
+ yval = NV_DATA_S(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");
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("Tolerance parameters: rtol = %Lg atol = %Lg %Lg %Lg \n",
+ rtol, atval[0],atval[1],atval[2]);
+ printf("Initial conditions y0 = (%Lg %Lg %Lg)\n",
+ yval[0], yval[1], yval[2]);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("Tolerance parameters: rtol = %lg atol = %lg %lg %lg \n",
+ rtol, atval[0],atval[1],atval[2]);
+ printf("Initial conditions y0 = (%lg %lg %lg)\n",
+ yval[0], yval[1], yval[2]);
+#else
+ printf("Tolerance parameters: rtol = %g atol = %g %g %g \n",
+ rtol, atval[0],atval[1],atval[2]);
+ printf("Initial conditions y0 = (%g %g %g)\n",
+ yval[0], yval[1], yval[2]);
+#endif
+ printf("Constraints and id not used.\n\n");
+ printf("-----------------------------------------------------------------------\n");
+ printf(" t y1 y2 y3");
+ printf(" | nst k h\n");
+ printf("-----------------------------------------------------------------------\n");
+}
+
+/*
+ * Print Output
+ */
+
+static void PrintOutput(void *mem, realtype t, N_Vector y)
+{
+ realtype *yval;
+ int retval, kused;
+ long int nst;
+ realtype hused;
+
+ yval = NV_DATA_S(y);
+
+ retval = IDAGetLastOrder(mem, &kused);
+ check_flag(&retval, "IDAGetLastOrder", 1);
+ retval = IDAGetNumSteps(mem, &nst);
+ check_flag(&retval, "IDAGetNumSteps", 1);
+ retval = IDAGetLastStep(mem, &hused);
+ check_flag(&retval, "IDAGetLastStep", 1);
+#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);
+#elif defined(SUNDIALS_DOUBLE_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
+}
+
+static void PrintRootInfo(int root_f1, int root_f2)
+{
+ printf(" rootsfound[] = %3d %3d\n", root_f1, root_f2);
+ return;
+}
+
+/*
+ * Print final integrator statistics
+ */
+
+static void PrintFinalStats(void *mem)
+{
+ int retval;
+ long int nst, nni, nje, nre, nreLS, netf, ncfn, nge;
+
+ retval = IDAGetNumSteps(mem, &nst);
+ check_flag(&retval, "IDAGetNumSteps", 1);
+ retval = IDAGetNumResEvals(mem, &nre);
+ check_flag(&retval, "IDAGetNumResEvals", 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 = IDADlsGetNumResEvals(mem, &nreLS);
+ check_flag(&retval, "IDADlsGetNumResEvals", 1);
+ 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 Jacobian evaluations = %ld\n", nje);
+ printf("Number of nonlinear iterations = %ld\n", nni);
+ printf("Number of error test failures = %ld\n", netf);
+ printf("Number of nonlinear conv. failures = %ld\n", ncfn);
+ printf("Number of root fn. evaluations = %ld\n", nge);
+}
+
+/*
+ * 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, 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/idas/serial/idasRoberts_dns.out b/examples/idas/serial/idasRoberts_dns.out
new file mode 100644
index 0000000..c2e4d03
--- /dev/null
+++ b/examples/idas/serial/idasRoberts_dns.out
@@ -0,0 +1,38 @@
+
+idasRoberts_dns: Robertson kinetics DAE serial example problem for IDA.
+ Three equation chemical kinetics problem.
+
+Linear solver: IDADENSE, 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.
+
+-----------------------------------------------------------------------
+ t y1 y2 y3 | nst k h
+-----------------------------------------------------------------------
+2.6402e-01 9.8997e-01 3.4706e-05 1.0000e-02 | 27 2 4.4012e-02
+ rootsfound[] = 0 1
+4.0000e-01 9.8517e-01 3.3864e-05 1.4794e-02 | 29 3 8.8024e-02
+4.0000e+00 9.0553e-01 2.2406e-05 9.4452e-02 | 43 4 6.3377e-01
+4.0000e+01 7.1579e-01 9.1838e-06 2.8420e-01 | 68 4 3.1932e+00
+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
+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
+
+Final Run Statistics:
+
+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 = 404
diff --git a/examples/idas/serial/idasSlCrank_FSA_dns.c b/examples/idas/serial/idasSlCrank_FSA_dns.c
new file mode 100644
index 0000000..425637d
--- /dev/null
+++ b/examples/idas/serial/idasSlCrank_FSA_dns.c
@@ -0,0 +1,550 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.3 $
+ * $Date: 2009/04/29 20:40:07 $
+ * -----------------------------------------------------------------
+ * 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 equations of motion are formulated as a system of stabilized
+ * index-2 DAEs (Gear-Gupta-Leimkuhler formulation).
+ *
+ * IDAS also computes sensitivities with respect to the problem
+ * parameters k (spring constant) and c (damper constant) of the
+ * kinetic energy:
+ * G = int_t0^tend g(t,y,p) dt,
+ * 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>
+
+
+#define Ith(v,i) NV_Ith_S(v,i-1) /* i-th vector component i= 1..NEQ */
+
+/* Problem Constants */
+
+#define NEQ 10
+#define NP 2
+
+#define TBEGIN RCONST(0.0)
+#define TEND RCONST(10.000)
+
+#define RTOLF RCONST(1.0e-06)
+#define ATOLF RCONST(1.0e-07)
+
+#define RTOLQ RCONST(1.0e-06)
+#define ATOLQ RCONST(1.0e-08)
+
+#define RTOLFD RCONST(1.0e-06)
+#define ATOLFD RCONST(1.0e-08)
+
+
+#define ZERO RCONST(0.00)
+#define QUARTER RCONST(0.25)
+#define HALF RCONST(0.50)
+#define ONE RCONST(1.00)
+#define TWO RCONST(2.00)
+#define FOUR RCONST(4.00)
+
+typedef struct {
+ realtype a;
+ realtype J1, J2, m1, m2;
+ realtype l0;
+ realtype params[2];
+ realtype F;
+} *UserData;
+
+static int ressc(realtype tres, N_Vector yy, N_Vector yp,
+ N_Vector resval, void *user_data);
+static int rhsQ(realtype t, N_Vector yy, N_Vector yp, N_Vector qdot, void *user_data);
+
+static int rhsQS(int Ns, realtype t, N_Vector yy, N_Vector yp,
+ N_Vector *yyS, N_Vector *ypS, N_Vector rrQ, N_Vector *rhsQS,
+ void *user_data, N_Vector yytmp, N_Vector yptmp, N_Vector tmpQS);
+
+
+static void setIC(N_Vector yy, N_Vector yp, UserData data);
+static void force(N_Vector yy, realtype *Q, UserData data);
+
+static void PrintFinalStats(void *mem);
+static int check_flag(void *flagvalue, char *funcname, int opt);
+/*
+ *--------------------------------------------------------------------
+ * Main Program
+ *--------------------------------------------------------------------
+ */
+
+int main(void)
+{
+ UserData data;
+
+ void *mem;
+ N_Vector yy, yp, id, q, *yyS, *ypS, *qS;
+ realtype tret;
+ realtype pbar[2];
+ realtype dp, G, Gm[2], Gp[2];
+ int flag, is;
+ realtype atolS[NP];
+
+ id = N_VNew_Serial(NEQ);
+ yy = N_VNew_Serial(NEQ);
+ yp = N_VNew_Serial(NEQ);
+ q = N_VNew_Serial(1);
+
+ yyS= N_VCloneVectorArray(NP,yy);
+ ypS= N_VCloneVectorArray(NP,yp);
+ qS = N_VCloneVectorArray_Serial(NP, q);
+
+ data = (UserData) malloc(sizeof *data);
+
+ data->a = 0.5; /* half-length of crank */
+ data->J1 = 1.0; /* crank moment of inertia */
+ data->m2 = 1.0; /* mass of connecting rod */
+ data->m1 = 1.0;
+ data->J2 = 2.0; /* moment of inertia of connecting rod */
+ data->params[0] = 1.0; /* spring constant */
+ data->params[1] = 1.0; /* damper constant */
+ data->l0 = 1.0; /* spring free length */
+ data->F = 1.0; /* external constant force */
+
+ N_VConst(ONE, id);
+ NV_Ith_S(id, 9) = ZERO;
+ NV_Ith_S(id, 8) = ZERO;
+ NV_Ith_S(id, 7) = ZERO;
+ NV_Ith_S(id, 6) = ZERO;
+
+ printf("\nSlider-Crank example for IDAS:\n");
+
+ /* Consistent IC*/
+ setIC(yy, yp, data);
+
+ for (is=0;is<NP;is++) {
+ N_VConst(ZERO, yyS[is]);
+ N_VConst(ZERO, ypS[is]);
+ }
+
+ /* IDA initialization */
+ mem = IDACreate();
+ flag = IDAInit(mem, ressc, TBEGIN, yy, yp);
+ flag = IDASStolerances(mem, RTOLF, ATOLF);
+ flag = IDASetUserData(mem, data);
+ flag = IDASetId(mem, id);
+ flag = IDASetSuppressAlg(mem, TRUE);
+ flag = IDASetMaxNumSteps(mem, 20000);
+
+ /* Call IDADense and set up the linear solver. */
+ flag = IDADense(mem, NEQ);
+
+ 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);
+
+ N_VConst(ZERO, q);
+ flag = IDAQuadInit(mem, rhsQ, q);
+ flag = IDAQuadSStolerances(mem, RTOLQ, ATOLQ);
+ flag = IDASetQuadErrCon(mem, TRUE);
+
+ N_VConst(ZERO, qS[0]);
+ flag = IDAQuadSensInit(mem, rhsQS, qS);
+ atolS[0] = atolS[1] = ATOLQ;
+ flag = IDAQuadSensSStolerances(mem, RTOLQ, atolS);
+ flag = IDASetQuadSensErrCon(mem, TRUE);
+
+
+ /* Perform forward run */
+ printf("\nForward integration ... ");
+
+ flag = IDASolve(mem, TEND, &tret, yy, yp, IDA_NORMAL);
+ if (check_flag(&flag, "IDASolve", 1)) return(1);
+
+ printf("done!\n");
+
+ PrintFinalStats(mem);
+
+ IDAGetQuad(mem, &tret, q);
+ printf("--------------------------------------------\n");
+ printf(" G = %24.16f\n", Ith(q,1));
+ printf("--------------------------------------------\n\n");
+
+ IDAGetQuadSens(mem, &tret, qS);
+ printf("-------------F O R W A R D------------------\n");
+ printf(" dG/dp: %12.4le %12.4le\n", Ith(qS[0],1), Ith(qS[1],1));
+ printf("--------------------------------------------\n\n");
+
+ IDAFree(&mem);
+
+
+
+ /* Finite differences for dG/dp */
+ dp = 0.00001;
+ data->params[0] = ONE;
+ data->params[1] = ONE;
+
+ mem = IDACreate();
+
+ setIC(yy, yp, data);
+ flag = IDAInit(mem, ressc, TBEGIN, yy, yp);
+ 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);
+
+ N_VConst(ZERO, q);
+ IDAQuadInit(mem, rhsQ, q);
+ IDAQuadSStolerances(mem, RTOLQ, ATOLQ);
+ IDASetQuadErrCon(mem, TRUE);
+
+ IDASolve(mem, TEND, &tret, yy, yp, IDA_NORMAL);
+
+ IDAGetQuad(mem,&tret,q);
+ G = Ith(q,1);
+ /*printf(" G =%12.6e\n", Ith(q,1));*/
+
+ /******************************
+ * BACKWARD for k
+ ******************************/
+ data->params[0] -= dp;
+ setIC(yy, yp, data);
+
+ IDAReInit(mem, TBEGIN, yy, yp);
+
+ N_VConst(ZERO, q);
+ IDAQuadReInit(mem, q);
+
+ IDASolve(mem, TEND, &tret, yy, yp, IDA_NORMAL);
+ IDAGetQuad(mem, &tret, q);
+ Gm[0] = Ith(q,1);
+ /*printf("Gm[0]=%12.6e\n", Ith(q,1));*/
+
+ /****************************
+ * FORWARD for k *
+ ****************************/
+ data->params[0] += (TWO*dp);
+ setIC(yy, yp, data);
+ IDAReInit(mem, TBEGIN, yy, yp);
+
+ N_VConst(ZERO, q);
+ IDAQuadReInit(mem, q);
+
+ IDASolve(mem, TEND, &tret, yy, yp, IDA_NORMAL);
+ IDAGetQuad(mem, &tret, q);
+ Gp[0] = Ith(q,1);
+ /*printf("Gp[0]=%12.6e\n", Ith(q,1));*/
+
+
+ /* Backward for c */
+ data->params[0] = ONE;
+ data->params[1] -= dp;
+ setIC(yy, yp, data);
+ IDAReInit(mem, TBEGIN, yy, yp);
+
+ N_VConst(ZERO, q);
+ IDAQuadReInit(mem, q);
+
+ IDASolve(mem, TEND, &tret, yy, yp, IDA_NORMAL);
+ IDAGetQuad(mem, &tret, q);
+ Gm[1] = Ith(q,1);
+
+ /* Forward for c */
+ data->params[1] += (TWO*dp);
+ setIC(yy, yp, data);
+ IDAReInit(mem, TBEGIN, yy, yp);
+
+ N_VConst(ZERO, q);
+ IDAQuadReInit(mem, q);
+
+ IDASolve(mem, TEND, &tret, yy, yp, IDA_NORMAL);
+ IDAGetQuad(mem, &tret, q);
+ Gp[1] = Ith(q,1);
+
+ IDAFree(&mem);
+
+ printf("\n\n Checking using Finite Differences \n\n");
+
+ printf("---------------BACKWARD------------------\n");
+ printf(" dG/dp: %12.4le %12.4le\n", (G-Gm[0])/dp, (G-Gm[1])/dp);
+ printf("-----------------------------------------\n\n");
+
+ printf("---------------FORWARD-------------------\n");
+ printf(" dG/dp: %12.4le %12.4le\n", (Gp[0]-G)/dp, (Gp[1]-G)/dp);
+ printf("-----------------------------------------\n\n");
+
+ printf("--------------CENTERED-------------------\n");
+ printf(" dG/dp: %12.4le %12.4le\n", (Gp[0]-Gm[0])/(TWO*dp) ,(Gp[1]-Gm[1])/(TWO*dp));
+ printf("-----------------------------------------\n\n");
+
+
+ /* Free memory */
+ free(data);
+
+ N_VDestroy(id);
+ N_VDestroy_Serial(yy);
+ N_VDestroy_Serial(yp);
+ N_VDestroy_Serial(q);
+ return(0);
+
+}
+
+static void setIC(N_Vector yy, N_Vector yp, UserData data)
+{
+ realtype pi;
+ realtype a, J1, m2, J2;
+ realtype q, p, x;
+ realtype Q[3];
+
+ N_VConst(ZERO, yy);
+ N_VConst(ZERO, yp);
+
+ pi = FOUR*atan(ONE);
+
+ a = data->a;
+ J1 = data->J1;
+ m2 = data->m2;
+ J2 = data->J2;
+
+ q = pi/TWO;
+ p = asin(-a);
+ x = cos(p);
+
+ NV_Ith_S(yy,0) = q;
+ NV_Ith_S(yy,1) = x;
+ NV_Ith_S(yy,2) = p;
+
+ force(yy, Q, data);
+
+ NV_Ith_S(yp,3) = Q[0]/J1;
+ NV_Ith_S(yp,4) = Q[1]/m2;
+ NV_Ith_S(yp,5) = Q[2]/J2;
+
+}
+
+static void force(N_Vector yy, realtype *Q, UserData data)
+{
+ realtype a, k, c, l0, F;
+ realtype q, x, p;
+ realtype qd, xd, pd;
+ realtype s1, c1, s2, c2, s21, c21;
+ realtype l2, l, ld;
+ realtype f, fl;
+
+ a = data->a;
+ k = data->params[0];
+ c = data->params[1];
+ l0 = data->l0;
+ F = data->F;
+
+ q = NV_Ith_S(yy,0);
+ x = NV_Ith_S(yy,1);
+ p = NV_Ith_S(yy,2);
+
+ qd = NV_Ith_S(yy,3);
+ xd = NV_Ith_S(yy,4);
+ pd = NV_Ith_S(yy,5);
+
+ s1 = sin(q);
+ c1 = cos(q);
+ s2 = sin(p);
+ c2 = cos(p);
+ s21 = s2*c1 - c2*s1;
+ c21 = c2*c1 + s2*s1;
+
+ l2 = x*x - x*(c2+a*c1) + (ONE + a*a)/FOUR + a*c21/TWO;
+ l = RSqrt(l2);
+ ld = TWO*x*xd - xd*(c2+a*c1) + x*(s2*pd+a*s1*qd) - a*s21*(pd-qd)/TWO;
+ ld /= TWO*l;
+
+ f = k*(l-l0) + c*ld;
+ fl = f/l;
+
+ Q[0] = - fl * a * (s21/TWO + x*s1) / TWO;
+ Q[1] = fl * (c2/TWO - x + a*c1/TWO) + F;
+ Q[2] = - fl * (x*s2 - a*s21/TWO) / TWO - F*s2;
+
+}
+
+static int ressc(realtype tres, N_Vector yy, N_Vector yp, N_Vector rr, void *user_data)
+{
+ UserData data;
+ realtype Q[3];
+ realtype a, J1, m2, J2;
+ realtype *yval, *ypval, *rval;
+ realtype q, x, p;
+ realtype qd, xd, pd;
+ realtype lam1, lam2, mu1, mu2;
+ realtype s1, c1, s2, c2;
+
+ data = (UserData) user_data;
+
+ a = data->a;
+ J1 = data->J1;
+ m2 = data->m2;
+ J2 = data->J2;
+
+ yval = NV_DATA_S(yy);
+ ypval = NV_DATA_S(yp);
+ rval = NV_DATA_S(rr);
+
+ q = yval[0];
+ x = yval[1];
+ p = yval[2];
+
+ qd = yval[3];
+ xd = yval[4];
+ pd = yval[5];
+
+ lam1 = yval[6];
+ lam2 = yval[7];
+
+ mu1 = yval[8];
+ mu2 = yval[9];
+
+ s1 = sin(q);
+ c1 = cos(q);
+ s2 = sin(p);
+ c2 = cos(p);
+
+ force(yy, Q, data);
+
+ rval[0] = ypval[0] - qd + a*s1*mu1 - a*c1*mu2;
+ rval[1] = ypval[1] - xd + mu1;
+ rval[2] = ypval[2] - pd + s2*mu1 - c2*mu2;
+
+ rval[3] = J1*ypval[3] - Q[0] + a*s1*lam1 - a*c1*lam2;
+ rval[4] = m2*ypval[4] - Q[1] + lam1;
+ rval[5] = J2*ypval[5] - Q[2] + s2*lam1 - c2*lam2;
+
+ rval[6] = x - c2 - a*c1;
+ rval[7] = -s2 - a*s1;
+
+ rval[8] = a*s1*qd + xd + s2*pd;
+ rval[9] = -a*c1*qd - c2*pd;
+
+ return(0);
+}
+
+static int rhsQ(realtype t, N_Vector yy, N_Vector yp, N_Vector qdot, void *user_data)
+{
+ realtype v1, v2, v3;
+ realtype m1, J1, m2, J2, a;
+ UserData data;
+
+ data = (UserData) user_data;
+ J1 = data->J1;
+ m1 = data->m1;
+ m2 = data->m2;
+ J2 = data->J2;
+ a = data->a;
+
+ v1 = Ith(yy,4);
+ v2 = Ith(yy,5);
+ v3 = Ith(yy,6);
+
+ Ith(qdot,1) = HALF*(J1*v1*v1 + m2*v2*v2 + J2*v3*v3);
+
+ return(0);
+}
+
+static int rhsQS(int Ns, realtype t, N_Vector yy, N_Vector yp,
+ N_Vector *yyS, N_Vector *ypS, N_Vector rrQ, N_Vector *rhsQS,
+ void *user_data, N_Vector yytmp, N_Vector yptmp, N_Vector tmpQS)
+{
+ realtype v1, v2, v3;
+ realtype m1, J1, m2, J2, a;
+ UserData data;
+ realtype s1, s2, s3;
+
+ data = (UserData) user_data;
+ J1 = data->J1;
+ m1 = data->m1;
+ m2 = data->m2;
+ J2 = data->J2;
+ a = data->a;
+
+ v1 = Ith(yy,4);
+ v2 = Ith(yy,5);
+ v3 = Ith(yy,6);
+
+ /* Sensitivities of v. */
+ s1 = Ith(yyS[0],4);
+ s2 = Ith(yyS[0],5);
+ s3 = Ith(yyS[0],6);
+
+ Ith(rhsQS[0], 1) = J1*v1*s1 + m2*v2*s2 + J2*v3*s3;
+
+ s1 = Ith(yyS[1],4);
+ s2 = Ith(yyS[1],5);
+ s3 = Ith(yyS[1],6);
+
+ Ith(rhsQS[1], 1) = J1*v1*s1 + m2*v2*s2 + J2*v3*s3;
+
+ return(0);
+}
+
+static void PrintFinalStats(void *mem)
+{
+ int flag;
+ long int nst, nni, nje, nre, nreLS, netf, ncfn;
+
+ flag = IDAGetNumSteps(mem, &nst);
+ flag = IDAGetNumResEvals(mem, &nre);
+ flag = IDADlsGetNumJacEvals(mem, &nje);
+ flag = IDAGetNumNonlinSolvIters(mem, &nni);
+ flag = IDAGetNumErrTestFails(mem, &netf);
+ flag = IDAGetNumNonlinSolvConvFails(mem, &ncfn);
+ flag = IDADlsGetNumResEvals(mem, &nreLS);
+
+ 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 Jacobian evaluations = %ld\n", nje);
+ printf("Number of nonlinear iterations = %ld\n", nni);
+ printf("Number of error test failures = %ld\n", netf);
+ printf("Number of nonlinear conv. failures = %ld\n", ncfn);
+}
+
+
+static int check_flag(void *flagvalue, 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/idasSlCrank_FSA_dns.out b/examples/idas/serial/idasSlCrank_FSA_dns.out
new file mode 100644
index 0000000..103893c
--- /dev/null
+++ b/examples/idas/serial/idasSlCrank_FSA_dns.out
@@ -0,0 +1,37 @@
+
+Slider-Crank example for IDAS:
+
+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 error test failures = 0
+Number of nonlinear conv. failures = 1
+--------------------------------------------
+ G = 3.3366156512592133
+--------------------------------------------
+
+-------------F O R W A R D------------------
+ dG/dp: 3.3346e-01 -3.6375e-01
+--------------------------------------------
+
+
+
+ Checking using Finite Differences
+
+---------------BACKWARD------------------
+ dG/dp: 3.3345e-01 -3.6375e-01
+-----------------------------------------
+
+---------------FORWARD-------------------
+ dG/dp: 3.3345e-01 -3.6375e-01
+-----------------------------------------
+
+--------------CENTERED-------------------
+ dG/dp: 3.3345e-01 -3.6375e-01
+-----------------------------------------
+
diff --git a/examples/idas/serial/idasSlCrank_dns.c b/examples/idas/serial/idasSlCrank_dns.c
new file mode 100644
index 0000000..999c96b
--- /dev/null
+++ b/examples/idas/serial/idasSlCrank_dns.c
@@ -0,0 +1,433 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.4 $
+ * $Date: 2009/09/30 23:33:29 $
+ * -----------------------------------------------------------------
+ * 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 equations of motion are formulated as a system of stabilized
+ * index-2 DAEs (Gear-Gupta-Leimkuhler formulation).
+ *
+ * IDAS also computes the average kinetic energy as the quadrature:
+ * G = int_t0^tend g(t,y,p) dt,
+ * 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>
+
+
+#define Ith(v,i) NV_Ith_S(v,i-1) /* i-th vector component i= 1..NEQ */
+
+/* Problem Constants */
+
+#define NEQ 10
+
+#define TBEGIN RCONST(0.0)
+#define TEND RCONST(10.0)
+
+#define NOUT 25
+
+#define RTOLF RCONST(1.0e-06)
+#define ATOLF RCONST(1.0e-07)
+
+#define RTOLQ RCONST(1.0e-06)
+#define ATOLQ RCONST(1.0e-08)
+
+#define ZERO RCONST(0.00)
+#define QUARTER RCONST(0.25)
+#define HALF RCONST(0.50)
+#define ONE RCONST(1.00)
+#define TWO RCONST(2.00)
+#define FOUR RCONST(4.00)
+
+typedef struct {
+ realtype a;
+ realtype J1, J2, m1, m2;
+ realtype l0;
+ realtype params[2];
+ realtype F;
+} *UserData;
+
+static int ressc(realtype tres, N_Vector yy, N_Vector yp,
+ N_Vector resval, void *user_data);
+static int rhsQ(realtype t, N_Vector yy, N_Vector yp, N_Vector qdot, void *user_data);
+
+static void setIC(N_Vector yy, N_Vector yp, UserData data);
+static void force(N_Vector yy, realtype *Q, UserData data);
+
+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, char *funcname, int opt);
+/*
+ *--------------------------------------------------------------------
+ * Main Program
+ *--------------------------------------------------------------------
+ */
+
+int main(void)
+{
+ UserData data;
+
+ void *mem;
+ N_Vector yy, yp, id, q;
+ realtype tret, tout;
+ int flag;
+
+ id = N_VNew_Serial(NEQ);
+ yy = N_VNew_Serial(NEQ);
+ yp = N_VNew_Serial(NEQ);
+ q = N_VNew_Serial(1);
+
+ data = (UserData) malloc(sizeof *data);
+
+ data->a = 0.5; /* half-length of crank */
+ data->J1 = 1.0; /* crank moment of inertia */
+ data->m2 = 1.0; /* mass of connecting rod */
+ data->m1 = 1.0;
+ data->J2 = 2.0; /* moment of inertia of connecting rod */
+ data->params[0] = 1.0; /* spring constant */
+ data->params[1] = 1.0; /* damper constant */
+ data->l0 = 1.0; /* spring free length */
+ data->F = 1.0; /* external constant force */
+
+ N_VConst(ONE, id);
+ NV_Ith_S(id, 9) = ZERO;
+ NV_Ith_S(id, 8) = ZERO;
+ NV_Ith_S(id, 7) = ZERO;
+ NV_Ith_S(id, 6) = ZERO;
+
+ /* Consistent IC*/
+ setIC(yy, yp, data);
+
+ /* IDAS initialization */
+ mem = IDACreate();
+ flag = IDAInit(mem, ressc, TBEGIN, yy, yp);
+ flag = IDASStolerances(mem, RTOLF, ATOLF);
+ flag = IDASetUserData(mem, data);
+ flag = IDASetId(mem, id);
+ flag = IDASetSuppressAlg(mem, TRUE);
+ flag = IDASetMaxNumSteps(mem, 20000);
+
+ /* Call IDADense and set up the linear solver. */
+ flag = IDADense(mem, NEQ);
+
+ N_VConst(ZERO, q);
+ flag = IDAQuadInit(mem, rhsQ, q);
+ flag = IDAQuadSStolerances(mem, RTOLQ, ATOLQ);
+ flag = IDASetQuadErrCon(mem, TRUE);
+
+ PrintHeader(RTOLF, ATOLF, yy);
+
+ /* Print initial states */
+ PrintOutput(mem,0.0,yy);
+
+ /* Perform forward run */
+ tout = TEND/NOUT;
+
+ while (1) {
+
+ flag = IDASolve(mem, tout, &tret, yy, yp, IDA_NORMAL);
+ if (check_flag(&flag, "IDASolve", 1)) return(1);
+
+ PrintOutput(mem,tret,yy);
+
+ tout += TEND/NOUT;
+
+ if (tret > TEND) break;
+ }
+
+ PrintFinalStats(mem);
+
+ IDAGetQuad(mem, &tret, q);
+ printf("--------------------------------------------\n");
+ printf(" G = %24.16f\n", Ith(q,1));
+ printf("--------------------------------------------\n\n");
+
+ IDAFree(&mem);
+
+ /* Free memory */
+
+ free(data);
+ N_VDestroy(id);
+ N_VDestroy_Serial(yy);
+ N_VDestroy_Serial(yp);
+ N_VDestroy_Serial(q);
+
+ return(0);
+}
+
+static void setIC(N_Vector yy, N_Vector yp, UserData data)
+{
+ realtype pi;
+ realtype a, J1, m2, J2;
+ realtype q, p, x;
+ realtype Q[3];
+
+ N_VConst(ZERO, yy);
+ N_VConst(ZERO, yp);
+
+ pi = FOUR*atan(ONE);
+
+ a = data->a;
+ J1 = data->J1;
+ m2 = data->m2;
+ J2 = data->J2;
+
+ q = pi/TWO;
+ p = asin(-a);
+ x = cos(p);
+
+ NV_Ith_S(yy,0) = q;
+ NV_Ith_S(yy,1) = x;
+ NV_Ith_S(yy,2) = p;
+
+ force(yy, Q, data);
+
+ NV_Ith_S(yp,3) = Q[0]/J1;
+ NV_Ith_S(yp,4) = Q[1]/m2;
+ NV_Ith_S(yp,5) = Q[2]/J2;
+
+}
+
+static void force(N_Vector yy, realtype *Q, UserData data)
+{
+ realtype a, k, c, l0, F;
+ realtype q, x, p;
+ realtype qd, xd, pd;
+ realtype s1, c1, s2, c2, s21, c21;
+ realtype l2, l, ld;
+ realtype f, fl;
+
+ a = data->a;
+ k = data->params[0];
+ c = data->params[1];
+ l0 = data->l0;
+ F = data->F;
+
+ q = NV_Ith_S(yy,0);
+ x = NV_Ith_S(yy,1);
+ p = NV_Ith_S(yy,2);
+
+ qd = NV_Ith_S(yy,3);
+ xd = NV_Ith_S(yy,4);
+ pd = NV_Ith_S(yy,5);
+
+ s1 = sin(q);
+ c1 = cos(q);
+ s2 = sin(p);
+ c2 = cos(p);
+ s21 = s2*c1 - c2*s1;
+ c21 = c2*c1 + s2*s1;
+
+ l2 = x*x - x*(c2+a*c1) + (ONE + a*a)/FOUR + a*c21/TWO;
+ l = RSqrt(l2);
+ ld = TWO*x*xd - xd*(c2+a*c1) + x*(s2*pd+a*s1*qd) - a*s21*(pd-qd)/TWO;
+ ld /= TWO*l;
+
+ f = k*(l-l0) + c*ld;
+ fl = f/l;
+
+ Q[0] = - fl * a * (s21/TWO + x*s1) / TWO;
+ Q[1] = fl * (c2/TWO - x + a*c1/TWO) + F;
+ Q[2] = - fl * (x*s2 - a*s21/TWO) / TWO - F*s2;
+
+}
+
+static int ressc(realtype tres, N_Vector yy, N_Vector yp, N_Vector rr, void *user_data)
+{
+ UserData data;
+ realtype Q[3];
+ realtype a, J1, m2, J2;
+ realtype *yval, *ypval, *rval;
+ realtype q, x, p;
+ realtype qd, xd, pd;
+ realtype lam1, lam2, mu1, mu2;
+ realtype s1, c1, s2, c2;
+
+ data = (UserData) user_data;
+
+ a = data->a;
+ J1 = data->J1;
+ m2 = data->m2;
+ J2 = data->J2;
+
+ yval = NV_DATA_S(yy);
+ ypval = NV_DATA_S(yp);
+ rval = NV_DATA_S(rr);
+
+ q = yval[0];
+ x = yval[1];
+ p = yval[2];
+
+ qd = yval[3];
+ xd = yval[4];
+ pd = yval[5];
+
+ lam1 = yval[6];
+ lam2 = yval[7];
+
+ mu1 = yval[8];
+ mu2 = yval[9];
+
+ s1 = sin(q);
+ c1 = cos(q);
+ s2 = sin(p);
+ c2 = cos(p);
+
+ force(yy, Q, data);
+
+ rval[0] = ypval[0] - qd + a*s1*mu1 - a*c1*mu2;
+ rval[1] = ypval[1] - xd + mu1;
+ rval[2] = ypval[2] - pd + s2*mu1 - c2*mu2;
+
+ rval[3] = J1*ypval[3] - Q[0] + a*s1*lam1 - a*c1*lam2;
+ rval[4] = m2*ypval[4] - Q[1] + lam1;
+ rval[5] = J2*ypval[5] - Q[2] + s2*lam1 - c2*lam2;
+
+ rval[6] = x - c2 - a*c1;
+ rval[7] = -s2 - a*s1;
+
+ rval[8] = a*s1*qd + xd + s2*pd;
+ rval[9] = -a*c1*qd - c2*pd;
+
+ return(0);
+}
+
+static int rhsQ(realtype t, N_Vector yy, N_Vector yp, N_Vector qdot, void *user_data)
+{
+ realtype v1, v2, v3;
+ realtype m1, J1, m2, J2, a;
+ UserData data;
+
+ data = (UserData) user_data;
+ J1 = data->J1;
+ m1 = data->m1;
+ m2 = data->m2;
+ J2 = data->J2;
+ a = data->a;
+
+ v1 = Ith(yy,4);
+ v2 = Ith(yy,5);
+ v3 = Ith(yy,6);
+
+ Ith(qdot,1) = HALF*(J1*v1*v1 + m2*v2*v2 + J2*v3*v3);
+
+ return(0);
+}
+
+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");
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("Tolerance parameters: rtol = %Lg atol = %Lg\n",
+ rtol, avtol);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("Tolerance parameters: rtol = %lg atol = %lg\n",
+ rtol, avtol);
+#else
+ printf("Tolerance parameters: rtol = %g atol = %g\n",
+ rtol, avtol);
+#endif
+ printf("-----------------------------------------------------------------------\n");
+ printf(" t y1 y2 y3");
+ printf(" | nst k h\n");
+ printf("-----------------------------------------------------------------------\n");
+}
+
+
+static void PrintOutput(void *mem, realtype t, N_Vector y)
+{
+ realtype *yval;
+ int retval, kused;
+ long int nst;
+ realtype hused;
+
+ yval = NV_DATA_S(y);
+
+ retval = IDAGetLastOrder(mem, &kused);
+ check_flag(&retval, "IDAGetLastOrder", 1);
+ retval = IDAGetNumSteps(mem, &nst);
+ check_flag(&retval, "IDAGetNumSteps", 1);
+ retval = IDAGetLastStep(mem, &hused);
+ check_flag(&retval, "IDAGetLastStep", 1);
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("%5.2Lf %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("%5.2lf %12.4le %12.4le %12.4le | %3ld %1d %12.4le\n",
+ t, yval[0], yval[1], yval[2], nst, kused, hused);
+#else
+ printf("%5.2f %12.4e %12.4e %12.4e | %3ld %1d %12.4e\n",
+ t, yval[0], yval[1], yval[2], nst, kused, hused);
+#endif
+}
+
+
+static void PrintFinalStats(void *mem)
+{
+ int flag;
+ long int nst, nni, nje, nre, nreLS, netf, ncfn;
+
+ flag = IDAGetNumSteps(mem, &nst);
+ flag = IDAGetNumResEvals(mem, &nre);
+ flag = IDADlsGetNumJacEvals(mem, &nje);
+ flag = IDAGetNumNonlinSolvIters(mem, &nni);
+ flag = IDAGetNumErrTestFails(mem, &netf);
+ flag = IDAGetNumNonlinSolvConvFails(mem, &ncfn);
+ flag = IDADlsGetNumResEvals(mem, &nreLS);
+
+ 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 Jacobian evaluations = %ld\n", nje);
+ printf("Number of nonlinear iterations = %ld\n", nni);
+ printf("Number of error test failures = %ld\n", netf);
+ printf("Number of nonlinear conv. failures = %ld\n", ncfn);
+}
+
+static int check_flag(void *flagvalue, 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/idasSlCrank_dns.out b/examples/idas/serial/idasSlCrank_dns.out
new file mode 100644
index 0000000..0bfcbf2
--- /dev/null
+++ b/examples/idas/serial/idasSlCrank_dns.out
@@ -0,0 +1,46 @@
+
+idasSlCrank_dns: Slider-Crank DAE serial example problem for IDAS
+Linear solver: IDADENSE, Jacobian is computed by IDAS.
+Tolerance parameters: rtol = 1e-06 atol = 1e-07
+-----------------------------------------------------------------------
+ t y1 y2 y3 | nst k h
+-----------------------------------------------------------------------
+ 0.00 1.5708e+00 8.6603e-01 -5.2360e-01 | 0 0 0.0000e+00
+ 0.40 1.5299e+00 8.8672e-01 -5.2312e-01 | 40 5 4.6748e-02
+ 0.80 1.4072e+00 9.5128e-01 -5.1591e-01 | 48 5 4.6748e-02
+ 1.20 1.2039e+00 1.0638e+00 -4.8559e-01 | 57 5 3.7866e-02
+ 1.60 9.2524e-01 1.2176e+00 -4.1084e-01 | 68 4 3.4080e-02
+ 2.00 5.7904e-01 1.3803e+00 -2.7714e-01 | 78 5 6.8159e-02
+ 2.40 1.7783e-01 1.4882e+00 -8.8565e-02 | 86 5 4.3666e-02
+ 2.80 -2.4460e-01 1.4778e+00 1.2138e-01 | 96 5 3.9299e-02
+ 3.20 -6.3618e-01 1.3570e+00 3.0161e-01 | 107 5 3.1832e-02
+ 3.60 -9.6169e-01 1.1981e+00 4.2254e-01 | 121 5 2.8649e-02
+ 4.00 -1.2064e+00 1.0623e+00 4.8609e-01 | 128 5 5.7298e-02
+ 4.40 -1.3632e+00 9.7518e-01 5.1125e-01 | 136 5 4.6412e-02
+ 4.80 -1.4300e+00 9.3903e-01 5.1789e-01 | 146 5 4.1770e-02
+ 5.20 -1.4081e+00 9.5081e-01 5.1599e-01 | 155 5 4.1770e-02
+ 5.60 -1.2995e+00 1.0103e+00 5.0261e-01 | 164 5 8.3541e-02
+ 6.00 -1.1080e+00 1.1176e+00 4.6386e-01 | 169 5 7.5187e-02
+ 6.40 -8.4049e-01 1.2616e+00 3.8168e-01 | 175 5 7.5187e-02
+ 6.80 -5.0621e-01 1.4075e+00 2.4487e-01 | 180 5 6.0901e-02
+ 7.20 -1.2091e-01 1.4945e+00 6.0346e-02 | 188 5 4.4397e-02
+ 7.60 2.7894e-01 1.4712e+00 -1.3811e-01 | 198 5 3.5962e-02
+ 8.00 6.4422e-01 1.3536e+00 -3.0500e-01 | 211 5 2.8980e-02
+ 8.40 9.4289e-01 1.2082e+00 -4.1657e-01 | 220 5 5.2163e-02
+ 8.80 1.1604e+00 1.0882e+00 -4.7630e-01 | 227 5 5.2163e-02
+ 9.20 1.2895e+00 1.0159e+00 -5.0105e-01 | 235 5 5.2163e-02
+ 9.60 1.3276e+00 9.9477e-01 -5.0669e-01 | 243 5 4.6947e-02
+10.00 1.2757e+00 1.0236e+00 -4.9881e-01 | 251 5 4.6947e-02
+
+Final Run Statistics:
+
+Number of steps = 251
+Number of residual evaluations = 1066
+Number of Jacobian evaluations = 39
+Number of nonlinear iterations = 676
+Number of error test failures = 1
+Number of nonlinear conv. failures = 0
+--------------------------------------------
+ G = 3.3366160663212514
+--------------------------------------------
+
diff --git a/examples/kinsol/fcmix_parallel/CMakeLists.txt b/examples/kinsol/fcmix_parallel/CMakeLists.txt
new file mode 100644
index 0000000..0141694
--- /dev/null
+++ b/examples/kinsol/fcmix_parallel/CMakeLists.txt
@@ -0,0 +1,119 @@
+# ---------------------------------------------------------------
+# $Revision: 1.4 $
+# $Date: 2009/02/17 02:58:47 $
+# ---------------------------------------------------------------
+# Programmer: Radu Serban @ LLNL
+# ---------------------------------------------------------------
+# Copyright (c) 2007, The Regents of the University of California.
+# Produced at the Lawrence Livermore National Laboratory.
+# All rights reserved.
+# For details, see the LICENSE file.
+# ---------------------------------------------------------------
+# CMakeLists.txt file for the FKINSOL parallel examples
+
+
+# Add variable kinsol_examples with the names of the parallel KINSOL examples
+
+SET(FKINSOL_examples
+ fkinDiagon_kry_p
+ )
+
+# 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 )
+ # use MPI_MPIF77 as the compiler
+ SET(CMAKE_Fortran_COMPILER ${MPI_MPIF77})
+ELSE(MPI_MPIF77)
+ # add MPI_INCLUDE_PATH to include directories
+ INCLUDE_DIRECTORIES(${MPI_INCLUDE_PATH})
+ENDIF(MPI_MPIF77)
+
+# 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")
+ SET(KINSOL_LIB sundials_kinsol_shared)
+ SET(NVECP_LIB sundials_nvecparallel_shared)
+ SET(FNVECP_LIB sundials_fnvecparallel_shared)
+ENDIF(LINK_LIBRARY_TYPE MATCHES "static")
+
+# 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)
+ SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${LAPACK_LINKER_FLAGS}")
+ SET(SUNDIALS_LIBS "${SUNDIALS_LIBS} ${LAPACK_LIBRARIES}")
+ENDIF(LAPACK_FOUND)
+
+# Add the build and install targets for each KINSOL example
+
+FOREACH(example ${FKINSOL_examples})
+ ADD_EXECUTABLE(${example} ${example}.f)
+ TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+ IF(NOT MPI_MPIF77)
+ TARGET_LINK_LIBRARIES(${example} ${MPI_LIBRARY} ${MPI_EXTRA_LIBRARIES})
+ ENDIF(NOT MPI_MPIF77)
+ IF(EXAMPLES_INSTALL)
+ INSTALL(FILES ${example}.f ${example}.out DESTINATION ${EXAMPLES_INSTALL_PATH}/kinsol/fcmix_parallel)
+ ENDIF(EXAMPLES_INSTALL)
+ENDFOREACH(example ${FKINSOL_examples})
+
+IF(EXAMPLES_INSTALL)
+
+ # Install the README file
+ INSTALL(FILES README DESTINATION ${EXAMPLES_INSTALL_PATH}/kinsol/fcmix_parallel)
+
+ # Prepare substitution variables for Makefile and/or CMakeLists templates
+ SET(SOLVER "KINSOL")
+ SET(SOLVER_LIB "sundials_kinsol")
+ SET(SOLVER_FLIB "sundials_fkinsol")
+ LIST2STRING(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
+ # 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/kinsol/fcmix_parallel/CMakeLists.txt
+ @ONLY
+ )
+
+ # install CMakelists.txt
+ INSTALL(
+ FILES ${PROJECT_BINARY_DIR}/examples/kinsol/fcmix_parallel/CMakeLists.txt
+ DESTINATION ${EXAMPLES_INSTALL_PATH}/kinsol/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
+ # 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_F77_ex.in
+ ${PROJECT_BINARY_DIR}/examples/kinsol/fcmix_parallel/Makefile_ex
+ @ONLY
+ )
+ # install the configured Makefile_ex as Makefile
+ INSTALL(
+ FILES ${PROJECT_BINARY_DIR}/examples/kinsol/fcmix_parallel/Makefile_ex
+ DESTINATION ${EXAMPLES_INSTALL_PATH}/kinsol/fcmix_parallel
+ RENAME Makefile
+ )
+ ENDIF(UNIX)
+
+ENDIF(EXAMPLES_INSTALL)
+
diff --git a/examples/kinsol/fcmix_parallel/Makefile.in b/examples/kinsol/fcmix_parallel/Makefile.in
new file mode 100644
index 0000000..e4bfcc9
--- /dev/null
+++ b/examples/kinsol/fcmix_parallel/Makefile.in
@@ -0,0 +1,114 @@
+# -----------------------------------------------------------------
+# $Revision: 1.9 $
+# $Date: 2009/02/17 02:58:47 $
+# -----------------------------------------------------------------
+# Programmer(s): Radu Serban and Aaron Collier @ LLNL
+# -----------------------------------------------------------------
+# Copyright (c) 2002, The Regents of the University of California.
+# Produced at the Lawrence Livermore National Laboratory.
+# All rights reserved.
+# For details, see the LICENSE file.
+# -----------------------------------------------------------------
+# Makefile for FKINSOL parallel examples
+#
+# @configure_input@
+# -----------------------------------------------------------------
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_builddir = @top_builddir@
+builddir = @builddir@
+abs_builddir = @abs_builddir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+includedir = @includedir@
+libdir = @libdir@
+
+INSTALL = @INSTALL@
+INSTALL_PROG = @INSTALL_PROGRAM@
+INSTALL_FILE = @INSTALL_DATA@
+
+LIBTOOL = @LIBTOOL@
+LIBTOOL_DEPS = @LIBTOOL_DEPS@
+
+FFLAGS = @FFLAGS@
+F77_LDFLAGS = @F77_LDFLAGS@
+F77_LIBS = @F77_LIBS@
+
+MPIF77 = @MPIF77@
+MPI_INC_DIR = @MPI_INC_DIR@
+MPI_FLAGS = @MPI_FLAGS@
+MPIF77_LNKR = @MPIF77_LNKR@
+MPI_LIB_DIR = @MPI_LIB_DIR@
+MPI_LIBS = @MPI_LIBS@
+
+BLAS_LAPACK_LIBS = @BLAS_LAPACK_LIBS@
+
+OBJ_EXT = @OBJEXT@
+EXE_EXT = @EXEEXT@
+
+EXS_INSTDIR = @EXS_INSTDIR@
+
+top_srcdir = $(srcdir)/../../..
+
+SUNDIALS_LIBS = $(top_builddir)/src/kinsol/fcmix/libsundials_fkinsol.la \
+ $(top_builddir)/src/kinsol/libsundials_kinsol.la \
+ $(top_builddir)/src/nvec_par/libsundials_fnvecparallel.la \
+ $(top_builddir)/src/nvec_par/libsundials_nvecparallel.la
+
+fortran-update = ${SHELL} ${top_builddir}/bin/fortran-update.sh
+
+mkinstalldirs = $(SHELL) $(top_srcdir)/config/mkinstalldirs
+rminstalldirs = $(SHELL) $(top_srcdir)/config/rminstalldirs
+
+EXAMPLES = fkinDiagon_kry_p
+
+OBJECTS = ${EXAMPLES:=${OBJ_EXT}}
+EXECS = ${EXAMPLES:=${EXE_EXT}}
+
+# ----------------------------------------------------------------------------------------------------------------------
+
+all:
+ @for i in ${EXAMPLES} ; do \
+ ${fortran-update} ${srcdir} $${i}.f ; \
+ ${LIBTOOL} --mode=compile ${MPIF77} ${MPI_FLAGS} -I${MPI_INC_DIR} ${FFLAGS} -c ${builddir}/$${i}-updated.f ; \
+ ${LIBTOOL} --mode=link ${MPIF77_LNKR} -o ${builddir}/$${i}${EXE_EXT} ${builddir}/$${i}-updated${OBJ_EXT} ${MPI_FLAGS} ${F77_LDFLAGS} ${SUNDIALS_LIBS} -L${MPI_LIB_DIR} ${MPI_LIBS} ${F77_LIBS} $(BLAS_LAPACK_LIBS) ; \
+ done
+
+install:
+ $(mkinstalldirs) $(EXS_INSTDIR)/kinsol/fcmix_parallel
+ $(INSTALL_FILE) Makefile_ex $(EXS_INSTDIR)/kinsol/fcmix_parallel/Makefile
+ $(INSTALL_FILE) $(top_srcdir)/examples/kinsol/fcmix_parallel/README $(EXS_INSTDIR)/kinsol/fcmix_parallel/
+ for i in ${EXAMPLES} ; do \
+ $(INSTALL_FILE) $(top_srcdir)/examples/kinsol/fcmix_parallel/$${i}.f $(EXS_INSTDIR)/kinsol/fcmix_parallel/ ; \
+ $(INSTALL_FILE) $(top_srcdir)/examples/kinsol/fcmix_parallel/$${i}.out $(EXS_INSTDIR)/kinsol/fcmix_parallel/ ; \
+ done
+
+uninstall:
+ rm -f $(EXS_INSTDIR)/kinsol/fcmix_parallel/Makefile
+ rm -f $(EXS_INSTDIR)/kinsol/fcmix_parallel/README
+ for i in ${EXAMPLES} ; do \
+ rm -f $(EXS_INSTDIR)/kinsol/fcmix_parallel/$${i}.f ; \
+ rm -f $(EXS_INSTDIR)/kinsol/fcmix_parallel/$${i}.out ; \
+ done
+ $(rminstalldirs) $(EXS_INSTDIR)/kinsol/fcmix_parallel
+ $(rminstalldirs) $(EXS_INSTDIR)/kinsol
+
+clean:
+ rm -rf .libs
+ rm -f *.lo *.o
+ rm -f *-updated.f
+ rm -f ${OBJECTS}
+ rm -f $(EXECS)
+
+distclean: clean
+ rm -f Makefile
+ rm -f Makefile_ex
+
+# ----------------------------------------------------------------------------------------------------------------------
+
+libtool: $(top_builddir)/$(LIBTOOL_DEPS)
+ @cd ${top_builddir} ; \
+ ${SHELL} ./config.status --recheck ; \
+ cd ${abs_builddir}
diff --git a/examples/kinsol/fcmix_parallel/README b/examples/kinsol/fcmix_parallel/README
new file mode 100644
index 0000000..5b78a3c
--- /dev/null
+++ b/examples/kinsol/fcmix_parallel/README
@@ -0,0 +1,15 @@
+List of parallel KINSOL FCMIX examples
+
+ fkinDiagon_kry_p: simple diagonal test with Fortran interface
+
+Sample result:
+
+ SUNDIALS was built with the following options:
+
+ ./configure CC=gcc F77=gfortran CFLAGS="-g3 -O0" FFLAGS="-g3 -O0" --enable-examples
+
+ System Architecture: IA-32
+ Processor Type: Intel Pentium 4 Xeon DP (i686)
+ Operating System: Red Hat Enterprise Linux WS 3 (Taroon Update 7)
+ C/Fortran Compilers: gcc/gfortran v4.1.0 (GCC)
+ MPI Implementation: Open MPI v1.1
diff --git a/examples/kinsol/fcmix_parallel/fkinDiagon_kry_p.f b/examples/kinsol/fcmix_parallel/fkinDiagon_kry_p.f
new file mode 100644
index 0000000..dd51516
--- /dev/null
+++ b/examples/kinsol/fcmix_parallel/fkinDiagon_kry_p.f
@@ -0,0 +1,246 @@
+ program fkinDiagon_kry_p
+c ----------------------------------------------------------------
+c $Revision: 1.2 $
+c $Date: 2009/09/30 23:42:12 $
+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
+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
+c Execution command: mpirun -np 4 fkinDiagon_kry_p
+c ----------------------------------------------------------------
+c
+ implicit none
+
+ include "mpif.h"
+
+ integer ier, size, globalstrat, rank, mype, npes
+ integer maxl, maxlrst
+ integer*4 localsize
+ parameter(localsize=32)
+ integer*4 neq, nlocal, msbpre, baseadd, i, ii
+ integer*4 iout(15)
+ double precision rout(2)
+ double precision pp, fnormtol, scsteptol
+ double precision uu(localsize), scale(localsize)
+ double precision constr(localsize)
+
+ common /pcom/ pp(localsize), mype, npes, baseadd, nlocal
+
+ nlocal = localsize
+ neq = 4 * nlocal
+ globalstrat = 0
+ fnormtol = 1.0d-5
+ scsteptol = 1.0d-4
+ maxl = 10
+ maxlrst = 2
+ msbpre = 5
+
+c The user MUST call mpi_init, Fortran binding, for the fkinsol package
+c to work. The communicator, MPI_COMM_WORLD, is the only one common
+c between the Fortran and C bindings. So in the following, the communicator
+c MPI_COMM_WORLD is used in calls to mpi_comm_size and mpi_comm_rank
+c to determine the total number of processors and the rank (0 ... size-1)
+c number of this process.
+
+ call mpi_init(ier)
+ if (ier .ne. 0) then
+ write(6,1210) ier
+ 1210 format('MPI_ERROR: MPI_INIT returned IER = ', i2)
+ stop
+ endif
+
+ call fnvinitp(mpi_comm_world, 3, nlocal, neq, ier)
+ if (ier .ne. 0) then
+ write(6,1220) ier
+ 1220 format('SUNDIALS_ERROR: FNVINITP returned IER = ', i2)
+ call mpi_finalize(ier)
+ stop
+ endif
+
+ call mpi_comm_size(mpi_comm_world, size, ier)
+ if (ier .ne. 0) then
+ write(6,1222) ier
+ 1222 format('MPI_ERROR: MPI_COMM_SIZE returned IER = ', i2)
+ call mpi_abort(mpi_comm_world, 1, ier)
+ stop
+ endif
+
+ if (size .ne. 4) then
+ write(6,1230)
+ 1230 format('MPI_ERROR: must use 4 processes')
+ call mpi_finalize(ier)
+ stop
+ endif
+ npes = size
+
+ call mpi_comm_rank(mpi_comm_world, rank, ier)
+ if (ier .ne. 0) then
+ write(6,1224) ier
+ 1224 format('MPI_ERROR: MPI_COMM_RANK returned IER = ', i2)
+ call mpi_abort(mpi_comm_world, 1, ier)
+ stop
+ endif
+
+ mype = rank
+ baseadd = mype * nlocal
+
+ do 20 ii = 1, nlocal
+ i = ii + baseadd
+ uu(ii) = 2.0d0 * i
+ scale(ii) = 1.0d0
+ constr(ii) = 0.0d0
+ 20 continue
+
+ call fkinmalloc(iout, rout, ier)
+
+ if (ier .ne. 0) then
+ write(6,1231)ier
+ 1231 format('SUNDIALS_ERROR: FKINMALLOC returned IER = ', i2)
+ call mpi_abort(mpi_comm_world, 1, ier)
+ stop
+ endif
+
+ call fkinsetiin('MAX_SETUPS', msbpre, ier)
+ call fkinsetrin('FNORM_TOL', fnormtol, ier)
+ call fkinsetrin('SSTEP_TOL', scsteptol, ier)
+ call fkinsetvin('CONSTR_VEC', constr, ier)
+
+ call fkinspgmr(maxl, maxlrst, ier)
+ call fkinspilssetprec(1, ier)
+
+ if (mype .eq. 0) write(6,1240)
+ 1240 format('Example program fkinDiagon_kry_p:'//
+ 1 ' This FKINSOL example',
+ 2 ' solves a 128 eqn diagonal algebraic system.'/
+ 3 ' Its purpose is to demonstrate the use of the Fortran',
+ 4 ' interface'/' in a parallel environment.')
+
+ call fkinsol(uu, globalstrat, scale, scale, ier)
+ if (ier .lt. 0) then
+ write(6,1242) ier, iout(9)
+ 1242 format('SUNDIALS_ERROR: FKINSOL returned IER = ', i2, /,
+ 1 ' Linear Solver returned IER = ', i2)
+ call mpi_abort(mpi_comm_world, 1, ier)
+ stop
+ endif
+
+ if (mype .eq. 0) write(6,1245) ier
+ 1245 format(/' FKINSOL return code is ', i4)
+
+ 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)
+ 1256 format(i4, 4(1x, f10.6))
+ 30 continue
+
+ if (mype .eq. 0) write(6,1267) iout(3), iout(14), iout(4),
+ 1 iout(12), iout(13), iout(15)
+ 1267 format(/'Final statistics:'//
+ 1 ' nni = ', i3, ', nli = ', i3, /,
+ 2 ' nfe = ', i3, ', npe = ', i3, /,
+ 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.
+ 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.
+
+ subroutine fkfun(uu, fval, ier)
+
+ implicit none
+
+ integer mype, npes, ier
+ integer*4 baseadd, nlocal, i, localsize
+ parameter(localsize=32)
+ double precision pp
+ double precision fval(*), uu(*)
+
+ common /pcom/ pp(localsize), mype, npes, baseadd, nlocal
+
+ do 10 i = 1, nlocal
+ 10 fval(i) = uu(i) * uu(i) - (i + baseadd) * (i + baseadd)
+
+ return
+ end
+
+
+c * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+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)
+
+ implicit none
+
+ integer ier, mype, npes
+ integer*4 localsize
+ parameter(localsize=32)
+ integer*4 baseadd, nlocal, i
+ double precision pp
+ double precision udata(*), uscale(*), fdata(*), fscale(*)
+ double precision vtemp1(*), vtemp2(*)
+
+ common /pcom/ pp(localsize), mype, npes, baseadd, nlocal
+
+ do 10 i = 1, nlocal
+ 10 pp(i) = 0.5d0 / (udata(i)+ 5.0d0)
+
+ ier = 0
+
+ return
+ end
+
+
+c * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+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)
+
+ implicit none
+
+ integer ier, mype, npes
+ integer*4 baseadd, nlocal, i
+ integer*4 localsize
+ parameter(localsize=32)
+ double precision udata(*), uscale(*), fdata(*), fscale(*)
+ double precision vv(*), ftem(*)
+ double precision pp
+
+ common /pcom/ pp(localsize), mype, npes, baseadd, nlocal
+
+ do 10 i = 1, nlocal
+ 10 vv(i) = vv(i) * pp(i)
+
+ ier = 0
+
+ return
+ end
diff --git a/examples/kinsol/fcmix_parallel/fkinDiagon_kry_p.out b/examples/kinsol/fcmix_parallel/fkinDiagon_kry_p.out
new file mode 100644
index 0000000..9a8f8ee
--- /dev/null
+++ b/examples/kinsol/fcmix_parallel/fkinDiagon_kry_p.out
@@ -0,0 +1,24 @@
+Example program fkinDiagon_kry_p:
+
+ This FKINSOL example solves a 128 eqn diagonal algebraic system.
+ Its purpose is to demonstrate the use of the Fortran interface
+ in a parallel environment.
+
+ FKINSOL return code is 0
+
+ The resultant values of uu (process 0) are:
+
+ 1 1.000000 2.000000 3.000000 4.000000
+ 5 5.000000 6.000000 7.000000 8.000000
+ 9 9.000000 10.000000 11.000000 12.000000
+ 13 13.000000 14.000000 15.000000 16.000000
+ 17 17.000000 18.000000 19.000000 20.000000
+ 21 21.000000 22.000000 23.000000 24.000000
+ 25 25.000000 26.000000 27.000000 28.000000
+ 29 29.000000 30.000000 31.000000 32.000000
+
+Final statistics:
+
+ nni = 7, nli = 21
+ nfe = 8, npe = 2
+ nps = 28, ncfl = 0
diff --git a/examples/kinsol/fcmix_serial/CMakeLists.txt b/examples/kinsol/fcmix_serial/CMakeLists.txt
new file mode 100644
index 0000000..01803e9
--- /dev/null
+++ b/examples/kinsol/fcmix_serial/CMakeLists.txt
@@ -0,0 +1,128 @@
+# ---------------------------------------------------------------
+# $Revision: 1.5 $
+# $Date: 2009/02/17 02:58:47 $
+# ---------------------------------------------------------------
+# Programmer: Radu Serban @ LLNL
+# ---------------------------------------------------------------
+# Copyright (c) 2007, The Regents of the University of California.
+# Produced at the Lawrence Livermore National Laboratory.
+# All rights reserved.
+# For details, see the LICENSE file.
+# ---------------------------------------------------------------
+# CMakeLists.txt file for the FKINSOL serial examples
+
+
+# Add variable kinsol_examples with the names of the serial FKINSOL examples
+
+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
+ )
+
+# 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")
+ SET(KINSOL_LIB sundials_kinsol_shared)
+ SET(NVECS_LIB sundials_nvecserial_shared)
+ SET(FNVECS_LIB sundials_fnvecserial_shared)
+ENDIF(LINK_LIBRARY_TYPE MATCHES "static")
+
+# 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)
+ SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${LAPACK_LINKER_FLAGS}")
+ SET(SUNDIALS_LIBS "${SUNDIALS_LIBS} ${LAPACK_LIBRARIES}")
+ENDIF(LAPACK_FOUND)
+
+# Add the build and install targets for each FKINSOL example
+
+FOREACH(example ${FKINSOL_examples})
+ ADD_EXECUTABLE(${example} ${example}.f)
+ 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})
+
+# 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)
+ 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)
+
+
+IF(EXAMPLES_INSTALL)
+
+ # Install the README file
+ INSTALL(FILES README DESTINATION ${EXAMPLES_INSTALL_PATH}/kinsol/fcmix_serial)
+
+ # Prepare substitution variables for Makefile and/or CMakeLists templates
+ 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)
+
+ # 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/kinsol/fcmix_serial/CMakeLists.txt
+ @ONLY
+ )
+
+ # install CMakelists.txt
+ INSTALL(
+ FILES ${PROJECT_BINARY_DIR}/examples/kinsol/fcmix_serial/CMakeLists.txt
+ DESTINATION ${EXAMPLES_INSTALL_PATH}/kinsol/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
+ # 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_F77_ex.in
+ ${PROJECT_BINARY_DIR}/examples/kinsol/fcmix_serial/Makefile_ex
+ @ONLY
+ )
+ # install the configured Makefile_ex as Makefile
+ INSTALL(
+ FILES ${PROJECT_BINARY_DIR}/examples/kinsol/fcmix_serial/Makefile_ex
+ DESTINATION ${EXAMPLES_INSTALL_PATH}/kinsol/fcmix_serial
+ RENAME Makefile
+ )
+ ENDIF(UNIX)
+
+ENDIF(EXAMPLES_INSTALL)
diff --git a/examples/kinsol/fcmix_serial/Makefile.in b/examples/kinsol/fcmix_serial/Makefile.in
new file mode 100644
index 0000000..20fb2c3
--- /dev/null
+++ b/examples/kinsol/fcmix_serial/Makefile.in
@@ -0,0 +1,134 @@
+# -----------------------------------------------------------------
+# $Revision: 1.10 $
+# $Date: 2009/02/17 02:58:47 $
+# -----------------------------------------------------------------
+# Programmer(s): Radu Serban and Aaron Collier @ LLNL
+# -----------------------------------------------------------------
+# Copyright (c) 2002, The Regents of the University of California.
+# Produced at the Lawrence Livermore National Laboratory.
+# All rights reserved.
+# For details, see the LICENSE file.
+# -----------------------------------------------------------------
+# Makefile for FKINSOL serial examples
+#
+# @configure_input@
+# -----------------------------------------------------------------
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_builddir = @top_builddir@
+builddir = @builddir@
+abs_builddir = @abs_builddir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+includedir = @includedir@
+libdir = @libdir@
+
+INSTALL = @INSTALL@
+INSTALL_PROG = @INSTALL_PROGRAM@
+INSTALL_FILE = @INSTALL_DATA@
+
+LIBTOOL = @LIBTOOL@
+LIBTOOL_DEPS = @LIBTOOL_DEPS@
+
+F77 = @F77@
+FFLAGS = @FFLAGS@
+F77_LNKR = @F77_LNKR@
+F77_LDFLAGS = @F77_LDFLAGS@
+F77_LIBS = @F77_LIBS@
+
+LAPACK_ENABLED = @LAPACK_ENABLED@
+BLAS_LAPACK_LIBS = @BLAS_LAPACK_LIBS@
+
+OBJ_EXT = @OBJEXT@
+EXE_EXT = @EXEEXT@
+
+EXS_INSTDIR = @EXS_INSTDIR@
+
+top_srcdir = $(srcdir)/../../..
+
+SUNDIALS_LIBS = $(top_builddir)/src/kinsol/fcmix/libsundials_fkinsol.la \
+ $(top_builddir)/src/kinsol/libsundials_kinsol.la \
+ $(top_builddir)/src/nvec_ser/libsundials_fnvecserial.la \
+ $(top_builddir)/src/nvec_ser/libsundials_nvecserial.la
+
+fortran-update = ${SHELL} ${top_builddir}/bin/fortran-update.sh
+
+mkinstalldirs = $(SHELL) $(top_srcdir)/config/mkinstalldirs
+rminstalldirs = $(SHELL) $(top_srcdir)/config/rminstalldirs
+
+EXAMPLES = fkinDiagon_kry
+
+EXAMPLES_BL =
+
+OBJECTS = ${EXAMPLES:=${OBJ_EXT}}
+OBJECTS_BL = ${EXAMPLES_BL:=${OBJ_EXT}}
+EXECS = ${EXAMPLES:=${EXE_EXT}}
+EXECS_BL = ${EXAMPLES_BL:=${EXE_EXT}}
+
+# ----------------------------------------------------------------------------------------------------------------------
+
+all:
+ @for i in ${EXAMPLES} ; do \
+ ${fortran-update} ${srcdir} $${i}.f ; \
+ ${LIBTOOL} --mode=compile ${F77} ${FFLAGS} -c ${builddir}/$${i}-updated.f ; \
+ ${LIBTOOL} --mode=link ${F77_LNKR} -o ${builddir}/$${i}${EXE_EXT} ${builddir}/$${i}-updated${OBJ_EXT} ${F77_LDFLAGS} ${SUNDIALS_LIBS} ${F77_LIBS} ${BLAS_LAPACK_LIBS} ; \
+ done
+ @if test "X${LAPACK_ENABLED}" = "Xyes"; then \
+ for i in ${EXAMPLES_BL} ; do \
+ ${fortran-update} ${srcdir} $${i}.f ; \
+ ${LIBTOOL} --mode=compile ${F77} ${FFLAGS} -c ${builddir}/$${i}-updated.f ; \
+ ${LIBTOOL} --mode=link ${F77_LNKR} -o ${builddir}/$${i}${EXE_EXT} ${builddir}/$${i}-updated${OBJ_EXT} ${F77_LDFLAGS} ${SUNDIALS_LIBS} ${F77_LIBS} ${BLAS_LAPACK_LIBS} ; \
+ done ; \
+ fi
+
+
+install:
+ $(mkinstalldirs) $(EXS_INSTDIR)/kinsol/fcmix_serial
+ $(INSTALL_FILE) Makefile_ex $(EXS_INSTDIR)/kinsol/fcmix_serial/Makefile
+ $(INSTALL_FILE) $(top_srcdir)/examples/kinsol/fcmix_serial/README $(EXS_INSTDIR)/kinsol/fcmix_serial/
+ for i in ${EXAMPLES} ; do \
+ $(INSTALL_FILE) $(top_srcdir)/examples/kinsol/fcmix_serial/$${i}.f $(EXS_INSTDIR)/kinsol/fcmix_serial/ ; \
+ $(INSTALL_FILE) $(top_srcdir)/examples/kinsol/fcmix_serial/$${i}.out $(EXS_INSTDIR)/kinsol/fcmix_serial/ ; \
+ done
+ @if test "X${LAPACK_ENABLED}" = "Xyes"; then \
+ for i in ${EXAMPLES_BL} ; do \
+ $(INSTALL_FILE) $(top_srcdir)/examples/kinsol/fcmix_serial/$${i}.f $(EXS_INSTDIR)/kinsol/fcmix_serial/ ; \
+ $(INSTALL_FILE) $(top_srcdir)/examples/kinsol/fcmix_serial/$${i}.out $(EXS_INSTDIR)/kinsol/fcmix_serial/ ; \
+ done ; \
+ fi
+
+uninstall:
+ rm -f $(EXS_INSTDIR)/kinsol/fcmix_serial/Makefile
+ rm -f $(EXS_INSTDIR)/kinsol/fcmix_serial/README
+ for i in ${EXAMPLES} ; do \
+ rm -f $(EXS_INSTDIR)/kinsol/fcmix_serial/$${i}.f ; \
+ rm -f $(EXS_INSTDIR)/kinsol/fcmix_serial/$${i}.out ; \
+ done
+ @if test "X${LAPACK_ENABLED}" = "Xyes"; then \
+ for i in ${EXAMPLES_BL} ; do \
+ rm -f $(EXS_INSTDIR)/kinsol/fcmix_serial/$${i}.f ; \
+ rm -f $(EXS_INSTDIR)/kinsol/fcmix_serial/$${i}.out ; \
+ done ; \
+ fi
+ $(rminstalldirs) $(EXS_INSTDIR)/kinsol/fcmix_serial
+ $(rminstalldirs) $(EXS_INSTDIR)/kinsol
+
+clean:
+ rm -rf .libs
+ rm -f *.lo *.o
+ rm -f *-updated.f
+ rm -f ${OBJECTS} ${OBJECTS_BL}
+ rm -f $(EXECS) $(EXECS_BL)
+
+distclean: clean
+ rm -f Makefile
+ rm -f Makefile_ex
+
+# ----------------------------------------------------------------------------------------------------------------------
+
+libtool: $(top_builddir)/$(LIBTOOL_DEPS)
+ @cd ${top_builddir} ; \
+ ${SHELL} ./config.status --recheck ; \
+ cd ${abs_builddir}
diff --git a/examples/kinsol/fcmix_serial/README b/examples/kinsol/fcmix_serial/README
new file mode 100644
index 0000000..0328aec
--- /dev/null
+++ b/examples/kinsol/fcmix_serial/README
@@ -0,0 +1,14 @@
+List of serial KINSOL FCMIX examples
+
+ fkinDiagon_kry: simple diagonal test with Fortran interface
+
+Sample result:
+
+ SUNDIALS was built with the following options:
+
+ ./configure CC=gcc F77=gfortran CFLAGS="-g3 -O0" FFLAGS="-g3 -O0" --enable-examples
+
+ System Architecture: IA-32
+ Processor Type: Intel Pentium 4 Xeon DP (i686)
+ Operating System: Red Hat Enterprise Linux WS 3 (Taroon Update 7)
+ C/Fortran Compilers: gcc/gfortran v4.1.0 (GCC)
diff --git a/examples/kinsol/fcmix_serial/fkinDiagon_kry.f b/examples/kinsol/fcmix_serial/fkinDiagon_kry.f
new file mode 100644
index 0000000..9c050d8
--- /dev/null
+++ b/examples/kinsol/fcmix_serial/fkinDiagon_kry.f
@@ -0,0 +1,197 @@
+ program fkinDiagon_kry
+c ----------------------------------------------------------------
+c $Revision: 1.2 $
+c $Date: 2009/09/30 23:41:32 $
+c ----------------------------------------------------------------
+c Programmer(s): Allan Taylor, Alan 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).
+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
+c ----------------------------------------------------------------
+c
+ implicit none
+
+ integer ier, globalstrat, maxl, maxlrst
+ integer*4 PROBSIZE
+ parameter(PROBSIZE=128)
+ integer*4 neq, i, msbpre
+ integer*4 iout(15)
+ double precision pp, fnormtol, scsteptol
+ double precision rout(2), uu(PROBSIZE), scale(PROBSIZE)
+ double precision constr(PROBSIZE)
+
+ common /pcom/ pp(PROBSIZE)
+ common /psize/ neq
+
+ neq = PROBSIZE
+ globalstrat = 0
+ fnormtol = 1.0d-5
+ scsteptol = 1.0d-4
+ maxl = 10
+ maxlrst = 2
+ msbpre = 5
+
+c * * * * * * * * * * * * * * * * * * * * * *
+
+ call fnvinits(3, neq, ier)
+ if (ier .ne. 0) then
+ write(6,1220) ier
+ 1220 format('SUNDIALS_ERROR: FNVINITS returned IER = ', i2)
+ stop
+ endif
+
+ do 20 i = 1, neq
+ uu(i) = 2.0d0 * i
+ scale(i) = 1.0d0
+ constr(i) = 0.0d0
+ 20 continue
+
+ call fkinmalloc(iout, rout, ier)
+ if (ier .ne. 0) then
+ write(6,1230) ier
+ 1230 format('SUNDIALS_ERROR: FKINMALLOC returned IER = ', i2)
+ stop
+ endif
+
+ call fkinsetiin('MAX_SETUPS', msbpre, ier)
+ call fkinsetrin('FNORM_TOL', fnormtol, ier)
+ call fkinsetrin('SSTEP_TOL', scsteptol, ier)
+ call fkinsetvin('CONSTR_VEC', constr, ier)
+
+ call fkinspgmr(maxl, maxlrst, ier)
+ if (ier .ne. 0) then
+ write(6,1235) ier
+ 1235 format('SUNDIALS_ERROR: FKINSPGMR returned IER = ', i2)
+ call fkinfree
+ stop
+ endif
+
+ call fkinspilssetprec(1, ier)
+
+ write(6,1240)
+ 1240 format('Example program fkinDiagon_kry:'//' This FKINSOL example',
+ 1 ' solves a 128 eqn diagonal algebraic system.'/
+ 2 ' Its purpose is to demonstrate the use of the Fortran',
+ 3 ' interface'/' in a serial environment.'///
+ 4 ' globalstrategy = KIN_NONE')
+
+ call fkinsol(uu, globalstrat, scale, scale, ier)
+ if (ier .lt. 0) then
+ write(6,1242) ier, iout(9)
+ 1242 format('SUNDIALS_ERROR: FKINSOL returned IER = ', i2, /,
+ 1 ' Linear Solver returned IER = ', i2)
+ call fkinfree
+ stop
+ endif
+
+ write(6,1245) ier
+ 1245 format(/' FKINSOL return code is ', i3)
+
+ write(6,1246)
+ 1246 format(//' The resultant values of uu are:'/)
+
+ do 30 i = 1, neq, 4
+ write(6,1256) i, uu(i), uu(i+1), uu(i+2), uu(i+3)
+ 1256 format(i4, 4(1x, f10.6))
+ 30 continue
+
+ write(6,1267) iout(3), iout(14), iout(4), iout(12), iout(13),
+ 1 iout(15)
+ 1267 format(//'Final statistics:'//
+ 1 ' nni = ', i3, ', nli = ', i3, /,
+ 2 ' nfe = ', i3, ', npe = ', i3, /,
+ 3 ' nps = ', i3, ', ncfl = ', i3)
+
+ call fkinfree
+
+ stop
+ end
+
+c * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+c The function defining the system f(u) = 0 must be defined by a Fortran
+c function of the following form.
+
+ subroutine fkfun(uu, fval, ier)
+
+ implicit none
+
+ integer ier
+ integer*4 neq, i
+ double precision fval(*), uu(*)
+
+ common /psize/ neq
+
+ do 10 i = 1, neq
+ fval(i) = uu(i) * uu(i) - i * i
+ 10 continue
+
+ ier = 0
+
+ return
+ end
+
+
+c * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+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)
+
+ implicit none
+
+ integer ier
+ integer*4 neq, i
+ 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
+ ier = 0
+
+ return
+ end
+
+
+c * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+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)
+
+ implicit none
+
+ integer ier
+ integer*4 neq, i
+ double precision pp
+ double precision udata(*), uscale(*), fdata(*), fscale(*)
+ double precision vv(*), ftem(*)
+
+ common /pcom/ pp(128)
+ common /psize/ neq
+
+ do 10 i = 1, neq
+ vv(i) = vv(i) * pp(i)
+ 10 continue
+ ier = 0
+
+ return
+ end
diff --git a/examples/kinsol/fcmix_serial/fkinDiagon_kry.out b/examples/kinsol/fcmix_serial/fkinDiagon_kry.out
new file mode 100644
index 0000000..27dd57d
--- /dev/null
+++ b/examples/kinsol/fcmix_serial/fkinDiagon_kry.out
@@ -0,0 +1,53 @@
+Example program fkinDiagon_kry:
+
+ This FKINSOL example solves a 128 eqn diagonal algebraic system.
+ Its purpose is to demonstrate the use of the Fortran interface
+ in a serial environment.
+
+
+ globalstrategy = KIN_NONE
+
+ FKINSOL return code is 0
+
+
+ The resultant values of uu are:
+
+ 1 1.000000 2.000000 3.000000 4.000000
+ 5 5.000000 6.000000 7.000000 8.000000
+ 9 9.000000 10.000000 11.000000 12.000000
+ 13 13.000000 14.000000 15.000000 16.000000
+ 17 17.000000 18.000000 19.000000 20.000000
+ 21 21.000000 22.000000 23.000000 24.000000
+ 25 25.000000 26.000000 27.000000 28.000000
+ 29 29.000000 30.000000 31.000000 32.000000
+ 33 33.000000 34.000000 35.000000 36.000000
+ 37 37.000000 38.000000 39.000000 40.000000
+ 41 41.000000 42.000000 43.000000 44.000000
+ 45 45.000000 46.000000 47.000000 48.000000
+ 49 49.000000 50.000000 51.000000 52.000000
+ 53 53.000000 54.000000 55.000000 56.000000
+ 57 57.000000 58.000000 59.000000 60.000000
+ 61 61.000000 62.000000 63.000000 64.000000
+ 65 65.000000 66.000000 67.000000 68.000000
+ 69 69.000000 70.000000 71.000000 72.000000
+ 73 73.000000 74.000000 75.000000 76.000000
+ 77 77.000000 78.000000 79.000000 80.000000
+ 81 81.000000 82.000000 83.000000 84.000000
+ 85 85.000000 86.000000 87.000000 88.000000
+ 89 89.000000 90.000000 91.000000 92.000000
+ 93 93.000000 94.000000 95.000000 96.000000
+ 97 97.000000 98.000000 99.000000 100.000000
+ 101 101.000000 102.000000 103.000000 104.000000
+ 105 105.000000 106.000000 107.000000 108.000000
+ 109 109.000000 110.000000 111.000000 112.000000
+ 113 113.000000 114.000000 115.000000 116.000000
+ 117 117.000000 118.000000 119.000000 120.000000
+ 121 121.000000 122.000000 123.000000 124.000000
+ 125 125.000000 126.000000 127.000000 128.000000
+
+
+Final statistics:
+
+ nni = 7, nli = 21
+ nfe = 8, npe = 2
+ nps = 28, ncfl = 0
diff --git a/examples/kinsol/parallel/CMakeLists.txt b/examples/kinsol/parallel/CMakeLists.txt
new file mode 100644
index 0000000..7a1edc9
--- /dev/null
+++ b/examples/kinsol/parallel/CMakeLists.txt
@@ -0,0 +1,112 @@
+# ---------------------------------------------------------------
+# $Revision: 1.4 $
+# $Date: 2009/02/17 02:58:47 $
+# ---------------------------------------------------------------
+# Programmer: Radu Serban @ LLNL
+# ---------------------------------------------------------------
+# Copyright (c) 2007, The Regents of the University of California.
+# Produced at the Lawrence Livermore National Laboratory.
+# All rights reserved.
+# For details, see the LICENSE file.
+# ---------------------------------------------------------------
+# CMakeLists.txt file for KINSOL parallel examples
+
+
+# Add variable KINSOL_examples with the names of the parallel KINSOL examples
+
+SET(KINSOL_examples
+ kinFoodWeb_kry_bbd_p
+ kinFoodWeb_kry_p
+ )
+
+# 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)
+ # add MPI_INCLUDE_PATH to include directories
+ INCLUDE_DIRECTORIES(${MPI_INCLUDE_PATH})
+ENDIF(MPI_MPICC)
+
+# 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")
+ SET(KINSOL_LIB sundials_kinsol_shared)
+ SET(NVECP_LIB sundials_nvecparallel_shared)
+ENDIF(LINK_LIBRARY_TYPE MATCHES "static")
+
+# Set-up linker flags and link libraries
+
+SET(SUNDIALS_LIBS ${KINSOL_LIB} ${NVECP_LIB} ${EXTRA_LINK_LIBS})
+IF(LAPACK_FOUND)
+ SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${LAPACK_LINKER_FLAGS}")
+ SET(SUNDIALS_LIBS "${SUNDIALS_LIBS} ${LAPACK_LIBRARIES}")
+ENDIF(LAPACK_FOUND)
+
+# Add the build and install targets for each KINSOL example
+
+FOREACH(example ${KINSOL_examples})
+ ADD_EXECUTABLE(${example} ${example}.c)
+ TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+ IF(NOT MPI_MPICC)
+ TARGET_LINK_LIBRARIES(${example} ${MPI_LIBRARY} ${MPI_EXTRA_LIBRARIES})
+ ENDIF(NOT MPI_MPICC)
+ IF(EXAMPLES_INSTALL)
+ INSTALL(FILES ${example}.c ${example}.out DESTINATION ${EXAMPLES_INSTALL_PATH}/kinsol/parallel)
+ ENDIF(EXAMPLES_INSTALL)
+ENDFOREACH(example ${KINSOL_examples})
+
+IF(EXAMPLES_INSTALL)
+
+ # Install the README file
+ INSTALL(FILES README DESTINATION ${EXAMPLES_INSTALL_PATH}/kinsol/parallel)
+
+ # Prepare substitution variables for Makefile and/or CMakeLists templates
+ SET(SOLVER "KINSOL")
+ SET(SOLVER_LIB "sundials_kinsol")
+ LIST2STRING(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
+ )
+
+ # install CMakelists.txt
+ INSTALL(
+ FILES ${PROJECT_BINARY_DIR}/examples/kinsol/parallel/CMakeLists.txt
+ 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
+ # 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/kinsol/parallel/Makefile_ex
+ @ONLY
+ )
+ # install the configured Makefile_ex as Makefile
+ INSTALL(
+ FILES ${PROJECT_BINARY_DIR}/examples/kinsol/parallel/Makefile_ex
+ DESTINATION ${EXAMPLES_INSTALL_PATH}/kinsol/parallel
+ RENAME Makefile
+ )
+ ENDIF(UNIX)
+
+ENDIF(EXAMPLES_INSTALL)
diff --git a/examples/kinsol/parallel/Makefile.in b/examples/kinsol/parallel/Makefile.in
new file mode 100644
index 0000000..8d24ac8
--- /dev/null
+++ b/examples/kinsol/parallel/Makefile.in
@@ -0,0 +1,111 @@
+# -----------------------------------------------------------------
+# $Revision: 1.9 $
+# $Date: 2009/02/17 02:58:47 $
+# -----------------------------------------------------------------
+# Programmer(s): Radu Serban and Aaron Collier @ LLNL
+# -----------------------------------------------------------------
+# Copyright (c) 2002, The Regents of the University of California.
+# Produced at the Lawrence Livermore National Laboratory.
+# All rights reserved.
+# For details, see the LICENSE file.
+# -----------------------------------------------------------------
+# Makefile for KINSOL parallel examples
+#
+# @configure_input@
+# -----------------------------------------------------------------
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_builddir = @top_builddir@
+builddir = @builddir@
+abs_builddir = @abs_builddir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+includedir = @includedir@
+libdir = @libdir@
+
+INSTALL = @INSTALL@
+INSTALL_PROG = @INSTALL_PROGRAM@
+INSTALL_FILE = @INSTALL_DATA@
+
+LIBTOOL = @LIBTOOL@
+LIBTOOL_DEPS = @LIBTOOL_DEPS@
+
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CC = @CC@
+CFLAGS = @CFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+MPICC = @MPICC@
+MPI_INC_DIR = @MPI_INC_DIR@
+MPI_LIB_DIR = @MPI_LIB_DIR@
+MPI_LIBS = @MPI_LIBS@
+MPI_FLAGS = @MPI_FLAGS@
+
+BLAS_LAPACK_LIBS = @BLAS_LAPACK_LIBS@
+
+OBJ_EXT = @OBJEXT@
+EXE_EXT = @EXEEXT@
+
+EXS_INSTDIR = @EXS_INSTDIR@
+
+top_srcdir = $(srcdir)/../../..
+
+SUNDIALS_INCS = -I$(top_srcdir)/include -I$(top_builddir)/include
+SUNDIALS_LIBS = $(top_builddir)/src/kinsol/libsundials_kinsol.la \
+ $(top_builddir)/src/nvec_par/libsundials_nvecparallel.la
+
+mkinstalldirs = $(SHELL) $(top_srcdir)/config/mkinstalldirs
+rminstalldirs = $(SHELL) $(top_srcdir)/config/rminstalldirs
+
+EXAMPLES = kinFoodWeb_kry_bbd_p \
+ kinFoodWeb_kry_p
+
+OBJECTS = ${EXAMPLES:=${OBJ_EXT}}
+EXECS = ${EXAMPLES:=${EXE_EXT}}
+
+# ----------------------------------------------------------------------------------------------------------------------
+
+all:
+ @for i in ${EXAMPLES} ; do \
+ $(LIBTOOL) --mode=compile $(MPICC) $(CPPFLAGS) $(MPI_FLAGS) $(SUNDIALS_INCS) -I$(MPI_INC_DIR) $(CFLAGS) -c $(srcdir)/$${i}.c -o $${i}${OBJ_EXT} ; \
+ $(LIBTOOL) --mode=link $(MPICC) -o $(builddir)/$${i}$(EXE_EXT) $(builddir)/$${i}$(OBJ_EXT) $(MPI_FLAGS) $(CFLAGS) $(LDFLAGS) $(SUNDIALS_LIBS) -L$(MPI_LIB_DIR) $(MPI_LIBS) $(LIBS) $(BLAS_LAPACK_LIBS) ; \
+ done
+
+install:
+ $(mkinstalldirs) $(EXS_INSTDIR)/kinsol/parallel
+ $(INSTALL_FILE) Makefile_ex $(EXS_INSTDIR)/kinsol/parallel/Makefile
+ $(INSTALL_FILE) $(top_srcdir)/examples/kinsol/parallel/README $(EXS_INSTDIR)/kinsol/parallel/
+ for i in ${EXAMPLES} ; do \
+ $(INSTALL_FILE) $(top_srcdir)/examples/kinsol/parallel/$${i}.c $(EXS_INSTDIR)/kinsol/parallel/ ; \
+ $(INSTALL_FILE) $(top_srcdir)/examples/kinsol/parallel/$${i}.out $(EXS_INSTDIR)/kinsol/parallel/ ; \
+ done
+
+uninstall:
+ rm -f $(EXS_INSTDIR)/kinsol/parallel/Makefile
+ rm -f $(EXS_INSTDIR)/kinsol/parallel/README
+ for i in ${EXAMPLES} ; do \
+ rm -f $(EXS_INSTDIR)/kinsol/parallel/$${i}.c ; \
+ rm -f $(EXS_INSTDIR)/kinsol/parallel/$${i}.out ; \
+ done
+ $(rminstalldirs) $(EXS_INSTDIR)/kinsol/parallel
+ $(rminstalldirs) $(EXS_INSTDIR)/kinsol
+
+clean:
+ rm -rf .libs
+ rm -f *.lo *.o
+ rm -f ${OBJECTS}
+ rm -f $(EXECS)
+
+distclean: clean
+ rm -f Makefile
+ rm -f Makefile_ex
+
+# ----------------------------------------------------------------------------------------------------------------------
+
+libtool: $(top_builddir)/$(LIBTOOL_DEPS)
+ @cd ${top_builddir} ; \
+ ${SHELL} ./config.status --recheck ; \
+ cd ${abs_builddir}
diff --git a/examples/kinsol/parallel/README b/examples/kinsol/parallel/README
new file mode 100644
index 0000000..eb18b72
--- /dev/null
+++ b/examples/kinsol/parallel/README
@@ -0,0 +1,16 @@
+List of parallel KINSOL examples
+
+ kinFoodWeb_kry_bbd_p: 2-D food web system, BBD preconditioner
+ kinFoodWeb_kry_p: 2-D food web system, block-diagonal preconditioner
+
+Sample results:
+
+ SUNDIALS was built with the following options:
+
+ ./configure CC=gcc F77=gfortran CFLAGS="-g3 -O0" FFLAGS="-g3 -O0" --enable-examples
+
+ System Architecture: IA-32
+ Processor Type: Intel Pentium 4 Xeon DP (i686)
+ Operating System: Red Hat Enterprise Linux WS 3 (Taroon Update 7)
+ C/Fortran Compilers: gcc/gfortran v4.1.0 (GCC)
+ MPI Implementation: Open MPI v1.1
diff --git a/examples/kinsol/parallel/kinFoodWeb_kry_bbd_p.c b/examples/kinsol/parallel/kinFoodWeb_kry_bbd_p.c
new file mode 100644
index 0000000..3401863
--- /dev/null
+++ b/examples/kinsol/parallel/kinFoodWeb_kry_bbd_p.c
@@ -0,0 +1,1009 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.4 $
+ * $Date: 2010/12/01 23:09:24 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Allan Taylor, Alan Hindmarsh and
+ * Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Example problem for KINSOL (parallel machine case) using the BBD
+ * preconditioner.
+ *
+ * This example solves a nonlinear system that arises from a system
+ * of partial differential equations. The PDE system is a food web
+ * 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
+ * 0 = d(i)*(c + c ) + f (x,y,c) (i=1,...,ns)
+ * xx yy i
+ *
+ * where
+ *
+ * i ns j
+ * f (x,y,c) = c * (b(i) + sum a(i,j)*c )
+ * i j=1
+ *
+ * The number of species is ns = 2 * np, with the first np being
+ * prey and the last np being predators. The number np is both the
+ * number of prey and predator species. The coefficients a(i,j),
+ * b(i), d(i) are:
+ *
+ * a(i,i) = -AA (all i)
+ * a(i,j) = -GG (i <= np , j > np)
+ * a(i,j) = EE (i > np, j <= np)
+ * b(i) = BB * (1 + alpha * x * y) (i <= np)
+ * b(i) =-BB * (1 + alpha * x * y) (i > np)
+ * d(i) = DPREY (i <= np)
+ * d(i) = DPRED ( i > np)
+ *
+ * The various scalar parameters are set using define's or in
+ * 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.
+ *
+ * The PDEs are discretized by central differencing on a MX by
+ * MY mesh.
+ *
+ * The nonlinear system is solved by KINSOL using the method
+ * specified in the local variable globalstrat.
+ *
+ * The preconditioner matrix is a band-block-diagonal matrix
+ * using the KINBBDPRE module. The half-bandwidths are as follows:
+ *
+ * Difference quotient half-bandwidths mldq = mudq = 2*ns - 1
+ * Retained banded blocks have half-bandwidths mlkeep = mukeep = ns.
+ *
+ * -----------------------------------------------------------------
+ * References:
+ *
+ * 1. Peter N. Brown and Youcef Saad,
+ * Hybrid Krylov Methods for Nonlinear Systems of Equations
+ * LLNL report UCRL-97645, November 1987.
+ *
+ * 2. Peter N. Brown and Alan C. Hindmarsh,
+ * Reduced Storage Matrix Methods in Stiff ODE systems,
+ * 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.)
+ * --------------------------------------------------------------------------
+ * Run command line: mpirun -np N -machinefile machines kinFoodWeb_kry_bbd_p
+ * where N = NPEX * NPEY is the number of processors.
+ * --------------------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#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 <mpi.h>
+
+
+/* Problem Constants */
+
+#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 NSMXSUB (NUM_SPECIES * MXSUB)
+#define NSMXSUB2 (NUM_SPECIES * (MXSUB+2))
+#define NEQ (NUM_SPECIES*MX*MY) /* number of equations in 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 */
+#define BB RCONST(1.0) /* value of coefficient BB in above eqns */
+#define DPREY RCONST(1.0) /* value of coefficient dprey above */
+#define DPRED RCONST(0.5) /* value of coefficient dpred above */
+#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 THOUSAND RCONST(1000.0) /* one thousand */
+#define ZERO RCONST(0.0) /* 0. */
+#define ONE RCONST(1.0) /* 1. */
+#define PREYIN RCONST(1.0) /* initial guess for prey concentrations. */
+#define PREDIN RCONST(30000.0)/* initial guess for predator concs. */
+
+/* User-defined vector access macro: IJ_Vptr */
+
+/* IJ_Vptr is defined in order to translate from the underlying 3D structure
+ of the dependent variable vector to the 1D storage scheme for an N-vector.
+ IJ_Vptr(vv,i,j) returns a pointer to the location in vv corresponding to
+ indices is = 0, jx = i, jy = j. */
+
+#define IJ_Vptr(vv,i,j) (&NV_Ith_P(vv, i*NUM_SPECIES + j*NSMXSUB))
+
+/* Type : UserData
+ contains problem constants and extended array */
+
+typedef struct {
+ realtype **acoef, *bcoef;
+ N_Vector rates;
+ realtype *cox, *coy;
+ realtype ax, ay, dx, dy;
+ long int 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 */
+
+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 func_local(long int 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 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,
+ 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,
+ void *user_data);
+static realtype DotProd(int size, realtype *x1, realtype *x2);
+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,
+ int isubx, int isuby,
+ int dsizex, int dsizey,
+ realtype *cext, realtype *buffer);
+static void BRecvWait(MPI_Request request[], int isubx,
+ int isuby, int dsizex, realtype *cext,
+ realtype *buffer);
+static int check_flag(void *flagvalue, char *funcname, int opt, int id);
+
+/*
+ *--------------------------------------------------------------------
+ * MAIN PROGRAM
+ *--------------------------------------------------------------------
+ */
+
+int main(int argc, char *argv[])
+{
+ MPI_Comm comm;
+ void *kmem;
+ UserData data;
+ N_Vector cc, sc, constraints;
+ int globalstrategy;
+ long int Nlocal;
+ realtype fnormtol, scsteptol, dq_rel_uu;
+ int flag, maxl, maxlrst;
+ long int mudq, mldq, mukeep, mlkeep;
+ int my_pe, npes, npelast = NPEX*NPEY-1;
+
+ data = NULL;
+ kmem = NULL;
+ cc = sc = constraints = NULL;
+
+ /* Get processor number and total number of pe's */
+ MPI_Init(&argc, &argv);
+ comm = MPI_COMM_WORLD;
+ MPI_Comm_size(comm, &npes);
+ MPI_Comm_rank(comm, &my_pe);
+
+ 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);
+ return(1);
+ }
+
+ /* Allocate memory, and set problem data, initial values, tolerances */
+
+ /* Set local length */
+ Nlocal = NUM_SPECIES*MXSUB*MYSUB;
+
+ /* Allocate and initialize user data block */
+ data = AllocUserData();
+ if (check_flag((void *)data, "AllocUserData", 2, my_pe)) MPI_Abort(comm, 1);
+ InitUserData(my_pe, Nlocal, comm, data);
+
+ /* Choose global strategy */
+ globalstrategy = KIN_NONE;
+
+ /* Allocate and initialize vectors */
+ cc = N_VNew_Parallel(comm, Nlocal, NEQ);
+ if (check_flag((void *)cc, "N_VNew_Parallel", 0, my_pe)) MPI_Abort(comm, 1);
+ 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);
+ constraints = N_VNew_Parallel(comm, Nlocal, 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;
+
+ /* 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();
+ if (check_flag((void *)kmem, "KINCreate", 0, my_pe)) MPI_Abort(comm, 1);
+
+ /* 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);
+
+ /* 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);
+
+ flag = KINSetScaledStepTol(kmem, scsteptol);
+ if (check_flag(&flag, "KINSetScaledStepTol", 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
+ communication functions func_local and gcomm=NULL (all communication
+ needed for the func_local is already done in func). */
+ dq_rel_uu = ZERO;
+ 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 */
+ flag = KINSol(kmem, /* KINSol memory block */
+ cc, /* initial guesss on input; solution vector */
+ globalstrategy, /* global stragegy 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);
+
+ /* Print final statistics and free memory */
+ if (my_pe == 0)
+ PrintFinalStats(kmem);
+
+ N_VDestroy_Parallel(cc);
+ N_VDestroy_Parallel(sc);
+
+ KINFree(&kmem);
+ FreeUserData(data);
+
+ MPI_Finalize();
+
+ return(0);
+}
+
+/* Readability definitions used in other routines below */
+
+#define acoef (data->acoef)
+#define bcoef (data->bcoef)
+#define cox (data->cox)
+#define coy (data->coy)
+
+/*
+ *--------------------------------------------------------------------
+ * FUNCTIONS CALLED BY KINSOL
+ *--------------------------------------------------------------------
+ */
+
+/*
+ * ccomm routine. This routine performs all communication
+ * between processors of data needed to calculate f.
+ */
+
+static int ccomm(long int Nlocal, N_Vector cc, void *userdata)
+{
+
+ realtype *cdata, *cext, buffer[2*NUM_SPECIES*MYSUB];
+ UserData data;
+ MPI_Comm comm;
+ int my_pe, isubx, isuby, nsmxsub, nsmysub;
+ MPI_Request request[4];
+
+ /* Get comm, my_pe, subgrid indices, data sizes, extended array cext */
+ data = (UserData) userdata;
+ comm = data->comm; my_pe = data->my_pe;
+ isubx = data->isubx; isuby = data->isuby;
+ nsmxsub = data->nsmxsub;
+ nsmysub = NUM_SPECIES*MYSUB;
+ cext = data->cext;
+
+ cdata = NV_DATA_P(cc);
+
+ /* Start receiving boundary data from neighboring PEs */
+ BRecvPost(comm, request, my_pe, isubx, isuby, nsmxsub, nsmysub, cext, buffer);
+
+ /* Send data from boundary of local grid to neighboring PEs */
+ BSend(comm, my_pe, isubx, isuby, nsmxsub, nsmysub, cdata);
+
+ /* Finish receiving boundary data from neighboring PEs */
+ BRecvWait(request, isubx, isuby, nsmxsub, cext, buffer);
+
+ return(0);
+}
+
+/*
+ * System function for predator-prey system - calculation part
+ */
+
+static int func_local(long int 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;
+ int i, jx, jy, is, ly;
+ int isubx, isuby, nsmxsub, nsmxsub2;
+ int shifty, offsetc, offsetce, offsetcl, offsetcr, offsetcd, offsetcu;
+ UserData data;
+
+ data = (UserData)user_data;
+ cdata = NV_DATA_P(cc);
+
+ /* Get subgrid indices, data sizes, extended work array cext */
+ isubx = data->isubx; isuby = data->isuby;
+ nsmxsub = data->nsmxsub; nsmxsub2 = data->nsmxsub2;
+ cext = data->cext;
+
+ /* Copy local segment of cc vector into the working extended array cext */
+ offsetc = 0;
+ offsetce = nsmxsub2 + NUM_SPECIES;
+ for (ly = 0; ly < MYSUB; ly++) {
+ for (i = 0; i < nsmxsub; i++) cext[offsetce+i] = cdata[offsetc+i];
+ offsetc = offsetc + nsmxsub;
+ offsetce = offsetce + nsmxsub2;
+ }
+
+ /* To facilitate homogeneous Neumann boundary conditions, when this is a
+ boundary PE, copy data from the first interior mesh line of cc to cext */
+
+ /* If isuby = 0, copy x-line 2 of cc to cext */
+ if (isuby == 0) {
+ for (i = 0; i < nsmxsub; i++) cext[NUM_SPECIES+i] = cdata[nsmxsub+i];
+ }
+
+ /* If isuby = NPEY-1, copy x-line MYSUB-1 of cc to cext */
+ if (isuby == NPEY-1) {
+ offsetc = (MYSUB-2)*nsmxsub;
+ offsetce = (MYSUB+1)*nsmxsub2 + NUM_SPECIES;
+ for (i = 0; i < nsmxsub; i++) cext[offsetce+i] = cdata[offsetc+i];
+ }
+
+ /* If isubx = 0, copy y-line 2 of cc to cext */
+ if (isubx == 0) {
+ for (ly = 0; ly < MYSUB; ly++) {
+ offsetc = ly*nsmxsub + NUM_SPECIES;
+ offsetce = (ly+1)*nsmxsub2;
+ for (i = 0; i < NUM_SPECIES; i++) cext[offsetce+i] = cdata[offsetc+i];
+ }
+ }
+
+ /* If isubx = NPEX-1, copy y-line MXSUB-1 of cc to cext */
+ if (isubx == NPEX-1) {
+ for (ly = 0; ly < MYSUB; ly++) {
+ offsetc = (ly+1)*nsmxsub - 2*NUM_SPECIES;
+ offsetce = (ly+2)*nsmxsub2 - NUM_SPECIES;
+ for (i = 0; i < NUM_SPECIES; i++) cext[offsetce+i] = cdata[offsetc+i];
+ }
+ }
+
+ /* Loop over all mesh points, evaluating rate arra at each point */
+ delx = data->dx;
+ dely = data->dy;
+ shifty = (MXSUB+2)*NUM_SPECIES;
+
+ for (jy = 0; jy < MYSUB; jy++) {
+
+ yy = dely*(jy + isuby * MYSUB);
+
+ for (jx = 0; jx < MXSUB; jx++) {
+
+ xx = delx * (jx + isubx * MXSUB);
+ cxy = IJ_Vptr(cc,jx,jy);
+ rxy = IJ_Vptr(data->rates,jx,jy);
+ fxy = IJ_Vptr(fval,jx,jy);
+
+ WebRate(xx, yy, cxy, rxy, user_data);
+
+ offsetc = (jx+1)*NUM_SPECIES + (jy+1)*NSMXSUB2;
+ offsetcd = offsetc - shifty;
+ offsetcu = offsetc + shifty;
+ offsetcl = offsetc - NUM_SPECIES;
+ offsetcr = offsetc + NUM_SPECIES;
+
+ for (is = 0; is < NUM_SPECIES; is++) {
+
+ /* differencing in x */
+ dcydi = cext[offsetc+is] - cext[offsetcd+is];
+ dcyui = cext[offsetcu+is] - cext[offsetc+is];
+
+ /* differencing in y */
+ dcxli = cext[offsetc+is] - cext[offsetcl+is];
+ dcxri = cext[offsetcr+is] - cext[offsetc+is];
+
+ /* compute the value at xx , yy */
+ fxy[is] = (coy)[is] * (dcyui - dcydi) +
+ (cox)[is] * (dcxri - dcxli) + rxy[is];
+
+ } /* end of is loop */
+
+ } /* end of jx loop */
+
+ } /* end of jy loop */
+
+ return(0);
+}
+
+/*
+ * System function routine. Evaluate f(cc). First call ccomm to do
+ * communication of subgrid boundary data into cext. Then calculate f
+ * by a call to func_local.
+ */
+
+static int func(N_Vector cc, N_Vector fval, void *user_data)
+{
+ UserData data;
+
+ data = (UserData) user_data;
+
+ /* Call ccomm to do inter-processor communicaiton */
+ ccomm(data->Nlocal, cc, data);
+
+ /* Call func_local to calculate all right-hand sides */
+ func_local(data->Nlocal, cc, fval, data);
+
+ return(0);
+}
+
+/*
+ * Interaction rate function routine
+ */
+
+static void WebRate(realtype xx, realtype yy, realtype *cxy, realtype *ratesxy,
+ void *user_data)
+{
+ int i;
+ realtype fac;
+ UserData data;
+
+ data = (UserData)user_data;
+
+ for (i = 0; i<NUM_SPECIES; i++)
+ ratesxy[i] = DotProd(NUM_SPECIES, cxy, acoef[i]);
+
+ fac = ONE + ALPHA * xx * yy;
+
+ for (i = 0; i < NUM_SPECIES; i++)
+ ratesxy[i] = cxy[i] * ( bcoef[i] * fac + ratesxy[i] );
+}
+
+/*
+ * Dot product routine for realtype arrays
+ */
+
+static realtype DotProd(int size, realtype *x1, realtype *x2)
+{
+ int i;
+ realtype *xx1, *xx2, temp = ZERO;
+
+ xx1 = x1; xx2 = x2;
+ for (i = 0; i < size; i++) temp += (*xx1++) * (*xx2++);
+
+ return(temp);
+}
+
+/*
+ *--------------------------------------------------------------------
+ * PRIVATE FUNCTIONS
+ *--------------------------------------------------------------------
+ */
+
+/*
+ * Allocate memory for data structure of type UserData
+ */
+
+static UserData AllocUserData(void)
+{
+ UserData data;
+
+ data = (UserData) malloc(sizeof *data);
+
+ acoef = newDenseMat(NUM_SPECIES, NUM_SPECIES);
+ bcoef = (realtype *)malloc(NUM_SPECIES * sizeof(realtype));
+ cox = (realtype *)malloc(NUM_SPECIES * sizeof(realtype));
+ coy = (realtype *)malloc(NUM_SPECIES * sizeof(realtype));
+
+ return(data);
+}
+
+/*
+ * Load problem constants in data
+ */
+
+static void InitUserData(int my_pe, long int Nlocal, 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;
+ data->np = NUM_SPECIES/2;
+ data->ax = AX;
+ data->ay = AY;
+ data->dx = (data->ax)/(MX-1);
+ data->dy = (data->ay)/(MY-1);
+ data->my_pe = my_pe;
+ data->Nlocal = Nlocal;
+ data->comm = comm;
+ data->isuby = my_pe/NPEX;
+ 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;
+
+ dx2=(data->dx)*(data->dx); dy2=(data->dy)*(data->dy);
+
+ for (i = 0; i < np; i++) {
+ a1= &(acoef[i][np]);
+ a2= &(acoef[i+np][0]);
+ a3= &(acoef[i][0]);
+ a4= &(acoef[i+np][np]);
+
+ /* Fill in the portion of acoef in the four quadrants, row by row */
+ for (j = 0; j < np; j++) {
+ *a1++ = -GG;
+ *a2++ = EE;
+ *a3++ = ZERO;
+ *a4++ = ZERO;
+ }
+
+ /* and then change the diagonal elements of acoef to -AA */
+ acoef[i][i]=-AA;
+ acoef[i+np][i+np] = -AA;
+
+ bcoef[i] = BB;
+ bcoef[i+np] = -BB;
+
+ cox[i]=DPREY/dx2;
+ cox[i+np]=DPRED/dx2;
+
+ coy[i]=DPREY/dy2;
+ coy[i+np]=DPRED/dy2;
+ }
+}
+
+/*
+ * Free data memory
+ */
+
+static void FreeUserData(UserData data)
+{
+
+ destroyMat(acoef);
+ free(bcoef);
+ free(cox); free(coy);
+ N_VDestroy_Parallel(data->rates);
+
+ free(data);
+
+}
+
+/*
+ * Set initial conditions in cc
+ */
+
+static void SetInitialProfiles(N_Vector cc, N_Vector sc)
+{
+ int i, jx, jy;
+ realtype *cloc, *sloc;
+ realtype ctemp[NUM_SPECIES], stemp[NUM_SPECIES];
+
+ /* Initialize arrays ctemp and stemp used in the loading process */
+ for (i = 0; i < NUM_SPECIES/2; i++) {
+ ctemp[i] = PREYIN;
+ stemp[i] = ONE;
+ }
+ for (i = NUM_SPECIES/2; i < NUM_SPECIES; i++) {
+ 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++) {
+ cloc = IJ_Vptr(cc,jx,jy);
+ sloc = IJ_Vptr(sc,jx,jy);
+ for (i = 0; i < NUM_SPECIES; i++){
+ cloc[i] = ctemp[i];
+ sloc[i] = stemp[i];
+ }
+ }
+ }
+
+}
+
+/*
+ * Print first lines of output (problem description)
+ */
+
+static void PrintHeader(int globalstrategy, int maxl, int maxlrst,
+ long int mudq, long int mldq,
+ long int mukeep, long int mlkeep,
+ realtype fnormtol, realtype scsteptol)
+{
+ printf("\nPredator-prey test problem-- KINSol (parallel-BBD 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 band-block-diagonal matrix from KINBBDPRE\n");
+ printf(" Difference quotient half-bandwidths: mudq = %d, mldq = %d\n",
+ mudq, mldq);
+ printf(" Retained band block half-bandwidths: mukeep = %d, mlkeep = %d\n",
+ mukeep, mlkeep);
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("Tolerance parameters: fnormtol = %Lg scsteptol = %Lg\n",
+ fnormtol, scsteptol);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("Tolerance parameters: fnormtol = %lg scsteptol = %lg\n",
+ fnormtol, scsteptol);
+#else
+ printf("Tolerance parameters: fnormtol = %g scsteptol = %g\n",
+ fnormtol, scsteptol);
+#endif
+
+ 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);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("At all mesh points: %lg %lg %lg %lg %lg %lg\n",
+ 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);
+#endif
+}
+
+/*
+ * Print sample of current cc values
+ */
+
+static void PrintOutput(int my_pe, MPI_Comm comm, N_Vector cc)
+{
+ int is, i0, npelast;
+ realtype *ct, tempc[NUM_SPECIES];
+ MPI_Status status;
+
+ npelast = NPEX*NPEY - 1;
+
+ ct = NV_DATA_P(cc);
+
+ /* Send the cc values (for all species) at the top right mesh point to PE 0 */
+ if (my_pe == npelast) {
+ i0 = NUM_SPECIES*(MXSUB*MYSUB-1);
+ if (npelast!=0)
+ MPI_Send(&ct[i0],NUM_SPECIES,PVEC_REAL_MPI_TYPE,0,0,comm);
+ else /* single processor case */
+ for (is = 0; is < NUM_SPECIES; is++) tempc[is]=ct[i0+is];
+ }
+
+ /* On PE 0, receive the cc values at top right, then print performance data
+ and sampled solution values */
+ if (my_pe == 0) {
+
+ if (npelast != 0)
+ MPI_Recv(&tempc[0],NUM_SPECIES,PVEC_REAL_MPI_TYPE,npelast,0,comm,&status);
+
+ 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]);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf(" %lg",ct[is]);
+#else
+ 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]);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf(" %lg",tempc[is]);
+#else
+ printf(" %g",tempc[is]);
+#endif
+ }
+ printf("\n\n");
+ }
+}
+
+/*
+ * Print final statistics contained in iopt
+ */
+
+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, 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);
+ check_flag(&flag, "KINSpilsGetNumPrecEvals", 1, 0);
+ flag = KINSpilsGetNumPrecSolves(kmem, &nps);
+ check_flag(&flag, "KINSpilsGetNumPrecSolves", 1, 0);
+ flag = KINSpilsGetNumConvFails(kmem, &ncfl);
+ check_flag(&flag, "KINSpilsGetNumConvFails", 1, 0);
+ flag = KINSpilsGetNumFuncEvals(kmem, &nfeSG);
+ check_flag(&flag, "KINSpilsGetNumFuncEvals", 1, 0);
+
+ printf("Final Statistics.. \n");
+ 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);
+
+}
+
+/*
+ * Routine to send boundary data to neighboring PEs
+ */
+
+static void BSend(MPI_Comm comm, int my_pe,
+ int isubx, int isuby,
+ int dsizex, int dsizey, realtype *cdata)
+{
+ int i, ly;
+ int offsetc, offsetbuf;
+ realtype bufleft[NUM_SPECIES*MYSUB], bufright[NUM_SPECIES*MYSUB];
+
+ /* If isuby > 0, send data from bottom x-line of u */
+ if (isuby != 0)
+ MPI_Send(&cdata[0], dsizex, PVEC_REAL_MPI_TYPE, my_pe-NPEX, 0, comm);
+
+ /* If isuby < NPEY-1, send data from top x-line of u */
+ if (isuby != NPEY-1) {
+ offsetc = (MYSUB-1)*dsizex;
+ MPI_Send(&cdata[offsetc], dsizex, PVEC_REAL_MPI_TYPE, my_pe+NPEX, 0, comm);
+ }
+
+ /* If isubx > 0, send data from left y-line of u (via bufleft) */
+ if (isubx != 0) {
+ for (ly = 0; ly < MYSUB; ly++) {
+ offsetbuf = ly*NUM_SPECIES;
+ offsetc = ly*dsizex;
+ for (i = 0; i < NUM_SPECIES; i++)
+ bufleft[offsetbuf+i] = cdata[offsetc+i];
+ }
+ MPI_Send(&bufleft[0], dsizey, PVEC_REAL_MPI_TYPE, my_pe-1, 0, comm);
+ }
+
+ /* If isubx < NPEX-1, send data from right y-line of u (via bufright) */
+ if (isubx != NPEX-1) {
+ for (ly = 0; ly < MYSUB; ly++) {
+ offsetbuf = ly*NUM_SPECIES;
+ offsetc = offsetbuf*MXSUB + (MXSUB-1)*NUM_SPECIES;
+ for (i = 0; i < NUM_SPECIES; i++)
+ bufright[offsetbuf+i] = cdata[offsetc+i];
+ }
+ MPI_Send(&bufright[0], dsizey, PVEC_REAL_MPI_TYPE, my_pe+1, 0, comm);
+ }
+}
+
+/*
+ * Routine to start receiving boundary data from neighboring PEs.
+ * Notes:
+ * 1) buffer should be able to hold 2*NUM_SPECIES*MYSUB realtype entries,
+ * should be passed to both the BRecvPost and BRecvWait functions, and
+ * should not be manipulated between the two calls.
+ * 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,
+ int dsizex, int dsizey,
+ realtype *cext, realtype *buffer)
+{
+ int offsetce;
+
+ /* Have bufleft and bufright use the same buffer */
+ realtype *bufleft = buffer, *bufright = buffer+NUM_SPECIES*MYSUB;
+
+ /* If isuby > 0, receive data for bottom x-line of cext */
+ if (isuby != 0)
+ MPI_Irecv(&cext[NUM_SPECIES], dsizex, PVEC_REAL_MPI_TYPE,
+ my_pe-NPEX, 0, comm, &request[0]);
+
+ /* If isuby < NPEY-1, receive data for top x-line of cext */
+ if (isuby != NPEY-1) {
+ offsetce = NUM_SPECIES*(1 + (MYSUB+1)*(MXSUB+2));
+ MPI_Irecv(&cext[offsetce], dsizex, PVEC_REAL_MPI_TYPE,
+ my_pe+NPEX, 0, comm, &request[1]);
+ }
+
+ /* If isubx > 0, receive data for left y-line of cext (via bufleft) */
+ if (isubx != 0) {
+ MPI_Irecv(&bufleft[0], dsizey, PVEC_REAL_MPI_TYPE,
+ my_pe-1, 0, comm, &request[2]);
+ }
+
+ /* If isubx < NPEX-1, receive data for right y-line of cext (via bufright) */
+ if (isubx != NPEX-1) {
+ MPI_Irecv(&bufright[0], dsizey, PVEC_REAL_MPI_TYPE,
+ my_pe+1, 0, comm, &request[3]);
+ }
+}
+
+/*
+ * Routine to finish receiving boundary data from neighboring PEs.
+ * Notes:
+ * 1) buffer should be able to hold 2*NUM_SPECIES*MYSUB realtype entries,
+ * should be passed to both the BRecvPost and BRecvWait functions, and
+ * should not be manipulated between the two calls.
+ * 2) request should have 4 entries, and should be passed in both calls also.
+ */
+
+static void BRecvWait(MPI_Request request[], int isubx,
+ int isuby, int dsizex, realtype *cext,
+ realtype *buffer)
+{
+ int i, ly;
+ int dsizex2, offsetce, offsetbuf;
+ realtype *bufleft = buffer, *bufright = buffer+NUM_SPECIES*MYSUB;
+ MPI_Status status;
+
+ dsizex2 = dsizex + 2*NUM_SPECIES;
+
+ /* If isuby > 0, receive data for bottom x-line of cext */
+ if (isuby != 0)
+ MPI_Wait(&request[0],&status);
+
+ /* If isuby < NPEY-1, receive data for top x-line of cext */
+ if (isuby != NPEY-1)
+ MPI_Wait(&request[1],&status);
+
+ /* If isubx > 0, receive data for left y-line of cext (via bufleft) */
+ if (isubx != 0) {
+ MPI_Wait(&request[2],&status);
+
+ /* Copy the buffer to cext */
+ for (ly = 0; ly < MYSUB; ly++) {
+ offsetbuf = ly*NUM_SPECIES;
+ offsetce = (ly+1)*dsizex2;
+ for (i = 0; i < NUM_SPECIES; i++)
+ cext[offsetce+i] = bufleft[offsetbuf+i];
+ }
+ }
+
+ /* If isubx < NPEX-1, receive data for right y-line of cext (via bufright) */
+ if (isubx != NPEX-1) {
+ MPI_Wait(&request[3],&status);
+
+ /* Copy the buffer to cext */
+ for (ly = 0; ly < MYSUB; ly++) {
+ offsetbuf = ly*NUM_SPECIES;
+ offsetce = (ly+2)*dsizex2 - NUM_SPECIES;
+ for (i = 0; i < NUM_SPECIES; i++)
+ cext[offsetce+i] = bufright[offsetbuf+i];
+ }
+ }
+}
+/*
+ * 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, char *funcname, int opt, int id)
+{
+ int *errflag;
+
+ /* Check if SUNDIALS function returned NULL pointer - no memory allocated */
+ if (opt == 0 && flagvalue == NULL) {
+ fprintf(stderr,
+ "\nSUNDIALS_ERROR(%d): %s() failed - returned NULL pointer\n\n",
+ id, funcname);
+ return(1);
+ }
+
+ /* Check if flag < 0 */
+ else if (opt == 1) {
+ errflag = (int *) flagvalue;
+ if (*errflag < 0) {
+ fprintf(stderr,
+ "\nSUNDIALS_ERROR(%d): %s() failed with flag = %d\n\n",
+ id, funcname, *errflag);
+ return(1);
+ }
+ }
+
+ /* Check if function returned NULL pointer - no memory allocated */
+ else if (opt == 2 && flagvalue == NULL) {
+ fprintf(stderr,
+ "\nMEMORY_ERROR(%d): %s() failed - returned NULL pointer\n\n",
+ id, funcname);
+ return(1);
+ }
+
+ return(0);
+}
diff --git a/examples/kinsol/parallel/kinFoodWeb_kry_bbd_p.out b/examples/kinsol/parallel/kinFoodWeb_kry_bbd_p.out
new file mode 100644
index 0000000..49f6ea8
--- /dev/null
+++ b/examples/kinsol/parallel/kinFoodWeb_kry_bbd_p.out
@@ -0,0 +1,33 @@
+
+Predator-prey test problem-- KINSol (parallel-BBD version)
+
+Mesh dimensions = 20 X 20
+Number of species = 6
+Total system size = 2400
+
+Subgrid dimensions = 10 X 10
+Processor array is 2 X 2
+
+Flag globalstrategy = 0 (0 = None, 1 = Linesearch)
+Linear solver is SPGMR with maxl = 20, maxlrst = 2
+Preconditioning uses band-block-diagonal matrix from KINBBDPRE
+ Difference quotient half-bandwidths: mudq = 11, mldq = 11
+ Retained band block half-bandwidths: mukeep = 6, mlkeep = 6
+Tolerance parameters: fnormtol = 1e-07 scsteptol = 1e-13
+
+Initial profile of concentration
+At all mesh points: 1 1 1 30000 30000 30000
+
+
+Computed equilibrium species concentrations:
+
+At bottom left:
+ 1.165 1.165 1.165 34949 34949 34949
+
+At top right:
+ 1.25552 1.25552 1.25552 37663.2 37663.2 37663.2
+
+Final Statistics..
+nni = 9 nli = 464
+nfe = 10 nfeSG = 473
+nps = 473 npe = 1 ncfl = 6
diff --git a/examples/kinsol/parallel/kinFoodWeb_kry_p.c b/examples/kinsol/parallel/kinFoodWeb_kry_p.c
new file mode 100644
index 0000000..35c4664
--- /dev/null
+++ b/examples/kinsol/parallel/kinFoodWeb_kry_p.c
@@ -0,0 +1,1112 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.3 $
+ * $Date: 2010/12/01 23:09:24 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Allan Taylor, Alan Hindmarsh and
+ * Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Example (parallel):
+ *
+ * This example solves a nonlinear system that arises from a system
+ * of partial differential equations. The PDE system is a food web
+ * 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
+ * 0 = d(i)*(c + c ) + f (x,y,c) (i=1,...,ns)
+ * xx yy i
+ *
+ * where
+ *
+ * i ns j
+ * f (x,y,c) = c * (b(i) + sum a(i,j)*c )
+ * i j=1
+ *
+ * The number of species is ns = 2 * np, with the first np being
+ * prey and the last np being predators. The number np is both
+ * the number of prey and predator species. The coefficients a(i,j),
+ * b(i), d(i) are:
+ *
+ * a(i,i) = -AA (all i)
+ * a(i,j) = -GG (i <= np , j > np)
+ * a(i,j) = EE (i > np, j <= np)
+ * b(i) = BB * (1 + alpha * x * y) (i <= np)
+ * b(i) =-BB * (1 + alpha * x * y) (i > np)
+ * d(i) = DPREY (i <= np)
+ * d(i) = DPRED ( i > np)
+ *
+ * The various scalar parameters are set using define's or in
+ * 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.
+ *
+ * The PDEs are discretized by central differencing on a MX by
+ * MY mesh.
+ *
+ * The nonlinear system is solved by KINSOL using the method
+ * 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.
+ * -----------------------------------------------------------------
+ * References:
+ *
+ * 1. Peter N. Brown and Youcef Saad,
+ * Hybrid Krylov Methods for Nonlinear Systems of Equations
+ * LLNL report UCRL-97645, November 1987.
+ *
+ * 2. Peter N. Brown and Alan C. Hindmarsh,
+ * Reduced Storage Matrix Methods in Stiff ODE systems,
+ * 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.)
+ * ----------------------------------------------------------------------
+ * Run command line: mpirun -np N -machinefile machines kinFoodWeb_kry_p
+ * where N = NPEX * NPEY is the number of processors.
+ * ----------------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#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 <mpi.h>
+
+
+/* Problem Constants */
+
+#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 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 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 */
+#define BB RCONST(1.0) /* value of coefficient BB in above eqns */
+#define DPREY RCONST(1.0) /* value of coefficient dprey above */
+#define DPRED RCONST(0.5) /* value of coefficient dpred above */
+#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 THOUSAND RCONST(1000.0) /* one thousand */
+#define ZERO RCONST(0.0) /* 0. */
+#define ONE RCONST(1.0) /* 1. */
+#define PREYIN RCONST(1.0) /* initial guess for prey concentrations. */
+#define PREDIN RCONST(30000.0)/* initial guess for predator concs. */
+
+/* User-defined vector access macro: IJ_Vptr */
+
+/* IJ_Vptr is defined in order to translate from the underlying 3D structure
+ of the dependent variable vector to the 1D storage scheme for an N-vector.
+ IJ_Vptr(vv,i,j) returns a pointer to the location in vv corresponding to
+ indices is = 0, jx = i, jy = j. */
+
+#define IJ_Vptr(vv,i,j) (&NV_Ith_P(vv, i*NUM_SPECIES + j*NSMXSUB))
+
+/* Type : UserData
+ contains preconditioner blocks, pivot arrays, and problem constants */
+
+typedef struct {
+ realtype **P[MXSUB][MYSUB];
+ long int *pivot[MXSUB][MYSUB];
+ realtype **acoef, *bcoef;
+ N_Vector rates;
+ realtype *cox, *coy;
+ realtype ax, ay, dx, dy;
+ realtype uround, sqruround;
+ int mx, my, ns, np;
+ realtype cext[NUM_SPECIES * (MXSUB+2)*(MYSUB+2)];
+ int my_pe, isubx, isuby, nsmxsub, nsmxsub2;
+ MPI_Comm comm;
+} *UserData;
+
+/* 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);
+
+static int PSolvebd(N_Vector cc, N_Vector cscale,
+ N_Vector fval, N_Vector fscale,
+ N_Vector vv, void *user_data,
+ N_Vector vtemp);
+
+/* Private Helper Functions */
+
+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,
+ 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,
+ void *user_data);
+static realtype DotProd(int size, realtype *x1, realtype *x2);
+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,
+ int isubx, int isuby,
+ int dsizex, int dsizey,
+ realtype *cext, realtype *buffer);
+static void BRecvWait(MPI_Request request[], int isubx,
+ int isuby, int dsizex, realtype *cext,
+ realtype *buffer);
+static void ccomm(realtype *cdata, UserData data);
+static void fcalcprpr(N_Vector cc, N_Vector fval,void *user_data);
+static int check_flag(void *flagvalue, char *funcname, int opt, int id);
+
+/*
+ *--------------------------------------------------------------------
+ * MAIN PROGRAM
+ *--------------------------------------------------------------------
+ */
+
+int main(int argc, char *argv[])
+
+{
+ int globalstrategy;
+ long int 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;
+ MPI_Comm comm;
+
+ cc = sc = constraints = NULL;
+ data = NULL;
+ kmem = NULL;
+
+ /* Get processor number and total number of pe's */
+ MPI_Init(&argc, &argv);
+ comm = MPI_COMM_WORLD;
+ MPI_Comm_size(comm, &npes);
+ MPI_Comm_rank(comm, &my_pe);
+
+ 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);
+ MPI_Finalize();
+ return(1);
+ }
+
+ /* Allocate memory, and set problem data, initial values, tolerances */
+
+ /* Set local vector length */
+ local_N = NUM_SPECIES*MXSUB*MYSUB;
+
+ /* Allocate and initialize user data block */
+ data = AllocUserData();
+ if (check_flag((void *)data, "AllocUserData", 0, my_pe)) MPI_Abort(comm, 1);
+ InitUserData(my_pe, comm, data);
+
+ /* 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);
+ sc = N_VNew_Parallel(comm, local_N, NEQ);
+ if (check_flag((void *)sc, "N_VNew_Parallel", 0, my_pe)) MPI_Abort(comm, 1);
+ data->rates = N_VNew_Parallel(comm, local_N, NEQ);
+ if (check_flag((void *)data->rates, "N_VNew_Parallel", 0, my_pe)) MPI_Abort(comm, 1);
+ 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;
+
+ /* 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);
+ 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, "KINSetScaledStepTop", 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);
+
+ flag = KINSpilsSetMaxRestarts(kmem, maxlrst);
+ if (check_flag(&flag, "KINSpilsSetMaxRestarts", 1, my_pe)) MPI_Abort(comm, 1);
+ 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)
+ 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 */
+ 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);
+
+ /* Print final statistics and free memory */
+ if (my_pe == 0)
+ PrintFinalStats(kmem);
+
+ N_VDestroy_Parallel(cc);
+ N_VDestroy_Parallel(sc);
+ KINFree(&kmem);
+ FreeUserData(data);
+
+ MPI_Finalize();
+
+ return(0);
+}
+
+/* Readability definitions used in other routines below */
+
+#define acoef (data->acoef)
+#define bcoef (data->bcoef)
+#define cox (data->cox)
+#define coy (data->coy)
+
+/*
+ *--------------------------------------------------------------------
+ * FUNCTIONS CALLED BY KINSOL
+ *--------------------------------------------------------------------
+ */
+
+/*
+ * System function routine. Evaluate funcprpr(cc). First call ccomm to do
+ * communication of subgrid boundary data into cext. Then calculate funcprpr
+ * by a call to fcalcprpr.
+ */
+
+static int funcprpr(N_Vector cc, N_Vector fval, void *user_data)
+{
+ realtype *cdata, *fvdata;
+ UserData data;
+
+ cdata = NV_DATA_P(cc);
+ fvdata = NV_DATA_P(fval);
+ data = (UserData) user_data;
+
+ /* Call ccomm to do inter-processor communicaiton */
+ ccomm (cdata, data);
+
+ /* Call fcalcprpr to calculate all right-hand sides */
+ fcalcprpr (cc, fval, data);
+
+ return(0);
+}
+
+/*
+ * Preconditioner setup routine. Generate and preprocess P.
+ */
+
+static int Precondbd(N_Vector cc, N_Vector cscale,
+ N_Vector fval, N_Vector fscale,
+ void *user_data,
+ N_Vector vtemp1, N_Vector vtemp2)
+{
+ 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;
+ delx = data->dx;
+ dely = data->dy;
+
+ uround = data->uround;
+ sqruround = data->sqruround;
+ fac = N_VWL2Norm(fval, fscale);
+ r0 = THOUSAND * uround * fac * NEQ;
+ if(r0 == ZERO) r0 = ONE;
+
+ /* Loop over spatial points; get size NUM_SPECIES Jacobian block at each */
+ for (jy = 0; jy < MYSUB; jy++) {
+ yy = dely*(jy + data->isuby * MYSUB);
+
+ for (jx = 0; jx < MXSUB; jx++) {
+ xx = delx*(jx + data->isubx * MXSUB);
+ Pxy = (data->P)[jx][jy];
+ 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++) {
+
+ csave = cxy[j]; /* Save the j,jx,jy element of cc */
+ r = MAX(sqruround*ABS(csave), r0/scxy[j]);
+ cxy[j] += r; /* Perturb the j,jx,jy element of cc */
+ fac = ONE/r;
+
+ WebRate(xx, yy, cxy, perturb_rates, data);
+
+ /* Restore j,jx,jy element of cc */
+ cxy[j] = csave;
+
+ /* Load the j-th column of difference quotients */
+ Pxycol = Pxy[j];
+ 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 */
+ ret = denseGETRF(Pxy, NUM_SPECIES, NUM_SPECIES, (data->pivot)[jx][jy]);
+ if (ret != 0) return(1);
+
+ } /* end of jx loop */
+ } /* end of jy loop */
+
+ return(0);
+}
+
+/*
+ * Preconditioner solve routine
+ */
+
+static int PSolvebd(N_Vector cc, N_Vector cscale,
+ N_Vector fval, N_Vector fscale,
+ N_Vector vv, void *user_data,
+ N_Vector vtemp)
+{
+ realtype **Pxy, *vxy;
+ long int *piv, jx, jy;
+ UserData data;
+
+ data = (UserData)user_data;
+
+ for (jx = 0; jx < MXSUB; jx++) {
+
+ for (jy = 0; jy < MYSUB; jy++) {
+
+ /* For each (jx,jy), solve a linear system of size NUM_SPECIES.
+ vxy is the address of the corresponding portion of the vector vv;
+ Pxy is the address of the corresponding block of the matrix P;
+ piv is the address of the corresponding block of the array pivot. */
+ vxy = IJ_Vptr(vv,jx,jy);
+ Pxy = (data->P)[jx][jy];
+ piv = (data->pivot)[jx][jy];
+ denseGETRS(Pxy, NUM_SPECIES, piv, vxy);
+
+ } /* end of jy loop */
+
+ } /* end of jx loop */
+
+ return(0);
+}
+
+/*
+ * Interaction rate function routine
+ */
+
+static void WebRate(realtype xx, realtype yy, realtype *cxy, realtype *ratesxy,
+ void *user_data)
+{
+ int i;
+ realtype fac;
+ UserData data;
+
+ data = (UserData)user_data;
+
+ for (i = 0; i<NUM_SPECIES; i++)
+ ratesxy[i] = DotProd(NUM_SPECIES, cxy, acoef[i]);
+
+ fac = ONE + ALPHA * xx * yy;
+
+ for (i = 0; i < NUM_SPECIES; i++)
+ ratesxy[i] = cxy[i] * ( bcoef[i] * fac + ratesxy[i] );
+
+}
+
+/*
+ * Dot product routine for realtype arrays
+ */
+
+static realtype DotProd(int size, realtype *x1, realtype *x2)
+{
+ int i;
+ realtype *xx1, *xx2, temp = ZERO;
+
+ xx1 = x1; xx2 = x2;
+ for (i = 0; i < size; i++) temp += (*xx1++) * (*xx2++);
+ return(temp);
+
+}
+
+/*
+ *--------------------------------------------------------------------
+ * PRIVATE FUNCTIONS
+ *--------------------------------------------------------------------
+ */
+
+/*
+ * Allocate memory for data structure of type UserData
+ */
+
+static UserData AllocUserData(void)
+{
+ int jx, jy;
+ UserData data;
+
+ data = (UserData) malloc(sizeof *data);
+
+ 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);
+ }
+ }
+
+ acoef = newDenseMat(NUM_SPECIES, NUM_SPECIES);
+ bcoef = (realtype *)malloc(NUM_SPECIES * sizeof(realtype));
+ cox = (realtype *)malloc(NUM_SPECIES * sizeof(realtype));
+ coy = (realtype *)malloc(NUM_SPECIES * sizeof(realtype));
+
+ return(data);
+
+}
+
+/*
+ * Load problem constants in data
+ */
+
+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;
+ data->np = NUM_SPECIES/2;
+ data->ax = AX;
+ data->ay = AY;
+ data->dx = (data->ax)/(MX-1);
+ data->dy = (data->ay)/(MY-1);
+ data->uround = UNIT_ROUNDOFF;
+ data->sqruround = SQRT(data->uround);
+ data->my_pe = my_pe;
+ data->comm = comm;
+ data->isuby = my_pe/NPEX;
+ 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;
+
+ dx2=(data->dx)*(data->dx); dy2=(data->dy)*(data->dy);
+
+ for (i = 0; i < np; i++) {
+ a1= &(acoef[i][np]);
+ a2= &(acoef[i+np][0]);
+ a3= &(acoef[i][0]);
+ a4= &(acoef[i+np][np]);
+
+ /* Fill in the portion of acoef in the four quadrants, row by row */
+ for (j = 0; j < np; j++) {
+ *a1++ = -GG;
+ *a2++ = EE;
+ *a3++ = ZERO;
+ *a4++ = ZERO;
+ }
+
+ /* and then change the diagonal elements of acoef to -AA */
+ acoef[i][i]=-AA;
+ acoef[i+np][i+np] = -AA;
+
+ bcoef[i] = BB;
+ bcoef[i+np] = -BB;
+
+ cox[i]=DPREY/dx2;
+ cox[i+np]=DPRED/dx2;
+
+ coy[i]=DPREY/dy2;
+ coy[i+np]=DPRED/dy2;
+ }
+
+}
+
+/*
+ * Free data memory
+ */
+
+static void FreeUserData(UserData data)
+{
+ int jx, jy;
+
+ for (jx = 0; jx < MXSUB; jx++) {
+ for (jy = 0; jy < MYSUB; jy++) {
+ destroyMat((data->P)[jx][jy]);
+ destroyArray((data->pivot)[jx][jy]);
+ }
+ }
+
+ destroyMat(acoef);
+ free(bcoef);
+ free(cox);
+ free(coy);
+ N_VDestroy_Parallel(data->rates);
+ free(data);
+}
+
+/*
+ * Set initial conditions in cc
+ */
+
+static void SetInitialProfiles(N_Vector cc, N_Vector sc)
+{
+ int i, jx, jy;
+ realtype *cloc, *sloc;
+ realtype ctemp[NUM_SPECIES], stemp[NUM_SPECIES];
+
+ /* Initialize arrays ctemp and stemp used in the loading process */
+ for (i = 0; i < NUM_SPECIES/2; i++) {
+ ctemp[i] = PREYIN;
+ stemp[i] = ONE;
+ }
+ for (i = NUM_SPECIES/2; i < NUM_SPECIES; i++) {
+ 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++) {
+ cloc = IJ_Vptr(cc,jx,jy);
+ sloc = IJ_Vptr(sc,jx,jy);
+ for (i = 0; i < NUM_SPECIES; i++) {
+ cloc[i] = ctemp[i];
+ sloc[i] = stemp[i];
+ }
+ }
+ }
+}
+
+/*
+ * Print first lines of output (problem description)
+ */
+
+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");
+
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("Tolerance parameters: fnormtol = %Lg scsteptol = %Lg\n",
+ fnormtol, scsteptol);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("Tolerance parameters: fnormtol = %lg scsteptol = %lg\n",
+ fnormtol, scsteptol);
+#else
+ printf("Tolerance parameters: fnormtol = %g scsteptol = %g\n",
+ fnormtol, scsteptol);
+#endif
+
+ 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);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("At all mesh points: %lg %lg %lg %lg %lg %lg\n",
+ 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);
+#endif
+}
+
+/*
+ * Print sample of current cc values
+ */
+
+static void PrintOutput(int my_pe, MPI_Comm comm, N_Vector cc)
+{
+ int is, i0, npelast;
+ realtype *ct, tempc[NUM_SPECIES];
+ MPI_Status status;
+
+ npelast = NPEX*NPEY - 1;
+
+ ct = NV_DATA_P(cc);
+
+ /* Send the cc values (for all species) at the top right mesh point to PE 0 */
+ if (my_pe == npelast) {
+ i0 = NUM_SPECIES*(MXSUB*MYSUB-1);
+ if (npelast!=0)
+ MPI_Send(&ct[i0],NUM_SPECIES,PVEC_REAL_MPI_TYPE,0,0,comm);
+ else /* single processor case */
+ for (is = 0; is < NUM_SPECIES; is++) tempc[is]=ct[i0+is];
+ }
+
+ /* On PE 0, receive the cc values at top right, then print performance data
+ and sampled solution values */
+ if (my_pe == 0) {
+
+ if (npelast != 0)
+ MPI_Recv(&tempc[0],NUM_SPECIES,PVEC_REAL_MPI_TYPE,npelast,0,comm,&status);
+
+ 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]);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf(" %lg",ct[is]);
+#else
+ 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]);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf(" %lg",tempc[is]);
+#else
+ printf(" %g",tempc[is]);
+#endif
+ }
+ printf("\n\n");
+ }
+}
+
+/*
+ * Print final statistics contained in iopt
+ */
+
+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, 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);
+ check_flag(&flag, "KINSpilsGetNumPrecEvals", 1, 0);
+ flag = KINSpilsGetNumPrecSolves(kmem, &nps);
+ check_flag(&flag, "KINSpilsGetNumPrecSolves", 1, 0);
+ flag = KINSpilsGetNumConvFails(kmem, &ncfl);
+ check_flag(&flag, "KINSpilsGetNumConvFails", 1, 0);
+ flag = KINSpilsGetNumFuncEvals(kmem, &nfeSG);
+ check_flag(&flag, "KINSpilsGetNumFuncEvals", 1, 0);
+
+ printf("Final Statistics.. \n");
+ 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);
+
+}
+
+/*
+ * Routine to send boundary data to neighboring PEs
+ */
+
+static void BSend(MPI_Comm comm, int my_pe,
+ int isubx, int isuby,
+ int dsizex, int dsizey, realtype *cdata)
+{
+ int i, ly;
+ int offsetc, offsetbuf;
+ realtype bufleft[NUM_SPECIES*MYSUB], bufright[NUM_SPECIES*MYSUB];
+
+ /* If isuby > 0, send data from bottom x-line of u */
+ if (isuby != 0)
+ MPI_Send(&cdata[0], dsizex, PVEC_REAL_MPI_TYPE, my_pe-NPEX, 0, comm);
+
+ /* If isuby < NPEY-1, send data from top x-line of u */
+ if (isuby != NPEY-1) {
+ offsetc = (MYSUB-1)*dsizex;
+ MPI_Send(&cdata[offsetc], dsizex, PVEC_REAL_MPI_TYPE, my_pe+NPEX, 0, comm);
+ }
+
+ /* If isubx > 0, send data from left y-line of u (via bufleft) */
+ if (isubx != 0) {
+ for (ly = 0; ly < MYSUB; ly++) {
+ offsetbuf = ly*NUM_SPECIES;
+ offsetc = ly*dsizex;
+ for (i = 0; i < NUM_SPECIES; i++)
+ bufleft[offsetbuf+i] = cdata[offsetc+i];
+ }
+ MPI_Send(&bufleft[0], dsizey, PVEC_REAL_MPI_TYPE, my_pe-1, 0, comm);
+ }
+
+ /* If isubx < NPEX-1, send data from right y-line of u (via bufright) */
+ if (isubx != NPEX-1) {
+ for (ly = 0; ly < MYSUB; ly++) {
+ offsetbuf = ly*NUM_SPECIES;
+ offsetc = offsetbuf*MXSUB + (MXSUB-1)*NUM_SPECIES;
+ for (i = 0; i < NUM_SPECIES; i++)
+ bufright[offsetbuf+i] = cdata[offsetc+i];
+ }
+ MPI_Send(&bufright[0], dsizey, PVEC_REAL_MPI_TYPE, my_pe+1, 0, comm);
+ }
+}
+
+/*
+ * Routine to start receiving boundary data from neighboring PEs.
+ * Notes:
+ * 1) buffer should be able to hold 2*NUM_SPECIES*MYSUB realtype entries,
+ * should be passed to both the BRecvPost and BRecvWait functions, and
+ * should not be manipulated between the two calls.
+ * 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,
+ int dsizex, int dsizey,
+ realtype *cext, realtype *buffer)
+{
+ int offsetce;
+
+ /* Have bufleft and bufright use the same buffer */
+ realtype *bufleft = buffer, *bufright = buffer+NUM_SPECIES*MYSUB;
+
+ /* If isuby > 0, receive data for bottom x-line of cext */
+ if (isuby != 0)
+ MPI_Irecv(&cext[NUM_SPECIES], dsizex, PVEC_REAL_MPI_TYPE,
+ my_pe-NPEX, 0, comm, &request[0]);
+
+ /* If isuby < NPEY-1, receive data for top x-line of cext */
+ if (isuby != NPEY-1) {
+ offsetce = NUM_SPECIES*(1 + (MYSUB+1)*(MXSUB+2));
+ MPI_Irecv(&cext[offsetce], dsizex, PVEC_REAL_MPI_TYPE,
+ my_pe+NPEX, 0, comm, &request[1]);
+ }
+
+ /* If isubx > 0, receive data for left y-line of cext (via bufleft) */
+ if (isubx != 0) {
+ MPI_Irecv(&bufleft[0], dsizey, PVEC_REAL_MPI_TYPE,
+ my_pe-1, 0, comm, &request[2]);
+ }
+
+ /* If isubx < NPEX-1, receive data for right y-line of cext (via bufright) */
+ if (isubx != NPEX-1) {
+ MPI_Irecv(&bufright[0], dsizey, PVEC_REAL_MPI_TYPE,
+ my_pe+1, 0, comm, &request[3]);
+ }
+}
+
+/*
+ * Routine to finish receiving boundary data from neighboring PEs.
+ * Notes:
+ * 1) buffer should be able to hold 2*NUM_SPECIES*MYSUB realtype entries,
+ * should be passed to both the BRecvPost and BRecvWait functions, and
+ * should not be manipulated between the two calls.
+ * 2) request should have 4 entries, and should be passed in both calls also.
+ */
+
+static void BRecvWait(MPI_Request request[], int isubx,
+ int isuby, int dsizex, realtype *cext,
+ realtype *buffer)
+{
+ int i, ly;
+ int dsizex2, offsetce, offsetbuf;
+ realtype *bufleft = buffer, *bufright = buffer+NUM_SPECIES*MYSUB;
+ MPI_Status status;
+
+ dsizex2 = dsizex + 2*NUM_SPECIES;
+
+ /* If isuby > 0, receive data for bottom x-line of cext */
+ if (isuby != 0)
+ MPI_Wait(&request[0],&status);
+
+ /* If isuby < NPEY-1, receive data for top x-line of cext */
+ if (isuby != NPEY-1)
+ MPI_Wait(&request[1],&status);
+
+ /* If isubx > 0, receive data for left y-line of cext (via bufleft) */
+ if (isubx != 0) {
+ MPI_Wait(&request[2],&status);
+
+ /* Copy the buffer to cext */
+ for (ly = 0; ly < MYSUB; ly++) {
+ offsetbuf = ly*NUM_SPECIES;
+ offsetce = (ly+1)*dsizex2;
+ for (i = 0; i < NUM_SPECIES; i++)
+ cext[offsetce+i] = bufleft[offsetbuf+i];
+ }
+ }
+
+ /* If isubx < NPEX-1, receive data for right y-line of cext (via bufright) */
+ if (isubx != NPEX-1) {
+ MPI_Wait(&request[3],&status);
+
+ /* Copy the buffer to cext */
+ for (ly = 0; ly < MYSUB; ly++) {
+ offsetbuf = ly*NUM_SPECIES;
+ offsetce = (ly+2)*dsizex2 - NUM_SPECIES;
+ for (i = 0; i < NUM_SPECIES; i++)
+ cext[offsetce+i] = bufright[offsetbuf+i];
+ }
+ }
+}
+
+/*
+ * ccomm routine. This routine performs all communication
+ * between processors of data needed to calculate f.
+ */
+
+static void ccomm(realtype *cdata, UserData data)
+{
+ realtype *cext, buffer[2*NUM_SPECIES*MYSUB];
+ MPI_Comm comm;
+ int my_pe, isubx, isuby, nsmxsub, nsmysub;
+ MPI_Request request[4];
+
+ /* Get comm, my_pe, subgrid indices, data sizes, extended array cext */
+ comm = data->comm; my_pe = data->my_pe;
+ isubx = data->isubx; isuby = data->isuby;
+ nsmxsub = data->nsmxsub;
+ nsmysub = NUM_SPECIES*MYSUB;
+ cext = data->cext;
+
+ /* Start receiving boundary data from neighboring PEs */
+ BRecvPost(comm, request, my_pe, isubx, isuby, nsmxsub, nsmysub, cext, buffer);
+
+ /* Send data from boundary of local grid to neighboring PEs */
+ BSend(comm, my_pe, isubx, isuby, nsmxsub, nsmysub, cdata);
+
+ /* Finish receiving boundary data from neighboring PEs */
+ BRecvWait(request, isubx, isuby, nsmxsub, cext, buffer);
+
+}
+
+/*
+ * System function for predator-prey system - calculation part
+ */
+
+static void fcalcprpr(N_Vector cc, N_Vector fval, void *user_data)
+{
+ realtype xx, yy, *cxy, *rxy, *fxy, dcydi, dcyui, dcxli, dcxri;
+ realtype *cext, dely, delx, *cdata;
+ int i, jx, jy, is, ly;
+ int isubx, isuby, nsmxsub, nsmxsub2;
+ int shifty, offsetc, offsetce, offsetcl, offsetcr, offsetcd, offsetcu;
+ UserData data;
+
+ data = (UserData)user_data;
+ cdata = NV_DATA_P(cc);
+
+ /* Get subgrid indices, data sizes, extended work array cext */
+ isubx = data->isubx; isuby = data->isuby;
+ nsmxsub = data->nsmxsub; nsmxsub2 = data->nsmxsub2;
+ cext = data->cext;
+
+ /* Copy local segment of cc vector into the working extended array cext */
+ offsetc = 0;
+ offsetce = nsmxsub2 + NUM_SPECIES;
+ for (ly = 0; ly < MYSUB; ly++) {
+ for (i = 0; i < nsmxsub; i++) cext[offsetce+i] = cdata[offsetc+i];
+ offsetc = offsetc + nsmxsub;
+ offsetce = offsetce + nsmxsub2;
+ }
+
+ /* To facilitate homogeneous Neumann boundary conditions, when this is a
+ boundary PE, copy data from the first interior mesh line of cc to cext */
+
+ /* If isuby = 0, copy x-line 2 of cc to cext */
+ if (isuby == 0) {
+ for (i = 0; i < nsmxsub; i++) cext[NUM_SPECIES+i] = cdata[nsmxsub+i];
+ }
+
+ /* If isuby = NPEY-1, copy x-line MYSUB-1 of cc to cext */
+ if (isuby == NPEY-1) {
+ offsetc = (MYSUB-2)*nsmxsub;
+ offsetce = (MYSUB+1)*nsmxsub2 + NUM_SPECIES;
+ for (i = 0; i < nsmxsub; i++) cext[offsetce+i] = cdata[offsetc+i];
+ }
+
+ /* If isubx = 0, copy y-line 2 of cc to cext */
+ if (isubx == 0) {
+ for (ly = 0; ly < MYSUB; ly++) {
+ offsetc = ly*nsmxsub + NUM_SPECIES;
+ offsetce = (ly+1)*nsmxsub2;
+ for (i = 0; i < NUM_SPECIES; i++) cext[offsetce+i] = cdata[offsetc+i];
+ }
+ }
+
+ /* If isubx = NPEX-1, copy y-line MXSUB-1 of cc to cext */
+ if (isubx == NPEX-1) {
+ for (ly = 0; ly < MYSUB; ly++) {
+ offsetc = (ly+1)*nsmxsub - 2*NUM_SPECIES;
+ offsetce = (ly+2)*nsmxsub2 - NUM_SPECIES;
+ for (i = 0; i < NUM_SPECIES; i++) cext[offsetce+i] = cdata[offsetc+i];
+ }
+ }
+
+ /* Loop over all mesh points, evaluating rate arra at each point */
+ delx = data->dx;
+ dely = data->dy;
+ shifty = (MXSUB+2)*NUM_SPECIES;
+
+ for (jy = 0; jy < MYSUB; jy++) {
+
+ yy = dely*(jy + isuby * MYSUB);
+
+ for (jx = 0; jx < MXSUB; jx++) {
+
+ xx = delx * (jx + isubx * MXSUB);
+ cxy = IJ_Vptr(cc,jx,jy);
+ rxy = IJ_Vptr(data->rates,jx,jy);
+ fxy = IJ_Vptr(fval,jx,jy);
+
+ WebRate(xx, yy, cxy, rxy, user_data);
+
+ offsetc = (jx+1)*NUM_SPECIES + (jy+1)*NSMXSUB2;
+ offsetcd = offsetc - shifty;
+ offsetcu = offsetc + shifty;
+ offsetcl = offsetc - NUM_SPECIES;
+ offsetcr = offsetc + NUM_SPECIES;
+
+ for (is = 0; is < NUM_SPECIES; is++) {
+
+ /* differencing in x */
+ dcydi = cext[offsetc+is] - cext[offsetcd+is];
+ dcyui = cext[offsetcu+is] - cext[offsetc+is];
+
+ /* differencing in y */
+ dcxli = cext[offsetc+is] - cext[offsetcl+is];
+ dcxri = cext[offsetcr+is] - cext[offsetc+is];
+
+ /* compute the value at xx , yy */
+ fxy[is] = (coy)[is] * (dcyui - dcydi) +
+ (cox)[is] * (dcxri - dcxli) + rxy[is];
+
+ } /* end of is loop */
+
+ } /* end of jx loop */
+
+ } /* end of jy loop */
+}
+
+/*
+ * 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, char *funcname, int opt, int id)
+{
+ int *errflag;
+
+ /* Check if SUNDIALS function returned NULL pointer - no memory allocated */
+ if (opt == 0 && flagvalue == NULL) {
+ fprintf(stderr,
+ "\nSUNDIALS_ERROR(%d): %s() failed - returned NULL pointer\n\n",
+ id, funcname);
+ return(1);
+ }
+
+ /* Check if flag < 0 */
+ else if (opt == 1) {
+ errflag = (int *) flagvalue;
+ if (*errflag < 0) {
+ fprintf(stderr,
+ "\nSUNDIALS_ERROR(%d): %s() failed with flag = %d\n\n",
+ id, funcname, *errflag);
+ return(1);
+ }
+ }
+
+ /* Check if function returned NULL pointer - no memory allocated */
+ else if (opt == 2 && flagvalue == NULL) {
+ fprintf(stderr,
+ "\nMEMORY_ERROR(%d): %s() failed - returned NULL pointer\n\n",
+ id, funcname);
+ return(1);
+ }
+
+ return(0);
+}
diff --git a/examples/kinsol/parallel/kinFoodWeb_kry_p.out b/examples/kinsol/parallel/kinFoodWeb_kry_p.out
new file mode 100644
index 0000000..63bd064
--- /dev/null
+++ b/examples/kinsol/parallel/kinFoodWeb_kry_p.out
@@ -0,0 +1,31 @@
+
+Predator-prey test problem -- KINSol (parallel version)
+
+Mesh dimensions = 20 X 20
+Number of species = 6
+Total system size = 2400
+
+Subgrid dimensions = 10 X 10
+Processor array is 2 X 2
+
+Flag globalstrategy = 0 (0 = None, 1 = Linesearch)
+Linear solver is SPGMR with maxl = 20, maxlrst = 2
+Preconditioning uses interaction-only block-diagonal matrix
+Tolerance parameters: fnormtol = 1e-07 scsteptol = 1e-13
+
+Initial profile of concentration
+At all mesh points: 1 1 1 30000 30000 30000
+
+
+Computed equilibrium species concentrations:
+
+At bottom left:
+ 1.165 1.165 1.165 34949 34949 34949
+
+At top right:
+ 1.25552 1.25552 1.25552 37663.2 37663.2 37663.2
+
+Final Statistics..
+nni = 19 nli = 1140
+nfe = 20 nfeSG = 1159
+nps = 1159 npe = 2 ncfl = 19
diff --git a/examples/kinsol/serial/CMakeLists.txt b/examples/kinsol/serial/CMakeLists.txt
new file mode 100644
index 0000000..f32a4dd
--- /dev/null
+++ b/examples/kinsol/serial/CMakeLists.txt
@@ -0,0 +1,125 @@
+# ---------------------------------------------------------------
+# $Revision: 1.5 $
+# $Date: 2009/02/17 02:58:47 $
+# ---------------------------------------------------------------
+# Programmer: Radu Serban @ LLNL
+# ---------------------------------------------------------------
+# Copyright (c) 2007, The Regents of the University of California.
+# Produced at the Lawrence Livermore National Laboratory.
+# All rights reserved.
+# For details, see the LICENSE file.
+# ---------------------------------------------------------------
+# CMakeLists.txt file for KINSOL serial examples
+
+
+# Add variable KINSOL_examples with the names of the serial KINSOL examples
+
+SET(KINSOL_examples
+ kinFerTron_dns
+ kinFoodWeb_kry
+ kinKrylovDemo_ls
+ kinLaplace_bnd
+ kinRoboKin_dns
+ )
+
+# Add variable KINSOL_examples_BL with the names of the serial KINSOL examples
+# that use Lapack
+
+SET(KINSOL_examples_BL
+ )
+
+# 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")
+ SET(KINSOL_LIB sundials_kinsol_shared)
+ SET(NVECS_LIB sundials_nvecserial_shared)
+ENDIF(LINK_LIBRARY_TYPE MATCHES "static")
+
+# Set-up linker flags and link libraries
+
+SET(SUNDIALS_LIBS ${KINSOL_LIB} ${NVECS_LIB} ${EXTRA_LINK_LIBS})
+IF(LAPACK_FOUND)
+ SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${LAPACK_LINKER_FLAGS}")
+ SET(SUNDIALS_LIBS "${SUNDIALS_LIBS} ${LAPACK_LIBRARIES}")
+ENDIF(LAPACK_FOUND)
+
+# Add the build and install targets for each KINSOL example
+
+FOREACH(example ${KINSOL_examples})
+ ADD_EXECUTABLE(${example} ${example}.c)
+ 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})
+
+# If Lapack support is enabled, add the build and install targets for
+# the examples using Lapack
+
+IF(LAPACK_FOUND)
+ FOREACH(example ${KINSOL_examples_BL})
+ ADD_EXECUTABLE(${example} ${example}.c)
+ 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_BL})
+ENDIF(LAPACK_FOUND)
+
+IF(EXAMPLES_INSTALL)
+
+ # Install the README file
+ INSTALL(FILES README DESTINATION ${EXAMPLES_INSTALL_PATH}/kinsol/serial)
+
+ # Prepare substitution variables for Makefile and/or CMakeLists templates
+ SET(SOLVER "KINSOL")
+ SET(SOLVER_LIB "sundials_kinsol")
+ LIST2STRING(KINSOL_examples EXAMPLES)
+ IF(LAPACK_FOUND)
+ LIST2STRING(KINSOL_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
+ # 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/kinsol/serial/CMakeLists.txt
+ @ONLY
+ )
+
+ # install CMakelists.txt
+ INSTALL(
+ FILES ${PROJECT_BINARY_DIR}/examples/kinsol/serial/CMakeLists.txt
+ DESTINATION ${EXAMPLES_INSTALL_PATH}/kinsol/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/kinsol/serial/Makefile_ex
+ @ONLY
+ )
+ # install the configured Makefile_ex as Makefile
+ INSTALL(
+ FILES ${PROJECT_BINARY_DIR}/examples/kinsol/serial/Makefile_ex
+ DESTINATION ${EXAMPLES_INSTALL_PATH}/kinsol/serial
+ RENAME Makefile
+ )
+ ENDIF(UNIX)
+
+
+ENDIF(EXAMPLES_INSTALL)
diff --git a/examples/kinsol/serial/Makefile.in b/examples/kinsol/serial/Makefile.in
new file mode 100644
index 0000000..daa6d4f
--- /dev/null
+++ b/examples/kinsol/serial/Makefile.in
@@ -0,0 +1,133 @@
+# -----------------------------------------------------------------
+# $Revision: 1.11 $
+# $Date: 2009/02/17 02:58:47 $
+# -----------------------------------------------------------------
+# Programmer(s): Radu Serban and Aaron Collier @ LLNL
+# -----------------------------------------------------------------
+# Copyright (c) 2002, The Regents of the University of California.
+# Produced at the Lawrence Livermore National Laboratory.
+# All rights reserved.
+# For details, see the LICENSE file.
+# -----------------------------------------------------------------
+# Makefile for KINSOL serial examples
+#
+# @configure_input@
+# -----------------------------------------------------------------
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_builddir = @top_builddir@
+builddir = @builddir@
+abs_builddir = @abs_builddir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+includedir = @includedir@
+libdir = @libdir@
+
+INSTALL = @INSTALL@
+INSTALL_PROG = @INSTALL_PROGRAM@
+INSTALL_FILE = @INSTALL_DATA@
+
+LIBTOOL = @LIBTOOL@
+LIBTOOL_DEPS = @LIBTOOL_DEPS@
+
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CC = @CC@
+CFLAGS = @CFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+
+LAPACK_ENABLED = @LAPACK_ENABLED@
+BLAS_LAPACK_LIBS = @BLAS_LAPACK_LIBS@
+
+OBJ_EXT = @OBJEXT@
+EXE_EXT = @EXEEXT@
+
+EXS_INSTDIR = @EXS_INSTDIR@
+
+top_srcdir = $(srcdir)/../../..
+
+SUNDIALS_INCS = -I$(top_srcdir)/include -I$(top_builddir)/include
+
+SUNDIALS_LIBS = $(top_builddir)/src/kinsol/libsundials_kinsol.la \
+ $(top_builddir)/src/nvec_ser/libsundials_nvecserial.la
+
+mkinstalldirs = $(SHELL) $(top_srcdir)/config/mkinstalldirs
+rminstalldirs = $(SHELL) $(top_srcdir)/config/rminstalldirs
+
+EXAMPLES = kinFerTron_dns \
+ kinFoodWeb_kry \
+ kinKrylovDemo_ls \
+ kinLaplace_bnd \
+ kinRoboKin_dns
+
+EXAMPLES_BL =
+
+OBJECTS = ${EXAMPLES:=${OBJ_EXT}}
+OBJECTS_BL = ${EXAMPLES_BL:=${OBJ_EXT}}
+EXECS = ${EXAMPLES:=${EXE_EXT}}
+EXECS_BL = ${EXAMPLES_BL:=${EXE_EXT}}
+
+# ----------------------------------------------------------------------------------------------------------------------
+
+all:
+ @for i in ${EXAMPLES} ; do \
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(SUNDIALS_INCS) $(CFLAGS) -c $(srcdir)/$${i}.c -o $${i}${OBJ_EXT} ; \
+ $(LIBTOOL) --mode=link $(CC) -o $(builddir)/$${i}$(EXE_EXT) $(builddir)/$${i}${OBJ_EXT} $(CFLAGS) $(LDFLAGS) $(SUNDIALS_LIBS) $(LIBS) $(BLAS_LAPACK_LIBS) ; \
+ done
+ @if test "X${LAPACK_ENABLED}" = "Xyes"; then \
+ for i in ${EXAMPLES_BL} ; do \
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(SUNDIALS_INCS) $(CFLAGS) -c $(srcdir)/$${i}.c -o $${i}${OBJ_EXT} ; \
+ $(LIBTOOL) --mode=link $(CC) -o $(builddir)/$${i}$(EXE_EXT) $(builddir)/$${i}${OBJ_EXT} $(CFLAGS) $(LDFLAGS) $(SUNDIALS_LIBS) $(LIBS) $(BLAS_LAPACK_LIBS) ; \
+ done ; \
+ fi
+
+install:
+ $(mkinstalldirs) $(EXS_INSTDIR)/kinsol/serial
+ $(INSTALL_FILE) Makefile_ex $(EXS_INSTDIR)/kinsol/serial/Makefile
+ $(INSTALL_FILE) $(top_srcdir)/examples/kinsol/serial/README $(EXS_INSTDIR)/kinsol/serial/
+ for i in ${EXAMPLES} ; do \
+ $(INSTALL_FILE) $(top_srcdir)/examples/kinsol/serial/$${i}.c $(EXS_INSTDIR)/kinsol/serial/ ; \
+ $(INSTALL_FILE) $(top_srcdir)/examples/kinsol/serial/$${i}.out $(EXS_INSTDIR)/kinsol/serial/ ; \
+ done
+ @if test "X${LAPACK_ENABLED}" = "Xyes"; then \
+ for i in ${EXAMPLES_BL} ; do \
+ $(INSTALL_FILE) $(top_srcdir)/examples/kinsol/serial/$${i}.c $(EXS_INSTDIR)/kinsol/serial/ ; \
+ $(INSTALL_FILE) $(top_srcdir)/examples/kinsol/serial/$${i}.out $(EXS_INSTDIR)/kinsol/serial/ ; \
+ done ; \
+ fi
+
+uninstall:
+ rm -f $(EXS_INSTDIR)/kinsol/serial/Makefile
+ rm -f $(EXS_INSTDIR)/kinsol/serial/README
+ for i in ${EXAMPLES} ; do \
+ rm -f $(EXS_INSTDIR)/kinsol/serial/$${i}.c ; \
+ rm -f $(EXS_INSTDIR)/kinsol/serial/$${i}.out ; \
+ done
+ @if test "X${LAPACK_ENABLED}" = "Xyes"; then \
+ for i in ${EXAMPLES_BL} ; do \
+ rm -f $(EXS_INSTDIR)/kinsol/serial/$${i}.c ; \
+ rm -f $(EXS_INSTDIR)/kinsol/serial/$${i}.out ; \
+ done ; \
+ fi
+ $(rminstalldirs) $(EXS_INSTDIR)/kinsol/serial
+ $(rminstalldirs) $(EXS_INSTDIR)/kinsol
+
+clean:
+ rm -rf .libs
+ rm -f *.lo
+ rm -f ${OBJECTS} ${OBJECTS_BL}
+ rm -f $(EXECS) $(EXECS_BL)
+
+distclean: clean
+ rm -f Makefile
+ rm -f Makefile_ex
+
+# ----------------------------------------------------------------------------------------------------------------------
+
+libtool: $(top_builddir)/$(LIBTOOL_DEPS)
+ @cd ${top_builddir} ; \
+ ${SHELL} ./config.status --recheck ; \
+ cd ${abs_builddir}
diff --git a/examples/kinsol/serial/README b/examples/kinsol/serial/README
new file mode 100644
index 0000000..a8d4959
--- /dev/null
+++ b/examples/kinsol/serial/README
@@ -0,0 +1,18 @@
+List of serial KINSOL examples
+
+ kinFerTron_dns: Ferraris-Tronconi example (DENSE)
+ 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)
+ kinRoboKin_dns: Robot kinematics problem (DENSE)
+
+Sample result:
+
+ SUNDIALS was built with the following options:
+
+ ./configure CC=gcc F77=gfortran CFLAGS="-g3 -O0" FFLAGS="-g3 -O0" --enable-examples
+
+ System Architecture: IA-32
+ Processor Type: Intel Pentium 4 Xeon DP (i686)
+ Operating System: Red Hat Enterprise Linux WS 3 (Taroon Update 7)
+ C/Fortran Compilers: gcc/gfortran v4.1.0 (GCC)
diff --git a/examples/kinsol/serial/kinFerTron_dns.c b/examples/kinsol/serial/kinFerTron_dns.c
new file mode 100644
index 0000000..3ea57bc
--- /dev/null
+++ b/examples/kinsol/serial/kinFerTron_dns.c
@@ -0,0 +1,494 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.2 $
+ * $Date: 2008/12/17 19:38:48 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Example (serial):
+ *
+ * This example solves a nonlinear system from.
+ *
+ * Source: "Handbook of Test Problems in Local and Global Optimization",
+ * 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
+ * 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.
+ * -----------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#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>
+
+/* 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 ZERO RCONST(0.0)
+#define PT25 RCONST(0.25)
+#define PT5 RCONST(0.5)
+#define ONE RCONST(1.0)
+#define ONEPT5 RCONST(1.5)
+#define TWO RCONST(2.0)
+
+#define PI RCONST(3.1415926)
+#define E RCONST(2.7182818)
+
+typedef struct {
+ realtype lb[NVAR];
+ realtype ub[NVAR];
+} *UserData;
+
+/* Accessor macro */
+#define Ith(v,i) NV_Ith_S(v,i-1)
+
+/* Functions Called by the KINSOL Solver */
+static int func(N_Vector u, N_Vector f, void *user_data);
+
+/* Private Helper Functions */
+static void SetInitialGuess1(N_Vector u, UserData data);
+static void SetInitialGuess2(N_Vector u, UserData data);
+static int SolveIt(void *kmem, N_Vector u, N_Vector s, int glstr, int mset);
+static void PrintHeader(int globalstrategy, realtype fnormtol,
+ realtype scsteptol);
+static void PrintOutput(N_Vector u);
+static void PrintFinalStats(void *kmem);
+static int check_flag(void *flagvalue, char *funcname, int opt);
+
+/*
+ *--------------------------------------------------------------------
+ * MAIN PROGRAM
+ *--------------------------------------------------------------------
+ */
+
+int main()
+{
+ UserData data;
+ realtype fnormtol, scsteptol;
+ N_Vector u1, u2, u, s, c;
+ int glstr, mset, flag;
+ void *kmem;
+
+ u1 = u2 = u = NULL;
+ s = c = NULL;
+ kmem = NULL;
+ data = NULL;
+ glstr = KIN_NONE;
+
+ /* User data */
+
+ data = (UserData)malloc(sizeof *data);
+ data->lb[0] = PT25; data->ub[0] = ONE;
+ data->lb[1] = ONEPT5; data->ub[1] = TWO*PI;
+
+ /* Create serial vectors of length NEQ */
+ u1 = N_VNew_Serial(NEQ);
+ if (check_flag((void *)u1, "N_VNew_Serial", 0)) return(1);
+
+ u2 = N_VNew_Serial(NEQ);
+ if (check_flag((void *)u2, "N_VNew_Serial", 0)) return(1);
+
+ u = N_VNew_Serial(NEQ);
+ if (check_flag((void *)u, "N_VNew_Serial", 0)) return(1);
+
+ s = N_VNew_Serial(NEQ);
+ if (check_flag((void *)s, "N_VNew_Serial", 0)) return(1);
+
+ c = N_VNew_Serial(NEQ);
+ if (check_flag((void *)c, "N_VNew_Serial", 0)) return(1);
+
+ SetInitialGuess1(u1,data);
+ SetInitialGuess2(u2,data);
+
+ N_VConst_Serial(ONE,s); /* no scaling */
+
+ Ith(c,1) = ZERO; /* no constraint on x1 */
+ Ith(c,2) = ZERO; /* no constraint on x2 */
+ Ith(c,3) = ONE; /* l1 = x1 - x1_min >= 0 */
+ Ith(c,4) = -ONE; /* L1 = x1 - x1_max <= 0 */
+ Ith(c,5) = ONE; /* l2 = x2 - x2_min >= 0 */
+ Ith(c,6) = -ONE; /* L2 = x2 - x22_min <= 0 */
+
+ fnormtol=FTOL; scsteptol=STOL;
+
+
+ kmem = KINCreate();
+ if (check_flag((void *)kmem, "KINCreate", 0)) return(1);
+
+ flag = KINSetUserData(kmem, data);
+ if (check_flag(&flag, "KINSetUserData", 1)) return(1);
+ flag = KINSetConstraints(kmem, c);
+ if (check_flag(&flag, "KINSetConstraints", 1)) return(1);
+ flag = KINSetFuncNormTol(kmem, fnormtol);
+ if (check_flag(&flag, "KINSetFuncNormTol", 1)) return(1);
+ flag = KINSetScaledStepTol(kmem, scsteptol);
+ if (check_flag(&flag, "KINSetScaledStepTol", 1)) return(1);
+
+ flag = KINInit(kmem, func, u);
+ if (check_flag(&flag, "KINInit", 1)) return(1);
+
+ /* Call KINDense to specify the linear solver */
+
+ flag = KINDense(kmem, NEQ);
+ if (check_flag(&flag, "KINDense", 1)) return(1);
+
+ /* Print out the problem size, solution parameters, initial guess. */
+ PrintHeader(glstr, fnormtol, scsteptol);
+
+ /* --------------------------- */
+
+ printf("\n------------------------------------------\n");
+ printf("\nInitial guess on lower bounds\n");
+ printf(" [x1,x2] = ");
+ PrintOutput(u1);
+
+ N_VScale_Serial(ONE,u1,u);
+ glstr = KIN_NONE;
+ mset = 1;
+ SolveIt(kmem, u, s, glstr, mset);
+
+ /* --------------------------- */
+
+ N_VScale_Serial(ONE,u1,u);
+ glstr = KIN_LINESEARCH;
+ mset = 1;
+ SolveIt(kmem, u, s, glstr, mset);
+
+ /* --------------------------- */
+
+ N_VScale_Serial(ONE,u1,u);
+ glstr = KIN_NONE;
+ mset = 0;
+ SolveIt(kmem, u, s, glstr, mset);
+
+ /* --------------------------- */
+
+ N_VScale_Serial(ONE,u1,u);
+ glstr = KIN_LINESEARCH;
+ mset = 0;
+ SolveIt(kmem, u, s, glstr, mset);
+
+
+
+ /* --------------------------- */
+
+ printf("\n------------------------------------------\n");
+ printf("\nInitial guess in middle of feasible region\n");
+ printf(" [x1,x2] = ");
+ PrintOutput(u2);
+
+ N_VScale_Serial(ONE,u2,u);
+ glstr = KIN_NONE;
+ mset = 1;
+ SolveIt(kmem, u, s, glstr, mset);
+
+ /* --------------------------- */
+
+ N_VScale_Serial(ONE,u2,u);
+ glstr = KIN_LINESEARCH;
+ mset = 1;
+ SolveIt(kmem, u, s, glstr, mset);
+
+ /* --------------------------- */
+
+ N_VScale_Serial(ONE,u2,u);
+ glstr = KIN_NONE;
+ mset = 0;
+ SolveIt(kmem, u, s, glstr, mset);
+
+ /* --------------------------- */
+
+ N_VScale_Serial(ONE,u2,u);
+ glstr = KIN_LINESEARCH;
+ mset = 0;
+ SolveIt(kmem, u, s, glstr, mset);
+
+
+
+
+ /* Free memory */
+
+ N_VDestroy_Serial(u);
+ N_VDestroy_Serial(s);
+ N_VDestroy_Serial(c);
+ KINFree(&kmem);
+ free(data);
+
+ return(0);
+}
+
+
+static int SolveIt(void *kmem, N_Vector u, N_Vector s, int glstr, int mset)
+{
+ int flag;
+
+ printf("\n");
+
+ if (mset==1)
+ printf("Exact Newton");
+ else
+ printf("Modified Newton");
+
+ if (glstr == KIN_NONE)
+ printf("\n");
+ else
+ printf(" with line search\n");
+
+ flag = KINSetMaxSetupCalls(kmem, mset);
+ if (check_flag(&flag, "KINSetMaxSetupCalls", 1)) return(1);
+
+ flag = KINSol(kmem, u, glstr, s, s);
+ if (check_flag(&flag, "KINSol", 1)) return(1);
+
+ printf("Solution:\n [x1,x2] = ");
+ PrintOutput(u);
+
+ PrintFinalStats(kmem);
+
+ return(0);
+
+}
+
+
+/*
+ *--------------------------------------------------------------------
+ * FUNCTIONS CALLED BY KINSOL
+ *--------------------------------------------------------------------
+ */
+
+/*
+ * System function for predator-prey system
+ */
+
+static int func(N_Vector u, N_Vector f, void *user_data)
+{
+ realtype *udata, *fdata;
+ realtype x1, l1, L1, x2, l2, L2;
+ realtype *lb, *ub;
+ UserData data;
+
+ data = (UserData)user_data;
+ lb = data->lb;
+ ub = data->ub;
+
+ udata = NV_DATA_S(u);
+ fdata = NV_DATA_S(f);
+
+ x1 = udata[0];
+ x2 = udata[1];
+ l1 = udata[2];
+ L1 = udata[3];
+ l2 = udata[4];
+ L2 = udata[5];
+
+ fdata[0] = PT5 * sin(x1*x2) - PT25 * x2 / PI - PT5 * x1;
+ fdata[1] = (ONE - PT25/PI)*(EXP(TWO*x1)-E) + E*x2/PI - TWO*E*x1;
+ fdata[2] = l1 - x1 + lb[0];
+ fdata[3] = L1 - x1 + ub[0];
+ fdata[4] = l2 - x2 + lb[1];
+ fdata[5] = L2 - x2 + ub[1];
+
+ return(0);
+}
+
+/*
+ *--------------------------------------------------------------------
+ * PRIVATE FUNCTIONS
+ *--------------------------------------------------------------------
+ */
+
+/*
+ * Initial guesses
+ */
+
+static void SetInitialGuess1(N_Vector u, UserData data)
+{
+ realtype x1, x2;
+ realtype *udata;
+ realtype *lb, *ub;
+
+ udata = NV_DATA_S(u);
+
+ lb = data->lb;
+ ub = data->ub;
+
+ /* There are two known solutions for this problem */
+
+ /* this init. guess should take us to (0.29945; 2.83693) */
+ x1 = lb[0];
+ x2 = lb[1];
+
+ udata[0] = x1;
+ udata[1] = x2;
+ udata[2] = x1 - lb[0];
+ udata[3] = x1 - ub[0];
+ udata[4] = x2 - lb[1];
+ udata[5] = x2 - ub[1];
+}
+
+static void SetInitialGuess2(N_Vector u, UserData data)
+{
+ realtype x1, x2;
+ realtype *udata;
+ realtype *lb, *ub;
+
+ udata = NV_DATA_S(u);
+
+ lb = data->lb;
+ ub = data->ub;
+
+ /* There are two known solutions for this problem */
+
+ /* this init. guess should take us to (0.5; 3.1415926) */
+ x1 = PT5 * (lb[0] + ub[0]);
+ x2 = PT5 * (lb[1] + ub[1]);
+
+ udata[0] = x1;
+ udata[1] = x2;
+ udata[2] = x1 - lb[0];
+ udata[3] = x1 - ub[0];
+ udata[4] = x2 - lb[1];
+ udata[5] = x2 - ub[1];
+}
+
+/*
+ * Print first lines of output (problem description)
+ */
+
+static void PrintHeader(int globalstrategy, realtype fnormtol,
+ realtype scsteptol)
+{
+ printf("\nFerraris and Tronconi test problem\n");
+ printf("Tolerance parameters:\n");
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf(" fnormtol = %10.6Lg\n scsteptol = %10.6Lg\n",
+ fnormtol, scsteptol);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf(" fnormtol = %10.6lg\n scsteptol = %10.6lg\n",
+ fnormtol, scsteptol);
+#else
+ printf(" fnormtol = %10.6g\n scsteptol = %10.6g\n",
+ fnormtol, scsteptol);
+#endif
+}
+
+/*
+ * Print solution
+ */
+
+static void PrintOutput(N_Vector u)
+{
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf(" %8.6Lg %8.6Lg\n", Ith(u,1), Ith(u,2));
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf(" %8.6lg %8.6lg\n", Ith(u,1), Ith(u,2));
+#else
+ printf(" %8.6g %8.6g\n", Ith(u,1), Ith(u,2));
+#endif
+}
+
+/*
+ * Print final statistics contained in iopt
+ */
+
+static void PrintFinalStats(void *kmem)
+{
+ long int nni, nfe, nje, nfeD;
+ 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 = KINDlsGetNumFuncEvals(kmem, &nfeD);
+ check_flag(&flag, "KINDlsGetNumFuncEvals", 1);
+
+ printf("Final Statistics:\n");
+ printf(" nni = %5ld nfe = %5ld \n", nni, nfe);
+ printf(" nje = %5ld nfeD = %5ld \n", nje, nfeD);
+}
+
+/*
+ * 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, 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/kinsol/serial/kinFerTron_dns.out b/examples/kinsol/serial/kinFerTron_dns.out
new file mode 100644
index 0000000..e659a0a
--- /dev/null
+++ b/examples/kinsol/serial/kinFerTron_dns.out
@@ -0,0 +1,71 @@
+
+Ferraris and Tronconi test problem
+Tolerance parameters:
+ fnormtol = 1e-05
+ scsteptol = 1e-05
+
+------------------------------------------
+
+Initial guess on lower bounds
+ [x1,x2] = 0.25 1.5
+
+Exact Newton
+Solution:
+ [x1,x2] = 0.299449 2.83693
+Final Statistics:
+ nni = 3 nfe = 4
+ nje = 3 nfeD = 18
+
+Exact Newton with line search
+Solution:
+ [x1,x2] = 0.299449 2.83693
+Final Statistics:
+ nni = 3 nfe = 4
+ nje = 3 nfeD = 18
+
+Modified Newton
+Solution:
+ [x1,x2] = 0.299449 2.83693
+Final Statistics:
+ nni = 11 nfe = 12
+ nje = 2 nfeD = 12
+
+Modified Newton with line search
+Solution:
+ [x1,x2] = 0.299449 2.83693
+Final Statistics:
+ nni = 11 nfe = 12
+ nje = 2 nfeD = 12
+
+------------------------------------------
+
+Initial guess in middle of feasible region
+ [x1,x2] = 0.625 3.89159
+
+Exact Newton
+Solution:
+ [x1,x2] = 0.5 3.14159
+Final Statistics:
+ nni = 5 nfe = 6
+ nje = 5 nfeD = 30
+
+Exact Newton with line search
+Solution:
+ [x1,x2] = 0.5 3.14159
+Final Statistics:
+ nni = 5 nfe = 6
+ nje = 5 nfeD = 30
+
+Modified Newton
+Solution:
+ [x1,x2] = 0.500003 3.1416
+Final Statistics:
+ nni = 12 nfe = 13
+ nje = 2 nfeD = 12
+
+Modified Newton with line search
+Solution:
+ [x1,x2] = 0.500003 3.1416
+Final Statistics:
+ nni = 12 nfe = 13
+ nje = 2 nfeD = 12
diff --git a/examples/kinsol/serial/kinFoodWeb_kry.c b/examples/kinsol/serial/kinFoodWeb_kry.c
new file mode 100644
index 0000000..c64018a
--- /dev/null
+++ b/examples/kinsol/serial/kinFoodWeb_kry.c
@@ -0,0 +1,789 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.3 $
+ * $Date: 2010/12/01 23:08:49 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Allan Taylor, Alan Hindmarsh and
+ * Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Example (serial):
+ *
+ * This example solves a nonlinear system that arises from a system
+ * of partial differential equations. The PDE system is a food web
+ * 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
+ * 0 = d(i)*(c + c ) + f (x,y,c) (i=1,...,ns)
+ * xx yy i
+ *
+ * where
+ *
+ * i ns j
+ * f (x,y,c) = c * (b(i) + sum a(i,j)*c )
+ * i j=1
+ *
+ * The number of species is ns = 2 * np, with the first np being
+ * prey and the last np being predators. The number np is both the
+ * number of prey and predator species. The coefficients a(i,j),
+ * b(i), d(i) are:
+ *
+ * a(i,i) = -AA (all i)
+ * a(i,j) = -GG (i <= np , j > np)
+ * a(i,j) = EE (i > np, j <= np)
+ * b(i) = BB * (1 + alpha * x * y) (i <= np)
+ * b(i) =-BB * (1 + alpha * x * y) (i > np)
+ * d(i) = DPREY (i <= np)
+ * d(i) = DPRED ( i > np)
+ *
+ * The various scalar parameters are set using define's or in
+ * routine InitUserData.
+ *
+ * The boundary conditions are: normal derivative = 0, and the
+ * initial guess is constant in x and y, but the final solution
+ * is not.
+ *
+ * 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.
+ *
+ * The preconditioner matrix is a block-diagonal matrix based on
+ * the partial derivatives of the interaction terms f only.
+ *
+ * Constraints are imposed to make all components of the solution
+ * positive.
+ * -----------------------------------------------------------------
+ * References:
+ *
+ * 1. Peter N. Brown and Youcef Saad,
+ * Hybrid Krylov Methods for Nonlinear Systems of Equations
+ * LLNL report UCRL-97645, November 1987.
+ *
+ * 2. Peter N. Brown and Alan C. Hindmarsh,
+ * Reduced Storage Matrix Methods in Stiff ODE systems,
+ * 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.)
+ * -----------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#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>
+
+/* Problem Constants */
+
+#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 MX 8 /* MX = number of x mesh points */
+#define MY 8 /* MY = number of y mesh points */
+#define NSMX (NUM_SPECIES * MX)
+#define NEQ (NSMX * 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 */
+#define BB RCONST(1.0) /* value of coefficient BB in above eqns */
+#define DPREY RCONST(1.0) /* value of coefficient dprey above */
+#define DPRED RCONST(0.5) /* value of coefficient dpred above */
+#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 THOUSAND RCONST(1000.0) /* one thousand */
+#define ZERO RCONST(0.) /* 0. */
+#define ONE RCONST(1.0) /* 1. */
+#define TWO RCONST(2.0) /* 2. */
+#define PREYIN RCONST(1.0) /* initial guess for prey concentrations. */
+#define PREDIN RCONST(30000.0)/* initial guess for predator concs. */
+
+/* User-defined vector access macro: IJ_Vptr */
+
+/* IJ_Vptr is defined in order to translate from the underlying 3D structure
+ of the dependent variable vector to the 1D storage scheme for an N-vector.
+ IJ_Vptr(vv,i,j) returns a pointer to the location in vv corresponding to
+ indices is = 0, jx = i, jy = j. */
+
+#define IJ_Vptr(vv,i,j) (&NV_Ith_S(vv, i*NUM_SPECIES + j*NSMX))
+
+/* Type : UserData
+ contains preconditioner blocks, pivot arrays, and problem constants */
+
+typedef struct {
+ realtype **P[MX][MY];
+ long int *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;
+} *UserData;
+
+/* Functions Called by the KINSOL Solver */
+
+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);
+
+static int PrecSolveBD(N_Vector cc, N_Vector cscale,
+ N_Vector fval, N_Vector fscale,
+ N_Vector vv, void *user_data,
+ N_Vector ftem);
+
+/* Private Helper Functions */
+
+static UserData AllocUserData(void);
+static void InitUserData(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,
+ realtype fnormtol, realtype scsteptol);
+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);
+
+/*
+ *--------------------------------------------------------------------
+ * MAIN PROGRAM
+ *--------------------------------------------------------------------
+ */
+
+int main(void)
+{
+ int globalstrategy;
+ realtype fnormtol, scsteptol;
+ N_Vector cc, sc, constraints;
+ UserData data;
+ int flag, maxl, maxlrst;
+ void *kmem;
+
+ cc = sc = constraints = NULL;
+ kmem = NULL;
+ data = NULL;
+
+ /* Allocate memory, and set problem data, initial values, tolerances */
+ globalstrategy = KIN_NONE;
+
+ data = AllocUserData();
+ if (check_flag((void *)data, "AllocUserData", 2)) return(1);
+ InitUserData(data);
+
+ /* Create serial vectors of length NEQ */
+ cc = N_VNew_Serial(NEQ);
+ if (check_flag((void *)cc, "N_VNew_Serial", 0)) return(1);
+ sc = N_VNew_Serial(NEQ);
+ if (check_flag((void *)sc, "N_VNew_Serial", 0)) return(1);
+ data->rates = N_VNew_Serial(NEQ);
+ if (check_flag((void *)data->rates, "N_VNew_Serial", 0)) return(1);
+
+ constraints = N_VNew_Serial(NEQ);
+ if (check_flag((void *)constraints, "N_VNew_Serial", 0)) return(1);
+ N_VConst(TWO, constraints);
+
+ SetInitialProfiles(cc, sc);
+
+ fnormtol=FTOL; scsteptol=STOL;
+
+ /* Call KINCreate/KINInit to initialize KINSOL.
+ A pointer to KINSOL problem memory is returned and stored in kmem. */
+ kmem = KINCreate();
+ if (check_flag((void *)kmem, "KINCreate", 0)) return(1);
+
+ /* Vector cc passed as template vector. */
+ flag = KINInit(kmem, func, cc);
+ if (check_flag(&flag, "KINInit", 1)) return(1);
+
+ flag = KINSetUserData(kmem, data);
+ if (check_flag(&flag, "KINSetUserData", 1)) return(1);
+ flag = KINSetConstraints(kmem, constraints);
+ if (check_flag(&flag, "KINSetConstraints", 1)) return(1);
+ flag = KINSetFuncNormTol(kmem, fnormtol);
+ if (check_flag(&flag, "KINSetFuncNormTol", 1)) return(1);
+ flag = KINSetScaledStepTol(kmem, scsteptol);
+ if (check_flag(&flag, "KINSetScaledStepTol", 1)) return(1);
+
+ /* We no longer need the constraints vector since KINSetConstraints
+ 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. */
+ maxl = 15;
+ maxlrst = 2;
+ flag = KINSpgmr(kmem, maxl);
+ if (check_flag(&flag, "KINSpgmr", 1)) return(1);
+
+ flag = KINSpilsSetMaxRestarts(kmem, maxlrst);
+ if (check_flag(&flag, "KINSpilsSetMaxRestarts", 1)) return(1);
+ flag = KINSpilsSetPreconditioner(kmem,
+ PrecSetupBD,
+ PrecSolveBD);
+ if (check_flag(&flag, "KINSpilsSetPreconditioner", 1)) return(1);
+
+ /* Print out the problem size, solution parameters, initial guess. */
+ 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 */
+ sc, /* scaling vector, for the variable cc */
+ sc); /* scaling vector for function values fval */
+ if (check_flag(&flag, "KINSol", 1)) return(1);
+
+ printf("\n\nComputed equilibrium species concentrations:\n");
+ PrintOutput(cc);
+
+ /* Print final statistics and free memory */
+ PrintFinalStats(kmem);
+
+ N_VDestroy_Serial(cc);
+ N_VDestroy_Serial(sc);
+ KINFree(&kmem);
+ FreeUserData(data);
+
+ return(0);
+}
+
+/* Readability definitions used in other routines below */
+
+#define acoef (data->acoef)
+#define bcoef (data->bcoef)
+#define cox (data->cox)
+#define coy (data->coy)
+
+/*
+ *--------------------------------------------------------------------
+ * FUNCTIONS CALLED BY KINSOL
+ *--------------------------------------------------------------------
+ */
+
+/*
+ * System function for predator-prey system
+ */
+
+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;
+ UserData data;
+
+ data = (UserData)user_data;
+ delx = data->dx;
+ dely = data->dy;
+
+ /* Loop over all mesh points, evaluating rate array at each point*/
+ for (jy = 0; jy < MY; jy++) {
+
+ yy = dely*jy;
+
+ /* Set lower/upper index shifts, special at boundaries. */
+ idyl = (jy != 0 ) ? NSMX : -NSMX;
+ idyu = (jy != MY-1) ? NSMX : -NSMX;
+
+ for (jx = 0; jx < MX; jx++) {
+
+ xx = delx*jx;
+
+ /* Set left/right index shifts, special at boundaries. */
+ idxl = (jx != 0 ) ? NUM_SPECIES : -NUM_SPECIES;
+ idxr = (jx != MX-1) ? NUM_SPECIES : -NUM_SPECIES;
+
+ cxy = IJ_Vptr(cc,jx,jy);
+ rxy = IJ_Vptr(data->rates,jx,jy);
+ fxy = IJ_Vptr(fval,jx,jy);
+
+ /* Get species interaction rate array at (xx,yy) */
+ WebRate(xx, yy, cxy, rxy, user_data);
+
+ for(is = 0; is < NUM_SPECIES; is++) {
+
+ /* Differencing in x direction */
+ dcyli = *(cxy+is) - *(cxy - idyl + is) ;
+ dcyui = *(cxy + idyu + is) - *(cxy+is);
+
+ /* Differencing in y direction */
+ dcxli = *(cxy+is) - *(cxy - idxl + is);
+ dcxri = *(cxy + idxr +is) - *(cxy+is);
+
+ /* Compute the total rate value at (xx,yy) */
+ fxy[is] = (coy)[is] * (dcyui - dcyli) +
+ (cox)[is] * (dcxri - dcxli) + rxy[is];
+
+ } /* end of is loop */
+
+ } /* end of jx loop */
+
+ } /* end of jy loop */
+
+ return(0);
+}
+
+/*
+ * Preconditioner setup routine. Generate and preprocess P.
+ */
+
+static int PrecSetupBD(N_Vector cc, N_Vector cscale,
+ N_Vector fval, N_Vector fscale,
+ void *user_data,
+ N_Vector vtemp1, N_Vector vtemp2)
+{
+ 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;
+ UserData data;
+
+ data = (UserData) user_data;
+ delx = data->dx;
+ dely = data->dy;
+
+ uround = data->uround;
+ sqruround = data->sqruround;
+ fac = N_VWL2Norm(fval, fscale);
+ r0 = THOUSAND * uround * fac * NEQ;
+ if(r0 == ZERO) r0 = ONE;
+
+ /* Loop over spatial points; get size NUM_SPECIES Jacobian block at each */
+ for (jy = 0; jy < MY; jy++) {
+ yy = jy*dely;
+
+ for (jx = 0; jx < MX; jx++) {
+ xx = jx*delx;
+ Pxy = (data->P)[jx][jy];
+ 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++) {
+
+ csave = cxy[j]; /* Save the j,jx,jy element of cc */
+ r = MAX(sqruround*ABS(csave), r0/scxy[j]);
+ cxy[j] += r; /* Perturb the j,jx,jy element of cc */
+ fac = ONE/r;
+
+ WebRate(xx, yy, cxy, perturb_rates, data);
+
+ /* Restore j,jx,jy element of cc */
+ cxy[j] = csave;
+
+ /* Load the j-th column of difference quotients */
+ Pxycol = Pxy[j];
+ 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 */
+ ret = denseGETRF(Pxy, NUM_SPECIES, NUM_SPECIES, (data->pivot)[jx][jy]);
+ if (ret != 0) return(1);
+
+ } /* end of jx loop */
+
+ } /* end of jy loop */
+
+ return(0);
+}
+
+/*
+ * Preconditioner solve routine
+ */
+
+static int PrecSolveBD(N_Vector cc, N_Vector cscale,
+ N_Vector fval, N_Vector fscale,
+ N_Vector vv, void *user_data,
+ N_Vector ftem)
+{
+ realtype **Pxy, *vxy;
+ long int *piv, jx, jy;
+ UserData data;
+
+ data = (UserData)user_data;
+
+ for (jx=0; jx<MX; jx++) {
+
+ for (jy=0; jy<MY; jy++) {
+
+ /* For each (jx,jy), solve a linear system of size NUM_SPECIES.
+ vxy is the address of the corresponding portion of the vector vv;
+ Pxy is the address of the corresponding block of the matrix P;
+ piv is the address of the corresponding block of the array pivot. */
+ vxy = IJ_Vptr(vv,jx,jy);
+ Pxy = (data->P)[jx][jy];
+ piv = (data->pivot)[jx][jy];
+ denseGETRS(Pxy, NUM_SPECIES, piv, vxy);
+
+ } /* end of jy loop */
+
+ } /* end of jx loop */
+
+ return(0);
+}
+
+/*
+ * Interaction rate function routine
+ */
+
+static void WebRate(realtype xx, realtype yy, realtype *cxy, realtype *ratesxy,
+ void *user_data)
+{
+ long int i;
+ realtype fac;
+ UserData data;
+
+ data = (UserData)user_data;
+
+ for (i = 0; i<NUM_SPECIES; i++)
+ ratesxy[i] = DotProd(NUM_SPECIES, cxy, acoef[i]);
+
+ fac = ONE + ALPHA * xx * yy;
+
+ for (i = 0; i < NUM_SPECIES; 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)
+{
+ long int i;
+ realtype *xx1, *xx2, temp = ZERO;
+
+ xx1 = x1; xx2 = x2;
+ for (i = 0; i < size; i++) temp += (*xx1++) * (*xx2++);
+
+ return(temp);
+}
+
+/*
+ *--------------------------------------------------------------------
+ * PRIVATE FUNCTIONS
+ *--------------------------------------------------------------------
+ */
+
+/*
+ * Allocate memory for data structure of type UserData
+ */
+
+static UserData AllocUserData(void)
+{
+ int jx, jy;
+ UserData data;
+
+ data = (UserData) malloc(sizeof *data);
+
+ 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);
+ }
+ }
+ acoef = newDenseMat(NUM_SPECIES, NUM_SPECIES);
+ bcoef = (realtype *)malloc(NUM_SPECIES * sizeof(realtype));
+ cox = (realtype *)malloc(NUM_SPECIES * sizeof(realtype));
+ coy = (realtype *)malloc(NUM_SPECIES * sizeof(realtype));
+
+ return(data);
+}
+
+/*
+ * Load problem constants in data
+ */
+
+static void InitUserData(UserData data)
+{
+ long int i, j, np;
+ realtype *a1,*a2, *a3, *a4, dx2, dy2;
+
+ data->mx = MX;
+ data->my = MY;
+ data->ns = NUM_SPECIES;
+ data->np = NUM_SPECIES/2;
+ data->ax = AX;
+ data->ay = AY;
+ data->dx = (data->ax)/(MX-1);
+ data->dy = (data->ay)/(MY-1);
+ data->uround = UNIT_ROUNDOFF;
+ data->sqruround = SQRT(data->uround);
+
+ /* Set up the coefficients a and b plus others found in the equations */
+ np = data->np;
+
+ dx2=(data->dx)*(data->dx); dy2=(data->dy)*(data->dy);
+
+ for (i = 0; i < np; i++) {
+ a1= &(acoef[i][np]);
+ a2= &(acoef[i+np][0]);
+ a3= &(acoef[i][0]);
+ a4= &(acoef[i+np][np]);
+
+ /* Fill in the portion of acoef in the four quadrants, row by row */
+ for (j = 0; j < np; j++) {
+ *a1++ = -GG;
+ *a2++ = EE;
+ *a3++ = ZERO;
+ *a4++ = ZERO;
+ }
+
+ /* and then change the diagonal elements of acoef to -AA */
+ acoef[i][i]=-AA;
+ acoef[i+np][i+np] = -AA;
+
+ bcoef[i] = BB;
+ bcoef[i+np] = -BB;
+
+ cox[i]=DPREY/dx2;
+ cox[i+np]=DPRED/dx2;
+
+ 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);
+ free(coy);
+ N_VDestroy_Serial(data->rates);
+ free(data);
+}
+
+/*
+ * Set initial conditions in cc
+ */
+
+static void SetInitialProfiles(N_Vector cc, N_Vector sc)
+{
+ int i, jx, jy;
+ realtype *cloc, *sloc;
+ realtype ctemp[NUM_SPECIES], stemp[NUM_SPECIES];
+
+ /* Initialize arrays ctemp and stemp used in the loading process */
+ for (i = 0; i < NUM_SPECIES/2; i++) {
+ ctemp[i] = PREYIN;
+ stemp[i] = ONE;
+ }
+ for (i = NUM_SPECIES/2; i < NUM_SPECIES; i++) {
+ ctemp[i] = PREDIN;
+ stemp[i] = RCONST(0.00001);
+ }
+
+ /* Load initial profiles into cc and sc vector from ctemp and stemp. */
+ for (jy = 0; jy < MY; jy++) {
+ for (jx = 0; jx < MX; jx++) {
+ cloc = IJ_Vptr(cc,jx,jy);
+ sloc = IJ_Vptr(sc,jx,jy);
+ for (i = 0; i < NUM_SPECIES; i++) {
+ cloc[i] = ctemp[i];
+ sloc[i] = stemp[i];
+ }
+ }
+ }
+}
+
+/*
+ * Print first lines of output (problem description)
+ */
+
+static void PrintHeader(int globalstrategy, int maxl, int maxlrst,
+ realtype fnormtol, realtype scsteptol)
+{
+ printf("\nPredator-prey test problem -- KINSol (serial 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("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("Positivity constraints imposed on all components \n");
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("Tolerance parameters: fnormtol = %Lg scsteptol = %Lg\n",
+ fnormtol, scsteptol);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("Tolerance parameters: fnormtol = %lg scsteptol = %lg\n",
+ fnormtol, scsteptol);
+#else
+ printf("Tolerance parameters: fnormtol = %g scsteptol = %g\n",
+ fnormtol, scsteptol);
+#endif
+
+ 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);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("At all mesh points: %lg %lg %lg %lg %lg %lg\n",
+ 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);
+#endif
+}
+
+/*
+ * Print sampled values of current cc
+ */
+
+static void PrintOutput(N_Vector cc)
+{
+ int is, jx, jy;
+ realtype *ct;
+
+ jy = 0; jx = 0;
+ ct = IJ_Vptr(cc,jx,jy);
+ printf("\nAt bottom left:");
+
+ /* Print out lines with up to 6 values per line */
+ for (is = 0; is < NUM_SPECIES; is++){
+ if ((is%6)*6 == is) printf("\n");
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf(" %Lg",ct[is]);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf(" %lg",ct[is]);
+#else
+ printf(" %g",ct[is]);
+#endif
+ }
+
+ jy = MY-1; jx = MX-1;
+ ct = IJ_Vptr(cc,jx,jy);
+ printf("\n\nAt top right:");
+
+ /* Print out lines with up to 6 values per line */
+ for (is = 0; is < NUM_SPECIES; is++) {
+ if ((is%6)*6 == is) printf("\n");
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf(" %Lg",ct[is]);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf(" %lg",ct[is]);
+#else
+ printf(" %g",ct[is]);
+#endif
+ }
+ printf("\n\n");
+}
+
+/*
+ * Print final statistics contained in iopt
+ */
+
+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);
+ check_flag(&flag, "KINGetNumFuncEvals", 1);
+ flag = KINSpilsGetNumLinIters(kmem, &nli);
+ check_flag(&flag, "KINSpilsGetNumLinIters", 1);
+ flag = KINSpilsGetNumPrecEvals(kmem, &npe);
+ check_flag(&flag, "KINSpilsGetNumPrecEvals", 1);
+ flag = KINSpilsGetNumPrecSolves(kmem, &nps);
+ check_flag(&flag, "KINSpilsGetNumPrecSolves", 1);
+ flag = KINSpilsGetNumConvFails(kmem, &ncfl);
+ check_flag(&flag, "KINSpilsGetNumConvFails", 1);
+ flag = KINSpilsGetNumFuncEvals(kmem, &nfeSG);
+ check_flag(&flag, "KINSpilsGetNumFuncEvals", 1);
+
+ printf("Final Statistics.. \n");
+ 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);
+
+}
+
+/*
+ * 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, 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/kinsol/serial/kinFoodWeb_kry.out b/examples/kinsol/serial/kinFoodWeb_kry.out
new file mode 100644
index 0000000..61a7dc0
--- /dev/null
+++ b/examples/kinsol/serial/kinFoodWeb_kry.out
@@ -0,0 +1,29 @@
+
+Predator-prey test problem -- KINSol (serial version)
+
+Mesh dimensions = 8 X 8
+Number of species = 6
+Total system size = 384
+
+Flag globalstrategy = 0 (0 = None, 1 = Linesearch)
+Linear solver is SPGMR with maxl = 15, maxlrst = 2
+Preconditioning uses interaction-only block-diagonal matrix
+Positivity constraints imposed on all components
+Tolerance parameters: fnormtol = 1e-07 scsteptol = 1e-13
+
+Initial profile of concentration
+At all mesh points: 1 1 1 30000 30000 30000
+
+
+Computed equilibrium species concentrations:
+
+At bottom left:
+ 1.16428 1.16428 1.16428 34927.5 34927.5 34927.5
+
+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
diff --git a/examples/kinsol/serial/kinKrylovDemo_ls.c b/examples/kinsol/serial/kinKrylovDemo_ls.c
new file mode 100644
index 0000000..6d465f0
--- /dev/null
+++ b/examples/kinsol/serial/kinKrylovDemo_ls.c
@@ -0,0 +1,879 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.2 $
+ * $Date: 2010/12/01 23:08:49 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Allan Taylor, Alan Hindmarsh and
+ * Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ *
+ * This example loops through the available iterative linear solvers:
+ * SPGMR, SPBCG and SPTFQMR.
+ *
+ * Example (serial):
+ *
+ * This example solves a nonlinear system that arises from a system
+ * of partial differential equations. The PDE system is a food web
+ * 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
+ * 0 = d(i)*(c + c ) + f (x,y,c) (i=1,...,ns)
+ * xx yy i
+ *
+ * where
+ *
+ * i ns j
+ * f (x,y,c) = c * (b(i) + sum a(i,j)*c )
+ * i j=1
+ *
+ * The number of species is ns = 2 * np, with the first np being
+ * prey and the last np being predators. The number np is both the
+ * number of prey and predator species. The coefficients a(i,j),
+ * b(i), d(i) are:
+ *
+ * a(i,i) = -AA (all i)
+ * a(i,j) = -GG (i <= np , j > np)
+ * a(i,j) = EE (i > np, j <= np)
+ * b(i) = BB * (1 + alpha * x * y) (i <= np)
+ * b(i) =-BB * (1 + alpha * x * y) (i > np)
+ * d(i) = DPREY (i <= np)
+ * d(i) = DPRED ( i > np)
+ *
+ * The various scalar parameters are set using define's or in
+ * routine InitUserData.
+ *
+ * The boundary conditions are: normal derivative = 0, and the
+ * initial guess is constant in x and y, but the final solution
+ * is not.
+ *
+ * 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.
+ *
+ * The preconditioner matrix is a block-diagonal matrix based on
+ * the partial derivatives of the interaction terms f only.
+ *
+ * Constraints are imposed to make all components of the solution
+ * positive.
+ * -----------------------------------------------------------------
+ * References:
+ *
+ * 1. Peter N. Brown and Youcef Saad,
+ * Hybrid Krylov Methods for Nonlinear Systems of Equations
+ * LLNL report UCRL-97645, November 1987.
+ *
+ * 2. Peter N. Brown and Alan C. Hindmarsh,
+ * Reduced Storage Matrix Methods in Stiff ODE systems,
+ * 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.)
+ * -----------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#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 <nvector/nvector_serial.h>
+#include <sundials/sundials_dense.h>
+#include <sundials/sundials_types.h>
+#include <sundials/sundials_math.h>
+
+/* Problem Constants */
+
+#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 MX 5 /* MX = number of x mesh points */
+#define MY 5 /* MY = number of y mesh points */
+#define NSMX (NUM_SPECIES * MX)
+#define NEQ (NSMX * 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 */
+#define BB RCONST(1.0) /* value of coefficient BB in above eqns */
+#define DPREY RCONST(1.0) /* value of coefficient dprey above */
+#define DPRED RCONST(0.5) /* value of coefficient dpred above */
+#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 THOUSAND RCONST(1000.0) /* one thousand */
+#define ZERO RCONST(0.) /* 0. */
+#define ONE RCONST(1.0) /* 1. */
+#define TWO RCONST(2.0) /* 2. */
+#define PREYIN RCONST(1.0) /* initial guess for prey concentrations. */
+#define PREDIN RCONST(30000.0)/* initial guess for predator concs. */
+
+/* Linear Solver Loop Constants */
+
+#define USE_SPGMR 0
+#define USE_SPBCG 1
+#define USE_SPTFQMR 2
+
+/* User-defined vector access macro: IJ_Vptr */
+
+/* IJ_Vptr is defined in order to translate from the underlying 3D structure
+ of the dependent variable vector to the 1D storage scheme for an N-vector.
+ IJ_Vptr(vv,i,j) returns a pointer to the location in vv corresponding to
+ indices is = 0, jx = i, jy = j. */
+
+#define IJ_Vptr(vv,i,j) (&NV_Ith_S(vv, i*NUM_SPECIES + j*NSMX))
+
+/* Type : UserData
+ contains preconditioner blocks, pivot arrays, and problem constants */
+
+typedef struct {
+ realtype **P[MX][MY];
+ long int *pivot[MX][MY];
+ realtype **acoef, *bcoef;
+ N_Vector rates;
+ realtype *cox, *coy;
+ realtype ax, ay, dx, dy;
+ realtype uround, sqruround;
+ int mx, my, ns, np;
+} *UserData;
+
+/* Functions Called by the KINSOL Solver */
+
+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);
+
+static int PrecSolveBD(N_Vector cc, N_Vector cscale,
+ N_Vector fval, N_Vector fscale,
+ N_Vector vv, void *user_data,
+ N_Vector ftem);
+
+/* Private Helper Functions */
+
+static UserData AllocUserData(void);
+static void InitUserData(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,
+ realtype fnormtol, realtype scsteptol,
+ int linsolver);
+static void PrintOutput(N_Vector cc);
+static void PrintFinalStats(void *kmem, int linsolver);
+static void WebRate(realtype xx, realtype yy, realtype *cxy, realtype *ratesxy,
+ void *user_data);
+static realtype DotProd(int size, realtype *x1, realtype *x2);
+static int check_flag(void *flagvalue, char *funcname, int opt);
+
+/*
+ *--------------------------------------------------------------------
+ * MAIN PROGRAM
+ *--------------------------------------------------------------------
+ */
+
+int main(void)
+{
+ int globalstrategy, linsolver;
+ realtype fnormtol, scsteptol;
+ N_Vector cc, sc, constraints;
+ UserData data;
+ int flag, maxl, maxlrst;
+ void *kmem;
+
+ cc = sc = constraints = NULL;
+ kmem = NULL;
+ data = NULL;
+
+ /* Allocate memory, and set problem data, initial values, tolerances */
+ globalstrategy = KIN_NONE;
+
+ data = AllocUserData();
+ if (check_flag((void *)data, "AllocUserData", 2)) return(1);
+ InitUserData(data);
+
+ /* Create serial vectors of length NEQ */
+ cc = N_VNew_Serial(NEQ);
+ if (check_flag((void *)cc, "N_VNew_Serial", 0)) return(1);
+ sc = N_VNew_Serial(NEQ);
+ if (check_flag((void *)sc, "N_VNew_Serial", 0)) return(1);
+ data->rates = N_VNew_Serial(NEQ);
+ if (check_flag((void *)data->rates, "N_VNew_Serial", 0)) return(1);
+
+ constraints = N_VNew_Serial(NEQ);
+ if (check_flag((void *)constraints, "N_VNew_Serial", 0)) return(1);
+ N_VConst(TWO, constraints);
+
+ SetInitialProfiles(cc, sc);
+
+ fnormtol=FTOL; scsteptol=STOL;
+
+ /* Call KINCreate/KINInit to initialize KINSOL:
+ nvSpec is the nvSpec pointer used in the serial version
+ A pointer to KINSOL problem memory is returned and stored in kmem. */
+ kmem = KINCreate();
+ if (check_flag((void *)kmem, "KINCreate", 0)) return(1);
+ /* Vector cc passed as template vector. */
+ flag = KINInit(kmem, func, cc);
+ if (check_flag(&flag, "KINInit", 1)) return(1);
+
+ flag = KINSetUserData(kmem, data);
+ if (check_flag(&flag, "KINSetUserData", 1)) return(1);
+ flag = KINSetConstraints(kmem, constraints);
+ if (check_flag(&flag, "KINSetConstraints", 1)) return(1);
+ flag = KINSetFuncNormTol(kmem, fnormtol);
+ if (check_flag(&flag, "KINSetFuncNormTol", 1)) return(1);
+ flag = KINSetScaledStepTol(kmem, scsteptol);
+ if (check_flag(&flag, "KINSetScaledStepTol", 1)) return(1);
+
+ /* We no longer need the constraints vector since KINSetConstraints
+ creates a private copy for KINSOL to use. */
+ N_VDestroy_Serial(constraints);
+
+ /* START: Loop through SPGMR, SPBCG and SPTFQMR linear solver modules */
+ for (linsolver = 0; linsolver < 3; ++linsolver) {
+
+ /* Re-initialize user data */
+ if (linsolver != 0) SetInitialProfiles(cc, sc);
+
+ /* Attach a linear solver module */
+ switch(linsolver) {
+
+ /* (a) SPGMR */
+ case(USE_SPGMR):
+
+ /* Print header */
+ printf(" -------");
+ 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. */
+ maxl = 15;
+ maxlrst = 2;
+ flag = KINSpgmr(kmem, maxl);
+ if (check_flag(&flag, "KINSpgmr", 1)) return(1);
+
+ flag = KINSpilsSetMaxRestarts(kmem, maxlrst);
+ if (check_flag(&flag, "KINSpilsSetMaxRestarts", 1)) return(1);
+
+ break;
+
+ /* (b) SPBCG */
+ case(USE_SPBCG):
+
+ /* Print header */
+ printf(" -------");
+ printf(" \n| SPBCG |\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. */
+ maxl = 15;
+ flag = KINSpbcg(kmem, maxl);
+ if (check_flag(&flag, "KINSpbcg", 1)) return(1);
+
+ break;
+
+ /* (c) SPTFQMR */
+ case(USE_SPTFQMR):
+
+ /* Print header */
+ printf(" ---------");
+ 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. */
+ maxl = 25;
+ flag = KINSptfqmr(kmem, maxl);
+ if (check_flag(&flag, "KINSptfqmr", 1)) return(1);
+
+ break;
+
+ }
+
+ /* Set preconditioner functions */
+ flag = KINSpilsSetPreconditioner(kmem,
+ PrecSetupBD,
+ PrecSolveBD);
+ if (check_flag(&flag, "KINSpilsSetPreconditioner", 1)) return(1);
+
+ /* Print out the problem size, solution parameters, initial guess. */
+ PrintHeader(globalstrategy, maxl, maxlrst, fnormtol, scsteptol, linsolver);
+
+ /* Call KINSol and print output concentration profile */
+ flag = KINSol(kmem, /* KINSol memory block */
+ cc, /* initial guess on input; solution vector */
+ globalstrategy, /* global stragegy choice */
+ sc, /* scaling vector, for the variable cc */
+ sc); /* scaling vector for function values fval */
+ if (check_flag(&flag, "KINSol", 1)) return(1);
+
+ printf("\n\nComputed equilibrium species concentrations:\n");
+ PrintOutput(cc);
+
+ /* Print final statistics and free memory */
+ PrintFinalStats(kmem, linsolver);
+
+ } /* END: Loop through SPGMR, SPBCG and SPTFQMR linear solver modules */
+
+ N_VDestroy_Serial(cc);
+ N_VDestroy_Serial(sc);
+ KINFree(&kmem);
+ FreeUserData(data);
+
+ return(0);
+}
+
+/* Readability definitions used in other routines below */
+
+#define acoef (data->acoef)
+#define bcoef (data->bcoef)
+#define cox (data->cox)
+#define coy (data->coy)
+
+/*
+ *--------------------------------------------------------------------
+ * FUNCTIONS CALLED BY KINSOL
+ *--------------------------------------------------------------------
+ */
+
+/*
+ * System function for predator-prey system
+ */
+
+static int func(N_Vector cc, N_Vector fval, void *user_data)
+{
+ realtype xx, yy, delx, dely, *cxy, *rxy, *fxy, dcyli, dcyui, dcxli, dcxri;
+ int jx, jy, is, idyu, idyl, idxr, idxl;
+ UserData data;
+
+ data = (UserData)user_data;
+ delx = data->dx;
+ dely = data->dy;
+
+ /* Loop over all mesh points, evaluating rate array at each point*/
+ for (jy = 0; jy < MY; jy++) {
+
+ yy = dely*jy;
+
+ /* Set lower/upper index shifts, special at boundaries. */
+ idyl = (jy != 0 ) ? NSMX : -NSMX;
+ idyu = (jy != MY-1) ? NSMX : -NSMX;
+
+ for (jx = 0; jx < MX; jx++) {
+
+ xx = delx*jx;
+
+ /* Set left/right index shifts, special at boundaries. */
+ idxl = (jx != 0 ) ? NUM_SPECIES : -NUM_SPECIES;
+ idxr = (jx != MX-1) ? NUM_SPECIES : -NUM_SPECIES;
+
+ cxy = IJ_Vptr(cc,jx,jy);
+ rxy = IJ_Vptr(data->rates,jx,jy);
+ fxy = IJ_Vptr(fval,jx,jy);
+
+ /* Get species interaction rate array at (xx,yy) */
+ WebRate(xx, yy, cxy, rxy, user_data);
+
+ for(is = 0; is < NUM_SPECIES; is++) {
+
+ /* Differencing in x direction */
+ dcyli = *(cxy+is) - *(cxy - idyl + is) ;
+ dcyui = *(cxy + idyu + is) - *(cxy+is);
+
+ /* Differencing in y direction */
+ dcxli = *(cxy+is) - *(cxy - idxl + is);
+ dcxri = *(cxy + idxr +is) - *(cxy+is);
+
+ /* Compute the total rate value at (xx,yy) */
+ fxy[is] = (coy)[is] * (dcyui - dcyli) +
+ (cox)[is] * (dcxri - dcxli) + rxy[is];
+
+ } /* end of is loop */
+
+ } /* end of jx loop */
+
+ } /* end of jy loop */
+
+ return(0);
+}
+
+/*
+ * Preconditioner setup routine. Generate and preprocess P.
+ */
+
+static int PrecSetupBD(N_Vector cc, N_Vector cscale,
+ N_Vector fval, N_Vector fscale,
+ void *user_data,
+ N_Vector vtemp1, N_Vector vtemp2)
+{
+ 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;
+ delx = data->dx;
+ dely = data->dy;
+
+ uround = data->uround;
+ sqruround = data->sqruround;
+ fac = N_VWL2Norm(fval, fscale);
+ r0 = THOUSAND * uround * fac * NEQ;
+ if(r0 == ZERO) r0 = ONE;
+
+ /* Loop over spatial points; get size NUM_SPECIES Jacobian block at each */
+ for (jy = 0; jy < MY; jy++) {
+ yy = jy*dely;
+
+ for (jx = 0; jx < MX; jx++) {
+ xx = jx*delx;
+ Pxy = (data->P)[jx][jy];
+ 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++) {
+
+ csave = cxy[j]; /* Save the j,jx,jy element of cc */
+ r = MAX(sqruround*ABS(csave), r0/scxy[j]);
+ cxy[j] += r; /* Perturb the j,jx,jy element of cc */
+ fac = ONE/r;
+
+ WebRate(xx, yy, cxy, perturb_rates, data);
+
+ /* Restore j,jx,jy element of cc */
+ cxy[j] = csave;
+
+ /* Load the j-th column of difference quotients */
+ Pxycol = Pxy[j];
+ 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 */
+ ret = denseGETRF(Pxy, NUM_SPECIES, NUM_SPECIES, (data->pivot)[jx][jy]);
+ if (ret != 0) return(1);
+
+ } /* end of jx loop */
+
+ } /* end of jy loop */
+
+ return(0);
+}
+
+/*
+ * Preconditioner solve routine
+ */
+
+static int PrecSolveBD(N_Vector cc, N_Vector cscale,
+ N_Vector fval, N_Vector fscale,
+ N_Vector vv, void *user_data,
+ N_Vector ftem)
+{
+ realtype **Pxy, *vxy;
+ long int *piv, jx, jy;
+ UserData data;
+
+ data = (UserData)user_data;
+
+ for (jx=0; jx<MX; jx++) {
+
+ for (jy=0; jy<MY; jy++) {
+
+ /* For each (jx,jy), solve a linear system of size NUM_SPECIES.
+ vxy is the address of the corresponding portion of the vector vv;
+ Pxy is the address of the corresponding block of the matrix P;
+ piv is the address of the corresponding block of the array pivot. */
+ vxy = IJ_Vptr(vv,jx,jy);
+ Pxy = (data->P)[jx][jy];
+ piv = (data->pivot)[jx][jy];
+ denseGETRS(Pxy, NUM_SPECIES, piv, vxy);
+
+ } /* end of jy loop */
+
+ } /* end of jx loop */
+
+ return(0);
+}
+
+/*
+ * Interaction rate function routine
+ */
+
+static void WebRate(realtype xx, realtype yy, realtype *cxy, realtype *ratesxy,
+ void *user_data)
+{
+ int i;
+ realtype fac;
+ UserData data;
+
+ data = (UserData)user_data;
+
+ for (i = 0; i<NUM_SPECIES; i++)
+ ratesxy[i] = DotProd(NUM_SPECIES, cxy, acoef[i]);
+
+ fac = ONE + ALPHA * xx * yy;
+
+ for (i = 0; i < NUM_SPECIES; i++)
+ ratesxy[i] = cxy[i] * ( bcoef[i] * fac + ratesxy[i] );
+}
+
+/*
+ * Dot product routine for realtype arrays
+ */
+
+static realtype DotProd(int size, realtype *x1, realtype *x2)
+{
+ int i;
+ realtype *xx1, *xx2, temp = ZERO;
+
+ xx1 = x1; xx2 = x2;
+ for (i = 0; i < size; i++) temp += (*xx1++) * (*xx2++);
+
+ return(temp);
+}
+
+/*
+ *--------------------------------------------------------------------
+ * PRIVATE FUNCTIONS
+ *--------------------------------------------------------------------
+ */
+
+/*
+ * Allocate memory for data structure of type UserData
+ */
+
+static UserData AllocUserData(void)
+{
+ int jx, jy;
+ UserData data;
+
+ data = (UserData) malloc(sizeof *data);
+
+ 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);
+ }
+ }
+ acoef = newDenseMat(NUM_SPECIES, NUM_SPECIES);
+ bcoef = (realtype *)malloc(NUM_SPECIES * sizeof(realtype));
+ cox = (realtype *)malloc(NUM_SPECIES * sizeof(realtype));
+ coy = (realtype *)malloc(NUM_SPECIES * sizeof(realtype));
+
+ return(data);
+}
+
+/*
+ * Load problem constants in data
+ */
+
+static void InitUserData(UserData data)
+{
+ int i, j, np;
+ realtype *a1,*a2, *a3, *a4, dx2, dy2;
+
+ data->mx = MX;
+ data->my = MY;
+ data->ns = NUM_SPECIES;
+ data->np = NUM_SPECIES/2;
+ data->ax = AX;
+ data->ay = AY;
+ data->dx = (data->ax)/(MX-1);
+ data->dy = (data->ay)/(MY-1);
+ data->uround = UNIT_ROUNDOFF;
+ data->sqruround = SQRT(data->uround);
+
+ /* Set up the coefficients a and b plus others found in the equations */
+ np = data->np;
+
+ dx2=(data->dx)*(data->dx); dy2=(data->dy)*(data->dy);
+
+ for (i = 0; i < np; i++) {
+ a1= &(acoef[i][np]);
+ a2= &(acoef[i+np][0]);
+ a3= &(acoef[i][0]);
+ a4= &(acoef[i+np][np]);
+
+ /* Fill in the portion of acoef in the four quadrants, row by row */
+ for (j = 0; j < np; j++) {
+ *a1++ = -GG;
+ *a2++ = EE;
+ *a3++ = ZERO;
+ *a4++ = ZERO;
+ }
+
+ /* and then change the diagonal elements of acoef to -AA */
+ acoef[i][i]=-AA;
+ acoef[i+np][i+np] = -AA;
+
+ bcoef[i] = BB;
+ bcoef[i+np] = -BB;
+
+ cox[i]=DPREY/dx2;
+ cox[i+np]=DPRED/dx2;
+
+ 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);
+ free(coy);
+ N_VDestroy_Serial(data->rates);
+ free(data);
+}
+
+/*
+ * Set initial conditions in cc
+ */
+
+static void SetInitialProfiles(N_Vector cc, N_Vector sc)
+{
+ int i, jx, jy;
+ realtype *cloc, *sloc;
+ realtype ctemp[NUM_SPECIES], stemp[NUM_SPECIES];
+
+ /* Initialize arrays ctemp and stemp used in the loading process */
+ for (i = 0; i < NUM_SPECIES/2; i++) {
+ ctemp[i] = PREYIN;
+ stemp[i] = ONE;
+ }
+ for (i = NUM_SPECIES/2; i < NUM_SPECIES; i++) {
+ ctemp[i] = PREDIN;
+ stemp[i] = RCONST(0.00001);
+ }
+
+ /* Load initial profiles into cc and sc vector from ctemp and stemp. */
+ for (jy = 0; jy < MY; jy++) {
+ for (jx = 0; jx < MX; jx++) {
+ cloc = IJ_Vptr(cc,jx,jy);
+ sloc = IJ_Vptr(sc,jx,jy);
+ for (i = 0; i < NUM_SPECIES; i++) {
+ cloc[i] = ctemp[i];
+ sloc[i] = stemp[i];
+ }
+ }
+ }
+}
+
+/*
+ * Print first lines of output (problem description)
+ */
+
+static void PrintHeader(int globalstrategy, int maxl, int maxlrst,
+ realtype fnormtol, realtype scsteptol,
+ int linsolver)
+{
+ printf("\nPredator-prey test problem -- KINSol (serial 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("Flag globalstrategy = %d (0 = None, 1 = Linesearch)\n",
+ globalstrategy);
+
+ switch(linsolver) {
+
+ case(USE_SPGMR):
+ printf("Linear solver is SPGMR with maxl = %d, maxlrst = %d\n",
+ maxl, maxlrst);
+ break;
+
+ case(USE_SPBCG):
+ printf("Linear solver is SPBCG with maxl = %d\n", maxl);
+ break;
+
+ case(USE_SPTFQMR):
+ printf("Linear solver is SPTFQMR with maxl = %d\n", maxl);
+ break;
+
+ }
+
+ printf("Preconditioning uses interaction-only block-diagonal matrix\n");
+ printf("Positivity constraints imposed on all components \n");
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("Tolerance parameters: fnormtol = %Lg scsteptol = %Lg\n",
+ fnormtol, scsteptol);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("Tolerance parameters: fnormtol = %lg scsteptol = %lg\n",
+ fnormtol, scsteptol);
+#else
+ printf("Tolerance parameters: fnormtol = %g scsteptol = %g\n",
+ fnormtol, scsteptol);
+#endif
+
+ 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);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("At all mesh points: %lg %lg %lg %lg %lg %lg\n",
+ 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);
+#endif
+}
+
+/*
+ * Print sampled values of current cc
+ */
+
+static void PrintOutput(N_Vector cc)
+{
+ int is, jx, jy;
+ realtype *ct;
+
+ jy = 0; jx = 0;
+ ct = IJ_Vptr(cc,jx,jy);
+ printf("\nAt bottom left:");
+
+ /* Print out lines with up to 6 values per line */
+ for (is = 0; is < NUM_SPECIES; is++){
+ if ((is%6)*6 == is) printf("\n");
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf(" %Lg",ct[is]);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf(" %lg",ct[is]);
+#else
+ printf(" %g",ct[is]);
+#endif
+ }
+
+ jy = MY-1; jx = MX-1;
+ ct = IJ_Vptr(cc,jx,jy);
+ printf("\n\nAt top right:");
+
+ /* Print out lines with up to 6 values per line */
+ for (is = 0; is < NUM_SPECIES; is++) {
+ if ((is%6)*6 == is) printf("\n");
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf(" %Lg",ct[is]);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf(" %lg",ct[is]);
+#else
+ printf(" %g",ct[is]);
+#endif
+ }
+ printf("\n\n");
+}
+
+/*
+ * Print final statistics contained in iopt
+ */
+
+static void PrintFinalStats(void *kmem, int linsolver)
+{
+ long int nni, nfe, nli, npe, nps, ncfl, nfeSG;
+ int flag;
+
+ flag = KINGetNumNonlinSolvIters(kmem, &nni);
+ check_flag(&flag, "KINGetNumNonlinSolvIters", 1);
+ flag = KINGetNumFuncEvals(kmem, &nfe);
+ check_flag(&flag, "KINGetNumFuncEvals", 1);
+
+ flag = KINSpilsGetNumLinIters(kmem, &nli);
+ check_flag(&flag, "KINSpilsGetNumLinIters", 1);
+ flag = KINSpilsGetNumPrecEvals(kmem, &npe);
+ check_flag(&flag, "KINSpilsGetNumPrecEvals", 1);
+ flag = KINSpilsGetNumPrecSolves(kmem, &nps);
+ check_flag(&flag, "KINSpilsGetNumPrecSolves", 1);
+ flag = KINSpilsGetNumConvFails(kmem, &ncfl);
+ check_flag(&flag, "KINSpilsGetNumConvFails", 1);
+ flag = KINSpilsGetNumFuncEvals(kmem, &nfeSG);
+ check_flag(&flag, "KINSpilsGetNumFuncEvals", 1);
+
+ printf("Final Statistics.. \n");
+ 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);
+
+ if (linsolver < 2) printf("\n=========================================================\n\n");
+
+}
+
+/*
+ * 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, 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/kinsol/serial/kinKrylovDemo_ls.out b/examples/kinsol/serial/kinKrylovDemo_ls.out
new file mode 100644
index 0000000..888089a
--- /dev/null
+++ b/examples/kinsol/serial/kinKrylovDemo_ls.out
@@ -0,0 +1,102 @@
+ -------
+| SPGMR |
+ -------
+
+Predator-prey test problem -- KINSol (serial version)
+
+Mesh dimensions = 5 X 5
+Number of species = 6
+Total system size = 150
+
+Flag globalstrategy = 0 (0 = None, 1 = Linesearch)
+Linear solver is SPGMR with maxl = 15, maxlrst = 2
+Preconditioning uses interaction-only block-diagonal matrix
+Positivity constraints imposed on all components
+Tolerance parameters: fnormtol = 1e-07 scsteptol = 1e-13
+
+Initial profile of concentration
+At all mesh points: 1 1 1 30000 30000 30000
+
+
+Computed equilibrium species concentrations:
+
+At bottom left:
+ 1.16253 1.16253 1.16253 34875 34875 34875
+
+At top right:
+ 1.2637 1.2637 1.2637 37908.7 37908.7 37908.7
+
+Final Statistics..
+nni = 5 nli = 90
+nfe = 6 nfeSG = 95
+nps = 95 npe = 1 ncfl = 0
+
+=========================================================
+
+ -------
+| SPBCG |
+ -------
+
+Predator-prey test problem -- KINSol (serial version)
+
+Mesh dimensions = 5 X 5
+Number of species = 6
+Total system size = 150
+
+Flag globalstrategy = 0 (0 = None, 1 = Linesearch)
+Linear solver is SPBCG with maxl = 15
+Preconditioning uses interaction-only block-diagonal matrix
+Positivity constraints imposed on all components
+Tolerance parameters: fnormtol = 1e-07 scsteptol = 1e-13
+
+Initial profile of concentration
+At all mesh points: 1 1 1 30000 30000 30000
+
+
+Computed equilibrium species concentrations:
+
+At bottom left:
+ 1.16253 1.16253 1.16253 34875 34875 34875
+
+At top right:
+ 1.2637 1.2637 1.2637 37908.7 37908.7 37908.7
+
+Final Statistics..
+nni = 7 nli = 82
+nfe = 8 nfeSG = 171
+nps = 171 npe = 1 ncfl = 4
+
+=========================================================
+
+ ---------
+| SPTFQMR |
+ ---------
+
+Predator-prey test problem -- KINSol (serial version)
+
+Mesh dimensions = 5 X 5
+Number of species = 6
+Total system size = 150
+
+Flag globalstrategy = 0 (0 = None, 1 = Linesearch)
+Linear solver is SPTFQMR with maxl = 25
+Preconditioning uses interaction-only block-diagonal matrix
+Positivity constraints imposed on all components
+Tolerance parameters: fnormtol = 1e-07 scsteptol = 1e-13
+
+Initial profile of concentration
+At all mesh points: 1 1 1 30000 30000 30000
+
+
+Computed equilibrium species concentrations:
+
+At bottom left:
+ 1.16253 1.16253 1.16253 34875 34875 34875
+
+At top right:
+ 1.2637 1.2637 1.2637 37908.7 37908.7 37908.7
+
+Final Statistics..
+nni = 8 nli = 166
+nfe = 9 nfeSG = 676
+nps = 676 npe = 1 ncfl = 6
diff --git a/examples/kinsol/serial/kinLaplace_bnd.c b/examples/kinsol/serial/kinLaplace_bnd.c
new file mode 100644
index 0000000..947f209
--- /dev/null
+++ b/examples/kinsol/serial/kinLaplace_bnd.c
@@ -0,0 +1,394 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.1 $
+ * $Date: 2007/10/25 20:03:41 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * This example solves a 2D elliptic PDE
+ *
+ * d^2 u / dx^2 + d^2 u / dy^2 = u^3 - u + 2.0
+ *
+ * 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
+ * solver.
+ * -----------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#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>
+
+/* Problem Constants */
+
+#define NX 31 /* no. of points in x direction */
+#define NY 31 /* no. of points in y direction */
+#define NEQ NX*NY /* problem dimension */
+
+#define SKIP 3 /* no. of points skipped for printing */
+
+#define FTOL RCONST(1.e-12) /* function tolerance */
+
+#define ZERO RCONST(0.0)
+#define ONE RCONST(1.0)
+#define TWO RCONST(2.0)
+
+/* 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 <= NX, 1 <= j <= NY.
+ The vdata array is obtained via the macro call vdata = NV_DATA_S(v),
+ where v is an N_Vector.
+ The variables are ordered by the y index j, then by the x index i. */
+
+#define IJth(vdata,i,j) (vdata[(j-1) + (i-1)*NY])
+
+/* Private functions */
+
+static int func(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, char *funcname, int opt);
+
+/*
+ *--------------------------------------------------------------------
+ * MAIN PROGRAM
+ *--------------------------------------------------------------------
+ */
+
+int main()
+{
+ realtype fnormtol, fnorm;
+ N_Vector y, scale;
+ int mset, msubset, flag;
+ void *kmem;
+
+ y = scale = NULL;
+ kmem = NULL;
+
+ /* -------------------------
+ * Print problem description
+ * ------------------------- */
+
+ printf("\n2D elliptic PDE on unit square\n");
+ 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: Modified Newton with band linear solver\n");
+ printf("Problem size: %2ld x %2ld = %4ld\n", (long int) NX, (long int) NY, (long int) NEQ);
+
+ /* --------------------------------------
+ * Create vectors for solution and scales
+ * -------------------------------------- */
+
+ y = N_VNew_Serial(NEQ);
+ if (check_flag((void *)y, "N_VNew_Serial", 0)) return(1);
+
+ scale = N_VNew_Serial(NEQ);
+ if (check_flag((void *)scale, "N_VNew_Serial", 0)) return(1);
+
+ /* -----------------------------------------
+ * Initialize and allocate memory for KINSOL
+ * ----------------------------------------- */
+
+ kmem = KINCreate();
+ if (check_flag((void *)kmem, "KINCreate", 0)) return(1);
+
+ /* y is used as a template */
+
+ flag = KINInit(kmem, func, y);
+ if (check_flag(&flag, "KINInit", 1)) return(1);
+
+ /* -------------------
+ * Set optional inputs
+ * ------------------- */
+
+ /* Specify stopping tolerance based on residual */
+
+ fnormtol = FTOL;
+ flag = KINSetFuncNormTol(kmem, fnormtol);
+ if (check_flag(&flag, "KINSetFuncNormTol", 1)) return(1);
+
+ /* -------------------------
+ * Attach band linear solver
+ * ------------------------- */
+
+ flag = KINBand(kmem, NEQ, NY, NY);
+ if (check_flag(&flag, "KINBand", 1)) return(1);
+
+ /* ------------------------------
+ * Parameters for Modified Newton
+ * ------------------------------ */
+
+ /* Force a Jacobian re-evaluation every mset iterations */
+ mset = 100;
+ flag = KINSetMaxSetupCalls(kmem, mset);
+ if (check_flag(&flag, "KINSetMaxSetupCalls", 1)) return(1);
+
+ /* Every msubset iterations, test if a Jacobian evaluation
+ is necessary */
+ msubset = 1;
+ flag = KINSetMaxSubSetupCalls(kmem, msubset);
+ if (check_flag(&flag, "KINSetMaxSubSetupCalls", 1)) return(1);
+
+ /* -------------
+ * Initial guess
+ * ------------- */
+
+ N_VConst_Serial(ZERO, y);
+
+ /* ----------------------------
+ * Call KINSol to solve problem
+ * ---------------------------- */
+
+ /* No scaling used */
+ N_VConst_Serial(ONE,scale);
+
+ /* Call main solver */
+ flag = KINSol(kmem, /* KINSol memory block */
+ y, /* initial guess on input; solution vector */
+ KIN_LINESEARCH, /* global stragegy choice */
+ scale, /* scaling vector, for the variable cc */
+ scale); /* scaling vector for function values fval */
+ if (check_flag(&flag, "KINSol", 1)) return(1);
+
+
+ /* ------------------------------------
+ * Print solution and solver statistics
+ * ------------------------------------ */
+
+ /* Get scaled norm of the system function */
+
+ flag = KINGetFuncNorm(kmem, &fnorm);
+ if (check_flag(&flag, "KINGetfuncNorm", 1)) return(1);
+
+ printf("\nComputed solution (||F|| = %g):\n\n",fnorm);
+ PrintOutput(y);
+
+ PrintFinalStats(kmem);
+
+ /* -----------
+ * Free memory
+ * ----------- */
+
+ N_VDestroy_Serial(y);
+ N_VDestroy_Serial(scale);
+ KINFree(&kmem);
+
+ return(0);
+}
+
+/*
+ *--------------------------------------------------------------------
+ * PRIVATE FUNCTIONS
+ *--------------------------------------------------------------------
+ */
+
+/*
+ * System function
+ */
+
+static int func(N_Vector u, N_Vector f, void *user_data)
+{
+ realtype dx, dy, hdiff, vdiff;
+ realtype hdc, vdc;
+ realtype uij, udn, uup, ult, urt;
+ realtype *udata, *fdata;
+ realtype x,y;
+
+ int i, j;
+
+ dx = ONE/(NX+1);
+ dy = ONE/(NY+1);
+ hdc = ONE/(dx*dx);
+ vdc = ONE/(dy*dy);
+
+ udata = NV_DATA_S(u);
+ fdata = NV_DATA_S(f);
+
+ for (j=1; j <= NY; j++) {
+
+ y = j*dy;
+
+ for (i=1; i <= NX; i++) {
+
+ x = i*dx;
+
+ /* Extract u at x_i, y_j and four neighboring points */
+
+ uij = IJth(udata, i, j);
+ udn = (j == 1) ? ZERO : IJth(udata, i, j-1);
+ uup = (j == NY) ? ZERO : IJth(udata, i, j+1);
+ ult = (i == 1) ? ZERO : IJth(udata, i-1, j);
+ urt = (i == NX) ? ZERO : IJth(udata, i+1, j);
+
+ /* Evaluate diffusion components */
+
+ hdiff = hdc*(ult - TWO*uij + urt);
+ vdiff = vdc*(uup - TWO*uij + udn);
+
+ /* Set residual at x_i, y_j */
+
+ IJth(fdata, i, j) = hdiff + vdiff + uij - uij*uij*uij + 2.0;
+
+ }
+
+ }
+
+ return(0);
+}
+
+/*
+ * Print solution at selected points
+ */
+
+static void PrintOutput(N_Vector u)
+{
+ int i, j;
+ realtype dx, dy, x, y;
+ realtype *udata;
+
+ dx = ONE/(NX+1);
+ dy = ONE/(NY+1);
+
+ udata = NV_DATA_S(u);
+
+ printf(" ");
+ for (i=1; i<=NX; i+= SKIP) {
+ x = i*dx;
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("%-8.5Lf ", x);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("%-8.5lf ", x);
+#else
+ printf("%-8.5f ", x);
+#endif
+ }
+ printf("\n\n");
+
+ for (j=1; j<=NY; j+= SKIP) {
+ y = j*dy;
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("%-8.5Lf ", y);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("%-8.5lf ", y);
+#else
+ printf("%-8.5f ", y);
+#endif
+ for (i=1; i<=NX; i+= SKIP) {
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("%-8.5Lf ", IJth(udata,i,j));
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("%-8.5lf ", IJth(udata,i,j));
+#else
+ printf("%-8.5f ", IJth(udata,i,j));
+#endif
+ }
+ printf("\n");
+ }
+}
+
+/*
+ * Print final statistics
+ */
+
+static void PrintFinalStats(void *kmem)
+{
+ long int nni, nfe, nje, nfeD;
+ long int lenrw, leniw, lenrwB, leniwB;
+ long int nbcfails, nbacktr;
+ int flag;
+
+ /* Main solver statistics */
+
+ flag = KINGetNumNonlinSolvIters(kmem, &nni);
+ check_flag(&flag, "KINGetNumNonlinSolvIters", 1);
+ flag = KINGetNumFuncEvals(kmem, &nfe);
+ check_flag(&flag, "KINGetNumFuncEvals", 1);
+
+ /* Linesearch statistics */
+
+ flag = KINGetNumBetaCondFails(kmem, &nbcfails);
+ check_flag(&flag, "KINGetNumBetacondFails", 1);
+ flag = KINGetNumBacktrackOps(kmem, &nbacktr);
+ check_flag(&flag, "KINGetNumBacktrackOps", 1);
+
+ /* Main solver workspace size */
+
+ flag = KINGetWorkSpace(kmem, &lenrw, &leniw);
+ check_flag(&flag, "KINGetWorkSpace", 1);
+
+ /* Band linear solver statistics */
+
+ flag = KINDlsGetNumJacEvals(kmem, &nje);
+ check_flag(&flag, "KINDlsGetNumJacEvals", 1);
+ flag = KINDlsGetNumFuncEvals(kmem, &nfeD);
+ check_flag(&flag, "KINDlsGetNumFuncEvals", 1);
+
+ /* Band linear solver workspace size */
+
+ flag = KINDlsGetWorkSpace(kmem, &lenrwB, &leniwB);
+ check_flag(&flag, "KINDlsGetWorkSpace", 1);
+
+ printf("\nFinal Statistics.. \n\n");
+ printf("nni = %6ld nfe = %6ld \n", nni, nfe);
+ printf("nbcfails = %6ld nbacktr = %6ld \n", nbcfails, nbacktr);
+ printf("nje = %6ld nfeB = %6ld \n", nje, nfeD);
+ printf("\n");
+ printf("lenrw = %6ld leniw = %6ld \n", lenrw, leniw);
+ printf("lenrwB = %6ld leniwB = %6ld \n", lenrwB, leniwB);
+
+}
+
+/*
+ * 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, 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/kinsol/serial/kinLaplace_bnd.out b/examples/kinsol/serial/kinLaplace_bnd.out
new file mode 100644
index 0000000..5f43154
--- /dev/null
+++ b/examples/kinsol/serial/kinLaplace_bnd.out
@@ -0,0 +1,32 @@
+
+2D elliptic PDE on unit square
+ d^2 u / dx^2 + d^2 u / dy^2 = u^3 - u + 2.0
+ + homogeneous Dirichlet boundary conditions
+
+Solution method: Modified Newton with band linear solver
+Problem size: 31 x 31 = 961
+
+Computed solution (||F|| = 1.37621e-12):
+
+ 0.03125 0.12500 0.21875 0.31250 0.40625 0.50000 0.59375 0.68750 0.78125 0.87500 0.96875
+
+0.03125 0.00405 0.01165 0.01617 0.01896 0.02051 0.02100 0.02051 0.01896 0.01617 0.01165 0.00405
+0.12500 0.01165 0.03772 0.05461 0.06530 0.07126 0.07318 0.07126 0.06530 0.05461 0.03772 0.01165
+0.21875 0.01617 0.05461 0.08098 0.09813 0.10780 0.11093 0.10780 0.09813 0.08098 0.05461 0.01617
+0.31250 0.01896 0.06530 0.09813 0.11989 0.13229 0.13631 0.13229 0.11989 0.09813 0.06530 0.01896
+0.40625 0.02051 0.07126 0.10780 0.13229 0.14632 0.15089 0.14632 0.13229 0.10780 0.07126 0.02051
+0.50000 0.02100 0.07318 0.11093 0.13631 0.15089 0.15564 0.15089 0.13631 0.11093 0.07318 0.02100
+0.59375 0.02051 0.07126 0.10780 0.13229 0.14632 0.15089 0.14632 0.13229 0.10780 0.07126 0.02051
+0.68750 0.01896 0.06530 0.09813 0.11989 0.13229 0.13631 0.13229 0.11989 0.09813 0.06530 0.01896
+0.78125 0.01617 0.05461 0.08098 0.09813 0.10780 0.11093 0.10780 0.09813 0.08098 0.05461 0.01617
+0.87500 0.01165 0.03772 0.05461 0.06530 0.07126 0.07318 0.07126 0.06530 0.05461 0.03772 0.01165
+0.96875 0.00405 0.01165 0.01617 0.01896 0.02051 0.02100 0.02051 0.01896 0.01617 0.01165 0.00405
+
+Final Statistics..
+
+nni = 7 nfe = 8
+nbcfails = 0 nbacktr = 0
+nje = 1 nfeB = 63
+
+lenrw = 4822 leniw = 27
+lenrwB = 150877 leniwB = 961
diff --git a/examples/kinsol/serial/kinRoboKin_dns.c b/examples/kinsol/serial/kinRoboKin_dns.c
new file mode 100644
index 0000000..e3842f3
--- /dev/null
+++ b/examples/kinsol/serial/kinRoboKin_dns.c
@@ -0,0 +1,437 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.2 $
+ * $Date: 2010/12/01 23:08:49 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * This example solves a nonlinear system from robot kinematics.
+ *
+ * Source: "Handbook of Test Problems in Local and Global Optimization",
+ * C.A. Floudas, P.M. Pardalos et al.
+ * Kluwer Academic Publishers, 1999.
+ * Test problem 6 from Section 14.1, Chapter 14
+ *
+ * The nonlinear system is solved by KINSOL using the DENSE linear
+ * solver.
+ *
+ * Constraints are imposed to make all components of the solution
+ * be within [-1,1].
+ * -----------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#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>
+
+/* Problem Constants */
+
+#define NVAR 8 /* variables */
+#define NEQ 3*NVAR /* equations + bounds */
+
+#define FTOL RCONST(1.e-5) /* function tolerance */
+#define STOL RCONST(1.e-5) /* step tolerance */
+
+#define ZERO RCONST(0.0)
+#define ONE RCONST(1.0)
+#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)
+
+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 void PrintOutput(N_Vector y);
+static void PrintFinalStats(void *kmem);
+static int check_flag(void *flagvalue, char *funcname, int opt);
+
+/*
+ *--------------------------------------------------------------------
+ * MAIN PROGRAM
+ *--------------------------------------------------------------------
+ */
+
+int main()
+{
+ realtype fnormtol, scsteptol;
+ N_Vector y, scale, constraints;
+ int mset, flag, i;
+ void *kmem;
+
+ y = scale = constraints = NULL;
+ kmem = NULL;
+
+ printf("\nRobot Kinematics Example\n");
+ printf("8 variables; -1 <= x_i <= 1\n");
+ printf("KINSOL problem size: 8 + 2*8 = 24 \n\n");
+
+ /* Create vectors for solution, scales, and constraints */
+
+ y = N_VNew_Serial(NEQ);
+ if (check_flag((void *)y, "N_VNew_Serial", 0)) return(1);
+
+ scale = N_VNew_Serial(NEQ);
+ if (check_flag((void *)scale, "N_VNew_Serial", 0)) return(1);
+
+ constraints = N_VNew_Serial(NEQ);
+ if (check_flag((void *)constraints, "N_VNew_Serial", 0)) return(1);
+
+ /* Initialize and allocate memory for KINSOL */
+
+ kmem = KINCreate();
+ if (check_flag((void *)kmem, "KINCreate", 0)) return(1);
+
+ flag = KINInit(kmem, func, y); /* y passed as a template */
+ if (check_flag(&flag, "KINInit", 1)) return(1);
+
+ /* Set optional inputs */
+
+ N_VConst_Serial(ZERO,constraints);
+ for (i = NVAR+1; i <= NEQ; i++) Ith(constraints, i) = ONE;
+
+ flag = KINSetConstraints(kmem, constraints);
+ if (check_flag(&flag, "KINSetConstraints", 1)) return(1);
+
+ fnormtol = FTOL;
+ flag = KINSetFuncNormTol(kmem, fnormtol);
+ if (check_flag(&flag, "KINSetFuncNormTol", 1)) return(1);
+
+ scsteptol = STOL;
+ flag = KINSetScaledStepTol(kmem, scsteptol);
+ if (check_flag(&flag, "KINSetScaledStepTol", 1)) return(1);
+
+ /* Attach dense linear solver */
+
+ flag = KINDense(kmem, NEQ);
+ if (check_flag(&flag, "KINDense", 1)) return(1);
+
+ flag = KINDlsSetDenseJacFn(kmem, jac);
+ if (check_flag(&flag, "KINDlsSetDenseJacFn", 1)) return(1);
+
+ /* Indicate exact Newton */
+
+ mset = 1;
+ flag = KINSetMaxSetupCalls(kmem, mset);
+ if (check_flag(&flag, "KINSetMaxSetupCalls", 1)) return(1);
+
+ /* Initial guess */
+
+ N_VConst_Serial(ONE, y);
+ for(i = 1; i <= NVAR; i++) Ith(y,i) = SQRT(TWO)/TWO;
+
+ printf("Initial guess:\n");
+ PrintOutput(y);
+
+ /* Call KINSol to solve problem */
+
+ N_VConst_Serial(ONE,scale);
+ flag = KINSol(kmem, /* KINSol memory block */
+ y, /* initial guess on input; solution vector */
+ KIN_LINESEARCH, /* global stragegy choice */
+ scale, /* scaling vector, for the variable cc */
+ scale); /* scaling vector for function values fval */
+ if (check_flag(&flag, "KINSol", 1)) return(1);
+
+ printf("\nComputed solution:\n");
+ PrintOutput(y);
+
+ /* Print final statistics and free memory */
+
+ PrintFinalStats(kmem);
+
+ N_VDestroy_Serial(y);
+ N_VDestroy_Serial(scale);
+ N_VDestroy_Serial(constraints);
+ KINFree(&kmem);
+
+ return(0);
+}
+
+/*
+ * System function
+ */
+
+static int func(N_Vector y, N_Vector f, void *user_data)
+{
+ realtype *yd, *fd;
+
+ realtype x1, x2, x3, x4, x5, x6, x7, x8;
+ realtype l1, l2, l3, l4, l5, l6, l7, l8;
+ realtype u1, u2, u3, u4, u5, u6, u7, u8;
+
+ realtype eq1, eq2, eq3, eq4, eq5, eq6, eq7, eq8;
+ realtype lb1, lb2, lb3, lb4, lb5, lb6, lb7, lb8;
+ realtype ub1, ub2, ub3, ub4, ub5, ub6, ub7, ub8;
+
+ yd = NV_DATA_S(y);
+ fd = NV_DATA_S(f);
+
+ x1 = yd[0]; l1 = yd[ 8]; u1 = yd[16];
+ x2 = yd[1]; l2 = yd[ 9]; u2 = yd[17];
+ x3 = yd[2]; l3 = yd[10]; u3 = yd[18];
+ x4 = yd[3]; l4 = yd[11]; u4 = yd[19];
+ x5 = yd[4]; l5 = yd[12]; u5 = yd[20];
+ x6 = yd[5]; l6 = yd[13]; u6 = yd[21];
+ x7 = yd[6]; l7 = yd[14]; u7 = yd[22];
+ x8 = yd[7]; l8 = yd[15]; u8 = yd[23];
+
+ /* Nonlinear equations */
+
+ eq1 = - 0.1238*x1 + x7 - 0.001637*x2
+ - 0.9338*x4 + 0.004731*x1*x3 - 0.3578*x2*x3 - 0.3571;
+ eq2 = 0.2638*x1 - x7 - 0.07745*x2
+ - 0.6734*x4 + 0.2238*x1*x3 + 0.7623*x2*x3 - 0.6022;
+ eq3 = 0.3578*x1 + 0.004731*x2 + x6*x8;
+ eq4 = - 0.7623*x1 + 0.2238*x2 + 0.3461;
+ eq5 = x1*x1 + x2*x2 - 1;
+ eq6 = x3*x3 + x4*x4 - 1;
+ eq7 = x5*x5 + x6*x6 - 1;
+ eq8 = x7*x7 + x8*x8 - 1;
+
+ /* Lower bounds ( l_i = 1 + x_i >= 0)*/
+
+ lb1 = l1 - 1.0 - x1;
+ lb2 = l2 - 1.0 - x2;
+ lb3 = l3 - 1.0 - x3;
+ lb4 = l4 - 1.0 - x4;
+ lb5 = l5 - 1.0 - x5;
+ lb6 = l6 - 1.0 - x6;
+ lb7 = l7 - 1.0 - x7;
+ lb8 = l8 - 1.0 - x8;
+
+ /* Upper bounds ( u_i = 1 - x_i >= 0)*/
+
+ ub1 = u1 - 1.0 + x1;
+ ub2 = u2 - 1.0 + x2;
+ ub3 = u3 - 1.0 + x3;
+ ub4 = u4 - 1.0 + x4;
+ ub5 = u5 - 1.0 + x5;
+ ub6 = u6 - 1.0 + x6;
+ ub7 = u7 - 1.0 + x7;
+ ub8 = u8 - 1.0 + x8;
+
+ fd[0] = eq1; fd[ 8] = lb1; fd[16] = ub1;
+ fd[1] = eq2; fd[ 9] = lb2; fd[17] = ub2;
+ fd[2] = eq3; fd[10] = lb3; fd[18] = ub3;
+ fd[3] = eq4; fd[11] = lb4; fd[19] = ub4;
+ fd[4] = eq5; fd[12] = lb5; fd[20] = ub5;
+ fd[5] = eq6; fd[13] = lb6; fd[21] = ub6;
+ fd[6] = eq7; fd[14] = lb7; fd[22] = ub7;
+ fd[7] = eq8; fd[15] = lb8; fd[23] = ub8;
+
+ return(0);
+}
+
+/*
+ * 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)
+{
+ int i;
+ realtype *yd;
+ realtype x1, x2, x3, x4, x5, x6, x7, x8;
+
+ yd = NV_DATA_S(y);
+
+ x1 = yd[0];
+ x2 = yd[1];
+ x3 = yd[2];
+ x4 = yd[3];
+ x5 = yd[4];
+ x6 = yd[5];
+ x7 = yd[6];
+ x8 = yd[7];
+
+ /* Nonlinear equations */
+
+ /*
+ - 0.1238*x1 + x7 - 0.001637*x2
+ - 0.9338*x4 + 0.004731*x1*x3 - 0.3578*x2*x3 - 0.3571
+ */
+ IJth(J,1,1) = - 0.1238 + 0.004731*x3;
+ IJth(J,1,2) = - 0.001637 - 0.3578*x3;
+ IJth(J,1,3) = 0.004731*x1 - 0.3578*x2;
+ IJth(J,1,4) = - 0.9338;
+ IJth(J,1,7) = 1.0;
+
+ /*
+ 0.2638*x1 - x7 - 0.07745*x2
+ - 0.6734*x4 + 0.2238*x1*x3 + 0.7623*x2*x3 - 0.6022
+ */
+ IJth(J,2,1) = 0.2638 + 0.2238*x3;
+ IJth(J,2,2) = - 0.07745 + 0.7623*x3;
+ IJth(J,2,3) = 0.2238*x1 + 0.7623*x2;
+ IJth(J,2,4) = - 0.6734;
+ IJth(J,2,7) = -1.0;
+
+ /*
+ 0.3578*x1 + 0.004731*x2 + x6*x8
+ */
+ IJth(J,3,1) = 0.3578;
+ IJth(J,3,2) = 0.004731;
+ IJth(J,3,6) = x8;
+ IJth(J,3,8) = x6;
+
+ /*
+ - 0.7623*x1 + 0.2238*x2 + 0.3461
+ */
+ IJth(J,4,1) = - 0.7623;
+ IJth(J,4,2) = 0.2238;
+
+ /*
+ x1*x1 + x2*x2 - 1
+ */
+ IJth(J,5,1) = 2.0*x1;
+ IJth(J,5,2) = 2.0*x2;
+
+ /*
+ x3*x3 + x4*x4 - 1
+ */
+ IJth(J,6,3) = 2.0*x3;
+ IJth(J,6,4) = 2.0*x4;
+
+ /*
+ x5*x5 + x6*x6 - 1
+ */
+ IJth(J,7,5) = 2.0*x5;
+ IJth(J,7,6) = 2.0*x6;
+
+ /*
+ x7*x7 + x8*x8 - 1
+ */
+ IJth(J,8,7) = 2.0*x7;
+ IJth(J,8,8) = 2.0*x8;
+
+
+ /*
+ Lower bounds ( l_i = 1 + x_i >= 0)
+ l_i - 1.0 - x_i
+ */
+
+ for(i=1;i<=8;i++) {
+ IJth(J,8+i,i) = -1.0;
+ IJth(J,8+i,8+i) = 1.0;
+ }
+
+ /*
+ Upper bounds ( u_i = 1 - x_i >= 0)
+ u_i - 1.0 + x_i
+ */
+
+ for(i=1;i<=8;i++) {
+ IJth(J,16+i,i) = 1.0;
+ IJth(J,16+i,16+i) = 1.0;
+ }
+
+ return(0);
+
+}
+
+/*
+ * Print solution
+ */
+
+static void PrintOutput(N_Vector y)
+{
+ int i;
+
+ printf(" l=x+1 x u=1-x\n");
+ printf(" ----------------------------------\n");
+
+ for(i=1; i<=NVAR; i++) {
+
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf(" %10.6Lg %10.6Lg %10.6Lg\n",
+ Ith(y,i+NVAR), Ith(y,i), Ith(y,i+2*NVAR));
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf(" %10.6lg %10.6lg %10.6lg\n",
+ Ith(y,i+NVAR), Ith(y,i), Ith(y,i+2*NVAR));
+#else
+ printf(" %10.6g %10.6g %10.6g\n",
+ Ith(y,i+NVAR), Ith(y,i), Ith(y,i+2*NVAR));
+#endif
+
+ }
+
+}
+
+/*
+ * Print final statistics
+ */
+
+static void PrintFinalStats(void *kmem)
+{
+ long int nni, nfe, nje, nfeD;
+ 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 = KINDlsGetNumFuncEvals(kmem, &nfeD);
+ check_flag(&flag, "KINDlsGetNumFuncEvals", 1);
+
+ printf("\nFinal Statistics.. \n");
+ printf("nni = %5ld nfe = %5ld \n", nni, nfe);
+ printf("nje = %5ld nfeD = %5ld \n", nje, nfeD);
+}
+
+/*
+ * 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, 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/kinsol/serial/kinRoboKin_dns.out b/examples/kinsol/serial/kinRoboKin_dns.out
new file mode 100644
index 0000000..28ed6a2
--- /dev/null
+++ b/examples/kinsol/serial/kinRoboKin_dns.out
@@ -0,0 +1,32 @@
+
+Robot Kinematics Example
+8 variables; -1 <= x_i <= 1
+KINSOL problem size: 8 + 2*8 = 24
+
+Initial guess:
+ l=x+1 x u=1-x
+ ----------------------------------
+ 1 0.707107 1
+ 1 0.707107 1
+ 1 0.707107 1
+ 1 0.707107 1
+ 1 0.707107 1
+ 1 0.707107 1
+ 1 0.707107 1
+ 1 0.707107 1
+
+Computed solution:
+ l=x+1 x u=1-x
+ ----------------------------------
+ 1.67155 0.671554 0.328446
+ 1.74096 0.740955 0.259045
+ 1.95189 0.951893 0.0481072
+ 0.693569 -0.306431 1.30643
+ 1.96381 0.963811 0.0361892
+ 0.733413 -0.266587 1.26659
+ 1.40464 0.404641 0.595359
+ 1.91448 0.914475 0.0855246
+
+Final Statistics..
+nni = 6 nfe = 7
+nje = 6 nfeD = 0
diff --git a/examples/templates/cmakelists_parallel_C_ex.in b/examples/templates/cmakelists_parallel_C_ex.in
new file mode 100644
index 0000000..25e8569
--- /dev/null
+++ b/examples/templates/cmakelists_parallel_C_ex.in
@@ -0,0 +1,83 @@
+# -----------------------------------------------------------------
+# $Revision: 1.2 $
+# $Date: 2009/02/17 02:58:47 $
+# -----------------------------------------------------------------
+# Programmer: Radu Serban @ LLNL
+# -----------------------------------------------------------------
+# Copyright (c) 2007, The Regents of the University of California.
+# Produced at the Lawrence Livermore National Laboratory.
+# All rights reserved.
+# For details, see the LICENSE file.
+# -----------------------------------------------------------------
+# 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...
+#
+# -----------------------------------------------------------------
+
+# Specify project name
+PROJECT(@SOLVER at _parallel_examples C)
+
+MARK_AS_ADVANCED(EXECUTABLE_OUTPUT_PATH LIBRARY_OUTPUT_PATH)
+
+# Set the names of the examples to be built
+SET(examples @EXAMPLES@)
+
+# Set name of MPI compiler to be used (CC or MPICC)
+SET(MPI_MPICC @MPICC@ CACHE STRING "MPICC compiler script")
+SET(CMAKE_C_COMPILER ${MPI_MPICC})
+
+# 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@)
+
+# Find the SUNDIALS solver's library
+FIND_LIBRARY(SUNDIALS_SOLVER_LIB
+ @SOLVER_LIB@ ${SUNDIALS_LIB_DIR}
+ DOC "@SOLVER@ library")
+
+# Find the NVECTOR library
+FIND_LIBRARY(SUNDIALS_NVEC_LIB
+ sundials_nvecparallel ${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)
+ SET(SUNDIALS_LIBS "${SUNDIALS_LIBS} ${LAPACK_LIBRARIES}")
+ENDIF(LAPACK_LIBRARIES)
+
+# Build each example one by one
+FOREACH(example ${examples})
+ ADD_EXECUTABLE(${example} ${example}.c)
+ 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
new file mode 100644
index 0000000..c77c0c1
--- /dev/null
+++ b/examples/templates/cmakelists_parallel_F77_ex.in
@@ -0,0 +1,85 @@
+# -----------------------------------------------------------------
+# $Revision: 1.2 $
+# $Date: 2009/02/17 02:58:47 $
+# -----------------------------------------------------------------
+# Programmer: Radu Serban @ LLNL
+# -----------------------------------------------------------------
+# Copyright (c) 2007, The Regents of the University of California.
+# Produced at the Lawrence Livermore National Laboratory.
+# All rights reserved.
+# For details, see the LICENSE file.
+# -----------------------------------------------------------------
+# 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...
+#
+# -----------------------------------------------------------------
+
+# Specify project name
+PROJECT(F at SOLVER@_parallel_examples Fortran)
+
+MARK_AS_ADVANCED(EXECUTABLE_OUTPUT_PATH LIBRARY_OUTPUT_PATH)
+
+# Set the names of the examples to be built
+SET(examples @EXAMPLES@)
+
+# Set name of MPI compiler to be used (F77 or MPIF77)
+SET(MPI_MPIF77 @MPIF77@ CACHE STRING "MPIF77 compiler script")
+SET(CMAKE_Fortran_COMPILER ${MPI_MPIF77})
+
+# Set search path for SUNDIALS libraries
+SET(SUNDIALS_LIB_DIR @libdir@)
+
+# Find the SUNDIALS solver's library
+FIND_LIBRARY(SUNDIALS_SOLVER_LIB
+ @SOLVER_LIB@ ${SUNDIALS_LIB_DIR}
+ DOC "@SOLVER@ library")
+
+FIND_LIBRARY(SUNDIALS_SOLVER_FLIB
+ @SOLVER_FLIB@ ${SUNDIALS_LIB_DIR}
+ DOC "@SOLVER@ F77-C library")
+
+# Find the NVECTOR library
+FIND_LIBRARY(SUNDIALS_NVEC_LIB
+ sundials_nvecparallel ${SUNDIALS_LIB_DIR}
+ DOC "NVECTOR library")
+
+FIND_LIBRARY(SUNDIALS_NVEC_FLIB
+ sundials_fnvecparallel ${SUNDIALS_LIB_DIR}
+ DOC "NVECTOR F77-C 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_FLIB} ${SUNDIALS_SOLVER_LIB}
+ ${SUNDIALS_NVEC_FLIB} ${SUNDIALS_NVEC_LIB}
+ ${SUNDIALS_EXTRA_LIB})
+IF(LAPACK_LIBRARIES)
+ SET(SUNDIALS_LIBS "${SUNDIALS_LIBS} ${LAPACK_LIBRARIES}")
+ENDIF(LAPACK_LIBRARIES)
+
+# Build each example one by one
+FOREACH(example ${examples})
+ ADD_EXECUTABLE(${example} ${example}.f)
+ TARGET_LINK_LIBRARIES(${example} ${LIBS})
+ENDFOREACH(example ${examples})
diff --git a/examples/templates/cmakelists_serial_C_ex.in b/examples/templates/cmakelists_serial_C_ex.in
new file mode 100644
index 0000000..c0523fd
--- /dev/null
+++ b/examples/templates/cmakelists_serial_C_ex.in
@@ -0,0 +1,80 @@
+# -----------------------------------------------------------------
+# $Revision: 1.3 $
+# $Date: 2009/02/17 02:58:47 $
+# -----------------------------------------------------------------
+# Programmer: Radu Serban @ LLNL
+# -----------------------------------------------------------------
+# Copyright (c) 2007, The Regents of the University of California.
+# Produced at the Lawrence Livermore National Laboratory.
+# All rights reserved.
+# For details, see the LICENSE file.
+# -----------------------------------------------------------------
+# CMakeLists.txt for @SOLVER@ serial 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...
+#
+# -----------------------------------------------------------------
+
+# Specify project name
+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@)
+
+# 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@)
+
+# Find the SUNDIALS solver's library
+FIND_LIBRARY(SUNDIALS_SOLVER_LIB
+ @SOLVER_LIB@ ${SUNDIALS_LIB_DIR}
+ DOC "@SOLVER@ library")
+
+# Find the NVECTOR library
+FIND_LIBRARY(SUNDIALS_NVEC_LIB
+ sundials_nvecserial ${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)
+ SET(SUNDIALS_LIBS "${SUNDIALS_LIBS} ${LAPACK_LIBRARIES}")
+ENDIF(LAPACK_LIBRARIES)
+
+# Build each example one by one
+FOREACH(example ${examples})
+ ADD_EXECUTABLE(${example} ${example}.c)
+ TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+ENDFOREACH(example ${examples})
+
diff --git a/examples/templates/cmakelists_serial_F77_ex.in b/examples/templates/cmakelists_serial_F77_ex.in
new file mode 100644
index 0000000..2288c40
--- /dev/null
+++ b/examples/templates/cmakelists_serial_F77_ex.in
@@ -0,0 +1,82 @@
+# -----------------------------------------------------------------
+# $Revision: 1.3 $
+# $Date: 2009/02/17 02:58:47 $
+# -----------------------------------------------------------------
+# Programmer: Radu Serban @ LLNL
+# -----------------------------------------------------------------
+# Copyright (c) 2007, The Regents of the University of California.
+# Produced at the Lawrence Livermore National Laboratory.
+# All rights reserved.
+# For details, see the LICENSE file.
+# -----------------------------------------------------------------
+# CMakeLists.txt for @SOLVER@ serial 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...
+#
+# -----------------------------------------------------------------
+
+# Specify project name
+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@)
+
+# Set search path for SUNDIALS libraries
+SET(SUNDIALS_LIB_DIR @libdir@)
+
+# Find the SUNDIALS solver's library
+FIND_LIBRARY(SUNDIALS_SOLVER_LIB
+ @SOLVER_LIB@ ${SUNDIALS_LIB_DIR}
+ DOC "@SOLVER@ library")
+
+FIND_LIBRARY(SUNDIALS_SOLVER_FLIB
+ @SOLVER_FLIB@ ${SUNDIALS_LIB_DIR}
+ DOC "@SOLVER@ F77-C library")
+
+# Find the NVECTOR library
+FIND_LIBRARY(SUNDIALS_NVEC_LIB
+ sundials_nvecserial ${SUNDIALS_LIB_DIR}
+ DOC "NVECTOR library")
+
+FIND_LIBRARY(SUNDIALS_NVEC_FLIB
+ sundials_fnvecserial ${SUNDIALS_LIB_DIR}
+ DOC "NVECTOR F77-C 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_FLIB} ${SUNDIALS_SOLVER_LIB}
+ ${SUNDIALS_NVEC_FLIB} ${SUNDIALS_NVEC_LIB}
+ ${SUNDIALS_EXTRA_LIB})
+IF(LAPACK_LIBRARIES)
+ SET(SUNDIALS_LIBS "${SUNDIALS_LIBS} ${LAPACK_LIBRARIES}")
+ENDIF(LAPACK_LIBRARIES)
+
+# Build each example one by one
+FOREACH(example ${examples})
+ ADD_EXECUTABLE(${example} ${example}.f)
+ TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+ENDFOREACH(example ${examples})
+
diff --git a/examples/templates/makefile_parallel_C_ex.in b/examples/templates/makefile_parallel_C_ex.in
new file mode 100644
index 0000000..d55656b
--- /dev/null
+++ b/examples/templates/makefile_parallel_C_ex.in
@@ -0,0 +1,78 @@
+# -----------------------------------------------------------------
+# $Revision: 1.2 $
+# $Date: 2009/02/17 02:58:47 $
+# -----------------------------------------------------------------
+# Programmer: Radu Serban @ LLNL
+# -----------------------------------------------------------------
+# Copyright (c) 2007, The Regents of the University of California.
+# Produced at the Lawrence Livermore National Laboratory.
+# All rights reserved.
+# For details, see the LICENSE file.
+# -----------------------------------------------------------------
+# 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@
+
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+includedir = @includedir@
+libdir = @libdir@
+
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CC = @CC@
+CFLAGS = @CFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+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}
+LIBRARIES = -l at SOLVER_LIB@ -lsundials_nvecparallel ${LIBS}
+LIBRARIES_BL = @BLAS_LAPACK_LIBS@
+
+EXAMPLES = @EXAMPLES@
+
+OBJECTS = ${EXAMPLES:=.o}
+
+# -----------------------------------------------------------------------------------------
+
+.SUFFIXES : .o .c
+
+.c.o :
+ ${MPICC} ${CPPFLAGS} ${CFLAGS} ${MPI_FLAGS} ${INCLUDES} -c $<
+
+# -----------------------------------------------------------------------------------------
+
+all: ${OBJECTS}
+ @for i in ${EXAMPLES} ; do \
+ echo "${MPICC} -o $${i} $${i}.o ${MPI_FLAGS} ${CFLAGS} ${LDFLAGS} -L${libdir} ${LIBRARIES} -L${MPI_LIB_DIR} ${MPI_LIBS} ${LIBRARIES_BL}" ; \
+ ${MPICC} -o $${i} $${i}.o ${MPI_FLAGS} ${CFLAGS} ${LDFLAGS} -L${libdir} ${LIBRARIES} -L${MPI_LIB_DIR} ${MPI_LIBS} ${LIBRARIES_BL}; \
+ done
+
+clean:
+ rm -f ${OBJECTS}
+ rm -f ${EXAMPLES}
+
+# -----------------------------------------------------------------------------------------
diff --git a/examples/templates/makefile_parallel_F77_ex.in b/examples/templates/makefile_parallel_F77_ex.in
new file mode 100644
index 0000000..8a7b34a
--- /dev/null
+++ b/examples/templates/makefile_parallel_F77_ex.in
@@ -0,0 +1,77 @@
+# -----------------------------------------------------------------
+# $Revision: 1.2 $
+# $Date: 2009/02/17 02:58:47 $
+# -----------------------------------------------------------------
+# Programmer: Radu Serban @ LLNL
+# -----------------------------------------------------------------
+# Copyright (c) 2007, The Regents of the University of California.
+# Produced at the Lawrence Livermore National Laboratory.
+# All rights reserved.
+# For details, see the LICENSE file.
+# -----------------------------------------------------------------
+# 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@
+
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+includedir = @includedir@
+libdir = @libdir@
+
+FFLAGS = @FFLAGS@
+F77_LDFLAGS = @F77_LDFLAGS@
+F77_LIBS = @F77_LIBS@
+
+MPIF77 = @MPIF77@
+MPI_INC_DIR = @MPI_INC_DIR@
+MPI_FLAGS = @MPI_FLAGS@
+MPIF77_LNKR = @MPIF77_LNKR@
+MPI_LIB_DIR = @MPI_LIB_DIR@
+MPI_LIBS = @MPI_LIBS@
+
+LIBRARIES = -l at SOLVER_FLIB@ -l at SOLVER_LIB@ -lsundials_fnvecparallel -lsundials_nvecparallel ${LIBS}
+LIBRARIES_BL = @BLAS_LAPACK_LIBS@
+
+EXAMPLES = @EXAMPLES@
+
+OBJECTS = ${EXAMPLES:=.o}
+
+# -----------------------------------------------------------------------------------------
+
+.SUFFIXES : .o .f
+
+.f.o :
+ ${MPIF77} ${FFLAGS} ${MPI_FLAGS} -I${MPI_INC_DIR} -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}" ; \
+ ${MPIF77_LNKR} -o $${i} $${i}.o ${MPI_FLAGS} ${F77_LDFLAGS} ${F77_LIBS} -L${libdir} ${LIBRARIES} -L${MPI_LIB_DIR} ${MPI_LIBS} ${LIBRARIES_BL}; \
+ done
+
+clean:
+ rm -f ${OBJECTS}
+ rm -f ${EXAMPLES}
+
+# -----------------------------------------------------------------------------------------
diff --git a/examples/templates/makefile_serial_C_ex.in b/examples/templates/makefile_serial_C_ex.in
new file mode 100644
index 0000000..a9b9382
--- /dev/null
+++ b/examples/templates/makefile_serial_C_ex.in
@@ -0,0 +1,73 @@
+# -----------------------------------------------------------------
+# $Revision: 1.3 $
+# $Date: 2009/02/17 02:58:47 $
+# -----------------------------------------------------------------
+# Programmer: Radu Serban @ LLNL
+# -----------------------------------------------------------------
+# Copyright (c) 2002, The Regents of the University of California.
+# Produced at the Lawrence Livermore National Laboratory.
+# All rights reserved.
+# For details, see the LICENSE file.
+# -----------------------------------------------------------------
+# Makefile for @SOLVER@ serial 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, 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@
+
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+includedir = @includedir@
+libdir = @libdir@
+
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CC = @CC@
+CFLAGS = @CFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+
+INCLUDES = -I${includedir}
+LIBRARIES = -l at SOLVER_LIB@ -lsundials_nvecserial ${LIBS}
+LIBRARIES_BL = @BLAS_LAPACK_LIBS@
+
+EXAMPLES = @EXAMPLES@ @EXAMPLES_BL@
+
+OBJECTS = ${EXAMPLES:=.o}
+
+# -----------------------------------------------------------------------------------------
+
+.SUFFIXES : .o .c
+
+.c.o :
+ ${CC} ${CPPFLAGS} ${CFLAGS} ${INCLUDES} -c $<
+
+# -----------------------------------------------------------------------------------------
+
+all: ${OBJECTS}
+ @for i in ${EXAMPLES} ; do \
+ echo "${CC} -o $${i} $${i}.o ${CFLAGS} ${LDFLAGS} -L${libdir} ${LIBRARIES} ${LIBRARIES_BL}" ; \
+ ${CC} -o $${i} $${i}.o ${CFLAGS} ${LDFLAGS} -L${libdir} ${LIBRARIES} ${LIBRARIES_BL}; \
+ done
+
+clean:
+ rm -f ${OBJECTS}
+ rm -f ${EXAMPLES}
+
+# -----------------------------------------------------------------------------------------
+
diff --git a/examples/templates/makefile_serial_F77_ex.in b/examples/templates/makefile_serial_F77_ex.in
new file mode 100644
index 0000000..863f354
--- /dev/null
+++ b/examples/templates/makefile_serial_F77_ex.in
@@ -0,0 +1,71 @@
+# -----------------------------------------------------------------
+# $Revision: 1.3 $
+# $Date: 2009/02/17 02:58:47 $
+# -----------------------------------------------------------------
+# Programmer: Radu Serban @ LLNL
+# -----------------------------------------------------------------
+# Copyright (c) 2007, The Regents of the University of California.
+# Produced at the Lawrence Livermore National Laboratory.
+# All rights reserved.
+# For details, see the LICENSE file.
+# -----------------------------------------------------------------
+# Makefile for @SOLVER@ Fortran serial 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, 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@
+
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+includedir = @includedir@
+libdir = @libdir@
+
+F77 = @F77@
+FFLAGS = @FFLAGS@
+F77_LNKR = @F77_LNKR@
+F77_LDFLAGS = @F77_LDFLAGS@
+F77_LIBS = @F77_LIBS@
+
+LIBRARIES = -l at SOLVER_FLIB@ -l at SOLVER_LIB@ -lsundials_fnvecserial -lsundials_nvecserial ${LIBS}
+LIBRARIES_BL = @BLAS_LAPACK_LIBS@
+
+EXAMPLES = @EXAMPLES@ @EXAMPLES_BL@
+
+OBJECTS = ${EXAMPLES:=.o}
+
+# -----------------------------------------------------------------------------------------
+
+.SUFFIXES : .o .f
+
+.f.o :
+ ${F77} ${FFLAGS} -c $<
+
+# -----------------------------------------------------------------------------------------
+
+all: ${OBJECTS}
+ @for i in ${EXAMPLES} ; do \
+ echo "${F77_LNKR} -o $${i} $${i}.o ${F77_LDFLAGS} ${F77_LIBS} -L${libdir} ${LIBRARIES} ${LIBRARIES_BL}" ; \
+ ${F77_LNKR} -o $${i} $${i}.o ${F77_LDFLAGS} ${F77_LIBS} -L${libdir} ${LIBRARIES} ${LIBRARIES_BL} ; \
+ done
+
+clean:
+ rm -f ${OBJECTS}
+ rm -f ${EXAMPLES}
+
+# -----------------------------------------------------------------------------------------
+
diff --git a/include/cvode/cvode.h b/include/cvode/cvode.h
new file mode 100644
index 0000000..e783256
--- /dev/null
+++ b/include/cvode/cvode.h
@@ -0,0 +1,790 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.13 $
+ * $Date: 2010/12/01 22:10:38 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh, Radu Serban
+ * and Dan Shumaker @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * This is the interface file for the main CVODE integrator.
+ * -----------------------------------------------------------------
+ *
+ * CVODE is used to solve numerically the ordinary initial value
+ * problem:
+ *
+ * y' = f(t,y),
+ * y(t0) = y0,
+ *
+ * where t0, y0 in R^N, and f: R x R^N -> R^N are given.
+ *
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _CVODE_H
+#define _CVODE_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <stdio.h>
+
+#include <sundials/sundials_nvector.h>
+
+/*
+ * =================================================================
+ * C V O D E C O N S T A N T S
+ * =================================================================
+ */
+
+/*
+ * -----------------------------------------------------------------
+ * Enumerations for inputs to CVodeCreate and CVode.
+ * -----------------------------------------------------------------
+ * Symbolic constants for the lmm and iter parameters to CVodeCreate
+ * and the input parameter itask to CVode, are given below.
+ *
+ * lmm: The user of the CVODE package specifies whether to use the
+ * CV_ADAMS (Adams-Moulton) or CV_BDF (Backward Differentiation
+ * Formula) linear multistep method. The BDF method is
+ * recommended for stiff problems, and the CV_ADAMS method is
+ * recommended for nonstiff problems.
+ *
+ * iter: At each internal time step, a nonlinear equation must
+ * be solved. The user can specify either CV_FUNCTIONAL
+ * iteration, which does not require linear algebra, or a
+ * CV_NEWTON iteration, which requires the solution of linear
+ * systems. In the CV_NEWTON case, the user also specifies a
+ * CVODE linear solver. CV_NEWTON is recommended in case of
+ * stiff problems.
+ *
+ * itask: The itask input parameter to CVode indicates the job
+ * of the solver for the next user step. The CV_NORMAL
+ * itask is to have the solver take internal steps until
+ * it has reached or just passed the user specified tout
+ * parameter. The solver then interpolates in order to
+ * return an approximate value of y(tout). The CV_ONE_STEP
+ * option tells the solver to just take one internal step
+ * and return the solution at the point reached by that step.
+ * -----------------------------------------------------------------
+ */
+
+/* lmm */
+#define CV_ADAMS 1
+#define CV_BDF 2
+
+/* iter */
+#define CV_FUNCTIONAL 1
+#define CV_NEWTON 2
+
+/* itask */
+#define CV_NORMAL 1
+#define CV_ONE_STEP 2
+
+/*
+ * ----------------------------------------
+ * CVODE return flags
+ * ----------------------------------------
+ */
+
+#define CV_SUCCESS 0
+#define CV_TSTOP_RETURN 1
+#define CV_ROOT_RETURN 2
+
+#define CV_WARNING 99
+
+#define CV_TOO_MUCH_WORK -1
+#define CV_TOO_MUCH_ACC -2
+#define CV_ERR_FAILURE -3
+#define CV_CONV_FAILURE -4
+
+#define CV_LINIT_FAIL -5
+#define CV_LSETUP_FAIL -6
+#define CV_LSOLVE_FAIL -7
+#define CV_RHSFUNC_FAIL -8
+#define CV_FIRST_RHSFUNC_ERR -9
+#define CV_REPTD_RHSFUNC_ERR -10
+#define CV_UNREC_RHSFUNC_ERR -11
+#define CV_RTFUNC_FAIL -12
+
+#define CV_MEM_FAIL -20
+#define CV_MEM_NULL -21
+#define CV_ILL_INPUT -22
+#define CV_NO_MALLOC -23
+#define CV_BAD_K -24
+#define CV_BAD_T -25
+#define CV_BAD_DKY -26
+#define CV_TOO_CLOSE -27
+
+/*
+ * =================================================================
+ * F U N C T I O N T Y P E S
+ * =================================================================
+ */
+
+/*
+ * -----------------------------------------------------------------
+ * Type : CVRhsFn
+ * -----------------------------------------------------------------
+ * The f function which defines the right hand side of the ODE
+ * system y' = f(t,y) must have type CVRhsFn.
+ * f takes as input the independent variable value t, and the
+ * dependent variable vector y. It stores the result of f(t,y)
+ * in the vector ydot. The y and ydot arguments are of type
+ * N_Vector.
+ * (Allocation of memory for ydot is handled within CVODE)
+ * The user_data parameter is the same as the user_data
+ * parameter set by the user through the CVodeSetUserData routine.
+ * This user-supplied pointer is passed to the user's f function
+ * every time it is called.
+ *
+ * A CVRhsFn should return 0 if successful, a negative value if
+ * an unrecoverable error occured, and a positive value if a
+ * recoverable error (e.g. invalid y values) occured.
+ * If an unrecoverable occured, the integration is halted.
+ * If a recoverable error occured, then (in most cases) CVODE
+ * will try to correct and retry.
+ * -----------------------------------------------------------------
+ */
+
+typedef int (*CVRhsFn)(realtype t, N_Vector y,
+ N_Vector ydot, void *user_data);
+
+/*
+ * -----------------------------------------------------------------
+ * Type : CVRootFn
+ * -----------------------------------------------------------------
+ * A function g, which defines a set of functions g_i(t,y) whose
+ * roots are sought during the integration, must have type CVRootFn.
+ * The function g takes as input the independent variable value
+ * t, and the dependent variable vector y. It stores the nrtfn
+ * values g_i(t,y) in the realtype array gout.
+ * (Allocation of memory for gout is handled within CVODE.)
+ * The user_data parameter is the same as that passed by the user
+ * to the CVodeSetUserData routine. This user-supplied pointer is
+ * passed to the user's g function every time it is called.
+ *
+ * A CVRootFn should return 0 if successful or a non-zero value
+ * if an error occured (in which case the integration will be halted).
+ * -----------------------------------------------------------------
+ */
+
+typedef int (*CVRootFn)(realtype t, N_Vector y, realtype *gout, void *user_data);
+
+/*
+ * -----------------------------------------------------------------
+ * Type : CVEwtFn
+ * -----------------------------------------------------------------
+ * A function e, which sets the error weight vector ewt, must have
+ * type CVEwtFn.
+ * The function e takes as input the current dependent variable y.
+ * It must set the vector of error weights used in the WRMS norm:
+ *
+ * ||y||_WRMS = sqrt [ 1/N * sum ( ewt_i * y_i)^2 ]
+ *
+ * Typically, the vector ewt has components:
+ *
+ * ewt_i = 1 / (reltol * |y_i| + abstol_i)
+ *
+ * The user_data parameter is the same as that passed by the user
+ * to the CVodeSetUserData routine. This user-supplied pointer is
+ * passed to the user's e function every time it is called.
+ * A CVEwtFn e must return 0 if the error weight vector has been
+ * successfuly set and a non-zero value otherwise.
+ * -----------------------------------------------------------------
+ */
+
+typedef int (*CVEwtFn)(N_Vector y, N_Vector ewt, void *user_data);
+
+/*
+ * -----------------------------------------------------------------
+ * Type : CVErrHandlerFn
+ * -----------------------------------------------------------------
+ * A function eh, which handles error messages, must have type
+ * CVErrHandlerFn.
+ * The function eh takes as input the error code, the name of the
+ * module reporting the error, the error message, and a pointer to
+ * user data, the same as that passed to CVodeSetUserData.
+ *
+ * All error codes are negative, except CV_WARNING which indicates
+ * a warning (the solver continues).
+ *
+ * A CVErrHandlerFn has no return value.
+ * -----------------------------------------------------------------
+ */
+
+typedef void (*CVErrHandlerFn)(int error_code,
+ const char *module, const char *function,
+ char *msg, void *user_data);
+
+/*
+ * =================================================================
+ * U S E R - C A L L A B L E R O U T I N E S
+ * =================================================================
+ */
+
+/*
+ * -----------------------------------------------------------------
+ * Function : CVodeCreate
+ * -----------------------------------------------------------------
+ * CVodeCreate creates an internal memory block for a problem to
+ * be solved by CVODE.
+ *
+ * lmm is the type of linear multistep method to be used.
+ * The legal values are CV_ADAMS and CV_BDF (see previous
+ * description).
+ *
+ * iter is the type of iteration used to solve the nonlinear
+ * system that arises during each internal time step.
+ * The legal values are CV_FUNCTIONAL and CV_NEWTON.
+ *
+ * If successful, CVodeCreate returns a pointer to initialized
+ * problem memory. This pointer should be passed to CVodeInit.
+ * If an initialization error occurs, CVodeCreate prints an error
+ * message to standard err and returns NULL.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT void *CVodeCreate(int lmm, int iter);
+
+/*
+ * -----------------------------------------------------------------
+ * Integrator optional input specification functions
+ * -----------------------------------------------------------------
+ * The following functions can be called to set optional inputs
+ * to values other than the defaults given below:
+ *
+ * Function | Optional input / [ default value ]
+ * -----------------------------------------------------------------
+ * |
+ * CVodeSetErrHandlerFn | user-provided ErrHandler function.
+ * | [internal]
+ * |
+ * CVodeSetErrFile | the file pointer for an error file
+ * | where all CVODE warning and error
+ * | messages will be written if the default
+ * | internal error handling function is used.
+ * | This parameter can be stdout (standard
+ * | output), stderr (standard error), or a
+ * | file pointer (corresponding to a user
+ * | error file opened for writing) returned
+ * | by fopen.
+ * | If not called, then all messages will
+ * | be written to the standard error stream.
+ * | [stderr]
+ * |
+ * CVodeSetUserData | a pointer to user data that will be
+ * | passed to the user's f function every
+ * | time f is called.
+ * | [NULL]
+ * |
+ * CVodeSetMaxOrd | maximum lmm order to be used by the
+ * | solver.
+ * | [12 for Adams , 5 for BDF]
+ * |
+ * CVodeSetMaxNumSteps | maximum number of internal steps to be
+ * | taken by the solver in its attempt to
+ * | reach tout.
+ * | [500]
+ * |
+ * CVodeSetMaxHnilWarns | maximum number of warning messages
+ * | issued by the solver that t+h==t on the
+ * | next internal step. A value of -1 means
+ * | no such messages are issued.
+ * | [10]
+ * |
+ * CVodeSetStabLimDet | flag to turn on/off stability limit
+ * | detection (TRUE = on, FALSE = 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]
+ * |
+ * CVodeSetInitStep | initial step size.
+ * | [estimated by CVODE]
+ * |
+ * CVodeSetMinStep | minimum absolute value of step size
+ * | allowed.
+ * | [0.0]
+ * |
+ * CVodeSetMaxStep | maximum absolute value of step size
+ * | allowed.
+ * | [infinity]
+ * |
+ * CVodeSetStopTime | the independent variable value past
+ * | which the solution is not to proceed.
+ * | [infinity]
+ * |
+ * CVodeSetMaxErrTestFails | Maximum number of error test failures
+ * | in attempting one step.
+ * | [7]
+ * |
+ * CVodeSetMaxNonlinIters | Maximum number of nonlinear solver
+ * | iterations at one solution.
+ * | [3]
+ * |
+ * CVodeSetMaxConvFails | Maximum number of convergence failures
+ * | allowed in attempting one step.
+ * | [10]
+ * |
+ * CVodeSetNonlinConvCoef | Coefficient in the nonlinear
+ * | convergence test.
+ * | [0.1]
+ * |
+ * -----------------------------------------------------------------
+ * |
+ * CVodeSetIterType | Changes the current nonlinear iteration
+ * | type.
+ * | [set by CVodecreate]
+ * |
+ * -----------------------------------------------------------------
+ * |
+ * CVodeSetRootDirection | Specifies the direction of zero
+ * | crossings to be monitored
+ * | [both directions]
+ * |
+ * CVodeSetNoInactiveRootWarn | disable warning about possible
+ * | g==0 at beginning of integration
+ * |
+ * -----------------------------------------------------------------
+
+ * -----------------------------------------------------------------
+ * Return flag:
+ * CV_SUCCESS if successful
+ * CV_MEM_NULL if the cvode memory is NULL
+ * CV_ILL_INPUT if an argument has an illegal value
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int CVodeSetErrHandlerFn(void *cvode_mem, CVErrHandlerFn ehfun, void *eh_data);
+SUNDIALS_EXPORT int CVodeSetErrFile(void *cvode_mem, FILE *errfp);
+SUNDIALS_EXPORT int CVodeSetUserData(void *cvode_mem, void *user_data);
+SUNDIALS_EXPORT int CVodeSetMaxOrd(void *cvode_mem, int maxord);
+SUNDIALS_EXPORT int CVodeSetMaxNumSteps(void *cvode_mem, long int mxsteps);
+SUNDIALS_EXPORT int CVodeSetMaxHnilWarns(void *cvode_mem, int mxhnil);
+SUNDIALS_EXPORT int CVodeSetStabLimDet(void *cvode_mem, booleantype stldet);
+SUNDIALS_EXPORT int CVodeSetInitStep(void *cvode_mem, realtype hin);
+SUNDIALS_EXPORT int CVodeSetMinStep(void *cvode_mem, realtype hmin);
+SUNDIALS_EXPORT int CVodeSetMaxStep(void *cvode_mem, realtype hmax);
+SUNDIALS_EXPORT int CVodeSetStopTime(void *cvode_mem, realtype tstop);
+SUNDIALS_EXPORT int CVodeSetMaxErrTestFails(void *cvode_mem, int maxnef);
+SUNDIALS_EXPORT int CVodeSetMaxNonlinIters(void *cvode_mem, int maxcor);
+SUNDIALS_EXPORT int CVodeSetMaxConvFails(void *cvode_mem, int maxncf);
+SUNDIALS_EXPORT int CVodeSetNonlinConvCoef(void *cvode_mem, realtype nlscoef);
+
+SUNDIALS_EXPORT int CVodeSetIterType(void *cvode_mem, int iter);
+
+SUNDIALS_EXPORT int CVodeSetRootDirection(void *cvode_mem, int *rootdir);
+SUNDIALS_EXPORT int CVodeSetNoInactiveRootWarn(void *cvode_mem);
+
+/*
+ * -----------------------------------------------------------------
+ * Function : CVodeInit
+ * -----------------------------------------------------------------
+ * CVodeInit allocates and initializes memory for a problem to
+ * to be solved by CVODE.
+ *
+ * cvode_mem is pointer to CVODE memory returned by CVodeCreate.
+ *
+ * f is the name of the C function defining the right-hand
+ * side function in y' = f(t,y).
+ *
+ * t0 is the initial value of t.
+ *
+ * y0 is the initial condition vector y(t0).
+ *
+ * Return flag:
+ * CV_SUCCESS if successful
+ * CV_MEM_NULL if the cvode memory was NULL
+ * CV_MEM_FAIL if a memory allocation failed
+ * CV_ILL_INPUT f an argument has an illegal value.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int CVodeInit(void *cvode_mem, CVRhsFn f, realtype t0, N_Vector y0);
+
+/*
+ * -----------------------------------------------------------------
+ * Function : CVodeReInit
+ * -----------------------------------------------------------------
+ * CVodeReInit re-initializes CVode for the solution of a problem,
+ * where a prior call to CVodeInit has been made with the same
+ * problem size N. CVodeReInit performs the same input checking
+ * and initializations that CVodeInit does.
+ * But it does no memory allocation, assuming that the existing
+ * internal memory is sufficient for the new problem.
+ *
+ * The use of CVodeReInit requires that the maximum method order,
+ * maxord, is no larger for the new problem than for the problem
+ * specified in the last call to CVodeInit. This condition is
+ * automatically fulfilled if the multistep method parameter lmm
+ * is unchanged (or changed from CV_ADAMS to CV_BDF) and the default
+ * value for maxord is specified.
+ *
+ * All of the arguments to CVodeReInit have names and meanings
+ * identical to those of CVodeInit.
+ *
+ * The return value of CVodeReInit is equal to CV_SUCCESS = 0 if
+ * there were no errors; otherwise it is a negative int equal to:
+ * CV_MEM_NULL indicating cvode_mem was NULL (i.e.,
+ * CVodeCreate has not been called).
+ * CV_NO_MALLOC indicating that cvode_mem has not been
+ * allocated (i.e., CVodeInit has not been
+ * called).
+ * CV_ILL_INPUT indicating an input argument was illegal
+ * (including an attempt to increase maxord).
+ * In case of an error return, an error message is also printed.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int CVodeReInit(void *cvode_mem, realtype t0, N_Vector y0);
+
+/*
+ * -----------------------------------------------------------------
+ * Functions : CVodeSStolerances
+ * CVodeSVtolerances
+ * CVodeWFtolerances
+ * -----------------------------------------------------------------
+ *
+ * These functions specify the integration tolerances. One of them
+ * MUST be called before the first call to CVode.
+ *
+ * CVodeSStolerances specifies scalar relative and absolute tolerances.
+ * CVodeSVtolerances specifies scalar relative tolerance and a vector
+ * absolute tolerance (a potentially different absolute tolerance
+ * for each vector component).
+ * CVodeWFtolerances specifies a user-provides function (of type CVEwtFn)
+ * which will be called to set the error weight vector.
+ *
+ * The tolerances reltol and abstol define a vector of error weights,
+ * ewt, with components
+ * ewt[i] = 1/(reltol*abs(y[i]) + abstol) (in the SS case), or
+ * ewt[i] = 1/(reltol*abs(y[i]) + abstol[i]) (in the SV case).
+ * This vector is used in all error and convergence tests, which
+ * use a weighted RMS norm on all error-like vectors v:
+ * WRMSnorm(v) = sqrt( (1/N) sum(i=1..N) (v[i]*ewt[i])^2 ),
+ * where N is the problem dimension.
+ *
+ * The return value of these functions is equal to CV_SUCCESS = 0 if
+ * there were no errors; otherwise it is a negative int equal to:
+ * CV_MEM_NULL indicating cvode_mem was NULL (i.e.,
+ * CVodeCreate has not been called).
+ * CV_NO_MALLOC indicating that cvode_mem has not been
+ * allocated (i.e., CVodeInit has not been
+ * called).
+ * CV_ILL_INPUT indicating an input argument was illegal
+ * (e.g. a negative tolerance)
+ * In case of an error return, an error message is also printed.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int CVodeSStolerances(void *cvode_mem, realtype reltol, realtype abstol);
+SUNDIALS_EXPORT int CVodeSVtolerances(void *cvode_mem, realtype reltol, N_Vector abstol);
+SUNDIALS_EXPORT int CVodeWFtolerances(void *cvode_mem, CVEwtFn efun);
+
+/*
+ * -----------------------------------------------------------------
+ * Function : CVodeRootInit
+ * -----------------------------------------------------------------
+ * CVodeRootInit initializes a rootfinding problem to be solved
+ * during the integration of the ODE system. It must be called
+ * after CVodeCreate, and before CVode. The arguments are:
+ *
+ * cvode_mem = pointer to CVODE memory returned by CVodeCreate.
+ *
+ * nrtfn = number of functions g_i, an int >= 0.
+ *
+ * g = name of user-supplied function, of type CVRootFn,
+ * defining the functions g_i whose roots are sought.
+ *
+ * If a new problem is to be solved with a call to CVodeReInit,
+ * where the new problem has no root functions but the prior one
+ * did, then call CVodeRootInit with nrtfn = 0.
+ *
+ * The return value of CVodeRootInit is CV_SUCCESS = 0 if there were
+ * no errors; otherwise it is a negative int equal to:
+ * CV_MEM_NULL indicating cvode_mem was NULL, or
+ * CV_MEM_FAIL indicating a memory allocation failed.
+ * (including an attempt to increase maxord).
+ * CV_ILL_INPUT indicating nrtfn > 0 but g = NULL.
+ * In case of an error return, an error message is also printed.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int CVodeRootInit(void *cvode_mem, int nrtfn, CVRootFn g);
+
+/*
+ * -----------------------------------------------------------------
+ * Function : CVode
+ * -----------------------------------------------------------------
+ * CVode integrates the ODE over an interval in t.
+ * If itask is CV_NORMAL, then the solver integrates from its
+ * current internal t value to a point at or beyond tout, then
+ * interpolates to t = tout and returns y(tout) in the user-
+ * allocated vector yout. If itask is CV_ONE_STEP, then the solver
+ * takes one internal time step and returns in yout the value of
+ * y at the new internal time. In this case, tout is used only
+ * during the first call to CVode to determine the direction of
+ * integration and the rough scale of the t variable. If tstop is
+ * enabled (through a call to CVodeSetStopTime), then CVode returns
+ * the solution at tstop. Once the integrator returns at a tstop
+ * time, any future testing for tstop is disabled (and can be
+ * reenabled only though a new call to CVodeSetStopTime).
+ * The time reached by the solver is placed in (*tret). The
+ * user is responsible for allocating the memory for this value.
+ *
+ * cvode_mem is the pointer to CVODE memory returned by
+ * CVodeCreate.
+ *
+ * tout is the next time at which a computed solution is desired.
+ *
+ * yout is the computed solution vector. In CV_NORMAL mode with no
+ * errors and no roots found, yout=y(tout).
+ *
+ * tret is a pointer to a real location. CVode sets (*tret) to
+ * the time reached by the solver and returns
+ * yout=y(*tret).
+ *
+ * itask is CV_NORMAL or CV_ONE_STEP. These two modes are described above.
+ *
+ * Here is a brief description of each return value:
+ *
+ * CV_SUCCESS: CVode succeeded and no roots were found.
+ *
+ * CV_ROOT_RETURN: CVode succeeded, and found one or more roots.
+ * If nrtfn > 1, call CVodeGetRootInfo to see
+ * which g_i were found to have a root at (*tret).
+ *
+ * CV_TSTOP_RETURN: CVode succeeded and returned at tstop.
+ *
+ * CV_MEM_NULL: The cvode_mem argument was NULL.
+ *
+ * CV_NO_MALLOC: cvode_mem was not allocated.
+ *
+ * CV_ILL_INPUT: One of the inputs to CVode is illegal. This
+ * includes the situation when a component of the
+ * error weight vectors becomes < 0 during
+ * internal time-stepping. It also includes the
+ * situation where a root of one of the root
+ * functions was found both at t0 and very near t0.
+ * The ILL_INPUT flag will also be returned if the
+ * linear solver routine CV--- (called by the user
+ * after calling CVodeCreate) failed to set one of
+ * the linear solver-related fields in cvode_mem or
+ * if the linear solver's init routine failed. In
+ * any case, the user should see the printed
+ * error message for more details.
+ *
+ * CV_TOO_MUCH_WORK: The solver took mxstep internal steps but
+ * could not reach tout. The default value for
+ * mxstep is MXSTEP_DEFAULT = 500.
+ *
+ * CV_TOO_MUCH_ACC: The solver could not satisfy the accuracy
+ * demanded by the user for some internal step.
+ *
+ * CV_ERR_FAILURE: Error test failures occurred too many times
+ * (= MXNEF = 7) during one internal time step or
+ * occurred with |h| = hmin.
+ *
+ * CV_CONV_FAILURE: Convergence test failures occurred too many
+ * times (= MXNCF = 10) during one internal time
+ * step or occurred with |h| = hmin.
+ *
+ * CV_LINIT_FAIL: The linear solver's initialization function
+ * failed.
+ *
+ * CV_LSETUP_FAIL: The linear solver's setup routine failed in an
+ * unrecoverable manner.
+ *
+ * CV_LSOLVE_FAIL: The linear solver's solve routine failed in an
+ * unrecoverable manner.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int CVode(void *cvode_mem, realtype tout, N_Vector yout,
+ realtype *tret, int itask);
+
+/*
+ * -----------------------------------------------------------------
+ * Function : CVodeGetDky
+ * -----------------------------------------------------------------
+ * CVodeGetDky computes the kth derivative of the y function at
+ * time t, where tn-hu <= t <= tn, tn denotes the current
+ * internal time reached, and hu is the last internal step size
+ * successfully used by the solver. The user may request
+ * k=0, 1, ..., qu, where qu is the order last used. The
+ * derivative vector is returned in dky. This vector must be
+ * allocated by the caller. It is only legal to call this
+ * function after a successful return from CVode.
+ *
+ * cvode_mem is the pointer to CVODE memory returned by
+ * CVodeCreate.
+ *
+ * t is the time at which the kth derivative of y is evaluated.
+ * The legal range for t is [tn-hu,tn] as described above.
+ *
+ * k is the order of the derivative of y to be computed. The
+ * legal range for k is [0,qu] as described above.
+ *
+ * dky is the output derivative vector [((d/dy)^k)y](t).
+ *
+ * The return value for CVodeGetDky is one of:
+ *
+ * CV_SUCCESS: CVodeGetDky succeeded.
+ *
+ * CV_BAD_K: k is not in the range 0, 1, ..., qu.
+ *
+ * CV_BAD_T: t is not in the interval [tn-hu,tn].
+ *
+ * CV_BAD_DKY: The dky argument was NULL.
+ *
+ * CV_MEM_NULL: The cvode_mem argument was NULL.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int CVodeGetDky(void *cvode_mem, realtype t, int k, N_Vector dky);
+
+/*
+ * -----------------------------------------------------------------
+ * Integrator optional output extraction functions
+ * -----------------------------------------------------------------
+ * The following functions can be called to get optional outputs
+ * and statistics related to the main integrator.
+ * -----------------------------------------------------------------
+ * CVodeGetWorkSpace returns the CVODE real and integer workspaces
+ * CVodeGetNumSteps returns the cumulative number of internal
+ * steps taken by the solver
+ * CVodeGetNumRhsEvals returns the number of calls to the user's
+ * f function
+ * CVodeGetNumLinSolvSetups returns the number of calls made to
+ * the linear solver's setup routine
+ * CVodeGetNumErrTestFails returns the number of local error test
+ * failures that have occured
+ * CVodeGetLastOrder returns the order used during the last
+ * internal step
+ * CVodeGetCurrentOrder returns the order to be used on the next
+ * internal step
+ * CVodeGetNumStabLimOrderReds returns the number of order
+ * reductions due to stability limit
+ * detection
+ * CVodeGetActualInitStep returns the actual initial step size
+ * used by CVODE
+ * CVodeGetLastStep returns the step size for the last internal
+ * step
+ * CVodeGetCurrentStep returns the step size to be attempted on
+ * the next internal step
+ * CVodeGetCurrentTime returns the current internal time reached
+ * by the solver
+ * CVodeGetTolScaleFactor returns a suggested factor by which the
+ * user's tolerances should be scaled when
+ * too much accuracy has been requested for
+ * some internal step
+ * CVodeGetErrWeights returns the current error weight vector.
+ * The user must allocate space for eweight.
+ * CVodeGetEstLocalErrors returns the vector of estimated local
+ * errors. The user must allocate space
+ * for ele.
+ * CVodeGetNumGEvals returns the number of calls to the user's
+ * g function (for rootfinding)
+ * CVodeGetRootInfo returns the indices for which g_i was found to
+ * have a root. The user must allocate space for
+ * rootsfound. For i = 0 ... nrtfn-1,
+ * rootsfound[i] = 1 if g_i has a root, and = 0 if not.
+ *
+ * CVodeGet* return values:
+ * CV_SUCCESS if succesful
+ * CV_MEM_NULL if the cvode memory was NULL
+ * CV_NO_SLDET if stability limit was not turned on
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int CVodeGetWorkSpace(void *cvode_mem, long int *lenrw, long int *leniw);
+SUNDIALS_EXPORT int CVodeGetNumSteps(void *cvode_mem, long int *nsteps);
+SUNDIALS_EXPORT int CVodeGetNumRhsEvals(void *cvode_mem, long int *nfevals);
+SUNDIALS_EXPORT int CVodeGetNumLinSolvSetups(void *cvode_mem, long int *nlinsetups);
+SUNDIALS_EXPORT int CVodeGetNumErrTestFails(void *cvode_mem, long int *netfails);
+SUNDIALS_EXPORT int CVodeGetLastOrder(void *cvode_mem, int *qlast);
+SUNDIALS_EXPORT int CVodeGetCurrentOrder(void *cvode_mem, int *qcur);
+SUNDIALS_EXPORT int CVodeGetNumStabLimOrderReds(void *cvode_mem, long int *nslred);
+SUNDIALS_EXPORT int CVodeGetActualInitStep(void *cvode_mem, realtype *hinused);
+SUNDIALS_EXPORT int CVodeGetLastStep(void *cvode_mem, realtype *hlast);
+SUNDIALS_EXPORT int CVodeGetCurrentStep(void *cvode_mem, realtype *hcur);
+SUNDIALS_EXPORT int CVodeGetCurrentTime(void *cvode_mem, realtype *tcur);
+SUNDIALS_EXPORT int CVodeGetTolScaleFactor(void *cvode_mem, realtype *tolsfac);
+SUNDIALS_EXPORT int CVodeGetErrWeights(void *cvode_mem, N_Vector eweight);
+SUNDIALS_EXPORT int CVodeGetEstLocalErrors(void *cvode_mem, N_Vector ele);
+SUNDIALS_EXPORT int CVodeGetNumGEvals(void *cvode_mem, long int *ngevals);
+SUNDIALS_EXPORT int CVodeGetRootInfo(void *cvode_mem, int *rootsfound);
+
+/*
+ * -----------------------------------------------------------------
+ * As a convenience, the following functions provides the
+ * optional outputs in one group.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int CVodeGetIntegratorStats(void *cvode_mem, long int *nsteps,
+ long int *nfevals, long int *nlinsetups,
+ long int *netfails, int *qlast,
+ int *qcur, realtype *hinused, realtype *hlast,
+ realtype *hcur, realtype *tcur);
+
+/*
+ * -----------------------------------------------------------------
+ * Nonlinear solver optional output extraction functions
+ * -----------------------------------------------------------------
+ * The following functions can be called to get optional outputs
+ * and statistics related to the nonlinear solver.
+ * -----------------------------------------------------------------
+ * CVodeGetNumNonlinSolvIters returns the number of nonlinear
+ * solver iterations performed.
+ * CVodeGetNumNonlinSolvConvFails returns the number of nonlinear
+ * convergence failures.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int CVodeGetNumNonlinSolvIters(void *cvode_mem, long int *nniters);
+SUNDIALS_EXPORT int CVodeGetNumNonlinSolvConvFails(void *cvode_mem, long int *nncfails);
+
+/*
+ * -----------------------------------------------------------------
+ * As a convenience, the following function provides the
+ * nonlinear solver optional outputs in a group.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int CVodeGetNonlinSolvStats(void *cvode_mem, long int *nniters,
+ long int *nncfails);
+
+/*
+ * -----------------------------------------------------------------
+ * The following function returns the name of the constant
+ * associated with a CVODE return flag
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT char *CVodeGetReturnFlagName(long int flag);
+
+/*
+ * -----------------------------------------------------------------
+ * Function : CVodeFree
+ * -----------------------------------------------------------------
+ * CVodeFree frees the problem memory cvode_mem allocated by
+ * CVodeCreate and CVodeInit. Its only argument is the pointer
+ * cvode_mem returned by CVodeCreate.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT void CVodeFree(void **cvode_mem);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/cvode/cvode_band.h b/include/cvode/cvode_band.h
new file mode 100644
index 0000000..7da3be9
--- /dev/null
+++ b/include/cvode/cvode_band.h
@@ -0,0 +1,61 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.6 $
+ * $Date: 2010/12/01 22:10:38 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh and
+ * Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * This is the header file for the CVODE band linear solver, CVBAND.
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _CVBAND_H
+#define _CVBAND_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <cvode/cvode_direct.h>
+#include <sundials/sundials_band.h>
+
+/*
+ * -----------------------------------------------------------------
+ * 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
new file mode 100644
index 0000000..0e15244
--- /dev/null
+++ b/include/cvode/cvode_bandpre.h
@@ -0,0 +1,141 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.6 $
+ * $Date: 2010/12/01 22:10:38 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Alan C. Hindmarsh and Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * 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, CVodeMalloc, 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 = CVodeMalloc(...);
+ * ...
+ * 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.
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _CVBANDPRE_H
+#define _CVBANDPRE_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <sundials/sundials_nvector.h>
+
+
+/*
+ * -----------------------------------------------------------------
+ * 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.
+ * -----------------------------------------------------------------
+ */
+
+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
+ * -----------------------------------------------------------------
+ */
+
+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
+}
+#endif
+
+#endif
diff --git a/include/cvode/cvode_bbdpre.h b/include/cvode/cvode_bbdpre.h
new file mode 100644
index 0000000..d350c87
--- /dev/null
+++ b/include/cvode/cvode_bbdpre.h
@@ -0,0 +1,268 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.8 $
+ * $Date: 2010/12/01 22:10:38 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Michael Wittman, Alan C. Hindmarsh and
+ * Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * 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 = CVodeMalloc(...);
+ * ...
+ * 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.
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _CVBBDPRE_H
+#define _CVBBDPRE_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <sundials/sundials_nvector.h>
+
+/*
+ * -----------------------------------------------------------------
+ * 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.
+ * -----------------------------------------------------------------
+ */
+
+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);
+
+/*
+ * -----------------------------------------------------------------
+ * 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,
+ realtype dqrely,
+ 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,
+ 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
+ * -----------------------------------------------------------------
+ */
+
+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
+}
+#endif
+
+#endif
diff --git a/include/cvode/cvode_dense.h b/include/cvode/cvode_dense.h
new file mode 100644
index 0000000..0a59ec9
--- /dev/null
+++ b/include/cvode/cvode_dense.h
@@ -0,0 +1,54 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.6 $
+ * $Date: 2010/12/01 22:10:38 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh and
+ * Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * This is the header file for the CVODE dense linear solver, CVDENSE.
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _CVDENSE_H
+#define _CVDENSE_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <cvode/cvode_direct.h>
+#include <sundials/sundials_dense.h>
+
+/*
+ * -----------------------------------------------------------------
+ * 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
new file mode 100644
index 0000000..1b4c93d
--- /dev/null
+++ b/include/cvode/cvode_diag.h
@@ -0,0 +1,106 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.4 $
+ * $Date: 2010/12/01 22:10:38 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh and
+ * Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * This is the header file for the CVODE diagonal linear solver, CVDIAG.
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _CVDIAG_H
+#define _CVDIAG_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <sundials/sundials_nvector.h>
+
+/*
+ * -----------------------------------------------------------------
+ * Function : CVDiag
+ * -----------------------------------------------------------------
+ * A call to the CVDiag function links the main integrator with
+ * the CVDIAG linear solver.
+ *
+ * cvode_mem is the pointer to the integrator memory returned by
+ * CVodeCreate.
+ *
+ * The return value of CVDiag is one of:
+ * CVDIAG_SUCCESS if successful
+ * CVDIAG_MEM_NULL if the cvode memory was NULL
+ * CVDIAG_MEM_FAIL if there was a memory allocation failure
+ * CVDIAG_ILL_INPUT if a required vector operation is missing
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int CVDiag(void *cvode_mem);
+
+/*
+ * -----------------------------------------------------------------
+ * Optional outputs from the CVDIAG linear solver
+ * -----------------------------------------------------------------
+ *
+ * CVDiagGetWorkSpace returns the real and integer workspace used
+ * by CVDIAG.
+ * CVDiagGetNumRhsEvals returns the number of calls to the user
+ * f routine due to finite difference Jacobian
+ * evaluation.
+ * Note: The number of diagonal approximate
+ * Jacobians formed is equal to the number of
+ * CVDiagSetup calls. This number is available
+ * through CVodeGetNumLinSolvSetups.
+ * CVDiagGetLastFlag returns the last error flag set by any of
+ * the CVDIAG interface functions.
+ *
+ * The return value of CVDiagGet* is one of:
+ * CVDIAG_SUCCESS if successful
+ * CVDIAG_MEM_NULL if the cvode memory was NULL
+ * CVDIAG_LMEM_NULL if the cvdiag memory was NULL
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int CVDiagGetWorkSpace(void *cvode_mem, long int *lenrwLS, long int *leniwLS);
+SUNDIALS_EXPORT int CVDiagGetNumRhsEvals(void *cvode_mem, long int *nfevalsLS);
+SUNDIALS_EXPORT int CVDiagGetLastFlag(void *cvode_mem, long int *flag);
+
+/*
+ * -----------------------------------------------------------------
+ * The following function returns the name of the constant
+ * associated with a CVDIAG return flag
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT char *CVDiagGetReturnFlagName(long int flag);
+
+/*
+ * -----------------------------------------------------------------
+ * CVDIAG return values
+ * -----------------------------------------------------------------
+ */
+
+#define CVDIAG_SUCCESS 0
+#define CVDIAG_MEM_NULL -1
+#define CVDIAG_LMEM_NULL -2
+#define CVDIAG_ILL_INPUT -3
+#define CVDIAG_MEM_FAIL -4
+
+/* Additional last_flag values */
+
+#define CVDIAG_INV_FAIL -5
+#define CVDIAG_RHSFUNC_UNRECVR -6
+#define CVDIAG_RHSFUNC_RECVR -7
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/cvode/cvode_direct.h b/include/cvode/cvode_direct.h
new file mode 100644
index 0000000..224e5ce
--- /dev/null
+++ b/include/cvode/cvode_direct.h
@@ -0,0 +1,285 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.6 $
+ * $Date: 2010/12/01 22:10:38 $
+ * -----------------------------------------------------------------
+ * Programmer: Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2006, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * Common header file for the direct linear solvers in CVODE.
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _CVDLS_H
+#define _CVDLS_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <sundials/sundials_direct.h>
+#include <sundials/sundials_nvector.h>
+
+/*
+ * =================================================================
+ * C V D I R E C T C O N S T A N T S
+ * =================================================================
+ */
+
+/*
+ * -----------------------------------------------------------------
+ * CVDLS return values
+ * -----------------------------------------------------------------
+ */
+
+#define CVDLS_SUCCESS 0
+#define CVDLS_MEM_NULL -1
+#define CVDLS_LMEM_NULL -2
+#define CVDLS_ILL_INPUT -3
+#define CVDLS_MEM_FAIL -4
+
+/* Additional last_flag values */
+
+#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.
+ *
+ * -----------------------------------------------------------------
+ */
+
+
+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);
+
+/*
+ * =================================================================
+ * 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
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT char *CVDlsGetReturnFlagName(long int flag);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/cvode/cvode_lapack.h b/include/cvode/cvode_lapack.h
new file mode 100644
index 0000000..e0e8d74
--- /dev/null
+++ b/include/cvode/cvode_lapack.h
@@ -0,0 +1,86 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.3 $
+ * $Date: 2006/11/29 00:05:06 $
+ * -----------------------------------------------------------------
+ * Programmer: Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2006, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * Header file for the CVODE dense linear solver CVLAPACK.
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _CVLAPACK_H
+#define _CVLAPACK_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <cvode/cvode_direct.h>
+#include <sundials/sundials_lapack.h>
+
+/*
+ * =================================================================
+ * 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_spbcgs.h b/include/cvode/cvode_spbcgs.h
new file mode 100644
index 0000000..278acf8
--- /dev/null
+++ b/include/cvode/cvode_spbcgs.h
@@ -0,0 +1,67 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.2 $
+ * $Date: 2006/11/29 00:05:06 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Aaron Collier @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2004, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * This is the header file for the CVODE scaled preconditioned
+ * Bi-CGSTAB linear solver, CVSPBCG.
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _CVSPBCG_H
+#define _CVSPBCG_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <cvode/cvode_spils.h>
+#include <sundials/sundials_spbcgs.h>
+
+/*
+ * -----------------------------------------------------------------
+ * 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
new file mode 100644
index 0000000..2b8499c
--- /dev/null
+++ b/include/cvode/cvode_spgmr.h
@@ -0,0 +1,69 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.3 $
+ * $Date: 2006/11/29 00:05:06 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh and
+ * Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * This is the header file for the CVODE scaled preconditioned GMRES
+ * linear solver, CVSPGMR.
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _CVSPGMR_H
+#define _CVSPGMR_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <cvode/cvode_spils.h>
+#include <sundials/sundials_spgmr.h>
+
+/*
+ * -----------------------------------------------------------------
+ * 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
new file mode 100644
index 0000000..531bd0b
--- /dev/null
+++ b/include/cvode/cvode_spils.h
@@ -0,0 +1,365 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.10 $
+ * $Date: 2010/12/01 22:10:38 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh and
+ * Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * This is the common header file for the Scaled, Preconditioned
+ * Iterative Linear Solvers in CVODE.
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _CVSPILS_H
+#define _CVSPILS_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <sundials/sundials_iterative.h>
+#include <sundials/sundials_nvector.h>
+
+
+/*
+ * -----------------------------------------------------------------
+ * CVSPILS return values
+ * -----------------------------------------------------------------
+ */
+
+#define CVSPILS_SUCCESS 0
+#define CVSPILS_MEM_NULL -1
+#define CVSPILS_LMEM_NULL -2
+#define CVSPILS_ILL_INPUT -3
+#define CVSPILS_MEM_FAIL -4
+#define CVSPILS_PMEM_NULL -5
+
+/*
+ * -----------------------------------------------------------------
+ * 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
+ * -----------------------------------------------------------------
+ */
+
+#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).
+ * -----------------------------------------------------------------
+ */
+
+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).
+ * -----------------------------------------------------------------
+ */
+
+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.
+ * -----------------------------------------------------------------
+ */
+
+typedef int (*CVSpilsJacTimesVecFn)(N_Vector v, N_Vector Jv, realtype t,
+ N_Vector y, N_Vector fy,
+ void *user_data, N_Vector tmp);
+
+
+
+/*
+ * -----------------------------------------------------------------
+ * 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 char *CVSpilsGetReturnFlagName(long int flag);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/cvode/cvode_sptfqmr.h b/include/cvode/cvode_sptfqmr.h
new file mode 100644
index 0000000..c19e67b
--- /dev/null
+++ b/include/cvode/cvode_sptfqmr.h
@@ -0,0 +1,67 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.3 $
+ * $Date: 2006/11/29 00:05:06 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Aaron Collier @ 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.
+ * -----------------------------------------------------------------
+ * This is the header file for the CVODE scaled preconditioned TFQMR
+ * linear solver, CVSPTFQMR.
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _CVSPTFQMR_H
+#define _CVSPTFQMR_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <cvode/cvode_spils.h>
+#include <sundials/sundials_sptfqmr.h>
+
+/*
+ * -----------------------------------------------------------------
+ * 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/cvodes/cvodes.h b/include/cvodes/cvodes.h
new file mode 100644
index 0000000..ad067bf
--- /dev/null
+++ b/include/cvodes/cvodes.h
@@ -0,0 +1,1968 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.23 $
+ * $Date: 2010/12/01 22:13:10 $
+ * -----------------------------------------------------------------
+ * Programmer(s): 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.
+ * -----------------------------------------------------------------
+ * This is the interface file for the main CVODES integrator.
+ * -----------------------------------------------------------------
+ *
+ * CVODES is used to solve numerically the ordinary initial value
+ * problem:
+ *
+ * y' = f(t,y),
+ * y(t0) = y0,
+ *
+ * where t0, y0 in R^N, and f: R x R^N -> R^N are given.
+ *
+ * Optionally, CVODES can perform forward or adjoint sensitivity
+ * analysis to find sensitivities of the solution y with respect
+ * to parameters in the right hand side f and/or in the initial
+ * conditions y0.
+ *
+ * -----------------------------------------------------------------
+ *
+ * 1: CONSTANTS
+ * input constants
+ * return flags
+ *
+ * 2: FUNCTION TYPES
+ * CVRhsFn CVQuadRhsFn CVSensRhsFn CVSensRhs1Fn CVQuadSensRhsFn
+ * CVRootFn
+ * CVEwtFn
+ * CVErrHandlerFn
+ * CVRhsFnB CVRhsFnBS
+ * CVQuadRhsFnB CVQuadRhsFnBS
+ *
+ * 3: INITIALIZATION AND DEALLOCATION FUNCTIONS FOR FORWARD PROBLEMS
+ * CVodeCreate
+ * CVodeInit CVodeReInit
+ * CVodeQuadInit CVodeQuadReInit
+ * CVodeSensInit CVodeSensReInit
+ * CVodeRootInit
+ * CVodeFree CVodeQuadFree CVodeSensFree
+ *
+ * 4: OPTIONAL INPUT FUNCTIONS FOR FORWARD PROBLEMS
+ *
+ * 5: MAIN SOLVER FUNCTION FOR FORWARD PROBLEMS
+ * CVode
+ *
+ * 6: EXTRACTION AND DENSE OUTPUT FUNCTIONS FOR FORWARD PROBLEMS
+ * CVodeGetDky
+ * CVodeGetQuad
+ * CVodeGetQuadDky
+ * CVodeGetSens CVodeGetSens1
+ * CVodeGetSensDky CVodeGetSensDky1
+ * CVodeGetQuadSens CVodeGetQuadSens1
+ * CVodeGetQuadSensDky CVodeGetQuadSensDky1
+ *
+ * 7: OPTIONAL OUTPUT FUNCTIONS FOR FORWARD PROBLEMS
+ *
+ * 8: INITIALIZATION AND DEALLOCATION FUNCTIONS FOR BACKWARD PROBLEMS
+ * CVodeAdjInit CVodeAdjReInit
+ * CVodeAdjFree
+ * CVodeInitB CVodeInitBS CVodeReInitB
+ * CVodeQuadInitB CVodeQuadInitBS CVodeQuadReInitB
+ *
+ * 9 MAIN SOLVER FUNCTIONS FOR FORWARD PROBLEMS
+ * CVodeF
+ * CVodeB
+ *
+ * 10: OPTIONAL INPUT FUNCTIONS FOR BACKWARD PROBLEMS
+ *
+ * 11: EXTRACTION AND DENSE OUTPUT FUNCTIONS FOR BACKWARD PROBLEMS
+ * CVodeGetB
+ * CVodeGetQuadB
+ *
+ * 12: OPTIONAL OUTPUT FUNCTIONS FOR BACKWARD PROBLEMS
+ *
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _CVODES_H
+#define _CVODES_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <stdio.h>
+
+#include <sundials/sundials_nvector.h>
+
+/*
+ * =================================================================
+ *
+ * CVODES CONSTANTS
+ *
+ * =================================================================
+ */
+
+/*
+ * -----------------------------------------------------------------
+ * Enumerations for inputs to:
+ * CVodeCreate (lmm, iter),
+ * CVodeSensInit, CvodeSensinit1, CVodeSensReInit (ism),
+ * CVodeAdjInit (interp),
+ * CVode (itask)
+ * -----------------------------------------------------------------
+ * Symbolic constants for the lmm and iter parameters to CVodeCreate
+ * the input parameter itask to CVode, and the input parameter interp
+ * to CVodeAdjInit, are given below.
+ *
+ * lmm: The user of the CVODES package specifies whether to use
+ * the CV_ADAMS or CV_BDF (backward differentiation formula)
+ * linear multistep method. The BDF method is recommended
+ * for stiff problems, and the CV_ADAMS method is recommended
+ * for nonstiff problems.
+ *
+ * iter: At each internal time step, a nonlinear equation must
+ * be solved. The user can specify either CV_FUNCTIONAL
+ * iteration, which does not require linear algebra, or a
+ * CV_NEWTON iteration, which requires the solution of linear
+ * systems. In the CV_NEWTON case, the user also specifies a
+ * CVODE linear solver. CV_NEWTON is recommended in case of
+ * stiff problems.
+ *
+ * ism: This parameter specifies the sensitivity corrector type
+ * to be used. In the CV_SIMULTANEOUS case, the nonlinear
+ * systems for states and all sensitivities are solved
+ * simultaneously. In the CV_STAGGERED case, the nonlinear
+ * system for states is solved first and then, the
+ * nonlinear systems for all sensitivities are solved
+ * at the same time. Finally, in the CV_STAGGERED1 approach
+ * all nonlinear systems are solved in a sequence.
+ *
+ * itask: The itask input parameter to CVode indicates the job
+ * of the solver for the next user step. The CV_NORMAL
+ * itask is to have the solver take internal steps until
+ * it has reached or just passed the user specified tout
+ * parameter. The solver then interpolates in order to
+ * return an approximate value of y(tout). The CV_ONE_STEP
+ * option tells the solver to just take one internal step
+ * and return the solution at the point reached by that step.
+ *
+ * interp: Specifies the interpolation type used to evaluate the
+ * forward solution during the backward integration phase.
+ * CV_HERMITE specifies cubic Hermite interpolation.
+ * CV_POYNOMIAL specifies the polynomial interpolation
+ * -----------------------------------------------------------------
+ */
+
+/* lmm */
+#define CV_ADAMS 1
+#define CV_BDF 2
+
+/* iter */
+#define CV_FUNCTIONAL 1
+#define CV_NEWTON 2
+
+/* itask */
+#define CV_NORMAL 1
+#define CV_ONE_STEP 2
+
+/* ism */
+#define CV_SIMULTANEOUS 1
+#define CV_STAGGERED 2
+#define CV_STAGGERED1 3
+
+/* DQtype */
+#define CV_CENTERED 1
+#define CV_FORWARD 2
+
+/* interp */
+#define CV_HERMITE 1
+#define CV_POLYNOMIAL 2
+
+/*
+ * ----------------------------------------
+ * CVODES return flags
+ * ----------------------------------------
+ */
+
+#define CV_SUCCESS 0
+#define CV_TSTOP_RETURN 1
+#define CV_ROOT_RETURN 2
+
+#define CV_WARNING 99
+
+#define CV_TOO_MUCH_WORK -1
+#define CV_TOO_MUCH_ACC -2
+#define CV_ERR_FAILURE -3
+#define CV_CONV_FAILURE -4
+
+#define CV_LINIT_FAIL -5
+#define CV_LSETUP_FAIL -6
+#define CV_LSOLVE_FAIL -7
+#define CV_RHSFUNC_FAIL -8
+#define CV_FIRST_RHSFUNC_ERR -9
+#define CV_REPTD_RHSFUNC_ERR -10
+#define CV_UNREC_RHSFUNC_ERR -11
+#define CV_RTFUNC_FAIL -12
+
+#define CV_MEM_FAIL -20
+#define CV_MEM_NULL -21
+#define CV_ILL_INPUT -22
+#define CV_NO_MALLOC -23
+#define CV_BAD_K -24
+#define CV_BAD_T -25
+#define CV_BAD_DKY -26
+#define CV_TOO_CLOSE -27
+
+#define CV_NO_QUAD -30
+#define CV_QRHSFUNC_FAIL -31
+#define CV_FIRST_QRHSFUNC_ERR -32
+#define CV_REPTD_QRHSFUNC_ERR -33
+#define CV_UNREC_QRHSFUNC_ERR -34
+
+#define CV_NO_SENS -40
+#define CV_SRHSFUNC_FAIL -41
+#define CV_FIRST_SRHSFUNC_ERR -42
+#define CV_REPTD_SRHSFUNC_ERR -43
+#define CV_UNREC_SRHSFUNC_ERR -44
+
+#define CV_BAD_IS -45
+
+#define CV_NO_QUADSENS -50
+#define CV_QSRHSFUNC_FAIL -51
+#define CV_FIRST_QSRHSFUNC_ERR -52
+#define CV_REPTD_QSRHSFUNC_ERR -53
+#define CV_UNREC_QSRHSFUNC_ERR -54
+
+/*
+ * ----------------------------------------
+ * CVODEA return flags
+ * ----------------------------------------
+ */
+
+#define CV_NO_ADJ -101
+#define CV_NO_FWD -102
+#define CV_NO_BCK -103
+#define CV_BAD_TB0 -104
+#define CV_REIFWD_FAIL -105
+#define CV_FWD_FAIL -106
+#define CV_GETY_BADT -107
+
+/*
+ * =================================================================
+ *
+ * FUNCTION TYPES
+ *
+ * =================================================================
+ */
+
+/*
+ * -----------------------------------------------------------------
+ * Type : CVRhsFn
+ * -----------------------------------------------------------------
+ * The f function which defines the right hand side of the ODE
+ * system y' = f(t,y) must have type CVRhsFn.
+ * f takes as input the independent variable value t, and the
+ * dependent variable vector y. It stores the result of f(t,y)
+ * in the vector ydot. The y and ydot arguments are of type
+ * N_Vector.
+ * (Allocation of memory for ydot is handled within CVODES)
+ * The user_data parameter is the same as the user_data
+ * parameter set by the user through the CVodeSetUserData routine.
+ * This user-supplied pointer is passed to the user's f function
+ * every time it is called.
+ *
+ * A CVRhsFn should return 0 if successful, a negative value if
+ * an unrecoverable error occured, and a positive value if a
+ * recoverable error (e.g. invalid y values) occured.
+ * If an unrecoverable occured, the integration is halted.
+ * If a recoverable error occured, then (in most cases) CVODES
+ * will try to correct and retry.
+ * -----------------------------------------------------------------
+ */
+
+typedef int (*CVRhsFn)(realtype t, N_Vector y,
+ N_Vector ydot, void *user_data);
+
+/*
+ * -----------------------------------------------------------------
+ * Type : CVRootFn
+ * -----------------------------------------------------------------
+ * A function g, which defines a set of functions g_i(t,y) whose
+ * roots are sought during the integration, must have type CVRootFn.
+ * The function g takes as input the independent variable value
+ * t, and the dependent variable vector y. It stores the nrtfn
+ * values g_i(t,y) in the realtype array gout.
+ * (Allocation of memory for gout is handled within CVODE.)
+ * The user_data parameter is the same as that passed by the user
+ * to the CVodeSetUserData routine. This user-supplied pointer is
+ * passed to the user's g function every time it is called.
+ *
+ * A CVRootFn should return 0 if successful or a non-zero value
+ * if an error occured (in which case the integration will be halted).
+ * -----------------------------------------------------------------
+ */
+
+typedef int (*CVRootFn)(realtype t, N_Vector y, realtype *gout, void *user_data);
+
+/*
+ * -----------------------------------------------------------------
+ * Type : CVEwtFn
+ * -----------------------------------------------------------------
+ * A function e, which sets the error weight vector ewt, must have
+ * type CVEwtFn.
+ * The function e takes as input the current dependent variable y.
+ * It must set the vector of error weights used in the WRMS norm:
+ *
+ * ||y||_WRMS = sqrt [ 1/N * sum ( ewt_i * y_i)^2 ]
+ *
+ * Typically, the vector ewt has components:
+ *
+ * ewt_i = 1 / (reltol * |y_i| + abstol_i)
+ *
+ * The user_data parameter is the same as that passed by the user
+ * to the CVodeSetUserData routine. This user-supplied pointer is
+ * passed to the user's e function every time it is called.
+ * A CVEwtFn e must return 0 if the error weight vector has been
+ * successfuly set and a non-zero value otherwise.
+ * -----------------------------------------------------------------
+ */
+
+typedef int (*CVEwtFn)(N_Vector y, N_Vector ewt, void *user_data);
+
+
+/*
+ * -----------------------------------------------------------------
+ * Type : CVErrHandlerFn
+ * -----------------------------------------------------------------
+ * A function eh, which handles error messages, must have type
+ * CVErrHandlerFn.
+ * The function eh takes as input the error code, the name of the
+ * module reporting the error, the error message, and a pointer to
+ * user data, the same as that passed to CVodeSetUserData.
+ *
+ * All error codes are negative, except CV_WARNING which indicates
+ * a warning (the solver continues).
+ *
+ * A CVErrHandlerFn has no return value.
+ * -----------------------------------------------------------------
+ */
+
+typedef void (*CVErrHandlerFn)(int error_code,
+ const char *module, const char *function,
+ char *msg, void *user_data);
+
+/*
+ * -----------------------------------------------------------------
+ * Type : CVQuadRhsFn
+ * -----------------------------------------------------------------
+ * The fQ function which defines the right hand side of the
+ * quadrature equations yQ' = fQ(t,y) must have type CVQuadRhsFn.
+ * fQ takes as input the value of the independent variable t,
+ * the vector of states y and must store the result of fQ in
+ * yQdot. (Allocation of memory for yQdot is handled by CVODES).
+ * The user_data parameter is the same as the user_data parameter
+ * set by the user through the CVodeSetUserData routine and is
+ * passed to the fQ function every time it is called.
+ *
+ * If the quadrature RHS also depends on the sensitivity variables,
+ * i.e., yQ' = fQs(t,y,yS), then fQ must be of type CVodeQuadRhsFnS.
+ *
+ * A CVQuadRhsFn or CVodeQuadRhsFnS should return 0 if successful,
+ * a negative value if an unrecoverable error occured, and a positive
+ * value if a recoverable error (e.g. invalid y values) occured.
+ * If an unrecoverable occured, the integration is halted.
+ * If a recoverable error occured, then (in most cases) CVODES
+ * will try to correct and retry.
+ * -----------------------------------------------------------------
+ */
+
+typedef int (*CVQuadRhsFn)(realtype t, N_Vector y,
+ N_Vector yQdot,
+ void *user_data);
+
+/*
+ * -----------------------------------------------------------------
+ * Type : CVSensRhsFn
+ * -----------------------------------------------------------------
+ * The fS function which defines the right hand side of the
+ * sensitivity ODE systems s' = f_y * s + f_p must have type
+ * CVSensRhsFn.
+ * fS takes as input the number of sensitivities Ns, the
+ * independent variable value t, the states y and the
+ * corresponding value of f(t,y) in ydot, and the dependent
+ * sensitivity vectors yS. It stores the result of fS in ySdot.
+ * (Allocation of memory for ySdot is handled within CVODES)
+ * The user_data parameter is the same as the user_data parameter
+ * set by the user through the CVodeSetUserData routine and is
+ * passed to the fS function every time it is called.
+ *
+ * A CVSensRhsFn should return 0 if successful, a negative value if
+ * an unrecoverable error occured, and a positive value if a
+ * recoverable error (e.g. invalid y or yS values) occured.
+ * If an unrecoverable occured, the integration is halted.
+ * If a recoverable error occured, then (in most cases) CVODES
+ * will try to correct and retry.
+ * -----------------------------------------------------------------
+ */
+
+typedef int (*CVSensRhsFn)(int Ns, realtype t,
+ N_Vector y, N_Vector ydot,
+ N_Vector *yS, N_Vector *ySdot,
+ void *user_data,
+ N_Vector tmp1, N_Vector tmp2);
+
+/*
+ * -----------------------------------------------------------------
+ * Type : CVSensRhs1Fn
+ * -----------------------------------------------------------------
+ * The fS1 function which defines the right hand side of the i-th
+ * sensitivity ODE system s_i' = f_y * s_i + f_p must have type
+ * CVSensRhs1Fn.
+ * fS1 takes as input the number of sensitivities Ns, the current
+ * sensitivity iS, the independent variable value t, the states y
+ * and the corresponding value of f(t,y) in ydot, and the
+ * dependent sensitivity vector yS. It stores the result of fS in
+ * ySdot.
+ * (Allocation of memory for ySdot is handled within CVODES)
+ * The user_data parameter is the same as the user_data parameter
+ * set by the user through the CVodeSetUserData routine and is
+ * passed to the fS1 function every time it is called.
+ *
+ * A CVSensRhs1Fn should return 0 if successful, a negative value if
+ * an unrecoverable error occured, and a positive value if a
+ * recoverable error (e.g. invalid y or yS values) occured.
+ * If an unrecoverable occured, the integration is halted.
+ * If a recoverable error occured, then (in most cases) CVODES
+ * will try to correct and retry.
+ * -----------------------------------------------------------------
+ */
+
+typedef int (*CVSensRhs1Fn)(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);
+
+/*
+ * -----------------------------------------------------------------
+ * Type : CVQuadSensRhsFn
+ * -----------------------------------------------------------------
+ * The fQS function which defines the right hand side of the
+ * sensitivity ODE systems for quadratures, yQS' = fQ_y * yS + fQ_p
+ * must have type CVQuadSensRhsFn.
+ *
+ * fQS takes as input the number of sensitivities Ns (the same as
+ * that passed to CVodeQuadSensInit), the independent variable
+ * value t, the states y and the dependent sensitivity vectors yS,
+ * as well as the current value of the quadrature RHS yQdot.
+ * It stores the result of fQS in yQSdot.
+ * (Allocation of memory for yQSdot is handled within CVODES)
+ *
+ * A CVQuadSensRhsFn should return 0 if successful, a negative
+ * value if an unrecoverable error occured, and a positive value
+ * if a recoverable error (e.g. invalid y or yS values) occured.
+ * If an unrecoverable occured, the integration is halted.
+ * If a recoverable error occured, then (in most cases) CVODES
+ * will try to correct and retry.
+ * -----------------------------------------------------------------
+ */
+
+typedef int (*CVQuadSensRhsFn)(int Ns, realtype t,
+ N_Vector y, N_Vector *yS,
+ N_Vector yQdot, N_Vector *yQSdot,
+ void *user_data,
+ N_Vector tmp, N_Vector tmpQ);
+
+/*
+ * -----------------------------------------------------------------
+ * CVRhsFnB and CVRhsFnBS
+ * The fB function which defines the right hand side of the
+ * ODE systems to be integrated backwards must have type CVRhsFnB.
+ * If the backward problem depends on forward sensitivities, its
+ * RHS function must have type CVRhsFnBS.
+ * -----------------------------------------------------------------
+ * CVQuadRhsFnB and CVQuadRhsFnBS
+ * The fQB function which defines the quadratures to be integrated
+ * backwards must have type CVQuadRhsFnB.
+ * If the backward problem depends on forward sensitivities, its
+ * quadrature RHS function must have type CVQuadRhsFnBS.
+ * -----------------------------------------------------------------
+ */
+
+typedef int (*CVRhsFnB)(realtype t, N_Vector y,
+ N_Vector yB, N_Vector yBdot,
+ void *user_dataB);
+
+typedef int (*CVRhsFnBS)(realtype t, N_Vector y, N_Vector *yS,
+ N_Vector yB, N_Vector yBdot,
+ void *user_dataB);
+
+
+typedef int (*CVQuadRhsFnB)(realtype t, N_Vector y,
+ N_Vector yB, N_Vector qBdot,
+ void *user_dataB);
+
+typedef int (*CVQuadRhsFnBS)(realtype t, N_Vector y, N_Vector *yS,
+ N_Vector yB, N_Vector qBdot,
+ void *user_dataB);
+
+
+/*
+ * =================================================================
+ *
+ * INITIALIZATION AND DEALLOCATION FUNCTIONS FOR FORWARD PROBLEMS
+ *
+ * =================================================================
+ */
+
+/*
+ * -----------------------------------------------------------------
+ * Function : CVodeCreate
+ * -----------------------------------------------------------------
+ * CVodeCreate creates an internal memory block for a problem to
+ * be solved by CVODES.
+ *
+ * lmm is the type of linear multistep method to be used.
+ * The legal values are CV_ADAMS and CV_BDF (see previous
+ * description).
+ *
+ * iter is the type of iteration used to solve the nonlinear
+ * system that arises during each internal time step.
+ * The legal values are CV_FUNCTIONAL and CV_NEWTON.
+ *
+ * If successful, CVodeCreate returns a pointer to initialized
+ * problem memory. This pointer should be passed to CVodeInit.
+ * If an initialization error occurs, CVodeCreate prints an error
+ * message to standard err and returns NULL.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT void *CVodeCreate(int lmm, int iter);
+
+/*
+ * -----------------------------------------------------------------
+ * Functions : CVodeInit and CVodeReInit
+ * -----------------------------------------------------------------
+ * CVodeInit allocates and initializes memory for a problem to
+ * to be solved by CVODE.
+ *
+ * CVodeReInit re-initializes CVode for the solution of a problem,
+ * where a prior call to CVodeInit has been made with the same
+ * problem size N. CVodeReInit performs the same input checking
+ * and initializations that CVodeInit does.
+ * But it does no memory allocation, assuming that the existing
+ * internal memory is sufficient for the new problem.
+ *
+ * The use of CVodeReInit requires that the maximum method order,
+ * maxord, is no larger for the new problem than for the problem
+ * specified in the last call to CVodeInit. This condition is
+ * automatically fulfilled if the multistep method parameter lmm
+ * is unchanged (or changed from CV_ADAMS to CV_BDF) and the default
+ * value for maxord is specified.
+ *
+ * cvode_mem is pointer to CVODE memory returned by CVodeCreate.
+ *
+ * f is the name of the C function defining the right-hand
+ * side function in y' = f(t,y).
+ *
+ * t0 is the initial value of t.
+ *
+ * y0 is the initial condition vector y(t0).
+ *
+ * Return flag:
+ * CV_SUCCESS if successful
+ * CV_MEM_NULL if the cvode memory was NULL
+ * CV_MEM_FAIL if a memory allocation failed
+ * CV_NO_MALLOC if cvode_mem has not been allocated
+ * (i.e., CVodeInit has not been called).
+ * CV_ILL_INPUT if an argument has an illegal value.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int CVodeInit(void *cvode_mem, CVRhsFn f, realtype t0, N_Vector y0);
+SUNDIALS_EXPORT int CVodeReInit(void *cvode_mem, realtype t0, N_Vector y0);
+
+/*
+ * -----------------------------------------------------------------
+ * Functions : CVodeSStolerances
+ * CVodeSVtolerances
+ * CVodeWFtolerances
+ * -----------------------------------------------------------------
+ *
+ * These functions specify the integration tolerances. One of them
+ * MUST be called before the first call to CVode.
+ *
+ * CVodeSStolerances specifies scalar relative and absolute tolerances.
+ * CVodeSVtolerances specifies scalar relative tolerance and a vector
+ * absolute tolerance (a potentially different absolute tolerance
+ * for each vector component).
+ * CVodeWFtolerances specifies a user-provides function (of type CVEwtFn)
+ * which will be called to set the error weight vector.
+ *
+ * The tolerances reltol and abstol define a vector of error weights,
+ * ewt, with components
+ * ewt[i] = 1/(reltol*abs(y[i]) + abstol) (in the SS case), or
+ * ewt[i] = 1/(reltol*abs(y[i]) + abstol[i]) (in the SV case).
+ * This vector is used in all error and convergence tests, which
+ * use a weighted RMS norm on all error-like vectors v:
+ * WRMSnorm(v) = sqrt( (1/N) sum(i=1..N) (v[i]*ewt[i])^2 ),
+ * where N is the problem dimension.
+ *
+ * The return value of these functions is equal to CV_SUCCESS = 0 if
+ * there were no errors; otherwise it is a negative int equal to:
+ * CV_MEM_NULL indicating cvode_mem was NULL (i.e.,
+ * CVodeCreate has not been called).
+ * CV_NO_MALLOC indicating that cvode_mem has not been
+ * allocated (i.e., CVodeInit has not been
+ * called).
+ * CV_ILL_INPUT indicating an input argument was illegal
+ * (e.g. a negative tolerance)
+ * In case of an error return, an error message is also printed.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int CVodeSStolerances(void *cvode_mem, realtype reltol, realtype abstol);
+SUNDIALS_EXPORT int CVodeSVtolerances(void *cvode_mem, realtype reltol, N_Vector abstol);
+SUNDIALS_EXPORT int CVodeWFtolerances(void *cvode_mem, CVEwtFn efun);
+
+/*
+ * -----------------------------------------------------------------
+ * Function : CVodeQuadInit and CVodeQuadReInit
+ * -----------------------------------------------------------------
+ * CVodeQuadInit allocates and initializes memory related to
+ * quadrature integration.
+ *
+ * CVodeQuadReInit re-initializes CVODES's quadrature related
+ * memory for a problem, assuming it has already been allocated
+ * in prior calls to CVodeInit and CVodeQuadInit.
+ * The number of quadratures Nq is assumed to be unchanged
+ * since the previous call to CVodeQuadInit.
+ *
+ * cvode_mem is a pointer to CVODES memory returned by CVodeCreate
+ *
+ * fQ is the user-provided integrand routine.
+ *
+ * yQ0 is an N_Vector with initial values for quadratures
+ * (typically yQ0 has all zero components).
+ *
+ * Return values:
+ * CV_SUCCESS if successful
+ * CV_MEM_NULL if the cvode memory was NULL
+ * CV_MEM_FAIL if a memory allocation failed
+ * CV_NO_QUAD if quadratures were not initialized
+ * (i.e. CVodeQuadInit has not been called)
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int CVodeQuadInit(void *cvode_mem, CVQuadRhsFn fQ, N_Vector yQ0);
+SUNDIALS_EXPORT int CVodeQuadReInit(void *cvode_mem, N_Vector yQ0);
+
+/*
+ * -----------------------------------------------------------------
+ * Functions : CVodeQuadSStolerances
+ * CVodeQuadSVtolerances
+ * -----------------------------------------------------------------
+ *
+ * These functions specify the integration tolerances for quadrature
+ * variables. One of them MUST be called before the first call to
+ * CVode IF error control on the quadrature variables is enabled
+ * (see CVodeSetQuadErrCon).
+ *
+ * CVodeSStolerances specifies scalar relative and absolute tolerances.
+ * CVodeSVtolerances specifies scalar relative tolerance and a vector
+ * absolute tolerance (a potentially different absolute tolerance
+ * for each vector component).
+ *
+ * Return values:
+ * CV_SUCCESS if successful
+ * CV_MEM_NULL if the cvode memory was NULL
+ * CV_NO_QUAD if quadratures were not initialized
+ * CV_ILL_INPUT if an input argument was illegal
+ * (e.g. a negative tolerance)
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int CVodeQuadSStolerances(void *cvode_mem, realtype reltolQ, realtype abstolQ);
+SUNDIALS_EXPORT int CVodeQuadSVtolerances(void *cvode_mem, realtype reltolQ, N_Vector abstolQ);
+
+/*
+ * -----------------------------------------------------------------
+ * Function : CVodeSensInit, CVSensInit1, and CVodeSensReInit
+ * -----------------------------------------------------------------
+ * CVodeSensInit and CVSensInit1 allocate and initialize memory
+ * related to sensitivity computations. They only differ in the
+ * type of the sensitivity RHS function: CVodeSensInit specifies
+ * fS of type CVSensRhsFn (i.e. a function that evaluates all
+ * sensitivity RHS simultaneously), while CVodeSensInit1 specifies
+ * fS of type CVSensRhs1Fn (i.e. a function that evaluates one
+ * sensitivity RHS at a time). Recall that ism=CV_STAGGERED1 is
+ * compatible ONLY with a CVSensRhs1Fn. As such, this value for
+ * ism cannot be passed to CVodeSensInit.
+ *
+ * CVodeSensReInit re-initializes CVODES's sensitivity related
+ * memory for a problem, assuming it has already been allocated
+ * in prior calls to CVodeInit and CVodeSensInit.
+ * The number of sensitivities Ns is assumed to be unchanged
+ * since the previous call to CVodeSensInit.
+ * If any error occurs during initialization, it is reported to
+ * the file whose file pointer is errfp.
+ * CVodeSensReInit potentially does some minimal memory allocation
+ * (for the sensitivity absolute tolerance and for arrays of
+ * counters used by the CV_STAGGERED1 method).
+
+ * cvode_mem is pointer to CVODES memory returned by CVodeCreate
+ *
+ * Ns is the number of sensitivities to be computed.
+ *
+ * ism is the type of corrector used in sensitivity
+ * analysis. The legal values are: CV_SIMULTANEOUS,
+ * CV_STAGGERED, and CV_STAGGERED1.
+ *
+ * fS is the sensitivity righ-hand side function
+ * (pass NULL to use the internal DQ approximation)
+ *
+ * yS0 is the array of initial condition vectors for
+ * sensitivity variables.
+ *
+ * Return values:
+ * CV_SUCCESS
+ * CV_MEM_NULL
+ * CV_ILL_INPUT
+ * CV_MEM_FAIL
+ * CV_NO_SENS
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int CVodeSensInit(void *cvode_mem, int Ns, int ism,
+ CVSensRhsFn fS, N_Vector *yS0);
+SUNDIALS_EXPORT int CVodeSensInit1(void *cvode_mem, int Ns, int ism,
+ CVSensRhs1Fn fS1, N_Vector *yS0);
+SUNDIALS_EXPORT int CVodeSensReInit(void *cvode_mem, int ism, N_Vector *yS0);
+
+/*
+ * -----------------------------------------------------------------
+ * Functions : CVodeSensSStolerances
+ * CVodeSensSVtolerances
+ * CVodeSensEEtolerances
+ * -----------------------------------------------------------------
+ *
+ * These functions specify the integration tolerances for sensitivity
+ * variables. One of them MUST be called before the first call to CVode.
+ *
+ * CVodeSensSStolerances specifies scalar relative and absolute tolerances.
+ * CVodeSensSVtolerances specifies scalar relative tolerance and a vector
+ * absolute tolerance for each sensitivity vector (a potentially different
+ * absolute tolerance for each vector component).
+ * CVodeSensEEtolerances specifies that tolerances for sensitivity variables
+ * should be estimated from those provided for the state variables.
+ *
+ * The return value is equal to CV_SUCCESS = 0 if there were no
+ * errors; otherwise it is a negative int equal to:
+ * CV_MEM_NULL indicating cvode_mem was NULL, or
+ * CV_NO_SENS indicating there was not a prior call to
+ * CVodeSensInit.
+ * CV_ILL_INPUT indicating an input argument was illegal
+ * (e.g. negative tolerances)
+ * In case of an error return, an error message is also printed.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int CVodeSensSStolerances(void *cvode_mem, realtype reltolS, realtype *abstolS);
+SUNDIALS_EXPORT int CVodeSensSVtolerances(void *cvode_mem, realtype reltolS, N_Vector *abstolS);
+SUNDIALS_EXPORT int CVodeSensEEtolerances(void *cvode_mem);
+
+/*
+ * -----------------------------------------------------------------
+ * Function : CVodeQuadSensInit and CVodeQuadSensReInit
+ * -----------------------------------------------------------------
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int CVodeQuadSensInit(void *cvode_mem, CVQuadSensRhsFn fQS, N_Vector *yQS0);
+SUNDIALS_EXPORT int CVodeQuadSensReInit(void *cvode_mem, N_Vector *yQS0);
+
+/*
+ * -----------------------------------------------------------------
+ * Functions : CVodeQuadSensSStolerances
+ * CVodeQuadSensSVtolerances
+ * CVodeQuadSensEEtolerances
+ * -----------------------------------------------------------------
+ *
+ * These functions specify the integration tolerances for quadrature
+ * sensitivity variables. One of them MUST be called before the first
+ * call to CVode IF these variables are included in the error test.
+ *
+ * CVodeQuadSensSStolerances specifies scalar relative and absolute tolerances.
+ * CVodeQuadSensSVtolerances specifies scalar relative tolerance and a vector
+ * absolute tolerance for each quadrature sensitivity vector (a potentially
+ * different absolute tolerance for each vector component).
+ * CVodeQuadSensEEtolerances specifies that tolerances for sensitivity variables
+ * should be estimated from those provided for the quadrature variables.
+ * In this case, tolerances for the quadrature variables must be
+ * specified through a call to one of CVodeQuad**tolerances.
+ *
+ * The return value is equal to CV_SUCCESS = 0 if there were no
+ * errors; otherwise it is a negative int equal to:
+ * CV_MEM_NULL if cvode_mem was NULL, or
+ * CV_NO_QuadSENS if there was not a prior call to
+ * CVodeQuadSensInit.
+ * CV_ILL_INPUT if an input argument was illegal
+ * (e.g. negative tolerances)
+ * In case of an error return, an error message is also printed.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int CVodeQuadSensSStolerances(void *cvode_mem, realtype reltolQS, realtype *abstolQS);
+SUNDIALS_EXPORT int CVodeQuadSensSVtolerances(void *cvode_mem, realtype reltolQS, N_Vector *abstolQS);
+SUNDIALS_EXPORT int CVodeQuadSensEEtolerances(void *cvode_mem);
+
+/*
+ * -----------------------------------------------------------------
+ * Function : CVodeRootInit
+ * -----------------------------------------------------------------
+ * CVodeRootInit initializes a rootfinding problem to be solved
+ * during the integration of the ODE system. It must be called
+ * after CVodeCreate, and before CVode. The arguments are:
+ *
+ * cvode_mem = pointer to CVODE memory returned by CVodeCreate.
+ *
+ * nrtfn = number of functions g_i, an int >= 0.
+ *
+ * g = name of user-supplied function, of type CVRootFn,
+ * defining the functions g_i whose roots are sought.
+ *
+ * If a new problem is to be solved with a call to CVodeReInit,
+ * where the new problem has no root functions but the prior one
+ * did, then call CVodeRootInit with nrtfn = 0.
+ *
+ * The return value of CVodeRootInit is CV_SUCCESS = 0 if there were
+ * no errors; otherwise it is a negative int equal to:
+ * CV_MEM_NULL indicating cvode_mem was NULL, or
+ * CV_MEM_FAIL indicating a memory allocation failed.
+ * (including an attempt to increase maxord).
+ * CV_ILL_INPUT indicating nrtfn > 0 but g = NULL.
+ * In case of an error return, an error message is also printed.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int CVodeRootInit(void *cvode_mem, int nrtfn, CVRootFn g);
+
+/*
+ * -----------------------------------------------------------------
+ * Function : CVodeFree
+ * -----------------------------------------------------------------
+ * CVodeFree frees the problem memory cvode_mem allocated by
+ * CVodeInit. Its only argument is the pointer cvode_mem
+ * returned by CVodeCreate.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT void CVodeFree(void **cvode_mem);
+
+/*
+ * -----------------------------------------------------------------
+ * Function : CVodeQuadFree
+ * -----------------------------------------------------------------
+ * CVodeQuadFree frees the problem memory in cvode_mem allocated
+ * for quadrature integration. Its only argument is the pointer
+ * cvode_mem returned by CVodeCreate.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT void CVodeQuadFree(void *cvode_mem);
+
+/*
+ * -----------------------------------------------------------------
+ * Function : CVodeSensFree
+ * -----------------------------------------------------------------
+ * CVodeSensFree frees the problem memory in cvode_mem allocated
+ * for sensitivity analysis. Its only argument is the pointer
+ * cvode_mem returned by CVodeCreate.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT void CVodeSensFree(void *cvode_mem);
+
+/*
+ * -----------------------------------------------------------------
+ * Function : CVodeQuadSensFree
+ * -----------------------------------------------------------------
+ * CVodeQuadSensFree frees the problem memory in cvode_mem allocated
+ * for quadrature sensitivity analysis. Its only argument is the
+ * pointer cvode_mem returned by CVodeCreate.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT void CVodeQuadSensFree(void *cvode_mem);
+
+/*
+ * =================================================================
+ *
+ * OPTIONAL INPUT FUNCTIONS FOR FORWARD PROBLEMS
+ *
+ * =================================================================
+ */
+
+/*
+ * -----------------------------------------------------------------
+ * Integrator optional input specification functions
+ * -----------------------------------------------------------------
+ * The following functions can be called to set optional inputs
+ * to values other than the defaults given below:
+ *
+ * Function | Optional input / [ default value ]
+ * -----------------------------------------------------------------
+ * |
+ * CVodeSetErrHandlerFn | user-provided ErrHandler function.
+ * | [internal]
+ * |
+ * CVodeSetErrFile | the file pointer for an error file
+ * | where all CVODE warning and error
+ * | messages will be written if the default
+ * | internal error handling function is used.
+ * | This parameter can be stdout (standard
+ * | output), stderr (standard error), or a
+ * | file pointer (corresponding to a user
+ * | error file opened for writing) returned
+ * | by fopen.
+ * | If not called, then all messages will
+ * | be written to the standard error stream.
+ * | [stderr]
+ * |
+ * CVodeSetUserData | a pointer to user data that will be
+ * | passed to the user's f function every
+ * | time f is called.
+ * | [NULL]
+ * |
+ * CVodeSetMaxOrd | maximum lmm order to be used by the
+ * | solver.
+ * | [12 for Adams , 5 for BDF]
+ * |
+ * CVodeSetMaxNumSteps | maximum number of internal steps to be
+ * | taken by the solver in its attempt to
+ * | reach tout.
+ * | [500]
+ * |
+ * CVodeSetMaxHnilWarns | maximum number of warning messages
+ * | issued by the solver that t+h==t on the
+ * | next internal step. A value of -1 means
+ * | no such messages are issued.
+ * | [10]
+ * |
+ * CVodeSetStabLimDet | flag to turn on/off stability limit
+ * | detection (TRUE = on, FALSE = 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]
+ * |
+ * CVodeSetInitStep | initial step size.
+ * | [estimated by CVODES]
+ * |
+ * CVodeSetMinStep | minimum absolute value of step size
+ * | allowed.
+ * | [0.0]
+ * |
+ * CVodeSetMaxStep | maximum absolute value of step size
+ * | allowed.
+ * | [infinity]
+ * |
+ * CVodeSetStopTime | the independent variable value past
+ * | which the solution is not to proceed.
+ * | [infinity]
+ * |
+ * CVodeSetMaxErrTestFails | Maximum number of error test failures
+ * | in attempting one step.
+ * | [7]
+ * |
+ * CVodeSetMaxNonlinIters | Maximum number of nonlinear solver
+ * | iterations at one solution.
+ * | [3]
+ * |
+ * CVodeSetMaxConvFails | Maximum number of allowable conv.
+ * | failures in attempting one step.
+ * | [10]
+ * |
+ * CVodeSetNonlinConvCoef | Coeficient in the nonlinear conv.
+ * | test.
+ * | [0.1]
+ * |
+ * -----------------------------------------------------------------
+ * |
+ * CVodeSetIterType | Changes the current nonlinear iteration
+ * | type.
+ * | [set by CVodecreate]
+ * |
+ * -----------------------------------------------------------------
+ * |
+ * CVodeSetRootDirection | Specifies the direction of zero
+ * | crossings to be monitored
+ * | [both directions]
+ * |
+ * CVodeSetNoInactiveRootWarn | disable warning about possible
+ * | g==0 at beginning of integration
+ * |
+ * -----------------------------------------------------------------
+ * Return flag:
+ * CV_SUCCESS if successful
+ * CV_MEM_NULL if the cvode memory is NULL
+ * CV_ILL_INPUT if an argument has an illegal value
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int CVodeSetErrHandlerFn(void *cvode_mem, CVErrHandlerFn ehfun, void *eh_data);
+SUNDIALS_EXPORT int CVodeSetErrFile(void *cvode_mem, FILE *errfp);
+SUNDIALS_EXPORT int CVodeSetUserData(void *cvode_mem, void *user_data);
+SUNDIALS_EXPORT int CVodeSetMaxOrd(void *cvode_mem, int maxord);
+SUNDIALS_EXPORT int CVodeSetMaxNumSteps(void *cvode_mem, long int mxsteps);
+SUNDIALS_EXPORT int CVodeSetMaxHnilWarns(void *cvode_mem, int mxhnil);
+SUNDIALS_EXPORT int CVodeSetStabLimDet(void *cvode_mem, booleantype stldet);
+SUNDIALS_EXPORT int CVodeSetInitStep(void *cvode_mem, realtype hin);
+SUNDIALS_EXPORT int CVodeSetMinStep(void *cvode_mem, realtype hmin);
+SUNDIALS_EXPORT int CVodeSetMaxStep(void *cvode_mem, realtype hmax);
+SUNDIALS_EXPORT int CVodeSetStopTime(void *cvode_mem, realtype tstop);
+SUNDIALS_EXPORT int CVodeSetMaxErrTestFails(void *cvode_mem, int maxnef);
+SUNDIALS_EXPORT int CVodeSetMaxNonlinIters(void *cvode_mem, int maxcor);
+SUNDIALS_EXPORT int CVodeSetMaxConvFails(void *cvode_mem, int maxncf);
+SUNDIALS_EXPORT int CVodeSetNonlinConvCoef(void *cvode_mem, realtype nlscoef);
+
+SUNDIALS_EXPORT int CVodeSetIterType(void *cvode_mem, int iter);
+
+SUNDIALS_EXPORT int CVodeSetRootDirection(void *cvode_mem, int *rootdir);
+SUNDIALS_EXPORT int CVodeSetNoInactiveRootWarn(void *cvode_mem);
+
+
+/*
+ * -----------------------------------------------------------------
+ * Quadrature optional input specification functions
+ * -----------------------------------------------------------------
+ * The following functions can be called to set optional inputs
+ * to values other than the defaults given below:
+ *
+ * Function | Optional input / [ default value ]
+ * --------------------------------------------------------------
+ * |
+ * CVodeSetQuadErrCon | are quadrature variables considered in
+ * | the error control?
+ * | If yes, tolerances for quadrature are
+ * | required (see CVodeQuad**tolerances)
+ * | [errconQ = FALSE]
+ * |
+ * -----------------------------------------------------------------
+ * If successful, these functions return CV_SUCCESS. If an argument
+ * has an illegal value, they return one of the error flags
+ * defined for the CVodeSet* routines.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int CVodeSetQuadErrCon(void *cvode_mem, booleantype errconQ);
+
+/*
+ * -----------------------------------------------------------------
+ * Forward sensitivity optional input specification functions
+ * -----------------------------------------------------------------
+ * The following functions can be called to set optional inputs
+ * to other values than the defaults given below:
+ *
+ * Function | Optional input / [ default value ]
+ * -----------------------------------------------------------------
+ * |
+ * CVodeSetSensDQMethod | controls the selection of finite
+ * | difference schemes used in evaluating
+ * | the sensitivity right hand sides:
+ * | (centered vs. forward and
+ * | simultaneous vs. separate)
+ * | [DQtype=CV_CENTERED]
+ * | [DQrhomax=0.0]
+ * |
+ * CVodeSetSensParams | parameter information:
+ * | p: pointer to problem parameters
+ * | plist: list of parameters with respect
+ * | to which sensitivities are to be
+ * | computed.
+ * | pbar: order of magnitude info.
+ * | Typically, if p[plist[i]] is nonzero,
+ * | pbar[i]=p[plist[i]].
+ * | [p=NULL]
+ * | [plist=NULL]
+ * | [pbar=NULL]
+ * |
+ * CVodeSetSensErrCon | are sensitivity variables considered in
+ * | the error control?
+ * | [FALSE]
+ * |
+ * CVodeSetSensMaxNonlinIters | Maximum number of nonlinear solver
+ * | iterations at one solution.
+ * | [3]
+ * |
+ * -----------------------------------------------------------------
+ * The return values are the same as for CVodeSet*
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int CVodeSetSensDQMethod(void *cvode_mem, int DQtype, realtype DQrhomax);
+SUNDIALS_EXPORT int CVodeSetSensErrCon(void *cvode_mem, booleantype errconS);
+SUNDIALS_EXPORT int CVodeSetSensMaxNonlinIters(void *cvode_mem, int maxcorS);
+SUNDIALS_EXPORT int CVodeSetSensParams(void *cvode_mem, realtype *p, realtype *pbar, int *plist);
+
+/*
+ * -----------------------------------------------------------------
+ * Quadrature sensitivity optional input specification functions
+ * -----------------------------------------------------------------
+ * The following functions can be called to set optional inputs
+ * to values other than the defaults given below:
+ *
+ * Function | Optional input / [ default value ]
+ * --------------------------------------------------------------
+ * |
+ * CVodeSetQuadSensErrCon | are quadrature sensitivity variables
+ * | considered in the error control?
+ * | If yes, tolerances for quadrature
+ * | sensitivity variables are required.
+ * | [errconQS = FALSE]
+ * |
+ * -----------------------------------------------------------------
+ * If successful, these functions return CV_SUCCESS. If an argument
+ * has an illegal value, they return one of the error flags
+ * defined for the CVodeSet* routines.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int CVodeSetQuadSensErrCon(void *cvode_mem, booleantype errconQS);
+
+/*
+ * -----------------------------------------------------------------
+ * Function : CVodeSensToggleOff
+ * -----------------------------------------------------------------
+ * CVodeSensToggleOff deactivates sensitivity calculations.
+ * It does NOT deallocate sensitivity-related memory so that
+ * sensitivity computations can be later toggled ON (through
+ * CVodeSensReInit).
+ *
+ * The return value is equal to CV_SUCCESS = 0 if there were no
+ * errors or CV_MEM_NULL if cvode_mem was NULL
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int CVodeSensToggleOff(void *cvode_mem);
+
+
+/*
+ * =================================================================
+ *
+ * MAIN SOLVER FUNCTION FOR FORWARD PROBLEMS
+ *
+ * =================================================================
+ */
+
+/*
+ * -----------------------------------------------------------------
+ * Function : CVode
+ * -----------------------------------------------------------------
+ * CVode integrates the ODE over an interval in t.
+ * If itask is CV_NORMAL, then the solver integrates from its
+ * current internal t value to a point at or beyond tout, then
+ * interpolates to t = tout and returns y(tout) in the user-
+ * allocated vector yout. If itask is CV_ONE_STEP, then the solver
+ * takes one internal time step and returns in yout the value of
+ * y at the new internal time. In this case, tout is used only
+ * during the first call to CVode to determine the direction of
+ * integration and the rough scale of the problem. If tstop is
+ * enabled (through a call to CVodeSetStopTime), then CVode returns
+ * the solution at tstop. Once the integrator returns at a tstop
+ * time, any future testing for tstop is disabled (and can be
+ * reenabled only though a new call to CVodeSetStopTime).
+ * The time reached by the solver is placed in (*tret). The
+ * user is responsible for allocating the memory for this value.
+ *
+ * cvode_mem is the pointer to CVODES memory returned by
+ * CVodeCreate.
+ *
+ * tout is the next time at which a computed solution is desired.
+ *
+ * yout is the computed solution vector. In CV_NORMAL mode with no
+ * errors and no roots found, yout=y(tout).
+ *
+ * tret is a pointer to a real location. CVode sets (*tret) to
+ * the time reached by the solver and returns yout=y(*tret).
+ *
+ * itask is CV_NORMAL or CV_ONE_STEP. These two modes are described above.
+ *
+ * Here is a brief description of each return value:
+ *
+ * CV_SUCCESS: CVode succeeded and no roots were found.
+ *
+ * CV_ROOT_RETURN: CVode succeeded, and found one or more roots.
+ * If nrtfn > 1, call CVodeGetRootInfo to see
+ * which g_i were found to have a root at (*tret).
+ *
+ * CV_TSTOP_RETURN: CVode succeded and returned at tstop.
+ *
+ * CV_MEM_NULL: The cvode_mem argument was NULL.
+ *
+ * CV_NO_MALLOC: cvode_mem was not allocated.
+ *
+ * CV_ILL_INPUT: One of the inputs to CVode is illegal. This
+ * includes the situation when a component of the
+ * error weight vectors becomes < 0 during
+ * internal time-stepping. The ILL_INPUT flag
+ * will also be returned if the linear solver
+ * routine CV--- (called by the user after
+ * calling CVodeCreate) failed to set one of the
+ * linear solver-related fields in cvode_mem or
+ * if the linear solver's init routine failed. In
+ * any case, the user should see the printed
+ * error message for more details.
+ *
+ * CV_TOO_MUCH_WORK: The solver took mxstep internal steps but
+ * could not reach tout. The default value for
+ * mxstep is MXSTEP_DEFAULT = 500.
+ *
+ * CV_TOO_MUCH_ACC: The solver could not satisfy the accuracy
+ * demanded by the user for some internal step.
+ *
+ * CV_ERR_FAILURE: Error test failures occurred too many times
+ * (= MXNEF = 7) during one internal time step or
+ * occurred with |h| = hmin.
+ *
+ * CV_CONV_FAILURE: Convergence test failures occurred too many
+ * times (= MXNCF = 10) during one internal time
+ * step or occurred with |h| = hmin.
+ *
+ * CV_LINIT_FAIL: The linear solver's initialization function
+ * failed.
+ *
+ * CV_LSETUP_FAIL: The linear solver's setup routine failed in an
+ * unrecoverable manner.
+ *
+ * CV_LSOLVE_FAIL: The linear solver's solve routine failed in an
+ * unrecoverable manner.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int CVode(void *cvode_mem, realtype tout, N_Vector yout,
+ realtype *tret, int itask);
+
+
+/*
+ * =================================================================
+ *
+ * EXTRACTION AND DENSE OUTPUT FUNCTIONS FOR FORWARD PROBLEMS
+ *
+ * =================================================================
+ */
+
+/*
+ * -----------------------------------------------------------------
+ * Function : CVodeGetDky
+ * -----------------------------------------------------------------
+ * CVodeGetDky computes the kth derivative of the y function at
+ * time t, where tn-hu <= t <= tn, tn denotes the current
+ * internal time reached, and hu is the last internal step size
+ * successfully used by the solver. The user may request
+ * k=0, 1, ..., qu, where qu is the current order. The
+ * derivative vector is returned in dky. This vector must be
+ * allocated by the caller. It is only legal to call this
+ * function after a successful return from CVode.
+ *
+ * cvode_mem is the pointer to CVODES memory returned by
+ * CVodeCreate.
+ *
+ * t is the time at which the kth derivative of y is evaluated.
+ * The legal range for t is [tn-hu,tn] as described above.
+ *
+ * k is the order of the derivative of y to be computed. The
+ * legal range for k is [0,qu] as described above.
+ *
+ * dky is the output derivative vector [(D_k)y](t).
+ *
+ * The return values for CVodeGetDky are defined below.
+ * Here is a brief description of each return value:
+ *
+ * CV_SUCCESS: CVodeGetDky succeeded.
+ *
+ * CV_BAD_K : k is not in the range 0, 1, ..., qu.
+ *
+ * CV_BAD_T : t is not in the interval [tn-hu,tn].
+ *
+ * CV_BAD_DKY : The dky argument was NULL.
+ *
+ * CV_MEM_NULL : The cvode_mem argument was NULL.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int CVodeGetDky(void *cvode_mem, realtype t, int k, N_Vector dky);
+
+
+/*
+ * -----------------------------------------------------------------
+ * Quadrature integration solution extraction routines
+ * -----------------------------------------------------------------
+ * The following functions can be called to obtain the quadrature
+ * variables after a successful integration step.
+ * If quadratures were not computed, they return CV_NO_QUAD.
+ *
+ * CVodeGetQuad returns the quadrature variables at the same time
+ * as that at which CVode returned the solution.
+ *
+ * CVodeGetQuadDky returns the quadrature variables (or their
+ * derivatives up to the current method order) at any time within
+ * the last integration step (dense output). See CVodeGetQuad for
+ * more information.
+ *
+ * The output vectors yQout and dky must be allocated by the user.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int CVodeGetQuad(void *cvode_mem, realtype *tret, N_Vector yQout);
+
+SUNDIALS_EXPORT int CVodeGetQuadDky(void *cvode_mem, realtype t, int k, N_Vector dky);
+
+/*
+ * -----------------------------------------------------------------
+ * Forward sensitivity solution extraction routines
+ * -----------------------------------------------------------------
+ * The following functions can be called to obtain the sensitivity
+ * variables after a successful integration step.
+ *
+ * CVodeGetSens and CVodeGetSens1 return all the sensitivity vectors
+ * or only one of them, respectively, at the same time as that at
+ * which CVode returned the solution.
+ * The array of output vectors or output vector ySout must be
+ * allocated by the user.
+ *
+ * CVodeGetSensDky1 computes the kth derivative of the is-th
+ * sensitivity (is=1, 2, ..., Ns) of the y function at time t,
+ * where tn-hu <= t <= tn, tn denotes the current internal time
+ * reached, and hu is the last internal step size successfully
+ * used by the solver. The user may request k=0, 1, ..., qu,
+ * where qu is the current order.
+ * The is-th sensitivity derivative vector is returned in dky.
+ * This vector must be allocated by the caller. It is only legal
+ * to call this function after a successful return from CVode
+ * with sensitivty computations enabled.
+ * Arguments have the same meaning as in CVodeDky.
+ *
+ * CVodeGetSensDky computes the k-th derivative of all
+ * sensitivities of the y function at time t. It repeatedly calls
+ * CVodeGetSensDky. The argument dkyA must be a pointer to
+ * N_Vector and must be allocated by the user to hold at least Ns
+ * vectors.
+ *
+ * Return values are similar to those of CVodeDky. Additionally,
+ * CVodeSensDky can return CV_NO_SENS if sensitivities were
+ * not computed and CV_BAD_IS if is < 0 or is >= Ns.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int CVodeGetSens(void *cvode_mem, realtype *tret, N_Vector *ySout);
+SUNDIALS_EXPORT int CVodeGetSens1(void *cvode_mem, realtype *tret, int is, N_Vector ySout);
+
+SUNDIALS_EXPORT int CVodeGetSensDky(void *cvode_mem, realtype t, int k, N_Vector *dkyA);
+SUNDIALS_EXPORT int CVodeGetSensDky1(void *cvode_mem, realtype t, int k, int is, N_Vector dky);
+
+/*
+ * -----------------------------------------------------------------
+ * Quadrature sensitivity solution extraction routines
+ * -----------------------------------------------------------------
+ * The following functions can be called to obtain the quadrature
+ * sensitivity variables after a successful integration step.
+ *
+ * CVodeGetQuadSens and CVodeGetQuadSens1 return all the quadrature
+ * sensitivity vectors or only one of them, respectively, at the
+ * same time as that at which CVode returned the solution.
+ * The array of output vectors or output vector yQSout must be
+ * allocated by the user.
+ *
+ * CVodeGetQuadSensDky1 computes the kth derivative of the is-th
+ * quadrature sensitivity (is=1, 2, ..., Ns) at time t, where
+ * tn-hu <= t <= tn, tn denotes the current internal time
+ * reached, and hu is the last internal step size successfully
+ * used by the solver. The user may request k=0, 1, ..., qu,
+ * where qu is the current order.
+ * The is-th sensitivity derivative vector is returned in dkyQS.
+ * This vector must be allocated by the caller. It is only legal
+ * to call this function after a successful return from CVode
+ * with quadrature sensitivty computations enabled.
+ * Arguments have the same meaning as in CVodeDky.
+ *
+ * CVodeGetQuadSensDky computes the k-th derivative of all
+ * quadrature sensitivities at time t. It repeatedly calls
+ * CVodeGetSensDky. The argument dkyQS_all must be a pointer to
+ * N_Vector and must be allocated by the user to hold at least Ns
+ * vectors.
+ *
+ * Return values are similar to those of CVodeDky. Additionally,
+ * CVodeQuadSensDky can return CV_NO_QUADSENS if quadrature
+ * sensitivities were not computed and CV_BAD_IS if is < 0 or is >= Ns.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int CVodeGetQuadSens(void *cvode_mem, realtype *tret, N_Vector *yQSout);
+SUNDIALS_EXPORT int CVodeGetQuadSens1(void *cvode_mem, realtype *tret, int is, N_Vector yQSout);
+
+SUNDIALS_EXPORT int CVodeGetQuadSensDky(void *cvode_mem, realtype t, int k, N_Vector *dkyQS_all);
+SUNDIALS_EXPORT int CVodeGetQuadSensDky1(void *cvode_mem, realtype t, int k, int is, N_Vector dkyQS);
+
+/*
+ * =================================================================
+ *
+ * OPTIONAL OUTPUT FUNCTIONS FOR FORWARD PROBLEMS
+ *
+ * =================================================================
+ */
+
+/*
+ * -----------------------------------------------------------------
+ * Integrator optional output extraction functions
+ * -----------------------------------------------------------------
+ * The following functions can be called to get optional outputs
+ * and statistics related to the main integrator.
+ * -----------------------------------------------------------------
+ * CVodeGetWorkSpace returns the CVODES real and integer workspaces
+ * CVodeGetNumSteps returns the cumulative number of internal
+ * steps taken by the solver
+ * CVodeGetNumRhsEvals returns the number of calls to the user's
+ * f function
+ * CVodeGetNumLinSolvSetups returns the number of calls made to
+ * the linear solver's setup routine
+ * CVodeGetNumErrTestFails returns the number of local error test
+ * failures that have occured
+ * CVodeGetLastOrder returns the order used during the last
+ * internal step
+ * CVodeGetCurrentOrder returns the order to be used on the next
+ * internal step
+ * CVodeGetNumStabLimOrderReds returns the number of order
+ * reductions due to stability limit detection
+ * CVodeGetActualInitStep returns the actual initial step size
+ * used by CVODES
+ * CVodeGetLastStep returns the step size for the last internal
+ * step
+ * CVodeGetCurrentStep returns the step size to be attempted on
+ * the next internal step
+ * CVodeGetCurrentTime returns the current internal time reached
+ * by the solver
+ * CVodeGetTolScaleFactor returns a suggested factor by which the
+ * user's tolerances should be scaled when too
+ * much accuracy has been requested for some
+ * internal step
+ * CVodeGetErrWeights returns the current error weight vector.
+ * The user must allocate space for eweight.
+ * CVodeGetEstLocalErrors returns the vector of estimated local
+ * errors. The user must allocate space for ele.
+ * CVodeGetNumGEvals returns the number of calls to the user's
+ * g function (for rootfinding)
+ * CVodeGetRootInfo returns the indices for which g_i was found to
+ * have a root. The user must allocate space for
+ * rootsfound. For i = 0 ... nrtfn-1,
+ * rootsfound[i] = 1 if g_i has a root, and = 0 if not.
+ *
+ * CVodeGet* return values:
+ * CV_SUCCESS if succesful
+ * CV_MEM_NULL if the cvode memory was NULL
+ * CV_NO_SLDET if stability limit was not turned on
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int CVodeGetWorkSpace(void *cvode_mem, long int *lenrw, long int *leniw);
+SUNDIALS_EXPORT int CVodeGetNumSteps(void *cvode_mem, long int *nsteps);
+SUNDIALS_EXPORT int CVodeGetNumRhsEvals(void *cvode_mem, long int *nfevals);
+SUNDIALS_EXPORT int CVodeGetNumLinSolvSetups(void *cvode_mem, long int *nlinsetups);
+SUNDIALS_EXPORT int CVodeGetNumErrTestFails(void *cvode_mem, long int *netfails);
+SUNDIALS_EXPORT int CVodeGetLastOrder(void *cvode_mem, int *qlast);
+SUNDIALS_EXPORT int CVodeGetCurrentOrder(void *cvode_mem, int *qcur);
+SUNDIALS_EXPORT int CVodeGetNumStabLimOrderReds(void *cvode_mem, long int *nslred);
+SUNDIALS_EXPORT int CVodeGetActualInitStep(void *cvode_mem, realtype *hinused);
+SUNDIALS_EXPORT int CVodeGetLastStep(void *cvode_mem, realtype *hlast);
+SUNDIALS_EXPORT int CVodeGetCurrentStep(void *cvode_mem, realtype *hcur);
+SUNDIALS_EXPORT int CVodeGetCurrentTime(void *cvode_mem, realtype *tcur);
+SUNDIALS_EXPORT int CVodeGetTolScaleFactor(void *cvode_mem, realtype *tolsfac);
+SUNDIALS_EXPORT int CVodeGetErrWeights(void *cvode_mem, N_Vector eweight);
+SUNDIALS_EXPORT int CVodeGetEstLocalErrors(void *cvode_mem, N_Vector ele);
+SUNDIALS_EXPORT int CVodeGetNumGEvals(void *cvode_mem, long int *ngevals);
+SUNDIALS_EXPORT int CVodeGetRootInfo(void *cvode_mem, int *rootsfound);
+
+/*
+ * -----------------------------------------------------------------
+ * As a convenience, the following functions provides the
+ * optional outputs in one group.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int CVodeGetIntegratorStats(void *cvode_mem, long int *nsteps,
+ long int *nfevals, long int *nlinsetups,
+ long int *netfails, int *qlast,
+ int *qcur, realtype *hinused, realtype *hlast,
+ realtype *hcur, realtype *tcur);
+
+/*
+ * -----------------------------------------------------------------
+ * Nonlinear solver optional output extraction functions
+ * -----------------------------------------------------------------
+ * The following functions can be called to get optional outputs
+ * and statistics related to the nonlinear solver.
+ * -----------------------------------------------------------------
+ * CVodeGetNumNonlinSolvIters returns the number of nonlinear
+ * solver iterations performed.
+ * CVodeGetNumNonlinSolvConvFails returns the number of nonlinear
+ * convergence failures.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int CVodeGetNumNonlinSolvIters(void *cvode_mem, long int *nniters);
+SUNDIALS_EXPORT int CVodeGetNumNonlinSolvConvFails(void *cvode_mem, long int *nncfails);
+
+/*
+ * -----------------------------------------------------------------
+ * As a convenience, the following function provides the
+ * nonlinear solver optional outputs in a group.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int CVodeGetNonlinSolvStats(void *cvode_mem, long int *nniters,
+ long int *nncfails);
+
+
+/*
+ * -----------------------------------------------------------------
+ * The following function returns the name of the constant
+ * associated with a CVODES return flag
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT char *CVodeGetReturnFlagName(long int flag);
+
+/*
+ * -----------------------------------------------------------------
+ * Quadrature integration optional output extraction routines
+ * -----------------------------------------------------------------
+ * The following functions can be called to get optional outputs
+ * and statistics related to the integration of quadratures.
+ * -----------------------------------------------------------------
+ * CVodeGetQuadNumRhsEvals returns the number of calls to the
+ * user function fQ defining the right hand
+ * side of the quadrature variables.
+ * CVodeGetQuadNumErrTestFails returns the number of local error
+ * test failures for quadrature variables.
+ * CVodeGetQuadErrWeights returns the vector of error weights for
+ * the quadrature variables. The user must
+ * allocate space for ewtQ.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int CVodeGetQuadNumRhsEvals(void *cvode_mem, long int *nfQevals);
+SUNDIALS_EXPORT int CVodeGetQuadNumErrTestFails(void *cvode_mem, long int *nQetfails);
+SUNDIALS_EXPORT int CVodeGetQuadErrWeights(void *cvode_mem, N_Vector eQweight);
+
+/*
+ * -----------------------------------------------------------------
+ * As a convenience, the following function provides the above
+ * optional outputs in a group.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int CVodeGetQuadStats(void *cvode_mem, long int *nfQevals,
+ long int *nQetfails);
+
+/*
+ * -----------------------------------------------------------------
+ * Forward sensitivity optional output extraction routines
+ * -----------------------------------------------------------------
+ * The following functions can be called to get optional outputs
+ * and statistics related to the integration of sensitivities.
+ * -----------------------------------------------------------------
+ * CVodeGetSensNumRhsEvals returns the number of calls to the
+ * sensitivity right hand side routine.
+ * CVodeGetNumRhsEvalsSens returns the number of calls to the
+ * user f routine due to finite difference evaluations of the
+ * sensitivity equations.
+ * CVodeGetSensNumErrTestFails returns the number of local error
+ * test failures for sensitivity variables.
+ * CVodeGetSensNumLinSolvSetups returns the number of calls made
+ * to the linear solver's setup routine due to sensitivity computations.
+ * CVodeGetSensErrWeights returns the sensitivity error weight
+ * vectors. The user need not allocate space for ewtS.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int CVodeGetSensNumRhsEvals(void *cvode_mem, long int *nfSevals);
+SUNDIALS_EXPORT int CVodeGetNumRhsEvalsSens(void *cvode_mem, long int *nfevalsS);
+SUNDIALS_EXPORT int CVodeGetSensNumErrTestFails(void *cvode_mem, long int *nSetfails);
+SUNDIALS_EXPORT int CVodeGetSensNumLinSolvSetups(void *cvode_mem, long int *nlinsetupsS);
+SUNDIALS_EXPORT int CVodeGetSensErrWeights(void *cvode_mem, N_Vector *eSweight);
+
+/*
+ * -----------------------------------------------------------------
+ * As a convenience, the following function provides the
+ * optional outputs in a group.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int CVodeGetSensStats(void *cvode_mem, long int *nfSevals, long int *nfevalsS,
+ long int *nSetfails, long int *nlinsetupsS);
+
+/*
+ * -----------------------------------------------------------------
+ * Sensitivity nonlinear solver optional output extraction
+ * -----------------------------------------------------------------
+ * The following functions can be called to get optional outputs
+ * and statistics related to the sensitivity nonlinear solver.
+ * -----------------------------------------------------------------
+ * CVodeGetSensNumNonlinSolvIters returns the total number of
+ * nonlinear iterations for sensitivity variables.
+ * CVodeGetSensNumNonlinSolvConvFails returns the total number
+ * of nonlinear convergence failures for sensitivity variables
+ * CVodeGetStgrSensNumNonlinSolvIters returns a vector of Ns
+ * nonlinear iteration counters for sensitivity variables in
+ * the CV_STAGGERED1 method.
+ * CVodeGetStgrSensNumNonlinSolvConvFails returns a vector of Ns
+ * nonlinear solver convergence failure counters for sensitivity
+ * variables in the CV_STAGGERED1 method.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int CVodeGetSensNumNonlinSolvIters(void *cvode_mem, long int *nSniters);
+SUNDIALS_EXPORT int CVodeGetSensNumNonlinSolvConvFails(void *cvode_mem, long int *nSncfails);
+SUNDIALS_EXPORT int CVodeGetStgrSensNumNonlinSolvIters(void *cvode_mem, long int *nSTGR1niters);
+SUNDIALS_EXPORT int CVodeGetStgrSensNumNonlinSolvConvFails(void *cvode_mem,
+ long int *nSTGR1ncfails);
+
+/*
+ * -----------------------------------------------------------------
+ * As a convenience, the following function provides the
+ * optional outputs in groups.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int CVodeGetSensNonlinSolvStats(void *cvode_mem, long int *nSniters,
+ long int *nSncfails);
+
+
+/*
+ * -----------------------------------------------------------------
+ * Quadrature sensitivity optional output extraction routines
+ * -----------------------------------------------------------------
+ * The following functions can be called to get optional outputs and
+ * statistics related to the integration of quadrature sensitivitiess.
+ * -----------------------------------------------------------------
+ * CVodeGetQuadSensNumRhsEvals returns the number of calls to the
+ * user function fQS defining the right hand side of the
+ * quadrature sensitivity equations.
+ * CVodeGetQuadSensNumErrTestFails returns the number of local error
+ * test failures for quadrature sensitivity variables.
+ * CVodeGetQuadSensErrWeights returns the vector of error weights
+ * for the quadrature sensitivity variables. The user must
+ * allocate space for ewtQS.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int CVodeGetQuadSensNumRhsEvals(void *cvode_mem, long int *nfQSevals);
+SUNDIALS_EXPORT int CVodeGetQuadSensNumErrTestFails(void *cvode_mem, long int *nQSetfails);
+SUNDIALS_EXPORT int CVodeGetQuadSensErrWeights(void *cvode_mem, N_Vector *eQSweight);
+
+/*
+ * -----------------------------------------------------------------
+ * As a convenience, the following function provides the above
+ * optional outputs in a group.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int CVodeGetQuadSensStats(void *cvode_mem,
+ long int *nfQSevals,
+ long int *nQSetfails);
+
+
+/*
+ * =================================================================
+ *
+ * INITIALIZATION AND DEALLOCATION FUNCTIONS FOR BACKWARD PROBLEMS
+ *
+ * =================================================================
+ */
+
+/*
+ * -----------------------------------------------------------------
+ * CVodeAdjInit
+ * -----------------------------------------------------------------
+ * CVodeAdjInit specifies some parameters for ASA, initializes ASA
+ * and allocates space for the adjoint memory structure.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int CVodeAdjInit(void *cvode_mem, long int steps, int interp);
+
+/*
+ * -----------------------------------------------------------------
+ * CVodeAdjReInit
+ * -----------------------------------------------------------------
+ * CVodeAdjReInit reinitializes the CVODES memory structure for ASA,
+ * assuming that the number of steps between check points and the
+ * type of interpolation remained unchanged. The list of check points
+ * (and associated memory) is deleted. The list of backward problems
+ * is kept (however, new backward problems can be added to this list
+ * by calling CVodeCreateB). The CVODES memory for the forward and
+ * backward problems can be reinitialized separately by calling
+ * CVodeReInit and CVodeReInitB, respectively.
+ * NOTE: if a entirely new list of backward problems is desired,
+ * then simply free the adjoint memory (by calling CVodeAdjFree)
+ * and reinitialize ASA with CVodeAdjInit.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int CVodeAdjReInit(void *cvode_mem);
+
+/*
+ * -----------------------------------------------------------------
+ * CVodeAdjFree
+ * -----------------------------------------------------------------
+ * CVodeAdjFree frees the memory allocated by CVodeAdjInit.
+ * It is typically called by CVodeFree.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT void CVodeAdjFree(void *cvode_mem);
+
+
+/*
+ * -----------------------------------------------------------------
+ * Interfaces to CVODES functions for setting-up backward problems.
+ * -----------------------------------------------------------------
+ * CVodeCreateB,
+ *
+ * CVodeInitB, CVodeInitBS, CVodeReInitB
+ *
+ * CVodeQuadInitB, CVodeQuadInitBS, CVodeQuadReInitB
+ *
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int CVodeCreateB(void *cvode_mem, int lmmB, int iterB, int *which);
+
+SUNDIALS_EXPORT int CVodeInitB(void *cvode_mem, int which,
+ CVRhsFnB fB,
+ realtype tB0, N_Vector yB0);
+SUNDIALS_EXPORT int CVodeInitBS(void *cvode_mem, int which,
+ CVRhsFnBS fBs,
+ realtype tB0, N_Vector yB0);
+SUNDIALS_EXPORT int CVodeReInitB(void *cvode_mem, int which,
+ realtype tB0, N_Vector yB0);
+
+SUNDIALS_EXPORT int CVodeSStolerancesB(void *cvode_mem, int which,
+ realtype reltolB, realtype abstolB);
+SUNDIALS_EXPORT int CVodeSVtolerancesB(void *cvode_mem, int which,
+ realtype reltolB, N_Vector abstolB);
+
+SUNDIALS_EXPORT int CVodeQuadInitB(void *cvode_mem, int which,
+ CVQuadRhsFnB fQB, N_Vector yQB0);
+SUNDIALS_EXPORT int CVodeQuadInitBS(void *cvode_mem, int which,
+ CVQuadRhsFnBS fQBs, N_Vector yQB0);
+SUNDIALS_EXPORT int CVodeQuadReInitB(void *cvode_mem, int which, N_Vector yQB0);
+
+SUNDIALS_EXPORT int CVodeQuadSStolerancesB(void *cvode_mem, int which,
+ realtype reltolQB, realtype abstolQB);
+SUNDIALS_EXPORT int CVodeQuadSVtolerancesB(void *cvode_mem, int which,
+ realtype reltolQB, N_Vector abstolQB);
+
+/*
+ * =================================================================
+ *
+ * MAIN SOLVER FUNCTIONS FOR FORWARD PROBLEMS
+ *
+ * =================================================================
+ */
+
+/*
+ * -----------------------------------------------------------------
+ * CVodeF
+ * -----------------------------------------------------------------
+ * CVodeF integrates towards tout and returns solution into yout.
+ * In the same time, it stores check point data every 'steps'.
+ *
+ * CVodeF can be called repeatedly by the user.
+ *
+ * ncheckPtr points to the number of check points stored so far.
+ *
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int CVodeF(void *cvode_mem, realtype tout, N_Vector yout,
+ realtype *tret, int itask, int *ncheckPtr);
+
+
+/*
+ * -----------------------------------------------------------------
+ * CVodeB
+ * -----------------------------------------------------------------
+ * CVodeB performs the integration of all backward problems specified
+ * through calls to CVodeCreateB through a sequence of forward-backward
+ * runs in between consecutive check points. CVodeB can be called
+ * either in CV_NORMAL or CV_ONE_STEP mode. After a successful return
+ * from CVodeB, the solution and quadrature variables at the current
+ * return time for any given backward problem can be obtained by
+ * calling CVodeGetB and CVodeGetQuadB, respectively.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int CVodeB(void *cvode_mem, realtype tBout, int itaskB);
+
+/*
+ * =================================================================
+ *
+ * OPTIONAL INPUT FUNCTIONS FOR BACKWARD PROBLEMS
+ *
+ * =================================================================
+ */
+
+/*
+ * -----------------------------------------------------------------
+ * CVodeSetAdjNoSensi
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int CVodeSetAdjNoSensi(void *cvode_mem);
+
+/*
+ * -----------------------------------------------------------------
+ * Optional input functions for backward problems
+ * -----------------------------------------------------------------
+ * These functions are just wrappers around the corresponding
+ * functions in cvodes.h, with some particularizations for the
+ * backward integration.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int CVodeSetIterTypeB(void *cvode_mem, int which, int iterB);
+SUNDIALS_EXPORT int CVodeSetUserDataB(void *cvode_mem, int which, void *user_dataB);
+SUNDIALS_EXPORT int CVodeSetMaxOrdB(void *cvode_mem, int which, int maxordB);
+SUNDIALS_EXPORT int CVodeSetMaxNumStepsB(void *cvode_mem, int which, long int mxstepsB);
+SUNDIALS_EXPORT int CVodeSetStabLimDetB(void *cvode_mem, int which, booleantype stldetB);
+SUNDIALS_EXPORT int CVodeSetInitStepB(void *cvode_mem, int which, realtype hinB);
+SUNDIALS_EXPORT int CVodeSetMinStepB(void *cvode_mem, int which, realtype hminB);
+SUNDIALS_EXPORT int CVodeSetMaxStepB(void *cvode_mem, int which, realtype hmaxB);
+
+SUNDIALS_EXPORT int CVodeSetQuadErrConB(void *cvode_mem, int which, booleantype errconQB);
+
+/*
+ * =================================================================
+ *
+ * EXTRACTION AND DENSE OUTPUT FUNCTIONS FOR BACKWARD PROBLEMS
+ *
+ * =================================================================
+ */
+
+/*
+ * -----------------------------------------------------------------
+ * CVodeGetB and CVodeGetQuadB
+ * -----------------------------------------------------------------
+ * Extraction functions for the solution and quadratures for a given
+ * backward problem. They return their corresponding output vector
+ * at the current time reached by the integration of the backward
+ * problem. To obtain the solution or quadratures associated with
+ * a given backward problem at some other time within the last
+ * integration step (dense output), first obtain a pointer to the
+ * proper CVODES memory by calling CVodeGetAdjCVodeBmem and then use it
+ * to call CVodeGetDky and CVodeGetQuadDky.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int CVodeGetB(void *cvode_mem, int which,
+ realtype *tBret, N_Vector yB);
+SUNDIALS_EXPORT int CVodeGetQuadB(void *cvode_mem, int which,
+ realtype *tBret, N_Vector qB);
+
+
+/*
+ * =================================================================
+ *
+ * OPTIONAL OUTPUT FUNCTIONS FOR BACKWARD PROBLEMS
+ *
+ * =================================================================
+ */
+
+
+/*
+ * -----------------------------------------------------------------
+ * CVodeGetAdjCVodeBmem
+ * -----------------------------------------------------------------
+ * CVodeGetAdjCVodeBmem returns a (void *) pointer to the CVODES
+ * memory allocated for the backward problem. This pointer can
+ * then be used to call any of the CVodeGet* CVODES routines to
+ * extract optional output for the backward integration phase.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT void *CVodeGetAdjCVodeBmem(void *cvode_mem, int which);
+
+
+/*
+ * -----------------------------------------------------------------
+ * CVodeGetAdjY
+ * Returns the interpolated forward solution at time t. This
+ * function is a wrapper around the interpType-dependent internal
+ * function.
+ * The calling function must allocate space for y.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int CVodeGetAdjY(void *cvode_mem, realtype t, N_Vector y);
+
+/*
+ * -----------------------------------------------------------------
+ * CVodeGetAdjCheckPointsInfo
+ * Loads an array of nckpnts structures of type CVadjCheckPointRec.
+ * The user must allocate space for ckpnt (ncheck+1).
+ * -----------------------------------------------------------------
+ */
+
+typedef struct {
+ void *my_addr;
+ void *next_addr;
+ realtype t0;
+ realtype t1;
+ long int nstep;
+ int order;
+ realtype step;
+} CVadjCheckPointRec;
+
+SUNDIALS_EXPORT int CVodeGetAdjCheckPointsInfo(void *cvode_mem, CVadjCheckPointRec *ckpnt);
+
+/*
+ * -----------------------------------------------------------------
+ * CVodeGetAdjDataPointHermite
+ * Returns the 2 vectors stored for cubic Hermite interpolation
+ * at the data point 'which'. The user must allocate space for
+ * y and yd. Returns CV_MEM_NULL if cvode_mem is NULL.
+ * Returns CV_ILL_INPUT if interpType != CV_HERMITE.
+ * CVodeGetAdjDataPointPolynomial
+ * Returns the vector stored for polynomial interpolation
+ * at the data point 'which'. The user must allocate space for
+ * y. Returns CV_MEM_NULL if cvode_mem is NULL.
+ * Returns CV_ILL_INPUT if interpType != CV_POLYNOMIAL.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int CVodeGetAdjDataPointHermite(void *cvode_mem, int which,
+ realtype *t, N_Vector y, N_Vector yd);
+
+SUNDIALS_EXPORT int CVodeGetAdjDataPointPolynomial(void *cvode_mem, int which,
+ realtype *t, int *order, N_Vector y);
+
+/*
+ * -----------------------------------------------------------------
+ * CVodeGetAdjCurrentCheckPoint
+ * Returns the address of the 'active' check point.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int CVodeGetAdjCurrentCheckPoint(void *cvode_mem, void **addr);
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/cvodes/cvodes_band.h b/include/cvodes/cvodes_band.h
new file mode 100644
index 0000000..071f881
--- /dev/null
+++ b/include/cvodes/cvodes_band.h
@@ -0,0 +1,72 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.8 $
+ * $Date: 2010/12/01 22:13:10 $
+ * -----------------------------------------------------------------
+ * Programmer(s): 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.
+ * -----------------------------------------------------------------
+ * This is the header file for the band linear solver CSVBAND.
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _CVSBAND_H
+#define _CVSBAND_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <cvodes/cvodes_direct.h>
+#include <sundials/sundials_band.h>
+
+/*
+ * -----------------------------------------------------------------
+ * 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.
+ * -----------------------------------------------------------------
+ */
+
+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
new file mode 100644
index 0000000..a612d30
--- /dev/null
+++ b/include/cvodes/cvodes_bandpre.h
@@ -0,0 +1,179 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.8 $
+ * $Date: 2010/12/01 22:13:10 $
+ * -----------------------------------------------------------------
+ * Programmer: 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.
+ * -----------------------------------------------------------------
+ * 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.
+ *
+ * Part I contains type definitions and function prototypes for using
+ * CVSBANDPRE on forward problems (IVP integration and/or FSA)
+ *
+ * Part II contains type definitions and function prototypes for using
+ * CVSBANDPRE on adjopint (backward) problems
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _CVSBANDPRE_H
+#define _CVSBANDPRE_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <sundials/sundials_nvector.h>
+
+/*
+ * =================================================================
+ * 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, CVodeMalloc, 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 = CVodeMalloc(...);
+ * ...
+ * 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.
+ * -----------------------------------------------------------------
+ */
+
+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
+ * -----------------------------------------------------------------
+ */
+
+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.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int CVBandPrecInitB(void *cvode_mem, int which,
+ long int nB, long int muB, long int mlB);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/cvodes/cvodes_bbdpre.h b/include/cvodes/cvodes_bbdpre.h
new file mode 100644
index 0000000..73d3a7e
--- /dev/null
+++ b/include/cvodes/cvodes_bbdpre.h
@@ -0,0 +1,331 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.11 $
+ * $Date: 2010/12/01 22:13:10 $
+ * -----------------------------------------------------------------
+ * Programmer(s): 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.
+ * -----------------------------------------------------------------
+ * 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.
+ *
+ *
+ * Part I contains type definitions and function prototypes for using
+ * CVBBDPRE on forward problems (IVP integration and/or FSA)
+ *
+ * Part II contains type definitions and function prototypes for using
+ * CVBBDPRE on adjopint (backward) problems
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _CVSBBDPRE_H
+#define _CVSBBDPRE_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <sundials/sundials_nvector.h>
+
+/*
+ * =================================================================
+ * 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 = CVodeMalloc(...);
+ * ...
+ * 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.
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * -----------------------------------------------------------------
+ * 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.
+ * -----------------------------------------------------------------
+ */
+
+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);
+
+/*
+ * -----------------------------------------------------------------
+ * 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,
+ realtype dqrely,
+ 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,
+ 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
+ * -----------------------------------------------------------------
+ */
+
+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
+ * =================================================================
+ */
+
+/*
+ * -----------------------------------------------------------------
+ * Types: CVLocalFnB and CVCommFnB
+ * -----------------------------------------------------------------
+ * Local approximation function and inter-process communication
+ * function for the BBD preconditioner on the backward phase.
+ * -----------------------------------------------------------------
+ */
+
+typedef int (*CVLocalFnB)(long int 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);
+
+/*
+ * -----------------------------------------------------------------
+ * Functions: CVBBDPrecInitB, CVBBDSp*B, CVBBDPrecReInit
+ * -----------------------------------------------------------------
+ * Interface functions for the CVBBDPRE preconditioner to be used on
+ * the backward phase.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT 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);
+
+SUNDIALS_EXPORT int CVBBDPrecReInitB(void *cvode_mem, int which,
+ long int mudqB, long int mldqB,
+ realtype dqrelyB);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/cvodes/cvodes_dense.h b/include/cvodes/cvodes_dense.h
new file mode 100644
index 0000000..d840f27
--- /dev/null
+++ b/include/cvodes/cvodes_dense.h
@@ -0,0 +1,64 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.8 $
+ * $Date: 2010/12/01 22:13:10 $
+ * -----------------------------------------------------------------
+ * Programmer(s): 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.
+ * -----------------------------------------------------------------
+ * This is the header file for the dense linear solver CVSDENSE.
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _CVSDENSE_H
+#define _CVSDENSE_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <cvodes/cvodes_direct.h>
+#include <sundials/sundials_dense.h>
+
+/*
+ * -----------------------------------------------------------------
+ * 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.
+ * -----------------------------------------------------------------
+ */
+
+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
new file mode 100644
index 0000000..55d52d1
--- /dev/null
+++ b/include/cvodes/cvodes_diag.h
@@ -0,0 +1,140 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.6 $
+ * $Date: 2010/12/01 22:13:10 $
+ * -----------------------------------------------------------------
+ * Programmer(s): 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.
+ * -----------------------------------------------------------------
+ * This is the header file for the diagonal linear solver CVSDIAG.
+ *
+ *
+ * Part I contains type definitions and function prototypes for using
+ * CVDIAG on forward problems (IVP integration and/or FSA)
+ *
+ * Part II contains type definitions and function prototypes for using
+ * CVDIAG on adjoint (backward) problems
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _CVSDIAG_H
+#define _CVSDIAG_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <sundials/sundials_nvector.h>
+
+/*
+ * -----------------------------------------------------------------
+ * CVDIAG return values
+ * -----------------------------------------------------------------
+ */
+
+#define CVDIAG_SUCCESS 0
+#define CVDIAG_MEM_NULL -1
+#define CVDIAG_LMEM_NULL -2
+#define CVDIAG_ILL_INPUT -3
+#define CVDIAG_MEM_FAIL -4
+
+/* Additional last_flag values */
+
+#define CVDIAG_INV_FAIL -5
+#define CVDIAG_RHSFUNC_UNRECVR -6
+#define CVDIAG_RHSFUNC_RECVR -7
+
+/* Return values for adjoint module */
+
+#define CVDIAG_NO_ADJ -101
+
+/*
+ * -----------------------------------------------------------------
+ * PART I - forward problems
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * -----------------------------------------------------------------
+ * Function : CVDiag
+ * -----------------------------------------------------------------
+ * A call to the CVDiag function links the main integrator with
+ * the CVDIAG linear solver.
+ *
+ * cvode_mem is the pointer to the integrator memory returned by
+ * CVodeCreate.
+ *
+ * The return value of CVDiag is one of:
+ * CVDIAG_SUCCESS if successful
+ * CVDIAG_MEM_NULL if the cvode memory was NULL
+ * CVDIAG_MEM_FAIL if there was a memory allocation failure
+ * CVDIAG_ILL_INPUT if a required vector operation is missing
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int CVDiag(void *cvode_mem);
+
+/*
+ * -----------------------------------------------------------------
+ * Optional outputs from the CVDIAG linear solver
+ * -----------------------------------------------------------------
+ *
+ * CVDiagGetWorkSpace returns the real and integer workspace used
+ * by CVDIAG.
+ * CVDiagGetNumRhsEvals returns the number of calls to the user
+ * f routine due to finite difference Jacobian
+ * evaluation.
+ * Note: The number of diagonal approximate
+ * Jacobians formed is equal to the number of
+ * CVDiagSetup calls. This number is available
+ * through CVodeGetNumLinSolvSetups.
+ * CVDiagGetLastFlag returns the last error flag set by any of
+ * the CVDIAG interface functions.
+ *
+ * The return value of CVDiagGet* is one of:
+ * CVDIAG_SUCCESS if successful
+ * CVDIAG_MEM_NULL if the cvode memory was NULL
+ * CVDIAG_LMEM_NULL if the cvdiag memory was NULL
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int CVDiagGetWorkSpace(void *cvode_mem, long int *lenrwLS, long int *leniwLS);
+SUNDIALS_EXPORT int CVDiagGetNumRhsEvals(void *cvode_mem, long int *nfevalsLS);
+SUNDIALS_EXPORT int CVDiagGetLastFlag(void *cvode_mem, long int *flag);
+
+/*
+ * -----------------------------------------------------------------
+ * The following function returns the name of the constant
+ * associated with a CVDIAG return flag
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT char *CVDiagGetReturnFlagName(long int flag);
+
+/*
+ * -----------------------------------------------------------------
+ * PART II - backward problems
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * -----------------------------------------------------------------
+ * Function: CVDiagB
+ * -----------------------------------------------------------------
+ * CVDiagB links the main CVODE integrator with the CVDIAG
+ * linear solver for the backward integration.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int CVDiagB(void *cvode_mem, int which);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/cvodes/cvodes_direct.h b/include/cvodes/cvodes_direct.h
new file mode 100644
index 0000000..13aa1cf
--- /dev/null
+++ b/include/cvodes/cvodes_direct.h
@@ -0,0 +1,365 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.8 $
+ * $Date: 2010/12/01 22:13:10 $
+ * -----------------------------------------------------------------
+ * Programmer: Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2006, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * Common header file for the direct linear solvers in CVODES.
+ *
+ * Part I contains type definitions and function prototypes for
+ * using a CVDLS linear solver on forward problems (IVP
+ * integration and/or FSA)
+ *
+ * Part II contains type definitions and function prototypes for
+ * using a CVDLS linear solver on adjoint (backward) problems
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _CVSDLS_H
+#define _CVSDLS_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <sundials/sundials_direct.h>
+#include <sundials/sundials_nvector.h>
+
+/*
+ * =================================================================
+ * C V S D I R E C T C O N S T A N T S
+ * =================================================================
+ */
+
+/*
+ * -----------------------------------------------------------------
+ * CVSDIRECT return values
+ * -----------------------------------------------------------------
+ */
+
+#define CVDLS_SUCCESS 0
+#define CVDLS_MEM_NULL -1
+#define CVDLS_LMEM_NULL -2
+#define CVDLS_ILL_INPUT -3
+#define CVDLS_MEM_FAIL -4
+
+/* Additional last_flag values */
+
+#define CVDLS_JACFUNC_UNRECVR -5
+#define CVDLS_JACFUNC_RECVR -6
+
+/* 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.
+ *
+ * -----------------------------------------------------------------
+ */
+
+
+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
+ * -----------------------------------------------------------------
+ */
+
+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 : 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);
+
+/*
+ * -----------------------------------------------------------------
+ * EXPORTED FUNCTIONS
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * -----------------------------------------------------------------
+ * Functions: CVDlsSetJacFnB
+ * -----------------------------------------------------------------
+ * CVDlsSetDenseJacFnB and CVDlsSetBandJacFnB specify the dense and
+ * band, respectively, Jacobian functions to be used by a
+ * CVSDIRECT linear solver for the bacward integration phase.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int CVDlsSetDenseJacFnB(void *cvode_mem, int which,
+ CVDlsDenseJacFnB jacB);
+SUNDIALS_EXPORT int CVDlsSetBandJacFnB(void *cvode_mem, int which,
+ CVDlsBandJacFnB jacB);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/cvodes/cvodes_lapack.h b/include/cvodes/cvodes_lapack.h
new file mode 100644
index 0000000..20eedf8
--- /dev/null
+++ b/include/cvodes/cvodes_lapack.h
@@ -0,0 +1,103 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.6 $
+ * $Date: 2008/04/18 19:42:37 $
+ * -----------------------------------------------------------------
+ * Programmer: Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2006, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * Header file for the CVODES dense linear solver CVSLAPACK.
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _CVSLAPACK_H
+#define _CVSLAPACK_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <cvodes/cvodes_direct.h>
+#include <sundials/sundials_lapack.h>
+
+/*
+ * -----------------------------------------------------------------
+ * 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.
+ * -----------------------------------------------------------------
+ */
+
+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.
+ * -----------------------------------------------------------------
+ */
+
+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_spbcgs.h b/include/cvodes/cvodes_spbcgs.h
new file mode 100644
index 0000000..acc56c9
--- /dev/null
+++ b/include/cvodes/cvodes_spbcgs.h
@@ -0,0 +1,87 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.4 $
+ * $Date: 2007/03/22 18:05:50 $
+ * -----------------------------------------------------------------
+ * 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.
+ * -----------------------------------------------------------------
+ * 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
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <cvodes/cvodes_spils.h>
+#include <sundials/sundials_spbcgs.h>
+
+/*
+ * -----------------------------------------------------------------
+ * 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
+ * -----------------------------------------------------------------
+ */
+
+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
new file mode 100644
index 0000000..73f2420
--- /dev/null
+++ b/include/cvodes/cvodes_spgmr.h
@@ -0,0 +1,88 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.4 $
+ * $Date: 2007/03/22 18:05:50 $
+ * -----------------------------------------------------------------
+ * Programmer(s): 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.
+ * -----------------------------------------------------------------
+ * 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
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <cvodes/cvodes_spils.h>
+#include <sundials/sundials_spgmr.h>
+
+/*
+ * -----------------------------------------------------------------
+ * 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
+ * -----------------------------------------------------------------
+ */
+
+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
new file mode 100644
index 0000000..aa63072
--- /dev/null
+++ b/include/cvodes/cvodes_spils.h
@@ -0,0 +1,450 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.12 $
+ * $Date: 2010/12/01 22:13:10 $
+ * -----------------------------------------------------------------
+ * Programmer(s): 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.
+ * -----------------------------------------------------------------
+ * This is the common header file for the Scaled, Preconditioned
+ * Iterative Linear Solvers in CVODES.
+ *
+ * Part I contains type definitions and functions for using the
+ * iterative linear solvers on forward problems
+ * (IVP integration and/or FSA)
+ *
+ * Part II contains type definitions and functions for using the
+ * iterative linear solvers on adjoint (backward) problems
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _CVSSPILS_H
+#define _CVSSPILS_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <sundials/sundials_iterative.h>
+#include <sundials/sundials_nvector.h>
+
+/*
+ * -----------------------------------------------------------------
+ * CVSPILS return values
+ * -----------------------------------------------------------------
+ */
+
+#define CVSPILS_SUCCESS 0
+#define CVSPILS_MEM_NULL -1
+#define CVSPILS_LMEM_NULL -2
+#define CVSPILS_ILL_INPUT -3
+#define CVSPILS_MEM_FAIL -4
+#define CVSPILS_PMEM_NULL -5
+
+/* 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
+ * -----------------------------------------------------------------
+ */
+
+#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).
+ * -----------------------------------------------------------------
+ */
+
+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).
+ * -----------------------------------------------------------------
+ */
+
+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.
+ * -----------------------------------------------------------------
+ */
+
+typedef int (*CVSpilsJacTimesVecFn)(N_Vector v, N_Vector Jv, realtype t,
+ N_Vector y, N_Vector fy,
+ void *user_data, N_Vector tmp);
+
+
+/*
+ * -----------------------------------------------------------------
+ * 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 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 : 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 : 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);
+
+/*
+ * -----------------------------------------------------------------
+ * Functions
+ * -----------------------------------------------------------------
+ */
+
+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,
+ CVSpilsPrecSolveFnB psolveB);
+SUNDIALS_EXPORT int CVSpilsSetJacTimesVecFnB(void *cvode_mem, int which,
+ CVSpilsJacTimesVecFnB jtvB);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/cvodes/cvodes_sptfqmr.h b/include/cvodes/cvodes_sptfqmr.h
new file mode 100644
index 0000000..2b91a3a
--- /dev/null
+++ b/include/cvodes/cvodes_sptfqmr.h
@@ -0,0 +1,88 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.4 $
+ * $Date: 2007/03/22 18:05:50 $
+ * -----------------------------------------------------------------
+ * 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.
+ * -----------------------------------------------------------------
+ * 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
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <cvodes/cvodes_spils.h>
+#include <sundials/sundials_sptfqmr.h>
+
+/*
+ * -----------------------------------------------------------------
+ * 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
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int CVSptfqmrB(void *cvode_mem, int which,
+ int pretypeB, int maxlB);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/ida/ida.h b/include/ida/ida.h
new file mode 100644
index 0000000..85f5a4d
--- /dev/null
+++ b/include/ida/ida.h
@@ -0,0 +1,938 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.14 $
+ * $Date: 2010/12/01 22:14:08 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Allan G. Taylor, Alan C. Hindmarsh, Radu Serban,
+ * and Aaron Collier @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California
+ * Produced at the Lawrence Livermore National Laboratory
+ * All rights reserved
+ * For details, see the LICENSE file
+ * -----------------------------------------------------------------
+ * This is the header (include) file for the main IDA solver.
+ * -----------------------------------------------------------------
+ *
+ * IDA is used to solve numerically the initial value problem
+ * for the differential algebraic equation (DAE) system
+ * F(t,y,y') = 0,
+ * given initial conditions
+ * y(t0) = y0, y'(t0) = yp0.
+ * Here y and F are vectors of length N.
+ *
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _IDA_H
+#define _IDA_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <stdio.h>
+
+#include <sundials/sundials_nvector.h>
+
+/*
+ * =================================================================
+ * I D A C O N S T A N T S
+ * =================================================================
+ */
+
+/*
+ * ----------------------------------------------------------------
+ * Inputs to IDAInit, IDAReInit, IDACalcIC, and IDASolve.
+ * ----------------------------------------------------------------
+ */
+
+/* itask */
+#define IDA_NORMAL 1
+#define IDA_ONE_STEP 2
+
+/* icopt */
+#define IDA_YA_YDP_INIT 1
+#define IDA_Y_INIT 2
+
+/*
+ * ----------------------------------------
+ * IDA return flags
+ * ----------------------------------------
+ */
+
+#define IDA_SUCCESS 0
+#define IDA_TSTOP_RETURN 1
+#define IDA_ROOT_RETURN 2
+
+#define IDA_WARNING 99
+
+#define IDA_TOO_MUCH_WORK -1
+#define IDA_TOO_MUCH_ACC -2
+#define IDA_ERR_FAIL -3
+#define IDA_CONV_FAIL -4
+
+#define IDA_LINIT_FAIL -5
+#define IDA_LSETUP_FAIL -6
+#define IDA_LSOLVE_FAIL -7
+#define IDA_RES_FAIL -8
+#define IDA_REP_RES_ERR -9
+#define IDA_RTFUNC_FAIL -10
+#define IDA_CONSTR_FAIL -11
+
+#define IDA_FIRST_RES_FAIL -12
+#define IDA_LINESEARCH_FAIL -13
+#define IDA_NO_RECOVERY -14
+
+#define IDA_MEM_NULL -20
+#define IDA_MEM_FAIL -21
+#define IDA_ILL_INPUT -22
+#define IDA_NO_MALLOC -23
+#define IDA_BAD_EWT -24
+#define IDA_BAD_K -25
+#define IDA_BAD_T -26
+#define IDA_BAD_DKY -27
+
+/*
+ * ----------------------------------------------------------------
+ * Type : IDAResFn
+ * ----------------------------------------------------------------
+ * The F function which defines the DAE system F(t,y,y')=0
+ * must have type IDAResFn.
+ * Symbols are as follows:
+ * t <-> t y <-> yy
+ * y' <-> yp F <-> rr
+ * A IDAResFn takes as input the independent variable value t,
+ * the dependent variable vector yy, and the derivative (with
+ * respect to t) of the yy vector, yp. It stores the result of
+ * F(t,y,y') in the vector rr. The yy, yp, and rr arguments are of
+ * type N_Vector. The user_data parameter is the pointer user_data
+ * passed by the user to the IDASetRdata routine. This user-supplied
+ * pointer is passed to the user's res function every time it is called,
+ * to provide access in res to user data.
+ *
+ * A IDAResFn res should return a value of 0 if successful, a positive
+ * value if a recoverable error occured (e.g. yy has an illegal value),
+ * or a negative value if a nonrecoverable error occured. In the latter
+ * case, the program halts. If a recoverable error occured, the integrator
+ * will attempt to correct and retry.
+ * ----------------------------------------------------------------
+ */
+
+typedef int (*IDAResFn)(realtype tt, N_Vector yy, N_Vector yp,
+ N_Vector rr, void *user_data);
+
+/*
+ * -----------------------------------------------------------------
+ * Type : IDARootFn
+ * -----------------------------------------------------------------
+ * A function g, which defines a set of functions g_i(t,y,y') whose
+ * roots are sought during the integration, must have type IDARootFn.
+ * The function g takes as input the independent variable value t,
+ * the dependent variable vector y, and its t-derivative yp (= y').
+ * It stores the nrtfn values g_i(t,y,y') in the realtype array gout.
+ * (Allocation of memory for gout is handled within IDA.)
+ * The user_data parameter is the same as that passed by the user
+ * to the IDASetRdata routine. This user-supplied pointer is
+ * passed to the user's g function every time it is called.
+ *
+ * An IDARootFn should return 0 if successful or a non-zero value
+ * if an error occured (in which case the integration will be halted).
+ * -----------------------------------------------------------------
+ */
+
+typedef int (*IDARootFn)(realtype t, N_Vector y, N_Vector yp,
+ realtype *gout, void *user_data);
+
+/*
+ * -----------------------------------------------------------------
+ * Type : IDAEwtFn
+ * -----------------------------------------------------------------
+ * A function e, which sets the error weight vector ewt, must have
+ * type IDAEwtFn.
+ * The function e takes as input the current dependent variable y.
+ * It must set the vector of error weights used in the WRMS norm:
+ *
+ * ||y||_WRMS = sqrt [ 1/N * sum ( ewt_i * y_i)^2 ]
+ *
+ * Typically, the vector ewt has components:
+ *
+ * ewt_i = 1 / (reltol * |y_i| + abstol_i)
+ *
+ * The user_data parameter is the same as that passed by the user
+ * to the IDASetRdata routine. This user-supplied pointer is
+ * passed to the user's e function every time it is called.
+ * An IDAEwtFn e must return 0 if the error weight vector has been
+ * successfuly set and a non-zero value otherwise.
+ * -----------------------------------------------------------------
+ */
+
+typedef int (*IDAEwtFn)(N_Vector y, N_Vector ewt, void *user_data);
+
+/*
+ * -----------------------------------------------------------------
+ * Type : IDAErrHandlerFn
+ * -----------------------------------------------------------------
+ * A function eh, which handles error messages, must have type
+ * IDAErrHandlerFn.
+ * The function eh takes as input the error code, the name of the
+ * module reporting the error, the error message, and a pointer to
+ * user data, the same as that passed to IDASetRdata.
+ *
+ * All error codes are negative, except IDA_WARNING which indicates
+ * a warning (the solver continues).
+ *
+ * An IDAErrHandlerFn has no return value.
+ * -----------------------------------------------------------------
+ */
+
+typedef void (*IDAErrHandlerFn)(int error_code,
+ const char *module, const char *function,
+ char *msg, void *user_data);
+
+/*
+ * ================================================================
+ * U S E R - C A L L A B L E R O U T I N E S
+ * ================================================================
+ */
+
+/*
+ * ----------------------------------------------------------------
+ * Function : IDACreate
+ * ----------------------------------------------------------------
+ * IDACreate creates an internal memory block for a problem to
+ * be solved by IDA.
+ *
+ * If successful, IDACreate returns a pointer to initialized
+ * problem memory. This pointer should be passed to IDAInit.
+ * If an initialization error occurs, IDACreate prints an error
+ * message to standard err and returns NULL.
+ *
+ * ----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT void *IDACreate(void);
+
+/*
+ * ----------------------------------------------------------------
+ * Integrator optional input specification functions
+ * ----------------------------------------------------------------
+ * The following functions can be called to set optional inputs
+ * to values other than the defaults given below:
+ *
+ * |
+ * Function | Optional input / [ default value ]
+ * |
+ * ----------------------------------------------------------------
+ * |
+ * IDASetErrHandlerFn | user-provided ErrHandler function.
+ * | [internal]
+ * |
+ * IDASetErrFile | the file pointer for an error file
+ * | where all IDA warning and error
+ * | messages will be written if the default
+ * | internal error handling function is used.
+ * | This parameter can be stdout (standard
+ * | output), stderr (standard error), or a
+ * | file pointer (corresponding to a user
+ * | error file opened for writing) returned
+ * | by fopen.
+ * | If not called, then all messages will
+ * | be written to the standard error stream.
+ * | [stderr]
+ * |
+ * IDASetUserData | a pointer to user data that will be
+ * | passed to the user's res function every
+ * | time a user-supplied function is called.
+ * | [NULL]
+ * |
+ * IDASetMaxOrd | maximum lmm order to be used by the
+ * | solver.
+ * | [5]
+ * |
+ * IDASetMaxNumSteps | maximum number of internal steps to be
+ * | taken by the solver in its attempt to
+ * | reach tout.
+ * | [500]
+ * |
+ * IDASetInitStep | initial step size.
+ * | [estimated by IDA]
+ * |
+ * IDASetMaxStep | maximum absolute value of step size
+ * | allowed.
+ * | [infinity]
+ * |
+ * IDASetStopTime | the independent variable value past
+ * | which the solution is not to proceed.
+ * | [infinity]
+ * |
+ * IDASetNonlinConvCoef | Newton convergence test constant
+ * | for use during integration.
+ * | [0.33]
+ * |
+ * IDASetMaxErrTestFails| Maximum number of error test failures
+ * | in attempting one step.
+ * | [10]
+ * |
+ * IDASetMaxNonlinIters | Maximum number of nonlinear solver
+ * | iterations at one solution.
+ * | [4]
+ * |
+ * IDASetMaxConvFails | Maximum number of allowable conv.
+ * | failures in attempting one step.
+ * | [10]
+ * |
+ * IDASetSuppressAlg | flag to indicate whether or not to
+ * | suppress algebraic variables in the
+ * | local error tests:
+ * | FALSE = do not suppress;
+ * | TRUE = do suppress;
+ * | [FALSE]
+ * | NOTE: if suppressed algebraic variables
+ * | is selected, the nvector 'id' must be
+ * | supplied for identification of those
+ * | algebraic components (see IDASetId).
+ * |
+ * IDASetId | an N_Vector, which states a given
+ * | element to be either algebraic or
+ * | differential.
+ * | A value of 1.0 indicates a differential
+ * | variable while a 0.0 indicates an
+ * | algebraic variable. 'id' is required
+ * | if optional input SUPPRESSALG is set,
+ * | or if IDACalcIC is to be called with
+ * | icopt = IDA_YA_YDP_INIT.
+ * |
+ * IDASetConstraints | an N_Vector defining inequality
+ * | constraints for each component of the
+ * | solution vector y. If a given element
+ * | of this vector has values +2 or -2,
+ * | then the corresponding component of y
+ * | will be constrained to be > 0.0 or
+ * | <0.0, respectively, while if it is +1
+ * | or -1, the y component is constrained
+ * | to be >= 0.0 or <= 0.0, respectively.
+ * | If a component of constraints is 0.0,
+ * | then no constraint is imposed on the
+ * | corresponding component of y.
+ * | The presence of a non-NULL constraints
+ * | vector that is not 0.0 (ZERO) in all
+ * | components will cause constraint
+ * | checking to be performed.
+ * |
+ * -----------------------------------------------------------------
+ * |
+ * IDASetRootDirection | Specifies the direction of zero
+ * | crossings to be monitored
+ * | [both directions]
+ * |
+ * IDASetNoInactiveRootWarn | disable warning about possible
+ * | g==0 at beginning of integration
+ * |
+ * -----------------------------------------------------------------
+ * 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
+ *
+ * ----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int IDASetErrHandlerFn(void *ida_mem, IDAErrHandlerFn ehfun, void *eh_data);
+SUNDIALS_EXPORT int IDASetErrFile(void *ida_mem, FILE *errfp);
+SUNDIALS_EXPORT int IDASetUserData(void *ida_mem, void *user_data);
+SUNDIALS_EXPORT int IDASetMaxOrd(void *ida_mem, int maxord);
+SUNDIALS_EXPORT int IDASetMaxNumSteps(void *ida_mem, long int mxsteps);
+SUNDIALS_EXPORT int IDASetInitStep(void *ida_mem, realtype hin);
+SUNDIALS_EXPORT int IDASetMaxStep(void *ida_mem, realtype hmax);
+SUNDIALS_EXPORT int IDASetStopTime(void *ida_mem, realtype tstop);
+SUNDIALS_EXPORT int IDASetNonlinConvCoef(void *ida_mem, realtype epcon);
+SUNDIALS_EXPORT int IDASetMaxErrTestFails(void *ida_mem, int maxnef);
+SUNDIALS_EXPORT int IDASetMaxNonlinIters(void *ida_mem, int maxcor);
+SUNDIALS_EXPORT int IDASetMaxConvFails(void *ida_mem, int maxncf);
+SUNDIALS_EXPORT int IDASetSuppressAlg(void *ida_mem, booleantype suppressalg);
+SUNDIALS_EXPORT int IDASetId(void *ida_mem, N_Vector id);
+SUNDIALS_EXPORT int IDASetConstraints(void *ida_mem, N_Vector constraints);
+
+SUNDIALS_EXPORT int IDASetRootDirection(void *ida_mem, int *rootdir);
+SUNDIALS_EXPORT int IDASetNoInactiveRootWarn(void *ida_mem);
+
+/*
+ * ----------------------------------------------------------------
+ * Function : IDAInit
+ * ----------------------------------------------------------------
+ * IDAInit allocates and initializes memory for a problem to
+ * to be solved by IDA.
+ *
+ * res is the residual function F in F(t,y,y') = 0.
+ *
+ * t0 is the initial value of t, the independent variable.
+ *
+ * yy0 is the initial condition vector y(t0).
+ *
+ * yp0 is the initial condition vector y'(t0)
+ *
+ * IDA_SUCCESS if successful
+ * IDA_MEM_NULL if the ida memory was NULL
+ * IDA_MEM_FAIL if a memory allocation failed
+ * IDA_ILL_INPUT f an argument has an illegal value.
+ *
+ * ----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int IDAInit(void *ida_mem, IDAResFn res,
+ realtype t0, N_Vector yy0, N_Vector yp0);
+
+/*
+ * ----------------------------------------------------------------
+ * Function : IDAReInit
+ * ----------------------------------------------------------------
+ * IDAReInit re-initializes IDA for the solution of a problem,
+ * where a prior call to IDAInit has been made.
+ * IDAReInit performs the same input checking and initializations
+ * that IDAInit does.
+ * But it does no memory allocation, assuming that the existing
+ * internal memory is sufficient for the new problem.
+ *
+ * The use of IDAReInit requires that the maximum method order,
+ * maxord, is no larger for the new problem than for the problem
+ * specified in the last call to IDAInit. This condition is
+ * automatically fulfilled if the default value for maxord is
+ * specified.
+ *
+ * Following the call to IDAReInit, a call to the linear solver
+ * specification routine is necessary if a different linear solver
+ * is chosen, but may not be otherwise. If the same linear solver
+ * is chosen, and there are no changes in its input parameters,
+ * then no call to that routine is needed.
+ *
+ * The first argument to IDAReInit is:
+ *
+ * ida_mem = pointer to IDA memory returned by IDACreate.
+ *
+ * All the remaining arguments to IDAReInit have names and
+ * meanings identical to those of IDAInit.
+ *
+ * The return value of IDAReInit is equal to SUCCESS = 0 if there
+ * were no errors; otherwise it is a negative int equal to:
+ * IDA_MEM_NULL indicating ida_mem was NULL, or
+ * IDA_NO_MALLOC indicating that ida_mem was not allocated.
+ * IDA_ILL_INPUT indicating an input argument was illegal
+ * (including an attempt to increase maxord).
+ * In case of an error return, an error message is also printed.
+ * ----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int IDAReInit(void *ida_mem,
+ realtype t0, N_Vector yy0, N_Vector yp0);
+
+/*
+ * -----------------------------------------------------------------
+ * Functions : IDASStolerances
+ * IDASVtolerances
+ * IDAWFtolerances
+ * -----------------------------------------------------------------
+ *
+ * These functions specify the integration tolerances. One of them
+ * MUST be called before the first call to IDA.
+ *
+ * IDASStolerances specifies scalar relative and absolute tolerances.
+ * IDASVtolerances specifies scalar relative tolerance and a vector
+ * absolute tolerance (a potentially different absolute tolerance
+ * for each vector component).
+ * IDAWFtolerances specifies a user-provides function (of type IDAEwtFn)
+ * which will be called to set the error weight vector.
+ *
+ * The tolerances reltol and abstol define a vector of error weights,
+ * ewt, with components
+ * ewt[i] = 1/(reltol*abs(y[i]) + abstol) (in the SS case), or
+ * ewt[i] = 1/(reltol*abs(y[i]) + abstol[i]) (in the SV case).
+ * This vector is used in all error and convergence tests, which
+ * use a weighted RMS norm on all error-like vectors v:
+ * WRMSnorm(v) = sqrt( (1/N) sum(i=1..N) (v[i]*ewt[i])^2 ),
+ * where N is the problem dimension.
+ *
+ * The return value of these functions is equal to IDA_SUCCESS = 0 if
+ * there were no errors; otherwise it is a negative int equal to:
+ * IDa_MEM_NULL indicating ida_mem was NULL (i.e.,
+ * IDACreate has not been called).
+ * IDA_NO_MALLOC indicating that ida_mem has not been
+ * allocated (i.e., IDAInit has not been
+ * called).
+ * IDA_ILL_INPUT indicating an input argument was illegal
+ * (e.g. a negative tolerance)
+ * In case of an error return, an error message is also printed.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int IDASStolerances(void *ida_mem, realtype reltol, realtype abstol);
+SUNDIALS_EXPORT int IDASVtolerances(void *ida_mem, realtype reltol, N_Vector abstol);
+SUNDIALS_EXPORT int IDAWFtolerances(void *ida_mem, IDAEwtFn efun);
+
+/* ----------------------------------------------------------------
+ * Initial Conditions optional input specification functions
+ * ----------------------------------------------------------------
+ * The following functions can be called to set optional inputs
+ * to control the initial conditions calculations.
+ *
+ * |
+ * Function | Optional input / [ default value ]
+ * |
+ * --------------------------------------------------------------
+ * |
+ * IDASetNonlinConvCoefIC | positive coeficient in the Newton
+ * | convergence test. This test uses a
+ * | weighted RMS norm (with weights
+ * | defined by the tolerances, as in
+ * | IDASolve). For new initial value
+ * | vectors y and y' to be accepted, the
+ * | norm of J-inverse F(t0,y,y') is
+ * | required to be less than epiccon,
+ * | where J is the system Jacobian.
+ * | [0.01 * 0.33]
+ * |
+ * IDASetMaxNumStepsIC | maximum number of values of h allowed
+ * | when icopt = IDA_YA_YDP_INIT, where
+ * | h appears in the system Jacobian,
+ * | J = dF/dy + (1/h)dF/dy'.
+ * | [5]
+ * |
+ * IDASetMaxNumJacsIC | maximum number of values of the
+ * | approximate Jacobian or preconditioner
+ * | allowed, when the Newton iterations
+ * | appear to be slowly converging.
+ * | [4]
+ * |
+ * IDASetMaxNumItersIC | maximum number of Newton iterations
+ * | allowed in any one attempt to solve
+ * | the IC problem.
+ * | [10]
+ * |
+ * IDASetLineSearchOffIC | a boolean flag to turn off the
+ * | linesearch algorithm.
+ * | [FALSE]
+ * |
+ * IDASetStepToleranceIC | positive lower bound on the norm of
+ * | a Newton step.
+ * | [(unit roundoff)^(2/3)
+ *
+ * ----------------------------------------------------------------
+ * 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
+ *
+ * ----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int IDASetNonlinConvCoefIC(void *ida_mem, realtype epiccon);
+SUNDIALS_EXPORT int IDASetMaxNumStepsIC(void *ida_mem, int maxnh);
+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);
+
+/*
+ * -----------------------------------------------------------------
+ * Function : IDARootInit
+ * -----------------------------------------------------------------
+ * IDARootInit initializes a rootfinding problem to be solved
+ * during the integration of the DAE system. It must be called
+ * after IDACreate, and before IDASolve. The arguments are:
+ *
+ * ida_mem = pointer to IDA memory returned by IDACreate.
+ *
+ * nrtfn = number of functions g_i, an int >= 0.
+ *
+ * g = name of user-supplied function, of type IDARootFn,
+ * defining the functions g_i whose roots are sought.
+ *
+ * If a new problem is to be solved with a call to IDAReInit,
+ * where the new problem has no root functions but the prior one
+ * did, then call IDARootInit with nrtfn = 0.
+ *
+ * The return value of IDARootInit is IDA_SUCCESS = 0 if there were
+ * no errors; otherwise it is a negative int equal to:
+ * IDA_MEM_NULL indicating ida_mem was NULL, or
+ * IDA_MEM_FAIL indicating a memory allocation failed.
+ * (including an attempt to increase maxord).
+ * IDA_ILL_INPUT indicating nrtfn > 0 but g = NULL.
+ * In case of an error return, an error message is also printed.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int IDARootInit(void *ida_mem, int nrtfn, IDARootFn g);
+
+/*
+ * ----------------------------------------------------------------
+ * Function : IDACalcIC
+ * ----------------------------------------------------------------
+ * IDACalcIC calculates corrected initial conditions for the DAE
+ * system for a class of index-one problems of semi-implicit form.
+ * It uses Newton iteration combined with a Linesearch algorithm.
+ * Calling IDACalcIC is optional. It is only necessary when the
+ * initial conditions do not solve the given system. I.e., if
+ * y0 and yp0 are known to satisfy F(t0, y0, yp0) = 0, then
+ * a call to IDACalcIC is NOT necessary (for index-one problems).
+ *
+ * A call to IDACalcIC must be preceded by a successful call to
+ * IDAInit or IDAReInit for the given DAE problem, and by a
+ * successful call to the linear system solver specification
+ * routine.
+ *
+ * The call to IDACalcIC should precede the call(s) to IDASolve
+ * for the given problem.
+ *
+ * The arguments to IDACalcIC are as follows:
+ *
+ * ida_mem is the pointer to IDA memory returned by IDACreate.
+ *
+ * icopt is the option of IDACalcIC to be used.
+ * icopt = IDA_YA_YDP_INIT directs IDACalcIC to compute
+ * the algebraic components of y and differential
+ * components of y', given the differential
+ * components of y. This option requires that the
+ * N_Vector id was set through a call to IDASetId
+ * specifying the differential and algebraic
+ * components.
+ * icopt = IDA_Y_INIT directs IDACalcIC to compute all
+ * components of y, given y'. id is not required.
+ *
+ * tout1 is the first value of t at which a soluton will be
+ * requested (from IDASolve). (This is needed here to
+ * determine the direction of integration and rough scale
+ * in the independent variable t.)
+ *
+ *
+ * IDACalcIC returns an int flag. Its symbolic values and their
+ * meanings are as follows. (The numerical return values are set
+ * above in this file.) All unsuccessful returns give a negative
+ * return value. If IFACalcIC failed, y0 and yp0 contain
+ * (possibly) altered values, computed during the attempt.
+ *
+ * IDA_SUCCESS IDACalcIC was successful. The corrected
+ * initial value vectors were stored internally.
+ *
+ * IDA_MEM_NULL The argument ida_mem was NULL.
+ *
+ * IDA_ILL_INPUT One of the input arguments was illegal.
+ * See printed message.
+ *
+ * IDA_LINIT_FAIL The linear solver's init routine failed.
+ *
+ * IDA_BAD_EWT Some component of the error weight vector
+ * is zero (illegal), either for the input
+ * value of y0 or a corrected value.
+ *
+ * IDA_RES_FAIL The user's residual routine returned
+ * a non-recoverable error flag.
+ *
+ * IDA_FIRST_RES_FAIL The user's residual routine returned
+ * a recoverable error flag on the first call,
+ * but IDACalcIC was unable to recover.
+ *
+ * IDA_LSETUP_FAIL The linear solver's setup routine had a
+ * non-recoverable error.
+ *
+ * IDA_LSOLVE_FAIL The linear solver's solve routine had a
+ * non-recoverable error.
+ *
+ * IDA_NO_RECOVERY The user's residual routine, or the linear
+ * solver's setup or solve routine had a
+ * recoverable error, but IDACalcIC was
+ * unable to recover.
+ *
+ * IDA_CONSTR_FAIL IDACalcIC was unable to find a solution
+ * satisfying the inequality constraints.
+ *
+ * IDA_LINESEARCH_FAIL The Linesearch algorithm failed to find a
+ * solution with a step larger than steptol
+ * in weighted RMS norm.
+ *
+ * IDA_CONV_FAIL IDACalcIC failed to get convergence of the
+ * Newton iterations.
+ *
+ * ----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int IDACalcIC(void *ida_mem, int icopt, realtype tout1);
+
+/*
+ * ----------------------------------------------------------------
+ * Function : IDASolve
+ * ----------------------------------------------------------------
+ * IDASolve integrates the DAE over an interval in t, the
+ * independent variable. If itask is IDA_NORMAL, then the solver
+ * integrates from its current internal t value to a point at or
+ * beyond tout, then interpolates to t = tout and returns y(tret)
+ * in the user-allocated vector yret. In general, tret = tout.
+ * If itask is IDA_ONE_STEP, then the solver takes one internal
+ * step of the independent variable and returns in yret the value
+ * of y at the new internal independent variable value. In this
+ * case, tout is used only during the first call to IDASolve to
+ * determine the direction of integration and the rough scale of
+ * the problem. If tstop is enabled (through a call to IDASetStopTime),
+ * then IDASolve returns the solution at tstop. Once the integrator
+ * returns at a tstop time, any future testing for tstop is disabled
+ * (and can be reenabled only though a new call to IDASetStopTime).
+ * The time reached by the solver is placed in (*tret). The
+ * user is responsible for allocating the memory for this value.
+ *
+ * ida_mem is the pointer (void) to IDA memory returned by
+ * IDACreate.
+ *
+ * tout is the next independent variable value at which a
+ * computed solution is desired.
+ *
+ * tret is a pointer to a real location. IDASolve sets (*tret)
+ * to the actual t value reached, corresponding to the
+ * solution vector yret. In IDA_NORMAL mode, with no
+ * errors and no roots found, (*tret) = tout.
+ *
+ * yret is the computed solution vector. With no errors,
+ * yret = y(tret).
+ *
+ * ypret is the derivative of the computed solution at t = tret.
+ *
+ * Note: yret and ypret may be the same N_Vectors as y0 and yp0
+ * in the call to IDAInit or IDAReInit.
+ *
+ * itask is IDA_NORMAL or IDA_ONE_STEP. These two modes are described above.
+ *
+ *
+ * The return values for IDASolve are described below.
+ * (The numerical return values are defined above in this file.)
+ * All unsuccessful returns give a negative return value.
+ *
+ * IDA_SUCCESS
+ * IDASolve succeeded and no roots were found.
+ *
+ * IDA_ROOT_RETURN: IDASolve succeeded, and found one or more roots.
+ * If nrtfn > 1, call IDAGetRootInfo to see which g_i were found
+ * to have a root at (*tret).
+ *
+ * IDA_TSTOP_RETURN:
+ * IDASolve returns computed results for the independent variable
+ * value tstop. That is, tstop was reached.
+ *
+ * IDA_MEM_NULL:
+ * The IDA_mem argument was NULL.
+ *
+ * IDA_ILL_INPUT:
+ * One of the inputs to IDASolve is illegal. This includes the
+ * situation when a component of the error weight vectors
+ * becomes < 0 during internal stepping. It also includes the
+ * situation where a root of one of the root functions was found
+ * both at t0 and very near t0. The ILL_INPUT flag
+ * will also be returned if the linear solver function IDA---
+ * (called by the user after calling IDACreate) failed to set one
+ * of the linear solver-related fields in ida_mem or if the linear
+ * solver's init routine failed. In any case, the user should see
+ * the printed error message for more details.
+ *
+ * IDA_TOO_MUCH_WORK:
+ * The solver took mxstep internal steps but could not reach tout.
+ * The default value for mxstep is MXSTEP_DEFAULT = 500.
+ *
+ * IDA_TOO_MUCH_ACC:
+ * The solver could not satisfy the accuracy demanded by the user
+ * for some internal step.
+ *
+ * IDA_ERR_FAIL:
+ * Error test failures occurred too many times (=MXETF = 10) during
+ * one internal step.
+ *
+ * IDA_CONV_FAIL:
+ * Convergence test failures occurred too many times (= MXNCF = 10)
+ * during one internal step.
+ *
+ * IDA_LSETUP_FAIL:
+ * The linear solver's setup routine failed
+ * in an unrecoverable manner.
+ *
+ * IDA_LSOLVE_FAIL:
+ * The linear solver's solve routine failed
+ * in an unrecoverable manner.
+ *
+ * IDA_CONSTR_FAIL:
+ * The inequality constraints were violated,
+ * and the solver was unable to recover.
+ *
+ * IDA_REP_RES_ERR:
+ * The user's residual function repeatedly returned a recoverable
+ * error flag, but the solver was unable to recover.
+ *
+ * IDA_RES_FAIL:
+ * The user's residual function returned a nonrecoverable error
+ * flag.
+ *
+ * ----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int IDASolve(void *ida_mem, realtype tout, realtype *tret,
+ N_Vector yret, N_Vector ypret, int itask);
+
+/*
+ * ----------------------------------------------------------------
+ * Function: IDAGetDky
+ * ----------------------------------------------------------------
+ *
+ * This routine computes the k-th derivative of the interpolating
+ * polynomial at the time t and stores the result in the vector dky.
+ *
+ * The return values are:
+ * IDA_SUCCESS: succeess.
+ * IDA_BAD_T: t is not in the interval [tn-hu,tn].
+ * IDA_MEM_NULL: The ida_mem argument was NULL.
+ * IDA_BAD_DKY if the dky vector is NULL.
+ * IDA_BAD_K if the requested k is not in the range 0,1,...,order used
+ *
+ * ----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int IDAGetDky(void *ida_mem, realtype t, int k, N_Vector dky);
+
+/* ----------------------------------------------------------------
+ * Integrator optional output extraction functions
+ * ----------------------------------------------------------------
+ *
+ * The following functions can be called to get optional outputs
+ * and statistics related to the main integrator.
+ * ----------------------------------------------------------------
+ *
+ * IDAGetWorkSpace returns the IDA real and integer workspace sizes
+ * IDAGetNumSteps returns the cumulative number of internal
+ * steps taken by the solver
+ * IDAGetNumRhsEvals returns the number of calls to the user's
+ * res function
+ * IDAGetNumLinSolvSetups returns the number of calls made to
+ * the linear solver's setup routine
+ * IDAGetNumErrTestFails returns the number of local error test
+ * failures that have occured
+ * IDAGetNumBacktrackOps returns the number of backtrack
+ * operations done in the linesearch algorithm in IDACalcIC
+ * IDAGetConsistentIC returns the consistent initial conditions
+ * computed by IDACalcIC
+ * IDAGetLastOrder returns the order used during the last
+ * internal step
+ * IDAGetCurentOrder returns the order to be used on the next
+ * internal step
+ * IDAGetActualInitStep returns the actual initial step size
+ * used by IDA
+ * IDAGetLAstStep returns the step size for the last internal
+ * step (if from IDASolve), or the last value of the
+ * artificial step size h (if from IDACalcIC)
+ * IDAGetCurrentStep returns the step size to be attempted on the
+ * next internal step
+ * IDAGetCurrentTime returns the current internal time reached
+ * by the solver
+ * IDAGetTolScaleFactor returns a suggested factor by which the
+ * user's tolerances should be scaled when too much
+ * accuracy has been requested for some internal step
+ * IDAGetErrWeights returns the current state error weight vector.
+ * The user must allocate space for eweight.
+ * IDAGetEstLocalErrors returns the estimated local errors. The user
+ * must allocate space for the vector ele.
+ * IDAGetNumGEvals returns the number of calls to the user's
+ * g function (for rootfinding)
+ * IDAGetRootInfo returns the indices for which g_i was found to
+ * have a root. The user must allocate space for rootsfound.
+ * For i = 0 ... nrtfn-1, rootsfound[i] = 1 if g_i has a root,
+ * and rootsfound[i]= 0 if not.
+ *
+ * IDAGet* return values:
+ * IDA_SUCCESS if succesful
+ * IDA_MEM_NULL if the ida memory was NULL
+ * IDA_ILL_INPUT if some input is illegal
+ *
+ * ----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int IDAGetWorkSpace(void *ida_mem, long int *lenrw, long int *leniw);
+SUNDIALS_EXPORT int IDAGetNumSteps(void *ida_mem, long int *nsteps);
+SUNDIALS_EXPORT int IDAGetNumResEvals(void *ida_mem, long int *nrevals);
+SUNDIALS_EXPORT int IDAGetNumLinSolvSetups(void *ida_mem, long int *nlinsetups);
+SUNDIALS_EXPORT int IDAGetNumErrTestFails(void *ida_mem, long int *netfails);
+SUNDIALS_EXPORT int IDAGetNumBacktrackOps(void *ida_mem, long int *nbacktr);
+SUNDIALS_EXPORT int IDAGetConsistentIC(void *ida_mem, N_Vector yy0_mod, N_Vector yp0_mod);
+SUNDIALS_EXPORT int IDAGetLastOrder(void *ida_mem, int *klast);
+SUNDIALS_EXPORT int IDAGetCurrentOrder(void *ida_mem, int *kcur);
+SUNDIALS_EXPORT int IDAGetActualInitStep(void *ida_mem, realtype *hinused);
+SUNDIALS_EXPORT int IDAGetLastStep(void *ida_mem, realtype *hlast);
+SUNDIALS_EXPORT int IDAGetCurrentStep(void *ida_mem, realtype *hcur);
+SUNDIALS_EXPORT int IDAGetCurrentTime(void *ida_mem, realtype *tcur);
+SUNDIALS_EXPORT int IDAGetTolScaleFactor(void *ida_mem, realtype *tolsfact);
+SUNDIALS_EXPORT int IDAGetErrWeights(void *ida_mem, N_Vector eweight);
+SUNDIALS_EXPORT int IDAGetEstLocalErrors(void *ida_mem, N_Vector ele);
+SUNDIALS_EXPORT int IDAGetNumGEvals(void *ida_mem, long int *ngevals);
+SUNDIALS_EXPORT int IDAGetRootInfo(void *ida_mem, int *rootsfound);
+
+/*
+ * ----------------------------------------------------------------
+ * As a convenience, the following function provides the
+ * optional outputs in a group.
+ * ----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int IDAGetIntegratorStats(void *ida_mem, long int *nsteps,
+ long int *nrevals, long int *nlinsetups,
+ long int *netfails, int *qlast, int *qcur,
+ realtype *hinused, realtype *hlast, realtype *hcur,
+ realtype *tcur);
+
+/*
+ * ----------------------------------------------------------------
+ * Nonlinear solver optional output extraction functions
+ * ----------------------------------------------------------------
+ *
+ * The following functions can be called to get optional outputs
+ * and statistics related to the nonlinear solver.
+ * --------------------------------------------------------------
+ *
+ * IDAGetNumNonlinSolvIters returns the number of nonlinear
+ * solver iterations performed.
+ * IDAGetNumNonlinSolvConvFails returns the number of nonlinear
+ * convergence failures.
+ *
+ * ----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int IDAGetNumNonlinSolvIters(void *ida_mem, long int *nniters);
+SUNDIALS_EXPORT int IDAGetNumNonlinSolvConvFails(void *ida_mem, long int *nncfails);
+
+/*
+ * ----------------------------------------------------------------
+ * As a convenience, the following function provides the
+ * nonlinear solver optional outputs in a group.
+ * ----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int IDAGetNonlinSolvStats(void *ida_mem, long int *nniters,
+ long int *nncfails);
+
+/*
+ * -----------------------------------------------------------------
+ * The following function returns the name of the constant
+ * associated with an IDA return flag
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT char *IDAGetReturnFlagName(long int flag);
+
+/*
+ * ----------------------------------------------------------------
+ * Function : IDAFree
+ * ----------------------------------------------------------------
+ * IDAFree frees the problem memory IDA_mem allocated by
+ * IDAInit. Its only argument is the pointer idamem
+ * returned by IDAInit.
+ * ----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT void IDAFree(void **ida_mem);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/ida/ida_band.h b/include/ida/ida_band.h
new file mode 100644
index 0000000..aecbf4d
--- /dev/null
+++ b/include/ida/ida_band.h
@@ -0,0 +1,59 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.6 $
+ * $Date: 2010/12/01 22:14:08 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Alan C. Hindmarsh, and Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * This is the header file for the IDABAND linear solver module.
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _IDABAND_H
+#define _IDABAND_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <ida/ida_direct.h>
+#include <sundials/sundials_band.h>
+
+/*
+ * -----------------------------------------------------------------
+ * 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
new file mode 100644
index 0000000..2a4f646
--- /dev/null
+++ b/include/ida/ida_bbdpre.h
@@ -0,0 +1,275 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.8 $
+ * $Date: 2010/12/01 22:14:08 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Alan C. Hindmarsh, Radu Serban and
+ * Aaron Collier @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * 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.
+ *
+ * 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 <ida/ida_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.
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _IDABBDPRE_H
+#define _IDABBDPRE_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <sundials/sundials_nvector.h>
+
+/*
+ * -----------------------------------------------------------------
+ * 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
+ * IDASetRdata 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)(long int 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.
+ * -----------------------------------------------------------------
+ */
+
+typedef int (*IDABBDCommFn)(long int Nlocal, realtype tt,
+ N_Vector yy, N_Vector yp,
+ void *user_data);
+
+/*
+ * -----------------------------------------------------------------
+ * 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,
+ realtype dq_rel_yy,
+ 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
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int IDABBDPrecReInit(void *ida_mem,
+ long int mudq, long int 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
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int IDABBDPrecGetWorkSpace(void *ida_mem,
+ long int *lenrwBBDP, long int *leniwBBDP);
+SUNDIALS_EXPORT int IDABBDPrecGetNumGfnEvals(void *ida_mem, long int *ngevalsBBDP);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/ida/ida_dense.h b/include/ida/ida_dense.h
new file mode 100644
index 0000000..20b3b4a
--- /dev/null
+++ b/include/ida/ida_dense.h
@@ -0,0 +1,58 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.6 $
+ * $Date: 2010/12/01 22:14:09 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Alan C. Hindmarsh and Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * This is the header file for the IDADENSE linear solver module.
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _IDADENSE_H
+#define _IDADENSE_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <ida/ida_direct.h>
+#include <sundials/sundials_dense.h>
+
+/*
+ * -----------------------------------------------------------------
+ * 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
new file mode 100644
index 0000000..2b68306
--- /dev/null
+++ b/include/ida/ida_direct.h
@@ -0,0 +1,300 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.7 $
+ * $Date: 2010/12/01 22:14:09 $
+ * -----------------------------------------------------------------
+ * Programmer: Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2006, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * Common header file for the direct linear solvers in IDA.
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _IDADLS_H
+#define _IDADLS_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <sundials/sundials_direct.h>
+#include <sundials/sundials_nvector.h>
+
+/*
+ * =================================================================
+ * I D A D I R E C T C O N S T A N T S
+ * =================================================================
+ */
+
+/*
+ * -----------------------------------------------------------------
+ * IDADLS 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
+
+/*
+ * =================================================================
+ * 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).
+ *
+ * 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 IDASetRdata.
+ *
+ * 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 IDASetRdata.
+ *
+ * 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
+ *
+ * -----------------------------------------------------------------
+ */
+
+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
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT char *IDADlsGetReturnFlagName(long int flag);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/ida/ida_lapack.h b/include/ida/ida_lapack.h
new file mode 100644
index 0000000..a50ed5c
--- /dev/null
+++ b/include/ida/ida_lapack.h
@@ -0,0 +1,80 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.4 $
+ * $Date: 2008/04/18 19:42:37 $
+ * -----------------------------------------------------------------
+ * Programmer: Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2006, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * Header file for the IDA dense linear solver IDALAPACK.
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _IDALAPACK_H
+#define _IDALAPACK_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <ida/ida_direct.h>
+#include <sundials/sundials_lapack.h>
+
+/*
+ * -----------------------------------------------------------------
+ * 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_spbcgs.h b/include/ida/ida_spbcgs.h
new file mode 100644
index 0000000..f733a11
--- /dev/null
+++ b/include/ida/ida_spbcgs.h
@@ -0,0 +1,59 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.2 $
+ * $Date: 2006/11/29 00:05:06 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Aaron Collier @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2004, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * This is the public header file for the IDA scaled preconditioned
+ * Bi-CGSTAB linear solver module, IDASPBCG.
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _IDASPBCG_H
+#define _IDASPBCG_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <ida/ida_spils.h>
+#include <sundials/sundials_spbcgs.h>
+
+/*
+ * -----------------------------------------------------------------
+ * 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
new file mode 100644
index 0000000..3604028
--- /dev/null
+++ b/include/ida/ida_spgmr.h
@@ -0,0 +1,60 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.2 $
+ * $Date: 2006/11/29 00:05:06 $
+ * -----------------------------------------------------------------
+ * Programmers: Alan C. Hindmarsh and Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California
+ * Produced at the Lawrence Livermore National Laboratory
+ * All rights reserved
+ * For details, see the LICENSE file
+ * -----------------------------------------------------------------
+ * This is the header file for the IDA Scaled Preconditioned GMRES
+ * linear solver module, IDASPGMR.
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _IDASPGMR_H
+#define _IDASPGMR_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <ida/ida_spils.h>
+#include <sundials/sundials_spgmr.h>
+
+/*
+ * -----------------------------------------------------------------
+ *
+ * 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
new file mode 100644
index 0000000..3b53b01
--- /dev/null
+++ b/include/ida/ida_spils.h
@@ -0,0 +1,321 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.9 $
+ * $Date: 2010/12/01 22:14:09 $
+ * -----------------------------------------------------------------
+ * Programmers: Alan Hindmarsh, Radu Serban and Aaron Collier @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California
+ * Produced at the Lawrence Livermore National Laboratory
+ * All rights reserved
+ * For details, see the LICENSE file
+ * -----------------------------------------------------------------
+ * This is the common header file for the Scaled and Preconditioned
+ * Iterative Linear Solvers in IDA.
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _IDASPILS_H
+#define _IDASPILS_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <sundials/sundials_iterative.h>
+#include <sundials/sundials_nvector.h>
+
+/*
+ * -----------------------------------------------------------------
+ * IDASPILS return values
+ * -----------------------------------------------------------------
+ */
+
+#define IDASPILS_SUCCESS 0
+#define IDASPILS_MEM_NULL -1
+#define IDASPILS_LMEM_NULL -2
+#define IDASPILS_ILL_INPUT -3
+#define IDASPILS_MEM_FAIL -4
+#define IDASPILS_PMEM_NULL -5
+
+/*
+ * -----------------------------------------------------------------
+ * 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);
+
+/*
+ * -----------------------------------------------------------------
+ * 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,
+ 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,
+ 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
+ * -----------------------------------------------------------------
+ */
+
+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 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
+}
+#endif
+
+#endif
diff --git a/include/ida/ida_sptfqmr.h b/include/ida/ida_sptfqmr.h
new file mode 100644
index 0000000..a7a32b5
--- /dev/null
+++ b/include/ida/ida_sptfqmr.h
@@ -0,0 +1,59 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.2 $
+ * $Date: 2006/11/29 00:05:07 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Aaron Collier @ 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.
+ * -----------------------------------------------------------------
+ * This is the public header file for the IDA scaled preconditioned
+ * TFQMR linear solver module, IDASPTFQMR.
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _IDASPTFQMR_H
+#define _IDASPTFQMR_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <ida/ida_spils.h>
+#include <sundials/sundials_sptfqmr.h>
+
+/*
+ * -----------------------------------------------------------------
+ * 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/idas/idas.h b/include/idas/idas.h
new file mode 100644
index 0000000..6f1ac11
--- /dev/null
+++ b/include/idas/idas.h
@@ -0,0 +1,2099 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.26 $
+ * $Date: 2010/12/01 22:15:15 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California
+ * Produced at the Lawrence Livermore National Laboratory
+ * All rights reserved
+ * For details, see the LICENSE file
+ * -----------------------------------------------------------------
+ * This is the header (include) file for the main IDAS solver.
+ * -----------------------------------------------------------------
+ *
+ * IDAS is used to solve numerically the initial value problem
+ * for the differential algebraic equation (DAE) system
+ * F(t,y,y') = 0,
+ * given initial conditions
+ * y(t0) = y0, y'(t0) = yp0.
+ * Here y and F are vectors of length N.
+ *
+ * Additionally, IDAS can perform forward or adjoint sensitivity
+ * analysis.
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _IDAS_H
+#define _IDAS_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <stdio.h>
+#include <sundials/sundials_nvector.h>
+
+/* * =================================================================
+ * I D A S C O N S T A N T S
+ * =================================================================
+ */
+
+/*
+ * ----------------------------------------------------------------
+ * Inputs to:
+ * IDAInit, IDAReInit,
+ * IDASensInit, IDASensReInit,
+ * IDAQuadInit, IDAQuadReInit,
+ * IDAQuadSensInit, IDAQuadSensReInit,
+ * IDACalcIC, IDASolve,
+ * IDAAdjInit
+ * ----------------------------------------------------------------
+ */
+
+/* itask */
+#define IDA_NORMAL 1
+#define IDA_ONE_STEP 2
+
+/* icopt */
+#define IDA_YA_YDP_INIT 1
+#define IDA_Y_INIT 2
+
+/* ism */
+#define IDA_SIMULTANEOUS 1
+#define IDA_STAGGERED 2
+
+/* DQtype */
+#define IDA_CENTERED 1
+#define IDA_FORWARD 2
+
+/* interp */
+#define IDA_HERMITE 1
+#define IDA_POLYNOMIAL 2
+
+/*
+ * ===============================================================
+ * IDAS RETURN VALUES
+ * ===============================================================
+ */
+
+#define IDA_SUCCESS 0
+#define IDA_TSTOP_RETURN 1
+#define IDA_ROOT_RETURN 2
+
+#define IDA_WARNING 99
+
+#define IDA_TOO_MUCH_WORK -1
+#define IDA_TOO_MUCH_ACC -2
+#define IDA_ERR_FAIL -3
+#define IDA_CONV_FAIL -4
+
+#define IDA_LINIT_FAIL -5
+#define IDA_LSETUP_FAIL -6
+#define IDA_LSOLVE_FAIL -7
+#define IDA_RES_FAIL -8
+#define IDA_REP_RES_ERR -9
+#define IDA_RTFUNC_FAIL -10
+#define IDA_CONSTR_FAIL -11
+
+#define IDA_FIRST_RES_FAIL -12
+#define IDA_LINESEARCH_FAIL -13
+#define IDA_NO_RECOVERY -14
+
+#define IDA_MEM_NULL -20
+#define IDA_MEM_FAIL -21
+#define IDA_ILL_INPUT -22
+#define IDA_NO_MALLOC -23
+#define IDA_BAD_EWT -24
+#define IDA_BAD_K -25
+#define IDA_BAD_T -26
+#define IDA_BAD_DKY -27
+
+#define IDA_NO_QUAD -30
+#define IDA_QRHS_FAIL -31
+#define IDA_FIRST_QRHS_ERR -32
+#define IDA_REP_QRHS_ERR -33
+
+#define IDA_NO_SENS -40
+#define IDA_SRES_FAIL -41
+#define IDA_REP_SRES_ERR -42
+#define IDA_BAD_IS -43
+
+#define IDA_NO_QUADSENS -50
+#define IDA_QSRHS_FAIL -51
+#define IDA_FIRST_QSRHS_ERR -52
+#define IDA_REP_QSRHS_ERR -53
+
+/*
+ * -----------------------------------------
+ * IDAA return flags
+ * -----------------------------------------
+ */
+
+#define IDA_NO_ADJ -101
+#define IDA_NO_FWD -102
+#define IDA_NO_BCK -103
+#define IDA_BAD_TB0 -104
+#define IDA_REIFWD_FAIL -105
+#define IDA_FWD_FAIL -106
+#define IDA_GETY_BADT -107
+
+/*
+ * =================================================================
+ * F U N C T I O N T Y P E S
+ * =================================================================
+ */
+
+/*
+ * ----------------------------------------------------------------
+ * Type : IDAResFn
+ * ----------------------------------------------------------------
+ * The F function which defines the DAE system F(t,y,y')=0
+ * must have type IDAResFn.
+ * Symbols are as follows:
+ * t <-> t y <-> yy
+ * y' <-> yp F <-> rr
+ * A IDAResFn takes as input the independent variable value t,
+ * the dependent variable vector yy, and the derivative (with
+ * respect to t) of the yy vector, yp. It stores the result of
+ * F(t,y,y') in the vector rr. The yy, yp, and rr arguments are of
+ * type N_Vector. The user_data parameter is the pointer user_data
+ * passed by the user to the IDASetUserData routine. This user-supplied
+ * pointer is passed to the user's res function every time it is called,
+ * to provide access in res to user data.
+ *
+ * A IDAResFn res should return a value of 0 if successful, a positive
+ * value if a recoverable error occured (e.g. yy has an illegal value),
+ * or a negative value if a nonrecoverable error occured. In the latter
+ * case, the program halts. If a recoverable error occured, the integrator
+ * will attempt to correct and retry.
+ * ----------------------------------------------------------------
+ */
+
+typedef int (*IDAResFn)(realtype tt, N_Vector yy, N_Vector yp,
+ N_Vector rr, void *user_data);
+
+/*
+ * -----------------------------------------------------------------
+ * Type : IDARootFn
+ * -----------------------------------------------------------------
+ * A function g, which defines a set of functions g_i(t,y,y') whose
+ * roots are sought during the integration, must have type IDARootFn.
+ * The function g takes as input the independent variable value t,
+ * the dependent variable vector y, and its t-derivative yp (= y').
+ * It stores the nrtfn values g_i(t,y,y') in the realtype array gout.
+ * (Allocation of memory for gout is handled within IDA.)
+ * The user_data parameter is the same as that passed by the user
+ * to the IDASetUserData routine. This user-supplied pointer is
+ * passed to the user's g function every time it is called.
+ *
+ * An IDARootFn should return 0 if successful or a non-zero value
+ * if an error occured (in which case the integration will be halted).
+ * -----------------------------------------------------------------
+ */
+
+typedef int (*IDARootFn)(realtype t, N_Vector y, N_Vector yp,
+ realtype *gout, void *user_data);
+
+/*
+ * -----------------------------------------------------------------
+ * Type : IDAEwtFn
+ * -----------------------------------------------------------------
+ * A function e, which sets the error weight vector ewt, must have
+ * type IDAEwtFn.
+ * The function e takes as input the current dependent variable y.
+ * It must set the vector of error weights used in the WRMS norm:
+ *
+ * ||y||_WRMS = sqrt [ 1/N * sum ( ewt_i * y_i)^2 ]
+ *
+ * Typically, the vector ewt has components:
+ *
+ * ewt_i = 1 / (reltol * |y_i| + abstol_i)
+ *
+ * The user_data parameter is the same as that passed by the user
+ * to the IDASetUserData routine. This user-supplied pointer is
+ * passed to the user's e function every time it is called.
+ * An IDAEwtFn e must return 0 if the error weight vector has been
+ * successfuly set and a non-zero value otherwise.
+ * -----------------------------------------------------------------
+ */
+
+typedef int (*IDAEwtFn)(N_Vector y, N_Vector ewt, void *user_data);
+
+/*
+ * -----------------------------------------------------------------
+ * Type : IDAErrHandlerFn
+ * -----------------------------------------------------------------
+ * A function eh, which handles error messages, must have type
+ * IDAErrHandlerFn.
+ * The function eh takes as input the error code, the name of the
+ * module reporting the error, the error message, and a pointer to
+ * user data, the same as that passed to IDASetUserData.
+ *
+ * All error codes are negative, except IDA_WARNING which indicates
+ * a warning (the solver continues).
+ *
+ * An IDAErrHandlerFn has no return value.
+ * -----------------------------------------------------------------
+ */
+
+typedef void (*IDAErrHandlerFn)(int error_code,
+ const char *module, const char *function,
+ char *msg, void *user_data);
+
+/*
+ * -----------------------------------------------------------------
+ * Type : IDAQuadRhsFn
+ * -----------------------------------------------------------------
+ * The rhsQ function which defines the right hand side of the
+ * quadrature equations yQ' = rhsQ(t,y) must have type IDAQuadRhsFn.
+ * rhsQ takes as input the value of the independent variable t,
+ * the vector of states y and y' and must store the result of rhsQ in
+ * rrQ. (Allocation of memory for rrQ is handled by IDAS).
+ *
+ * The user_data parameter is the same as the user_data parameter
+ * set by the user through the IDASetUserData routine and is
+ * passed to the rhsQ function every time it is called.
+ *
+ * A function of type IDAQuadRhsFn should return 0 if successful,
+ * a negative value if an unrecoverable error occured, and a positive
+ * value if a recoverable error (e.g. invalid y values) occured.
+ * If an unrecoverable occured, the integration is halted.
+ * If a recoverable error occured, then (in most cases) IDAS will
+ * try to correct and retry.
+ * -----------------------------------------------------------------
+ */
+
+typedef int (*IDAQuadRhsFn)(realtype tres,
+ N_Vector yy, N_Vector yp,
+ N_Vector rrQ,
+ void *user_data);
+
+/*
+ * -----------------------------------------------------------------
+ * Type : IDASensResFn
+ * -----------------------------------------------------------------
+ * The resS function which defines the right hand side of the
+ * sensitivity DAE systems F_y * s + F_y' * s' + F_p = 0
+ * must have type IDASensResFn.
+ *
+ * resS takes as input the number of sensitivities Ns, the
+ * independent variable value t, the states yy and yp and the
+ * corresponding value of the residual in resval, and the dependent
+ * sensitivity vectors yyS and ypS. It stores the residual in
+ * resvalS. (Memory allocation for resvalS is handled within IDAS)
+ *
+ * The user_data parameter is the same as the user_data parameter
+ * set by the user through the IDASetUserData routine and is
+ * passed to the resS function every time it is called.
+ *
+ * A IDASensResFn should return 0 if successful, a negative value if
+ * an unrecoverable error occured, and a positive value if a
+ * recoverable error (e.g. invalid y, yp, yyS or ypS values)
+ * occured. If an unrecoverable occured, the integration is halted.
+ * If a recoverable error occured, then (in most cases) IDAS will
+ * try to correct and retry.
+ * -----------------------------------------------------------------
+ */
+
+typedef int (*IDASensResFn)(int Ns, realtype t,
+ N_Vector yy, N_Vector yp, N_Vector resval,
+ N_Vector *yyS, N_Vector *ypS,
+ N_Vector *resvalS, void *user_data,
+ N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
+
+/*
+ * -----------------------------------------------------------------
+ * Type : IDAQuadSensRhsFn
+ * -----------------------------------------------------------------
+ * The rhsQS function which defines the RHS of the sensitivity DAE
+ * systems for quadratures must have type IDAQuadSensRhsFn.
+ *
+ * rhsQS takes as input the number of sensitivities Ns (the same as
+ * that passed to IDAQuadSensInit), the independent variable
+ * value t, the states yy, yp and the dependent sensitivity vectors
+ * yyS and ypS, as well as the current value of the quadrature RHS
+ * rrQ. It stores the result of rhsQS in rhsvalQS.
+ * (Allocation of memory for resvalQS is handled within IDAS)
+ *
+ * A IDAQuadSensRhsFn should return 0 if successful, a negative
+ * value if an unrecoverable error occured, and a positive value
+ * if a recoverable error (e.g. invalid yy, yp, yyS or ypS values)
+ * occured. If an unrecoverable occured, the integration is halted.
+ * If a recoverable error occured, then (in most cases) IDAS
+ * will try to correct and retry.
+ * -----------------------------------------------------------------
+ */
+
+typedef int (*IDAQuadSensRhsFn)(int Ns, realtype t,
+ N_Vector yy, N_Vector yp,
+ N_Vector *yyS, N_Vector *ypS,
+ N_Vector rrQ, N_Vector *rhsvalQS,
+ void *user_data,
+ N_Vector yytmp, N_Vector yptmp, N_Vector tmpQS);
+
+/*
+ * -----------------------------------------------------------------
+ * Types: IDAResFnB and IDAResFnBS
+ * -----------------------------------------------------------------
+ * The resB function which defines the right hand side of the
+ * DAE systems to be integrated backwards must have type IDAResFnB.
+ * If the backward problem depends on forward sensitivities, its
+ * RHS function must have type IDAResFnBS.
+ * -----------------------------------------------------------------
+ * Types: IDAQuadRhsFnB and IDAQuadRhsFnBS
+ * -----------------------------------------------------------------
+ * The rhsQB function which defines the quadratures to be integrated
+ * backwards must have type IDAQuadRhsFnB.
+ * If the backward problem depends on forward sensitivities, its
+ * quadrature RHS function must have type IDAQuadRhsFnBS.
+ * -----------------------------------------------------------------
+ */
+
+typedef int (*IDAResFnB)(realtype tt,
+ N_Vector yy, N_Vector yp,
+ N_Vector yyB, N_Vector ypB,
+ N_Vector rrB, void *user_dataB);
+
+typedef int (*IDAResFnBS)(realtype t,
+ N_Vector yy, N_Vector yp,
+ N_Vector *yyS, N_Vector *ypS,
+ N_Vector yyB, N_Vector ypB,
+ N_Vector rrBS, void *user_dataB);
+
+typedef int (*IDAQuadRhsFnB)(realtype tt,
+ N_Vector yy, N_Vector yp,
+ N_Vector yyB, N_Vector ypB,
+ N_Vector rhsvalBQ, void *user_dataB);
+
+typedef int (*IDAQuadRhsFnBS)(realtype t,
+ N_Vector yy, N_Vector yp,
+ N_Vector *yyS, N_Vector *ypS,
+ N_Vector yyB, N_Vector ypB,
+ N_Vector rhsvalBQS, void *user_dataB);
+/*
+ * ================================================================
+ * U S E R - C A L L A B L E R O U T I N E S
+ * ================================================================
+ */
+
+/*
+ * ----------------------------------------------------------------
+ * Function : IDACreate
+ * ----------------------------------------------------------------
+ * IDACreate creates an internal memory block for a problem to
+ * be solved by IDA.
+ *
+ * If successful, IDACreate returns a pointer to initialized
+ * problem memory. This pointer should be passed to IDAInit.
+ * If an initialization error occurs, IDACreate prints an error
+ * message to standard err and returns NULL.
+ *
+ * ----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT void *IDACreate(void);
+
+/*
+ * ----------------------------------------------------------------
+ * Integrator optional input specification functions
+ * ----------------------------------------------------------------
+ * The following functions can be called to set optional inputs
+ * to values other than the defaults given below:
+ *
+ * |
+ * Function | Optional input / [ default value ]
+ * |
+ * ----------------------------------------------------------------
+ * |
+ * IDASetErrHandlerFn | user-provided ErrHandler function.
+ * | [internal]
+ * |
+ * IDASetErrFile | the file pointer for an error file
+ * | where all IDA warning and error
+ * | messages will be written if the default
+ * | internal error handling function is used.
+ * | This parameter can be stdout (standard
+ * | output), stderr (standard error), or a
+ * | file pointer (corresponding to a user
+ * | error file opened for writing) returned
+ * | by fopen.
+ * | If not called, then all messages will
+ * | be written to the standard error stream.
+ * | [stderr]
+ * |
+ * IDASetUserData | a pointer to user data that will be
+ * | passed to all user-supplied functions.
+ * | [NULL]
+ * |
+ * IDASetMaxOrd | maximum lmm order to be used by the
+ * | solver.
+ * | [5]
+ * |
+ * IDASetMaxNumSteps | maximum number of internal steps to be
+ * | taken by the solver in its attempt to
+ * | reach tout.
+ * | [500]
+ * |
+ * IDASetInitStep | initial step size.
+ * | [estimated by IDA]
+ * |
+ * IDASetMaxStep | maximum absolute value of step size
+ * | allowed.
+ * | [infinity]
+ * |
+ * IDASetStopTime | the independent variable value past
+ * | which the solution is not to proceed.
+ * | [infinity]
+ * |
+ * IDASetNonlinConvCoef | Newton convergence test constant
+ * | for use during integration.
+ * | [0.33]
+ * |
+ * IDASetMaxErrTestFails| Maximum number of error test failures
+ * | in attempting one step.
+ * | [10]
+ * |
+ * IDASetMaxNonlinIters | Maximum number of nonlinear solver
+ * | iterations at one solution.
+ * | [4]
+ * |
+ * IDASetMaxConvFails | Maximum number of allowable conv.
+ * | failures in attempting one step.
+ * | [10]
+ * |
+ * IDASetSuppressAlg | flag to indicate whether or not to
+ * | suppress algebraic variables in the
+ * | local error tests:
+ * | FALSE = do not suppress;
+ * | TRUE = do suppress;
+ * | [FALSE]
+ * | NOTE: if suppressed algebraic variables
+ * | is selected, the nvector 'id' must be
+ * | supplied for identification of those
+ * | algebraic components (see IDASetId)
+ * |
+ * IDASetId | an N_Vector, which states a given
+ * | element to be either algebraic or
+ * | differential.
+ * | A value of 1.0 indicates a differential
+ * | variable while a 0.0 indicates an
+ * | algebraic variable. 'id' is required
+ * | if optional input SUPPRESSALG is set,
+ * | or if IDACalcIC is to be called with
+ * | icopt = IDA_YA_YDP_INIT.
+ * |
+ * IDASetConstraints | an N_Vector defining inequality
+ * | constraints for each component of the
+ * | solution vector y. If a given element
+ * | of this vector has values +2 or -2,
+ * | then the corresponding component of y
+ * | will be constrained to be > 0.0 or
+ * | <0.0, respectively, while if it is +1
+ * | or -1, the y component is constrained
+ * | to be >= 0.0 or <= 0.0, respectively.
+ * | If a component of constraints is 0.0,
+ * | then no constraint is imposed on the
+ * | corresponding component of y.
+ * | The presence of a non-NULL constraints
+ * | vector that is not 0.0 (ZERO) in all
+ * | components will cause constraint
+ * | checking to be performed.
+ * |
+ * -----------------------------------------------------------------
+ * |
+ * IDASetRootDirection | Specifies the direction of zero
+ * | crossings to be monitored
+ * | [both directions]
+ * |
+ * IDASetNoInactiveRootWarn | disable warning about possible
+ * | g==0 at beginning of integration
+ * |
+ * ----------------------------------------------------------------
+ * 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
+ *
+ * ----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int IDASetErrHandlerFn(void *ida_mem, IDAErrHandlerFn ehfun, void *eh_data);
+SUNDIALS_EXPORT int IDASetErrFile(void *ida_mem, FILE *errfp);
+SUNDIALS_EXPORT int IDASetUserData(void *ida_mem, void *user_data);
+SUNDIALS_EXPORT int IDASetMaxOrd(void *ida_mem, int maxord);
+SUNDIALS_EXPORT int IDASetMaxNumSteps(void *ida_mem, long int mxsteps);
+SUNDIALS_EXPORT int IDASetInitStep(void *ida_mem, realtype hin);
+SUNDIALS_EXPORT int IDASetMaxStep(void *ida_mem, realtype hmax);
+SUNDIALS_EXPORT int IDASetStopTime(void *ida_mem, realtype tstop);
+SUNDIALS_EXPORT int IDASetNonlinConvCoef(void *ida_mem, realtype epcon);
+SUNDIALS_EXPORT int IDASetMaxErrTestFails(void *ida_mem, int maxnef);
+SUNDIALS_EXPORT int IDASetMaxNonlinIters(void *ida_mem, int maxcor);
+SUNDIALS_EXPORT int IDASetMaxConvFails(void *ida_mem, int maxncf);
+SUNDIALS_EXPORT int IDASetSuppressAlg(void *ida_mem, booleantype suppressalg);
+SUNDIALS_EXPORT int IDASetId(void *ida_mem, N_Vector id);
+SUNDIALS_EXPORT int IDASetConstraints(void *ida_mem, N_Vector constraints);
+
+SUNDIALS_EXPORT int IDASetRootDirection(void *ida_mem, int *rootdir);
+SUNDIALS_EXPORT int IDASetNoInactiveRootWarn(void *ida_mem);
+
+/*
+ * ----------------------------------------------------------------
+ * Function : IDAInit
+ * ----------------------------------------------------------------
+ * IDAInit allocates and initializes memory for a problem to
+ * to be solved by IDAS.
+ *
+ * res is the residual function F in F(t,y,y') = 0.
+ *
+ * t0 is the initial value of t, the independent variable.
+ *
+ * yy0 is the initial condition vector y(t0).
+ *
+ * yp0 is the initial condition vector y'(t0)
+ *
+ * IDA_SUCCESS if successful
+ * IDA_MEM_NULL if the IDAS memory was NULL
+ * IDA_MEM_FAIL if a memory allocation failed
+ * IDA_ILL_INPUT f an argument has an illegal value.
+ *
+ * ----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int IDAInit(void *ida_mem, IDAResFn res,
+ realtype t0, N_Vector yy0, N_Vector yp0);
+
+/*
+ * ----------------------------------------------------------------
+ * Function : IDAReInit
+ * ----------------------------------------------------------------
+ * IDAReInit re-initializes IDAS for the solution of a problem,
+ * where a prior call to IDAInit has been made.
+ * IDAReInit performs the same input checking and initializations
+ * that IDAInit does.
+ * But it does no memory allocation, assuming that the existing
+ * internal memory is sufficient for the new problem.
+ *
+ * The use of IDAReInit requires that the maximum method order,
+ * maxord, is no larger for the new problem than for the problem
+ * specified in the last call to IDAInit. This condition is
+ * automatically fulfilled if the default value for maxord is
+ * specified.
+ *
+ * Following the call to IDAReInit, a call to the linear solver
+ * specification routine is necessary if a different linear solver
+ * is chosen, but may not be otherwise. If the same linear solver
+ * is chosen, and there are no changes in its input parameters,
+ * then no call to that routine is needed.
+ *
+ * The first argument to IDAReInit is:
+ *
+ * ida_mem = pointer to IDA memory returned by IDACreate.
+ *
+ * All the remaining arguments to IDAReInit have names and
+ * meanings identical to those of IDAInit.
+ *
+ * The return value of IDAReInit is equal to SUCCESS = 0 if there
+ * were no errors; otherwise it is a negative int equal to:
+ * IDA_MEM_NULL indicating ida_mem was NULL, or
+ * IDA_NO_MALLOC indicating that ida_mem was not allocated.
+ * IDA_ILL_INPUT indicating an input argument was illegal
+ * (including an attempt to increase maxord).
+ * In case of an error return, an error message is also printed.
+ * ----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int IDAReInit(void *ida_mem,
+ realtype t0, N_Vector yy0, N_Vector yp0);
+
+/*
+ * -----------------------------------------------------------------
+ * Functions : IDASStolerances
+ * IDASVtolerances
+ * IDAWFtolerances
+ * -----------------------------------------------------------------
+ *
+ * These functions specify the integration tolerances. One of them
+ * MUST be called before the first call to IDA.
+ *
+ * IDASStolerances specifies scalar relative and absolute tolerances.
+ * IDASVtolerances specifies scalar relative tolerance and a vector
+ * absolute tolerance (a potentially different absolute tolerance
+ * for each vector component).
+ * IDAWFtolerances specifies a user-provides function (of type IDAEwtFn)
+ * which will be called to set the error weight vector.
+ *
+ * The tolerances reltol and abstol define a vector of error weights,
+ * ewt, with components
+ * ewt[i] = 1/(reltol*abs(y[i]) + abstol) (in the SS case), or
+ * ewt[i] = 1/(reltol*abs(y[i]) + abstol[i]) (in the SV case).
+ * This vector is used in all error and convergence tests, which
+ * use a weighted RMS norm on all error-like vectors v:
+ * WRMSnorm(v) = sqrt( (1/N) sum(i=1..N) (v[i]*ewt[i])^2 ),
+ * where N is the problem dimension.
+ *
+ * The return value of these functions is equal to IDA_SUCCESS = 0 if
+ * there were no errors; otherwise it is a negative int equal to:
+ * IDa_MEM_NULL indicating ida_mem was NULL (i.e.,
+ * IDACreate has not been called).
+ * IDA_NO_MALLOC indicating that ida_mem has not been
+ * allocated (i.e., IDAInit has not been
+ * called).
+ * IDA_ILL_INPUT indicating an input argument was illegal
+ * (e.g. a negative tolerance)
+ * In case of an error return, an error message is also printed.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int IDASStolerances(void *ida_mem, realtype reltol, realtype abstol);
+SUNDIALS_EXPORT int IDASVtolerances(void *ida_mem, realtype reltol, N_Vector abstol);
+SUNDIALS_EXPORT int IDAWFtolerances(void *ida_mem, IDAEwtFn efun);
+
+/* ----------------------------------------------------------------
+ * Initial Conditions optional input specification functions
+ * ----------------------------------------------------------------
+ * The following functions can be called to set optional inputs
+ * to control the initial conditions calculations.
+ *
+ * |
+ * Function | Optional input / [ default value ]
+ * |
+ * --------------------------------------------------------------
+ * |
+ * IDASetNonlinConvCoefIC | positive coeficient in the Newton
+ * | convergence test. This test uses a
+ * | weighted RMS norm (with weights
+ * | defined by the tolerances, as in
+ * | IDASolve). For new initial value
+ * | vectors y and y' to be accepted, the
+ * | norm of J-inverse F(t0,y,y') is
+ * | required to be less than epiccon,
+ * | where J is the system Jacobian.
+ * | [0.01 * 0.33]
+ * |
+ * IDASetMaxNumStepsIC | maximum number of values of h allowed
+ * | when icopt = IDA_YA_YDP_INIT, where
+ * | h appears in the system Jacobian,
+ * | J = dF/dy + (1/h)dF/dy'.
+ * | [5]
+ * |
+ * IDASetMaxNumJacsIC | maximum number of values of the
+ * | approximate Jacobian or preconditioner
+ * | allowed, when the Newton iterations
+ * | appear to be slowly converging.
+ * | [4]
+ * |
+ * IDASetMaxNumItersIC | maximum number of Newton iterations
+ * | allowed in any one attempt to solve
+ * | the IC problem.
+ * | [10]
+ * |
+ * IDASetLineSearchOffIC | a boolean flag to turn off the
+ * | linesearch algorithm.
+ * | [FALSE]
+ * |
+ * IDASetStepToleranceIC | positive lower bound on the norm of
+ * | a Newton step.
+ * | [(unit roundoff)^(2/3)
+ *
+ * ----------------------------------------------------------------
+ * 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
+ *
+ * ----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int IDASetNonlinConvCoefIC(void *ida_mem, realtype epiccon);
+SUNDIALS_EXPORT int IDASetMaxNumStepsIC(void *ida_mem, int maxnh);
+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);
+
+/*
+ * -----------------------------------------------------------------
+ * Function : IDARootInit
+ * -----------------------------------------------------------------
+ * IDARootInit initializes a rootfinding problem to be solved
+ * during the integration of the DAE system. It must be called
+ * after IDACreate, and before IDASolve. The arguments are:
+ *
+ * ida_mem = pointer to IDA memory returned by IDACreate.
+ *
+ * nrtfn = number of functions g_i, an int >= 0.
+ *
+ * g = name of user-supplied function, of type IDARootFn,
+ * defining the functions g_i whose roots are sought.
+ *
+ * If a new problem is to be solved with a call to IDAReInit,
+ * where the new problem has no root functions but the prior one
+ * did, then call IDARootInit with nrtfn = 0.
+ *
+ * The return value of IDARootInit is IDA_SUCCESS = 0 if there were
+ * no errors; otherwise it is a negative int equal to:
+ * IDA_MEM_NULL indicating ida_mem was NULL, or
+ * IDA_MEM_FAIL indicating a memory allocation failed.
+ * (including an attempt to increase maxord).
+ * IDA_ILL_INPUT indicating nrtfn > 0 but g = NULL.
+ * In case of an error return, an error message is also printed.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int IDARootInit(void *ida_mem, int nrtfn, IDARootFn g);
+
+/*
+ * -----------------------------------------------------------------
+ * Quadrature optional input specification functions
+ * -----------------------------------------------------------------
+ * The following function can be called to set optional inputs
+ * to values other than the defaults given below:
+ *
+ * Function | Optional input / [ default value ]
+ * --------------------------------------------------------------
+ * |
+ * IDASetQuadErrCon | are quadrature variables considered in
+ * | the error control?
+ * | If yes, set tolerances for quadrature
+ * | integration.
+ * | [errconQ = FALSE]
+ * |
+ * -----------------------------------------------------------------
+ * If successful, the function return IDA_SUCCESS. If an argument
+ * has an illegal value, they print an error message to the
+ * file specified by errfp and return one of the error flags
+ * defined for the IDASet* routines.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int IDASetQuadErrCon(void *ida_mem, booleantype errconQ);
+
+/*
+ * ----------------------------------------------------------------
+ * Function : IDAQuadInit and IDAQuadReInit
+ * ----------------------------------------------------------------
+ * IDAQuadInit allocates and initializes memory related to
+ * quadrature integration.
+ *
+ * IDAQuadReInit re-initializes IDAS's quadrature related
+ * memory for a problem, assuming it has already been allocated
+ * in prior calls to IDAInit and IDAQuadInit.
+ *
+ * ida_mem is a pointer to IDAS memory returned by IDACreate
+ *
+ * rhsQ is the user-provided integrand routine.
+ *
+ * yQ0 is a pointer to a vector specification structure
+ * for N_Vectors containing quadrature variables.
+ *
+ *
+ * ----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int IDAQuadInit(void *ida_mem, IDAQuadRhsFn rhsQ, N_Vector yQ0);
+SUNDIALS_EXPORT int IDAQuadReInit(void *ida_mem, N_Vector yQ0);
+
+/*
+ * -----------------------------------------------------------------
+ * Functions : IDAQuadSStolerances
+ * IDAQuadSVtolerances
+ * -----------------------------------------------------------------
+ *
+ * These functions specify the integration tolerances for quadrature
+ * variables. One of them MUST be called before the first call to
+ * IDA IF error control on the quadrature variables is enabled
+ * (see IDASetQuadErrCon).
+ *
+ * IDASStolerances specifies scalar relative and absolute tolerances.
+ * IDASVtolerances specifies scalar relative tolerance and a vector
+ * absolute tolerance (a potentially different absolute tolerance
+ * for each vector component).
+ *
+ * Return values:
+ * IDA_SUCCESS if successful
+ * IDA_MEM_NULL if the solver memory was NULL
+ * IDA_NO_QUAD if quadratures were not initialized
+ * IDA_ILL_INPUT if an input argument was illegal
+ * (e.g. a negative tolerance)
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int IDAQuadSStolerances(void *ida_mem, realtype reltolQ, realtype abstolQ);
+SUNDIALS_EXPORT int IDAQuadSVtolerances(void *ida_mem, realtype reltolQ, N_Vector abstolQ);
+
+/*
+ * ----------------------------------------------------------------
+ * Forward sensitivity optional input specification functions
+ * ----------------------------------------------------------------
+ * The following functions can be called to set optional inputs
+ * to other values than the defaults given below:
+ *
+ * Function | Optional input / [ default value ]
+ * |
+ * --------------------------------------------------------------
+ * |
+ * IDASetSensDQMethod | controls the selection of finite
+ * | difference schemes used in evaluating
+ * | the sensitivity right hand sides:
+ * | (centered vs. forward and
+ * | simultaneous vs. separate)
+ * | [DQtype=IDA_CENTERED]
+ * | [DQrhomax=0.0]
+ * |
+ * IDASetSensParams | parameter information:
+ * | p: pointer to problem parameters
+ * | plist: list of parameters with respect
+ * | to which sensitivities are to be
+ * | computed.
+ * | pbar: order of magnitude info.
+ * | Typically, if p[plist[i]] is nonzero,
+ * | pbar[i]=p[plist[i]].
+ * | [p=NULL]
+ * | [plist=NULL]
+ * | [pbar=NULL]
+ * |
+ * IDASetSensErrCon | are sensitivity variables considered in
+ * | the error control?
+ * | [TRUE]
+ * |
+ * IDASetSensMaxNonlinIters | Maximum number of nonlinear solver
+ * | iterations for sensitivity systems
+ * | (staggered)
+ * | [4]
+ * |
+ * --------------------------------------------------------------
+ * If successful, these functions return IDA_SUCCESS. If an argument
+ * has an illegal value, they return one of the error flags
+ * defined for the IDASet* routines.
+ * ----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int IDASetSensDQMethod(void *ida_mem, int DQtype, realtype DQrhomax);
+SUNDIALS_EXPORT int IDASetSensParams(void *ida_mem, realtype *p, realtype *pbar, int *plist);
+SUNDIALS_EXPORT int IDASetSensErrCon(void *ida_mem, booleantype errconS);
+SUNDIALS_EXPORT int IDASetSensMaxNonlinIters(void *ida_mem, int maxcorS);
+
+/*
+ * ----------------------------------------------------------------
+ * Function : IDASensInit
+ * ----------------------------------------------------------------
+ * IDASensInit allocates and initializes memory related to
+ * sensitivity computations.
+ *
+ * ida_mem is a pointer to IDAS memory returned by IDACreate.
+ *
+ * Ns is the number of sensitivities to be computed.
+ *
+ * ism is the type of corrector used in sensitivity
+ * analysis. The legal values are: SIMULTANEOUS
+ * and STAGGERED (see previous description)
+ *
+ * yS0 is the array of initial condition vectors for
+ * sensitivity variables.
+ *
+ * ypS0 is the array of initial condition vectors for
+ * sensitivity derivatives.
+ *
+ * If successful, IDASensInit returns SUCCESS. If an
+ * initialization error occurs, IDASensInit returns one of
+ * the error flags defined above.
+ *
+ * ----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int IDASensInit(void *ida_mem, int Ns, int ism,
+ IDASensResFn resS,
+ N_Vector *yS0, N_Vector *ypS0);
+
+
+/*
+ * ----------------------------------------------------------------
+ * Function : IDASensReInit
+ * ----------------------------------------------------------------
+ * IDASensReInit re-initializes the IDAS sensitivity related
+ * memory for a problem, assuming it has already been allocated
+ * in prior calls to IDAInit and IDASensInit.
+ *
+ * All problem specification inputs are checked for errors.
+ * The number of sensitivities Ns is assumed to be unchanged
+ * since the previous call to IDASensInit.
+ * If any error occurs during initialization, it is reported to
+ * the file whose file pointer is errfp.
+ *
+ * IDASensReInit potentially does some minimal memory allocation
+ * (for the sensitivity absolute tolerance).
+ *
+ * ----------------------------------------------------------------
+ */
+SUNDIALS_EXPORT int IDASensReInit(void *ida_mem, int ism, N_Vector *yS0, N_Vector *ypS0);
+
+/*
+ * -----------------------------------------------------------------
+ * Function : IDASensToggleOff
+ * -----------------------------------------------------------------
+ * IDASensToggleOff deactivates sensitivity calculations.
+ * It does NOT deallocate sensitivity-related memory so that
+ * sensitivity computations can be later toggled ON (through
+ * IDASensReInit).
+ *
+ *
+ * The return value is equal to IDA_SUCCESS = 0 if there were no
+ * errors or IDA_MEM_NULL if ida_mem was NULL
+ * -----------------------------------------------------------------
+ */
+SUNDIALS_EXPORT int IDASensToggleOff(void *ida_mem);
+
+/*
+ * -----------------------------------------------------------------
+ * Functions : IDASensSStolerances
+ * IDASensSVtolerances
+ * IDASensEEtolerances
+ * -----------------------------------------------------------------
+ *
+ * These functions specify the integration tolerances for sensitivity
+ * variables. One of them MUST be called before the first call to IDASolve.
+ *
+ * IDASensSStolerances specifies scalar relative and absolute tolerances.
+ * IDASensSVtolerances specifies scalar relative tolerance and a vector
+ * absolute tolerance for each sensitivity vector (a potentially different
+ * absolute tolerance for each vector component).
+ * IDASensEEtolerances specifies that tolerances for sensitivity variables
+ * should be estimated from those provided for the state variables.
+ *
+ * The return value is equal to IDA_SUCCESS = 0 if there were no
+ * errors; otherwise it is a negative int equal to:
+ * IDA_MEM_NULL indicating ida_mem was NULL, or
+ * IDA_NO_SENS indicating there was not a prior call to
+ * IDASensInit.
+ * IDA_ILL_INPUT indicating an input argument was illegal
+ * (e.g. negative tolerances)
+ * In case of an error return, an error message is also printed.
+ * -----------------------------------------------------------------
+ */
+SUNDIALS_EXPORT int IDASensSStolerances(void *ida_mem, realtype reltolS, realtype *abstolS);
+SUNDIALS_EXPORT int IDASensSVtolerances(void *ida_mem, realtype reltolS, N_Vector *abstolS);
+SUNDIALS_EXPORT int IDASensEEtolerances(void *ida_mem);
+
+
+/*
+ * -----------------------------------------------------------------
+ * Function : IDAQuadSensInit and IDAQuadSensReInit
+ * -----------------------------------------------------------------
+ * IDAQuadSensInit allocates and initializes memory related to
+ * quadrature integration.
+ *
+ * IDAQuadSensReInit re-initializes IDAS' sensitivity quadrature
+ * related memory for a problem, assuming it has already been
+ * allocated in prior calls to IDAInit and IDAQuadSensInit.
+ * The number of quadratures Ns is assumed to be unchanged
+ * since the previous call to IDAQuadInit.
+ *
+ * ida_mem is a pointer to IDAS memory returned by IDACreate
+ *
+ * resQS is the sensitivity righ-hand side function
+ * (pass NULL to use the internal DQ approximation)
+ *
+ * yQS is an N_Vector with initial values for sensitivities
+
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int IDAQuadSensInit(void *ida_mem, IDAQuadSensRhsFn resQS, N_Vector *yQS0);
+SUNDIALS_EXPORT int IDAQuadSensReInit(void *ida_mem, N_Vector *yQS0);
+
+/*
+ * -----------------------------------------------------------------
+ * Functions : IDAQuadSensSStolerances
+ * IDAQuadSensSVtolerances
+ * IDAQuadSensEEtolerances
+ * -----------------------------------------------------------------
+ *
+ * These functions specify the integration tolerances for quadrature
+ * sensitivity variables. One of them MUST be called before the first
+ * call to IDAS IF these variables are included in the error test.
+ *
+ * IDAQuadSensSStolerances specifies scalar relative and absolute tolerances.
+ * IDAQuadSensSVtolerances specifies scalar relative tolerance and a vector
+ * absolute tolerance for each quadrature sensitivity vector (a potentially
+ * different absolute tolerance for each vector component).
+ * IDAQuadSensEEtolerances specifies that tolerances for sensitivity variables
+ * should be estimated from those provided for the quadrature variables.
+ * In this case, tolerances for the quadrature variables must be
+ * specified through a call to one of IDAQuad**tolerances.
+ *
+ * The return value is equal to IDA_SUCCESS = 0 if there were no
+ * errors; otherwise it is a negative int equal to:
+ * IDA_MEM_NULL if ida_mem was NULL, or
+ * IDA_NO_QUADSENS if there was not a prior call to
+ * IDAQuadSensInit.
+ * IDA_ILL_INPUT if an input argument was illegal
+ * (e.g. negative tolerances)
+ * In case of an error return, an error message is also printed.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int IDAQuadSensSStolerances(void *ida_mem, realtype reltolQS, realtype *abstolQS);
+SUNDIALS_EXPORT int IDAQuadSensSVtolerances(void *ida_mem, realtype reltolQS, N_Vector *abstolQS);
+SUNDIALS_EXPORT int IDAQuadSensEEtolerances(void *ida_mem);
+
+/*
+ * -----------------------------------------------------------------
+ * Function: IDASetQuadSensErrCon
+ * -----------------------------------------------------------------
+ * IDASetQuadSensErrCon specifies if quadrature sensitivity variables
+ * are considered or not in the error control.
+ *
+ * If yes, tolerances for quadrature sensitivity variables are
+ * required. The function is optional, by default IDAS does not
+ * quadrature sensitivities in error control.
+ *
+ * The return value is equal to IDA_SUCCESS = 0 if there were no
+ * errors or IDA_MEM_NULL if ida_mem was NULL
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int IDASetQuadSensErrCon(void *ida_mem, booleantype errconQS);
+
+
+/*
+ * ----------------------------------------------------------------
+ * Function : IDACalcIC
+ * ----------------------------------------------------------------
+ * IDACalcIC calculates corrected initial conditions for the DAE
+ * system for a class of index-one problems of semi-implicit form.
+ * It uses Newton iteration combined with a Linesearch algorithm.
+ * Calling IDACalcIC is optional. It is only necessary when the
+ * initial conditions do not solve the given system. I.e., if
+ * y0 and yp0 are known to satisfy F(t0, y0, yp0) = 0, then
+ * a call to IDACalcIC is NOT necessary (for index-one problems).
+ *
+ * A call to IDACalcIC must be preceded by a successful call to
+ * IDAInit or IDAReInit for the given DAE problem, and by a
+ * successful call to the linear system solver specification
+ * routine.
+ *
+ * The call to IDACalcIC should precede the call(s) to IDASolve
+ * for the given problem.
+ *
+ * The arguments to IDACalcIC are as follows:
+ *
+ * ida_mem is the pointer to IDA memory returned by IDACreate.
+ *
+ * icopt is the option of IDACalcIC to be used.
+ * icopt = IDA_YA_YDP_INIT directs IDACalcIC to compute
+ * the algebraic components of y and differential
+ * components of y', given the differential
+ * components of y. This option requires that the
+ * N_Vector id was set through a call to IDASetId
+ * specifying the differential and algebraic
+ * components.
+ * icopt = IDA_Y_INIT directs IDACalcIC to compute all
+ * components of y, given y'. id is not required.
+ *
+ * tout1 is the first value of t at which a soluton will be
+ * requested (from IDASolve). (This is needed here to
+ * determine the direction of integration and rough scale
+ * in the independent variable t.)
+ *
+ *
+ * IDACalcIC returns an int flag. Its symbolic values and their
+ * meanings are as follows. (The numerical return values are set
+ * above in this file.) All unsuccessful returns give a negative
+ * return value. If IFACalcIC failed, y0 and yp0 contain
+ * (possibly) altered values, computed during the attempt.
+ *
+ * IDA_SUCCESS IDACalcIC was successful. The corrected
+ * initial value vectors were stored internally.
+ *
+ * IDA_MEM_NULL The argument ida_mem was NULL.
+ *
+ * IDA_ILL_INPUT One of the input arguments was illegal.
+ * See printed message.
+ *
+ * IDA_LINIT_FAIL The linear solver's init routine failed.
+ *
+ * IDA_BAD_EWT Some component of the error weight vector
+ * is zero (illegal), either for the input
+ * value of y0 or a corrected value.
+ *
+ * IDA_RES_FAIL The user's residual routine returned
+ * a non-recoverable error flag.
+ *
+ * IDA_FIRST_RES_FAIL The user's residual routine returned
+ * a recoverable error flag on the first call,
+ * but IDACalcIC was unable to recover.
+ *
+ * IDA_LSETUP_FAIL The linear solver's setup routine had a
+ * non-recoverable error.
+ *
+ * IDA_LSOLVE_FAIL The linear solver's solve routine had a
+ * non-recoverable error.
+ *
+ * IDA_NO_RECOVERY The user's residual routine, or the linear
+ * solver's setup or solve routine had a
+ * recoverable error, but IDACalcIC was
+ * unable to recover.
+ *
+ * IDA_CONSTR_FAIL IDACalcIC was unable to find a solution
+ * satisfying the inequality constraints.
+ *
+ * IDA_LINESEARCH_FAIL The Linesearch algorithm failed to find a
+ * solution with a step larger than steptol
+ * in weighted RMS norm.
+ *
+ * IDA_CONV_FAIL IDACalcIC failed to get convergence of the
+ * Newton iterations.
+ *
+ * ----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int IDACalcIC(void *ida_mem, int icopt, realtype tout1);
+
+/*
+ * ----------------------------------------------------------------
+ * Function : IDASolve
+ * ----------------------------------------------------------------
+ * IDASolve integrates the DAE over an interval in t, the
+ * independent variable. If itask is IDA_NORMAL, then the solver
+ * integrates from its current internal t value to a point at or
+ * beyond tout, then interpolates to t = tout and returns y(tret)
+ * in the user-allocated vector yret. In general, tret = tout.
+ * If itask is IDA_ONE_STEP, then the solver takes one internal
+ * step of the independent variable and returns in yret the value
+ * of y at the new internal independent variable value. In this
+ * case, tout is used only during the first call to IDASolve to
+ * determine the direction of integration and the rough scale of
+ * the problem. If tstop is enabled (through a call to IDASetStopTime),
+ * then IDASolve returns the solution at tstop. Once the integrator
+ * returns at a tstop time, any future testing for tstop is disabled
+ * (and can be reenabled only though a new call to IDASetStopTime).
+ * The time reached by the solver is placed in (*tret). The
+ * user is responsible for allocating the memory for this value.
+ *
+ * ida_mem is the pointer (void) to IDA memory returned by
+ * IDACreate.
+ *
+ * tout is the next independent variable value at which a
+ * computed solution is desired.
+ *
+ * tret is a pointer to a real location. IDASolve sets (*tret)
+ * to the actual t value reached, corresponding to the
+ * solution vector yret. In IDA_NORMAL mode, with no
+ * errors and no roots found, (*tret) = tout.
+ *
+ * yret is the computed solution vector. With no errors,
+ * yret = y(tret).
+ *
+ * ypret is the derivative of the computed solution at t = tret.
+ *
+ * Note: yret and ypret may be the same N_Vectors as y0 and yp0
+ * in the call to IDAInit or IDAReInit.
+ *
+ * itask is IDA_NORMAL or IDA_ONE_STEP. These two modes are described above.
+ *
+ *
+ * The return values for IDASolve are described below.
+ * (The numerical return values are defined above in this file.)
+ * All unsuccessful returns give a negative return value.
+ *
+ * IDA_SUCCESS
+ * IDASolve succeeded and no roots were found.
+ *
+ * IDA_ROOT_RETURN: IDASolve succeeded, and found one or more roots.
+ * If nrtfn > 1, call IDAGetRootInfo to see which g_i were found
+ * to have a root at (*tret).
+ *
+ * IDA_TSTOP_RETURN:
+ * IDASolve returns computed results for the independent variable
+ * value tstop. That is, tstop was reached.
+ *
+ * IDA_MEM_NULL:
+ * The ida_mem argument was NULL.
+ *
+ * IDA_ILL_INPUT:
+ * One of the inputs to IDASolve is illegal. This includes the
+ * situation when a component of the error weight vectors
+ * becomes < 0 during internal stepping. It also includes the
+ * situation where a root of one of the root functions was found
+ * both at t0 and very near t0. The ILL_INPUT flag
+ * will also be returned if the linear solver function IDA---
+ * (called by the user after calling IDACreate) failed to set one
+ * of the linear solver-related fields in ida_mem or if the linear
+ * solver's init routine failed. In any case, the user should see
+ * the printed error message for more details.
+ *
+ * IDA_TOO_MUCH_WORK:
+ * The solver took mxstep internal steps but could not reach tout.
+ * The default value for mxstep is MXSTEP_DEFAULT = 500.
+ *
+ * IDA_TOO_MUCH_ACC:
+ * The solver could not satisfy the accuracy demanded by the user
+ * for some internal step.
+ *
+ * IDA_ERR_FAIL:
+ * Error test failures occurred too many times (=MXETF = 10) during
+ * one internal step.
+ *
+ * IDA_CONV_FAIL:
+ * Convergence test failures occurred too many times (= MXNCF = 10)
+ * during one internal step.
+ *
+ * IDA_LSETUP_FAIL:
+ * The linear solver's setup routine failed
+ * in an unrecoverable manner.
+ *
+ * IDA_LSOLVE_FAIL:
+ * The linear solver's solve routine failed
+ * in an unrecoverable manner.
+ *
+ * IDA_CONSTR_FAIL:
+ * The inequality constraints were violated,
+ * and the solver was unable to recover.
+ *
+ * IDA_REP_RES_ERR:
+ * The user's residual function repeatedly returned a recoverable
+ * error flag, but the solver was unable to recover.
+ *
+ * IDA_RES_FAIL:
+ * The user's residual function returned a nonrecoverable error
+ * flag.
+ *
+ * ----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int IDASolve(void *ida_mem, realtype tout, realtype *tret,
+ N_Vector yret, N_Vector ypret, int itask);
+
+/*
+ * ----------------------------------------------------------------
+ * Function: IDAGetDky
+ * ----------------------------------------------------------------
+ *
+ * This routine computes the k-th derivative of the interpolating
+ * polynomial at the time t and stores the result in the vector dky.
+ *
+ * The return values are:
+ * IDA_SUCCESS: succeess.
+ * IDA_BAD_T: t is not in the interval [tn-hu,tn].
+ * IDA_MEM_NULL: The ida_mem argument was NULL.
+ * IDA_BAD_DKY if the dky vector is NULL.
+ * IDA_BAD_K if the requested k is not in the range 0,1,...,order used
+ *
+ * ----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int IDAGetDky(void *ida_mem, realtype t, int k, N_Vector dky);
+
+/* ----------------------------------------------------------------
+ * Integrator optional output extraction functions
+ * ----------------------------------------------------------------
+ *
+ * The following functions can be called to get optional outputs
+ * and statistics related to the main integrator.
+ * ----------------------------------------------------------------
+ *
+ * IDAGetWorkSpace returns the IDA real and integer workspace sizes
+ * IDAGetNumSteps returns the cumulative number of internal
+ * steps taken by the solver
+ * IDAGetNumResEvals returns the number of calls to the user's
+ * res function
+ * IDAGetNumLinSolvSetups returns the number of calls made to
+ * the linear solver's setup routine
+ * IDAGetNumErrTestFails returns the number of local error test
+ * failures that have occured
+ * IDAGetNumBacktrackOps returns the number of backtrack
+ * operations done in the linesearch algorithm in IDACalcIC
+ * IDAGetConsistentIC returns the consistent initial conditions
+ * computed by IDACalcIC
+ * IDAGetLastOrder returns the order used during the last
+ * internal step
+ * IDAGetCurentOrder returns the order to be used on the next
+ * internal step
+ * IDAGetActualInitStep returns the actual initial step size
+ * used by IDA
+ * IDAGetLastStep returns the step size for the last internal
+ * step (if from IDASolve), or the last value of the
+ * artificial step size h (if from IDACalcIC)
+ * IDAGetCurrentStep returns the step size to be attempted on the
+ * next internal step
+ * IDAGetCurrentTime returns the current internal time reached
+ * by the solver
+ * IDAGetTolScaleFactor returns a suggested factor by which the
+ * user's tolerances should be scaled when too much
+ * accuracy has been requested for some internal step
+ * IDAGetErrWeights returns the current state error weight vector.
+ * The user must allocate space for eweight.
+ * IDAGetEstLocalErrors returns the estimated local errors. The user
+ * must allocate space for the vector ele.
+ * IDAGetNumGEvals returns the number of calls to the user's
+ * g function (for rootfinding)
+ * IDAGetRootInfo returns the indices for which g_i was found to
+ * have a root. The user must allocate space for rootsfound.
+ * For i = 0 ... nrtfn-1, rootsfound[i] = 1 if g_i has a root,
+ * and rootsfound[i]= 0 if not.
+ *
+ * IDAGet* return values:
+ * IDA_SUCCESS if succesful
+ * IDA_MEM_NULL if the IDAS memory was NULL
+ * IDA_ILL_INPUT if some input is illegal
+ *
+ * ----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int IDAGetWorkSpace(void *ida_mem, long int *lenrw, long int *leniw);
+SUNDIALS_EXPORT int IDAGetNumSteps(void *ida_mem, long int *nsteps);
+SUNDIALS_EXPORT int IDAGetNumResEvals(void *ida_mem, long int *nrevals);
+SUNDIALS_EXPORT int IDAGetNumLinSolvSetups(void *ida_mem, long int *nlinsetups);
+SUNDIALS_EXPORT int IDAGetNumErrTestFails(void *ida_mem, long int *netfails);
+SUNDIALS_EXPORT int IDAGetNumBacktrackOps(void *ida_mem, long int *nbacktr);
+SUNDIALS_EXPORT int IDAGetConsistentIC(void *ida_mem, N_Vector yy0_mod, N_Vector yp0_mod);
+SUNDIALS_EXPORT int IDAGetLastOrder(void *ida_mem, int *klast);
+SUNDIALS_EXPORT int IDAGetCurrentOrder(void *ida_mem, int *kcur);
+SUNDIALS_EXPORT int IDAGetActualInitStep(void *ida_mem, realtype *hinused);
+SUNDIALS_EXPORT int IDAGetLastStep(void *ida_mem, realtype *hlast);
+SUNDIALS_EXPORT int IDAGetCurrentStep(void *ida_mem, realtype *hcur);
+SUNDIALS_EXPORT int IDAGetCurrentTime(void *ida_mem, realtype *tcur);
+SUNDIALS_EXPORT int IDAGetTolScaleFactor(void *ida_mem, realtype *tolsfact);
+SUNDIALS_EXPORT int IDAGetErrWeights(void *ida_mem, N_Vector eweight);
+SUNDIALS_EXPORT int IDAGetEstLocalErrors(void *ida_mem, N_Vector ele);
+SUNDIALS_EXPORT int IDAGetNumGEvals(void *ida_mem, long int *ngevals);
+SUNDIALS_EXPORT int IDAGetRootInfo(void *ida_mem, int *rootsfound);
+
+/*
+ * ----------------------------------------------------------------
+ * As a convenience, the following function provides the
+ * optional outputs in a group.
+ * ----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int IDAGetIntegratorStats(void *ida_mem, long int *nsteps,
+ long int *nrevals, long int *nlinsetups,
+ long int *netfails, int *qlast, int *qcur,
+ realtype *hinused, realtype *hlast, realtype *hcur,
+ realtype *tcur);
+/*
+ * ----------------------------------------------------------------
+ * Nonlinear solver optional output extraction functions
+ * ----------------------------------------------------------------
+ *
+ * The following functions can be called to get optional outputs
+ * and statistics related to the nonlinear solver.
+ * --------------------------------------------------------------
+ *
+ * IDAGetNumNonlinSolvIters returns the number of nonlinear
+ * solver iterations performed.
+ * IDAGetNumNonlinSolvConvFails returns the number of nonlinear
+ * convergence failures.
+ *
+ * ----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int IDAGetNumNonlinSolvIters(void *ida_mem, long int *nniters);
+SUNDIALS_EXPORT int IDAGetNumNonlinSolvConvFails(void *ida_mem, long int *nncfails);
+
+/*
+ * ----------------------------------------------------------------
+ * As a convenience, the following function provides the
+ * nonlinear solver optional outputs in a group.
+ * ----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int IDAGetNonlinSolvStats(void *ida_mem, long int *nniters,
+ long int *nncfails);
+
+/*
+ * -----------------------------------------------------------------
+ * Quadrature integration solution extraction routines
+ * -----------------------------------------------------------------
+ * The following function can be called to obtain the quadrature
+ * variables after a successful integration step.
+ * If quadratures were not computed, it returns IDA_NO_QUAD.
+ *
+ * IDAGetQuad returns the quadrature variables at the same time
+ * as that at which IDASolve returned the solution.
+ *
+ * IDAGetQuadDky returns the quadrature variables (or their
+ * derivatives up to the current method order) at any time within
+ * the last integration step (dense output).
+ *
+ * The output vectors yQout and dky must be allocated by the user.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int IDAGetQuad(void *ida_mem, realtype *t, N_Vector yQout);
+SUNDIALS_EXPORT int IDAGetQuadDky(void *ida_mem, realtype t, int k, N_Vector dky);
+/*
+ * -----------------------------------------------------------------
+ * Quadrature integration optional output extraction routines
+ * -----------------------------------------------------------------
+ * The following functions can be called to get optional outputs
+ * and statistics related to the integration of quadratures.
+ * -----------------------------------------------------------------
+ * IDAGetQuadNumRhsEvals returns the number of calls to the
+ * user function rhsQ defining the right hand
+ * side of the quadrature variables.
+ * IDAGetQuadNumErrTestFails returns the number of local error
+ * test failures for quadrature variables.
+ * IDAGetQuadErrWeights returns the vector of error weights for
+ * the quadrature variables. The user must
+ * allocate space for ewtQ.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int IDAGetQuadNumRhsEvals(void *ida_mem, long int *nrhsQevals);
+SUNDIALS_EXPORT int IDAGetQuadNumErrTestFails(void *ida_mem, long int *nQetfails);
+SUNDIALS_EXPORT int IDAGetQuadErrWeights(void *ida_mem, N_Vector eQweight);
+
+/*
+ * -----------------------------------------------------------------
+ * As a convenience, the following function provides the
+ * optional outputs in a group.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int IDAGetQuadStats(void *ida_mem,
+ long int *nrhsQevals, long int *nQetfails);
+
+/*
+ * -----------------------------------------------------------------
+ * Sensitivity solution extraction routines
+ * -----------------------------------------------------------------
+ * The following functions can be called to obtain the sensitivity
+ * variables after a successful integration step.
+ *
+ * IDAGetSens and IDAGetSens1 return all the sensitivity vectors
+ * or only one of them, respectively, at the same time as that at
+ * which IDASolve returned the solution.
+ * The array of output vectors or output vector ySout must be
+ * allocated by the user.
+ *
+ * IDAGetSensDky1 computes the kth derivative of the is-th
+ * sensitivity (is=1, 2, ..., Ns) of the y function at time t,
+ * where tn-hu <= t <= tn, tn denotes the current internal time
+ * reached, and hu is the last internal step size successfully
+ * used by the solver. The user may request k=0, 1, ..., qu,
+ * where qu is the current order.
+ * The is-th sensitivity derivative vector is returned in dky.
+ * This vector must be allocated by the caller. It is only legal
+ * to call this function after a successful return from IDASolve
+ * with sensitivity computations enabled.
+ * Arguments have the same meaning as in IDADGetky.
+ *
+ * IDAGetSensDky computes the k-th derivative of all
+ * sensitivities of the y function at time t. It repeatedly calls
+ * IDAGetSensDky. The argument dkyS must be a pointer to
+ * N_Vector and must be allocated by the user to hold at least Ns
+ * vectors.
+ *
+ * Return values are similar to those of IDAGetDky. Additionally,
+ * these functions can return IDA_NO_SENS if sensitivities were
+ * not computed and IDA_BAD_IS if is < 0 or is >= Ns.
+ * -----------------------------------------------------------------
+ */
+
+
+SUNDIALS_EXPORT int IDAGetSens(void *ida_mem, realtype *tret, N_Vector *yySout);
+SUNDIALS_EXPORT int IDAGetSens1(void *ida_mem, realtype *tret, int is, N_Vector yySret);
+
+SUNDIALS_EXPORT int IDAGetSensDky(void *ida_mem, realtype t, int k, N_Vector *dkyS);
+SUNDIALS_EXPORT int IDAGetSensDky1(void *ida_mem, realtype t, int k, int is, N_Vector dkyS);
+
+
+/*
+ * -----------------------------------------------------------------
+ * Consistent sensitivity IC calculation optional outputs
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int IDAGetSensConsistentIC(void *ida_mem, N_Vector *yyS0, N_Vector *ypS0);
+
+/*
+ * -----------------------------------------------------------------
+ * Forward sensitivity optional output extraction routines
+ * -----------------------------------------------------------------
+ * The following functions can be called to get optional outputs
+ * and statistics related to the integration of sensitivities.
+ * -----------------------------------------------------------------
+ * IDAGetSensNumResEvals returns the number of calls to the
+ * sensitivity residual function.
+ * IDAGetNumResEvalsSens returns the number of calls to the
+ * user res routine due to finite difference
+ * evaluations of the sensitivity equations.
+ * IDAGetSensNumErrTestFails returns the number of local error
+ * test failures for sensitivity variables.
+ * IDAGetSensNumLinSolvSetups returns the number of calls made
+ * to the linear solver's setup routine
+ * due to sensitivity computations.
+ * IDAGetSensErrWeights returns the sensitivity error weight
+ * vectors. The user need not allocate space
+ * for ewtS.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int IDAGetSensNumResEvals(void *ida_mem, long int *nresSevals);
+SUNDIALS_EXPORT int IDAGetNumResEvalsSens(void *ida_mem, long int *nresevalsS);
+SUNDIALS_EXPORT int IDAGetSensNumErrTestFails(void *ida_mem, long int *nSetfails);
+SUNDIALS_EXPORT int IDAGetSensNumLinSolvSetups(void *ida_mem, long int *nlinsetupsS);
+SUNDIALS_EXPORT int IDAGetSensErrWeights(void *ida_mem, N_Vector_S eSweight);
+
+/*
+ * -----------------------------------------------------------------
+ * As a convenience, the following function provides the
+ * optional outputs in a group.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int IDAGetSensStats(void *ida_mem, long int *nresSevals,
+ long int *nresevalsS,
+ long int *nSetfails,
+ long int *nlinsetupsS);
+
+/*
+ * ----------------------------------------------------------------
+ * Sensitivity nonlinear solver optional output extraction functions
+ * ----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int IDAGetSensNumNonlinSolvIters(void *ida_mem, long int *nSniters);
+SUNDIALS_EXPORT int IDAGetSensNumNonlinSolvConvFails(void *ida_mem,
+ long int *nSncfails);
+SUNDIALS_EXPORT int IDAGetSensNonlinSolvStats(void *ida_mem,
+ long int *nSniters,
+ long int *nSncfails);
+
+
+/*
+ * -----------------------------------------------------------------
+ * Quadrature sensitivity optional output extraction routines
+ * -----------------------------------------------------------------
+ * The following functions can be called to get optional outputs and
+ * statistics related to the integration of quadrature sensitivitiess.
+ * -----------------------------------------------------------------
+ * IDAGetQuadSensNumRhsEvals returns the number of calls to the
+ * user function fQS defining the right hand side of the
+ * quadrature sensitivity equations.
+ * IDAGetQuadSensNumErrTestFails returns the number of local error
+ * test failures for quadrature sensitivity variables.
+ * IDAGetQuadSensErrWeights returns the vector of error weights
+ * for the quadrature sensitivity variables. The user must
+ * allocate space for ewtQS.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int IDAGetQuadSensNumRhsEvals(void *ida_mem, long int *nrhsQSevals);
+SUNDIALS_EXPORT int IDAGetQuadSensNumErrTestFails(void *ida_mem, long int *nQSetfails);
+SUNDIALS_EXPORT int IDAGetQuadSensErrWeights(void *ida_mem, N_Vector *eQSweight);
+
+/*
+ * -----------------------------------------------------------------
+ * As a convenience, the following function provides the above
+ * optional outputs in a group.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int IDAGetQuadSensStats(void *ida_mem,
+ long int *nrhsQSevals,
+ long int *nQSetfails);
+
+
+/*
+ * -----------------------------------------------------------------
+ * Quadrature Sensitivity solution extraction routines
+ * -----------------------------------------------------------------
+ * The following functions can be called to obtain the sensitivity
+ * variables after a successful integration step.
+ *
+ * IDAGetQuadSens and IDAGetQuadSens1 return all the sensitivity
+ * vectors or only one of them, respectively, at the same time
+ * as that at which IDASolve returned the solution.
+ * The array of output vectors or output vector yQSout must be
+ * allocated by the user.
+ *
+ * IDAGetQuadSensDky1 computes the kth derivative of the is-th
+ * sensitivity (is=1, 2, ..., Ns) of the quadrature function at
+ * time t, where tn - hu <= t <= tn, tn denotes the current
+ * internal time reached and hu is the last internal
+ * successfully step size. The user may request k=0,..., qu,
+ * where qu is the current order.
+ *
+ * The is-th sensitivity derivative vector is returned in dky.
+ * This vector must be allocated by the caller. It is only legal
+ * to call this function after a successful return from IDASolve
+ * with sensitivity computations enabled.
+ * Arguments have the same meaning as in IDADGetky.
+ *
+ * IDAGetQuadSensDky computes the k-th derivative of all
+ * sensitivities of the y function at time t. It repeatedly calls
+ * IDAGetQuadSensDky. The argument dkyS must be a pointer to
+ * N_Vector and must be allocated by the user to hold at least Ns
+ * vectors.
+ *
+ * Return values are similar to those of IDAGetDky. Additionally,
+ * these functions can return IDA_NO_SENS if sensitivities were
+ * not computed and IDA_BAD_IS if is < 0 or is >= Ns.
+ * -----------------------------------------------------------------
+ */
+
+
+SUNDIALS_EXPORT int IDAGetQuadSens(void *ida_mem, realtype *tret, N_Vector *yyQSout);
+SUNDIALS_EXPORT int IDAGetQuadSens1(void *ida_mem, realtype *tret, int is, N_Vector yyQSret);
+
+SUNDIALS_EXPORT int IDAGetQuadSensDky(void *ida_mem, realtype t, int k, N_Vector *dkyQS);
+SUNDIALS_EXPORT int IDAGetQuadSensDky1(void *ida_mem, realtype t, int k, int is, N_Vector dkyQS);
+
+
+/*
+ * -----------------------------------------------------------------
+ * The following function returns the name of the constant
+ * associated with an IDAS return flag
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT char *IDAGetReturnFlagName(long int flag);
+
+/*
+ * ----------------------------------------------------------------
+ * Function : IDAFree
+ * ----------------------------------------------------------------
+ * IDAFree frees the problem memory IDA_mem allocated by
+ * IDAInit. Its only argument is the pointer idamem
+ * returned by IDAInit.
+ * ----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT void IDAFree(void **ida_mem);
+
+/*
+ * -----------------------------------------------------------------
+ * Function : IDAQuadFree
+ * -----------------------------------------------------------------
+ * IDAQuadFree frees the problem memory in ida_mem allocated
+ * for quadrature integration. Its only argument is the pointer
+ * ida_mem returned by IDACreate.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT void IDAQuadFree(void *ida_mem);
+
+/*
+ * -----------------------------------------------------------------
+ * Function : IDASensFree
+ * -----------------------------------------------------------------
+ * IDASensFree frees the problem memory in ida_mem allocated
+ * for sensitivity analysis. Its only argument is the pointer
+ * ida_mem returned by IDACreate.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT void IDASensFree(void *ida_mem);
+
+/*
+ * -----------------------------------------------------------------
+ * Function : IDAQuadSensFree
+ * -----------------------------------------------------------------
+ * IDAQuadSensFree frees the problem memory in ida_mem allocated
+ * for quadrature sensitivity analysis. Its only argument is the
+ * pointer ida_mem returned by IDACreate.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT void IDAQuadSensFree(void* ida_mem);
+
+/*
+ * =================================================================
+ *
+ * INITIALIZATION AND DEALLOCATION FUNCTIONS FOR BACKWARD PROBLEMS
+ *
+ * =================================================================
+ */
+
+/*
+ * -----------------------------------------------------------------
+ * IDAAdjInit
+ * -----------------------------------------------------------------
+ * IDAAdjInit specifies some parameters for ASA, initializes ASA
+ * and allocates space for the adjoint memory structure.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int IDAAdjInit(void *ida_mem, long int steps, int interp);
+/*
+ * -----------------------------------------------------------------
+ * IDAAdjReInit
+ * -----------------------------------------------------------------
+ * IDAAdjReInit reinitializes the IDAS memory structure for ASA,
+ * assuming that the number of steps between check points and the
+ * type of interpolation remained unchanged. The list of check points
+ * (and associated memory) is deleted. The list of backward problems
+ * is kept (however, new backward problems can be added to this list
+ * by calling IDACreateB). The IDAS memory for the forward and
+ * backward problems can be reinitialized separately by calling
+ * IDAReInit and IDAReInitB, respectively.
+ * NOTE: if a entirely new list of backward problems is desired,
+ * then simply free the adjoint memory (by calling IDAAdjFree)
+ * and reinitialize ASA with IDAAdjReInit
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int IDAAdjReInit(void *ida_mem);
+
+/*
+ * -----------------------------------------------------------------
+ * IDAAdjFree
+ * -----------------------------------------------------------------
+ * IDAAdjFree frees the memory allocated by IDAAdjInit.
+ * It is typically called by IDAFree.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT void IDAAdjFree(void *ida_mem);
+
+/*
+ * =================================================================
+ *
+ * OPTIONAL INPUT FUNCTIONS FOR BACKWARD PROBLEMS
+ *
+ * =================================================================
+ */
+
+
+/*
+ * =================================================================
+ *
+ * Interfaces to IDAS functions for setting-up backward problems.
+ *
+ * =================================================================
+ */
+
+SUNDIALS_EXPORT int IDACreateB(void *ida_mem, int *which);
+
+SUNDIALS_EXPORT int IDAInitB(void *ida_mem, int which, IDAResFnB resB,
+ realtype tB0, N_Vector yyB0, N_Vector ypB0);
+
+SUNDIALS_EXPORT int IDAInitBS(void *ida_mem, int which, IDAResFnBS resS,
+ realtype tB0, N_Vector yyB0, N_Vector ypB0);
+
+SUNDIALS_EXPORT int IDAReInitB(void *ida_mem, int which,
+ realtype tB0, N_Vector yyB0, N_Vector ypB0);
+
+SUNDIALS_EXPORT int IDASStolerancesB(void *ida_mem, int which,
+ realtype relTolB, realtype absTolB);
+SUNDIALS_EXPORT int IDASVtolerancesB(void *ida_mem, int which,
+ realtype relTolB, N_Vector absTolB);
+
+SUNDIALS_EXPORT int IDAQuadInitB(void *ida_mem, int which,
+ IDAQuadRhsFnB rhsQB, N_Vector yQB0);
+
+SUNDIALS_EXPORT int IDAQuadInitBS(void *ida_mem, int which,
+ IDAQuadRhsFnBS rhsQS, N_Vector yQB0);
+
+SUNDIALS_EXPORT int IDAQuadReInitB(void *ida_mem, int which, N_Vector yQB0);
+
+SUNDIALS_EXPORT int IDAQuadSStolerancesB(void *ida_mem, int which,
+ realtype reltolQB, realtype abstolQB);
+SUNDIALS_EXPORT int IDAQuadSVtolerancesB(void *ida_mem, int which,
+ realtype reltolQB, N_Vector abstolQB);
+
+/*
+ * ----------------------------------------------------------------
+ * The following functions computes consistent initial conditions
+ * for the backward problems.
+ * ----------------------------------------------------------------
+ * Function : IDACalcICB
+ * ----------------------------------------------------------------
+ * IDACalcICB calculates corrected initial conditions for a DAE
+ * backward system (index-one in semi-implicit form).
+ * ----------------------------------------------------------------
+ * Function : IDACalcICBS
+ * ----------------------------------------------------------------
+ * IDACalcICBS calculates corrected initial conditions for a DAE
+ * backward problems that also depends on the sensitivities.
+ *
+ * They use Newton iteration combined with a Linesearch algorithm.
+ *
+ * Calling IDACalcICB(S) is optional. It is only necessary when the
+ * initial conditions do not solve the given system. I.e., if
+ * yB0 and ypB0 are known to satisfy the backward problem, then
+ * a call to IDACalcICB is NOT necessary (for index-one problems).
+ *
+ * Any call to IDACalcICB(S) should precede the call(s) to
+ * IDASolveB for the given problem.
+ *
+ * The functions compute the algebraic components of y and
+ * differential components of y', given the differential
+ * components of y. This option requires that the N_Vector id was
+ * set through a call to IDASetIdB specifying the differential and
+ * algebraic components.
+ *
+ * The arguments to IDACalcICB(S) are as follows:
+ *
+ * ida_mem is the pointer to IDA memory returned by IDACreate.
+ *
+ * which is the index of the backward problem returned by
+ * IDACreateB
+ *
+ * tout1 is the first value of t at which a soluton will be
+ * requested (from IDASolveB). (This is needed here to
+ * determine the direction of integration and rough
+ * scale in the independent variable t.)
+ *
+ * yy0 state variables y and y' corresponding to the initial
+ * yp0 time at which the backward problem is (re)started.
+ *
+ * yyS0 sensitivities variables corresponding to the initial
+ * ypS0 time at which the backward problem is (re)started.
+ *
+ * Return value is a int flag. For more information see IDACalcIC.
+*/
+
+SUNDIALS_EXPORT int IDACalcICB (void *ida_mem, int which, realtype tout1,
+ N_Vector yy0, N_Vector yp0);
+
+SUNDIALS_EXPORT int IDACalcICBS(void *ida_mem, int which, realtype tout1,
+ N_Vector yy0, N_Vector yp0,
+ N_Vector *yyS0, N_Vector *ypS0);
+
+
+/*
+ * =================================================================
+ *
+ * MAIN SOLVER FUNCTIONS FOR FORWARD PROBLEMS
+ *
+ * =================================================================
+ */
+
+/*
+ * -----------------------------------------------------------------
+ * IDASolveF
+ * -----------------------------------------------------------------
+ * IDASolveF integrates towards tout and returns solution into yret
+ * and ypret.
+ *
+ * In the same time, it stores check point data every 'steps'.
+ *
+ * IDASolveF can be called repeatedly by the user.
+ *
+ * ncheckPtr represents the number of check points stored so far.
+ *
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int IDASolveF(void *ida_mem, realtype tout,
+ realtype *tret,
+ N_Vector yret, N_Vector ypret,
+ int itask, int *ncheckPtr);
+
+
+/*
+ * -----------------------------------------------------------------
+ * IDASolveB
+ * -----------------------------------------------------------------
+ * IDASolveB performs the integration of all backward problems
+ * specified through calls to IDACreateB through a sequence of
+ * forward-backward runs in between consecutive check points. It can
+ * be called either in IDA_NORMAL or IDA_ONE_STEP mode. After a
+ * successful return from IDASolveB, the solution and quadrature
+ * variables at the current return time for any given backward
+ * problem can be obtained by calling IDAGetB and IDAGetQuadB.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int IDASolveB(void *ida_mem, realtype tBout, int itaskB);
+
+
+/*
+ * =================================================================
+ *
+ * OPTIONAL INPUT FUNCTIONS FOR BACKWARD PROBLEMS
+ *
+ * =================================================================
+ */
+
+/*
+ * -----------------------------------------------------------------
+ * IDASetAdjNoSensi
+ * -----------------------------------------------------------------
+ * Disables the forward sensitivity analysis in IDASolveF.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int IDASetAdjNoSensi(void *ida_mem);
+
+/*
+ * -----------------------------------------------------------------
+ * Optional input functions for backward problems
+ * -----------------------------------------------------------------
+ * These functions are just wrappers around the corresponding
+ * functions from the forward module, with some particularizations
+ * for the backward integration.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int IDASetUserDataB(void *ida_mem, int which, void *user_dataB);
+
+SUNDIALS_EXPORT int IDASetMaxOrdB(void *ida_mem, int which, int maxordB);
+
+SUNDIALS_EXPORT int IDASetMaxNumStepsB(void *ida_mem, int which, long int mxstepsB);
+
+SUNDIALS_EXPORT int IDASetInitStepB(void *ida_mem, int which, realtype hinB);
+
+SUNDIALS_EXPORT int IDASetMaxStepB(void *ida_mem, int which, realtype hmaxB);
+
+SUNDIALS_EXPORT int IDASetSuppressAlgB(void *ida_mem, int which,
+ booleantype suppressalgB);
+SUNDIALS_EXPORT int IDASetIdB(void *ida_mem, int which, N_Vector idB);
+
+SUNDIALS_EXPORT int IDASetConstraintsB(void *ida_mem, int which,
+ N_Vector constraintsB);
+
+SUNDIALS_EXPORT int IDASetQuadErrConB(void *ida_mem, int which, int errconQB);
+
+/*
+ * =================================================================
+ *
+ * EXTRACTION AND DENSE OUTPUT FUNCTIONS FOR BACKWARD PROBLEMS
+ *
+ * =================================================================
+ */
+
+/*
+ * -----------------------------------------------------------------
+ * IDAGetB and IDAGetQuadB
+ * -----------------------------------------------------------------
+ * Extraction functions for the solution and quadratures for a given
+ * backward problem. They return their corresponding output vector
+ * at the current time reached by the integration of the backward
+ * problem. To obtain the solution or quadratures associated with
+ * a given backward problem at some other time within the last
+ * integration step (dense output), first obtain a pointer to the
+ * proper IDAS memory by calling IDAGetAdjIDABmem and then use it
+ * to call IDAGetDky and IDAGetQuadDky.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int IDAGetB(void* ida_mem, int which, realtype *tret,
+ N_Vector yy, N_Vector yp);
+
+SUNDIALS_EXPORT int IDAGetQuadB(void *ida_mem, int which,
+ realtype *tret, N_Vector qB);
+
+/*
+ * =================================================================
+ *
+ * OPTIONAL OUTPUT FUNCTIONS FOR BACKWARD PROBLEMS
+ *
+ * =================================================================
+ */
+
+/*
+ * -----------------------------------------------------------------
+ * IDAGetAdjIDABmem
+ * -----------------------------------------------------------------
+ * IDAGetAdjIDABmem returns a (void *) pointer to the IDAS
+ * memory allocated for the backward problem. This pointer can
+ * then be used to call any of the IDAGet* IDAS routines to
+ * extract optional output for the backward integration phase.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT void *IDAGetAdjIDABmem(void *ida_mem, int which);
+
+/*
+ * -----------------------------------------------------------------
+ * IDAGetConsistentICB
+ * -----------------------------------------------------------------
+ * IDAGetConsistentIC returns the consistent initial conditions
+ * computed by IDACalcICB or IDCalcICBS
+ */
+SUNDIALS_EXPORT int IDAGetConsistentICB(void *ida_mem, int which,
+ N_Vector yyB0, N_Vector ypB0);
+
+/*
+ * -----------------------------------------------------------------
+ * IDAGetAdjY
+ * -----------------------------------------------------------------
+ * Returns the interpolated forward solution at time t. This
+ * function is a wrapper around the interpType-dependent internal
+ * function.
+ * The calling function must allocate space for yy and yp.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int IDAGetAdjY(void *ida_mem, realtype t,
+ N_Vector yy, N_Vector yp);
+
+
+/*
+ * -----------------------------------------------------------------
+ * IDAGetAdjCheckPointsInfo
+ * -----------------------------------------------------------------
+ * Loads an array of nckpnts structures of type IDAadjCheckPointRec
+ * defined below.
+ *
+ * The user must allocate space for ckpnt (ncheck+1).
+ * -----------------------------------------------------------------
+ */
+
+ typedef struct {
+ void *my_addr;
+ void *next_addr;
+ realtype t0;
+ realtype t1;
+ long int nstep;
+ int order;
+ realtype step;
+ } IDAadjCheckPointRec;
+
+SUNDIALS_EXPORT int IDAGetAdjCheckPointsInfo(void *ida_mem,
+ IDAadjCheckPointRec *ckpnt);
+
+/*
+ * -----------------------------------------------------------------
+ * IDAGetAdjDataPointHermite
+ * -----------------------------------------------------------------
+ * Returns the 2 vectors stored for cubic Hermite interpolation at
+ * the data point 'which'. The user must allocate space for yy and
+ * yd.
+ *
+ * Returns IDA_MEM_NULL if ida_mem is NULL, IDA_ILL_INPUT if the
+ * interpolation type previously specified is not IDA_HERMITE or
+ * IDA_SUCCESS otherwise.
+ *
+ * -----------------------------------------------------------------
+ * IDAGetAdjDataPointPolynomial
+ * -----------------------------------------------------------------
+ * Returns the vector stored for polynomial interpolation at the
+ * data point 'which'. The user must allocate space for y.
+ *
+ * Returns IDA_MEM_NULL if ida_mem is NULL, IDA_ILL_INPUT if the
+ * interpolation type previously specified is not IDA_POLYNOMIAL or
+ * IDA_SUCCESS otherwise.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int IDAGetAdjDataPointHermite(void *ida_mem, int which,
+ realtype *t, N_Vector yy, N_Vector yd);
+
+SUNDIALS_EXPORT int IDAGetAdjDataPointPolynomial(void *ida_mem, int which,
+ realtype *t, int *order,
+ N_Vector y);
+
+
+/*
+ * -----------------------------------------------------------------
+ * IDAGetAdjCurrentCheckPoint
+ * -----------------------------------------------------------------
+ * Returns the address of the 'active' check point.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int IDAGetAdjCurrentCheckPoint(void *ida_mem, void **addr);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/idas/idas_band.h b/include/idas/idas_band.h
new file mode 100644
index 0000000..6d4d23d
--- /dev/null
+++ b/include/idas/idas_band.h
@@ -0,0 +1,80 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.7 $
+ * $Date: 2010/12/01 22:15:15 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Alan C. Hindmarsh, and Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * 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
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <idas/idas_direct.h>
+#include <sundials/sundials_band.h>
+
+/*
+ * -----------------------------------------------------------------
+ * 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.
+ * -----------------------------------------------------------------
+ */
+
+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
new file mode 100644
index 0000000..70adaff
--- /dev/null
+++ b/include/idas/idas_bbdpre.h
@@ -0,0 +1,327 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.9 $
+ * $Date: 2010/12/01 22:15:15 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Alan C. Hindmarsh, Radu Serban and
+ * Aaron Collier @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * 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.
+ */
+
+#ifndef _IDASBBDPRE_H
+#define _IDASBBDPRE_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <sundials/sundials_nvector.h>
+
+/*
+ * =================================================================
+ * 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.
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * -----------------------------------------------------------------
+ * 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).
+ * -----------------------------------------------------------------
+ */
+
+typedef int (*IDABBDLocalFn)(long int 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.
+ * -----------------------------------------------------------------
+ */
+
+typedef int (*IDABBDCommFn)(long int Nlocal, realtype tt,
+ N_Vector yy, N_Vector yp,
+ void *user_data);
+
+/*
+ * -----------------------------------------------------------------
+ * 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,
+ realtype dq_rel_yy,
+ 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
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int IDABBDPrecReInit(void *ida_mem,
+ long int mudq, long int 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
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int IDABBDPrecGetWorkSpace(void *ida_mem,
+ 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);
+
+typedef int (*IDABBDCommFnB)(long int 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.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT 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 GresB, IDABBDCommFnB GcommB);
+
+SUNDIALS_EXPORT int IDABBDPrecReInitB(void *ida_mem, int which,
+ long int mudqB, long int mldqB, realtype dq_rel_yyB);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/idas/idas_dense.h b/include/idas/idas_dense.h
new file mode 100644
index 0000000..73c1340
--- /dev/null
+++ b/include/idas/idas_dense.h
@@ -0,0 +1,69 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.7 $
+ * $Date: 2010/12/01 22:15:15 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Alan C. Hindmarsh and Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * This is the header file for the IDADENSE linear solver module.
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _IDASDENSE_H
+#define _IDASDENSE_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <idas/idas_direct.h>
+#include <sundials/sundials_dense.h>
+
+/*
+ * -----------------------------------------------------------------
+ * 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.
+ * -----------------------------------------------------------------
+ */
+
+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
new file mode 100644
index 0000000..da20021
--- /dev/null
+++ b/include/idas/idas_direct.h
@@ -0,0 +1,374 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.9 $
+ * $Date: 2010/12/01 22:15:15 $
+ * -----------------------------------------------------------------
+ * Programmer: Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2006, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * Common header file for the direct linear solvers in IDAS.
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _IDADLS_H
+#define _IDADLS_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <sundials/sundials_direct.h>
+#include <sundials/sundials_nvector.h>
+
+/*
+ * =================================================================
+ * I D A S D I R E C T C O N S T A N T S
+ * =================================================================
+ */
+
+/*
+ * -----------------------------------------------------------------
+ * IDASDIRECT 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
+
+/* 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 IDASetRdata.
+ *
+ * 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 IDASetRdata.
+ *
+ * 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
+ *
+ * -----------------------------------------------------------------
+ */
+
+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
+ * -----------------------------------------------------------------
+ */
+
+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 : 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);
+
+/*
+ * -----------------------------------------------------------------
+ * EXPORTED FUNCTIONS
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * -----------------------------------------------------------------
+ * Functions: IDADlsSetJacFnB
+ * -----------------------------------------------------------------
+ * IDADlsSetDenseJacFnB and IDADlsSetBandJacFnB specify the dense
+ * and band, respectively, Jacobian functions to be used by a
+ * IDASDIRECT linear solver for the bacward integration phase.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int IDADlsSetDenseJacFnB(void *ida_mem, int which, IDADlsDenseJacFnB jacB);
+SUNDIALS_EXPORT int IDADlsSetBandJacFnB(void *idaa_mem, int which, IDADlsBandJacFnB jacB);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/idas/idas_lapack.h b/include/idas/idas_lapack.h
new file mode 100644
index 0000000..d94f94e
--- /dev/null
+++ b/include/idas/idas_lapack.h
@@ -0,0 +1,103 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.5 $
+ * $Date: 2008/04/18 19:42:38 $
+ * -----------------------------------------------------------------
+ * Programmer: Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2006, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * Header file for the IDAS dense linear solver IDASLAPACK.
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _IDALAPACK_H
+#define _IDALAPACK_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <idas/idas_direct.h>
+#include <sundials/sundials_lapack.h>
+
+/*
+ * -----------------------------------------------------------------
+ * 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.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int IDALapackDenseB(void *ida_mem, int NeqB);
+
+/*
+ * -----------------------------------------------------------------
+ * Function: IDALapackBandB
+ * -----------------------------------------------------------------
+ * IDALapackBandB links the main IDAS integrator with the band
+ * IDALAPACK linear solver for the backward integration.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int IDALapackBandB(void *ida_mem, int NeqB, int mupperB, int mlowerB);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/idas/idas_spbcgs.h b/include/idas/idas_spbcgs.h
new file mode 100644
index 0000000..1e45c38
--- /dev/null
+++ b/include/idas/idas_spbcgs.h
@@ -0,0 +1,79 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.3 $
+ * $Date: 2007/07/05 19:10:36 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Aaron Collier and Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2004, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * 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
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <idas/idas_spils.h>
+#include <sundials/sundials_spbcgs.h>
+
+/*
+ * -----------------------------------------------------------------
+ * 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
+ * -----------------------------------------------------------------
+ */
+
+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
new file mode 100644
index 0000000..d85aa97
--- /dev/null
+++ b/include/idas/idas_spgmr.h
@@ -0,0 +1,80 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.3 $
+ * $Date: 2007/07/05 19:10:36 $
+ * -----------------------------------------------------------------
+ * Programmers: Alan Hindmarsh and Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California
+ * Produced at the Lawrence Livermore National Laboratory
+ * All rights reserved
+ * For details, see the LICENSE file
+ * -----------------------------------------------------------------
+ * 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
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <idas/idas_spils.h>
+#include <sundials/sundials_spgmr.h>
+
+/*
+ * -----------------------------------------------------------------
+ * 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
+ * -----------------------------------------------------------------
+ */
+
+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
new file mode 100644
index 0000000..b7469dd
--- /dev/null
+++ b/include/idas/idas_spils.h
@@ -0,0 +1,413 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.12 $
+ * $Date: 2010/12/01 22:15:15 $
+ * -----------------------------------------------------------------
+ * Programmers: Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California
+ * Produced at the Lawrence Livermore National Laboratory
+ * All rights reserved
+ * For details, see the LICENSE file
+ * -----------------------------------------------------------------
+ * This is the common header file for the Scaled and Preconditioned
+ * Iterative Linear Solvers in IDAS.
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _IDASSPILS_H
+#define _IDASSPILS_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <sundials/sundials_iterative.h>
+#include <sundials/sundials_nvector.h>
+
+/*
+ * -----------------------------------------------------------------
+ * IDASPILS return values
+ * -----------------------------------------------------------------
+ */
+
+#define IDASPILS_SUCCESS 0
+#define IDASPILS_MEM_NULL -1
+#define IDASPILS_LMEM_NULL -2
+#define IDASPILS_ILL_INPUT -3
+#define IDASPILS_MEM_FAIL -4
+#define IDASPILS_PMEM_NULL -5
+
+/* 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);
+
+/*
+ * -----------------------------------------------------------------
+ * 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,
+ 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,
+ 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
+ * -----------------------------------------------------------------
+ */
+
+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
+ * -----------------------------------------------------------------
+ */
+
+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 : 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 : 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);
+
+/*
+ * -----------------------------------------------------------------
+ * Functions
+ * -----------------------------------------------------------------
+ */
+
+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);
+
+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 IDASpilsSetJacTimesVecFnB(void *ida_mem, int which,
+ IDASpilsJacTimesVecFnB jtvB);
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/idas/idas_sptfqmr.h b/include/idas/idas_sptfqmr.h
new file mode 100644
index 0000000..18d931e
--- /dev/null
+++ b/include/idas/idas_sptfqmr.h
@@ -0,0 +1,78 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.3 $
+ * $Date: 2007/07/05 19:10:36 $
+ * -----------------------------------------------------------------
+ * 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.
+ * -----------------------------------------------------------------
+ * 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
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <idas/idas_spils.h>
+#include <sundials/sundials_sptfqmr.h>
+
+/*
+ * -----------------------------------------------------------------
+ * 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
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int IDASptfqmrB(void *ida_mem, int which, int maxlB);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/kinsol/kinsol.h b/include/kinsol/kinsol.h
new file mode 100644
index 0000000..3bace44
--- /dev/null
+++ b/include/kinsol/kinsol.h
@@ -0,0 +1,765 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.7 $
+ * $Date: 2010/12/01 22:16:17 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Allan Taylor, Alan Hindmarsh, Radu Serban, and
+ * Aaron Collier @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * KINSOL solver module header file
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _KINSOL_H
+#define _KINSOL_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <stdio.h>
+
+#include <sundials/sundials_nvector.h>
+
+/*
+ * =================================================================
+ * K I N S O L C O N S T A N T S
+ * =================================================================
+ */
+
+/*
+ * -----------------------------------------------------------------
+ * KINSOL return flags
+ * -----------------------------------------------------------------
+ */
+
+#define KIN_SUCCESS 0
+#define KIN_INITIAL_GUESS_OK 1
+#define KIN_STEP_LT_STPTOL 2
+
+#define KIN_WARNING 99
+
+#define KIN_MEM_NULL -1
+#define KIN_ILL_INPUT -2
+#define KIN_NO_MALLOC -3
+#define KIN_MEM_FAIL -4
+#define KIN_LINESEARCH_NONCONV -5
+#define KIN_MAXITER_REACHED -6
+#define KIN_MXNEWT_5X_EXCEEDED -7
+#define KIN_LINESEARCH_BCFAIL -8
+#define KIN_LINSOLV_NO_RECOVERY -9
+#define KIN_LINIT_FAIL -10
+#define KIN_LSETUP_FAIL -11
+#define KIN_LSOLVE_FAIL -12
+
+#define KIN_SYSFUNC_FAIL -13
+#define KIN_FIRST_SYSFUNC_ERR -14
+#define KIN_REPTD_SYSFUNC_ERR -15
+
+
+/*
+ * -----------------------------------------------------------------
+ * Enumeration for inputs to KINSetEtaForm (eta choice)
+ * -----------------------------------------------------------------
+ * KIN_ETACONSTANT : use constant value for eta (default value is
+ * 0.1 but a different value can be specified via
+ * a call to KINSetEtaConstValue)
+ *
+ * KIN_ETACHOICE1 : use choice #1 as given in Eisenstat and Walker's
+ * paper of SIAM J.Sci.Comput.,17 (1996), pp 16-32,
+ * wherein eta is defined to be:
+ *
+ * eta(k+1) = ABS(||F(u_k+1)||_L2-||F(u_k)+J(u_k)*p_k||_L2)
+ * ---------------------------------------------
+ * ||F(u_k)||_L2
+ *
+ * 1+sqrt(5)
+ * eta_safe = eta(k)^ealpha where ealpha = ---------
+ * 2
+ *
+ * KIN_ETACHOICE2 : use choice #2 as given in Eisenstat and Walker's
+ * paper wherein eta is defined to be:
+ *
+ * [ ||F(u_k+1)||_L2 ]^ealpha
+ * eta(k+1) = egamma * [ --------------- ]
+ * [ ||F(u_k)||_L2 ]
+ *
+ * where egamma = [0,1] and ealpha = (1,2]
+ *
+ * eta_safe = egamma*(eta(k)^ealpha)
+ *
+ * Note: The default values of the scalar
+ * coefficients egamma and ealpha (both required)
+ * are egamma = 0.9 and ealpha = 2.0, but the
+ * routine KINSetEtaParams can be used to specify
+ * different values.
+ *
+ * When using either KIN_ETACHOICE1 or KIN_ETACHOICE2, if
+ * eta_safe > 0.1 then the following safeguard is applied:
+ *
+ * eta(k+1) = MAX {eta(k+1), eta_safe}
+ *
+ * The following safeguards are always applied when using either
+ * KIN_ETACHOICE1 or KIN_ETACHOICE2 so that eta_min <= eta <= eta_max:
+ *
+ * eta(k+1) = MAX {eta(k+1), eta_min}
+ * eta(k+1) = MIN {eta(k+1), eta_max}
+ *
+ * where eta_min = 1.0e-4 and eta_max = 0.9 (see KINForcingTerm).
+ * -----------------------------------------------------------------
+ */
+
+#define KIN_ETACHOICE1 1
+#define KIN_ETACHOICE2 2
+#define KIN_ETACONSTANT 3
+
+/*
+ * -----------------------------------------------------------------
+ * Enumeration for global strategy
+ * -----------------------------------------------------------------
+ * Choices are KIN_NONE and KIN_LINESEARCH.
+ * -----------------------------------------------------------------
+ */
+
+#define KIN_NONE 0
+#define KIN_LINESEARCH 1
+
+/*
+ * =================================================================
+ * F U N C T I O N T Y P E S
+ * =================================================================
+ */
+
+/*
+ * -----------------------------------------------------------------
+ * Type : KINSysFn
+ * -----------------------------------------------------------------
+ * The user-supplied subroutine implementing the nonlinear system
+ * function (vector-valued function) F must take as input the
+ * dependent variable vector uu (type N_Vector), and set fval (type
+ * N_Vector) equal to F(uu) before returning. Additional workspace
+ * is allocated by the user and referenced by the user_data memory
+ * pointer.
+ *
+ * Note: The user-defined routine (internally referenced by a
+ * a pointer (type KINSysFn) named func) should have an 'int' return
+ * value type. However, the return value is currently ignored.
+ * -----------------------------------------------------------------
+ */
+
+typedef int (*KINSysFn)(N_Vector uu, N_Vector fval, void *user_data );
+
+
+/*
+ * -----------------------------------------------------------------
+ * Type : KINErrHandlerFn
+ * -----------------------------------------------------------------
+ * A function eh, which handles error messages, must have type
+ * KINErrHandlerFn.
+ * The function eh takes as input the error code, the name of the
+ * module reporting the error, the error message, and a pointer to
+ * user data, the same as that passed to KINSetUserData.
+ *
+ * All error codes are negative, except KIN_WARNING which indicates
+ * a warning (the solver continues).
+ *
+ * A KINErrHandlerFn has no return value.
+ * -----------------------------------------------------------------
+ */
+
+typedef void (*KINErrHandlerFn)(int error_code,
+ const char *module, const char *function,
+ char *msg, void *user_data);
+
+
+/*
+ * -----------------------------------------------------------------
+ * Type : KINInfoHandlerFn
+ * -----------------------------------------------------------------
+ * A function ih, which handles info messages, must have type
+ * KINInfoHandlerFn.
+ * The function ih takes as input the name of the module and of the
+ * function reporting the info message and a pointer to
+ * user data, the same as that passed to KINSetfdata.
+ *
+ * A KINInfoHandlerFn has no return value.
+ * -----------------------------------------------------------------
+ */
+
+typedef void (*KINInfoHandlerFn)(const char *module, const char *function,
+ char *msg, void *user_data);
+
+/*
+ * ================================================================
+ * U S E R - C A L L A B L E R O U T I N E S
+ * ================================================================
+ */
+
+/*
+ * -----------------------------------------------------------------
+ * Function : KINCreate
+ * -----------------------------------------------------------------
+ * KINCreate allocates and initializes an internal memory block for
+ * the KINSOL solver module.
+ *
+ * If successful, KINCreate returns a pointer to the initialized
+ * memory block which should be passed to KINInit. If an
+ * error occurs, then KINCreate returns a NULL pointer.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT void *KINCreate(void);
+
+/*
+ * -----------------------------------------------------------------
+ * Optional Input Specification Functions (KINSOL)
+ * -----------------------------------------------------------------
+ * The following functions can be called to set optional inputs:
+ *
+ * Function Name | Optional Input [Default Value]
+ * |
+ * -----------------------------------------------------------------
+ * |
+ * KINSetErrHandlerFn | user-provided ErrHandler function.
+ * | [internal]
+ * |
+ * KINSetErrFile | pointer (type FILE) indicating where all
+ * | warning/error messages should be sent
+ * | if the default internal error handler
+ * | is used
+ * | [stderr]
+ * |
+ * KINSetPrintLevel | level of verbosity of output:
+ * |
+ * | 0 no statistical information is
+ * | displayed (default level)
+ * |
+ * | 1 for each nonlinear iteration display
+ * | the following information: the scaled
+ * | norm (L2) of the system function
+ * | evaluated at the current iterate, the
+ * | scaled norm of the Newton step (only if
+ * | using KIN_NONE), and the
+ * | number of function evaluations performed
+ * | thus far
+ * |
+ * | 2 display level 1 output and the
+ * | following values for each iteration:
+ * |
+ * | fnorm (L2) = ||fscale*func(u)||_L2
+ * | (only for KIN_NONE)
+ * |
+ * | scaled fnorm (for stopping) =
+ * | ||fscale*ABS(func(u))||_L-infinity
+ * | (for KIN_NONE and
+ * | KIN_LINESEARCH)
+ * |
+ * | 3 display level 2 output plus additional
+ * | values used by the global strategy
+ * | (only if using KIN_LINESEARCH), and
+ * | statistical information for the linear
+ * | solver
+ * | [0]
+ * |
+ * KINSetInfoHandlerFn | user-provided InfoHandler function.
+ * | [internal]
+ * |
+ * KINSetInfoFile | pointer (type FILE) specifying where
+ * | informative (non-error) messages should
+ * | be sent if the default internal info
+ * | handler is used
+ * | [stdout]
+ * |
+ * KINSetUserData | pointer to user-allocated memory that is
+ * | passed to the user-supplied subroutine
+ * | implementing the nonlinear system function
+ * | F(u)
+ * | [NULL]
+ * |
+ * KINSetNumMaxIters | maximum number of nonlinear iterations
+ * | [MXITER_DEFAULT] (defined in kinsol_impl.h)
+ * |
+ * 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]
+ * |
+ * 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]
+ * |
+ * KINSetMaxSetupCalls | mbset, number of nonlinear iteraions, such
+ * | that a call to the linear solver setup routine
+ * | (lsetup) is forced every mbset iterations.
+ * | If mbset=1, lsetup s called at every iteration.
+ * | [MSBSET_DEFAULT] (defined in kinsol_impl.h)
+ * |
+ * KINSetMaxSubSetupCalls | mbsetsub is the number of nonlinear iterations
+ * | between checks by the nonlinear residual
+ * | monitoring algorithm (specifies length of
+ * | subinterval)
+ * | NOTE: mbset should be a multiple of mbsetsub
+ * | [MSBSET_SUB_DEFAULT] (defined in kinsol_impl.h)
+ * |
+ * KINSetEtaForm | flag indicating which method to use to
+ * | compute the value of the eta coefficient
+ * | used in the calculation of the linear
+ * | solver convergence tolerance:
+ * |
+ * | eps = (eta+uround)*||fscale*func(u)||_L2
+ * |
+ * | the linear solver tests for convergence by
+ * | checking if the following inequality has
+ * | been satisfied:
+ * |
+ * | ||fscale*(func(u)+J(u)*p)||_L2 <= eps
+ * |
+ * | where J(u) is the system Jacobian
+ * | evaluated at the current iterate, and p
+ * | denotes the Newton step
+ * |
+ * | choices for computing eta are as follows:
+ * |
+ * | KIN_ETACHOICE1 (refer to KINForcingTerm)
+ * |
+ * | eta = ABS(||F(u_k+1)||_L2-||F(u_k)+J(u_k)*p_k||_L2)
+ * | ---------------------------------------------
+ * | ||F(u_k)||_L2
+ * |
+ * | KIN_ETACHOICE2 (refer to KINForcingTerm)
+ * |
+ * | [ ||F(u_k+1)||_L2 ]^alpha
+ * | eta = gamma * [ --------------- ]
+ * | [ ||F(u_k)||_L2 ]
+ * |
+ * | where gamma = [0,1] and alpha = (1,2]
+ * |
+ * | KIN_ETACONSTANT use a constant value for eta
+ * | [KIN_ETACHOICE1]
+ * |
+ * KINSetEtaConstValue | constant value of eta - use with
+ * | KIN_ETACONSTANT option
+ * | [0.1]
+ * |
+ * KINSetEtaParams | values of eta_gamma (egamma) and eta_alpha
+ * | (ealpha) coefficients - use with KIN_ETACHOICE2
+ * | option
+ * | [0.9 and 2.0]
+ * |
+ * KINSetResMonParams | values of omega_min and omega_max scalars
+ * | used by nonlinear residual monitoring
+ * | algorithm (see KINStop)
+ * | [0.00001 and 0.9]
+ * |
+ * KINSetResMonConstValue | constant value used by residual monitoring
+ * | algorithm. If omega=0, then it is estimated
+ * | using omega_min and omega_max.
+ * | [0.0]
+ * |
+ * KINSetNoMinEps | flag controlling whether or not the value
+ * | of eps is bounded below by 0.01*fnormtol
+ * | (see KINSetFuncNormTol)
+ * |
+ * | FALSE constrain value of eps by setting
+ * | to the following:
+ * |
+ * | eps = MAX{0.01*fnormtol, eps}
+ * |
+ * | TRUE do not constrain value of eps
+ * | [FALSE]
+ * |
+ * KINSetMaxNewtonStep | maximum scaled length of Newton step
+ * | (reset to value of one if user-supplied
+ * | value is less than one)
+ * | [1000*||uscale*u_0||_L2]
+ * |
+ * KINSetMaxBetaFails | maximum number of beta condition failures
+ * | in the line search algorithm.
+ * | [MXNBCF_DEFAULT] (defined in kinsol_impl.h)
+ * |
+ * KINSetRelErrFunc | real scalar equal to realative error in
+ * | computing F(u) (used in difference-
+ * | quotient approximation of matrix-vector
+ * | product J(u)*v)
+ * | [(uround)^1/2]
+ * |
+ * KINSetFuncNormTol | real scalar used as stopping tolerance on
+ * | ||fscale*ABS(func(u))||_L-infinity (see
+ * | KINStop and KINInitialStop)
+ * | [(uround)^1/3]
+ * |
+ * KINSetScaledStepTol | real scalar used as stopping tolerance on
+ * | the maximum scaled step length:
+ * |
+ * | || u_k+1 - u_k ||
+ * | || ----------------- ||_L-infinity
+ * | || ABS(u_k+1)+uscale ||
+ * |
+ * | (see KINStop)
+ * | [(uround)^2/3]
+ * |
+ * KINSetConstraints | pointer to an array (type N_Vector) of
+ * | constraints on the solution vector u
+ * |
+ * | if constraints[i] =
+ * |
+ * | 0 u[i] not constrained
+ * |
+ * | +1 u[i] constrained to be >= 0
+ * | -1 u[i] constrained to be <= 0
+ * |
+ * | +2 u[i] constrained to be > 0
+ * | -2 u[i] constrained to be < 0
+ * |
+ * | if a NULL pointer is given, then no
+ * | constraints are applied to vector u
+ * | [NULL]
+ * |
+ * KINSetSysFunc | set the user-provided routine which
+ * | defines the nonlinear problem to be
+ * | solved
+ * | [none]
+ * -----------------------------------------------------------------
+ * The possible return values for the KINSet* subroutines are the
+ * following:
+ *
+ * KIN_SUCCESS : means the associated variable was successfully
+ * set [0]
+ *
+ * KIN_MEM_NULL : means a NULL KINSOL memory block pointer was given
+ * (must call the KINCreate and KINInit memory
+ * allocation subroutines prior to calling KINSol) [-1]
+ *
+ * KIN_ILL_INPUT : means the supplied parameter was invalid (check
+ * error message) [-2]
+ * -----------------------------------------------------------------
+ * Note: If successful, these functions return KIN_SUCCESS. If an
+ * argument has an illegal value, then an error message is printed
+ * to the file specified by errfp and an error code is returned.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int KINSetErrHandlerFn(void *kinmem, KINErrHandlerFn ehfun, void *eh_data);
+SUNDIALS_EXPORT int KINSetErrFile(void *kinmem, FILE *errfp);
+SUNDIALS_EXPORT int KINSetInfoHandlerFn(void *kinmem, KINInfoHandlerFn ihfun, void *ih_data);
+SUNDIALS_EXPORT int KINSetInfoFile(void *kinmem, FILE *infofp);
+SUNDIALS_EXPORT int KINSetUserData(void *kinmem, void *user_data);
+SUNDIALS_EXPORT int KINSetPrintLevel(void *kinmemm, int printfl);
+SUNDIALS_EXPORT int KINSetNumMaxIters(void *kinmem, long int mxiter);
+SUNDIALS_EXPORT int KINSetNoInitSetup(void *kinmem, booleantype noInitSetup);
+SUNDIALS_EXPORT int KINSetNoResMon(void *kinmem, booleantype noNNIResMon);
+SUNDIALS_EXPORT int KINSetMaxSetupCalls(void *kinmem, long int msbset);
+SUNDIALS_EXPORT int KINSetMaxSubSetupCalls(void *kinmem, long int msbsetsub);
+SUNDIALS_EXPORT int KINSetEtaForm(void *kinmem, int etachoice);
+SUNDIALS_EXPORT int KINSetEtaConstValue(void *kinmem, realtype eta);
+SUNDIALS_EXPORT int KINSetEtaParams(void *kinmem, realtype egamma, realtype ealpha);
+SUNDIALS_EXPORT int KINSetResMonParams(void *kinmem, realtype omegamin, realtype omegamax);
+SUNDIALS_EXPORT int KINSetResMonConstValue(void *kinmem, realtype omegaconst);
+SUNDIALS_EXPORT int KINSetNoMinEps(void *kinmem, booleantype noMinEps);
+SUNDIALS_EXPORT int KINSetMaxNewtonStep(void *kinmem, realtype mxnewtstep);
+SUNDIALS_EXPORT int KINSetMaxBetaFails(void *kinmem, long int mxnbcf);
+SUNDIALS_EXPORT int KINSetRelErrFunc(void *kinmem, realtype relfunc);
+SUNDIALS_EXPORT int KINSetFuncNormTol(void *kinmem, realtype fnormtol);
+SUNDIALS_EXPORT int KINSetScaledStepTol(void *kinmem, realtype scsteptol);
+SUNDIALS_EXPORT int KINSetConstraints(void *kinmem, N_Vector constraints);
+SUNDIALS_EXPORT int KINSetSysFunc(void *kinmem, KINSysFn func);
+
+/*
+ * -----------------------------------------------------------------
+ * Function : KINInit
+ * -----------------------------------------------------------------
+ * KINInit allocates additional memory for vector storage and
+ * sets a couple problem-specific KINSOL variables.
+ *
+ * Note: Additional vectors must be initialized by the user and
+ * passed to the KINSol routine.
+ *
+ * kinmem pointer to an internal memory block allocated during a
+ * prior call to KINCreate
+ *
+ * func name of user-supplied subroutine implementing the
+ * nonlinear function F(u)
+ *
+ * tmpl implementation-specific template vector (type N_Vector)
+ * (created using either N_VNew_Serial or N_VNew_Parallel)
+ *
+ * KINInit return flags: KIN_SUCCESS, KIN_MEM_NULL, KIN_ILL_INPUT,
+ * and KIN_MEM_FAIL (see below). If an error occurs, then KINInit
+ * prints an error message.
+ *
+ * -----------------------------------------------------------------
+ * The possible return values for the KINInit subroutine are the
+ * following:
+ *
+ * KIN_SUCCESS : means the necessary system memory was successfully
+ * allocated [0]
+ *
+ * KIN_MEM_NULL : means a NULL KINSOL memory block pointer was given
+ * (must call the KINCreate routine before calling
+ * KINInit) [-1]
+ *
+ * KIN_ILL_INPUT : means the name of a user-supplied subroutine
+ * implementing the nonlinear system function F(u)
+ * was not given [-2]
+ *
+ * KIN_MEM_FAIL : means an error occurred during memory allocation
+ * (either insufficient system resources are available
+ * or the vector kernel has not yet been initialized)
+ * [-4]
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int KINInit(void *kinmem, KINSysFn func, N_Vector tmpl);
+
+/*
+ * -----------------------------------------------------------------
+ * Function : KINSol
+ * -----------------------------------------------------------------
+ * KINSol (main KINSOL driver routine) manages the computational
+ * process of computing an approximate solution of the nonlinear
+ * system. If the initial guess (initial value assigned to vector u)
+ * doesn't violate any user-defined constraints, then the subroutine
+ * attempts to solve the system F(u) = 0 using a nonlinear Krylov
+ * subspace projection method. The Newton-Krylov iterations are
+ * stopped if either of the following conditions is satisfied:
+ *
+ * ||F(u)||_L-infinity <= 0.01*fnormtol
+ *
+ * ||u[i+1] - u[i]||_L-infinity <= scsteptol
+ *
+ * However, if the current iterate satisfies the second stopping
+ * criterion, it doesn't necessarily mean an approximate solution
+ * has been found since the algorithm may have stalled, or the
+ * user-specified step tolerance (scsteptol) may be too large.
+ *
+ * kinmem pointer to an internal memory block allocated during a
+ * prior call to KINCreate
+ *
+ * uu vector set to initial guess by user before calling KINSol,
+ * but which upon return contains an approximate solution of
+ * the nonlinear system F(u) = 0
+ *
+ * strategy global strategy applied to Newton step if unsatisfactory
+ * (KIN_NONE or KIN_LINESEARCH)
+ *
+ * u_scale vector containing diagonal elements of scaling matrix
+ * for vector u chosen so that the components of
+ * u_scale*u (as a matrix multiplication) all have
+ * about the same magnitude when u is close to a root
+ * of F(u)
+ *
+ * f_scale vector containing diagonal elements of scaling matrix
+ * for F(u) chosen so that the components of
+ * f_scale*F(u) (as a matrix multiplication) all have
+ * roughly the same magnitude when u is not too near a
+ * root of F(u)
+ *
+ * Note: The components of vectors u_scale and f_scale should be
+ * positive.
+ *
+ * If successful, KINSol returns a vector uu contains an approximate
+ * solution of the given nonlinear system. If an error occurs, then
+ * an error message is printed and an error code is returned.
+ *
+ * -----------------------------------------------------------------
+ * KINSol Return Values
+ * -----------------------------------------------------------------
+ *
+ * The possible return values for the KINSol subroutine are the
+ * following:
+ *
+ * KIN_SUCCESS : means ||fscale*ABS(func(u))||_L-infinity <= 0.01*fnormtol
+ * and the current iterate uu is probably an approximate
+ * solution of the nonlinear system F(u) = 0 [0]
+ *
+ * KIN_INITIAL_GUESS_OK : means the initial user-supplied guess
+ * already satisfies the stopping criterion
+ * given above [1]
+ *
+ * KIN_STEP_LT_STPTOL : means the following inequality has been
+ * satisfied (stopping tolerance on scaled
+ * step length):
+ *
+ * || u_k+1 - u_k ||
+ * || ----------------- ||_L-infinity <= scsteptol
+ * || ABS(u_k+1)+uscale ||
+ *
+ * so the current iterate (denoted above by u_k+1)
+ * may be an approximate solution of the given
+ * nonlinear system, but it is also quite possible
+ * that the algorithm is "stalled" (making
+ * insufficient progress) near an invalid solution,
+ * or the real scalar scsteptol is too large [2]
+ *
+ * KIN_LINESEARCH_NONCONV : means the line search algorithm was unable
+ * to find an iterate sufficiently distinct
+ * from the current iterate
+ *
+ * failure to satisfy the sufficient decrease
+ * condition could mean the current iterate is
+ * "close" to an approximate solution of the given
+ * nonlinear system, the finite-difference
+ * approximation of the matrix-vector product
+ * J(u)*v is inaccurate, or the real scalar
+ * scsteptol is too large [-5]
+ *
+ * KIN_MAXITER_REACHED : means the maximum number of nonlinear iterations
+ * has been reached [-6]
+ *
+ * KIN_MXNEWT_5X_EXCEEDED : means five consecutive steps have been taken
+ * that satisfy the following inequality:
+ *
+ * ||uscale*p||_L2 > 0.99*mxnewtstep
+ *
+ * where p denotes the current step and
+ * mxnewtstep is a real scalar upper bound
+ * on the scaled step length
+ *
+ * such a failure may mean ||fscale*func(u)||_L2
+ * asymptotes from above to a finite value, or
+ * the real scalar mxnewtstep is too small [-7]
+ *
+ * KIN_LINESEARCH_BCFAIL : means the line search algorithm (implemented
+ * in KINLineSearch) was unable to satisfy the
+ * beta-condition for MXNBCF + 1 nonlinear
+ * iterations (not necessarily consecutive),
+ * which may indicate the algorithm is making
+ * poor progress [-8]
+ *
+ * KIN_LINSOLV_NO_RECOVERY : means the user-supplied routine psolve
+ * encountered a recoverable error, but
+ * the preconditioner is already current [-9]
+ *
+ * KIN_LINIT_FAIL : means the linear solver initialization routine (linit)
+ * encountered an error [-10]
+ *
+ * KIN_LSETUP_FAIL : means the user-supplied routine pset (used to compute
+ * the preconditioner) encountered an unrecoverable
+ * error [-11]
+ *
+ * KIN_LSOLVE_FAIL : means either the user-supplied routine psolve (used to
+ * to solve the preconditioned linear system) encountered
+ * an unrecoverable error, or the linear solver routine
+ * (lsolve) encountered an error condition [-12]
+ *
+ * KIN_MEM_NULL : means a NULL KINSOL memory block pointer was given
+ * (must call the KINCreate and KINInit memory
+ * allocation subroutines prior to calling KINSol) [-1]
+ *
+ * KIN_NO_MALLOC : means additional system memory has not yet been
+ * allocated for vector storage (forgot to call the
+ * KINInit routine) [-3]
+ *
+ * KIN_ILL_INPUT : means at least one input parameter was invalid
+ * (check error output) [-2]
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int KINSol(void *kinmem, N_Vector uu, int strategy,
+ N_Vector u_scale, N_Vector f_scale);
+
+/*
+ * -----------------------------------------------------------------
+ * Optional Output Extraction Functions (KINSOL)
+ * -----------------------------------------------------------------
+ * The following functions can be called to get optional outputs
+ * and statistical information related to the KINSOL solver:
+ *
+ * Function Name | Returned Value
+ * |
+ * -----------------------------------------------------------------
+ * |
+ * KINGetWorkSpace | returns both integer workspace size
+ * | (total number of long int-sized blocks
+ * | of memory allocated by KINSOL for
+ * | vector storage) and real workspace
+ * | size (total number of realtype-sized
+ * | blocks of memory allocated by KINSOL
+ * | for vector storage)
+ * |
+ * KINGetNumFuncEvals | total number evaluations of the
+ * | nonlinear system function F(u)
+ * | (number of direct calls made to the
+ * | user-supplied subroutine by KINSOL
+ * | module member functions)
+ * |
+ * KINGetNumNonlinSolvIters | total number of nonlinear iterations
+ * | performed
+ * |
+ * KINGetNumBetaCondFails | total number of beta-condition
+ * | failures (see KINLineSearch)
+ * |
+ * | KINSOL halts if the number of such
+ * | failures exceeds the value of the
+ * | constant MXNBCF (defined in kinsol.c)
+ * |
+ * KINGetNumBacktrackOps | total number of backtrack operations
+ * | (step length adjustments) performed
+ * | by the line search algorithm (see
+ * | KINLineSearch)
+ * |
+ * KINGetFuncNorm | scaled norm of the nonlinear system
+ * | function F(u) evaluated at the
+ * | current iterate:
+ * |
+ * | ||fscale*func(u)||_L2
+ * |
+ * KINGetStepLength | scaled norm (or length) of the step
+ * | used during the previous iteration:
+ * |
+ * | ||uscale*p||_L2
+ * |
+ * KINGetReturnFlagName | returns the name of the constant
+ * | associated with a KINSOL return flag
+ * |
+ * -----------------------------------------------------------------
+ *
+ * The possible return values for the KINSet* subroutines are the
+ * following:
+ *
+ * KIN_SUCCESS : means the information was successfully retrieved [0]
+ *
+ * KIN_MEM_NULL : means a NULL KINSOL memory block pointer was given
+ * (must call the KINCreate and KINInit memory
+ * allocation subroutines prior to calling KINSol) [-1]
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int KINGetWorkSpace(void *kinmem, long int *lenrw, long int *leniw);
+SUNDIALS_EXPORT int KINGetNumNonlinSolvIters(void *kinmem, long int *nniters);
+SUNDIALS_EXPORT int KINGetNumFuncEvals(void *kinmem, long int *nfevals);
+SUNDIALS_EXPORT int KINGetNumBetaCondFails(void *kinmem, long int *nbcfails);
+SUNDIALS_EXPORT int KINGetNumBacktrackOps(void *kinmem, long int *nbacktr);
+SUNDIALS_EXPORT int KINGetFuncNorm(void *kinmem, realtype *fnorm);
+SUNDIALS_EXPORT int KINGetStepLength(void *kinmem, realtype *steplength);
+SUNDIALS_EXPORT char *KINGetReturnFlagName(long int flag);
+
+/*
+ * -----------------------------------------------------------------
+ * Function : KINFree
+ * -----------------------------------------------------------------
+ * KINFree frees system memory resources reserved for the KINSOL
+ * solver module.
+ *
+ * kinmem pointer to an internal memory block allocated during
+ * prior calls to KINCreate and KINInit
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT void KINFree(void **kinmem);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/kinsol/kinsol_band.h b/include/kinsol/kinsol_band.h
new file mode 100644
index 0000000..73c3a3d
--- /dev/null
+++ b/include/kinsol/kinsol_band.h
@@ -0,0 +1,57 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.5 $
+ * $Date: 2010/12/01 22:16:17 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * This is the header file for the KINSOL band linear solver, KINBAND.
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _KINBAND_H
+#define _KINBAND_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <kinsol/kinsol_direct.h>
+#include <sundials/sundials_band.h>
+
+/*
+ * -----------------------------------------------------------------
+ * 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
new file mode 100644
index 0000000..6ca9aad
--- /dev/null
+++ b/include/kinsol/kinsol_bbdpre.h
@@ -0,0 +1,233 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.7 $
+ * $Date: 2010/12/01 22:16:17 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Alan Hindmarsh, Radu Serban, and Aaron Collier @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * 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.
+ *
+ * Summary:
+ *
+ * These routines provide a preconditioner matrix for KINSol that
+ * is block-diagonal with banded blocks. The blocking corresponds
+ * to the distribution of the dependent variable vector u amongst
+ * the processes. Each preconditioner block is generated from
+ * the Jacobian of the local part (associated with the current
+ * process) of a given function g(u) approximating f(u). The blocks
+ * are generated by each process via a difference quotient scheme,
+ * utilizing the assumed banded structure with given half-bandwidths,
+ * mudq and mldq. However, the banded Jacobian block kept by the
+ * scheme has half-bandwidths mukeep and mlkeep, which may be smaller.
+ *
+ * The user's calling program should have the following form:
+ *
+ * #include <sundials/sundials_types.h>
+ * #include <sundials/sundials_math.h>
+ * #include <sundials/sundials_iterative.h>
+ * #include <nvector_parallel.h>
+ * #include <kinsol.h>
+ * #include <kinsol/kinsol_bbdpre.h>
+ * ...
+ * MPI_Init(&argc,&argv);
+ * ...
+ * 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,...);
+ * ...
+ * flag = KINBBDPrecInit(kin_mem,...);
+ * ...
+ * KINSol(kin_mem,...);
+ * ...
+ * KINFree(&kin_mem);
+ * ...
+ * N_VDestroy_Parallel(tmpl);
+ * ...
+ * MPI_Finalize();
+ *
+ * The user-supplied routines required are:
+ *
+ * func the function f(u) defining the system to be solved:
+ * f(u) = 0
+ *
+ * glocal the function defining the approximation g(u) to f(u)
+ *
+ * gcomm the function to do necessary communication for glocal
+ *
+ * Notes:
+ *
+ * 1) This header file (kinsol_bbdpre.h) is included by the user for
+ * the definition of the KBBDData data type and for needed
+ * function prototypes.
+ *
+ * 2) The KINBBDPrecInit 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 greater efficiency. Also, the half-bandwidths mukeep and
+ * mlkeep of the retained banded approximate Jacobian block may be
+ * even smaller, to furhter reduce storage and computational costs.
+ * For all four half-bandwidths, the values need not be the same
+ * for every process.
+ *
+ * 3) The actual name of the user's f function is passed to
+ * KINInit, and the names of the user's glocal and gcomm
+ * functions are passed to KINBBDPrecInit.
+ *
+ * 4) Optional outputs specific to this module are available by
+ * way of the functions listed below. These include work space
+ * sizes and the cumulative number of glocal calls.
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _KINBBDPRE_H
+#define _KINBBDPRE_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <sundials/sundials_nvector.h>
+
+/* KINBBDPRE return values */
+
+#define KINBBDPRE_SUCCESS 0
+#define KINBBDPRE_PDATA_NULL -11
+#define KINBBDPRE_FUNC_UNRECVR -12
+/*
+ * -----------------------------------------------------------------
+ * Type : KINCommFn
+ * -----------------------------------------------------------------
+ * The user must supply a function of type KINCommFn which
+ * performs all inter-process communication necessary to
+ * evaluate the approximate system function described above.
+ *
+ * This function takes as input the local vector size Nlocal,
+ * 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
+ * space defined with the structure *user_data.
+ *
+ * Each call to the KINCommFn 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
+ * 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 non-zero value if an error occured.
+ * -----------------------------------------------------------------
+ */
+
+typedef int (*KINCommFn)(long int Nlocal, N_Vector u, void *user_data);
+
+/*
+ * -----------------------------------------------------------------
+ * Type : KINLocalFn
+ * -----------------------------------------------------------------
+ * 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
+ * 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
+ * compute the local part of g(u) and store the result in the
+ * vector gval. (Note: Memory for uu 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.
+ *
+ * A KINLocalFn function should return 0 if successful or
+ * a non-zero value if an error occured.
+ * -----------------------------------------------------------------
+ */
+
+typedef int (*KINLocalFn)(long int Nlocal, N_Vector uu,
+ N_Vector gval, void *user_data);
+
+/*
+ * -----------------------------------------------------------------
+ * Function : KINBBDPrecInit
+ * -----------------------------------------------------------------
+ * KINBBDPrecInit allocates and initializes the BBD preconditioner.
+ *
+ * The parameters of KINBBDPrecInit are as follows:
+ *
+ * kinmem is a pointer to the KINSol memory block.
+ *
+ * Nlocal is the length of the local block of the vectors
+ * on the current process.
+ *
+ * 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 of the
+ * retained banded approximation to the local
+ * Jacobian block.
+ *
+ * dq_rel_uu is the relative error to be used in the difference
+ * quotient Jacobian calculation in the preconditioner.
+ * The default is sqrt(unit roundoff), obtained by
+ * passing 0.
+ *
+ * gloc is the name of the user-supplied function g(u) 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 inter-process communication for the
+ * execution of gloc.
+ *
+ * The return value of KINBBDPrecInit is one of:
+ * KINSPILS_SUCCESS if no errors occurred
+ * KINSPILS_MEM_NULL if the integrator memory is NULL
+ * KINSPILS_LMEM_NULL if the linear solver memory is NULL
+ * KINSPILS_ILL_INPUT if an input has an illegal value
+ * KINSPILS_MEM_FAIL if a memory allocation request failed
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int KINBBDPrecInit(void *kinmem, long int Nlocal,
+ long int mudq, long int mldq,
+ long int mukeep, long int mlkeep,
+ realtype dq_rel_uu,
+ KINLocalFn gloc, KINCommFn gcomm);
+
+/*
+ * -----------------------------------------------------------------
+ * Function : KINBBDPrecGet*
+ *
+ * The return value of KINBBDPrecGet* is one of:
+ * KINBBDPRE_SUCCESS if successful
+ * KINBBDPRE_PDATA_NULL if the p_data memory was NULL
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int KINBBDPrecGetWorkSpace(void *kinmem, long int *lenrwBBDP, long int *leniwBBDP);
+SUNDIALS_EXPORT int KINBBDPrecGetNumGfnEvals(void *kinmem, long int *ngevalsBBDP);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/kinsol/kinsol_dense.h b/include/kinsol/kinsol_dense.h
new file mode 100644
index 0000000..abf808b
--- /dev/null
+++ b/include/kinsol/kinsol_dense.h
@@ -0,0 +1,54 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.5 $
+ * $Date: 2010/12/01 22:16:17 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * This is the header file for the KINSOL dense linear solver module,
+ * KINDENSE.
+ * -----------------------------------------------------------------
+ */
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#ifndef _KINDENSE_H
+#define _KINDENSE_H
+
+#include <kinsol/kinsol_direct.h>
+#include <sundials/sundials_dense.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
new file mode 100644
index 0000000..953e26f
--- /dev/null
+++ b/include/kinsol/kinsol_direct.h
@@ -0,0 +1,262 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.6 $
+ * $Date: 2010/12/01 22:16:17 $
+ * -----------------------------------------------------------------
+ * Programmer: Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2006, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * Common header file for the direct linear solvers in KINSOL.
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _KINDLS_H
+#define _KINDLS_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <sundials/sundials_direct.h>
+#include <sundials/sundials_nvector.h>
+
+/*
+ * =================================================================
+ * K I N D I R E C T C O N S T A N T S
+ * =================================================================
+ */
+
+/*
+ * -----------------------------------------------------------------
+ * KINDLS return values
+ * -----------------------------------------------------------------
+ */
+
+#define KINDLS_SUCCESS 0
+#define KINDLS_MEM_NULL -1
+#define KINDLS_LMEM_NULL -2
+#define KINDLS_ILL_INPUT -3
+#define KINDLS_MEM_FAIL -4
+
+/* Additional last_flag values */
+
+#define KINDLS_JACFUNC_UNRECVR -5
+#define KINDLS_JACFUNC_RECVR -6
+
+/*
+ * =================================================================
+ * F U N C T I O N T Y P E S
+ * =================================================================
+ */
+
+/*
+ * -----------------------------------------------------------------
+ * Type: KINDlsDenseJacFn
+ * -----------------------------------------------------------------
+ *
+ * A dense Jacobian approximation function Jac must be of type
+ * KINDlsDenseJacFn. Its parameters are:
+ *
+ * N - problem size.
+ *
+ * u - current iterate (unscaled) [input]
+ *
+ * fu - vector (type N_Vector) containing result of nonlinear
+ * 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).
+ *
+ * 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.
+ *
+ * -----------------------------------------------------------------
+ *
+ * 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.
+ *
+ * -----------------------------------------------------------------
+ */
+
+
+typedef int (*KINDlsDenseJacFn)(long int N,
+ N_Vector u, N_Vector fu,
+ DlsMat J, void *user_data,
+ N_Vector tmp1, N_Vector tmp2);
+
+/*
+ * -----------------------------------------------------------------
+ * Type: KINDlsBandJacFn
+ * -----------------------------------------------------------------
+ *
+ * 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.
+ *
+ * -----------------------------------------------------------------
+ */
+
+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
+ * =================================================================
+ */
+
+/*
+ * -----------------------------------------------------------------
+ * 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.
+ *
+ * By default, a difference quotient approximation, supplied with
+ * the solver is used.
+ *
+ * The return value is one of:
+ * KINDLS_SUCCESS if successful
+ * KINDLS_MEM_NULL if the KINSOL memory was NULL
+ * KINDLS_LMEM_NULL if the linear solver memory was NULL
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int KINDlsSetDenseJacFn(void *kinmem, KINDlsDenseJacFn jac);
+SUNDIALS_EXPORT int KINDlsSetBandJacFn(void *kinmem, KINDlsBandJacFn jac);
+
+/*
+ * -----------------------------------------------------------------
+ * Optional outputs from a KINDLS linear solver
+ * -----------------------------------------------------------------
+ *
+ * KINDlsGetWorkSpace returns the real and integer workspace used
+ * by the KINDLS linear solver.
+ * KINDlsGetNumJacEvals returns the number of calls made to the
+ * Jacobian evaluation routine.
+ * KINDlsGetNumFuncEvals returns the number of calls to the user's F
+ * routine due to finite difference Jacobian
+ * evaluation.
+ * 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
+ *
+ * The return value of KINDlsGet* is one of:
+ * KINDLS_SUCCESS if successful
+ * KINDLS_MEM_NULL if the KINSOL memory was NULL
+ * KINDLS_LMEM_NULL if the linear solver memory was NULL
+ * -----------------------------------------------------------------
+ */
+
+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 KINDlsGetLastFlag(void *kinmem, long int *flag);
+SUNDIALS_EXPORT char *KINDlsGetReturnFlagName(long int flag);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/kinsol/kinsol_lapack.h b/include/kinsol/kinsol_lapack.h
new file mode 100644
index 0000000..bebfc80
--- /dev/null
+++ b/include/kinsol/kinsol_lapack.h
@@ -0,0 +1,84 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.4 $
+ * $Date: 2008/04/18 19:42:38 $
+ * -----------------------------------------------------------------
+ * Programmer: Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2006, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * Header file for the KINSOL dense linear solver KINLAPACK.
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _KINLAPACK_H
+#define _KINLAPACK_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <kinsol/kinsol_direct.h>
+#include <sundials/sundials_lapack.h>
+
+/*
+ * =================================================================
+ * 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_spbcgs.h b/include/kinsol/kinsol_spbcgs.h
new file mode 100644
index 0000000..1869abe
--- /dev/null
+++ b/include/kinsol/kinsol_spbcgs.h
@@ -0,0 +1,89 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.2 $
+ * $Date: 2006/11/29 00:05:07 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Aaron Collier @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2004, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * This is the public header file for the KINSOL scaled preconditioned
+ * Bi-CGSTAB linear solver module, KINSPBCG.
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _KINSPBCG_H
+#define _KINSPBCG_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <kinsol/kinsol_spils.h>
+#include <sundials/sundials_spbcgs.h>
+
+/*
+ * -----------------------------------------------------------------
+ * 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_spgmr.h b/include/kinsol/kinsol_spgmr.h
new file mode 100644
index 0000000..b117046
--- /dev/null
+++ b/include/kinsol/kinsol_spgmr.h
@@ -0,0 +1,86 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.2 $
+ * $Date: 2006/11/29 00:05:07 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Allan Taylor, Alan Hindmarsh, Radu Serban, and
+ * Aaron Collier @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * This is the header file for the KINSOL Scaled Preconditioned GMRES
+ * linear solver module, KINSPGMR.
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _KINSPGMR_H
+#define _KINSPGMR_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <kinsol/kinsol_spils.h>
+#include <sundials/sundials_spgmr.h>
+
+/*
+ * -----------------------------------------------------------------
+ * 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
new file mode 100644
index 0000000..90ccd2d
--- /dev/null
+++ b/include/kinsol/kinsol_spils.h
@@ -0,0 +1,319 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.7 $
+ * $Date: 2010/12/01 22:16:17 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Scott Cohen, Alan Hindmarsh, Radu Serban, and
+ * Aaron Collier @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * This is the common header file for the Scaled Preconditioned
+ * Iterative Linear Solvers in KINSOL.
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _KINSPILS_H
+#define _KINSPILS_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <sundials/sundials_iterative.h>
+#include <sundials/sundials_nvector.h>
+
+
+/*
+ * -----------------------------------------------------------------
+ * KINSPILS return values
+ * -----------------------------------------------------------------
+ */
+
+#define KINSPILS_SUCCESS 0
+
+#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
+
+/*
+ * -----------------------------------------------------------------
+ * KINSPILS solver constant
+ * -----------------------------------------------------------------
+ * KINSPILS_MAXL : default maximum dimension of Krylov subspace
+ * -----------------------------------------------------------------
+ */
+
+#define KINSPILS_MAXL 10
+
+/*
+ * -----------------------------------------------------------------
+ * 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.
+ * -----------------------------------------------------------------
+ */
+
+typedef int (*KINSpilsPrecSetupFn)(N_Vector uu, N_Vector uscale,
+ N_Vector fval, N_Vector fscale,
+ void *user_data, N_Vector vtemp1,
+ N_Vector vtemp2);
+
+/*
+ * -----------------------------------------------------------------
+ * 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.
+ * -----------------------------------------------------------------
+ */
+
+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.
+ * -----------------------------------------------------------------
+ */
+
+typedef int (*KINSpilsJacTimesVecFn)(N_Vector v, N_Vector Jv,
+ N_Vector uu, booleantype *new_uu,
+ void *J_data);
+
+
+
+
+
+/*
+ * -----------------------------------------------------------------
+ * 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]
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int KINSpilsSetMaxRestarts(void *kinmem, int maxrs);
+SUNDIALS_EXPORT int KINSpilsSetPreconditioner(void *kinmem,
+ KINSpilsPrecSetupFn pset,
+ 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]
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * -----------------------------------------------------------------
+ * 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 char *KINSpilsGetReturnFlagName(long int flag);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/kinsol/kinsol_sptfqmr.h b/include/kinsol/kinsol_sptfqmr.h
new file mode 100644
index 0000000..1fd3ec2
--- /dev/null
+++ b/include/kinsol/kinsol_sptfqmr.h
@@ -0,0 +1,90 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.2 $
+ * $Date: 2006/11/29 00:05:07 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Aaron Collier @ 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.
+ * -----------------------------------------------------------------
+ * This is the public header file for the KINSOL scaled preconditioned
+ * TFQMR linear solver module, KINSPTFQMR.
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _KINSPTFQMR_H
+#define _KINSPTFQMR_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <kinsol/kinsol_spils.h>
+#include <sundials/sundials_sptfqmr.h>
+
+/*
+ * -----------------------------------------------------------------
+ * 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/nvector/nvector_parallel.h b/include/nvector/nvector_parallel.h
new file mode 100644
index 0000000..f8a006c
--- /dev/null
+++ b/include/nvector/nvector_parallel.h
@@ -0,0 +1,314 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.2 $
+ * $Date: 2006/11/29 00:05:07 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh, Radu Serban,
+ * and Aaron Collier @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * This is the main header file for the MPI-enabled implementation
+ * of the NVECTOR module.
+ *
+ * Part I contains declarations specific to the parallel
+ * implementation of the supplied NVECTOR module.
+ *
+ * Part II defines accessor macros that allow the user to efficiently
+ * use the type N_Vector without making explicit references to the
+ * underlying data structure.
+ *
+ * Part III contains the prototype for the constructor
+ * N_VNew_Parallel 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_Parallel(a,x,b,y,y);
+ *
+ * (which stores the result of the operation a*x+b*y in y)
+ * is legal.
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _NVECTOR_PARALLEL_H
+#define _NVECTOR_PARALLEL_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <mpi.h>
+
+#include <sundials/sundials_nvector.h>
+
+
+/*
+ * -----------------------------------------------------------------
+ * PART I: PARALLEL implementation of N_Vector
+ * -----------------------------------------------------------------
+ */
+
+/* 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 */
+ booleantype own_data; /* ownership of data */
+ realtype *data; /* local data array */
+ MPI_Comm comm; /* pointer to MPI communicator */
+};
+
+typedef struct _N_VectorContent_Parallel *N_VectorContent_Parallel;
+
+/*
+ * -----------------------------------------------------------------
+ * PART II: macros NV_CONTENT_P, NV_DATA_P, NV_OWN_DATA_P,
+ * NV_LOCLENGTH_P, NV_GLOBLENGTH_P,NV_COMM_P, and NV_Ith_P
+ * -----------------------------------------------------------------
+ * In the descriptions below, the following user declarations
+ * are assumed:
+ *
+ * N_Vector v;
+ * long int v_len, s_len, i;
+ *
+ * (1) NV_CONTENT_P
+ *
+ * This routines gives access to the contents of the parallel
+ * vector N_Vector.
+ *
+ * The assignment v_cont = NV_CONTENT_P(v) sets v_cont to be
+ * a pointer to the parallel N_Vector content structure.
+ *
+ * (2) NV_DATA_P, NV_OWN_DATA_P, NV_LOCLENGTH_P, NV_GLOBLENGTH_P,
+ * and NV_COMM_P
+ *
+ * These routines give access to the individual parts of
+ * the content structure of a parallel N_Vector.
+ *
+ * The assignment v_data = NV_DATA_P(v) sets v_data to be
+ * a pointer to the first component of the local data for
+ * the vector v. The assignment NV_DATA_P(v) = data_v sets
+ * the component array of v to be data_V by storing the
+ * pointer data_v.
+ *
+ * The assignment v_llen = NV_LOCLENGTH_P(v) sets v_llen to
+ * be the length of the local part of the vector v. The call
+ * NV_LOCLENGTH_P(v) = llen_v sets the local length
+ * of v to be llen_v.
+ *
+ * The assignment v_glen = NV_GLOBLENGTH_P(v) sets v_glen to
+ * be the global length of the vector v. The call
+ * NV_GLOBLENGTH_P(v) = glen_v sets the global length of v to
+ * be glen_v.
+ *
+ * The assignment v_comm = NV_COMM_P(v) sets v_comm to be the
+ * MPI communicator of the vector v. The assignment
+ * NV_COMM_C(v) = comm_v sets the MPI communicator of v to be
+ * comm_v.
+ *
+ * (3) NV_Ith_P
+ *
+ * In the following description, the components of the
+ * local part of an N_Vector are numbered 0..n-1, where n
+ * is the local length of (the local part of) v.
+ *
+ * The assignment r = NV_Ith_P(v,i) sets r to be the value
+ * of the ith component of the local part of the vector v.
+ * The assignment NV_Ith_P(v,i) = r sets the value of the
+ * ith local component of v to be r.
+ *
+ * Note: When looping over the components of an N_Vector v, it is
+ * more efficient to first obtain the component array via
+ * v_data = NV_DATA_P(v) and then access v_data[i] within the
+ * loop than it is to use NV_Ith_P(v,i) within the loop.
+ * -----------------------------------------------------------------
+ */
+
+#define NV_CONTENT_P(v) ( (N_VectorContent_Parallel)(v->content) )
+
+#define NV_LOCLENGTH_P(v) ( NV_CONTENT_P(v)->local_length )
+
+#define NV_GLOBLENGTH_P(v) ( NV_CONTENT_P(v)->global_length )
+
+#define NV_OWN_DATA_P(v) ( NV_CONTENT_P(v)->own_data )
+
+#define NV_DATA_P(v) ( NV_CONTENT_P(v)->data )
+
+#define NV_COMM_P(v) ( NV_CONTENT_P(v)->comm )
+
+#define NV_Ith_P(v,i) ( NV_DATA_P(v)[i] )
+
+/*
+ * -----------------------------------------------------------------
+ * PART III: functions exported by nvector_parallel
+ *
+ * CONSTRUCTORS:
+ * N_VNew_Parallel
+ * N_VNewEmpty_Parallel
+ * N_VMake_Parallel
+ * N_VCloneVectorArray_Parallel
+ * N_VCloneVectorArrayEmpty_Parallel
+ * DESTRUCTORS:
+ * N_VDestroy_Parallel
+ * N_VDestroyVectorArray_Parallel
+ * OTHER:
+ * N_VPrint_Parallel
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * -----------------------------------------------------------------
+ * Function : N_VNew_Parallel
+ * -----------------------------------------------------------------
+ * This function creates and allocates memory for a parallel vector.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT N_Vector N_VNew_Parallel(MPI_Comm comm,
+ long int local_length,
+ long int global_length);
+
+/*
+ * -----------------------------------------------------------------
+ * Function : N_VNewEmpty_Parallel
+ * -----------------------------------------------------------------
+ * This function creates a new parallel N_Vector with an empty
+ * (NULL) data array.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT N_Vector N_VNewEmpty_Parallel(MPI_Comm comm,
+ long int local_length,
+ long int global_length);
+
+/*
+ * -----------------------------------------------------------------
+ * Function : N_VMake_Parallel
+ * -----------------------------------------------------------------
+ * This function creates and allocates memory for a parallel vector
+ * with a user-supplied data array.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT N_Vector N_VMake_Parallel(MPI_Comm comm,
+ long int local_length,
+ long int global_length,
+ realtype *v_data);
+
+/*
+ * -----------------------------------------------------------------
+ * Function : N_VCloneVectorArray_Parallel
+ * -----------------------------------------------------------------
+ * This function creates an array of 'count' PARALLEL vectors by
+ * cloning a given vector w.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT N_Vector *N_VCloneVectorArray_Parallel(int count, N_Vector w);
+
+/*
+ * -----------------------------------------------------------------
+ * Function : N_VCloneVectorArrayEmpty_Parallel
+ * -----------------------------------------------------------------
+ * This function creates an array of 'count' PARALLEL vectors each
+ * with an empty (NULL) data array by cloning w.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT N_Vector *N_VCloneVectorArrayEmpty_Parallel(int count, N_Vector w);
+
+/*
+ * -----------------------------------------------------------------
+ * Function : N_VDestroyVectorArray_Parallel
+ * -----------------------------------------------------------------
+ * This function frees an array of N_Vector created with
+ * N_VCloneVectorArray_Parallel or N_VCloneVectorArrayEmpty_Parallel.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT void N_VDestroyVectorArray_Parallel(N_Vector *vs, int count);
+
+/*
+ * -----------------------------------------------------------------
+ * Function : N_VPrint_Parallel
+ * -----------------------------------------------------------------
+ * This function prints the content of a parallel vector to stdout.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT void N_VPrint_Parallel(N_Vector v);
+
+/*
+ * -----------------------------------------------------------------
+ * parallel implementations of the vector operations
+ * -----------------------------------------------------------------
+ */
+
+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 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);
+SUNDIALS_EXPORT void N_VConst_Parallel(realtype c, N_Vector z);
+SUNDIALS_EXPORT void N_VProd_Parallel(N_Vector x, N_Vector y, N_Vector z);
+SUNDIALS_EXPORT void N_VDiv_Parallel(N_Vector x, N_Vector y, N_Vector z);
+SUNDIALS_EXPORT void N_VScale_Parallel(realtype c, N_Vector x, N_Vector z);
+SUNDIALS_EXPORT void N_VAbs_Parallel(N_Vector x, N_Vector z);
+SUNDIALS_EXPORT void N_VInv_Parallel(N_Vector x, N_Vector z);
+SUNDIALS_EXPORT void N_VAddConst_Parallel(N_Vector x, realtype b, N_Vector z);
+SUNDIALS_EXPORT realtype N_VDotProd_Parallel(N_Vector x, N_Vector y);
+SUNDIALS_EXPORT realtype N_VMaxNorm_Parallel(N_Vector x);
+SUNDIALS_EXPORT realtype N_VWrmsNorm_Parallel(N_Vector x, N_Vector w);
+SUNDIALS_EXPORT realtype N_VWrmsNormMask_Parallel(N_Vector x, N_Vector w, N_Vector id);
+SUNDIALS_EXPORT realtype N_VMin_Parallel(N_Vector x);
+SUNDIALS_EXPORT realtype N_VWL2Norm_Parallel(N_Vector x, N_Vector w);
+SUNDIALS_EXPORT realtype N_VL1Norm_Parallel(N_Vector x);
+SUNDIALS_EXPORT void N_VCompare_Parallel(realtype c, N_Vector x, N_Vector z);
+SUNDIALS_EXPORT booleantype N_VInvTest_Parallel(N_Vector x, N_Vector z);
+SUNDIALS_EXPORT booleantype N_VConstrMask_Parallel(N_Vector c, N_Vector x, N_Vector m);
+SUNDIALS_EXPORT realtype N_VMinQuotient_Parallel(N_Vector num, N_Vector denom);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/nvector/nvector_serial.h b/include/nvector/nvector_serial.h
new file mode 100644
index 0000000..4301a68
--- /dev/null
+++ b/include/nvector/nvector_serial.h
@@ -0,0 +1,265 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.2 $
+ * $Date: 2006/11/29 00:05:07 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh, Radu Serban,
+ * and Aaron Collier @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * This is the header file for the serial implementation of the
+ * NVECTOR module.
+ *
+ * Part I contains declarations specific to the serial
+ * implementation of the supplied NVECTOR module.
+ *
+ * Part II defines accessor macros that allow the user to
+ * efficiently use the type N_Vector without making explicit
+ * references to the underlying data structure.
+ *
+ * Part III contains the prototype for the constructor N_VNew_Serial
+ * 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_Serial(a,x,b,y,y);
+ *
+ * (which stores the result of the operation a*x+b*y in y)
+ * is legal.
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _NVECTOR_SERIAL_H
+#define _NVECTOR_SERIAL_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <sundials/sundials_nvector.h>
+
+/*
+ * -----------------------------------------------------------------
+ * PART I: SERIAL implementation of N_Vector
+ * -----------------------------------------------------------------
+ */
+
+/* serial 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_Serial {
+ long int length;
+ booleantype own_data;
+ realtype *data;
+};
+
+typedef struct _N_VectorContent_Serial *N_VectorContent_Serial;
+
+/*
+ * -----------------------------------------------------------------
+ * PART II: macros NV_CONTENT_S, NV_DATA_S, NV_OWN_DATA_S,
+ * NV_LENGTH_S, and NV_Ith_S
+ * -----------------------------------------------------------------
+ * In the descriptions below, the following user declarations
+ * are assumed:
+ *
+ * N_Vector v;
+ * long int i;
+ *
+ * (1) NV_CONTENT_S
+ *
+ * This routines gives access to the contents of the serial
+ * vector N_Vector.
+ *
+ * The assignment v_cont = NV_CONTENT_S(v) sets v_cont to be
+ * a pointer to the serial N_Vector content structure.
+ *
+ * (2) NV_DATA_S NV_OWN_DATA_S and NV_LENGTH_S
+ *
+ * These routines give access to the individual parts of
+ * the content structure of a serial N_Vector.
+ *
+ * The assignment v_data = NV_DATA_S(v) sets v_data to be
+ * a pointer to the first component of v. The assignment
+ * NV_DATA_S(v) = data_V sets the component array of v to
+ * be data_v by storing the pointer data_v.
+ *
+ * The assignment v_len = NV_LENGTH_S(v) sets v_len to be
+ * the length of v. The call NV_LENGTH_S(v) = len_v sets
+ * the length of v to be len_v.
+ *
+ * (3) NV_Ith_S
+ *
+ * In the following description, the components of an
+ * N_Vector are numbered 0..n-1, where n is the length of v.
+ *
+ * The assignment r = NV_Ith_S(v,i) sets r to be the value of
+ * the ith component of v. The assignment NV_Ith_S(v,i) = r
+ * sets the value of the ith component of v to be r.
+ *
+ * Note: When looping over the components of an N_Vector v, it is
+ * more efficient to first obtain the component array via
+ * v_data = NV_DATA_S(v) and then access v_data[i] within the
+ * loop than it is to use NV_Ith_S(v,i) within the loop.
+ * -----------------------------------------------------------------
+ */
+
+#define NV_CONTENT_S(v) ( (N_VectorContent_Serial)(v->content) )
+
+#define NV_LENGTH_S(v) ( NV_CONTENT_S(v)->length )
+
+#define NV_OWN_DATA_S(v) ( NV_CONTENT_S(v)->own_data )
+
+#define NV_DATA_S(v) ( NV_CONTENT_S(v)->data )
+
+#define NV_Ith_S(v,i) ( NV_DATA_S(v)[i] )
+
+/*
+ * -----------------------------------------------------------------
+ * PART III: functions exported by nvector_serial
+ *
+ * CONSTRUCTORS:
+ * N_VNew_Serial
+ * N_VNewEmpty_Serial
+ * N_VMake_Serial
+ * N_VCloneVectorArray_Serial
+ * N_VCloneVectorArrayEmpty_Serial
+ * DESTRUCTORS:
+ * N_VDestroy_Serial
+ * N_VDestroyVectorArray_Serial
+ * OTHER:
+ * N_VPrint_Serial
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * -----------------------------------------------------------------
+ * Function : N_VNew_Serial
+ * -----------------------------------------------------------------
+ * This function creates and allocates memory for a serial vector.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT N_Vector N_VNew_Serial(long int vec_length);
+
+/*
+ * -----------------------------------------------------------------
+ * Function : N_VNewEmpty_Serial
+ * -----------------------------------------------------------------
+ * This function creates a new serial N_Vector with an empty (NULL)
+ * data array.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT N_Vector N_VNewEmpty_Serial(long int vec_length);
+
+/*
+ * -----------------------------------------------------------------
+ * Function : N_VMake_Serial
+ * -----------------------------------------------------------------
+ * This function creates and allocates memory for a serial vector
+ * with a user-supplied data array.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT N_Vector N_VMake_Serial(long int vec_length, realtype *v_data);
+
+/*
+ * -----------------------------------------------------------------
+ * Function : N_VCloneVectorArray_Serial
+ * -----------------------------------------------------------------
+ * This function creates an array of 'count' SERIAL vectors by
+ * cloning a given vector w.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT N_Vector *N_VCloneVectorArray_Serial(int count, N_Vector w);
+
+/*
+ * -----------------------------------------------------------------
+ * Function : N_VCloneVectorArrayEmpty_Serial
+ * -----------------------------------------------------------------
+ * This function creates an array of 'count' SERIAL vectors each
+ * with an empty (NULL) data array by cloning w.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT N_Vector *N_VCloneVectorArrayEmpty_Serial(int count, N_Vector w);
+
+/*
+ * -----------------------------------------------------------------
+ * Function : N_VDestroyVectorArray_Serial
+ * -----------------------------------------------------------------
+ * This function frees an array of SERIAL vectors created with
+ * N_VCloneVectorArray_Serial or N_VCloneVectorArrayEmpty_Serial.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT void N_VDestroyVectorArray_Serial(N_Vector *vs, int count);
+
+/*
+ * -----------------------------------------------------------------
+ * Function : N_VPrint_Serial
+ * -----------------------------------------------------------------
+ * This function prints the content of a serial vector to stdout.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT void N_VPrint_Serial(N_Vector v);
+
+/*
+ * -----------------------------------------------------------------
+ * serial implementations of various useful vector operations
+ * -----------------------------------------------------------------
+ */
+
+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 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);
+SUNDIALS_EXPORT void N_VConst_Serial(realtype c, N_Vector z);
+SUNDIALS_EXPORT void N_VProd_Serial(N_Vector x, N_Vector y, N_Vector z);
+SUNDIALS_EXPORT void N_VDiv_Serial(N_Vector x, N_Vector y, N_Vector z);
+SUNDIALS_EXPORT void N_VScale_Serial(realtype c, N_Vector x, N_Vector z);
+SUNDIALS_EXPORT void N_VAbs_Serial(N_Vector x, N_Vector z);
+SUNDIALS_EXPORT void N_VInv_Serial(N_Vector x, N_Vector z);
+SUNDIALS_EXPORT void N_VAddConst_Serial(N_Vector x, realtype b, N_Vector z);
+SUNDIALS_EXPORT realtype N_VDotProd_Serial(N_Vector x, N_Vector y);
+SUNDIALS_EXPORT realtype N_VMaxNorm_Serial(N_Vector x);
+SUNDIALS_EXPORT realtype N_VWrmsNorm_Serial(N_Vector x, N_Vector w);
+SUNDIALS_EXPORT realtype N_VWrmsNormMask_Serial(N_Vector x, N_Vector w, N_Vector id);
+SUNDIALS_EXPORT realtype N_VMin_Serial(N_Vector x);
+SUNDIALS_EXPORT realtype N_VWL2Norm_Serial(N_Vector x, N_Vector w);
+SUNDIALS_EXPORT realtype N_VL1Norm_Serial(N_Vector x);
+SUNDIALS_EXPORT void N_VCompare_Serial(realtype c, N_Vector x, N_Vector z);
+SUNDIALS_EXPORT booleantype N_VInvTest_Serial(N_Vector x, N_Vector z);
+SUNDIALS_EXPORT booleantype N_VConstrMask_Serial(N_Vector c, N_Vector x, N_Vector m);
+SUNDIALS_EXPORT realtype N_VMinQuotient_Serial(N_Vector num, N_Vector denom);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/sundials/sundials_band.h b/include/sundials/sundials_band.h
new file mode 100644
index 0000000..a4d9109
--- /dev/null
+++ b/include/sundials/sundials_band.h
@@ -0,0 +1,154 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.6 $
+ * $Date: 2010/12/01 22:17:18 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Alan C. Hindmarsh and Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * This is the header file for a generic BAND linear solver
+ * package, based on the DlsMat type defined in sundials_direct.h.
+ *
+ * There are two sets of band solver routines listed in
+ * this file: one set uses type DlsMat defined below and the
+ * other set uses the type realtype ** for band matrix arguments.
+ * Routines that work with the type DlsMat begin with "Band".
+ * Routines that work with realtype ** begin with "band"
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _SUNDIALS_BAND_H
+#define _SUNDIALS_BAND_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <sundials/sundials_direct.h>
+
+/*
+ * -----------------------------------------------------------------
+ * Function : BandGBTRF
+ * -----------------------------------------------------------------
+ * Usage : ier = BandGBTRF(A, p);
+ * if (ier != 0) ... A is singular
+ * -----------------------------------------------------------------
+ * BandGBTRF performs the LU factorization of the N by N band
+ * matrix A. This is done using standard Gaussian elimination
+ * with partial pivoting.
+ *
+ * A successful LU factorization leaves the "matrix" A and the
+ * pivot array p with the following information:
+ *
+ * (1) p[k] contains the row number of the pivot element chosen
+ * at the beginning of elimination step k, k=0, 1, ..., N-1.
+ *
+ * (2) If the unique LU factorization of A is given by PA = LU,
+ * where P is a permutation matrix, L is a lower triangular
+ * matrix with all 1's on the diagonal, and U is an upper
+ * triangular matrix, then the upper triangular part of A
+ * (including its diagonal) contains U and the strictly lower
+ * triangular part of A contains the multipliers, I-L.
+ *
+ * BandGBTRF returns 0 if successful. Otherwise it encountered
+ * a zero diagonal element during the factorization. In this case
+ * it returns the column index (numbered from one) at which
+ * it encountered the zero.
+ *
+ * Important Note: A must be allocated to accommodate the increase
+ * in upper bandwidth that occurs during factorization. If
+ * mathematically, A is a band matrix with upper bandwidth mu and
+ * lower bandwidth ml, then the upper triangular factor U can
+ * have upper bandwidth as big as smu = MIN(n-1,mu+ml). The lower
+ * triangular factor L has lower bandwidth ml. Allocate A with
+ * call A = BandAllocMat(N,mu,ml,smu), where mu, ml, and smu are
+ * as defined above. The user does not have to zero the "extra"
+ * storage allocated for the purpose of factorization. This will
+ * handled by the BandGBTRF routine.
+ *
+ * BandGBTRF is only a wrapper around bandGBTRF. All work is done
+ * in bandGBTRF works directly on the data in the DlsMat A (i.e.,
+ * the field cols).
+ * -----------------------------------------------------------------
+ */
+
+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);
+
+/*
+ * -----------------------------------------------------------------
+ * Function : BandGBTRS
+ * -----------------------------------------------------------------
+ * Usage : BandGBTRS(A, p, b);
+ * -----------------------------------------------------------------
+ * BandGBTRS solves the N-dimensional system A x = b using
+ * the LU factorization in A and the pivot information in p
+ * computed in BandGBTRF. The solution x is returned in b. This
+ * routine cannot fail if the corresponding call to BandGBTRF
+ * did not fail.
+ *
+ * BandGBTRS is only a wrapper around bandGBTRS which does all the
+ * work directly on the data in the DlsMat A (i.e., the field cols).
+ * -----------------------------------------------------------------
+ */
+
+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);
+
+/*
+ * -----------------------------------------------------------------
+ * Function : BandCopy
+ * -----------------------------------------------------------------
+ * Usage : BandCopy(A, B, copymu, copyml);
+ * -----------------------------------------------------------------
+ * BandCopy copies the submatrix with upper and lower bandwidths
+ * copymu, copyml of the N by N band matrix A into the N by N
+ * band matrix B.
+ *
+ * BandCopy is a wrapper around bandCopy which accesses the data
+ * in the DlsMat A and B (i.e. the fields cols)
+ * -----------------------------------------------------------------
+ */
+
+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);
+
+/*
+ * -----------------------------------------------------------------
+ * Function: BandScale
+ * -----------------------------------------------------------------
+ * Usage : BandScale(c, A);
+ * -----------------------------------------------------------------
+ * A(i,j) <- c*A(i,j), j-(A->mu) <= i <= j+(A->ml).
+ *
+ * BandScale is a wrapper around bandScale which performs the actual
+ * scaling by accessing the data in the DlsMat A (i.e. the field
+ * cols).
+ * -----------------------------------------------------------------
+ */
+
+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);
+
+/*
+ * -----------------------------------------------------------------
+ * Function: bandAddIdentity
+ * -----------------------------------------------------------------
+ * bandAddIdentity adds the identity matrix to the n-by-n matrix
+ * stored in the realtype** arrays.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT void bandAddIdentity(realtype **a, long int n, long int smu);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/sundials/sundials_config.in b/include/sundials/sundials_config.in
new file mode 100644
index 0000000..8a10b7e
--- /dev/null
+++ b/include/sundials/sundials_config.in
@@ -0,0 +1,76 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.6 $
+ * $Date: 2010/12/15 22:45:17 $
+ * -----------------------------------------------------------------
+ * 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@"
+
+/* FCMIX: Define Fortran name-mangling macro for C identifiers.
+ * Depending on the inferred scheme, one of the following six
+ * macros will be defined:
+ * #define SUNDIALS_F77_FUNC(name,NAME) name
+ * #define SUNDIALS_F77_FUNC(name,NAME) name ## _
+ * #define SUNDIALS_F77_FUNC(name,NAME) name ## __
+ * #define SUNDIALS_F77_FUNC(name,NAME) NAME
+ * #define SUNDIALS_F77_FUNC(name,NAME) NAME ## _
+ * #define SUNDIALS_F77_FUNC(name,NAME) NAME ## __
+ */
+ at F77_MANGLE_MACRO1@
+
+/* FCMIX: Define Fortran name-mangling macro for C identifiers
+ * which contain underscores.
+ */
+ at F77_MANGLE_MACRO2@
+
+/* Define precision of SUNDIALS data type 'realtype'
+ * Depending on the precision level, one of the following
+ * three macros will be defined:
+ * #define SUNDIALS_SINGLE_PRECISION 1
+ * #define SUNDIALS_DOUBLE_PRECISION 1
+ * #define SUNDIALS_EXTENDED_PRECISION 1
+ */
+ at PRECISION_LEVEL@
+
+/* Use generic math functions
+ * If it was decided that generic math functions can be used, then
+ * #define SUNDIALS_USE_GENERIC_MATH
+ */
+ at GENERIC_MATH_LIB@
+
+/* Blas/Lapack available
+ * If working libraries for Blas/lapack support were found, then
+ * #define SUNDIALS_BLAS_LAPACK 1
+ * otherwise
+ * #define SUNDIALS_BLAS_LAPACK 0
+ */
+ at BLAS_LAPACK_MACRO@
+
+/* FNVECTOR: Allow user to specify different MPI communicator
+ * If it was found that the MPI implementation supports MPI_Comm_f2c, then
+ * #define SUNDIALS_MPI_COMM_F2C 1
+ * otherwise
+ * #define SUNDIALS_MPI_COMM_F2C 0
+ */
+ at F77_MPI_COMM_F2C@
+
+/* Mark SUNDIALS API functions for export/import
+ * When building shared SUNDIALS libraries under Windows, use
+ * #define SUNDIALS_EXPORT __declspec(dllexport)
+ * When linking to shared SUNDIALS libraries under Windows, use
+ * #define SUNDIALS_EXPORT __declspec(dllimport)
+ * In all other cases (other platforms or static libraries under
+ * Windows), the SUNDIALS_EXPORT macro is empty
+ */
+ at SUNDIALS_EXPORT@
diff --git a/include/sundials/sundials_dense.h b/include/sundials/sundials_dense.h
new file mode 100644
index 0000000..f2ddeb0
--- /dev/null
+++ b/include/sundials/sundials_dense.h
@@ -0,0 +1,187 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.8 $
+ * $Date: 2010/12/01 22:17:18 $
+ * -----------------------------------------------------------------
+ * Programmer: Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2006, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * This is the header file for a generic package of DENSE matrix
+ * operations, based on the DlsMat type defined in sundials_direct.h.
+ *
+ * There are two sets of dense solver routines listed in
+ * this file: one set uses type DlsMat defined below and the
+ * other set uses the type realtype ** for dense matrix arguments.
+ * Routines that work with the type DlsMat begin with "Dense".
+ * Routines that work with realtype** begin with "dense".
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _SUNDIALS_DENSE_H
+#define _SUNDIALS_DENSE_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <sundials/sundials_direct.h>
+
+/*
+ * -----------------------------------------------------------------
+ * Functions: DenseGETRF and DenseGETRS
+ * -----------------------------------------------------------------
+ * DenseGETRF performs the LU factorization of the M by N dense
+ * matrix A. This is done using standard Gaussian elimination
+ * with partial (row) pivoting. Note that this applies only
+ * to matrices with M >= N and full column rank.
+ *
+ * A successful LU factorization leaves the matrix A and the
+ * pivot array p with the following information:
+ *
+ * (1) p[k] contains the row number of the pivot element chosen
+ * at the beginning of elimination step k, k=0, 1, ..., N-1.
+ *
+ * (2) If the unique LU factorization of A is given by PA = LU,
+ * where P is a permutation matrix, L is a lower trapezoidal
+ * matrix with all 1's on the diagonal, and U is an upper
+ * triangular matrix, then the upper triangular part of A
+ * (including its diagonal) contains U and the strictly lower
+ * trapezoidal part of A contains the multipliers, I-L.
+ *
+ * For square matrices (M=N), L is unit lower triangular.
+ *
+ * DenseGETRF returns 0 if successful. Otherwise it encountered
+ * a zero diagonal element during the factorization. In this case
+ * it returns the column index (numbered from one) at which
+ * it encountered the zero.
+ *
+ * DenseGETRS solves the N-dimensional system A x = b using
+ * the LU factorization in A and the pivot information in p
+ * computed in DenseGETRF. The solution x is returned in b. This
+ * routine cannot fail if the corresponding call to DenseGETRF
+ * did not fail.
+ * DenseGETRS does NOT check for a square matrix!
+ *
+ * -----------------------------------------------------------------
+ * DenseGETRF and DenseGETRS are simply wrappers around denseGETRF
+ * and denseGETRS, respectively, which perform all the work by
+ * directly accessing the data in the DlsMat A (i.e. the field cols)
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT long int DenseGETRF(DlsMat A, long int *p);
+SUNDIALS_EXPORT void DenseGETRS(DlsMat A, long int *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);
+
+/*
+ * -----------------------------------------------------------------
+ * Functions : DensePOTRF and DensePOTRS
+ * -----------------------------------------------------------------
+ * DensePOTRF computes the Cholesky factorization of a real symmetric
+ * positive definite matrix A.
+ * -----------------------------------------------------------------
+ * DensePOTRS solves a system of linear equations A*X = B with a
+ * symmetric positive definite matrix A using the Cholesky factorization
+ * A = L*L**T computed by DensePOTRF.
+ *
+ * -----------------------------------------------------------------
+ * DensePOTRF and DensePOTRS are simply wrappers around densePOTRF
+ * and densePOTRS, respectively, which perform all the work by
+ * directly accessing the data in the DlsMat A (i.e. the field cols)
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT long int 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);
+
+/*
+ * -----------------------------------------------------------------
+ * Functions : DenseGEQRF and DenseORMQR
+ * -----------------------------------------------------------------
+ * DenseGEQRF computes a QR factorization of a real M-by-N matrix A:
+ * A = Q * R (with M>= N).
+ *
+ * DenseGEQRF requires a temporary work vector wrk of length M.
+ * -----------------------------------------------------------------
+ * DenseORMQR computes the product w = Q * v where Q is a real
+ * orthogonal matrix defined as the product of k elementary reflectors
+ *
+ * Q = H(1) H(2) . . . H(k)
+ *
+ * as returned by DenseGEQRF. Q is an M-by-N matrix, v is a vector
+ * of length N and w is a vector of length M (with M>=N).
+ *
+ * DenseORMQR requires a temporary work vector wrk of length M.
+ *
+ * -----------------------------------------------------------------
+ * DenseGEQRF and DenseORMQR are simply wrappers around denseGEQRF
+ * and denseORMQR, respectively, which perform all the work by
+ * directly accessing the data in the DlsMat A (i.e. the field cols)
+ * -----------------------------------------------------------------
+ */
+
+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, realtype *v);
+SUNDIALS_EXPORT int denseORMQR(realtype **a, long int m, long int n, realtype *beta,
+ realtype *v, realtype *w, realtype *wrk);
+
+/*
+ * -----------------------------------------------------------------
+ * Function : DenseCopy
+ * -----------------------------------------------------------------
+ * DenseCopy copies the contents of the M-by-N matrix A into the
+ * M-by-N matrix B.
+ *
+ * DenseCopy is a wrapper around denseCopy which accesses the data
+ * in the DlsMat A and B (i.e. the fields cols)
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT void DenseCopy(DlsMat A, DlsMat B);
+SUNDIALS_EXPORT void denseCopy(realtype **a, realtype **b, long int m, long int n);
+
+/*
+ * -----------------------------------------------------------------
+ * Function: DenseScale
+ * -----------------------------------------------------------------
+ * DenseScale scales the elements of the M-by-N matrix A by the
+ * constant c and stores the result back in A.
+ *
+ * DenseScale is a wrapper around denseScale which performs the actual
+ * scaling by accessing the data in the DlsMat A (i.e. the field
+ * cols).
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT void DenseScale(realtype c, DlsMat A);
+SUNDIALS_EXPORT void denseScale(realtype c, realtype **a, long int m, long int n);
+
+
+/*
+ * -----------------------------------------------------------------
+ * Function: denseAddIdentity
+ * -----------------------------------------------------------------
+ * denseAddIdentity adds the identity matrix to the n-by-n matrix
+ * stored in the realtype** arrays.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT void denseAddIdentity(realtype **a, long int n);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/sundials/sundials_direct.h b/include/sundials/sundials_direct.h
new file mode 100644
index 0000000..da99f2b
--- /dev/null
+++ b/include/sundials/sundials_direct.h
@@ -0,0 +1,336 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.6 $
+ * $Date: 2010/12/22 22:18:49 $
+ * -----------------------------------------------------------------
+ * Programmer: Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2006, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * 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
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <sundials/sundials_types.h>
+
+/*
+ * =================================================================
+ * C O N S T A N T S
+ * =================================================================
+ */
+
+/*
+ * SUNDIALS_DENSE: dense matrix
+ * SUNDIALS_BAND: banded matrix
+ */
+
+#define SUNDIALS_DENSE 1
+#define SUNDIALS_BAND 2
+
+/*
+ * ==================================================================
+ * Type definitions
+ * ==================================================================
+ */
+
+/*
+ * -----------------------------------------------------------------
+ * Type : DlsMat
+ * -----------------------------------------------------------------
+ * The type DlsMat is defined to be a pointer to a structure
+ * with various sizes, a data field, and an array of pointers to
+ * the columns which defines a dense or band matrix for use in
+ * direct linear solvers. The M and N fields indicates the number
+ * of rows and columns, respectively. The data field is a one
+ * dimensional array used for component storage. The cols field
+ * stores the pointers in data for the beginning of each column.
+ * -----------------------------------------------------------------
+ * For DENSE matrices, the relevant fields in DlsMat are:
+ * type = SUNDIALS_DENSE
+ * M - number of rows
+ * N - number of columns
+ * ldim - leading dimension (ldim >= M)
+ * data - pointer to a contiguous block of realtype variables
+ * ldata - length of the data array =ldim*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).
+ * If A is of type DlsMat, then the (i,j)th element of A (with
+ * 0 <= i < M and 0 <= j < N) is given by (A->data)[j*n+i].
+ *
+ * The DENSE_COL and DENSE_ELEM macros below allow a user to access
+ * efficiently individual matrix elements without writing out explicit
+ * data structure references and without knowing too much about the
+ * underlying element storage. The only storage assumption needed is
+ * that elements are stored columnwise and that a pointer to the
+ * jth column of elements can be obtained via the DENSE_COL macro.
+ * -----------------------------------------------------------------
+ * For BAND matrices, the relevant fields in DlsMat are:
+ * type = SUNDIALS_BAND
+ * 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 BAND_COL, BAND_COL_ELEM, and BAND_ELEM macros below allow a
+ * user to access individual matrix elements without writing out
+ * explicit data structure references and without knowing too much
+ * about the underlying element storage. The only storage assumption
+ * needed is that elements are stored columnwise and that a pointer
+ * into the jth column of elements can be obtained via the BAND_COL
+ * macro. The BAND_COL_ELEM macro selects an element from a column
+ * which has already been isolated via BAND_COL. The macro
+ * BAND_COL_ELEM allows the user to avoid the translation
+ * from the matrix location (i,j) to the index in the array returned
+ * by BAND_COL at which the (i,j)th element is stored.
+ * -----------------------------------------------------------------
+ */
+
+typedef struct _DlsMat {
+ int type;
+ long int M;
+ long int N;
+ long int ldim;
+ long int mu;
+ long int ml;
+ long int s_mu;
+ realtype *data;
+ long int ldata;
+ realtype **cols;
+} *DlsMat;
+
+/*
+ * ==================================================================
+ * Data accessor macros
+ * ==================================================================
+ */
+
+/*
+ * -----------------------------------------------------------------
+ * DENSE_COL and DENSE_ELEM
+ * -----------------------------------------------------------------
+ *
+ * DENSE_COL(A,j) references the jth column of the M-by-N dense
+ * matrix A, 0 <= j < N. The type of the expression DENSE_COL(A,j)
+ * is (realtype *). After the assignment in the usage above, 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].
+ *
+ * DENSE_ELEM(A,i,j) references the (i,j)th element of the dense
+ * M-by-N matrix A, 0 <= i < M ; 0 <= j < N.
+ *
+ * -----------------------------------------------------------------
+ */
+
+#define DENSE_COL(A,j) ((A->cols)[j])
+#define DENSE_ELEM(A,i,j) ((A->cols)[j][i])
+
+/*
+ * -----------------------------------------------------------------
+ * BAND_COL, BAND_COL_ELEM, and BAND_ELEM
+ * -----------------------------------------------------------------
+ *
+ * BAND_COL(A,j) references the diagonal element of the jth column
+ * of the N by N band matrix A, 0 <= j <= N-1. The type of the
+ * expression BAND_COL(A,j) is realtype *. The pointer returned by
+ * the call BAND_COL(A,j) can be treated as an array which is
+ * indexed from -(A->mu) to (A->ml).
+ *
+ * BAND_COL_ELEM references the (i,j)th entry of the band matrix A
+ * when used in conjunction with BAND_COL. The index (i,j) should
+ * satisfy j-(A->mu) <= i <= j+(A->ml).
+ *
+ * BAND_ELEM(A,i,j) references the (i,j)th element of the M-by-N
+ * band matrix A, where 0 <= i,j <= N-1. The location (i,j) should
+ * further satisfy j-(A->mu) <= i <= j+(A->ml).
+ *
+ * -----------------------------------------------------------------
+ */
+
+#define BAND_COL(A,j) (((A->cols)[j])+(A->s_mu))
+#define BAND_COL_ELEM(col_j,i,j) (col_j[(i)-(j)])
+#define BAND_ELEM(A,i,j) ((A->cols)[j][(i)-(j)+(A->s_mu)])
+
+/*
+ * ==================================================================
+ * Exported function prototypes (functions working on dlsMat)
+ * ==================================================================
+ */
+
+/*
+ * -----------------------------------------------------------------
+ * Function: NewDenseMat
+ * -----------------------------------------------------------------
+ * NewDenseMat allocates memory for an M-by-N dense matrix and
+ * returns the storage allocated (type DlsMat). NewDenseMat
+ * returns NULL if the request for matrix storage cannot be
+ * satisfied. See the above documentation for the type DlsMat
+ * for matrix storage details.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT DlsMat NewDenseMat(long int M, long int N);
+
+/*
+ * -----------------------------------------------------------------
+ * Function: NewBandMat
+ * -----------------------------------------------------------------
+ * NewBandMat 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.
+ *
+ * NewBandMat returns the storage allocated (type DlsMat) or
+ * NULL if the request for matrix storage cannot be satisfied.
+ * See the documentation for the type DlsMat for matrix storage
+ * details.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT DlsMat NewBandMat(long int N, long int mu, long int ml, long int smu);
+
+/*
+ * -----------------------------------------------------------------
+ * Functions: DestroyMat
+ * -----------------------------------------------------------------
+ * DestroyMat frees the memory allocated by NewDenseMat or NewBandMat
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT void DestroyMat(DlsMat A);
+
+/*
+ * -----------------------------------------------------------------
+ * Function: NewIntArray
+ * -----------------------------------------------------------------
+ * NewIntArray allocates memory an array of N int's and returns
+ * the pointer to the memory it allocates. If the request for
+ * memory storage cannot be satisfied, it returns NULL.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int *NewIntArray(int N);
+
+/*
+ * -----------------------------------------------------------------
+ * Function: NewLintArray
+ * -----------------------------------------------------------------
+ * 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.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT long int *NewLintArray(long int N);
+
+/*
+ * -----------------------------------------------------------------
+ * Function: NewRealArray
+ * -----------------------------------------------------------------
+ * NewRealArray allocates memory an array of N realtype and returns
+ * the pointer to the memory it allocates. If the request for
+ * memory storage cannot be satisfied, it returns NULL.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT realtype *NewRealArray(long int N);
+
+/*
+ * -----------------------------------------------------------------
+ * Function: DestroyArray
+ * -----------------------------------------------------------------
+ * DestroyArray frees memory allocated by NewIntArray, NewLintArray,
+ * or NewRealArray.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT void DestroyArray(void *p);
+
+/*
+ * -----------------------------------------------------------------
+ * Function : AddIdentity
+ * -----------------------------------------------------------------
+ * AddIdentity adds 1.0 to the main diagonal (A_ii, i=1,2,...,N-1) of
+ * the M-by-N matrix A (M>= N) and stores the result back in A.
+ * AddIdentity is typically used with square matrices.
+ * AddIdentity does not check for M >= N and therefore a segmentation
+ * fault will occur if M < N!
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT void AddIdentity(DlsMat A);
+
+/*
+ * -----------------------------------------------------------------
+ * Function : SetToZero
+ * -----------------------------------------------------------------
+ * SetToZero sets all the elements of the M-by-N matrix A to 0.0.
+ * -----------------------------------------------------------------
+ */
+
+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.
+ * 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);
+
+
+/*
+ * ==================================================================
+ * Exported function prototypes (functions working on realtype**)
+ * ==================================================================
+ */
+
+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 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 void destroyArray(void *v);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/sundials/sundials_fnvector.h b/include/sundials/sundials_fnvector.h
new file mode 100644
index 0000000..bbc9a95
--- /dev/null
+++ b/include/sundials/sundials_fnvector.h
@@ -0,0 +1,41 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.1 $
+ * $Date: 2006/07/05 15:27:52 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Radu Serban and Aaron Collier @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * This file (companion of nvector.h) contains definitions
+ * needed for the initialization of vector operations in Fortran.
+ * -----------------------------------------------------------------
+ */
+
+
+#ifndef _FNVECTOR_H
+#define _FNVECTOR_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#ifndef _SUNDIALS_CONFIG_H
+#define _SUNDIALS_CONFIG_H
+#include <sundials/sundials_config.h>
+#endif
+
+/* SUNDIALS solver IDs */
+
+#define FCMIX_CVODE 1
+#define FCMIX_IDA 2
+#define FCMIX_KINSOL 3
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/sundials/sundials_iterative.h b/include/sundials/sundials_iterative.h
new file mode 100644
index 0000000..5e7e4bf
--- /dev/null
+++ b/include/sundials/sundials_iterative.h
@@ -0,0 +1,242 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.2 $
+ * $Date: 2006/11/29 00:05:07 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Scott D. Cohen and Alan C. Hindmarsh @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * This header file contains declarations intended for use by
+ * generic iterative solvers of Ax = b. The enumeration gives
+ * symbolic names for the type of preconditioning to be used.
+ * 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
+ * solving the preconditioner equation Pz = r (PSolveFn).
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _ITERATIVE_H
+#define _ITERATIVE_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <sundials/sundials_nvector.h>
+
+
+/*
+ * -----------------------------------------------------------------
+ * enum : types of preconditioning
+ * -----------------------------------------------------------------
+ * PREC_NONE : The iterative linear solver should not use
+ * preconditioning.
+ *
+ * PREC_LEFT : The iterative linear solver uses preconditioning on
+ * the left only.
+ *
+ * PREC_RIGHT : The iterative linear solver uses preconditioning on
+ * the right only.
+ *
+ * PREC_BOTH : The iterative linear solver uses preconditioning on
+ * both the left and the right.
+ * -----------------------------------------------------------------
+ */
+
+enum { PREC_NONE, PREC_LEFT, PREC_RIGHT, PREC_BOTH };
+
+/*
+ * -----------------------------------------------------------------
+ * enum : types of Gram-Schmidt routines
+ * -----------------------------------------------------------------
+ * MODIFIED_GS : The iterative solver uses the modified
+ * Gram-Schmidt routine ModifiedGS listed in this
+ * file.
+ *
+ * CLASSICAL_GS : The iterative solver uses the classical
+ * Gram-Schmidt routine ClassicalGS listed in this
+ * file.
+ * -----------------------------------------------------------------
+ */
+
+enum { MODIFIED_GS = 1, CLASSICAL_GS = 2 };
+
+/*
+ * -----------------------------------------------------------------
+ * Type: ATimesFn
+ * -----------------------------------------------------------------
+ * An ATimesFn multiplies Av and stores the result in z. The
+ * caller is responsible for allocating memory for the z vector.
+ * The parameter A_data is a pointer to any information about A
+ * which the function needs in order to do its job. The vector v
+ * is unchanged. An ATimesFn returns 0 if successful and a
+ * non-zero value if unsuccessful.
+ * -----------------------------------------------------------------
+ */
+
+typedef int (*ATimesFn)(void *A_data, N_Vector v, N_Vector z);
+
+/*
+ * -----------------------------------------------------------------
+ * Type: PSolveFn
+ * -----------------------------------------------------------------
+ * A PSolveFn solves the preconditioner equation Pz = r for the
+ * vector z. The caller is responsible for allocating memory for
+ * the z vector. The parameter P_data is a pointer to any
+ * information about P which the function needs in order to do
+ * its job. The parameter lr is input, and indicates whether P
+ * 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.
+ * 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
+ * a recoverable one, in which the calling routine may reattempt
+ * the solution after updating preconditioner data.
+ * -----------------------------------------------------------------
+ */
+
+typedef int (*PSolveFn)(void *P_data, N_Vector r, N_Vector z, int lr);
+
+/*
+ * -----------------------------------------------------------------
+ * Function: ModifiedGS
+ * -----------------------------------------------------------------
+ * ModifiedGS performs a modified Gram-Schmidt orthogonalization
+ * of the N_Vector v[k] against the p unit N_Vectors at
+ * v[k-1], v[k-2], ..., v[k-p].
+ *
+ * v is an array of (k+1) N_Vectors v[i], i=0, 1, ..., k.
+ * v[k-1], v[k-2], ..., v[k-p] are assumed to have L2-norm
+ * equal to 1.
+ *
+ * h is the output k by k Hessenberg matrix of inner products.
+ * This matrix must be allocated row-wise so that the (i,j)th
+ * entry is h[i][j]. The inner products (v[i],v[k]),
+ * i=i0, i0+1, ..., k-1, are stored at h[i][k-1]. Here
+ * i0=MAX(0,k-p).
+ *
+ * k is the index of the vector in the v array that needs to be
+ * orthogonalized against previous vectors in the v array.
+ *
+ * p is the number of previous vectors in the v array against
+ * which v[k] is to be orthogonalized.
+ *
+ * new_vk_norm is a pointer to memory allocated by the caller to
+ * hold the Euclidean norm of the orthogonalized vector v[k].
+ *
+ * If (k-p) < 0, then ModifiedGS uses p=k. The orthogonalized
+ * v[k] is NOT normalized and is stored over the old v[k]. Once
+ * the orthogonalization has been performed, the Euclidean norm
+ * of v[k] is stored in (*new_vk_norm).
+ *
+ * ModifiedGS returns 0 to indicate success. It cannot fail.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int ModifiedGS(N_Vector *v, realtype **h, int k, int p,
+ realtype *new_vk_norm);
+
+/*
+ * -----------------------------------------------------------------
+ * Function: ClassicalGS
+ * -----------------------------------------------------------------
+ * ClassicalGS performs a classical Gram-Schmidt
+ * orthogonalization of the N_Vector v[k] against the p unit
+ * N_Vectors at v[k-1], v[k-2], ..., v[k-p]. The parameters v, h,
+ * k, p, and new_vk_norm are as described in the documentation
+ * for ModifiedGS.
+ *
+ * temp is an N_Vector which can be used as workspace by the
+ * ClassicalGS routine.
+ *
+ * s is a length k array of realtype which can be used as
+ * workspace by the ClassicalGS routine.
+ *
+ * ClassicalGS returns 0 to indicate success. It cannot fail.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int ClassicalGS(N_Vector *v, realtype **h, int k, int p,
+ realtype *new_vk_norm, N_Vector temp, realtype *s);
+
+/*
+ * -----------------------------------------------------------------
+ * Function: QRfact
+ * -----------------------------------------------------------------
+ * QRfact performs a QR factorization of the Hessenberg matrix H.
+ *
+ * n is the problem size; the matrix H is (n+1) by n.
+ *
+ * h is the (n+1) by n Hessenberg matrix H to be factored. It is
+ * stored row-wise.
+ *
+ * q is an array of length 2*n containing the Givens rotations
+ * computed by this function. A Givens rotation has the form:
+ * | c -s |
+ * | s c |.
+ * The components of the Givens rotations are stored in q as
+ * (c, s, c, s, ..., c, s).
+ *
+ * job is a control flag. If job==0, then a new QR factorization
+ * is performed. If job!=0, then it is assumed that the first
+ * n-1 columns of h have already been factored and only the last
+ * column needs to be updated.
+ *
+ * QRfact returns 0 if successful. If a zero is encountered on
+ * the diagonal of the triangular factor R, then QRfact returns
+ * the equation number of the zero entry, where the equations are
+ * numbered from 1, not 0. If QRsol is subsequently called in
+ * this situation, it will return an error because it could not
+ * divide by the zero diagonal entry.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int QRfact(int n, realtype **h, realtype *q, int job);
+
+/*
+ * -----------------------------------------------------------------
+ * Function: QRsol
+ * -----------------------------------------------------------------
+ * QRsol solves the linear least squares problem
+ *
+ * min (b - H*x, b - H*x), x in R^n,
+ *
+ * where H is a Hessenberg matrix, and b is in R^(n+1).
+ * It uses the QR factors of H computed by QRfact.
+ *
+ * n is the problem size; the matrix H is (n+1) by n.
+ *
+ * h is a matrix (computed by QRfact) containing the upper
+ * triangular factor R of the original Hessenberg matrix H.
+ *
+ * q is an array of length 2*n (computed by QRfact) containing
+ * the Givens rotations used to factor H.
+ *
+ * b is the (n+1)-vector appearing in the least squares problem
+ * above.
+ *
+ * On return, b contains the solution x of the least squares
+ * problem, if QRsol was successful.
+ *
+ * QRsol returns a 0 if successful. Otherwise, a zero was
+ * encountered on the diagonal of the triangular factor R.
+ * In this case, QRsol returns the equation number (numbered
+ * from 1, not 0) of the zero entry.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int QRsol(int n, realtype **h, realtype *q, realtype *b);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/sundials/sundials_lapack.h b/include/sundials/sundials_lapack.h
new file mode 100644
index 0000000..4af89df
--- /dev/null
+++ b/include/sundials/sundials_lapack.h
@@ -0,0 +1,126 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.6 $
+ * $Date: 2009/02/17 02:39:26 $
+ * -----------------------------------------------------------------
+ * Programmer: Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2006, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * This is the header file for a generic package of direct matrix
+ * operations for use with BLAS/LAPACK.
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _SUNDIALS_LAPACK_H
+#define _SUNDIALS_LAPACK_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+/*
+ * ==================================================================
+ * Blas and Lapack functions
+ * ==================================================================
+ */
+
+#if defined(SUNDIALS_F77_FUNC)
+
+#define dcopy_f77 SUNDIALS_F77_FUNC(dcopy, DCOPY)
+#define dscal_f77 SUNDIALS_F77_FUNC(dscal, DSCAL)
+#define dgemv_f77 SUNDIALS_F77_FUNC(dgemv, DGEMV)
+#define dtrsv_f77 SUNDIALS_F77_FUNC(dtrsv, DTRSV)
+#define dsyrk_f77 SUNDIALS_F77_FUNC(dsyrk, DSKYR)
+
+#define dgbtrf_f77 SUNDIALS_F77_FUNC(dgbtrf, DGBTRF)
+#define dgbtrs_f77 SUNDIALS_F77_FUNC(dgbtrs, DGBTRS)
+#define dgetrf_f77 SUNDIALS_F77_FUNC(dgetrf, DGETRF)
+#define dgetrs_f77 SUNDIALS_F77_FUNC(dgetrs, DGETRS)
+#define dgeqp3_f77 SUNDIALS_F77_FUNC(dgeqp3, DGEQP3)
+#define dgeqrf_f77 SUNDIALS_F77_FUNC(dgeqrf, DGEQRF)
+#define dormqr_f77 SUNDIALS_F77_FUNC(dormqr, DORMQR)
+#define dpotrf_f77 SUNDIALS_F77_FUNC(dpotrf, DPOTRF)
+#define dpotrs_f77 SUNDIALS_F77_FUNC(dpotrs, DPOTRS)
+
+#else
+
+#define dcopy_f77 dcopy_
+#define dscal_f77 dscal_
+#define dgemv_f77 dgemv_
+#define dtrsv_f77 dtrsv_
+#define dsyrk_f77 dsyrk_
+
+#define dgbtrf_f77 dgbtrf_
+#define dgbtrs_f77 dgbtrs_
+#define dgeqp3_f77 dgeqp3_
+#define dgeqrf_f77 dgeqrf_
+#define dgetrf_f77 dgetrf_
+#define dgetrs_f77 dgetrs_
+#define dormqr_f77 dormqr_
+#define dpotrf_f77 dpotrf_
+#define dpotrs_f77 dpotrs_
+
+#endif
+
+/* Level-1 BLAS */
+
+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);
+
+/* Level-2 BLAS */
+
+extern void dgemv_f77(const char *trans, int *m, int *n, const double *alpha, const double *a,
+ int *lda, const double *x, int *inc_x, const double *beta, double *y, int *inc_y,
+ int len_trans);
+
+extern void dtrsv_f77(const char *uplo, const char *trans, const char *diag, const int *n,
+ const double *a, const int *lda, double *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);
+
+/* LAPACK */
+
+extern void dgbtrf_f77(const int *m, const int *n, const int *kl, const int *ku,
+ double *ab, int *ldab, int *ipiv, int *info);
+
+extern void dgbtrs_f77(const char *trans, const int *n, const int *kl, const int *ku, const int *nrhs,
+ double *ab, const int *ldab, int *ipiv, double *b, const int *ldb,
+ int *info, int len_trans);
+
+
+extern void dgeqp3_f77(const int *m, const int *n, double *a, const int *lda, int *jpvt, double *tau,
+ double *work, const int *lwork, int *info);
+
+extern void dgeqrf_f77(const int *m, const int *n, double *a, const int *lda, double *tau, double *work,
+ const int *lwork, int *info);
+
+extern void dgetrf_f77(const int *m, const int *n, double *a, int *lda, int *ipiv, int *info);
+
+extern void dgetrs_f77(const char *trans, const int *n, const int *nrhs, double *a, const int *lda,
+ int *ipiv, double *b, const int *ldb, int *info, int len_trans);
+
+
+extern void dormqr_f77(const char *side, const char *trans, const int *m, const int *n, const int *k,
+ double *a, const int *lda, double *tau, double *c, const int *ldc,
+ double *work, const int *lwork, int *info, int len_side, int len_trans);
+
+extern void dpotrf_f77(const char *uplo, const int *n, double *a, int *lda, int *info, int len_uplo);
+
+extern void dpotrs_f77(const char *uplo, const int *n, const int *nrhs, double *a, const int *lda,
+ double *b, const int *ldb, int * info, int len_uplo);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/sundials/sundials_math.h b/include/sundials/sundials_math.h
new file mode 100644
index 0000000..99de085
--- /dev/null
+++ b/include/sundials/sundials_math.h
@@ -0,0 +1,139 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.2 $
+ * $Date: 2006/11/29 00:05:07 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh and
+ * Aaron Collier @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * This is the header file for a simple C-language math library. The
+ * routines listed here work with the type realtype as defined in
+ * the header file sundials_types.h.
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _SUNDIALSMATH_H
+#define _SUNDIALSMATH_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <sundials/sundials_types.h>
+
+/*
+ * -----------------------------------------------------------------
+ * Macros : MIN and MAX
+ * -----------------------------------------------------------------
+ * MIN(A,B) returns the minimum of A and B
+ *
+ * MAX(A,B) returns the maximum of A and B
+ *
+ * SQR(A) returns A^2
+ * -----------------------------------------------------------------
+ */
+
+#ifndef MIN
+#define MIN(A, B) ((A) < (B) ? (A) : (B))
+#endif
+
+#ifndef MAX
+#define MAX(A, B) ((A) > (B) ? (A) : (B))
+#endif
+
+#ifndef SQR
+#define SQR(A) ((A)*(A))
+#endif
+
+#ifndef ABS
+#define ABS RAbs
+#endif
+
+#ifndef SQRT
+#define SQRT RSqrt
+#endif
+
+#ifndef EXP
+#define EXP RExp
+#endif
+
+/*
+ * -----------------------------------------------------------------
+ * Function : RPowerI
+ * -----------------------------------------------------------------
+ * Usage : int exponent;
+ * realtype base, ans;
+ * ans = RPowerI(base,exponent);
+ * -----------------------------------------------------------------
+ * RPowerI returns the value of base^exponent, where base is of type
+ * realtype and exponent is of type int.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT realtype RPowerI(realtype base, int exponent);
+
+/*
+ * -----------------------------------------------------------------
+ * Function : RPowerR
+ * -----------------------------------------------------------------
+ * Usage : realtype base, exponent, ans;
+ * ans = RPowerR(base,exponent);
+ * -----------------------------------------------------------------
+ * RPowerR returns the value of base^exponent, where both base and
+ * exponent are of type realtype. If base < ZERO, then RPowerR
+ * returns ZERO.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT realtype RPowerR(realtype base, realtype exponent);
+
+/*
+ * -----------------------------------------------------------------
+ * Function : RSqrt
+ * -----------------------------------------------------------------
+ * Usage : realtype sqrt_x;
+ * sqrt_x = RSqrt(x);
+ * -----------------------------------------------------------------
+ * RSqrt(x) returns the square root of x. If x < ZERO, then RSqrt
+ * returns ZERO.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT realtype RSqrt(realtype x);
+
+/*
+ * -----------------------------------------------------------------
+ * Function : RAbs (a.k.a. ABS)
+ * -----------------------------------------------------------------
+ * Usage : realtype abs_x;
+ * abs_x = RAbs(x);
+ * -----------------------------------------------------------------
+ * RAbs(x) returns the absolute value of x.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT realtype RAbs(realtype x);
+
+/*
+ * -----------------------------------------------------------------
+ * Function : RExp (a.k.a. EXP)
+ * -----------------------------------------------------------------
+ * Usage : realtype exp_x;
+ * exp_x = RExp(x);
+ * -----------------------------------------------------------------
+ * RExp(x) returns e^x (base-e exponential function).
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT realtype RExp(realtype x);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/sundials/sundials_nvector.h b/include/sundials/sundials_nvector.h
new file mode 100644
index 0000000..6142b32
--- /dev/null
+++ b/include/sundials/sundials_nvector.h
@@ -0,0 +1,373 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.2 $
+ * $Date: 2006/11/29 00:05:07 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Radu Serban and Aaron Collier @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * This is the header file for a generic NVECTOR package.
+ * It defines the N_Vector structure (_generic_N_Vector) which
+ * contains the following fields:
+ * - an implementation-dependent 'content' field which contains
+ * the description and actual data of the vector
+ * - an 'ops' filed which contains a structure listing operations
+ * acting on such vectors
+ *
+ * Part I of this file contains type declarations for the
+ * _generic_N_Vector and _generic_N_Vector_Ops structures, as well
+ * as references to pointers to such structures (N_Vector).
+ *
+ * Part II of this file contains the prototypes for the vector
+ * functions which operate on N_Vector.
+ *
+ * At a minimum, a particular implementation of an NVECTOR must
+ * do the following:
+ * - specify the 'content' field of N_Vector,
+ * - implement the operations on those N_Vectors,
+ * - provide a constructor routine for new vectors
+ *
+ * Additionally, an NVECTOR implementation may provide the following:
+ * - macros to access the underlying N_Vector data
+ * - a constructor for an array of N_Vectors
+ * - a constructor for an empty N_Vector (i.e., a new N_Vector with
+ * a NULL data pointer).
+ * - a routine to print the content of an N_Vector
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _NVECTOR_H
+#define _NVECTOR_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <sundials/sundials_types.h>
+
+/*
+ * -----------------------------------------------------------------
+ * Generic definition of N_Vector
+ * -----------------------------------------------------------------
+ */
+
+/* Forward reference for pointer to N_Vector_Ops object */
+typedef struct _generic_N_Vector_Ops *N_Vector_Ops;
+
+/* Forward reference for pointer to N_Vector object */
+typedef struct _generic_N_Vector *N_Vector;
+
+/* Define array of N_Vectors */
+typedef N_Vector *N_Vector_S;
+
+/* Structure containing function pointers to vector operations */
+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 *);
+ realtype* (*nvgetarraypointer)(N_Vector);
+ void (*nvsetarraypointer)(realtype *, N_Vector);
+ void (*nvlinearsum)(realtype, N_Vector, realtype, N_Vector, N_Vector);
+ void (*nvconst)(realtype, N_Vector);
+ void (*nvprod)(N_Vector, N_Vector, N_Vector);
+ void (*nvdiv)(N_Vector, N_Vector, N_Vector);
+ void (*nvscale)(realtype, N_Vector, N_Vector);
+ void (*nvabs)(N_Vector, N_Vector);
+ void (*nvinv)(N_Vector, N_Vector);
+ void (*nvaddconst)(N_Vector, realtype, N_Vector);
+ realtype (*nvdotprod)(N_Vector, N_Vector);
+ realtype (*nvmaxnorm)(N_Vector);
+ realtype (*nvwrmsnorm)(N_Vector, N_Vector);
+ realtype (*nvwrmsnormmask)(N_Vector, N_Vector, N_Vector);
+ realtype (*nvmin)(N_Vector);
+ realtype (*nvwl2norm)(N_Vector, N_Vector);
+ realtype (*nvl1norm)(N_Vector);
+ void (*nvcompare)(realtype, N_Vector, N_Vector);
+ booleantype (*nvinvtest)(N_Vector, N_Vector);
+ booleantype (*nvconstrmask)(N_Vector, N_Vector, N_Vector);
+ realtype (*nvminquotient)(N_Vector, N_Vector);
+};
+
+/*
+ * -----------------------------------------------------------------
+ * A vector is a structure with an implementation-dependent
+ * 'content' field, and a pointer to a structure of vector
+ * operations corresponding to that implementation.
+ * -----------------------------------------------------------------
+ */
+
+struct _generic_N_Vector {
+ void *content;
+ struct _generic_N_Vector_Ops *ops;
+};
+
+/*
+ * -----------------------------------------------------------------
+ * Functions exported by NVECTOR module
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * -----------------------------------------------------------------
+ * N_VClone
+ * Creates a new vector of the same type as an existing vector.
+ * It does not copy the vector, but rather allocates storage for
+ * the new vector.
+ *
+ * N_VCloneEmpty
+ * Creates a new vector of the same type as an existing vector,
+ * but does not allocate storage.
+ *
+ * N_VDestroy
+ * Destroys a vector created with N_VClone.
+ *
+ * N_VSpace
+ * Returns space requirements for one N_Vector (type 'realtype' in
+ * lrw and type 'long int' in liw).
+ *
+ * N_VGetArrayPointer
+ * Returns a pointer to the data component of the given N_Vector.
+ * NOTE: This function assumes that the internal data is stored
+ * as a contiguous 'realtype' array. This routine is only used in
+ * the solver-specific interfaces to the dense and banded linear
+ * solvers, as well as the interfaces to the banded preconditioners
+ * distributed with SUNDIALS.
+ *
+ * N_VSetArrayPointer
+ * Overwrites the data field in the given N_Vector with a user-supplied
+ * array of type 'realtype'.
+ * NOTE: This function assumes that the internal data is stored
+ * as a contiguous 'realtype' array. This routine is only used in
+ * the interfaces to the dense linear solver.
+ *
+ * N_VLinearSum
+ * Performs the operation z = a*x + b*y
+ *
+ * N_VConst
+ * Performs the operation z[i] = c for i = 0, 1, ..., N-1
+ *
+ * N_VProd
+ * Performs the operation z[i] = x[i]*y[i] for i = 0, 1, ..., N-1
+ *
+ * N_VDiv
+ * Performs the operation z[i] = x[i]/y[i] for i = 0, 1, ..., N-1
+ *
+ * N_VScale
+ * Performs the operation z = c*x
+ *
+ * N_VAbs
+ * Performs the operation z[i] = |x[i]| for i = 0, 1, ..., N-1
+ *
+ * N_VInv
+ * Performs the operation z[i] = 1/x[i] for i = 0, 1, ..., N-1
+ * This routine does not check for division by 0. It should be
+ * called only with an N_Vector x which is guaranteed to have
+ * all non-zero components.
+ *
+ * N_VAddConst
+ * Performs the operation z[i] = x[i] + b for i = 0, 1, ..., N-1
+ *
+ * N_VDotProd
+ * Returns the dot product of two vectors:
+ * sum (i = 0 to N-1) {x[i]*y[i]}
+ *
+ * N_VMaxNorm
+ * Returns the maximum norm of x:
+ * max (i = 0 to N-1) ABS(x[i])
+ *
+ * N_VWrmsNorm
+ * Returns the weighted root mean square norm of x with weight
+ * vector w:
+ * sqrt [(sum (i = 0 to N-1) {(x[i]*w[i])^2})/N]
+ *
+ * N_VWrmsNormMask
+ * Returns the weighted root mean square norm of x with weight
+ * vector w, masked by the elements of id:
+ * sqrt [(sum (i = 0 to N-1) {(x[i]*w[i]*msk[i])^2})/N]
+ * where msk[i] = 1.0 if id[i] > 0 and
+ * msk[i] = 0.0 if id[i] < 0
+ *
+ * N_VMin
+ * Returns the smallest element of x:
+ * min (i = 0 to N-1) x[i]
+ *
+ * N_VWL2Norm
+ * Returns the weighted Euclidean L2 norm of x with weight
+ * vector w:
+ * sqrt [(sum (i = 0 to N-1) {(x[i]*w[i])^2})]
+ *
+ * N_VL1Norm
+ * Returns the L1 norm of x:
+ * sum (i = 0 to N-1) {ABS(x[i])}
+ *
+ * N_VCompare
+ * Performs the operation
+ * z[i] = 1.0 if ABS(x[i]) >= c i = 0, 1, ..., N-1
+ * 0.0 otherwise
+ *
+ * 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.
+ *
+ * N_VConstrMask
+ * Performs the operation :
+ * m[i] = 1.0 if constraint test fails for x[i]
+ * m[i] = 0.0 if constraint test passes for x[i]
+ * where the constraint tests are as follows:
+ * If c[i] = +2.0, then x[i] must be > 0.0.
+ * 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
+ * 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.
+ * This routine is specialized in that it is used only for
+ * constraint checking.
+ *
+ * N_VMinQuotient
+ * Performs the operation :
+ * minq = min ( num[i]/denom[i]) over all i such that
+ * denom[i] != 0.
+ * This routine returns the minimum of the quotients obtained
+ * by term-wise dividing num[i] by denom[i]. A zero element
+ * in denom will be skipped. If no such quotients are found,
+ * then the large value BIG_REAL is returned.
+ *
+ * -----------------------------------------------------------------
+ *
+ * The following table lists the vector functions used by
+ * different modules in SUNDIALS. The symbols in the table
+ * have the following meaning:
+ * S - called by the solver;
+ * D - called by the dense linear solver module
+ * B - called by the band linear solver module
+ * Di - called by the diagonal linear solver module
+ * I - called by the iterative linear solver module
+ * BP - called by the band preconditioner module
+ * BBDP - called by the band-block diagonal preconditioner module
+ * F - called by the Fortran-to-C interface
+ *
+ * ------------------------------------------------
+ * MODULES
+ * NVECTOR ------------------------------------------------
+ * FUNCTIONS CVODE/CVODES IDA KINSOL
+ * -----------------------------------------------------------------
+ * N_VClone S Di I S I BBDP S I BBDP
+ * -----------------------------------------------------------------
+ * N_VCloneEmpty F F F
+ * -----------------------------------------------------------------
+ * N_VDestroy S Di I S I BBDP S I BBDP
+ * -----------------------------------------------------------------
+ * N_VSpace S S S
+ * -----------------------------------------------------------------
+ * N_VGetArrayPointer D B BP BBDP F D B BBDP BBDP F
+ * -----------------------------------------------------------------
+ * N_VSetArrayPointer D F D F
+ * -----------------------------------------------------------------
+ * N_VLinearSum S D Di I S D I S I
+ * -----------------------------------------------------------------
+ * N_VConst S I S I I
+ * -----------------------------------------------------------------
+ * N_VProd S Di I S I S I
+ * -----------------------------------------------------------------
+ * N_VDiv S Di I S I S I
+ * -----------------------------------------------------------------
+ * N_VScale S D B Di I BP BBDP S D B I BBDP S I BBDP
+ * -----------------------------------------------------------------
+ * N_VAbs S S S
+ * -----------------------------------------------------------------
+ * N_VInv S Di S S
+ * -----------------------------------------------------------------
+ * N_VAddConst S Di S
+ * -----------------------------------------------------------------
+ * N_VDotProd I I I
+ * -----------------------------------------------------------------
+ * N_VMaxNorm S S S
+ * -----------------------------------------------------------------
+ * N_VWrmsNorm S D B I BP BBDP S
+ * -----------------------------------------------------------------
+ * N_VWrmsNormMask S
+ * -----------------------------------------------------------------
+ * N_VMin S S S
+ * -----------------------------------------------------------------
+ * N_VWL2Norm S I
+ * -----------------------------------------------------------------
+ * N_VL1Norm I
+ * -----------------------------------------------------------------
+ * N_VCompare Di S
+ * -----------------------------------------------------------------
+ * N_VInvTest Di
+ * -----------------------------------------------------------------
+ * N_VConstrMask S S
+ * -----------------------------------------------------------------
+ * N_VMinQuotient S S
+ * -----------------------------------------------------------------
+ */
+
+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 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);
+SUNDIALS_EXPORT void N_VConst(realtype c, N_Vector z);
+SUNDIALS_EXPORT void N_VProd(N_Vector x, N_Vector y, N_Vector z);
+SUNDIALS_EXPORT void N_VDiv(N_Vector x, N_Vector y, N_Vector z);
+SUNDIALS_EXPORT void N_VScale(realtype c, N_Vector x, N_Vector z);
+SUNDIALS_EXPORT void N_VAbs(N_Vector x, N_Vector z);
+SUNDIALS_EXPORT void N_VInv(N_Vector x, N_Vector z);
+SUNDIALS_EXPORT void N_VAddConst(N_Vector x, realtype b, N_Vector z);
+SUNDIALS_EXPORT realtype N_VDotProd(N_Vector x, N_Vector y);
+SUNDIALS_EXPORT realtype N_VMaxNorm(N_Vector x);
+SUNDIALS_EXPORT realtype N_VWrmsNorm(N_Vector x, N_Vector w);
+SUNDIALS_EXPORT realtype N_VWrmsNormMask(N_Vector x, N_Vector w, N_Vector id);
+SUNDIALS_EXPORT realtype N_VMin(N_Vector x);
+SUNDIALS_EXPORT realtype N_VWL2Norm(N_Vector x, N_Vector w);
+SUNDIALS_EXPORT realtype N_VL1Norm(N_Vector x);
+SUNDIALS_EXPORT void N_VCompare(realtype c, N_Vector x, N_Vector z);
+SUNDIALS_EXPORT booleantype N_VInvTest(N_Vector x, N_Vector z);
+SUNDIALS_EXPORT booleantype N_VConstrMask(N_Vector c, N_Vector x, N_Vector m);
+SUNDIALS_EXPORT realtype N_VMinQuotient(N_Vector num, N_Vector denom);
+
+/*
+ * -----------------------------------------------------------------
+ * Additional functions exported by NVECTOR module
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * -----------------------------------------------------------------
+ * N_VCloneEmptyVectorArray
+ * Creates (by cloning 'w') an array of 'count' empty N_Vectors
+ *
+ * N_VCloneVectorArray
+ * Creates (by cloning 'w') an array of 'count' N_Vectors
+ *
+ * N_VDestroyVectorArray
+ * Frees memory for an array of 'count' N_Vectors that was
+ * created by a call to N_VCloneVectorArray
+ *
+ * These functions are used by the SPGMR iterative linear solver
+ * module and by the CVODES and IDAS solvers.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT N_Vector *N_VCloneEmptyVectorArray(int count, N_Vector w);
+SUNDIALS_EXPORT N_Vector *N_VCloneVectorArray(int count, N_Vector w);
+SUNDIALS_EXPORT void N_VDestroyVectorArray(N_Vector *vs, int count);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/sundials/sundials_spbcgs.h b/include/sundials/sundials_spbcgs.h
new file mode 100644
index 0000000..d569d1d
--- /dev/null
+++ b/include/sundials/sundials_spbcgs.h
@@ -0,0 +1,199 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.2 $
+ * $Date: 2006/11/29 00:05:07 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Peter Brown and Aaron Collier @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2004, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * This is the header file for the implementation of the scaled,
+ * preconditioned Bi-CGSTAB (SPBCG) iterative linear solver.
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _SPBCG_H
+#define _SPBCG_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <sundials/sundials_iterative.h>
+
+/*
+ * -----------------------------------------------------------------
+ * Types: struct SpbcgMemRec and struct *SpbcgMem
+ * -----------------------------------------------------------------
+ * A variable declaration of type struct *SpbcgMem denotes a pointer
+ * to a data structure of type struct SpbcgMemRec. The SpbcgMemRec
+ * structure contains numerous fields that must be accessed by the
+ * SPBCG linear solver module.
+ *
+ * l_max maximum Krylov subspace dimension that SpbcgSolve will
+ * be permitted to use
+ *
+ * r vector (type N_Vector) which holds the scaled, preconditioned
+ * linear system residual
+ *
+ * r_star 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 scratch vector (type N_Vector) used as temporary vector
+ * storage
+ * -----------------------------------------------------------------
+ */
+
+typedef struct {
+
+ int l_max;
+
+ N_Vector r_star;
+ N_Vector r;
+ N_Vector p;
+ N_Vector q;
+ N_Vector u;
+ N_Vector Ap;
+ N_Vector vtemp;
+
+} SpbcgMemRec, *SpbcgMem;
+
+/*
+ * -----------------------------------------------------------------
+ * Function : SpbcgMalloc
+ * -----------------------------------------------------------------
+ * SpbcgMalloc allocates additional memory needed by the SPBCG
+ * linear solver module.
+ *
+ * l_max maximum Krylov subspace dimension that SpbcgSolve will
+ * be permitted to use
+ *
+ * vec_tmpl implementation-specific template vector (type N_Vector)
+ * (created using either N_VNew_Serial or N_VNew_Parallel)
+ *
+ * If successful, SpbcgMalloc returns a non-NULL memory pointer. If
+ * an error occurs, then a NULL pointer is returned.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT SpbcgMem SpbcgMalloc(int l_max, N_Vector vec_tmpl);
+
+/*
+ * -----------------------------------------------------------------
+ * Function : SpbcgSolve
+ * -----------------------------------------------------------------
+ * SpbcgSolve solves the linear system Ax = b by means of a scaled
+ * preconditioned Bi-CGSTAB (SPBCG) iterative method.
+ *
+ * mem pointer to an internal memory block allocated during a
+ * prior call to SpbcgMalloc
+ *
+ * A_data pointer to a data structure containing information
+ * about the coefficient matrix A (passed to user-supplied
+ * function referenced by atimes (function pointer))
+ *
+ * x vector (type N_Vector) containing initial guess x_0 upon
+ * entry, but which upon return contains an approximate solution
+ * of the linear system Ax = b (solution only valid if return
+ * value is either SPBCG_SUCCESS or SPBCG_RES_REDUCED)
+ *
+ * b vector (type N_Vector) set to the right-hand side vector b
+ * of the linear system (undisturbed by function)
+ *
+ * pretype variable (type int) indicating the type of
+ * preconditioning to be used (see sundials_iterative.h)
+ *
+ * delta tolerance on the L2 norm of the scaled, preconditioned
+ * residual (if return value == SPBCG_SUCCESS, then
+ * ||sb*P1_inv*(b-Ax)||_L2 <= delta)
+ *
+ * P_data pointer to a data structure containing preconditioner
+ * information (passed to user-supplied function referenced
+ * by psolve (function pointer))
+ *
+ * sx vector (type N_Vector) containing positive scaling factors
+ * for x (pass sx == NULL if scaling NOT required)
+ *
+ * sb vector (type N_Vector) containing positive scaling factors
+ * for b (pass sb == NULL if scaling NOT required)
+ *
+ * atimes user-supplied routine responsible for computing the
+ * matrix-vector product Ax (see sundials_iterative.h)
+ *
+ * psolve user-supplied routine responsible for solving the
+ * preconditioned linear system Pz = r (ignored if
+ * pretype == PREC_NONE) (see sundials_iterative.h)
+ *
+ * res_norm pointer (type realtype*) to the L2 norm of the
+ * scaled, preconditioned residual (if return value
+ * is either SPBCG_SUCCESS or SPBCG_RES_REDUCED, then
+ * *res_norm = ||sb*P1_inv*(b-Ax)||_L2, where x is
+ * the computed approximate solution, sb is the diagonal
+ * scaling matrix for the right-hand side b, and P1_inv
+ * is the inverse of the left-preconditioner matrix)
+ *
+ * nli pointer (type int*) to the total number of linear
+ * iterations performed
+ *
+ * nps pointer (type int*) to the total number of calls made
+ * to the psolve routine
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int SpbcgSolve(SpbcgMem mem, void *A_data, N_Vector x, N_Vector b,
+ int pretype, realtype delta, void *P_data, N_Vector sx,
+ N_Vector sb, ATimesFn atimes, PSolveFn psolve,
+ realtype *res_norm, int *nli, int *nps);
+
+/* Return values for SpbcgSolve */
+
+#define SPBCG_SUCCESS 0 /* SPBCG algorithm converged */
+#define SPBCG_RES_REDUCED 1 /* SPBCG did NOT converge, but the
+ residual was reduced */
+#define SPBCG_CONV_FAIL 2 /* SPBCG algorithm failed to converge */
+#define SPBCG_PSOLVE_FAIL_REC 3 /* psolve failed recoverably */
+#define SPBCG_ATIMES_FAIL_REC 4 /* atimes failed recoverably */
+#define SPBCG_PSET_FAIL_REC 5 /* pset faild recoverably */
+
+#define SPBCG_MEM_NULL -1 /* mem argument is NULL */
+#define SPBCG_ATIMES_FAIL_UNREC -2 /* atimes returned failure flag */
+#define SPBCG_PSOLVE_FAIL_UNREC -3 /* psolve failed unrecoverably */
+#define SPBCG_PSET_FAIL_UNREC -4 /* pset failed unrecoverably */
+
+/*
+ * -----------------------------------------------------------------
+ * Function : SpbcgFree
+ * -----------------------------------------------------------------
+ * SpbcgFree frees the memory allocated by a call to SpbcgMalloc.
+ * It is illegal to use the pointer mem after a call to SpbcgFree.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT void SpbcgFree(SpbcgMem mem);
+
+/*
+ * -----------------------------------------------------------------
+ * Macro : SPBCG_VTEMP
+ * -----------------------------------------------------------------
+ * This macro provides access to the vector r in the
+ * memory block of the SPBCG module. The argument mem is the
+ * memory pointer returned by SpbcgMalloc, of type SpbcgMem,
+ * and the macro value is of type N_Vector.
+ *
+ * Note: Only used by IDA (r contains P_inverse F if nli_inc == 0).
+ * -----------------------------------------------------------------
+ */
+
+#define SPBCG_VTEMP(mem) (mem->r)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/sundials/sundials_spgmr.h b/include/sundials/sundials_spgmr.h
new file mode 100644
index 0000000..880c1c5
--- /dev/null
+++ b/include/sundials/sundials_spgmr.h
@@ -0,0 +1,296 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.3 $
+ * $Date: 2011/06/23 00:17:51 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh and
+ * Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * This is the header file for the implementation of SPGMR Krylov
+ * iterative linear solver. 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 two routines
+ * and making three calls. The user-supplied routines are
+ * atimes (A_data, x, y) to compute y = A x, given x,
+ * and
+ * psolve (P_data, y, x, lr)
+ * to solve P1 x = y or P2 x = y for x, given y.
+ * The three user calls are:
+ * mem = SpgmrMalloc(lmax, vec_tmpl);
+ * to initialize memory,
+ * flag = SpgmrSolve(mem,A_data,x,b,...,
+ * P_data,s1,s2,atimes,psolve,...);
+ * to solve the system, and
+ * SpgmrFree(mem);
+ * to free the memory created by SpgmrMalloc.
+ * Complete details for specifying atimes and psolve and for the
+ * usage calls are given below and in sundials_iterative.h.
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _SPGMR_H
+#define _SPGMR_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <sundials/sundials_iterative.h>
+
+/*
+ * -----------------------------------------------------------------
+ * Types: SpgmrMemRec, SpgmrMem
+ * -----------------------------------------------------------------
+ * SpgmrMem is a pointer to an SpgmrMemRec which contains
+ * the memory needed by SpgmrSolve. The SpgmrMalloc routine
+ * returns a pointer of type SpgmrMem which should then be passed
+ * in subsequent calls to SpgmrSolve. The SpgmrFree routine frees
+ * the memory allocated by SpgmrMalloc.
+ *
+ * l_max is the maximum Krylov dimension that SpgmrSolve will be
+ * permitted to use.
+ *
+ * V is the array of Krylov basis vectors v_1, ..., v_(l_max+1),
+ * stored in V[0], ..., V[l_max], where l_max is the second
+ * parameter to SpgmrMalloc. Each v_i is a vector of type
+ * N_Vector.
+ *
+ * Hes is the (l_max+1) x l_max Hessenberg matrix. It is stored
+ * row-wise so that the (i,j)th element is given by Hes[i][j].
+ *
+ * givens is a length 2*l_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 is a vector (type N_Vector) which holds the scaled,
+ * preconditioned correction to the initial guess.
+ *
+ * yg is a length (l_max+1) array of realtype used to hold "short"
+ * vectors (e.g. y and g).
+ *
+ * vtemp is a vector (type N_Vector) used as temporary vector
+ * storage during calculations.
+ * -----------------------------------------------------------------
+ */
+
+typedef struct _SpgmrMemRec {
+
+ int l_max;
+
+ N_Vector *V;
+ realtype **Hes;
+ realtype *givens;
+ N_Vector xcor;
+ realtype *yg;
+ N_Vector vtemp;
+
+} SpgmrMemRec, *SpgmrMem;
+
+/*
+ * -----------------------------------------------------------------
+ * Function : SpgmrMalloc
+ * -----------------------------------------------------------------
+ * SpgmrMalloc allocates the memory used by SpgmrSolve. It
+ * returns a pointer of type SpgmrMem which the user of the
+ * SPGMR package should pass to SpgmrSolve. The parameter l_max
+ * is the maximum Krylov dimension that SpgmrSolve will be
+ * permitted to use. The parameter vec_tmpl is a pointer to an
+ * N_Vector used as a template to create new vectors by duplication.
+ * This routine returns NULL if there is a memory request failure.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT SpgmrMem SpgmrMalloc(int l_max, N_Vector vec_tmpl);
+
+/*
+ * -----------------------------------------------------------------
+ * Function : SpgmrSolve
+ * -----------------------------------------------------------------
+ * SpgmrSolve solves the linear system Ax = b using the SPGMR
+ * method. The return values are given by the symbolic constants
+ * below. The first SpgmrSolve parameter is a pointer to memory
+ * allocated by a prior call to SpgmrMalloc.
+ *
+ * mem is the pointer returned by SpgmrMalloc to the structure
+ * containing the memory needed by SpgmrSolve.
+ *
+ * A_data is a pointer to information about the coefficient
+ * matrix A. This pointer is passed to the user-supplied function
+ * atimes.
+ *
+ * x is the initial guess x_0 upon entry and the solution
+ * N_Vector upon exit with return value SPGMR_SUCCESS or
+ * SPGMR_RES_REDUCED. For all other return values, the output x
+ * is undefined.
+ *
+ * b is the right hand side N_Vector. It is undisturbed by this
+ * function.
+ *
+ * pretype is the type of preconditioning to be used. Its
+ * legal values are enumerated in sundials_iterative.h. These
+ * values are PREC_NONE=0, PREC_LEFT=1, PREC_RIGHT=2, and
+ * PREC_BOTH=3.
+ *
+ * gstype is the type of Gram-Schmidt orthogonalization to be
+ * used. Its legal values are enumerated in sundials_iterative.h.
+ * These values are MODIFIED_GS=0 and CLASSICAL_GS=1.
+ *
+ * delta is the tolerance on the L2 norm of the scaled,
+ * preconditioned residual. On return with value SPGMR_SUCCESS,
+ * this residual satisfies || s1 P1_inv (b - Ax) ||_2 <= delta.
+ *
+ * max_restarts is the maximum number of times the algorithm is
+ * allowed to restart.
+ *
+ * P_data is a pointer to preconditioner information. This
+ * pointer is passed to the user-supplied function psolve.
+ *
+ * s1 is an N_Vector of positive scale factors for P1-inv b, where
+ * P1 is the left preconditioner. (Not tested for positivity.)
+ * Pass NULL if no scaling on P1-inv b is required.
+ *
+ * s2 is an N_Vector of positive scale factors for P2 x, where
+ * P2 is the right preconditioner. (Not tested for positivity.)
+ * Pass NULL if no scaling on P2 x is required.
+ *
+ * atimes is the user-supplied function which performs the
+ * operation of multiplying A by a given vector. Its description
+ * is given in sundials_iterative.h.
+ *
+ * psolve is the user-supplied function which solves a
+ * preconditioner system Pz = r, where P is P1 or P2. Its full
+ * description is given in sundials_iterative.h. The psolve function
+ * will not be called if pretype is NONE; in that case, the user
+ * should pass NULL for psolve.
+ *
+ * res_norm is a pointer to the L2 norm of the scaled,
+ * preconditioned residual. On return with value SPGMR_SUCCESS or
+ * SPGMR_RES_REDUCED, (*res_norm) contains the value
+ * || s1 P1_inv (b - Ax) ||_2 for the computed solution x.
+ * For all other return values, (*res_norm) is undefined. The
+ * caller is responsible for allocating the memory (*res_norm)
+ * to be filled in by SpgmrSolve.
+ *
+ * nli is a pointer to the number of linear iterations done in
+ * the execution of SpgmrSolve. The caller is responsible for
+ * allocating the memory (*nli) to be filled in by SpgmrSolve.
+ *
+ * nps is a pointer to the number of calls made to psolve during
+ * the execution of SpgmrSolve. The caller is responsible for
+ * allocating the memory (*nps) to be filled in by SpgmrSolve.
+ *
+ * Note: Repeated calls can be made to SpgmrSolve with varying
+ * input arguments. If, however, the problem size N or the
+ * maximum Krylov dimension l_max changes, then a call to
+ * SpgmrMalloc must be made to obtain new memory for SpgmrSolve
+ * to use.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int SpgmrSolve(SpgmrMem mem, void *A_data, N_Vector x, N_Vector b,
+ int pretype, int gstype, realtype delta,
+ int max_restarts, void *P_data, N_Vector s1,
+ N_Vector s2, ATimesFn atimes, PSolveFn psolve,
+ realtype *res_norm, int *nli, int *nps);
+
+
+/* Return values for SpgmrSolve */
+
+#define SPGMR_SUCCESS 0 /* Converged */
+#define SPGMR_RES_REDUCED 1 /* Did not converge, but reduced
+ norm of residual */
+#define SPGMR_CONV_FAIL 2 /* Failed to converge */
+#define SPGMR_QRFACT_FAIL 3 /* QRfact found singular matrix */
+#define SPGMR_PSOLVE_FAIL_REC 4 /* psolve failed recoverably */
+#define SPGMR_ATIMES_FAIL_REC 5 /* atimes failed recoverably */
+#define SPGMR_PSET_FAIL_REC 6 /* pset faild recoverably */
+
+#define SPGMR_MEM_NULL -1 /* mem argument is NULL */
+#define SPGMR_ATIMES_FAIL_UNREC -2 /* atimes returned failure flag */
+#define SPGMR_PSOLVE_FAIL_UNREC -3 /* psolve failed unrecoverably */
+#define SPGMR_GS_FAIL -4 /* Gram-Schmidt routine faiuled */
+#define SPGMR_QRSOL_FAIL -5 /* QRsol found singular R */
+#define SPGMR_PSET_FAIL_UNREC -6 /* pset failed unrecoverably */
+
+/*
+ * -----------------------------------------------------------------
+ * Function : SpgmrFree
+ * -----------------------------------------------------------------
+ * SpgmrMalloc frees the memory allocated by SpgmrMalloc. It is
+ * illegal to use the pointer mem after a call to SpgmrFree.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT void SpgmrFree(SpgmrMem mem);
+
+/*
+ * -----------------------------------------------------------------
+ * Macro: SPGMR_VTEMP
+ * -----------------------------------------------------------------
+ * This macro provides access to the work vector vtemp in the
+ * memory block of the SPGMR module. The argument mem is the
+ * memory pointer returned by SpgmrMalloc, of type SpgmrMem,
+ * and the macro value is of type N_Vector.
+ * On a return from SpgmrSolve with *nli = 0, this vector
+ * contains the scaled preconditioned initial residual,
+ * s1 * P1_inverse * (b - A x_0).
+ * -----------------------------------------------------------------
+ */
+
+#define SPGMR_VTEMP(mem) (mem->vtemp)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/sundials/sundials_sptfqmr.h b/include/sundials/sundials_sptfqmr.h
new file mode 100644
index 0000000..6502101
--- /dev/null
+++ b/include/sundials/sundials_sptfqmr.h
@@ -0,0 +1,254 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.3 $
+ * $Date: 2011/06/23 00:17:51 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Aaron Collier @ 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.
+ * -----------------------------------------------------------------
+ * This is the header file for the implementation of the scaled
+ * preconditioned Transpose-Free Quasi-Minimal Residual (SPTFQMR)
+ * linear solver.
+ *
+ * The SPTFQMR algorithm solves a linear system of the form Ax = b.
+ * Preconditioning is allowed on the left (PREC_LEFT), right
+ * (PREC_RIGHT), or both (PREC_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 two routines
+ * and making three calls. The user-supplied routines are:
+ * atimes(A_data, x, y) to compute y = A x, given x,
+ * and
+ * psolve(P_data, y, x, lr) to solve P1 x = y or P2 x = y for x,
+ * given y.
+ * The three user calls are:
+ * mem = SptfqmrMalloc(lmax, vec_tmpl);
+ * to initialize memory
+ * flag = SptfqmrSolve(mem, A_data, x, b, pretype, delta, P_data,
+ * sx, sb, atimes, psolve, res_norm, nli, nps);
+ * to solve the system, and
+ * SptfqmrFree(mem);
+ * to free the memory allocated by SptfqmrMalloc().
+ * Complete details for specifying atimes() and psolve() and for the
+ * usage calls are given in the paragraphs below and in the header
+ * file sundials_iterative.h.
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _SPTFQMR_H
+#define _SPTFQMR_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <sundials/sundials_iterative.h>
+
+/*
+ * -----------------------------------------------------------------
+ * Types: struct SptfqmrMemRec and struct *SptfqmrMem
+ * -----------------------------------------------------------------
+ * A variable declaration of type struct *SptfqmrMem denotes a pointer
+ * to a data structure of type struct SptfqmrMemRec. The SptfqmrMemRec
+ * structure contains numerous fields that must be accessed by the
+ * SPTFQMR linear solver module.
+ *
+ * l_max maximum Krylov subspace dimension that SptfqmrSolve will
+ * be permitted to use
+ *
+ * r_star vector (type N_Vector) which holds the initial scaled,
+ * preconditioned linear system residual
+ *
+ * q/d/v/p/u/r vectors (type N_Vector) used for workspace by
+ * the SPTFQMR algorithm
+ *
+ * vtemp1/vtemp2/vtemp3 scratch vectors (type N_Vector) used as
+ * temporary storage
+ * -----------------------------------------------------------------
+ */
+
+typedef struct {
+
+ int l_max;
+
+ 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;
+
+} SptfqmrMemRec, *SptfqmrMem;
+
+/*
+ * -----------------------------------------------------------------
+ * Function : SptfqmrMalloc
+ * -----------------------------------------------------------------
+ * SptfqmrMalloc allocates additional memory needed by the SPTFQMR
+ * linear solver module.
+ *
+ * l_max maximum Krylov subspace dimension that SptfqmrSolve will
+ * be permitted to use
+ *
+ * vec_tmpl implementation-specific template vector (type N_Vector)
+ * (created using either N_VNew_Serial or N_VNew_Parallel)
+ *
+ * If successful, SptfqmrMalloc returns a non-NULL memory pointer. If
+ * an error occurs, then a NULL pointer is returned.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT SptfqmrMem SptfqmrMalloc(int l_max, N_Vector vec_tmpl);
+
+/*
+ * -----------------------------------------------------------------
+ * Function : SptfqmrSolve
+ * -----------------------------------------------------------------
+ * SptfqmrSolve solves the linear system Ax = b by means of a scaled
+ * preconditioned Transpose-Free Quasi-Minimal Residual (SPTFQMR)
+ * method.
+ *
+ * mem pointer to an internal memory block allocated during a
+ * prior call to SptfqmrMalloc
+ *
+ * A_data pointer to a data structure containing information
+ * about the coefficient matrix A (passed to user-supplied
+ * function referenced by atimes (function pointer))
+ *
+ * x vector (type N_Vector) containing initial guess x_0 upon
+ * entry, but which upon return contains an approximate solution
+ * of the linear system Ax = b (solution only valid if return
+ * value is either SPTFQMR_SUCCESS or SPTFQMR_RES_REDUCED)
+ *
+ * b vector (type N_Vector) set to the right-hand side vector b
+ * of the linear system (undisturbed by function)
+ *
+ * pretype variable (type int) indicating the type of
+ * preconditioning to be used (see sundials_iterative.h)
+ *
+ * delta tolerance on the L2 norm of the scaled, preconditioned
+ * residual (if return value == SPTFQMR_SUCCESS, then
+ * ||sb*P1_inv*(b-Ax)||_L2 <= delta)
+ *
+ * P_data pointer to a data structure containing preconditioner
+ * information (passed to user-supplied function referenced
+ * by psolve (function pointer))
+ *
+ * sx vector (type N_Vector) containing positive scaling factors
+ * for x (pass sx == NULL if scaling NOT required)
+ *
+ * sb vector (type N_Vector) containing positive scaling factors
+ * for b (pass sb == NULL if scaling NOT required)
+ *
+ * atimes user-supplied routine responsible for computing the
+ * matrix-vector product Ax (see sundials_iterative.h)
+ *
+ * psolve user-supplied routine responsible for solving the
+ * preconditioned linear system Pz = r (ignored if
+ * pretype == PREC_NONE) (see sundials_iterative.h)
+ *
+ * res_norm pointer (type realtype*) to the L2 norm of the
+ * scaled, preconditioned residual (if return value
+ * is either SPTFQMR_SUCCESS or SPTFQMR_RES_REDUCED, then
+ * *res_norm = ||sb*P1_inv*(b-Ax)||_L2, where x is
+ * the computed approximate solution, sb is the diagonal
+ * scaling matrix for the right-hand side b, and P1_inv
+ * is the inverse of the left-preconditioner matrix)
+ *
+ * nli pointer (type int*) to the total number of linear
+ * iterations performed
+ *
+ * nps pointer (type int*) to the total number of calls made
+ * to the psolve routine
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int SptfqmrSolve(SptfqmrMem mem, void *A_data, N_Vector x, N_Vector b,
+ int pretype, realtype delta, void *P_data, N_Vector sx,
+ N_Vector sb, ATimesFn atimes, PSolveFn psolve,
+ realtype *res_norm, int *nli, int *nps);
+
+/* Return values for SptfqmrSolve */
+
+#define SPTFQMR_SUCCESS 0 /* SPTFQMR algorithm converged */
+#define SPTFQMR_RES_REDUCED 1 /* SPTFQMR did NOT converge, but the
+ residual was reduced */
+#define SPTFQMR_CONV_FAIL 2 /* SPTFQMR algorithm failed to converge */
+#define SPTFQMR_PSOLVE_FAIL_REC 3 /* psolve failed recoverably */
+#define SPTFQMR_ATIMES_FAIL_REC 4 /* atimes failed recoverably */
+#define SPTFQMR_PSET_FAIL_REC 5 /* pset faild recoverably */
+
+#define SPTFQMR_MEM_NULL -1 /* mem argument is NULL */
+#define SPTFQMR_ATIMES_FAIL_UNREC -2 /* atimes returned failure flag */
+#define SPTFQMR_PSOLVE_FAIL_UNREC -3 /* psolve failed unrecoverably */
+#define SPTFQMR_PSET_FAIL_UNREC -4 /* pset failed unrecoverably */
+
+/*
+ * -----------------------------------------------------------------
+ * Function : SptfqmrFree
+ * -----------------------------------------------------------------
+ * SptfqmrFree frees the memory allocated by a call to SptfqmrMalloc.
+ * It is illegal to use the pointer mem after a call to SptfqmrFree.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT void SptfqmrFree(SptfqmrMem mem);
+
+/*
+ * -----------------------------------------------------------------
+ * Macro : SPTFQMR_VTEMP
+ * -----------------------------------------------------------------
+ * This macro provides access to the work vector vtemp1 in the
+ * memory block of the SPTFQMR module. The argument mem is the
+ * memory pointer returned by SptfqmrMalloc, of type SptfqmrMem,
+ * and the macro value is of type N_Vector.
+ *
+ * Note: Only used by IDA (vtemp1 contains P_inverse F if
+ * nli_inc == 0).
+ * -----------------------------------------------------------------
+ */
+
+#define SPTFQMR_VTEMP(mem) (mem->vtemp1)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/sundials/sundials_types.h b/include/sundials/sundials_types.h
new file mode 100644
index 0000000..953f6e0
--- /dev/null
+++ b/include/sundials/sundials_types.h
@@ -0,0 +1,122 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.2 $
+ * $Date: 2006/11/29 00:05:07 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Scott Cohen, Alan Hindmarsh, Radu Serban, and
+ * Aaron Collier @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * 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.
+ *
+ * Users should include the header file sundials_types.h in every
+ * program file and use the exported name realtype instead of
+ * float, double or long double.
+ *
+ * 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.
+ *
+ * The legal types for realtype are float, double and long double.
+ *
+ * The macro RCONST gives the user a convenient way to define
+ * real-valued constants. To use the constant 1.0, for example,
+ * the user should write the following:
+ *
+ * #define ONE RCONST(1.0)
+ *
+ * If realtype is defined as a double, then RCONST(1.0) expands
+ * 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).
+ *------------------------------------------------------------------
+ */
+
+#ifndef _SUNDIALSTYPES_H
+#define _SUNDIALSTYPES_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#ifndef _SUNDIALS_CONFIG_H
+#define _SUNDIALS_CONFIG_H
+#include <sundials/sundials_config.h>
+#endif
+
+#include <float.h>
+
+/*
+ *------------------------------------------------------------------
+ * Type realtype
+ * Macro RCONST
+ * Constants BIG_REAL, SMALL_REAL, and UNIT_ROUNDOFF
+ *------------------------------------------------------------------
+ */
+
+#if defined(SUNDIALS_SINGLE_PRECISION)
+
+typedef float realtype;
+# define RCONST(x) x##F
+# define BIG_REAL FLT_MAX
+# define SMALL_REAL FLT_MIN
+# define UNIT_ROUNDOFF FLT_EPSILON
+
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+
+typedef double realtype;
+# define RCONST(x) x
+# define BIG_REAL DBL_MAX
+# define SMALL_REAL DBL_MIN
+# define UNIT_ROUNDOFF DBL_EPSILON
+
+#elif defined(SUNDIALS_EXTENDED_PRECISION)
+
+typedef long double realtype;
+# define RCONST(x) x##L
+# define BIG_REAL LDBL_MAX
+# define SMALL_REAL LDBL_MIN
+# define UNIT_ROUNDOFF LDBL_EPSILON
+
+#endif
+
+/*
+ *------------------------------------------------------------------
+ * Type : booleantype
+ *------------------------------------------------------------------
+ * Constants : FALSE and TRUE
+ *------------------------------------------------------------------
+ * 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,
+ * respectively.
+ *------------------------------------------------------------------
+ */
+
+#ifndef booleantype
+#define booleantype int
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/cvode/CMakeLists.txt b/src/cvode/CMakeLists.txt
new file mode 100644
index 0000000..5756cab
--- /dev/null
+++ b/src/cvode/CMakeLists.txt
@@ -0,0 +1,128 @@
+# ---------------------------------------------------------------
+# $Revision: 1.4 $
+# $Date: 2009/02/17 02:58:47 $
+# ---------------------------------------------------------------
+# Programmer: Radu Serban @ LLNL
+# ---------------------------------------------------------------
+# Copyright (c) 2007, The Regents of the University of California.
+# Produced at the Lawrence Livermore National Laboratory.
+# All rights reserved.
+# For details, see the LICENSE file.
+# ---------------------------------------------------------------
+# CMakeLists.txt file for the CVODE library
+
+INSTALL(CODE "MESSAGE(\"\nInstall CVODE\n\")")
+
+# 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_bandpre.c
+ cvode_bbdpre.c
+ )
+
+# 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_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 cvode_HEADERS with the exported CVODE header files
+SET(cvode_HEADERS
+ cvode_band.h
+ cvode_bandpre.h
+ cvode_bbdpre.h
+ cvode_dense.h
+ cvode_diag.h
+ cvode_direct.h
+ cvode.h
+ cvode_spbcgs.h
+ cvode_spgmr.h
+ cvode_spils.h
+ cvode_sptfqmr.h
+ )
+
+# 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(.)
+INCLUDE_DIRECTORIES(../sundials)
+
+# Define C preprocessor flag -DBUILD_SUNDIALS_LIBRARY
+ADD_DEFINITIONS(-DBUILD_SUNDIALS_LIBRARY)
+
+# Build the static library
+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})
+
+ # Set the library name and make sure it is not deleted
+ SET_TARGET_PROPERTIES(sundials_cvode_static
+ PROPERTIES OUTPUT_NAME sundials_cvode CLEAN_DIRECT_OUTPUT 1)
+
+ # Install the CVODE library
+ INSTALL(TARGETS sundials_cvode_static DESTINATION lib)
+
+ENDIF(BUILD_STATIC_LIBS)
+
+# Build the shared library
+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})
+
+ # Set the library name and make sure it is not deleted
+ SET_TARGET_PROPERTIES(sundials_cvode_shared
+ PROPERTIES OUTPUT_NAME sundials_cvode CLEAN_DIRECT_OUTPUT 1)
+
+ # Set VERSION and SOVERSION for shared libraries
+ SET_TARGET_PROPERTIES(sundials_cvode_shared
+ PROPERTIES VERSION ${cvodelib_VERSION} SOVERSION ${cvodelib_SOVERSION})
+
+ # Install the CVODE library
+ INSTALL(TARGETS sundials_cvode_shared DESTINATION lib)
+
+ENDIF(BUILD_SHARED_LIBS)
+
+# Install the CVODE header files
+INSTALL(FILES ${cvode_HEADERS} ${cvode_BL_HEADERS} DESTINATION include/cvode)
+
+# Install the CVODE implementation header file
+INSTALL(FILES cvode_impl.h DESTINATION include/cvode)
+
+#
+MESSAGE(STATUS "Added CVODE module")
diff --git a/debian/copyright b/src/cvode/LICENSE
similarity index 83%
copy from debian/copyright
copy to src/cvode/LICENSE
index 98cde97..c093380 100644
--- a/debian/copyright
+++ b/src/cvode/LICENSE
@@ -1,22 +1,10 @@
-This package was debianized by Andrey Romanenko <andrey at enginum.com> on
-Wed, 20 Apr 2005 12:01:42 +0100.
+Copyright (c) 2002, The Regents of the University of California.
+Produced at the Lawrence Livermore National Laboratory.
+Written by Scott Cohen, Alan Hindmarsh, Radu Serban, Dan Shumaker.
+UCRL-CODE-155951
+All rights reserved.
-It was downloaded from http://www.llnl.gov/CASC/sundials/
-
-Authors: Peter Brown, Aaron Collier, Keith Grant, Alan Hindmarsh,
- Steve Lee, Radu Serban, Dan Shumaker, Carol Woodward
-
-Copyright Holder: The Regents of the University of California.
-
-License:
-
-Copyright (c) 2002, The Regents of the University of California.
-Produced at the Lawrence Livermore National Laboratory
-Written by A.C. Hindmarsh and R. Serban.
-UCRL-CODE-155950
-All rights reserved.
-
-This file is part of CVODES v2.1.0.
+This file is part of CVODE.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
diff --git a/src/cvode/Makefile.in b/src/cvode/Makefile.in
new file mode 100644
index 0000000..268f043
--- /dev/null
+++ b/src/cvode/Makefile.in
@@ -0,0 +1,175 @@
+# -----------------------------------------------------------------
+# $Revision: 1.12 $
+# $Date: 2009/03/25 23:10:50 $
+# -----------------------------------------------------------------
+# Programmer(s): Radu Serban and Aaron Collier @ LLNL
+# -----------------------------------------------------------------
+# Copyright (c) 2002, The Regents of the University of California.
+# Produced at the Lawrence Livermore National Laboratory.
+# All rights reserved.
+# For details, see the LICENSE file.
+# -----------------------------------------------------------------
+# Makefile for CVODE module
+#
+# @configure_input@
+# -----------------------------------------------------------------
+
+SHELL = @SHELL@
+
+ at SET_MAKE@
+
+srcdir = @srcdir@
+builddir = @builddir@
+abs_builddir = @abs_builddir@
+top_builddir = @top_builddir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+includedir = @includedir@
+libdir = @libdir@
+
+INSTALL = @INSTALL@
+INSTALL_LIB = @INSTALL_PROGRAM@
+INSTALL_HEADER = @INSTALL_DATA@
+
+LIBTOOL = @LIBTOOL@
+LIBTOOL_DEPS = @LIBTOOL_DEPS@
+
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CC = @CC@
+CFLAGS = @CFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+
+LAPACK_ENABLED = @LAPACK_ENABLED@
+
+top_srcdir = $(srcdir)/../..
+
+INCLUDES = -I$(top_srcdir)/include -I$(top_builddir)/include
+
+LIB_REVISION = 1:0:0
+
+CVODE_LIB = libsundials_cvode.la
+
+CVODE_SRC_FILES = 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_bandpre.c cvode_bbdpre.c
+CVODE_BL_SRC_FILES = cvode_lapack.c
+
+CVODE_OBJ_FILES = $(CVODE_SRC_FILES:.c=.o)
+CVODE_BL_OBJ_FILES = $(CVODE_BL_SRC_FILES:.c=.o)
+
+CVODE_LIB_FILES = $(CVODE_SRC_FILES:.c=.lo)
+CVODE_BL_LIB_FILES = $(CVODE_BL_SRC_FILES:.c=.lo)
+
+SHARED_LIB_FILES = $(top_builddir)/src/sundials/sundials_band.lo \
+ $(top_builddir)/src/sundials/sundials_dense.lo \
+ $(top_builddir)/src/sundials/sundials_direct.lo \
+ $(top_builddir)/src/sundials/sundials_iterative.lo \
+ $(top_builddir)/src/sundials/sundials_spgmr.lo \
+ $(top_builddir)/src/sundials/sundials_spbcgs.lo \
+ $(top_builddir)/src/sundials/sundials_sptfqmr.lo \
+ $(top_builddir)/src/sundials/sundials_math.lo \
+ $(top_builddir)/src/sundials/sundials_nvector.lo
+
+mkinstalldirs = $(SHELL) $(top_srcdir)/config/mkinstalldirs
+rminstalldirs = $(SHELL) $(top_srcdir)/config/rminstalldirs
+
+# ----------------------------------------------------------------------------------------------------------------------
+
+all: $(CVODE_LIB)
+
+$(CVODE_LIB): shared $(CVODE_LIB_FILES)
+ @if test "X${LAPACK_ENABLED}" = "Xyes"; then \
+ make lib_with_bl; \
+ else \
+ make lib_without_bl; \
+ fi
+
+lib_without_bl: shared $(CVODE_LIB_FILES)
+ $(LIBTOOL) --mode=link $(CC) $(CFLAGS) -o $(CVODE_LIB) $(CVODE_LIB_FILES) $(SHARED_LIB_FILES) -rpath $(libdir) $(LDFLAGS) $(LIBS) -version-info $(LIB_REVISION)
+
+lib_with_bl: shared $(CVODE_LIB_FILES) $(CVODE_BL_LIB_FILES)
+ $(LIBTOOL) --mode=link $(CC) $(CFLAGS) -o $(CVODE_LIB) $(CVODE_LIB_FILES) $(CVODE_BL_LIB_FILES) $(SHARED_LIB_FILES) -rpath $(libdir) $(LDFLAGS) $(LIBS) -version-info $(LIB_REVISION)
+
+install: $(CVODE_LIB)
+ $(mkinstalldirs) $(includedir)/cvode
+ $(mkinstalldirs) $(libdir)
+ $(LIBTOOL) --mode=install $(INSTALL_LIB) $(CVODE_LIB) $(libdir)
+ $(INSTALL_HEADER) $(top_srcdir)/include/cvode/cvode.h $(includedir)/cvode/
+ $(INSTALL_HEADER) $(top_srcdir)/include/cvode/cvode_direct.h $(includedir)/cvode/
+ $(INSTALL_HEADER) $(top_srcdir)/include/cvode/cvode_dense.h $(includedir)/cvode/
+ $(INSTALL_HEADER) $(top_srcdir)/include/cvode/cvode_band.h $(includedir)/cvode/
+ $(INSTALL_HEADER) $(top_srcdir)/include/cvode/cvode_diag.h $(includedir)/cvode/
+ $(INSTALL_HEADER) $(top_srcdir)/include/cvode/cvode_spils.h $(includedir)/cvode/
+ $(INSTALL_HEADER) $(top_srcdir)/include/cvode/cvode_spbcgs.h $(includedir)/cvode/
+ $(INSTALL_HEADER) $(top_srcdir)/include/cvode/cvode_spgmr.h $(includedir)/cvode/
+ $(INSTALL_HEADER) $(top_srcdir)/include/cvode/cvode_sptfqmr.h $(includedir)/cvode/
+ $(INSTALL_HEADER) $(top_srcdir)/include/cvode/cvode_bandpre.h $(includedir)/cvode/
+ $(INSTALL_HEADER) $(top_srcdir)/include/cvode/cvode_bbdpre.h $(includedir)/cvode/
+ $(INSTALL_HEADER) $(top_srcdir)/src/cvode/cvode_impl.h $(includedir)/cvode/
+ @if test "X${LAPACK_ENABLED}" = "Xyes"; then \
+ $(INSTALL_HEADER) $(top_srcdir)/include/cvode/cvode_lapack.h $(includedir)/cvode/ ; \
+ fi
+
+uninstall:
+ $(LIBTOOL) --mode=uninstall rm -f $(libdir)/$(CVODE_LIB)
+ rm -f $(includedir)/cvode/cvode.h
+ rm -f $(includedir)/cvode/cvode_direct.h
+ rm -f $(includedir)/cvode/cvode_dense.h
+ rm -f $(includedir)/cvode/cvode_band.h
+ rm -f $(includedir)/cvode/cvode_diag.h
+ rm -f $(includedir)/cvode/cvode_lapack.h
+ rm -f $(includedir)/cvode/cvode_spils.h
+ rm -f $(includedir)/cvode/cvode_spbcgs.h
+ rm -f $(includedir)/cvode/cvode_spgmr.h
+ rm -f $(includedir)/cvode/cvode_sptfqmr.h
+ rm -f $(includedir)/cvode/cvode_bandpre.h
+ rm -f $(includedir)/cvode/cvode_bbdpre.h
+ rm -f $(includedir)/cvode/cvode_impl.h
+ $(rminstalldirs) $(includedir)/cvode
+
+shared:
+ @cd ${top_builddir}/src/sundials ; \
+ ${MAKE} ; \
+ cd ${abs_builddir}
+
+clean:
+ $(LIBTOOL) --mode=clean rm -f $(CVODE_LIB)
+ rm -f $(CVODE_LIB_FILES)
+ rm -f $(CVODE_BL_LIB_FILES)
+ rm -f $(CVODE_OBJ_FILES)
+ rm -f $(CVODE_BL_OBJ_FILES)
+
+distclean: clean
+ rm -f Makefile
+
+cvode.lo: $(srcdir)/cvode.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/cvode.c
+cvode_io.lo: $(srcdir)/cvode_io.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/cvode_io.c
+cvode_direct.lo: $(srcdir)/cvode_direct.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/cvode_direct.c
+cvode_dense.lo: $(srcdir)/cvode_dense.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/cvode_dense.c
+cvode_band.lo: $(srcdir)/cvode_band.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/cvode_band.c
+cvode_diag.lo: $(srcdir)/cvode_diag.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/cvode_diag.c
+cvode_lapack.lo: $(srcdir)/cvode_lapack.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/cvode_lapack.c
+cvode_spils.lo: $(srcdir)/cvode_spils.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/cvode_spils.c
+cvode_spbcgs.lo: $(srcdir)/cvode_spbcgs.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/cvode_spbcgs.c
+cvode_spgmr.lo: $(srcdir)/cvode_spgmr.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/cvode_spgmr.c
+cvode_sptfqmr.lo: $(srcdir)/cvode_sptfqmr.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/cvode_sptfqmr.c
+cvode_bandpre.lo: $(srcdir)/cvode_bandpre.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/cvode_bandpre.c
+cvode_bbdpre.lo: $(srcdir)/cvode_bbdpre.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/cvode_bbdpre.c
+
+libtool: $(top_builddir)/$(LIBTOOL_DEPS)
+ @cd ${top_builddir} ; \
+ ${SHELL} ./config.status --recheck ; \
+ cd ${abs_builddir}
diff --git a/src/cvode/README b/src/cvode/README
new file mode 100644
index 0000000..fe98969
--- /dev/null
+++ b/src/cvode/README
@@ -0,0 +1,462 @@
+ CVODE
+ Release 2.7.0, March 2012
+ Alan C. Hindmarsh and Radu Serban
+ Center for Applied Scientific Computing, LLNL
+
+CVODE is a solver for stiff and nonstiff ODE systems (initial value problem)
+given in explicit form dy/dt = f(t,y). It is written in ANSI standard C.
+
+CVODE can be used both on serial and parallel (MPI) computers. The main
+difference is in the NVECTOR module of vector kernels. The desired
+version is obtained when compiling the example files by linking the
+appropriate library of NVECTOR kernels. In the parallel version,
+communication between processors is done with the MPI (Message Passage
+Interface) system.
+
+When used with the serial NVECTOR module, CVODE provides both direct (dense
+and band) and preconditioned Krylov (iterative) linear solvers. Three different
+iterative solvers are available: scaled preconditioned GMRES (SPGMR), scaled
+preconditioned BiCGStab (SPBCG), and scaled preconditioned TFQMR (SPTFQMR).
+When CVODE 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 CVBANDPRE available for use with the Krylov solvers, while for the parallel
+version there is a preconditioner module called CVBBDPRE which provides a
+band-block-diagonal preconditioner.
+
+CVODE is part of a software family called SUNDIALS: SUite of Nonlinear
+and DIfferential/ALgebraic equation Solvers. This suite consists of
+CVODE, KINSOL, IDAS, and IDA, and variants of these. The directory
+structure of the package supplied reflects this family relationship.
+
+For use with Fortran applications, a set of Fortran/C interface routines,
+called FCVODE, is also supplied. These are written in C, but assume that
+the user calling program and all user-supplied routines are in Fortran.
+
+The notes below provide the location of documentation, directions for the
+installation of the CVODE package, and relevant references. Following that
+is a brief history of revisions to the package.
+
+
+A. Documentation
+----------------
+
+/sundials/doc/cvode/ contains PDF files for the CVODE User Guide [1] (cv_guide.pdf)
+and the CVODE Examples [2] (cv_examples.pdf) documents.
+
+
+B. Installation
+---------------
+
+For basic installation instructions see the file /sundials/INSTALL_NOTES.
+For complete installation instructions see the "CVODE Installation Procedure"
+chapter in the CVODE User Guide.
+
+
+C. References
+-------------
+
+[1] A. C. Hindmarsh and R. Serban, "User Documentation for CVODE v2.7.0,"
+ LLNL technical report UCRL-SM-208108, December 2011.
+
+[2] A. C. Hindmarsh and R. Serban, "Example Programs for CVODE v2.7.0,"
+ LLNL technical report UCRL-SM-208110, December 2011.
+
+[3] S.D. Cohen and A.C. Hindmarsh, "CVODE, a Stiff/nonstiff ODE Solver in C,"
+ Computers in Physics, 10(2), pp. 138-143, 1996.
+
+[4] A. C. Hindmarsh, P. N. Brown, K. E. Grant, S. L. Lee, R. Serban,
+ D. E. Shumaker, and C. S. Woodward, "SUNDIALS, Suite of Nonlinear and
+ Differential/Algebraic Equation Solvers," ACM Trans. Math. Softw.,
+ 31(3), pp. 363-396, 2005.
+
+
+D. Releases
+-----------
+
+v. 2.7.0 - Mar. 2012
+v. 2.6.0 - May 2009
+v. 2.5.0 - Nov. 2006
+v. 2.4.0 - Mar. 2006
+v. 2.3.0 - Apr. 2005
+v. 2.2.2 - Mar. 2005
+v. 2.2.1 - Jan. 2005
+v. 2.2.0 - Dec. 2004
+v. 2.0 - Jul. 2002 (first SUNDIALS release)
+v. 1.0 - Mar. 2002 (CVODE and PVODE combined)
+v. 1.0 (PVODE) - Jul. 1997 (date written)
+v. 1.0 (CVODE) - Sep. 1994 (date written)
+
+
+E. Revision History
+-------------------
+
+v. 2.6.0 (May 2009) ---> v. 2.7.0 (Mar. 2012)
+---------------------------------------------
+
+- Bug fixes
+ - in CVSetTqBDF, the logic was changed to avoid a divide by zero.
+ - after the solver memory is created, it is set to zero before being filled.
+ - in each linear solver interface function, the linear solver memory is
+ freed on an error return, and the **Free function now includes a line
+ setting to NULL the main memory pointer to the linear solver memory.
+ - in rootfinding functions CVRcheck1/CVRcheck2, when an exact zero is found,
+ the array glo at the left endpoint is adjusted instead of shifting tlo.
+
+- Changes to user interface
+ - One significant design change was made with this release: The problem
+ size and its relatives, bandwidth parameters, related internal indices,
+ pivot arrays, and the optional output lsflag, have all been
+ changed from type int to type long int, except for the
+ problem size and bandwidths in user calls to routines specifying
+ BLAS/LAPACK routines for the dense/band linear solvers. The function
+ NewIntArray is replaced by a pair NewIntArray/NewLintArray,
+ for int and long int arrays, respectively.
+ - in the installation files, we modified the treatment of the macro
+ SUNDIALS_USE_GENERIC_MATH, so that the parameter GENERIC_MATH_LIB
+ is either defined (with no value) or not defined.
+
+v. 2.5.0 (Nov. 2006) ---> v. 2.6.0 (May 2009)
+---------------------------------------------
+
+- New features
+ - added a new linear solver module based on Blas + Lapack for
+ both dense and banded matrices.
+ - added optional input to specify which direction of zero-crossing
+ is to be monitored while performing root-finding. The root information
+ array iroots (returned by CVodeGetRootInfo) also encodes the
+ direction of zero-crossing.
+
+- Bug fixes
+ - in the rootfinding algorithm, fixed a bug resulting in unnecessary
+ evaluations of the root functions after reinitialization of the
+ solver right after a return at a root.
+ - in the initial step size calculation, restrict h based on tstop.
+ - modified the setting and use of the tq[] array. Now tq[i] (i = 1,2,3)
+ are defined to be the reciprocals of what they were before. This
+ eliminates a rare crash that can occur with xistar_inv = 0.
+
+- Changes to user interface
+ - renamed all **Malloc functions to **Init
+ - tolerances are now specified through separate functions instead of
+ the initialization functions CVodeInit (former CVodeMalloc) and
+ CVodeReInit. Depending on the tolerance type, one of 3 functions
+ must be called before the first call to CVode.
+ - removed function inputs from argument lists of all re-initialization
+ functions.
+ - all user-supplied functions now receive the same pointer to user data
+ (instead of having different ones for the system evaluation, Jacobian
+ information functions, etc.).
+ - removed CV_NORMAL_TSTOP and CV_ONE_STEP_TSTOP named constants for the
+ itask argument to CVode. A tstop value is now both set and activated
+ through CVodeSetStopTime. Once tstop is reached it is also deactivated.
+ A new value can be then specified by calling again CVodeSetStopTime.
+ - common functionality for all direct linear solvers (dense, band, and
+ the new Lapack solver) has been collected into the DLS (Direct Linear
+ Solver) module, similar to the SPILS module for the iterative linear
+ solvers. All optional input and output functions for these linear
+ solver now have the prefix 'CVDls'. In addition, in order to include
+ the new Lapack-based linear solver, all dimensions for these linear
+ solvers (problem sizes, bandwidths, etc) are now of type 'int'
+ (instead of 'long int').
+ - the initialization functions for the two preconditioner modules,
+ CVBANDPRE and CVBBDPRE were renamed ***Init (from ***Alloc) and they
+ do not return a pointer to preconditioner memory anymore. Instead,
+ all preconditioner module-related functions are now called with
+ the main solver memory pointer as their first argument. When using
+ one of these two modules, there is no need to use special functions
+ to attach one of the SPILS linear solvers (instead use one of
+ CVSpgmr, CVSpbcg, or CVSptfqmr). Moreover, there is no need to call
+ a memory deallocation function for the preconditioner module.
+ - changed names CVSpilsSetDelt and delt to CVSpilsSetEpsLin and eplifac.
+ - added the error return CV_RTFUNC_FAIL.
+ - changes corresponding to the above were made to the FCMIX interface.
+
+
+v. 2.4.0 (Mar. 2006) ---> v. 2.5.0 (Nov. 2006)
+----------------------------------------------
+
+- Bug fixes
+ - added a roundoff factor when testing whether tn was just returned
+ (in root finding) to prevent an unnecessary return.
+ - fixed wrong logic in final stopping tests: now we check if
+ tout was reached before checking if tstop was reached.
+
+- Changes related to the build system
+ - reorganized source tree: header files in ${srcdir}/include/cvode,
+ source files in ${srcdir}/src/cvode, fcmix source files in
+ ${srcdir}/src/cvode/fcmix, examples in ${srcdir}/examples/cvode
+ - exported header files are installed unde ${includedir}/cvode
+
+- Changes to user interface
+ - all included header files use relative paths from ${includedir}
+
+v. 2.3.0 (Apr. 2005) ---> v. 2.4.0 (Mar. 2006)
+----------------------------------------------
+
+- New features
+ - added CVSPBCG interface module to allow CVODE to interface with the
+ shared SPBCG (scaled preconditioned Bi-CGSTAB) linear solver module.
+ - added CVSPTFQMR interface module to allow CVODE to interface with
+ the shared SPTFQMR (scaled preconditioned TFQMR) linear solver module.
+ - added support for SPBCG and SPTFQMR to the CVBBDPRE and CVBANDPRE
+ preconditioner modules.
+ - added support for interpreting failures in user-supplied functions.
+
+- Changes to user interface
+ - changed argument of CVodeFree, CVBandPrecFree, and CVBBDPrecFree to
+ be the address of the respective memory block pointer, so that its
+ NULL value is propagated back to the calling function.
+ - added CVSPBCG module which defines appropriate CVSpbcg* functions to
+ allow CVODE to interface with the shared SPBCG linear solver module.
+ - added CVBBDSpbcg function to CVBBDPRE module and CVBPSpbcg function to
+ CVBANDPRE module to support SPBCG linear solver module.
+ - added CVBBDSptfqmr function to CVBBDPRE module and CVBPSptfqmr function to
+ CVBANDPRE module to support SPTFQMR linear solver module.
+ - changed function type names (not the actual definition) to accomodate
+ all the Scaled Preconditioned Iterative Linear Solvers now available:
+ CVSpgmrJactimesVecFn -> CVSpilsJacTimesVecFn
+ CVSpgmrPrecSetupFn -> CVSpilsPrecSetupFn
+ CVSpgmrPrecSolveFn -> CVSpilsPrecSolveFn
+ - changed function types so that all user-supplied functions return
+ an integer flag (not all of them currently used).
+ - changed some names for CVBBDPRE and CVBANDPRE function outputs
+ - added option for user-supplied error handler function.
+ - renamed all exported header files (except for cvode.h, all header files
+ have the prefix 'cvode_')
+ - changed naming scheme for CVODE examples
+
+- Changes to the FCVODE module
+ - added support for CVSPBCG/SPBCG (added FCV*SPBCG* functions).
+ - added support for CVSPTFQMR/SPTFQMR (added FCV*SPTFQMR* functions).
+ - optional inputs are now set using routines FCVSETIIN (integer inputs)
+ and FCVSETRIN (real inputs) through pairs key-value. Optional outputs
+ are still obtained from two arrays (IOUT and ROUT), owned by the user
+ and passed as arguments to FCVMALLOC. Note that the argument OPTIN
+ was removed from FCVMALLOC.
+ - changed the prototypes of user-supplied functions so that they all
+ return an error flag as their last argument (not all of them currently used).
+ - the arguments OPTIN, IOPT, and ROPT were removed from FCVREINIT
+
+- Changes related to the build system
+ - updated configure script and Makefiles for Fortran examples to avoid C++
+ compiler errors (now use CC and MPICC to link only if necessary)
+ - the main CVODE header file (cvode.h) is still exported to the install include
+ directory. However, all other CVODE header files are exported into a 'cvode'
+ subdirectory of the install include directory.
+ - the CVODE library now contains all shared object files (there is no separate
+ libsundials_shared library anymore)
+
+v. 2.2.2 (Mar. 2005) ---> v. 2.3.0 (Apr. 2005)
+----------------------------------------------
+
+- New features
+ - added option for user-provided error weight computation function
+ (of type CVEwtFn specified through CVodeSetEwtFn).
+
+- Changes to user interface
+ - CVODE now stores tolerances through values rather than references
+ (to resolve potential scoping issues).
+ - CVODE now passes information back to the user through values rather
+ than references (error weights, estimated local errors, root info)
+ - CVodeMalloc, CVodeReInit, CVodeSetTolerances: added option itol=CV_WF
+ to indicate user-supplied function for computing the error weights;
+ reltol is now declared as realtype. Note that it is now illegal to call
+ CVodeSetTolerances before CVodeMalloc. It is now legal to deallocate
+ the absolute tolerance N_Vector right after its use.
+ - CVodeGetErrorWeights: the user is now responsible for allocating space
+ for the N_Vector in which error weights will be copied.
+ - CVodeGetEstLocalErrors: the user is now responsible for allocating space
+ for the N_Vector in which estimated local errors will be copied.
+ - CVodeGetRootInfo: the user is now responsible for allocating space
+ for the int array in which root information will be copied.
+ - Passing a value of 0 for the maximum step size, the minimum step
+ size, or for maxsteps results in the solver using the corresponding
+ default value (infinity, 0, 500, respectively)
+ - Several optional input functions were combined into a single one
+ (CVodeRootInit and CvodeSetGdata, CVDenseSetJacFn and CVDenseSetJacData,
+ CVBandSetJacFn and CVBandSetJacData, CVSpgmrSetPrecSolveFn and
+ CVSpgmrSetPrecSetFn and CVSpgmrSetPrecData, CVSpgmrSetJacTimesVecFn and
+ CVSpgmrSetJacData).
+
+- Changes to the FCVODE module:
+ - Added option for user-supplied error weight computation subroutine
+ (FCVEWT). Use FCVEWTSET to indicate that FCVEWT is provided.
+ - Due to the changes to the main solver, if FCVPSOL is provided then
+ FCVPSET must also be defined, even if it is empty.
+
+v. 2.2.1 (Jan. 2005) ---> v. 2.2.2 (Mar. 2005)
+----------------------------------------------
+
+- Bug fixes
+ - fixed bug in CVode function: Initial setting of tretlast = *tret = tn removed
+ (correcting erroneous behavior at first call to CVRcheck3).
+ - removed redundant setting of tretlast = *tret = tn at CLOSE_ROOTS return from CVode.
+ - modified FCMIX files to avoid C++ compiler errors
+ - changed implicit type conversion to explicit in check_flag() routine in
+ examples to avoid C++ compiler errors
+
+- Changes to documentation
+ - added section with numerical values of all input and output solver constants
+ - added more detailed notes on the type of absolute tolerances
+ - added more details on ownership of memory for the array returned by CVodeGetRootInfo
+ - corrected/added descriptions of error returns.
+ - added description of --with-mpi-flags option
+
+- Changes related to the build system
+ - fixed autoconf-related bug to allow configuration with the PGI Fortran compiler
+ - modified to use customized detection of the Fortran name mangling scheme
+ (autoconf's AC_F77_WRAPPERS routine is problematic on some platforms)
+ - added --with-mpi-flags as a configure option to allow user to specify
+ MPI-specific flags
+ - updated Makefiles for Fortran examples to avoid C++ compiler errors (now use
+ CC and MPICC to link)
+
+v. 2.2.0 (Dec. 2004) ---> v. 2.2.1 (Jan. 2005)
+----------------------------------------------
+
+- Changes related to the build system
+ - changed order of compiler directives in header files to avoid compilation
+ errors when using a C++ compiler.
+
+v. 2.0 (Jul. 2002) ---> v. 2.2.0 (Dec. 2004)
+--------------------------------------------
+
+- New features
+ - added option to specify a value of the independent variable (time)
+ past which the integration is never to proceed.
+ - added rootfinding capabilities.
+ - added option to disable all error messages.
+
+- Changes related to the NVECTOR module (see also file sundials/shared/README)
+ - removed machEnv, redefined table of vector operations (now contained
+ in the N_Vector structure itself).
+ - all CVODE functions create new N_Vector variables through cloning, using
+ an N_Vector passed by the user as a template.
+
+- Changes to type names and CVODE constants
+ - removed type 'integertype'; instead use int or long int, as appropriate.
+ - restructured the list of return values from the various CVODE functions.
+ - changed all CVODE constants (inputs and return values) to have the
+ prefix 'CV_' (e.g. CV_SUCCESS).
+ - renamed various function types to have the prefix 'CV' (e.g. CVRhsFn).
+
+- Changes to optional input/ouput
+ - added CVodeSet* and CVodeGet* functions for optional inputs/outputs,
+ replacing the arrays iopt and ropt.
+ - added new optional inputs (e.g. maximum number of Newton iterations,
+ maximum number of convergence failures, etc).
+ - the value of the last return flag from any function within a linear
+ solver module can be obtained as an optional output (e.g. CVDenseGetLastFlag).
+
+- Changes to user-callable functions
+ - added new function CVodeCreate which initializes the CVODE solver
+ object and returns a pointer to the CVODE memory block.
+ - removed N (problem size) from all functions except the initialization
+ functions for the direct linear solvers (CVDense and CVBand).
+ - shortened argument lists of most CVODE functions (the arguments that
+ were dropped can now be specified through CVodeSet* functions).
+ - removed reinitialization functions for band/dense/SPGMR linear
+ solvers (same functionality can be obtained using CV*Set* functions).
+ - in CVBBDPRE, added a new function, CVBBDSpgmr to initialize the
+ SPGMR linear solver with the BBD preconditioner.
+ - function names changed in CVBANDPRE and CVBBDPRE for uniformity.
+
+- Changes to user-supplied functions
+ - removed N (probem dimension) from argument lists.
+ - shortened argument lists for user dense/band/SPGMR Jacobian routines.
+ (Data needed to do difference quotients is accessible in other ways.)
+ - in CVSPGMR, shortened argument lists for user preconditioner functions.
+
+- Changes to the FCVODE module
+ - revised to use underscore and precision flags at compile time (from
+ configure); example sources are preprocessed accordingly.
+ - reorganized FCVODE into fewer files.
+ - added tstop options, and interfaces to CVBANDPRE and rootfinding features.
+ - use CV*Set* and CV*Get* functions from CVODE (although the optional I/O
+ is still communicated to the user of FCVODE through arrays IOPT and ROPT).
+ - added new optional inputs and outputs (e.g.tstop, nlscoef, maxnef, maxcor,
+ maxncf, etc.) and rearranged locations in IOPT and ROPT for uniformity.
+
+
+Summary of previous revisions (YYYYMMDD) (significant revisions only)
+---------------------------------------------------------------------
+
+Combined CVODE package (Mar. 2002 - Jul. 2002)
+-----------------------------------------------
+
+20020313 Modified to work with new NVECTOR abstraction.
+ Changed name PVBBDPRE to CVBBDPRE, etc.
+20020321 Revisions throughout to reflect usage changes for NVECTOR modules.
+ Changed dense/band backsolve argument b type from N_Vector to real*.
+20020328 In FCVODE, added interfaces to dense/band linear solvers.
+20020626 Changed type names real/integer to realtype/integertype.
+
+PVODE (Jul. 1995 - Mar. 2002)
+-----------------------------
+
+19950726 DATE WRITTEN; MPI version of VECTOR module written, creating
+ MPI_PVODE; makefiles written with defs. specific to IBM-SP.
+19950929 Formed package directory structure; added Cray-T3D defs. to Makefiles.
+19970219 FPVODE package of Fortran/C interfaces written, with examples.
+19970724 Wrote preconditioner module BBDPRE and Fortran/C interface.
+19970811 Type names changed to LLNL_FLOAT etc.
+19970813 Changed first FFUN arg. in FPVODE to local length NLOC.
+19971103 Added argc,argv to PVInitMPI call list; removed ICOMM
+ argument to FPVINITMPI (pass MPI_COMM_WORLD).
+19971201 Name changes: PVInitMPI/PVFreeMPI to PVecInitMPI/PVecFreeMPI.
+19971208 Added optional argument dqrely to BBDPRE.
+19971217 Revised FPVODE to use name mappings via parameters in fcmixpar.h.
+19980120 Name changes: VECTOR to NVECTOR etc.
+19980206 Name changes: BBDPRE to PVBBDPRE, FFUN to PVFUN, etc.
+19980508 Wrappers on header files for C++ use; type bool changed to boole.
+19980923 In PVBBDPRE and Fortran interface, added two half-bandwidth arguments.
+20000316 SPGMR module modified for correct treatment of scalings.
+ added new routine CVReInit for re-initialization of CVODE.
+20000320 In NVECTOR module: removed comm = NULL option in PVecInitMPI.
+20000321 Added interface FPVREINIT, and expanded diagkf example.
+20000719 Fixed memory leak bugs in CVReInit and FPVREINIT.
+20000808 Fixed bug in N_VMin routine.
+20011114 Added option for stability limit detection algorithm STALD.
+20011220 Default type 'integer' changed to 'long int' in llnltyps.h.
+20011220 Optional input ropt[HMAX] examined on every call to CVode.
+20011221 Optional input iopt[MXHNIL] = -1 means no t+h=t messages.
+20011228 Added arguments to CVSpgmr: jtimes (user J*v routine), jac_data.
+ Added optional jtimes to FPVODE. Revised examples accordingly.
+20020114 Linear solver modules reorganized: specification routines
+ CVDiag and CVSpgmr perform malloc operations and return a
+ completion flag. Re-use of linear solver memory is allowed if
+ linear solver choice and parameters are unchanged. Fortran
+ interface routines modified analogously. All examples
+ modified to receive and test new return flag.
+20020301 Added CVReInitSpgmr routine to CVSPGMR module, and added Fortran
+ interfaces to it. Revised cvdemk and pvdiagkf accordingly.
+20020306 Added PVReInitBBD routine to PVBBDPRE, and added Fortran interface
+ to it. Revised pvkxb and pvidagkbf examples accordingly.
+
+CVODE (1993 - Mar. 2002)
+------------------------
+
+1993-94 DATE WRITTEN. First released 2 September 1994.
+19970811 Type names changed to LLNL_FLOAT etc.
+19980120 Name changes: VECTOR to NVECTOR etc.
+19980508 Wrappers on header files for C++ use; type bool changed to boole.
+20000316 SPGMR module modified for correct treatment of scalings.
+ Added CVODE re-initialization routine CVReInit.
+20000323 Added band preconditioner module CVBANDPRE.
+20000719 Fixed memory leak bugs in CVReInit.
+20000808 Fixed bug in N_VMin routine.
+20011114 Added option for stability limit detection algorithm STALD.
+20011115 Reorganized DENSE module, with smalldense.* files separate.
+20011220 Default type 'integer' changed to 'long int' in llnltyps.h.
+20011220 Optional input ropt[HMAX] examined on every call to CVode.
+20011221 Optional input iopt[MXHNIL] = -1 means no t+h=t messages.
+20011228 Added arguments to CVSpgmr: jtimes (user J*v routine), jac_data.
+20020114 Linear solver modules reorganized: linear solver specification
+ routines perform malloc operations and return a completion flag.
+ Re-use of linear solver memory is allowed if linear solver choice
+ and parameters are unchanged. All examples modified accordingly.
+20020301 Added ReInit routine to CVDENSE, CVBAND, CVSPGMR modules.
+20020305 Added CVReInitBandPre routine to CVBANDPRE module.
+
+
diff --git a/src/cvode/cvode.c b/src/cvode/cvode.c
new file mode 100644
index 0000000..466a6fe
--- /dev/null
+++ b/src/cvode/cvode.c
@@ -0,0 +1,4191 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.24 $
+ * $Date: 2012/03/06 21:58:36 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh, Radu Serban,
+ * and Dan Shumaker @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * This is the implementation file for the main CVODE integrator.
+ * It is independent of the CVODE linear solver in use.
+ * -----------------------------------------------------------------
+ */
+
+/*=================================================================*/
+/* Import Header Files */
+/*=================================================================*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+
+#include "cvode_impl.h"
+#include <sundials/sundials_math.h>
+#include <sundials/sundials_types.h>
+
+/*=================================================================*/
+/* Macros */
+/*=================================================================*/
+
+/* Macro: loop */
+#define loop for(;;)
+
+/*=================================================================*/
+/* CVODE Private Constants */
+/*=================================================================*/
+
+#define ZERO RCONST(0.0) /* real 0.0 */
+#define TINY RCONST(1.0e-10) /* small number */
+#define TENTH RCONST(0.1) /* real 0.1 */
+#define POINT2 RCONST(0.2) /* real 0.2 */
+#define FOURTH RCONST(0.25) /* real 0.25 */
+#define HALF RCONST(0.5) /* real 0.5 */
+#define ONE RCONST(1.0) /* real 1.0 */
+#define TWO RCONST(2.0) /* real 2.0 */
+#define THREE RCONST(3.0) /* real 3.0 */
+#define FOUR RCONST(4.0) /* real 4.0 */
+#define FIVE RCONST(5.0) /* real 5.0 */
+#define TWELVE RCONST(12.0) /* real 12.0 */
+#define HUN RCONST(100.0) /* real 100.0 */
+
+/*=================================================================*/
+/* CVODE Routine-Specific Constants */
+/*=================================================================*/
+
+/*
+ * Control constants for lower-level functions used by CVStep
+ * ----------------------------------------------------------
+ *
+ * CVHin return values:
+ * CV_SUCCESS
+ * CV_RHSFUNC_FAIL
+ * CV_TOO_CLOSE
+ *
+ * CVStep control constants:
+ * DO_ERROR_TEST
+ * PREDICT_AGAIN
+ *
+ * CVStep return values:
+ * CV_SUCCESS,
+ * CV_LSETUP_FAIL, CV_LSOLVE_FAIL,
+ * CV_RHSFUNC_FAIL, CV_RTFUNC_FAIL
+ * CV_CONV_FAILURE, CV_ERR_FAILURE,
+ * CV_FIRST_RHSFUNC_ERR
+ *
+ * CVNls input nflag values:
+ * FIRST_CALL
+ * PREV_CONV_FAIL
+ * PREV_ERR_FAIL
+ *
+ * CVNls return values:
+ * CV_SUCCESS,
+ * CV_LSETUP_FAIL, CV_LSOLVE_FAIL, CV_RHSFUNC_FAIL,
+ * CONV_FAIL, RHSFUNC_RECVR
+ *
+ * CVNewtonIteration return values:
+ * CV_SUCCESS,
+ * CV_LSOLVE_FAIL, CV_RHSFUNC_FAIL
+ * CONV_FAIL, RHSFUNC_RECVR,
+ * TRY_AGAIN
+ *
+ */
+
+#define DO_ERROR_TEST +2
+#define PREDICT_AGAIN +3
+
+#define CONV_FAIL +4
+#define TRY_AGAIN +5
+
+#define FIRST_CALL +6
+#define PREV_CONV_FAIL +7
+#define PREV_ERR_FAIL +8
+
+#define RHSFUNC_RECVR +9
+
+/*
+ * Control constants for lower-level rootfinding functions
+ * -------------------------------------------------------
+ *
+ * CVRcheck1 return values:
+ * CV_SUCCESS,
+ * CV_RTFUNC_FAIL,
+ * CVRcheck2 return values:
+ * CV_SUCCESS
+ * CV_RTFUNC_FAIL,
+ * CLOSERT
+ * RTFOUND
+ * CVRcheck3 return values:
+ * CV_SUCCESS
+ * CV_RTFUNC_FAIL,
+ * RTFOUND
+ * CVRootfind return values:
+ * CV_SUCCESS
+ * CV_RTFUNC_FAIL,
+ * RTFOUND
+ */
+
+#define RTFOUND +1
+#define CLOSERT +3
+
+/*
+ * Control constants for tolerances
+ * --------------------------------
+ */
+
+#define CV_NN 0
+#define CV_SS 1
+#define CV_SV 2
+#define CV_WF 3
+
+/*
+ * Algorithmic constants
+ * ---------------------
+ *
+ * CVodeGetDky and CVStep
+ *
+ * FUZZ_FACTOR
+ *
+ * CVHin
+ *
+ * HLB_FACTOR
+ * HUB_FACTOR
+ * H_BIAS
+ * MAX_ITERS
+ *
+ * CVodeCreate
+ *
+ * CORTES
+ *
+ * CVStep
+ *
+ * THRESH
+ * ETAMX1
+ * ETAMX2
+ * ETAMX3
+ * ETAMXF
+ * ETAMIN
+ * ETACF
+ * ADDON
+ * BIAS1
+ * BIAS2
+ * BIAS3
+ * ONEPSM
+ *
+ * SMALL_NST nst > SMALL_NST => use ETAMX3
+ * MXNCF max no. of convergence failures during one step try
+ * MXNEF max no. of error test failures during one step try
+ * MXNEF1 max no. of error test failures before forcing a reduction of order
+ * SMALL_NEF if an error failure occurs and SMALL_NEF <= nef <= MXNEF1, then
+ * reset eta = MIN(eta, ETAMXF)
+ * LONG_WAIT number of steps to wait before considering an order change when
+ * q==1 and MXNEF1 error test failures have occurred
+ *
+ * CVNls
+ *
+ * NLS_MAXCOR maximum no. of corrector iterations for the nonlinear solver
+ * CRDOWN constant used in the estimation of the convergence rate (crate)
+ * of the iterates for the nonlinear equation
+ * DGMAX iter == CV_NEWTON, |gamma/gammap-1| > DGMAX => call lsetup
+ * RDIV declare divergence if ratio del/delp > RDIV
+ * MSBP max no. of steps between lsetup calls
+ *
+ */
+
+
+#define FUZZ_FACTOR RCONST(100.0)
+
+#define HLB_FACTOR RCONST(100.0)
+#define HUB_FACTOR RCONST(0.1)
+#define H_BIAS HALF
+#define MAX_ITERS 4
+
+#define CORTES RCONST(0.1)
+
+#define THRESH RCONST(1.5)
+#define ETAMX1 RCONST(10000.0)
+#define ETAMX2 RCONST(10.0)
+#define ETAMX3 RCONST(10.0)
+#define ETAMXF RCONST(0.2)
+#define ETAMIN RCONST(0.1)
+#define ETACF RCONST(0.25)
+#define ADDON RCONST(0.000001)
+#define BIAS1 RCONST(6.0)
+#define BIAS2 RCONST(6.0)
+#define BIAS3 RCONST(10.0)
+#define ONEPSM RCONST(1.000001)
+
+#define SMALL_NST 10
+#define MXNCF 10
+#define MXNEF 7
+#define MXNEF1 3
+#define SMALL_NEF 2
+#define LONG_WAIT 10
+
+#define NLS_MAXCOR 3
+#define CRDOWN RCONST(0.3)
+#define DGMAX RCONST(0.3)
+
+#define RDIV TWO
+#define MSBP 20
+
+/*=================================================================*/
+/* Private Helper Functions Prototypes */
+/*=================================================================*/
+
+static booleantype CVCheckNvector(N_Vector tmpl);
+
+static int CVInitialSetup(CVodeMem cv_mem);
+
+static booleantype CVAllocVectors(CVodeMem cv_mem, N_Vector tmpl);
+static void CVFreeVectors(CVodeMem cv_mem);
+
+static int CVEwtSetSS(CVodeMem cv_mem, N_Vector ycur, N_Vector weight);
+static int CVEwtSetSV(CVodeMem cv_mem, N_Vector ycur, N_Vector weight);
+
+static int CVHin(CVodeMem cv_mem, realtype tout);
+static realtype CVUpperBoundH0(CVodeMem cv_mem, realtype tdist);
+static int CVYddNorm(CVodeMem cv_mem, realtype hg, realtype *yddnrm);
+
+static int CVStep(CVodeMem cv_mem);
+
+static int CVsldet(CVodeMem cv_mem);
+
+static void CVAdjustParams(CVodeMem cv_mem);
+static void CVAdjustOrder(CVodeMem cv_mem, int deltaq);
+static void CVAdjustAdams(CVodeMem cv_mem, int deltaq);
+static void CVAdjustBDF(CVodeMem cv_mem, int deltaq);
+static void CVIncreaseBDF(CVodeMem cv_mem);
+static void CVDecreaseBDF(CVodeMem cv_mem);
+
+static void CVRescale(CVodeMem cv_mem);
+
+static void CVPredict(CVodeMem cv_mem);
+
+static void CVSet(CVodeMem cv_mem);
+static void CVSetAdams(CVodeMem cv_mem);
+static realtype CVAdamsStart(CVodeMem cv_mem, realtype m[]);
+static void CVAdamsFinish(CVodeMem cv_mem, realtype m[], realtype M[], realtype hsum);
+static realtype CVAltSum(int iend, realtype a[], int k);
+static void CVSetBDF(CVodeMem cv_mem);
+static void CVSetTqBDF(CVodeMem cv_mem, realtype hsum, realtype alpha0,
+ realtype alpha0_hat, realtype xi_inv, realtype xistar_inv);
+
+static int CVNls(CVodeMem cv_mem, int nflag);
+static int CVNlsFunctional(CVodeMem cv_mem);
+static int CVNlsNewton(CVodeMem cv_mem, int nflag);
+static int CVNewtonIteration(CVodeMem cv_mem);
+
+static int CVHandleNFlag(CVodeMem cv_mem, int *nflagPtr, realtype saved_t,
+ int *ncfPtr);
+
+static void CVRestore(CVodeMem cv_mem, realtype saved_t);
+
+static int CVDoErrorTest(CVodeMem cv_mem, int *nflagPtr,
+ realtype saved_t, int *nefPtr, realtype *dsmPtr);
+
+static void CVCompleteStep(CVodeMem cv_mem);
+
+static void CVPrepareNextStep(CVodeMem cv_mem, realtype dsm);
+static void CVSetEta(CVodeMem cv_mem);
+static realtype CVComputeEtaqm1(CVodeMem cv_mem);
+static realtype CVComputeEtaqp1(CVodeMem cv_mem);
+static void CVChooseEta(CVodeMem cv_mem);
+static void CVBDFStab(CVodeMem cv_mem);
+
+static int CVHandleFailure(CVodeMem cv_mem,int flag);
+
+static int CVRcheck1(CVodeMem cv_mem);
+static int CVRcheck2(CVodeMem cv_mem);
+static int CVRcheck3(CVodeMem cv_mem);
+static int CVRootfind(CVodeMem cv_mem);
+
+/*
+ * =================================================================
+ * EXPORTED FUNCTIONS IMPLEMENTATION
+ * =================================================================
+ */
+
+/*
+ * CVodeCreate
+ *
+ * CVodeCreate creates an internal memory block for a problem to
+ * be solved by CVODE.
+ * If successful, CVodeCreate returns a pointer to the problem memory.
+ * This pointer should be passed to CVodeInit.
+ * If an initialization error occurs, CVodeCreate prints an error
+ * message to standard err and returns NULL.
+ */
+
+void *CVodeCreate(int lmm, int iter)
+{
+ int maxord;
+ CVodeMem cv_mem;
+
+ /* Test inputs */
+
+ if ((lmm != CV_ADAMS) && (lmm != CV_BDF)) {
+ CVProcessError(NULL, 0, "CVODE", "CVodeCreate", MSGCV_BAD_LMM);
+ return(NULL);
+ }
+
+ if ((iter != CV_FUNCTIONAL) && (iter != CV_NEWTON)) {
+ CVProcessError(NULL, 0, "CVODE", "CVodeCreate", MSGCV_BAD_ITER);
+ return(NULL);
+ }
+
+ cv_mem = NULL;
+ cv_mem = (CVodeMem) malloc(sizeof(struct CVodeMemRec));
+ if (cv_mem == NULL) {
+ CVProcessError(NULL, 0, "CVODE", "CVodeCreate", MSGCV_CVMEM_FAIL);
+ return(NULL);
+ }
+
+ /* Zero out cv_mem */
+ memset(cv_mem, 0, sizeof(struct CVodeMemRec));
+
+ maxord = (lmm == CV_ADAMS) ? ADAMS_Q_MAX : BDF_Q_MAX;
+
+ /* copy input parameters into cv_mem */
+ cv_mem->cv_lmm = lmm;
+ cv_mem->cv_iter = iter;
+
+ /* Set uround */
+ cv_mem->cv_uround = UNIT_ROUNDOFF;
+
+ /* Set default values for integrator optional inputs */
+ 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_efun = NULL;
+ cv_mem->cv_e_data = NULL;
+ cv_mem->cv_ehfun = CVErrHandler;
+ cv_mem->cv_eh_data = cv_mem;
+ cv_mem->cv_errfp = stderr;
+ 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_hin = ZERO;
+ cv_mem->cv_hmin = HMIN_DEFAULT;
+ cv_mem->cv_hmax_inv = HMAX_INV_DEFAULT;
+ cv_mem->cv_tstopset = FALSE;
+ 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;
+ cv_mem->cv_ghi = NULL;
+ cv_mem->cv_grout = NULL;
+ cv_mem->cv_iroots = NULL;
+ cv_mem->cv_rootdir = NULL;
+ cv_mem->cv_gfun = NULL;
+ cv_mem->cv_nrtfn = 0;
+ cv_mem->cv_gactive = NULL;
+ cv_mem->cv_mxgnull = 1;
+
+ /* Set the saved value qmax_alloc */
+
+ cv_mem->cv_qmax_alloc = maxord;
+
+ /* Initialize lrw and liw */
+
+ cv_mem->cv_lrw = 58 + 2*L_MAX + NUM_TESTS;
+ cv_mem->cv_liw = 40;
+
+ /* No mallocs have been done yet */
+
+ cv_mem->cv_VabstolMallocDone = FALSE;
+ cv_mem->cv_MallocDone = FALSE;
+
+ /* Return pointer to CVODE memory block */
+
+ return((void *)cv_mem);
+}
+
+/*-----------------------------------------------------------------*/
+
+#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
+ *
+ * CVodeInit allocates and initializes memory for a problem. All
+ * problem inputs are checked for errors. If any error occurs during
+ * initialization, it is reported to the file whose file pointer is
+ * errfp and an error flag is returned. Otherwise, it returns CV_SUCCESS
+ */
+
+int CVodeInit(void *cvode_mem, CVRhsFn f, realtype t0, N_Vector y0)
+{
+ CVodeMem cv_mem;
+ booleantype nvectorOK, allocOK;
+ long int lrw1, liw1;
+ int i,k;
+
+ /* Check cvode_mem */
+
+ if (cvode_mem==NULL) {
+ CVProcessError(NULL, CV_MEM_NULL, "CVODE", "CVodeInit", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+ cv_mem = (CVodeMem) cvode_mem;
+
+ /* Check for legal input parameters */
+
+ if (y0==NULL) {
+ CVProcessError(cv_mem, CV_ILL_INPUT, "CVODE", "CVodeInit", MSGCV_NULL_Y0);
+ return(CV_ILL_INPUT);
+ }
+
+ if (f == NULL) {
+ CVProcessError(cv_mem, CV_ILL_INPUT, "CVODE", "CVodeInit", MSGCV_NULL_F);
+ return(CV_ILL_INPUT);
+ }
+
+ /* Test if all required vector operations are implemented */
+
+ nvectorOK = CVCheckNvector(y0);
+ if(!nvectorOK) {
+ CVProcessError(cv_mem, CV_ILL_INPUT, "CVODE", "CVodeInit", MSGCV_BAD_NVECTOR);
+ return(CV_ILL_INPUT);
+ }
+
+ /* Set space requirements for one N_Vector */
+
+ if (y0->ops->nvspace != NULL) {
+ N_VSpace(y0, &lrw1, &liw1);
+ } else {
+ lrw1 = 0;
+ liw1 = 0;
+ }
+ cv_mem->cv_lrw1 = lrw1;
+ cv_mem->cv_liw1 = liw1;
+
+ /* Allocate the vectors (using y0 as a template) */
+
+ allocOK = CVAllocVectors(cv_mem, y0);
+ if (!allocOK) {
+ CVProcessError(cv_mem, CV_MEM_FAIL, "CVODE", "CVodeInit", MSGCV_MEM_FAIL);
+ return(CV_MEM_FAIL);
+ }
+
+ /* All error checking is complete at this point */
+
+ /* Copy the input parameters into CVODE state */
+
+ cv_mem->cv_f = f;
+ cv_mem->cv_tn = t0;
+
+ /* Set step parameters */
+
+ cv_mem->cv_q = 1;
+ cv_mem->cv_L = 2;
+ cv_mem->cv_qwait = cv_mem->cv_L;
+ cv_mem->cv_etamax = ETAMX1;
+
+ cv_mem->cv_qu = 0;
+ cv_mem->cv_hu = ZERO;
+ cv_mem->cv_tolsf = ONE;
+
+ /* Set the linear solver addresses to NULL.
+ (We check != NULL later, in CVode, if using CV_NEWTON.) */
+
+ cv_mem->cv_linit = NULL;
+ cv_mem->cv_lsetup = NULL;
+ cv_mem->cv_lsolve = NULL;
+ cv_mem->cv_lfree = NULL;
+ cv_mem->cv_lmem = NULL;
+
+ /* Initialize zn[0] in the history array */
+
+ N_VScale(ONE, y0, cv_mem->cv_zn[0]);
+
+ /* Initialize all the counters */
+
+ cv_mem->cv_nst = 0;
+ cv_mem->cv_nfe = 0;
+ cv_mem->cv_ncfn = 0;
+ cv_mem->cv_netf = 0;
+ cv_mem->cv_nni = 0;
+ cv_mem->cv_nsetups = 0;
+ cv_mem->cv_nhnil = 0;
+ cv_mem->cv_nstlp = 0;
+ cv_mem->cv_nscon = 0;
+ cv_mem->cv_nge = 0;
+
+ cv_mem->cv_irfnd = 0;
+
+ /* Initialize other integrator optional outputs */
+
+ cv_mem->cv_h0u = ZERO;
+ cv_mem->cv_next_h = ZERO;
+ cv_mem->cv_next_q = 0;
+
+ /* Initialize Stablilty Limit Detection data */
+ /* NOTE: We do this even if stab lim det was not
+ turned on yet. This way, the user can turn it
+ on at any time */
+
+ cv_mem->cv_nor = 0;
+ for (i = 1; i <= 5; i++)
+ for (k = 1; k <= 3; k++)
+ cv_mem->cv_ssdat[i-1][k-1] = ZERO;
+
+ /* Problem has been successfully initialized */
+
+ cv_mem->cv_MallocDone = TRUE;
+
+ return(CV_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+#define lrw1 (cv_mem->cv_lrw1)
+#define liw1 (cv_mem->cv_liw1)
+
+/*-----------------------------------------------------------------*/
+
+/*
+ * CVodeReInit
+ *
+ * CVodeReInit re-initializes CVODE's memory for a problem, assuming
+ * it has already been allocated in a prior CVodeInit call.
+ * All problem specification inputs are checked for errors.
+ * If any error occurs during initialization, it is reported to the
+ * file whose file pointer is errfp.
+ * The return value is CV_SUCCESS = 0 if no errors occurred, or
+ * a negative value otherwise.
+ */
+
+int CVodeReInit(void *cvode_mem, realtype t0, N_Vector y0)
+{
+ CVodeMem cv_mem;
+ int i,k;
+
+ /* Check cvode_mem */
+
+ if (cvode_mem==NULL) {
+ CVProcessError(NULL, CV_MEM_NULL, "CVODE", "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, "CVODE", "CVodeReInit", MSGCV_NO_MALLOC);
+ return(CV_NO_MALLOC);
+ }
+
+ /* Check for legal input parameters */
+
+ if (y0 == NULL) {
+ CVProcessError(cv_mem, CV_ILL_INPUT, "CVODE", "CVodeReInit", MSGCV_NULL_Y0);
+ return(CV_ILL_INPUT);
+ }
+
+ /* Copy the input parameters into CVODE state */
+
+ cv_mem->cv_tn = t0;
+
+ /* Set step parameters */
+
+ cv_mem->cv_q = 1;
+ cv_mem->cv_L = 2;
+ cv_mem->cv_qwait = cv_mem->cv_L;
+ cv_mem->cv_etamax = ETAMX1;
+
+ cv_mem->cv_qu = 0;
+ cv_mem->cv_hu = ZERO;
+ cv_mem->cv_tolsf = ONE;
+
+ /* Initialize zn[0] in the history array */
+
+ N_VScale(ONE, y0, cv_mem->cv_zn[0]);
+
+ /* Initialize all the counters */
+
+ cv_mem->cv_nst = 0;
+ cv_mem->cv_nfe = 0;
+ cv_mem->cv_ncfn = 0;
+ cv_mem->cv_netf = 0;
+ cv_mem->cv_nni = 0;
+ cv_mem->cv_nsetups = 0;
+ cv_mem->cv_nhnil = 0;
+ cv_mem->cv_nstlp = 0;
+ cv_mem->cv_nscon = 0;
+ cv_mem->cv_nge = 0;
+
+ cv_mem->cv_irfnd = 0;
+
+ /* Initialize other integrator optional outputs */
+
+ cv_mem->cv_h0u = ZERO;
+ cv_mem->cv_next_h = ZERO;
+ cv_mem->cv_next_q = 0;
+
+ /* Initialize Stablilty Limit Detection data */
+
+ cv_mem->cv_nor = 0;
+ for (i = 1; i <= 5; i++)
+ for (k = 1; k <= 3; k++)
+ cv_mem->cv_ssdat[i-1][k-1] = ZERO;
+
+ /* Problem has been successfully re-initialized */
+
+ return(CV_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+/*
+ * CVodeSStolerances
+ * CVodeSVtolerances
+ * CVodeWFtolerances
+ *
+ * These functions specify the integration tolerances. One of them
+ * MUST be called before the first call to CVode.
+ *
+ * CVodeSStolerances specifies scalar relative and absolute tolerances.
+ * CVodeSVtolerances specifies scalar relative tolerance and a vector
+ * absolute tolerance (a potentially different absolute tolerance
+ * for each vector component).
+ * CVodeWFtolerances specifies a user-provides function (of type CVEwtFn)
+ * which will be called to set the error weight vector.
+ */
+
+int CVodeSStolerances(void *cvode_mem, realtype reltol, realtype abstol)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ CVProcessError(NULL, CV_MEM_NULL, "CVODE", "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, "CVODE", "CVodeSStolerances", MSGCV_NO_MALLOC);
+ return(CV_NO_MALLOC);
+ }
+
+ /* Check inputs */
+
+ if (reltol < ZERO) {
+ CVProcessError(cv_mem, CV_ILL_INPUT, "CVODE", "CVodeSStolerances", MSGCV_BAD_RELTOL);
+ return(CV_ILL_INPUT);
+ }
+
+ if (abstol < ZERO) {
+ CVProcessError(cv_mem, CV_ILL_INPUT, "CVODE", "CVodeSStolerances", MSGCV_BAD_ABSTOL);
+ return(CV_ILL_INPUT);
+ }
+
+ /* Copy tolerances into memory */
+
+ cv_mem->cv_reltol = reltol;
+ cv_mem->cv_Sabstol = abstol;
+
+ cv_mem->cv_itol = CV_SS;
+
+ cv_mem->cv_user_efun = FALSE;
+ cv_mem->cv_efun = CVEwtSet;
+ cv_mem->cv_e_data = NULL; /* will be set to cvode_mem in InitialSetup */
+
+ return(CV_SUCCESS);
+}
+
+
+int CVodeSVtolerances(void *cvode_mem, realtype reltol, N_Vector abstol)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ CVProcessError(NULL, CV_MEM_NULL, "CVODE", "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, "CVODE", "CVodeSVtolerances", MSGCV_NO_MALLOC);
+ return(CV_NO_MALLOC);
+ }
+
+ /* Check inputs */
+
+ if (reltol < ZERO) {
+ CVProcessError(cv_mem, CV_ILL_INPUT, "CVODE", "CVodeSVtolerances", MSGCV_BAD_RELTOL);
+ return(CV_ILL_INPUT);
+ }
+
+ if (N_VMin(abstol) < ZERO) {
+ CVProcessError(cv_mem, CV_ILL_INPUT, "CVODE", "CVodeSVtolerances", MSGCV_BAD_ABSTOL);
+ return(CV_ILL_INPUT);
+ }
+
+ /* Copy tolerances into memory */
+
+ 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_reltol = reltol;
+ N_VScale(ONE, abstol, cv_mem->cv_Vabstol);
+
+ cv_mem->cv_itol = CV_SV;
+
+ cv_mem->cv_user_efun = FALSE;
+ cv_mem->cv_efun = CVEwtSet;
+ cv_mem->cv_e_data = NULL; /* will be set to cvode_mem in InitialSetup */
+
+ return(CV_SUCCESS);
+}
+
+
+int CVodeWFtolerances(void *cvode_mem, CVEwtFn efun)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ CVProcessError(NULL, CV_MEM_NULL, "CVODE", "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, "CVODE", "CVodeWFtolerances", MSGCV_NO_MALLOC);
+ return(CV_NO_MALLOC);
+ }
+
+ cv_mem->cv_itol = CV_WF;
+
+ cv_mem->cv_user_efun = TRUE;
+ cv_mem->cv_efun = efun;
+ cv_mem->cv_e_data = NULL; /* will be set to user_data in InitialSetup */
+
+ 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
+ *
+ * CVodeRootInit initializes a rootfinding problem to be solved
+ * during the integration of the ODE system. It loads the root
+ * function pointer and the number of root functions, and allocates
+ * workspace memory. The return value is CV_SUCCESS = 0 if no errors
+ * occurred, or a negative value otherwise.
+ */
+
+int CVodeRootInit(void *cvode_mem, int nrtfn, CVRootFn g)
+{
+ CVodeMem cv_mem;
+ int i, nrt;
+
+ /* Check cvode_mem pointer */
+ if (cvode_mem == NULL) {
+ CVProcessError(NULL, CV_MEM_NULL, "CVODE", "CVodeRootInit", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+ cv_mem = (CVodeMem) cvode_mem;
+
+ nrt = (nrtfn < 0) ? 0 : nrtfn;
+
+ /* If rerunning CVodeRootInit() with a different number of root
+ 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);
+ }
+
+ /* 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;
+ return(CV_SUCCESS);
+ }
+
+ /* If rerunning CVodeRootInit() with the same number of root functions
+ (not changing number of gfun components), then check if the root
+ function argument has changed */
+ /* If g != NULL then return as currently reserved memory resources
+ will suffice */
+ if (nrt == cv_mem->cv_nrtfn) {
+ if (g != 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, "CVODE", "CVodeRootInit", MSGCV_NULL_G);
+ return(CV_ILL_INPUT);
+ }
+ else {
+ gfun = g;
+ return(CV_SUCCESS);
+ }
+ }
+ else return(CV_SUCCESS);
+ }
+
+ /* Set variable values in CVode memory block */
+ cv_mem->cv_nrtfn = nrt;
+ if (g == NULL) {
+ CVProcessError(cv_mem, CV_ILL_INPUT, "CVODE", "CVodeRootInit", MSGCV_NULL_G);
+ return(CV_ILL_INPUT);
+ }
+ else gfun = g;
+
+ /* Allocate necessary memory and return */
+ glo = NULL;
+ glo = (realtype *) malloc(nrt*sizeof(realtype));
+ if (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;
+ 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;
+ 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;
+ 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;
+ 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;
+ 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;
+
+ /* Set default values for gactive (all active) */
+ for(i=0; i<nrt; i++) gactive[i] = TRUE;
+
+ lrw += 3*nrt;
+ 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)
+
+
+/*-----------------------------------------------------------------*/
+
+/*
+ * CVode
+ *
+ * This routine is the main driver of the CVODE package.
+ *
+ * It integrates over a time interval defined by the user, by calling
+ * CVStep to do internal time steps.
+ *
+ * The first time that CVode is called for a successfully initialized
+ * problem, it computes a tentative initial step size h.
+ *
+ * CVode supports two modes, specified by itask: CV_NORMAL, CV_ONE_STEP.
+ * In the CV_NORMAL mode, the solver steps until it reaches or passes tout
+ * and then interpolates to obtain y(tout).
+ * In the CV_ONE_STEP mode, it takes one internal step and returns.
+ */
+
+int CVode(void *cvode_mem, realtype tout, N_Vector yout,
+ realtype *tret, int itask)
+{
+ CVodeMem cv_mem;
+ long int nstloc;
+ int retval, hflag, kflag, istate, ir, ier, irfndp;
+ int ewtsetOK;
+ realtype troundoff, tout_hin, rh, nrm;
+ booleantype inactive_roots;
+
+ /*
+ * -------------------------------------
+ * 1. Check and process inputs
+ * -------------------------------------
+ */
+
+ /* Check if cvode_mem exists */
+ if (cvode_mem == NULL) {
+ CVProcessError(NULL, CV_MEM_NULL, "CVODE", "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, "CVODE", "CVode", MSGCV_NO_MALLOC);
+ return(CV_NO_MALLOC);
+ }
+
+ /* Check for yout != NULL */
+ if ((y = yout) == NULL) {
+ CVProcessError(cv_mem, CV_ILL_INPUT, "CVODE", "CVode", MSGCV_YOUT_NULL);
+ return(CV_ILL_INPUT);
+ }
+
+ /* Check for tret != NULL */
+ if (tret == NULL) {
+ CVProcessError(cv_mem, CV_ILL_INPUT, "CVODE", "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, "CVODE", "CVode", MSGCV_BAD_ITASK);
+ return(CV_ILL_INPUT);
+ }
+
+ if (itask == CV_NORMAL) toutc = tout;
+ taskc = itask;
+
+ /*
+ * ----------------------------------------
+ * 2. Initializations performed only at
+ * the first step (nst=0):
+ * - initial setup
+ * - initialize Nordsieck history array
+ * - compute initial step size
+ * - check for approach to tstop
+ * - check for approach to a root
+ * ----------------------------------------
+ */
+
+ if (nst == 0) {
+
+ ier = CVInitialSetup(cv_mem);
+ if (ier!= CV_SUCCESS) return(ier);
+
+ /* Call f at (t0,y0), set zn[1] = y'(t0),
+ 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++;
+ if (retval < 0) {
+ CVProcessError(cv_mem, CV_RHSFUNC_FAIL, "CVODE", "CVode", MSGCV_RHSFUNC_FAILED, tn);
+ return(CV_RHSFUNC_FAIL);
+ }
+ if (retval > 0) {
+ CVProcessError(cv_mem, CV_FIRST_RHSFUNC_ERR, "CVODE", "CVode", MSGCV_RHSFUNC_FIRST);
+ return(CV_FIRST_RHSFUNC_ERR);
+ }
+
+ /* Set initial h (from H0 or CVHin). */
+
+ h = hin;
+ if ( (h != ZERO) && ((tout-tn)*h < ZERO) ) {
+ CVProcessError(cv_mem, CV_ILL_INPUT, "CVODE", "CVode", MSGCV_BAD_H0);
+ return(CV_ILL_INPUT);
+ }
+ if (h == ZERO) {
+ tout_hin = tout;
+ if ( tstopset && (tout-tn)*(tout-tstop) > 0 ) tout_hin = tstop;
+ hflag = CVHin(cv_mem, tout_hin);
+ if (hflag != CV_SUCCESS) {
+ istate = CVHandleFailure(cv_mem, hflag);
+ return(istate);
+ }
+ }
+ rh = ABS(h)*hmax_inv;
+ if (rh > ONE) h /= rh;
+ if (ABS(h) < hmin) h *= hmin/ABS(h);
+
+ /* Check for approach to tstop */
+
+ if (tstopset) {
+ if ( (tstop - tn)*h < ZERO ) {
+ CVProcessError(cv_mem, CV_ILL_INPUT, "CVODE", "CVode", MSGCV_BAD_TSTOP, tstop, tn);
+ return(CV_ILL_INPUT);
+ }
+ if ( (tn + h - tstop)*h > ZERO )
+ h = (tstop - tn)*(ONE-FOUR*uround);
+ }
+
+ /* Scale zn[1] by h.*/
+
+ hscale = h;
+ h0u = h;
+ hprime = h;
+
+ N_VScale(h, zn[1], zn[1]);
+
+ /* Check for zeros of root function g at and near t0. */
+
+ if (nrtfn > 0) {
+
+ retval = CVRcheck1(cv_mem);
+
+ if (retval == CV_RTFUNC_FAIL) {
+ CVProcessError(cv_mem, CV_RTFUNC_FAIL, "CVODE", "CVRcheck1", MSGCV_RTFUNC_FAILED, tn);
+ return(CV_RTFUNC_FAIL);
+ }
+
+ }
+
+ } /* end of first call block */
+
+ /*
+ * ------------------------------------------------------
+ * 3. At following steps, perform stop tests:
+ * - check for root in last step
+ * - check if we passed tstop
+ * - check if we passed tout (NORMAL mode)
+ * - check if current tn was returned (ONE_STEP mode)
+ * - check if we are close to tstop
+ * (adjust step size if needed)
+ * -------------------------------------------------------
+ */
+
+ if (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*(ABS(tn) + ABS(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) {
+
+ irfndp = irfnd;
+
+ retval = CVRcheck2(cv_mem);
+
+ if (retval == CLOSERT) {
+ CVProcessError(cv_mem, CV_ILL_INPUT, "CVODE", "CVRcheck2", MSGCV_CLOSE_ROOTS, tlo);
+ return(CV_ILL_INPUT);
+ } else if (retval == CV_RTFUNC_FAIL) {
+ CVProcessError(cv_mem, CV_RTFUNC_FAIL, "CVODE", "CVRcheck2", MSGCV_RTFUNC_FAILED, tlo);
+ return(CV_RTFUNC_FAIL);
+ } else if (retval == RTFOUND) {
+ tretlast = *tret = tlo;
+ return(CV_ROOT_RETURN);
+ }
+
+ /* If tn is distinct from tretlast (within roundoff),
+ check remaining interval for roots */
+ if ( ABS(tn - tretlast) > troundoff ) {
+
+ retval = CVRcheck3(cv_mem);
+
+ if (retval == CV_SUCCESS) { /* no root found */
+ irfnd = 0;
+ if ((irfndp == 1) && (itask == CV_ONE_STEP)) {
+ tretlast = *tret = tn;
+ N_VScale(ONE, zn[0], yout);
+ return(CV_SUCCESS);
+ }
+ } else if (retval == RTFOUND) { /* a new root was found */
+ irfnd = 1;
+ tretlast = *tret = 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);
+ return(CV_RTFUNC_FAIL);
+ }
+
+ }
+
+ } /* 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;
+ ier = CVodeGetDky(cv_mem, tout, 0, yout);
+ if (ier != CV_SUCCESS) {
+ 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 && ABS(tn - tretlast) > troundoff ) {
+ tretlast = *tret = tn;
+ N_VScale(ONE, zn[0], yout);
+ return(CV_SUCCESS);
+ }
+
+ /* Test for tn at tstop or near tstop */
+ if ( tstopset ) {
+
+ if ( ABS(tn - tstop) <= troundoff) {
+ ier = CVodeGetDky(cv_mem, tstop, 0, yout);
+ if (ier != CV_SUCCESS) {
+ CVProcessError(cv_mem, CV_ILL_INPUT, "CVODE", "CVode", MSGCV_BAD_TSTOP, tstop, tn);
+ return(CV_ILL_INPUT);
+ }
+ tretlast = *tret = tstop;
+ tstopset = FALSE;
+ 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;
+ }
+
+ }
+
+ } /* end stopping tests block */
+
+ /*
+ * --------------------------------------------------
+ * 4. Looping point for internal steps
+ *
+ * 4.1. check for errors (too many steps, too much
+ * accuracy requested, step size too small)
+ * 4.2. take a new step (call CVStep)
+ * 4.3. stop on error
+ * 4.4. perform stop tests:
+ * - check for root in last step
+ * - check if tout was passed
+ * - check if close to tstop
+ * - check if in ONE_STEP mode (must return)
+ * --------------------------------------------------
+ */
+
+ nstloc = 0;
+ loop {
+
+ next_h = h;
+ next_q = q;
+
+ /* Reset and check ewt */
+ if (nst > 0) {
+
+ ewtsetOK = efun(zn[0], ewt, e_data);
+
+ if (ewtsetOK != 0) {
+
+ if (itol == CV_WF)
+ CVProcessError(cv_mem, CV_ILL_INPUT, "CVODE", "CVode", MSGCV_EWT_NOW_FAIL, tn);
+ else
+ CVProcessError(cv_mem, CV_ILL_INPUT, "CVODE", "CVode", MSGCV_EWT_NOW_BAD, tn);
+
+ istate = CV_ILL_INPUT;
+ tretlast = *tret = tn;
+ N_VScale(ONE, 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);
+ istate = CV_TOO_MUCH_WORK;
+ tretlast = *tret = tn;
+ N_VScale(ONE, 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);
+ istate = CV_TOO_MUCH_ACC;
+ tretlast = *tret = tn;
+ N_VScale(ONE, zn[0], yout);
+ tolsf *= TWO;
+ break;
+ } else {
+ 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)
+ CVProcessError(cv_mem, CV_WARNING, "CVODE", "CVode", MSGCV_HNIL_DONE);
+ }
+
+ /* Call CVStep to take a step */
+ kflag = CVStep(cv_mem);
+
+ /* 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);
+ break;
+ }
+
+ nstloc++;
+
+ /* Check for root in last step taken. */
+ if (nrtfn > 0) {
+
+ retval = CVRcheck3(cv_mem);
+
+ if (retval == RTFOUND) { /* A new root was found */
+ irfnd = 1;
+ istate = CV_ROOT_RETURN;
+ tretlast = *tret = tlo;
+ break;
+ } else if (retval == CV_RTFUNC_FAIL) { /* g failed */
+ CVProcessError(cv_mem, CV_RTFUNC_FAIL, "CVODE", "CVRcheck3", MSGCV_RTFUNC_FAILED, tlo);
+ istate = CV_RTFUNC_FAIL;
+ break;
+ }
+
+ /* If we are at the end of the first step and we still have
+ * some event functions that are inactive, issue a warning
+ * 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;
+ break;
+ }
+ }
+ if ((cv_mem->cv_mxgnull > 0) && 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 ) {
+ istate = CV_SUCCESS;
+ tretlast = *tret = tout;
+ (void) CVodeGetDky(cv_mem, tout, 0, yout);
+ next_q = qprime;
+ next_h = hprime;
+ break;
+ }
+
+ /* Check if tn is at tstop or near tstop */
+ if ( tstopset ) {
+
+ troundoff = FUZZ_FACTOR*uround*(ABS(tn) + ABS(h));
+ if ( ABS(tn - tstop) <= troundoff) {
+ (void) CVodeGetDky(cv_mem, tstop, 0, yout);
+ tretlast = *tret = tstop;
+ tstopset = FALSE;
+ istate = CV_TSTOP_RETURN;
+ break;
+ }
+
+ if ( (tn + hprime - tstop)*h > ZERO ) {
+ hprime = (tstop - tn)*(ONE-FOUR*uround);
+ eta = hprime/h;
+ }
+
+ }
+
+ /* 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;
+ break;
+ }
+
+ } /* end looping for internal steps */
+
+ return(istate);
+}
+
+/*-----------------------------------------------------------------*/
+
+/*
+ * CVodeGetDky
+ *
+ * This routine computes the k-th derivative of the interpolating
+ * polynomial at the time t and stores the result in the vector dky.
+ * The formula is:
+ * q
+ * dky = SUM c(j,k) * (t - tn)^(j-k) * h^(-j) * zn[j] ,
+ * j=k
+ * where c(j,k) = j*(j-1)*...*(j-k+1), q is the current order, and
+ * zn[j] is the j-th column of the Nordsieck history array.
+ *
+ * This function is called by CVode with k = 0 and t = tout, but
+ * may also be called directly by the user.
+ */
+
+int CVodeGetDky(void *cvode_mem, realtype t, int k, N_Vector dky)
+{
+ realtype s, c, r;
+ realtype tfuzz, tp, tn1;
+ int i, j;
+ CVodeMem cv_mem;
+
+ /* Check all inputs for legality */
+
+ if (cvode_mem == NULL) {
+ CVProcessError(NULL, CV_MEM_NULL, "CVODE", "CVodeGetDky", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+ cv_mem = (CVodeMem) cvode_mem;
+
+ if (dky == NULL) {
+ CVProcessError(cv_mem, CV_BAD_DKY, "CVODE", "CVodeGetDky", MSGCV_NULL_DKY);
+ return(CV_BAD_DKY);
+ }
+
+ if ((k < 0) || (k > q)) {
+ CVProcessError(cv_mem, CV_BAD_K, "CVODE", "CVodeGetDky", MSGCV_BAD_K);
+ return(CV_BAD_K);
+ }
+
+ /* Allow for some slack */
+ tfuzz = FUZZ_FACTOR * uround * (ABS(tn) + ABS(hu));
+ if (hu < ZERO) tfuzz = -tfuzz;
+ tp = tn - hu - tfuzz;
+ tn1 = tn + tfuzz;
+ if ((t-tp)*(t-tn1) > ZERO) {
+ CVProcessError(cv_mem, CV_BAD_T, "CVODE", "CVodeGetDky", MSGCV_BAD_T, t, tn-hu, tn);
+ return(CV_BAD_T);
+ }
+
+ /* Sum the differentiated interpolating polynomial */
+
+ s = (t - tn) / h;
+ for (j=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);
+ } else {
+ N_VLinearSum(c, zn[j], s, dky, dky);
+ }
+ }
+ if (k == 0) return(CV_SUCCESS);
+ r = RPowerI(h,-k);
+ N_VScale(r, dky, dky);
+ return(CV_SUCCESS);
+}
+
+/*
+ * CVodeFree
+ *
+ * This routine frees the problem memory allocated by CVodeInit.
+ * Such memory includes all the vectors allocated by CVAllocVectors,
+ * and the memory lmem for the linear solver (deallocated by a call
+ * to lfree).
+ */
+
+void CVodeFree(void **cvode_mem)
+{
+ CVodeMem cv_mem;
+
+ if (*cvode_mem == NULL) return;
+
+ cv_mem = (CVodeMem) (*cvode_mem);
+
+ CVFreeVectors(cv_mem);
+
+ if (iter == CV_NEWTON && lfree != NULL) 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;
+ }
+
+ free(*cvode_mem);
+ *cvode_mem = NULL;
+}
+
+/*
+ * =================================================================
+ * Private Functions Implementation
+ * =================================================================
+ */
+
+/*
+ * CVCheckNvector
+ * This routine checks if all required vector operations are present.
+ * If any of them is missing it returns FALSE.
+ */
+
+static booleantype CVCheckNvector(N_Vector tmpl)
+{
+ if((tmpl->ops->nvclone == NULL) ||
+ (tmpl->ops->nvdestroy == NULL) ||
+ (tmpl->ops->nvlinearsum == NULL) ||
+ (tmpl->ops->nvconst == NULL) ||
+ (tmpl->ops->nvprod == NULL) ||
+ (tmpl->ops->nvdiv == NULL) ||
+ (tmpl->ops->nvscale == NULL) ||
+ (tmpl->ops->nvabs == NULL) ||
+ (tmpl->ops->nvinv == NULL) ||
+ (tmpl->ops->nvaddconst == NULL) ||
+ (tmpl->ops->nvmaxnorm == NULL) ||
+ (tmpl->ops->nvwrmsnorm == NULL) ||
+ (tmpl->ops->nvmin == NULL))
+ return(FALSE);
+ else
+ return(TRUE);
+}
+
+/*
+ * CVAllocVectors
+ *
+ * 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.
+ * This routine also sets the optional outputs lrw and liw, which are
+ * (respectively) the lengths of the real and integer work spaces
+ * allocated here.
+ */
+
+static booleantype CVAllocVectors(CVodeMem cv_mem, N_Vector tmpl)
+{
+ int i, j;
+
+ /* Allocate ewt, acor, tempv, ftemp */
+
+ ewt = N_VClone(tmpl);
+ if (ewt == NULL) return(FALSE);
+
+ acor = N_VClone(tmpl);
+ if (acor == NULL) {
+ N_VDestroy(ewt);
+ return(FALSE);
+ }
+
+ tempv = N_VClone(tmpl);
+ if (tempv == NULL) {
+ N_VDestroy(ewt);
+ N_VDestroy(acor);
+ return(FALSE);
+ }
+
+ ftemp = N_VClone(tmpl);
+ if (ftemp == NULL) {
+ N_VDestroy(tempv);
+ N_VDestroy(ewt);
+ N_VDestroy(acor);
+ return(FALSE);
+ }
+
+ /* 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);
+ }
+ }
+
+ /* Update solver workspace lengths */
+ lrw += (qmax + 5)*lrw1;
+ liw += (qmax + 5)*liw1;
+
+ /* Store the value of qmax used here */
+ cv_mem->cv_qmax_alloc = qmax;
+
+ return(TRUE);
+}
+
+/*
+ * CVFreeVectors
+ *
+ * This routine frees the CVODE vectors allocated in CVAllocVectors.
+ */
+
+static void CVFreeVectors(CVodeMem cv_mem)
+{
+ int j, maxord;
+
+ 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]);
+
+ lrw -= (maxord + 5)*lrw1;
+ liw -= (maxord + 5)*liw1;
+
+ if (cv_mem->cv_VabstolMallocDone) {
+ N_VDestroy(Vabstol);
+ lrw -= lrw1;
+ liw -= liw1;
+ }
+}
+
+/*
+ * CVInitialSetup
+ *
+ * This routine performs input consistency checks at the first step.
+ * If needed, it also checks the linear solver module and calls the
+ * linear solver initialization routine.
+ */
+
+static int CVInitialSetup(CVodeMem cv_mem)
+{
+ int ier;
+
+ /* Did the user specify tolerances? */
+ if (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;
+
+ /* Load initial error weights */
+ ier = efun(zn[0], ewt, e_data);
+ if (ier != 0) {
+ if (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);
+ return(CV_ILL_INPUT);
+ }
+
+ /* 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, "CVODE", "CVInitialSetup", MSGCV_LSOLVE_NULL);
+ return(CV_ILL_INPUT);
+ }
+ if (linit != NULL) {
+ ier = linit(cv_mem);
+ if (ier != 0) {
+ CVProcessError(cv_mem, CV_LINIT_FAIL, "CVODE", "CVInitialSetup", MSGCV_LINIT_FAIL);
+ return(CV_LINIT_FAIL);
+ }
+ }
+ }
+
+ return(CV_SUCCESS);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * PRIVATE FUNCTIONS FOR CVODE
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * CVHin
+ *
+ * This routine computes a tentative initial step size h0.
+ * If tout is too close to tn (= t0), then CVHin returns CV_TOO_CLOSE
+ * and h remains uninitialized. Note that here tout is either the value
+ * passed to CVode at the first call or the value of tstop (if tstop is
+ * enabled and it is closer to t0=tn than tout).
+ * If the RHS function fails unrecoverably, CVHin returns CV_RHSFUNC_FAIL.
+ * If the RHS function fails recoverably too many times and recovery is
+ * not possible, CVHin returns CV_REPTD_RHSFUNC_ERR.
+ * Otherwise, CVHin sets h to the chosen value h0 and returns CV_SUCCESS.
+ *
+ * The algorithm used seeks to find h0 as a solution of
+ * (WRMS norm of (h0^2 ydd / 2)) = 1,
+ * where ydd = estimated second derivative of y.
+ *
+ * We start with an initial estimate equal to the geometric mean of the
+ * lower and upper bounds on the step size.
+ *
+ * Loop up to MAX_ITERS times to find h0.
+ * Stop if new and previous values differ by a factor < 2.
+ * Stop if hnew/hg > 2 after one iteration, as this probably means
+ * that the ydd value is bad because of cancellation error.
+ *
+ * For each new proposed hg, we allow MAX_ITERS attempts to
+ * resolve a possible recoverable failure from f() by reducing
+ * the proposed stepsize by a factor of 0.2. If a legal stepsize
+ * still cannot be found, fall back on a previous value if possible,
+ * or else return CV_REPTD_RHSFUNC_ERR.
+ *
+ * Finally, we apply a bias (0.5) and verify that h0 is within bounds.
+ */
+
+static int CVHin(CVodeMem cv_mem, realtype tout)
+{
+ int retval, sign, count1, count2;
+ realtype tdiff, tdist, tround, hlb, hub;
+ realtype hg, hgs, hs, hnew, hrat, h0, yddnrm;
+ booleantype hgOK, hnewOK;
+
+ /* If tout is too close to tn, give up */
+
+ if ((tdiff = tout-tn) == ZERO) return(CV_TOO_CLOSE);
+
+ sign = (tdiff > ZERO) ? 1 : -1;
+ tdist = ABS(tdiff);
+ tround = uround * MAX(ABS(tn), ABS(tout));
+
+ if (tdist < TWO*tround) return(CV_TOO_CLOSE);
+
+ /*
+ Set lower and upper bounds on h0, and take geometric mean
+ as first trial value.
+ Exit with this value if the bounds cross each other.
+ */
+
+ hlb = HLB_FACTOR * tround;
+ hub = CVUpperBoundH0(cv_mem, tdist);
+
+ hg = RSqrt(hlb*hub);
+
+ if (hub < hlb) {
+ if (sign == -1) h = -hg;
+ else h = hg;
+ return(CV_SUCCESS);
+ }
+
+ /* Outer loop */
+
+ hnewOK = FALSE;
+ hs = hg; /* safeguard against 'uninitialized variable' warning */
+
+ for(count1 = 1; count1 <= MAX_ITERS; count1++) {
+
+ /* Attempts to estimate ydd */
+
+ hgOK = FALSE;
+
+ for (count2 = 1; count2 <= MAX_ITERS; count2++) {
+ hgs = hg*sign;
+ retval = CVYddNorm(cv_mem, hgs, &yddnrm);
+ /* 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;}
+ /* f() failed recoverably; cut step size and test it again */
+ hg *= POINT2;
+ }
+
+ /* If f() failed recoverably MAX_ITERS times */
+
+ if (!hgOK) {
+ /* Exit if this is the first or second pass. No recovery possible */
+ if (count1 <= 2) return(CV_REPTD_RHSFUNC_ERR);
+ /* We have a fall-back option. The value hs is a previous hnew which
+ passed through f(). Use it and break */
+ hnew = hs;
+ break;
+ }
+
+ /* The proposed step size is feasible. Save it. */
+ hs = hg;
+
+ /* If the stopping criteria was met, or if this is the last pass, stop */
+ if ( (hnewOK) || (count1 == MAX_ITERS)) {hnew = hg; break;}
+
+ /* Propose new step size */
+ hnew = (yddnrm*hub*hub > TWO) ? RSqrt(TWO/yddnrm) : RSqrt(hg*hub);
+ 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;
+ }
+
+ /* After one pass, if ydd seems to be bad, use fall-back value. */
+ if ((count1 > 1) && (hrat > TWO)) {
+ hnew = hg;
+ hnewOK = TRUE;
+ }
+
+ /* Send this value back through f() */
+ hg = hnew;
+
+ }
+
+ /* Apply bounds, bias factor, and attach sign */
+
+ h0 = H_BIAS*hnew;
+ if (h0 < hlb) h0 = hlb;
+ if (h0 > hub) h0 = hub;
+ if (sign == -1) h0 = -h0;
+ h = h0;
+
+ return(CV_SUCCESS);
+}
+
+/*
+ * CVUpperBoundH0
+ *
+ * This routine sets an upper bound on abs(h0) based on
+ * tdist = tn - t0 and the values of y[i]/y'[i].
+ */
+
+static realtype CVUpperBoundH0(CVodeMem cv_mem, realtype tdist)
+{
+ realtype hub_inv, hub;
+ N_Vector temp1, temp2;
+
+ /*
+ * Bound based on |y0|/|y0'| -- allow at most an increase of
+ * HUB_FACTOR in y0 (based on a forward Euler step). The weight
+ * factor is used as a safeguard against zero components in y0.
+ */
+
+ temp1 = tempv;
+ temp2 = acor;
+
+ N_VAbs(zn[0], temp2);
+ efun(zn[0], temp1, e_data);
+ N_VInv(temp1, temp1);
+ N_VLinearSum(HUB_FACTOR, temp2, ONE, temp1, temp1);
+
+ N_VAbs(zn[1], temp2);
+
+ N_VDiv(temp2, temp1, temp1);
+ hub_inv = N_VMaxNorm(temp1);
+
+ /*
+ * bound based on tdist -- allow at most a step of magnitude
+ * HUB_FACTOR * tdist
+ */
+
+ hub = HUB_FACTOR*tdist;
+
+ /* Use the smaler of the two */
+
+ if (hub*hub_inv > ONE) hub = ONE/hub_inv;
+
+ return(hub);
+}
+
+/*
+ * CVYddNorm
+ *
+ * This routine computes an estimate of the second derivative of y
+ * using a difference quotient, and returns its WRMS norm.
+ */
+
+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++;
+ 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);
+
+ *yddnrm = N_VWrmsNorm(tempv, ewt);
+
+ return(CV_SUCCESS);
+}
+
+/*
+ * CVStep
+ *
+ * This routine performs one internal cvode step, from tn to tn + h.
+ * It calls other routines to do all the work.
+ *
+ * The main operations done here are as follows:
+ * - preliminary adjustments if a new step size was chosen;
+ * - prediction of the Nordsieck history array zn at tn + h;
+ * - setting of multistep method coefficients and test quantities;
+ * - solution of the nonlinear system;
+ * - testing the local error;
+ * - updating zn and other state data if successful;
+ * - resetting stepsize and order for the next step.
+ * - if SLDET is on, check for stability, reduce order if necessary.
+ * On a failure in the nonlinear system solution or error test, the
+ * step may be reattempted, depending on the nature of the failure.
+ */
+
+static int CVStep(CVodeMem cv_mem)
+{
+ realtype saved_t, dsm;
+ int ncf, nef;
+ int nflag, kflag, eflag;
+
+ saved_t = tn;
+ ncf = nef = 0;
+ nflag = FIRST_CALL;
+
+ if ((nst > 0) && (hprime != h)) CVAdjustParams(cv_mem);
+
+ /* Looping point for attempts to take a step */
+ loop {
+
+ CVPredict(cv_mem);
+ CVSet(cv_mem);
+
+ nflag = CVNls(cv_mem, nflag);
+ kflag = CVHandleNFlag(cv_mem, &nflag, saved_t, &ncf);
+
+ /* Go back in loop if we need to predict again (nflag=PREV_CONV_FAIL)*/
+ if (kflag == PREDICT_AGAIN) continue;
+
+ /* Return if nonlinear solve failed and recovery not possible. */
+ if (kflag != DO_ERROR_TEST) return(kflag);
+
+ /* Perform error test (nflag=CV_SUCCESS) */
+ eflag = CVDoErrorTest(cv_mem, &nflag, saved_t, &nef, &dsm);
+
+ /* Go back in loop if we need to predict again (nflag=PREV_ERR_FAIL) */
+ if (eflag == TRY_AGAIN) continue;
+
+ /* Return if error test failed and recovery not possible. */
+ if (eflag != CV_SUCCESS) return(eflag);
+
+ /* Error test passed (eflag=CV_SUCCESS), break from loop */
+ break;
+
+ }
+
+ /* Nonlinear system solve and error test were both successful.
+ Update data, and consider change of step and/or order. */
+
+ CVCompleteStep(cv_mem);
+
+ CVPrepareNextStep(cv_mem, dsm);
+
+ /* If Stablilty Limit Detection is turned on, call stability limit
+ detection routine for possible order reduction. */
+
+ if (sldeton) CVBDFStab(cv_mem);
+
+ etamax = (nst <= SMALL_NST) ? ETAMX2 : ETAMX3;
+
+ /* Finally, we rescale the acor array to be the
+ estimated local error vector. */
+
+ N_VScale(tq[2], acor, acor);
+ return(CV_SUCCESS);
+
+}
+
+/*
+ * CVAdjustParams
+ *
+ * This routine is called when a change in step size was decided upon,
+ * and it handles the required adjustments to the history array zn.
+ * If there is to be a change in order, we call CVAdjustOrder and reset
+ * q, L = q+1, and qwait. Then in any case, we call CVRescale, which
+ * resets h and rescales the Nordsieck array.
+ */
+
+static void CVAdjustParams(CVodeMem cv_mem)
+{
+ if (qprime != q) {
+ CVAdjustOrder(cv_mem, qprime-q);
+ q = qprime;
+ L = q+1;
+ qwait = L;
+ }
+ CVRescale(cv_mem);
+}
+
+/*
+ * CVAdjustOrder
+ *
+ * This routine is a high level routine which handles an order
+ * change by an amount deltaq (= +1 or -1). If a decrease in order
+ * is requested and q==2, then the routine returns immediately.
+ * Otherwise CVAdjustAdams or CVAdjustBDF is called to handle the
+ * order change (depending on the value of lmm).
+ */
+
+static void CVAdjustOrder(CVodeMem cv_mem, int deltaq)
+{
+ if ((q==2) && (deltaq != 1)) return;
+
+ switch(lmm){
+ case CV_ADAMS:
+ CVAdjustAdams(cv_mem, deltaq);
+ break;
+ case CV_BDF:
+ CVAdjustBDF(cv_mem, deltaq);
+ break;
+ }
+}
+
+/*
+ * CVAdjustAdams
+ *
+ * This routine adjusts the history array on a change of order q by
+ * deltaq, in the case that lmm == CV_ADAMS.
+ */
+
+static void CVAdjustAdams(CVodeMem cv_mem, int deltaq)
+{
+ int i, j;
+ realtype xi, hsum;
+
+ /* On an order increase, set new column of zn to zero and return */
+
+ if (deltaq==1) {
+ N_VConst(ZERO, zn[L]);
+ return;
+ }
+
+ /*
+ * On an order decrease, each zn[j] is adjusted by a multiple of zn[q].
+ * The coeffs. in the adjustment are the coeffs. of the polynomial:
+ * x
+ * q * INT { u * ( u + xi_1 ) * ... * ( u + xi_{q-2} ) } du
+ * 0
+ * where xi_j = [t_n - t_(n-j)]/h => xi_0 = 0
+ */
+
+ for (i=0; i <= qmax; i++) l[i] = ZERO;
+ 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 <= q-2; j++) l[j+1] = q * (l[j] / (j+1));
+
+ for (j=2; j < q; j++)
+ N_VLinearSum(-l[j], zn[q], ONE, zn[j], zn[j]);
+}
+
+/*
+ * CVAdjustBDF
+ *
+ * This is a high level routine which handles adjustments to the
+ * history array on a change of order by deltaq in the case that
+ * lmm == CV_BDF. CVAdjustBDF calls CVIncreaseBDF if deltaq = +1 and
+ * CVDecreaseBDF if deltaq = -1 to do the actual work.
+ */
+
+static void CVAdjustBDF(CVodeMem cv_mem, int deltaq)
+{
+ switch(deltaq) {
+ case 1 :
+ CVIncreaseBDF(cv_mem);
+ return;
+ case -1:
+ CVDecreaseBDF(cv_mem);
+ return;
+ }
+}
+
+/*
+ * CVIncreaseBDF
+ *
+ * This routine adjusts the history array on an increase in the
+ * order q in the case that lmm == CV_BDF.
+ * A new column zn[q+1] is set equal to a multiple of the saved
+ * vector (= acor) in zn[indx_acor]. Then each zn[j] is adjusted by
+ * a multiple of zn[q+1]. The coefficients in the adjustment are the
+ * coefficients of the polynomial x*x*(x+xi_1)*...*(x+xi_j),
+ * where xi_j = [t_n - t_(n-j)]/h.
+ */
+
+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;
+ alpha0 = -ONE;
+ hsum = hscale;
+ if (q > 1) {
+ for (j=1; j < q; j++) {
+ hsum += tau[j+1];
+ xi = hsum / 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];
+ 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]);
+ }
+}
+
+/*
+ * CVDecreaseBDF
+ *
+ * This routine adjusts the history array on a decrease in the
+ * order q in the case that lmm == CV_BDF.
+ * Each zn[j] is adjusted by a multiple of zn[q]. The coefficients
+ * in the adjustment are the coefficients of the polynomial
+ * x*x*(x+xi_1)*...*(x+xi_j), where xi_j = [t_n - t_(n-j)]/h.
+ */
+
+static void CVDecreaseBDF(CVodeMem cv_mem)
+{
+ realtype hsum, xi;
+ int i, j;
+
+ for (i=0; i <= qmax; i++) l[i] = ZERO;
+ 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=2; j < q; j++)
+ N_VLinearSum(-l[j], zn[q], ONE, zn[j], zn[j]);
+}
+
+/*
+ * CVRescale
+ *
+ * This routine rescales the Nordsieck array by multiplying the
+ * jth column zn[j] by eta^j, j = 1, ..., q. Then the value of
+ * h is rescaled by eta, and hscale is reset to h.
+ */
+
+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;
+ }
+ h = hscale * eta;
+ next_h = h;
+ hscale = h;
+ nscon = 0;
+}
+
+/*
+ * CVPredict
+ *
+ * This routine advances tn by the tentative step size h, and computes
+ * the predicted array z_n(0), which is overwritten on zn. The
+ * prediction of zn is done by repeated additions.
+ * If tstop is enabled, it is possible for tn + h to be past tstop by roundoff,
+ * and in that case, we reset tn (after incrementing by h) to tstop.
+ */
+
+static void CVPredict(CVodeMem cv_mem)
+{
+ int j, k;
+
+ tn += h;
+ if (tstopset) {
+ if ((tn - tstop)*h > ZERO) tn = 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]);
+}
+
+/*
+ * CVSet
+ *
+ * This routine is a high level routine which calls CVSetAdams or
+ * CVSetBDF to set the polynomial l, the test quantity array tq,
+ * and the related variables rl1, gamma, and gamrat.
+ *
+ * The array tq is loaded with constants used in the control of estimated
+ * local errors and in the nonlinear convergence test. Specifically, while
+ * running at order q, the components of tq are as follows:
+ * tq[1] = a coefficient used to get the est. local error at order q-1
+ * tq[2] = a coefficient used to get the est. local error at order q
+ * tq[3] = a coefficient used to get the est. local error at order q+1
+ * tq[4] = constant used in nonlinear iteration convergence test
+ * tq[5] = coefficient used to get the order q+2 derivative vector used in
+ * the est. local error at order q+1
+ */
+
+static void CVSet(CVodeMem cv_mem)
+{
+ switch(lmm) {
+ case CV_ADAMS:
+ CVSetAdams(cv_mem);
+ break;
+ case CV_BDF:
+ 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 */
+}
+
+/*
+ * CVSetAdams
+ *
+ * This routine handles the computation of l and tq for the
+ * case lmm == CV_ADAMS.
+ *
+ * The components of the array l are the coefficients of a
+ * polynomial Lambda(x) = l_0 + l_1 x + ... + l_q x^q, given by
+ * q-1
+ * (d/dx) Lambda(x) = c * PRODUCT (1 + x / xi_i) , where
+ * i=1
+ * Lambda(-1) = 0, Lambda(0) = 1, and c is a normalization factor.
+ * Here xi_i = [t_n - t_(n-i)] / h.
+ *
+ * The array tq is set to test quantities used in the convergence
+ * test, the error test, and the selection of h at a new order.
+ */
+
+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] */
+ return;
+ }
+
+ hsum = CVAdamsStart(cv_mem, m);
+
+ M[0] = CVAltSum(q-1, m, 1);
+ M[1] = CVAltSum(q-1, m, 2);
+
+ CVAdamsFinish(cv_mem, m, M, hsum);
+}
+
+/*
+ * CVAdamsStart
+ *
+ * This routine generates in m[] the coefficients of the product
+ * polynomial needed for the Adams l and tq coefficients for q > 1.
+ */
+
+static realtype CVAdamsStart(CVodeMem cv_mem, realtype m[])
+{
+ realtype hsum, xi_inv, sum;
+ int i, j;
+
+ hsum = 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];
+ /* The m[i] are coefficients of product(1 to j) (1 + x/xi_i) */
+ }
+ return(hsum);
+}
+
+/*
+ * CVAdamsFinish
+ *
+ * This routine completes the calculation of the Adams l and tq.
+ */
+
+static void CVAdamsFinish(CVodeMem cv_mem, realtype m[], realtype M[], realtype hsum)
+{
+ int i;
+ realtype M0_inv, xi, xi_inv;
+
+ 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;
+ xi_inv = ONE / xi;
+
+ tq[2] = M[1] * M0_inv / xi;
+ tq[5] = xi / l[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;
+ }
+
+ tq[4] = nlscoef / tq[2];
+}
+
+/*
+ * CVAltSum
+ *
+ * CVAltSum returns the value of the alternating sum
+ * sum (i= 0 ... iend) [ (-1)^i * (a[i] / (i + k)) ].
+ * If iend < 0 then CVAltSum returns 0.
+ * This operation is needed to compute the integral, from -1 to 0,
+ * of a polynomial x^(k-1) M(x) given the coefficients of M(x).
+ */
+
+static realtype CVAltSum(int iend, realtype a[], int k)
+{
+ int i, sign;
+ realtype sum;
+
+ if (iend < 0) return(ZERO);
+
+ sum = ZERO;
+ sign = 1;
+ for (i=0; i <= iend; i++) {
+ sum += sign * (a[i] / (i+k));
+ sign = -sign;
+ }
+ return(sum);
+}
+
+/*
+ * CVSetBDF
+ *
+ * This routine computes the coefficients l and tq in the case
+ * lmm == CV_BDF. CVSetBDF calls CVSetTqBDF to set the test
+ * quantity array tq.
+ *
+ * The components of the array l are the coefficients of a
+ * polynomial Lambda(x) = l_0 + l_1 x + ... + l_q x^q, given by
+ * q-1
+ * Lambda(x) = (1 + x / xi*_q) * PRODUCT (1 + x / xi_i) , where
+ * i=1
+ * xi_i = [t_n - t_(n-i)] / h.
+ *
+ * The array tq is set to test quantities used in the convergence
+ * test, the error test, and the selection of h at a new order.
+ */
+
+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;
+ alpha0 = alpha0_hat = -ONE;
+ hsum = h;
+ if (q > 1) {
+ for (j=2; j < q; j++) {
+ hsum += tau[j-1];
+ xi_inv = h / hsum;
+ alpha0 -= ONE / j;
+ for(i=j; i >= 1; i--) l[i] += 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;
+ }
+
+ CVSetTqBDF(cv_mem, hsum, alpha0, alpha0_hat, xi_inv, xistar_inv);
+}
+
+/*
+ * CVSetTqBDF
+ *
+ * This routine sets the test quantity array tq in the case
+ * lmm == CV_BDF.
+ */
+
+static void CVSetTqBDF(CVodeMem cv_mem, realtype hsum, realtype alpha0,
+ realtype alpha0_hat, realtype xi_inv, realtype xistar_inv)
+{
+ realtype A1, A2, A3, A4, A5, A6;
+ realtype C, Cpinv, Cppinv;
+
+ A1 = ONE - alpha0_hat + alpha0;
+ A2 = ONE + q * A1;
+ tq[2] = ABS(A1 / (alpha0 * A2));
+ tq[5] = ABS(A2 * xistar_inv / (l[q] * xi_inv));
+ if (qwait == 1) {
+ if (q > 1) {
+ C = xistar_inv / l[q];
+ A3 = alpha0 + ONE / q;
+ A4 = alpha0_hat + xi_inv;
+ Cpinv = (ONE - A4 + A3) / A3;
+ tq[1] = ABS(C * Cpinv);
+ }
+ else tq[1] = ONE;
+ hsum += tau[q];
+ xi_inv = h / hsum;
+ A5 = alpha0 - (ONE / (q+1));
+ A6 = alpha0_hat - xi_inv;
+ Cppinv = (ONE - A6 + A5) / A2;
+ tq[3] = ABS(Cppinv / (xi_inv * (q+2) * A5));
+ }
+ tq[4] = nlscoef / tq[2];
+}
+
+/*
+ * CVNls
+ *
+ * This routine attempts to solve the nonlinear system associated
+ * with a single implicit step of the linear multistep method.
+ * Depending on iter, it calls CVNlsFunctional or CVNlsNewton
+ * to do the work.
+ */
+
+static int CVNls(CVodeMem cv_mem, int nflag)
+{
+ int flag = CV_SUCCESS;
+
+ switch(iter) {
+ case CV_FUNCTIONAL:
+ flag = CVNlsFunctional(cv_mem);
+ break;
+ case CV_NEWTON:
+ flag = CVNlsNewton(cv_mem, nflag);
+ break;
+ }
+
+ return(flag);
+}
+
+/*
+ * CVNlsFunctional
+ *
+ * This routine attempts to solve the nonlinear system using
+ * functional iteration (no matrices involved).
+ *
+ * Possible return values are:
+ *
+ * CV_SUCCESS ---> continue with error test
+ *
+ * CV_RHSFUNC_FAIL ---> halt the integration
+ *
+ * CONV_FAIL -+
+ * RHSFUNC_RECVR -+-> predict again or stop if too many
+ *
+ */
+
+static int CVNlsFunctional(CVodeMem cv_mem)
+{
+ int retval, m;
+ realtype del, delp, dcon;
+
+ /* Initialize counter and evaluate f at predicted y */
+
+ crate = ONE;
+ m = 0;
+
+ retval = f(tn, zn[0], tempv, user_data);
+ nfe++;
+ if (retval < 0) return(CV_RHSFUNC_FAIL);
+ if (retval > 0) return(RHSFUNC_RECVR);
+
+ N_VConst(ZERO, acor);
+
+ /* Initialize delp to avoid compiler warning message */
+ del = delp = ZERO;
+
+ /* Loop until convergence; accumulate corrections in acor */
+
+ loop {
+
+ 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);
+ /* 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);
+
+ /* 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 = MAX(CRDOWN * crate, del / delp);
+ dcon = del * MIN(ONE, crate) / tq[4];
+ if (dcon <= ONE) {
+ acnrm = (m == 0) ? del : N_VWrmsNorm(acor, 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);
+
+ /* Save norm of correction, evaluate f, and loop again */
+ delp = del;
+
+ retval = f(tn, y, tempv, user_data);
+ nfe++;
+ if (retval < 0) return(CV_RHSFUNC_FAIL);
+ if (retval > 0) return(RHSFUNC_RECVR);
+
+ }
+}
+
+/*
+ * CVNlsNewton
+ *
+ * This routine handles the Newton iteration. It calls lsetup if
+ * indicated, calls CVNewtonIteration to perform the iteration, and
+ * retries a failed attempt at Newton iteration if that is indicated.
+ *
+ * Possible return values:
+ *
+ * CV_SUCCESS ---> continue with error test
+ *
+ * CV_RHSFUNC_FAIL -+
+ * CV_LSETUP_FAIL |-> halt the integration
+ * CV_LSOLVE_FAIL -+
+ *
+ * CONV_FAIL -+
+ * RHSFUNC_RECVR -+-> predict again or stop if too many
+ *
+ */
+
+static int CVNlsNewton(CVodeMem cv_mem, int nflag)
+{
+ N_Vector vtemp1, vtemp2, vtemp3;
+ 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 */
+
+ /* 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) {
+ callSetup = (nflag == PREV_CONV_FAIL) || (nflag == PREV_ERR_FAIL) ||
+ (nst == 0) || (nst >= nstlp + MSBP) || (ABS(gamrat-ONE) > DGMAX);
+ } else {
+ crate = ONE;
+ callSetup = FALSE;
+ }
+
+ /* 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 {
+
+ retval = f(tn, zn[0], ftemp, user_data);
+ 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;
+ /* 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);
+
+ /* Do the Newton iteration */
+ ier = CVNewtonIteration(cv_mem);
+
+ /* If there is a convergence failure and the Jacobian-related
+ data appears not to be current, loop again with a call to lsetup
+ in which convfail=CV_FAIL_BAD_J. Otherwise return. */
+ if (ier != TRY_AGAIN) return(ier);
+
+ callSetup = TRUE;
+ convfail = CV_FAIL_BAD_J;
+ }
+}
+
+/*
+ * CVNewtonIteration
+ *
+ * This routine performs the Newton iteration. If the iteration succeeds,
+ * it returns the value CV_SUCCESS. If not, it may signal the CVNlsNewton
+ * routine to call lsetup again and reattempt the iteration, by
+ * returning the value TRY_AGAIN. (In this case, CVNlsNewton must set
+ * convfail to CV_FAIL_BAD_J before calling setup again).
+ * Otherwise, this routine returns one of the appropriate values
+ * CV_LSOLVE_FAIL, CV_RHSFUNC_FAIL, CONV_FAIL, or RHSFUNC_RECVR back
+ * to CVNlsNewton.
+ */
+
+static int CVNewtonIteration(CVodeMem cv_mem)
+{
+ int m, retval;
+ realtype del, delp, dcon;
+ N_Vector b;
+
+ mnewt = m = 0;
+
+ /* Initialize delp to avoid compiler warning message */
+ del = delp = ZERO;
+
+ /* Looping point for Newton iteration */
+ loop {
+
+ /* Evaluate the residual of the nonlinear system*/
+ N_VLinearSum(rl1, zn[1], ONE, acor, tempv);
+ N_VLinearSum(gamma, ftemp, -ONE, tempv, tempv);
+
+ /* Call the lsolve function */
+ b = tempv;
+ retval = lsolve(cv_mem, b, ewt, y, ftemp);
+ 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);
+ }
+
+ /* 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);
+
+ /* 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 = MAX(CRDOWN * crate, del/delp);
+ }
+ dcon = del * MIN(ONE, crate) / tq[4];
+
+ if (dcon <= ONE) {
+ acnrm = (m==0) ? del : N_VWrmsNorm(acor, ewt);
+ jcur = FALSE;
+ return(CV_SUCCESS); /* Nonlinear system was solved successfully */
+ }
+
+ 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);
+ }
+
+ /* Save norm of correction, evaluate f, and loop again */
+ delp = del;
+ retval = f(tn, y, ftemp, user_data);
+ nfe++;
+ if (retval < 0) return(CV_RHSFUNC_FAIL);
+ if (retval > 0) {
+ if ((!jcur) && (setupNonNull)) return(TRY_AGAIN);
+ else return(RHSFUNC_RECVR);
+ }
+
+ } /* end loop */
+}
+
+/*
+ * CVHandleFlag
+ *
+ * This routine takes action on the return value nflag = *nflagPtr
+ * returned by CVNls, as follows:
+ *
+ * If CVNls succeeded in solving the nonlinear system, then
+ * CVHandleNFlag returns the constant DO_ERROR_TEST, which tells CVStep
+ * to perform the error test.
+ *
+ * If the nonlinear system was not solved successfully, then ncfn and
+ * ncf = *ncfPtr are incremented and Nordsieck array zn is restored.
+ *
+ * If the solution of the nonlinear system failed due to an
+ * unrecoverable failure by setup, we return the value CV_LSETUP_FAIL.
+ *
+ * If it failed due to an unrecoverable failure in solve, then we return
+ * the value CV_LSOLVE_FAIL.
+ *
+ * If it failed due to an unrecoverable failure in rhs, then we return
+ * the value CV_RHSFUNC_FAIL.
+ *
+ * Otherwise, a recoverable failure occurred when solving the
+ * nonlinear system (CVNls returned nflag == CONV_FAIL or RHSFUNC_RECVR).
+ * In this case, if ncf is now equal to maxncf or |h| = hmin,
+ * we return the value CV_CONV_FAILURE (if nflag=CONV_FAIL) or
+ * CV_REPTD_RHSFUNC_ERR (if nflag=RHSFUNC_RECVR).
+ * If not, we set *nflagPtr = PREV_CONV_FAIL and return the value
+ * PREDICT_AGAIN, telling CVStep to reattempt the step.
+ *
+ */
+
+static int CVHandleNFlag(CVodeMem cv_mem, int *nflagPtr, realtype saved_t,
+ int *ncfPtr)
+{
+ int nflag;
+
+ nflag = *nflagPtr;
+
+ if (nflag == CV_SUCCESS) return(DO_ERROR_TEST);
+
+ /* The nonlinear soln. failed; increment ncfn and restore zn */
+ ncfn++;
+ CVRestore(cv_mem, saved_t);
+
+ /* Return if lsetup, lsolve, or rhs failed unrecoverably */
+ if (nflag == CV_LSETUP_FAIL) return(CV_LSETUP_FAIL);
+ if (nflag == CV_LSOLVE_FAIL) return(CV_LSOLVE_FAIL);
+ if (nflag == CV_RHSFUNC_FAIL) return(CV_RHSFUNC_FAIL);
+
+ /* At this point, nflag = CONV_FAIL or RHSFUNC_RECVR; increment ncf */
+
+ (*ncfPtr)++;
+ etamax = ONE;
+
+ /* If we had maxncf failures or |h| = hmin,
+ return CV_CONV_FAILURE or CV_REPTD_RHSFUNC_ERR. */
+
+ if ((ABS(h) <= hmin*ONEPSM) || (*ncfPtr == 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 = MAX(ETACF, hmin / ABS(h));
+ *nflagPtr = PREV_CONV_FAIL;
+ CVRescale(cv_mem);
+
+ return(PREDICT_AGAIN);
+}
+
+/*
+ * CVRestore
+ *
+ * This routine restores the value of 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.
+ */
+
+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]);
+}
+
+/*
+ * CVDoErrorTest
+ *
+ * This routine performs the local error test.
+ * The weighted local error norm dsm is loaded into *dsmPtr, and
+ * the test dsm ?<= 1 is made.
+ *
+ * If the test passes, CVDoErrorTest returns CV_SUCCESS.
+ *
+ * If the test fails, we undo the step just taken (call CVRestore) and
+ *
+ * - if maxnef error test failures have occurred or if ABS(h) = hmin,
+ * we return CV_ERR_FAILURE.
+ *
+ * - if more than MXNEF1 error test failures have occurred, an order
+ * reduction is forced. If already at order 1, restart by reloading
+ * zn from scratch. If f() fails we return either CV_RHSFUNC_FAIL
+ * or CV_UNREC_RHSFUNC_ERR (no recovery is possible at this stage).
+ *
+ * - otherwise, set *nflagPtr to PREV_ERR_FAIL, and return TRY_AGAIN.
+ *
+ */
+
+static booleantype CVDoErrorTest(CVodeMem cv_mem, int *nflagPtr,
+ realtype saved_t, int *nefPtr, realtype *dsmPtr)
+{
+ realtype dsm;
+ int retval;
+
+ dsm = acnrm * tq[2];
+
+ /* If est. local error norm dsm passes test, return CV_SUCCESS */
+ *dsmPtr = dsm;
+ if (dsm <= ONE) return(CV_SUCCESS);
+
+ /* Test failed; increment counters, set nflag, and restore zn array */
+ (*nefPtr)++;
+ netf++;
+ *nflagPtr = PREV_ERR_FAIL;
+ CVRestore(cv_mem, saved_t);
+
+ /* At maxnef failures or |h| = hmin, return CV_ERR_FAILURE */
+ if ((ABS(h) <= hmin*ONEPSM) || (*nefPtr == maxnef)) return(CV_ERR_FAILURE);
+
+ /* Set etamax = 1 to prevent step size increase at end of this step */
+ etamax = ONE;
+
+ /* Set h ratio eta from dsm, rescale, and return for retry of step */
+ if (*nefPtr <= MXNEF1) {
+ eta = ONE / (RPowerR(BIAS2*dsm,ONE/L) + ADDON);
+ eta = MAX(ETAMIN, MAX(eta, hmin / ABS(h)));
+ if (*nefPtr >= SMALL_NEF) eta = MIN(eta, ETAMXF);
+ CVRescale(cv_mem);
+ return(TRY_AGAIN);
+ }
+
+ /* After MXNEF1 failures, force an order reduction and retry step */
+ if (q > 1) {
+ eta = MAX(ETAMIN, hmin / ABS(h));
+ CVAdjustOrder(cv_mem,-1);
+ L = q;
+ q--;
+ qwait = L;
+ CVRescale(cv_mem);
+ return(TRY_AGAIN);
+ }
+
+ /* If already at order 1, restart: reload zn from scratch */
+
+ eta = MAX(ETAMIN, hmin / ABS(h));
+ h *= eta;
+ next_h = h;
+ hscale = h;
+ qwait = LONG_WAIT;
+ nscon = 0;
+
+ retval = f(tn, zn[0], tempv, user_data);
+ nfe++;
+ if (retval < 0) return(CV_RHSFUNC_FAIL);
+ if (retval > 0) return(CV_UNREC_RHSFUNC_ERR);
+
+ N_VScale(h, tempv, zn[1]);
+
+ return(TRY_AGAIN);
+}
+
+/*
+ * =================================================================
+ * Private Functions Implementation after succesful step
+ * =================================================================
+ */
+
+/*
+ * CVCompleteStep
+ *
+ * This routine performs various update operations when the solution
+ * to the nonlinear system has passed the local error test.
+ * We increment the step counter nst, record the values hu and qu,
+ * 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.
+ */
+
+static void CVCompleteStep(CVodeMem cv_mem)
+{
+ int i, j;
+
+ nst++;
+ nscon++;
+ hu = h;
+ qu = 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 (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;
+ }
+}
+
+/*
+ * CVprepareNextStep
+ *
+ * This routine handles the setting of stepsize and order for the
+ * next step -- hprime and qprime. Along with hprime, it sets the
+ * ratio eta = hprime/h. It also updates other state variables
+ * related to a change of step size or order.
+ */
+
+ static void CVPrepareNextStep(CVodeMem cv_mem, realtype dsm)
+{
+ /* If etamax = 1, defer step size or order changes */
+ if (etamax == ONE) {
+ qwait = MAX(qwait, 2);
+ qprime = q;
+ hprime = h;
+ eta = ONE;
+ return;
+ }
+
+ /* etaq is the ratio of new to old h at the current order */
+ etaq = ONE /(RPowerR(BIAS2*dsm,ONE/L) + ADDON);
+
+ /* If no order change, adjust eta and acor in CVSetEta and return */
+ if (qwait != 0) {
+ eta = etaq;
+ qprime = q;
+ CVSetEta(cv_mem);
+ return;
+ }
+
+ /* 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);
+ CVChooseEta(cv_mem);
+ CVSetEta(cv_mem);
+}
+
+/*
+ * CVsetEta
+ *
+ * This routine adjusts the value of eta according to the various
+ * heuristic limits and the optional input hmax. It also resets
+ * etamax to be the estimated local error vector.
+ */
+
+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;
+ } else {
+ /* Limit eta by etamax and hmax, then set hprime */
+ eta = MIN(eta, etamax);
+ eta /= MAX(ONE, ABS(h)*hmax_inv*eta);
+ hprime = h * eta;
+ if (qprime < q) nscon = 0;
+ }
+
+ /* Reset etamax for the next step size change, and scale acor */
+}
+
+/*
+ * CVComputeEtaqm1
+ *
+ * This routine computes and returns the value of etaqm1 for a
+ * possible decrease in order by 1.
+ */
+
+static realtype CVComputeEtaqm1(CVodeMem cv_mem)
+{
+ realtype ddn;
+
+ etaqm1 = ZERO;
+ if (q > 1) {
+ ddn = N_VWrmsNorm(zn[q], ewt) * tq[1];
+ etaqm1 = ONE/(RPowerR(BIAS1*ddn, ONE/q) + ADDON);
+ }
+ return(etaqm1);
+}
+
+/*
+ * CVComputeEtaqp1
+ *
+ * This routine computes and returns the value of etaqp1 for a
+ * possible increase in order by 1.
+ */
+
+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) * RPowerI(h/tau[2], L);
+ N_VLinearSum(-cquot, zn[qmax], ONE, acor, tempv);
+ dup = N_VWrmsNorm(tempv, ewt) * tq[3];
+ etaqp1 = ONE / (RPowerR(BIAS3*dup, ONE/(L+1)) + ADDON);
+ }
+ return(etaqp1);
+}
+
+/*
+ * CVChooseEta
+ * Given etaqm1, etaq, etaqp1 (the values of eta for qprime =
+ * q - 1, q, or q + 1, respectively), this routine chooses the
+ * maximum eta value, sets eta to that value, and sets qprime to the
+ * corresponding value of q. If there is a tie, the preference
+ * order is to (1) keep the same order, then (2) decrease the order,
+ * and finally (3) increase the order. If the maximum eta value
+ * is below the threshhold THRESH, the order is kept unchanged and
+ * eta is set to 1.
+ */
+
+static void CVChooseEta(CVodeMem cv_mem)
+{
+ realtype etam;
+
+ etam = MAX(etaqm1, MAX(etaq, etaqp1));
+
+ if (etam < THRESH) {
+ eta = ONE;
+ qprime = q;
+ return;
+ }
+
+ if (etam == etaq) {
+
+ eta = etaq;
+ qprime = q;
+
+ } else if (etam == etaqm1) {
+
+ eta = etaqm1;
+ qprime = q - 1;
+
+ } else {
+
+ eta = etaqp1;
+ qprime = q + 1;
+
+ if (lmm == CV_BDF) {
+
+ /*
+ * Store Delta_n in zn[qmax] to be used in order increase
+ *
+ * This happens at the last step of order q before an increase
+ * to order q+1, so it represents Delta_n in the ELTE at q+1
+ */
+
+ N_VScale(ONE, acor, zn[qmax]);
+
+ }
+
+ }
+
+}
+
+/*
+ * CVHandleFailure
+ *
+ * This routine prints error messages for all cases of failure by
+ * CVHin and CVStep. It returns to CVode the value that CVode is
+ * to return to the user.
+ */
+
+static int CVHandleFailure(CVodeMem cv_mem, int flag)
+{
+
+ /* Set vector of absolute weighted local errors */
+ /*
+ N_VProd(acor, ewt, tempv);
+ N_VAbs(tempv, tempv);
+ */
+
+ /* 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);
+ break;
+ case CV_CONV_FAILURE:
+ CVProcessError(cv_mem, CV_CONV_FAILURE, "CVODE", "CVode", MSGCV_CONV_FAILS, tn, h);
+ break;
+ case CV_LSETUP_FAIL:
+ CVProcessError(cv_mem, CV_LSETUP_FAIL, "CVODE", "CVode", MSGCV_SETUP_FAILED, tn);
+ break;
+ case CV_LSOLVE_FAIL:
+ CVProcessError(cv_mem, CV_LSOLVE_FAIL, "CVODE", "CVode", MSGCV_SOLVE_FAILED, tn);
+ break;
+ case CV_RHSFUNC_FAIL:
+ CVProcessError(cv_mem, CV_RHSFUNC_FAIL, "CVODE", "CVode", MSGCV_RHSFUNC_FAILED, tn);
+ break;
+ case CV_UNREC_RHSFUNC_ERR:
+ CVProcessError(cv_mem, CV_UNREC_RHSFUNC_ERR, "CVODE", "CVode", MSGCV_RHSFUNC_UNREC, tn);
+ break;
+ case CV_REPTD_RHSFUNC_ERR:
+ CVProcessError(cv_mem, CV_REPTD_RHSFUNC_ERR, "CVODE", "CVode", MSGCV_RHSFUNC_REPTD, tn);
+ break;
+ case CV_RTFUNC_FAIL:
+ CVProcessError(cv_mem, CV_RTFUNC_FAIL, "CVODE", "CVode", MSGCV_RTFUNC_FAILED, tn);
+ break;
+ case CV_TOO_CLOSE:
+ CVProcessError(cv_mem, CV_TOO_CLOSE, "CVODE", "CVode", MSGCV_TOO_CLOSE);
+ break;
+ default:
+ return(CV_SUCCESS);
+ }
+
+ return(flag);
+
+}
+
+/*
+ * =================================================================
+ * BDF Stability Limit Detection
+ * =================================================================
+ */
+
+/*
+ * CVBDFStab
+ *
+ * This routine handles the BDF Stability Limit Detection Algorithm
+ * STALD. It is called if lmm = CV_BDF and the SLDET option is on.
+ * If the order is 3 or more, the required norm data is saved.
+ * If a decision to reduce order has not already been made, and
+ * enough data has been saved, CVsldet is called. If it signals
+ * a stability limit violation, the order is reduced, and the step
+ * size is reset accordingly.
+ */
+
+void CVBDFStab(CVodeMem cv_mem)
+{
+ int i,k, ldflag, factorial;
+ realtype sq, sqm1, sqm2;
+
+ /* 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) {
+ for (k = 1; k <= 3; k++)
+ { for (i = 5; i >= 2; i--) ssdat[i][k] = ssdat[i-1][k]; }
+ factorial = 1;
+ for (i = 1; i <= q-1; i++) factorial *= i;
+ sq = factorial*q*(q+1)*acnrm/MAX(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;
+ }
+
+ if (qprime >= 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) ) {
+ 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 = MIN(eta,etamax);
+ eta = eta/MAX(ONE,ABS(h)*hmax_inv*eta);
+ hprime = h*eta;
+ nor = nor + 1;
+ }
+ }
+ }
+ else {
+ /* Otherwise, let order increase happen, and
+ reset stability limit counter, nscon. */
+ nscon = 0;
+ }
+}
+
+/*
+ * CVsldet
+ *
+ * This routine detects stability limitation using stored scaled
+ * derivatives data. CVsldet returns the magnitude of the
+ * dominate characteristic root, rr. The presents of a stability
+ * limit is indicated by rr > "something a little less then 1.0",
+ * and a positive kflag. This routine should only be called if
+ * order is greater than or equal to 3, and data has been collected
+ * for 5 time steps.
+ *
+ * Returned values:
+ * kflag = 1 -> Found stable characteristic root, normal matrix case
+ * kflag = 2 -> Found stable characteristic root, quartic solution
+ * kflag = 3 -> Found stable characteristic root, quartic solution,
+ * with Newton correction
+ * kflag = 4 -> Found stability violation, normal matrix case
+ * kflag = 5 -> Found stability violation, quartic solution
+ * kflag = 6 -> Found stability violation, quartic solution,
+ * with Newton correction
+ *
+ * kflag < 0 -> No stability limitation,
+ * or could not compute limitation.
+ *
+ * kflag = -1 -> Min/max ratio of ssdat too small.
+ * kflag = -2 -> For normal matrix case, vmax > vrrt2*vrrt2
+ * kflag = -3 -> For normal matrix case, The three ratios
+ * are inconsistent.
+ * kflag = -4 -> Small coefficient prevents elimination of quartics.
+ * kflag = -5 -> R value from quartics not consistent.
+ * kflag = -6 -> No corrected root passes test on qk values
+ * kflag = -7 -> Trouble solving for sigsq.
+ * kflag = -8 -> Trouble solving for B, or R via B.
+ * kflag = -9 -> R via sigsq[k] disagrees with R from data.
+ */
+
+static int CVsldet(CVodeMem cv_mem)
+{
+ int i, k, j, it, kmin, kflag = 0;
+ realtype rat[5][4], rav[4], qkr[4], sigsq[4], smax[4], ssmax[4];
+ realtype drr[4], rrc[4],sqmx[4], qjk[4][4], vrat[5], qc[6][4], qco[6][4];
+ realtype rr, rrcut, vrrtol, vrrt2, sqtol, rrtol;
+ realtype smink, smaxk, sumrat, sumrsq, vmin, vmax, drrmax, adrr;
+ realtype tem, sqmax, saqk, qp, s, sqmaxk, saqj, sqmin;
+ realtype rsa, rsb, rsc, rsd, rd1a, rd1b, rd1c;
+ realtype rd2a, rd2b, rd3a, cest1, corr1;
+ realtype ratp, ratm, qfac1, qfac2, bb, rrb;
+
+ /* The following are cutoffs and tolerances used by this routine */
+
+ rrcut = RCONST(0.98);
+ vrrtol = RCONST(1.0e-4);
+ vrrt2 = RCONST(5.0e-4);
+ sqtol = RCONST(1.0e-3);
+ rrtol = RCONST(1.0e-2);
+
+ rr = ZERO;
+
+ /* Index k corresponds to the degree of the interpolating polynomial. */
+ /* k = 1 -> q-1 */
+ /* k = 2 -> q */
+ /* k = 3 -> q+1 */
+
+ /* Index i is a backward-in-time index, i = 1 -> current time, */
+ /* i = 2 -> previous step, etc */
+
+ /* get maxima, minima, and variances, and form quartic coefficients */
+
+ for (k=1; k<=3; k++) {
+ smink = ssdat[1][k];
+ smaxk = ZERO;
+
+ for (i=1; i<=5; i++) {
+ smink = MIN(smink,ssdat[i][k]);
+ smaxk = MAX(smaxk,ssdat[i][k]);
+ }
+
+ if (smink < TINY*smaxk) {
+ kflag = -1;
+ return(kflag);
+ }
+ smax[k] = smaxk;
+ ssmax[k] = smaxk*smaxk;
+
+ sumrat = ZERO;
+ sumrsq = ZERO;
+ for (i=1; i<=4; i++) {
+ rat[i][k] = ssdat[i][k]/ssdat[i+1][k];
+ sumrat = sumrat + rat[i][k];
+ sumrsq = sumrsq + rat[i][k]*rat[i][k];
+ }
+ rav[k] = FOURTH*sumrat;
+ vrat[k] = ABS(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[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];
+
+ 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
+ have common or nearly-common roots in this case.
+ Return a kflag = 1 if this procedure works. If three root
+ differ more than vrrt2, return error kflag = -3. */
+
+ vmin = MIN(vrat[1],MIN(vrat[2],vrat[3]));
+ vmax = MAX(vrat[1],MAX(vrat[2],vrat[3]));
+
+ if(vmin < vrrtol*vrrtol) {
+ if (vmax > vrrt2*vrrt2) {
+ kflag = -2;
+ return(kflag);
+ } else {
+ rr = (rav[1] + rav[2] + rav[3])/THREE;
+
+ drrmax = ZERO;
+ for(k = 1;k<=3;k++) {
+ adrr = ABS(rav[k] - rr);
+ drrmax = MAX(drrmax, adrr);
+ }
+ if (drrmax > vrrt2) {
+ kflag = -3;
+ }
+
+ kflag = 1;
+
+ /* can compute charactistic root, drop to next section */
+
+ }
+ } else {
+
+ /* use the quartics to get rr. */
+
+ if (ABS(qco[1][1]) < TINY*ssmax[1]) {
+ kflag = -4;
+ return(kflag);
+ }
+
+ tem = qco[1][2]/qco[1][1];
+ for(i=2; i<=5; i++) {
+ qco[i][2] = qco[i][2] - tem*qco[i][1];
+ }
+
+ qco[1][2] = ZERO;
+ tem = qco[1][3]/qco[1][1];
+ for(i=2; i<=5; i++) {
+ qco[i][3] = qco[i][3] - tem*qco[i][1];
+ }
+ qco[1][3] = ZERO;
+
+ if (ABS(qco[2][2]) < TINY*ssmax[2]) {
+ kflag = -4;
+ return(kflag);
+ }
+
+ tem = qco[2][3]/qco[2][2];
+ for(i=3; i<=5; i++) {
+ qco[i][3] = qco[i][3] - tem*qco[i][2];
+ }
+
+ if (ABS(qco[4][3]) < TINY*ssmax[3]) {
+ kflag = -4;
+ return(kflag);
+ }
+
+ rr = -qco[5][3]/qco[4][3];
+
+ if (rr < TINY || rr > HUN) {
+ kflag = -5;
+ return(kflag);
+ }
+
+ for(k=1; k<=3; k++) {
+ qkr[k] = qc[5][k] + rr*(qc[4][k] + rr*rr*(qc[2][k] + rr*qc[1][k]));
+ }
+
+ sqmax = ZERO;
+ for(k=1; k<=3; k++) {
+ saqk = ABS(qkr[k])/ssmax[k];
+ if (saqk > sqmax) sqmax = saqk;
+ }
+
+ if (sqmax < sqtol) {
+ kflag = 2;
+
+ /* can compute charactistic root, drop to "given rr,etc" */
+
+ } else {
+
+ /* do Newton corrections to improve rr. */
+
+ for(it=1; it<=3; it++) {
+ for(k=1; k<=3; k++) {
+ qp = qc[4][k] + rr*rr*(THREE*qc[2][k] + rr*FOUR*qc[1][k]);
+ drr[k] = ZERO;
+ if (ABS(qp) > TINY*ssmax[k]) drr[k] = -qkr[k]/qp;
+ rrc[k] = rr + drr[k];
+ }
+
+ for(k=1; k<=3; k++) {
+ s = rrc[k];
+ sqmaxk = ZERO;
+ for(j=1; j<=3; j++) {
+ qjk[j][k] = qc[5][j] + s*(qc[4][j] +
+ s*s*(qc[2][j] + s*qc[1][j]));
+ saqj = ABS(qjk[j][k])/ssmax[j];
+ if (saqj > sqmaxk) sqmaxk = saqj;
+ }
+ sqmx[k] = sqmaxk;
+ }
+
+ sqmin = sqmx[1]; kmin = 1;
+ for(k=2; k<=3; k++) {
+ if (sqmx[k] < sqmin) {
+ kmin = k;
+ sqmin = sqmx[k];
+ }
+ }
+ rr = rrc[kmin];
+
+ if (sqmin < sqtol) {
+ kflag = 3;
+ /* can compute charactistic root */
+ /* break out of Newton correction loop and drop to "given rr,etc" */
+ break;
+ } else {
+ for(j=1; j<=3; j++) {
+ qkr[j] = qjk[j][kmin];
+ }
+ }
+ } /* end of Newton correction loop */
+
+ if (sqmin > sqtol) {
+ kflag = -6;
+ return(kflag);
+ }
+ } /* end of if (sqmax < sqtol) else */
+ } /* end of if(vmin < vrrtol*vrrtol) else, quartics to get rr. */
+
+ /* given rr, find sigsq[k] and verify rr. */
+ /* 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;
+ rd1a = rsa - rsb;
+ rd1b = rsb - rsc;
+ rd1c = rsc - rsd;
+ rd2a = rd1a - rd1b;
+ rd2b = rd1b - rd1c;
+ rd3a = rd2a - rd2b;
+
+ if (ABS(rd1b) < TINY*smax[k]) {
+ kflag = -7;
+ return(kflag);
+ }
+
+ cest1 = -rd3a/rd1b;
+ if (cest1 < TINY || cest1 > FOUR) {
+ kflag = -7;
+ return(kflag);
+ }
+ corr1 = (rd2b/cest1)/(rr*rr);
+ sigsq[k] = ssdat[3][k] + corr1;
+ }
+
+ if (sigsq[2] < TINY) {
+ kflag = -8;
+ return(kflag);
+ }
+
+ ratp = sigsq[3]/sigsq[2];
+ ratm = sigsq[1]/sigsq[2];
+ qfac1 = FOURTH*(q*q - ONE);
+ qfac2 = TWO/(q - ONE);
+ bb = ratp*ratm - ONE - qfac1*ratp;
+ tem = ONE - qfac2*bb;
+
+ if (ABS(tem) < TINY) {
+ kflag = -8;
+ return(kflag);
+ }
+
+ rrb = ONE/tem;
+
+ if (ABS(rrb - rr) > rrtol) {
+ kflag = -9;
+ return(kflag);
+ }
+
+ /* Check to see if rr is above cutoff rrcut */
+ if (rr > rrcut) {
+ if (kflag == 1) kflag = 4;
+ if (kflag == 2) kflag = 5;
+ if (kflag == 3) kflag = 6;
+ }
+
+ /* All positive kflag returned at this point */
+
+ return(kflag);
+
+}
+
+/*
+ * =================================================================
+ * Root finding
+ * =================================================================
+ */
+
+/*-----------------------------------------------------------------*/
+
+/*
+ * CVRcheck1
+ *
+ * This routine completes the initialization of rootfinding memory
+ * information, and checks whether g has a zero both at and very near
+ * the initial point of the IVP.
+ *
+ * This routine returns an int equal to:
+ * CV_RTFUNC_FAIL = -12 if the g function failed, or
+ * CV_SUCCESS = 0 otherwise.
+ */
+
+static int CVRcheck1(CVodeMem cv_mem)
+{
+ int i, retval;
+ realtype smallh, hratio, tplus;
+ booleantype zroot;
+
+ for (i = 0; i < nrtfn; i++) iroots[i] = 0;
+ tlo = tn;
+ ttol = (ABS(tn) + ABS(h))*uround*HUN;
+
+ /* Evaluate g at initial t and check for zero values. */
+ retval = gfun(tlo, zn[0], glo, user_data);
+ nge = 1;
+ if (retval != 0) return(CV_RTFUNC_FAIL);
+
+ zroot = FALSE;
+ for (i = 0; i < nrtfn; i++) {
+ if (ABS(glo[i]) == ZERO) {
+ zroot = TRUE;
+ gactive[i] = FALSE;
+ }
+ }
+ if (!zroot) return(CV_SUCCESS);
+
+ /* Some g_i is zero at t0; look at g at t0+(small increment). */
+ hratio = MAX(ttol/ABS(h), TENTH);
+ smallh = hratio*h;
+ tplus = tlo + smallh;
+ N_VLinearSum(ONE, zn[0], hratio, zn[1], y);
+ retval = gfun(tplus, y, ghi, user_data);
+ 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] && ABS(ghi[i]) != ZERO) {
+ gactive[i] = TRUE;
+ glo[i] = ghi[i];
+ }
+ }
+ return(CV_SUCCESS);
+}
+
+/*
+ * CVRcheck2
+ *
+ * This routine checks for exact zeros of g at the last root found,
+ * if the last return was a root. It then checks for a close pair of
+ * zeros (an error condition), and for a new root at a nearby point.
+ * The array glo = g(tlo) at the left endpoint of the search interval
+ * is adjusted if necessary to assure that all g_i are nonzero
+ * there, before returning to do a root search in the interval.
+ *
+ * On entry, tlo = tretlast is the last value of tret returned by
+ * CVode. This may be the previous tn, the previous tout value, or
+ * the last root location.
+ *
+ * This routine returns an int equal to:
+ * CV_RTFUNC_FAIL = -12 if the g function failed, or
+ * CLOSERT = 3 if a close pair of zeros was found, or
+ * RTFOUND = 1 if a new zero of g was found near tlo, or
+ * CV_SUCCESS = 0 otherwise.
+ */
+
+static int CVRcheck2(CVodeMem cv_mem)
+{
+ int i, retval;
+ realtype smallh, hratio, tplus;
+ booleantype zroot;
+
+ if (irfnd == 0) return(CV_SUCCESS);
+
+ (void) CVodeGetDky(cv_mem, tlo, 0, y);
+ retval = gfun(tlo, y, glo, user_data);
+ 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 (ABS(glo[i]) == ZERO) {
+ zroot = TRUE;
+ iroots[i] = 1;
+ }
+ }
+ if (!zroot) return(CV_SUCCESS);
+
+ /* One or more g_i has a zero at tlo. Check g at tlo+smallh. */
+ ttol = (ABS(tn) + ABS(h))*uround*HUN;
+ smallh = (h > ZERO) ? ttol : -ttol;
+ tplus = tlo + smallh;
+ if ( (tplus - tn)*h >= ZERO) {
+ hratio = smallh/h;
+ N_VLinearSum(ONE, y, hratio, zn[1], y);
+ } else {
+ (void) CVodeGetDky(cv_mem, tplus, 0, y);
+ }
+ retval = gfun(tplus, y, ghi, user_data);
+ 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 (ABS(ghi[i]) == ZERO) {
+ if (!gactive[i]) continue;
+ if (iroots[i] == 1) return(CLOSERT);
+ zroot = TRUE;
+ iroots[i] = 1;
+ } else {
+ if (iroots[i] == 1) glo[i] = ghi[i];
+ }
+ }
+ if (zroot) return(RTFOUND);
+ return(CV_SUCCESS);
+}
+
+/*
+ * CVRcheck3
+ *
+ * This routine interfaces to CVRootfind to look for a root of g
+ * between tlo and either tn or tout, whichever comes first.
+ * Only roots beyond tlo in the direction of integration are sought.
+ *
+ * This routine returns an int equal to:
+ * CV_RTFUNC_FAIL = -12 if the g function failed, or
+ * RTFOUND = 1 if a root of g was found, or
+ * CV_SUCCESS = 0 otherwise.
+ */
+
+static int CVRcheck3(CVodeMem cv_mem)
+{
+ int i, retval, ier;
+
+ /* 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);
+ } else {
+ thi = toutc;
+ (void) CVodeGetDky(cv_mem, thi, 0, y);
+ }
+ }
+
+ /* Set ghi = g(thi) and call CVRootfind to search (tlo,thi) for roots. */
+ retval = gfun(thi, y, ghi, user_data);
+ nge++;
+ if (retval != 0) return(CV_RTFUNC_FAIL);
+
+ ttol = (ABS(tn) + ABS(h))*uround*HUN;
+ 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;
+ }
+ tlo = trout;
+ for (i = 0; i < nrtfn; i++) glo[i] = 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);
+ return(RTFOUND);
+
+}
+
+/*
+ * CVRootfind
+ *
+ * This routine solves for a root of g(t) between tlo and thi, if
+ * one exists. Only roots of odd multiplicity (i.e. with a change
+ * of sign in one of the g_i), or exact zeros, are found.
+ * Here the sign of tlo - thi is arbitrary, but if multiple roots
+ * are found, the one closest to tlo is returned.
+ *
+ * The method used is the Illinois algorithm, a modified secant method.
+ * Reference: Kathie L. Hiebert and Lawrence F. Shampine, Implicitly
+ * Defined Output Points for Solutions of ODEs, Sandia National
+ * Laboratory Report SAND80-0180, February 1980.
+ *
+ * This routine uses the following parameters for communication:
+ *
+ * nrtfn = number of functions g_i, or number of components of
+ * the vector-valued function g(t). Input only.
+ *
+ * gfun = user-defined function for g(t). Its form is
+ * (void) gfun(t, y, gt, user_data)
+ *
+ * rootdir = in array specifying the direction of zero-crossings.
+ * If rootdir[i] > 0, search for roots of g_i only if
+ * g_i is increasing; if rootdir[i] < 0, search for
+ * roots of g_i only if g_i is decreasing; otherwise
+ * always search for roots of g_i.
+ *
+ * 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
+ * both at the I.C. and at a small perturbation of them.
+ * gactive[i] is then set back on TRUE only after the
+ * corresponding g function moves away from 0.0.
+ *
+ * nge = cumulative counter for gfun calls.
+ *
+ * ttol = a convergence tolerance for trout. Input only.
+ * When a root at trout is found, it is located only to
+ * within a tolerance of ttol. Typically, ttol should
+ * be set to a value on the order of
+ * 100 * UROUND * max (ABS(tlo), ABS(thi))
+ * where UROUND is the unit roundoff of the machine.
+ *
+ * tlo, thi = endpoints of the interval in which roots are sought.
+ * On input, and must be distinct, but tlo - thi may
+ * be of either sign. The direction of integration is
+ * assumed to be from tlo to thi. On return, tlo and thi
+ * are the endpoints of the final relevant interval.
+ *
+ * glo, ghi = arrays of length nrtfn containing the vectors g(tlo)
+ * and g(thi) respectively. Input and output. On input,
+ * none of the glo[i] should be zero.
+ *
+ * trout = root location, if a root was found, or thi if not.
+ * Output only. If a root was found other than an exact
+ * zero of g, trout is the endpoint thi of the final
+ * interval bracketing the root, with size at most ttol.
+ *
+ * grout = array of length nrtfn containing g(trout) on return.
+ *
+ * iroots = int array of length nrtfn with root information.
+ * Output only. If a root was found, iroots indicates
+ * which components g_i have a root at trout. For
+ * i = 0, ..., nrtfn-1, iroots[i] = 1 if g_i has a root
+ * and g_i is increasing, iroots[i] = -1 if g_i has a
+ * root and g_i is decreasing, and iroots[i] = 0 if g_i
+ * has no roots or g_i varies in the direction opposite
+ * to that indicated by rootdir[i].
+ *
+ * This routine returns an int equal to:
+ * CV_RTFUNC_FAIL = -12 if the g function failed, or
+ * RTFOUND = 1 if a root of g was found, or
+ * CV_SUCCESS = 0 otherwise.
+ */
+
+static int CVRootfind(CVodeMem cv_mem)
+{
+ realtype alpha, tmid, gfrac, maxfrac, fracint, fracsub;
+ int i, retval, imax, side, sideprev;
+ booleantype zroot, sgnchg;
+
+ imax = 0;
+
+ /* 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 (ABS(ghi[i]) == ZERO) {
+ if(rootdir[i]*glo[i] <= ZERO) {
+ zroot = TRUE;
+ }
+ } else {
+ if ( (glo[i]*ghi[i] < ZERO) && (rootdir[i]*glo[i] <= ZERO) ) {
+ gfrac = ABS(ghi[i]/(ghi[i] - glo[i]));
+ if (gfrac > maxfrac) {
+ sgnchg = TRUE;
+ maxfrac = gfrac;
+ imax = i;
+ }
+ }
+ }
+ }
+
+ /* 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];
+ if (!zroot) return(CV_SUCCESS);
+ for (i = 0; i < nrtfn; i++) {
+ iroots[i] = 0;
+ if(!gactive[i]) continue;
+ if (ABS(ghi[i]) == ZERO) iroots[i] = glo[i] > 0 ? -1:1;
+ }
+ return(RTFOUND);
+ }
+
+ /* Initialize alpha to avoid compiler warning */
+ alpha = ONE;
+
+ /* A sign change was found. Loop to locate nearest root. */
+
+ side = 0; sideprev = -1;
+ loop { /* Looping point */
+
+ /* Set weight alpha.
+ On the first two passes, set alpha = 1. Thereafter, reset alpha
+ according to the side (low vs high) of the subinterval in which
+ the sign change was found in the previous two passes.
+ If the sides were opposite, set alpha = 1.
+ If the sides were the same, then double alpha (if high side),
+ or halve alpha (if low side).
+ The next guess tmid is the secant method value if alpha = 1, but
+ is closer to tlo if alpha < 1, and closer to thi if alpha > 1. */
+
+ if (sideprev == side) {
+ alpha = (side == 2) ? alpha*TWO : alpha*HALF;
+ } else {
+ alpha = ONE;
+ }
+
+ /* 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] - alpha*glo[imax]);
+ if (ABS(tmid - tlo) < HALF*ttol) {
+ fracint = ABS(thi - tlo)/ttol;
+ fracsub = (fracint > FIVE) ? TENTH : HALF/fracint;
+ tmid = tlo + fracsub*(thi - tlo);
+ }
+ if (ABS(thi - tmid) < HALF*ttol) {
+ fracint = ABS(thi - tlo)/ttol;
+ fracsub = (fracint > FIVE) ? TENTH : HALF/fracint;
+ tmid = thi - fracsub*(thi - tlo);
+ }
+
+ (void) CVodeGetDky(cv_mem, tmid, 0, y);
+ retval = gfun(tmid, y, grout, user_data);
+ 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;
+ sideprev = side;
+ for (i = 0; i < nrtfn; i++) {
+ if(!gactive[i]) continue;
+ if (ABS(grout[i]) == ZERO) {
+ if(rootdir[i]*glo[i] <= ZERO) {
+ zroot = TRUE;
+ }
+ } else {
+ if ( (glo[i]*grout[i] < ZERO) && (rootdir[i]*glo[i] <= ZERO) ) {
+ gfrac = ABS(grout[i]/(grout[i] - glo[i]));
+ if (gfrac > maxfrac) {
+ sgnchg = TRUE;
+ maxfrac = gfrac;
+ imax = i;
+ }
+ }
+ }
+ }
+ if (sgnchg) {
+ /* Sign change found in (tlo,tmid); replace thi with tmid. */
+ thi = tmid;
+ for (i = 0; i < nrtfn; i++) ghi[i] = grout[i];
+ side = 1;
+ /* Stop at root thi if converged; otherwise loop. */
+ if (ABS(thi - tlo) <= 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];
+ 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];
+ side = 2;
+ /* Stop at root thi if converged; otherwise loop back. */
+ if (ABS(thi - tlo) <= 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 ( (ABS(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;
+ }
+ return(RTFOUND);
+}
+
+/*
+ * =================================================================
+ * Internal EWT function
+ * =================================================================
+ */
+
+/*
+ * CVEwtSet
+ *
+ * This routine is responsible for setting the error weight vector ewt,
+ * according to tol_type, as follows:
+ *
+ * (1) ewt[i] = 1 / (reltol * ABS(ycur[i]) + *abstol), i=0,...,neq-1
+ * if tol_type = CV_SS
+ * (2) ewt[i] = 1 / (reltol * ABS(ycur[i]) + abstol[i]), i=0,...,neq-1
+ * if tol_type = CV_SV
+ *
+ * CVEwtSet returns 0 if ewt is successfully set as above to a
+ * positive vector and -1 otherwise. In the latter case, ewt is
+ * considered undefined.
+ *
+ * All the real work is done in the routines CVEwtSetSS, CVEwtSetSV.
+ */
+
+int CVEwtSet(N_Vector ycur, N_Vector weight, void *data)
+{
+ CVodeMem cv_mem;
+ int flag = 0;
+
+ /* data points to cv_mem here */
+
+ cv_mem = (CVodeMem) data;
+
+ switch(itol) {
+ case CV_SS:
+ flag = CVEwtSetSS(cv_mem, ycur, weight);
+ break;
+ case CV_SV:
+ flag = CVEwtSetSV(cv_mem, ycur, weight);
+ break;
+ }
+
+ return(flag);
+}
+
+/*
+ * CVEwtSetSS
+ *
+ * This routine sets ewt as decribed above in the case tol_type = CV_SS.
+ * It tests for non-positive components before inverting. CVEwtSetSS
+ * returns 0 if ewt is successfully set to a positive vector
+ * and -1 otherwise. In the latter case, ewt is considered undefined.
+ */
+
+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);
+ return(0);
+}
+
+/*
+ * CVEwtSetSV
+ *
+ * This routine sets ewt as decribed above in the case tol_type = CV_SV.
+ * It tests for non-positive components before inverting. CVEwtSetSV
+ * returns 0 if ewt is successfully set to a positive vector
+ * and -1 otherwise. In the latter case, ewt is considered undefined.
+ */
+
+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);
+ return(0);
+}
+
+/*
+ * =================================================================
+ * CVODE Error Handling function
+ * =================================================================
+ */
+
+/*
+ * CVProcessError is a high level error handling function
+ * - if cv_mem==NULL it prints the error message to stderr
+ * - otherwise, it sets-up and calls the error hadling function
+ * 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, ...)
+{
+ va_list ap;
+ char msg[256];
+
+ /* Initialize the argument pointer variable
+ (msgfmt is the last required argument to CVProcessError) */
+
+ va_start(ap, msgfmt);
+
+ if (cv_mem == NULL) { /* We write to stderr */
+
+#ifndef NO_FPRINTF_OUTPUT
+ fprintf(stderr, "\n[%s ERROR] %s\n ", module, fname);
+ fprintf(stderr, msgfmt);
+ fprintf(stderr, "\n\n");
+#endif
+
+ } else { /* We can call ehfun */
+
+ /* Compose the message */
+
+ vsprintf(msg, msgfmt, ap);
+
+ /* Call ehfun */
+
+ ehfun(error_code, module, fname, msg, eh_data);
+
+ }
+
+ /* Finalize argument processing */
+
+ va_end(ap);
+
+ return;
+
+}
+
+/* CVErrHandler is the default error handling function.
+ 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)
+{
+ CVodeMem cv_mem;
+ char err_type[10];
+
+ /* data points to cv_mem here */
+
+ cv_mem = (CVodeMem) data;
+
+ if (error_code == CV_WARNING)
+ sprintf(err_type,"WARNING");
+ else
+ 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);
+ }
+#endif
+
+ return;
+}
diff --git a/src/cvode/cvode_band.c b/src/cvode/cvode_band.c
new file mode 100644
index 0000000..9ea0b4a
--- /dev/null
+++ b/src/cvode/cvode_band.c
@@ -0,0 +1,361 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.13 $
+ * $Date: 2011/03/23 22:27:43 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh and
+ * Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * 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 void 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;
+
+ 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 = MIN(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;
+
+ nje = 0;
+ nfeDQ = 0;
+ nstlj = 0;
+
+ /* 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 = ABS((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 void 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;
+}
+
diff --git a/src/cvode/cvode_bandpre.c b/src/cvode/cvode_bandpre.c
new file mode 100644
index 0000000..6892ba6
--- /dev/null
+++ b/src/cvode/cvode_bandpre.c
@@ -0,0 +1,478 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.8 $
+ * $Date: 2010/12/01 22:21:04 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh, Radu Serban,
+ * and Aaron Collier @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * This file contains implementations of the banded difference
+ * quotient Jacobian-based preconditioner and solver routines for
+ * use with the CVSPILS linear solvers..
+ * -----------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#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);
+
+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);
+
+/* Prototype for CVBandPrecFree */
+
+static void 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)
+{
+ CVodeMem cv_mem;
+ CVSpilsMem cvspils_mem;
+ CVBandPrecData pdata;
+ long int mup, mlp, storagemu;
+ int flag;
+
+ if (cvode_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 */
+ if (cv_mem->cv_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);
+ return(CVSPILS_ILL_INPUT);
+ }
+
+ pdata = NULL;
+ pdata = (CVBandPrecData) malloc(sizeof *pdata); /* Allocate data memory */
+ if (pdata == NULL) {
+ CVProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVBANDPRE", "CVBandPrecInit", MSGBP_MEM_FAIL);
+ return(CVSPILS_MEM_FAIL);
+ }
+
+ /* Load pointers and bandwidths into pdata block. */
+ pdata->cvode_mem = cvode_mem;
+ pdata->N = N;
+ pdata->mu = mup = MIN(N-1, MAX(0,mu));
+ pdata->ml = mlp = MIN(N-1, MAX(0,ml));
+
+ /* Initialize nfeBP counter */
+ pdata->nfeBP = 0;
+
+ /* Allocate memory for saved banded Jacobian approximation. */
+ pdata->savedJ = NULL;
+ pdata->savedJ = NewBandMat(N, mup, mlp, mup);
+ if (pdata->savedJ == NULL) {
+ free(pdata); pdata = NULL;
+ CVProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVBANDPRE", "CVBandPrecInit", MSGBP_MEM_FAIL);
+ return(CVSPILS_MEM_FAIL);
+ }
+
+ /* Allocate memory for banded preconditioner. */
+ storagemu = MIN(N-1, mup+mlp);
+ pdata->savedP = NULL;
+ pdata->savedP = NewBandMat(N, mup, mlp, storagemu);
+ if (pdata->savedP == NULL) {
+ DestroyMat(pdata->savedJ);
+ free(pdata); pdata = NULL;
+ 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);
+ free(pdata); pdata = NULL;
+ CVProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVBANDPRE", "CVBandPrecInit", MSGBP_MEM_FAIL);
+ return(CVSPILS_MEM_FAIL);
+ }
+
+ /* Overwrite the P_data field in the SPILS memory */
+ cvspils_mem->s_P_data = pdata;
+
+ /* Attach the pfree function */
+ cvspils_mem->s_pfree = CVBandPrecFree;
+
+ /* Attach preconditioner solve and setup functions */
+ flag = CVSpilsSetPreconditioner(cvode_mem, CVBandPrecSetup, CVBandPrecSolve);
+
+ return(flag);
+}
+
+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;
+
+
+ if (cvode_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);
+ 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);
+ return(CVSPILS_PMEM_NULL);
+ }
+ pdata = (CVBandPrecData) cvspils_mem->s_P_data;
+
+ N = pdata->N;
+ mu = pdata->mu;
+ ml = pdata->ml;
+ smu = MIN( N-1, mu + ml);
+
+ *leniwBP = pdata->N;
+ *lenrwBP = N * ( 2*ml + smu + mu + 2 );
+
+ return(CVSPILS_SUCCESS);
+}
+
+int CVBandPrecGetNumRhsEvals(void *cvode_mem, long int *nfevalsBP)
+{
+ CVodeMem cv_mem;
+ CVSpilsMem cvspils_mem;
+ CVBandPrecData pdata;
+
+ if (cvode_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);
+ 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);
+ return(CVSPILS_PMEM_NULL);
+ }
+ pdata = (CVBandPrecData) cvspils_mem->s_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.
+ * -----------------------------------------------------------------
+ */
+
+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)
+{
+ CVBandPrecData pdata;
+ CVodeMem cv_mem;
+ int retval;
+ long int 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);
+
+ } else {
+
+ /* If jok = FALSE, call CVBandPDQJac for new J value. */
+ *jcurPtr = TRUE;
+ SetToZero(savedJ);
+
+ retval = CVBandPDQJac(pdata, t, y, fy, tmp1, tmp2);
+ if (retval < 0) {
+ CVProcessError(cv_mem, -1, "CVBANDPRE", "CVBandPrecSetup", MSGBP_RHSFUNC_FAILED);
+ return(-1);
+ }
+ if (retval > 0) {
+ return(1);
+ }
+
+ BandCopy(savedJ, savedP, mu, ml);
+
+ }
+
+ /* 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);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * 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)
+{
+ CVBandPrecData pdata;
+ realtype *zd;
+
+ /* 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);
+}
+
+
+static void CVBandPrecFree(CVodeMem cv_mem)
+{
+ CVSpilsMem cvspils_mem;
+ CVBandPrecData pdata;
+
+ if (cv_mem->cv_lmem == NULL) return;
+ cvspils_mem = (CVSpilsMem) cv_mem->cv_lmem;
+
+ if (cvspils_mem->s_P_data == NULL) return;
+ pdata = (CVBandPrecData) cvspils_mem->s_P_data;
+
+ DestroyMat(savedJ);
+ DestroyMat(savedP);
+ DestroyArray(lpivots);
+
+ free(pdata);
+ pdata = NULL;
+}
+
+#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)
+{
+ CVodeMem cv_mem;
+ realtype fnorm, minInc, inc, inc_inv, srur;
+ long int 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);
+ fy_data = N_VGetArrayPointer(fy);
+ ftemp_data = N_VGetArrayPointer(ftemp);
+ y_data = N_VGetArrayPointer(y);
+ ytemp_data = N_VGetArrayPointer(ytemp);
+
+ /* Load ytemp with y = predicted y vector. */
+ N_VScale(ONE, y, ytemp);
+
+ /* Set minimum increment based on uround and norm of f. */
+ srur = RSqrt(uround);
+ fnorm = N_VWrmsNorm(fy, ewt);
+ minInc = (fnorm != ZERO) ?
+ (MIN_INC_MULT * ABS(h) * uround * N * fnorm) : ONE;
+
+ /* Set bandwidth and number of column groups for band differencing. */
+ width = ml + mu + 1;
+ ngroups = MIN(width, N);
+
+ for (group = 1; group <= ngroups; group++) {
+
+ /* Increment all y_j in group. */
+ for(j = group-1; j < N; j += width) {
+ inc = MAX(srur*ABS(y_data[j]), minInc/ewt_data[j]);
+ ytemp_data[j] += inc;
+ }
+
+ /* Evaluate f with incremented y. */
+
+ retval = f(t, ytemp, ftemp, user_data);
+ nfeBP++;
+ if (retval != 0) return(retval);
+
+ /* 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(savedJ,j);
+ inc = MAX(srur*ABS(y_data[j]), minInc/ewt_data[j]);
+ inc_inv = ONE/inc;
+ i1 = MAX(0, j-mu);
+ i2 = MIN(j+ml, N-1);
+ for (i=i1; i <= i2; i++)
+ BAND_COL_ELEM(col_j,i,j) =
+ inc_inv * (ftemp_data[i] - fy_data[i]);
+ }
+ }
+
+ return(0);
+}
diff --git a/src/cvode/cvode_bandpre_impl.h b/src/cvode/cvode_bandpre_impl.h
new file mode 100644
index 0000000..09e56d3
--- /dev/null
+++ b/src/cvode/cvode_bandpre_impl.h
@@ -0,0 +1,76 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.7 $
+ * $Date: 2010/12/01 22:19:48 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Michael Wittman, Alan C. Hindmarsh and
+ * Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * Implementation header file for the CVBANDPRE module.
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _CVBANDPRE_IMPL_H
+#define _CVBANDPRE_IMPL_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <cvode/cvode_bandpre.h>
+#include <sundials/sundials_band.h>
+#include <sundials/sundials_direct.h>
+
+/*
+ * -----------------------------------------------------------------
+ * Type: CVBandPrecData
+ * -----------------------------------------------------------------
+ */
+
+typedef struct CVBandPrecDataRec {
+
+ /* Data set by user in CVBandPrecInit */
+
+ long int N;
+ long int ml, mu;
+
+ /* Data set by CVBandPrecSetup */
+
+ DlsMat savedJ;
+ DlsMat savedP;
+ long int *lpivots;
+
+ /* Rhs calls */
+
+ long int nfeBP;
+
+ /* Pointer to cvode_mem */
+
+ void *cvode_mem;
+
+} *CVBandPrecData;
+
+/*
+ * -----------------------------------------------------------------
+ * 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_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."
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/cvode/cvode_bbdpre.c b/src/cvode/cvode_bbdpre.c
new file mode 100644
index 0000000..30f6844
--- /dev/null
+++ b/src/cvode/cvode_bbdpre.c
@@ -0,0 +1,550 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.9 $
+ * $Date: 2010/12/01 22:21:04 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Michael Wittman, Alan C. Hindmarsh, Radu Serban,
+ * and Aaron Collier @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * 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.
+ * -----------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#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>
+
+#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);
+
+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);
+
+/* Prototype for CVBBDPrecFree */
+static void 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)
+{
+ CVodeMem cv_mem;
+ CVSpilsMem cvspils_mem;
+ CVBBDPrecData pdata;
+ long int muk, mlk, storage_mu;
+ int flag;
+
+ if (cvode_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 */
+ if (cv_mem->cv_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);
+ return(CVSPILS_ILL_INPUT);
+ }
+
+ /* Allocate data memory */
+ pdata = NULL;
+ pdata = (CVBBDPrecData) malloc(sizeof *pdata);
+ if (pdata == NULL) {
+ CVProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVBBDPRE", "CVBBDPrecInit", MSGBBD_MEM_FAIL);
+ return(CVSPILS_MEM_FAIL);
+ }
+
+ /* Set pointers to gloc and cfn; load half-bandwidths */
+ pdata->cvode_mem = cvode_mem;
+ pdata->gloc = gloc;
+ pdata->cfn = cfn;
+ pdata->mudq = MIN(Nlocal-1, MAX(0,mudq));
+ pdata->mldq = MIN(Nlocal-1, MAX(0,mldq));
+ muk = MIN(Nlocal-1, MAX(0,mukeep));
+ mlk = MIN(Nlocal-1, MAX(0,mlkeep));
+ pdata->mukeep = muk;
+ pdata->mlkeep = mlk;
+
+ /* Allocate memory for saved Jacobian */
+ pdata->savedJ = NewBandMat(Nlocal, muk, mlk, muk);
+ if (pdata->savedJ == NULL) {
+ free(pdata); pdata = NULL;
+ CVProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVBBDPRE", "CVBBDPrecInit", MSGBBD_MEM_FAIL);
+ return(CVSPILS_MEM_FAIL);
+ }
+
+ /* Allocate memory for preconditioner matrix */
+ storage_mu = MIN(Nlocal-1, muk + mlk);
+ pdata->savedP = NULL;
+ pdata->savedP = NewBandMat(Nlocal, muk, mlk, storage_mu);
+ if (pdata->savedP == NULL) {
+ DestroyMat(pdata->savedJ);
+ free(pdata); pdata = NULL;
+ 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);
+ free(pdata); pdata = NULL;
+ CVProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVBBDPRE", "CVBBDPrecInit", MSGBBD_MEM_FAIL);
+ return(CVSPILS_MEM_FAIL);
+ }
+
+ /* Set pdata->dqrely based on input dqrely (0 implies default). */
+ pdata->dqrely = (dqrely > ZERO) ? dqrely : RSqrt(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->nge = 0;
+
+ /* Overwrite the P_data field in the SPILS memory */
+ cvspils_mem->s_P_data = pdata;
+
+ /* Attach the pfree function */
+ cvspils_mem->s_pfree = CVBBDPrecFree;
+
+ /* Attach preconditioner solve and setup functions */
+ flag = CVSpilsSetPreconditioner(cvode_mem, CVBBDPrecSetup, CVBBDPrecSolve);
+
+ return(flag);
+}
+
+
+int CVBBDPrecReInit(void *cvode_mem,
+ long int mudq, long int mldq,
+ realtype dqrely)
+{
+ CVodeMem cv_mem;
+ CVSpilsMem cvspils_mem;
+ CVBBDPrecData pdata;
+ long int Nlocal;
+
+ if (cvode_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 */
+ if (cv_mem->cv_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);
+ return(CVSPILS_PMEM_NULL);
+ }
+ pdata = (CVBBDPrecData) cvspils_mem->s_P_data;
+
+ /* Load half-bandwidths */
+ Nlocal = pdata->n_local;
+ pdata->mudq = MIN(Nlocal-1, MAX(0,mudq));
+ pdata->mldq = MIN(Nlocal-1, MAX(0,mldq));
+
+ /* Set pdata->dqrely based on input dqrely (0 implies default). */
+ pdata->dqrely = (dqrely > ZERO) ? dqrely : RSqrt(uround);
+
+ /* Re-initialize nge */
+ pdata->nge = 0;
+
+ return(CVSPILS_SUCCESS);
+}
+
+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);
+ 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);
+ 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);
+ return(CVSPILS_PMEM_NULL);
+ }
+ pdata = (CVBBDPrecData) cvspils_mem->s_P_data;
+
+ *lenrwBBDP = pdata->rpwsize;
+ *leniwBBDP = pdata->ipwsize;
+
+ return(CVSPILS_SUCCESS);
+}
+
+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);
+ 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);
+ 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);
+ return(CVSPILS_PMEM_NULL);
+ }
+ pdata = (CVBBDPrecData) cvspils_mem->s_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).
+ * -----------------------------------------------------------------
+ */
+
+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)
+{
+ long int ier;
+ CVBBDPrecData pdata;
+ CVodeMem cv_mem;
+ int retval;
+
+ pdata = (CVBBDPrecData) bbd_data;
+
+ cv_mem = (CVodeMem) pdata->cvode_mem;
+
+ if (jok) {
+
+ /* If jok = TRUE, use saved copy of J */
+ *jcurPtr = FALSE;
+ BandCopy(savedJ, savedP, mukeep, mlkeep);
+
+ } else {
+
+ /* Otherwise call CVBBDDQJac for new J value */
+ *jcurPtr = TRUE;
+ SetToZero(savedJ);
+
+ retval = CVBBDDQJac(pdata, t, y, tmp1, tmp2, tmp3);
+ if (retval < 0) {
+ CVProcessError(cv_mem, -1, "CVBBDPRE", "CVBBDPrecSetup", MSGBBD_FUNC_FAILED);
+ return(-1);
+ }
+ if (retval > 0) {
+ return(1);
+ }
+
+ BandCopy(savedJ, savedP, mukeep, mlkeep);
+
+ }
+
+ /* 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);
+
+ /* Return 0 if the LU was complete; otherwise return 1 */
+ if (ier > 0) return(1);
+ return(0);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * 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)
+{
+ CVBBDPrecData pdata;
+ realtype *zd;
+
+ pdata = (CVBBDPrecData) bbd_data;
+
+ /* Copy r to z, then do backsolve and return */
+ N_VScale(ONE, r, z);
+
+ zd = N_VGetArrayPointer(z);
+
+ BandGBTRS(savedP, lpivots, zd);
+
+ return(0);
+}
+
+
+static void CVBBDPrecFree(CVodeMem cv_mem)
+{
+ CVSpilsMem cvspils_mem;
+ CVBBDPrecData pdata;
+
+ if (cv_mem->cv_lmem == NULL) return;
+ cvspils_mem = (CVSpilsMem) cv_mem->cv_lmem;
+
+ if (cvspils_mem->s_P_data == NULL) return;
+ pdata = (CVBBDPrecData) cvspils_mem->s_P_data;
+
+ DestroyMat(savedJ);
+ DestroyMat(savedP);
+ DestroyArray(lpivots);
+
+ free(pdata);
+ pdata = NULL;
+}
+
+
+#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)
+{
+ CVodeMem cv_mem;
+ realtype gnorm, minInc, inc, inc_inv;
+ long int group, i, j, width, ngroups, i1, i2;
+ realtype *y_data, *ewt_data, *gy_data, *gtemp_data, *ytemp_data, *col_j;
+ int retval;
+
+ cv_mem = (CVodeMem) pdata->cvode_mem;
+
+ /* Load ytemp with y = predicted solution vector */
+ 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 (retval != 0) return(retval);
+ }
+
+ retval = gloc(Nlocal, t, ytemp, gy, user_data);
+ 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);
+ 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);
+ minInc = (gnorm != ZERO) ?
+ (MIN_INC_MULT * ABS(h) * uround * Nlocal * gnorm) : ONE;
+
+ /* Set bandwidth and number of column groups for band differencing */
+ width = mldq + mudq + 1;
+ ngroups = MIN(width, Nlocal);
+
+ /* Loop over groups */
+ for (group=1; group <= ngroups; group++) {
+
+ /* Increment all y_j in group */
+ for(j=group-1; j < Nlocal; j+=width) {
+ inc = MAX(dqrely*ABS(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++;
+ if (retval != 0) return(retval);
+
+ /* Restore ytemp, then form and load difference quotients */
+ for (j=group-1; j < Nlocal; j+=width) {
+ ytemp_data[j] = y_data[j];
+ col_j = BAND_COL(savedJ,j);
+ inc = MAX(dqrely*ABS(y_data[j]), minInc/ewt_data[j]);
+ inc_inv = ONE/inc;
+ i1 = MAX(0, j-mukeep);
+ i2 = MIN(j+mlkeep, Nlocal-1);
+ for (i=i1; i <= i2; i++)
+ BAND_COL_ELEM(col_j,i,j) =
+ inc_inv * (gtemp_data[i] - gy_data[i]);
+ }
+ }
+
+ return(0);
+}
diff --git a/src/cvode/cvode_bbdpre_impl.h b/src/cvode/cvode_bbdpre_impl.h
new file mode 100644
index 0000000..10bb8bc
--- /dev/null
+++ b/src/cvode/cvode_bbdpre_impl.h
@@ -0,0 +1,82 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.6 $
+ * $Date: 2010/12/01 22:19:48 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Michael Wittman, Alan C. Hindmarsh and
+ * Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * Implementation header file for the CVBBDPRE module.
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _CVBBDPRE_IMPL_H
+#define _CVBBDPRE_IMPL_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <cvode/cvode_bbdpre.h>
+#include <sundials/sundials_band.h>
+
+/*
+ * -----------------------------------------------------------------
+ * Type: CVBBDPrecData
+ * -----------------------------------------------------------------
+ */
+
+typedef struct CVBBDPrecDataRec {
+
+ /* passed by user to CVBBDPrecAlloc and used by PrecSetup/PrecSolve */
+
+ long int 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;
+
+ /* available for optional output */
+
+ long int rpwsize;
+ long int ipwsize;
+ long int nge;
+
+ /* pointer to cvode_mem */
+
+ void *cvode_mem;
+
+} *CVBBDPrecData;
+
+/*
+ * -----------------------------------------------------------------
+ * 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_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."
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/cvode/cvode_dense.c b/src/cvode/cvode_dense.c
new file mode 100644
index 0000000..a2e9f3b
--- /dev/null
+++ b/src/cvode/cvode_dense.c
@@ -0,0 +1,341 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.12 $
+ * $Date: 2010/12/01 22:21:04 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh and
+ * Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * 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 void 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;
+
+ 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;
+
+ 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 = ABS((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 void 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;
+}
+
diff --git a/src/cvode/cvode_diag.c b/src/cvode/cvode_diag.c
new file mode 100644
index 0000000..b7cfba2
--- /dev/null
+++ b/src/cvode/cvode_diag.c
@@ -0,0 +1,437 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.6 $
+ * $Date: 2010/12/01 22:21:04 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh and
+ * Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * This is the implementation file for the CVDIAG linear solver.
+ * -----------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "cvode_diag_impl.h"
+#include "cvode_impl.h"
+
+/* Other Constants */
+
+#define FRACT RCONST(0.1)
+#define ONE RCONST(1.0)
+
+/* CVDIAG linit, lsetup, lsolve, and lfree routines */
+
+static int CVDiagInit(CVodeMem cv_mem);
+
+static int CVDiagSetup(CVodeMem cv_mem, int convfail, N_Vector ypred,
+ N_Vector fpred, booleantype *jcurPtr, N_Vector vtemp1,
+ N_Vector vtemp2, N_Vector vtemp3);
+
+static int CVDiagSolve(CVodeMem cv_mem, N_Vector b, N_Vector weight,
+ N_Vector ycur, N_Vector fcur);
+
+static void CVDiagFree(CVodeMem cv_mem);
+
+/* Readability Replacements */
+
+#define lrw1 (cv_mem->cv_lrw1)
+#define liw1 (cv_mem->cv_liw1)
+#define f (cv_mem->cv_f)
+#define uround (cv_mem->cv_uround)
+#define tn (cv_mem->cv_tn)
+#define h (cv_mem->cv_h)
+#define rl1 (cv_mem->cv_rl1)
+#define gamma (cv_mem->cv_gamma)
+#define ewt (cv_mem->cv_ewt)
+#define nfe (cv_mem->cv_nfe)
+#define zn (cv_mem->cv_zn)
+#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 gammasv (cvdiag_mem->di_gammasv)
+#define M (cvdiag_mem->di_M)
+#define bit (cvdiag_mem->di_bit)
+#define bitcomp (cvdiag_mem->di_bitcomp)
+#define nfeDI (cvdiag_mem->di_nfeDI)
+#define last_flag (cvdiag_mem->di_last_flag)
+
+/*
+ * -----------------------------------------------------------------
+ * CVDiag
+ * -----------------------------------------------------------------
+ * This routine initializes the memory record and sets various function
+ * fields specific to the diagonal 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 CVDiagInit, CVDiagSetup, CVDiagSolve, and CVDiagFree,
+ * 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.
+ * The CVDiag return value is SUCCESS = 0, LMEM_FAIL = -1, or
+ * LIN_ILL_INPUT=-2.
+ * -----------------------------------------------------------------
+ */
+
+int CVDiag(void *cvode_mem)
+{
+ CVodeMem cv_mem;
+ CVDiagMem cvdiag_mem;
+
+ /* Return immediately if cvode_mem is NULL */
+ if (cvode_mem == NULL) {
+ CVProcessError(NULL, CVDIAG_MEM_NULL, "CVDIAG", "CVDiag", MSGDG_CVMEM_NULL);
+ return(CVDIAG_MEM_NULL);
+ }
+ cv_mem = (CVodeMem) cvode_mem;
+
+ /* Check if N_VCompare and N_VInvTest are present */
+ if(vec_tmpl->ops->nvcompare == NULL ||
+ vec_tmpl->ops->nvinvtest == NULL) {
+ CVProcessError(cv_mem, CVDIAG_ILL_INPUT, "CVDIAG", "CVDiag", MSGDG_BAD_NVECTOR);
+ return(CVDIAG_ILL_INPUT);
+ }
+
+ if (lfree != NULL) lfree(cv_mem);
+
+ /* Set four main function fields in cv_mem */
+ linit = CVDiagInit;
+ lsetup = CVDiagSetup;
+ lsolve = CVDiagSolve;
+ lfree = CVDiagFree;
+
+ /* Get memory for CVDiagMemRec */
+ cvdiag_mem = NULL;
+ cvdiag_mem = (CVDiagMem) malloc(sizeof(CVDiagMemRec));
+ if (cvdiag_mem == NULL) {
+ CVProcessError(cv_mem, CVDIAG_MEM_FAIL, "CVDIAG", "CVDiag", MSGDG_MEM_FAIL);
+ return(CVDIAG_MEM_FAIL);
+ }
+
+ 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);
+ free(cvdiag_mem); cvdiag_mem = NULL;
+ return(CVDIAG_MEM_FAIL);
+ }
+
+ bit = N_VClone(vec_tmpl);
+ if (bit == NULL) {
+ CVProcessError(cv_mem, CVDIAG_MEM_FAIL, "CVDIAG", "CVDiag", MSGDG_MEM_FAIL);
+ N_VDestroy(M);
+ free(cvdiag_mem); cvdiag_mem = NULL;
+ return(CVDIAG_MEM_FAIL);
+ }
+
+ bitcomp = N_VClone(vec_tmpl);
+ if (bitcomp == NULL) {
+ CVProcessError(cv_mem, CVDIAG_MEM_FAIL, "CVDIAG", "CVDiag", MSGDG_MEM_FAIL);
+ N_VDestroy(M);
+ N_VDestroy(bit);
+ free(cvdiag_mem); cvdiag_mem = NULL;
+ return(CVDIAG_MEM_FAIL);
+ }
+
+ /* Attach linear solver memory to integrator memory */
+ lmem = cvdiag_mem;
+
+ return(CVDIAG_SUCCESS);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * CVDiagGetWorkSpace
+ * -----------------------------------------------------------------
+ */
+
+int CVDiagGetWorkSpace(void *cvode_mem, long int *lenrwLS, long int *leniwLS)
+{
+ CVodeMem cv_mem;
+
+ /* Return immediately if cvode_mem is NULL */
+ if (cvode_mem == NULL) {
+ CVProcessError(NULL, CVDIAG_MEM_NULL, "CVDIAG", "CVDiagGetWorkSpace", MSGDG_CVMEM_NULL);
+ return(CVDIAG_MEM_NULL);
+ }
+ cv_mem = (CVodeMem) cvode_mem;
+
+ *lenrwLS = 3*lrw1;
+ *leniwLS = 3*liw1;
+
+ return(CVDIAG_SUCCESS);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * CVDiagGetNumRhsEvals
+ * -----------------------------------------------------------------
+ */
+
+int CVDiagGetNumRhsEvals(void *cvode_mem, long int *nfevalsLS)
+{
+ CVodeMem cv_mem;
+ CVDiagMem cvdiag_mem;
+
+ /* Return immediately if cvode_mem is NULL */
+ if (cvode_mem == NULL) {
+ CVProcessError(NULL, CVDIAG_MEM_NULL, "CVDIAG", "CVDiagGetNumRhsEvals", MSGDG_CVMEM_NULL);
+ return(CVDIAG_MEM_NULL);
+ }
+ cv_mem = (CVodeMem) cvode_mem;
+
+ if (lmem == NULL) {
+ CVProcessError(cv_mem, CVDIAG_LMEM_NULL, "CVDIAG", "CVDiagGetNumRhsEvals", MSGDG_LMEM_NULL);
+ return(CVDIAG_LMEM_NULL);
+ }
+ cvdiag_mem = (CVDiagMem) lmem;
+
+ *nfevalsLS = nfeDI;
+
+ return(CVDIAG_SUCCESS);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * CVDiagGetLastFlag
+ * -----------------------------------------------------------------
+ */
+
+int CVDiagGetLastFlag(void *cvode_mem, long int *flag)
+{
+ CVodeMem cv_mem;
+ CVDiagMem cvdiag_mem;
+
+ /* Return immediately if cvode_mem is NULL */
+ if (cvode_mem == NULL) {
+ CVProcessError(NULL, CVDIAG_MEM_NULL, "CVDIAG", "CVDiagGetLastFlag", MSGDG_CVMEM_NULL);
+ return(CVDIAG_MEM_NULL);
+ }
+ cv_mem = (CVodeMem) cvode_mem;
+
+ if (lmem == NULL) {
+ CVProcessError(cv_mem, CVDIAG_LMEM_NULL, "CVDIAG", "CVDiagGetLastFlag", MSGDG_LMEM_NULL);
+ return(CVDIAG_LMEM_NULL);
+ }
+ cvdiag_mem = (CVDiagMem) lmem;
+
+ *flag = last_flag;
+
+ return(CVDIAG_SUCCESS);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * CVDiagGetReturnFlagName
+ * -----------------------------------------------------------------
+ */
+
+char *CVDiagGetReturnFlagName(long int flag)
+{
+ char *name;
+
+ name = (char *)malloc(30*sizeof(char));
+
+ switch(flag) {
+ case CVDIAG_SUCCESS:
+ sprintf(name,"CVDIAG_SUCCESS");
+ break;
+ case CVDIAG_MEM_NULL:
+ sprintf(name,"CVDIAG_MEM_NULL");
+ break;
+ case CVDIAG_LMEM_NULL:
+ sprintf(name,"CVDIAG_LMEM_NULL");
+ break;
+ case CVDIAG_ILL_INPUT:
+ sprintf(name,"CVDIAG_ILL_INPUT");
+ break;
+ case CVDIAG_MEM_FAIL:
+ sprintf(name,"CVDIAG_MEM_FAIL");
+ break;
+ case CVDIAG_INV_FAIL:
+ sprintf(name,"CVDIAG_INV_FAIL");
+ break;
+ case CVDIAG_RHSFUNC_UNRECVR:
+ sprintf(name,"CVDIAG_RHSFUNC_UNRECVR");
+ break;
+ case CVDIAG_RHSFUNC_RECVR:
+ sprintf(name,"CVDIAG_RHSFUNC_RECVR");
+ break;
+ default:
+ sprintf(name,"NONE");
+ }
+
+ return(name);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * CVDiagInit
+ * -----------------------------------------------------------------
+ * This routine does remaining initializations specific to the diagonal
+ * linear solver.
+ * -----------------------------------------------------------------
+ */
+
+static int CVDiagInit(CVodeMem cv_mem)
+{
+ CVDiagMem cvdiag_mem;
+
+ cvdiag_mem = (CVDiagMem) lmem;
+
+ nfeDI = 0;
+
+ last_flag = CVDIAG_SUCCESS;
+ return(0);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * CVDiagSetup
+ * -----------------------------------------------------------------
+ * This routine does the setup operations for the diagonal linear
+ * solver. It constructs a diagonal approximation to the Newton matrix
+ * M = I - gamma*J, updates counters, and inverts M.
+ * -----------------------------------------------------------------
+ */
+
+static int CVDiagSetup(CVodeMem cv_mem, int convfail, N_Vector ypred,
+ N_Vector fpred, booleantype *jcurPtr, N_Vector vtemp1,
+ N_Vector vtemp2, N_Vector vtemp3)
+{
+ realtype r;
+ N_Vector ftemp, y;
+ booleantype invOK;
+ CVDiagMem cvdiag_mem;
+ int retval;
+
+ cvdiag_mem = (CVDiagMem) lmem;
+
+ /* Rename work vectors for use as temporary values of y and f */
+ ftemp = vtemp1;
+ y = vtemp2;
+
+ /* Form y with perturbation = FRACT*(func. iter. correction) */
+ r = FRACT * rl1;
+ N_VLinearSum(h, fpred, -ONE, zn[1], ftemp);
+ N_VLinearSum(r, ftemp, ONE, ypred, y);
+
+ /* Evaluate f at perturbed y */
+ retval = f(tn, y, M, cv_mem->cv_user_data);
+ nfeDI++;
+ if (retval < 0) {
+ CVProcessError(cv_mem, CVDIAG_RHSFUNC_UNRECVR, "CVDIAG", "CVDiagSetup", MSGDG_RHSFUNC_FAILED);
+ last_flag = CVDIAG_RHSFUNC_UNRECVR;
+ return(-1);
+ }
+ if (retval > 0) {
+ last_flag = CVDIAG_RHSFUNC_RECVR;
+ return(1);
+ }
+
+ /* Construct M = I - gamma*J with J = diag(deltaf_i/deltay_i) */
+ N_VLinearSum(ONE, M, -ONE, fpred, M);
+ N_VLinearSum(FRACT, ftemp, -h, M, M);
+ N_VProd(ftemp, ewt, y);
+ /* Protect against deltay_i being at roundoff level */
+ N_VCompare(uround, y, bit);
+ N_VAddConst(bit, -ONE, bitcomp);
+ N_VProd(ftemp, bit, y);
+ N_VLinearSum(FRACT, y, -ONE, bitcomp, y);
+ N_VDiv(M, y, M);
+ N_VProd(M, bit, M);
+ N_VLinearSum(ONE, M, -ONE, bitcomp, M);
+
+ /* Invert M with test for zero components */
+ invOK = N_VInvTest(M, M);
+ if (!invOK) {
+ last_flag = CVDIAG_INV_FAIL;
+ return(1);
+ }
+
+ /* Set jcur = TRUE, save gamma in gammasv, and return */
+ *jcurPtr = TRUE;
+ gammasv = gamma;
+ last_flag = CVDIAG_SUCCESS;
+ return(0);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * CVDiagSolve
+ * -----------------------------------------------------------------
+ * This routine performs the solve operation for the diagonal linear
+ * solver. If necessary it first updates gamma in M = I - gamma*J.
+ * -----------------------------------------------------------------
+ */
+
+static int CVDiagSolve(CVodeMem cv_mem, N_Vector b, N_Vector weight,
+ N_Vector ycur, N_Vector fcur)
+{
+ booleantype invOK;
+ realtype r;
+ CVDiagMem cvdiag_mem;
+
+ cvdiag_mem = (CVDiagMem) lmem;
+
+ /* If gamma has changed, update factor in M, and save gamma value */
+
+ if (gammasv != gamma) {
+ r = gamma / gammasv;
+ N_VInv(M, M);
+ N_VAddConst(M, -ONE, M);
+ N_VScale(r, M, M);
+ N_VAddConst(M, ONE, M);
+ invOK = N_VInvTest(M, M);
+ if (!invOK) {
+ last_flag = CVDIAG_INV_FAIL;
+ return (1);
+ }
+ gammasv = gamma;
+ }
+
+ /* Apply M-inverse to b */
+ N_VProd(b, M, b);
+
+ last_flag = CVDIAG_SUCCESS;
+ return(0);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * CVDiagFree
+ * -----------------------------------------------------------------
+ * This routine frees memory specific to the diagonal linear solver.
+ * -----------------------------------------------------------------
+ */
+
+static void CVDiagFree(CVodeMem cv_mem)
+{
+ CVDiagMem cvdiag_mem;
+
+ cvdiag_mem = (CVDiagMem) lmem;
+
+ N_VDestroy(M);
+ N_VDestroy(bit);
+ N_VDestroy(bitcomp);
+ free(cvdiag_mem);
+ cv_mem->cv_lmem = NULL;
+}
diff --git a/src/cvode/cvode_diag_impl.h b/src/cvode/cvode_diag_impl.h
new file mode 100644
index 0000000..9ccf5ad
--- /dev/null
+++ b/src/cvode/cvode_diag_impl.h
@@ -0,0 +1,66 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.2 $
+ * $Date: 2010/12/01 22:19:48 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh and
+ * Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * Implementation header file for the diagonal linear solver, CVDIAG.
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _CVDIAG_IMPL_H
+#define _CVDIAG_IMPL_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <cvode/cvode_diag.h>
+
+/*
+ * -----------------------------------------------------------------
+ * Types: CVDiagMemRec, CVDiagMem
+ * -----------------------------------------------------------------
+ * The type CVDiagMem is pointer to a CVDiagMemRec.
+ * This structure contains CVDiag solver-specific data.
+ * -----------------------------------------------------------------
+ */
+
+typedef struct {
+
+ realtype di_gammasv; /* gammasv = gamma at the last call to setup */
+ /* or solve */
+
+ N_Vector di_M; /* M = (I - gamma J)^{-1} , gamma = h / l1 */
+
+ N_Vector di_bit; /* temporary storage vector */
+
+ N_Vector di_bitcomp; /* temporary storage vector */
+
+ 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 */
+
+} CVDiagMemRec, *CVDiagMem;
+
+/* Error Messages */
+
+#define MSGDG_CVMEM_NULL "Integrator memory is NULL."
+#define MSGDG_BAD_NVECTOR "A required vector operation is not implemented."
+#define MSGDG_MEM_FAIL "A memory request failed."
+#define MSGDG_LMEM_NULL "CVDIAG memory is NULL."
+#define MSGDG_RHSFUNC_FAILED "The right-hand side routine failed in an unrecoverable manner."
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/cvode/cvode_direct.c b/src/cvode/cvode_direct.c
new file mode 100644
index 0000000..0e2d6e0
--- /dev/null
+++ b/src/cvode/cvode_direct.c
@@ -0,0 +1,463 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.5 $
+ * $Date: 2010/12/01 22:21:04 $
+ * -----------------------------------------------------------------
+ * Programmer: Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2006, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * This is the implementation file for the CVDLS linear solvers
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * =================================================================
+ * IMPORTED HEADER FILES
+ * =================================================================
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "cvode_impl.h"
+#include "cvode_direct_impl.h"
+#include <sundials/sundials_math.h>
+
+/*
+ * =================================================================
+ * FUNCTION SPECIFIC CONSTANTS
+ * =================================================================
+ */
+
+/* Constant for DQ Jacobian approximation */
+#define MIN_INC_MULT RCONST(1000.0)
+
+#define ZERO RCONST(0.0)
+#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
+ * =================================================================
+ */
+
+/*
+ * CVDlsSetDenseJacFn specifies the dense Jacobian function.
+ */
+int CVDlsSetDenseJacFn(void *cvode_mem, CVDlsDenseJacFn jac)
+{
+ CVodeMem cv_mem;
+ CVDlsMem cvdls_mem;
+
+ /* Return immediately if cvode_mem is NULL */
+ if (cvode_mem == NULL) {
+ CVProcessError(NULL, CVDLS_MEM_NULL, "CVDLS", "CVDlsSetDenseJacFn", MSGD_CVMEM_NULL);
+ return(CVDLS_MEM_NULL);
+ }
+ cv_mem = (CVodeMem) cvode_mem;
+
+ if (lmem == NULL) {
+ CVProcessError(cv_mem, CVDLS_LMEM_NULL, "CVDLS", "CVDlsSetDenseJacFn", MSGD_LMEM_NULL);
+ return(CVDLS_LMEM_NULL);
+ }
+ cvdls_mem = (CVDlsMem) lmem;
+
+ if (jac != NULL) {
+ jacDQ = FALSE;
+ djac = jac;
+ } else {
+ jacDQ = TRUE;
+ }
+
+ return(CVDLS_SUCCESS);
+}
+
+/*
+ * CVDlsSetBandJacFn specifies the band Jacobian function.
+ */
+int CVDlsSetBandJacFn(void *cvode_mem, CVDlsBandJacFn jac)
+{
+ CVodeMem cv_mem;
+ CVDlsMem cvdls_mem;
+
+ /* Return immediately if cvode_mem is NULL */
+ if (cvode_mem == NULL) {
+ CVProcessError(NULL, CVDLS_MEM_NULL, "CVDLS", "CVDlsSetBandJacFn", 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);
+ return(CVDLS_LMEM_NULL);
+ }
+ cvdls_mem = (CVDlsMem) lmem;
+
+ if (jac != NULL) {
+ jacDQ = FALSE;
+ bjac = jac;
+ } else {
+ jacDQ = TRUE;
+ }
+
+ 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)
+{
+ CVodeMem cv_mem;
+ CVDlsMem cvdls_mem;
+
+ /* Return immediately if cvode_mem is NULL */
+ if (cvode_mem == 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);
+ return(CVDLS_LMEM_NULL);
+ }
+ cvdls_mem = (CVDlsMem) 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;
+ }
+
+ return(CVDLS_SUCCESS);
+}
+
+/*
+ * 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 */
+ if (cvode_mem == 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);
+ return(CVDLS_LMEM_NULL);
+ }
+ cvdls_mem = (CVDlsMem) lmem;
+
+ *njevals = nje;
+
+ return(CVDLS_SUCCESS);
+}
+
+/*
+ * 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 */
+ if (cvode_mem == 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);
+ return(CVDLS_LMEM_NULL);
+ }
+ cvdls_mem = (CVDlsMem) lmem;
+
+ *nfevalsLS = nfeDQ;
+
+ return(CVDLS_SUCCESS);
+}
+
+/*
+ * CVDlsGetReturnFlagName returns the name associated with a CVDLS
+ * return value.
+ */
+char *CVDlsGetReturnFlagName(long int flag)
+{
+ char *name;
+
+ name = (char *)malloc(30*sizeof(char));
+
+ switch(flag) {
+ case CVDLS_SUCCESS:
+ sprintf(name,"CVDLS_SUCCESS");
+ break;
+ case CVDLS_MEM_NULL:
+ sprintf(name,"CVDLS_MEM_NULL");
+ break;
+ case CVDLS_LMEM_NULL:
+ sprintf(name,"CVDLS_LMEM_NULL");
+ break;
+ case CVDLS_ILL_INPUT:
+ sprintf(name,"CVDLS_ILL_INPUT");
+ break;
+ case CVDLS_MEM_FAIL:
+ sprintf(name,"CVDLS_MEM_FAIL");
+ break;
+ case CVDLS_JACFUNC_UNRECVR:
+ sprintf(name,"CVDLS_JACFUNC_UNRECVR");
+ break;
+ case CVDLS_JACFUNC_RECVR:
+ sprintf(name,"CVDLS_JACFUNC_RECVR");
+ break;
+ default:
+ sprintf(name,"NONE");
+ }
+
+ return(name);
+}
+
+/*
+ * 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 */
+ if (cvode_mem == 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);
+ return(CVDLS_LMEM_NULL);
+ }
+ cvdls_mem = (CVDlsMem) lmem;
+
+ *flag = 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.
+ * -----------------------------------------------------------------
+ */
+
+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)
+{
+ realtype fnorm, minInc, inc, inc_inv, yjsaved, srur;
+ realtype *tmp2_data, *y_data, *ewt_data;
+ N_Vector ftemp, jthCol;
+ long int j;
+ int retval = 0;
+
+ CVodeMem cv_mem;
+ CVDlsMem cvdls_mem;
+
+ /* data points to cvode_mem */
+ cv_mem = (CVodeMem) data;
+ cvdls_mem = (CVDlsMem) lmem;
+
+ /* Save pointer to the array in tmp2 */
+ tmp2_data = N_VGetArrayPointer(tmp2);
+
+ /* Rename work vectors for readibility */
+ ftemp = tmp1;
+ jthCol = tmp2;
+
+ /* Obtain pointers to the data for ewt, y */
+ ewt_data = N_VGetArrayPointer(ewt);
+ y_data = N_VGetArrayPointer(y);
+
+ /* Set minimum increment based on uround and norm of f */
+ srur = RSqrt(uround);
+ fnorm = N_VWrmsNorm(fy, ewt);
+ minInc = (fnorm != ZERO) ?
+ (MIN_INC_MULT * ABS(h) * 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);
+
+ yjsaved = y_data[j];
+ inc = MAX(srur*ABS(yjsaved), minInc/ewt_data[j]);
+ y_data[j] += inc;
+
+ retval = f(t, y, ftemp, user_data);
+ nfeDQ++;
+ if (retval != 0) break;
+
+ y_data[j] = yjsaved;
+
+ inc_inv = ONE/inc;
+ N_VLinearSum(inc_inv, ftemp, -inc_inv, fy, jthCol);
+
+ DENSE_COL(Jac,j) = N_VGetArrayPointer(jthCol);
+ }
+
+ /* Restore original array pointer in tmp2 */
+ N_VSetArrayPointer(tmp2_data, tmp2);
+
+ 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)
+{
+ 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;
+ int retval = 0;
+
+ CVodeMem cv_mem;
+ CVDlsMem cvdls_mem;
+
+ /* data points to cvode_mem */
+ cv_mem = (CVodeMem) data;
+ cvdls_mem = (CVDlsMem) lmem;
+
+ /* 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);
+ fy_data = N_VGetArrayPointer(fy);
+ ftemp_data = N_VGetArrayPointer(ftemp);
+ y_data = N_VGetArrayPointer(y);
+ ytemp_data = N_VGetArrayPointer(ytemp);
+
+ /* Load ytemp with y = predicted y vector */
+ N_VScale(ONE, y, ytemp);
+
+ /* Set minimum increment based on uround and norm of f */
+ srur = RSqrt(uround);
+ fnorm = N_VWrmsNorm(fy, ewt);
+ minInc = (fnorm != ZERO) ?
+ (MIN_INC_MULT * ABS(h) * uround * N * fnorm) : ONE;
+
+ /* Set bandwidth and number of column groups for band differencing */
+ width = mlower + mupper + 1;
+ ngroups = MIN(width, N);
+
+ /* Loop over column groups. */
+ for (group=1; group <= ngroups; group++) {
+
+ /* Increment all y_j in group */
+ for(j=group-1; j < N; j+=width) {
+ inc = MAX(srur*ABS(y_data[j]), minInc/ewt_data[j]);
+ ytemp_data[j] += inc;
+ }
+
+ /* Evaluate f with incremented y */
+
+ retval = f(tn, ytemp, ftemp, user_data);
+ 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);
+ inc = MAX(srur*ABS(y_data[j]), minInc/ewt_data[j]);
+ inc_inv = ONE/inc;
+ i1 = MAX(0, j-mupper);
+ i2 = MIN(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]);
+ }
+ }
+
+ return(retval);
+}
+
diff --git a/src/cvode/cvode_direct_impl.h b/src/cvode/cvode_direct_impl.h
new file mode 100644
index 0000000..75ee016
--- /dev/null
+++ b/src/cvode/cvode_direct_impl.h
@@ -0,0 +1,111 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.6 $
+ * $Date: 2010/12/01 22:19:48 $
+ * -----------------------------------------------------------------
+ * Programmer: Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2006, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * Common implementation header file for the CVDLS linear solvers.
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _CVDLS_IMPL_H
+#define _CVDLS_IMPL_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <cvode/cvode_direct.h>
+
+/*
+ * -----------------------------------------------------------------
+ * 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.
+ * -----------------------------------------------------------------
+ */
+
+typedef struct CVDlsMemRec {
+
+ int d_type; /* SUNDIALS_DENSE or SUNDIALS_BAND */
+
+ long int d_n; /* problem dimension */
+
+ 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) */
+
+ 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 */
+
+ 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. */
+
+ long int d_nje; /* nje = no. of calls to jac */
+
+ long int d_nfeDQ; /* no. of calls to f due to DQ Jacobian approx. */
+
+ long int d_last_flag; /* last error return flag */
+
+} *CVDlsMem;
+
+/*
+ * -----------------------------------------------------------------
+ * Prototypes of internal functions
+ * -----------------------------------------------------------------
+ */
+
+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);
+
+
+/*
+ * -----------------------------------------------------------------
+ * Error Messages
+ * -----------------------------------------------------------------
+ */
+
+#define MSGD_CVMEM_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_JACFUNC_FAILED "The Jacobian routine failed in an unrecoverable manner."
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/cvode/cvode_impl.h b/src/cvode/cvode_impl.h
new file mode 100644
index 0000000..5c4010f
--- /dev/null
+++ b/src/cvode/cvode_impl.h
@@ -0,0 +1,515 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.13 $
+ * $Date: 2007/11/26 16:19:59 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh, Radu Serban
+ * and Dan Shumaker @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * Implementation header file for the main CVODE integrator.
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _CVODE_IMPL_H
+#define _CVODE_IMPL_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <stdarg.h>
+
+#include <cvode/cvode.h>
+
+/*
+ * =================================================================
+ * M A I N I N T E G R A T O R M E M O R Y B L O C K
+ * =================================================================
+ */
+
+/* Basic CVODE constants */
+
+#define ADAMS_Q_MAX 12 /* max value of q for lmm == ADAMS */
+#define BDF_Q_MAX 5 /* max value of q for lmm == BDF */
+#define Q_MAX ADAMS_Q_MAX /* max value of q for either lmm */
+#define L_MAX (Q_MAX+1) /* max value of L for either lmm */
+#define NUM_TESTS 5 /* number of error test quantities */
+
+#define HMIN_DEFAULT RCONST(0.0) /* hmin default value */
+#define HMAX_INV_DEFAULT RCONST(0.0) /* hmax_inv default value */
+#define MXHNIL_DEFAULT 10 /* mxhnil default value */
+#define MXSTEP_DEFAULT 500 /* mxstep default value */
+
+/*
+ * -----------------------------------------------------------------
+ * Types : struct CVodeMemRec, CVodeMem
+ * -----------------------------------------------------------------
+ * The type CVodeMem is type pointer to struct CVodeMemRec.
+ * This structure contains fields to keep track of problem state.
+ * -----------------------------------------------------------------
+ */
+
+typedef struct CVodeMemRec {
+
+ 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 */
+ int cv_lmm; /* lmm = CV_ADAMS or CV_BDF */
+ int cv_iter; /* iter = CV_FUNCTIONAL or CV_NEWTON */
+ int cv_itol; /* itol = CV_SS, CV_SV, CV_WF, 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 */
+
+ /*-----------------------
+ Nordsieck History Array
+ -----------------------*/
+
+ N_Vector cv_zn[L_MAX]; /* Nordsieck array, of size N x (q+1).
+ zn[j] is a vector of length N (j=0,...,q)
+ zn[j] = [1/factorial(j)] * h^j * (jth
+ derivative of the interpolating polynomial */
+
+ /*--------------------------
+ other vectors of length N
+ -------------------------*/
+
+ N_Vector cv_ewt; /* error weight vector */
+ N_Vector cv_y; /* y is used as temporary storage by the solver
+ The memory is provided by the user to CVode
+ where the vector is named yout. */
+ N_Vector cv_acor; /* In the context of the solution of the nonlinear
+ equation, acor = y_n(m) - y_n(0). On return,
+ this vector is scaled to give the est. local err. */
+ N_Vector cv_tempv; /* temporary storage vector */
+ N_Vector cv_ftemp; /* temporary storage vector */
+
+ /*-----------------
+ Tstop information
+ -----------------*/
+
+ booleantype cv_tstopset;
+ realtype cv_tstop;
+
+ /*---------
+ Step Data
+ ---------*/
+
+ int cv_q; /* current order */
+ int cv_qprime; /* order to be used on the next step
+ = q-1, q, or q+1 */
+ int cv_next_q; /* order to be used on the next step */
+ int cv_qwait; /* number of internal steps to wait before
+ considering a change in q */
+ int cv_L; /* L = q + 1 */
+
+ realtype cv_hin; /* initial step size */
+ realtype cv_h; /* current step size */
+ realtype cv_hprime; /* step size to be used on the next step */
+ realtype cv_next_h; /* step size to be used on the next step */
+ realtype cv_eta; /* eta = hprime / h */
+ realtype cv_hscale; /* value of h used in zn */
+ realtype cv_tn; /* current internal value of t */
+ realtype cv_tretlast; /* value of tret last returned by CVode */
+
+ realtype cv_tau[L_MAX+1]; /* array of previous q+1 successful step
+ sizes indexed from 1 to q+1 */
+ realtype cv_tq[NUM_TESTS+1]; /* array of test quantities indexed from
+ 1 to NUM_TESTS(=5) */
+ realtype cv_l[L_MAX]; /* coefficients of l(x) (degree q poly) */
+
+ realtype cv_rl1; /* the scalar 1/l[1] */
+ realtype cv_gamma; /* gamma = h * rl1 */
+ realtype cv_gammap; /* gamma at the last setup call */
+ realtype cv_gamrat; /* gamma / gammap */
+
+ realtype cv_crate; /* estimated corrector convergence rate */
+ realtype cv_acnrm; /* | acor | wrms */
+ realtype cv_nlscoef; /* coeficient in nonlinear convergence test */
+ int cv_mnewt; /* Newton iteration counter */
+
+ /*------
+ Limits
+ ------*/
+
+ int cv_qmax; /* q <= qmax */
+ long int cv_mxstep; /* maximum number of internal steps for one user call */
+ int cv_maxcor; /* maximum number of corrector iterations for the
+ solution of the nonlinear equation */
+ int cv_mxhnil; /* maximum number of warning messages issued to the
+ 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 convergence failures */
+
+ realtype cv_hmin; /* |h| >= hmin */
+ realtype cv_hmax_inv; /* |h| <= 1/hmax_inv */
+ realtype cv_etamax; /* eta <= etamax */
+
+ /*--------
+ Counters
+ --------*/
+
+ long int cv_nst; /* number of internal steps taken */
+ long int cv_nfe; /* number of f calls */
+ long int cv_ncfn; /* number of corrector convergence failures */
+ long int cv_netf; /* number of error test failures */
+ long int cv_nni; /* number of Newton iterations performed */
+ long int cv_nsetups; /* number of setup calls */
+ int cv_nhnil; /* number of messages issued to the user that
+ t + h == t for the next iternal step */
+
+ realtype cv_etaqm1; /* ratio of new to old h for order q-1 */
+ realtype cv_etaq; /* ratio of new to old h for order q */
+ realtype cv_etaqp1; /* ratio of new to old h for order q+1 */
+
+ /*----------------------------
+ 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 */
+
+ /*------------------
+ Linear Solver Data
+ ------------------*/
+
+ /* Linear Solver functions to be called */
+
+ int (*cv_linit)(struct CVodeMemRec *cv_mem);
+
+ int (*cv_lsetup)(struct CVodeMemRec *cv_mem, int convfail, N_Vector ypred,
+ N_Vector fpred, booleantype *jcurPtr, N_Vector vtemp1,
+ N_Vector vtemp2, N_Vector vtemp3);
+
+ int (*cv_lsolve)(struct CVodeMemRec *cv_mem, N_Vector b, N_Vector weight,
+ N_Vector ycur, N_Vector fcur);
+
+ void (*cv_lfree)(struct CVodeMemRec *cv_mem);
+
+ /* Linear Solver specific memory */
+
+ void *cv_lmem;
+
+ /*------------
+ Saved Values
+ ------------*/
+
+ int cv_qu; /* last successful q value used */
+ long int cv_nstlp; /* step number of last setup call */
+ realtype cv_h0u; /* actual initial stepsize */
+ realtype cv_hu; /* last successful h value used */
+ realtype cv_saved_tq5; /* saved value of tq[5] */
+ booleantype cv_jcur; /* is Jacobian info. for lin. solver current? */
+ 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;
+
+ /*-------------------------------------------
+ Error handler function and error ouput file
+ -------------------------------------------*/
+
+ CVErrHandlerFn cv_ehfun; /* error messages are handled by ehfun */
+ void *cv_eh_data; /* data pointer passed to ehfun */
+ FILE *cv_errfp; /* CVODE error messages are sent to errfp */
+
+ /*-------------------------
+ Stability Limit Detection
+ -------------------------*/
+
+ booleantype cv_sldeton; /* is Stability Limit Detection on? */
+ realtype cv_ssdat[6][4]; /* scaled data array for STALD */
+ int cv_nscon; /* counter for STALD method */
+ long int cv_nor; /* counter for number of order reductions */
+
+ /*----------------
+ Rootfinding Data
+ ----------------*/
+
+ CVRootFn cv_gfun; /* function g for roots sought */
+ int cv_nrtfn; /* number of components of g */
+ int *cv_iroots; /* array for root information */
+ int *cv_rootdir; /* array specifying direction of zero-crossing */
+ realtype cv_tlo; /* nearest endpoint of interval in root search */
+ realtype cv_thi; /* farthest endpoint of interval in root search */
+ realtype cv_trout; /* t value returned by rootfinding routine */
+ realtype *cv_glo; /* saved array of g values at t = tlo */
+ realtype *cv_ghi; /* saved array of g values at t = thi */
+ realtype *cv_grout; /* array of g values at t = trout */
+ realtype cv_toutc; /* copy of tout (if NORMAL mode) */
+ realtype cv_ttol; /* tolerance on root location */
+ int cv_taskc; /* copy of parameter itask */
+ int cv_irfnd; /* flag showing whether last step had a root */
+ long int cv_nge; /* counter for g evaluations */
+ booleantype *cv_gactive; /* array with active/inactive event functions */
+ int cv_mxgnull; /* number of warning messages about possible g==0 */
+
+
+} *CVodeMem;
+
+/*
+ * =================================================================
+ * I N T E R F A C E T O L I N E A R S O L V E R S
+ * =================================================================
+ */
+
+/*
+ * -----------------------------------------------------------------
+ * Communication between CVODE and a CVODE Linear Solver
+ * -----------------------------------------------------------------
+ * convfail (input to cv_lsetup)
+ *
+ * CV_NO_FAILURES : Either this is the first cv_setup call for this
+ * step, or the local error test failed on the
+ * previous attempt at this step (but the Newton
+ * iteration converged).
+ *
+ * CV_FAIL_BAD_J : This value is passed to cv_lsetup if
+ *
+ * (a) The previous Newton corrector iteration
+ * did not converge and the linear solver's
+ * setup routine indicated that its Jacobian-
+ * related data is not current
+ * or
+ * (b) During the previous Newton corrector
+ * iteration, the linear solver's solve routine
+ * failed in a recoverable manner and the
+ * linear solver's setup routine indicated that
+ * its Jacobian-related data is not current.
+ *
+ * CV_FAIL_OTHER : During the current internal step try, the
+ * previous Newton iteration failed to converge
+ * even though the linear solver was using current
+ * Jacobian-related data.
+ * -----------------------------------------------------------------
+ */
+
+/* Constants for convfail (input to cv_lsetup) */
+
+#define CV_NO_FAILURES 0
+#define CV_FAIL_BAD_J 1
+#define CV_FAIL_OTHER 2
+
+/*
+ * -----------------------------------------------------------------
+ * int (*cv_linit)(CVodeMem cv_mem);
+ * -----------------------------------------------------------------
+ * The purpose of cv_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
+ * CVODE linear solver and a negative value otherwise.
+ * If an error does occur, an appropriate message should be sent to
+ * the error handler function.
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * -----------------------------------------------------------------
+ * int (*cv_lsetup)(CVodeMem cv_mem, int convfail, N_Vector ypred,
+ * N_Vector fpred, booleantype *jcurPtr,
+ * N_Vector vtemp1, N_Vector vtemp2,
+ * N_Vector vtemp3);
+ * -----------------------------------------------------------------
+ * The job of cv_lsetup is to prepare the linear solver for
+ * subsequent calls to cv_lsolve. It may recompute Jacobian-
+ * related data is it deems necessary. Its parameters are as
+ * follows:
+ *
+ * cv_mem - problem memory pointer of type CVodeMem. See the
+ * typedef earlier in this file.
+ *
+ * convfail - a flag to indicate any problem that occurred during
+ * the solution of the nonlinear equation on the
+ * current time step for which the linear solver is
+ * being used. This flag can be used to help decide
+ * whether the Jacobian data kept by a CVODE linear
+ * solver needs to be updated or not.
+ * Its possible values have been documented above.
+ *
+ * ypred - the predicted y vector for the current CVODE internal
+ * step.
+ *
+ * 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
+ * data is current after the call and should set
+ * *jcurPtr=FALSE 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;
+ * otherwise an infinite loop can result.
+ *
+ * vtemp1 - temporary N_Vector provided for use by cv_lsetup.
+ *
+ * vtemp3 - temporary N_Vector provided for use by cv_lsetup.
+ *
+ * vtemp3 - temporary N_Vector provided for use by cv_lsetup.
+ *
+ * The cv_lsetup routine should return 0 if successful, a positive
+ * value for a recoverable error, and a negative value for an
+ * unrecoverable error.
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * -----------------------------------------------------------------
+ * int (*cv_lsolve)(CVodeMem cv_mem, N_Vector b, N_Vector weight,
+ * N_Vector ycur, N_Vector fcur);
+ * -----------------------------------------------------------------
+ * cv_lsolve must solve the linear equation P x = b, where
+ * P is some approximation to (I - gamma J), 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. cv_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.
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * -----------------------------------------------------------------
+ * void (*cv_lfree)(CVodeMem cv_mem);
+ * -----------------------------------------------------------------
+ * cv_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.
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * =================================================================
+ * C V O D E I N T E R N A L F U N C T I O N S
+ * =================================================================
+ */
+
+/* Prototype of internal ewtSet function */
+
+int CVEwtSet(N_Vector ycur, N_Vector weight, void *data);
+
+/* High level error handler */
+
+void CVProcessError(CVodeMem cv_mem,
+ int error_code, const char *module, const char *fname,
+ const char *msgfmt, ...);
+
+/* Prototype of internal errHandler function */
+
+void CVErrHandler(int error_code, const char *module, const char *function,
+ char *msg, void *data);
+
+/*
+ * =================================================================
+ * C V O D E E R R O R M E S S A G E S
+ * =================================================================
+ */
+
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+
+#define MSG_TIME "t = %Lg"
+#define MSG_TIME_H "t = %Lg and h = %Lg"
+#define MSG_TIME_INT "t = %Lg is not between tcur - hu = %Lg and tcur = %Lg."
+#define MSG_TIME_TOUT "tout = %Lg"
+#define MSG_TIME_TSTOP "tstop = %Lg"
+
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+
+#define MSG_TIME "t = %lg"
+#define MSG_TIME_H "t = %lg and h = %lg"
+#define MSG_TIME_INT "t = %lg is not between tcur - hu = %lg and tcur = %lg."
+#define MSG_TIME_TOUT "tout = %lg"
+#define MSG_TIME_TSTOP "tstop = %lg"
+
+#else
+
+#define MSG_TIME "t = %g"
+#define MSG_TIME_H "t = %g and h = %g"
+#define MSG_TIME_INT "t = %g is not between tcur - hu = %g and tcur = %g."
+#define MSG_TIME_TOUT "tout = %g"
+#define MSG_TIME_TSTOP "tstop = %g"
+
+#endif
+
+/* Initialization and I/O error messages */
+
+#define MSGCV_NO_MEM "cvode_mem = NULL illegal."
+#define MSGCV_CVMEM_FAIL "Allocation of cvode_mem failed."
+#define MSGCV_MEM_FAIL "A memory request failed."
+#define MSGCV_BAD_LMM "Illegal value for lmm. The legal values are CV_ADAMS and CV_BDF."
+#define MSGCV_BAD_ITER "Illegal value for iter. The legal values are CV_FUNCTIONAL and CV_NEWTON."
+#define MSGCV_NO_MALLOC "Attempt to call before CVodeInit."
+#define MSGCV_NEG_MAXORD "maxord <= 0 illegal."
+#define MSGCV_BAD_MAXORD "Illegal attempt to increase maximum method order."
+#define MSGCV_SET_SLDET "Attempt to use stability limit detection with the CV_ADAMS method illegal."
+#define MSGCV_NEG_HMIN "hmin < 0 illegal."
+#define MSGCV_NEG_HMAX "hmax < 0 illegal."
+#define MSGCV_BAD_HMIN_HMAX "Inconsistent step size limits: hmin > hmax."
+#define MSGCV_BAD_RELTOL "reltol < 0 illegal."
+#define MSGCV_BAD_ABSTOL "abstol has negative component(s) (illegal)."
+#define MSGCV_NULL_ABSTOL "abstol = NULL illegal."
+#define MSGCV_NULL_Y0 "y0 = NULL illegal."
+#define MSGCV_NULL_F "f = NULL illegal."
+#define MSGCV_NULL_G "g = NULL illegal."
+#define MSGCV_BAD_NVECTOR "A required vector operation is not implemented."
+#define MSGCV_BAD_K "Illegal value for k."
+#define MSGCV_NULL_DKY "dky = NULL illegal."
+#define MSGCV_BAD_T "Illegal value for t." MSG_TIME_INT
+#define MSGCV_NO_ROOT "Rootfinding was not initialized."
+
+/* CVode Error Messages */
+
+#define MSGCV_NO_TOLS "No integration tolerances have been specified."
+#define MSGCV_LSOLVE_NULL "The linear solver's solve routine is NULL."
+#define MSGCV_YOUT_NULL "yout = NULL illegal."
+#define MSGCV_TRET_NULL "tret = NULL illegal."
+#define MSGCV_BAD_EWT "Initial ewt has component(s) equal to zero (illegal)."
+#define MSGCV_EWT_NOW_BAD "At " MSG_TIME ", a component of ewt has become <= 0."
+#define MSGCV_BAD_ITASK "Illegal value for itask."
+#define MSGCV_BAD_H0 "h0 and tout - t0 inconsistent."
+#define MSGCV_BAD_TOUT "Trouble interpolating at " MSG_TIME_TOUT ". tout too far back in direction of integration"
+#define MSGCV_EWT_FAIL "The user-provide EwtSet function failed."
+#define MSGCV_EWT_NOW_FAIL "At " MSG_TIME ", the user-provide EwtSet function failed."
+#define MSGCV_LINIT_FAIL "The linear solver's init routine failed."
+#define MSGCV_HNIL_DONE "The above warning has been issued mxhnil times and will not be issued again for this problem."
+#define MSGCV_TOO_CLOSE "tout too close to t0 to start integration."
+#define MSGCV_MAX_STEPS "At " MSG_TIME ", mxstep steps taken before reaching tout."
+#define MSGCV_TOO_MUCH_ACC "At " MSG_TIME ", too much accuracy requested."
+#define MSGCV_HNIL "Internal " MSG_TIME_H " are such that t + h = t on the next step. The solver will continue anyway."
+#define MSGCV_ERR_FAILS "At " MSG_TIME_H ", the error test failed repeatedly or with |h| = hmin."
+#define MSGCV_CONV_FAILS "At " MSG_TIME_H ", the corrector convergence test failed repeatedly or with |h| = hmin."
+#define MSGCV_SETUP_FAILED "At " MSG_TIME ", the setup routine failed in an unrecoverable manner."
+#define MSGCV_SOLVE_FAILED "At " MSG_TIME ", the solve routine failed in an unrecoverable manner."
+#define MSGCV_RHSFUNC_FAILED "At " MSG_TIME ", the right-hand side routine failed in an unrecoverable manner."
+#define MSGCV_RHSFUNC_UNREC "At " MSG_TIME ", the right-hand side failed in a recoverable manner, but no recovery is possible."
+#define MSGCV_RHSFUNC_REPTD "At " MSG_TIME " repeated recoverable right-hand side function errors."
+#define MSGCV_RHSFUNC_FIRST "The right-hand side routine failed at the first call."
+#define MSGCV_RTFUNC_FAILED "At " MSG_TIME ", the rootfinding routine failed in an unrecoverable manner."
+#define MSGCV_CLOSE_ROOTS "Root found at and very near " MSG_TIME "."
+#define MSGCV_BAD_TSTOP "The value " MSG_TIME_TSTOP " is behind current " MSG_TIME " in the direction of integration."
+#define MSGCV_INACTIVE_ROOTS "At the end of the first step, there are still some root functions identically 0. This warning will not be issued again."
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/cvode/cvode_io.c b/src/cvode/cvode_io.c
new file mode 100644
index 0000000..2645ca1
--- /dev/null
+++ b/src/cvode/cvode_io.c
@@ -0,0 +1,1129 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.12 $
+ * $Date: 2010/12/01 22:21:04 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Alan C. Hindmarsh and Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * This is the implementation file for the optional input and output
+ * functions for the CVODE solver.
+ * -----------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "cvode_impl.h"
+#include <sundials/sundials_types.h>
+
+#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
+ * =================================================================
+ */
+
+/*
+ * CVodeSetErrHandlerFn
+ *
+ * Specifies the error handler function
+ */
+
+int CVodeSetErrHandlerFn(void *cvode_mem, CVErrHandlerFn ehfun, void *eh_data)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ CVProcessError(NULL, CV_MEM_NULL, "CVODE", "CVodeSetErrHandlerFn", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ cv_mem->cv_ehfun = ehfun;
+ cv_mem->cv_eh_data = eh_data;
+
+ return(CV_SUCCESS);
+}
+
+/*
+ * CVodeSetErrFile
+ *
+ * Specifies the FILE pointer for output (NULL means no messages)
+ */
+
+int CVodeSetErrFile(void *cvode_mem, FILE *errfp)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ CVProcessError(NULL, CV_MEM_NULL, "CVODE", "CVodeSetErrFile", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ cv_mem->cv_errfp = errfp;
+
+ return(CV_SUCCESS);
+}
+
+/*
+ * CVodeSetIterType
+ *
+ * Specifies the iteration type (CV_FUNCTIONAL or CV_NEWTON)
+ */
+
+int CVodeSetIterType(void *cvode_mem, int iter)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ CVProcessError(NULL, CV_MEM_NULL, "CVODE", "CVodeSetIterType", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ if ((iter != CV_FUNCTIONAL) && (iter != CV_NEWTON)) {
+ CVProcessError(cv_mem, CV_ILL_INPUT, "CVODE", "CVodeSetIterType", MSGCV_BAD_ITER);
+ return (CV_ILL_INPUT);
+ }
+
+ cv_mem->cv_iter = iter;
+
+ return(CV_SUCCESS);
+}
+
+/*
+ * CVodeSetUserData
+ *
+ * Specifies the user data pointer for f
+ */
+
+int CVodeSetUserData(void *cvode_mem, void *user_data)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ CVProcessError(NULL, CV_MEM_NULL, "CVODE", "CVodeSetUserData", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ cv_mem->cv_user_data = user_data;
+
+ return(CV_SUCCESS);
+}
+
+/*
+ * CVodeSetMaxOrd
+ *
+ * Specifies the maximum method order
+ */
+
+int CVodeSetMaxOrd(void *cvode_mem, int maxord)
+{
+ CVodeMem cv_mem;
+ int qmax_alloc;
+
+ if (cvode_mem==NULL) {
+ CVProcessError(NULL, CV_MEM_NULL, "CVODE", "CVodeSetMaxOrd", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ if (maxord <= 0) {
+ CVProcessError(cv_mem, CV_ILL_INPUT, "CVODE", "CVodeSetMaxOrd", MSGCV_NEG_MAXORD);
+ return(CV_ILL_INPUT);
+ }
+
+ /* Cannot increase maximum order beyond the value that
+ was used when allocating memory */
+ qmax_alloc = cv_mem->cv_qmax_alloc;
+
+ if (maxord > qmax_alloc) {
+ CVProcessError(cv_mem, CV_ILL_INPUT, "CVODE", "CVodeSetMaxOrd", MSGCV_BAD_MAXORD);
+ return(CV_ILL_INPUT);
+ }
+
+ cv_mem->cv_qmax = maxord;
+
+ return(CV_SUCCESS);
+}
+
+/*
+ * CVodeSetMaxNumSteps
+ *
+ * Specifies the maximum number of integration steps
+ */
+
+int CVodeSetMaxNumSteps(void *cvode_mem, long int mxsteps)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ CVProcessError(NULL, CV_MEM_NULL, "CVODE", "CVodeSetMaxNumSteps", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ /* Passing mxsteps=0 sets the default. Passing mxsteps<0 disables the test. */
+
+ if (mxsteps == 0)
+ cv_mem->cv_mxstep = MXSTEP_DEFAULT;
+ else
+ cv_mem->cv_mxstep = mxsteps;
+
+ return(CV_SUCCESS);
+}
+
+/*
+ * CVodeSetMaxHnilWarns
+ *
+ * Specifies the maximum number of warnings for small h
+ */
+
+int CVodeSetMaxHnilWarns(void *cvode_mem, int mxhnil)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ CVProcessError(NULL, CV_MEM_NULL, "CVODE", "CVodeSetMaxHnilWarns", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ cv_mem->cv_mxhnil = mxhnil;
+
+ return(CV_SUCCESS);
+}
+
+/*
+ *CVodeSetStabLimDet
+ *
+ * Turns on/off the stability limit detection algorithm
+ */
+
+int CVodeSetStabLimDet(void *cvode_mem, booleantype sldet)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ CVProcessError(NULL, CV_MEM_NULL, "CVODE", "CVodeSetStabLimDet", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ if( sldet && (cv_mem->cv_lmm != CV_BDF) ) {
+ CVProcessError(cv_mem, CV_ILL_INPUT, "CVODE", "CVodeSetStabLimDet", MSGCV_SET_SLDET);
+ return(CV_ILL_INPUT);
+ }
+
+ cv_mem->cv_sldeton = sldet;
+
+ return(CV_SUCCESS);
+}
+
+/*
+ * CVodeSetInitStep
+ *
+ * Specifies the initial step size
+ */
+
+int CVodeSetInitStep(void *cvode_mem, realtype hin)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ CVProcessError(NULL, CV_MEM_NULL, "CVODE", "CVodeSetInitStep", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ cv_mem->cv_hin = hin;
+
+ return(CV_SUCCESS);
+}
+
+/*
+ * CVodeSetMinStep
+ *
+ * Specifies the minimum step size
+ */
+
+int CVodeSetMinStep(void *cvode_mem, realtype hmin)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ CVProcessError(NULL, CV_MEM_NULL, "CVODE", "CVodeSetMinStep", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ if (hmin<0) {
+ CVProcessError(cv_mem, CV_ILL_INPUT, "CVODE", "CVodeSetMinStep", MSGCV_NEG_HMIN);
+ return(CV_ILL_INPUT);
+ }
+
+ /* Passing 0 sets hmin = zero */
+ if (hmin == ZERO) {
+ cv_mem->cv_hmin = HMIN_DEFAULT;
+ return(CV_SUCCESS);
+ }
+
+ if (hmin * cv_mem->cv_hmax_inv > ONE) {
+ CVProcessError(cv_mem, CV_ILL_INPUT, "CVODE", "CVodeSetMinStep", MSGCV_BAD_HMIN_HMAX);
+ return(CV_ILL_INPUT);
+ }
+
+ cv_mem->cv_hmin = hmin;
+
+ return(CV_SUCCESS);
+}
+
+/*
+ * CVodeSetMaxStep
+ *
+ * Specifies the maximum step size
+ */
+
+int CVodeSetMaxStep(void *cvode_mem, realtype hmax)
+{
+ realtype hmax_inv;
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ CVProcessError(NULL, CV_MEM_NULL, "CVODE", "CVodeSetMaxStep", MSGCV_NO_MEM);
+ return (CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ if (hmax < 0) {
+ CVProcessError(cv_mem, CV_ILL_INPUT, "CVODE", "CVodeSetMaxStep", MSGCV_NEG_HMAX);
+ return(CV_ILL_INPUT);
+ }
+
+ /* Passing 0 sets hmax = infinity */
+ if (hmax == ZERO) {
+ cv_mem->cv_hmax_inv = HMAX_INV_DEFAULT;
+ return(CV_SUCCESS);
+ }
+
+ hmax_inv = ONE/hmax;
+ if (hmax_inv * cv_mem->cv_hmin > ONE) {
+ CVProcessError(cv_mem, CV_ILL_INPUT, "CVODE", "CVodeSetMaxStep", MSGCV_BAD_HMIN_HMAX);
+ return(CV_ILL_INPUT);
+ }
+
+ cv_mem->cv_hmax_inv = hmax_inv;
+
+ return(CV_SUCCESS);
+}
+
+/*
+ * CVodeSetStopTime
+ *
+ * Specifies the time beyond which the integration is not to proceed.
+ */
+
+int CVodeSetStopTime(void *cvode_mem, realtype tstop)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ CVProcessError(NULL, CV_MEM_NULL, "CVODE", "CVodeSetStopTime", MSGCV_NO_MEM);
+ return (CV_MEM_NULL);
+ }
+ cv_mem = (CVodeMem) cvode_mem;
+
+ /* If CVode was called at least once, test if tstop is legal
+ * (i.e. if it was not already passed).
+ * If CVodeSetStopTime is called before the first call to CVode,
+ * tstop will be checked in CVode. */
+ if (cv_mem->cv_nst > 0) {
+
+ if ( (tstop - cv_mem->cv_tn) * cv_mem->cv_h < ZERO ) {
+ CVProcessError(cv_mem, CV_ILL_INPUT, "CVODE", "CVodeSetStopTime", MSGCV_BAD_TSTOP, cv_mem->cv_tn);
+ return(CV_ILL_INPUT);
+ }
+
+ }
+
+ cv_mem->cv_tstop = tstop;
+ cv_mem->cv_tstopset = TRUE;
+
+ return(CV_SUCCESS);
+}
+
+/*
+ * CVodeSetMaxErrTestFails
+ *
+ * Specifies the maximum number of error test failures during one
+ * step try.
+ */
+
+int CVodeSetMaxErrTestFails(void *cvode_mem, int maxnef)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ CVProcessError(NULL, CV_MEM_NULL, "CVODE", "CVodeSetMaxErrTestFails", MSGCV_NO_MEM);
+ return (CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ cv_mem->cv_maxnef = maxnef;
+
+ return(CV_SUCCESS);
+}
+
+/*
+ * CVodeSetMaxConvFails
+ *
+ * Specifies the maximum number of nonlinear convergence failures
+ * during one step try.
+ */
+
+int CVodeSetMaxConvFails(void *cvode_mem, int maxncf)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ CVProcessError(NULL, CV_MEM_NULL, "CVODE", "CVodeSetMaxConvFails", MSGCV_NO_MEM);
+ return (CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ cv_mem->cv_maxncf = maxncf;
+
+ return(CV_SUCCESS);
+}
+
+/*
+ * CVodeSetMaxNonlinIters
+ *
+ * Specifies the maximum number of nonlinear iterations during
+ * one solve.
+ */
+
+int CVodeSetMaxNonlinIters(void *cvode_mem, int maxcor)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ CVProcessError(NULL, CV_MEM_NULL, "CVODE", "CVodeSetMaxNonlinIters", MSGCV_NO_MEM);
+ return (CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ cv_mem->cv_maxcor = maxcor;
+
+ return(CV_SUCCESS);
+}
+
+/*
+ * CVodeSetNonlinConvCoef
+ *
+ * Specifies the coeficient in the nonlinear solver convergence
+ * test
+ */
+
+int CVodeSetNonlinConvCoef(void *cvode_mem, realtype nlscoef)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ CVProcessError(NULL, CV_MEM_NULL, "CVODE", "CVodeSetNonlinConvCoef", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ cv_mem->cv_nlscoef = nlscoef;
+
+ return(CV_SUCCESS);
+}
+
+/*
+ * CVodeSetRootDirection
+ *
+ * Specifies the direction of zero-crossings to be monitored.
+ * The default is to monitor both crossings.
+ */
+
+int CVodeSetRootDirection(void *cvode_mem, int *rootdir)
+{
+ CVodeMem cv_mem;
+ int i, nrt;
+
+ if (cvode_mem==NULL) {
+ CVProcessError(NULL, CV_MEM_NULL, "CVODE", "CVodeSetRootDirection", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ nrt = cv_mem->cv_nrtfn;
+ if (nrt==0) {
+ CVProcessError(NULL, CV_ILL_INPUT, "CVODE", "CVodeSetRootDirection", MSGCV_NO_ROOT);
+ return(CV_ILL_INPUT);
+ }
+
+ for(i=0; i<nrt; i++) cv_mem->cv_rootdir[i] = rootdir[i];
+
+ return(CV_SUCCESS);
+}
+
+/*
+ * CVodeSetNoInactiveRootWarn
+ *
+ * Disables issuing a warning if some root function appears
+ * to be identically zero at the beginning of the integration
+ */
+
+int CVodeSetNoInactiveRootWarn(void *cvode_mem)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ CVProcessError(NULL, CV_MEM_NULL, "CVODE", "CVodeSetNoInactiveRootWarn", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ cv_mem->cv_mxgnull = 0;
+
+ return(CV_SUCCESS);
+}
+
+
+/*
+ * =================================================================
+ * CVODE optional output functions
+ * =================================================================
+ */
+
+/*
+ * 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
+ *
+ * Returns the current number of integration steps
+ */
+
+int CVodeGetNumSteps(void *cvode_mem, long int *nsteps)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ CVProcessError(NULL, CV_MEM_NULL, "CVODE", "CVodeGetNumSteps", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ *nsteps = nst;
+
+ return(CV_SUCCESS);
+}
+
+/*
+ * CVodeGetNumRhsEvals
+ *
+ * Returns the current number of calls to f
+ */
+
+int CVodeGetNumRhsEvals(void *cvode_mem, long int *nfevals)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ CVProcessError(NULL, CV_MEM_NULL, "CVODE", "CVodeGetNumRhsEvals", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ *nfevals = nfe;
+
+ return(CV_SUCCESS);
+}
+
+/*
+ * CVodeGetNumLinSolvSetups
+ *
+ * Returns the current number of calls to the linear solver setup routine
+ */
+
+int CVodeGetNumLinSolvSetups(void *cvode_mem, long int *nlinsetups)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ CVProcessError(NULL, CV_MEM_NULL, "CVODE", "CVodeGetNumLinSolvSetups", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ *nlinsetups = nsetups;
+
+ return(CV_SUCCESS);
+}
+
+/*
+ * CVodeGetNumErrTestFails
+ *
+ * Returns the current number of error test failures
+ */
+
+int CVodeGetNumErrTestFails(void *cvode_mem, long int *netfails)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ CVProcessError(NULL, CV_MEM_NULL, "CVODE", "CVodeGetNumErrTestFails", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ *netfails = netf;
+
+ return(CV_SUCCESS);
+}
+
+/*
+ * CVodeGetLastOrder
+ *
+ * Returns the order on the last succesful step
+ */
+
+int CVodeGetLastOrder(void *cvode_mem, int *qlast)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ CVProcessError(NULL, CV_MEM_NULL, "CVODE", "CVodeGetLastOrder", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ *qlast = qu;
+
+ return(CV_SUCCESS);
+}
+
+/*
+ * CVodeGetCurrentOrder
+ *
+ * Returns the order to be attempted on the next step
+ */
+
+int CVodeGetCurrentOrder(void *cvode_mem, int *qcur)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ CVProcessError(NULL, CV_MEM_NULL, "CVODE", "CVodeGetCurrentOrder", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ *qcur = next_q;
+
+ return(CV_SUCCESS);
+}
+
+/*
+ * CVodeGetNumStabLimOrderReds
+ *
+ * Returns the number of order reductions triggered by the stability
+ * limit detection algorithm
+ */
+
+int CVodeGetNumStabLimOrderReds(void *cvode_mem, long int *nslred)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ CVProcessError(NULL, CV_MEM_NULL, "CVODE", "CVodeGetNumStabLimOrderReds", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ if (sldeton==FALSE)
+ *nslred = 0;
+ else
+ *nslred = nor;
+
+ return(CV_SUCCESS);
+}
+
+/*
+ * CVodeGetActualInitStep
+ *
+ * Returns the step size used on the first step
+ */
+
+int CVodeGetActualInitStep(void *cvode_mem, realtype *hinused)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ CVProcessError(NULL, CV_MEM_NULL, "CVODE", "CVodeGetActualInitStep", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ *hinused = h0u;
+
+ return(CV_SUCCESS);
+}
+
+/*
+ * CVodeGetLastStep
+ *
+ * Returns the step size used on the last successful step
+ */
+
+int CVodeGetLastStep(void *cvode_mem, realtype *hlast)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ CVProcessError(NULL, CV_MEM_NULL, "CVODE", "CVodeGetLastStep", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ *hlast = hu;
+
+ return(CV_SUCCESS);
+}
+
+/*
+ * CVodeGetCurrentStep
+ *
+ * Returns the step size to be attempted on the next step
+ */
+
+int CVodeGetCurrentStep(void *cvode_mem, realtype *hcur)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ CVProcessError(NULL, CV_MEM_NULL, "CVODE", "CVodeGetCurrentStep", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ *hcur = next_h;
+
+ return(CV_SUCCESS);
+}
+
+/*
+ * CVodeGetCurrentTime
+ *
+ * Returns the current value of the independent variable
+ */
+
+int CVodeGetCurrentTime(void *cvode_mem, realtype *tcur)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ CVProcessError(NULL, CV_MEM_NULL, "CVODE", "CVodeGetCurrentTime", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ *tcur = tn;
+
+ return(CV_SUCCESS);
+}
+
+/*
+ * CVodeGetTolScaleFactor
+ *
+ * Returns a suggested factor for scaling tolerances
+ */
+
+int CVodeGetTolScaleFactor(void *cvode_mem, realtype *tolsfact)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ CVProcessError(NULL, CV_MEM_NULL, "CVODE", "CVodeGetTolScaleFactor", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ *tolsfact = tolsf;
+
+ return(CV_SUCCESS);
+}
+
+/*
+ * CVodeGetErrWeights
+ *
+ * This routine returns the current weight vector.
+ */
+
+int CVodeGetErrWeights(void *cvode_mem, N_Vector eweight)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ CVProcessError(NULL, CV_MEM_NULL, "CVODE", "CVodeGetErrWeights", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ N_VScale(ONE, ewt, eweight);
+
+ return(CV_SUCCESS);
+}
+
+/*
+ * CVodeGetEstLocalErrors
+ *
+ * Returns an estimate of the local error
+ */
+
+int CVodeGetEstLocalErrors(void *cvode_mem, N_Vector ele)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ CVProcessError(NULL, CV_MEM_NULL, "CVODE", "CVodeGetEstLocalErrors", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ N_VScale(ONE, acor, ele);
+
+ return(CV_SUCCESS);
+}
+
+/*
+ * CVodeGetWorkSpace
+ *
+ * Returns integrator work space requirements
+ */
+
+int CVodeGetWorkSpace(void *cvode_mem, long int *lenrw, long int *leniw)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ CVProcessError(NULL, CV_MEM_NULL, "CVODE", "CVodeGetWorkSpace", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ *leniw = liw;
+ *lenrw = lrw;
+
+ return(CV_SUCCESS);
+}
+
+/*
+ * CVodeGetIntegratorStats
+ *
+ * Returns integrator statistics
+ */
+
+int CVodeGetIntegratorStats(void *cvode_mem, long int *nsteps, long int *nfevals,
+ long int *nlinsetups, long int *netfails, int *qlast,
+ int *qcur, realtype *hinused, realtype *hlast,
+ realtype *hcur, realtype *tcur)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ CVProcessError(NULL, CV_MEM_NULL, "CVODE", "CVodeGetIntegratorStats", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+
+ 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;
+
+ return(CV_SUCCESS);
+}
+
+/*
+ * CVodeGetNumGEvals
+ *
+ * Returns the current number of calls to g (for rootfinding)
+ */
+
+int CVodeGetNumGEvals(void *cvode_mem, long int *ngevals)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ CVProcessError(NULL, CV_MEM_NULL, "CVODE", "CVodeGetNumGEvals", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ *ngevals = nge;
+
+ return(CV_SUCCESS);
+}
+
+/*
+ * CVodeGetRootInfo
+ *
+ * Returns pointer to array rootsfound showing roots found
+ */
+
+int CVodeGetRootInfo(void *cvode_mem, int *rootsfound)
+{
+ CVodeMem cv_mem;
+ int i, nrt;
+
+ if (cvode_mem==NULL) {
+ CVProcessError(NULL, CV_MEM_NULL, "CVODE", "CVodeGetRootInfo", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ nrt = cv_mem->cv_nrtfn;
+
+ for (i=0; i<nrt; i++) rootsfound[i] = iroots[i];
+
+ return(CV_SUCCESS);
+}
+
+
+/*
+ * CVodeGetNumNonlinSolvIters
+ *
+ * Returns the current number of iterations in the nonlinear solver
+ */
+
+int CVodeGetNumNonlinSolvIters(void *cvode_mem, long int *nniters)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ CVProcessError(NULL, CV_MEM_NULL, "CVODE", "CVodeGetNumNonlinSolvIters", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ *nniters = nni;
+
+ return(CV_SUCCESS);
+}
+
+/*
+ * CVodeGetNumNonlinSolvConvFails
+ *
+ * Returns the current number of convergence failures in the
+ * nonlinear solver
+ */
+
+int CVodeGetNumNonlinSolvConvFails(void *cvode_mem, long int *nncfails)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ CVProcessError(NULL, CV_MEM_NULL, "CVODE", "CVodeGetNumNonlinSolvConvFails", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ *nncfails = ncfn;
+
+ return(CV_SUCCESS);
+}
+
+/*
+ * CVodeGetNonlinSolvStats
+ *
+ * Returns nonlinear solver statistics
+ */
+
+int CVodeGetNonlinSolvStats(void *cvode_mem, long int *nniters,
+ long int *nncfails)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ CVProcessError(NULL, CV_MEM_NULL, "CVODE", "CVodeGetNonlinSolvStats", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ *nniters = nni;
+ *nncfails = ncfn;
+
+ return(CV_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+char *CVodeGetReturnFlagName(long int flag)
+{
+ char *name;
+
+ name = (char *)malloc(24*sizeof(char));
+
+ switch(flag) {
+ case CV_SUCCESS:
+ sprintf(name,"CV_SUCCESS");
+ break;
+ case CV_TSTOP_RETURN:
+ sprintf(name,"CV_TSTOP_RETURN");
+ break;
+ case CV_ROOT_RETURN:
+ sprintf(name,"CV_ROOT_RETURN");
+ break;
+ case CV_TOO_MUCH_WORK:
+ sprintf(name,"CV_TOO_MUCH_WORK");
+ break;
+ case CV_TOO_MUCH_ACC:
+ sprintf(name,"CV_TOO_MUCH_ACC");
+ break;
+ case CV_ERR_FAILURE:
+ sprintf(name,"CV_ERR_FAILURE");
+ break;
+ case CV_CONV_FAILURE:
+ sprintf(name,"CV_CONV_FAILURE");
+ break;
+ case CV_LINIT_FAIL:
+ sprintf(name,"CV_LINIT_FAIL");
+ break;
+ case CV_LSETUP_FAIL:
+ sprintf(name,"CV_LSETUP_FAIL");
+ break;
+ case CV_LSOLVE_FAIL:
+ sprintf(name,"CV_LSOLVE_FAIL");
+ break;
+ case CV_RHSFUNC_FAIL:
+ sprintf(name,"CV_RHSFUNC_FAIL");
+ break;
+ case CV_FIRST_RHSFUNC_ERR:
+ sprintf(name,"CV_FIRST_RHSFUNC_ERR");
+ break;
+ case CV_REPTD_RHSFUNC_ERR:
+ sprintf(name,"CV_REPTD_RHSFUNC_ERR");
+ break;
+ case CV_UNREC_RHSFUNC_ERR:
+ sprintf(name,"CV_UNREC_RHSFUNC_ERR");
+ break;
+ case CV_RTFUNC_FAIL:
+ sprintf(name,"CV_RTFUNC_FAIL");
+ break;
+ case CV_MEM_FAIL:
+ sprintf(name,"CV_MEM_FAIL");
+ break;
+ case CV_MEM_NULL:
+ sprintf(name,"CV_MEM_NULL");
+ break;
+ case CV_ILL_INPUT:
+ sprintf(name,"CV_ILL_INPUT");
+ break;
+ case CV_NO_MALLOC:
+ sprintf(name,"CV_NO_MALLOC");
+ break;
+ case CV_BAD_K:
+ sprintf(name,"CV_BAD_K");
+ break;
+ case CV_BAD_T:
+ sprintf(name,"CV_BAD_T");
+ break;
+ case CV_BAD_DKY:
+ sprintf(name,"CV_BAD_DKY");
+ break;
+ case CV_TOO_CLOSE:
+ sprintf(name,"CV_TOO_CLOSE");
+ break;
+ default:
+ sprintf(name,"NONE");
+ }
+
+ return(name);
+}
+
diff --git a/src/cvode/cvode_lapack.c b/src/cvode/cvode_lapack.c
new file mode 100644
index 0000000..c058bea
--- /dev/null
+++ b/src/cvode/cvode_lapack.c
@@ -0,0 +1,653 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.15 $
+ * $Date: 2011/03/23 22:45:54 $
+ * -----------------------------------------------------------------
+ * Programmer: Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2006, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * 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 void 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 void 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;
+ 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;
+ 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 = MIN(n-1, 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;
+
+ nje = 0;
+ nfeDQ = 0;
+ nstlj = 0;
+
+ /* 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 = ABS((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 void cvLapackDenseFree(CVodeMem cv_mem)
+{
+ CVDlsMem cvdls_mem;
+
+ cvdls_mem = (CVDlsMem) lmem;
+
+ DestroyMat(M);
+ DestroyArray(pivots);
+ DestroyMat(savedJ);
+ free(cvdls_mem);
+ cvdls_mem = NULL;
+}
+
+/*
+ * =================================================================
+ * 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;
+
+ nje = 0;
+ nfeDQ = 0;
+ nstlj = 0;
+
+ /* 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 = ABS((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 void cvLapackBandFree(CVodeMem cv_mem)
+{
+ CVDlsMem cvdls_mem;
+
+ cvdls_mem = (CVDlsMem) lmem;
+
+ DestroyMat(M);
+ DestroyArray(pivots);
+ DestroyMat(savedJ);
+ free(cvdls_mem);
+ cvdls_mem = NULL;
+}
+
diff --git a/src/cvode/cvode_spbcgs.c b/src/cvode/cvode_spbcgs.c
new file mode 100644
index 0000000..ffe1090
--- /dev/null
+++ b/src/cvode/cvode_spbcgs.c
@@ -0,0 +1,459 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.10 $
+ * $Date: 2011/03/23 22:27:43 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Aaron Collier and Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2004, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * 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 void 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;
+
+ 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 = RSqrt(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 */
+ npe = nli = nps = ncfl = nstlpre = 0;
+ njtimes = nfes = 0;
+
+ /* 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 = ABS((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 void 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;
+}
+
diff --git a/src/cvode/cvode_spgmr.c b/src/cvode/cvode_spgmr.c
new file mode 100644
index 0000000..08d85da
--- /dev/null
+++ b/src/cvode/cvode_spgmr.c
@@ -0,0 +1,463 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.10 $
+ * $Date: 2011/03/23 22:27:43 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh and
+ * Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * 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 void 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;
+
+ 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 = RSqrt( 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 */
+ npe = nli = nps = ncfl = nstlpre = 0;
+ njtimes = nfes = 0;
+
+ /* 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 = ABS((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 void 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;
+}
+
diff --git a/src/cvode/cvode_spils.c b/src/cvode/cvode_spils.c
new file mode 100644
index 0000000..2fa5e4e
--- /dev/null
+++ b/src/cvode/cvode_spils.c
@@ -0,0 +1,697 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.7 $
+ * $Date: 2011/06/23 00:19:54 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Alan C. Hindmarsh 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.
+ * -----------------------------------------------------------------
+ * This is the implementation file for the CVSPILS linear solvers.
+ * -----------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "cvode_impl.h"
+#include "cvode_spils_impl.h"
+
+/* Private constants */
+
+#define ZERO RCONST(0.0)
+#define PT25 RCONST(0.25)
+#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 (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
+ * -----------------------------------------------------------------
+ */
+
+int CVSpilsSetPrecType(void *cvode_mem, int pretype)
+{
+ CVodeMem cv_mem;
+ CVSpilsMem cvspils_mem;
+
+ /* Return immediately if cvode_mem is NULL */
+ if (cvode_mem == NULL) {
+ CVProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS", "CVSpilsSetPrecType", MSGS_CVMEM_NULL);
+ return(CVSPILS_MEM_NULL);
+ }
+ cv_mem = (CVodeMem) cvode_mem;
+
+ if (lmem == NULL) {
+ CVProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSPILS", "CVSpilsSetPrecType", MSGS_LMEM_NULL);
+ return(CVSPILS_LMEM_NULL);
+ }
+ 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);
+ return(CVSPILS_ILL_INPUT);
+ }
+
+ cvspils_mem->s_pretype = pretype;
+
+ 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);
+ }
+ cv_mem = (CVodeMem) cvode_mem;
+
+ if (lmem == NULL) {
+ CVProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSPILS", "CVSpilsSetGSType", MSGS_LMEM_NULL);
+ return(CVSPILS_LMEM_NULL);
+ }
+ cvspils_mem = (CVSpilsMem) 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);
+ return(CVSPILS_ILL_INPUT);
+ }
+
+ cvspils_mem->s_gstype = gstype;
+
+ return(CVSPILS_SUCCESS);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Function : CVSpilsSetMaxl
+ * -----------------------------------------------------------------
+ */
+
+int CVSpilsSetMaxl(void *cvode_mem, int maxl)
+{
+ CVodeMem cv_mem;
+ CVSpilsMem cvspils_mem;
+ int mxl;
+
+ /* Return immediately if cvode_mem is NULL */
+ if (cvode_mem == NULL) {
+ CVProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS", "CVSpilsSetMaxl", 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);
+ 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);
+ }
+
+ mxl = (maxl <= 0) ? CVSPILS_MAXL : maxl;
+ cvspils_mem->s_maxl = mxl;
+
+ return(CVSPILS_SUCCESS);
+}
+
+
+/*
+ * -----------------------------------------------------------------
+ * CVSpilsSetEpsLin
+ * -----------------------------------------------------------------
+ */
+
+int CVSpilsSetEpsLin(void *cvode_mem, realtype eplifac)
+{
+ CVodeMem cv_mem;
+ CVSpilsMem cvspils_mem;
+
+ /* Return immediately if cvode_mem is NULL */
+ if (cvode_mem == NULL) {
+ CVProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS", "CVSpilsSetEpsLin", 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);
+ 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->s_eplifac = (eplifac == ZERO) ? CVSPILS_EPLIN : eplifac;
+
+ return(CVSPILS_SUCCESS);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * CVSpilsSetPrecSetupFn
+ * -----------------------------------------------------------------
+ */
+
+int CVSpilsSetPreconditioner(void *cvode_mem,
+ CVSpilsPrecSetupFn pset, CVSpilsPrecSolveFn psolve)
+{
+ CVodeMem cv_mem;
+ CVSpilsMem cvspils_mem;
+
+ /* Return immediately if cvode_mem is NULL */
+ if (cvode_mem == 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", "CVSpilsSetPreconditioner", MSGS_LMEM_NULL);
+ return(CVSPILS_LMEM_NULL);
+ }
+ cvspils_mem = (CVSpilsMem) lmem;
+
+ cvspils_mem->s_pset = pset;
+ cvspils_mem->s_psolve = psolve;
+
+ 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);
+ }
+ 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;
+ }
+
+ return(CVSPILS_SUCCESS);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * CVSpilsGetWorkSpace
+ * -----------------------------------------------------------------
+ */
+
+int CVSpilsGetWorkSpace(void *cvode_mem, long int *lenrwLS, long int *leniwLS)
+{
+ CVodeMem cv_mem;
+ CVSpilsMem cvspils_mem;
+ int maxl;
+
+ /* Return immediately if cvode_mem is NULL */
+ if (cvode_mem == 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", "CVSpilsGetWorkSpace", 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;
+ }
+
+
+ return(CVSPILS_SUCCESS);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * CVSpilsGetNumPrecEvals
+ * -----------------------------------------------------------------
+ */
+
+int CVSpilsGetNumPrecEvals(void *cvode_mem, long int *npevals)
+{
+ CVodeMem cv_mem;
+ CVSpilsMem cvspils_mem;
+
+ /* Return immediately if cvode_mem is NULL */
+ if (cvode_mem == 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", "CVSpilsGetNumPrecEvals", MSGS_LMEM_NULL);
+ return(CVSPILS_LMEM_NULL);
+ }
+ cvspils_mem = (CVSpilsMem) lmem;
+
+ *npevals = npe;
+
+ return(CVSPILS_SUCCESS);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * CVSpilsGetNumPrecSolves
+ * -----------------------------------------------------------------
+ */
+
+int CVSpilsGetNumPrecSolves(void *cvode_mem, long int *npsolves)
+{
+ CVodeMem cv_mem;
+ CVSpilsMem cvspils_mem;
+
+ /* Return immediately if cvode_mem is NULL */
+ if (cvode_mem == 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", "CVSpilsGetNumPrecSolves", MSGS_LMEM_NULL);
+ return(CVSPILS_LMEM_NULL);
+ }
+ cvspils_mem = (CVSpilsMem) lmem;
+
+ *npsolves = nps;
+
+ return(CVSPILS_SUCCESS);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * CVSpilsGetNumLinIters
+ * -----------------------------------------------------------------
+ */
+
+int CVSpilsGetNumLinIters(void *cvode_mem, long int *nliters)
+{
+ CVodeMem cv_mem;
+ CVSpilsMem cvspils_mem;
+
+ /* Return immediately if cvode_mem is NULL */
+ if (cvode_mem == 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", "CVSpilsGetNumLinIters", MSGS_LMEM_NULL);
+ return(CVSPILS_LMEM_NULL);
+ }
+ cvspils_mem = (CVSpilsMem) lmem;
+
+ *nliters = nli;
+
+ return(CVSPILS_SUCCESS);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * CVSpilsGetNumConvFails
+ * -----------------------------------------------------------------
+ */
+
+int CVSpilsGetNumConvFails(void *cvode_mem, long int *nlcfails)
+{
+ CVodeMem cv_mem;
+ CVSpilsMem cvspils_mem;
+
+ /* Return immediately if cvode_mem is NULL */
+ if (cvode_mem == 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", "CVSpilsGetNumConvFails", MSGS_LMEM_NULL);
+ return(CVSPILS_LMEM_NULL);
+ }
+ cvspils_mem = (CVSpilsMem) lmem;
+
+ *nlcfails = ncfl;
+
+ 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 */
+ if (cvode_mem == 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);
+ return(CVSPILS_LMEM_NULL);
+ }
+ cvspils_mem = (CVSpilsMem) lmem;
+
+ *njvevals = 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 */
+ if (cvode_mem == 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);
+ return(CVSPILS_LMEM_NULL);
+ }
+ cvspils_mem = (CVSpilsMem) lmem;
+
+ *nfevalsLS = 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 */
+ if (cvode_mem == 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);
+ return(CVSPILS_LMEM_NULL);
+ }
+ cvspils_mem = (CVSpilsMem) lmem;
+
+ *flag = last_flag;
+
+ return(CVSPILS_SUCCESS);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * CVSpilsGetReturnFlagName
+ * -----------------------------------------------------------------
+ */
+
+char *CVSpilsGetReturnFlagName(long int flag)
+{
+ char *name;
+
+ name = (char *)malloc(30*sizeof(char));
+
+ switch(flag) {
+ case CVSPILS_SUCCESS:
+ sprintf(name,"CVSPILS_SUCCESS");
+ break;
+ case CVSPILS_MEM_NULL:
+ sprintf(name,"CVSPILS_MEM_NULL");
+ break;
+ case CVSPILS_LMEM_NULL:
+ sprintf(name,"CVSPILS_LMEM_NULL");
+ break;
+ case CVSPILS_ILL_INPUT:
+ sprintf(name,"CVSPILS_ILL_INPUT");
+ break;
+ case CVSPILS_MEM_FAIL:
+ sprintf(name,"CVSPILS_MEM_FAIL");
+ break;
+ case CVSPILS_PMEM_NULL:
+ sprintf(name,"CVSPILS_PMEM_NULL");
+ break;
+ default:
+ sprintf(name,"NONE");
+ }
+
+ return(name);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * CVSPILS private functions
+ * -----------------------------------------------------------------
+ */
+
+
+/* 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 P_data (cvspils_mem->s_P_data)
+
+/*
+ * -----------------------------------------------------------------
+ * 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)
+{
+ CVodeMem cv_mem;
+ CVSpilsMem cvspils_mem;
+ int jtflag;
+
+ cv_mem = (CVodeMem) cvode_mem;
+ cvspils_mem = (CVSpilsMem) lmem;
+
+ jtflag = jtimes(v, z, tn, ycur, fcur, j_data, ytemp);
+ njtimes++;
+ if (jtflag != 0) return(jtflag);
+
+ N_VLinearSum(ONE, v, -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)
+{
+ CVodeMem cv_mem;
+ CVSpilsMem cvspils_mem;
+ int retval;
+
+ cv_mem = (CVodeMem) cvode_mem;
+ cvspils_mem = (CVSpilsMem)lmem;
+
+ /* 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(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.
+ * -----------------------------------------------------------------
+ */
+
+int CVSpilsDQJtimes(N_Vector v, N_Vector Jv, realtype t,
+ N_Vector y, N_Vector fy,
+ void *data, 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;
+
+ /* Initialize perturbation to 1/||v|| */
+ sig = ONE/N_VWrmsNorm(v, ewt);
+
+ for (iter=0; iter<MAX_ITERS; iter++) {
+
+ /* Set work = y + sig*v */
+ N_VLinearSum(sig, v, ONE, y, work);
+
+ /* Set Jv = f(tn, y+sig*v) */
+ retval = f(t, work, Jv, user_data);
+ nfes++;
+ if (retval == 0) break;
+ if (retval < 0) return(-1);
+
+ sig *= PT25;
+ }
+
+ if (retval > 0) return(+1);
+
+ /* Replace Jv by (Jv - fy)/sig */
+ siginv = ONE/sig;
+ N_VLinearSum(siginv, Jv, -siginv, fy, Jv);
+
+ return(0);
+}
diff --git a/src/cvode/cvode_spils_impl.h b/src/cvode/cvode_spils_impl.h
new file mode 100644
index 0000000..be5491f
--- /dev/null
+++ b/src/cvode/cvode_spils_impl.h
@@ -0,0 +1,142 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.7 $
+ * $Date: 2010/12/01 22:19:48 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Alan C. Hindmarsh 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.
+ * -----------------------------------------------------------------
+ * Common implementation header file for the scaled, preconditioned
+ * linear solver modules.
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _CVSPILS_IMPL_H
+#define _CVSPILS_IMPL_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <cvode/cvode_spils.h>
+#include "cvode_impl.h"
+
+/* 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.
+ * -----------------------------------------------------------------
+ */
+
+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 */
+
+ /* Preconditioner computation
+ * (a) user-provided:
+ * - P_data == user_data
+ * - 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;
+ void (*s_pfree)(CVodeMem cv_mem);
+ void *s_P_data;
+
+ /* Jacobian times vector compuation
+ * (a) jtimes function provided by the user:
+ * - j_data == user_data
+ * - jtimesDQ == FALSE
+ * (b) internal jtimes
+ * - j_data == cvode_mem
+ * - jtimesDQ == TRUE
+ */
+ booleantype s_jtimesDQ;
+ CVSpilsJacTimesVecFn s_jtimes;
+ void *s_j_data;
+
+ long int s_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);
+
+int CVSpilsPSolve(void *cv_mem, N_Vector r, N_Vector z, 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);
+
+/*
+ * -----------------------------------------------------------------
+ * 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_JTIMES_FAILED "The Jacobian x vector routine failed in an unrecoverable manner."
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/cvode/cvode_sptfqmr.c b/src/cvode/cvode_sptfqmr.c
new file mode 100644
index 0000000..bf84290
--- /dev/null
+++ b/src/cvode/cvode_sptfqmr.c
@@ -0,0 +1,459 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.10 $
+ * $Date: 2011/03/23 22:27:43 $
+ * -----------------------------------------------------------------
+ * 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.
+ * -----------------------------------------------------------------
+ * 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 void 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;
+
+ 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 = RSqrt(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 */
+ npe = nli = nps = ncfl = nstlpre = 0;
+ njtimes = nfes = 0;
+
+ /* 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 = ABS((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 void 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;
+}
+
diff --git a/src/cvode/fcmix/CMakeLists.txt b/src/cvode/fcmix/CMakeLists.txt
new file mode 100644
index 0000000..0c19eaa
--- /dev/null
+++ b/src/cvode/fcmix/CMakeLists.txt
@@ -0,0 +1,45 @@
+# CMakeLists.txt file for the FCVODE library
+
+# Add variable fcvode_SOURCES with the sources for the FCVODE library
+SET(fcvode_SOURCES
+ fcvband.c
+ fcvbbd.c
+ fcvbp.c
+ fcvdense.c
+ fcvewt.c
+ fcvjtimes.c
+ fcvode.c
+ fcvpreco.c
+ fcvroot.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 source directories to include directories for access to
+# implementation only header files (both for fcvode and cvode)
+INCLUDE_DIRECTORIES(.)
+INCLUDE_DIRECTORIES(..)
+
+# Define C preprocessor flag -DBUILD_SUNDIALS_LIBRARY
+ADD_DEFINITIONS(-DBUILD_SUNDIALS_LIBRARY)
+
+# Only build STATIC libraries (we cannot build shared libraries
+# for the FCMIX interfaces due to unresolved symbol errors
+# 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})
+
+# Set the library name and make sure it is not deleted
+SET_TARGET_PROPERTIES(sundials_fcvode_static
+ PROPERTIES OUTPUT_NAME sundials_fcvode CLEAN_DIRECT_OUTPUT 1)
+
+# Install the FCVODE library
+INSTALL(TARGETS sundials_fcvode_static DESTINATION lib)
+
+#
+MESSAGE(STATUS "Added CVODE FCMIX module")
diff --git a/src/cvode/fcmix/Makefile.in b/src/cvode/fcmix/Makefile.in
new file mode 100644
index 0000000..9dec9a6
--- /dev/null
+++ b/src/cvode/fcmix/Makefile.in
@@ -0,0 +1,125 @@
+# -----------------------------------------------------------------
+# $Revision: 1.9 $
+# $Date: 2009/03/25 23:10:50 $
+# -----------------------------------------------------------------
+# Programmer(s): Radu Serban and Aaron Collier @ LLNL
+# -----------------------------------------------------------------
+# Copyright (c) 2002, The Regents of the University of California.
+# Produced at the Lawrence Livermore National Laboratory.
+# All rights reserved.
+# For details, see the LICENSE file.
+# -----------------------------------------------------------------
+# Makefile for FCVODE module
+#
+# @configure_input@
+# -----------------------------------------------------------------
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+builddir = @builddir@
+abs_builddir = @abs_builddir@
+top_builddir = @top_builddir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+includedir = @includedir@
+libdir = @libdir@
+
+INSTALL = @INSTALL@
+INSTALL_LIB = @INSTALL_PROGRAM@
+INSTALL_HEADER = @INSTALL_DATA@
+
+LIBTOOL = @LIBTOOL@
+LIBTOOL_DEPS = @LIBTOOL_DEPS@
+
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CC = @CC@
+CFLAGS = @CFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+
+LAPACK_ENABLED = @LAPACK_ENABLED@
+
+top_srcdir = $(srcdir)/../../..
+
+INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/src/cvode -I$(top_builddir)/include
+
+LIB_REVISION = 0:1:0
+
+FCVODE_LIB = libsundials_fcvode.la
+
+FCVODE_SRC_FILES = fcvode.c fcvband.c fcvdense.c fcvjtimes.c fcvpreco.c fcvbbd.c fcvbp.c fcvroot.c fcvewt.c
+FCVODE_BL_SRC_FILES = fcvlapack.c fcvlapband.c fcvlapdense.c
+
+FCVODE_OBJ_FILES = $(FCVODE_SRC_FILES:.c=.o)
+FCVODE_BL_OBJ_FILES = $(FCVODE_BL_SRC_FILES:.c=.o)
+
+FCVODE_LIB_FILES = $(FCVODE_SRC_FILES:.c=.lo)
+FCVODE_BL_LIB_FILES = $(FCVODE_BL_SRC_FILES:.c=.lo)
+
+mkinstalldirs = $(SHELL) $(top_srcdir)/config/mkinstalldirs
+
+# ----------------------------------------------------------------------------------------------------------------------
+
+all: $(FCVODE_LIB)
+
+$(FCVODE_LIB): $(FCVODE_LIB_FILES)
+ @if test "X${LAPACK_ENABLED}" = "Xyes"; then \
+ make lib_with_bl; \
+ else \
+ make lib_without_bl; \
+ fi
+
+lib_without_bl: $(FCVODE_LIB_FILES)
+ $(LIBTOOL) --mode=link $(CC) $(CFLAGS) -o $(FCVODE_LIB) $(FCVODE_LIB_FILES) -rpath $(libdir) $(LDFLAGS) $(LIBS) -static -version-info $(LIB_REVISION)
+
+lib_with_bl: $(FCVODE_LIB_FILES) $(FCVODE_BL_LIB_FILES)
+ $(LIBTOOL) --mode=link $(CC) $(CFLAGS) -o $(FCVODE_LIB) $(FCVODE_LIB_FILES) $(FCVODE_BL_LIB_FILES) -rpath $(libdir) $(LDFLAGS) $(LIBS) -static -version-info $(LIB_REVISION)
+
+install: $(FCVODE_LIB)
+ $(mkinstalldirs) $(libdir)
+ $(LIBTOOL) --mode=install $(INSTALL_LIB) $(FCVODE_LIB) $(libdir)
+
+uninstall:
+ $(LIBTOOL) --mode=uninstall rm -f $(libdir)/$(FCVODE_LIB)
+
+clean:
+ $(LIBTOOL) --mode=clean rm -f $(FCVODE_LIB)
+ rm -f $(FCVODE_LIB_FILES)
+ rm -f $(FCVODE_BL_LIB_FILES)
+ rm -f $(FCVODE_OBJ_FILES)
+ rm -f $(FCVODE_BL_OBJ_FILES)
+
+distclean: clean
+ rm -f Makefile
+
+fcvode.lo: $(srcdir)/fcvode.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/fcvode.c
+fcvewt.lo: $(srcdir)/fcvewt.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/fcvewt.c
+fcvband.lo: $(srcdir)/fcvband.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/fcvband.c
+fcvdense.lo: $(srcdir)/fcvdense.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/fcvdense.c
+fcvlapack.lo: $(srcdir)/fcvlapack.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/fcvlapack.c
+fcvlapband.lo: $(srcdir)/fcvlapband.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/fcvlapband.c
+fcvlapdense.lo: $(srcdir)/fcvlapdense.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/fcvlapdense.c
+fcvjtimes.lo: $(srcdir)/fcvjtimes.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/fcvjtimes.c
+fcvpreco.lo: $(srcdir)/fcvpreco.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/fcvpreco.c
+fcvbbd.lo: $(srcdir)/fcvbbd.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/fcvbbd.c
+fcvbp.lo: $(srcdir)/fcvbp.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/fcvbp.c
+fcvroot.lo: $(srcdir)/fcvroot.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/fcvroot.c
+
+libtool: $(top_builddir)/$(LIBTOOL_DEPS)
+ @cd ${top_builddir} ; \
+ ${SHELL} ./config.status --recheck ; \
+ cd ${abs_builddir}
diff --git a/src/cvode/fcmix/fcvband.c b/src/cvode/fcmix/fcvband.c
new file mode 100644
index 0000000..e7d75f0
--- /dev/null
+++ b/src/cvode/fcmix/fcvband.c
@@ -0,0 +1,97 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.6 $
+ * $Date: 2010/12/01 22:27:37 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Alan C. Hindmarsh and Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * Fortran/C interface routines for CVODE/CVBAND, for the case of
+ * a user-supplied 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_band.h>
+
+/******************************************************************************/
+
+/* Prototype of the Fortran routine */
+
+#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 */
+#ifdef __cplusplus
+}
+#endif
+
+/***************************************************************************/
+
+void FCV_BANDSETJAC(int *flag, int *ier)
+{
+ CVodeMem cv_mem;
+
+ if (*flag == 0) {
+ *ier = CVDlsSetBandJacFn(CV_cvodemem, NULL);
+ } else {
+ cv_mem = (CVodeMem) CV_cvodemem;
+ *ier = CVDlsSetBandJacFn(CV_cvodemem, FCVBandJac);
+ }
+}
+
+/***************************************************************************/
+
+/* 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.
+ 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 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 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/fcvbbd.c b/src/cvode/fcmix/fcvbbd.c
new file mode 100644
index 0000000..30400da
--- /dev/null
+++ b/src/cvode/fcmix/fcvbbd.c
@@ -0,0 +1,141 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.6 $
+ * $Date: 2010/12/01 22:27:37 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Alan C. Hindmarsh, Radu Serban and
+ * Aaron Collier @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * This module contains the routines necessary to interface with the
+ * CVBBDPRE 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 CVBBDPRE package.
+ * -----------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "fcvode.h" /* actual function names, prototypes, global vars.*/
+#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 */
+
+/***************************************************************************/
+
+/* Prototypes of the Fortran routines */
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+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_COMMFN(long int*, /* NLOC */
+ realtype*, realtype*, /* T, Y */
+ long int*, realtype*, /* IPAR, RPAR */
+ int *ier); /* IER */
+
+#ifdef __cplusplus
+}
+#endif
+
+/***************************************************************************/
+
+void FCV_BBDINIT(long int *Nloc, long int *mudq, long int *mldq, long int *mu, long int *ml,
+ realtype* dqrely, int *ier)
+{
+
+ /*
+ First call CVBBDPrecInit to initialize CVBBDPRE module:
+ Nloc is the local vector size
+ mudq,mldq are the half-bandwidths for computing preconditioner blocks
+ mu, ml are the half-bandwidths of the retained preconditioner blocks
+ dqrely is the difference quotient relative increment factor
+ FCVgloc is a pointer to the CVLocalFn function
+ FCVcfn is a pointer to the CVCommFn function
+ */
+
+ *ier = CVBBDPrecInit(CV_cvodemem, *Nloc, *mudq, *mldq, *mu, *ml,
+ *dqrely, FCVgloc, FCVcfn);
+
+ return;
+}
+
+/***************************************************************************/
+
+void FCV_BBDREINIT(long int *Nloc, long int *mudq, long int *mldq, realtype* dqrely, int *ier)
+{
+ /*
+ First call CVReInitBBD to re-initialize CVBBDPRE module:
+ mudq,mldq are the half-bandwidths for computing preconditioner blocks
+ dqrely is the difference quotient relative increment factor
+ FCVgloc is a pointer to the CVLocalFn function
+ FCVcfn is a pointer to the CVCommFn function
+ */
+
+ *ier = CVBBDPrecReInit(CV_cvodemem, *mudq, *mldq, *dqrely);
+}
+
+/***************************************************************************/
+
+/* 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 ier;
+ realtype *yloc_data, *gloc_data;
+ FCVUserData CV_userdata;
+
+ yloc_data = N_VGetArrayPointer(yloc);
+ gloc_data = N_VGetArrayPointer(gloc);
+
+ CV_userdata = (FCVUserData) user_data;
+
+ FCV_GLOCFN(&Nloc, &t, yloc_data, gloc_data,
+ CV_userdata->ipar, CV_userdata->rpar,
+ &ier);
+ return(ier);
+}
+
+/***************************************************************************/
+
+/* C function FCVcfn to interface between CVBBDPRE module and a Fortran
+ subroutine FCVCOMMF. */
+
+int FCVcfn(long int Nloc, realtype t, N_Vector y, void *user_data)
+{
+ int ier;
+ realtype *yloc;
+ FCVUserData CV_userdata;
+
+ yloc = N_VGetArrayPointer(y);
+
+ CV_userdata = (FCVUserData) user_data;
+
+ FCV_COMMFN(&Nloc, &t, yloc, CV_userdata->ipar, CV_userdata->rpar, &ier);
+
+ return(ier);
+}
+
+/***************************************************************************/
+
+/* C function FCVBBDOPT to access optional outputs from CVBBD_Data */
+
+void FCV_BBDOPT(long int *lenrwbbd, long int *leniwbbd, long int *ngebbd)
+{
+ CVBBDPrecGetWorkSpace(CV_cvodemem, lenrwbbd, leniwbbd);
+ CVBBDPrecGetNumGfnEvals(CV_cvodemem, ngebbd);
+}
diff --git a/src/cvode/fcmix/fcvbbd.h b/src/cvode/fcmix/fcvbbd.h
new file mode 100644
index 0000000..9401141
--- /dev/null
+++ b/src/cvode/fcmix/fcvbbd.h
@@ -0,0 +1,331 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.9 $
+ * $Date: 2010/12/15 19:40:08 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Alan Hindmarsh, Radu Serban and
+ * Aaron Collier @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * This is the Fortran interface include file for the BBD
+ * preconditioner (CVBBDPRE)
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * ==============================================================================
+ *
+ * FCVBBD Interface Package
+ *
+ * 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.
+ * 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
+ * FCVBBDSPTFQMR interfaces to CVBBDSptfqmr
+ * FCVBBDSPBCG interfaces to CVBBDSpbcg
+ * FCVBBDPSGMR interfaces to CVBBDSpgmr
+ * FCVBBDREINIT interfaces to 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.)
+ *
+ * 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 fcvbbd.h.
+ *
+ * ==============================================================================
+ *
+ * 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
+ * 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 CVODE user document
+ * for more complete information.
+ *
+ * (1) User-supplied right-hand side routine: FCVFUN
+ * 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) 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.
+ *
+ * (2.1) Local approximate function FCVLOCFN.
+ * 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.
+ *
+ * (2.2) Communication function FCVCOMMF.
+ * 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.
+ *
+ * (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.
+ *
+ * (4) Initialization: FNVINITP, FCVMALLOC, FCVBBDINIT.
+ *
+ * (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.
+ *
+ * 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 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.
+ *
+ * (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.4) To allocate memory and initialize data associated with the CVBBDPRE
+ * 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
+ *
+ * CALL FCVBBDSPTFQMR(IPRETYPE, MAXL, DELT, IER)
+ * (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
+ * CALL FCVSPILSSETJAC(FLAG, IER)
+ * where FLAG=0 for finite differences approximation or
+ * FLAG=1 to use the supplied routine FCVJTIMES
+ *
+ * (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:
+ * 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.
+ *
+ * (6) 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 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.
+ *
+ * (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:
+ * 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.
+ *
+ * (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:
+ * 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
+ *
+ * (9) Memory freeing: FCVFREE
+ * To the free the internal memory created by the calls to FNVINITP,
+ * FCVMALLOC, and FCVBBDINIT, make the following call:
+ * CALL FCVFREE
+ *
+ * ==============================================================================
+ */
+
+#ifndef _FCVBBD_H
+#define _FCVBBD_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+/* header files */
+
+#include <sundials/sundials_nvector.h> /* definition of type N_Vector */
+#include <sundials/sundials_types.h> /* definition of type realtype */
+
+/* Definitions of interface function names */
+
+#if defined(SUNDIALS_F77_FUNC)
+
+#define FCV_BBDINIT SUNDIALS_F77_FUNC(fcvbbdinit, FCVBBDINIT)
+#define FCV_BBDSPTFQMR SUNDIALS_F77_FUNC(fcvbbdsptfqmr, FCVBBDSPTFQMR)
+#define FCV_BBDSPBCG SUNDIALS_F77_FUNC(fcvbbdspbcg, FCVBBDSPBCG)
+#define FCV_BBDSPGMR SUNDIALS_F77_FUNC(fcvbbdspgmr, FCVBBDSPGMR)
+#define FCV_BBDREINIT SUNDIALS_F77_FUNC(fcvbbdreinit, FCVBBDREINIT)
+#define FCV_BBDOPT SUNDIALS_F77_FUNC(fcvbbdopt, FCVBBDOPT)
+#define FCV_GLOCFN SUNDIALS_F77_FUNC(fcvglocfn, FCVGLOCFN)
+#define FCV_COMMFN SUNDIALS_F77_FUNC(fcvcommfn, FCVCOMMFN)
+
+#else
+
+#define FCV_BBDINIT fcvbbdinit_
+#define FCV_BBDSPTFQMR fcvbbdsptfqmr_
+#define FCV_BBDSPBCG fcvbbdspbcg_
+#define FCV_BBDSPGMR fcvbbdspgmr_
+#define FCV_BBDREINIT fcvbbdreinit_
+#define FCV_BBDOPT fcvbbdopt_
+#define FCV_GLOCFN fcvglocfn_
+#define FCV_COMMFN fcvcommfn_
+
+#endif
+
+/* 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);
+
+/* Prototypes: Functions Called by the CVBBDPRE Module */
+
+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);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/cvode/fcmix/fcvbp.c b/src/cvode/fcmix/fcvbp.c
new file mode 100644
index 0000000..4c6b110
--- /dev/null
+++ b/src/cvode/fcmix/fcvbp.c
@@ -0,0 +1,54 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.4 $
+ * $Date: 2010/09/30 20:51:36 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Radu Serban and Aaron Collier @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * This module contains the routines necessary to interface with the
+ * CVBANDPRE 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 CVBANDPRE package.
+ * -----------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "fcvode.h" /* actual fn. names, prototypes and global vars.*/
+#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 */
+
+/***************************************************************************/
+
+void FCV_BPINIT(long int *N, long int *mu, long int *ml, int *ier)
+{
+ /*
+ Call CVBandPrecInit to initialize the CVBANDPRE module:
+ N is the vector size
+ mu, ml are the half-bandwidths of the retained preconditioner blocks
+ */
+
+ *ier = CVBandPrecInit(CV_cvodemem, *N, *mu, *ml);
+
+ return;
+}
+
+/***************************************************************************/
+
+/* C function FCVBPOPT to access optional outputs from CVBANDPRE_Data */
+
+void FCV_BPOPT(long int *lenrwbp, long int *leniwbp, long int *nfebp)
+{
+ CVBandPrecGetWorkSpace(CV_cvodemem, lenrwbp, leniwbp);
+ CVBandPrecGetNumRhsEvals(CV_cvodemem, nfebp);
+}
diff --git a/src/cvode/fcmix/fcvbp.h b/src/cvode/fcmix/fcvbp.h
new file mode 100644
index 0000000..2312e9e
--- /dev/null
+++ b/src/cvode/fcmix/fcvbp.h
@@ -0,0 +1,256 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.4 $
+ * $Date: 2010/12/15 19:40:08 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Radu Serban and Aaron Collier @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * This is the Fortran interface include file for the BAND
+ * preconditioner (CVBANDPRE).
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * ==============================================================================
+ *
+ * FCVBP Interface Package
+ *
+ * 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.
+ *
+ * The user-callable functions in this package, with the corresponding
+ * CVODE and CVBBDPRE functions, are as follows:
+ * FCVBPINIT interfaces to CVBandPrecInit
+ * FCVBPSPTFQMR interfaces to CVBPSptfqmr
+ * FCVBPSPBCG interfaces to CVBPSpbcg
+ * FCVBPSPGMR interfaces to CVBPSpgmr
+ * 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.)
+ *
+ * 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 fcvbp.h.
+ *
+ * ==============================================================================
+ *
+ * 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
+ * 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 CVODE user document
+ * for more complete information.
+ *
+ * (1) User-supplied right-hand side routine: FCVFUN
+ * 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:
+ * 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) Initialization: FNVINITS, FCVMALLOC, 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.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:
+ * 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 FCVBPSPGMR(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 FCVBPSPBCG(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 FCVBPSPTFQMR(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
+ * CALL FCVSPILSSETJAC(FLAG, IER)
+ * where FLAG=0 for finite differences approxaimtion or
+ * FLAG=1 to use the supplied routine FCVJTIMES
+ *
+ * (4) 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 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.
+ *
+ * (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:
+ * 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
+ *
+ * (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:
+ * 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
+ *
+ * (7) Memory freeing: FCVFREE
+ * To the free the internal memory created by the calls to FNVINITS,
+ * FCVMALLOC, and FCVBPINIT, make the following call:
+ * CALL FCVFREE
+ *
+ * ==============================================================================
+ */
+
+#ifndef _FCVBP_H
+#define _FCVBP_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+/* header files */
+
+#include <sundials/sundials_nvector.h> /* definition of type N_Vector */
+#include <sundials/sundials_types.h> /* definition of type realtype */
+
+/* Definitions of interface function names */
+
+#if defined(SUNDIALS_F77_FUNC)
+
+#define FCV_BPINIT SUNDIALS_F77_FUNC(fcvbpinit, FCVBPINIT)
+#define FCV_BPSPTFQMR SUNDIALS_F77_FUNC(fcvbpsptfqmr, FCVBPSPTFQMR)
+#define FCV_BPSPBCG SUNDIALS_F77_FUNC(fcvbpspbcg, FCVBPSPBCG)
+#define FCV_BPSPGMR SUNDIALS_F77_FUNC(fcvbpspgmr, FCVBPSPGMR)
+#define FCV_BPOPT SUNDIALS_F77_FUNC(fcvbpopt, FCVBPOPT)
+
+#else
+
+#define FCV_BPINIT fcvbpinit_
+#define FCV_BPSPTFQMR fcvbpsptfqmr_
+#define FCV_BPSPBCG fcvbpspbcg_
+#define FCV_BPSPGMR fcvbpspgmr_
+#define FCV_BPOPT fcvbpopt_
+
+#endif
+
+/* Prototypes of exported function */
+void FCV_BPINIT(long int *N, long int *mu, long int *ml, int *ier);
+void FCV_BPSPTFQMR(int *pretype, int *maxl, realtype *delt, int *ier);
+void FCV_BPSPBCG(int *pretype, int *maxl, realtype *delt, int *ier);
+void FCV_BPSPGMR(int *pretype, int *gstype, int *maxl, realtype *delt, int *ier);
+void FCV_BPOPT(long int *lenrwbp, long int *leniwbp, long int *nfebp);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/cvode/fcmix/fcvdense.c b/src/cvode/fcmix/fcvdense.c
new file mode 100644
index 0000000..fa7cd4c
--- /dev/null
+++ b/src/cvode/fcmix/fcvdense.c
@@ -0,0 +1,93 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.6 $
+ * $Date: 2010/12/01 22:27:37 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Alan C. Hindmarsh and Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * Fortran/C interface routines for CVODE/CVDENSE, for the case
+ * of a user-supplied 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_dense.h>
+
+/***************************************************************************/
+
+/* Prototype of the Fortran routine */
+
+#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 */
+#ifdef __cplusplus
+}
+#endif
+
+/***************************************************************************/
+
+void FCV_DENSESETJAC(int *flag, int *ier)
+{
+ CVodeMem cv_mem;
+
+ if (*flag == 0) {
+ *ier = CVDlsSetDenseJacFn(CV_cvodemem, NULL);
+ } else {
+ cv_mem = (CVodeMem) CV_cvodemem;
+ *ier = CVDlsSetDenseJacFn(CV_cvodemem, FCVDenseJac);
+ }
+}
+
+/***************************************************************************/
+
+/* 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)
+{
+ 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/fcvewt.c b/src/cvode/fcmix/fcvewt.c
new file mode 100644
index 0000000..60a1f8d
--- /dev/null
+++ b/src/cvode/fcmix/fcvewt.c
@@ -0,0 +1,74 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.3 $
+ * $Date: 2007/04/30 19:28:59 $
+ * -----------------------------------------------------------------
+ * Programmer: Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * Fortran/C interface routines for CVODE, for the case of a
+ * user-supplied error weight calculation 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 */
+
+/***************************************************************************/
+
+/* Prototype of the Fortran routine */
+
+#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 */
+#ifdef __cplusplus
+}
+#endif
+
+/***************************************************************************/
+
+/*
+ * User-callable function to interface to CVodeSetEwtFn.
+ */
+
+void FCV_EWTSET(int *flag, int *ier)
+{
+ CVodeMem cv_mem;
+
+ if (*flag != 0) {
+ cv_mem = (CVodeMem) CV_cvodemem;
+ *ier = CVodeWFtolerances(CV_cvodemem, FCVEwtSet);
+ }
+}
+
+/***************************************************************************/
+
+/*
+ * C function to interface between CVODE and a Fortran subroutine FCVEWT.
+ */
+
+int FCVEwtSet(N_Vector y, N_Vector ewt, void *user_data)
+{
+ int ier = 0;
+ realtype *ydata, *ewtdata;
+ FCVUserData CV_userdata;
+
+ ydata = N_VGetArrayPointer(y);
+ ewtdata = N_VGetArrayPointer(ewt);
+
+ CV_userdata = (FCVUserData) user_data;
+
+ FCV_EWT(ydata, ewtdata, CV_userdata->ipar, CV_userdata->rpar, &ier);
+
+ return(ier);
+}
diff --git a/src/cvode/fcmix/fcvjtimes.c b/src/cvode/fcmix/fcvjtimes.c
new file mode 100644
index 0000000..eb5f20e
--- /dev/null
+++ b/src/cvode/fcmix/fcvjtimes.c
@@ -0,0 +1,95 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.3 $
+ * $Date: 2007/04/30 19:28:59 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Alan C. Hindmarsh, Radu Serban and
+ * Aaron Collier @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * 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.
+ * -----------------------------------------------------------------
+ */
+
+#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_spils.h>
+
+/***************************************************************************/
+
+/* Prototype of the Fortran routine */
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+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 */
+
+#ifdef __cplusplus
+}
+#endif
+
+/***************************************************************************/
+
+void FCV_SPILSSETJAC(int *flag, int *ier)
+{
+ CVodeMem cv_mem;
+
+ if (*flag == 0) {
+ *ier = CVSpilsSetJacTimesVecFn(CV_cvodemem, NULL);
+ } else {
+ cv_mem = (CVodeMem) CV_cvodemem;
+ *ier = CVSpilsSetJacTimesVecFn(CV_cvodemem, FCVJtimes);
+ }
+}
+
+/***************************************************************************/
+
+/* 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. */
+
+int FCVJtimes(N_Vector v, N_Vector Jv, realtype t,
+ N_Vector y, N_Vector fy,
+ void *user_data, N_Vector work)
+{
+ realtype *vdata, *Jvdata, *ydata, *fydata, *wkdata;
+ realtype h;
+ FCVUserData CV_userdata;
+
+ int ier = 0;
+
+ CVodeGetLastStep(CV_cvodemem, &h);
+
+ vdata = N_VGetArrayPointer(v);
+ Jvdata = N_VGetArrayPointer(Jv);
+ ydata = N_VGetArrayPointer(y);
+ fydata = N_VGetArrayPointer(fy);
+ wkdata = N_VGetArrayPointer(work);
+
+ CV_userdata = (FCVUserData) user_data;
+
+ FCV_JTIMES (vdata, Jvdata, &t, ydata, fydata, &h,
+ CV_userdata->ipar, CV_userdata->rpar, wkdata, &ier);
+
+ return(ier);
+}
diff --git a/src/cvode/fcmix/fcvlapack.c b/src/cvode/fcmix/fcvlapack.c
new file mode 100644
index 0000000..62ec757
--- /dev/null
+++ b/src/cvode/fcmix/fcvlapack.c
@@ -0,0 +1,52 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.1 $
+ * $Date: 2006/11/10 21:04:11 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * 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
new file mode 100644
index 0000000..e3fe9f6
--- /dev/null
+++ b/src/cvode/fcmix/fcvlapband.c
@@ -0,0 +1,106 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.6 $
+ * $Date: 2010/12/01 22:27:37 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * 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)
+{
+ CVodeMem cv_mem;
+
+ if (*flag == 0) {
+
+ *ier = CVDlsSetBandJacFn(CV_cvodemem, NULL);
+
+ } else {
+
+ cv_mem = (CVodeMem) CV_cvodemem;
+ *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
new file mode 100644
index 0000000..bb87e24
--- /dev/null
+++ b/src/cvode/fcmix/fcvlapdense.c
@@ -0,0 +1,95 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.6 $
+ * $Date: 2010/12/01 22:27:37 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * 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)
+{
+ CVodeMem cv_mem;
+
+ if (*flag == 0) {
+ *ier = CVDlsSetDenseJacFn(CV_cvodemem, NULL);
+ } else {
+ cv_mem = (CVodeMem) CV_cvodemem;
+ *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
new file mode 100644
index 0000000..883c58d
--- /dev/null
+++ b/src/cvode/fcmix/fcvode.c
@@ -0,0 +1,603 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.9 $
+ * $Date: 2010/12/09 19:36:24 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Alan C. Hindmarsh, Radu Serban and
+ * Aaron Collier @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * 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.
+ * -----------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "fcvode.h" /* actual function names, prototypes, global vars.*/
+#include "cvode_impl.h" /* definition of CVodeMem type */
+
+#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_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 */
+
+/***************************************************************************/
+
+/* Definitions for global variables shared amongst various routines */
+
+void *CV_cvodemem;
+long int *CV_iout;
+realtype *CV_rout;
+int CV_nrtfn;
+int CV_ls;
+
+/***************************************************************************/
+
+/* private constant(s) */
+#define ZERO RCONST(0.0)
+
+/***************************************************************************/
+
+/* Prototypes of the Fortran routines */
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+ extern void FCV_FUN(realtype*, /* T */
+ realtype*, /* Y */
+ realtype*, /* YDOT */
+ long int*, /* IPAR */
+ realtype*, /* RPAR */
+ int*); /* IER */
+#ifdef __cplusplus
+}
+#endif
+
+/**************************************************************************/
+
+void FCV_MALLOC(realtype *t0, realtype *y0,
+ int *meth, int *itmeth, int *iatol,
+ realtype *rtol, realtype *atol,
+ long int *iout, realtype *rout,
+ long int *ipar, realtype *rpar,
+ int *ier)
+{
+ int lmm, iter;
+ N_Vector Vatol;
+ FCVUserData CV_userdata;
+
+ *ier = 0;
+
+ /* Check for required vector operations */
+ 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");
+ return;
+ }
+
+ /* Initialize all pointers to NULL */
+ CV_cvodemem = NULL;
+ Vatol = NULL;
+
+ /* Create CVODE object */
+ lmm = (*meth == 1) ? CV_ADAMS : CV_BDF;
+ iter = (*itmeth == 1) ? CV_FUNCTIONAL : CV_NEWTON;
+ CV_cvodemem = CVodeCreate(lmm, iter);
+ if (CV_cvodemem == NULL) {
+ *ier = -1;
+ return;
+ }
+
+ /* Set and attach user data */
+ CV_userdata = NULL;
+ CV_userdata = (FCVUserData) malloc(sizeof *CV_userdata);
+ if (CV_userdata == NULL) {
+ *ier = -1;
+ return;
+ }
+ CV_userdata->rpar = rpar;
+ CV_userdata->ipar = ipar;
+
+ *ier = CVodeSetUserData(CV_cvodemem, CV_userdata);
+ if(*ier != CV_SUCCESS) {
+ free(CV_userdata); CV_userdata = NULL;
+ *ier = -1;
+ return;
+ }
+
+ /* Set data in F2C_CVODE_vec to y0 */
+ N_VSetArrayPointer(y0, F2C_CVODE_vec);
+
+ /* Call CVodeInit */
+ *ier = CVodeInit(CV_cvodemem, FCVf, *t0, F2C_CVODE_vec);
+
+ /* Reset data pointers */
+ N_VSetArrayPointer(NULL, F2C_CVODE_vec);
+
+ /* On failure, exit */
+ if(*ier != CV_SUCCESS) {
+ free(CV_userdata); CV_userdata = NULL;
+ *ier = -1;
+ return;
+ }
+
+ /* Set tolerances */
+ switch (*iatol) {
+ case 1:
+ *ier = CVodeSStolerances(CV_cvodemem, *rtol, *atol);
+ break;
+ case 2:
+ Vatol = NULL;
+ Vatol = N_VCloneEmpty(F2C_CVODE_vec);
+ if (Vatol == NULL) {
+ free(CV_userdata); CV_userdata = NULL;
+ *ier = -1;
+ return;
+ }
+ N_VSetArrayPointer(atol, Vatol);
+ *ier = CVodeSVtolerances(CV_cvodemem, *rtol, Vatol);
+ N_VDestroy(Vatol);
+ break;
+ }
+
+ /* On failure, exit */
+ if(*ier != CV_SUCCESS) {
+ free(CV_userdata); CV_userdata = NULL;
+ *ier = -1;
+ return;
+ }
+
+ /* Grab optional output arrays and store them in global variables */
+ CV_iout = iout;
+ CV_rout = rout;
+
+ /* Store the unit roundoff in rout for user access */
+ CV_rout[5] = UNIT_ROUNDOFF;
+
+ return;
+}
+
+/***************************************************************************/
+
+void FCV_REINIT(realtype *t0, realtype *y0,
+ int *iatol, realtype *rtol, realtype *atol,
+ int *ier)
+{
+ N_Vector Vatol;
+
+ *ier = 0;
+
+ /* Initialize all pointers to NULL */
+ Vatol = NULL;
+
+ /* Set data in F2C_CVODE_vec to y0 */
+ N_VSetArrayPointer(y0, F2C_CVODE_vec);
+
+ /* Call CVReInit */
+ *ier = CVodeReInit(CV_cvodemem, *t0, F2C_CVODE_vec);
+
+ /* Reset data pointers */
+ N_VSetArrayPointer(NULL, F2C_CVODE_vec);
+
+ /* On failure, exit */
+ if (*ier != CV_SUCCESS) {
+ *ier = -1;
+ return;
+ }
+
+ /* Set tolerances */
+ switch (*iatol) {
+ case 1:
+ *ier = CVodeSStolerances(CV_cvodemem, *rtol, *atol);
+ break;
+ case 2:
+ Vatol = NULL;
+ Vatol = N_VCloneEmpty(F2C_CVODE_vec);
+ if (Vatol == NULL) {
+ *ier = -1;
+ return;
+ }
+ N_VSetArrayPointer(atol, Vatol);
+ *ier = CVodeSVtolerances(CV_cvodemem, *rtol, Vatol);
+ N_VDestroy(Vatol);
+ break;
+ }
+
+ /* On failure, exit */
+ if (*ier != CV_SUCCESS) {
+ *ier = -1;
+ return;
+ }
+
+ return;
+}
+
+/***************************************************************************/
+
+void FCV_SETIIN(char key_name[], long int *ival, int *ier, int key_len)
+{
+ if (!strncmp(key_name,"MAX_ORD", (size_t)key_len))
+ *ier = CVodeSetMaxOrd(CV_cvodemem, (int) *ival);
+ else if (!strncmp(key_name,"MAX_NSTEPS", (size_t)key_len))
+ *ier = CVodeSetMaxNumSteps(CV_cvodemem, (int) *ival);
+ else if (!strncmp(key_name,"MAX_ERRFAIL", (size_t)key_len))
+ *ier = CVodeSetMaxErrTestFails(CV_cvodemem, (int) *ival);
+ else if (!strncmp(key_name,"MAX_NITERS", (size_t)key_len))
+ *ier = CVodeSetMaxNonlinIters(CV_cvodemem, (int) *ival);
+ else if (!strncmp(key_name,"MAX_CONVFAIL", (size_t)key_len))
+ *ier = CVodeSetMaxConvFails(CV_cvodemem, (int) *ival);
+ else if (!strncmp(key_name,"HNIL_WARNS", (size_t)key_len))
+ *ier = CVodeSetMaxHnilWarns(CV_cvodemem, (int) *ival);
+ else if (!strncmp(key_name,"STAB_LIM", (size_t)key_len))
+ *ier = CVodeSetStabLimDet(CV_cvodemem, (int) *ival);
+ else {
+ *ier = -99;
+ printf("FCVSETIIN: Unrecognized key.\n\n");
+ }
+
+}
+
+/***************************************************************************/
+
+void FCV_SETRIN(char key_name[], realtype *rval, int *ier, int key_len)
+{
+ if (!strncmp(key_name,"INIT_STEP", (size_t)key_len))
+ *ier = CVodeSetInitStep(CV_cvodemem, *rval);
+ else if (!strncmp(key_name,"MAX_STEP", (size_t)key_len))
+ *ier = CVodeSetMaxStep(CV_cvodemem, *rval);
+ else if (!strncmp(key_name,"MIN_STEP", (size_t)key_len))
+ *ier = CVodeSetMinStep(CV_cvodemem, *rval);
+ else if (!strncmp(key_name,"STOP_TIME", (size_t)key_len))
+ *ier = CVodeSetStopTime(CV_cvodemem, *rval);
+ else if (!strncmp(key_name,"NLCONV_COEF", (size_t)key_len))
+ *ier = CVodeSetNonlinConvCoef(CV_cvodemem, *rval);
+ else {
+ *ier = -99;
+ printf("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_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_DIAG(int *ier)
+{
+ *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;
+}
+
+/***************************************************************************/
+
+void FCV_CVODE(realtype *tout, realtype *t, realtype *y, int *itask, int *ier)
+{
+ /*
+ tout is the t value where output is desired
+ F2C_CVODE_vec is the N_Vector containing the solution on return
+ t is the returned independent variable value
+ itask is the task indicator (1 = CV_NORMAL, 2 = CV_ONE_STEP,
+ 3 = CV_NORMAL_TSTOP, 4 = CV_ONE_STEP_TSTOP)
+ */
+
+ int qu, qcur;
+
+ N_VSetArrayPointer(y, F2C_CVODE_vec);
+
+ *ier = CVode(CV_cvodemem, *tout, F2C_CVODE_vec, t, *itask);
+
+ N_VSetArrayPointer(NULL, F2C_CVODE_vec);
+
+ /* Load optional outputs in iout & rout */
+ CVodeGetWorkSpace(CV_cvodemem,
+ &CV_iout[0], /* LENRW */
+ &CV_iout[1]); /* LENIW */
+ CVodeGetIntegratorStats(CV_cvodemem,
+ &CV_iout[2], /* NST */
+ &CV_iout[3], /* NFE */
+ &CV_iout[7], /* NSETUPS */
+ &CV_iout[4], /* NETF */
+ &qu, /* QU */
+ &qcur, /* QCUR */
+ &CV_rout[0], /* H0U */
+ &CV_rout[1], /* HU */
+ &CV_rout[2], /* HCUR */
+ &CV_rout[3]); /* TCUR */
+ CV_iout[8] = (long int) qu;
+ CV_iout[9] = (long int) qcur;
+ CVodeGetTolScaleFactor(CV_cvodemem,
+ &CV_rout[4]); /* TOLSFAC */
+ CVodeGetNonlinSolvStats(CV_cvodemem,
+ &CV_iout[6], /* NNI */
+ &CV_iout[5]); /* NCFN */
+ CVodeGetNumStabLimOrderReds(CV_cvodemem, &CV_iout[10]); /* NOR */
+
+ /* Root finding is on */
+ if (CV_nrtfn != 0)
+ 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:
+ 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_SPGMR:
+ case CV_LS_SPBCG:
+ case CV_LS_SPTFQMR:
+ 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 */
+ CVSpilsGetNumJtimesEvals(CV_cvodemem, &CV_iout[16]); /* NJTV */
+ CVSpilsGetNumPrecEvals(CV_cvodemem, &CV_iout[17]); /* NPE */
+ CVSpilsGetNumPrecSolves(CV_cvodemem, &CV_iout[18]); /* NPS */
+ CVSpilsGetNumLinIters(CV_cvodemem, &CV_iout[19]); /* NLI */
+ CVSpilsGetNumConvFails(CV_cvodemem, &CV_iout[20]); /* NCFL */
+ }
+}
+
+/***************************************************************************/
+
+void FCV_DKY (realtype *t, int *k, realtype *dky, int *ier)
+{
+ /*
+ t is the t value where output is desired
+ k is the derivative order
+ F2C_CVODE_vec is the N_Vector containing the solution derivative on return
+ */
+
+ N_VSetArrayPointer(dky, F2C_CVODE_vec);
+
+ *ier = 0;
+ *ier = CVodeGetDky(CV_cvodemem, *t, *k, F2C_CVODE_vec);
+
+ N_VSetArrayPointer(NULL, F2C_CVODE_vec);
+
+}
+
+/*************************************************/
+
+void FCV_GETERRWEIGHTS(realtype *eweight, int *ier)
+{
+ /* Attach user data to vector */
+ N_VSetArrayPointer(eweight, F2C_CVODE_vec);
+
+ *ier = 0;
+ *ier = CVodeGetErrWeights(CV_cvodemem, F2C_CVODE_vec);
+
+ /* Reset data pointers */
+ N_VSetArrayPointer(NULL, F2C_CVODE_vec);
+
+ return;
+}
+
+/*************************************************/
+
+void FCV_GETESTLOCALERR(realtype *ele, int *ier)
+{
+ /* Attach user data to vector */
+ N_VSetArrayPointer(ele, F2C_CVODE_vec);
+
+ *ier = 0;
+ *ier = CVodeGetEstLocalErrors(CV_cvodemem, F2C_CVODE_vec);
+
+ /* Reset data pointers */
+ N_VSetArrayPointer(NULL, F2C_CVODE_vec);
+
+ return;
+}
+
+/***************************************************************************/
+
+void FCV_FREE ()
+{
+ CVodeMem cv_mem;
+
+ cv_mem = (CVodeMem) CV_cvodemem;
+
+ 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);
+}
+
+/***************************************************************************/
+
+/*
+ * C function CVf to interface between CVODE and a Fortran subroutine FCVFUN.
+ * Addresses of t, y, and ydot are passed to CVFUN, using the
+ * routine N_VGetArrayPointer from the NVECTOR module.
+ * Auxiliary data is assumed to be communicated by Common.
+ */
+
+int FCVf(realtype t, N_Vector y, N_Vector ydot, void *user_data)
+{
+ int ier;
+ realtype *ydata, *dydata;
+ FCVUserData CV_userdata;
+
+ ydata = N_VGetArrayPointer(y);
+ dydata = N_VGetArrayPointer(ydot);
+
+ CV_userdata = (FCVUserData) user_data;
+
+ FCV_FUN(&t, ydata, dydata, CV_userdata->ipar, CV_userdata->rpar, &ier);
+
+ return(ier);
+}
diff --git a/src/cvode/fcmix/fcvode.h b/src/cvode/fcmix/fcvode.h
new file mode 100644
index 0000000..08232af
--- /dev/null
+++ b/src/cvode/fcmix/fcvode.h
@@ -0,0 +1,758 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.9 $
+ * $Date: 2010/12/01 22:27:37 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Alan C. Hindmarsh, Radu Serban and
+ * Aaron Collier @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * This is the header file for FCVODE, the Fortran interface to
+ * the CVODE package.
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * =============================================================================
+ *
+ * FCVODE Interface Package
+ *
+ * The FCVODE Interface Package is a package of C functions which support
+ * the use of the CVODE solver, for the solution of ODE systems
+ * dy/dt = f(t,y), in a mixed Fortran/C setting. While CVODE 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 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
+ *
+ * FCVMALLOC interfaces to CVodeCreate, CVodeSetUserData, and CVodeInit
+ *
+ * FCVREINIT interfaces to CVReInit
+ *
+ * FCVSETIIN and FCVSETRIN interface to CVodeSet*
+ *
+ * FCVEWTSET interfaces to CVodeWFtolerances
+ *
+ * FCVDIAG interfaces to CVDiag
+ *
+ * FCVDENSE interfaces to CVDense
+ * FCVDENSESETJAC interfaces to CVDenseSetJacFn
+ *
+ * FCVBAND interfaces to CVBand
+ * FCVBANDSETJAC interfaces to CVBandSetJacFn
+ *
+ * FCVLAPACKDENSE interfaces to CVLapackDense
+ * FCVLAPACKBAND interfaces to CVLapackBand
+ * FCVLAPACKDENSESETJAC interfaces to CVLapackSetJacFn
+ * FCVLAPACKBANDSETJAC interfaces to CVLapackSetJacFn
+ *
+ * FCVSPGMR and FCVSPGMRREINIT interface to CVSpgmr and CVSpilsSet*
+ * FCVSPBCG, FCVSPBCGREINIT interface to CVSpbcg and CVSpilsSet*
+ * FCVSPTFQMR, FCVSPTFQMRREINIT interface to CVSptfqmr and CVSpilsSet*
+ *
+ * FCVSPILSSETJAC interfaces to CVSpilsSetJacTimesVecFn
+ * FCVSPILSSETPREC interfaces to CVSpilsSetPreconditioner
+ *
+ * FCVODE interfaces to CVode, CVodeGet*, and CV*Get*
+ *
+ * FCVDKY interfaces to CVodeGetDky
+ *
+ * FCVGETERRWEIGHTS interfaces to CVodeGetErrWeights
+ *
+ * FCVGETESTLOCALERR interfaces to CVodeGetEstLocalErrors
+ *
+ * FCVFREE interfaces to 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
+ * FCVEWT is called by interface fn. FCVEwtSet of type 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.
+ *
+ * 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 FCVODE Interface Package
+ *
+ * The usage of FCVODE requires calls to five or more 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 CVODE 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 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.
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * (1) User-supplied right-hand side routine: FCVFUN
+ * 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.
+ *
+ * (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.
+ *
+ * (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.
+ *
+ * (4s) 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.
+ *
+ * (5s) 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.
+ *
+ * (6) 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.
+ *
+ * (7) 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.
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * (8) Initialization: FNVINITS / FNVINITP , FCVMALLOC, FCVREINIT
+ *
+ * (8.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.
+ *
+ * (8.1p) To initialize the 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.
+ *
+ * (8.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 optional outputs are:
+ * LENRW = IOUT( 1) from CVodeGetWorkSpace
+ * LENIW = IOUT( 2) from CVodeGetWorkSpace
+ * NST = IOUT( 3) from CVodeGetNumSteps
+ * NFE = IOUT( 4) from CVodeGetNumRhsEvals
+ * NETF = IOUT( 5) from CVodeGetNumErrTestFails
+ * NCFN = IOUT( 6) from CVodeGetNumNonlinSolvConvFails
+ * NNI = IOUT( 7) from CVodeGetNumNonlinSolvIters
+ * NSETUPS = IOUT( 8) from CVodeGetNumLinSolvSetups
+ * QU = IOUT( 9) from CVodeGetLastOrder
+ * QCUR = IOUT(10) from CVodeGetCurrentOrder
+ * NOR = IOUT(11) from CVodeGetNumStabLimOrderReds
+ * NGE = IOUT(12) from CVodeGetNumGEvals
+ *
+ * H0U = ROUT( 1) from CVodeGetActualInitStep
+ * HU = ROUT( 2) from CVodeGetLastStep
+ * HCUR = ROUT( 3) from CVodeGetCurrentStep
+ * TCUR = ROUT( 4) from CVodeGetCurrentTime
+ * TOLSF = ROUT( 5) from CVodeGetTolScaleFactor
+ * UROUND = ROUT( 6) from UNIT_ROUNDOFF
+ * 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.
+ *
+ * (8.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.
+ *
+ * (8.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.
+ *
+ * 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.
+ *
+ * FCVSETIIN and FCVSETRIN return IER = 0 if successful and IER < 0 if an
+ * error occured.
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * (9) 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.
+ *
+ * (9.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:
+ * 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.
+ *
+ * (9.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
+ *
+ * If the user program includes the FCVDJAC routine for the evaluation of the
+ * dense approximation to the Jacobian, 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.
+ *
+ * (9.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
+ *
+ * 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.
+ *
+ * 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.
+ *
+ * (9.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.
+ *
+ * (9.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)
+ *
+ * (9.6) 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
+ *
+ *
+ * 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.
+ *
+ * (9.7) 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.
+ *
+ * (9.8) 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.
+ *
+ * (9.9) 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.
+ *
+ * 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.
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * (10) 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.
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * (11) 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.
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * (12) Memory freeing: FCVFREE
+ * To free the internal memory created by the calls to FCVMALLOC and
+ * FNVINITS or FNVINITP, make the call
+ * CALL FCVFREE
+ *
+ * =============================================================================
+ */
+
+#ifndef _FCVODE_H
+#define _FCVODE_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+/* header files */
+
+#include <cvode/cvode.h>
+#include <sundials/sundials_direct.h> /* definition of type DlsMat */
+#include <sundials/sundials_nvector.h> /* definition of type N_Vector */
+#include <sundials/sundials_types.h> /* definition of type realtype */
+
+/* Definitions of interface function names */
+
+#if defined(SUNDIALS_F77_FUNC)
+
+#define FCV_MALLOC SUNDIALS_F77_FUNC(fcvmalloc, FCVMALLOC)
+#define FCV_REINIT SUNDIALS_F77_FUNC(fcvreinit, FCVREINIT)
+#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_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_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_SPILSSETJAC SUNDIALS_F77_FUNC(fcvspilssetjac, FCVSPILSSETJAC)
+#define FCV_SPILSSETPREC SUNDIALS_F77_FUNC(fcvspilssetprec, FCVSPILSSETPREC)
+#define FCV_CVODE SUNDIALS_F77_FUNC(fcvode, FCVODE)
+#define FCV_DKY SUNDIALS_F77_FUNC(fcvdky, FCVDKY)
+#define FCV_FREE SUNDIALS_F77_FUNC(fcvfree, FCVFREE)
+#define FCV_FUN SUNDIALS_F77_FUNC(fcvfun, FCVFUN)
+#define FCV_DJAC SUNDIALS_F77_FUNC(fcvdjac, FCVDJAC)
+#define FCV_BJAC SUNDIALS_F77_FUNC(fcvbjac, FCVBJAC)
+#define FCV_PSOL SUNDIALS_F77_FUNC(fcvpsol, FCVPSOL)
+#define FCV_PSET SUNDIALS_F77_FUNC(fcvpset, FCVPSET)
+#define FCV_JTIMES SUNDIALS_F77_FUNC(fcvjtimes, FCVJTIMES)
+#define FCV_EWT SUNDIALS_F77_FUNC(fcvewt, FCVEWT)
+#define FCV_GETERRWEIGHTS SUNDIALS_F77_FUNC(fcvgeterrweights, FCVGETERRWEIGHTS)
+#define FCV_GETESTLOCALERR SUNDIALS_F77_FUNC(fcvgetestlocalerr, FCVGETESTLOCALERR)
+
+#else
+
+#define FCV_MALLOC fcvmalloc_
+#define FCV_REINIT fcvreinit_
+#define FCV_SETIIN fcvsetiin_
+#define FCV_SETRIN fcvsetrin_
+#define FCV_EWTSET fcvewtset_
+#define FCV_DIAG fcvdiag_
+#define FCV_DENSE fcvdense_
+#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_SPTFQMR fcvsptfqmr_
+#define FCV_SPTFQMRREINIT fcvsptfqmrreinit_
+#define FCV_SPBCG fcvspbcg_
+#define FCV_SPBCGREINIT fcvspbcgreinit_
+#define FCV_SPGMR fcvspgmr_
+#define FCV_SPGMRREINIT fcvspgmrreinit_
+#define FCV_SPILSSETJAC fcvspilssetjac_
+#define FCV_SPILSSETPREC fcvspilssetprec_
+#define FCV_CVODE fcvode_
+#define FCV_DKY fcvdky_
+#define FCV_FREE fcvfree_
+#define FCV_FUN fcvfun_
+#define FCV_DJAC fcvdjac_
+#define FCV_BJAC fcvbjac_
+#define FCV_PSOL fcvpsol_
+#define FCV_PSET fcvpset_
+#define FCV_JTIMES fcvjtimes_
+#define FCV_EWT fcvewt_
+#define FCV_GETERRWEIGHTS fcvgeterrweights_
+#define FCV_GETESTLOCALERR fcvgetestlocalerr_
+
+#endif
+
+ /* Type for user data */
+
+ typedef struct {
+ realtype *rpar;
+ long int *ipar;
+ } *FCVUserData;
+
+ /* Prototypes of exported functions */
+
+ void FCV_MALLOC(realtype *t0, realtype *y0,
+ int *meth, int *itmeth, int *iatol,
+ realtype *rtol, realtype *atol,
+ long int *iout, realtype *rout,
+ long int *ipar, realtype *rpar,
+ int *ier);
+
+ void FCV_REINIT(realtype *t0, realtype *y0,
+ int *iatol, realtype *rtol, realtype *atol,
+ int *ier);
+
+ void FCV_SETIIN(char key_name[], long int *ival, int *ier, int key_len);
+
+ void FCV_SETRIN(char key_name[], realtype *rval, int *ier, int key_len);
+
+ void FCV_EWTSET(int *flag, int *ier);
+
+ void FCV_DIAG(int *ier);
+
+ void FCV_DENSE(long int *neq, 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_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_SPILSSETJAC(int *flag, int *ier);
+ void FCV_SPILSSETPREC(int *flag, 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);
+
+ void FCV_GETERRWEIGHTS(realtype *eweight, int *ier);
+ void FCV_GETESTLOCALERR(realtype *ele, int *ier);
+
+ void FCV_FREE(void);
+
+
+ /* Prototypes: Functions Called by the CVODE Solver */
+
+ 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,
+ 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,
+ 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 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);
+
+ 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 FCVJtimes(N_Vector v, N_Vector Jv, realtype t,
+ N_Vector y, N_Vector fy,
+ void *user_data, N_Vector work);
+
+ int FCVEwtSet(N_Vector y, N_Vector ewt, void *user_data);
+
+ /* Declarations for global variables shared amongst various routines */
+
+ extern N_Vector F2C_CVODE_vec; /* defined in FNVECTOR module */
+
+ extern void *CV_cvodemem; /* defined in fcvode.c */
+ extern long int *CV_iout; /* defined in fcvode.c */
+ extern realtype *CV_rout; /* defined in fcvode.c */
+ extern int CV_nrtfn; /* defined in fcvode.c */
+ extern int CV_ls; /* defined in fcvode.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_SPGMR = 6, CV_LS_SPBCG = 7, CV_LS_SPTFQMR = 8 };
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/cvode/fcmix/fcvpreco.c b/src/cvode/fcmix/fcvpreco.c
new file mode 100644
index 0000000..eb4203e
--- /dev/null
+++ b/src/cvode/fcmix/fcvpreco.c
@@ -0,0 +1,136 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.3 $
+ * $Date: 2007/04/30 19:28:59 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Alan C. Hindmarsh, Radu Serban and
+ * Aaron Collier @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * 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.
+ * -----------------------------------------------------------------
+ */
+
+#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_spils.h>
+
+/*********************************************************************/
+
+/* Prototype of the Fortran routines */
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+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 */
+
+#ifdef __cplusplus
+}
+#endif
+
+/***************************************************************************/
+
+void FCV_SPILSSETPREC(int *flag, int *ier)
+{
+ CVodeMem cv_mem;
+
+ if (*flag == 0) {
+ *ier = CVSpilsSetPreconditioner(CV_cvodemem, NULL, NULL);
+ } else {
+ cv_mem = (CVodeMem) CV_cvodemem;
+ *ier = CVSpilsSetPreconditioner(CV_cvodemem, FCVPSet, FCVPSol);
+ }
+}
+
+/***************************************************************************/
+
+/* C function FCVPSet to interface between CVODE and a Fortran subroutine
+ FCVPSET for setup of a Krylov preconditioner.
+ Addresses of t, y, fy, jok, gamma, h, vtemp1, vtemp2, vtemp3, and the
+ address jcurPtr are passed to FCVPSET, using the routine
+ N_VGetArrayPointer from NVECTOR.
+ A return flag ier from FCVPSET is returned by FCVPSet.
+ Auxiliary data is assumed to be communicated by common blocks. */
+
+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)
+{
+ int ier = 0;
+ realtype *ydata, *fydata, *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);
+
+ CV_userdata = (FCVUserData) user_data;
+
+ FCV_PSET(&t, ydata, fydata, &jok, jcurPtr, &gamma, &h,
+ CV_userdata->ipar, CV_userdata->rpar,
+ v1data, v2data, v3data, &ier);
+
+ return(ier);
+}
+
+/***************************************************************************/
+
+/* C function FCVPSol to interface between CVODE and a Fortran subroutine
+ FCVPSOL for solution of a Krylov preconditioner.
+ Addresses of t, y, fy, gamma, delta, lr, vtemp, r, and z are
+ passed to FCVPSOL, using the routine N_VGetArrayPointer from NVECTOR.
+ A return flag ier from FCVPSOL is returned by FCVPSol.
+ Auxiliary data is assumed to be communicated by Common blocks. */
+
+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 ier = 0;
+ realtype *ydata, *fydata, *vtdata, *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);
+
+ return(ier);
+}
diff --git a/src/cvode/fcmix/fcvroot.c b/src/cvode/fcmix/fcvroot.c
new file mode 100644
index 0000000..1317f19
--- /dev/null
+++ b/src/cvode/fcmix/fcvroot.c
@@ -0,0 +1,86 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.3 $
+ * $Date: 2007/04/30 19:28:59 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Aaron Collier @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * The FCVROOT module contains the routines necessary to use
+ * the rootfinding feature of the CVODE module and to interface
+ * with the user-supplied Fortran subroutine.
+ * -----------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "fcvode.h" /* actual fn. names, prototypes and global variables */
+#include "fcvroot.h" /* prototypes of interfaces to CVODE */
+#include "cvode_impl.h" /* definition of CVodeMem type */
+
+/***************************************************************************/
+
+/* Prototype of the Fortran routine */
+
+#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 */
+#ifdef __cplusplus
+}
+#endif
+
+/***************************************************************************/
+
+void FCV_ROOTINIT(int *nrtfn, int *ier)
+{
+ CVodeMem cv_mem;
+
+ cv_mem = (CVodeMem) CV_cvodemem;
+ *ier = CVodeRootInit(CV_cvodemem, *nrtfn, (CVRootFn) FCVrootfunc);
+ CV_nrtfn = *nrtfn;
+
+ return;
+}
+
+/***************************************************************************/
+
+void FCV_ROOTINFO(int *nrtfn, int *info, int *ier)
+{
+ *ier = CVodeGetRootInfo(CV_cvodemem, info);
+ return;
+}
+
+/***************************************************************************/
+
+void FCV_ROOTFREE(void)
+{
+ CVodeRootInit(CV_cvodemem, 0, NULL);
+
+ return;
+}
+
+/***************************************************************************/
+
+int FCVrootfunc(realtype t, N_Vector y, realtype *gout, void *user_data)
+{
+ int ier;
+ realtype *ydata;
+ FCVUserData CV_userdata;
+
+ ydata = N_VGetArrayPointer(y);
+
+ CV_userdata = (FCVUserData) user_data;
+
+ FCV_ROOTFN(&t, ydata, gout, CV_userdata->ipar, CV_userdata->rpar, &ier);
+
+ return(ier);
+}
+
diff --git a/src/cvode/fcmix/fcvroot.h b/src/cvode/fcmix/fcvroot.h
new file mode 100644
index 0000000..5733189
--- /dev/null
+++ b/src/cvode/fcmix/fcvroot.h
@@ -0,0 +1,140 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.5 $
+ * $Date: 2010/12/15 19:40:08 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Aaron Collier @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * This is the Fortran interface include file for the rootfinding
+ * feature of CVODE.
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * ==============================================================================
+ *
+ * FCVROOT Interface Package
+ *
+ * The FCVROOT interface package allows programs written in FORTRAN to
+ * use the rootfinding feature of the CVODE solver module.
+ *
+ * The user-callable functions constituting the FCVROOT package are the
+ * following: FCVROOTINIT, FCVROOTINFO, and FCVROOTFREE. The corresponding
+ * CVODE subroutine called by each interface function is given below.
+ *
+ * ----------------- -----------------------
+ * | FCVROOT routine | | CVODE function called |
+ * ----------------- -----------------------
+ * FCVROOTINIT -> CVodeRootInit
+ * FCVROOTINFO -> CVodeGetRootInfo
+ * FCVROOTFREE -> CVodeRootInit
+ *
+ * FCVROOTFN is a user-supplied subroutine defining the functions whose
+ * roots are sought.
+ *
+ * ==============================================================================
+ *
+ * Usage of the FCVROOT Interface Package
+ *
+ * 1. In order to use the rootfinding feature of the CVODE package the user must
+ * define the following subroutine:
+ *
+ * SUBROUTINE FCVROOTFN (T, Y, G, IPAR, RPAR, IER)
+ * DIMENSION Y(*), G(*), IPAR(*), RPAR(*)
+ *
+ * The arguments are:
+ * 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]
+ * 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
+ * allocate and initialize memory for the FCVROOT module by making the
+ * following call:
+ *
+ * CALL FCVROOTINIT (NRTFN, IER)
+ *
+ * The arguments are:
+ * NRTFN = total number of root functions [input]
+ * IER = return completion flag (0 = success, -1 = CVODE memory NULL and
+ * -11 memory allocation error) [output]
+ *
+ * 3. After calling FCVODE, to see whether a root was found, test the FCVODE
+ * return flag IER. The value IER = 2 means one or more roots were found.
+ *
+ * 4. If a root was found, and if NRTFN > 1, then to determine which root
+ * functions G(*) were found to have a root, make the following call:
+ * CALL FCVROOTINFO (NRTFN, INFO, IER)
+ * The arguments are:
+ * NRTFN = total number of root functions [input]
+ * INFO = integer array of length NRTFN, with values 0 or 1 [output]
+ * For i = 1,...,NRTFN, G(i) was found to have a root if INFO(i) = 1.
+ * IER = completion flag (0 = success, negative = failure)
+ *
+ * 5. The total number of calls made to the root function (FCVROOTFN), NGE,
+ * can be obtained from IOUT(12).
+ *
+ * If the FCVODE/CVODE memory block is reinitialized to solve a different
+ * problem via a call to FCVREINIT, then the counter variable NGE is cleared
+ * (reset to zero).
+ *
+ * 6. To free the memory resources allocated by a prior call to FCVROOTINIT make
+ * the following call:
+ * CALL FCVROOTFREE
+ * See the CVODE documentation for additional information.
+ *
+ * ==============================================================================
+ */
+
+#ifndef _FCVROOT_H
+#define _FCVROOT_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+/* header files */
+
+#include <sundials/sundials_nvector.h> /* definition of type N_Vector */
+#include <sundials/sundials_types.h> /* definition of SUNDIALS type realtype */
+
+/* Definitions of interface function names */
+
+#if defined(SUNDIALS_F77_FUNC)
+
+#define FCV_ROOTINIT SUNDIALS_F77_FUNC(fcvrootinit, FCVROOTINIT)
+#define FCV_ROOTINFO SUNDIALS_F77_FUNC(fcvrootinfo, FCVROOTINFO)
+#define FCV_ROOTFREE SUNDIALS_F77_FUNC(fcvrootfree, FCVROOTFREE)
+#define FCV_ROOTFN SUNDIALS_F77_FUNC(fcvrootfn, FCVROOTFN)
+
+#else
+
+#define FCV_ROOTINIT fcvrootinit_
+#define FCV_ROOTINFO fcvrootinfo_
+#define FCV_ROOTFREE fcvrootfree_
+#define FCV_ROOTFN fcvrootfn_
+
+#endif
+
+/* Prototypes of exported function */
+
+void FCV_ROOTINIT(int *nrtfn, int *ier);
+void FCV_ROOTINFO(int *nrtfn, int *info, int *ier);
+void FCV_ROOTFREE(void);
+
+/* Prototype of function called by CVODE module */
+
+int FCVrootfunc(realtype t, N_Vector y, realtype *gout, void *user_data);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif
diff --git a/src/cvodes/CMakeLists.txt b/src/cvodes/CMakeLists.txt
new file mode 100644
index 0000000..d1724b7
--- /dev/null
+++ b/src/cvodes/CMakeLists.txt
@@ -0,0 +1,131 @@
+# ---------------------------------------------------------------
+# $Revision: 1.4 $
+# $Date: 2009/02/17 02:58:47 $
+# ---------------------------------------------------------------
+# Programmer: Radu Serban @ LLNL
+# ---------------------------------------------------------------
+# Copyright (c) 2007, The Regents of the University of California.
+# Produced at the Lawrence Livermore National Laboratory.
+# All rights reserved.
+# For details, see the LICENSE file.
+# ---------------------------------------------------------------
+# CMakeLists.txt file for the CVODES library
+
+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_spils.c
+ cvodes_spbcgs.c
+ cvodes_spgmr.c
+ cvodes_sptfqmr.c
+ cvodes_bandpre.c
+ cvodes_bbdpre.c
+ )
+
+# 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_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 cvodes_HEADERS with the exported CVODES header files
+SET(cvodes_HEADERS
+ cvodes_band.h
+ cvodes_bandpre.h
+ cvodes_bbdpre.h
+ cvodes_dense.h
+ cvodes_diag.h
+ cvodes_direct.h
+ cvodes.h
+ cvodes_spbcgs.h
+ cvodes_spgmr.h
+ cvodes_spils.h
+ cvodes_sptfqmr.h
+ )
+
+# 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(.)
+INCLUDE_DIRECTORIES(../sundials)
+
+# Define C preprocessor flag -DBUILD_SUNDIALS_LIBRARY
+ADD_DEFINITIONS(-DBUILD_SUNDIALS_LIBRARY)
+
+# Build the static library
+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})
+
+ # Set the library name and make sure it is not deleted
+ SET_TARGET_PROPERTIES(sundials_cvodes_static
+ PROPERTIES OUTPUT_NAME sundials_cvodes CLEAN_DIRECT_OUTPUT 1)
+
+ # Install the CVODES library
+ INSTALL(TARGETS sundials_cvodes_static DESTINATION lib)
+
+ENDIF(BUILD_STATIC_LIBS)
+
+# Build the shared library
+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})
+
+ # Set the library name and make sure it is not deleted
+ SET_TARGET_PROPERTIES(sundials_cvodes_shared
+ PROPERTIES OUTPUT_NAME sundials_cvodes CLEAN_DIRECT_OUTPUT 1)
+
+ # Set VERSION and SOVERSION for shared libraries
+ SET_TARGET_PROPERTIES(sundials_cvodes_shared
+ PROPERTIES VERSION ${cvodeslib_VERSION} SOVERSION ${cvodeslib_SOVERSION})
+
+ # Install the CVODES library
+ INSTALL(TARGETS sundials_cvodes_shared DESTINATION lib)
+
+ENDIF(BUILD_SHARED_LIBS)
+
+# Install the CVODES header files
+INSTALL(FILES ${cvodes_HEADERS} ${cvodes_BL_HEADERS} DESTINATION include/cvodes)
+
+# Install the CVODES implementation header file
+INSTALL(FILES cvodes_impl.h DESTINATION include/cvodes)
+
+#
+MESSAGE(STATUS "Added CVODES module")
diff --git a/debian/copyright b/src/cvodes/LICENSE
similarity index 86%
copy from debian/copyright
copy to src/cvodes/LICENSE
index 98cde97..dd9a383 100644
--- a/debian/copyright
+++ b/src/cvodes/LICENSE
@@ -1,20 +1,8 @@
-This package was debianized by Andrey Romanenko <andrey at enginum.com> on
-Wed, 20 Apr 2005 12:01:42 +0100.
-
-It was downloaded from http://www.llnl.gov/CASC/sundials/
-
-Authors: Peter Brown, Aaron Collier, Keith Grant, Alan Hindmarsh,
- Steve Lee, Radu Serban, Dan Shumaker, Carol Woodward
-
-Copyright Holder: The Regents of the University of California.
-
-License:
-
-Copyright (c) 2002, The Regents of the University of California.
-Produced at the Lawrence Livermore National Laboratory
+Copyright (c) 2002, The Regents of the University of California.
+Produced at the Lawrence Livermore National Laboratory
Written by A.C. Hindmarsh and R. Serban.
UCRL-CODE-155950
-All rights reserved.
+All rights reserved.
This file is part of CVODES v2.1.0.
diff --git a/src/cvodes/Makefile.in b/src/cvodes/Makefile.in
new file mode 100644
index 0000000..9cf23cb
--- /dev/null
+++ b/src/cvodes/Makefile.in
@@ -0,0 +1,180 @@
+# -----------------------------------------------------------------
+# $Revision: 1.12 $
+# $Date: 2009/03/25 23:10:50 $
+# -----------------------------------------------------------------
+# Programmer(s): Radu Serban and Aaron Collier @ 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.
+# -----------------------------------------------------------------
+# Makefile for CVODES module
+#
+# @configure_input@
+# -----------------------------------------------------------------
+
+SHELL = @SHELL@
+
+ at SET_MAKE@
+
+srcdir = @srcdir@
+builddir = @builddir@
+abs_builddir = @abs_builddir@
+top_builddir = @top_builddir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+includedir = @includedir@
+libdir = @libdir@
+
+INSTALL = @INSTALL@
+INSTALL_LIB = @INSTALL_PROGRAM@
+INSTALL_HEADER = @INSTALL_DATA@
+
+LIBTOOL = @LIBTOOL@
+LIBTOOL_DEPS = @LIBTOOL_DEPS@
+
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CC = @CC@
+CFLAGS = @CFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+
+LAPACK_ENABLED = @LAPACK_ENABLED@
+
+top_srcdir = $(srcdir)/../..
+
+INCLUDES = -I$(top_srcdir)/include -I$(top_builddir)/include
+
+LIB_REVISION = 2:0:0
+
+CVODES_LIB = libsundials_cvodes.la
+
+CVODES_SRC_FILES = cvodes.c cvodes_io.c cvodea.c cvodea_io.c cvodes_direct.c cvodes_band.c cvodes_dense.c cvodes_diag.c cvodes_spils.c cvodes_spbcgs.c cvodes_spgmr.c cvodes_sptfqmr.c cvodes_bandpre.c cvodes_bbdpre.c
+CVODES_BL_SRC_FILES = cvodes_lapack.c
+
+CVODES_OBJ_FILES = $(CVODES_SRC_FILES:.c=.o)
+CVODES_BL_OBJ_FILES = $(CVODES_BL_SRC_FILES:.c=.o)
+
+CVODES_LIB_FILES = $(CVODES_SRC_FILES:.c=.lo)
+CVODES_BL_LIB_FILES = $(CVODES_BL_SRC_FILES:.c=.lo)
+
+SHARED_LIB_FILES = $(top_builddir)/src/sundials/sundials_band.lo \
+ $(top_builddir)/src/sundials/sundials_dense.lo \
+ $(top_builddir)/src/sundials/sundials_direct.lo \
+ $(top_builddir)/src/sundials/sundials_iterative.lo \
+ $(top_builddir)/src/sundials/sundials_spgmr.lo \
+ $(top_builddir)/src/sundials/sundials_spbcgs.lo \
+ $(top_builddir)/src/sundials/sundials_sptfqmr.lo \
+ $(top_builddir)/src/sundials/sundials_math.lo \
+ $(top_builddir)/src/sundials/sundials_nvector.lo
+
+mkinstalldirs = $(SHELL) $(top_srcdir)/config/mkinstalldirs
+rminstalldirs = $(SHELL) $(top_srcdir)/config/rminstalldirs
+
+# ----------------------------------------------------------------------------------------------------------------------
+
+all: $(CVODES_LIB)
+
+$(CVODES_LIB): shared $(CVODES_LIB_FILES)
+ @if test "X${LAPACK_ENABLED}" = "Xyes"; then \
+ make lib_with_bl; \
+ else \
+ make lib_without_bl; \
+ fi
+
+lib_without_bl: shared $(CVODES_LIB_FILES)
+ $(LIBTOOL) --mode=link $(CC) $(CFLAGS) -o $(CVODES_LIB) $(CVODES_LIB_FILES) $(SHARED_LIB_FILES) -rpath $(libdir) $(LDFLAGS) $(LIBS) -version-info $(LIB_REVISION)
+
+lib_with_bl: shared $(CVODES_LIB_FILES) $(CVODES_BL_LIB_FILES)
+ $(LIBTOOL) --mode=link $(CC) $(CFLAGS) -o $(CVODES_LIB) $(CVODES_LIB_FILES) $(CVODES_BL_LIB_FILES) $(SHARED_LIB_FILES) -rpath $(libdir) $(LDFLAGS) $(LIBS) -version-info $(LIB_REVISION)
+
+install: $(CVODES_LIB)
+ $(mkinstalldirs) $(includedir)/cvodes
+ $(mkinstalldirs) $(libdir)
+ $(LIBTOOL) --mode=install $(INSTALL_LIB) $(CVODES_LIB) $(libdir)
+ $(INSTALL_HEADER) $(top_srcdir)/include/cvodes/cvodes.h $(includedir)/cvodes/
+ $(INSTALL_HEADER) $(top_srcdir)/include/cvodes/cvodes_direct.h $(includedir)/cvodes/
+ $(INSTALL_HEADER) $(top_srcdir)/include/cvodes/cvodes_dense.h $(includedir)/cvodes/
+ $(INSTALL_HEADER) $(top_srcdir)/include/cvodes/cvodes_band.h $(includedir)/cvodes/
+ $(INSTALL_HEADER) $(top_srcdir)/include/cvodes/cvodes_diag.h $(includedir)/cvodes/
+ $(INSTALL_HEADER) $(top_srcdir)/include/cvodes/cvodes_spils.h $(includedir)/cvodes/
+ $(INSTALL_HEADER) $(top_srcdir)/include/cvodes/cvodes_spbcgs.h $(includedir)/cvodes/
+ $(INSTALL_HEADER) $(top_srcdir)/include/cvodes/cvodes_spgmr.h $(includedir)/cvodes/
+ $(INSTALL_HEADER) $(top_srcdir)/include/cvodes/cvodes_sptfqmr.h $(includedir)/cvodes/
+ $(INSTALL_HEADER) $(top_srcdir)/include/cvodes/cvodes_bandpre.h $(includedir)/cvodes/
+ $(INSTALL_HEADER) $(top_srcdir)/include/cvodes/cvodes_bbdpre.h $(includedir)/cvodes/
+ $(INSTALL_HEADER) $(top_srcdir)/src/cvodes/cvodes_impl.h $(includedir)/cvodes/
+ @if test "X${LAPACK_ENABLED}" = "Xyes"; then \
+ $(INSTALL_HEADER) $(top_srcdir)/include/cvodes/cvodes_lapack.h $(includedir)/cvodes/ ; \
+ fi
+
+uninstall:
+ $(LIBTOOL) --mode=uninstall rm -f $(libdir)/$(CVODES_LIB)
+ rm -f $(includedir)/cvodes/cvodes.h
+ rm -f $(includedir)/cvodes/cvodes_direct.h
+ rm -f $(includedir)/cvodes/cvodes_dense.h
+ rm -f $(includedir)/cvodes/cvodes_band.h
+ rm -f $(includedir)/cvodes/cvodes_diag.h
+ rm -f $(includedir)/cvodes/cvodes_lapack.h
+ rm -f $(includedir)/cvodes/cvodes_spils.h
+ rm -f $(includedir)/cvodes/cvodes_spbcgs.h
+ rm -f $(includedir)/cvodes/cvodes_spgmr.h
+ rm -f $(includedir)/cvodes/cvodes_sptfqmr.h
+ rm -f $(includedir)/cvodes/cvodes_bandpre.h
+ rm -f $(includedir)/cvodes/cvodes_bbdpre.h
+ rm -f $(includedir)/cvodes/cvodes_impl.h
+ $(rminstalldirs) ${includedir}/cvodes
+
+shared:
+ @cd ${top_builddir}/src/sundials ; \
+ ${MAKE} ; \
+ cd ${abs_builddir}
+
+clean:
+ $(LIBTOOL) --mode=clean rm -f $(CVODES_LIB)
+ rm -f $(CVODES_LIB_FILES)
+ rm -f $(CVODES_BL_LIB_FILES)
+ rm -f $(CVODES_OBJ_FILES)
+ rm -f $(CVODES_BL_OBJ_FILES)
+
+distclean: clean
+ rm -f Makefile
+
+cvodes.lo: $(srcdir)/cvodes.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/cvodes.c
+cvodes_io.lo: $(srcdir)/cvodes_io.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/cvodes_io.c
+cvodea.lo: $(srcdir)/cvodea.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/cvodea.c
+cvodea_io.lo: $(srcdir)/cvodea_io.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/cvodea_io.c
+cvodes_direct.lo: $(srcdir)/cvodes_direct.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/cvodes_direct.c
+cvodes_dense.lo: $(srcdir)/cvodes_dense.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/cvodes_dense.c
+cvodes_band.lo: $(srcdir)/cvodes_band.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/cvodes_band.c
+cvodes_diag.lo: $(srcdir)/cvodes_diag.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/cvodes_diag.c
+cvodes_lapack.lo: $(srcdir)/cvodes_lapack.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/cvodes_lapack.c
+cvodes_spils.lo: $(srcdir)/cvodes_spils.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/cvodes_spils.c
+cvodes_spbcgs.lo: $(srcdir)/cvodes_spils.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/cvodes_spbcgs.c
+cvodes_spgmr.lo: $(srcdir)/cvodes_spgmr.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/cvodes_spgmr.c
+cvodes_sptfqmr.lo: $(srcdir)/cvodes_sptfqmr.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/cvodes_sptfqmr.c
+cvodes_bandpre.lo: $(srcdir)/cvodes_bandpre.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/cvodes_bandpre.c
+cvodes_bbdpre.lo: $(srcdir)/cvodes_bbdpre.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/cvodes_bbdpre.c
+
+
+libtool: $(top_builddir)/$(LIBTOOL_DEPS)
+ @cd ${top_builddir} ; \
+ ${SHELL} ./config.status --recheck ; \
+ cd ${abs_builddir}
diff --git a/src/cvodes/README b/src/cvodes/README
new file mode 100644
index 0000000..d42a27e
--- /dev/null
+++ b/src/cvodes/README
@@ -0,0 +1,468 @@
+ CVODES
+ Release 2.7.0, March 2012
+ Alan C. Hindmarsh and Radu Serban
+ Center for Applied Scientific Computing, LLNL
+
+CVODES is a solver for stiff and nonstiff ODE systems (initial value
+problem) given in explicit form y' = f(t,y,p) with sensitivity analysis
+capabilities (both forward and adjoint modes).
+It is written in ANSI standard C.
+
+CVODES can be used both on serial and parallel (MPI) computers. The
+main difference is in the NVECTOR module of vector kernels. The desired
+version is obtained when compiling the example files by linking the
+appropriate library of NVECTOR kernels. In the parallel version,
+communication between processors is done with the MPI (Message Passage
+Interface) system.
+
+When used with the serial NVECTOR module, CVODES provides both direct (dense
+and band) and preconditioned Krylov (iterative) linear solvers. Three different
+iterative solvers are available: scaled preconditioned GMRES (SPGMR), scaled
+preconditioned BiCGStab (SPBCG), and scaled preconditioned TFQMR (SPTFQMR).
+When CVODES 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 CVBANDPRE available for use with the Krylov solvers, while for the parallel
+version there is a preconditioner module called CVBBDPRE which provides a
+band-block-diagonal preconditioner.
+
+CVODES is part of a software family called SUNDIALS: SUite of Nonlinear and
+DIfferential/ALgebraic equation Solvers [4]. This suite consists of CVODE,
+CVODES, IDA, IDAS, and KINSOL. The directory structure of the package supplied
+reflects this family relationship.
+
+The notes below provide the location of documentation, directions for the
+installation of the CVODES package, and relevant references. Following that
+is a brief history of revisions to the package.
+
+
+A. Documentation
+----------------
+
+/sundials/doc/cvodes/ contains PDF files for the CVODES User Guide [1] (cvs_guide.pdf)
+and the CVODES Examples [2] (cvs_examples.pdf) documents.
+
+
+B. Installation
+---------------
+
+For basic installation instructions see /sundials/INSTALL_NOTES.
+For complete installation instructions see the "CVODES Installation Procedure"
+chapter in the CVODES User Guide.
+
+
+C. References
+-------------
+
+[1] A. C. Hindmarsh and R. Serban, "User Documentation for CVODES v2.7.0,"
+ LLNL technical report UCRL-SM-208111, December 2011.
+
+[2] A. C. Hindmarsh and R. Serban, "Example Programs for CVODES v2.7.0,"
+ LLNL technical report UCRL-SM-208115, December 2011.
+
+[3] R. Serban and A. C. Hindmarsh, "CVODES: the Sensitivity-Enabled ODE
+ solver in SUNDIALS," Proceedings of IDETC/CIE 2005, Sept. 2005,
+ Long Beach, CA.
+
+[4] A. C. Hindmarsh, P. N. Brown, K. E. Grant, S. L. Lee, R. Serban,
+ D. E. Shumaker, and C. S. Woodward, "SUNDIALS, Suite of Nonlinear and
+ Differential/Algebraic Equation Solvers," ACM Trans. Math. Softw.,
+ 31(3), pp. 363-396, 2005.
+
+
+D. Releases
+-----------
+
+v. 2.7.0 - Mar. 2012
+v. 2.6.0 - May 2009
+v. 2.5.0 - Nov. 2006
+v. 2.4.0 - Mar. 2006
+v. 2.3.0 - May. 2005
+v. 2.2.0 - Apr. 2005
+v. 2.1.2 - Mar. 2005
+v. 2.1.1 - Jan. 2005
+v. 2.1.0 - Dec. 2004
+v. 1.0 - Jul. 2002 (first SUNDIALS release)
+
+
+E. Revision History
+-------------------
+
+
+v. 2.6.0 (May 2009) ---> v. 2.7.0 (Mar. 2012)
+---------------------------------------------
+
+- Bug fixes
+ - errors in the logic for the integration of backward problems were
+ identified and fixed.
+ - in CVSetTqBDF, the logic was changed to avoid a divide by zero.
+ - after the solver memory is created, it is set to zero before being filled.
+ - in each linear solver interface function, the linear solver memory is
+ freed on an error return, and the **Free function now includes a
+ line setting to NULL the main memory pointer to the linear solver memory.
+ - in rootfinding functions cvRcheck1/cvRcheck2, when an exact zero is found,
+ the array glo at the left endpoint is adjusted instead of shifting tlo.
+
+- Changes to user interface
+ - One significant design change was made with this release: The problem
+ size and its relatives, bandwidth parameters, related internal indices,
+ pivot arrays, and the optional output lsflag have all been
+ changed from type int to type long int, except for the
+ problem size and bandwidths in user calls to routines specifying
+ BLAS/LAPACK routines for the dense/band linear solvers. The function
+ NewIntArray is replaced by a pair NewIntArray/NewLintArray,
+ for int and long int arrays, respectively.
+ - in a minor change to the user interface, the type of the index
+ which in CVODES was changed from long int to int.
+ - in the installation files, we modified the treatment of the macro
+ SUNDIALS_USE_GENERIC_MATH, so that the parameter GENERIC_MATH_LIB is
+ either defined (with no value) or not defined.
+
+v. 2.5.0 (Nov. 2006) ---> v. 2.6.0 (May 2009)
+---------------------------------------------
+
+- New features
+ - added a new linear solver module based on Blas + Lapack for
+ both dense and banded matrices.
+ - added optional input to specify which direction of zero-crossing
+ is to be monitored while performing root-finding. The root information
+ array iroots (returned by CVodeGetRootInfo) also encodes the
+ direction of zero-crossing.
+ - added support for performing FSA of quadrature variables (see functions
+ CVode**QuadSens**).
+ - in the adjoint module, added support for integrating forward sensitivities
+ of states and quadrature variables during the forward integration
+ phase (e.g. for computing 2nd order sensitivity information using
+ the "forward over adjoint" method).
+ - in the adjoint module, added support for propagating backwards in time
+ multiple adjoint systems, each initialized at posibly different times.
+ - added option for reinitializing the adjoint module in order to
+ solve a new adjoint problem (with same number of steps between
+ check points and the same interpolation type).
+
+- Bug fixes
+ - in the rootfinding algorithm, fixed a bug resulting in unnecessary
+ evaluations of the root functions after reinitialization of the
+ solver right after a return at a root.
+ - in the initial step size calculation, restrict h based on tstop.
+ - modified the setting and use of the tq[] array. Now tq[i] (i = 1,2,3)
+ are defined to be the reciprocals of what they were before. This
+ eliminates a rare crash that can occur with xistar_inv = 0.
+
+- Changes to user interface
+ - renamed all **Malloc functions to **Init
+ - tolerances are now specified through separate functions instead of
+ the initialization functions CVodeInit (former CVodeMalloc) and
+ CVodeReInit. Depending on the tolerance type, one of 3 functions
+ must be called before the first call to CVode.
+ - tolerances for quadratures, sensitivities, and quadrature sensitivities
+ are specified in a manner similar to that for state variables, with the
+ exception that toelrances for quadratures and quadrature sensitivities
+ are required only if the corresponding variables are included in the
+ error test.
+ - removed function inputs from argument lists of all re-initialization
+ functions.
+ - all user-supplied functions now receive the same pointer to user data
+ (instead of having different ones for the system evaluation, Jacobian
+ information functions, etc.)
+ - removed CV_NORMAL_TSTOP and CV_ONE_STEP_TSTOP named constants for the
+ itask argument to CVode/CVodeF. A tstop value is now both set and activated
+ through CVodeSetStopTime. Once tstop is reached it is also deactivated.
+ A new value can be then specified by calling again CVodeSetStopTime.
+ - common functionality for all direct linear solvers (dense, band, and
+ the new Lapack solver) has been collected into the DLS (Direct Linear
+ Solver) module, similar to the SPILS module for the iterative linear
+ solvers. All optional input and output functions for these linear
+ solver now have the prefix 'CVDls'. In addition, in order to include
+ the new Lapack-based linear solver, all dimensions for these linear
+ solvers (problem sizes, bandwidths, etc) are now of type 'int'
+ (instead of 'long int').
+ - the initialization functions for the two preconditioner modules,
+ CVBANDPRE and CVBBDPRE were renamed ***Init (from ***Alloc) and they
+ do not return a pointer to preconditioner memory anymore. Instead,
+ all preconditioner module-related functions are now called with
+ the main solver memory pointer as their first argument. When using
+ one of these two modules, there is no need to use special functions
+ to attach one of the SPILS linear solvers (instead use one of
+ CVSpgmr, CVSpbcg, or CVSptfqmr). Moreover, there is no need to call
+ a memory deallocation function for the preconditioner module.
+ - CVodeSensMalloc was replaced by CVodeSensInit and CvodeSensInit1.
+ The sensitivity RHS function is now passed as an argument to these
+ initialization functions. The former takes as argument fS a function
+ of type CVSensRhsFn, while the latter takes as argument fS1 of type
+ CVSensRhs1Fn. Removed the functions CVodeSetSensRhsFn and CVodeSetSensRhs1Fn.
+ - changed the API for all functions in the adjoint module related to
+ initialization, set-up, and solution of backward problems. A backward problem
+ is always identified by its index (of type int) returned by the CvodeCreateB
+ function.
+ - the extraction functions CVodeGetQuad, CVodeGetSens, and CVodeGetSens1
+ now return the values of quadrature and sensitivity variables, respectively,
+ at the same time as that at which CVode returned the solution (for dense
+ output of quadrature or sensitivity variables, the user can only use
+ CVodeGetQuadDky, CVodeGetSensDky, or CVodeGetSensDky1). Similar functions are
+ available for the new quadrature sensitivity feature.
+ - changed names CVSpilsSetDelt and delt to CVSpilsSetEpsLin and eplifac.
+ - added the error return CV_RTFUNC_FAIL.
+
+v. 2.4.0 (Mar. 2006) ---> v. 2.5.0 (Nov. 2006)
+----------------------------------------------
+
+- Bug fixes
+ - fixed wrong logic in final stopping tests: now we check if
+ tout was reached before checking if tstop was reached.
+ - added a roundoff factor when testing whether tn was just returned
+ (in root finding) to prevent an unnecessary return.
+ - fixed bug in CVodeB in searching for the current check point
+ (i.e. the check point for which interpolation data is available)
+ - fixed bug in CVodeF to ensure that in NORMAL mode no extra
+ step is taken (which sometimes resulted in an error from the
+ interpolated output function).
+ - changed address variable type in CVadjCheckPointRec structure from
+ 'unsigned int' to 'void *' to avoid address truncation/mangling on
+ 64-bit platforms (see CVS_P1).
+
+- Changes related to the build system
+ - reorganized source tree: header files in ${srcdir}/include/cvodes,
+ source files in ${srcdir}/src/cvodes,examples in ${srcdir}/examples/cvodes
+ - exported header files are installed unde ${includedir}/cvodes
+
+- Changes to user interface
+ - all included header files use relative paths from ${includedir}
+ - changed the API for specifying the DQ method used to approximate
+ the sensitivity equations: renamed CVodeSetSensRho to CVodeSetSensDQMethod.
+ The user passes two values: DQtype (CV_CENTERED or CV_FORWARD) and
+ DQrhomax (the cut-off value for switching between simultaneous and
+ separate approximations of the two terms in the sensi. eqs.)
+
+v. 2.3.0 (May. 2005) ---> v. 2.4.0 (Mar. 2006)
+----------------------------------------------
+
+- New features
+ - added CVSPBCG interface module to allow CVODES to interface with the
+ shared SPBCG (scaled preconditioned Bi-CGSTAB) linear solver module.
+ - added CVSPTFQMR interface module to allow CVODES to interface with
+ the shared SPTFQMR (scaled preconditioned TFQMR) linear solver module.
+ - added support for SPBCG and SPTFQMR to the CVBBDPRE and CVBANDPRE
+ preconditioner modules.
+ - added support for interpreting failures in user-supplied functions.
+ - added a new variable-degree polynomial interpolation method as an
+ an alternative to the current cubic Hermite interpolation for the
+ adjoint module.
+
+- Changes to user interface
+ - changed argument of CVodeFree, CVBandPrecFree, CVBBDPrecFree, and
+ CVadjFree to be the address of the respective memory block pointer,
+ so that its NULL value is propagated back to the calling function.
+ - added CVSPBCG module which defines appropriate CVSpbcg* functions to
+ allow CVODES to interface with the shared SPBCG linear solver module.
+ - added CVBBDSpbcg function to CVBBDPRE module and CVBPSpbcg function to
+ CVBANDPRE module to support SPBCG linear solver module.
+ - added CVBBDSptfqmr function to CVBBDPRE module and CVBPSptfqmr function to
+ CVBANDPRE module to support SPTFQMR linear solver module.
+ - changed function type names (not the actual definition) to accomodate
+ all the Scaled Preconditioned Iterative Linear Solvers now available:
+ CVSpgmrJactimesVecFn -> CVSpilsJacTimesVecFn
+ CVSpgmrPrecSetupFn -> CVSpilsPrecSetupFn
+ CVSpgmrPrecSolveFn -> CVSpilsPrecSolveFn
+ - changed function types so that all user-supplied functions return
+ an integer flag (not all of them currently used).
+ - changed some names for CVBBDPRE and CVBANDPRE function outputs
+ - added option for user-supplied error handler function.
+ - added a argument to CVadjMalloc to specify the type of interpolation
+ (possible values are CV_HERMITE for cubic Hermite and CV_POLYNOMIAL
+ for variable-order polynomial interpolation)
+ - renamed all exported header files (except for cvodes.h and cvodea.h all
+ header files have the prefix 'cvodes_')
+ - changed naming scheme for CVODES examples
+
+- Changes related to the build system
+ - the main CVODES header files (cvodes.h and cvodea.h) are still exported to
+ the install include directory. However, all other CVODES header files are
+ exported into a 'cvodes' subdirectory of the install include directory.
+ - the CVODES library now contains all shared object files (there is no separate
+ libsundials_shared library anymore)
+
+v. 2.2.0 (Apr. 2005) ---> v. 2.3.0 (May. 2005)
+----------------------------------------------
+
+- Bug fixes
+ - in the adjoint module, fixed bug in storing interpolation data at
+ a point corresponding to a check point (improperly scaled y').
+
+- Changes to user interface
+ - removed CVadjGetcheckPointsList from the list of user-callable functions.
+
+v. 2.1.2 (Mar. 2005) ---> v. 2.2.0 (Apr. 2005)
+----------------------------------------------
+
+- New features
+ - added option for user-provided error weight computation function for
+ the solution vector (of type CVEwtFn specified through CVodeSetEwtFn).
+
+- Changes to user interface
+ - CVODES now stores tolerances through values rather than references
+ (to resolve potential scoping issues).
+ - CVODES now passes information back to the user through values rather
+ than references (error weights, estimated local errors, root info,
+ STAGGERED1 statistics, etc.)
+ - CVodeMalloc, CVodeReInit, CVodeSetTolerances: added option itol=CV_WF
+ to indicate user-supplied function for computing the error weights;
+ reltol is now declared as realtype. Note that it is now illegal to call
+ CVodeSetTolerances before CVodeMalloc. It is now legal to deallocate
+ the absolute tolerance N_Vector right after its use.
+ - Several optional input functions were combined into a single one
+ (CVodeRootInit and CvodeSetGdata, CVDenseSetJacFn and CVDenseSetJacData,
+ CVBandSetJacFn and CVBandSetJacData, CVSpgmrSetPrecSolveFn and
+ CVSpgmrSetPrecSetFn and CVSpgmrSetPrecData, CVSpgmrSetJacTimesVecFn and
+ CVSpgmrSetJacData).
+ - Removed CVodeSetQuadtolerances. CVodeSetQuadErrCon now sets both the
+ error control flag and the tolerances for quadratures.
+ - CVodeSetQuadErrCon, CVodeSetSensTolerances: the relative tolerance
+ must now be passed as a realtype. It is now illegal to call
+ CVodeSetQuadErrCon before CVodeQuadMalloc or to call CVodeSetSensTolerances
+ before CVodeSensMalloc.
+ - CvodeSensMalloc: removed p and plist from argument list.
+ - CVodeSensParams replaces CVodeSensPbar and sets p, pbar, and plist. NULL
+ can be passed for any of them if it will not be needed given the current
+ set of options. The array pbar must now contain Ns non-zero realtype
+ values giving order of magnitude for the parameters with respect to which
+ sensitivities will be computed. The array plist can now only have positive
+ entries.
+ - CVodeGetErrorWeights, CVodeGetQuadErrorWeights: the user is now responsible
+ for allocating space for the N_Vector in which error weights will be copied.
+ - CVodeGetEstLocalErrors: the user is now responsible for allocating space
+ for the N_Vector in which estimated local errors will be copied.
+ - CVodeGetRootInfo: the user is now responsible for allocating space
+ for the int array in which root information will be copied.
+ - CVodeGetNumStgrSensNonlinSolvIters, CVodeGetNumStgrSensNonlinSolvConvFails:
+ the user is now responsible for allocating space for the long int arrays
+ in which STAGGERED1 statistics will be copied.
+ - CVodeMallocB, CVodeReInitB, CVodeSetQuadErrConB: the relative tolerance
+ for the backward integration must now be passed as a realtype. It is now
+ illegal to call CVodeSetQuadErrConB before CVQuadMallocB.
+ - Passing a value of 0 for the maximum step size, the minimum step
+ size, or for maxsteps results in the solver using the corresponding
+ default value (infinity, 0, 500, respectively)
+ - User-callable functions in the adjoint module were modified similarly
+ to their corresponding counterparts for forward simulation.
+
+
+v. 2.1.1 (Jan. 2005) ---> v. 2.1.2 (Mar. 2005)
+----------------------------------------------
+
+- Bug fixes
+ - fixed bug in CVode function: Initial setting of tretlast = *tret = tn removed
+ (correcting erroneous behavior at first call to CVRcheck3).
+ - removed redundant setting of tretlast = *tret = tn at CLOSE_ROOTS return from CVode.
+ - fixed bug in CVCompleteStep related to quadrature and sensitivity variables
+ (leading to wrong values at a BDF order increase)
+ - in CVUpperBoundH0, fixed a potential, although not harmful, use of
+ uninitialized memory
+ - changed implicit type conversion to explicit in check_flag() routine in
+ examples to avoid C++ compiler errors
+
+- Changes to documentation
+ - added section with numerical values of all input and output solver constants
+ - added more detailed notes on the type of absolute tolerances
+ - added more details on ownership of memory for the array returned by CVodeGetRootInfo
+ - corrected/added descriptions of error returns.
+ - added description of --with-mpi-flags option
+
+- Changes related to the build system
+ - fixed autoconf-related bug to allow configuration with the PGI Fortran compiler
+ - modified to use customized detection of the Fortran name mangling scheme
+ (autoconf's AC_F77_WRAPPERS routine is problematic on some platforms)
+ - added --with-mpi-flags as a configure option to allow user to specify
+ MPI-specific flags
+ - updated Makefiles for Fortran examples to avoid C++ compiler errors (now use
+ CC and MPICC to link)
+
+
+v. 2.1.0 (Dec. 2004) ---> v. 2.1.1 (Jan. 2005)
+----------------------------------------------
+
+- New features
+ - added function CVodeSensToggle to allow activation/deactivation of
+ sensitivity calculations without memory allocation/deallocation.
+
+- Bug fixes
+ - fixed bug in CVCompleteStep related to quadrature and sensitivity variables
+ (leading to wrong values at a BDF order increase).
+ - in CVUpperBoundH0, fixed a potential, although not harmful, use of
+ uninitialized memory.
+ - fixed logic in testing for negative values of user-supplied absolute tolerances
+ for sensitivity variables.
+
+- Changes related to the build system
+ - changed order of compiler directives in header files to avoid compilation
+ errors when using a C++ compiler.
+
+v. 1.0 (Jul. 2002) ---> v. 2.1.0 (Dec. 2004)
+--------------------------------------------
+
+- New features
+ - added quadrature integration capabilities.
+ - added root finding capabilities.
+ - added option for different user data structures for ODE r.h.s.
+ and sensitivity r.h.s.
+ - in adjoint module, added interface to CVBBDPRE for the backward
+ phase.
+ - in adjoint module, added option for using CVDIAG during backward
+ phase.
+ - in adjoint module, added option for ONE_STEP integration during
+ backward phase.
+ - in adjoint module, added option to reinitialize the backward
+ integration phase (and perform a new backward integration using
+ the same check points).
+ - in adjoint module, relaxed assumption that t_final > t_0 (now
+ accepts t_final < t_0).
+
+- Bug fixes
+ - fixed bug in adjustment of sensitivity Nordsieck history array on an
+ order decrease (when using BDF).
+ - in adjoint module, fixed a potential use of memory before being set.
+ - in adjoint module, fixed a bug related to data saved at check points.
+ This addresses the case in which an order increase is deemed necessary
+ at the very first step after a check-point.
+
+- Changes related to the NVECTOR module
+ (see also the file sundials/shared/README)
+ - removed machEnv, redefined table of vector operations (now contained
+ in the N_Vector structure itself).
+ - all CVODES functions create new N_Vector variables through cloning, using
+ an N_Vector passed by the user as a template.
+
+- Changes to type names and CVODES constants
+ - removed type 'integertype'; instead use int or long int, as appropriate.
+ - restructured the list of return values from the various CVODES functions.
+ - changed all CVODES constants (inputs and return values) to have the
+ prefix 'CV_' (e.g. CV_SUCCESS).
+ - renamed various function types to have the prefix 'CV' (e.g. CVRhsFn).
+
+- Changes to optional input/ouput
+ - added CVodeSet* and CVodeGet* functions for optional inputs/outputs,
+ replacing the arrays iopt and ropt.
+ - added new optional inputs (e.g. maximum number of Newton iterations,
+ maximum number of convergence failures, etc).
+ - the value of the last return flag from any function within a linear
+ solver module can be obtained as an optional output (e.g. CVDenseGetLastFlag).
+
+- Changes to user-callable functions
+ - renamed header files to have prefix 'cv' instead of 'cvs' (e.g. cvdense.h
+ replaces cvsdense.h).
+ - added new function CVodeCreate which initializes the CVODES solver
+ object and returns a pointer to the CVODES memory block.
+ - removed N (problem size) from all functions except the initialization
+ functions for the direct linear solvers (CVDense and CVBand).
+ - shortened argument lists of most CVODES functions (the arguments that
+ were dropped can now be specified through CVodeSet* functions).
+ - removed reinitialization functions for band/dense/SPGMR linear
+ solvers (same functionality can be obtained using CV*Set* functions).
+ - in CVBBDPRE, added a new function, CVBBDSpgmr to initialize the
+ SPGMR linear solver with the BBD preconditioner.
+ - function names changed in CVBANDPRE and CVBBDPRE for uniformity.
+
+- Changes to user-supplied functions
+ - removed N (probem dimension) from argument lists.
+ - shortened argument lists for user dense/band/SPGMR Jacobian routines.
+ - in CVSPGMR, shortened argument lists for user preconditioner functions.
diff --git a/src/cvodes/cvodea.c b/src/cvodes/cvodea.c
new file mode 100644
index 0000000..44c55a1
--- /dev/null
+++ b/src/cvodes/cvodea.c
@@ -0,0 +1,2980 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.25 $
+ * $Date: 2011/12/07 23:12:46 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2006, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * This is the implementation file for the CVODEA adjoint integrator.
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * =================================================================
+ * IMPORTED HEADER FILES
+ * =================================================================
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "cvodes_impl.h"
+
+#include <sundials/sundials_math.h>
+#include <sundials/sundials_types.h>
+
+/*
+ * =================================================================
+ * MACRO DEFINITIONS
+ * =================================================================
+ */
+
+#define loop for(;;)
+
+/*
+ * =================================================================
+ * CVODEA PRIVATE CONSTANTS
+ * =================================================================
+ */
+
+#define ZERO RCONST(0.0) /* real 0.0 */
+#define ONE RCONST(1.0) /* real 1.0 */
+#define TWO RCONST(2.0) /* real 2.0 */
+#define HUNDRED RCONST(100.0) /* real 100.0 */
+#define FUZZ_FACTOR RCONST(1000000.0) /* fuzz factor for IMget */
+
+/*
+ * =================================================================
+ * PRIVATE FUNCTION PROTOTYPES
+ * =================================================================
+ */
+
+static CkpntMem CVAckpntInit(CVodeMem cv_mem);
+static CkpntMem CVAckpntNew(CVodeMem cv_mem);
+static void CVAckpntDelete(CkpntMem *ck_memPtr);
+
+static void CVAbckpbDelete(CVodeBMem *cvB_memPtr);
+
+static int CVAdataStore(CVodeMem cv_mem, CkpntMem ck_mem);
+static int CVAckpntGet(CVodeMem cv_mem, CkpntMem ck_mem);
+
+static int CVAfindIndex(CVodeMem cv_mem, realtype t,
+ long int *indx, booleantype *newpoint);
+
+static booleantype CVAhermiteMalloc(CVodeMem cv_mem);
+static void CVAhermiteFree(CVodeMem cv_mem);
+static int CVAhermiteGetY(CVodeMem cv_mem, realtype t, N_Vector y, N_Vector *yS);
+static int CVAhermiteStorePnt(CVodeMem cv_mem, DtpntMem d);
+
+static booleantype CVApolynomialMalloc(CVodeMem cv_mem);
+static void CVApolynomialFree(CVodeMem cv_mem);
+static int CVApolynomialGetY(CVodeMem cv_mem, realtype t, N_Vector y, N_Vector *yS);
+static int CVApolynomialStorePnt(CVodeMem cv_mem, DtpntMem d);
+
+/* Wrappers */
+
+static int CVArhs(realtype t, N_Vector yB,
+ N_Vector yBdot, void *cvode_mem);
+
+static int CVArhsQ(realtype t, N_Vector yB,
+ N_Vector qBdot, void *cvode_mem);
+
+/*
+ * =================================================================
+ * EXPORTED FUNCTIONS IMPLEMENTATION
+ * =================================================================
+ */
+
+/*
+ * CVodeAdjInit
+ *
+ * This routine initializes ASA and allocates space for the adjoint
+ * memory structure.
+ */
+
+int CVodeAdjInit(void *cvode_mem, long int steps, int interp)
+{
+ CVadjMem ca_mem;
+ CVodeMem cv_mem;
+ long int i, ii;
+
+ /* ---------------
+ * Check arguments
+ * --------------- */
+
+ if (cvode_mem == NULL) {
+ cvProcessError(NULL, CV_MEM_NULL, "CVODEA", "CVodeAdjInit", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+ cv_mem = (CVodeMem)cvode_mem;
+
+ if (steps <= 0) {
+ cvProcessError(cv_mem, CV_ILL_INPUT, "CVODEA", "CVodeAdjInit", MSGCV_BAD_STEPS);
+ return(CV_ILL_INPUT);
+ }
+
+ if ( (interp != CV_HERMITE) && (interp != CV_POLYNOMIAL) ) {
+ cvProcessError(cv_mem, CV_ILL_INPUT, "CVODEA", "CVodeAdjInit", MSGCV_BAD_INTERP);
+ return(CV_ILL_INPUT);
+ }
+
+ /* ----------------------------
+ * Allocate CVODEA memory block
+ * ---------------------------- */
+
+ ca_mem = NULL;
+ ca_mem = (CVadjMem) malloc(sizeof(struct CVadjMemRec));
+ if (ca_mem == NULL) {
+ cvProcessError(cv_mem, CV_MEM_FAIL, "CVODEA", "CVodeAdjInit", MSGCV_MEM_FAIL);
+ return(CV_MEM_FAIL);
+ }
+
+ /* Attach ca_mem to CVodeMem structure */
+
+ cv_mem->cv_adj_mem = ca_mem;
+
+ /* ------------------------------
+ * Initialization of check points
+ * ------------------------------ */
+
+ /* Set Check Points linked list to NULL */
+ ca_mem->ck_mem = NULL;
+
+ /* Initialize nckpnts to ZERO */
+ ca_mem->ca_nckpnts = 0;
+
+ /* No interpolation data is available */
+ ca_mem->ca_ckpntData = NULL;
+
+ /* ------------------------------------
+ * Initialization of interpolation data
+ * ------------------------------------ */
+
+ /* Interpolation type */
+
+ ca_mem->ca_IMtype = interp;
+
+ /* Number of steps between check points */
+
+ ca_mem->ca_nsteps = steps;
+
+ /* Allocate space for the array of Data Point structures */
+
+ ca_mem->dt_mem = NULL;
+ ca_mem->dt_mem = (DtpntMem *) malloc((steps+1)*sizeof(struct DtpntMemRec *));
+ if (ca_mem->dt_mem == NULL) {
+ free(ca_mem); ca_mem = NULL;
+ cvProcessError(cv_mem, CV_MEM_FAIL, "CVODEA", "CVodeAdjInit", MSGCV_MEM_FAIL);
+ return(CV_MEM_FAIL);
+ }
+
+ for (i=0; i<=steps; i++) {
+ ca_mem->dt_mem[i] = NULL;
+ ca_mem->dt_mem[i] = (DtpntMem) malloc(sizeof(struct DtpntMemRec));
+ if (ca_mem->dt_mem[i] == NULL) {
+ for(ii=0; ii<i; ii++) {free(ca_mem->dt_mem[ii]); ca_mem->dt_mem[ii] = NULL;}
+ free(ca_mem->dt_mem); ca_mem->dt_mem = NULL;
+ free(ca_mem); ca_mem = NULL;
+ cvProcessError(cv_mem, CV_MEM_FAIL, "CVODEA", "CVodeAdjInit", MSGCV_MEM_FAIL);
+ return(CV_MEM_FAIL);
+ }
+ }
+
+ /* Attach functions for the appropriate interpolation module */
+
+ switch(interp) {
+
+ case CV_HERMITE:
+
+ ca_mem->ca_IMmalloc = CVAhermiteMalloc;
+ ca_mem->ca_IMfree = CVAhermiteFree;
+ ca_mem->ca_IMget = CVAhermiteGetY;
+ ca_mem->ca_IMstore = CVAhermiteStorePnt;
+
+ break;
+
+ case CV_POLYNOMIAL:
+
+ ca_mem->ca_IMmalloc = CVApolynomialMalloc;
+ ca_mem->ca_IMfree = CVApolynomialFree;
+ ca_mem->ca_IMget = CVApolynomialGetY;
+ ca_mem->ca_IMstore = CVApolynomialStorePnt;
+
+ break;
+
+ }
+
+ /* The interpolation module has not been initialized yet */
+
+ ca_mem->ca_IMmallocDone = FALSE;
+
+ /* By default we will store but not interpolate sensitivities
+ * - IMstoreSensi will be set in CVodeF to FALSE 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 */
+
+ ca_mem->ca_IMstoreSensi = TRUE;
+ ca_mem->ca_IMinterpSensi = FALSE;
+
+ /* ------------------------------------
+ * Initialize list of backward problems
+ * ------------------------------------ */
+
+ ca_mem->cvB_mem = NULL;
+ ca_mem->ca_bckpbCrt = NULL;
+ ca_mem->ca_nbckpbs = 0;
+
+ /* --------------------------------
+ * CVodeF and CVodeB not called yet
+ * -------------------------------- */
+
+ ca_mem->ca_firstCVodeFcall = TRUE;
+ ca_mem->ca_tstopCVodeFcall = FALSE;
+
+ ca_mem->ca_firstCVodeBcall = TRUE;
+
+ /* ---------------------------------------------
+ * ASA initialized and allocated
+ * --------------------------------------------- */
+
+ cv_mem->cv_adj = TRUE;
+ cv_mem->cv_adjMallocDone = TRUE;
+
+ return(CV_SUCCESS);
+}
+
+/* CVodeAdjReInit
+ *
+ * This routine reinitializes the CVODEA memory structure assuming that the
+ * the number of steps between check points and the type of interpolation
+ * remain unchanged.
+ * The list of check points (and associated memory) is deleted.
+ * The list of backward problems is kept (however, new backward problems can
+ * be added to this list by calling CVodeCreateB).
+ * The CVODES memory for the forward and backward problems can be reinitialized
+ * separately by calling CVodeReInit and CVodeReInitB, respectively.
+ * NOTE: if a completely new list of backward problems is also needed, then
+ * simply free the adjoint memory (by calling CVodeAdjFree) and reinitialize
+ * ASA with CVodeAdjInit.
+ */
+
+int CVodeAdjReInit(void *cvode_mem)
+{
+ CVadjMem ca_mem;
+ CVodeMem cv_mem;
+
+ /* Check cvode_mem */
+ if (cvode_mem == NULL) {
+ cvProcessError(NULL, CV_MEM_NULL, "CVODEA", "CVodeAdjReInit", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+ cv_mem = (CVodeMem) cvode_mem;
+
+ /* Was ASA initialized? */
+ if (cv_mem->cv_adjMallocDone == FALSE) {
+ cvProcessError(cv_mem, CV_NO_ADJ, "CVODEA", "CVodeAdjReInit", MSGCV_NO_ADJ);
+ return(CV_NO_ADJ);
+ }
+
+ ca_mem = cv_mem->cv_adj_mem;
+
+ /* Free current list of Check Points */
+
+ while (ca_mem->ck_mem != NULL) CVAckpntDelete(&(ca_mem->ck_mem));
+
+ /* Initialization of check points */
+
+ ca_mem->ck_mem = NULL;
+ ca_mem->ca_nckpnts = 0;
+ ca_mem->ca_ckpntData = NULL;
+
+ /* CVodeF and CVodeB not called yet */
+
+ ca_mem->ca_firstCVodeFcall = TRUE;
+ ca_mem->ca_tstopCVodeFcall = FALSE;
+ ca_mem->ca_firstCVodeBcall = TRUE;
+
+ return(CV_SUCCESS);
+}
+
+/*
+ * CVodeAdjFree
+ *
+ * This routine frees the memory allocated by CVodeAdjInit.
+ */
+
+void CVodeAdjFree(void *cvode_mem)
+{
+ CVodeMem cv_mem;
+ CVadjMem ca_mem;
+ long int i;
+
+ if (cvode_mem == NULL) return;
+ cv_mem = (CVodeMem) cvode_mem;
+
+ if (cv_mem->cv_adjMallocDone) {
+
+ ca_mem = cv_mem->cv_adj_mem;
+
+ /* Delete check points one by one */
+ while (ca_mem->ck_mem != NULL) CVAckpntDelete(&(ca_mem->ck_mem));
+
+ /* Free vectors at all data points */
+ if (ca_mem->ca_IMmallocDone) {
+ ca_mem->ca_IMfree(cv_mem);
+ }
+ for(i=0; i<=ca_mem->ca_nsteps; i++) {
+ free(ca_mem->dt_mem[i]);
+ ca_mem->dt_mem[i] = NULL;
+ }
+ free(ca_mem->dt_mem);
+ ca_mem->dt_mem = NULL;
+
+ /* Delete backward problems one by one */
+ while (ca_mem->cvB_mem != NULL) CVAbckpbDelete(&(ca_mem->cvB_mem));
+
+ /* Free CVODEA memory */
+ free(ca_mem);
+ cv_mem->cv_adj_mem = NULL;
+
+ }
+
+}
+
+/*
+ * -----------------------------------------------------------------
+ * 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
+ *
+ * This routine integrates to tout and returns solution into yout.
+ * In the same time, it stores check point data every 'steps' steps.
+ *
+ * CVodeF can be called repeatedly by the user.
+ *
+ * ncheckPtr points to the number of check points stored so far.
+ */
+
+int CVodeF(void *cvode_mem, realtype tout, N_Vector yout,
+ realtype *tret, int itask, int *ncheckPtr)
+{
+ CVadjMem ca_mem;
+ CVodeMem cv_mem;
+ CkpntMem tmp;
+ DtpntMem *dt_mem;
+ int flag, i;
+ booleantype iret, allocOK;
+
+ /* Check if cvode_mem exists */
+ if (cvode_mem == NULL) {
+ cvProcessError(NULL, CV_MEM_NULL, "CVODEA", "CVodeF", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+ cv_mem = (CVodeMem) cvode_mem;
+
+ /* Was ASA initialized? */
+ if (cv_mem->cv_adjMallocDone == FALSE) {
+ cvProcessError(cv_mem, CV_NO_ADJ, "CVODEA", "CVodeF", MSGCV_NO_ADJ);
+ return(CV_NO_ADJ);
+ }
+
+ ca_mem = cv_mem->cv_adj_mem;
+
+ /* Check for yout != NULL */
+ if (yout == NULL) {
+ cvProcessError(cv_mem, CV_ILL_INPUT, "CVODEA", "CVodeF", MSGCV_YOUT_NULL);
+ return(CV_ILL_INPUT);
+ }
+
+ /* Check for tret != NULL */
+ if (tret == NULL) {
+ cvProcessError(cv_mem, CV_ILL_INPUT, "CVODEA", "CVodeF", 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, "CVODEA", "CVodeF", MSGCV_BAD_ITASK);
+ return(CV_ILL_INPUT);
+ }
+
+ /* All error checking done */
+
+ dt_mem = ca_mem->dt_mem;
+
+ /* If tstop is enabled, store some info */
+ if (cv_mem->cv_tstopset) {
+ ca_mem->ca_tstopCVodeFcall = TRUE;
+ 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;
+
+ /* On the first step:
+ * - set tinitial
+ * - initialize list of check points
+ * - if needed, initialize the interpolation module
+ * - load dt_mem[0]
+ * On subsequent steps, test if taking a new step is necessary.
+ */
+ if ( ca_mem->ca_firstCVodeFcall ) {
+
+ tinitial = tn;
+
+ ca_mem->ck_mem = CVAckpntInit(cv_mem);
+ if (ca_mem->ck_mem == NULL) {
+ cvProcessError(cv_mem, CV_MEM_FAIL, "CVODEA", "CVodeF", MSGCV_MEM_FAIL);
+ return(CV_MEM_FAIL);
+ }
+
+ if ( !IMmallocDone ) {
+
+ /* Do we need to store sensitivities? */
+ if (!sensi) IMstoreSensi = FALSE;
+
+ /* Allocate space for interpolation data */
+ allocOK = 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];
+ }
+
+ IMmallocDone = TRUE;
+
+ }
+
+ dt_mem[0]->t = ca_mem->ck_mem->ck_t0;
+ IMstore(cv_mem, dt_mem[0]);
+
+ ca_mem->ca_firstCVodeFcall = FALSE;
+
+ } else if ( (tn - tout)*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;
+
+ return(flag);
+
+ }
+
+ /* Integrate to tout (in CV_ONE_STEP mode) while loading check points */
+ loop {
+
+ /* Perform one step of the integration */
+
+ flag = CVode(cv_mem, tout, yout, tret, CV_ONE_STEP);
+ if (flag < 0) break;
+
+ /* Test if a new check point is needed */
+
+ if ( nst % nsteps == 0 ) {
+
+ ca_mem->ck_mem->ck_t1 = *tret;
+
+ /* Create a new check point, load it, and append it to the list */
+ tmp = CVAckpntNew(cv_mem);
+ if (tmp == NULL) {
+ cvProcessError(cv_mem, CV_MEM_FAIL, "CVODEA", "CVodeF", MSGCV_MEM_FAIL);
+ flag = CV_MEM_FAIL;
+ break;
+ }
+ tmp->ck_next = ca_mem->ck_mem;
+ ca_mem->ck_mem = tmp;
+ nckpnts++;
+ forceSetup = TRUE;
+
+ /* Reset i=0 and load dt_mem[0] */
+ dt_mem[0]->t = ca_mem->ck_mem->ck_t0;
+ 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]);
+
+ }
+
+ /* Set t1 field of the current ckeck point structure
+ for the case in which there will be no future
+ check points */
+ ca_mem->ck_mem->ck_t1 = *tret;
+
+ /* tfinal is now set to *tret */
+ tfinal = *tret;
+
+ /* Return if in CV_ONE_STEP mode */
+ if (iret) break;
+
+ /* Return if tout reached */
+ if ( (*tret - tout)*h >= ZERO ) {
+ *tret = tout;
+ CVodeGetDky(cv_mem, tout, 0, yout);
+ /* Reset tretlast in cv_mem so that CVodeGetQuad and CVodeGetSens
+ * evaluate quadratures and/or sensitivities at the proper time */
+ cv_mem->cv_tretlast = tout;
+ break;
+ }
+
+ } /* end of loop() */
+
+ /* Get ncheck from ca_mem */
+ *ncheckPtr = nckpnts;
+
+ /* Data is available for the last interval */
+ IMnewData = TRUE;
+ ckpntData = ca_mem->ck_mem;
+ np = nst % nsteps + 1;
+
+ return(flag);
+}
+
+
+
+/*
+ * =================================================================
+ * FUNCTIONS FOR BACKWARD PROBLEMS
+ * =================================================================
+ */
+
+
+int CVodeCreateB(void *cvode_mem, int lmmB, int iterB, int *which)
+{
+ CVodeMem cv_mem;
+ CVadjMem ca_mem;
+ CVodeBMem new_cvB_mem;
+ void *cvodeB_mem;
+
+ /* Check if cvode_mem exists */
+ if (cvode_mem == NULL) {
+ cvProcessError(NULL, CV_MEM_NULL, "CVODEA", "CVodeCreateB", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+ cv_mem = (CVodeMem) cvode_mem;
+
+ /* Was ASA initialized? */
+ if (cv_mem->cv_adjMallocDone == FALSE) {
+ cvProcessError(cv_mem, CV_NO_ADJ, "CVODEA", "CVodeCreateB", MSGCV_NO_ADJ);
+ return(CV_NO_ADJ);
+ }
+ ca_mem = cv_mem->cv_adj_mem;
+
+ /* Allocate space for new CVodeBMem object */
+
+ new_cvB_mem = NULL;
+ new_cvB_mem = (CVodeBMem) malloc(sizeof(struct CVodeBMemRec));
+ if (new_cvB_mem == NULL) {
+ cvProcessError(cv_mem, CV_MEM_FAIL, "CVODEA", "CVodeCreateB", MSGCV_MEM_FAIL);
+ return(CV_MEM_FAIL);
+ }
+
+ /* Create and set a new CVODES object for the backward problem */
+
+ cvodeB_mem = CVodeCreate(lmmB, iterB);
+ if (cvodeB_mem == NULL) {
+ cvProcessError(cv_mem, CV_MEM_FAIL, "CVODEA", "CVodeCreateB", MSGCV_MEM_FAIL);
+ return(CV_MEM_FAIL);
+ }
+
+ CVodeSetUserData(cvodeB_mem, cvode_mem);
+
+ CVodeSetMaxHnilWarns(cvodeB_mem, -1);
+
+ CVodeSetErrHandlerFn(cvodeB_mem, cv_mem->cv_ehfun, cv_mem->cv_eh_data);
+ CVodeSetErrFile(cvodeB_mem, cv_mem->cv_errfp);
+
+ /* Set/initialize fields in the new CVodeBMem object, new_cvB_mem */
+
+ new_cvB_mem->cv_index = nbckpbs;
+
+ new_cvB_mem->cv_mem = (CVodeMem) cvodeB_mem;
+
+ new_cvB_mem->cv_f = NULL;
+ new_cvB_mem->cv_fs = NULL;
+
+ new_cvB_mem->cv_fQ = NULL;
+ new_cvB_mem->cv_fQs = NULL;
+
+ new_cvB_mem->cv_user_data = NULL;
+
+ new_cvB_mem->cv_lmem = NULL;
+ new_cvB_mem->cv_lfree = NULL;
+ new_cvB_mem->cv_pmem = NULL;
+ new_cvB_mem->cv_pfree = NULL;
+
+ new_cvB_mem->cv_y = NULL;
+
+ new_cvB_mem->cv_f_withSensi = FALSE;
+ new_cvB_mem->cv_fQ_withSensi = FALSE;
+
+ /* Attach the new object to the linked list cvB_mem */
+
+ new_cvB_mem->cv_next = ca_mem->cvB_mem;
+ ca_mem->cvB_mem = new_cvB_mem;
+
+ /* Return the index of the newly created CVodeBMem object.
+ * This must be passed to CVodeInitB and to other ***B
+ * functions to set optional inputs for this backward problem */
+
+ *which = nbckpbs;
+
+ nbckpbs++;
+
+ return(CV_SUCCESS);
+}
+
+int CVodeInitB(void *cvode_mem, int which,
+ CVRhsFnB fB,
+ realtype tB0, N_Vector yB0)
+{
+ 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, CV_MEM_NULL, "CVODEA", "CVodeInitB", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+ cv_mem = (CVodeMem) cvode_mem;
+
+ /* Was ASA initialized? */
+
+ if (cv_mem->cv_adjMallocDone == FALSE) {
+ cvProcessError(cv_mem, CV_NO_ADJ, "CVODEA", "CVodeInitB", MSGCV_NO_ADJ);
+ return(CV_NO_ADJ);
+ }
+ ca_mem = cv_mem->cv_adj_mem;
+
+ /* Check the value of which */
+
+ if ( which >= nbckpbs ) {
+ cvProcessError(cv_mem, CV_ILL_INPUT, "CVODEA", "CVodeInitB", MSGCV_BAD_WHICH);
+ return(CV_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);
+
+ /* Allocate and set the CVODES object */
+
+ flag = CVodeInit(cvodeB_mem, CVArhs, tB0, yB0);
+
+ if (flag != CV_SUCCESS) return(flag);
+
+ /* Copy fB function in cvB_mem */
+
+ cvB_mem->cv_f_withSensi = FALSE;
+ cvB_mem->cv_f = fB;
+
+ /* Allocate space and initialize the y Nvector in cvB_mem */
+
+ cvB_mem->cv_t0 = tB0;
+ cvB_mem->cv_y = N_VClone(yB0);
+ N_VScale(ONE, yB0, cvB_mem->cv_y);
+
+ return(CV_SUCCESS);
+}
+
+int CVodeInitBS(void *cvode_mem, int which,
+ CVRhsFnBS fBs,
+ realtype tB0, N_Vector yB0)
+{
+ 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, CV_MEM_NULL, "CVODEA", "CVodeInitBS", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+ cv_mem = (CVodeMem) cvode_mem;
+
+ /* Was ASA initialized? */
+
+ if (cv_mem->cv_adjMallocDone == FALSE) {
+ cvProcessError(cv_mem, CV_NO_ADJ, "CVODEA", "CVodeInitBS", MSGCV_NO_ADJ);
+ return(CV_NO_ADJ);
+ }
+ ca_mem = cv_mem->cv_adj_mem;
+
+ /* Check the value of which */
+
+ if ( which >= nbckpbs ) {
+ cvProcessError(cv_mem, CV_ILL_INPUT, "CVODEA", "CVodeInitBS", MSGCV_BAD_WHICH);
+ return(CV_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);
+
+ /* Allocate and set the CVODES object */
+
+ flag = CVodeInit(cvodeB_mem, CVArhs, tB0, yB0);
+
+ if (flag != CV_SUCCESS) return(flag);
+
+ /* Copy fBs function in cvB_mem */
+
+ cvB_mem->cv_f_withSensi = TRUE;
+ cvB_mem->cv_fs = fBs;
+
+ /* Allocate space and initialize the y Nvector in cvB_mem */
+
+ cvB_mem->cv_t0 = tB0;
+ cvB_mem->cv_y = N_VClone(yB0);
+ N_VScale(ONE, yB0, cvB_mem->cv_y);
+
+ return(CV_SUCCESS);
+}
+
+
+int CVodeReInitB(void *cvode_mem, int which,
+ realtype tB0, N_Vector yB0)
+{
+ 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, CV_MEM_NULL, "CVODEA", "CVodeReInitB", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+ cv_mem = (CVodeMem) cvode_mem;
+
+ /* Was ASA initialized? */
+ if (cv_mem->cv_adjMallocDone == FALSE) {
+ 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 ) {
+ cvProcessError(cv_mem, CV_ILL_INPUT, "CVODEA", "CVodeReInitB", MSGCV_BAD_WHICH);
+ return(CV_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);
+
+ /* Reinitialize CVODES object */
+
+ flag = CVodeReInit(cvodeB_mem, tB0, yB0);
+
+ return(flag);
+}
+
+
+int CVodeSStolerancesB(void *cvode_mem, int which, realtype reltolB, realtype abstolB)
+{
+ 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, CV_MEM_NULL, "CVODEA", "CVodeSStolerancesB", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+ cv_mem = (CVodeMem) cvode_mem;
+
+ /* Was ASA initialized? */
+
+ if (cv_mem->cv_adjMallocDone == FALSE) {
+ cvProcessError(cv_mem, CV_NO_ADJ, "CVODEA", "CVodeSStolerancesB", MSGCV_NO_ADJ);
+ return(CV_NO_ADJ);
+ }
+ ca_mem = cv_mem->cv_adj_mem;
+
+ /* Check the value of which */
+
+ if ( which >= nbckpbs ) {
+ cvProcessError(cv_mem, CV_ILL_INPUT, "CVODEA", "CVodeSStolerancesB", MSGCV_BAD_WHICH);
+ return(CV_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);
+
+ /* Set tolerances */
+
+ flag = CVodeSStolerances(cvodeB_mem, reltolB, abstolB);
+
+ return(flag);
+}
+
+
+int CVodeSVtolerancesB(void *cvode_mem, int which, realtype reltolB, N_Vector abstolB)
+{
+ 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, CV_MEM_NULL, "CVODEA", "CVodeSVtolerancesB", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+ cv_mem = (CVodeMem) cvode_mem;
+
+ /* Was ASA initialized? */
+
+ if (cv_mem->cv_adjMallocDone == FALSE) {
+ cvProcessError(cv_mem, CV_NO_ADJ, "CVODEA", "CVodeSVtolerancesB", MSGCV_NO_ADJ);
+ return(CV_NO_ADJ);
+ }
+ ca_mem = cv_mem->cv_adj_mem;
+
+ /* Check the value of which */
+
+ if ( which >= nbckpbs ) {
+ cvProcessError(cv_mem, CV_ILL_INPUT, "CVODEA", "CVodeSVtolerancesB", MSGCV_BAD_WHICH);
+ return(CV_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);
+
+ /* Set tolerances */
+
+ flag = CVodeSVtolerances(cvodeB_mem, reltolB, abstolB);
+
+ return(flag);
+}
+
+
+int CVodeQuadInitB(void *cvode_mem, int which,
+ CVQuadRhsFnB fQB, N_Vector yQB0)
+{
+ 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, CV_MEM_NULL, "CVODEA", "CVodeQuadInitB", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+ cv_mem = (CVodeMem) cvode_mem;
+
+ /* Was ASA initialized? */
+ if (cv_mem->cv_adjMallocDone == FALSE) {
+ 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 ) {
+ cvProcessError(cv_mem, CV_ILL_INPUT, "CVODEA", "CVodeQuadInitB", MSGCV_BAD_WHICH);
+ return(CV_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 = CVodeQuadInit(cvodeB_mem, CVArhsQ, yQB0);
+ if (flag != CV_SUCCESS) return(flag);
+
+ cvB_mem->cv_fQ_withSensi = FALSE;
+ cvB_mem->cv_fQ = fQB;
+
+ return(CV_SUCCESS);
+}
+
+int CVodeQuadInitBS(void *cvode_mem, int which,
+ CVQuadRhsFnBS fQBs, N_Vector yQB0)
+{
+ 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, CV_MEM_NULL, "CVODEA", "CVodeQuadInitBS", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+ cv_mem = (CVodeMem) cvode_mem;
+
+ /* Was ASA initialized? */
+ if (cv_mem->cv_adjMallocDone == FALSE) {
+ 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 ) {
+ cvProcessError(cv_mem, CV_ILL_INPUT, "CVODEA", "CVodeQuadInitBS", MSGCV_BAD_WHICH);
+ return(CV_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 = CVodeQuadInit(cvodeB_mem, CVArhsQ, yQB0);
+ if (flag != CV_SUCCESS) return(flag);
+
+ cvB_mem->cv_fQ_withSensi = TRUE;
+ cvB_mem->cv_fQs = fQBs;
+
+ return(CV_SUCCESS);
+}
+
+int CVodeQuadReInitB(void *cvode_mem, int which, N_Vector yQB0)
+{
+ 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, CV_MEM_NULL, "CVODEA", "CVodeQuadReInitB", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+ cv_mem = (CVodeMem) cvode_mem;
+
+ /* Was ASA initialized? */
+ if (cv_mem->cv_adjMallocDone == FALSE) {
+ 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 ) {
+ cvProcessError(cv_mem, CV_ILL_INPUT, "CVODEA", "CVodeQuadReInitB", MSGCV_BAD_WHICH);
+ return(CV_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 = CVodeQuadReInit(cvodeB_mem, yQB0);
+ if (flag != CV_SUCCESS) return(flag);
+
+ return(CV_SUCCESS);
+}
+
+int CVodeQuadSStolerancesB(void *cvode_mem, int which, realtype reltolQB, realtype abstolQB)
+{
+ 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, CV_MEM_NULL, "CVODEA", "CVodeQuadSStolerancesB", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+ cv_mem = (CVodeMem) cvode_mem;
+
+ /* Was ASA initialized? */
+ if (cv_mem->cv_adjMallocDone == FALSE) {
+ 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 ) {
+ cvProcessError(cv_mem, CV_ILL_INPUT, "CVODEA", "CVodeQuadSStolerancesB", MSGCV_BAD_WHICH);
+ return(CV_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 = CVodeQuadSStolerances(cvodeB_mem, reltolQB, abstolQB);
+
+ return(flag);
+}
+
+int CVodeQuadSVtolerancesB(void *cvode_mem, int which, realtype reltolQB, N_Vector abstolQB)
+{
+ 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, CV_MEM_NULL, "CVODEA", "CVodeQuadSStolerancesB", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+ cv_mem = (CVodeMem) cvode_mem;
+
+ /* Was ASA initialized? */
+ if (cv_mem->cv_adjMallocDone == FALSE) {
+ 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 ) {
+ cvProcessError(cv_mem, CV_ILL_INPUT, "CVODEA", "CVodeQuadSStolerancesB", MSGCV_BAD_WHICH);
+ return(CV_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 = CVodeQuadSVtolerances(cvodeB_mem, reltolQB, abstolQB);
+
+ return(flag);
+}
+
+/*
+ * CVodeB
+ *
+ * This routine performs the backward integration towards tBout
+ * of all backward problems that were defined.
+ * When necessary, it performs a forward integration between two
+ * consecutive check points to update interpolation data.
+ *
+ * On a successful return, CVodeB returns CV_SUCCESS.
+ *
+ * NOTE that CVodeB DOES NOT return the solution for the backward
+ * problem(s). Use CVodeGetB to extract the solution at tBret
+ * for any given backward problem.
+ *
+ * If there are multiple backward problems and multiple check points,
+ * CVodeB may not succeed in getting all problems to take one step
+ * when called in ONE_STEP mode.
+ */
+
+int CVodeB(void *cvode_mem, realtype tBout, int itaskB)
+{
+ CVodeMem cv_mem;
+ CVadjMem ca_mem;
+ CVodeBMem cvB_mem, tmp_cvB_mem;
+ CkpntMem ck_mem;
+ int sign, flag;
+ realtype tfuzz, tBret, tBn;
+ booleantype gotCheckpoint, isActive, reachedTBout;
+
+ /* Check if cvode_mem exists */
+
+ if (cvode_mem == NULL) {
+ cvProcessError(NULL, CV_MEM_NULL, "CVODEA", "CVodeB", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+ cv_mem = (CVodeMem) cvode_mem;
+
+ /* Was ASA initialized? */
+
+ if (cv_mem->cv_adjMallocDone == FALSE) {
+ cvProcessError(cv_mem, CV_NO_ADJ, "CVODEA", "CVodeB", MSGCV_NO_ADJ);
+ return(CV_NO_ADJ);
+ }
+ ca_mem = cv_mem->cv_adj_mem;
+
+ /* Check if any backward problem has been defined */
+
+ if ( nbckpbs == 0 ) {
+ cvProcessError(cv_mem, CV_NO_BCK, "CVODEA", "CVodeB", MSGCV_NO_BCK);
+ return(CV_NO_BCK);
+ }
+ cvB_mem = ca_mem->cvB_mem;
+
+ /* Check whether CVodeF has been called */
+
+ if ( ca_mem->ca_firstCVodeFcall ) {
+ cvProcessError(cv_mem, CV_NO_FWD, "CVODEA", "CVodeB", MSGCV_NO_FWD);
+ return(CV_NO_FWD);
+ }
+ sign = (tfinal - tinitial > ZERO) ? 1 : -1;
+
+ /* If this is the first call, loop over all backward problems and
+ * - check that tB0 is valid
+ * - check that tBout is ahead of tB0 in the backward direction
+ * - check whether we need to interpolate forward sensitivities
+ */
+
+ if ( ca_mem->ca_firstCVodeBcall ) {
+
+ tmp_cvB_mem = cvB_mem;
+
+ while(tmp_cvB_mem != NULL) {
+
+ tBn = tmp_cvB_mem->cv_mem->cv_tn;
+
+ if ( (sign*(tBn-tinitial) < ZERO) || (sign*(tfinal-tBn) < ZERO) ) {
+ cvProcessError(cv_mem, CV_BAD_TB0, "CVODEA", "CVodeB", MSGCV_BAD_TB0,
+ tmp_cvB_mem->cv_index);
+ return(CV_BAD_TB0);
+ }
+
+ if (sign*(tBn-tBout) <= ZERO) {
+ cvProcessError(cv_mem, CV_ILL_INPUT, "CVODEA", "CVodeB", MSGCV_BAD_TBOUT,
+ tmp_cvB_mem->cv_index);
+ return(CV_ILL_INPUT);
+ }
+
+ if ( tmp_cvB_mem->cv_f_withSensi || tmp_cvB_mem->cv_fQ_withSensi )
+ IMinterpSensi = TRUE;
+
+ tmp_cvB_mem = tmp_cvB_mem->cv_next;
+
+ }
+
+ if ( IMinterpSensi && !IMstoreSensi) {
+ cvProcessError(cv_mem, CV_ILL_INPUT, "CVODEA", "CVodeB", MSGCV_BAD_SENSI);
+ return(CV_ILL_INPUT);
+ }
+
+ ca_mem->ca_firstCVodeBcall = FALSE;
+ }
+
+ /* Check if itaskB is legal */
+
+ if ( (itaskB != CV_NORMAL) && (itaskB != CV_ONE_STEP) ) {
+ cvProcessError(cv_mem, CV_ILL_INPUT, "CVODEA", "CVodeB", MSGCV_BAD_ITASKB);
+ return(CV_ILL_INPUT);
+ }
+
+ /* Check if tBout is legal */
+
+ if ( (sign*(tBout-tinitial) < ZERO) || (sign*(tfinal-tBout) < ZERO) ) {
+ tfuzz = HUNDRED*uround*(ABS(tinitial) + ABS(tfinal));
+ if ( (sign*(tBout-tinitial) < ZERO) && (ABS(tBout-tinitial) < tfuzz) ) {
+ tBout = tinitial;
+ } else {
+ cvProcessError(cv_mem, CV_ILL_INPUT, "CVODEA", "CVodeB", MSGCV_BAD_TBOUT);
+ return(CV_ILL_INPUT);
+ }
+ }
+
+ /* Loop through the check points and stop as soon as a backward
+ * problem has its tn value behind the current check point's t0_
+ * value (in the backward direction) */
+
+ ck_mem = ca_mem->ck_mem;
+
+ gotCheckpoint = FALSE;
+
+ loop {
+
+ 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;
+ break;
+ }
+
+ if ( (itaskB==CV_NORMAL) && (tBn == t0_) && (sign*(tBout-t0_) >= ZERO) ) {
+ gotCheckpoint = TRUE;
+ break;
+ }
+
+ tmp_cvB_mem = tmp_cvB_mem->cv_next;
+ }
+
+ if (gotCheckpoint) break;
+
+ if (next_ == NULL) break;
+
+ ck_mem = next_;
+ }
+
+ /* Starting with the current check point from above, loop over check points
+ while propagating backward problems */
+
+ loop {
+
+ /* Store interpolation data if not available.
+ This is the 2nd forward integration pass */
+
+ if (ck_mem != ckpntData) {
+ flag = CVAdataStore(cv_mem, ck_mem);
+ if (flag != CV_SUCCESS) break;
+ }
+
+ /* Loop through all backward problems and, if needed,
+ * propagate their solution towards tBout */
+
+ tmp_cvB_mem = cvB_mem;
+ while (tmp_cvB_mem != NULL) {
+
+ /* Decide if current backward problem is "active" in this check point */
+
+ isActive = TRUE;
+
+ 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 ( sign * (tBn - t0_) < ZERO ) isActive = FALSE;
+
+ if ( isActive ) {
+
+ /* Store the address of current backward problem memory
+ * in ca_mem to be used in the wrapper functions */
+ ca_mem->ca_bckpbCrt = tmp_cvB_mem;
+
+ /* Integrate current backward problem */
+ CVodeSetStopTime(tmp_cvB_mem->cv_mem, 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 */
+ tmp_cvB_mem->cv_tout = tBret;
+
+ /* If an error occurred, exit while loop */
+ if (flag < 0) break;
+
+ } else {
+ flag = CV_SUCCESS;
+ tmp_cvB_mem->cv_tout = tBn;
+ }
+
+ /* Move to next backward problem */
+
+ tmp_cvB_mem = tmp_cvB_mem->cv_next;
+ }
+
+ /* If an error occurred, return now */
+
+ if (flag <0) {
+ cvProcessError(cv_mem, flag, "CVODEA", "CVodeB", MSGCV_BACK_ERROR,
+ tmp_cvB_mem->cv_index);
+ return(flag);
+ }
+
+ /* If in CV_ONE_STEP mode, return now (flag = CV_SUCCESS) */
+
+ if (itaskB == CV_ONE_STEP) break;
+
+ /* If all backward problems have succesfully reached tBout, return now */
+
+ reachedTBout = TRUE;
+
+ tmp_cvB_mem = cvB_mem;
+ while(tmp_cvB_mem != NULL) {
+ if ( sign*(tmp_cvB_mem->cv_tout - tBout) > ZERO ) {
+ reachedTBout = FALSE;
+ break;
+ }
+ tmp_cvB_mem = tmp_cvB_mem->cv_next;
+ }
+
+ if ( reachedTBout ) break;
+
+ /* Move check point in linked list to next one */
+
+ ck_mem = next_;
+
+ }
+
+ return(flag);
+}
+
+
+int CVodeGetB(void *cvode_mem, int which, realtype *tret, N_Vector yB)
+{
+ CVodeMem cv_mem;
+ CVadjMem ca_mem;
+ CVodeBMem cvB_mem;
+
+ /* Check if cvode_mem exists */
+ if (cvode_mem == NULL) {
+ cvProcessError(NULL, CV_MEM_NULL, "CVODEA", "CVodeGetB", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+ cv_mem = (CVodeMem) cvode_mem;
+
+ /* Was ASA initialized? */
+ if (cv_mem->cv_adjMallocDone == FALSE) {
+ cvProcessError(cv_mem, CV_NO_ADJ, "CVODEA", "CVodeGetB", MSGCV_NO_ADJ);
+ return(CV_NO_ADJ);
+ }
+
+ ca_mem = cv_mem->cv_adj_mem;
+
+ /* Check the value of which */
+ if ( which >= nbckpbs ) {
+ cvProcessError(cv_mem, CV_ILL_INPUT, "CVODEA", "CVodeGetB", MSGCV_BAD_WHICH);
+ return(CV_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;
+ }
+
+ N_VScale(ONE, cvB_mem->cv_y, yB);
+ *tret = cvB_mem->cv_tout;
+
+ return(CV_SUCCESS);
+}
+
+
+/*
+ * CVodeGetQuadB
+ */
+
+int CVodeGetQuadB(void *cvode_mem, int which, realtype *tret, N_Vector qB)
+{
+ CVodeMem cv_mem;
+ CVadjMem ca_mem;
+ CVodeBMem cvB_mem;
+ void *cvodeB_mem;
+ long int nstB;
+ int flag;
+
+ /* Check if cvode_mem exists */
+ if (cvode_mem == NULL) {
+ cvProcessError(NULL, CV_MEM_NULL, "CVODEA", "CVodeGetQuadB", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+ cv_mem = (CVodeMem) cvode_mem;
+
+ /* Was ASA initialized? */
+ if (cv_mem->cv_adjMallocDone == FALSE) {
+ cvProcessError(cv_mem, CV_NO_ADJ, "CVODEA", "CVodeGetQuadB", MSGCV_NO_ADJ);
+ return(CV_NO_ADJ);
+ }
+
+ ca_mem = cv_mem->cv_adj_mem;
+
+ /* Check the value of which */
+ if ( which >= nbckpbs ) {
+ cvProcessError(cv_mem, CV_ILL_INPUT, "CVODEA", "CVodeGetQuadB", MSGCV_BAD_WHICH);
+ return(CV_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 the integration for this backward problem has not started yet,
+ * simply return the current value of qB (i.e. the final conditions) */
+
+ flag = CVodeGetNumSteps(cvodeB_mem, &nstB);
+
+ if (nstB == 0) {
+ N_VScale(ONE, cvB_mem->cv_mem->cv_znQ[0], qB);
+ *tret = cvB_mem->cv_tout;
+ } else {
+ flag = CVodeGetQuad(cvodeB_mem, tret, qB);
+ }
+
+ return(flag);
+}
+
+
+/*
+ * =================================================================
+ * PRIVATE FUNCTIONS FOR CHECK POINTS
+ * =================================================================
+ */
+
+/*
+ * CVAckpntInit
+ *
+ * This routine initializes the check point linked list with
+ * information from the initial time.
+ */
+
+static CkpntMem CVAckpntInit(CVodeMem cv_mem)
+{
+ CkpntMem ck_mem;
+ int is;
+
+ /* Allocate space for ckdata */
+ ck_mem = NULL;
+ ck_mem = (CkpntMem) malloc(sizeof(struct CkpntMemRec));
+ if (ck_mem == NULL) return(NULL);
+
+ zn_[0] = N_VClone(tempv);
+ if (zn_[0] == NULL) {
+ free(ck_mem); ck_mem = NULL;
+ return(NULL);
+ }
+
+ zn_[1] = N_VClone(tempv);
+ if (zn_[1] == NULL) {
+ N_VDestroy(zn_[0]);
+ free(ck_mem); ck_mem = NULL;
+ return(NULL);
+ }
+
+ /* zn_[qmax] was not allocated */
+ zqm_ = 0;
+
+ /* Load ckdata from cv_mem */
+ N_VScale(ONE, zn[0], zn_[0]);
+ t0_ = tn;
+ nst_ = 0;
+ q_ = 1;
+ h_ = 0.0;
+
+ /* Do we need to carry quadratures */
+ quadr_ = quadr && errconQ;
+
+ if (quadr_) {
+
+ znQ_[0] = N_VClone(tempvQ);
+ if (znQ_[0] == NULL) {
+ N_VDestroy(zn_[0]);
+ N_VDestroy(zn_[1]);
+ free(ck_mem); ck_mem = NULL;
+ return(NULL);
+ }
+
+ N_VScale(ONE, znQ[0], znQ_[0]);
+
+ }
+
+ /* Do we need to carry sensitivities? */
+ sensi_ = sensi;
+
+ if (sensi_) {
+
+ Ns_ = 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]);
+ free(ck_mem); ck_mem = NULL;
+ return(NULL);
+ }
+
+ for (is=0; is<Ns; is++)
+ N_VScale(ONE, znS[0][is], 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);
+ free(ck_mem); ck_mem = NULL;
+ return(NULL);
+ }
+
+ for (is=0; is<Ns; is++)
+ N_VScale(ONE, znQS[0][is], znQS_[0][is]);
+
+ }
+
+ /* Next in list */
+ next_ = NULL;
+
+ return(ck_mem);
+}
+
+/*
+ * CVAckpntNew
+ *
+ * This routine allocates space for a new check point and sets
+ * its data from current values in cv_mem.
+ */
+
+static CkpntMem CVAckpntNew(CVodeMem cv_mem)
+{
+ CkpntMem ck_mem;
+ int j, jj, is, qmax;
+
+ /* Allocate space for ckdata */
+ ck_mem = NULL;
+ ck_mem = (CkpntMem) malloc(sizeof(struct CkpntMemRec));
+ if (ck_mem == NULL) return(NULL);
+
+ /* Set cv_next to NULL */
+ ck_mem->ck_next = NULL;
+
+ /* Test if we need to allocate space for the last zn.
+ * 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;
+
+ 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]);
+ 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]);
+ free(ck_mem); ck_mem = NULL;
+ return(NULL);
+ }
+ }
+
+ /* Test if we need to carry quadratures */
+ quadr_ = quadr && errconQ;
+
+ if (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]);
+ 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]);
+ free(ck_mem); ck_mem = NULL;
+ return(NULL);
+ }
+ }
+
+ }
+
+ /* Test if we need to carry sensitivities */
+ sensi_ = sensi;
+
+ if (sensi_) {
+
+ Ns_ = 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]);
+ }
+ if (q < qmax) N_VDestroy(zn_[qmax]);
+ for (jj=0; jj<=q; jj++) N_VDestroy(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]);
+ }
+ N_VDestroy(zn_[qmax]);
+ for (jj=0; jj<=q; jj++) N_VDestroy(zn_[jj]);
+ free(ck_mem); ck_mem = NULL;
+ return(NULL);
+ }
+ }
+
+ }
+
+ /* 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]);
+ }
+ if (q < qmax) N_VDestroy(zn_[qmax]);
+ for (jj=0; jj<=q; jj++) N_VDestroy(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]);
+ }
+ N_VDestroy(zn_[qmax]);
+ for (jj=0; jj<=q; jj++) N_VDestroy(zn_[jj]);
+ free(ck_mem); ck_mem = NULL;
+ return(NULL);
+ }
+ }
+
+ }
+
+ /* 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]);
+
+ 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 (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 (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]);
+ }
+ }
+
+ 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;
+
+ return(ck_mem);
+}
+
+/*
+ * CVAckpntDelete
+ *
+ * This routine deletes the first check point in list and returns
+ * the new list head
+ */
+
+static void CVAckpntDelete(CkpntMem *ck_memPtr)
+{
+ CkpntMem tmp;
+ int j;
+
+ if (*ck_memPtr == NULL) return;
+
+ /* store head of list */
+ tmp = *ck_memPtr;
+
+ /* move head of list */
+ *ck_memPtr = (*ck_memPtr)->ck_next;
+
+ /* free N_Vectors in tmp */
+ for (j=0;j<=tmp->ck_q;j++) N_VDestroy(tmp->ck_zn[j]);
+ if (tmp->ck_zqm != 0) N_VDestroy(tmp->ck_zn[tmp->ck_zqm]);
+
+ /* free N_Vectors for quadratures in tmp
+ * Note that at the check point at t_initial, only znQ_[0]
+ * was allocated */
+ if (tmp->ck_quadr) {
+
+ if (tmp->ck_next != NULL) {
+ for (j=0;j<=tmp->ck_q;j++) N_VDestroy(tmp->ck_znQ[j]);
+ if (tmp->ck_zqm != 0) N_VDestroy(tmp->ck_znQ[tmp->ck_zqm]);
+ } else {
+ N_VDestroy(tmp->ck_znQ[0]);
+ }
+
+ }
+
+ /* free N_Vectors for sensitivities in tmp
+ * Note that at the check point at t_initial, only znS_[0]
+ * was allocated */
+ if (tmp->ck_sensi) {
+
+ if (tmp->ck_next != NULL) {
+ for (j=0;j<=tmp->ck_q;j++) N_VDestroyVectorArray(tmp->ck_znS[j], tmp->ck_Ns);
+ if (tmp->ck_zqm != 0) N_VDestroyVectorArray(tmp->ck_znS[tmp->ck_zqm], tmp->ck_Ns);
+ } else {
+ N_VDestroyVectorArray(tmp->ck_znS[0], tmp->ck_Ns);
+ }
+
+ }
+
+ /* free N_Vectors for quadrature sensitivities in tmp
+ * Note that at the check point at t_initial, only znQS_[0]
+ * was allocated */
+ if (tmp->ck_quadr_sensi) {
+
+ if (tmp->ck_next != NULL) {
+ for (j=0;j<=tmp->ck_q;j++) N_VDestroyVectorArray(tmp->ck_znQS[j], tmp->ck_Ns);
+ if (tmp->ck_zqm != 0) N_VDestroyVectorArray(tmp->ck_znQS[tmp->ck_zqm], tmp->ck_Ns);
+ } else {
+ N_VDestroyVectorArray(tmp->ck_znQS[0], tmp->ck_Ns);
+ }
+
+ }
+
+ free(tmp); tmp = NULL;
+
+}
+
+/*
+ * =================================================================
+ * PRIVATE FUNCTIONS FOR BACKWARD PROBLEMS
+ * =================================================================
+ */
+
+static void CVAbckpbDelete(CVodeBMem *cvB_memPtr)
+{
+ CVodeBMem tmp;
+ void *cvode_mem;
+
+ if (*cvB_memPtr != NULL) {
+
+ /* Save head of the list */
+ tmp = *cvB_memPtr;
+
+ /* Move head of the list */
+ *cvB_memPtr = (*cvB_memPtr)->cv_next;
+
+ /* Free CVODES memory in tmp */
+ cvode_mem = (void *)(tmp->cv_mem);
+ CVodeFree(&cvode_mem);
+
+ /* Free linear solver memory */
+ if (tmp->cv_lfree != NULL) tmp->cv_lfree(tmp);
+
+ /* Free preconditioner memory */
+ if (tmp->cv_pfree != NULL) tmp->cv_pfree(tmp);
+
+ /* Free workspace Nvector */
+ N_VDestroy(tmp->cv_y);
+
+ free(tmp); tmp = NULL;
+
+ }
+
+}
+
+/*
+ * =================================================================
+ * PRIVATE FUNCTIONS FOR INTERPOLATION
+ * =================================================================
+ */
+
+/*
+ * CVAdataStore
+ *
+ * This routine integrates the forward model starting at the check
+ * point ck_mem and stores y and yprime at all intermediate steps.
+ *
+ * Return values:
+ * CV_SUCCESS
+ * CV_REIFWD_FAIL
+ * CV_FWD_FAIL
+ */
+
+static int CVAdataStore(CVodeMem cv_mem, CkpntMem ck_mem)
+{
+ CVadjMem ca_mem;
+ DtpntMem *dt_mem;
+ realtype t;
+ long int i;
+ int flag, sign;
+
+ ca_mem = cv_mem->cv_adj_mem;
+ dt_mem = ca_mem->dt_mem;
+
+ /* Initialize cv_mem with data from ck_mem */
+ flag = CVAckpntGet(cv_mem, ck_mem);
+ if (flag != CV_SUCCESS)
+ return(CV_REIFWD_FAIL);
+
+ /* Set first structure in dt_mem[0] */
+ dt_mem[0]->t = t0_;
+ 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;
+
+
+ /* Run CVode to set following structures in dt_mem[i] */
+ i = 1;
+ do {
+
+ flag = CVode(cv_mem, t1_, ytmp, &t, CV_ONE_STEP);
+ if (flag < 0) return(CV_FWD_FAIL);
+
+ dt_mem[i]->t = t;
+ IMstore(cv_mem, dt_mem[i]);
+ i++;
+
+ } while ( sign*(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 */
+
+ return(CV_SUCCESS);
+}
+
+/*
+ * CVAckpntGet
+ *
+ * This routine prepares CVODES for a hot restart from
+ * the check point ck_mem
+ */
+
+static int CVAckpntGet(CVodeMem cv_mem, CkpntMem ck_mem)
+{
+ int flag, j, is, qmax;
+
+ if (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);
+
+ flag = CVodeReInit(cv_mem, t0_, zn_[0]);
+ if (flag != CV_SUCCESS) return(flag);
+
+ if (quadr_) {
+ flag = CVodeQuadReInit(cv_mem, znQ_[0]);
+ if (flag != CV_SUCCESS) return(flag);
+ }
+
+ if (sensi_) {
+ flag = CVodeSensReInit(cv_mem, cv_mem->cv_ism, znS_[0]);
+ if (flag != CV_SUCCESS) return(flag);
+ }
+
+ if (quadr_sensi_) {
+ flag = CVodeQuadSensReInit(cv_mem, znQS_[0]);
+ if (flag != CV_SUCCESS) return(flag);
+ }
+
+ } else {
+
+ qmax = cv_mem->cv_qmax;
+
+ /* 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_;
+
+ /* 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]);
+
+ 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 (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 (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]);
+ }
+ }
+
+ 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];
+
+ /* Force a call to setup */
+
+ forceSetup = TRUE;
+
+ }
+
+ return(CV_SUCCESS);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Functions for interpolation
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * CVAfindIndex
+ *
+ * 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 t is beyond the leftmost limit, but close enough, indx=0.
+ *
+ * Returns CV_SUCCESS if successful and CV_GETY_BADT if unable to
+ * find indx (t is too far beyond limits).
+ */
+
+static int CVAfindIndex(CVodeMem cv_mem, realtype t,
+ long int *indx, booleantype *newpoint)
+{
+ CVadjMem ca_mem;
+ static long int ilast;
+ DtpntMem *dt_mem;
+ int sign;
+ booleantype to_left, to_right;
+
+ ca_mem = cv_mem->cv_adj_mem;
+ dt_mem = ca_mem->dt_mem;
+
+ *newpoint = FALSE;
+
+ /* Find the direction of integration */
+ sign = (tfinal - tinitial > ZERO) ? 1 : -1;
+
+ /* If this is the first time we use new data */
+ if (IMnewData) {
+ ilast = np-1;
+ *newpoint = TRUE;
+ IMnewData = FALSE;
+ }
+
+ /* Search for indx starting from ilast */
+ to_left = ( sign*(t - dt_mem[ilast-1]->t) < ZERO);
+ to_right = ( sign*(t - dt_mem[ilast]->t) > ZERO);
+
+ if ( to_left ) {
+ /* look for a new indx to the left */
+
+ *newpoint = TRUE;
+
+ *indx = ilast;
+ loop {
+ if ( *indx == 0 ) break;
+ if ( sign*(t - dt_mem[*indx-1]->t) <= ZERO ) (*indx)--;
+ else break;
+ }
+
+ if ( *indx == 0 )
+ ilast = 1;
+ else
+ ilast = *indx;
+
+ if ( *indx == 0 ) {
+ /* t is beyond leftmost limit. Is it too far? */
+ if ( ABS(t - dt_mem[0]->t) > FUZZ_FACTOR * uround ) {
+ return(CV_GETY_BADT);
+ }
+ }
+
+ } else if ( to_right ) {
+ /* look for a new indx to the right */
+
+ *newpoint = TRUE;
+
+ *indx = ilast;
+ loop {
+ if ( sign*(t - dt_mem[*indx]->t) > ZERO) (*indx)++;
+ else break;
+ }
+
+ ilast = *indx;
+
+
+ } else {
+ /* ilast is still OK */
+
+ *indx = ilast;
+
+ }
+
+ return(CV_SUCCESS);
+
+
+}
+
+/*
+ * CVodeGetAdjY
+ *
+ * This routine returns the interpolated forward solution at time t.
+ * The user must allocate space for y.
+ */
+
+int CVodeGetAdjY(void *cvode_mem, realtype t, N_Vector y)
+{
+ CVodeMem cv_mem;
+ CVadjMem ca_mem;
+ int flag;
+
+ if (cvode_mem == NULL) {
+ cvProcessError(NULL, CV_MEM_NULL, "CVODEA", "CVodeGetAdjY", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+ cv_mem = (CVodeMem) cvode_mem;
+
+ ca_mem = cv_mem->cv_adj_mem;
+
+ flag = IMget(cv_mem, t, y, NULL);
+
+ return(flag);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Functions specific to cubic Hermite interpolation
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * CVAhermiteMalloc
+ *
+ * This routine allocates memory for storing information at all
+ * intermediate points between two consecutive check points.
+ * This data is then used to interpolate the forward solution
+ * at any other time.
+ */
+
+static booleantype CVAhermiteMalloc(CVodeMem cv_mem)
+{
+ CVadjMem ca_mem;
+ DtpntMem *dt_mem;
+ HermiteDataMem content;
+ long int i, ii=0;
+ booleantype allocOK;
+
+ allocOK = TRUE;
+
+ ca_mem = cv_mem->cv_adj_mem;
+
+ /* Allocate space for the vectors ytmp and yStmp */
+
+ ytmp = N_VClone(tempv);
+ if (ytmp == NULL) {
+ return(FALSE);
+ }
+
+ if (IMstoreSensi) {
+ yStmp = N_VCloneVectorArray(Ns, tempv);
+ if (yStmp == NULL) {
+ N_VDestroy(ytmp);
+ return(FALSE);
+ }
+ }
+
+ /* Allocate space for the content field of the dt structures */
+
+ dt_mem = ca_mem->dt_mem;
+
+ for (i=0; i<=nsteps; i++) {
+
+ content = NULL;
+ content = (HermiteDataMem) malloc(sizeof(struct HermiteDataMemRec));
+ if (content == NULL) {
+ ii = i;
+ allocOK = FALSE;
+ break;
+ }
+
+ content->y = N_VClone(tempv);
+ if (content->y == NULL) {
+ free(content); content = NULL;
+ ii = i;
+ allocOK = FALSE;
+ break;
+ }
+
+ content->yd = N_VClone(tempv);
+ if (content->yd == NULL) {
+ N_VDestroy(content->y);
+ free(content); content = NULL;
+ ii = i;
+ allocOK = FALSE;
+ break;
+ }
+
+ if (IMstoreSensi) {
+
+ content->yS = N_VCloneVectorArray(Ns, tempv);
+ if (content->yS == NULL) {
+ N_VDestroy(content->y);
+ N_VDestroy(content->yd);
+ free(content); content = NULL;
+ ii = i;
+ allocOK = FALSE;
+ break;
+ }
+
+ content->ySd = N_VCloneVectorArray(Ns, tempv);
+ if (content->ySd == NULL) {
+ N_VDestroy(content->y);
+ N_VDestroy(content->yd);
+ N_VDestroyVectorArray(content->yS, Ns);
+ free(content); content = NULL;
+ ii = i;
+ allocOK = FALSE;
+ break;
+ }
+
+ }
+
+ dt_mem[i]->content = content;
+
+ }
+
+ /* If an error occurred, deallocate and return */
+
+ if (!allocOK) {
+
+ N_VDestroy(ytmp);
+
+ if (IMstoreSensi) {
+ N_VDestroyVectorArray(yStmp, 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);
+ }
+ free(dt_mem[i]->content); dt_mem[i]->content = NULL;
+ }
+
+ }
+
+ return(allocOK);
+}
+
+/*
+ * CVAhermiteFree
+ *
+ * This routine frees the memory allocated for data storage.
+ */
+
+static void CVAhermiteFree(CVodeMem cv_mem)
+{
+ CVadjMem ca_mem;
+ DtpntMem *dt_mem;
+ HermiteDataMem content;
+ long int i;
+
+ ca_mem = cv_mem->cv_adj_mem;
+
+ N_VDestroy(ytmp);
+
+ if (IMstoreSensi) {
+ N_VDestroyVectorArray(yStmp, Ns);
+ }
+
+ dt_mem = ca_mem->dt_mem;
+
+ for (i=0; i<=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);
+ }
+ free(dt_mem[i]->content); dt_mem[i]->content = NULL;
+ }
+}
+
+/*
+ * CVAhermiteStorePnt ( -> IMstore )
+ *
+ * This routine stores a new point (y,yd) in the structure d for use
+ * in the cubic Hermite interpolation.
+ * Note that the time is already stored.
+ */
+
+static int CVAhermiteStorePnt(CVodeMem cv_mem, DtpntMem d)
+{
+ CVadjMem ca_mem;
+ HermiteDataMem content;
+ int is, retval;
+
+ ca_mem = cv_mem->cv_adj_mem;
+
+ content = (HermiteDataMem) d->content;
+
+ /* Load solution */
+
+ N_VScale(ONE, zn[0], content->y);
+
+ if (IMstoreSensi) {
+ for (is=0; is<Ns; is++)
+ N_VScale(ONE, znS[0][is], content->yS[is]);
+ }
+
+ /* Load derivative */
+
+ if (nst == 0) {
+
+ retval = f(tn, content->y, content->yd, user_data);
+
+ if (IMstoreSensi) {
+ retval = cvSensRhsWrapper(cv_mem, 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);
+
+ if (IMstoreSensi) {
+ for (is=0; is<Ns; is++)
+ N_VScale(ONE/h, znS[1][is], content->ySd[is]);
+ }
+
+ }
+
+ return(0);
+}
+
+/*
+ * CVAhermiteGetY ( -> IMget )
+ *
+ * This routine uses cubic piece-wise Hermite interpolation for
+ * the forward solution vector.
+ * It is typically called by the wrapper routines before calling
+ * user provided routines (fB, djacB, bjacB, jtimesB, psolB) but
+ * can be directly called by the user through CVodeGetAdjY
+ */
+
+static int CVAhermiteGetY(CVodeMem cv_mem, realtype t,
+ N_Vector y, N_Vector *yS)
+{
+ CVadjMem ca_mem;
+ DtpntMem *dt_mem;
+ HermiteDataMem content0, content1;
+
+ realtype t0, t1, delta;
+ realtype factor1, factor2, factor3;
+
+ N_Vector y0, yd0, y1, yd1;
+ N_Vector *yS0, *ySd0, *yS1, *ySd1;
+
+ int flag, is, NS;
+ long int indx;
+ booleantype newpoint;
+
+
+ ca_mem = cv_mem->cv_adj_mem;
+ dt_mem = ca_mem->dt_mem;
+
+ /* Local value of Ns */
+
+ NS = IMinterpSensi ? Ns : 0;
+
+ /* Get the index in dt_mem */
+
+ flag = CVAfindIndex(cv_mem, t, &indx, &newpoint);
+ if (flag != CV_SUCCESS) return(flag);
+
+ /* If we are beyond the left limit but close enough,
+ then return y at the left limit. */
+
+ if (indx == 0) {
+ content0 = (HermiteDataMem) (dt_mem[0]->content);
+ N_VScale(ONE, content0->y, y);
+ for (is=0; is<NS; is++) N_VScale(ONE, content0->yS[is], yS[is]);
+ return(CV_SUCCESS);
+ }
+
+ /* Extract stuff from the appropriate data points */
+
+ t0 = dt_mem[indx-1]->t;
+ t1 = dt_mem[indx]->t;
+ delta = t1 - t0;
+
+ content0 = (HermiteDataMem) (dt_mem[indx-1]->content);
+ y0 = content0->y;
+ yd0 = content0->yd;
+ if (IMinterpSensi) {
+ yS0 = content0->yS;
+ ySd0 = content0->ySd;
+ }
+
+ if (newpoint) {
+
+ /* Recompute Y0 and Y1 */
+
+ content1 = (HermiteDataMem) (dt_mem[indx]->content);
+
+ 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]);
+
+
+ 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]);
+ }
+
+ }
+
+ /* Perform the actual interpolation. */
+
+ factor1 = t - t0;
+
+ factor2 = factor1/delta;
+ factor2 = factor2*factor2;
+
+ 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);
+
+ 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]);
+ }
+
+
+ return(CV_SUCCESS);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Functions specific to Polynomial interpolation
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * CVApolynomialMalloc
+ *
+ * This routine allocates memory for storing information at all
+ * intermediate points between two consecutive check points.
+ * This data is then used to interpolate the forward solution
+ * at any other time.
+ */
+
+static booleantype CVApolynomialMalloc(CVodeMem cv_mem)
+{
+ CVadjMem ca_mem;
+ DtpntMem *dt_mem;
+ PolynomialDataMem content;
+ long int i, ii=0;
+ booleantype allocOK;
+
+ allocOK = TRUE;
+
+ ca_mem = cv_mem->cv_adj_mem;
+
+ /* Allocate space for the vectors ytmp and yStmp */
+
+ ytmp = N_VClone(tempv);
+ if (ytmp == NULL) {
+ return(FALSE);
+ }
+
+ if (IMstoreSensi) {
+ yStmp = N_VCloneVectorArray(Ns, tempv);
+ if (yStmp == NULL) {
+ N_VDestroy(ytmp);
+ return(FALSE);
+ }
+ }
+
+ /* Allocate space for the content field of the dt structures */
+
+ dt_mem = ca_mem->dt_mem;
+
+ for (i=0; i<=nsteps; i++) {
+
+ content = NULL;
+ content = (PolynomialDataMem) malloc(sizeof(struct PolynomialDataMemRec));
+ if (content == NULL) {
+ ii = i;
+ allocOK = FALSE;
+ break;
+ }
+
+ content->y = N_VClone(tempv);
+ if (content->y == NULL) {
+ free(content); content = NULL;
+ ii = i;
+ allocOK = FALSE;
+ break;
+ }
+
+ if (IMstoreSensi) {
+
+ content->yS = N_VCloneVectorArray(Ns, tempv);
+ if (content->yS == NULL) {
+ N_VDestroy(content->y);
+ free(content); content = NULL;
+ ii = i;
+ allocOK = FALSE;
+ break;
+ }
+
+ }
+
+ dt_mem[i]->content = content;
+
+ }
+
+ /* If an error occurred, deallocate and return */
+
+ if (!allocOK) {
+
+ N_VDestroy(ytmp);
+
+ if (IMstoreSensi) {
+ N_VDestroyVectorArray(yStmp, Ns);
+ }
+
+ for (i=0; i<ii; i++) {
+ content = (PolynomialDataMem) (dt_mem[i]->content);
+ N_VDestroy(content->y);
+ if (IMstoreSensi) {
+ N_VDestroyVectorArray(content->yS, Ns);
+ }
+ free(dt_mem[i]->content); dt_mem[i]->content = NULL;
+ }
+
+ }
+
+ return(allocOK);
+
+}
+
+/*
+ * CVApolynomialFree
+ *
+ * This routine frees the memeory allocated for data storage.
+ */
+
+static void CVApolynomialFree(CVodeMem cv_mem)
+{
+ CVadjMem ca_mem;
+ DtpntMem *dt_mem;
+ PolynomialDataMem content;
+ long int i;
+
+ ca_mem = cv_mem->cv_adj_mem;
+
+ N_VDestroy(ytmp);
+
+ if (IMstoreSensi) {
+ N_VDestroyVectorArray(yStmp, Ns);
+ }
+
+ dt_mem = ca_mem->dt_mem;
+
+ for (i=0; i<=nsteps; i++) {
+ content = (PolynomialDataMem) (dt_mem[i]->content);
+ N_VDestroy(content->y);
+ if (IMstoreSensi) {
+ N_VDestroyVectorArray(content->yS, Ns);
+ }
+ free(dt_mem[i]->content); dt_mem[i]->content = NULL;
+ }
+}
+
+/*
+ * CVApolynomialStorePnt ( -> IMstore )
+ *
+ * This routine stores a new point y in the structure d for use
+ * in the Polynomial interpolation.
+ * Note that the time is already stored.
+ */
+
+static int CVApolynomialStorePnt(CVodeMem cv_mem, DtpntMem d)
+{
+ CVadjMem ca_mem;
+ PolynomialDataMem content;
+ int is;
+
+ ca_mem = cv_mem->cv_adj_mem;
+
+ content = (PolynomialDataMem) d->content;
+
+ N_VScale(ONE, zn[0], content->y);
+
+ if (IMstoreSensi) {
+ for (is=0; is<Ns; is++)
+ N_VScale(ONE, znS[0][is], content->yS[is]);
+ }
+
+ content->order = qu;
+
+ return(0);
+}
+
+/*
+ * CVApolynomialGetY ( -> IMget )
+ *
+ * This routine uses polynomial interpolation for the forward solution vector.
+ * It is typically called by the wrapper routines before calling
+ * user provided routines (fB, djacB, bjacB, jtimesB, psolB)) but
+ * can be directly called by the user through CVodeGetAdjY.
+ */
+
+static int CVApolynomialGetY(CVodeMem cv_mem, realtype t,
+ N_Vector y, N_Vector *yS)
+{
+ CVadjMem ca_mem;
+ DtpntMem *dt_mem;
+ PolynomialDataMem content;
+
+ int flag, dir, order, i, j, is, NS;
+ long int indx, base;
+ booleantype newpoint;
+ realtype dt, factor;
+
+ ca_mem = cv_mem->cv_adj_mem;
+ dt_mem = ca_mem->dt_mem;
+
+ /* Local value of Ns */
+
+ NS = IMinterpSensi ? Ns : 0;
+
+ /* Get the index in dt_mem */
+
+ flag = CVAfindIndex(cv_mem, t, &indx, &newpoint);
+ if (flag != CV_SUCCESS) return(flag);
+
+ /* If we are beyond the left limit but close enough,
+ then return y at the left limit. */
+
+ if (indx == 0) {
+ content = (PolynomialDataMem) (dt_mem[0]->content);
+ N_VScale(ONE, content->y, y);
+ for (is=0; is<NS; is++) N_VScale(ONE, content->yS[is], yS[is]);
+ return(CV_SUCCESS);
+ }
+
+ /* Scaling factor */
+
+ dt = ABS(dt_mem[indx]->t - dt_mem[indx-1]->t);
+
+ /* Find the direction of the forward integration */
+
+ dir = (tfinal - 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 */
+
+ if (dir == 1) {
+ base = indx;
+ content = (PolynomialDataMem) (dt_mem[base]->content);
+ order = content->order;
+ if(indx < order) base += order-indx;
+ } else {
+ base = indx-1;
+ content = (PolynomialDataMem) (dt_mem[base]->content);
+ order = content->order;
+ if (np-indx > order) base -= indx+order-np;
+ }
+
+ /* Recompute Y (divided differences for Newton polynomial) if needed */
+
+ if (newpoint) {
+
+ /* Store 0-th order DD */
+ if (dir == 1) {
+ for(j=0;j<=order;j++) {
+ 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]);
+ }
+ } else {
+ for(j=0;j<=order;j++) {
+ 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]);
+ }
+ }
+
+ /* 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]);
+ }
+ }
+ }
+
+ /* 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]);
+ 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]);
+ }
+
+ return(CV_SUCCESS);
+
+}
+
+/*
+ * =================================================================
+ * WRAPPERS FOR ADJOINT SYSTEM
+ * =================================================================
+ */
+/*
+ * CVArhs
+ *
+ * This routine interfaces to the CVRhsFnB (or CVRhsFnBS) routine
+ * provided by the user.
+ */
+
+static int CVArhs(realtype t, N_Vector yB,
+ N_Vector yBdot, void *cvode_mem)
+{
+ CVodeMem cv_mem;
+ CVadjMem ca_mem;
+ CVodeBMem cvB_mem;
+ int flag, retval;
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ ca_mem = cv_mem->cv_adj_mem;
+
+ cvB_mem = ca_mem->ca_bckpbCrt;
+
+ /* Get 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, "CVODEA", "CVArhs", MSGCV_BAD_TINTERP, t);
+ return(-1);
+ }
+
+ /* 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);
+ else
+ retval = (cvB_mem->cv_f)(t, ytmp, yB, yBdot, cvB_mem->cv_user_data);
+
+ return(retval);
+}
+
+/*
+ * CVArhsQ
+ *
+ * This routine interfaces to the CVQuadRhsFnB (or CVQuadRhsFnBS) routine
+ * provided by the user.
+ */
+
+static int CVArhsQ(realtype t, N_Vector yB,
+ N_Vector qBdot, void *cvode_mem)
+{
+ CVodeMem cv_mem;
+ CVadjMem ca_mem;
+ CVodeBMem cvB_mem;
+ int flag, retval;
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ ca_mem = cv_mem->cv_adj_mem;
+
+ cvB_mem = ca_mem->ca_bckpbCrt;
+
+ /* Get forward solution from interpolation */
+
+ if (IMinterpSensi)
+ flag = IMget(cv_mem, t, ytmp, yStmp);
+ else
+ flag = IMget(cv_mem, t, 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);
+ else
+ retval = (cvB_mem->cv_fQ)(t, ytmp, yB, qBdot, cvB_mem->cv_user_data);
+
+ return(retval);
+}
diff --git a/src/cvodes/cvodea_io.c b/src/cvodes/cvodea_io.c
new file mode 100644
index 0000000..e4bc16c
--- /dev/null
+++ b/src/cvodes/cvodea_io.c
@@ -0,0 +1,716 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.10 $
+ * $Date: 2010/12/01 22:33:22 $
+ * -----------------------------------------------------------------
+ * Programmer: Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2006, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * This is the implementation file for the optional input and output
+ * functions for the adjoint module in the CVODES solver.
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * =================================================================
+ * IMPORTED HEADER FILES
+ * =================================================================
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "cvodes_impl.h"
+#include <sundials/sundials_types.h>
+
+/*
+ * =================================================================
+ * CVODEA PRIVATE CONSTANTS
+ * =================================================================
+ */
+
+#define ONE RCONST(1.0)
+
+/*
+ * =================================================================
+ * EXPORTED FUNCTIONS IMPLEMENTATION
+ * =================================================================
+ */
+
+/*
+ * -----------------------------------------------------------------
+ * 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
+ * -----------------------------------------------------------------
+ */
+
+int CVodeSetAdjNoSensi(void *cvode_mem)
+{
+ CVodeMem cv_mem;
+ CVadjMem ca_mem;
+
+ /* Check if cvode_mem exists */
+ if (cvode_mem == NULL) {
+ cvProcessError(NULL, CV_MEM_NULL, "CVODEA", "CVodeSetAdjNoSensi", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+ cv_mem = (CVodeMem) cvode_mem;
+
+ /* Was ASA initialized? */
+ if (cv_mem->cv_adjMallocDone == FALSE) {
+ 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;
+
+ return(CV_SUCCESS);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Optional input functions for backward integration
+ * -----------------------------------------------------------------
+ */
+
+int CVodeSetIterTypeB(void *cvode_mem, int which, int iterB)
+{
+ 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, CV_MEM_NULL, "CVODEA", "CVodeSetIterTypeB", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+ cv_mem = (CVodeMem) cvode_mem;
+
+ /* Was ASA initialized? */
+ if (cv_mem->cv_adjMallocDone == FALSE) {
+ 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 ) {
+ cvProcessError(cv_mem, CV_ILL_INPUT, "CVODEA", "CVodeSetIterTypeB", MSGCV_BAD_WHICH);
+ return(CV_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 = CVodeSetIterType(cvodeB_mem, iterB);
+
+ return(flag);
+}
+
+int CVodeSetUserDataB(void *cvode_mem, int which, void *user_dataB)
+{
+ CVodeMem cv_mem;
+ CVadjMem ca_mem;
+ CVodeBMem cvB_mem;
+
+ /* Check if cvode_mem exists */
+ if (cvode_mem == NULL) {
+ cvProcessError(NULL, CV_MEM_NULL, "CVODEA", "CVodeSetUserDataB", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+ cv_mem = (CVodeMem) cvode_mem;
+
+ /* Was ASA initialized? */
+ if (cv_mem->cv_adjMallocDone == FALSE) {
+ 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 ) {
+ cvProcessError(cv_mem, CV_ILL_INPUT, "CVODEA", "CVodeSetUserDataB", MSGCV_BAD_WHICH);
+ return(CV_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;
+ }
+
+ cvB_mem->cv_user_data = user_dataB;
+
+ return(CV_SUCCESS);
+}
+
+int CVodeSetMaxOrdB(void *cvode_mem, int which, int maxordB)
+{
+ 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, CV_MEM_NULL, "CVODEA", "CVodeSetMaxOrdB", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+ cv_mem = (CVodeMem) cvode_mem;
+
+ /* Was ASA initialized? */
+ if (cv_mem->cv_adjMallocDone == FALSE) {
+ 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 ) {
+ cvProcessError(cv_mem, CV_ILL_INPUT, "CVODEA", "CVodeSetMaxOrdB", MSGCV_BAD_WHICH);
+ return(CV_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 = CVodeSetMaxOrd(cvodeB_mem, maxordB);
+
+ return(flag);
+}
+
+
+int CVodeSetMaxNumStepsB(void *cvode_mem, int which, long int mxstepsB)
+{
+ 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, CV_MEM_NULL, "CVODEA", "CVodeSetMaxNumStepsB", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+ cv_mem = (CVodeMem) cvode_mem;
+
+ /* Was ASA initialized? */
+ if (cv_mem->cv_adjMallocDone == FALSE) {
+ 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 ) {
+ cvProcessError(cv_mem, CV_ILL_INPUT, "CVODEA", "CVodeSetMaxNumStepsB", MSGCV_BAD_WHICH);
+ return(CV_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 = CVodeSetMaxNumSteps(cvodeB_mem, mxstepsB);
+
+ return(flag);
+}
+
+int CVodeSetStabLimDetB(void *cvode_mem, int which, booleantype stldetB)
+{
+ 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, CV_MEM_NULL, "CVODEA", "CVodeSetStabLimDetB", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+ cv_mem = (CVodeMem) cvode_mem;
+
+ /* Was ASA initialized? */
+ if (cv_mem->cv_adjMallocDone == FALSE) {
+ 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 ) {
+ cvProcessError(cv_mem, CV_ILL_INPUT, "CVODEA", "CVodeSetStabLimDetB", MSGCV_BAD_WHICH);
+ return(CV_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 = CVodeSetStabLimDet(cvodeB_mem, stldetB);
+
+ return(flag);
+}
+
+int CVodeSetInitStepB(void *cvode_mem, int which, realtype hinB)
+{
+ 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, CV_MEM_NULL, "CVODEA", "CVodeSetInitStepB", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+ cv_mem = (CVodeMem) cvode_mem;
+
+ /* Was ASA initialized? */
+ if (cv_mem->cv_adjMallocDone == FALSE) {
+ 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 ) {
+ cvProcessError(cv_mem, CV_ILL_INPUT, "CVODEA", "CVodeSetInitStepB", MSGCV_BAD_WHICH);
+ return(CV_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 = CVodeSetInitStep(cvodeB_mem, hinB);
+
+ return(flag);
+}
+
+int CVodeSetMinStepB(void *cvode_mem, int which, realtype hminB)
+{
+ 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, CV_MEM_NULL, "CVODEA", "CVodeSetMinStepB", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+ cv_mem = (CVodeMem) cvode_mem;
+
+ /* Was ASA initialized? */
+ if (cv_mem->cv_adjMallocDone == FALSE) {
+ 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 ) {
+ cvProcessError(cv_mem, CV_ILL_INPUT, "CVODEA", "CVodeSetMinStepB", MSGCV_BAD_WHICH);
+ return(CV_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 = CVodeSetMinStep(cvodeB_mem, hminB);
+
+ return(flag);
+}
+
+int CVodeSetMaxStepB(void *cvode_mem, int which, realtype hmaxB)
+{
+ 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, CV_MEM_NULL, "CVODEA", "CVodeSetMaxStepB", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+ cv_mem = (CVodeMem) cvode_mem;
+
+ /* Was ASA initialized? */
+ if (cv_mem->cv_adjMallocDone == FALSE) {
+ 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 ) {
+ cvProcessError(cv_mem, CV_ILL_INPUT, "CVODEA", "CVodeSetMaxStepB", MSGCV_BAD_WHICH);
+ return(CV_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 = CVodeSetMaxStep(cvodeB_mem, hmaxB);
+
+ return(flag);
+}
+
+/*
+ * CVodeSetQuad*B
+ *
+ * Wrappers for the backward phase around the corresponding
+ * CVODES quadrature optional input functions
+ */
+
+int CVodeSetQuadErrConB(void *cvode_mem, int which, booleantype errconQB)
+{
+ 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, CV_MEM_NULL, "CVODEA", "CVodeSetQuadErrConB", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+ cv_mem = (CVodeMem) cvode_mem;
+
+ /* Was ASA initialized? */
+ if (cv_mem->cv_adjMallocDone == FALSE) {
+ 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 ) {
+ cvProcessError(cv_mem, CV_ILL_INPUT, "CVODEA", "CVodeSetQuadErrConB", MSGCV_BAD_WHICH);
+ return(CV_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 = CVodeSetQuadErrCon(cvodeB_mem, errconQB);
+
+ return(flag);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Optional output functions for backward integration
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * CVodeGetAdjCVodeBmem
+ *
+ * This function returns a (void *) pointer to the CVODES
+ * memory allocated for the backward problem. This pointer can
+ * then be used to call any of the CVodeGet* CVODES routines to
+ * extract optional output for the backward integration phase.
+ */
+
+void *CVodeGetAdjCVodeBmem(void *cvode_mem, int which)
+{
+ CVodeMem cv_mem;
+ CVadjMem ca_mem;
+ CVodeBMem cvB_mem;
+ void *cvodeB_mem;
+
+ /* Check if cvode_mem exists */
+ if (cvode_mem == NULL) {
+ cvProcessError(NULL, 0, "CVODEA", "CVodeGetAdjCVodeBmem", MSGCV_NO_MEM);
+ return(NULL);
+ }
+ cv_mem = (CVodeMem) cvode_mem;
+
+ /* Was ASA initialized? */
+ if (cv_mem->cv_adjMallocDone == FALSE) {
+ cvProcessError(cv_mem, 0, "CVODEA", "CVodeGetAdjCVodeBmem", MSGCV_NO_ADJ);
+ return(NULL);
+ }
+ ca_mem = cv_mem->cv_adj_mem;
+
+ /* Check which */
+ if ( which >= nbckpbs ) {
+ cvProcessError(cv_mem, 0, "CVODEA", "CVodeGetAdjCVodeBmem", MSGCV_BAD_WHICH);
+ return(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;
+ }
+
+ cvodeB_mem = (void *) (cvB_mem->cv_mem);
+
+ return(cvodeB_mem);
+}
+
+/*
+ * CVodeGetAdjCheckPointsInfo
+ *
+ * This routine loads an array of nckpnts structures of type CVadjCheckPointRec.
+ * The user must allocate space for ckpnt.
+ */
+
+int CVodeGetAdjCheckPointsInfo(void *cvode_mem, CVadjCheckPointRec *ckpnt)
+{
+ CVodeMem cv_mem;
+ CVadjMem ca_mem;
+ CkpntMem ck_mem;
+ int i;
+
+ /* Check if cvode_mem exists */
+ if (cvode_mem == NULL) {
+ cvProcessError(NULL, CV_MEM_NULL, "CVODEA", "CVodeGetAdjCheckPointsInfo", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+ cv_mem = (CVodeMem) cvode_mem;
+
+ /* Was ASA initialized? */
+ if (cv_mem->cv_adjMallocDone == FALSE) {
+ cvProcessError(cv_mem, CV_NO_ADJ, "CVODEA", "CVodeGetAdjCheckPointsInfo", MSGCV_NO_ADJ);
+ return(CV_NO_ADJ);
+ }
+ ca_mem = cv_mem->cv_adj_mem;
+
+ ck_mem = ca_mem->ck_mem;
+
+ i = 0;
+
+ 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_;
+ i++;
+
+ }
+
+ return(CV_SUCCESS);
+
+}
+
+/*
+ * CVodeGetAdjDataPointHermite
+ *
+ * This routine returns the solution stored in the data structure
+ * at the 'which' data point. Cubic Hermite interpolation.
+ */
+
+int CVodeGetAdjDataPointHermite(void *cvode_mem, int which,
+ realtype *t, N_Vector y, N_Vector yd)
+{
+ CVodeMem cv_mem;
+ CVadjMem ca_mem;
+ DtpntMem *dt_mem;
+ HermiteDataMem content;
+
+ /* Check if cvode_mem exists */
+ if (cvode_mem == NULL) {
+ cvProcessError(NULL, CV_MEM_NULL, "CVODEA", "CVodeGetAdjDataPointHermite", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+ cv_mem = (CVodeMem) cvode_mem;
+
+ /* Was ASA initialized? */
+ if (cv_mem->cv_adjMallocDone == FALSE) {
+ cvProcessError(cv_mem, CV_NO_ADJ, "CVODEA", "CVodeGetAdjDataPointHermite", MSGCV_NO_ADJ);
+ return(CV_NO_ADJ);
+ }
+ ca_mem = cv_mem->cv_adj_mem;
+
+ dt_mem = ca_mem->dt_mem;
+
+ if (IMtype != CV_HERMITE) {
+ cvProcessError(cv_mem, CV_ILL_INPUT, "CVODEA", "CVadjGetDataPointHermite", MSGCV_WRONG_INTERP);
+ return(CV_ILL_INPUT);
+ }
+
+ *t = dt_mem[which]->t;
+
+ content = (HermiteDataMem) (dt_mem[which]->content);
+
+ if (y != NULL)
+ N_VScale(ONE, content->y, y);
+
+ if (yd != NULL)
+ N_VScale(ONE, content->yd, yd);
+
+ return(CV_SUCCESS);
+}
+
+/*
+ * CVodeGetAdjDataPointPolynomial
+ *
+ * This routine returns the solution stored in the data structure
+ * at the 'which' data point. Polynomial interpolation.
+ */
+
+int CVodeGetAdjDataPointPolynomial(void *cvode_mem, int which,
+ realtype *t, int *order, N_Vector y)
+{
+ CVodeMem cv_mem;
+ CVadjMem ca_mem;
+ DtpntMem *dt_mem;
+ PolynomialDataMem content;
+
+ /* Check if cvode_mem exists */
+ if (cvode_mem == NULL) {
+ cvProcessError(NULL, CV_MEM_NULL, "CVODEA", "CVodeGetAdjDataPointPolynomial", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+ cv_mem = (CVodeMem) cvode_mem;
+
+ /* Was ASA initialized? */
+ if (cv_mem->cv_adjMallocDone == FALSE) {
+ cvProcessError(cv_mem, CV_NO_ADJ, "CVODEA", "CVodeGetAdjDataPointPolynomial", MSGCV_NO_ADJ);
+ return(CV_NO_ADJ);
+ }
+ ca_mem = cv_mem->cv_adj_mem;
+
+ dt_mem = ca_mem->dt_mem;
+
+ if (IMtype != CV_POLYNOMIAL) {
+ cvProcessError(cv_mem, CV_ILL_INPUT, "CVODEA", "CVadjGetDataPointPolynomial", MSGCV_WRONG_INTERP);
+ return(CV_ILL_INPUT);
+ }
+
+ *t = dt_mem[which]->t;
+
+ content = (PolynomialDataMem) (dt_mem[which]->content);
+
+ if (y != NULL)
+ N_VScale(ONE, content->y, y);
+
+ *order = content->order;
+
+ return(CV_SUCCESS);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * UNDOCUMENTED development user-callable functions
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * CVodeGetAdjCurrentCheckPoint
+ *
+ * Returns the address of the 'active' check point.
+ */
+
+int CVodeGetAdjCurrentCheckPoint(void *cvode_mem, void **addr)
+{
+ CVodeMem cv_mem;
+ CVadjMem ca_mem;
+
+ /* Check if cvode_mem exists */
+ if (cvode_mem == NULL) {
+ cvProcessError(NULL, CV_MEM_NULL, "CVODEA", "CVodeGetAdjCurrentCheckPoint", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+ cv_mem = (CVodeMem) cvode_mem;
+
+ /* Was ASA initialized? */
+ if (cv_mem->cv_adjMallocDone == FALSE) {
+ 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;
+
+ return(CV_SUCCESS);
+}
diff --git a/src/cvodes/cvodes.c b/src/cvodes/cvodes.c
new file mode 100644
index 0000000..df7ab91
--- /dev/null
+++ b/src/cvodes/cvodes.c
@@ -0,0 +1,9011 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.34 $
+ * $Date: 2012/03/06 21:58:49 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Alan C. Hindmarsh and Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2006, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * This is the implementation file for the main CVODES integrator
+ * with sensitivity analysis capabilities.
+ * -----------------------------------------------------------------
+ *
+ * EXPORTED FUNCTIONS
+ * ------------------
+ *
+ * Creation, allocation and re-initialization functions
+ *
+ * CVodeCreate
+ *
+ * CVodeInit
+ * CVodeReInit
+ * CVodeSStolerances
+ * CVodeSVtolerances
+ * CVodeWFtolerances
+ *
+ * CVodeQuadInit
+ * CVodeQuadReInit
+ * CVodeQuadSStolerances
+ * CVodeQuadSVtolerances
+ *
+ * CVodeSensInit
+ * CVodeSensInit1
+ * CVodeSensReInit
+ * CVodeSensSStolerances
+ * CVodeSensSVtolerances
+ * CVodeSensEEtolerances
+ *
+ * CVodeQuadSensInit
+ * CVodeQuadSensReInit
+ *
+ * CVodeSensToggleOff
+ *
+ * CVodeRootInit
+ *
+ * Main solver function
+ * CVode
+ *
+ * Interpolated output and extraction functions
+ * CVodeGetDky
+ * CVodeGetQuad
+ * CVodeGetQuadDky
+ * CVodeGetSens
+ * CVodeGetSens1
+ * CVodeGetSensDky
+ * CVodeGetSensDky1
+ * CVodeGetQuadSens
+ * CVodeGetQuadSens1
+ * CVodeGetQuadSensDky
+ * CVodeGetQuadSensDky1
+ *
+ * Deallocation functions
+ * CVodeFree
+ * CVodeQuadFree
+ * CVodeSensFree
+ * CVodeQuadSensFree
+ *
+ * PRIVATE FUNCTIONS
+ * -----------------
+ *
+ * cvCheckNvector
+ *
+ * Memory allocation/deallocation
+ * cvAllocVectors
+ * cvFreeVectors
+ * cvQuadAllocVectors
+ * cvQuadFreeVectors
+ * cvSensAllocVectors
+ * cvSensFreeVectors
+ * cvQuadSensAllocVectors
+ * cvQuadSensFreeVectors
+ *
+ * Initial stepsize calculation
+ * cvHin
+ * cvUpperBoundH0
+ * cvYddNorm
+ *
+ * Initial setup
+ * cvInitialSetup
+ * cvEwtSet
+ * cvEwtSetSS
+ * cvEwtSetSV
+ * cvQuadEwtSet
+ * cvQuadEwtSetSS
+ * cvQuadEwtSetSV
+ * cvSensEwtSet
+ * cvSensEwtSetEE
+ * cvSensEwtSetSS
+ * cvSensEwtSetSV
+ * cvQuadSensEwtSet
+ * cvQuadSensEwtSetEE
+ * cvQuadSensEwtSetSS
+ * cvQuadSensEwtSetSV
+ *
+ * Main cvStep function
+ * cvStep
+ *
+ * Functions called at beginning of step
+ * cvAdjustParams
+ * cvAdjustOrder
+ * cvAdjustAdams
+ * cvAdjustBDF
+ * cvIncreaseBDF
+ * cvDecreaseBDF
+ * cvRescale
+ * cvPredict
+ * cvSet
+ * cvSetAdams
+ * cvAdamsStart
+ * cvAdamsFinish
+ * cvAltSum
+ * cvSetBDF
+ * cvSetTqBDF
+ *
+ * Nonlinear solver functions
+ * cvNls
+ * cvNlsFunctional
+ * cvNlsNewton
+ * cvNewtonIteration
+ * cvQuadNls
+ * cvStgrNls
+ * cvStgrNlsFunctional
+ * cvStgrNlsNewton
+ * cvStgrNewtonIteration
+ * cvStgr1Nls
+ * cvStgr1NlsFunctional
+ * cvStgr1NlsNewton
+ * cvStgr1NewtonIteration
+ * cvQuadSensNls
+ * cvHandleNFlag
+ * cvRestore
+ *
+ * Error Test
+ * cvDoErrorTest
+ *
+ * Functions called after a successful step
+ * cvCompleteStep
+ * cvPrepareNextStep
+ * cvSetEta
+ * cvComputeEtaqm1
+ * cvComputeEtaqp1
+ * cvChooseEta
+ *
+ * Function to handle failures
+ * cvHandleFailure
+ *
+ * Functions for BDF Stability Limit Detection
+ * cvBDFStab
+ * cvSLdet
+ *
+ * Functions for rootfinding
+ * cvRcheck1
+ * cvRcheck2
+ * cvRcheck3
+ * cvRootFind
+ *
+ * Functions for combined norms
+ * cvQuadUpdateNorm
+ * cvSensNorm
+ * cvSensUpdateNorm
+ * cvQuadSensNorm
+ * cvQuadSensUpdateNorm
+ *
+ * Wrappers for sensitivity RHS
+ * cvSensRhsWrapper
+ * cvSensRhs1Wrapper
+ *
+ * Internal DQ approximations for sensitivity RHS
+ * cvSensRhsInternalDQ
+ * cvSensRhs1InternalDQ
+ * cvQuadSensRhsDQ
+ *
+ * Error message handling functions
+ * cvProcessError
+ * cvErrHandler
+ *
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * =================================================================
+ * IMPORTED HEADER FILES
+ * =================================================================
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+
+#include "cvodes_impl.h"
+#include <sundials/sundials_math.h>
+#include <sundials/sundials_types.h>
+
+/*
+ * =================================================================
+ * MACRO DEFINITIONS
+ * =================================================================
+ */
+
+/* Macro: loop */
+#define loop for(;;)
+
+/*
+ * =================================================================
+ * CVODES PRIVATE CONSTANTS
+ * =================================================================
+ */
+
+#define ZERO RCONST(0.0)
+#define TINY RCONST(1.0e-10)
+#define TENTH RCONST(0.1)
+#define POINT2 RCONST(0.2)
+#define FOURTH RCONST(0.25)
+#define HALF RCONST(0.5)
+#define ONE RCONST(1.0)
+#define TWO RCONST(2.0)
+#define THREE RCONST(3.0)
+#define FOUR RCONST(4.0)
+#define FIVE RCONST(5.0)
+#define TWELVE RCONST(12.0)
+#define HUN RCONST(100.0)
+
+/*
+ * =================================================================
+ * CVODES ROUTINE-SPECIFIC CONSTANTS
+ * =================================================================
+ */
+
+/*
+ * Control constants for lower-level functions used by cvStep
+ * ----------------------------------------------------------
+ *
+ * cvHin return values:
+ * CV_SUCCESS,
+ * CV_RHSFUNC_FAIL, CV_RPTD_RHSFUNC_ERR,
+ * CV_QRHSFUNC_FAIL, CV_RPTD_QRHSFUNC_ERR,
+ * CV_SRHSFUNC_FAIL, CV_RPTD_SRHSFUNC_ERR,
+ * CV_TOO_CLOSE
+ *
+ * cvStep control constants:
+ * DO_ERROR_TEST
+ * PREDICT_AGAIN
+ *
+ * cvStep return values:
+ * CV_SUCCESS,
+ * CV_CONV_FAILURE, CV_ERR_FAILURE,
+ * CV_LSETUP_FAIL, CV_LSOLVE_FAIL,
+ * CV_RTFUNC_FAIL,
+ * CV_RHSFUNC_FAIL, CV_QRHSFUNC_FAIL, CV_SRHSFUNC_FAIL, CV_QSRHSFUNC_FAIL,
+ * CV_FIRST_RHSFUNC_ERR, CV_FIRST_QRHSFUNC_ERR, CV_FIRST_SRHSFUNC_ERR, CV_FIRST_QSRHSFUNC_ERR,
+ * CV_UNREC_RHSFUNC_ERR, CV_UNREC_QRHSFUNC_ERR, CV_UNREC_SRHSFUNC_ERR, CV_UNREC_QSRHSFUNC_ERR,
+ * CV_REPTD_RHSFUNC_ERR, CV_REPTD_QRHSFUNC_ERR, CV_REPTD_SRHSFUNC_ERR, CV_REPTD_QSRHSFUNC_ERR,
+ *
+ * cvNls input nflag values:
+ * FIRST_CALL
+ * PREV_CONV_FAIL
+ * PREV_ERR_FAIL
+ *
+ * cvNls return values:
+ * CV_SUCCESS,
+ * CV_LSETUP_FAIL, CV_LSOLVE_FAIL,
+ * CV_RHSFUNC_FAIL, CV_SRHSFUNC_FAIL,
+ * CONV_FAIL,
+ * RHSFUNC_RECVR, SRHSFUNC_RECVR
+ *
+ * cvNewtonIteration return values:
+ * CV_SUCCESS,
+ * CV_LSOLVE_FAIL,
+ * CV_RHSFUNC_FAIL, CV_SRHSFUNC_FAIL,
+ * CONV_FAIL, TRY_AGAIN
+ * RHSFUNC_RECVR, SRHSFUNC_RECVR
+ *
+ */
+
+#define DO_ERROR_TEST +2
+#define PREDICT_AGAIN +3
+
+#define CONV_FAIL +4
+#define TRY_AGAIN +5
+
+#define FIRST_CALL +6
+#define PREV_CONV_FAIL +7
+#define PREV_ERR_FAIL +8
+
+#define RHSFUNC_RECVR +9
+
+#define QRHSFUNC_RECVR +11
+#define SRHSFUNC_RECVR +12
+#define QSRHSFUNC_RECVR +13
+
+/*
+ * Control constants for lower-level rootfinding functions
+ * -------------------------------------------------------
+ *
+ * cvRcheck1 return values:
+ * CV_SUCCESS,
+ * CV_RTFUNC_FAIL,
+ * cvRcheck2 return values:
+ * CV_SUCCESS,
+ * CV_RTFUNC_FAIL,
+ * CLOSERT,
+ * RTFOUND
+ * cvRcheck3 return values:
+ * CV_SUCCESS,
+ * CV_RTFUNC_FAIL,
+ * RTFOUND
+ * cvRootFind return values:
+ * CV_SUCCESS,
+ * CV_RTFUNC_FAIL,
+ * RTFOUND
+ */
+
+#define RTFOUND +1
+#define CLOSERT +3
+
+/*
+ * Control constants for sensitivity DQ
+ * ------------------------------------
+ */
+
+#define CENTERED1 +1
+#define CENTERED2 +2
+#define FORWARD1 +3
+#define FORWARD2 +4
+
+/*
+ * Control constants for type of sensitivity RHS
+ * ---------------------------------------------
+ */
+
+#define CV_ONESENS 1
+#define CV_ALLSENS 2
+
+/*
+ * Control constants for tolerances
+ * --------------------------------
+ */
+
+#define CV_NN 0
+#define CV_SS 1
+#define CV_SV 2
+#define CV_WF 3
+#define CV_EE 4
+
+/*
+ * Algorithmic constants
+ * ---------------------
+ *
+ * CVodeGetDky and cvStep
+ *
+ * FUZZ_FACTOR fuzz factor used to estimate infinitesimal time intervals
+ *
+ * cvHin
+ *
+ * HLB_FACTOR factor for upper bound on initial step size
+ * HUB_FACTOR factor for lower bound on initial step size
+ * H_BIAS bias factor in selection of intial step size
+ * MAX_ITERS maximum attempts to compute the initial step size
+ *
+ * CVodeCreate
+ *
+ * CORTES constant in nonlinear iteration convergence test
+ *
+ * cvStep
+ *
+ * THRESH if eta < THRESH reject a change in step size or order
+ * ETAMX1 -+
+ * ETAMX2 |
+ * ETAMX3 |-> bounds for eta (step size change)
+ * ETAMXF |
+ * ETAMIN |
+ * ETACF -+
+ * ADDON safety factor in computing eta
+ * BIAS1 -+
+ * BIAS2 |-> bias factors in eta selection
+ * BIAS3 -+
+ * ONEPSM (1+epsilon) used in testing if the step size is below its bound
+ *
+ * SMALL_NST nst > SMALL_NST => use ETAMX3
+ * MXNCF max no. of convergence failures during one step try
+ * MXNEF max no. of error test failures during one step try
+ * MXNEF1 max no. of error test failures before forcing a reduction of order
+ * SMALL_NEF if an error failure occurs and SMALL_NEF <= nef <= MXNEF1, then
+ * reset eta = MIN(eta, ETAMXF)
+ * LONG_WAIT number of steps to wait before considering an order change when
+ * q==1 and MXNEF1 error test failures have occurred
+ *
+ * cvNls
+ *
+ * NLS_MAXCOR maximum no. of corrector iterations for the nonlinear solver
+ * CRDOWN constant used in the estimation of the convergence rate (crate)
+ * of the iterates for the nonlinear equation
+ * DGMAX iter == CV_NEWTON, |gamma/gammap-1| > DGMAX => call lsetup
+ * RDIV declare divergence if ratio del/delp > RDIV
+ * MSBP max no. of steps between lsetup calls
+ *
+ */
+
+
+#define FUZZ_FACTOR RCONST(100.0)
+
+#define HLB_FACTOR RCONST(100.0)
+#define HUB_FACTOR RCONST(0.1)
+#define H_BIAS HALF
+#define MAX_ITERS 4
+
+#define CORTES RCONST(0.1)
+
+#define THRESH RCONST(1.5)
+#define ETAMX1 RCONST(10000.0)
+#define ETAMX2 RCONST(10.0)
+#define ETAMX3 RCONST(10.0)
+#define ETAMXF RCONST(0.2)
+#define ETAMIN RCONST(0.1)
+#define ETACF RCONST(0.25)
+#define ADDON RCONST(0.000001)
+#define BIAS1 RCONST(6.0)
+#define BIAS2 RCONST(6.0)
+#define BIAS3 RCONST(10.0)
+#define ONEPSM RCONST(1.000001)
+
+#define SMALL_NST 10
+#define MXNCF 10
+#define MXNEF 7
+#define MXNEF1 3
+#define SMALL_NEF 2
+#define LONG_WAIT 10
+
+#define NLS_MAXCOR 3
+#define CRDOWN RCONST(0.3)
+#define DGMAX RCONST(0.3)
+
+#define RDIV TWO
+#define MSBP 20
+
+/*
+ * =================================================================
+ * PRIVATE FUNCTION PROTOTYPES
+ * =================================================================
+ */
+
+static booleantype cvCheckNvector(N_Vector tmpl);
+
+/* Memory allocation/deallocation */
+
+static booleantype cvAllocVectors(CVodeMem cv_mem, N_Vector tmpl);
+static void cvFreeVectors(CVodeMem cv_mem);
+
+static booleantype cvQuadAllocVectors(CVodeMem cv_mem, N_Vector tmpl);
+static void cvQuadFreeVectors(CVodeMem cv_mem);
+
+static booleantype cvSensAllocVectors(CVodeMem cv_mem, N_Vector tmpl);
+static void cvSensFreeVectors(CVodeMem cv_mem);
+
+static booleantype cvQuadSensAllocVectors(CVodeMem cv_mem, N_Vector tmpl);
+static void cvQuadSensFreeVectors(CVodeMem cv_mem);
+
+/* Initial stepsize calculation */
+
+static int cvHin(CVodeMem cv_mem, realtype tout);
+static realtype cvUpperBoundH0(CVodeMem cv_mem, realtype tdist);
+static int cvYddNorm(CVodeMem cv_mem, realtype hg, realtype *yddnrm);
+
+/* Initial setup */
+
+static int cvInitialSetup(CVodeMem cv_mem);
+
+static int cvEwtSetSS(CVodeMem cv_mem, N_Vector ycur, N_Vector weight);
+static int cvEwtSetSV(CVodeMem cv_mem, N_Vector ycur, N_Vector weight);
+
+static int cvQuadEwtSet(CVodeMem cv_mem, N_Vector qcur, N_Vector weightQ);
+static int cvQuadEwtSetSS(CVodeMem cv_mem, N_Vector qcur, N_Vector weightQ);
+static int cvQuadEwtSetSV(CVodeMem cv_mem, N_Vector qcur, N_Vector weightQ);
+
+static int cvSensEwtSet(CVodeMem cv_mem, N_Vector *yScur, N_Vector *weightS);
+static int cvSensEwtSetEE(CVodeMem cv_mem, N_Vector *yScur, N_Vector *weightS);
+static int cvSensEwtSetSS(CVodeMem cv_mem, N_Vector *yScur, N_Vector *weightS);
+static int cvSensEwtSetSV(CVodeMem cv_mem, N_Vector *yScur, N_Vector *weightS);
+
+static int cvQuadSensEwtSet(CVodeMem cv_mem, N_Vector *yQScur, N_Vector *weightQS);
+static int cvQuadSensEwtSetEE(CVodeMem cv_mem, N_Vector *yQScur, N_Vector *weightQS);
+static int cvQuadSensEwtSetSS(CVodeMem cv_mem, N_Vector *yQScur, N_Vector *weightQS);
+static int cvQuadSensEwtSetSV(CVodeMem cv_mem, N_Vector *yQScur, N_Vector *weightQS);
+
+/* Main cvStep function */
+
+static int cvStep(CVodeMem cv_mem);
+
+/* Function called at beginning of step */
+
+static void cvAdjustParams(CVodeMem cv_mem);
+static void cvAdjustOrder(CVodeMem cv_mem, int deltaq);
+static void cvAdjustAdams(CVodeMem cv_mem, int deltaq);
+static void cvAdjustBDF(CVodeMem cv_mem, int deltaq);
+static void cvIncreaseBDF(CVodeMem cv_mem);
+static void cvDecreaseBDF(CVodeMem cv_mem);
+static void cvRescale(CVodeMem cv_mem);
+static void cvPredict(CVodeMem cv_mem);
+static void cvSet(CVodeMem cv_mem);
+static void cvSetAdams(CVodeMem cv_mem);
+static realtype cvAdamsStart(CVodeMem cv_mem, realtype m[]);
+static void cvAdamsFinish(CVodeMem cv_mem, realtype m[], realtype M[], realtype hsum);
+static realtype cvAltSum(int iend, realtype a[], int k);
+static void cvSetBDF(CVodeMem cv_mem);
+static void cvSetTqBDF(CVodeMem cv_mem, realtype hsum, realtype alpha0,
+ realtype alpha0_hat, realtype xi_inv, realtype xistar_inv);
+
+/* Nonlinear solver functions */
+
+static int cvNls(CVodeMem cv_mem, int nflag);
+static int cvNlsFunctional(CVodeMem cv_mem);
+static int cvNlsNewton(CVodeMem cv_mem, int nflag);
+static int cvNewtonIteration(CVodeMem cv_mem);
+
+static int cvQuadNls(CVodeMem cv_mem);
+
+static int cvStgrNls(CVodeMem cv_mem);
+static int cvStgrNlsFunctional(CVodeMem cv_mem);
+static int cvStgrNlsNewton(CVodeMem cv_mem);
+static int cvStgrNewtonIteration(CVodeMem cv_mem);
+
+static int cvStgr1Nls(CVodeMem cv_mem, int is);
+static int cvStgr1NlsFunctional(CVodeMem cv_mem, int is);
+static int cvStgr1NlsNewton(CVodeMem cv_mem, int is);
+static int cvStgr1NewtonIteration(CVodeMem cv_mem, int is);
+
+static int cvQuadSensNls(CVodeMem cv_mem);
+
+static int cvHandleNFlag(CVodeMem cv_mem, int *nflagPtr, realtype saved_t,
+ int *ncfPtr, long int *ncfnPtr);
+
+static void cvRestore(CVodeMem cv_mem, realtype saved_t);
+
+/* Error Test */
+
+static int cvDoErrorTest(CVodeMem cv_mem, int *nflagPtr, realtype saved_t,
+ realtype acor_nrm,
+ int *nefPtr, long int *netfPtr, realtype *dsmPtr);
+
+/* Function called after a successful step */
+
+static void cvCompleteStep(CVodeMem cv_mem);
+static void cvPrepareNextStep(CVodeMem cv_mem, realtype dsm);
+static void cvSetEta(CVodeMem cv_mem);
+static realtype cvComputeEtaqm1(CVodeMem cv_mem);
+static realtype cvComputeEtaqp1(CVodeMem cv_mem);
+static void cvChooseEta(CVodeMem cv_mem);
+
+/* Function to handle failures */
+
+static int cvHandleFailure(CVodeMem cv_mem,int flag);
+
+/* Functions for BDF Stability Limit Detection */
+
+static void cvBDFStab(CVodeMem cv_mem);
+static int cvSLdet(CVodeMem cv_mem);
+
+/* Functions for rootfinding */
+
+static int cvRcheck1(CVodeMem cv_mem);
+static int cvRcheck2(CVodeMem cv_mem);
+static int cvRcheck3(CVodeMem cv_mem);
+static int cvRootFind(CVodeMem cv_mem);
+
+/* Function for combined norms */
+
+static realtype cvQuadUpdateNorm(CVodeMem cv_mem, realtype old_nrm,
+ N_Vector xQ, N_Vector wQ);
+
+static realtype cvSensNorm(CVodeMem cv_mem, N_Vector *xS, N_Vector *wS);
+static realtype cvSensUpdateNorm(CVodeMem cv_mem, realtype old_nrm,
+ N_Vector *xS, N_Vector *wS);
+
+static realtype cvQuadSensNorm(CVodeMem cv_mem, N_Vector *xQS, N_Vector *wQS);
+static realtype cvQuadSensUpdateNorm(CVodeMem cv_mem, realtype old_nrm,
+ N_Vector *xQS, N_Vector *wQS);
+
+/* Internal sensitivity RHS DQ functions */
+
+static int cvQuadSensRhsInternalDQ(int Ns, realtype t,
+ N_Vector y, N_Vector *yS,
+ N_Vector yQdot, N_Vector *yQSdot,
+ void *cvode_mem,
+ N_Vector tmp, N_Vector tmpQ);
+
+static int cvQuadSensRhs1InternalDQ(CVodeMem cv_mem, int is, realtype t,
+ N_Vector y, N_Vector yS,
+ N_Vector yQdot, N_Vector yQSdot,
+ N_Vector tmp, N_Vector tmpQ);
+
+/*
+ * =================================================================
+ * EXPORTED FUNCTIONS IMPLEMENTATION
+ * =================================================================
+ */
+
+/*
+ * -----------------------------------------------------------------
+ * Creation, allocation and re-initialization functions
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * CVodeCreate
+ *
+ * CVodeCreate creates an internal memory block for a problem to
+ * be solved by CVODES.
+ * If successful, CVodeCreate returns a pointer to the problem memory.
+ * This pointer should be passed to CVodeInit.
+ * If an initialization error occurs, CVodeCreate prints an error
+ * message to standard err and returns NULL.
+ */
+
+void *CVodeCreate(int lmm, int iter)
+{
+ int maxord;
+ CVodeMem cv_mem;
+
+ /* Test inputs */
+
+ if ((lmm != CV_ADAMS) && (lmm != CV_BDF)) {
+ cvProcessError(NULL, 0, "CVODES", "CVodeCreate", MSGCV_BAD_LMM);
+ return(NULL);
+ }
+
+ if ((iter != CV_FUNCTIONAL) && (iter != CV_NEWTON)) {
+ cvProcessError(NULL, 0, "CVODES", "CVodeCreate", MSGCV_BAD_ITER);
+ return(NULL);
+ }
+
+ cv_mem = NULL;
+ cv_mem = (CVodeMem) malloc(sizeof(struct CVodeMemRec));
+ if (cv_mem == NULL) {
+ cvProcessError(NULL, 0, "CVODES", "CVodeCreate", MSGCV_CVMEM_FAIL);
+ return(NULL);
+ }
+
+ /* Zero out cv_mem */
+ memset(cv_mem, 0, sizeof(struct CVodeMemRec));
+
+ maxord = (lmm == CV_ADAMS) ? ADAMS_Q_MAX : BDF_Q_MAX;
+
+ /* copy input parameters into cv_mem */
+
+ cv_mem->cv_lmm = lmm;
+ cv_mem->cv_iter = iter;
+
+ /* Set uround */
+
+ cv_mem->cv_uround = UNIT_ROUNDOFF;
+
+ /* Set default values for integrator optional inputs */
+
+ 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_efun = NULL;
+ cv_mem->cv_e_data = NULL;
+ cv_mem->cv_ehfun = cvErrHandler;
+ cv_mem->cv_eh_data = cv_mem;
+ cv_mem->cv_errfp = stderr;
+ 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_hin = ZERO;
+ cv_mem->cv_hmin = HMIN_DEFAULT;
+ cv_mem->cv_hmax_inv = HMAX_INV_DEFAULT;
+ cv_mem->cv_tstopset = FALSE;
+ 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;
+ cv_mem->cv_ghi = NULL;
+ cv_mem->cv_grout = NULL;
+ cv_mem->cv_iroots = NULL;
+ cv_mem->cv_rootdir = NULL;
+ cv_mem->cv_gfun = NULL;
+ cv_mem->cv_nrtfn = 0;
+ cv_mem->cv_gactive = NULL;
+ cv_mem->cv_mxgnull = 1;
+
+ /* Set default values for quad. optional inputs */
+
+ cv_mem->cv_quadr = FALSE;
+ cv_mem->cv_fQ = NULL;
+ cv_mem->cv_errconQ = FALSE;
+ cv_mem->cv_itolQ = CV_NN;
+
+ /* Set default values for sensi. optional inputs */
+
+ cv_mem->cv_sensi = FALSE;
+ cv_mem->cv_fS_data = NULL;
+ cv_mem->cv_fS = cvSensRhsInternalDQ;
+ cv_mem->cv_fS1 = cvSensRhs1InternalDQ;
+ cv_mem->cv_fSDQ = TRUE;
+ 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_maxcorS = NLS_MAXCOR;
+ cv_mem->cv_ncfS1 = NULL;
+ cv_mem->cv_ncfnS1 = NULL;
+ cv_mem->cv_nniS1 = NULL;
+ cv_mem->cv_itolS = CV_NN;
+
+ /* Set default values for quad. sensi. optional inputs */
+
+ cv_mem->cv_quadr_sensi = FALSE;
+ cv_mem->cv_fQS = NULL;
+ cv_mem->cv_fQS_data = NULL;
+ cv_mem->cv_fQSDQ = TRUE;
+ cv_mem->cv_errconQS = FALSE;
+ cv_mem->cv_itolQS = CV_NN;
+
+ /* Set default for ASA */
+
+ cv_mem->cv_adj = FALSE;
+ cv_mem->cv_adj_mem = NULL;
+
+ /* Set the saved values for qmax_alloc */
+
+ cv_mem->cv_qmax_alloc = maxord;
+ cv_mem->cv_qmax_allocQ = maxord;
+ cv_mem->cv_qmax_allocS = maxord;
+
+ /* Initialize lrw and liw */
+
+ cv_mem->cv_lrw = 65 + 2*L_MAX + NUM_TESTS;
+ cv_mem->cv_liw = 52;
+
+ /* No mallocs have been done yet */
+
+ cv_mem->cv_VabstolMallocDone = FALSE;
+ cv_mem->cv_MallocDone = FALSE;
+
+ cv_mem->cv_VabstolQMallocDone = FALSE;
+ cv_mem->cv_QuadMallocDone = FALSE;
+
+ cv_mem->cv_VabstolSMallocDone = FALSE;
+ cv_mem->cv_SabstolSMallocDone = FALSE;
+ cv_mem->cv_SensMallocDone = FALSE;
+
+ cv_mem->cv_VabstolQSMallocDone = FALSE;
+ cv_mem->cv_SabstolQSMallocDone = FALSE;
+ cv_mem->cv_QuadSensMallocDone = FALSE;
+
+ cv_mem->cv_adjMallocDone = FALSE;
+
+ /* Return pointer to CVODES memory block */
+
+ return((void *)cv_mem);
+}
+
+/*-----------------------------------------------------------------*/
+
+#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
+ *
+ * CVodeInit allocates and initializes memory for a problem. All
+ * problem inputs are checked for errors. If any error occurs during
+ * initialization, it is reported to the file whose file pointer is
+ * errfp and an error flag is returned. Otherwise, it returns CV_SUCCESS
+ */
+
+int CVodeInit(void *cvode_mem, CVRhsFn f, realtype t0, N_Vector y0)
+{
+ CVodeMem cv_mem;
+ booleantype nvectorOK, allocOK;
+ long int lrw1, liw1;
+ int i,k;
+
+ /* Check cvode_mem */
+
+ if (cvode_mem==NULL) {
+ cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeInit", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+ cv_mem = (CVodeMem) cvode_mem;
+
+ /* Check for legal input parameters */
+
+ if (y0==NULL) {
+ 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);
+ return(CV_ILL_INPUT);
+ }
+
+ /* Test if all required vector operations are implemented */
+
+ nvectorOK = cvCheckNvector(y0);
+ if(!nvectorOK) {
+ cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeInit", MSGCV_BAD_NVECTOR);
+ return(CV_ILL_INPUT);
+ }
+
+ /* Set space requirements for one N_Vector */
+
+ if (y0->ops->nvspace != NULL) {
+ N_VSpace(y0, &lrw1, &liw1);
+ } else {
+ lrw1 = 0;
+ liw1 = 0;
+ }
+ cv_mem->cv_lrw1 = lrw1;
+ cv_mem->cv_liw1 = liw1;
+
+ /* Allocate the vectors (using y0 as a template) */
+
+ allocOK = cvAllocVectors(cv_mem, y0);
+ if (!allocOK) {
+ cvProcessError(cv_mem, CV_MEM_FAIL, "CVODES", "CVodeInit", MSGCV_MEM_FAIL);
+ return(CV_MEM_FAIL);
+ }
+
+ /* All error checking is complete at this point */
+
+ /* Copy the input parameters into CVODES state */
+
+ cv_mem->cv_f = f;
+ cv_mem->cv_tn = t0;
+
+ /* Set step parameters */
+
+ cv_mem->cv_q = 1;
+ cv_mem->cv_L = 2;
+ cv_mem->cv_qwait = cv_mem->cv_L;
+ cv_mem->cv_etamax = ETAMX1;
+
+ cv_mem->cv_qu = 0;
+ cv_mem->cv_hu = ZERO;
+ cv_mem->cv_tolsf = ONE;
+
+ /* Set the linear solver addresses to NULL.
+ (We check != NULL later, in CVode, if using CV_NEWTON.) */
+
+ cv_mem->cv_linit = NULL;
+ cv_mem->cv_lsetup = NULL;
+ cv_mem->cv_lsolve = NULL;
+ cv_mem->cv_lfree = NULL;
+ cv_mem->cv_lmem = NULL;
+
+ /* Set forceSetup to FALSE */
+
+ cv_mem->cv_forceSetup = FALSE;
+
+ /* Initialize zn[0] in the history array */
+
+ N_VScale(ONE, y0, cv_mem->cv_zn[0]);
+
+ /* Initialize all the counters */
+
+ cv_mem->cv_nst = 0;
+ cv_mem->cv_nfe = 0;
+ cv_mem->cv_ncfn = 0;
+ cv_mem->cv_netf = 0;
+ cv_mem->cv_nni = 0;
+ cv_mem->cv_nsetups = 0;
+ cv_mem->cv_nhnil = 0;
+ cv_mem->cv_nstlp = 0;
+ cv_mem->cv_nscon = 0;
+ cv_mem->cv_nge = 0;
+
+ cv_mem->cv_irfnd = 0;
+
+ /* Initialize other integrator optional outputs */
+
+ cv_mem->cv_h0u = ZERO;
+ cv_mem->cv_next_h = ZERO;
+ cv_mem->cv_next_q = 0;
+
+ /* Initialize Stablilty Limit Detection data */
+ /* NOTE: We do this even if stab lim det was not
+ turned on yet. This way, the user can turn it
+ on at any time */
+
+ cv_mem->cv_nor = 0;
+ for (i = 1; i <= 5; i++)
+ for (k = 1; k <= 3; k++)
+ cv_mem->cv_ssdat[i-1][k-1] = ZERO;
+
+ /* Problem has been successfully initialized */
+
+ cv_mem->cv_MallocDone = TRUE;
+
+ return(CV_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+#define lrw1 (cv_mem->cv_lrw1)
+#define liw1 (cv_mem->cv_liw1)
+
+/*-----------------------------------------------------------------*/
+
+/*
+ * CVodeReInit
+ *
+ * CVodeReInit re-initializes CVODES's memory for a problem, assuming
+ * it has already been allocated in a prior CVodeInit call.
+ * All problem specification inputs are checked for errors.
+ * If any error occurs during initialization, it is reported to the
+ * file whose file pointer is errfp.
+ * The return value is CV_SUCCESS = 0 if no errors occurred, or
+ * a negative value otherwise.
+ */
+
+int CVodeReInit(void *cvode_mem, realtype t0, N_Vector y0)
+{
+ CVodeMem cv_mem;
+ int i,k;
+
+ /* Check cvode_mem */
+
+ if (cvode_mem==NULL) {
+ 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);
+ return(CV_NO_MALLOC);
+ }
+
+ /* Check for legal input parameters */
+
+ if (y0 == NULL) {
+ cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeReInit", MSGCV_NULL_Y0);
+ return(CV_ILL_INPUT);
+ }
+
+ /* Copy the input parameters into CVODES state */
+
+ cv_mem->cv_tn = t0;
+
+ /* Set step parameters */
+
+ cv_mem->cv_q = 1;
+ cv_mem->cv_L = 2;
+ cv_mem->cv_qwait = cv_mem->cv_L;
+ cv_mem->cv_etamax = ETAMX1;
+
+ cv_mem->cv_qu = 0;
+ cv_mem->cv_hu = ZERO;
+ cv_mem->cv_tolsf = ONE;
+
+ /* Set forceSetup to FALSE */
+
+ cv_mem->cv_forceSetup = FALSE;
+
+ /* Initialize zn[0] in the history array */
+
+ N_VScale(ONE, y0, cv_mem->cv_zn[0]);
+
+ /* Initialize all the counters */
+
+ cv_mem->cv_nst = 0;
+ cv_mem->cv_nfe = 0;
+ cv_mem->cv_ncfn = 0;
+ cv_mem->cv_netf = 0;
+ cv_mem->cv_nni = 0;
+ cv_mem->cv_nsetups = 0;
+ cv_mem->cv_nhnil = 0;
+ cv_mem->cv_nstlp = 0;
+ cv_mem->cv_nscon = 0;
+ cv_mem->cv_nge = 0;
+
+ cv_mem->cv_irfnd = 0;
+
+ /* Initialize other integrator optional outputs */
+
+ cv_mem->cv_h0u = ZERO;
+ cv_mem->cv_next_h = ZERO;
+ cv_mem->cv_next_q = 0;
+
+ /* Initialize Stablilty Limit Detection data */
+
+ cv_mem->cv_nor = 0;
+ for (i = 1; i <= 5; i++)
+ for (k = 1; k <= 3; k++)
+ cv_mem->cv_ssdat[i-1][k-1] = ZERO;
+
+ /* Problem has been successfully re-initialized */
+
+ return(CV_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+/*
+ * CVodeSStolerances
+ * CVodeSVtolerances
+ * CVodeWFtolerances
+ *
+ * These functions specify the integration tolerances. One of them
+ * MUST be called before the first call to CVode.
+ *
+ * CVodeSStolerances specifies scalar relative and absolute tolerances.
+ * CVodeSVtolerances specifies scalar relative tolerance and a vector
+ * absolute tolerance (a potentially different absolute tolerance
+ * for each vector component).
+ * CVodeWFtolerances specifies a user-provides function (of type CVEwtFn)
+ * which will be called to set the error weight vector.
+ */
+
+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);
+ 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);
+ return(CV_NO_MALLOC);
+ }
+
+ /* Check inputs */
+
+ if (reltol < ZERO) {
+ 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);
+ return(CV_ILL_INPUT);
+ }
+
+ /* Copy tolerances into memory */
+
+ cv_mem->cv_reltol = reltol;
+ cv_mem->cv_Sabstol = abstol;
+
+ cv_mem->cv_itol = CV_SS;
+
+ cv_mem->cv_user_efun = FALSE;
+ cv_mem->cv_efun = cvEwtSet;
+ cv_mem->cv_e_data = NULL; /* will be set to cvode_mem in InitialSetup */
+
+ return(CV_SUCCESS);
+}
+
+
+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);
+ 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);
+ return(CV_NO_MALLOC);
+ }
+
+ /* Check inputs */
+
+ if (reltol < ZERO) {
+ 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);
+ return(CV_ILL_INPUT);
+ }
+
+ /* Copy tolerances into memory */
+
+ 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_reltol = reltol;
+ N_VScale(ONE, abstol, cv_mem->cv_Vabstol);
+
+ cv_mem->cv_itol = CV_SV;
+
+ cv_mem->cv_user_efun = FALSE;
+ cv_mem->cv_efun = cvEwtSet;
+ cv_mem->cv_e_data = NULL; /* will be set to cvode_mem in InitialSetup */
+
+ return(CV_SUCCESS);
+}
+
+
+int CVodeWFtolerances(void *cvode_mem, CVEwtFn efun)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ 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);
+ return(CV_NO_MALLOC);
+ }
+
+ cv_mem->cv_itol = CV_WF;
+
+ cv_mem->cv_user_efun = TRUE;
+ cv_mem->cv_efun = efun;
+ cv_mem->cv_e_data = NULL; /* will be set to user_data in InitialSetup */
+
+ return(CV_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+/*
+ * CVodeQuadInit
+ *
+ * CVodeQuadInit allocates and initializes quadrature related
+ * memory for a problem. All problem specification inputs are
+ * checked for errors. If any error occurs during initialization,
+ * it is reported to the file whose file pointer is errfp.
+ * The return value is CV_SUCCESS = 0 if no errors occurred, or
+ * a negative value otherwise.
+ */
+
+int CVodeQuadInit(void *cvode_mem, CVQuadRhsFn fQ, N_Vector yQ0)
+{
+ CVodeMem cv_mem;
+ booleantype allocOK;
+ long int lrw1Q, liw1Q;
+
+ /* Check cvode_mem */
+ if (cvode_mem==NULL) {
+ cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeQuadInit", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+ cv_mem = (CVodeMem) cvode_mem;
+
+ /* Set space requirements for one N_Vector */
+ N_VSpace(yQ0, &lrw1Q, &liw1Q);
+ cv_mem->cv_lrw1Q = lrw1Q;
+ cv_mem->cv_liw1Q = liw1Q;
+
+ /* 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);
+ return(CV_MEM_FAIL);
+ }
+
+ /* Initialize znQ[0] in the history array */
+ N_VScale(ONE, yQ0, cv_mem->cv_znQ[0]);
+
+ /* Copy the input parameters into CVODES state */
+ cv_mem->cv_fQ = fQ;
+
+ /* Initialize counters */
+ cv_mem->cv_nfQe = 0;
+ cv_mem->cv_netfQ = 0;
+
+ /* Quadrature integration turned ON */
+ cv_mem->cv_quadr = TRUE;
+ cv_mem->cv_QuadMallocDone = TRUE;
+
+ /* Quadrature initialization was successfull */
+ return(CV_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+#define lrw1Q (cv_mem->cv_lrw1Q)
+#define liw1Q (cv_mem->cv_liw1Q)
+
+/*-----------------------------------------------------------------*/
+
+/*
+ * CVodeQuadReInit
+ *
+ * CVodeQuadReInit re-initializes CVODES's quadrature related memory
+ * for a problem, assuming it has already been allocated in prior
+ * calls to CVodeInit and CVodeQuadInit.
+ * All problem specification inputs are checked for errors.
+ * If any error occurs during initialization, it is reported to the
+ * file whose file pointer is errfp.
+ * The return value is CV_SUCCESS = 0 if no errors occurred, or
+ * a negative value otherwise.
+ */
+
+int CVodeQuadReInit(void *cvode_mem, N_Vector yQ0)
+{
+ CVodeMem cv_mem;
+
+ /* Check cvode_mem */
+ if (cvode_mem==NULL) {
+ 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);
+ return(CV_NO_QUAD);
+ }
+
+ /* Initialize znQ[0] in the history array */
+ N_VScale(ONE, yQ0, cv_mem->cv_znQ[0]);
+
+ /* Initialize counters */
+ cv_mem->cv_nfQe = 0;
+ cv_mem->cv_netfQ = 0;
+
+ /* Quadrature integration turned ON */
+ cv_mem->cv_quadr = TRUE;
+
+ /* Quadrature re-initialization was successfull */
+ return(CV_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+/*
+ * CVodeQuadSStolerances
+ * CVodeQuadSVtolerances
+ *
+ * These functions specify the integration tolerances for sensitivity
+ * variables. One of them MUST be called before the first call to
+ * CVode IF error control on the quadrature variables is enabled
+ * (see CVodeSetQuadErrCon).
+ *
+ * CVodeQuadSStolerances specifies scalar relative and absolute tolerances.
+ * CVodeQuadSVtolerances specifies scalar relative tolerance and a vector
+ * absolute toleranc (a potentially different absolute tolerance for each
+ * vector component).
+ */
+
+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);
+ 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);
+ return(CV_NO_QUAD);
+ }
+
+ /* Test user-supplied tolerances */
+
+ if (reltolQ < ZERO) {
+ 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);
+ return(CV_ILL_INPUT);
+ }
+
+ /* Copy tolerances into memory */
+
+ cv_mem->cv_itolQ = CV_SS;
+
+ cv_mem->cv_reltolQ = reltolQ;
+ cv_mem->cv_SabstolQ = abstolQ;
+
+ return(CV_SUCCESS);
+}
+
+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);
+ 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);
+ return(CV_NO_QUAD);
+ }
+
+ /* Test user-supplied tolerances */
+
+ if (reltolQ < ZERO) {
+ 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);
+ return(CV_ILL_INPUT);
+ }
+
+ if (N_VMin(abstolQ) < ZERO) {
+ cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeQuadSVtolerances", MSGCV_BAD_ABSTOLQ);
+ return(CV_ILL_INPUT);
+ }
+
+ /* Copy tolerances into memory */
+
+ cv_mem->cv_itolQ = CV_SV;
+
+ cv_mem->cv_reltolQ = reltolQ;
+
+ if ( !(cv_mem->cv_VabstolQMallocDone) ) {
+ cv_mem->cv_VabstolQ = N_VClone(cv_mem->cv_tempvQ);
+ lrw += lrw1Q;
+ liw += liw1Q;
+ cv_mem->cv_VabstolQMallocDone = TRUE;
+ }
+
+ N_VScale(ONE, abstolQ, cv_mem->cv_VabstolQ);
+
+ return(CV_SUCCESS);
+}
+
+
+/*-----------------------------------------------------------------*/
+
+#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
+ *
+ * CVodeSensInit allocates and initializes sensitivity related
+ * memory for a problem (using a sensitivity RHS function of type
+ * CVSensRhsFn). All problem specification inputs are checked for
+ * errors.
+ * The return value is CV_SUCCESS = 0 if no errors occurred, or
+ * a negative value otherwise.
+ */
+
+int CVodeSensInit(void *cvode_mem, int Ns, int ism, CVSensRhsFn fS, N_Vector *yS0)
+{
+ CVodeMem cv_mem;
+ booleantype allocOK;
+ int is;
+
+ /* Check cvode_mem */
+
+ if (cvode_mem==NULL) {
+ cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeSensInit", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+ cv_mem = (CVodeMem) cvode_mem;
+
+ /* Check if CVodeSensInit or CVodeSensInit1 was already called */
+
+ if (cv_mem->cv_SensMallocDone) {
+ 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);
+ return(CV_ILL_INPUT);
+ }
+ cv_mem->cv_Ns = Ns;
+
+ /* Check if ism is compatible */
+
+ if (ism==CV_STAGGERED1) {
+ 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);
+ return(CV_ILL_INPUT);
+ }
+ cv_mem->cv_ism = ism;
+
+ /* Check if yS0 is non-null */
+
+ if (yS0 == NULL) {
+ cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeSensInit", MSGCV_NULL_YS0);
+ return(CV_ILL_INPUT);
+ }
+
+ /* Store sensitivity RHS-related data */
+
+ cv_mem->cv_ifS = CV_ALLSENS;
+ cv_mem->cv_fS1 = NULL;
+
+ if (fS == NULL) {
+
+ cv_mem->cv_fSDQ = TRUE;
+ cv_mem->cv_fS = cvSensRhsInternalDQ;
+ cv_mem->cv_fS_data = cvode_mem;
+
+ } else {
+
+ cv_mem->cv_fSDQ = FALSE;
+ cv_mem->cv_fS = fS;
+ cv_mem->cv_fS_data = cv_mem->cv_user_data;
+
+ }
+
+ /* No memory allocation for STAGGERED1 */
+
+ stgr1alloc = FALSE;
+
+ /* 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);
+ return(CV_MEM_FAIL);
+ }
+
+ /*----------------------------------------------
+ All error checking is complete at this point
+ -----------------------------------------------*/
+
+ /* Initialize znS[0] in the history array */
+
+ for (is=0; is<Ns; is++)
+ N_VScale(ONE, yS0[is], cv_mem->cv_znS[0][is]);
+
+ /* Initialize all sensitivity related counters */
+
+ cv_mem->cv_nfSe = 0;
+ cv_mem->cv_nfeS = 0;
+ cv_mem->cv_ncfnS = 0;
+ cv_mem->cv_netfS = 0;
+ cv_mem->cv_nniS = 0;
+ cv_mem->cv_nsetupsS = 0;
+
+ /* Set default values for plist and pbar */
+
+ for (is=0; is<Ns; is++) {
+ cv_mem->cv_plist[is] = is;
+ cv_mem->cv_pbar[is] = ONE;
+ }
+
+ /* Sensitivities will be computed */
+
+ cv_mem->cv_sensi = TRUE;
+ cv_mem->cv_SensMallocDone = TRUE;
+
+ /* Sensitivity initialization was successfull */
+
+ return(CV_SUCCESS);
+}
+
+/*
+ * CVodeSensInit1
+ *
+ * CVodeSensInit1 allocates and initializes sensitivity related
+ * memory for a problem (using a sensitivity RHS function of type
+ * CVSensRhs1Fn). All problem specification inputs are checked for
+ * errors.
+ * The return value is CV_SUCCESS = 0 if no errors occurred, or
+ * a negative value otherwise.
+ */
+
+int CVodeSensInit1(void *cvode_mem, int Ns, int ism, CVSensRhs1Fn fS1, N_Vector *yS0)
+{
+ CVodeMem cv_mem;
+ booleantype allocOK;
+ int is;
+
+ /* Check cvode_mem */
+
+ if (cvode_mem==NULL) {
+ cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeSensInit1", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+ cv_mem = (CVodeMem) cvode_mem;
+
+ /* Check if CVodeSensInit or CVodeSensInit1 was already called */
+
+ if (cv_mem->cv_SensMallocDone) {
+ 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);
+ return(CV_ILL_INPUT);
+ }
+ cv_mem->cv_Ns = Ns;
+
+ /* 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);
+ return(CV_ILL_INPUT);
+ }
+ cv_mem->cv_ism = ism;
+
+ /* Check if yS0 is non-null */
+
+ if (yS0 == NULL) {
+ cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeSensInit1", MSGCV_NULL_YS0);
+ return(CV_ILL_INPUT);
+ }
+
+ /* Store sensitivity RHS-related data */
+
+ cv_mem->cv_ifS = CV_ONESENS;
+ cv_mem->cv_fS = NULL;
+
+ if (fS1 == NULL) {
+
+ cv_mem->cv_fSDQ = TRUE;
+ cv_mem->cv_fS1 = cvSensRhs1InternalDQ;
+ cv_mem->cv_fS_data = cvode_mem;
+
+ } else {
+
+ cv_mem->cv_fSDQ = FALSE;
+ cv_mem->cv_fS1 = fS1;
+ cv_mem->cv_fS_data = cv_mem->cv_user_data;
+
+ }
+
+ /* 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);
+ return(CV_MEM_FAIL);
+ }
+ } else {
+ stgr1alloc = FALSE;
+ }
+
+ /* 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;
+ }
+ cvProcessError(cv_mem, CV_MEM_FAIL, "CVODES", "CVodeSensInit1", MSGCV_MEM_FAIL);
+ return(CV_MEM_FAIL);
+ }
+
+ /*----------------------------------------------
+ All error checking is complete at this point
+ -----------------------------------------------*/
+
+ /* Initialize znS[0] in the history array */
+
+ for (is=0; is<Ns; is++)
+ N_VScale(ONE, yS0[is], cv_mem->cv_znS[0][is]);
+
+ /* Initialize all sensitivity related counters */
+
+ cv_mem->cv_nfSe = 0;
+ cv_mem->cv_nfeS = 0;
+ cv_mem->cv_ncfnS = 0;
+ cv_mem->cv_netfS = 0;
+ 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;
+ }
+
+ /* Set default values for plist and pbar */
+
+ for (is=0; is<Ns; is++) {
+ cv_mem->cv_plist[is] = is;
+ cv_mem->cv_pbar[is] = ONE;
+ }
+
+ /* Sensitivities will be computed */
+
+ cv_mem->cv_sensi = TRUE;
+ cv_mem->cv_SensMallocDone = TRUE;
+
+ /* Sensitivity initialization was successfull */
+
+ return(CV_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+#define Ns (cv_mem->cv_Ns)
+#define ifS (cv_mem->cv_ifS)
+
+/*-----------------------------------------------------------------*/
+
+/*
+ * CVodeSensReInit
+ *
+ * CVodeSensReInit re-initializes CVODES's sensitivity related memory
+ * for a problem, assuming it has already been allocated in prior
+ * calls to CVodeInit and CVodeSensInit/CVodeSensInit1.
+ * All problem specification inputs are checked for errors.
+ * The number of sensitivities Ns is assumed to be unchanged since
+ * the previous call to CVodeSensInit.
+ * If any error occurs during initialization, it is reported to the
+ * file whose file pointer is errfp.
+ * The return value is CV_SUCCESS = 0 if no errors occurred, or
+ * a negative value otherwise.
+ */
+
+int CVodeSensReInit(void *cvode_mem, int ism, N_Vector *yS0)
+{
+ CVodeMem cv_mem;
+ int is;
+
+ /* Check cvode_mem */
+
+ if (cvode_mem==NULL) {
+ 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);
+ 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);
+ 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);
+ return(CV_ILL_INPUT);
+ }
+ cv_mem->cv_ism = ism;
+
+ /* Check if yS0 is non-null */
+
+ if (yS0 == NULL) {
+ 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);
+ return(CV_MEM_FAIL);
+ }
+ }
+
+ /*----------------------------------------------
+ All error checking is complete at this point
+ -----------------------------------------------*/
+
+ /* Initialize znS[0] in the history array */
+
+ for (is=0; is<Ns; is++)
+ N_VScale(ONE, yS0[is], cv_mem->cv_znS[0][is]);
+
+ /* Initialize all sensitivity related counters */
+
+ cv_mem->cv_nfSe = 0;
+ cv_mem->cv_nfeS = 0;
+ cv_mem->cv_ncfnS = 0;
+ cv_mem->cv_netfS = 0;
+ 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;
+ }
+
+ /* Problem has been successfully re-initialized */
+
+ cv_mem->cv_sensi = TRUE;
+
+ return(CV_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+/*
+ * CVodeSensSStolerances
+ * CVodeSensSVtolerances
+ * CVodeSensEEtolerances
+ *
+ * These functions specify the integration tolerances for sensitivity
+ * variables. One of them MUST be called before the first call to CVode.
+ *
+ * CVodeSensSStolerances specifies scalar relative and absolute tolerances.
+ * CVodeSensSVtolerances specifies scalar relative tolerance and a vector
+ * absolute tolerance for each sensitivity vector (a potentially different
+ * absolute tolerance for each vector component).
+ * CVodeEEtolerances specifies that tolerances for sensitivity variables
+ * should be estimated from those provided for the state variables.
+ */
+
+int CVodeSensSStolerances(void *cvode_mem, realtype reltolS, realtype *abstolS)
+{
+ CVodeMem cv_mem;
+ int is;
+
+ if (cvode_mem==NULL) {
+ 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);
+ return(CV_NO_SENS);
+ }
+
+ /* Test user-supplied tolerances */
+
+ if (reltolS < ZERO) {
+ 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);
+ return(CV_ILL_INPUT);
+ }
+
+ for (is=0; is<Ns; is++)
+ if (abstolS[is] < ZERO) {
+ cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeSensSStolerances", MSGCV_BAD_ABSTOLS);
+ return(CV_ILL_INPUT);
+ }
+
+ /* Copy tolerances into memory */
+
+ cv_mem->cv_itolS = CV_SS;
+
+ cv_mem->cv_reltolS = reltolS;
+
+ 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;
+ }
+
+ for (is=0; is<Ns; is++)
+ cv_mem->cv_SabstolS[is] = abstolS[is];
+
+ return(CV_SUCCESS);
+}
+
+int CVodeSensSVtolerances(void *cvode_mem, realtype reltolS, N_Vector *abstolS)
+{
+ CVodeMem cv_mem;
+ int is;
+
+ if (cvode_mem==NULL) {
+ 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);
+ 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);
+ return(CV_ILL_INPUT);
+ }
+
+ if (abstolS == NULL) {
+ cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeSensSVtolerances", MSGCV_NULL_ABSTOLS);
+ return(CV_ILL_INPUT);
+ }
+
+ for (is=0; is<Ns; is++)
+ if (N_VMin(abstolS[is]) < ZERO) {
+ cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeSensSVtolerances", MSGCV_BAD_ABSTOLS);
+ return(CV_ILL_INPUT);
+ }
+
+ /* Copy tolerances into memory */
+
+ cv_mem->cv_itolS = CV_SV;
+
+ 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;
+ }
+
+ for (is=0; is<Ns; is++)
+ N_VScale(ONE, abstolS[is], cv_mem->cv_VabstolS[is]);
+
+ return(CV_SUCCESS);
+}
+
+
+int CVodeSensEEtolerances(void *cvode_mem)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ 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);
+ return(CV_NO_SENS);
+ }
+
+ cv_mem->cv_itolS = CV_EE;
+
+ return(CV_SUCCESS);
+}
+
+
+/*-----------------------------------------------------------------*/
+
+/*
+ * CVodeQuadSensInit
+ *
+ */
+
+int CVodeQuadSensInit(void *cvode_mem, CVQuadSensRhsFn fQS, N_Vector *yQS0)
+{
+ CVodeMem cv_mem;
+ booleantype allocOK;
+ int is;
+
+ /* Check cvode_mem */
+ if (cvode_mem==NULL) {
+ 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);
+ return(CV_ILL_INPUT);
+ }
+
+ /* Check if yQS0 is non-null */
+ if (yQS0 == NULL) {
+ 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);
+ return(CV_MEM_FAIL);
+ }
+
+ /*----------------------------------------------
+ All error checking is complete at this point
+ -----------------------------------------------*/
+
+ /* Set fQS */
+ if (fQS == NULL) {
+
+ cv_mem->cv_fQSDQ = TRUE;
+ cv_mem->cv_fQS = cvQuadSensRhsInternalDQ;
+
+ cv_mem->cv_fQS_data = cvode_mem;
+
+ } else {
+
+ cv_mem->cv_fQSDQ = FALSE;
+ cv_mem->cv_fQS = fQS;
+
+ cv_mem->cv_fS_data = cv_mem->cv_user_data;
+
+ }
+
+ /* Initialize znQS[0] in the history array */
+ for (is=0; is<Ns; is++)
+ N_VScale(ONE, yQS0[is], cv_mem->cv_znQS[0][is]);
+
+ /* Initialize all sensitivity related counters */
+ cv_mem->cv_nfQSe = 0;
+ cv_mem->cv_nfQeS = 0;
+ cv_mem->cv_netfQS = 0;
+
+ /* Quadrature sensitivities will be computed */
+ cv_mem->cv_quadr_sensi = TRUE;
+ cv_mem->cv_QuadSensMallocDone = TRUE;
+
+ /* Sensitivity initialization was successfull */
+ return(CV_SUCCESS);
+}
+
+/*
+ * CVodeQuadSensReInit
+ *
+ */
+
+int CVodeQuadSensReInit(void *cvode_mem, N_Vector *yQS0)
+{
+ CVodeMem cv_mem;
+ int is;
+
+ /* Check cvode_mem */
+ if (cvode_mem==NULL) {
+ 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);
+ 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);
+ return(CV_NO_QUADSENS);
+ }
+
+ /* Check if yQS0 is non-null */
+ if (yQS0 == NULL) {
+ cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeQuadSensReInit", MSGCV_NULL_YQS0);
+ return(CV_ILL_INPUT);
+ }
+
+ /*----------------------------------------------
+ All error checking is complete at this point
+ -----------------------------------------------*/
+
+ /* Initialize znQS[0] in the history array */
+ for (is=0; is<Ns; is++)
+ N_VScale(ONE, yQS0[is], cv_mem->cv_znQS[0][is]);
+
+ /* Initialize all sensitivity related counters */
+ cv_mem->cv_nfQSe = 0;
+ cv_mem->cv_nfQeS = 0;
+ cv_mem->cv_netfQS = 0;
+
+ /* Quadrature sensitivities will be computed */
+ cv_mem->cv_quadr_sensi = TRUE;
+
+ /* Problem has been successfully re-initialized */
+ return(CV_SUCCESS);
+}
+
+
+/*
+ * CVodeQuadSensSStolerances
+ * CVodeQuadSensSVtolerances
+ * CVodeQuadSensEEtolerances
+ *
+ * These functions specify the integration tolerances for quadrature
+ * sensitivity variables. One of them MUST be called before the first
+ * call to CVode IF these variables are included in the error test.
+ *
+ * CVodeQuadSensSStolerances specifies scalar relative and absolute tolerances.
+ * CVodeQuadSensSVtolerances specifies scalar relative tolerance and a vector
+ * absolute tolerance for each quadrature sensitivity vector (a potentially
+ * different absolute tolerance for each vector component).
+ * CVodeQuadSensEEtolerances specifies that tolerances for sensitivity variables
+ * should be estimated from those provided for the quadrature variables.
+ * In this case, tolerances for the quadrature variables must be
+ * specified through a call to one of CVodeQuad**tolerances.
+ */
+
+int CVodeQuadSensSStolerances(void *cvode_mem, realtype reltolQS, realtype *abstolQS)
+{
+ CVodeMem cv_mem;
+ int is;
+
+ if (cvode_mem==NULL) {
+ 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);
+ 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);
+ return(CV_NO_QUAD);
+ }
+
+ /* Test user-supplied tolerances */
+
+ if (reltolQS < ZERO) {
+ 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);
+ return(CV_ILL_INPUT);
+ }
+
+ for (is=0; is<Ns; is++)
+ if (abstolQS[is] < ZERO) {
+ cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeQuadSensSStolerances", MSGCV_BAD_ABSTOLQS);
+ return(CV_ILL_INPUT);
+ }
+
+ /* Copy tolerances into memory */
+
+ cv_mem->cv_itolQS = CV_SS;
+
+ cv_mem->cv_reltolQS = reltolQS;
+
+ 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;
+ }
+
+ for (is=0; is<Ns; is++)
+ cv_mem->cv_SabstolQS[is] = abstolQS[is];
+
+ return(CV_SUCCESS);
+}
+
+int CVodeQuadSensSVtolerances(void *cvode_mem, realtype reltolQS, N_Vector *abstolQS)
+{
+ CVodeMem cv_mem;
+ int is;
+
+ if (cvode_mem==NULL) {
+ 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);
+ 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);
+ 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);
+ return(CV_ILL_INPUT);
+ }
+
+ if (abstolQS == NULL) {
+ cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeSensSVtolerances", MSGCV_NULL_ABSTOLQS);
+ return(CV_ILL_INPUT);
+ }
+
+ for (is=0; is<Ns; is++)
+ if (N_VMin(abstolQS[is]) < ZERO) {
+ cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeQuadSensSVtolerances", MSGCV_BAD_ABSTOLQS);
+ return(CV_ILL_INPUT);
+ }
+
+ /* Copy tolerances into memory */
+
+ cv_mem->cv_itolQS = CV_SV;
+
+ 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;
+ }
+
+ for (is=0; is<Ns; is++)
+ N_VScale(ONE, abstolQS[is], cv_mem->cv_VabstolQS[is]);
+
+ return(CV_SUCCESS);
+}
+
+
+int CVodeQuadSensEEtolerances(void *cvode_mem)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ 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);
+ 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);
+ return(CV_NO_QUAD);
+ }
+
+ cv_mem->cv_itolQS = CV_EE;
+
+ return(CV_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+/*
+ * CVodeSensToggleOff
+ *
+ * CVodeSensToggleOff deactivates sensitivity calculations.
+ * It does NOT deallocate sensitivity-related memory.
+ */
+
+int CVodeSensToggleOff(void *cvode_mem)
+{
+ CVodeMem cv_mem;
+
+ /* Check cvode_mem */
+ if (cvode_mem==NULL) {
+ 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;
+
+ 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
+ *
+ * CVodeRootInit initializes a rootfinding problem to be solved
+ * during the integration of the ODE system. It loads the root
+ * function pointer and the number of root functions, and allocates
+ * workspace memory. The return value is CV_SUCCESS = 0 if no errors
+ * occurred, or a negative value otherwise.
+ */
+
+int CVodeRootInit(void *cvode_mem, int nrtfn, CVRootFn g)
+{
+ CVodeMem cv_mem;
+ int i, nrt;
+
+ /* Check cvode_mem */
+ if (cvode_mem==NULL) {
+ cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeRootInit", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+ cv_mem = (CVodeMem) cvode_mem;
+
+ nrt = (nrtfn < 0) ? 0 : nrtfn;
+
+ /* If rerunning CVodeRootInit() with a different number of root
+ 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);
+
+ }
+
+ /* 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;
+ return(CV_SUCCESS);
+ }
+
+ /* If rerunning CVodeRootInit() with the same number of root functions
+ (not changing number of gfun components), then check if the root
+ function argument has changed */
+ /* If g != NULL then return as currently reserved memory resources
+ will suffice */
+ if (nrt == cv_mem->cv_nrtfn) {
+ if (g != 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);
+ return(CV_ILL_INPUT);
+ }
+ else {
+ gfun = g;
+ return(CV_SUCCESS);
+ }
+ }
+ else return(CV_SUCCESS);
+ }
+
+ /* 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);
+ return(CV_ILL_INPUT);
+ }
+ else 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);
+ 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);
+ 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);
+ 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);
+ 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);
+ 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);
+ return(CV_MEM_FAIL);
+ }
+
+
+ /* Set default values for rootdir (both directions) */
+ for(i=0; i<nrt; i++) rootdir[i] = 0;
+
+ /* Set default values for gactive (all active) */
+ for(i=0; i<nrt; i++) gactive[i] = TRUE;
+
+ lrw += 3*nrt;
+ 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
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * CVode
+ *
+ * This routine is the main driver of the CVODES package.
+ *
+ * It integrates over a time interval defined by the user, by calling
+ * cvStep to do internal time steps.
+ *
+ * The first time that CVode is called for a successfully initialized
+ * problem, it computes a tentative initial step size h.
+ *
+ * CVode supports two modes, specified by itask: CV_NORMAL, CV_ONE_STEP.
+ * In the CV_NORMAL mode, the solver steps until it reaches or passes tout
+ * and then interpolates to obtain y(tout).
+ * In the CV_ONE_STEP mode, it takes one internal step and returns.
+ */
+
+int CVode(void *cvode_mem, realtype tout, N_Vector yout,
+ realtype *tret, int itask)
+{
+ CVodeMem cv_mem;
+ long int nstloc;
+ int retval, hflag, kflag, istate, is, ir, ier, irfndp;
+ realtype troundoff, tout_hin, rh, nrm;
+ booleantype inactive_roots;
+
+ /*
+ * -------------------------------------
+ * 1. Check and process inputs
+ * -------------------------------------
+ */
+
+ /* Check if cvode_mem exists */
+ if (cvode_mem == NULL) {
+ 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);
+ return(CV_NO_MALLOC);
+ }
+
+ /* Check for yout != NULL */
+ if ((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);
+ 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);
+ return(CV_ILL_INPUT);
+ }
+
+ if (itask == CV_NORMAL) toutc = tout;
+ taskc = itask;
+
+ /*
+ * ----------------------------------------
+ * 2. Initializations performed only at
+ * the first step (nst=0):
+ * - initial setup
+ * - initialize Nordsieck history array
+ * - compute initial step size
+ * - check for approach to tstop
+ * - check for approach to a root
+ * ----------------------------------------
+ */
+
+ if (nst == 0) {
+
+ /* Check inputs for corectness */
+
+ ier = cvInitialSetup(cv_mem);
+ if (ier!= CV_SUCCESS) return(ier);
+
+ /*
+ * Call f at (t0,y0), set zn[1] = y'(t0).
+ * If computing any quadratures, call fQ at (t0,y0), set znQ[1] = yQ'(t0)
+ * If computing sensitivities, call fS at (t0,y0,yS0), set znS[1][is] = yS'(t0), is=1,...,Ns.
+ * 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++;
+ if (retval < 0) {
+ cvProcessError(cv_mem, CV_RHSFUNC_FAIL, "CVODES", "CVode", MSGCV_RHSFUNC_FAILED, tn);
+ return(CV_RHSFUNC_FAIL);
+ }
+ if (retval > 0) {
+ 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 (retval < 0) {
+ cvProcessError(cv_mem, CV_QRHSFUNC_FAIL, "CVODES", "CVode", MSGCV_QRHSFUNC_FAILED, tn);
+ return(CV_QRHSFUNC_FAIL);
+ }
+ if (retval > 0) {
+ 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 (retval < 0) {
+ cvProcessError(cv_mem, CV_SRHSFUNC_FAIL, "CVODES", "CVode", MSGCV_SRHSFUNC_FAILED, tn);
+ return(CV_SRHSFUNC_FAIL);
+ }
+ if (retval > 0) {
+ 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 (retval < 0) {
+ cvProcessError(cv_mem, CV_QSRHSFUNC_FAIL, "CVODES", "CVode", MSGCV_QSRHSFUNC_FAILED, tn);
+ return(CV_QSRHSFUNC_FAIL);
+ }
+ if (retval > 0) {
+ cvProcessError(cv_mem, CV_FIRST_QSRHSFUNC_ERR, "CVODES", "CVode", MSGCV_QSRHSFUNC_FIRST);
+ return(CV_FIRST_QSRHSFUNC_ERR);
+ }
+ }
+
+ /* Set initial h (from H0 or cvHin). */
+
+ h = hin;
+ if ( (h != ZERO) && ((tout-tn)*h < ZERO) ) {
+ cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVode", MSGCV_BAD_H0);
+ return(CV_ILL_INPUT);
+ }
+ if (h == ZERO) {
+ tout_hin = tout;
+ if ( tstopset && (tout-tn)*(tout-tstop) > 0 ) tout_hin = tstop;
+ hflag = cvHin(cv_mem, tout_hin);
+ if (hflag != CV_SUCCESS) {
+ istate = cvHandleFailure(cv_mem, hflag);
+ return(istate);
+ }
+ }
+ rh = ABS(h)*hmax_inv;
+ if (rh > ONE) h /= rh;
+ if (ABS(h) < hmin) h *= hmin/ABS(h);
+
+ /* Check for approach to tstop */
+
+ if (tstopset) {
+ if ( (tstop - tn)*h < ZERO ) {
+ cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVode", MSGCV_BAD_TSTOP, tstop, tn);
+ return(CV_ILL_INPUT);
+ }
+ if ( (tn + h - tstop)*h > ZERO )
+ h = (tstop - tn)*(ONE-FOUR*uround);
+ }
+
+ /*
+ * Scale zn[1] by h.
+ * If computing any quadratures, scale znQ[1] by h.
+ * If computing sensitivities, scale znS[1][is] by h.
+ * If computing quadrature sensitivities, scale znQS[1][is] by h.
+ */
+
+ hscale = h;
+ h0u = h;
+ hprime = h;
+
+ N_VScale(h, zn[1], zn[1]);
+
+ if (quadr)
+ N_VScale(h, znQ[1], znQ[1]);
+
+ if (sensi)
+ for (is=0; is<Ns; is++)
+ N_VScale(h, znS[1][is], znS[1][is]);
+
+ if (quadr_sensi)
+ for (is=0; is<Ns; is++)
+ N_VScale(h, znQS[1][is], znQS[1][is]);
+
+ /* Check for zeros of root function g at and near t0. */
+
+ if (nrtfn > 0) {
+
+ retval = cvRcheck1(cv_mem);
+
+ if (retval == CV_RTFUNC_FAIL) {
+ cvProcessError(cv_mem, CV_RTFUNC_FAIL, "CVODES", "cvRcheck1", MSGCV_RTFUNC_FAILED, tn);
+ return(CV_RTFUNC_FAIL);
+ }
+
+ }
+
+ } /* end first call block */
+
+ /*
+ * ------------------------------------------------------
+ * 3. At following steps, perform stop tests:
+ * - check for root in last step
+ * - check if we passed tstop
+ * - check if we passed tout (NORMAL mode)
+ * - check if current tn was returned (ONE_STEP mode)
+ * - check if we are close to tstop
+ * (adjust step size if needed)
+ * -------------------------------------------------------
+ */
+
+ if (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*(ABS(tn) + ABS(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) {
+
+ irfndp = irfnd;
+
+ retval = cvRcheck2(cv_mem);
+
+ if (retval == CLOSERT) {
+ cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "cvRcheck2", MSGCV_CLOSE_ROOTS, tlo);
+ return(CV_ILL_INPUT);
+ } else if (retval == CV_RTFUNC_FAIL) {
+ cvProcessError(cv_mem, CV_RTFUNC_FAIL, "CVODES", "cvRcheck2", MSGCV_RTFUNC_FAILED, tlo);
+ return(CV_RTFUNC_FAIL);
+ } else if (retval == RTFOUND) {
+ tretlast = *tret = tlo;
+ return(CV_ROOT_RETURN);
+ }
+
+ /* If tn is distinct from tretlast (within roundoff),
+ check remaining interval for roots */
+ if ( ABS(tn - tretlast) > troundoff ) {
+
+ retval = cvRcheck3(cv_mem);
+
+ if (retval == CV_SUCCESS) { /* no root found */
+ irfnd = 0;
+ if ((irfndp == 1) && (itask == CV_ONE_STEP)) {
+ tretlast = *tret = tn;
+ N_VScale(ONE, zn[0], yout);
+ return(CV_SUCCESS);
+ }
+ } else if (retval == RTFOUND) { /* a new root was found */
+ irfnd = 1;
+ tretlast = *tret = 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);
+ return(CV_RTFUNC_FAIL);
+ }
+
+ }
+
+ } /* 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;
+ ier = CVodeGetDky(cv_mem, tout, 0, yout);
+ if (ier != CV_SUCCESS) {
+ 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 && ABS(tn - tretlast) > troundoff ) {
+ tretlast = *tret = tn;
+ N_VScale(ONE, zn[0], yout);
+ return(CV_SUCCESS);
+ }
+
+ /* Test for tn at tstop or near tstop */
+ if ( tstopset ) {
+
+ if ( ABS(tn - tstop) <= troundoff ) {
+ ier = CVodeGetDky(cv_mem, tstop, 0, yout);
+ if (ier != CV_SUCCESS) {
+ cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVode", MSGCV_BAD_TSTOP, tstop, tn);
+ return(CV_ILL_INPUT);
+ }
+ tretlast = *tret = tstop;
+ tstopset = FALSE;
+ 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;
+ }
+
+ }
+
+ } /* end stopping tests block at nst>0 */
+
+ /*
+ * --------------------------------------------------
+ * 4. Looping point for internal steps
+ *
+ * 4.1. check for errors (too many steps, too much
+ * accuracy requested, step size too small)
+ * 4.2. take a new step (call cvStep)
+ * 4.3. stop on error
+ * 4.4. perform stop tests:
+ * - check for root in last step
+ * - check if tout was passed
+ * - check if close to tstop
+ * - check if in ONE_STEP mode (must return)
+ * --------------------------------------------------
+ */
+
+ nstloc = 0;
+ loop {
+
+ next_h = h;
+ next_q = q;
+
+ /* Reset and check ewt, ewtQ, ewtS */
+ if (nst > 0) {
+
+ ier = efun(zn[0], ewt, 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);
+ istate = CV_ILL_INPUT;
+ tretlast = *tret = tn;
+ N_VScale(ONE, zn[0], yout);
+ break;
+ }
+
+ if (quadr && errconQ) {
+ ier = cvQuadEwtSet(cv_mem, znQ[0], ewtQ);
+ if(ier != 0) {
+ cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVode", MSGCV_EWTQ_NOW_BAD, tn);
+ istate = CV_ILL_INPUT;
+ tretlast = *tret = tn;
+ N_VScale(ONE, zn[0], yout);
+ break;
+ }
+ }
+
+ if (sensi) {
+ ier = cvSensEwtSet(cv_mem, znS[0], ewtS);
+ if (ier != 0) {
+ cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVode", MSGCV_EWTS_NOW_BAD, tn);
+ istate = CV_ILL_INPUT;
+ tretlast = *tret = tn;
+ N_VScale(ONE, zn[0], yout);
+ break;
+ }
+ }
+
+ if (quadr_sensi && errconQS) {
+ ier = cvQuadSensEwtSet(cv_mem, znQS[0], ewtQS);
+ if (ier != 0) {
+ cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVode", MSGCV_EWTQS_NOW_BAD, tn);
+ istate = CV_ILL_INPUT;
+ tretlast = *tret = tn;
+ N_VScale(ONE, zn[0], yout);
+ break;
+ }
+ }
+
+ }
+
+ /* Check for too many steps */
+ if ( (mxstep>0) && (nstloc >= mxstep) ) {
+ cvProcessError(cv_mem, CV_TOO_MUCH_WORK, "CVODES", "CVode", MSGCV_MAX_STEPS, tn);
+ istate = CV_TOO_MUCH_WORK;
+ tretlast = *tret = tn;
+ N_VScale(ONE, 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);
+ }
+ if (sensi && errconS) {
+ nrm = cvSensUpdateNorm(cv_mem, nrm, znS[0], ewtS);
+ }
+ if (quadr_sensi && errconQS) {
+ nrm = cvQuadSensUpdateNorm(cv_mem, nrm, znQS[0], ewtQS);
+ }
+ tolsf = uround * nrm;
+ if (tolsf > ONE) {
+ cvProcessError(cv_mem, CV_TOO_MUCH_ACC, "CVODES", "CVode", MSGCV_TOO_MUCH_ACC, tn);
+ istate = CV_TOO_MUCH_ACC;
+ tretlast = *tret = tn;
+ N_VScale(ONE, zn[0], yout);
+ tolsf *= TWO;
+ break;
+ } else {
+ 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)
+ cvProcessError(cv_mem, CV_WARNING, "CVODES", "CVode", MSGCV_HNIL_DONE);
+ }
+
+ /* Call cvStep to take a step */
+ kflag = cvStep(cv_mem);
+
+ /* 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);
+ break;
+ }
+
+ nstloc++;
+
+ /* If tstop is set and was reached, reset tn = tstop */
+ if ( tstopset ) {
+ troundoff = FUZZ_FACTOR*uround*(ABS(tn) + ABS(h));
+ if ( ABS(tn - tstop) <= troundoff) tn = tstop;
+ }
+
+ /* Check for root in last step taken. */
+ if (nrtfn > 0) {
+
+ retval = cvRcheck3(cv_mem);
+
+ if (retval == RTFOUND) { /* A new root was found */
+ irfnd = 1;
+ istate = CV_ROOT_RETURN;
+ tretlast = *tret = tlo;
+ break;
+ } else if (retval == CV_RTFUNC_FAIL) { /* g failed */
+ cvProcessError(cv_mem, CV_RTFUNC_FAIL, "CVODES", "cvRcheck3", MSGCV_RTFUNC_FAILED, tlo);
+ istate = CV_RTFUNC_FAIL;
+ break;
+ }
+
+ /* If we are at the end of the first step and we still have
+ * some event functions that are inactive, issue a warning
+ * 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;
+ break;
+ }
+ }
+ if ((cv_mem->cv_mxgnull > 0) && 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 ) {
+ istate = CV_SUCCESS;
+ tretlast = *tret = tout;
+ (void) CVodeGetDky(cv_mem, tout, 0, yout);
+ next_q = qprime;
+ next_h = hprime;
+ break;
+ }
+
+ /* Check if tn is at tstop, or about to pass tstop */
+ if ( tstopset ) {
+
+ troundoff = FUZZ_FACTOR*uround*(ABS(tn) + ABS(h));
+ if ( ABS(tn - tstop) <= troundoff) {
+ (void) CVodeGetDky(cv_mem, tstop, 0, yout);
+ tretlast = *tret = tstop;
+ tstopset = FALSE;
+ istate = CV_TSTOP_RETURN;
+ break;
+ }
+
+ if ( (tn + hprime - tstop)*h > ZERO ) {
+ hprime = (tstop - tn)*(ONE-FOUR*uround);
+ eta = hprime/h;
+ }
+
+ }
+
+ /* 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;
+ 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];
+ }
+ }
+
+ return(istate);
+
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Interpolated output and extraction functions
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * CVodeGetDky
+ *
+ * This routine computes the k-th derivative of the interpolating
+ * polynomial at the time t and stores the result in the vector dky.
+ * The formula is:
+ * q
+ * dky = SUM c(j,k) * (t - tn)^(j-k) * h^(-j) * zn[j] ,
+ * j=k
+ * where c(j,k) = j*(j-1)*...*(j-k+1), q is the current order, and
+ * zn[j] is the j-th column of the Nordsieck history array.
+ *
+ * This function is called by CVode with k = 0 and t = tout, but
+ * may also be called directly by the user.
+ */
+
+int CVodeGetDky(void *cvode_mem, realtype t, int k, N_Vector dky)
+{
+ realtype s, c, r;
+ realtype tfuzz, tp, tn1;
+ int i, j;
+ CVodeMem cv_mem;
+
+ /* Check all inputs for legality */
+
+ if (cvode_mem == NULL) {
+ cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetDky", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+ cv_mem = (CVodeMem) cvode_mem;
+
+ if (dky == NULL) {
+ cvProcessError(cv_mem, CV_BAD_DKY, "CVODES", "CVodeGetDky", MSGCV_NULL_DKY);
+ return(CV_BAD_DKY);
+ }
+
+ if ((k < 0) || (k > q)) {
+ cvProcessError(cv_mem, CV_BAD_K, "CVODES", "CVodeGetDky", MSGCV_BAD_K);
+ return(CV_BAD_K);
+ }
+
+ /* Allow for some slack */
+ tfuzz = FUZZ_FACTOR * uround * (ABS(tn) + ABS(hu));
+ if (hu < ZERO) tfuzz = -tfuzz;
+ tp = tn - hu - tfuzz;
+ tn1 = tn + tfuzz;
+ if ((t-tp)*(t-tn1) > ZERO) {
+ cvProcessError(cv_mem, CV_BAD_T, "CVODES", "CVodeGetDky", MSGCV_BAD_T, t, tn-hu, tn);
+ return(CV_BAD_T);
+ }
+
+ /* Sum the differentiated interpolating polynomial */
+
+ s = (t - tn) / h;
+ for (j=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);
+ } else {
+ N_VLinearSum(c, zn[j], s, dky, dky);
+ }
+ }
+ if (k == 0) return(CV_SUCCESS);
+ r = RPowerI(h,-k);
+ N_VScale(r, dky, dky);
+ return(CV_SUCCESS);
+}
+
+/*
+ * CVodeGetQuad
+ *
+ * This routine extracts quadrature solution into yQout at the
+ * time which CVode returned the solution.
+ * This is just a wrapper that calls CVodeGetQuadDky with k=0.
+ */
+
+int CVodeGetQuad(void *cvode_mem, realtype *tret, N_Vector yQout)
+{
+ CVodeMem cv_mem;
+ int flag;
+
+ if (cvode_mem == NULL) {
+ cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetQuad", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+ cv_mem = (CVodeMem) cvode_mem;
+
+ *tret = tretlast;
+
+ flag = CVodeGetQuadDky(cvode_mem,tretlast,0,yQout);
+
+ return(flag);
+}
+
+/*
+ * CVodeGetQuadDky
+ *
+ * CVodeQuadDky computes the kth derivative of the yQ function at
+ * time t, where tn-hu <= t <= tn, tn denotes the current
+ * internal time reached, and hu is the last internal step size
+ * successfully used by the solver. The user may request
+ * k=0, 1, ..., qu, where qu is the current order.
+ * The derivative vector is returned in dky. This vector
+ * must be allocated by the caller. It is only legal to call this
+ * function after a successful return from CVode with quadrature
+ * computation enabled.
+ */
+
+int CVodeGetQuadDky(void *cvode_mem, realtype t, int k, N_Vector dkyQ)
+{
+ realtype s, c, r;
+ realtype tfuzz, tp, tn1;
+ int i, j;
+ CVodeMem cv_mem;
+
+ /* Check all inputs for legality */
+
+ if (cvode_mem == NULL) {
+ cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetQuadDky", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+ cv_mem = (CVodeMem) cvode_mem;
+
+ if(quadr != TRUE) {
+ cvProcessError(cv_mem, CV_NO_QUAD, "CVODES", "CVodeGetQuadDky", MSGCV_NO_QUAD);
+ return(CV_NO_QUAD);
+ }
+
+ if (dkyQ == NULL) {
+ cvProcessError(cv_mem, CV_BAD_DKY, "CVODES", "CVodeGetQuadDky", MSGCV_NULL_DKY);
+ return(CV_BAD_DKY);
+ }
+
+ if ((k < 0) || (k > q)) {
+ cvProcessError(cv_mem, CV_BAD_K, "CVODES", "CVodeGetQuadDky", MSGCV_BAD_K);
+ return(CV_BAD_K);
+ }
+
+ /* Allow for some slack */
+ tfuzz = FUZZ_FACTOR * uround * (ABS(tn) + ABS(hu));
+ if (hu < ZERO) tfuzz = -tfuzz;
+ tp = tn - hu - tfuzz;
+ tn1 = tn + tfuzz;
+ if ((t-tp)*(t-tn1) > ZERO) {
+ cvProcessError(cv_mem, CV_BAD_T, "CVODES", "CVodeGetQuadDky", MSGCV_BAD_T);
+ return(CV_BAD_T);
+ }
+
+ /* Sum the differentiated interpolating polynomial */
+
+ s = (t - tn) / h;
+ for (j=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);
+ } else {
+ N_VLinearSum(c, znQ[j], s, dkyQ, dkyQ);
+ }
+ }
+ if (k == 0) return(CV_SUCCESS);
+ r = RPowerI(h,-k);
+ N_VScale(r, dkyQ, dkyQ);
+ return(CV_SUCCESS);
+
+}
+
+/*
+ * CVodeGetSens
+ *
+ * This routine extracts sensitivity solution into ySout at the
+ * time at which CVode returned the solution.
+ * This is just a wrapper that calls CVodeSensDky with k=0.
+ */
+
+int CVodeGetSens(void *cvode_mem, realtype *tret, N_Vector *ySout)
+{
+ CVodeMem cv_mem;
+ int flag;
+
+ if (cvode_mem == NULL) {
+ cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetSens", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+ cv_mem = (CVodeMem) cvode_mem;
+
+ *tret = tretlast;
+
+ flag = CVodeGetSensDky(cvode_mem,tretlast,0,ySout);
+
+ return(flag);
+}
+
+/*
+ * CVodeGetSens1
+ *
+ * This routine extracts the is-th sensitivity solution into ySout
+ * at the time at which CVode returned the solution.
+ * This is just a wrapper that calls CVodeSensDky1 with k=0.
+ */
+
+int CVodeGetSens1(void *cvode_mem, realtype *tret, int is, N_Vector ySout)
+{
+ CVodeMem cv_mem;
+ int flag;
+
+ if (cvode_mem == NULL) {
+ cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetSens1", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+ cv_mem = (CVodeMem) cvode_mem;
+
+ *tret = tretlast;
+
+ flag = CVodeGetSensDky1(cvode_mem,tretlast,0,is,ySout);
+
+ return(flag);
+}
+
+/*
+ * CVodeGetSensDky
+ *
+ * If the user calls directly CVodeSensDky then s must be allocated
+ * prior to this call. When CVodeSensDky is called by
+ * CVodeGetSens, only ier=CV_SUCCESS, ier=CV_NO_SENS, or
+ * ier=CV_BAD_T are possible.
+ */
+
+int CVodeGetSensDky(void *cvode_mem, realtype t, int k, N_Vector *dkyS)
+{
+ int ier=CV_SUCCESS;
+ int is;
+ CVodeMem cv_mem;
+
+ if (cvode_mem == NULL) {
+ cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetSensDky", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+ cv_mem = (CVodeMem) cvode_mem;
+
+ if (dkyS == NULL) {
+ cvProcessError(cv_mem, CV_BAD_DKY, "CVODES", "CVodeGetSensDky", MSGCV_NULL_DKYA);
+ return(CV_BAD_DKY);
+ }
+
+ for (is=0; is<Ns; is++) {
+ ier = CVodeGetSensDky1(cvode_mem,t,k,is,dkyS[is]);
+ if (ier!=CV_SUCCESS) break;
+ }
+
+ return(ier);
+}
+
+/*
+ * CVodeGetSensDky1
+ *
+ * CVodeSensDky1 computes the kth derivative of the yS[is] function at
+ * time t, where tn-hu <= t <= tn, tn denotes the current
+ * internal time reached, and hu is the last internal step size
+ * successfully used by the solver. The user may request
+ * is=0, 1, ..., Ns-1 and k=0, 1, ..., qu, where qu is the current
+ * order. The derivative vector is returned in dky. This vector
+ * must be allocated by the caller. It is only legal to call this
+ * function after a successful return from CVode with sensitivity
+ * computation enabled.
+ */
+
+int CVodeGetSensDky1(void *cvode_mem, realtype t, int k, int is, N_Vector dkyS)
+{
+ realtype s, c, r;
+ realtype tfuzz, tp, tn1;
+ int i, j;
+ CVodeMem cv_mem;
+
+ /* Check all inputs for legality */
+
+ if (cvode_mem == NULL) {
+ 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);
+ return(CV_NO_SENS);
+ }
+
+ if (dkyS == NULL) {
+ 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);
+ return(CV_BAD_K);
+ }
+
+ if ((is < 0) || (is > 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 * (ABS(tn) + ABS(hu));
+ if (hu < ZERO) tfuzz = -tfuzz;
+ tp = tn - hu - tfuzz;
+ tn1 = tn + tfuzz;
+ if ((t-tp)*(t-tn1) > ZERO) {
+ 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--) {
+ c = ONE;
+ for (i=j; i >= j-k+1; i--) c *= i;
+ if (j == q) {
+ N_VScale(c, znS[q][is], dkyS);
+ } else {
+ N_VLinearSum(c, znS[j][is], s, dkyS, dkyS);
+ }
+ }
+ if (k == 0) return(CV_SUCCESS);
+ r = RPowerI(h,-k);
+ N_VScale(r, dkyS, dkyS);
+ return(CV_SUCCESS);
+
+}
+
+/*
+ * CVodeGetQuadSens and CVodeGetQuadSens1
+ *
+ * Extraction functions for all or only one of the quadrature sensitivity
+ * vectors at the time at which CVode returned the ODE solution.
+ */
+
+int CVodeGetQuadSens(void *cvode_mem, realtype *tret, N_Vector *yQSout)
+{
+ CVodeMem cv_mem;
+ int flag;
+
+ if (cvode_mem == NULL) {
+ cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetQuadSens", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+ cv_mem = (CVodeMem) cvode_mem;
+
+ *tret = tretlast;
+
+ flag = CVodeGetQuadSensDky(cvode_mem,tretlast,0,yQSout);
+
+ return(flag);
+}
+
+int CVodeGetQuadSens1(void *cvode_mem, realtype *tret, int is, N_Vector yQSout)
+{
+ CVodeMem cv_mem;
+ int flag;
+
+ if (cvode_mem == NULL) {
+ cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetQuadSens1", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+ cv_mem = (CVodeMem) cvode_mem;
+
+ *tret = tretlast;
+
+ flag = CVodeGetQuadSensDky1(cvode_mem,tretlast,0,is,yQSout);
+
+ return(flag);
+}
+
+/*
+ * CVodeGetQuadSensDky and CVodeGetQuadSensDky1
+ *
+ * Dense output functions for all or only one of the quadrature sensitivity
+ * vectors (or derivative thereof).
+ */
+
+int CVodeGetQuadSensDky(void *cvode_mem, realtype t, int k, N_Vector *dkyQS_all)
+{
+ int ier=CV_SUCCESS;
+ int is;
+ CVodeMem cv_mem;
+
+ if (cvode_mem == NULL) {
+ 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);
+ return(CV_BAD_DKY);
+ }
+
+ for (is=0; is<Ns; is++) {
+ ier = CVodeGetQuadSensDky1(cvode_mem,t,k,is,dkyQS_all[is]);
+ if (ier!=CV_SUCCESS) break;
+ }
+
+ return(ier);
+}
+
+int CVodeGetQuadSensDky1(void *cvode_mem, realtype t, int k, int is, N_Vector dkyQS)
+{
+ realtype s, c, r;
+ realtype tfuzz, tp, tn1;
+ int i, j;
+ CVodeMem cv_mem;
+
+ /* Check all inputs for legality */
+
+ if (cvode_mem == NULL) {
+ 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);
+ return(CV_NO_QUADSENS);
+ }
+
+ if (dkyQS == NULL) {
+ 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);
+ return(CV_BAD_K);
+ }
+
+ if ((is < 0) || (is > 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 * (ABS(tn) + ABS(hu));
+ if (hu < ZERO) tfuzz = -tfuzz;
+ tp = tn - hu - tfuzz;
+ tn1 = tn + tfuzz;
+ if ((t-tp)*(t-tn1) > ZERO) {
+ 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--) {
+ c = ONE;
+ for (i=j; i >= j-k+1; i--) c *= i;
+ if (j == q) {
+ N_VScale(c, znQS[q][is], dkyQS);
+ } else {
+ N_VLinearSum(c, znQS[j][is], s, dkyQS, dkyQS);
+ }
+ }
+ if (k == 0) return(CV_SUCCESS);
+ r = RPowerI(h,-k);
+ N_VScale(r, dkyQS, dkyQS);
+ return(CV_SUCCESS);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Deallocation functions
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * CVodeFree
+ *
+ * This routine frees the problem memory allocated by CVodeInit.
+ * Such memory includes all the vectors allocated by cvAllocVectors,
+ * and the memory lmem for the linear solver (deallocated by a call
+ * to lfree), as well as (if Ns!=0) all memory allocated for
+ * sensitivity computations by CVodeSensInit.
+ */
+
+void CVodeFree(void **cvode_mem)
+{
+ CVodeMem cv_mem;
+
+ if (*cvode_mem == NULL) return;
+
+ cv_mem = (CVodeMem) (*cvode_mem);
+
+ cvFreeVectors(cv_mem);
+
+ CVodeQuadFree(cv_mem);
+
+ CVodeSensFree(cv_mem);
+
+ CVodeQuadSensFree(cv_mem);
+
+ CVodeAdjFree(cv_mem);
+
+ if (iter == CV_NEWTON && lfree != NULL) 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;
+ }
+
+ free(*cvode_mem);
+ *cvode_mem = NULL;
+}
+
+/*
+ * CVodeQuadFree
+ *
+ * CVodeQuadFree frees the problem memory in cvode_mem allocated
+ * for quadrature integration. Its only argument is the pointer
+ * cvode_mem returned by CVodeCreate.
+ */
+
+void CVodeQuadFree(void *cvode_mem)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem == NULL) return;
+ cv_mem = (CVodeMem) cvode_mem;
+
+ if(QuadMallocDone) {
+ cvQuadFreeVectors(cv_mem);
+ QuadMallocDone = FALSE;
+ quadr = FALSE;
+ }
+}
+
+/*
+ * CVodeSensFree
+ *
+ * CVodeSensFree frees the problem memory in cvode_mem allocated
+ * for sensitivity analysis. Its only argument is the pointer
+ * cvode_mem returned by CVodeCreate.
+ */
+
+void CVodeSensFree(void *cvode_mem)
+{
+ CVodeMem cv_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;
+ }
+ cvSensFreeVectors(cv_mem);
+ SensMallocDone = FALSE;
+ sensi = FALSE;
+ }
+}
+
+/*
+ * CVodeQuadSensFree
+ *
+ * CVodeQuadSensFree frees the problem memory in cvode_mem allocated
+ * for quadrature sensitivity analysis. Its only argument is the pointer
+ * cvode_mem returned by CVodeCreate.
+ */
+
+void CVodeQuadSensFree(void *cvode_mem)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem == NULL) return;
+ cv_mem = (CVodeMem) cvode_mem;
+
+ if(QuadSensMallocDone) {
+ cvQuadSensFreeVectors(cv_mem);
+ QuadSensMallocDone = FALSE;
+ quadr_sensi = FALSE;
+ }
+}
+
+
+/*
+ * =================================================================
+ * PRIVATE FUNCTIONS
+ * =================================================================
+ */
+
+/*
+ * cvCheckNvector
+ * This routine checks if all required vector operations are present.
+ * If any of them is missing it returns FALSE.
+ */
+
+static booleantype cvCheckNvector(N_Vector tmpl)
+{
+ if((tmpl->ops->nvclone == NULL) ||
+ (tmpl->ops->nvdestroy == NULL) ||
+ (tmpl->ops->nvlinearsum == NULL) ||
+ (tmpl->ops->nvconst == NULL) ||
+ (tmpl->ops->nvprod == NULL) ||
+ (tmpl->ops->nvdiv == NULL) ||
+ (tmpl->ops->nvscale == NULL) ||
+ (tmpl->ops->nvabs == NULL) ||
+ (tmpl->ops->nvinv == NULL) ||
+ (tmpl->ops->nvaddconst == NULL) ||
+ (tmpl->ops->nvmaxnorm == NULL) ||
+ (tmpl->ops->nvwrmsnorm == NULL) ||
+ (tmpl->ops->nvmin == NULL))
+ return(FALSE);
+ else
+ return(TRUE);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Memory allocation/deallocation
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * cvAllocVectors
+ *
+ * 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.
+ * This routine also sets the optional outputs lrw and liw, which are
+ * (respectively) the lengths of the real and integer work spaces
+ * allocated here.
+ */
+
+static booleantype cvAllocVectors(CVodeMem cv_mem, N_Vector tmpl)
+{
+ int i, j;
+
+ /* Allocate ewt, acor, tempv, ftemp */
+
+ ewt = N_VClone(tmpl);
+ if (ewt == NULL) return(FALSE);
+
+ acor = N_VClone(tmpl);
+ if (acor == NULL) {
+ N_VDestroy(ewt);
+ return(FALSE);
+ }
+
+ tempv = N_VClone(tmpl);
+ if (tempv == NULL) {
+ N_VDestroy(ewt);
+ N_VDestroy(acor);
+ return(FALSE);
+ }
+
+ ftemp = N_VClone(tmpl);
+ if (ftemp == NULL) {
+ N_VDestroy(tempv);
+ N_VDestroy(ewt);
+ N_VDestroy(acor);
+ return(FALSE);
+ }
+
+ /* 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);
+ }
+ }
+
+ /* Update solver workspace lengths */
+ lrw += (qmax + 5)*lrw1;
+ liw += (qmax + 5)*liw1;
+
+ /* Store the value of qmax used here */
+ cv_mem->cv_qmax_alloc = qmax;
+
+ return(TRUE);
+}
+
+/*
+ * cvFreeVectors
+ *
+ * This routine frees the CVODES vectors allocated in cvAllocVectors.
+ */
+
+static void cvFreeVectors(CVodeMem cv_mem)
+{
+ int j, maxord;
+
+ 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]);
+
+ lrw -= (maxord + 5)*lrw1;
+ liw -= (maxord + 5)*liw1;
+
+ if (cv_mem->cv_VabstolMallocDone) {
+ N_VDestroy(Vabstol);
+ lrw -= lrw1;
+ liw -= liw1;
+ }
+}
+
+/*
+ * CVodeQuadAllocVectors
+ *
+ * NOTE: Space for ewtQ is allocated even when errconQ=FALSE,
+ * 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
+ * CVodeQuadReInit.
+ */
+
+static booleantype cvQuadAllocVectors(CVodeMem cv_mem, N_Vector tmpl)
+{
+ int i, j;
+
+ /* Allocate ewtQ */
+ ewtQ = N_VClone(tmpl);
+ if (ewtQ == NULL) {
+ return(FALSE);
+ }
+
+ /* Allocate acorQ */
+ acorQ = N_VClone(tmpl);
+ if (acorQ == NULL) {
+ N_VDestroy(ewtQ);
+ return(FALSE);
+ }
+
+ /* Allocate yQ */
+ yQ = N_VClone(tmpl);
+ if (yQ == NULL) {
+ N_VDestroy(ewtQ);
+ N_VDestroy(acorQ);
+ return(FALSE);
+ }
+
+ /* Allocate tempvQ */
+ tempvQ = N_VClone(tmpl);
+ if (tempvQ == NULL) {
+ N_VDestroy(ewtQ);
+ N_VDestroy(acorQ);
+ N_VDestroy(yQ);
+ return(FALSE);
+ }
+
+ /* 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);
+ }
+ }
+
+ /* Store the value of qmax used here */
+ cv_mem->cv_qmax_allocQ = qmax;
+
+ /* Update solver workspace lengths */
+ lrw += (qmax + 5)*lrw1Q;
+ liw += (qmax + 5)*liw1Q;
+
+ return(TRUE);
+}
+
+/*
+ * cvQuadFreeVectors
+ *
+ * This routine frees the CVODES vectors allocated in cvQuadAllocVectors.
+ */
+
+static void cvQuadFreeVectors(CVodeMem cv_mem)
+{
+ int j, maxord;
+
+ maxord = cv_mem->cv_qmax_allocQ;
+
+ N_VDestroy(ewtQ);
+ N_VDestroy(acorQ);
+ N_VDestroy(yQ);
+ N_VDestroy(tempvQ);
+
+ for (j=0; j<=maxord; j++) N_VDestroy(znQ[j]);
+
+ lrw -= (maxord + 5)*lrw1Q;
+ liw -= (maxord + 5)*liw1Q;
+
+ if (cv_mem->cv_VabstolQMallocDone) {
+ N_VDestroy(VabstolQ);
+ lrw -= lrw1Q;
+ liw -= liw1Q;
+ }
+
+ cv_mem->cv_VabstolQMallocDone = FALSE;
+}
+
+/*
+ * cvSensAllocVectors
+ *
+ * Create (through duplication) N_Vectors used for sensitivity analysis,
+ * using the N_Vector 'tmpl' as a template.
+ */
+
+static booleantype cvSensAllocVectors(CVodeMem cv_mem, N_Vector tmpl)
+{
+ int i, j;
+
+ /* Allocate yS */
+ yS = N_VCloneVectorArray(Ns, tmpl);
+ if (yS == NULL) {
+ return(FALSE);
+ }
+
+ /* Allocate ewtS */
+ ewtS = N_VCloneVectorArray(Ns, tmpl);
+ if (ewtS == NULL) {
+ N_VDestroyVectorArray(yS, Ns);
+ return(FALSE);
+ }
+
+ /* Allocate acorS */
+ acorS = N_VCloneVectorArray(Ns, tmpl);
+ if (acorS == NULL) {
+ N_VDestroyVectorArray(yS, Ns);
+ N_VDestroyVectorArray(ewtS, Ns);
+ return(FALSE);
+ }
+
+ /* Allocate tempvS */
+ tempvS = N_VCloneVectorArray(Ns, tmpl);
+ if (tempvS == NULL) {
+ N_VDestroyVectorArray(yS, Ns);
+ N_VDestroyVectorArray(ewtS, Ns);
+ N_VDestroyVectorArray(acorS, Ns);
+ return(FALSE);
+ }
+
+ /* 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);
+ }
+
+ /* 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);
+ }
+ }
+
+ /* 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);
+ }
+
+ /* Update solver workspace lengths */
+ lrw += (qmax + 6)*Ns*lrw1 + Ns;
+ liw += (qmax + 6)*Ns*liw1 + Ns;
+
+ /* Store the value of qmax used here */
+ cv_mem->cv_qmax_allocS = qmax;
+
+ return(TRUE);
+}
+
+/*
+ * cvSensFreeVectors
+ *
+ * This routine frees the CVODES vectors allocated in cvSensAllocVectors.
+ */
+
+static void cvSensFreeVectors(CVodeMem cv_mem)
+{
+ int j, maxord;
+
+ 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);
+
+ for (j=0; j<=maxord; j++) N_VDestroyVectorArray(znS[j], Ns);
+
+ free(pbar); pbar = NULL;
+ free(plist); plist = NULL;
+
+ lrw -= (maxord + 6)*Ns*lrw1 + Ns;
+ liw -= (maxord + 6)*Ns*liw1 + Ns;
+
+ if (cv_mem->cv_VabstolSMallocDone) {
+ N_VDestroyVectorArray(VabstolS, Ns);
+ lrw -= Ns*lrw1;
+ liw -= Ns*liw1;
+ }
+ if (cv_mem->cv_SabstolSMallocDone) {
+ free(SabstolS); SabstolS = NULL;
+ lrw -= Ns;
+ }
+ cv_mem->cv_VabstolSMallocDone = FALSE;
+ cv_mem->cv_SabstolSMallocDone = FALSE;
+}
+
+/*
+ * cvQuadSensAllocVectors
+ *
+ * Create (through duplication) N_Vectors used for quadrature sensitivity analysis,
+ * using the N_Vector 'tmpl' as a template.
+ */
+
+static booleantype cvQuadSensAllocVectors(CVodeMem cv_mem, N_Vector tmpl)
+{
+ int i, j;
+
+ /* Allocate ftempQ */
+ ftempQ = N_VClone(tmpl);
+ if (ftempQ == NULL) {
+ return(FALSE);
+ }
+
+ /* Allocate yQS */
+ yQS = N_VCloneVectorArray(Ns, tmpl);
+ if (yQS == NULL) {
+ N_VDestroy(ftempQ);
+ return(FALSE);
+ }
+
+ /* Allocate ewtQS */
+ ewtQS = N_VCloneVectorArray(Ns, tmpl);
+ if (ewtQS == NULL) {
+ N_VDestroy(ftempQ);
+ N_VDestroyVectorArray(yQS, Ns);
+ return(FALSE);
+ }
+
+ /* Allocate acorQS */
+ acorQS = N_VCloneVectorArray(Ns, tmpl);
+ if (acorQS == NULL) {
+ N_VDestroy(ftempQ);
+ N_VDestroyVectorArray(yQS, Ns);
+ N_VDestroyVectorArray(ewtQS, Ns);
+ return(FALSE);
+ }
+
+ /* 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);
+ }
+
+ /* 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);
+ }
+ }
+
+ /* Update solver workspace lengths */
+ lrw += (qmax + 5)*Ns*lrw1Q;
+ liw += (qmax + 5)*Ns*liw1Q;
+
+ /* Store the value of qmax used here */
+ cv_mem->cv_qmax_allocQS = qmax;
+
+ return(TRUE);
+}
+
+/*
+ * cvQuadSensFreeVectors
+ *
+ * This routine frees the CVODES vectors allocated in cvQuadSensAllocVectors.
+ */
+
+static void cvQuadSensFreeVectors(CVodeMem cv_mem)
+{
+ int j, maxord;
+
+ maxord = cv_mem->cv_qmax_allocQS;
+
+ N_VDestroy(ftempQ);
+
+ N_VDestroyVectorArray(yQS, Ns);
+ N_VDestroyVectorArray(ewtQS, Ns);
+ N_VDestroyVectorArray(acorQS, Ns);
+ N_VDestroyVectorArray(tempvQS, Ns);
+
+ for (j=0; j<=maxord; j++) N_VDestroyVectorArray(znQS[j], Ns);
+
+ lrw -= (maxord + 5)*Ns*lrw1Q;
+ liw -= (maxord + 5)*Ns*liw1Q;
+
+ if (cv_mem->cv_VabstolQSMallocDone) {
+ N_VDestroyVectorArray(VabstolQS, Ns);
+ lrw -= Ns*lrw1Q;
+ liw -= Ns*liw1Q;
+ }
+ if (cv_mem->cv_SabstolQSMallocDone) {
+ free(SabstolQS); SabstolQS = NULL;
+ lrw -= Ns;
+ }
+ cv_mem->cv_VabstolQSMallocDone = FALSE;
+ cv_mem->cv_SabstolQSMallocDone = FALSE;
+
+}
+
+
+/*
+ * -----------------------------------------------------------------
+ * Initial stepsize calculation
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * cvHin
+ *
+ * This routine computes a tentative initial step size h0.
+ * If tout is too close to tn (= t0), then cvHin returns CV_TOO_CLOSE
+ * and h remains uninitialized. Note that here tout is either the value
+ * passed to CVode at the first call or the value of tstop (if tstop is
+ * enabled and it is closer to t0=tn than tout).
+ * If any RHS function fails unrecoverably, cvHin returns CV_*RHSFUNC_FAIL.
+ * If any RHS function fails recoverably too many times and recovery is
+ * not possible, cvHin returns CV_REPTD_*RHSFUNC_ERR.
+ * Otherwise, cvHin sets h to the chosen value h0 and returns CV_SUCCESS.
+ *
+ * The algorithm used seeks to find h0 as a solution of
+ * (WRMS norm of (h0^2 ydd / 2)) = 1,
+ * where ydd = estimated second derivative of y. Here, y includes
+ * all variables considered in the error test.
+ *
+ * We start with an initial estimate equal to the geometric mean of the
+ * lower and upper bounds on the step size.
+ *
+ * Loop up to MAX_ITERS times to find h0.
+ * Stop if new and previous values differ by a factor < 2.
+ * Stop if hnew/hg > 2 after one iteration, as this probably means
+ * that the ydd value is bad because of cancellation error.
+ *
+ * For each new proposed hg, we allow MAX_ITERS attempts to
+ * resolve a possible recoverable failure from f() by reducing
+ * the proposed stepsize by a factor of 0.2. If a legal stepsize
+ * still cannot be found, fall back on a previous value if possible,
+ * or else return CV_REPTD_RHSFUNC_ERR.
+ *
+ * Finally, we apply a bias (0.5) and verify that h0 is within bounds.
+ */
+
+static int cvHin(CVodeMem cv_mem, realtype tout)
+{
+ int retval, sign, count1, count2;
+ realtype tdiff, tdist, tround, hlb, hub;
+ realtype hg, hgs, hs, hnew, hrat, h0, yddnrm;
+ booleantype hgOK, hnewOK;
+
+ /* If tout is too close to tn, give up */
+
+ if ((tdiff = tout-tn) == ZERO) return(CV_TOO_CLOSE);
+
+ sign = (tdiff > ZERO) ? 1 : -1;
+ tdist = ABS(tdiff);
+ tround = uround * MAX(ABS(tn), ABS(tout));
+
+ if (tdist < TWO*tround) return(CV_TOO_CLOSE);
+
+ /*
+ Set lower and upper bounds on h0, and take geometric mean
+ as first trial value.
+ Exit with this value if the bounds cross each other.
+ */
+
+ hlb = HLB_FACTOR * tround;
+ hub = cvUpperBoundH0(cv_mem, tdist);
+
+ hg = RSqrt(hlb*hub);
+
+ if (hub < hlb) {
+ if (sign == -1) h = -hg;
+ else h = hg;
+ return(CV_SUCCESS);
+ }
+
+ /* Outer loop */
+
+ hnewOK = FALSE;
+ hs = hg; /* safeguard against 'uninitialized variable' warning */
+
+ for(count1 = 1; count1 <= MAX_ITERS; count1++) {
+
+ /* Attempts to estimate ydd */
+
+ hgOK = FALSE;
+
+ for (count2 = 1; count2 <= MAX_ITERS; count2++) {
+ hgs = hg*sign;
+ retval = cvYddNorm(cv_mem, hgs, &yddnrm);
+ /* 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;}
+ /* A RHS function failed recoverably; cut step size and test it again */
+ hg *= POINT2;
+ }
+
+ /* If a RHS function failed recoverably MAX_ITERS times */
+
+ if (!hgOK) {
+ /* Exit if this is the first or second pass. No recovery possible */
+ if (count1 <= 2)
+ if (retval == RHSFUNC_RECVR) return(CV_REPTD_RHSFUNC_ERR);
+ if (retval == QRHSFUNC_RECVR) return(CV_REPTD_QRHSFUNC_ERR);
+ if (retval == SRHSFUNC_RECVR) return(CV_REPTD_SRHSFUNC_ERR);
+ /* We have a fall-back option. The value hs is a previous hnew which
+ passed through f(). Use it and break */
+ hnew = hs;
+ break;
+ }
+
+ /* The proposed step size is feasible. Save it. */
+ hs = hg;
+
+ /* If the stopping criteria was met, or if this is the last pass, stop */
+ if ( (hnewOK) || (count1 == MAX_ITERS)) {hnew = hg; break;}
+
+ /* Propose new step size */
+ hnew = (yddnrm*hub*hub > TWO) ? RSqrt(TWO/yddnrm) : RSqrt(hg*hub);
+ 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;
+ }
+
+ /* After one pass, if ydd seems to be bad, use fall-back value. */
+ if ((count1 > 1) && (hrat > TWO)) {
+ hnew = hg;
+ hnewOK = TRUE;
+ }
+
+ /* Send this value back through f() */
+ hg = hnew;
+
+ }
+
+ /* Apply bounds, bias factor, and attach sign */
+
+ h0 = H_BIAS*hnew;
+ if (h0 < hlb) h0 = hlb;
+ if (h0 > hub) h0 = hub;
+ if (sign == -1) h0 = -h0;
+ h = h0;
+
+ return(CV_SUCCESS);
+}
+
+/*
+ * cvUpperBoundH0
+ *
+ * This routine sets an upper bound on abs(h0) based on
+ * tdist = tn - t0 and the values of y[i]/y'[i].
+ */
+
+static realtype cvUpperBoundH0(CVodeMem cv_mem, realtype tdist)
+{
+ realtype hub_inv, hubQ_inv, hubS_inv, hubQS_inv, hub;
+ N_Vector temp1, temp2;
+ N_Vector tempQ1, tempQ2;
+ N_Vector *tempS1;
+ N_Vector *tempQS1;
+ int is;
+
+ /*
+ * Bound based on |y|/|y'| -- allow at most an increase of
+ * HUB_FACTOR in y0 (based on a forward Euler step). The weight
+ * factor is used as a safeguard against zero components in y0.
+ */
+
+ temp1 = tempv;
+ temp2 = acor;
+
+ N_VAbs(zn[0], temp2);
+ efun(zn[0], temp1, e_data);
+ N_VInv(temp1, temp1);
+ N_VLinearSum(HUB_FACTOR, temp2, ONE, temp1, temp1);
+
+ N_VAbs(zn[1], temp2);
+
+ N_VDiv(temp2, temp1, temp1);
+ hub_inv = N_VMaxNorm(temp1);
+
+ /* Bound based on |yQ|/|yQ'| */
+
+ if (quadr && errconQ) {
+
+ tempQ1 = tempvQ;
+ tempQ2 = acorQ;
+
+ N_VAbs(znQ[0], tempQ2);
+ cvQuadEwtSet(cv_mem, znQ[0], tempQ1);
+ N_VInv(tempQ1, tempQ1);
+ N_VLinearSum(HUB_FACTOR, tempQ2, ONE, tempQ1, tempQ1);
+
+ N_VAbs(znQ[1], tempQ2);
+
+ N_VDiv(tempQ2, tempQ1, tempQ1);
+ hubQ_inv = N_VMaxNorm(tempQ1);
+
+ if (hubQ_inv > hub_inv) hub_inv = hubQ_inv;
+
+ }
+
+ /* Bound based on |yS|/|yS'| */
+
+ if (sensi && errconS) {
+
+ tempS1 = acorS;
+ cvSensEwtSet(cv_mem, znS[0], tempS1);
+
+ for (is=0; is<Ns; is++) {
+
+ N_VAbs(znS[0][is], temp2);
+ N_VInv(tempS1[is], temp1);
+ N_VLinearSum(HUB_FACTOR, temp2, ONE, temp1, temp1);
+
+ N_VAbs(znS[1][is], temp2);
+
+ N_VDiv(temp2, temp1, temp1);
+ hubS_inv = N_VMaxNorm(temp1);
+
+ if (hubS_inv > hub_inv) hub_inv = hubS_inv;
+
+ }
+
+ }
+
+ /* Bound based on |yQS|/|yQS'| */
+
+ if (quadr_sensi && errconQS) {
+
+ tempQ1 = tempvQ;
+ tempQ2 = acorQ;
+
+ tempQS1 = acorQS;
+ cvQuadSensEwtSet(cv_mem, znQS[0], tempQS1);
+
+ for (is=0; is<Ns; is++) {
+
+ N_VAbs(znQS[0][is], tempQ2);
+ N_VInv(tempQS1[is], tempQ1);
+ N_VLinearSum(HUB_FACTOR, tempQ2, ONE, tempQ1, tempQ1);
+
+ N_VAbs(znQS[1][is], tempQ2);
+
+ N_VDiv(tempQ2, tempQ1, tempQ1);
+ hubQS_inv = N_VMaxNorm(tempQ1);
+
+ if (hubQS_inv > hub_inv) hub_inv = hubQS_inv;
+
+ }
+
+ }
+
+
+ /*
+ * bound based on tdist -- allow at most a step of magnitude
+ * HUB_FACTOR * tdist
+ */
+
+ hub = HUB_FACTOR*tdist;
+
+ /* Use the smaler of the two */
+
+ if (hub*hub_inv > ONE) hub = ONE/hub_inv;
+
+ return(hub);
+}
+
+/*
+ * cvYddNorm
+ *
+ * This routine computes an estimate of the second derivative of Y
+ * using a difference quotient, and returns its WRMS norm.
+ *
+ * Y contains all variables included in the error test.
+ */
+
+static int cvYddNorm(CVodeMem cv_mem, realtype hg, realtype *yddnrm)
+{
+ int retval, is;
+ N_Vector wrk1, wrk2;
+
+ /* y <- h*y'(t) + y(t) */
+
+ N_VLinearSum(hg, zn[1], ONE, zn[0], y);
+
+ if (sensi && errconS)
+ for (is=0; is<Ns; is++)
+ N_VLinearSum(hg, znS[1][is], ONE, znS[0][is], yS[is]);
+
+ /* tempv <- f(t+h, h*y'(t)+y(t)) */
+
+ retval = f(tn+hg, y, tempv, user_data);
+ 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 (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 (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);
+
+ nfQSe++;
+ if (retval < 0) return(CV_QSRHSFUNC_FAIL);
+ if (retval > 0) return(QSRHSFUNC_RECVR);
+ }
+
+ /* 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);
+
+ 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 (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]);
+ }
+ *yddnrm = cvSensUpdateNorm(cv_mem, *yddnrm, tempvS, 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]);
+ }
+ *yddnrm = cvQuadSensUpdateNorm(cv_mem, *yddnrm, tempvQS, ewtQS);
+ }
+
+ return(CV_SUCCESS);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Initial setup
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * cvInitialSetup
+ *
+ * This routine performs input consistency checks at the first step.
+ * If needed, it also checks the linear solver module and calls the
+ * linear solver initialization routine.
+ */
+
+static int cvInitialSetup(CVodeMem cv_mem)
+{
+ int ier;
+
+ /* Did the user specify tolerances? */
+ if (itol == CV_NN) {
+ cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVode", 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;
+
+ /* Load intial error weights */
+ ier = efun(zn[0], ewt, e_data);
+ if (ier != 0) {
+ if (itol == CV_WF)
+ cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVode", MSGCV_EWT_FAIL);
+ else
+ cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVode", MSGCV_BAD_EWT);
+ return(CV_ILL_INPUT);
+ }
+
+ /* Quadrature initial setup */
+
+ if (quadr && errconQ) {
+
+ /* Did the user specify tolerances? */
+ if (itolQ == CV_NN) {
+ cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVode", MSGCV_NO_TOLQ);
+ return(CV_ILL_INPUT);
+ }
+
+ /* Load ewtQ */
+ ier = cvQuadEwtSet(cv_mem, znQ[0], ewtQ);
+ if (ier != 0) {
+ cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVode", MSGCV_BAD_EWTQ);
+ return(CV_ILL_INPUT);
+ }
+
+ }
+
+ if (!quadr) errconQ = FALSE;
+
+ /* Forward sensitivity initial setup */
+
+ if (sensi) {
+
+ /* Did the user specify tolerances? */
+ if (itolS == CV_NN) {
+ cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVode", 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", "CVode", MSGCV_NULL_P);
+ return(CV_ILL_INPUT);
+ }
+
+ /* Load ewtS */
+ ier = cvSensEwtSet(cv_mem, znS[0], ewtS);
+ if (ier != 0) {
+ cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVode", MSGCV_BAD_EWTS);
+ return(CV_ILL_INPUT);
+ }
+
+ }
+
+ /* FSA of quadrature variables */
+
+ if (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) {
+
+ /* Test if quadratures are defined, so we can use fQ */
+ if (!quadr) {
+ cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVode", MSGCV_NULL_FQ);
+ return(CV_ILL_INPUT);
+ }
+
+ /* Test if we have the problem parameters */
+ if(p == NULL) {
+ cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVode", MSGCV_NULL_P);
+ return(CV_ILL_INPUT);
+ }
+
+ }
+
+ if (errconQS) {
+
+ /* Did the user specify tolerances? */
+ if (itolQS == CV_NN) {
+ cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVode", 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", "CVode", MSGCV_NO_TOLQ);
+ return(CV_ILL_INPUT);
+ }
+
+ /* Load ewtQS */
+ ier = cvQuadSensEwtSet(cv_mem, znQS[0], ewtQS);
+ if (ier != 0) {
+ cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVode", MSGCV_BAD_EWTQS);
+ return(CV_ILL_INPUT);
+ }
+
+ }
+
+ } else {
+
+ errconQS = FALSE;
+
+ }
+
+ /* 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", "CVode", MSGCV_LSOLVE_NULL);
+ return(CV_ILL_INPUT);
+ }
+ if (linit != NULL) {
+ ier = linit(cv_mem);
+ if (ier != 0) {
+ cvProcessError(cv_mem, CV_LINIT_FAIL, "CVODES", "CVode", MSGCV_LINIT_FAIL);
+ return(CV_LINIT_FAIL);
+ }
+ }
+ }
+
+ return(CV_SUCCESS);
+}
+
+/*
+ * cvEwtSet
+ *
+ * This routine is responsible for setting the error weight vector ewt,
+ * according to tol_type, as follows:
+ *
+ * (1) ewt[i] = 1 / (reltol * ABS(ycur[i]) + *abstol), i=0,...,neq-1
+ * if tol_type = CV_SS
+ * (2) ewt[i] = 1 / (reltol * ABS(ycur[i]) + abstol[i]), i=0,...,neq-1
+ * if tol_type = CV_SV
+ *
+ * cvEwtSet returns 0 if ewt is successfully set as above to a
+ * positive vector and -1 otherwise. In the latter case, ewt is
+ * considered undefined.
+ *
+ * All the real work is done in the routines cvEwtSetSS, cvEwtSetSV.
+ */
+
+int cvEwtSet(N_Vector ycur, N_Vector weight, void *data)
+{
+ CVodeMem cv_mem;
+ int flag = 0;
+
+ /* data points to cv_mem here */
+
+ cv_mem = (CVodeMem) data;
+
+ switch(itol) {
+ case CV_SS:
+ flag = cvEwtSetSS(cv_mem, ycur, weight);
+ break;
+ case CV_SV:
+ flag = cvEwtSetSV(cv_mem, ycur, weight);
+ break;
+ }
+
+ return(flag);
+}
+
+/*
+ * cvEwtSetSS
+ *
+ * This routine sets ewt as decribed above in the case tol_type = CV_SS.
+ * It tests for non-positive components before inverting. cvEwtSetSS
+ * returns 0 if ewt is successfully set to a positive vector
+ * and -1 otherwise. In the latter case, ewt is considered undefined.
+ */
+
+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);
+
+ return(0);
+}
+
+/*
+ * cvEwtSetSV
+ *
+ * This routine sets ewt as decribed above in the case tol_type = CV_SV.
+ * It tests for non-positive components before inverting. cvEwtSetSV
+ * returns 0 if ewt is successfully set to a positive vector
+ * and -1 otherwise. In the latter case, ewt is considered undefined.
+ */
+
+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);
+ return(0);
+}
+
+/*
+ * cvQuadEwtSet
+ *
+ */
+
+static int cvQuadEwtSet(CVodeMem cv_mem, N_Vector qcur, N_Vector weightQ)
+{
+ int flag=0;
+
+ switch (itolQ) {
+ case CV_SS:
+ flag = cvQuadEwtSetSS(cv_mem, qcur, weightQ);
+ break;
+ case CV_SV:
+ flag = cvQuadEwtSetSV(cv_mem, qcur, weightQ);
+ break;
+ }
+
+ return(flag);
+
+}
+
+/*
+ * cvQuadEwtSetSS
+ *
+ */
+
+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);
+
+ return(0);
+}
+
+/*
+ * cvQuadEwtSetSV
+ *
+ */
+
+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);
+
+ return(0);
+}
+
+/*
+ * cvSensEwtSet
+ *
+ */
+
+static int cvSensEwtSet(CVodeMem cv_mem, N_Vector *yScur, N_Vector *weightS)
+{
+ int flag=0;
+
+ switch (itolS) {
+ case CV_EE:
+ flag = cvSensEwtSetEE(cv_mem, yScur, weightS);
+ break;
+ case CV_SS:
+ flag = cvSensEwtSetSS(cv_mem, yScur, weightS);
+ break;
+ case CV_SV:
+ flag = cvSensEwtSetSV(cv_mem, yScur, weightS);
+ break;
+ }
+
+ return(flag);
+}
+
+/*
+ * cvSensEwtSetEE
+ *
+ * In this case, the error weight vector for the i-th sensitivity is set to
+ *
+ * ewtS_i = pbar_i * efun(pbar_i*yS_i)
+ *
+ * In other words, the scaled sensitivity pbar_i * yS_i has the same error
+ * weight vector calculation as the solution vector.
+ *
+ */
+
+static int cvSensEwtSetEE(CVodeMem cv_mem, N_Vector *yScur, N_Vector *weightS)
+{
+ int is;
+ N_Vector pyS;
+ int flag;
+
+ /* Use tempvS[0] as temporary storage for the scaled sensitivity */
+ pyS = tempvS[0];
+
+ for (is=0; is<Ns; is++) {
+ N_VScale(pbar[is], yScur[is], pyS);
+ flag = efun(pyS, weightS[is], e_data);
+ if (flag != 0) return(-1);
+ N_VScale(pbar[is], weightS[is], weightS[is]);
+ }
+
+ return(0);
+}
+
+/*
+ * cvSensEwtSetSS
+ *
+ */
+
+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]);
+ }
+ return(0);
+}
+
+/*
+ * cvSensEwtSetSV
+ *
+ */
+
+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]);
+ }
+
+ return(0);
+}
+
+/*
+ * cvQuadSensEwtSet
+ *
+ */
+
+static int cvQuadSensEwtSet(CVodeMem cv_mem, N_Vector *yQScur, N_Vector *weightQS)
+{
+ int flag=0;
+
+ switch (itolQS) {
+ case CV_EE:
+ flag = cvQuadSensEwtSetEE(cv_mem, yQScur, weightQS);
+ break;
+ case CV_SS:
+ flag = cvQuadSensEwtSetSS(cv_mem, yQScur, weightQS);
+ break;
+ case CV_SV:
+ flag = cvQuadSensEwtSetSV(cv_mem, yQScur, weightQS);
+ break;
+ }
+
+ return(flag);
+}
+
+/*
+ * cvQuadSensEwtSetEE
+ *
+ * In this case, the error weight vector for the i-th quadrature sensitivity
+ * is set to
+ *
+ * ewtQS_i = pbar_i * cvQuadEwtSet(pbar_i*yQS_i)
+ *
+ * In other words, the scaled sensitivity pbar_i * yQS_i has the same error
+ * weight vector calculation as the quadrature vector.
+ *
+ */
+static int cvQuadSensEwtSetEE(CVodeMem cv_mem, N_Vector *yQScur, N_Vector *weightQS)
+{
+ int is;
+ N_Vector pyS;
+ int flag;
+
+ /* Use tempvQS[0] as temporary storage for the scaled sensitivity */
+ pyS = tempvQS[0];
+
+ for (is=0; is<Ns; is++) {
+ N_VScale(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]);
+ }
+
+ return(0);
+}
+
+static int cvQuadSensEwtSetSS(CVodeMem cv_mem, N_Vector *yQScur, N_Vector *weightQS)
+{
+ 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]);
+ }
+
+ return(0);
+}
+
+static int cvQuadSensEwtSetSV(CVodeMem cv_mem, N_Vector *yQScur, N_Vector *weightQS)
+{
+ 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]);
+ }
+
+ return(0);
+}
+
+
+
+/*
+ * -----------------------------------------------------------------
+ * Main cvStep function
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * cvStep
+ *
+ * This routine performs one internal cvode step, from tn to tn + h.
+ * It calls other routines to do all the work.
+ *
+ * The main operations done here are as follows:
+ * - preliminary adjustments if a new step size was chosen;
+ * - prediction of the Nordsieck history array zn at tn + h;
+ * - setting of multistep method coefficients and test quantities;
+ * - solution of the nonlinear system;
+ * - testing the local error;
+ * - updating zn and other state data if successful;
+ * - resetting stepsize and order for the next step.
+ * - if SLDET is on, check for stability, reduce order if necessary.
+ * On a failure in the nonlinear system solution or error test, the
+ * step may be reattempted, depending on the nature of the failure.
+ */
+
+static int cvStep(CVodeMem cv_mem)
+{
+ realtype saved_t, dsm, dsmQ, dsmS, dsmQS;
+ booleantype do_sensi_stg, do_sensi_stg1;
+ int ncf, ncfS;
+ int nef, nefQ, nefS, nefQS;
+ int nflag, kflag, eflag;
+ int retval, is;
+
+ /* Are we computing sensitivities with a staggered approach? */
+
+ do_sensi_stg = (sensi && (ism==CV_STAGGERED));
+ do_sensi_stg1 = (sensi && (ism==CV_STAGGERED1));
+
+ /* Initialize local counters for convergence and error test failures */
+
+ ncf = nef = 0;
+ nefQ = 0;
+ ncfS = nefS = 0;
+ if (do_sensi_stg1) {
+ for (is=0; is<Ns; is++) ncfS1[is] = 0;
+ }
+
+ /* If needed, adjust method parameters */
+
+ if ((nst > 0) && (hprime != h)) cvAdjustParams(cv_mem);
+
+ /* Looping point for attempts to take a step */
+
+ saved_t = tn;
+ nflag = FIRST_CALL;
+
+ loop {
+
+ cvPredict(cv_mem);
+ cvSet(cv_mem);
+
+ /* ------ Correct state variables ------ */
+
+ nflag = cvNls(cv_mem, nflag);
+ kflag = cvHandleNFlag(cv_mem, &nflag, saved_t, &ncf, &ncfn);
+
+ /* Go back in loop if we need to predict again (nflag=PREV_CONV_FAIL) */
+ if (kflag == PREDICT_AGAIN) continue;
+
+ /* Return if nonlinear solve failed and recovery not possible. */
+ if (kflag != DO_ERROR_TEST) return(kflag);
+
+ /* Perform error test (nflag=CV_SUCCESS) */
+ eflag = cvDoErrorTest(cv_mem, &nflag, saved_t, acnrm, &nef, &netf, &dsm);
+
+ /* Go back in loop if we need to predict again (nflag=PREV_ERR_FAIL) */
+ if (eflag == TRY_AGAIN) continue;
+
+ /* Return if error test failed and recovery not possible. */
+ if (eflag != CV_SUCCESS) return(eflag);
+
+ /* Error test passed (eflag=CV_SUCCESS, nflag=CV_SUCCESS), go on */
+
+ /* ------ Correct the quadrature variables ------ */
+
+ if (quadr) {
+
+ ncf = nef = 0; /* reset counters for states */
+
+ nflag = cvQuadNls(cv_mem);
+ kflag = cvHandleNFlag(cv_mem, &nflag, saved_t, &ncf, &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 (eflag == TRY_AGAIN) continue;
+ if (eflag != CV_SUCCESS) return(eflag);
+
+ /* Set dsm = max(dsm, dsmQ) to be used in cvPrepareNextStep */
+ if (dsmQ > dsm) dsm = dsmQ;
+ }
+
+ }
+
+ /* ------ Correct the sensitivity variables (STAGGERED or STAGGERED1) ------- */
+
+ if (do_sensi_stg || do_sensi_stg1) {
+
+ ncf = nef = 0; /* reset counters for states */
+ if (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++;
+ if (retval < 0) return(CV_RHSFUNC_FAIL);
+ if (retval > 0) {
+ nflag = PREV_CONV_FAIL;
+ continue;
+ }
+
+ if (do_sensi_stg) {
+ /* Nonlinear solve for sensitivities (all-at-once) */
+ nflag = cvStgrNls(cv_mem);
+ kflag = cvHandleNFlag(cv_mem, &nflag, saved_t, &ncfS, &ncfnS);
+ } else {
+ /* Nonlinear solve for sensitivities (one-by-one) */
+ for (is=0; is<Ns; is++) {
+ nflag = cvStgr1Nls(cv_mem, is);
+ kflag = cvHandleNFlag(cv_mem, &nflag, saved_t, &ncfS1[is], &ncfnS1[is]);
+ if (kflag != DO_ERROR_TEST) break;
+ }
+ }
+
+ if (kflag == PREDICT_AGAIN) continue;
+ if (kflag != DO_ERROR_TEST) return(kflag);
+
+ /* Error test on sensitivities */
+ if (errconS) {
+
+ if (do_sensi_stg1) acnrmS = cvSensNorm(cv_mem, acorS, ewtS);
+
+ eflag = cvDoErrorTest(cv_mem, &nflag, saved_t, acnrmS, &nefS, &netfS, &dsmS);
+
+ if (eflag == TRY_AGAIN) continue;
+ if (eflag != CV_SUCCESS) return(eflag);
+
+ /* Set dsm = max(dsm, dsmS) to be used in cvPrepareNextStep */
+ if (dsmS > dsm) dsm = dsmS;
+
+ }
+
+ }
+
+ /* ------ Correct the quadrature sensitivity variables ------ */
+
+ if (quadr_sensi) {
+
+ /* Reset local convergence and error test failure counters */
+ ncf = nef = 0;
+ if (quadr) nefQ = 0;
+ if (do_sensi_stg) ncfS = nefS = 0;
+ if (do_sensi_stg1) {
+ for (is=0; is<Ns; is++) ncfS1[is] = 0;
+ nefS = 0;
+ }
+
+ /* Note that ftempQ contains yQdot evaluated at the converged y
+ * (stored in cvQuadNls) and can be used in evaluating fQS */
+
+ nflag = cvQuadSensNls(cv_mem);
+ kflag = cvHandleNFlag(cv_mem, &nflag, saved_t, &ncf, &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 (eflag == TRY_AGAIN) continue;
+ if (eflag != CV_SUCCESS) return(eflag);
+
+ /* Set dsm = max(dsm, dsmQS) to be used in cvPrepareNextStep */
+ if (dsmQS > dsm) dsm = dsmQS;
+ }
+
+
+ }
+
+
+ /* Everything went fine; exit loop */
+ break;
+
+ }
+
+ /* Nonlinear system solve and error test were both successful.
+ Update data, and consider change of step and/or order. */
+
+ cvCompleteStep(cv_mem);
+
+ cvPrepareNextStep(cv_mem, dsm);
+
+ /* If Stablilty Limit Detection is turned on, call stability limit
+ detection routine for possible order reduction. */
+
+ if (sldeton) cvBDFStab(cv_mem);
+
+ etamax = (nst <= SMALL_NST) ? ETAMX2 : ETAMX3;
+
+ /* Finally, we rescale the acor array to be the
+ estimated local error vector. */
+
+ N_VScale(tq[2], acor, acor);
+
+ if (quadr)
+ N_VScale(tq[2], acorQ, acorQ);
+
+ if (sensi)
+ for (is=0; is<Ns; is++)
+ N_VScale(tq[2], acorS[is], acorS[is]);
+
+ if (quadr_sensi)
+ for (is=0; is<Ns; is++)
+ N_VScale(tq[2], acorQS[is], acorQS[is]);
+
+ return(CV_SUCCESS);
+
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Function called at beginning of step
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * cvAdjustParams
+ *
+ * This routine is called when a change in step size was decided upon,
+ * and it handles the required adjustments to the history array zn.
+ * If there is to be a change in order, we call cvAdjustOrder and reset
+ * q, L = q+1, and qwait. Then in any case, we call cvRescale, which
+ * resets h and rescales the Nordsieck array.
+ */
+
+static void cvAdjustParams(CVodeMem cv_mem)
+{
+ if (qprime != q) {
+ cvAdjustOrder(cv_mem, qprime-q);
+ q = qprime;
+ L = q+1;
+ qwait = L;
+ }
+ cvRescale(cv_mem);
+}
+
+/*
+ * cvAdjustOrder
+ *
+ * This routine is a high level routine which handles an order
+ * change by an amount deltaq (= +1 or -1). If a decrease in order
+ * is requested and q==2, then the routine returns immediately.
+ * Otherwise cvAdjustAdams or cvAdjustBDF is called to handle the
+ * order change (depending on the value of lmm).
+ */
+
+static void cvAdjustOrder(CVodeMem cv_mem, int deltaq)
+{
+ if ((q==2) && (deltaq != 1)) return;
+
+ switch(lmm){
+ case CV_ADAMS:
+ cvAdjustAdams(cv_mem, deltaq);
+ break;
+ case CV_BDF:
+ cvAdjustBDF(cv_mem, deltaq);
+ break;
+ }
+}
+
+/*
+ * cvAdjustAdams
+ *
+ * This routine adjusts the history array on a change of order q by
+ * deltaq, in the case that lmm == CV_ADAMS.
+ */
+
+static void cvAdjustAdams(CVodeMem cv_mem, int deltaq)
+{
+ int i, j;
+ int is;
+ realtype xi, hsum;
+
+ /* 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]);
+ return;
+ }
+
+ /*
+ * On an order decrease, each zn[j] is adjusted by a multiple of zn[q].
+ * The coeffs. in the adjustment are the coeffs. of the polynomial:
+ * x
+ * q * INT { u * ( u + xi_1 ) * ... * ( u + xi_{q-2} ) } du
+ * 0
+ * where xi_j = [t_n - t_(n-j)]/h => xi_0 = 0
+ */
+
+ for (i=0; i <= qmax; i++) l[i] = ZERO;
+ 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 <= q-2; j++) l[j+1] = q * (l[j] / (j+1));
+
+ for (j=2; j < q; j++)
+ N_VLinearSum(-l[j], zn[q], ONE, zn[j], zn[j]);
+
+ if (quadr)
+ for (j=2; j < q; j++)
+ N_VLinearSum(-l[j], znQ[q], ONE, znQ[j], 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]);
+
+}
+
+/*
+ * cvAdjustBDF
+ *
+ * This is a high level routine which handles adjustments to the
+ * history array on a change of order by deltaq in the case that
+ * lmm == CV_BDF. cvAdjustBDF calls cvIncreaseBDF if deltaq = +1 and
+ * cvDecreaseBDF if deltaq = -1 to do the actual work.
+ */
+
+static void cvAdjustBDF(CVodeMem cv_mem, int deltaq)
+{
+ switch(deltaq) {
+ case 1:
+ cvIncreaseBDF(cv_mem);
+ return;
+ case -1:
+ cvDecreaseBDF(cv_mem);
+ return;
+ }
+}
+
+/*
+ * cvIncreaseBDF
+ *
+ * This routine adjusts the history array on an increase in the
+ * order q in the case that lmm == CV_BDF.
+ * A new column zn[q+1] is set equal to a multiple of the saved
+ * vector (= acor) in zn[indx_acor]. Then each zn[j] is adjusted by
+ * a multiple of zn[q+1]. The coefficients in the adjustment are the
+ * coefficients of the polynomial x*x*(x+xi_1)*...*(x+xi_j),
+ * where xi_j = [t_n - t_(n-j)]/h.
+ */
+
+static void cvIncreaseBDF(CVodeMem cv_mem)
+{
+ realtype alpha0, alpha1, prod, xi, xiold, hsum, A1;
+ int i, j;
+ int is;
+
+ for (i=0; i <= qmax; i++) l[i] = ZERO;
+ 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;
+ prod *= xi;
+ alpha0 -= ONE / (j+1);
+ alpha1 += ONE / xi;
+ for (i=j+2; i >= 2; i--) l[i] = l[i]*xiold + l[i-1];
+ xiold = xi;
+ }
+ }
+ A1 = (-alpha0 - alpha1) / prod;
+
+ /*
+ zn[indx_acor] contains the value Delta_n = y_n - y_n(0)
+ This value was stored there at the previous successful
+ step (in cvCompleteStep)
+
+ 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]);
+
+ 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 (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 (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]);
+ }
+ }
+
+}
+
+/*
+ * cvDecreaseBDF
+ *
+ * This routine adjusts the history array on a decrease in the
+ * order q in the case that lmm == CV_BDF.
+ * Each zn[j] is adjusted by a multiple of zn[q]. The coefficients
+ * in the adjustment are the coefficients of the polynomial
+ * x*x*(x+xi_1)*...*(x+xi_j), where xi_j = [t_n - t_(n-j)]/h.
+ */
+
+static void cvDecreaseBDF(CVodeMem cv_mem)
+{
+ realtype hsum, xi;
+ int i, j;
+ int is;
+
+ for (i=0; i <= qmax; i++) l[i] = ZERO;
+ 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=2; j < q; j++)
+ N_VLinearSum(-l[j], zn[q], ONE, zn[j], zn[j]);
+
+ if (quadr) {
+ for (j=2; j < q; j++)
+ N_VLinearSum(-l[j], znQ[q], ONE, znQ[j], 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 (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]);
+ }
+}
+
+/*
+ * cvRescale
+ *
+ * This routine rescales the Nordsieck array by multiplying the
+ * jth column zn[j] by eta^j, j = 1, ..., q. Then the value of
+ * h is rescaled by eta, and hscale is reset to h.
+ */
+
+static void cvRescale(CVodeMem cv_mem)
+{
+ int j;
+ int is;
+ realtype factor;
+
+ factor = eta;
+ for (j=1; j <= q; j++) {
+
+ N_VScale(factor, zn[j], zn[j]);
+
+ if (quadr)
+ N_VScale(factor, znQ[j], znQ[j]);
+
+ if (sensi)
+ for (is=0; is<Ns; is++)
+ N_VScale(factor, znS[j][is], znS[j][is]);
+
+ if (quadr_sensi)
+ for (is=0; is<Ns; is++)
+ N_VScale(factor, znQS[j][is], znQS[j][is]);
+
+ factor *= eta;
+
+ }
+
+ h = hscale * eta;
+ next_h = h;
+ hscale = h;
+ nscon = 0;
+
+}
+
+/*
+ * cvPredict
+ *
+ * This routine advances tn by the tentative step size h, and computes
+ * the predicted array z_n(0), which is overwritten on zn. The
+ * prediction of zn is done by repeated additions.
+ * If tstop is enabled, it is possible for tn + h to be past tstop by roundoff,
+ * and in that case, we reset tn (after incrementing by h) to tstop.
+ */
+
+static void cvPredict(CVodeMem cv_mem)
+{
+ int j, k;
+ int is;
+
+ tn += h;
+ if (tstopset) {
+ if ((tn - tstop)*h > ZERO) tn = 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]);
+
+ 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 (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 (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]);
+ }
+ }
+
+}
+
+/*
+ * cvSet
+ *
+ * This routine is a high level routine which calls cvSetAdams or
+ * cvSetBDF to set the polynomial l, the test quantity array tq,
+ * and the related variables rl1, gamma, and gamrat.
+ *
+ * The array tq is loaded with constants used in the control of estimated
+ * local errors and in the nonlinear convergence test. Specifically, while
+ * running at order q, the components of tq are as follows:
+ * tq[1] = a coefficient used to get the est. local error at order q-1
+ * tq[2] = a coefficient used to get the est. local error at order q
+ * tq[3] = a coefficient used to get the est. local error at order q+1
+ * tq[4] = constant used in nonlinear iteration convergence test
+ * tq[5] = coefficient used to get the order q+2 derivative vector used in
+ * the est. local error at order q+1
+ */
+
+static void cvSet(CVodeMem cv_mem)
+{
+ switch(lmm) {
+ case CV_ADAMS:
+ cvSetAdams(cv_mem);
+ break;
+ case CV_BDF:
+ 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 */
+}
+
+/*
+ * cvSetAdams
+ *
+ * This routine handles the computation of l and tq for the
+ * case lmm == CV_ADAMS.
+ *
+ * The components of the array l are the coefficients of a
+ * polynomial Lambda(x) = l_0 + l_1 x + ... + l_q x^q, given by
+ * q-1
+ * (d/dx) Lambda(x) = c * PRODUCT (1 + x / xi_i) , where
+ * i=1
+ * Lambda(-1) = 0, Lambda(0) = 1, and c is a normalization factor.
+ * Here xi_i = [t_n - t_(n-i)] / h.
+ *
+ * The array tq is set to test quantities used in the convergence
+ * test, the error test, and the selection of h at a new order.
+ */
+
+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] */
+ return;
+ }
+
+ hsum = cvAdamsStart(cv_mem, m);
+
+ M[0] = cvAltSum(q-1, m, 1);
+ M[1] = cvAltSum(q-1, m, 2);
+
+ cvAdamsFinish(cv_mem, m, M, hsum);
+}
+
+/*
+ * cvAdamsStart
+ *
+ * This routine generates in m[] the coefficients of the product
+ * polynomial needed for the Adams l and tq coefficients for q > 1.
+ */
+
+static realtype cvAdamsStart(CVodeMem cv_mem, realtype m[])
+{
+ realtype hsum, xi_inv, sum;
+ int i, j;
+
+ hsum = 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];
+ /* The m[i] are coefficients of product(1 to j) (1 + x/xi_i) */
+ }
+ return(hsum);
+}
+
+/*
+ * cvAdamsFinish
+ *
+ * This routine completes the calculation of the Adams l and tq.
+ */
+
+static void cvAdamsFinish(CVodeMem cv_mem, realtype m[], realtype M[], realtype hsum)
+{
+ int i;
+ realtype M0_inv, xi, xi_inv;
+
+ 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;
+ xi_inv = ONE / xi;
+
+ tq[2] = M[1] * M0_inv / xi;
+ tq[5] = xi / l[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;
+ }
+
+ tq[4] = nlscoef / tq[2];
+}
+
+/*
+ * cvAltSum
+ *
+ * cvAltSum returns the value of the alternating sum
+ * sum (i= 0 ... iend) [ (-1)^i * (a[i] / (i + k)) ].
+ * If iend < 0 then cvAltSum returns 0.
+ * This operation is needed to compute the integral, from -1 to 0,
+ * of a polynomial x^(k-1) M(x) given the coefficients of M(x).
+ */
+
+static realtype cvAltSum(int iend, realtype a[], int k)
+{
+ int i, sign;
+ realtype sum;
+
+ if (iend < 0) return(ZERO);
+
+ sum = ZERO;
+ sign = 1;
+ for (i=0; i <= iend; i++) {
+ sum += sign * (a[i] / (i+k));
+ sign = -sign;
+ }
+ return(sum);
+}
+
+/*
+ * cvSetBDF
+ *
+ * This routine computes the coefficients l and tq in the case
+ * lmm == CV_BDF. cvSetBDF calls cvSetTqBDF to set the test
+ * quantity array tq.
+ *
+ * The components of the array l are the coefficients of a
+ * polynomial Lambda(x) = l_0 + l_1 x + ... + l_q x^q, given by
+ * q-1
+ * Lambda(x) = (1 + x / xi*_q) * PRODUCT (1 + x / xi_i) , where
+ * i=1
+ * xi_i = [t_n - t_(n-i)] / h.
+ *
+ * The array tq is set to test quantities used in the convergence
+ * test, the error test, and the selection of h at a new order.
+ */
+
+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;
+ alpha0 = alpha0_hat = -ONE;
+ hsum = h;
+ if (q > 1) {
+ for (j=2; j < q; j++) {
+ hsum += tau[j-1];
+ xi_inv = h / hsum;
+ alpha0 -= ONE / j;
+ for (i=j; i >= 1; i--) l[i] += 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;
+ }
+
+ cvSetTqBDF(cv_mem, hsum, alpha0, alpha0_hat, xi_inv, xistar_inv);
+}
+
+/*
+ * cvSetTqBDF
+ *
+ * This routine sets the test quantity array tq in the case
+ * lmm == CV_BDF.
+ */
+
+static void cvSetTqBDF(CVodeMem cv_mem, realtype hsum, realtype alpha0,
+ realtype alpha0_hat, realtype xi_inv, realtype xistar_inv)
+{
+ realtype A1, A2, A3, A4, A5, A6;
+ realtype C, Cpinv, Cppinv;
+
+ A1 = ONE - alpha0_hat + alpha0;
+ A2 = ONE + q * A1;
+ tq[2] = ABS(A1 / (alpha0 * A2));
+ tq[5] = ABS(A2 * xistar_inv / (l[q] * xi_inv));
+ if (qwait == 1) {
+ if (q > 1) {
+ C = xistar_inv / l[q];
+ A3 = alpha0 + ONE / q;
+ A4 = alpha0_hat + xi_inv;
+ Cpinv = (ONE - A4 + A3) / A3;
+ tq[1] = ABS(C * Cpinv);
+ }
+ else tq[1] = ONE;
+ hsum += tau[q];
+ xi_inv = h / hsum;
+ A5 = alpha0 - (ONE / (q+1));
+ A6 = alpha0_hat - xi_inv;
+ Cppinv = (ONE - A6 + A5) / A2;
+ tq[3] = ABS(Cppinv / (xi_inv * (q+2) * A5));
+ }
+ tq[4] = nlscoef / tq[2];
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Nonlinear solver functions
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * cvNls
+ *
+ * This routine attempts to solve the nonlinear system associated
+ * with a single implicit step of the linear multistep method.
+ * Depending on iter, it calls cvNlsFunctional or cvNlsNewton
+ * to do the work.
+ */
+
+static int cvNls(CVodeMem cv_mem, int nflag)
+{
+ int flag=CV_SUCCESS;
+
+ switch(iter) {
+ case CV_FUNCTIONAL:
+ flag = cvNlsFunctional(cv_mem);
+ break;
+ case CV_NEWTON:
+ flag = cvNlsNewton(cv_mem, nflag);
+ break;
+ }
+
+ return(flag);
+
+}
+
+/*
+ * cvNlsFunctional
+ *
+ * This routine attempts to solve the nonlinear system using
+ * functional iteration (no matrices involved).
+ *
+ * This routine also handles the functional iteration of the
+ * combined system (states + sensitivities) when sensitivities are
+ * computed using the CV_SIMULTANEOUS approach.
+ *
+ * Possible return values are:
+ *
+ * CV_SUCCESS ---> continue with error test
+ *
+ * CV_RHSFUNC_FAIL -+
+ * CV_SRHSFUNC_FAIL -+-> halt the integration
+ *
+ * CONV_FAIL -+
+ * RHSFUNC_RECVR |-> predict again or stop if too many
+ * SRHSFUNC_RECVR -+
+ *
+ */
+
+static int cvNlsFunctional(CVodeMem cv_mem)
+{
+ int m;
+ realtype del, delS, Del, Delp, dcon;
+ int retval, is;
+ booleantype do_sensi_sim;
+ N_Vector wrk1, wrk2;
+
+ /* Are we computing sensitivities with the CV_SIMULTANEOUS approach? */
+ do_sensi_sim = (sensi && (ism==CV_SIMULTANEOUS));
+
+ /* Initialize counter and evaluate f at predicted y */
+ 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++;
+ 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);
+ if (retval < 0) return(CV_SRHSFUNC_FAIL);
+ if (retval > 0) return(SRHSFUNC_RECVR);
+ }
+
+ /* Initialize correction to zero */
+
+ N_VConst(ZERO, acor);
+ if (do_sensi_sim) {
+ for (is=0; is<Ns; is++)
+ N_VConst(ZERO,acorS[is]);
+ }
+
+ /* Loop until convergence; accumulate corrections in acor */
+
+ loop {
+
+ 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);
+
+ 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]);
+ }
+
+ /* Get WRMS norm of current correction to use in convergence test */
+
+ N_VLinearSum(ONE, tempv, -ONE, acor, acor);
+ if (do_sensi_sim)
+ for (is=0; is<Ns; is++)
+ N_VLinearSum(ONE, tempvS[is], -ONE, acorS[is], acorS[is]);
+
+ del = N_VWrmsNorm(acor, ewt);
+ if (do_sensi_sim)
+ delS = cvSensUpdateNorm(cv_mem, del, acorS, ewtS);
+
+ N_VScale(ONE, tempv, acor);
+ if (do_sensi_sim)
+ for (is=0; is<Ns; is++)
+ N_VScale(ONE, tempvS[is], 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
+ 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
+ del and delS)
+ */
+
+ Del = (do_sensi_sim) ? delS : del;
+ if (m > 0) crate = MAX(CRDOWN * crate, Del / Delp);
+ dcon = Del * MIN(ONE, crate) / tq[4];
+
+ if (dcon <= ONE) {
+ if (m == 0)
+ if (do_sensi_sim && errconS) acnrm = delS;
+ else acnrm = del;
+ else {
+ acnrm = N_VWrmsNorm(acor, ewt);
+ if (do_sensi_sim && errconS)
+ acnrm = cvSensUpdateNorm(cv_mem, acnrm, acorS, ewtS);
+ }
+ 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);
+
+ /* Save norm of correction, evaluate f, and loop again */
+
+ Delp = Del;
+
+ retval = f(tn, y, tempv, user_data);
+ 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);
+ if (retval < 0) return(CV_SRHSFUNC_FAIL);
+ if (retval > 0) return(SRHSFUNC_RECVR);
+ }
+
+ } /* end loop */
+
+}
+
+/*
+ * cvNlsNewton
+ *
+ * This routine handles the Newton iteration. It calls lsetup if
+ * indicated, calls cvNewtonIteration to perform the iteration, and
+ * retries a failed attempt at Newton iteration if that is indicated.
+ * See return values at top of this file.
+ *
+ * This routine also handles the Newton iteration of the combined
+ * system when sensitivities are computed using the CV_SIMULTANEOUS
+ * approach. Since in that case we use a quasi-Newton on the
+ * combined system (by approximating the Jacobian matrix by its
+ * block diagonal) and thus only solve linear systems with
+ * multiple right hand sides (all sharing the same coefficient
+ * matrix - whatever iteration matrix we decide on) we set-up
+ * the linear solver to handle N equations at a time.
+ *
+ * Possible return values:
+ *
+ * CV_SUCCESS ---> continue with error test
+ *
+ * CV_RHSFUNC_FAIL -+
+ * CV_LSETUP_FAIL |
+ * CV_LSOLVE_FAIL |-> halt the integration
+ * CV_SRHSFUNC_FAIL -+
+ *
+ * CONV_FAIL -+
+ * RHSFUNC_RECVR |-> predict again or stop if too many
+ * SRHSFUNC_RECVR -+
+ *
+ */
+
+static int cvNlsNewton(CVodeMem cv_mem, int nflag)
+{
+ N_Vector vtemp1, vtemp2, vtemp3, wrk1, wrk2;
+ int convfail, ier;
+ booleantype callSetup, do_sensi_sim;
+ int retval, is;
+
+ /* Are we computing sensitivities with the CV_SIMULTANEOUS approach? */
+ do_sensi_sim = (sensi && (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 */
+
+ /* 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) {
+ callSetup = (nflag == PREV_CONV_FAIL) || (nflag == PREV_ERR_FAIL) ||
+ (nst == 0) || (nst >= nstlp + MSBP) || (ABS(gamrat-ONE) > DGMAX);
+
+ /* Decide whether to force a call to setup */
+ if (forceSetup) {
+ callSetup = TRUE;
+ convfail = CV_FAIL_OTHER;
+ }
+
+ } else {
+ crate = ONE;
+ crateS = ONE; /* if NO lsetup all conv. rates are set to ONE */
+ callSetup = FALSE;
+ }
+
+ /* 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 {
+
+ retval = f(tn, zn[0], ftemp, user_data);
+ 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);
+ 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;
+ /* 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);
+
+ if (do_sensi_sim)
+ for (is=0; is<Ns; is++) {
+ N_VConst(ZERO, acorS[is]);
+ N_VScale(ONE, znS[0][is], yS[is]);
+ }
+
+ /* Do the Newton iteration */
+ ier = cvNewtonIteration(cv_mem);
+
+ /* If there is a convergence failure and the Jacobian-related
+ data appears not to be current, loop again with a call to lsetup
+ in which convfail=CV_FAIL_BAD_J. Otherwise return. */
+ if (ier != TRY_AGAIN) return(ier);
+
+ callSetup = TRUE;
+ convfail = CV_FAIL_BAD_J;
+ }
+}
+
+/*
+ * cvNewtonIteration
+ *
+ * This routine performs the Newton iteration. If the iteration succeeds,
+ * it returns the value CV_SUCCESS. If not, it may signal the cvNlsNewton
+ * routine to call lsetup again and reattempt the iteration, by
+ * returning the value TRY_AGAIN. (In this case, cvNlsNewton must set
+ * convfail to CV_FAIL_BAD_J before calling setup again).
+ * Otherwise, this routine returns one of the appropriate values
+ * CV_LSOLVE_FAIL, CV_RHSFUNC_FAIL, CV_SRHSFUNC_FAIL, CONV_FAIL,
+ * RHSFUNC_RECVR, or SRHSFUNC_RECVR back to cvNlsNewton.
+ *
+ * If sensitivities are computed using the CV_SIMULTANEOUS approach, this
+ * routine performs a quasi-Newton on the combined nonlinear system.
+ * The iteration matrix of the combined system is block diagonal with
+ * each block being the iteration matrix of the original system. Thus
+ * we solve linear systems with the same matrix but different right
+ * hand sides.
+ */
+
+static int cvNewtonIteration(CVodeMem cv_mem)
+{
+ int m;
+ realtype del, delS, Del, Delp, dcon;
+ N_Vector b, *bS=NULL, wrk1, wrk2;
+ booleantype do_sensi_sim;
+ int retval, is;
+
+ /* Are we computing sensitivities with the CV_SIMULTANEOUS approach? */
+ do_sensi_sim = (sensi && (ism==CV_SIMULTANEOUS));
+
+ mnewt = m = 0;
+
+ /* Initialize delS and Delp to avoid compiler warning message */
+ delS = Delp = ZERO;
+
+ /* At this point, ftemp <- f(t_n, y_n(0))
+ ftempS <- fS(t_n, y_n(0), s_n(0))
+ acor <- 0
+ acorS <- 0
+ y <- y_n(0)
+ yS <- yS_n(0) */
+
+ /* Looping point for Newton iteration */
+ loop {
+
+ /* Evaluate the residual of the nonlinear system */
+ N_VLinearSum(rl1, zn[1], ONE, acor, tempv);
+ N_VLinearSum(gamma, ftemp, -ONE, tempv, tempv);
+
+ /* Call the lsolve function */
+ b = tempv;
+
+ retval = lsolve(cv_mem, b, ewt, y, ftemp);
+ 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);
+ }
+
+ /* Solve the sensitivity linear systems and do the same
+ tests on the return value of lsolve. */
+
+ 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]);
+ }
+ bS = tempvS;
+ for (is=0; is<Ns; is++) {
+ retval = lsolve(cv_mem, bS[is], ewtS[is], y, ftemp);
+ if (retval < 0) return(CV_LSOLVE_FAIL);
+ if (retval > 0) {
+ if ((!jcur) && (setupNonNull)) 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);
+
+ 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]);
+ }
+ }
+
+ /* Test for convergence. If m > 0, an estimate of the convergence
+ rate constant is stored in crate, and used in the test. */
+
+ Del = (do_sensi_sim) ? delS : del;
+ if (m > 0) crate = MAX(CRDOWN * crate, Del/Delp);
+ dcon = Del * MIN(ONE, crate) / tq[4];
+
+ if (dcon <= ONE) {
+ if (m == 0)
+ if (do_sensi_sim && errconS) acnrm = delS;
+ else acnrm = del;
+ else {
+ acnrm = N_VWrmsNorm(acor, ewt);
+ if (do_sensi_sim && errconS)
+ acnrm = cvSensUpdateNorm(cv_mem, acnrm, acorS, ewtS);
+ }
+ jcur = FALSE;
+ return(CV_SUCCESS); /* Convergence achieved */
+ }
+
+ 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);
+ }
+
+ /* Save norm of correction, evaluate f, and loop again */
+ Delp = Del;
+ retval = f(tn, y, ftemp, user_data);
+ nfe++;
+ if (retval < 0) return(CV_RHSFUNC_FAIL);
+ if (retval > 0) {
+ if ((!jcur) && (setupNonNull)) 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);
+ if (retval < 0) return(CV_SRHSFUNC_FAIL);
+ if (retval > 0) {
+ if ((!jcur) && (setupNonNull)) return(TRY_AGAIN);
+ else return(SRHSFUNC_RECVR);
+ }
+ }
+
+ } /* end loop */
+
+}
+
+/*
+ * cvQuadNls
+ *
+ * This routine solves for the quadrature variables at the new step.
+ * It does not solve a nonlinear system, but rather updates the
+ * quadrature variables. The name for this function is just for
+ * uniformity purposes.
+ *
+ * Possible return values (interpreted by cvHandleNFlag)
+ *
+ * CV_SUCCESS -> continue with error test
+ * CV_QRHSFUNC_FAIL -> halt the integration
+ * QRHSFUNC_RECVR -> predict again or stop if too many
+ *
+ */
+
+static int cvQuadNls(CVodeMem cv_mem)
+{
+ int retval;
+
+ /* Save quadrature correction in acorQ */
+ retval = fQ(tn, y, acorQ, user_data);
+ 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);
+ }
+
+ N_VLinearSum(h, acorQ, -ONE, znQ[1], acorQ);
+ N_VScale(rl1, acorQ, acorQ);
+
+ /* Apply correction to quadrature variables */
+ N_VLinearSum(ONE, znQ[0], ONE, acorQ, yQ);
+
+ return(CV_SUCCESS);
+}
+
+/*
+ * cvQuadSensNls
+ *
+ * This routine solves for the quadrature sensitivity variables
+ * at the new step. It does not solve a nonlinear system, but
+ * rather updates the quadrature variables. The name for this
+ * function is just for uniformity purposes.
+ *
+ * Possible return values (interpreted by cvHandleNFlag)
+ *
+ * CV_SUCCESS -> continue with error test
+ * CV_QSRHSFUNC_FAIL -> halt the integration
+ * QSRHSFUNC_RECVR -> predict again or stop if too many
+ *
+ */
+
+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++;
+ 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]);
+ /* Apply correction to quadrature sensitivity variables */
+ N_VLinearSum(ONE, znQS[0][is], ONE, acorQS[is], yQS[is]);
+ }
+
+ return(CV_SUCCESS);
+}
+
+
+/*
+ * cvStgrNls
+ *
+ * This is a high-level routine that attempts to solve the
+ * sensitivity linear systems using nonlinear iterations (CV_FUNCTIONAL
+ * or CV_NEWTON - depending on the value of iter) once the states y_n
+ * were obtained and passed the error test.
+ */
+
+static int cvStgrNls(CVodeMem cv_mem)
+{
+ int flag=CV_SUCCESS;
+
+ switch(iter) {
+ case CV_FUNCTIONAL:
+ flag = cvStgrNlsFunctional(cv_mem);
+ break;
+ case CV_NEWTON:
+ flag = cvStgrNlsNewton(cv_mem);
+ break;
+ }
+
+ return(flag);
+
+}
+
+/*
+ * cvStgrNlsfunctional
+ *
+ * This routine attempts to solve the sensitivity linear systems
+ * using functional iteration (no matrices involved).
+ *
+ * Possible return values:
+ * CV_SUCCESS,
+ * CV_SRHSFUNC_FAIL,
+ * CONV_FAIL, SRHSFUNC_RECVR
+ */
+
+static int cvStgrNlsFunctional(CVodeMem cv_mem)
+{
+ int m;
+ int retval, is;
+ realtype Del, Delp, dcon;
+ N_Vector wrk1, wrk2;
+
+ /* Initialize estimated conv. rate and counter */
+ 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);
+ 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]);
+
+ /* Loop until convergence; accumulate corrections in acorS */
+
+ loop {
+
+ 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]);
+ }
+ /* 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]);
+
+ /* 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 = MAX(CRDOWN * crateS, Del / Delp);
+ dcon = Del * MIN(ONE, crateS) / tq[4];
+
+ if (dcon <= ONE) {
+ if (errconS)
+ acnrmS = (m==0)? Del : cvSensNorm(cv_mem, acorS, 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);
+
+ /* 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);
+ if (retval < 0) return(CV_SRHSFUNC_FAIL);
+ if (retval > 0) return(SRHSFUNC_RECVR);
+
+ } /* end loop */
+
+}
+
+/*
+ * cvStgrNlsNewton
+ *
+ * This routine attempts to solve the sensitivity linear systems using
+ * Newton iteration. It calls cvStgrNlsNewton to perform the actual
+ * iteration. If the Newton iteration fails with out-of-date Jacobian
+ * data (ier=TRY_AGAIN), it calls lsetup and retries the Newton iteration.
+ * This second try is unlikely to happen when using a Krylov linear solver.
+ *
+ * Possible return values:
+ *
+ * CV_SUCCESS
+ *
+ * CV_LSOLVE_FAIL -+
+ * CV_LSETUP_FAIL |
+ * CV_SRHSFUNC_FAIL -+
+ *
+ * CONV_FAIL -+
+ * SRHSFUNC_RECVR -+
+ */
+
+static int cvStgrNlsNewton(CVodeMem cv_mem)
+{
+ int retval, is;
+ int convfail, ier;
+ N_Vector vtemp1, vtemp2, vtemp3, wrk1, wrk2;
+
+ loop {
+
+ /* 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]);
+ }
+
+ /* 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);
+ if (retval < 0) return(CV_SRHSFUNC_FAIL);
+ if (retval > 0) return(SRHSFUNC_RECVR);
+
+ /* Do the Newton iteration */
+ ier = cvStgrNewtonIteration(cv_mem);
+
+ /* If the solve was successful (ier=CV_SUCCESS) or if an error
+ that cannot be fixed by a call to lsetup occured
+ (ier = CV_LSOLVE_FAIL or CONV_FAIL) return */
+ if (ier != TRY_AGAIN) return(ier);
+
+ /* There was a convergence failure and the Jacobian-related data
+ appears not to be current. Call lsetup with convfail=CV_FAIL_BAD_J
+ and then loop again */
+ convfail = CV_FAIL_BAD_J;
+
+ /* Rename some vectors for readibility */
+ vtemp1 = tempv;
+ vtemp2 = yS[0];
+ vtemp3 = 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;
+
+ /* Return if lsetup failed */
+ if (ier < 0) return(CV_LSETUP_FAIL);
+ if (ier > 0) return(CONV_FAIL);
+
+ } /* end loop */
+
+}
+
+/*
+ * cvStgrNewtonIteration
+ *
+ * This routine performs the Newton iteration for all sensitivities.
+ * If the iteration succeeds, it returns the value CV_SUCCESS.
+ * If not, it may signal the cvStgrNlsNewton routine to call lsetup and
+ * reattempt the iteration, by returning the value TRY_AGAIN. (In this case,
+ * cvStgrNlsNewton must set convfail to CV_FAIL_BAD_J before calling setup again).
+ * Otherwise, this routine returns one of the appropriate values
+ * CV_LSOLVE_FAIL or CONV_FAIL back to cvStgrNlsNewton.
+ */
+
+static int cvStgrNewtonIteration(CVodeMem cv_mem)
+{
+ int m, retval;
+ realtype Del, Delp, dcon;
+ N_Vector *bS, wrk1, wrk2;
+ int is;
+
+ m = 0;
+
+ /* Initialize Delp to avoid compiler warning message */
+ Delp = ZERO;
+
+ /* ftemp <- f(t_n, y_n)
+ y <- y_n
+ ftempS <- fS(t_n, y_n(0), s_n(0))
+ acorS <- 0
+ yS <- yS_n(0) */
+
+ loop {
+
+ /* 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]);
+ }
+
+ /* Call the lsolve function */
+ bS = tempvS;
+ nniS++;
+ for (is=0; is<Ns; is++) {
+
+ retval = lsolve(cv_mem, bS[is], ewtS[is], y, 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);
+ }
+
+ }
+
+ /* 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]);
+ }
+
+ /* 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 = MAX(CRDOWN * crateS, Del/Delp);
+ dcon = Del * MIN(ONE, crateS) / tq[4];
+ if (dcon <= ONE) {
+ if (errconS)
+ acnrmS = (m==0) ? Del : cvSensNorm(cv_mem, acorS, ewtS);
+ jcur = FALSE;
+ return(CV_SUCCESS); /* Convergence achieved */
+ }
+
+ 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 == maxcorS) || ((m >= 2) && (Del > RDIV * Delp))) {
+ if ((!jcur) && (setupNonNull)) 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);
+ if (retval < 0) return(CV_SRHSFUNC_FAIL);
+ if (retval > 0) {
+ if ((!jcur) && (setupNonNull)) return(TRY_AGAIN);
+ else return(SRHSFUNC_RECVR);
+ }
+
+ } /* end loop */
+
+}
+
+/*
+ * cvStgr1Nls
+ *
+ * This is a high-level routine that attempts to solve the i-th
+ * sensitivity linear system using nonlinear iterations (CV_FUNCTIONAL
+ * or CV_NEWTON - depending on the value of iter) once the states y_n
+ * were obtained and passed the error test.
+ */
+
+static int cvStgr1Nls(CVodeMem cv_mem, int is)
+{
+ int flag=CV_SUCCESS;
+
+ switch(iter) {
+ case CV_FUNCTIONAL:
+ flag = cvStgr1NlsFunctional(cv_mem,is);
+ break;
+ case CV_NEWTON:
+ flag = cvStgr1NlsNewton(cv_mem,is);
+ break;
+ }
+
+ return(flag);
+
+}
+
+/*
+ * cvStgr1NlsFunctional
+ *
+ * This routine attempts to solve the i-th sensitivity linear system
+ * using functional iteration (no matrices involved).
+ *
+ * Possible return values:
+ * CV_SUCCESS,
+ * CV_SRHSFUNC_FAIL,
+ * CONV_FAIL, SRHSFUNC_RECVR
+ */
+
+static int cvStgr1NlsFunctional(CVodeMem cv_mem, int is)
+{
+ int retval, m;
+ realtype Del, Delp, dcon;
+ N_Vector wrk1, wrk2;
+
+ /* Initialize estimated conv. rate and counter */
+ 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);
+ if (retval < 0) return(CV_SRHSFUNC_FAIL);
+ if (retval > 0) return(SRHSFUNC_RECVR);
+
+ /* Initialize correction to zero */
+ N_VConst(ZERO,acorS[is]);
+
+ /* Loop until convergence; accumulate corrections in acorS */
+
+ loop {
+
+ 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]);
+
+ /* 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]);
+
+ /* 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 = MAX(CRDOWN * crateS, Del / Delp);
+ dcon = Del * MIN(ONE, crateS) / tq[4];
+
+ if (dcon <= ONE) {
+ 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);
+
+ /* Save norm of correction, evaluate f, and loop again */
+ Delp = Del;
+
+ wrk1 = tempv;
+ wrk2 = ftempS[0];
+
+ retval = cvSensRhs1Wrapper(cv_mem, tn, y, ftemp, is, yS[is], tempvS[is], wrk1, wrk2);
+ if (retval < 0) return(CV_SRHSFUNC_FAIL);
+ if (retval > 0) return(SRHSFUNC_RECVR);
+
+ } /* end loop */
+
+}
+
+/*
+ * cvStgr1NlsNewton
+ *
+ * This routine attempts to solve the i-th sensitivity linear system
+ * using Newton iteration. It calls cvStgr1NlsNewton to perform the
+ * actual iteration. If the Newton iteration fails with out-of-date
+ * Jacobian data (ier=TRY_AGAIN), it calls lsetup and retries the
+ * Newton iteration. This second try is unlikely to happen when
+ * using a Krylov linear solver.
+ *
+ * Possible return values:
+ *
+ * CV_SUCCESS
+ *
+ * CV_LSOLVE_FAIL
+ * CV_LSETUP_FAIL
+ * CV_SRHSFUNC_FAIL
+ *
+ * CONV_FAIL
+ * SRHSFUNC_RECVR
+ */
+
+static int cvStgr1NlsNewton(CVodeMem cv_mem, int is)
+{
+ int convfail, retval, ier;
+ N_Vector vtemp1, vtemp2, vtemp3, wrk1, wrk2;
+
+ loop {
+
+ /* Set acorS to zero and load prediction into yS vector */
+ N_VConst(ZERO, acorS[is]);
+ N_VScale(ONE, znS[0][is], 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);
+ if (retval < 0) return(CV_SRHSFUNC_FAIL);
+ if (retval > 0) return(SRHSFUNC_RECVR);
+
+ /* Do the Newton iteration */
+ ier = cvStgr1NewtonIteration(cv_mem, is);
+
+ /* If the solve was successful (ier=CV_SUCCESS) or if an error
+ that cannot be fixed by a call to lsetup occured
+ (ier = CV_LSOLVE_FAIL or CONV_FAIL) return */
+ if (ier != TRY_AGAIN) return(ier);
+
+ /* There was a convergence failure and the Jacobian-related data
+ appears not to be current. Call lsetup with convfail=CV_FAIL_BAD_J
+ and then loop again */
+ convfail = CV_FAIL_BAD_J;
+
+ /* Rename some vectors for readibility */
+ vtemp1 = tempv;
+ vtemp2 = yS[0];
+ vtemp3 = 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;
+
+ /* Return if lsetup failed */
+ if (ier < 0) return(CV_LSETUP_FAIL);
+ if (ier > 0) return(CONV_FAIL);
+
+ } /* end loop */
+
+}
+
+/*
+ * cvStgr1NewtonIteration
+ *
+ * This routine performs the Newton iteration for the i-th sensitivity.
+ * If the iteration succeeds, it returns the value CV_SUCCESS.
+ * If not, it may signal the cvStgr1NlsNewton routine to call lsetup
+ * and reattempt the iteration, by returning the value TRY_AGAIN.
+ * (In this case, cvStgr1NlsNewton must set convfail to CV_FAIL_BAD_J
+ * before calling setup again). Otherwise, this routine returns one
+ * of the appropriate values CV_LSOLVE_FAIL or CONV_FAIL back to
+ * cvStgr1NlsNewton.
+ */
+
+static int cvStgr1NewtonIteration(CVodeMem cv_mem, int is)
+{
+ int m, retval;
+ realtype Del, Delp, dcon;
+ N_Vector *bS, wrk1, wrk2;
+
+ m = 0;
+
+ /* Initialize Delp to avoid compiler warning message */
+ Delp = ZERO;
+
+ /* ftemp <- f(t_n, y_n)
+ y <- y_n
+ ftempS[is] <- fS(is, t_n, y_n(0), s_n(0))
+ acorS[is] <- 0
+ yS[is] <- yS_n(0)[is] */
+
+ loop {
+
+ /* 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]);
+
+ /* Call the lsolve function */
+ bS = tempvS;
+
+ nniS1[is]++;
+
+ retval = lsolve(cv_mem, bS[is], ewtS[is], y, 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);
+ }
+
+ /* 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]);
+
+ /* 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 = MAX(CRDOWN * crateS, Del/Delp);
+ dcon = Del * MIN(ONE, crateS) / tq[4];
+ if (dcon <= ONE) {
+ jcur = FALSE;
+ return(CV_SUCCESS); /* Convergence achieved */
+ }
+
+ 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 == maxcorS) || ((m >= 2) && (Del > RDIV * Delp))) {
+ if ((!jcur) && (setupNonNull)) 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);
+ if (retval < 0) return(CV_SRHSFUNC_FAIL);
+ if (retval > 0) {
+ if ((!jcur) && (setupNonNull)) return(TRY_AGAIN);
+ else return(SRHSFUNC_RECVR);
+ }
+
+ } /* end loop */
+
+}
+
+/*
+ * cvHandleNFlag
+ *
+ * This routine takes action on the return value nflag = *nflagPtr
+ * returned by cvNls, as follows:
+ *
+ * If cvNls succeeded in solving the nonlinear system, then
+ * cvHandleNFlag returns the constant DO_ERROR_TEST, which tells cvStep
+ * to perform the error test.
+ *
+ * If the nonlinear system was not solved successfully, then ncfn and
+ * ncf = *ncfPtr are incremented and Nordsieck array zn is restored.
+ *
+ * If the solution of the nonlinear system failed due to an
+ * unrecoverable failure by setup, we return the value CV_LSETUP_FAIL.
+ *
+ * If it failed due to an unrecoverable failure in solve, then we return
+ * the value CV_LSOLVE_FAIL.
+ *
+ * If it failed due to an unrecoverable failure in rhs, then we return
+ * the value CV_RHSFUNC_FAIL.
+ *
+ * If it failed due to an unrecoverable failure in quad rhs, then we return
+ * the value CV_QRHSFUNC_FAIL.
+ *
+ * If it failed due to an unrecoverable failure in sensi rhs, then we return
+ * the value CV_SRHSFUNC_FAIL.
+ *
+ * Otherwise, a recoverable failure occurred when solving the
+ * nonlinear system (cvNls returned nflag = CONV_FAIL, RHSFUNC_RECVR, or
+ * SRHSFUNC_RECVR).
+ * In this case, if ncf is now equal to maxncf or |h| = hmin,
+ * we return the value CV_CONV_FAILURE (if nflag=CONV_FAIL), or
+ * CV_REPTD_RHSFUNC_ERR (if nflag=RHSFUNC_RECVR), or CV_REPTD_SRHSFUNC_ERR
+ * (if nflag=SRHSFUNC_RECVR).
+ * If not, we set *nflagPtr = PREV_CONV_FAIL and return the value
+ * PREDICT_AGAIN, telling cvStep to reattempt the step.
+ *
+ */
+
+static int cvHandleNFlag(CVodeMem cv_mem, int *nflagPtr, realtype saved_t,
+ int *ncfPtr, long int *ncfnPtr)
+{
+ int nflag;
+
+ nflag = *nflagPtr;
+
+ if (nflag == CV_SUCCESS) return(DO_ERROR_TEST);
+
+ /* The nonlinear soln. failed; increment ncfn and restore zn */
+ (*ncfnPtr)++;
+ cvRestore(cv_mem, saved_t);
+
+ /* Return if lsetup, lsolve, or some rhs failed unrecoverably */
+ if (nflag == CV_LSETUP_FAIL) return(CV_LSETUP_FAIL);
+ if (nflag == CV_LSOLVE_FAIL) return(CV_LSOLVE_FAIL);
+ if (nflag == CV_RHSFUNC_FAIL) return(CV_RHSFUNC_FAIL);
+ if (nflag == CV_QRHSFUNC_FAIL) return(CV_QRHSFUNC_FAIL);
+ if (nflag == CV_SRHSFUNC_FAIL) return(CV_SRHSFUNC_FAIL);
+ if (nflag == CV_QSRHSFUNC_FAIL) return(CV_QSRHSFUNC_FAIL);
+
+ /* At this point, nflag = CONV_FAIL, RHSFUNC_RECVR, or SRHSFUNC_RECVR;
+ increment ncf */
+
+ (*ncfPtr)++;
+ 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 ((ABS(h) <= hmin*ONEPSM) || (*ncfPtr == 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);
+ if (nflag == SRHSFUNC_RECVR) return(CV_REPTD_SRHSFUNC_ERR);
+ if (nflag == QSRHSFUNC_RECVR) return(CV_REPTD_QSRHSFUNC_ERR);
+ }
+
+ /* Reduce step size; return to reattempt the step */
+
+ eta = MAX(ETACF, hmin / ABS(h));
+ *nflagPtr = PREV_CONV_FAIL;
+ cvRescale(cv_mem);
+
+ return(PREDICT_AGAIN);
+}
+
+/*
+ * cvRestore
+ *
+ * This routine restores the value of 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.
+ */
+
+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]);
+
+ 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 (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 (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]);
+ }
+ }
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Error Test
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * cvDoErrorTest
+ *
+ * This routine performs the local error test, for the state, quadrature,
+ * or sensitivity variables. Its last three arguments change depending
+ * on which variables the error test is to be performed on.
+ *
+ * The weighted local error norm dsm is loaded into *dsmPtr, and
+ * the test dsm ?<= 1 is made.
+ *
+ * If the test passes, cvDoErrorTest returns CV_SUCCESS.
+ *
+ * If the test fails, we undo the step just taken (call cvRestore) and
+ *
+ * - if maxnef error test failures have occurred or if ABS(h) = hmin,
+ * we return CV_ERR_FAILURE.
+ *
+ * - if more than MXNEF1 error test failures have occurred, an order
+ * reduction is forced. If already at order 1, restart by reloading
+ * zn from scratch (also znQ and znS if appropriate).
+ * If f() fails, we return CV_RHSFUNC_FAIL or CV_UNREC_RHSFUNC_ERR;
+ * if fQ() fails, we return CV_QRHSFUNC_FAIL or CV_UNREC_QRHSFUNC_ERR;
+ * if cvSensRhsWrapper() fails, we return CV_SRHSFUNC_FAIL or CV_UNREC_SRHSFUNC_ERR;
+ * (no recovery is possible at this stage).
+ *
+ * - otherwise, set *nflagPtr to PREV_ERR_FAIL, and return TRY_AGAIN.
+ *
+ */
+
+static int cvDoErrorTest(CVodeMem cv_mem, int *nflagPtr, realtype saved_t,
+ realtype acor_nrm,
+ int *nefPtr, long int *netfPtr, realtype *dsmPtr)
+{
+ realtype dsm;
+ int retval, is;
+ N_Vector wrk1, wrk2;
+
+ dsm = acor_nrm * tq[2];
+
+ /* If est. local error norm dsm passes test, return CV_SUCCESS */
+ *dsmPtr = dsm;
+ if (dsm <= ONE) return(CV_SUCCESS);
+
+ /* Test failed; increment counters, set nflag, and restore zn array */
+ (*nefPtr)++;
+ (*netfPtr)++;
+ *nflagPtr = PREV_ERR_FAIL;
+ cvRestore(cv_mem, saved_t);
+
+ /* At maxnef failures or |h| = hmin, return CV_ERR_FAILURE */
+ if ((ABS(h) <= hmin*ONEPSM) || (*nefPtr == maxnef)) return(CV_ERR_FAILURE);
+
+ /* Set etamax = 1 to prevent step size increase at end of this step */
+ etamax = ONE;
+
+ /* Set h ratio eta from dsm, rescale, and return for retry of step */
+ if (*nefPtr <= MXNEF1) {
+ eta = ONE / (RPowerR(BIAS2*dsm,ONE/L) + ADDON);
+ eta = MAX(ETAMIN, MAX(eta, hmin / ABS(h)));
+ if (*nefPtr >= SMALL_NEF) eta = MIN(eta, ETAMXF);
+ cvRescale(cv_mem);
+ return(TRY_AGAIN);
+ }
+
+ /* After MXNEF1 failures, force an order reduction and retry step */
+ if (q > 1) {
+ eta = MAX(ETAMIN, hmin / ABS(h));
+ cvAdjustOrder(cv_mem,-1);
+ L = q;
+ q--;
+ qwait = L;
+ cvRescale(cv_mem);
+ return(TRY_AGAIN);
+ }
+
+ /* If already at order 1, restart: reload zn, znQ, znS, znQS from scratch */
+ eta = MAX(ETAMIN, hmin / ABS(h));
+ h *= eta;
+ next_h = h;
+ hscale = h;
+ qwait = LONG_WAIT;
+ nscon = 0;
+
+ retval = f(tn, zn[0], tempv, user_data);
+ nfe++;
+ if (retval < 0) return(CV_RHSFUNC_FAIL);
+ if (retval > 0) return(CV_UNREC_RHSFUNC_ERR);
+
+ N_VScale(h, tempv, zn[1]);
+
+ if (quadr) {
+
+ retval = fQ(tn, zn[0], tempvQ, user_data);
+ nfQe++;
+ if (retval < 0) return(CV_QRHSFUNC_FAIL);
+ if (retval > 0) return(CV_UNREC_QRHSFUNC_ERR);
+
+ N_VScale(h, tempvQ, znQ[1]);
+
+ }
+
+ if (sensi) {
+
+ wrk1 = ftemp;
+ wrk2 = ftempS[0];
+
+ retval = cvSensRhsWrapper(cv_mem, tn, zn[0], tempv, znS[0], 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]);
+
+ }
+
+ if (quadr_sensi) {
+
+ wrk1 = ftemp;
+ wrk2 = ftempQ;
+
+ retval = fQS(Ns, tn, zn[0], znS[0], tempvQ, tempvQS, fQS_data, wrk1, wrk2);
+ 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]);
+
+ }
+
+
+ return(TRY_AGAIN);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Functions called after a successful step
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * cvCompleteStep
+ *
+ * This routine performs various update operations when the solution
+ * to the nonlinear system has passed the local error test.
+ * We increment the step counter nst, record the values hu and qu,
+ * 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.
+ */
+
+static void cvCompleteStep(CVodeMem cv_mem)
+{
+ int i, j;
+ int is;
+
+ nst++;
+ nscon++;
+ hu = h;
+ qu = q;
+
+ for (i=q; i >= 2; i--) tau[i] = tau[i-1];
+ if ((q==1) && (nst > 1)) tau[2] = tau[1];
+ tau[1] = 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]);
+
+ if (quadr) {
+ for (j=0; j <= q; j++)
+ N_VLinearSum(l[j], acorQ, ONE, znQ[j], 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 (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 necessary, store Delta_n in zn[qmax] to be used in order increase.
+ * This actually will be Delta_{n-1} in the ELTE at q+1 since it happens at
+ * the next to last step of order q before a possible one at order q+1
+ */
+
+ qwait--;
+ if ((qwait == 1) && (q != qmax)) {
+
+ N_VScale(ONE, acor, zn[qmax]);
+
+ if (quadr)
+ N_VScale(ONE, acorQ, znQ[qmax]);
+
+ if (sensi)
+ for (is=0; is<Ns; is++)
+ N_VScale(ONE, acorS[is], znS[qmax][is]);
+
+ if (quadr_sensi)
+ for (is=0; is<Ns; is++)
+ N_VScale(ONE, acorQS[is], znQS[qmax][is]);
+
+ saved_tq5 = tq[5];
+ indx_acor = qmax;
+ }
+
+}
+
+/*
+ * cvPrepareNextStep
+ *
+ * This routine handles the setting of stepsize and order for the
+ * next step -- hprime and qprime. Along with hprime, it sets the
+ * ratio eta = hprime/h. It also updates other state variables
+ * related to a change of step size or order.
+ */
+
+static void cvPrepareNextStep(CVodeMem cv_mem, realtype dsm)
+{
+ /* If etamax = 1, defer step size or order changes */
+ if (etamax == ONE) {
+ qwait = MAX(qwait, 2);
+ qprime = q;
+ hprime = h;
+ eta = ONE;
+ return;
+ }
+
+ /* etaq is the ratio of new to old h at the current order */
+ etaq = ONE /(RPowerR(BIAS2*dsm,ONE/L) + ADDON);
+
+ /* If no order change, adjust eta and acor in cvSetEta and return */
+ if (qwait != 0) {
+ eta = etaq;
+ qprime = q;
+ cvSetEta(cv_mem);
+ return;
+ }
+
+ /* 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);
+ cvChooseEta(cv_mem);
+ cvSetEta(cv_mem);
+}
+
+/*
+ * cvSetEta
+ *
+ * This routine adjusts the value of eta according to the various
+ * heuristic limits and the optional input hmax. It also resets
+ * etamax to be the estimated local error vector.
+ */
+
+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;
+ } else {
+ /* Limit eta by etamax and hmax, then set hprime */
+ eta = MIN(eta, etamax);
+ eta /= MAX(ONE, ABS(h)*hmax_inv*eta);
+ hprime = h * eta;
+ if (qprime < q) nscon = 0;
+ }
+
+ /* Reset etamx for the next step size change, and scale acor */
+}
+
+/*
+ * cvComputeEtaqm1
+ *
+ * This routine computes and returns the value of etaqm1 for a
+ * possible decrease in order by 1.
+ */
+
+static realtype cvComputeEtaqm1(CVodeMem cv_mem)
+{
+ realtype ddn;
+
+ etaqm1 = ZERO;
+
+ if (q > 1) {
+
+ ddn = N_VWrmsNorm(zn[q], ewt);
+
+ if ( quadr && errconQ) {
+ ddn = cvQuadUpdateNorm(cv_mem, ddn, znQ[q], ewtQ);
+ }
+
+ if ( sensi && errconS ) {
+ ddn = cvSensUpdateNorm(cv_mem, ddn, znS[q], ewtS);
+ }
+
+ if ( quadr_sensi && errconQS ) {
+ ddn = cvQuadSensUpdateNorm(cv_mem, ddn, znQS[q], ewtQS);
+ }
+
+ ddn = ddn * tq[1];
+
+ etaqm1 = ONE/(RPowerR(BIAS1*ddn, ONE/q) + ADDON);
+
+ }
+
+ return(etaqm1);
+}
+
+/*
+ * cvComputeEtaqp1
+ *
+ * This routine computes and returns the value of etaqp1 for a
+ * possible increase in order by 1.
+ */
+
+static realtype cvComputeEtaqp1(CVodeMem cv_mem)
+{
+ realtype dup, cquot;
+ int is;
+
+ etaqp1 = ZERO;
+
+ if (q != qmax) {
+
+ if (saved_tq5 == ZERO) return(etaqp1);
+
+ cquot = (tq[5] / saved_tq5) * RPowerI(h/tau[2], L);
+
+ N_VLinearSum(-cquot, zn[qmax], ONE, acor, tempv);
+
+ dup = N_VWrmsNorm(tempv, ewt);
+
+ if ( quadr && errconQ ) {
+ N_VLinearSum(-cquot, znQ[qmax], ONE, acorQ, tempvQ);
+ dup = cvQuadUpdateNorm(cv_mem, dup, tempvQ, 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 ( 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);
+ }
+
+ dup = dup * tq[3];
+
+ etaqp1 = ONE / (RPowerR(BIAS3*dup, ONE/(L+1)) + ADDON);
+
+ }
+
+ return(etaqp1);
+}
+
+/*
+ * cvChooseEta
+ * Given etaqm1, etaq, etaqp1 (the values of eta for qprime =
+ * q - 1, q, or q + 1, respectively), this routine chooses the
+ * maximum eta value, sets eta to that value, and sets qprime to the
+ * corresponding value of q. If there is a tie, the preference
+ * order is to (1) keep the same order, then (2) decrease the order,
+ * and finally (3) increase the order. If the maximum eta value
+ * is below the threshhold THRESH, the order is kept unchanged and
+ * eta is set to 1.
+ */
+
+static void cvChooseEta(CVodeMem cv_mem)
+{
+ realtype etam;
+ int is;
+
+ etam = MAX(etaqm1, MAX(etaq, etaqp1));
+
+ if (etam < THRESH) {
+ eta = ONE;
+ qprime = q;
+ return;
+ }
+
+ if (etam == etaq) {
+
+ eta = etaq;
+ qprime = q;
+
+ } else if (etam == etaqm1) {
+
+ eta = etaqm1;
+ qprime = q - 1;
+
+ } else {
+
+ eta = etaqp1;
+ qprime = q + 1;
+
+ if (lmm == CV_BDF) {
+
+ /*
+ * Store Delta_n in zn[qmax] to be used in order increase
+ *
+ * This happens at the last step of order q before an increase
+ * to order q+1, so it represents Delta_n in the ELTE at q+1
+ */
+
+ N_VScale(ONE, acor, zn[qmax]);
+
+ if (quadr && errconQ)
+ N_VScale(ONE, acorQ, znQ[qmax]);
+
+ if (sensi && errconS)
+ for (is=0; is<Ns; is++)
+ N_VScale(ONE, acorS[is], znS[qmax][is]);
+
+ if (quadr_sensi && errconQS)
+ for (is=0; is<Ns; is++)
+ N_VScale(ONE, acorQS[is], znQS[qmax][is]);
+
+ }
+
+ }
+
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Function to handle failures
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * cvHandleFailure
+ *
+ * This routine prints error messages for all cases of failure by
+ * cvHin or cvStep.
+ * It returns to CVode the value that CVode is to return to the user.
+ */
+
+static int cvHandleFailure(CVodeMem cv_mem, int flag)
+{
+
+ /* Set vector of absolute weighted local errors */
+ /*
+ N_VProd(acor, ewt, tempv);
+ N_VAbs(tempv, tempv);
+ */
+
+ /* 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);
+ break;
+ case CV_CONV_FAILURE:
+ cvProcessError(cv_mem, CV_CONV_FAILURE, "CVODES", "CVode", MSGCV_CONV_FAILS, tn, h);
+ break;
+ case CV_LSETUP_FAIL:
+ cvProcessError(cv_mem, CV_LSETUP_FAIL, "CVODES", "CVode", MSGCV_SETUP_FAILED, tn);
+ break;
+ case CV_LSOLVE_FAIL:
+ cvProcessError(cv_mem, CV_LSOLVE_FAIL, "CVODES", "CVode", MSGCV_SOLVE_FAILED, tn);
+ break;
+ case CV_RHSFUNC_FAIL:
+ cvProcessError(cv_mem, CV_RHSFUNC_FAIL, "CVODES", "CVode", MSGCV_RHSFUNC_FAILED, tn);
+ break;
+ case CV_UNREC_RHSFUNC_ERR:
+ cvProcessError(cv_mem, CV_UNREC_RHSFUNC_ERR, "CVODES", "CVode", MSGCV_RHSFUNC_UNREC, tn);
+ break;
+ case CV_REPTD_RHSFUNC_ERR:
+ cvProcessError(cv_mem, CV_REPTD_RHSFUNC_ERR, "CVODES", "CVode", MSGCV_RHSFUNC_REPTD, tn);
+ break;
+ case CV_RTFUNC_FAIL:
+ cvProcessError(cv_mem, CV_RTFUNC_FAIL, "CVODES", "CVode", MSGCV_RTFUNC_FAILED, tn);
+ break;
+ case CV_QRHSFUNC_FAIL:
+ cvProcessError(cv_mem, CV_QRHSFUNC_FAIL, "CVODES", "CVode", MSGCV_QRHSFUNC_FAILED, tn);
+ break;
+ case CV_UNREC_QRHSFUNC_ERR:
+ cvProcessError(cv_mem, CV_UNREC_QRHSFUNC_ERR, "CVODES", "CVode", MSGCV_QRHSFUNC_UNREC, tn);
+ break;
+ case CV_REPTD_QRHSFUNC_ERR:
+ cvProcessError(cv_mem, CV_REPTD_QRHSFUNC_ERR, "CVODES", "CVode", MSGCV_QRHSFUNC_REPTD, tn);
+ break;
+ case CV_SRHSFUNC_FAIL:
+ cvProcessError(cv_mem, CV_SRHSFUNC_FAIL, "CVODES", "CVode", MSGCV_SRHSFUNC_FAILED, tn);
+ break;
+ case CV_UNREC_SRHSFUNC_ERR:
+ cvProcessError(cv_mem, CV_UNREC_SRHSFUNC_ERR, "CVODES", "CVode", MSGCV_SRHSFUNC_UNREC, tn);
+ break;
+ case CV_REPTD_SRHSFUNC_ERR:
+ cvProcessError(cv_mem, CV_REPTD_SRHSFUNC_ERR, "CVODES", "CVode", MSGCV_SRHSFUNC_REPTD, tn);
+ break;
+
+ case CV_QSRHSFUNC_FAIL:
+ cvProcessError(cv_mem, CV_QSRHSFUNC_FAIL, "CVODES", "CVode", MSGCV_QSRHSFUNC_FAILED, tn);
+ break;
+ case CV_UNREC_QSRHSFUNC_ERR:
+ cvProcessError(cv_mem, CV_UNREC_QSRHSFUNC_ERR, "CVODES", "CVode", MSGCV_QSRHSFUNC_UNREC, tn);
+ break;
+ case CV_REPTD_QSRHSFUNC_ERR:
+ cvProcessError(cv_mem, CV_REPTD_QSRHSFUNC_ERR, "CVODES", "CVode", MSGCV_QSRHSFUNC_REPTD, tn);
+ break;
+
+
+ case CV_TOO_CLOSE:
+ cvProcessError(cv_mem, CV_TOO_CLOSE, "CVODES", "CVode", MSGCV_TOO_CLOSE);
+ break;
+ default:
+ return(CV_SUCCESS);
+ }
+
+ return(flag);
+
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Functions for BDF Stability Limit Detection
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * cvBDFStab
+ *
+ * This routine handles the BDF Stability Limit Detection Algorithm
+ * STALD. It is called if lmm = CV_BDF and the SLDET option is on.
+ * If the order is 3 or more, the required norm data is saved.
+ * If a decision to reduce order has not already been made, and
+ * enough data has been saved, cvSLdet is called. If it signals
+ * a stability limit violation, the order is reduced, and the step
+ * size is reset accordingly.
+ */
+
+static void cvBDFStab(CVodeMem cv_mem)
+{
+ int i,k, ldflag, factorial;
+ realtype sq, sqm1, sqm2;
+
+ /* 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) {
+ for (k = 1; k <= 3; k++)
+ for (i = 5; i >= 2; i--)
+ ssdat[i][k] = ssdat[i-1][k];
+ factorial = 1;
+ for (i = 1; i <= q-1; i++) factorial *= i;
+ sq = factorial*q*(q+1)*acnrm/MAX(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;
+ }
+
+ if (qprime >= 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) ) {
+ 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 = MIN(eta,etamax);
+ eta = eta/MAX(ONE,ABS(h)*hmax_inv*eta);
+ hprime = h*eta;
+ nor = nor + 1;
+ }
+ }
+ }
+ else {
+ /* Otherwise, let order increase happen, and
+ reset stability limit counter, nscon. */
+ nscon = 0;
+ }
+}
+
+/*
+ * cvSLdet
+ *
+ * This routine detects stability limitation using stored scaled
+ * derivatives data. cvSLdet returns the magnitude of the
+ * dominate characteristic root, rr. The presents of a stability
+ * limit is indicated by rr > "something a little less then 1.0",
+ * and a positive kflag. This routine should only be called if
+ * order is greater than or equal to 3, and data has been collected
+ * for 5 time steps.
+ *
+ * Returned values:
+ * kflag = 1 -> Found stable characteristic root, normal matrix case
+ * kflag = 2 -> Found stable characteristic root, quartic solution
+ * kflag = 3 -> Found stable characteristic root, quartic solution,
+ * with Newton correction
+ * kflag = 4 -> Found stability violation, normal matrix case
+ * kflag = 5 -> Found stability violation, quartic solution
+ * kflag = 6 -> Found stability violation, quartic solution,
+ * with Newton correction
+ *
+ * kflag < 0 -> No stability limitation,
+ * or could not compute limitation.
+ *
+ * kflag = -1 -> Min/max ratio of ssdat too small.
+ * kflag = -2 -> For normal matrix case, vmax > vrrt2*vrrt2
+ * kflag = -3 -> For normal matrix case, The three ratios
+ * are inconsistent.
+ * kflag = -4 -> Small coefficient prevents elimination of quartics.
+ * kflag = -5 -> R value from quartics not consistent.
+ * kflag = -6 -> No corrected root passes test on qk values
+ * kflag = -7 -> Trouble solving for sigsq.
+ * kflag = -8 -> Trouble solving for B, or R via B.
+ * kflag = -9 -> R via sigsq[k] disagrees with R from data.
+ */
+
+static int cvSLdet(CVodeMem cv_mem)
+{
+ int i, k, j, it, kmin=0, kflag=0;
+ realtype rat[5][4], rav[4], qkr[4], sigsq[4], smax[4], ssmax[4];
+ realtype drr[4], rrc[4],sqmx[4], qjk[4][4], vrat[5], qc[6][4], qco[6][4];
+ realtype rr, rrcut, vrrtol, vrrt2, sqtol, rrtol;
+ realtype smink, smaxk, sumrat, sumrsq, vmin, vmax, drrmax, adrr;
+ realtype tem, sqmax, saqk, qp, s, sqmaxk, saqj, sqmin;
+ realtype rsa, rsb, rsc, rsd, rd1a, rd1b, rd1c;
+ realtype rd2a, rd2b, rd3a, cest1, corr1;
+ realtype ratp, ratm, qfac1, qfac2, bb, rrb;
+
+ /* The following are cutoffs and tolerances used by this routine */
+
+ rrcut = RCONST(0.98);
+ vrrtol = RCONST(1.0e-4);
+ vrrt2 = RCONST(5.0e-4);
+ sqtol = RCONST(1.0e-3);
+ rrtol = RCONST(1.0e-2);
+
+ rr = ZERO;
+
+ /* Index k corresponds to the degree of the interpolating polynomial. */
+ /* k = 1 -> q-1 */
+ /* k = 2 -> q */
+ /* k = 3 -> q+1 */
+
+ /* Index i is a backward-in-time index, i = 1 -> current time, */
+ /* i = 2 -> previous step, etc */
+
+ /* get maxima, minima, and variances, and form quartic coefficients */
+
+ for (k=1; k<=3; k++) {
+ smink = ssdat[1][k];
+ smaxk = ZERO;
+
+ for (i=1; i<=5; i++) {
+ smink = MIN(smink,ssdat[i][k]);
+ smaxk = MAX(smaxk,ssdat[i][k]);
+ }
+
+ if (smink < TINY*smaxk) {
+ kflag = -1;
+ return(kflag);
+ }
+ smax[k] = smaxk;
+ ssmax[k] = smaxk*smaxk;
+
+ sumrat = ZERO;
+ sumrsq = ZERO;
+ for (i=1; i<=4; i++) {
+ rat[i][k] = ssdat[i][k]/ssdat[i+1][k];
+ sumrat = sumrat + rat[i][k];
+ sumrsq = sumrsq + rat[i][k]*rat[i][k];
+ }
+ rav[k] = FOURTH*sumrat;
+ vrat[k] = ABS(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[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];
+
+ 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
+ have common or nearly-common roots in this case.
+ Return a kflag = 1 if this procedure works. If three root
+ differ more than vrrt2, return error kflag = -3. */
+
+ vmin = MIN(vrat[1],MIN(vrat[2],vrat[3]));
+ vmax = MAX(vrat[1],MAX(vrat[2],vrat[3]));
+
+ if (vmin < vrrtol*vrrtol) {
+
+ if (vmax > vrrt2*vrrt2) {
+ kflag = -2;
+ return(kflag);
+ } else {
+ rr = (rav[1] + rav[2] + rav[3])/THREE;
+ drrmax = ZERO;
+ for (k = 1;k<=3;k++) {
+ adrr = ABS(rav[k] - rr);
+ drrmax = MAX(drrmax, adrr);
+ }
+ if (drrmax > vrrt2)
+ kflag = -3;
+ kflag = 1;
+ /* can compute charactistic root, drop to next section */
+ }
+
+ } else {
+
+ /* use the quartics to get rr. */
+
+ if (ABS(qco[1][1]) < TINY*ssmax[1]) {
+ kflag = -4;
+ return(kflag);
+ }
+
+ tem = qco[1][2]/qco[1][1];
+ for (i=2; i<=5; i++) {
+ qco[i][2] = qco[i][2] - tem*qco[i][1];
+ }
+
+ qco[1][2] = ZERO;
+ tem = qco[1][3]/qco[1][1];
+ for (i=2; i<=5; i++) {
+ qco[i][3] = qco[i][3] - tem*qco[i][1];
+ }
+ qco[1][3] = ZERO;
+
+ if (ABS(qco[2][2]) < TINY*ssmax[2]) {
+ kflag = -4;
+ return(kflag);
+ }
+
+ tem = qco[2][3]/qco[2][2];
+ for (i=3; i<=5; i++) {
+ qco[i][3] = qco[i][3] - tem*qco[i][2];
+ }
+
+ if (ABS(qco[4][3]) < TINY*ssmax[3]) {
+ kflag = -4;
+ return(kflag);
+ }
+
+ rr = -qco[5][3]/qco[4][3];
+
+ if (rr < TINY || rr > HUN) {
+ kflag = -5;
+ return(kflag);
+ }
+
+ for (k=1; k<=3; k++) {
+ qkr[k] = qc[5][k] + rr*(qc[4][k] + rr*rr*(qc[2][k] + rr*qc[1][k]));
+ }
+
+ sqmax = ZERO;
+ for (k=1; k<=3; k++) {
+ saqk = ABS(qkr[k])/ssmax[k];
+ if (saqk > sqmax) sqmax = saqk;
+ }
+
+ if (sqmax < sqtol) {
+ kflag = 2;
+
+ /* can compute charactistic root, drop to "given rr,etc" */
+
+ } else {
+
+ /* do Newton corrections to improve rr. */
+
+ for (it=1; it<=3; it++) {
+ for (k=1; k<=3; k++) {
+ qp = qc[4][k] + rr*rr*(THREE*qc[2][k] + rr*FOUR*qc[1][k]);
+ drr[k] = ZERO;
+ if (ABS(qp) > TINY*ssmax[k]) drr[k] = -qkr[k]/qp;
+ rrc[k] = rr + drr[k];
+ }
+
+ for (k=1; k<=3; k++) {
+ s = rrc[k];
+ sqmaxk = ZERO;
+ for (j=1; j<=3; j++) {
+ qjk[j][k] = qc[5][j] + s*(qc[4][j] +
+ s*s*(qc[2][j] + s*qc[1][j]));
+ saqj = ABS(qjk[j][k])/ssmax[j];
+ if (saqj > sqmaxk) sqmaxk = saqj;
+ }
+ sqmx[k] = sqmaxk;
+ }
+
+ sqmin = sqmx[1] + ONE;
+ for (k=1; k<=3; k++) {
+ if (sqmx[k] < sqmin) {
+ kmin = k;
+ sqmin = sqmx[k];
+ }
+ }
+ rr = rrc[kmin];
+
+ if (sqmin < sqtol) {
+ kflag = 3;
+ /* can compute charactistic root */
+ /* break out of Newton correction loop and drop to "given rr,etc" */
+ break;
+ } else {
+ for (j=1; j<=3; j++) {
+ qkr[j] = qjk[j][kmin];
+ }
+ }
+ } /* end of Newton correction loop */
+
+ if (sqmin > sqtol) {
+ kflag = -6;
+ return(kflag);
+ }
+ } /* end of if (sqmax < sqtol) else */
+ } /* end of if (vmin < vrrtol*vrrtol) else, quartics to get rr. */
+
+ /* given rr, find sigsq[k] and verify rr. */
+ /* 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;
+ rd1a = rsa - rsb;
+ rd1b = rsb - rsc;
+ rd1c = rsc - rsd;
+ rd2a = rd1a - rd1b;
+ rd2b = rd1b - rd1c;
+ rd3a = rd2a - rd2b;
+
+ if (ABS(rd1b) < TINY*smax[k]) {
+ kflag = -7;
+ return(kflag);
+ }
+
+ cest1 = -rd3a/rd1b;
+ if (cest1 < TINY || cest1 > FOUR) {
+ kflag = -7;
+ return(kflag);
+ }
+ corr1 = (rd2b/cest1)/(rr*rr);
+ sigsq[k] = ssdat[3][k] + corr1;
+ }
+
+ if (sigsq[2] < TINY) {
+ kflag = -8;
+ return(kflag);
+ }
+
+ ratp = sigsq[3]/sigsq[2];
+ ratm = sigsq[1]/sigsq[2];
+ qfac1 = FOURTH*(q*q - ONE);
+ qfac2 = TWO/(q - ONE);
+ bb = ratp*ratm - ONE - qfac1*ratp;
+ tem = ONE - qfac2*bb;
+
+ if (ABS(tem) < TINY) {
+ kflag = -8;
+ return(kflag);
+ }
+
+ rrb = ONE/tem;
+
+ if (ABS(rrb - rr) > rrtol) {
+ kflag = -9;
+ return(kflag);
+ }
+
+ /* Check to see if rr is above cutoff rrcut */
+ if (rr > rrcut) {
+ if (kflag == 1) kflag = 4;
+ if (kflag == 2) kflag = 5;
+ if (kflag == 3) kflag = 6;
+ }
+
+ /* All positive kflag returned at this point */
+
+ return(kflag);
+
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Functions for rootfinding
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * cvRcheck1
+ *
+ * This routine completes the initialization of rootfinding memory
+ * information, and checks whether g has a zero both at and very near
+ * the initial point of the IVP.
+ *
+ * This routine returns an int equal to:
+ * CV_RTFUNC_FAIL = -12 if the g function failed, or
+ * CV_SUCCESS = 0 otherwise.
+ */
+
+static int cvRcheck1(CVodeMem cv_mem)
+{
+ int i, retval;
+ realtype smallh, hratio, tplus;
+ booleantype zroot;
+
+ for (i = 0; i < nrtfn; i++) iroots[i] = 0;
+ tlo = tn;
+ ttol = (ABS(tn) + ABS(h))*uround*HUN;
+
+ /* Evaluate g at initial t and check for zero values. */
+ retval = gfun(tlo, zn[0], glo, user_data);
+ nge = 1;
+ if (retval != 0) return(CV_RTFUNC_FAIL);
+
+ zroot = FALSE;
+ for (i = 0; i < nrtfn; i++) {
+ if (ABS(glo[i]) == ZERO) {
+ zroot = TRUE;
+ gactive[i] = FALSE;
+ }
+ }
+ if (!zroot) return(CV_SUCCESS);
+
+ /* Some g_i is zero at t0; look at g at t0+(small increment). */
+ hratio = MAX(ttol/ABS(h), TENTH);
+ smallh = hratio*h;
+ tplus = tlo + smallh;
+ N_VLinearSum(ONE, zn[0], hratio, zn[1], y);
+ retval = gfun(tplus, y, ghi, user_data);
+ 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] && ABS(ghi[i]) != ZERO) {
+ gactive[i] = TRUE;
+ glo[i] = ghi[i];
+ }
+ }
+ return(CV_SUCCESS);
+}
+
+/*
+ * cvRcheck2
+ *
+ * This routine checks for exact zeros of g at the last root found,
+ * if the last return was a root. It then checks for a close pair of
+ * zeros (an error condition), and for a new root at a nearby point.
+ * The array glo = g(tlo) at the left endpoint of the search interval
+ * is adjusted if necessary to assure that all g_i are nonzero
+ * there, before returning to do a root search in the interval.
+ *
+ * On entry, tlo = tretlast is the last value of tret returned by
+ * CVode. This may be the previous tn, the previous tout value, or
+ * the last root location.
+ *
+ * This routine returns an int equal to:
+ * CV_RTFUNC_FAIL = -12 if the g function failed, or
+ * CLOSERT = 3 if a close pair of zeros was found, or
+ * RTFOUND = 1 if a new zero of g was found near tlo, or
+ * CV_SUCCESS = 0 otherwise.
+ */
+
+static int cvRcheck2(CVodeMem cv_mem)
+{
+ int i, retval;
+ realtype smallh, hratio, tplus;
+ booleantype zroot;
+
+ if (irfnd == 0) return(CV_SUCCESS);
+
+ (void) CVodeGetDky(cv_mem, tlo, 0, y);
+ retval = gfun(tlo, y, glo, user_data);
+ 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 (ABS(glo[i]) == ZERO) {
+ zroot = TRUE;
+ iroots[i] = 1;
+ }
+ }
+ if (!zroot) return(CV_SUCCESS);
+
+ /* One or more g_i has a zero at tlo. Check g at tlo+smallh. */
+ ttol = (ABS(tn) + ABS(h))*uround*HUN;
+ smallh = (h > ZERO) ? ttol : -ttol;
+ tplus = tlo + smallh;
+ if ( (tplus - tn)*h >= ZERO) {
+ hratio = smallh/h;
+ N_VLinearSum(ONE, y, hratio, zn[1], y);
+ } else {
+ (void) CVodeGetDky(cv_mem, tplus, 0, y);
+ }
+ retval = gfun(tplus, y, ghi, user_data);
+ 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 (ABS(ghi[i]) == ZERO) {
+ if (!gactive[i]) continue;
+ if (iroots[i] == 1) return(CLOSERT);
+ zroot = TRUE;
+ iroots[i] = 1;
+ } else {
+ if (iroots[i] == 1) glo[i] = ghi[i];
+ }
+ }
+ if (zroot) return(RTFOUND);
+ return(CV_SUCCESS);
+}
+
+/*
+ * cvRcheck3
+ *
+ * This routine interfaces to cvRootFind to look for a root of g
+ * between tlo and either tn or tout, whichever comes first.
+ * Only roots beyond tlo in the direction of integration are sought.
+ *
+ * This routine returns an int equal to:
+ * CV_RTFUNC_FAIL = -12 if the g function failed, or
+ * RTFOUND = 1 if a root of g was found, or
+ * CV_SUCCESS = 0 otherwise.
+ */
+
+static int cvRcheck3(CVodeMem cv_mem)
+{
+ int i, retval, ier;
+
+ /* 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);
+ } else {
+ thi = toutc;
+ (void) CVodeGetDky(cv_mem, thi, 0, y);
+ }
+ }
+
+ /* Set ghi = g(thi) and call cvRootFind to search (tlo,thi) for roots. */
+ retval = gfun(thi, y, ghi, user_data);
+ nge++;
+ if (retval != 0) return(CV_RTFUNC_FAIL);
+
+ ttol = (ABS(tn) + ABS(h))*uround*HUN;
+ 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;
+ }
+ tlo = trout;
+ for (i = 0; i < nrtfn; i++) glo[i] = 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);
+ return(RTFOUND);
+
+}
+
+/*
+ * cvRootFind
+ *
+ * This routine solves for a root of g(t) between tlo and thi, if
+ * one exists. Only roots of odd multiplicity (i.e. with a change
+ * of sign in one of the g_i), or exact zeros, are found.
+ * Here the sign of tlo - thi is arbitrary, but if multiple roots
+ * are found, the one closest to tlo is returned.
+ *
+ * The method used is the Illinois algorithm, a modified secant method.
+ * Reference: Kathie L. Hiebert and Lawrence F. Shampine, Implicitly
+ * Defined Output Points for Solutions of ODEs, Sandia National
+ * Laboratory Report SAND80-0180, February 1980.
+ *
+ * This routine uses the following parameters for communication:
+ *
+ * nrtfn = number of functions g_i, or number of components of
+ * the vector-valued function g(t). Input only.
+ *
+ * gfun = user-defined function for g(t). Its form is
+ * (void) gfun(t, y, gt, user_data)
+ *
+ * rootdir = in array specifying the direction of zero-crossings.
+ * If rootdir[i] > 0, search for roots of g_i only if
+ * g_i is increasing; if rootdir[i] < 0, search for
+ * roots of g_i only if g_i is decreasing; otherwise
+ * always search for roots of g_i.
+ *
+ * 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
+ * both at the I.C. and at a small perturbation of them.
+ * gactive[i] is then set back on TRUE only after the
+ * corresponding g function moves away from 0.0.
+ *
+ * nge = cumulative counter for gfun calls.
+ *
+ * ttol = a convergence tolerance for trout. Input only.
+ * When a root at trout is found, it is located only to
+ * within a tolerance of ttol. Typically, ttol should
+ * be set to a value on the order of
+ * 100 * UROUND * max (ABS(tlo), ABS(thi))
+ * where UROUND is the unit roundoff of the machine.
+ *
+ * tlo, thi = endpoints of the interval in which roots are sought.
+ * On input, and must be distinct, but tlo - thi may
+ * be of either sign. The direction of integration is
+ * assumed to be from tlo to thi. On return, tlo and thi
+ * are the endpoints of the final relevant interval.
+ *
+ * glo, ghi = arrays of length nrtfn containing the vectors g(tlo)
+ * and g(thi) respectively. Input and output. On input,
+ * none of the glo[i] should be zero.
+ *
+ * trout = root location, if a root was found, or thi if not.
+ * Output only. If a root was found other than an exact
+ * zero of g, trout is the endpoint thi of the final
+ * interval bracketing the root, with size at most ttol.
+ *
+ * grout = array of length nrtfn containing g(trout) on return.
+ *
+ * iroots = int array of length nrtfn with root information.
+ * Output only. If a root was found, iroots indicates
+ * which components g_i have a root at trout. For
+ * i = 0, ..., nrtfn-1, iroots[i] = 1 if g_i has a root
+ * and g_i is increasing, iroots[i] = -1 if g_i has a
+ * root and g_i is decreasing, and iroots[i] = 0 if g_i
+ * has no roots or g_i varies in the direction opposite
+ * to that indicated by rootdir[i].
+ *
+ * This routine returns an int equal to:
+ * CV_RTFUNC_FAIL = -12 if the g function failed, or
+ * RTFOUND = 1 if a root of g was found, or
+ * CV_SUCCESS = 0 otherwise.
+ */
+
+static int cvRootFind(CVodeMem cv_mem)
+{
+ realtype alpha, tmid, gfrac, maxfrac, fracint, fracsub;
+ int i, retval, imax, side, sideprev;
+ booleantype zroot, sgnchg;
+
+ imax = 0;
+
+ /* 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 (ABS(ghi[i]) == ZERO) {
+ if(rootdir[i]*glo[i] <= ZERO) {
+ zroot = TRUE;
+ }
+ } else {
+ if ( (glo[i]*ghi[i] < ZERO) && (rootdir[i]*glo[i] <= ZERO) ) {
+ gfrac = ABS(ghi[i]/(ghi[i] - glo[i]));
+ if (gfrac > maxfrac) {
+ sgnchg = TRUE;
+ maxfrac = gfrac;
+ imax = i;
+ }
+ }
+ }
+ }
+
+ /* 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];
+ if (!zroot) return(CV_SUCCESS);
+ for (i = 0; i < nrtfn; i++) {
+ iroots[i] = 0;
+ if(!gactive[i]) continue;
+ if (ABS(ghi[i]) == ZERO) iroots[i] = glo[i] > 0 ? -1:1;
+ }
+ return(RTFOUND);
+ }
+
+ /* Initialize alpha to avoid compiler warning */
+ alpha = ONE;
+
+ /* A sign change was found. Loop to locate nearest root. */
+
+ side = 0; sideprev = -1;
+ loop { /* Looping point */
+
+ /* Set weight alpha.
+ On the first two passes, set alpha = 1. Thereafter, reset alpha
+ according to the side (low vs high) of the subinterval in which
+ the sign change was found in the previous two passes.
+ If the sides were opposite, set alpha = 1.
+ If the sides were the same, then double alpha (if high side),
+ or halve alpha (if low side).
+ The next guess tmid is the secant method value if alpha = 1, but
+ is closer to tlo if alpha < 1, and closer to thi if alpha > 1. */
+
+ if (sideprev == side) {
+ alpha = (side == 2) ? alpha*TWO : alpha*HALF;
+ } else {
+ alpha = ONE;
+ }
+
+ /* 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] - alpha*glo[imax]);
+ if (ABS(tmid - tlo) < HALF*ttol) {
+ fracint = ABS(thi - tlo)/ttol;
+ fracsub = (fracint > FIVE) ? TENTH : HALF/fracint;
+ tmid = tlo + fracsub*(thi - tlo);
+ }
+ if (ABS(thi - tmid) < HALF*ttol) {
+ fracint = ABS(thi - tlo)/ttol;
+ fracsub = (fracint > FIVE) ? TENTH : HALF/fracint;
+ tmid = thi - fracsub*(thi - tlo);
+ }
+
+ (void) CVodeGetDky(cv_mem, tmid, 0, y);
+ retval = gfun(tmid, y, grout, user_data);
+ 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;
+ sideprev = side;
+ for (i = 0; i < nrtfn; i++) {
+ if(!gactive[i]) continue;
+ if (ABS(grout[i]) == ZERO) {
+ if(rootdir[i]*glo[i] <= ZERO) {
+ zroot = TRUE;
+ }
+ } else {
+ if ( (glo[i]*grout[i] < ZERO) && (rootdir[i]*glo[i] <= ZERO) ) {
+ gfrac = ABS(grout[i]/(grout[i] - glo[i]));
+ if (gfrac > maxfrac) {
+ sgnchg = TRUE;
+ maxfrac = gfrac;
+ imax = i;
+ }
+ }
+ }
+ }
+ if (sgnchg) {
+ /* Sign change found in (tlo,tmid); replace thi with tmid. */
+ thi = tmid;
+ for (i = 0; i < nrtfn; i++) ghi[i] = grout[i];
+ side = 1;
+ /* Stop at root thi if converged; otherwise loop. */
+ if (ABS(thi - tlo) <= 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];
+ 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];
+ side = 2;
+ /* Stop at root thi if converged; otherwise loop back. */
+ if (ABS(thi - tlo) <= 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 ( (ABS(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;
+ }
+ return(RTFOUND);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Functions for combined norms
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * cvQuadUpdateNorm
+ *
+ * Updates the norm old_nrm to account for all quadratures.
+ */
+
+static realtype cvQuadUpdateNorm(CVodeMem cv_mem, realtype old_nrm,
+ N_Vector xQ, N_Vector wQ)
+{
+ realtype qnrm;
+
+ qnrm = N_VWrmsNorm(xQ, wQ);
+ if (old_nrm > qnrm) return(old_nrm);
+ else return(qnrm);
+}
+
+/*
+ * cvSensNorm
+ *
+ * This routine returns the maximum over the weighted root mean
+ * square norm of xS with weight vectors wS:
+ *
+ * max { wrms(xS[0],wS[0]) ... wrms(xS[Ns-1],wS[Ns-1]) }
+ *
+ * Called by cvSensUpdateNorm or directly in the CV_STAGGERED approach
+ * during the NLS solution and before the error test.
+ */
+
+static realtype cvSensNorm(CVodeMem cv_mem, N_Vector *xS, N_Vector *wS)
+{
+ int is;
+ realtype nrm, snrm;
+
+ nrm = N_VWrmsNorm(xS[0],wS[0]);
+ for (is=1; is<Ns; is++) {
+ snrm = N_VWrmsNorm(xS[is],wS[is]);
+ if ( snrm > nrm ) nrm = snrm;
+ }
+
+ return(nrm);
+}
+
+/*
+ * cvSensUpdateNorm
+ *
+ * Updates the norm old_nrm to account for all sensitivities.
+ */
+
+static realtype cvSensUpdateNorm(CVodeMem cv_mem, realtype old_nrm,
+ N_Vector *xS, N_Vector *wS)
+{
+ realtype snrm;
+
+ snrm = cvSensNorm(cv_mem, xS, wS);
+ if (old_nrm > snrm) return(old_nrm);
+ else return(snrm);
+}
+
+/*
+ * cvQuadSensNorm
+ *
+ * This routine returns the maximum over the weighted root mean
+ * square norm of xQS with weight vectors wQS:
+ *
+ * max { wrms(xQS[0],wS[0]) ... wrms(xQS[Ns-1],wS[Ns-1]) }
+ *
+ * Called by cvQuadSensUpdateNorm.
+ */
+
+static realtype cvQuadSensNorm(CVodeMem cv_mem, N_Vector *xQS, N_Vector *wQS)
+{
+ int is;
+ realtype nrm, snrm;
+
+ nrm = N_VWrmsNorm(xQS[0],wQS[0]);
+ for (is=1; is<Ns; is++) {
+ snrm = N_VWrmsNorm(xQS[is],wQS[is]);
+ if ( snrm > nrm ) nrm = snrm;
+ }
+
+ return(nrm);
+}
+
+/*
+ * cvSensUpdateNorm
+ *
+ * Updates the norm old_nrm to account for all quadrature sensitivities.
+ */
+
+static realtype cvQuadSensUpdateNorm(CVodeMem cv_mem, realtype old_nrm,
+ N_Vector *xQS, N_Vector *wQS)
+{
+ realtype snrm;
+
+ snrm = cvQuadSensNorm(cv_mem, xQS, wQS);
+ if (old_nrm > snrm) return(old_nrm);
+ else return(snrm);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Wrappers for sensitivity RHS
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * cvSensRhsWrapper
+ *
+ * CVSensRhs is a high level routine that returns right hand side
+ * of sensitivity equations. Depending on the 'ifS' flag, it either
+ * calls directly the fS routine (ifS=CV_ALLSENS) or (if ifS=CV_ONESENS)
+ * calls the fS1 routine in a loop over all sensitivities.
+ *
+ * CVSensRhs is called:
+ * (*) by CVode at the first step
+ * (*) by cvYddNorm if errcon=TRUE
+ * (*) by cvNlsFunctional, cvNlsNewton, and cvNewtonIteration
+ * if ism=CV_SIMULTANEOUS
+ * (*) by cvDoErrorTest when restarting from scratch
+ * (*) in the corrector loop if ism=CV_STAGGERED
+ * (*) by cvStgrDoErrorTest when restarting from scratch
+ *
+ * The return value is that of the sensitivity RHS function fS,
+ *
+ */
+
+int cvSensRhsWrapper(CVodeMem cv_mem, realtype time,
+ N_Vector ycur, N_Vector fcur,
+ N_Vector *yScur, N_Vector *fScur,
+ N_Vector temp1, N_Vector temp2)
+{
+ int retval=0, is;
+
+ if (ifS==CV_ALLSENS) {
+ retval = fS(Ns, time, ycur, fcur, yScur, fScur,
+ fS_data, temp1, temp2);
+ nfSe++;
+ } else {
+ for (is=0; is<Ns; is++) {
+ retval = fS1(Ns, time, ycur, fcur, is, yScur[is], fScur[is],
+ fS_data, temp1, temp2);
+ nfSe++;
+ if (retval != 0) break;
+ }
+ }
+
+ return(retval);
+}
+
+/*
+ * cvSensRhs1Wrapper
+ *
+ * cvSensRhs1Wrapper is a high level routine that returns right-hand
+ * side of the is-th sensitivity equation.
+ *
+ * cvSensRhs1Wrapper is called only during the CV_STAGGERED1 corrector loop
+ * (ifS must be CV_ONESENS, otherwise CVodeSensInit would have
+ * issued an error message).
+ *
+ * The return value is that of the sensitivity RHS function fS1,
+ */
+
+int cvSensRhs1Wrapper(CVodeMem cv_mem, realtype time,
+ N_Vector ycur, N_Vector fcur,
+ int is, N_Vector yScur, N_Vector fScur,
+ N_Vector temp1, N_Vector temp2)
+{
+ int retval;
+
+ retval = fS1(Ns, time, ycur, fcur, is, yScur, fScur,
+ fS_data, temp1, temp2);
+ nfSe++;
+
+ return(retval);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Internal DQ approximations for sensitivity RHS
+ * -----------------------------------------------------------------
+ */
+
+/* Undefine Readibility Constants */
+
+#undef Ns
+#undef y
+#undef yS
+#undef ftemp
+
+/*
+ * cvSensRhsInternalDQ - internal CVSensRhsFn
+ *
+ * cvSensRhsInternalDQ computes right hand side of all sensitivity equations
+ * by finite differences
+ */
+
+int cvSensRhsInternalDQ(int Ns, realtype t,
+ N_Vector y, N_Vector ydot,
+ N_Vector *yS, N_Vector *ySdot,
+ void *cvode_mem,
+ N_Vector ytemp, N_Vector ftemp)
+{
+ int is, retval;
+
+ for (is=0; is<Ns; is++) {
+ retval = cvSensRhs1InternalDQ(Ns, t, y, ydot, is, yS[is], ySdot[is],
+ cvode_mem, ytemp, ftemp);
+ if (retval!=0) return(retval);
+ }
+
+ return(0);
+}
+
+/*
+ * cvSensRhs1InternalDQ - internal CVSensRhs1Fn
+ *
+ * cvSensRhs1InternalDQ computes the right hand side of the is-th sensitivity
+ * equation by finite differences
+ *
+ * cvSensRhs1InternalDQ returns 0 if successful. Otherwise it returns the
+ * non-zero return value from f().
+ */
+
+int cvSensRhs1InternalDQ(int Ns, realtype t,
+ N_Vector y, N_Vector ydot,
+ int is, N_Vector yS, N_Vector ySdot,
+ void *cvode_mem,
+ N_Vector ytemp, N_Vector ftemp)
+{
+ CVodeMem cv_mem;
+ int retval, method;
+ int nfel = 0, which;
+ realtype psave, pbari;
+ realtype delta , rdelta;
+ realtype Deltap, rDeltap, r2Deltap;
+ realtype Deltay, rDeltay, r2Deltay;
+ realtype Delta , rDelta , r2Delta ;
+ realtype norms, ratio;
+
+ /* cvode_mem is passed here as user data */
+ cv_mem = (CVodeMem) cvode_mem;
+
+ delta = RSqrt(MAX(reltol, uround));
+ rdelta = ONE/delta;
+
+ pbari = pbar[is];
+
+ which = plist[is];
+
+ psave = p[which];
+
+ Deltap = pbari * delta;
+ rDeltap = ONE/Deltap;
+ norms = N_VWrmsNorm(yS, ewt) * pbari;
+ rDeltay = MAX(norms, rdelta) / pbari;
+ Deltay = ONE/rDeltay;
+
+ if (DQrhomax == ZERO) {
+ /* No switching */
+ method = (DQtype==CV_CENTERED) ? CENTERED1 : FORWARD1;
+ } else {
+ /* switch between simultaneous/separate DQ */
+ ratio = Deltay * rDeltap;
+ if ( MAX(ONE/ratio, ratio) <= DQrhomax )
+ method = (DQtype==CV_CENTERED) ? CENTERED1 : FORWARD1;
+ else
+ method = (DQtype==CV_CENTERED) ? CENTERED2 : FORWARD2;
+ }
+
+ switch(method) {
+
+ case CENTERED1:
+
+ Delta = MIN(Deltay, Deltap);
+ r2Delta = HALF/Delta;
+
+ N_VLinearSum(ONE,y,Delta,yS,ytemp);
+ p[which] = psave + Delta;
+
+ retval = f(t, ytemp, ySdot, user_data);
+ nfel++;
+ if (retval != 0) return(retval);
+
+ N_VLinearSum(ONE,y,-Delta,yS,ytemp);
+ p[which] = psave - Delta;
+
+ retval = f(t, ytemp, ftemp, user_data);
+ nfel++;
+ if (retval != 0) return(retval);
+
+ N_VLinearSum(r2Delta,ySdot,-r2Delta,ftemp,ySdot);
+
+ break;
+
+ case CENTERED2:
+
+ r2Deltap = HALF/Deltap;
+ r2Deltay = HALF/Deltay;
+
+ N_VLinearSum(ONE,y,Deltay,yS,ytemp);
+
+ retval = f(t, ytemp, ySdot, user_data);
+ nfel++;
+ if (retval != 0) return(retval);
+
+ N_VLinearSum(ONE,y,-Deltay,yS,ytemp);
+
+ retval = f(t, ytemp, ftemp, 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);
+ nfel++;
+ if (retval != 0) return(retval);
+
+ p[which] = psave - Deltap;
+ retval = f(t, y, ftemp, user_data);
+ nfel++;
+ if (retval != 0) return(retval);
+
+ N_VLinearSum(r2Deltap,ytemp,-r2Deltap,ftemp,ftemp);
+
+ N_VLinearSum(ONE,ySdot,ONE,ftemp,ySdot);
+
+ break;
+
+ case FORWARD1:
+
+ Delta = MIN(Deltay, Deltap);
+ rDelta = ONE/Delta;
+
+ N_VLinearSum(ONE,y,Delta,yS,ytemp);
+ p[which] = psave + Delta;
+
+ retval = f(t, ytemp, ySdot, user_data);
+ nfel++;
+ if (retval != 0) return(retval);
+
+ N_VLinearSum(rDelta,ySdot,-rDelta,ydot,ySdot);
+
+ break;
+
+ case FORWARD2:
+
+ N_VLinearSum(ONE,y,Deltay,yS,ytemp);
+
+ retval = f(t, ytemp, ySdot, 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);
+ nfel++;
+ if (retval != 0) return(retval);
+
+ N_VLinearSum(rDeltap,ytemp,-rDeltap,ydot,ftemp);
+
+ N_VLinearSum(ONE,ySdot,ONE,ftemp,ySdot);
+
+ break;
+
+ }
+
+ p[which] = psave;
+
+ /* Increment counter nfeS */
+ nfeS += nfel;
+
+ return(0);
+}
+
+
+/*
+ * cvQuadSensRhsInternalDQ - internal CVQuadSensRhsFn
+ *
+ * cvQuadSensRhsInternalDQ computes right hand side of all quadrature
+ * sensitivity equations by finite differences. All work is actually
+ * done in cvQuadSensRhs1InternalDQ.
+ */
+
+static int cvQuadSensRhsInternalDQ(int Ns, realtype t,
+ N_Vector y, N_Vector *yS,
+ N_Vector yQdot, N_Vector *yQSdot,
+ void *cvode_mem,
+ N_Vector tmp, N_Vector tmpQ)
+{
+ CVodeMem cv_mem;
+ int is, retval;
+
+ /* cvode_mem is passed here as user data */
+ cv_mem = (CVodeMem) cvode_mem;
+
+ for (is=0; is<Ns; is++) {
+ retval = cvQuadSensRhs1InternalDQ(cv_mem, is, t,
+ y, yS[is],
+ yQdot, yQSdot[is],
+ tmp, tmpQ);
+ if (retval!=0) return(retval);
+ }
+
+ return(0);
+}
+
+static int cvQuadSensRhs1InternalDQ(CVodeMem cv_mem, int is, realtype t,
+ N_Vector y, N_Vector yS,
+ N_Vector yQdot, N_Vector yQSdot,
+ N_Vector tmp, N_Vector tmpQ)
+{
+ int retval, method;
+ int nfel = 0, which;
+ realtype psave, pbari;
+ realtype delta , rdelta;
+ realtype Deltap, rDeltap;
+ realtype Deltay, rDeltay;
+ realtype Delta , rDelta , r2Delta ;
+ realtype norms;
+
+ delta = RSqrt(MAX(reltol, uround));
+ rdelta = ONE/delta;
+
+ pbari = pbar[is];
+
+ which = plist[is];
+
+ psave = p[which];
+
+ Deltap = pbari * delta;
+ rDeltap = ONE/Deltap;
+ norms = N_VWrmsNorm(yS, ewt) * pbari;
+ rDeltay = MAX(norms, rdelta) / pbari;
+ Deltay = ONE/rDeltay;
+
+ method = (DQtype==CV_CENTERED) ? CENTERED1 : FORWARD1;
+
+ switch(method) {
+
+ case CENTERED1:
+
+ Delta = MIN(Deltay, Deltap);
+ r2Delta = HALF/Delta;
+
+ N_VLinearSum(ONE, y, Delta, yS, tmp);
+ p[which] = psave + Delta;
+
+ retval = fQ(t, tmp, yQSdot, user_data);
+ nfel++;
+ if (retval != 0) return(retval);
+
+ N_VLinearSum(ONE, y, -Delta, yS, tmp);
+ p[which] = psave - Delta;
+
+ retval = fQ(t, tmp, tmpQ, user_data);
+ nfel++;
+ if (retval != 0) return(retval);
+
+ N_VLinearSum(r2Delta, yQSdot, -r2Delta, tmpQ, yQSdot);
+
+ break;
+
+ case FORWARD1:
+
+ Delta = MIN(Deltay, Deltap);
+ rDelta = ONE/Delta;
+
+ N_VLinearSum(ONE, y, Delta, yS, tmp);
+ p[which] = psave + Delta;
+
+ retval = fQ(t, tmp, yQSdot, user_data);
+ nfel++;
+ if (retval != 0) return(retval);
+
+ N_VLinearSum(rDelta, yQSdot, -rDelta, yQdot, yQSdot);
+
+ break;
+
+ }
+
+ p[which] = psave;
+
+ /* Increment counter nfQeS */
+ nfQeS += nfel;
+
+ return(0);
+}
+
+
+
+/*
+ * -----------------------------------------------------------------
+ * Error message handling functions
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * cvProcessError is a high level error handling function
+ * - if cv_mem==NULL it prints the error message to stderr
+ * - otherwise, it sets-up and calls the error hadling function
+ * 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, ...)
+{
+ va_list ap;
+ char msg[256];
+
+ /* Initialize the argument pointer variable
+ (msgfmt is the last required argument to cvProcessError) */
+
+ va_start(ap, msgfmt);
+
+ /* Compose the message */
+
+ vsprintf(msg, msgfmt, ap);
+
+ if (cv_mem == NULL) { /* We write to stderr */
+
+#ifndef NO_FPRINTF_OUTPUT
+ fprintf(stderr, "\n[%s ERROR] %s\n ", module, fname);
+ fprintf(stderr, msg);
+ fprintf(stderr, "\n\n");
+#endif
+
+ } else { /* We can call ehfun */
+
+ /* Call ehfun */
+
+ ehfun(error_code, module, fname, msg, eh_data);
+
+ }
+
+ /* Finalize argument processing */
+
+ va_end(ap);
+
+ return;
+
+}
+
+/*
+ * cvErrHandler is the default error handling function.
+ * 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)
+{
+ CVodeMem cv_mem;
+ char err_type[10];
+
+ /* data points to cv_mem here */
+
+ cv_mem = (CVodeMem) data;
+
+ if (error_code == CV_WARNING)
+ sprintf(err_type,"WARNING");
+ else
+ 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);
+ }
+#endif
+
+ return;
+}
diff --git a/src/cvodes/cvodes_band.c b/src/cvodes/cvodes_band.c
new file mode 100644
index 0000000..4a96404
--- /dev/null
+++ b/src/cvodes/cvodes_band.c
@@ -0,0 +1,461 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.16 $
+ * $Date: 2011/03/23 22:58:46 $
+ * -----------------------------------------------------------------
+ * Programmer(s): 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.
+ * -----------------------------------------------------------------
+ * 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 void cvBandFree(CVodeMem cv_mem);
+
+/* CVSBAND lfreeB function */
+static void 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;
+
+ 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 = MIN(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;
+
+ nje = 0;
+ nfeDQ = 0;
+ nstlj = 0;
+
+ /* 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 = ABS((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 void 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;
+}
+
+/*
+ * ================================================================
+ *
+ * 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 void cvBandFreeB(CVodeBMem cvB_mem)
+{
+ CVDlsMemB cvdlsB_mem;
+
+ cvdlsB_mem = (CVDlsMemB) (cvB_mem->cv_lmem);
+
+ free(cvdlsB_mem);
+}
+
diff --git a/src/cvodes/cvodes_bandpre.c b/src/cvodes/cvodes_bandpre.c
new file mode 100644
index 0000000..df311de
--- /dev/null
+++ b/src/cvodes/cvodes_bandpre.c
@@ -0,0 +1,545 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.11 $
+ * $Date: 2010/12/01 22:30:43 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Radu Serban and Aaron Collier @ 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.
+ * -----------------------------------------------------------------
+ * This file contains implementations of the banded difference
+ * quotient Jacobian-based preconditioner and solver routines for
+ * use with the CVSPILS linear solvers.
+ * -----------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#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)
+#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);
+
+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);
+
+/* Prototype for cvBandPrecFree */
+
+static void 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)
+{
+ CVodeMem cv_mem;
+ CVSpilsMem cvspils_mem;
+ CVBandPrecData pdata;
+ long int mup, mlp, storagemu;
+ int flag;
+
+ if (cvode_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 */
+ if (cv_mem->cv_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);
+ return(CVSPILS_ILL_INPUT);
+ }
+
+ pdata = NULL;
+ pdata = (CVBandPrecData) malloc(sizeof *pdata); /* Allocate data memory */
+ if (pdata == NULL) {
+ cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVBANDPRE", "CVBandPrecInit", MSGBP_MEM_FAIL);
+ return(CVSPILS_MEM_FAIL);
+ }
+
+ /* Load pointers and bandwidths into pdata block. */
+ pdata->cvode_mem = cvode_mem;
+ pdata->N = N;
+ pdata->mu = mup = MIN(N-1, MAX(0,mu));
+ pdata->ml = mlp = MIN(N-1, MAX(0,ml));
+
+ /* Initialize nfeBP counter */
+ pdata->nfeBP = 0;
+
+ /* Allocate memory for saved banded Jacobian approximation. */
+ pdata->savedJ = NULL;
+ pdata->savedJ = NewBandMat(N, mup, mlp, mup);
+ if (pdata->savedJ == NULL) {
+ free(pdata); pdata = NULL;
+ cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVBANDPRE", "CVBandPrecInit", MSGBP_MEM_FAIL);
+ return(CVSPILS_MEM_FAIL);
+ }
+
+
+ /* Allocate memory for banded preconditioner. */
+ storagemu = MIN(N-1, mup+mlp);
+ pdata->savedP = NULL;
+ pdata->savedP = NewBandMat(N, mup, mlp, storagemu);
+ if (pdata->savedP == NULL) {
+ DestroyMat(pdata->savedJ);
+ free(pdata); pdata = NULL;
+ 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);
+ free(pdata); pdata = NULL;
+ cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVBANDPRE", "CVBandPrecInit", MSGBP_MEM_FAIL);
+ return(CVSPILS_MEM_FAIL);
+ }
+
+ /* Overwrite the P_data field in the SPILS memory */
+ cvspils_mem->s_P_data = pdata;
+
+ /* Attach the pfree function */
+ cvspils_mem->s_pfree = cvBandPrecFree;
+
+ /* Attach preconditioner solve and setup functions */
+ flag = CVSpilsSetPreconditioner(cvode_mem, cvBandPrecSetup, cvBandPrecSolve);
+
+ return(flag);
+}
+
+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;
+
+
+ if (cvode_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);
+ 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);
+ return(CVSPILS_PMEM_NULL);
+ }
+ pdata = (CVBandPrecData) cvspils_mem->s_P_data;
+
+ N = pdata->N;
+ mu = pdata->mu;
+ ml = pdata->ml;
+ smu = MIN( N-1, mu + ml);
+
+ *leniwBP = pdata->N;
+ *lenrwBP = N * ( 2*ml + smu + mu + 2 );
+
+ return(CVSPILS_SUCCESS);
+}
+
+int CVBandPrecGetNumRhsEvals(void *cvode_mem, long int *nfevalsBP)
+{
+ CVodeMem cv_mem;
+ CVSpilsMem cvspils_mem;
+ CVBandPrecData pdata;
+
+ if (cvode_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);
+ 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);
+ return(CVSPILS_PMEM_NULL);
+ }
+ pdata = (CVBandPrecData) cvspils_mem->s_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.
+ * -----------------------------------------------------------------
+ */
+
+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)
+{
+ CVBandPrecData pdata;
+ CVodeMem cv_mem;
+ int retval;
+ long int 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);
+
+ } else {
+
+ /* If jok = FALSE, call cvBandPrecDQJac for new J value. */
+ *jcurPtr = TRUE;
+ SetToZero(savedJ);
+
+ retval = cvBandPrecDQJac(pdata, t, y, fy, tmp1, tmp2);
+ if (retval < 0) {
+ cvProcessError(cv_mem, -1, "CVBANDPRE", "cvBandPrecSetup", MSGBP_RHSFUNC_FAILED);
+ return(-1);
+ }
+ if (retval > 0) {
+ return(1);
+ }
+
+ BandCopy(savedJ, savedP, mu, ml);
+
+ }
+
+ /* 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);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * 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)
+{
+ CVBandPrecData pdata;
+ realtype *zd;
+
+ /* 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);
+}
+
+
+static void cvBandPrecFree(CVodeMem cv_mem)
+{
+ CVSpilsMem cvspils_mem;
+ CVBandPrecData pdata;
+
+ if (cv_mem->cv_lmem == NULL) return;
+ cvspils_mem = (CVSpilsMem) cv_mem->cv_lmem;
+
+ if (cvspils_mem->s_P_data == NULL) return;
+ pdata = (CVBandPrecData) cvspils_mem->s_P_data;
+
+ DestroyMat(savedJ);
+ DestroyMat(savedP);
+ DestroyArray(lpivots);
+
+ free(pdata);
+ pdata = NULL;
+}
+
+
+#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)
+{
+ CVodeMem cv_mem;
+ realtype fnorm, minInc, inc, inc_inv, srur;
+ long int 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);
+ fy_data = N_VGetArrayPointer(fy);
+ ftemp_data = N_VGetArrayPointer(ftemp);
+ y_data = N_VGetArrayPointer(y);
+ ytemp_data = N_VGetArrayPointer(ytemp);
+
+ /* Load ytemp with y = predicted y vector. */
+ N_VScale(ONE, y, ytemp);
+
+ /* Set minimum increment based on uround and norm of f. */
+ srur = RSqrt(uround);
+ fnorm = N_VWrmsNorm(fy, ewt);
+ minInc = (fnorm != ZERO) ?
+ (MIN_INC_MULT * ABS(h) * uround * N * fnorm) : ONE;
+
+ /* Set bandwidth and number of column groups for band differencing. */
+ width = ml + mu + 1;
+ ngroups = MIN(width, N);
+
+ for (group = 1; group <= ngroups; group++) {
+
+ /* Increment all y_j in group. */
+ for(j = group-1; j < N; j += width) {
+ inc = MAX(srur*ABS(y_data[j]), minInc/ewt_data[j]);
+ ytemp_data[j] += inc;
+ }
+
+ /* Evaluate f with incremented y. */
+
+ retval = f(t, ytemp, ftemp, user_data);
+ nfeBP++;
+ if (retval != 0) return(retval);
+
+ /* 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(savedJ,j);
+ inc = MAX(srur*ABS(y_data[j]), minInc/ewt_data[j]);
+ inc_inv = ONE/inc;
+ i1 = MAX(0, j-mu);
+ i2 = MIN(j+ml, N-1);
+ for (i=i1; i <= i2; i++)
+ BAND_COL_ELEM(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
+ */
+
+int CVBandPrecInitB(void *cvode_mem, int which, long int nB, long int muB, long int mlB)
+{
+ 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, "CVBANDPRE", "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);
+ 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);
+ 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;
+ }
+
+ cvB_mem->cv_pfree = NULL;
+
+ cvodeB_mem = (void *) (cvB_mem->cv_mem);
+
+ 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
new file mode 100644
index 0000000..b1f2302
--- /dev/null
+++ b/src/cvodes/cvodes_bandpre_impl.h
@@ -0,0 +1,77 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.10 $
+ * $Date: 2010/12/01 22:30:42 $
+ * -----------------------------------------------------------------
+ * Programmer(s): 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.
+ * -----------------------------------------------------------------
+ * Implementation header file for the CVBANDPRE module.
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _CVSBANDPRE_IMPL_H
+#define _CVSBANDPRE_IMPL_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <cvodes/cvodes_bandpre.h>
+#include <sundials/sundials_band.h>
+#include <sundials/sundials_direct.h>
+
+/*
+ * -----------------------------------------------------------------
+ * Type: CVBandPrecData
+ * -----------------------------------------------------------------
+ */
+
+typedef struct CVBandPrecDataRec {
+
+ /* Data set by user in CVBandPrecInit */
+
+ long int N;
+ long int ml, mu;
+
+ /* Data set by CVBandPrecSetup */
+
+ DlsMat savedJ;
+ DlsMat savedP;
+ long int *lpivots;
+
+ /* Rhs calls */
+
+ long int nfeBP;
+
+ /* Pointer to cvode_mem */
+
+ void *cvode_mem;
+
+} *CVBandPrecData;
+
+/*
+ * -----------------------------------------------------------------
+ * 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_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."
+
+#define MSGBP_NO_ADJ "Illegal attempt to call before calling CVodeAdjInit."
+#define MSGBP_BAD_WHICH "Illegal value for parameter which."
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/cvodes/cvodes_bbdpre.c b/src/cvodes/cvodes_bbdpre.c
new file mode 100644
index 0000000..0c848fc
--- /dev/null
+++ b/src/cvodes/cvodes_bbdpre.c
@@ -0,0 +1,785 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.14 $
+ * $Date: 2010/12/01 22:30:43 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Radu Serban and Aaron Collier @ 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.
+ * -----------------------------------------------------------------
+ * 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.
+ * -----------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#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>
+
+#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);
+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);
+
+/* Prototype for cvBBDPrecFree */
+static void cvBBDPrecFree(CVodeMem cv_mem);
+
+/* Wrapper functions for adjoint code */
+static int cvGlocWrapper(long int 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);
+
+/* 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 */
+static void CVBBDPrecFreeB(CVodeBMem cvB_mem);
+
+/*
+ * ================================================================
+ *
+ * PART I - forward problems
+ *
+ * ================================================================
+ */
+
+/* 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)
+{
+ CVodeMem cv_mem;
+ CVSpilsMem cvspils_mem;
+ CVBBDPrecData pdata;
+ long int muk, mlk, storage_mu;
+ int flag;
+
+ if (cvode_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 */
+ if (cv_mem->cv_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);
+ return(CVSPILS_ILL_INPUT);
+ }
+
+ /* Allocate data memory */
+ pdata = NULL;
+ pdata = (CVBBDPrecData) malloc(sizeof *pdata);
+ if (pdata == NULL) {
+ cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVBBDPRE", "CVBBDPrecInit", MSGBBD_MEM_FAIL);
+ return(CVSPILS_MEM_FAIL);
+ }
+
+ /* Set pointers to gloc and cfn; load half-bandwidths */
+ pdata->cvode_mem = cvode_mem;
+ pdata->gloc = gloc;
+ pdata->cfn = cfn;
+ pdata->mudq = MIN(Nlocal-1, MAX(0,mudq));
+ pdata->mldq = MIN(Nlocal-1, MAX(0,mldq));
+ muk = MIN(Nlocal-1, MAX(0,mukeep));
+ mlk = MIN(Nlocal-1, MAX(0,mlkeep));
+ pdata->mukeep = muk;
+ pdata->mlkeep = mlk;
+
+ /* Allocate memory for saved Jacobian */
+ pdata->savedJ = NewBandMat(Nlocal, muk, mlk, muk);
+ if (pdata->savedJ == NULL) {
+ free(pdata); pdata = NULL;
+ cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVBBDPRE", "CVBBDPrecInit", MSGBBD_MEM_FAIL);
+ return(CVSPILS_MEM_FAIL);
+ }
+
+ /* Allocate memory for preconditioner matrix */
+ storage_mu = MIN(Nlocal-1, muk + mlk);
+ pdata->savedP = NULL;
+ pdata->savedP = NewBandMat(Nlocal, muk, mlk, storage_mu);
+ if (pdata->savedP == NULL) {
+ DestroyMat(pdata->savedJ);
+ free(pdata); pdata = NULL;
+ 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);
+ free(pdata); pdata = NULL;
+ cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVBBDPRE", "CVBBDPrecInit", MSGBBD_MEM_FAIL);
+ return(CVSPILS_MEM_FAIL);
+ }
+
+ /* Set pdata->dqrely based on input dqrely (0 implies default). */
+ pdata->dqrely = (dqrely > ZERO) ? dqrely : RSqrt(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->nge = 0;
+
+ /* Overwrite the P_data field in the SPILS memory */
+ cvspils_mem->s_P_data = pdata;
+
+ /* Attach the pfree function */
+ cvspils_mem->s_pfree = cvBBDPrecFree;
+
+ /* Attach preconditioner solve and setup functions */
+ flag = CVSpilsSetPreconditioner(cvode_mem, cvBBDPrecSetup, cvBBDPrecSolve);
+
+ return(flag);
+}
+
+
+int CVBBDPrecReInit(void *cvode_mem,
+ long int mudq, long int mldq,
+ realtype dqrely)
+{
+ CVodeMem cv_mem;
+ CVSpilsMem cvspils_mem;
+ CVBBDPrecData pdata;
+ long int Nlocal;
+
+ if (cvode_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 */
+ if (cv_mem->cv_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);
+ return(CVSPILS_PMEM_NULL);
+ }
+ pdata = (CVBBDPrecData) cvspils_mem->s_P_data;
+
+ /* Load half-bandwidths */
+ Nlocal = pdata->n_local;
+ pdata->mudq = MIN(Nlocal-1, MAX(0,mudq));
+ pdata->mldq = MIN(Nlocal-1, MAX(0,mldq));
+
+ /* Set pdata->dqrely based on input dqrely (0 implies default). */
+ pdata->dqrely = (dqrely > ZERO) ? dqrely : RSqrt(uround);
+
+ /* Re-initialize nge */
+ pdata->nge = 0;
+
+ return(CVSPILS_SUCCESS);
+}
+
+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);
+ 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);
+ 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);
+ return(CVSPILS_PMEM_NULL);
+ }
+ pdata = (CVBBDPrecData) cvspils_mem->s_P_data;
+
+ *lenrwBBDP = pdata->rpwsize;
+ *leniwBBDP = pdata->ipwsize;
+
+ return(CVSPILS_SUCCESS);
+}
+
+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);
+ 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);
+ 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);
+ return(CVSPILS_PMEM_NULL);
+ }
+ pdata = (CVBBDPrecData) cvspils_mem->s_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).
+ * -----------------------------------------------------------------
+ */
+
+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)
+{
+ CVBBDPrecData pdata;
+ CVodeMem cv_mem;
+ int retval;
+ long int ier;
+
+ pdata = (CVBBDPrecData) bbd_data;
+
+ cv_mem = (CVodeMem) pdata->cvode_mem;
+
+ if (jok) {
+
+ /* If jok = TRUE, use saved copy of J */
+ *jcurPtr = FALSE;
+ BandCopy(savedJ, savedP, mukeep, mlkeep);
+
+ } else {
+
+ /* Otherwise call cvBBDDQJac for new J value */
+ *jcurPtr = TRUE;
+ SetToZero(savedJ);
+
+ retval = cvBBDDQJac(pdata, t, y, tmp1, tmp2, tmp3);
+ if (retval < 0) {
+ cvProcessError(cv_mem, -1, "CVBBDPRE", "cvBBDPrecSetup", MSGBBD_FUNC_FAILED);
+ return(-1);
+ }
+ if (retval > 0) {
+ return(1);
+ }
+
+ BandCopy(savedJ, savedP, mukeep, mlkeep);
+
+ }
+
+ /* 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);
+
+ /* Return 0 if the LU was complete; otherwise return 1 */
+ if (ier > 0) return(1);
+ return(0);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * 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)
+{
+ CVBBDPrecData pdata;
+ realtype *zd;
+
+ pdata = (CVBBDPrecData) bbd_data;
+
+ /* Copy r to z, then do backsolve and return */
+ N_VScale(ONE, r, z);
+
+ zd = N_VGetArrayPointer(z);
+
+ BandGBTRS(savedP, lpivots, zd);
+
+ return(0);
+}
+
+
+static void cvBBDPrecFree(CVodeMem cv_mem)
+{
+ CVSpilsMem cvspils_mem;
+ CVBBDPrecData pdata;
+
+ if (cv_mem->cv_lmem == NULL) return;
+ cvspils_mem = (CVSpilsMem) cv_mem->cv_lmem;
+
+ if (cvspils_mem->s_P_data == NULL) return;
+ pdata = (CVBBDPrecData) cvspils_mem->s_P_data;
+
+ DestroyMat(savedJ);
+ DestroyMat(savedP);
+ DestroyArray(lpivots);
+
+ free(pdata);
+ pdata = NULL;
+}
+
+
+
+#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)
+{
+ CVodeMem cv_mem;
+ realtype gnorm, minInc, inc, inc_inv;
+ long int group, i, j, width, ngroups, i1, i2;
+ realtype *y_data, *ewt_data, *gy_data, *gtemp_data, *ytemp_data, *col_j;
+ int retval;
+
+ cv_mem = (CVodeMem) pdata->cvode_mem;
+
+ /* Load ytemp with y = predicted solution vector */
+ 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 (retval != 0) return(retval);
+ }
+
+ retval = gloc(Nlocal, t, ytemp, gy, user_data);
+ 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);
+ 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);
+ minInc = (gnorm != ZERO) ?
+ (MIN_INC_MULT * ABS(h) * uround * Nlocal * gnorm) : ONE;
+
+ /* Set bandwidth and number of column groups for band differencing */
+ width = mldq + mudq + 1;
+ ngroups = MIN(width, Nlocal);
+
+ /* Loop over groups */
+ for (group=1; group <= ngroups; group++) {
+
+ /* Increment all y_j in group */
+ for(j=group-1; j < Nlocal; j+=width) {
+ inc = MAX(dqrely*ABS(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++;
+ if (retval != 0) return(retval);
+
+ /* Restore ytemp, then form and load difference quotients */
+ for (j=group-1; j < Nlocal; j+=width) {
+ ytemp_data[j] = y_data[j];
+ col_j = BAND_COL(savedJ,j);
+ inc = MAX(dqrely*ABS(y_data[j]), minInc/ewt_data[j]);
+ inc_inv = ONE/inc;
+ i1 = MAX(0, j-mukeep);
+ i2 = MIN(j+mlkeep, Nlocal-1);
+ for (i=i1; i <= i2; i++)
+ BAND_COL_ELEM(col_j,i,j) =
+ inc_inv * (gtemp_data[i] - gy_data[i]);
+ }
+ }
+
+ return(0);
+}
+
+
+/*
+ * ================================================================
+ *
+ * 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
+ */
+
+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)
+{
+ CVodeMem cv_mem;
+ CVadjMem ca_mem;
+ CVodeBMem cvB_mem;
+ void *cvodeB_mem;
+ CVBBDPrecDataB cvbbdB_mem;
+ int flag;
+
+ /* Check if cvode_mem exists */
+ if (cvode_mem == NULL) {
+ cvProcessError(NULL, CVSPILS_MEM_NULL, "CVBBDPRE", "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);
+ 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);
+ 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);
+
+ /* Initialize the BBD preconditioner */
+ 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 */
+ 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);
+ return(CVSPILS_MEM_FAIL);
+ }
+
+ gloc_B = glocB;
+ cfn_B = cfnB;
+
+ /* 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)
+{
+ 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, "CVBBDPRE", "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);
+ 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);
+ 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);
+
+ flag = CVBBDPrecReInit(cvodeB_mem, mudqB, mldqB, dqrelyB);
+
+ return(flag);
+}
+
+
+static void CVBBDPrecFreeB(CVodeBMem cvB_mem)
+{
+ free(cvB_mem->cv_pmem);
+ cvB_mem->cv_pmem = NULL;
+}
+
+
+/*
+ * cvGlocWrapper
+ *
+ * This routine interfaces to the CVLocalFnB routine
+ * provided by the user.
+ */
+
+static int cvGlocWrapper(long int 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;
+
+ 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);
+ if (flag != CV_SUCCESS) {
+ cvProcessError(cv_mem, -1, "CVBBDPRE", "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);
+}
+
+/*
+ * 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)
+{
+ CVodeMem cv_mem;
+ CVadjMem ca_mem;
+ CVodeBMem cvB_mem;
+ CVBBDPrecDataB cvbbdB_mem;
+ int retval, 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 (cfn_B == NULL) return(0);
+
+ /* Forward solution from interpolation */
+ flag = IMget(cv_mem, t, ytmp, NULL);
+ if (flag != CV_SUCCESS) {
+ cvProcessError(cv_mem, -1, "CVBBDPRE", "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);
+}
+
diff --git a/src/cvodes/cvodes_bbdpre_impl.h b/src/cvodes/cvodes_bbdpre_impl.h
new file mode 100644
index 0000000..7ea5695
--- /dev/null
+++ b/src/cvodes/cvodes_bbdpre_impl.h
@@ -0,0 +1,102 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.8 $
+ * $Date: 2010/12/01 22:30:42 $
+ * -----------------------------------------------------------------
+ * Programmer(s): 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.
+ * -----------------------------------------------------------------
+ * Implementation header file for the CVBBDPRE module.
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _CVSBBDPRE_IMPL_H
+#define _CVSBBDPRE_IMPL_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <cvodes/cvodes_bbdpre.h>
+#include <sundials/sundials_band.h>
+
+/*
+ * -----------------------------------------------------------------
+ * Type: CVBBDPrecData
+ * -----------------------------------------------------------------
+ */
+
+typedef struct CVBBDPrecDataRec {
+
+ /* passed by user to CVBBDPrecAlloc and used by PrecSetup/PrecSolve */
+
+ long int 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;
+
+ /* available for optional output */
+
+ long int rpwsize;
+ long int ipwsize;
+ long int nge;
+
+ /* pointer to cvode_mem */
+
+ void *cvode_mem;
+
+} *CVBBDPrecData;
+
+
+/*
+ * -----------------------------------------------------------------
+ * Type: CVBBDPrecDataB
+ * -----------------------------------------------------------------
+ */
+
+typedef struct CVBBDPrecDataRecB {
+
+ /* BBD user functions (glocB and cfnB) for backward run */
+ CVLocalFnB glocB;
+ CVCommFnB cfnB;
+
+} *CVBBDPrecDataB;
+
+/*
+ * -----------------------------------------------------------------
+ * 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_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."
+
+#define MSGBBD_NO_ADJ "Illegal attempt to call before calling CVodeAdjInit."
+#define MSGBBD_BAD_WHICH "Illegal value for the which parameter."
+#define MSGBBD_PDATAB_NULL "BBD preconditioner memory is NULL for the backward integration."
+#define MSGBBD_BAD_TINTERP "Bad t for interpolation."
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/cvodes/cvodes_dense.c b/src/cvodes/cvodes_dense.c
new file mode 100644
index 0000000..6a1f733
--- /dev/null
+++ b/src/cvodes/cvodes_dense.c
@@ -0,0 +1,440 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.15 $
+ * $Date: 2010/12/01 22:30:43 $
+ * -----------------------------------------------------------------
+ * Programmer(s): 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.
+ * -----------------------------------------------------------------
+ * 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 void cvDenseFree(CVodeMem cv_mem);
+
+/* CVSDENSE lfreeB function */
+static void 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;
+
+ 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;
+
+ 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 = ABS((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 void 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;
+}
+
+/*
+ * ================================================================
+ *
+ * PART II - backward problems
+ *
+ * ================================================================
+ */
+
+/*
+ * CVDenseB is a wraper 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 void cvDenseFreeB(CVodeBMem cvB_mem)
+{
+ CVDlsMemB cvdlsB_mem;
+
+ cvdlsB_mem = (CVDlsMemB) (cvB_mem->cv_lmem);
+
+ free(cvdlsB_mem);
+}
+
diff --git a/src/cvodes/cvodes_diag.c b/src/cvodes/cvodes_diag.c
new file mode 100644
index 0000000..88ccd31
--- /dev/null
+++ b/src/cvodes/cvodes_diag.c
@@ -0,0 +1,508 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.9 $
+ * $Date: 2010/12/01 22:30:43 $
+ * -----------------------------------------------------------------
+ * Programmer(s): 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.
+ * -----------------------------------------------------------------
+ * This is the implementation file for the CVDIAG linear solver.
+ * -----------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "cvodes_diag_impl.h"
+#include "cvodes_impl.h"
+
+/* Other Constants */
+
+#define FRACT RCONST(0.1)
+#define ONE RCONST(1.0)
+
+/* CVDIAG linit, lsetup, lsolve, and lfree routines */
+
+static int CVDiagInit(CVodeMem cv_mem);
+
+static int CVDiagSetup(CVodeMem cv_mem, int convfail, N_Vector ypred,
+ N_Vector fpred, booleantype *jcurPtr, N_Vector vtemp1,
+ N_Vector vtemp2, N_Vector vtemp3);
+
+static int CVDiagSolve(CVodeMem cv_mem, N_Vector b, N_Vector weight,
+ N_Vector ycur, N_Vector fcur);
+
+static void CVDiagFree(CVodeMem cv_mem);
+
+
+/*
+ * ================================================================
+ *
+ * PART I - forward problems
+ *
+ * ================================================================
+ */
+
+
+/* Readability Replacements */
+
+#define lrw1 (cv_mem->cv_lrw1)
+#define liw1 (cv_mem->cv_liw1)
+#define f (cv_mem->cv_f)
+#define uround (cv_mem->cv_uround)
+#define tn (cv_mem->cv_tn)
+#define h (cv_mem->cv_h)
+#define rl1 (cv_mem->cv_rl1)
+#define gamma (cv_mem->cv_gamma)
+#define ewt (cv_mem->cv_ewt)
+#define nfe (cv_mem->cv_nfe)
+#define zn (cv_mem->cv_zn)
+#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 gammasv (cvdiag_mem->di_gammasv)
+#define M (cvdiag_mem->di_M)
+#define bit (cvdiag_mem->di_bit)
+#define bitcomp (cvdiag_mem->di_bitcomp)
+#define nfeDI (cvdiag_mem->di_nfeDI)
+#define last_flag (cvdiag_mem->di_last_flag)
+
+
+/*
+ * -----------------------------------------------------------------
+ * CVDiag
+ * -----------------------------------------------------------------
+ * This routine initializes the memory record and sets various function
+ * fields specific to the diagonal 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 CVDiagInit, CVDiagSetup, CVDiagSolve, and CVDiagFree,
+ * 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.
+ * The CVDiag return value is SUCCESS = 0, LMEM_FAIL = -1, or
+ * LIN_ILL_INPUT=-2.
+ * -----------------------------------------------------------------
+ */
+
+int CVDiag(void *cvode_mem)
+{
+ CVodeMem cv_mem;
+ CVDiagMem cvdiag_mem;
+
+ /* Return immediately if cvode_mem is NULL */
+ if (cvode_mem == NULL) {
+ cvProcessError(NULL, CVDIAG_MEM_NULL, "CVDIAG", "CVDiag", MSGDG_CVMEM_NULL);
+ return(CVDIAG_MEM_NULL);
+ }
+ cv_mem = (CVodeMem) cvode_mem;
+
+ /* Check if N_VCompare and N_VInvTest are present */
+ if(vec_tmpl->ops->nvcompare == NULL ||
+ vec_tmpl->ops->nvinvtest == NULL) {
+ cvProcessError(cv_mem, CVDIAG_ILL_INPUT, "CVDIAG", "CVDiag", MSGDG_BAD_NVECTOR);
+ return(CVDIAG_ILL_INPUT);
+ }
+
+ if (lfree != NULL) lfree(cv_mem);
+
+ /* Set four main function fields in cv_mem */
+ linit = CVDiagInit;
+ lsetup = CVDiagSetup;
+ lsolve = CVDiagSolve;
+ lfree = CVDiagFree;
+
+ /* Get memory for CVDiagMemRec */
+ cvdiag_mem = NULL;
+ cvdiag_mem = (CVDiagMem) malloc(sizeof(CVDiagMemRec));
+ if (cvdiag_mem == NULL) {
+ cvProcessError(cv_mem, CVDIAG_MEM_FAIL, "CVDIAG", "CVDiag", MSGDG_MEM_FAIL);
+ return(CVDIAG_MEM_FAIL);
+ }
+
+ 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);
+ free(cvdiag_mem); cvdiag_mem = NULL;
+ return(CVDIAG_MEM_FAIL);
+ }
+ bit = N_VClone(vec_tmpl);
+ if (bit == NULL) {
+ cvProcessError(cv_mem, CVDIAG_MEM_FAIL, "CVDIAG", "CVDiag", MSGDG_MEM_FAIL);
+ N_VDestroy(M);
+ free(cvdiag_mem); cvdiag_mem = NULL;
+ return(CVDIAG_MEM_FAIL);
+ }
+ bitcomp = N_VClone(vec_tmpl);
+ if (bitcomp == NULL) {
+ cvProcessError(cv_mem, CVDIAG_MEM_FAIL, "CVDIAG", "CVDiag", MSGDG_MEM_FAIL);
+ N_VDestroy(M);
+ N_VDestroy(bit);
+ free(cvdiag_mem); cvdiag_mem = NULL;
+ return(CVDIAG_MEM_FAIL);
+ }
+
+ /* Attach linear solver memory to integrator memory */
+ lmem = cvdiag_mem;
+
+ return(CVDIAG_SUCCESS);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * CVDiagGetWorkSpace
+ * -----------------------------------------------------------------
+ */
+
+int CVDiagGetWorkSpace(void *cvode_mem, long int *lenrwLS, long int *leniwLS)
+{
+ CVodeMem cv_mem;
+
+ /* Return immediately if cvode_mem is NULL */
+ if (cvode_mem == NULL) {
+ cvProcessError(NULL, CVDIAG_MEM_NULL, "CVDIAG", "CVDiagGetWorkSpace", MSGDG_CVMEM_NULL);
+ return(CVDIAG_MEM_NULL);
+ }
+ cv_mem = (CVodeMem) cvode_mem;
+
+ *lenrwLS = 3*lrw1;
+ *leniwLS = 3*liw1;
+
+ return(CVDIAG_SUCCESS);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * CVDiagGetNumRhsEvals
+ * -----------------------------------------------------------------
+ */
+
+int CVDiagGetNumRhsEvals(void *cvode_mem, long int *nfevalsLS)
+{
+ CVodeMem cv_mem;
+ CVDiagMem cvdiag_mem;
+
+ /* Return immediately if cvode_mem is NULL */
+ if (cvode_mem == NULL) {
+ cvProcessError(NULL, CVDIAG_MEM_NULL, "CVDIAG", "CVDiagGetNumRhsEvals", MSGDG_CVMEM_NULL);
+ return(CVDIAG_MEM_NULL);
+ }
+ cv_mem = (CVodeMem) cvode_mem;
+
+ if (lmem == NULL) {
+ cvProcessError(cv_mem, CVDIAG_LMEM_NULL, "CVDIAG", "CVDiagGetNumRhsEvals", MSGDG_LMEM_NULL);
+ return(CVDIAG_LMEM_NULL);
+ }
+ cvdiag_mem = (CVDiagMem) lmem;
+
+ *nfevalsLS = nfeDI;
+
+ return(CVDIAG_SUCCESS);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * CVDiagGetLastFlag
+ * -----------------------------------------------------------------
+ */
+
+int CVDiagGetLastFlag(void *cvode_mem, long int *flag)
+{
+ CVodeMem cv_mem;
+ CVDiagMem cvdiag_mem;
+
+ /* Return immediately if cvode_mem is NULL */
+ if (cvode_mem == NULL) {
+ cvProcessError(NULL, CVDIAG_MEM_NULL, "CVDIAG", "CVDiagGetLastFlag", MSGDG_CVMEM_NULL);
+ return(CVDIAG_MEM_NULL);
+ }
+ cv_mem = (CVodeMem) cvode_mem;
+
+ if (lmem == NULL) {
+ cvProcessError(cv_mem, CVDIAG_LMEM_NULL, "CVDIAG", "CVDiagGetLastFlag", MSGDG_LMEM_NULL);
+ return(CVDIAG_LMEM_NULL);
+ }
+ cvdiag_mem = (CVDiagMem) lmem;
+
+ *flag = last_flag;
+
+ return(CVDIAG_SUCCESS);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * CVDiagGetReturnFlagName
+ * -----------------------------------------------------------------
+ */
+
+char *CVDiagGetReturnFlagName(long int flag)
+{
+ char *name;
+
+ name = (char *)malloc(30*sizeof(char));
+
+ switch(flag) {
+ case CVDIAG_SUCCESS:
+ sprintf(name,"CVDIAG_SUCCESS");
+ break;
+ case CVDIAG_MEM_NULL:
+ sprintf(name,"CVDIAG_MEM_NULL");
+ break;
+ case CVDIAG_LMEM_NULL:
+ sprintf(name,"CVDIAG_LMEM_NULL");
+ break;
+ case CVDIAG_ILL_INPUT:
+ sprintf(name,"CVDIAG_ILL_INPUT");
+ break;
+ case CVDIAG_MEM_FAIL:
+ sprintf(name,"CVDIAG_MEM_FAIL");
+ break;
+ case CVDIAG_INV_FAIL:
+ sprintf(name,"CVDIAG_INV_FAIL");
+ break;
+ case CVDIAG_RHSFUNC_UNRECVR:
+ sprintf(name,"CVDIAG_RHSFUNC_UNRECVR");
+ break;
+ case CVDIAG_RHSFUNC_RECVR:
+ sprintf(name,"CVDIAG_RHSFUNC_RECVR");
+ break;
+ case CVDIAG_NO_ADJ:
+ sprintf(name,"CVDIAG_NO_ADJ");
+ break;
+ default:
+ sprintf(name,"NONE");
+ }
+
+ return(name);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * CVDiagInit
+ * -----------------------------------------------------------------
+ * This routine does remaining initializations specific to the diagonal
+ * linear solver.
+ * -----------------------------------------------------------------
+ */
+
+static int CVDiagInit(CVodeMem cv_mem)
+{
+ CVDiagMem cvdiag_mem;
+
+ cvdiag_mem = (CVDiagMem) lmem;
+
+ nfeDI = 0;
+
+ last_flag = CVDIAG_SUCCESS;
+ return(0);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * CVDiagSetup
+ * -----------------------------------------------------------------
+ * This routine does the setup operations for the diagonal linear
+ * solver. It constructs a diagonal approximation to the Newton matrix
+ * M = I - gamma*J, updates counters, and inverts M.
+ * -----------------------------------------------------------------
+ */
+
+static int CVDiagSetup(CVodeMem cv_mem, int convfail, N_Vector ypred,
+ N_Vector fpred, booleantype *jcurPtr, N_Vector vtemp1,
+ N_Vector vtemp2, N_Vector vtemp3)
+{
+ realtype r;
+ N_Vector ftemp, y;
+ booleantype invOK;
+ CVDiagMem cvdiag_mem;
+ int retval;
+
+ cvdiag_mem = (CVDiagMem) lmem;
+
+ /* Rename work vectors for use as temporary values of y and f */
+ ftemp = vtemp1;
+ y = vtemp2;
+
+ /* Form y with perturbation = FRACT*(func. iter. correction) */
+ r = FRACT * rl1;
+ N_VLinearSum(h, fpred, -ONE, zn[1], ftemp);
+ N_VLinearSum(r, ftemp, ONE, ypred, y);
+
+ /* Evaluate f at perturbed y */
+ retval = f(tn, y, M, cv_mem->cv_user_data);
+ nfeDI++;
+ if (retval < 0) {
+ cvProcessError(cv_mem, CVDIAG_RHSFUNC_UNRECVR, "CVDIAG", "CVDiagSetup", MSGDG_RHSFUNC_FAILED);
+ last_flag = CVDIAG_RHSFUNC_UNRECVR;
+ return(-1);
+ }
+ if (retval > 0) {
+ last_flag = CVDIAG_RHSFUNC_RECVR;
+ return(1);
+ }
+
+ /* Construct M = I - gamma*J with J = diag(deltaf_i/deltay_i) */
+ N_VLinearSum(ONE, M, -ONE, fpred, M);
+ N_VLinearSum(FRACT, ftemp, -h, M, M);
+ N_VProd(ftemp, ewt, y);
+ /* Protect against deltay_i being at roundoff level */
+ N_VCompare(uround, y, bit);
+ N_VAddConst(bit, -ONE, bitcomp);
+ N_VProd(ftemp, bit, y);
+ N_VLinearSum(FRACT, y, -ONE, bitcomp, y);
+ N_VDiv(M, y, M);
+ N_VProd(M, bit, M);
+ N_VLinearSum(ONE, M, -ONE, bitcomp, M);
+
+ /* Invert M with test for zero components */
+ invOK = N_VInvTest(M, M);
+ if (!invOK) {
+ last_flag = CVDIAG_INV_FAIL;
+ return(1);
+ }
+
+ /* Set jcur = TRUE, save gamma in gammasv, and return */
+ *jcurPtr = TRUE;
+ gammasv = gamma;
+ last_flag = CVDIAG_SUCCESS;
+ return(0);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * CVDiagSolve
+ * -----------------------------------------------------------------
+ * This routine performs the solve operation for the diagonal linear
+ * solver. If necessary it first updates gamma in M = I - gamma*J.
+ * -----------------------------------------------------------------
+ */
+
+static int CVDiagSolve(CVodeMem cv_mem, N_Vector b, N_Vector weight,
+ N_Vector ycur, N_Vector fcur)
+{
+ booleantype invOK;
+ realtype r;
+ CVDiagMem cvdiag_mem;
+
+ cvdiag_mem = (CVDiagMem) lmem;
+
+ /* If gamma has changed, update factor in M, and save gamma value */
+
+ if (gammasv != gamma) {
+ r = gamma / gammasv;
+ N_VInv(M, M);
+ N_VAddConst(M, -ONE, M);
+ N_VScale(r, M, M);
+ N_VAddConst(M, ONE, M);
+ invOK = N_VInvTest(M, M);
+ if (!invOK) {
+ last_flag = CVDIAG_INV_FAIL;
+ return (1);
+ }
+ gammasv = gamma;
+ }
+
+ /* Apply M-inverse to b */
+ N_VProd(b, M, b);
+
+ last_flag = CVDIAG_SUCCESS;
+ return(0);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * CVDiagFree
+ * -----------------------------------------------------------------
+ * This routine frees memory specific to the diagonal linear solver.
+ * -----------------------------------------------------------------
+ */
+
+static void CVDiagFree(CVodeMem cv_mem)
+{
+ CVDiagMem cvdiag_mem;
+
+ cvdiag_mem = (CVDiagMem) lmem;
+
+ N_VDestroy(M);
+ N_VDestroy(bit);
+ N_VDestroy(bitcomp);
+ free(cvdiag_mem);
+ cv_mem->cv_lmem = NULL;
+}
+
+
+/*
+ * ================================================================
+ *
+ * PART II - backward problems
+ *
+ * ================================================================
+ */
+
+
+/*
+ * CVDiagB
+ *
+ * Wrappers for the backward phase around the corresponding
+ * CVODES functions
+ */
+
+int CVDiagB(void *cvode_mem, int which)
+{
+ 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, CVDIAG_MEM_NULL, "CVSDIAG", "CVDiagB", MSGDG_CVMEM_NULL);
+ return(CVDIAG_MEM_NULL);
+ }
+ cv_mem = (CVodeMem) cvode_mem;
+
+ /* Was ASA initialized? */
+ if (cv_mem->cv_adjMallocDone == FALSE) {
+ cvProcessError(cv_mem, CVDIAG_NO_ADJ, "CVSDIAG", "CVDiagB", MSGDG_NO_ADJ);
+ return(CVDIAG_NO_ADJ);
+ }
+ ca_mem = cv_mem->cv_adj_mem;
+
+ /* Check which */
+ if ( which >= ca_mem->ca_nbckpbs ) {
+ cvProcessError(cv_mem, CVDIAG_ILL_INPUT, "CVSDIAG", "CVDiagB", MSGDG_BAD_WHICH);
+ return(CVDIAG_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 = CVDiag(cvodeB_mem);
+
+ return(flag);
+}
+
diff --git a/src/cvodes/cvodes_diag_impl.h b/src/cvodes/cvodes_diag_impl.h
new file mode 100644
index 0000000..f500187
--- /dev/null
+++ b/src/cvodes/cvodes_diag_impl.h
@@ -0,0 +1,67 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.5 $
+ * $Date: 2010/12/01 22:30:42 $
+ * -----------------------------------------------------------------
+ * Programmer(s): 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.
+ * -----------------------------------------------------------------
+ * Implementation header file for the diagonal linear solver, CVDIAG.
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _CVSDIAG_IMPL_H
+#define _CVSDIAG_IMPL_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <cvodes/cvodes_diag.h>
+
+/*
+ * -----------------------------------------------------------------
+ * Types: CVDiagMemRec, CVDiagMem
+ * -----------------------------------------------------------------
+ * The type CVDiagMem is pointer to a CVDiagMemRec.
+ * This structure contains CVDiag solver-specific data.
+ * -----------------------------------------------------------------
+ */
+
+typedef struct {
+
+ realtype di_gammasv; /* gammasv = gamma at the last call to setup or solve */
+
+ N_Vector di_M; /* M = (I - gamma J)^{-1} , gamma = h / l1 */
+
+ N_Vector di_bit; /* temporary storage vector */
+
+ N_Vector di_bitcomp; /* temporary storage vector */
+
+ 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 */
+
+} CVDiagMemRec, *CVDiagMem;
+
+/* Error Messages */
+
+#define MSGDG_CVMEM_NULL "Integrator memory is NULL."
+#define MSGDG_MEM_FAIL "A memory request failed."
+#define MSGDG_BAD_NVECTOR "A required vector operation is not implemented."
+#define MSGDG_LMEM_NULL "CVDIAG memory is NULL."
+#define MSGDG_RHSFUNC_FAILED "The right-hand side routine failed in an unrecoverable manner."
+
+#define MSGDG_NO_ADJ "Illegal attempt to call before calling CVodeAdjMalloc."
+#define MSGDG_BAD_WHICH "Illegal value for which."
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/cvodes/cvodes_direct.c b/src/cvodes/cvodes_direct.c
new file mode 100644
index 0000000..04430a0
--- /dev/null
+++ b/src/cvodes/cvodes_direct.c
@@ -0,0 +1,711 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.10 $
+ * $Date: 2010/12/01 22:30:43 $
+ * -----------------------------------------------------------------
+ * Programmer: Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2006, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * This is the implementation file for the CVSDLS linear solvers
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * =================================================================
+ * IMPORTED HEADER FILES
+ * =================================================================
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "cvodes_impl.h"
+#include "cvodes_direct_impl.h"
+#include <sundials/sundials_math.h>
+
+/*
+ * =================================================================
+ * FUNCTION SPECIFIC CONSTANTS
+ * =================================================================
+ */
+
+/* Constant for DQ Jacobian approximation */
+#define MIN_INC_MULT RCONST(1000.0)
+
+#define ZERO RCONST(0.0)
+#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 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);
+
+
+/*
+ * =================================================================
+ * 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)
+ * =================================================================
+ */
+
+/*
+ * CVDlsSetDenseJacFn specifies the dense Jacobian function.
+ */
+int CVDlsSetDenseJacFn(void *cvode_mem, CVDlsDenseJacFn jac)
+{
+ CVodeMem cv_mem;
+ CVDlsMem cvdls_mem;
+
+ /* Return immediately if cvode_mem is NULL */
+ if (cvode_mem == NULL) {
+ cvProcessError(NULL, CVDLS_MEM_NULL, "CVDLS", "CVDlsSetDenseJacFn", MSGD_CVMEM_NULL);
+ return(CVDLS_MEM_NULL);
+ }
+ cv_mem = (CVodeMem) cvode_mem;
+
+ if (lmem == NULL) {
+ cvProcessError(cv_mem, CVDLS_LMEM_NULL, "CVDLS", "CVDlsSetDenseJacFn", MSGD_LMEM_NULL);
+ return(CVDLS_LMEM_NULL);
+ }
+ cvdls_mem = (CVDlsMem) lmem;
+
+ if (jac != NULL) {
+ jacDQ = FALSE;
+ djac = jac;
+ } else {
+ jacDQ = TRUE;
+ }
+
+ return(CVDLS_SUCCESS);
+}
+
+/*
+ * CVDlsSetBandJacFn specifies the band Jacobian function.
+ */
+int CVDlsSetBandJacFn(void *cvode_mem, CVDlsBandJacFn jac)
+{
+ CVodeMem cv_mem;
+ CVDlsMem cvdls_mem;
+
+ /* Return immediately if cvode_mem is NULL */
+ if (cvode_mem == NULL) {
+ cvProcessError(NULL, CVDLS_MEM_NULL, "CVDLS", "CVDlsSetBandJacFn", 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);
+ return(CVDLS_LMEM_NULL);
+ }
+ cvdls_mem = (CVDlsMem) lmem;
+
+ if (jac != NULL) {
+ jacDQ = FALSE;
+ bjac = jac;
+ } else {
+ jacDQ = TRUE;
+ }
+
+ 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)
+{
+ CVodeMem cv_mem;
+ CVDlsMem cvdls_mem;
+
+ /* Return immediately if cvode_mem is NULL */
+ if (cvode_mem == 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);
+ return(CVDLS_LMEM_NULL);
+ }
+ cvdls_mem = (CVDlsMem) 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;
+ }
+
+ return(CVDLS_SUCCESS);
+}
+
+/*
+ * 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 */
+ if (cvode_mem == 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);
+ return(CVDLS_LMEM_NULL);
+ }
+ cvdls_mem = (CVDlsMem) lmem;
+
+ *njevals = nje;
+
+ return(CVDLS_SUCCESS);
+}
+
+/*
+ * 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 */
+ if (cvode_mem == 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);
+ return(CVDLS_LMEM_NULL);
+ }
+ cvdls_mem = (CVDlsMem) lmem;
+
+ *nfevalsLS = nfeDQ;
+
+ return(CVDLS_SUCCESS);
+}
+
+/*
+ * CVDlsGetReturnFlagName returns the name associated with a CVDLS
+ * return value.
+ */
+char *CVDlsGetReturnFlagName(long int flag)
+{
+ char *name;
+
+ name = (char *)malloc(30*sizeof(char));
+
+ switch(flag) {
+ case CVDLS_SUCCESS:
+ sprintf(name,"CVDLS_SUCCESS");
+ break;
+ case CVDLS_MEM_NULL:
+ sprintf(name,"CVDLS_MEM_NULL");
+ break;
+ case CVDLS_LMEM_NULL:
+ sprintf(name,"CVDLS_LMEM_NULL");
+ break;
+ case CVDLS_ILL_INPUT:
+ sprintf(name,"CVDLS_ILL_INPUT");
+ break;
+ case CVDLS_MEM_FAIL:
+ sprintf(name,"CVDLS_MEM_FAIL");
+ break;
+ case CVDLS_JACFUNC_UNRECVR:
+ sprintf(name,"CVDLS_JACFUNC_UNRECVR");
+ break;
+ case CVDLS_JACFUNC_RECVR:
+ sprintf(name,"CVDLS_JACFUNC_RECVR");
+ break;
+ default:
+ sprintf(name,"NONE");
+ }
+
+ return(name);
+}
+
+/*
+ * 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 */
+ if (cvode_mem == 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);
+ return(CVDLS_LMEM_NULL);
+ }
+ cvdls_mem = (CVDlsMem) lmem;
+
+ *flag = 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.
+ * -----------------------------------------------------------------
+ */
+
+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)
+{
+ realtype fnorm, minInc, inc, inc_inv, yjsaved, srur;
+ realtype *tmp2_data, *y_data, *ewt_data;
+ N_Vector ftemp, jthCol;
+ long int j;
+ int retval = 0;
+
+ CVodeMem cv_mem;
+ CVDlsMem cvdls_mem;
+
+ /* data points to cvode_mem */
+ cv_mem = (CVodeMem) data;
+ cvdls_mem = (CVDlsMem) lmem;
+
+ /* Save pointer to the array in tmp2 */
+ tmp2_data = N_VGetArrayPointer(tmp2);
+
+ /* Rename work vectors for readibility */
+ ftemp = tmp1;
+ jthCol = tmp2;
+
+ /* Obtain pointers to the data for ewt, y */
+ ewt_data = N_VGetArrayPointer(ewt);
+ y_data = N_VGetArrayPointer(y);
+
+ /* Set minimum increment based on uround and norm of f */
+ srur = RSqrt(uround);
+ fnorm = N_VWrmsNorm(fy, ewt);
+ minInc = (fnorm != ZERO) ?
+ (MIN_INC_MULT * ABS(h) * 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);
+
+ yjsaved = y_data[j];
+ inc = MAX(srur*ABS(yjsaved), minInc/ewt_data[j]);
+ y_data[j] += inc;
+
+ retval = f(t, y, ftemp, user_data);
+ nfeDQ++;
+ if (retval != 0) break;
+
+ y_data[j] = yjsaved;
+
+ inc_inv = ONE/inc;
+ N_VLinearSum(inc_inv, ftemp, -inc_inv, fy, jthCol);
+
+ DENSE_COL(Jac,j) = N_VGetArrayPointer(jthCol);
+ }
+
+ /* Restore original array pointer in tmp2 */
+ N_VSetArrayPointer(tmp2_data, tmp2);
+
+ 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)
+{
+ 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;
+ int retval = 0;
+
+ CVodeMem cv_mem;
+ CVDlsMem cvdls_mem;
+
+ /* data points to cvode_mem */
+ cv_mem = (CVodeMem) data;
+ cvdls_mem = (CVDlsMem) lmem;
+
+ /* 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);
+ fy_data = N_VGetArrayPointer(fy);
+ ftemp_data = N_VGetArrayPointer(ftemp);
+ y_data = N_VGetArrayPointer(y);
+ ytemp_data = N_VGetArrayPointer(ytemp);
+
+ /* Load ytemp with y = predicted y vector */
+ N_VScale(ONE, y, ytemp);
+
+ /* Set minimum increment based on uround and norm of f */
+ srur = RSqrt(uround);
+ fnorm = N_VWrmsNorm(fy, ewt);
+ minInc = (fnorm != ZERO) ?
+ (MIN_INC_MULT * ABS(h) * uround * N * fnorm) : ONE;
+
+ /* Set bandwidth and number of column groups for band differencing */
+ width = mlower + mupper + 1;
+ ngroups = MIN(width, N);
+
+ /* Loop over column groups. */
+ for (group=1; group <= ngroups; group++) {
+
+ /* Increment all y_j in group */
+ for(j=group-1; j < N; j+=width) {
+ inc = MAX(srur*ABS(y_data[j]), minInc/ewt_data[j]);
+ ytemp_data[j] += inc;
+ }
+
+ /* Evaluate f with incremented y */
+
+ retval = f(tn, ytemp, ftemp, user_data);
+ 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);
+ inc = MAX(srur*ABS(y_data[j]), minInc/ewt_data[j]);
+ inc_inv = ONE/inc;
+ i1 = MAX(0, j-mupper);
+ i2 = MIN(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]);
+ }
+ }
+
+ return(retval);
+}
+
+/*
+ * =================================================================
+ * BACKWARD INTEGRATION SUPPORT
+ * =================================================================
+ */
+
+/*
+ * -----------------------------------------------------------------
+ * Additional readability replacements
+ * -----------------------------------------------------------------
+ */
+
+#define ytmp (ca_mem->ca_ytmp)
+#define yStmp (ca_mem->ca_yStmp)
+#define IMget (ca_mem->ca_IMget)
+
+#define mtypeB (cvdlsB_mem->d_typeB)
+#define djacB (cvdlsB_mem->d_djacB)
+#define bjacB (cvdlsB_mem->d_bjacB)
+
+/*
+ * -----------------------------------------------------------------
+ * EXPORTED FUNCTIONS
+ * -----------------------------------------------------------------
+ */
+
+int CVDlsSetDenseJacFnB(void *cvode_mem, int which, CVDlsDenseJacFnB jacB)
+{
+ CVodeMem cv_mem;
+ CVadjMem ca_mem;
+ CVodeBMem cvB_mem;
+ CVDlsMemB cvdlsB_mem;
+ void *cvodeB_mem;
+ int flag;
+
+ /* Check if cvode_mem exists */
+ if (cvode_mem == NULL) {
+ cvProcessError(NULL, CVDLS_MEM_NULL, "CVSDLS", "CVDlsSetDenseJacFnB", 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", "CVDlsSetDenseJacFnB", 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", "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;
+ }
+
+ cvodeB_mem = (void *) (cvB_mem->cv_mem);
+
+ if (cvB_mem->cv_lmem == NULL) {
+ cvProcessError(cv_mem, CVDLS_LMEMB_NULL, "CVSDLS", "CVDlsSetDenseJacFnB", MSGD_LMEMB_NULL);
+ return(CVDLS_LMEMB_NULL);
+ }
+ cvdlsB_mem = (CVDlsMemB) (cvB_mem->cv_lmem);
+
+ djacB = jacB;
+
+ if (jacB != NULL) {
+ flag = CVDlsSetDenseJacFn(cvodeB_mem, cvDlsDenseJacBWrapper);
+ } else {
+ flag = CVDlsSetDenseJacFn(cvodeB_mem, NULL);
+ }
+
+ return(flag);
+}
+
+int CVDlsSetBandJacFnB(void *cvode_mem, int which, CVDlsBandJacFnB jacB)
+{
+ CVodeMem cv_mem;
+ CVadjMem ca_mem;
+ CVodeBMem cvB_mem;
+ CVDlsMemB cvdlsB_mem;
+ void *cvodeB_mem;
+ int flag;
+
+ /* Check if cvode_mem exists */
+ if (cvode_mem == NULL) {
+ cvProcessError(NULL, CVDLS_MEM_NULL, "CVSDLS", "CVDlsSetBandJacFnB", 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);
+ 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);
+ 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);
+
+ if (cvB_mem->cv_lmem == NULL) {
+ cvProcessError(cv_mem, CVDLS_LMEMB_NULL, "CVSDLS", "CVDlsSetBandJacFnB", MSGD_LMEMB_NULL);
+ return(CVDLS_LMEMB_NULL);
+ }
+ cvdlsB_mem = (CVDlsMemB) (cvB_mem->cv_lmem);
+
+ bjacB = jacB;
+
+ if (jacB != NULL) {
+ flag = CVDlsSetBandJacFn(cvodeB_mem, cvDlsBandJacBWrapper);
+ } else {
+ flag = CVDlsSetBandJacFn(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
+ */
+
+
+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)
+{
+ 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;
+
+ 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);
+
+}
+
+
+/*
+ * 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;
+
+ ca_mem = cv_mem->cv_adj_mem;
+
+ cvB_mem = ca_mem->ca_bckpbCrt;
+
+ 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", "cvDlsBandJacBWrapper", 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);
+
+ return(retval);
+}
+
diff --git a/src/cvodes/cvodes_direct_impl.h b/src/cvodes/cvodes_direct_impl.h
new file mode 100644
index 0000000..ce803b6
--- /dev/null
+++ b/src/cvodes/cvodes_direct_impl.h
@@ -0,0 +1,154 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.9 $
+ * $Date: 2010/12/01 22:30:42 $
+ * -----------------------------------------------------------------
+ * Programmer: Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2006, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * Common implementation header file for the CVDLS linear solvers.
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _CVSDLS_IMPL_H
+#define _CVSDLS_IMPL_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <cvodes/cvodes_direct.h>
+
+/*
+ * =================================================================
+ * 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
+ * =================================================================
+ */
+
+/*
+ * -----------------------------------------------------------------
+ * 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
+ * =================================================================
+ */
+
+/*
+ * -----------------------------------------------------------------
+ * 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 */
+
+ 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) */
+
+ 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 */
+
+ 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. */
+
+ long int d_nje; /* nje = no. of calls to jac */
+
+ long int d_nfeDQ; /* no. of calls to f due to DQ Jacobian approx. */
+
+ long int d_last_flag; /* last error return flag */
+
+} *CVDlsMem;
+
+/*
+ * -----------------------------------------------------------------
+ * Prototypes of internal functions
+ * -----------------------------------------------------------------
+ */
+
+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);
+
+
+/*
+ * =================================================================
+ * PART II: B A C K W A R D P R O B L E M S
+ * =================================================================
+ */
+
+/*
+ * -----------------------------------------------------------------
+ * 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;
+ CVDlsBandJacFnB d_bjacB;
+
+} *CVDlsMemB;
+
+
+/*
+ * =================================================================
+ * E R R O R M E S S A G E S
+ * =================================================================
+ */
+
+#define MSGD_CVMEM_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_JACFUNC_FAILED "The Jacobian 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."
+#define MSGD_LMEMB_NULL "Linear solver memory is NULL for the backward integration."
+#define MSGD_BAD_TINTERP "Bad t for interpolation."
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/cvodes/cvodes_impl.h b/src/cvodes/cvodes_impl.h
new file mode 100644
index 0000000..8683633
--- /dev/null
+++ b/src/cvodes/cvodes_impl.h
@@ -0,0 +1,1088 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.21 $
+ * $Date: 2007/11/26 16:19:59 $
+ * -----------------------------------------------------------------
+ * Programmer(s): 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.
+ * -----------------------------------------------------------------
+ * Implementation header file for the main CVODES integrator.
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _CVODES_IMPL_H
+#define _CVODES_IMPL_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <stdarg.h>
+
+#include <cvodes/cvodes.h>
+#include <sundials/sundials_nvector.h>
+#include <sundials/sundials_types.h>
+
+/*
+ * =================================================================
+ * I N T E R N A L C V O D E S C O N S T A N T S
+ * =================================================================
+ */
+
+/* Basic CVODES constants */
+
+#define ADAMS_Q_MAX 12 /* max value of q for lmm == ADAMS */
+#define BDF_Q_MAX 5 /* max value of q for lmm == BDF */
+#define Q_MAX ADAMS_Q_MAX /* max value of q for either lmm */
+#define L_MAX (Q_MAX+1) /* max value of L for either lmm */
+#define NUM_TESTS 5 /* number of error test quantities */
+
+#define HMIN_DEFAULT RCONST(0.0) /* hmin default value */
+#define HMAX_INV_DEFAULT RCONST(0.0) /* hmax_inv default value */
+#define MXHNIL_DEFAULT 10 /* mxhnil default value */
+#define MXSTEP_DEFAULT 500 /* mxstep default value */
+
+/*
+ * =================================================================
+ * F O R W A R D P O I N T E R R E F E R E N C E S
+ * =================================================================
+ */
+
+typedef struct CVadjMemRec *CVadjMem;
+typedef struct CkpntMemRec *CkpntMem;
+typedef struct DtpntMemRec *DtpntMem;
+typedef struct CVodeBMemRec *CVodeBMem;
+
+/*
+ * =================================================================
+ * M A I N I N T E G R A T O R M E M O R Y B L O C K
+ * =================================================================
+ */
+
+
+/*
+ * -----------------------------------------------------------------
+ * Types: struct CVodeMemRec, CVodeMem
+ * -----------------------------------------------------------------
+ * The type CVodeMem is type pointer to struct CVodeMemRec.
+ * This structure contains fields to keep track of problem state.
+ * -----------------------------------------------------------------
+ */
+
+typedef struct CVodeMemRec {
+
+ 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 */
+
+ 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 */
+
+ /*-----------------------
+ Quadrature Related Data
+ -----------------------*/
+
+ booleantype cv_quadr; /* TRUE if integrating quadratures */
+
+ CVQuadRhsFn cv_fQ; /* q' = fQ(t, y(t)) */
+
+ booleantype cv_errconQ; /* TRUE 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 */
+
+ /*------------------------
+ Sensitivity Related Data
+ ------------------------*/
+
+ booleantype cv_sensi; /* TRUE if computing sensitivities */
+
+ int cv_Ns; /* Number of sensitivities */
+
+ int cv_ism; /* ism = SIMULTANEOUS or STAGGERED */
+
+ 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 */
+ int cv_ifS; /* ifS = ALLSENS or ONESENS */
+
+ realtype *cv_p; /* parameters in f(t,y,p) */
+ realtype *cv_pbar; /* scale factors for parameters */
+ int *cv_plist; /* list of sensitivities */
+ 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 */
+
+ int cv_itolS;
+ realtype cv_reltolS; /* relative tolerance for sensitivities */
+ realtype *cv_SabstolS; /* scalar absolute tolerances for sensi. */
+ N_Vector *cv_VabstolS; /* vector absolute tolerances for sensi. */
+
+ /*-----------------------------------
+ Quadrature Sensitivity Related Data
+ -----------------------------------*/
+
+ booleantype cv_quadr_sensi; /* TRUE 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_errconQS; /* TRUE if yQS are considered in err. con. */
+
+ int cv_itolQS;
+ realtype cv_reltolQS; /* relative tolerance for yQS */
+ realtype *cv_SabstolQS; /* scalar absolute tolerances for yQS */
+ N_Vector *cv_VabstolQS; /* vector absolute tolerances for yQS */
+
+ /*-----------------------
+ Nordsieck History Array
+ -----------------------*/
+
+ N_Vector cv_zn[L_MAX]; /* Nordsieck array, of size N x (q+1).
+ zn[j] is a vector of length N (j=0,...,q)
+ zn[j] = [1/factorial(j)] * h^j *
+ (jth derivative of the interpolating poly.) */
+
+ /*-------------------
+ Vectors of length N
+ -------------------*/
+
+ N_Vector cv_ewt; /* error weight vector */
+ N_Vector cv_y; /* y is used as temporary storage by the solver.
+ The memory is provided by the user to CVode
+ where the vector is named yout. */
+ N_Vector cv_acor; /* In the context of the solution of the
+ nonlinear equation, acor = y_n(m) - y_n(0).
+ On return, this vector is scaled to give
+ the estimated local error in y. */
+ N_Vector cv_tempv; /* temporary storage vector */
+ N_Vector cv_ftemp; /* temporary storage vector */
+
+ /*--------------------------
+ Quadrature Related Vectors
+ --------------------------*/
+
+ N_Vector cv_znQ[L_MAX]; /* Nordsieck arrays for quadratures */
+ N_Vector cv_ewtQ; /* error weight vector for quadratures */
+ N_Vector cv_yQ; /* Unlike y, yQ is not allocated by the user */
+ N_Vector cv_acorQ; /* acorQ = yQ_n(m) - yQ_n(0) */
+ N_Vector cv_tempvQ; /* temporary storage vector (~ tempv) */
+
+ /*---------------------------
+ Sensitivity Related Vectors
+ ---------------------------*/
+
+ N_Vector *cv_znS[L_MAX]; /* Nordsieck arrays for sensitivities */
+ N_Vector *cv_ewtS; /* error weight vectors for sensitivities */
+ N_Vector *cv_yS; /* yS=yS0 (allocated by the user) */
+ N_Vector *cv_acorS; /* acorS = yS_n(m) - yS_n(0) */
+ N_Vector *cv_tempvS; /* temporary storage vector (~ tempv) */
+ N_Vector *cv_ftempS; /* temporary storage vector (~ ftemp) */
+
+ booleantype cv_stgr1alloc; /* Did we allocate ncfS1, ncfnS1, and nniS1? */
+
+ /*--------------------------------------
+ Quadrature Sensitivity Related Vectors
+ --------------------------------------*/
+
+ N_Vector *cv_znQS[L_MAX]; /* Nordsieck arrays for quadr. sensitivities */
+ N_Vector *cv_ewtQS; /* error weight vectors for sensitivities */
+ N_Vector *cv_yQS; /* Unlike yS, yQS is not allocated by the user */
+ N_Vector *cv_acorQS; /* acorQS = yQS_n(m) - yQS_n(0) */
+ N_Vector *cv_tempvQS; /* temporary storage vector (~ tempv) */
+ N_Vector cv_ftempQ; /* temporary storage vector (~ ftemp) */
+
+ /*-----------------
+ Tstop information
+ -----------------*/
+
+ booleantype cv_tstopset;
+ realtype cv_tstop;
+
+ /*---------
+ Step Data
+ ---------*/
+
+ int cv_q; /* current order */
+ int cv_qprime; /* order to be used on the next step
+ * qprime = q-1, q, or q+1 */
+ int cv_next_q; /* order to be used on the next step */
+ int cv_qwait; /* number of internal steps to wait before
+ * considering a change in q */
+ int cv_L; /* L = q + 1 */
+
+ realtype cv_hin;
+ realtype cv_h; /* current step size */
+ realtype cv_hprime; /* step size to be used on the next step */
+ realtype cv_next_h; /* step size to be used on the next step */
+ realtype cv_eta; /* eta = hprime / h */
+ realtype cv_hscale; /* value of h used in zn */
+ realtype cv_tn; /* current internal value of t */
+ realtype cv_tretlast; /* last value of t returned */
+
+ realtype cv_tau[L_MAX+1]; /* array of previous q+1 successful step
+ * sizes indexed from 1 to q+1 */
+ realtype cv_tq[NUM_TESTS+1]; /* array of test quantities indexed from
+ * 1 to NUM_TESTS(=5) */
+ realtype cv_l[L_MAX]; /* coefficients of l(x) (degree q poly) */
+
+ realtype cv_rl1; /* the scalar 1/l[1] */
+ realtype cv_gamma; /* gamma = h * rl1 */
+ realtype cv_gammap; /* gamma at the last setup call */
+ realtype cv_gamrat; /* gamma / gammap */
+
+ realtype cv_crate; /* est. corrector conv. rate in Nls */
+ realtype cv_crateS; /* est. corrector conv. rate in NlsStgr */
+ realtype cv_acnrm; /* | acor | */
+ realtype cv_acnrmQ; /* | acorQ | */
+ realtype cv_acnrmS; /* | acorS | */
+ realtype cv_acnrmQS; /* | acorQS | */
+ realtype cv_nlscoef; /* coeficient in nonlinear convergence test */
+ int cv_mnewt; /* Newton iteration counter */
+ int *cv_ncfS1; /* Array of Ns local counters for conv.
+ * failures (used in CVStep for STAGGERED1) */
+
+ /*------
+ Limits
+ ------*/
+
+ int cv_qmax; /* q <= qmax */
+ long int cv_mxstep; /* maximum number of internal steps for one
+ user call */
+ int cv_maxcor; /* maximum number of corrector iterations for
+ the solution of the nonlinear equation */
+ int cv_maxcorS;
+ int cv_mxhnil; /* max. number of warning messages issued to the
+ 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 */
+
+ /*----------
+ Counters
+ ----------*/
+
+ long int cv_nst; /* number of internal steps taken */
+
+ long int cv_nfe; /* number of f calls */
+ long int cv_nfQe; /* number of fQ calls */
+ long int cv_nfSe; /* number of fS calls */
+ long int cv_nfeS; /* number of f calls from sensi DQ */
+ long int cv_nfQSe; /* number of fQS calls */
+ long int cv_nfQeS; /* number of fQ calls from sensi DQ */
+
+
+ long int cv_ncfn; /* number of corrector convergence failures */
+ long int cv_ncfnS; /* number of total sensi. corr. conv. failures */
+ long int *cv_ncfnS1; /* number of sensi. corrector conv. failures */
+
+ long int cv_nni; /* number of nonlinear iterations performed */
+ long int cv_nniS; /* number of total sensi. nonlinear iterations */
+ long int *cv_nniS1; /* number of sensi. nonlinear iterations */
+
+ long int cv_netf; /* number of error test failures */
+ long int cv_netfQ; /* number of quadr. error test failures */
+ long int cv_netfS; /* number of sensi. error test failures */
+ long int cv_netfQS; /* number of quadr. sensi. error test failures */
+
+ long int cv_nsetups; /* number of setup calls */
+ long int cv_nsetupsS; /* number of setup calls due to sensitivities */
+
+ int cv_nhnil; /* number of messages issued to the user that
+ t + h == t for the next iternal step */
+
+ /*-----------------------------
+ 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 */
+
+ /*----------------
+ Step size ratios
+ ----------------*/
+
+ realtype cv_etaqm1; /* ratio of new to old h for order q-1 */
+ realtype cv_etaq; /* ratio of new to old h for order q */
+ realtype cv_etaqp1; /* ratio of new to old h for order q+1 */
+
+ /*------------------
+ Linear Solver Data
+ ------------------*/
+
+ /* Linear Solver functions to be called */
+
+ int (*cv_linit)(struct CVodeMemRec *cv_mem);
+
+ int (*cv_lsetup)(struct CVodeMemRec *cv_mem, int convfail,
+ N_Vector ypred, N_Vector fpred, booleantype *jcurPtr,
+ N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3);
+
+ int (*cv_lsolve)(struct CVodeMemRec *cv_mem, N_Vector b, N_Vector weight,
+ N_Vector ycur, N_Vector fcur);
+
+ void (*cv_lfree)(struct CVodeMemRec *cv_mem);
+
+ /* Linear Solver specific memory */
+
+ void *cv_lmem;
+
+ /* Flag to request a call to the setup routine */
+
+ booleantype cv_forceSetup;
+
+ /*------------
+ Saved Values
+ ------------*/
+
+ int cv_qu; /* last successful q value used */
+ long int cv_nstlp; /* step number of last setup call */
+ realtype cv_h0u; /* actual initial stepsize */
+ 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? */
+ 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
+ and read by CVodeReInit, CVodeSensReInit, and CVodeQuadReInit
+ --------------------------------------------------------------------*/
+
+ booleantype cv_VabstolMallocDone;
+ booleantype cv_MallocDone;
+
+ booleantype cv_VabstolQMallocDone;
+ booleantype cv_QuadMallocDone;
+
+ booleantype cv_VabstolSMallocDone;
+ booleantype cv_SabstolSMallocDone;
+ booleantype cv_SensMallocDone;
+
+ booleantype cv_VabstolQSMallocDone;
+ booleantype cv_SabstolQSMallocDone;
+ booleantype cv_QuadSensMallocDone;
+
+ /*-------------------------------------------
+ Error handler function and error ouput file
+ -------------------------------------------*/
+
+ CVErrHandlerFn cv_ehfun; /* Error messages are handled by ehfun */
+ void *cv_eh_data; /* dats pointer passed to ehfun */
+ FILE *cv_errfp; /* CVODES error messages are sent to errfp */
+
+ /*-------------------------
+ Stability Limit Detection
+ -------------------------*/
+
+ booleantype cv_sldeton; /* Is Stability Limit Detection on? */
+ realtype cv_ssdat[6][4]; /* scaled data array for STALD */
+ int cv_nscon; /* counter for STALD method */
+ long int cv_nor; /* counter for number of order reductions */
+
+ /*----------------
+ Rootfinding Data
+ ----------------*/
+
+ CVRootFn cv_gfun; /* Function g for roots sought */
+ int cv_nrtfn; /* number of components of g */
+ int *cv_iroots; /* array for root information */
+ int *cv_rootdir; /* array specifying direction of zero-crossing */
+ realtype cv_tlo; /* nearest endpoint of interval in root search */
+ realtype cv_thi; /* farthest endpoint of interval in root search */
+ realtype cv_trout; /* t value returned by rootfinding routine */
+ realtype *cv_glo; /* saved array of g values at t = tlo */
+ realtype *cv_ghi; /* saved array of g values at t = thi */
+ realtype *cv_grout; /* array of g values at t = trout */
+ realtype cv_toutc; /* copy of tout (if NORMAL mode) */
+ realtype cv_ttol; /* tolerance on root location trout */
+ int cv_taskc; /* copy of parameter itask */
+ int cv_irfnd; /* flag showing whether last step had a root */
+ long int cv_nge; /* counter for g evaluations */
+ booleantype *cv_gactive; /* array with active/inactive event functions */
+ int cv_mxgnull; /* number of warning messages about possible g==0 */
+
+ /*------------------------
+ Adjoint sensitivity data
+ ------------------------*/
+
+ booleantype cv_adj; /* TRUE if performing ASA */
+
+ struct CVadjMemRec *cv_adj_mem; /* Pointer to adjoint memory structure */
+
+ booleantype cv_adjMallocDone;
+
+} *CVodeMem;
+
+
+/*
+ * =================================================================
+ * A D J O I N T M O D U L E M E M O R Y B L O C K
+ * =================================================================
+ */
+
+/*
+ * -----------------------------------------------------------------
+ * Types : struct CkpntMemRec, CkpntMem
+ * -----------------------------------------------------------------
+ * The type CkpntMem is type pointer to struct CkpntMemRec.
+ * This structure contains fields to store all information at a
+ * check point that is needed to 'hot' start cvodes.
+ * -----------------------------------------------------------------
+ */
+
+struct CkpntMemRec {
+
+ /* Integration limits */
+ realtype ck_t0;
+ realtype ck_t1;
+
+ /* Nordsieck History Array */
+ N_Vector ck_zn[L_MAX];
+
+ /* Do we need to carry quadratures? */
+ booleantype ck_quadr;
+
+ /* Nordsieck History Array for quadratures */
+ N_Vector ck_znQ[L_MAX];
+
+ /* Do we need to carry sensitivities? */
+ booleantype ck_sensi;
+
+ /* number of sensitivities */
+ int ck_Ns;
+
+ /* Nordsieck History Array for sensitivities */
+ N_Vector *ck_znS[L_MAX];
+
+ /* Do we need to carry quadrature sensitivities? */
+ booleantype ck_quadr_sensi;
+
+ /* Nordsieck History Array for quadrature sensitivities */
+ N_Vector *ck_znQS[L_MAX];
+
+ /* Was ck_zn[qmax] allocated?
+ ck_zqm = 0 - no
+ ck_zqm = qmax - yes */
+ int ck_zqm;
+
+ /* Step data */
+ long int ck_nst;
+ realtype ck_tretlast;
+ int ck_q;
+ int ck_qprime;
+ int ck_qwait;
+ int ck_L;
+ realtype ck_gammap;
+ realtype ck_h;
+ realtype ck_hprime;
+ realtype ck_hscale;
+ realtype ck_eta;
+ realtype ck_etamax;
+ realtype ck_tau[L_MAX+1];
+ realtype ck_tq[NUM_TESTS+1];
+ realtype ck_l[L_MAX];
+
+ /* Saved values */
+ realtype ck_saved_tq5;
+
+ /* Pointer to next structure in list */
+ struct CkpntMemRec *ck_next;
+
+};
+
+/*
+ * -----------------------------------------------------------------
+ * Types for functions provided by an interpolation module
+ * -----------------------------------------------------------------
+ * cvaIMMallocFn: Type for a function that initializes the content
+ * field of the structures in the dt array
+ * cvaIMFreeFn: Type for a function that deallocates the content
+ * field of the structures in the dt array
+ * cvaIMGetYFn: Type for a function that returns the
+ * interpolated forward solution.
+ * cvaIMStorePnt: Type for a function that stores a new
+ * point in the structure d
+ * -----------------------------------------------------------------
+ */
+
+typedef booleantype (*cvaIMMallocFn)(CVodeMem cv_mem);
+typedef void (*cvaIMFreeFn)(CVodeMem cv_mem);
+typedef int (*cvaIMGetYFn)(CVodeMem cv_mem, realtype t, N_Vector y, N_Vector *yS);
+typedef int (*cvaIMStorePntFn)(CVodeMem cv_mem, DtpntMem d);
+
+/*
+ * -----------------------------------------------------------------
+ * Type : struct DtpntMemRec
+ * -----------------------------------------------------------------
+ * This structure contains fields to store all information at a
+ * data point that is needed to interpolate solution of forward
+ * simulations. Its content field depends on IMtype.
+ * -----------------------------------------------------------------
+ */
+
+struct DtpntMemRec {
+ realtype t; /* time */
+ void *content; /* IMtype-dependent content */
+};
+
+/* Data for cubic Hermite interpolation */
+typedef struct HermiteDataMemRec {
+ N_Vector y;
+ N_Vector yd;
+ N_Vector *yS;
+ N_Vector *ySd;
+} *HermiteDataMem;
+
+/* Data for polynomial interpolation */
+typedef struct PolynomialDataMemRec {
+ N_Vector y;
+ N_Vector *yS;
+ int order;
+} *PolynomialDataMem;
+
+
+/*
+ * -----------------------------------------------------------------
+ * Type : struct CVodeBMemRec
+ * -----------------------------------------------------------------
+ * The type CVodeBMem is a pointer to a structure which stores all
+ * information for ONE backward problem.
+ * The CVadjMem structure contains a linked list of CVodeBMem pointers
+ * -----------------------------------------------------------------
+ */
+
+struct CVodeBMemRec {
+
+ /* Index of this backward problem */
+ int cv_index;
+
+ /* Time at which the backward problem is intialized */
+ realtype cv_t0;
+
+ /* CVODES memory for this backward problem */
+ CVodeMem cv_mem;
+
+ /* Flags to indicate that this backward problem's RHS or quad RHS
+ * require forward sensitivities */
+ booleantype cv_f_withSensi;
+ booleantype cv_fQ_withSensi;
+
+ /* Right hand side function for backward run */
+ CVRhsFnB cv_f;
+ CVRhsFnBS cv_fs;
+
+ /* Right hand side quadrature function for backward run */
+ CVQuadRhsFnB cv_fQ;
+ CVQuadRhsFnBS cv_fQs;
+
+ /* User user_data */
+ void *cv_user_data;
+
+ /* Memory block for a linear solver's interface to CVODEA */
+ void *cv_lmem;
+
+ /* Function to free any memory allocated by the linear solver */
+ void (*cv_lfree)(CVodeBMem cvB_mem);
+
+ /* Memory block for a preconditioner's module interface to CVODEA */
+ void *cv_pmem;
+
+ /* Function to free any memory allocated by the preconditioner module */
+ void (*cv_pfree)(CVodeBMem cvB_mem);
+
+ /* Time at which to extract solution / quadratures */
+ realtype cv_tout;
+
+ /* Workspace Nvector */
+ N_Vector cv_y;
+
+ /* Pointer to next structure in list */
+ struct CVodeBMemRec *cv_next;
+
+};
+
+/*
+ * -----------------------------------------------------------------
+ * Type : struct CVadjMemRec
+ * -----------------------------------------------------------------
+ * The type CVadjMem is type pointer to struct CVadjMemRec.
+ * This structure contins fields to store all information
+ * necessary for adjoint sensitivity analysis.
+ * -----------------------------------------------------------------
+ */
+
+struct CVadjMemRec {
+
+ /* --------------------
+ * Forward problem data
+ * -------------------- */
+
+ /* Integration interval */
+ realtype ca_tinitial, ca_tfinal;
+
+ /* Flag for first call to CVodeF */
+ booleantype ca_firstCVodeFcall;
+
+ /* Flag if CVodeF was called with TSTOP */
+ booleantype ca_tstopCVodeFcall;
+ realtype ca_tstopCVodeF;
+
+ /* ----------------------
+ * Backward problems data
+ * ---------------------- */
+
+ /* Storage for backward problems */
+ struct CVodeBMemRec *cvB_mem;
+
+ /* Number of backward problems */
+ int ca_nbckpbs;
+
+ /* Address of current backward problem */
+ struct CVodeBMemRec *ca_bckpbCrt;
+
+ /* Flag for first call to CVodeB */
+ booleantype ca_firstCVodeBcall;
+
+ /* ----------------
+ * Check point data
+ * ---------------- */
+
+ /* Storage for check point information */
+ struct CkpntMemRec *ck_mem;
+
+ /* Number of check points */
+ int ca_nckpnts;
+
+ /* address of the check point structure for which data is available */
+ struct CkpntMemRec *ca_ckpntData;
+
+ /* ------------------
+ * Interpolation data
+ * ------------------ */
+
+ /* Number of steps between 2 check points */
+ long int ca_nsteps;
+
+ /* Storage for data from forward runs */
+ struct DtpntMemRec **dt_mem;
+
+ /* Actual number of data points in dt_mem (typically np=nsteps+1) */
+ long int ca_np;
+
+ /* Interpolation type */
+ int ca_IMtype;
+
+ /* Functions set by the interpolation module */
+ cvaIMMallocFn ca_IMmalloc;
+ cvaIMFreeFn ca_IMfree;
+ cvaIMStorePntFn ca_IMstore; /* store a new interpolation point */
+ cvaIMGetYFn ca_IMget; /* interpolate forward solution */
+
+ /* Flags controlling the interpolation module */
+ booleantype ca_IMmallocDone; /* IM initialized? */
+ booleantype ca_IMnewData; /* new data available in dt_mem?*/
+ booleantype ca_IMstoreSensi; /* store sensitivities? */
+ booleantype ca_IMinterpSensi; /* interpolate sensitivities? */
+
+ /* Workspace for the interpolation module */
+ N_Vector ca_Y[L_MAX]; /* pointers to zn[i] */
+ N_Vector *ca_YS[L_MAX]; /* pointers to znS[i] */
+ realtype ca_T[L_MAX];
+
+ /* -------------------------------
+ * Workspace for wrapper functions
+ * ------------------------------- */
+
+ N_Vector ca_ytmp;
+
+ N_Vector *ca_yStmp;
+
+};
+
+
+/*
+ * =================================================================
+ * I N T E R F A C E T O L I N E A R S O L V E R S
+ * =================================================================
+ */
+
+/*
+ * -----------------------------------------------------------------
+ * Communication between CVODE and a CVODE Linear Solver
+ * -----------------------------------------------------------------
+ * convfail (input to cv_lsetup)
+ *
+ * CV_NO_FAILURES : Either this is the first cv_setup call for this
+ * step, or the local error test failed on the
+ * previous attempt at this step (but the Newton
+ * iteration converged).
+ *
+ * CV_FAIL_BAD_J : This value is passed to cv_lsetup if
+ *
+ * (a) The previous Newton corrector iteration
+ * did not converge and the linear solver's
+ * setup routine indicated that its Jacobian-
+ * related data is not current
+ * or
+ * (b) During the previous Newton corrector
+ * iteration, the linear solver's solve routine
+ * failed in a recoverable manner and the
+ * linear solver's setup routine indicated that
+ * its Jacobian-related data is not current.
+ *
+ * CV_FAIL_OTHER : During the current internal step try, the
+ * previous Newton iteration failed to converge
+ * even though the linear solver was using current
+ * Jacobian-related data.
+ * -----------------------------------------------------------------
+ */
+
+/* Constants for convfail (input to cv_lsetup) */
+
+#define CV_NO_FAILURES 0
+#define CV_FAIL_BAD_J 1
+#define CV_FAIL_OTHER 2
+
+/*
+ * -----------------------------------------------------------------
+ * int (*cv_linit)(CVodeMem cv_mem);
+ * -----------------------------------------------------------------
+ * The purpose of cv_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
+ * CVODE linear solver and a negative value otherwise.
+ * If an error does occur, an appropriate message should be sent to
+ * the error handler function.
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * -----------------------------------------------------------------
+ * int (*cv_lsetup)(CVodeMem cv_mem, int convfail, N_Vector ypred,
+ * N_Vector fpred, booleantype *jcurPtr,
+ * N_Vector vtemp1, N_Vector vtemp2,
+ * N_Vector vtemp3);
+ * -----------------------------------------------------------------
+ * The job of cv_lsetup is to prepare the linear solver for
+ * subsequent calls to cv_lsolve. It may recompute Jacobian-
+ * related data is it deems necessary. Its parameters are as
+ * follows:
+ *
+ * cv_mem - problem memory pointer of type CVodeMem. See the
+ * typedef earlier in this file.
+ *
+ * convfail - a flag to indicate any problem that occurred during
+ * the solution of the nonlinear equation on the
+ * current time step for which the linear solver is
+ * being used. This flag can be used to help decide
+ * whether the Jacobian data kept by a CVODE linear
+ * solver needs to be updated or not.
+ * Its possible values have been documented above.
+ *
+ * ypred - the predicted y vector for the current CVODE internal
+ * step.
+ *
+ * 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
+ * data is current after the call and should set
+ * *jcurPtr=FALSE 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;
+ * otherwise an infinite loop can result.
+ *
+ * vtemp1 - temporary N_Vector provided for use by cv_lsetup.
+ *
+ * vtemp3 - temporary N_Vector provided for use by cv_lsetup.
+ *
+ * vtemp3 - temporary N_Vector provided for use by cv_lsetup.
+ *
+ * The cv_lsetup routine should return 0 if successful, a positive
+ * value for a recoverable error, and a negative value for an
+ * unrecoverable error.
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * -----------------------------------------------------------------
+ * int (*cv_lsolve)(CVodeMem cv_mem, N_Vector b, N_Vector weight,
+ * N_Vector ycur, N_Vector fcur);
+ * -----------------------------------------------------------------
+ * cv_lsolve must solve the linear equation P x = b, where
+ * P is some approximation to (I - gamma J), 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. cv_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.
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * -----------------------------------------------------------------
+ * void (*cv_lfree)(CVodeMem cv_mem);
+ * -----------------------------------------------------------------
+ * cv_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.
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * =================================================================
+ * C V O D E S I N T E R N A L F U N C T I O N S
+ * =================================================================
+ */
+
+/* Prototype of internal ewtSet function */
+
+int cvEwtSet(N_Vector ycur, N_Vector weight, void *data);
+
+/* High level error handler */
+
+void cvProcessError(CVodeMem cv_mem,
+ int error_code, const char *module, const char *fname,
+ const char *msgfmt, ...);
+
+/* Prototype of internal errHandler function */
+
+void cvErrHandler(int error_code, const char *module, const char *function,
+ char *msg, void *data);
+
+/* Prototypes for internal sensitivity rhs wrappers */
+
+int cvSensRhsWrapper(CVodeMem cv_mem, realtype time,
+ N_Vector ycur, N_Vector fcur,
+ N_Vector *yScur, N_Vector *fScur,
+ N_Vector temp1, N_Vector temp2);
+
+int cvSensRhs1Wrapper(CVodeMem cv_mem, realtype time,
+ N_Vector ycur, N_Vector fcur,
+ int is, N_Vector yScur, N_Vector fScur,
+ N_Vector temp1, N_Vector temp2);
+
+/* Prototypes for internal sensitivity rhs DQ functions */
+
+int cvSensRhsInternalDQ(int Ns, realtype t,
+ N_Vector y, N_Vector ydot,
+ N_Vector *yS, N_Vector *ySdot,
+ void *fS_data,
+ N_Vector tempv, N_Vector ftemp);
+
+int cvSensRhs1InternalDQ(int Ns, realtype t,
+ N_Vector y, N_Vector ydot,
+ int is, N_Vector yS, N_Vector ySdot,
+ void *fS_data,
+ N_Vector tempv, N_Vector ftemp);
+
+/*
+ * =================================================================
+ * C V O D E S E R R O R M E S S A G E S
+ * =================================================================
+ */
+
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+
+#define MSG_TIME "t = %Lg"
+#define MSG_TIME_H "t = %Lg and h = %Lg"
+#define MSG_TIME_INT "t = %Lg is not between tcur - hu = %Lg and tcur = %Lg."
+#define MSG_TIME_TOUT "tout = %Lg"
+#define MSG_TIME_TSTOP "tstop = %Lg"
+
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+
+#define MSG_TIME "t = %lg"
+#define MSG_TIME_H "t = %lg and h = %lg"
+#define MSG_TIME_INT "t = %lg is not between tcur - hu = %lg and tcur = %lg."
+#define MSG_TIME_TOUT "tout = %lg"
+#define MSG_TIME_TSTOP "tstop = %lg"
+
+#else
+
+#define MSG_TIME "t = %g"
+#define MSG_TIME_H "t = %g and h = %g"
+#define MSG_TIME_INT "t = %g is not between tcur - hu = %g and tcur = %g."
+#define MSG_TIME_TOUT "tout = %g"
+#define MSG_TIME_TSTOP "tstop = %g"
+
+#endif
+
+
+/* Initialization and I/O error messages */
+
+#define MSGCV_NO_MEM "cvode_mem = NULL illegal."
+#define MSGCV_CVMEM_FAIL "Allocation of cvode_mem failed."
+#define MSGCV_MEM_FAIL "A memory request failed."
+#define MSGCV_BAD_LMM "Illegal value for lmm. The legal values are CV_ADAMS and CV_BDF."
+#define MSGCV_BAD_ITER "Illegal value for iter. The legal values are CV_FUNCTIONAL and CV_NEWTON."
+#define MSGCV_NO_MALLOC "Attempt to call before CVodeInit."
+#define MSGCV_NEG_MAXORD "maxord <= 0 illegal."
+#define MSGCV_BAD_MAXORD "Illegal attempt to increase maximum method order."
+#define MSGCV_SET_SLDET "Attempt to use stability limit detection with the CV_ADAMS method illegal."
+#define MSGCV_NEG_HMIN "hmin < 0 illegal."
+#define MSGCV_NEG_HMAX "hmax < 0 illegal."
+#define MSGCV_BAD_HMIN_HMAX "Inconsistent step size limits: hmin > hmax."
+#define MSGCV_BAD_RELTOL "reltol < 0 illegal."
+#define MSGCV_BAD_ABSTOL "abstol has negative component(s) (illegal)."
+#define MSGCV_NULL_ABSTOL "abstol = NULL illegal."
+#define MSGCV_NULL_Y0 "y0 = NULL illegal."
+#define MSGCV_NULL_F "f = NULL illegal."
+#define MSGCV_NULL_G "g = NULL illegal."
+#define MSGCV_BAD_NVECTOR "A required vector operation is not implemented."
+#define MSGCV_BAD_K "Illegal value for k."
+#define MSGCV_NULL_DKY "dky = NULL illegal."
+#define MSGCV_BAD_T "Illegal value for t." MSG_TIME_INT
+#define MSGCV_NO_ROOT "Rootfinding was not initialized."
+
+#define MSGCV_NO_QUAD "Quadrature integration not activated."
+#define MSGCV_BAD_ITOLQ "Illegal value for itolQ. The legal values are CV_SS and CV_SV."
+#define MSGCV_NULL_ABSTOLQ "abstolQ = NULL illegal."
+#define MSGCV_BAD_RELTOLQ "reltolQ < 0 illegal."
+#define MSGCV_BAD_ABSTOLQ "abstolQ has negative component(s) (illegal)."
+
+#define MSGCV_SENSINIT_2 "Sensitivity analysis already initialized."
+#define MSGCV_NO_SENSI "Forward sensitivity analysis not activated."
+#define MSGCV_BAD_ITOLS "Illegal value for itolS. The legal values are CV_SS, CV_SV, and CV_EE."
+#define MSGCV_NULL_ABSTOLS "abstolS = NULL illegal."
+#define MSGCV_BAD_RELTOLS "reltolS < 0 illegal."
+#define MSGCV_BAD_ABSTOLS "abstolS has negative component(s) (illegal)."
+#define MSGCV_BAD_PBAR "pbar has zero component(s) (illegal)."
+#define MSGCV_BAD_PLIST "plist has negative component(s) (illegal)."
+#define MSGCV_BAD_NS "NS <= 0 illegal."
+#define MSGCV_NULL_YS0 "yS0 = NULL illegal."
+#define MSGCV_BAD_ISM "Illegal value for ism. Legal values are: CV_SIMULTANEOUS, CV_STAGGERED and CV_STAGGERED1."
+#define MSGCV_BAD_IFS "Illegal value for ifS. Legal values are: CV_ALLSENS and CV_ONESENS."
+#define MSGCV_BAD_ISM_IFS "Illegal ism = CV_STAGGERED1 for CVodeSensInit."
+#define MSGCV_BAD_IS "Illegal value for is."
+#define MSGCV_NULL_DKYA "dkyA = NULL illegal."
+#define MSGCV_BAD_DQTYPE "Illegal value for DQtype. Legal values are: CV_CENTERED and CV_FORWARD."
+#define MSGCV_BAD_DQRHO "DQrhomax < 0 illegal."
+
+#define MSGCV_BAD_ITOLQS "Illegal value for itolQS. The legal values are CV_SS, CV_SV, and CV_EE."
+#define MSGCV_NULL_ABSTOLQS "abstolQS = NULL illegal."
+#define MSGCV_BAD_RELTOLQS "reltolQS < 0 illegal."
+#define MSGCV_BAD_ABSTOLQS "abstolQS has negative component(s) (illegal)."
+#define MSGCV_NO_QUADSENSI "Forward sensitivity analysis for quadrature variables not activated."
+#define MSGCV_NULL_YQS0 "yQS0 = NULL illegal."
+
+/* CVode Error Messages */
+
+#define MSGCV_NO_TOL "No integration tolerances have been specified."
+#define MSGCV_LSOLVE_NULL "The linear solver's solve routine is NULL."
+#define MSGCV_YOUT_NULL "yout = NULL illegal."
+#define MSGCV_TRET_NULL "tret = NULL illegal."
+#define MSGCV_BAD_EWT "Initial ewt has component(s) equal to zero (illegal)."
+#define MSGCV_EWT_NOW_BAD "At " MSG_TIME ", a component of ewt has become <= 0."
+#define MSGCV_BAD_ITASK "Illegal value for itask."
+#define MSGCV_BAD_H0 "h0 and tout - t0 inconsistent."
+#define MSGCV_BAD_TOUT "Trouble interpolating at " MSG_TIME_TOUT ". tout too far back in direction of integration"
+#define MSGCV_EWT_FAIL "The user-provide EwtSet function failed."
+#define MSGCV_EWT_NOW_FAIL "At " MSG_TIME ", the user-provide EwtSet function failed."
+#define MSGCV_LINIT_FAIL "The linear solver's init routine failed."
+#define MSGCV_HNIL_DONE "The above warning has been issued mxhnil times and will not be issued again for this problem."
+#define MSGCV_TOO_CLOSE "tout too close to t0 to start integration."
+#define MSGCV_MAX_STEPS "At " MSG_TIME ", mxstep steps taken before reaching tout."
+#define MSGCV_TOO_MUCH_ACC "At " MSG_TIME ", too much accuracy requested."
+#define MSGCV_HNIL "Internal " MSG_TIME_H " are such that t + h = t on the next step. The solver will continue anyway."
+#define MSGCV_ERR_FAILS "At " MSG_TIME_H ", the error test failed repeatedly or with |h| = hmin."
+#define MSGCV_CONV_FAILS "At " MSG_TIME_H ", the corrector convergence test failed repeatedly or with |h| = hmin."
+#define MSGCV_SETUP_FAILED "At " MSG_TIME ", the setup routine failed in an unrecoverable manner."
+#define MSGCV_SOLVE_FAILED "At " MSG_TIME ", the solve routine failed in an unrecoverable manner."
+#define MSGCV_RHSFUNC_FAILED "At " MSG_TIME ", the right-hand side routine failed in an unrecoverable manner."
+#define MSGCV_RHSFUNC_UNREC "At " MSG_TIME ", the right-hand side failed in a recoverable manner, but no recovery is possible."
+#define MSGCV_RHSFUNC_REPTD "At " MSG_TIME " repeated recoverable right-hand side function errors."
+#define MSGCV_RHSFUNC_FIRST "The right-hand side routine failed at the first call."
+#define MSGCV_RTFUNC_FAILED "At " MSG_TIME ", the rootfinding routine failed in an unrecoverable manner."
+#define MSGCV_CLOSE_ROOTS "Root found at and very near " MSG_TIME "."
+#define MSGCV_BAD_TSTOP "The value " MSG_TIME_TSTOP " is behind current " MSG_TIME " in the direction of integration."
+#define MSGCV_INACTIVE_ROOTS "At the end of the first step, there are still some root functions identically 0. This warning will not be issued again."
+
+#define MSGCV_NO_TOLQ "No integration tolerances for quadrature variables have been specified."
+#define MSGCV_BAD_EWTQ "Initial ewtQ has component(s) equal to zero (illegal)."
+#define MSGCV_EWTQ_NOW_BAD "At " MSG_TIME ", a component of ewtQ has become <= 0."
+#define MSGCV_QRHSFUNC_FAILED "At " MSG_TIME ", the quadrature right-hand side routine failed in an unrecoverable manner."
+#define MSGCV_QRHSFUNC_UNREC "At " MSG_TIME ", the quadrature right-hand side failed in a recoverable manner, but no recovery is possible."
+#define MSGCV_QRHSFUNC_REPTD "At " MSG_TIME " repeated recoverable quadrature right-hand side function errors."
+#define MSGCV_QRHSFUNC_FIRST "The quadrature right-hand side routine failed at the first call."
+
+#define MSGCV_NO_TOLS "No integration tolerances for sensitivity variables have been specified."
+#define MSGCV_NULL_P "p = NULL when using internal DQ for sensitivity RHS illegal."
+#define MSGCV_BAD_EWTS "Initial ewtS has component(s) equal to zero (illegal)."
+#define MSGCV_EWTS_NOW_BAD "At " MSG_TIME ", a component of ewtS has become <= 0."
+#define MSGCV_SRHSFUNC_FAILED "At " MSG_TIME ", the sensitivity right-hand side routine failed in an unrecoverable manner."
+#define MSGCV_SRHSFUNC_UNREC "At " MSG_TIME ", the sensitivity right-hand side failed in a recoverable manner, but no recovery is possible."
+#define MSGCV_SRHSFUNC_REPTD "At " MSG_TIME " repeated recoverable sensitivity right-hand side function errors."
+#define MSGCV_SRHSFUNC_FIRST "The sensitivity right-hand side routine failed at the first call."
+
+#define MSGCV_NULL_FQ "CVODES is expected to use DQ to evaluate the RHS of quad. sensi., but quadratures were not initialized."
+#define MSGCV_NO_TOLQS "No integration tolerances for quadrature sensitivity variables have been specified."
+#define MSGCV_BAD_EWTQS "Initial ewtQS has component(s) equal to zero (illegal)."
+#define MSGCV_EWTQS_NOW_BAD "At " MSG_TIME ", a component of ewtQS has become <= 0."
+#define MSGCV_QSRHSFUNC_FAILED "At " MSG_TIME ", the quadrature sensitivity right-hand side routine failed in an unrecoverable manner."
+#define MSGCV_QSRHSFUNC_UNREC "At " MSG_TIME ", the quadrature sensitivity right-hand side failed in a recoverable manner, but no recovery is possible."
+#define MSGCV_QSRHSFUNC_REPTD "At " MSG_TIME " repeated recoverable quadrature sensitivity right-hand side function errors."
+#define MSGCV_QSRHSFUNC_FIRST "The quadrature sensitivity right-hand side routine failed at the first call."
+
+/*
+ * =================================================================
+ * C V O D E A E R R O R M E S S A G E S
+ * =================================================================
+ */
+
+#define MSGCV_NO_ADJ "Illegal attempt to call before calling CVodeAdjMalloc."
+#define MSGCV_BAD_STEPS "Steps nonpositive illegal."
+#define MSGCV_BAD_INTERP "Illegal value for interp."
+#define MSGCV_BAD_WHICH "Illegal value for which."
+#define MSGCV_NO_BCK "No backward problems have been defined yet."
+#define MSGCV_NO_FWD "Illegal attempt to call before calling CVodeF."
+#define MSGCV_BAD_TB0 "The initial time tB0 for problem %d is outside the interval over which the forward problem was solved."
+#define MSGCV_BAD_SENSI "At least one backward problem requires sensitivities, but they were not stored for interpolation."
+#define MSGCV_BAD_ITASKB "Illegal value for itaskB. Legal values are CV_NORMAL and CV_ONE_STEP."
+#define MSGCV_BAD_TBOUT "The final time tBout is outside the interval over which the forward problem was solved."
+#define MSGCV_BACK_ERROR "Error occured while integrating backward problem # %d"
+#define MSGCV_BAD_TINTERP "Bad t = %g for interpolation."
+#define MSGCV_WRONG_INTERP "This function cannot be called for the specified interp type."
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/cvodes/cvodes_io.c b/src/cvodes/cvodes_io.c
new file mode 100644
index 0000000..0ebd0e7
--- /dev/null
+++ b/src/cvodes/cvodes_io.c
@@ -0,0 +1,1877 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.19 $
+ * $Date: 2010/12/01 22:30:43 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Alan C. Hindmarsh 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.
+ * -----------------------------------------------------------------
+ * This is the implementation file for the optional input and output
+ * functions for the CVODES solver.
+ * -----------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "cvodes_impl.h"
+
+#include <sundials/sundials_math.h>
+#include <sundials/sundials_types.h>
+
+#define ZERO RCONST(0.0)
+#define ONE RCONST(1.0)
+
+/*
+ * =================================================================
+ * CVODES optional input functions
+ * =================================================================
+ */
+
+/*
+ * CVodeSetErrHandlerFn
+ *
+ * Specifies the error handler function
+ */
+
+int CVodeSetErrHandlerFn(void *cvode_mem, CVErrHandlerFn ehfun, void *eh_data)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeSetErrHandlerFn", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ cv_mem->cv_ehfun = ehfun;
+ cv_mem->cv_eh_data = eh_data;
+
+ return(CV_SUCCESS);
+}
+
+/*
+ * CVodeSetErrFile
+ *
+ * Specifies the FILE pointer for output (NULL means no messages)
+ */
+
+int CVodeSetErrFile(void *cvode_mem, FILE *errfp)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeSetErrFile", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ cv_mem->cv_errfp = errfp;
+
+ return(CV_SUCCESS);
+}
+
+/*
+ * CVodeSetIterType
+ *
+ * Specifies the iteration type (CV_FUNCTIONAL or CV_NEWTON)
+ */
+
+int CVodeSetIterType(void *cvode_mem, int iter)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeSetIterType", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ if ((iter != CV_FUNCTIONAL) && (iter != CV_NEWTON)) {
+ cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeSetIterType", MSGCV_BAD_ITER);
+ return (CV_ILL_INPUT);
+ }
+
+ cv_mem->cv_iter = iter;
+
+ return(CV_SUCCESS);
+}
+
+/*
+ * CVodeSetUserData
+ *
+ * Specifies the user data pointer for f
+ */
+
+int CVodeSetUserData(void *cvode_mem, void *user_data)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeSetUserData", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ cv_mem->cv_user_data = user_data;
+
+ return(CV_SUCCESS);
+}
+
+/*
+ * CVodeSetMaxOrd
+ *
+ * Specifies the maximum method order
+ */
+
+int CVodeSetMaxOrd(void *cvode_mem, int maxord)
+{
+ CVodeMem cv_mem;
+ int qmax_alloc;
+
+ if (cvode_mem==NULL) {
+ cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeSetMaxOrd", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ if (maxord <= 0) {
+ cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeSetMaxOrd", MSGCV_NEG_MAXORD);
+ return(CV_ILL_INPUT);
+ }
+
+ /* Cannot increase maximum order beyond the value that
+ was used when allocating memory */
+ qmax_alloc = cv_mem->cv_qmax_alloc;
+ qmax_alloc = MIN(qmax_alloc, cv_mem->cv_qmax_allocQ);
+ qmax_alloc = MIN(qmax_alloc, cv_mem->cv_qmax_allocS);
+
+ if (maxord > qmax_alloc) {
+ cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeSetMaxOrd", MSGCV_BAD_MAXORD);
+ return(CV_ILL_INPUT);
+ }
+
+ cv_mem->cv_qmax = maxord;
+
+ return(CV_SUCCESS);
+}
+
+/*
+ * CVodeSetMaxNumSteps
+ *
+ * Specifies the maximum number of integration steps
+ */
+
+int CVodeSetMaxNumSteps(void *cvode_mem, long int mxsteps)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeSetMaxNumSteps", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ /* Passing mxsteps=0 sets the default. Passing mxsteps<0 disables the test. */
+ if (mxsteps == 0)
+ cv_mem->cv_mxstep = MXSTEP_DEFAULT;
+ else
+ cv_mem->cv_mxstep = mxsteps;
+
+ return(CV_SUCCESS);
+}
+
+/*
+ * CVodeSetMaxHnilWarns
+ *
+ * Specifies the maximum number of warnings for small h
+ */
+
+int CVodeSetMaxHnilWarns(void *cvode_mem, int mxhnil)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeSetMaxHnilWarns", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ cv_mem->cv_mxhnil = mxhnil;
+
+ return(CV_SUCCESS);
+}
+
+/*
+ *CVodeSetStabLimDet
+ *
+ * Turns on/off the stability limit detection algorithm
+ */
+
+int CVodeSetStabLimDet(void *cvode_mem, booleantype sldet)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeSetStabLimDet", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ if( sldet && (cv_mem->cv_lmm != CV_BDF) ) {
+ cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeSetStabLimDet", MSGCV_SET_SLDET);
+ return(CV_ILL_INPUT);
+ }
+
+ cv_mem->cv_sldeton = sldet;
+
+ return(CV_SUCCESS);
+}
+
+/*
+ * CVodeSetInitStep
+ *
+ * Specifies the initial step size
+ */
+
+int CVodeSetInitStep(void *cvode_mem, realtype hin)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeSetInitStep", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ cv_mem->cv_hin = hin;
+
+ return(CV_SUCCESS);
+}
+
+/*
+ * CVodeSetMinStep
+ *
+ * Specifies the minimum step size
+ */
+
+int CVodeSetMinStep(void *cvode_mem, realtype hmin)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeSetMinStep", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ if (hmin<0) {
+ cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeSetMinStep", MSGCV_NEG_HMIN);
+ return(CV_ILL_INPUT);
+ }
+
+ /* Passing 0 sets hmin = zero */
+ if (hmin == ZERO) {
+ cv_mem->cv_hmin = HMIN_DEFAULT;
+ return(CV_SUCCESS);
+ }
+
+ if (hmin * cv_mem->cv_hmax_inv > ONE) {
+ cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeSetMinStep", MSGCV_BAD_HMIN_HMAX);
+ return(CV_ILL_INPUT);
+ }
+
+ cv_mem->cv_hmin = hmin;
+
+ return(CV_SUCCESS);
+}
+
+/*
+ * CVodeSetMaxStep
+ *
+ * Specifies the maximum step size
+ */
+
+int CVodeSetMaxStep(void *cvode_mem, realtype hmax)
+{
+ realtype hmax_inv;
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeSetMaxStep", MSGCV_NO_MEM);
+ return (CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ if (hmax < 0) {
+ cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeSetMaxStep", MSGCV_NEG_HMAX);
+ return(CV_ILL_INPUT);
+ }
+
+ /* Passing 0 sets hmax = infinity */
+ if (hmax == ZERO) {
+ cv_mem->cv_hmax_inv = HMAX_INV_DEFAULT;
+ return(CV_SUCCESS);
+ }
+
+ hmax_inv = ONE/hmax;
+ if (hmax_inv * cv_mem->cv_hmin > ONE) {
+ cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeSetMaxStep", MSGCV_BAD_HMIN_HMAX);
+ return(CV_ILL_INPUT);
+ }
+
+ cv_mem->cv_hmax_inv = hmax_inv;
+
+ return(CV_SUCCESS);
+}
+
+/*
+ * CVodeSetStopTime
+ *
+ * Specifies the time beyond which the integration is not to proceed.
+ */
+
+int CVodeSetStopTime(void *cvode_mem, realtype tstop)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeSetStopTime", MSGCV_NO_MEM);
+ return (CV_MEM_NULL);
+ }
+ cv_mem = (CVodeMem) cvode_mem;
+
+ /* If CVode was called at least once, test if tstop is legal
+ * (i.e. if it was not already passed).
+ * If CVodeSetStopTime is called before the first call to CVode,
+ * tstop will be checked in CVode. */
+ if (cv_mem->cv_nst > 0) {
+
+ if ( (tstop - cv_mem->cv_tn) * cv_mem->cv_h < ZERO ) {
+ cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeSetStopTime", MSGCV_BAD_TSTOP, cv_mem->cv_tn);
+ return(CV_ILL_INPUT);
+ }
+
+ }
+
+ cv_mem->cv_tstop = tstop;
+ cv_mem->cv_tstopset = TRUE;
+
+ return(CV_SUCCESS);
+}
+
+/*
+ * CVodeSetMaxErrTestFails
+ *
+ * Specifies the maximum number of error test failures during one
+ * step try.
+ */
+
+int CVodeSetMaxErrTestFails(void *cvode_mem, int maxnef)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeSetMaxErrTestFails", MSGCV_NO_MEM);
+ return (CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ cv_mem->cv_maxnef = maxnef;
+
+ return(CV_SUCCESS);
+}
+
+/*
+ * CVodeSetMaxConvFails
+ *
+ * Specifies the maximum number of nonlinear convergence failures
+ * during one step try.
+ */
+
+int CVodeSetMaxConvFails(void *cvode_mem, int maxncf)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeSetMaxConvFails", MSGCV_NO_MEM);
+ return (CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ cv_mem->cv_maxncf = maxncf;
+
+ return(CV_SUCCESS);
+}
+
+/*
+ * CVodeSetMaxNonlinIters
+ *
+ * Specifies the maximum number of nonlinear iterations during
+ * one solve.
+ */
+
+int CVodeSetMaxNonlinIters(void *cvode_mem, int maxcor)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeSetMaxNonlinIters", MSGCV_NO_MEM);
+ return (CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ cv_mem->cv_maxcor = maxcor;
+
+ return(CV_SUCCESS);
+}
+
+/*
+ * CVodeSetNonlinConvCoef
+ *
+ * Specifies the coeficient in the nonlinear solver convergence
+ * test
+ */
+
+int CVodeSetNonlinConvCoef(void *cvode_mem, realtype nlscoef)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeSetNonlinConvCoef", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ cv_mem->cv_nlscoef = nlscoef;
+
+ return(CV_SUCCESS);
+}
+
+/*
+ * CVodeSetRootDirection
+ *
+ * Specifies the direction of zero-crossings to be monitored.
+ * The default is to monitor both crossings.
+ */
+
+int CVodeSetRootDirection(void *cvode_mem, int *rootdir)
+{
+ CVodeMem cv_mem;
+ int i, nrt;
+
+ if (cvode_mem==NULL) {
+ cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeSetRootDirection", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ nrt = cv_mem->cv_nrtfn;
+ if (nrt==0) {
+ cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeSetRootDirection", MSGCV_NO_ROOT);
+ return(CV_ILL_INPUT);
+ }
+
+ for(i=0; i<nrt; i++) cv_mem->cv_rootdir[i] = rootdir[i];
+
+ return(CV_SUCCESS);
+}
+
+
+/*
+ * CVodeSetNoInactiveRootWarn
+ *
+ * Disables issuing a warning if some root function appears
+ * to be identically zero at the beginning of the integration
+ */
+
+int CVodeSetNoInactiveRootWarn(void *cvode_mem)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeSetNoInactiveRootWarn", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ cv_mem->cv_mxgnull = 0;
+
+ return(CV_SUCCESS);
+}
+
+/*
+ * =================================================================
+ * Quadrature optional input functions
+ * =================================================================
+ */
+
+int CVodeSetQuadErrCon(void *cvode_mem, booleantype errconQ)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeSetQuadErrCon", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+ cv_mem = (CVodeMem) cvode_mem;
+
+ cv_mem->cv_errconQ = errconQ;
+
+ return(CV_SUCCESS);
+}
+
+/*
+ * =================================================================
+ * FSA optional input functions
+ * =================================================================
+ */
+
+int CVodeSetSensDQMethod(void *cvode_mem, int DQtype, realtype DQrhomax)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeSetSensDQMethod", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ if ( (DQtype != CV_CENTERED) && (DQtype != CV_FORWARD) ) {
+ cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeSetSensDQMethod", MSGCV_BAD_DQTYPE);
+ return(CV_ILL_INPUT);
+ }
+
+ if (DQrhomax < ZERO ) {
+ cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeSetSensDQMethod", MSGCV_BAD_DQRHO);
+ return(CV_ILL_INPUT);
+ }
+
+ cv_mem->cv_DQtype = DQtype;
+ cv_mem->cv_DQrhomax = DQrhomax;
+
+ return(CV_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int CVodeSetSensErrCon(void *cvode_mem, booleantype errconS)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeSetSensErrCon", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+ cv_mem = (CVodeMem) cvode_mem;
+
+ cv_mem->cv_errconS = errconS;
+
+ return(CV_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int CVodeSetSensMaxNonlinIters(void *cvode_mem, int maxcorS)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeSetSensMaxNonlinIters", MSGCV_NO_MEM);
+ return (CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ cv_mem->cv_maxcorS = maxcorS;
+
+ return(CV_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int CVodeSetSensParams(void *cvode_mem, realtype *p, realtype *pbar, int *plist)
+{
+ CVodeMem cv_mem;
+ int is, Ns;
+
+ if (cvode_mem==NULL) {
+ cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeSetSensParams", 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", "CVodeSetSensParams", MSGCV_NO_SENSI);
+ return(CV_NO_SENS);
+ }
+
+ Ns = cv_mem->cv_Ns;
+
+ /* Parameters */
+
+ cv_mem->cv_p = p;
+
+ /* pbar */
+
+ if (pbar != NULL)
+ for (is=0; is<Ns; is++) {
+ if (pbar[is] == ZERO) {
+ cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeSetSensParams", MSGCV_BAD_PBAR);
+ return(CV_ILL_INPUT);
+ }
+ cv_mem->cv_pbar[is] = ABS(pbar[is]);
+ }
+ else
+ for (is=0; is<Ns; is++)
+ cv_mem->cv_pbar[is] = ONE;
+
+ /* plist */
+
+ if (plist != NULL)
+ for (is=0; is<Ns; is++) {
+ if ( plist[is] < 0 ) {
+ cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeSetSensParams", MSGCV_BAD_PLIST);
+ return(CV_ILL_INPUT);
+ }
+ cv_mem->cv_plist[is] = plist[is];
+ }
+ else
+ for (is=0; is<Ns; is++)
+ cv_mem->cv_plist[is] = is;
+
+ return(CV_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int CVodeSetQuadSensErrCon(void *cvode_mem, booleantype errconQS)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeSetQuadSensErrCon", 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", "CVodeSetQuadSensTolerances", 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", "CVodeSetQuadSensErrCon", MSGCV_NO_QUADSENSI);
+ return(CV_NO_QUAD);
+ }
+
+ cv_mem->cv_errconQS = errconQS;
+
+ return(CV_SUCCESS);
+}
+
+/*
+ * =================================================================
+ * CVODES optional output functions
+ * =================================================================
+ */
+
+/*
+ * 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
+ *
+ * Returns the current number of integration steps
+ */
+
+int CVodeGetNumSteps(void *cvode_mem, long int *nsteps)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetNumSteps", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ *nsteps = nst;
+
+ return(CV_SUCCESS);
+}
+
+/*
+ * CVodeGetNumRhsEvals
+ *
+ * Returns the current number of calls to f
+ */
+
+int CVodeGetNumRhsEvals(void *cvode_mem, long int *nfevals)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetNumRhsEvals", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ *nfevals = nfe;
+
+ return(CV_SUCCESS);
+}
+
+/*
+ * CVodeGetNumLinSolvSetups
+ *
+ * Returns the current number of calls to the linear solver setup routine
+ */
+
+int CVodeGetNumLinSolvSetups(void *cvode_mem, long int *nlinsetups)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetNumLinSolvSetups", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ *nlinsetups = nsetups;
+
+ return(CV_SUCCESS);
+}
+
+/*
+ * CVodeGetNumErrTestFails
+ *
+ * Returns the current number of error test failures
+ */
+
+int CVodeGetNumErrTestFails(void *cvode_mem, long int *netfails)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetNumErrTestFails", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ *netfails = netf;
+
+ return(CV_SUCCESS);
+}
+
+/*
+ * CVodeGetLastOrder
+ *
+ * Returns the order on the last succesful step
+ */
+
+int CVodeGetLastOrder(void *cvode_mem, int *qlast)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetLastOrder", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ *qlast = qu;
+
+ return(CV_SUCCESS);
+}
+
+/*
+ * CVodeGetCurrentOrder
+ *
+ * Returns the order to be attempted on the next step
+ */
+
+int CVodeGetCurrentOrder(void *cvode_mem, int *qcur)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetCurrentOrder", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ *qcur = next_q;
+
+ return(CV_SUCCESS);
+}
+
+/*
+ * CVodeGetNumStabLimOrderReds
+ *
+ * Returns the number of order reductions triggered by the stability
+ * limit detection algorithm
+ */
+
+int CVodeGetNumStabLimOrderReds(void *cvode_mem, long int *nslred)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetNumStabLimOrderReds", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ if (sldeton==FALSE)
+ *nslred = 0;
+ else
+ *nslred = nor;
+
+ return(CV_SUCCESS);
+}
+
+/*
+ * CVodeGetActualInitStep
+ *
+ * Returns the step size used on the first step
+ */
+
+int CVodeGetActualInitStep(void *cvode_mem, realtype *hinused)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetActualInitStep", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ *hinused = h0u;
+
+ return(CV_SUCCESS);
+}
+
+/*
+ * CVodeGetLastStep
+ *
+ * Returns the step size used on the last successful step
+ */
+
+int CVodeGetLastStep(void *cvode_mem, realtype *hlast)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetLastStep", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ *hlast = hu;
+
+ return(CV_SUCCESS);
+}
+
+/*
+ * CVodeGetCurrentStep
+ *
+ * Returns the step size to be attempted on the next step
+ */
+
+int CVodeGetCurrentStep(void *cvode_mem, realtype *hcur)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetCurrentStep", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ *hcur = next_h;
+
+ return(CV_SUCCESS);
+}
+
+/*
+ * CVodeGetCurrentTime
+ *
+ * Returns the current value of the independent variable
+ */
+
+int CVodeGetCurrentTime(void *cvode_mem, realtype *tcur)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetCurrentTime", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ *tcur = tn;
+
+ return(CV_SUCCESS);
+}
+
+/*
+ * CVodeGetTolScaleFactor
+ *
+ * Returns a suggested factor for scaling tolerances
+ */
+
+int CVodeGetTolScaleFactor(void *cvode_mem, realtype *tolsfact)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetTolScaleFactor", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ *tolsfact = tolsf;
+
+ return(CV_SUCCESS);
+}
+
+/*
+ * CVodeGetErrWeights
+ *
+ * This routine returns the current weight vector.
+ */
+
+int CVodeGetErrWeights(void *cvode_mem, N_Vector eweight)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetErrWeights", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ N_VScale(ONE, ewt, eweight);
+
+ return(CV_SUCCESS);
+}
+
+/*
+ * CVodeGetEstLocalErrors
+ *
+ * Returns an estimate of the local error
+ */
+
+int CVodeGetEstLocalErrors(void *cvode_mem, N_Vector ele)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetEstLocalErrors", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ N_VScale(ONE, acor, ele);
+
+ return(CV_SUCCESS);
+}
+
+/*
+ * CVodeGetWorkSpace
+ *
+ * Returns integrator work space requirements
+ */
+
+int CVodeGetWorkSpace(void *cvode_mem, long int *lenrw, long int *leniw)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetWorkSpace", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ *leniw = liw;
+ *lenrw = lrw;
+
+ return(CV_SUCCESS);
+}
+
+/*
+ * CVodeGetIntegratorStats
+ *
+ * Returns integrator statistics
+ */
+
+int CVodeGetIntegratorStats(void *cvode_mem, long int *nsteps, long int *nfevals,
+ long int *nlinsetups, long int *netfails, int *qlast,
+ int *qcur, realtype *hinused, realtype *hlast,
+ realtype *hcur, realtype *tcur)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetIntegratorStats", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+
+ 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;
+
+ return(CV_SUCCESS);
+}
+
+/*
+ * CVodeGetNumGEvals
+ *
+ * Returns the current number of calls to g (for rootfinding)
+ */
+
+int CVodeGetNumGEvals(void *cvode_mem, long int *ngevals)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetNumGEvals", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ *ngevals = nge;
+
+ return(CV_SUCCESS);
+}
+
+/*
+ * CVodeGetRootInfo
+ *
+ * Returns pointer to array rootsfound showing roots found
+ */
+
+int CVodeGetRootInfo(void *cvode_mem, int *rootsfound)
+{
+ CVodeMem cv_mem;
+ int i, nrt;
+
+ if (cvode_mem==NULL) {
+ cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetRootInfo", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ nrt = cv_mem->cv_nrtfn;
+
+ for (i=0; i<nrt; i++) rootsfound[i] = iroots[i];
+
+ return(CV_SUCCESS);
+}
+
+
+/*
+ * CVodeGetNumNonlinSolvIters
+ *
+ * Returns the current number of iterations in the nonlinear solver
+ */
+
+int CVodeGetNumNonlinSolvIters(void *cvode_mem, long int *nniters)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetNumNonlinSolvIters", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ *nniters = nni;
+
+ return(CV_SUCCESS);
+}
+
+/*
+ * CVodeGetNumNonlinSolvConvFails
+ *
+ * Returns the current number of convergence failures in the
+ * nonlinear solver
+ */
+
+int CVodeGetNumNonlinSolvConvFails(void *cvode_mem, long int *nncfails)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetNumNonlinSolvConvFails", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ *nncfails = ncfn;
+
+ return(CV_SUCCESS);
+}
+
+/*
+ * CVodeGetNonlinSolvStats
+ *
+ * Returns nonlinear solver statistics
+ */
+
+int CVodeGetNonlinSolvStats(void *cvode_mem, long int *nniters,
+ long int *nncfails)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetNonlinSolvStats", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ *nniters = nni;
+ *nncfails = ncfn;
+
+ return(CV_SUCCESS);
+}
+
+
+/*
+ * =================================================================
+ * Quadrature optional output functions
+ * =================================================================
+ */
+
+/*
+ * 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)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetQuadNumRhsEvals", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ if (quadr==FALSE) {
+ cvProcessError(cv_mem, CV_NO_QUAD, "CVODES", "CVodeGetQuadNumRhsEvals", MSGCV_NO_QUAD);
+ return(CV_NO_QUAD);
+ }
+
+ *nfQevals = nfQe;
+
+ return(CV_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int CVodeGetQuadNumErrTestFails(void *cvode_mem, long int *nQetfails)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetQuadNumErrTestFails", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ if (quadr==FALSE) {
+ cvProcessError(cv_mem, CV_NO_QUAD, "CVODES", "CVodeGetQuadNumErrTestFails", MSGCV_NO_QUAD);
+ return(CV_NO_QUAD);
+ }
+
+ *nQetfails = netfQ;
+
+ return(CV_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int CVodeGetQuadErrWeights(void *cvode_mem, N_Vector eQweight)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetQuadErrWeights", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ if (quadr==FALSE) {
+ cvProcessError(cv_mem, CV_NO_QUAD, "CVODES", "CVodeGetQuadErrWeights", MSGCV_NO_QUAD);
+ return(CV_NO_QUAD);
+ }
+
+ if(errconQ) N_VScale(ONE, ewtQ, eQweight);
+
+ return(CV_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int CVodeGetQuadStats(void *cvode_mem, long int *nfQevals, long int *nQetfails)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetQuadStats", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ if (quadr==FALSE) {
+ cvProcessError(cv_mem, CV_NO_QUAD, "CVODES", "CVodeGetQuadStats", MSGCV_NO_QUAD);
+ return(CV_NO_QUAD);
+ }
+
+ *nfQevals = nfQe;
+ *nQetfails = netfQ;
+
+ return(CV_SUCCESS);
+}
+
+/*
+ * =================================================================
+ * Quadrature FSA optional output functions
+ * =================================================================
+ */
+
+/*
+ * 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)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetQuadSensNumRhsEvals", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ if (quadr_sensi == FALSE) {
+ cvProcessError(cv_mem, CV_NO_QUADSENS, "CVODES", "CVodeGetQuadSensNumRhsEvals", MSGCV_NO_QUADSENSI);
+ return(CV_NO_QUADSENS);
+ }
+
+ *nfQSevals = nfQSe;
+
+ return(CV_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int CVodeGetQuadSensNumErrTestFails(void *cvode_mem, long int *nQSetfails)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetQuadSensNumErrTestFails", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ if (quadr_sensi == FALSE) {
+ cvProcessError(cv_mem, CV_NO_QUADSENS, "CVODES", "CVodeGetQuadSensNumErrTestFails", MSGCV_NO_QUADSENSI);
+ return(CV_NO_QUADSENS);
+ }
+
+ *nQSetfails = netfQS;
+
+ return(CV_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int CVodeGetQuadSensErrWeights(void *cvode_mem, N_Vector *eQSweight)
+{
+ CVodeMem cv_mem;
+ int is, Ns;
+
+ if (cvode_mem==NULL) {
+ cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetQuadSensErrWeights", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ if (quadr_sensi == FALSE) {
+ cvProcessError(cv_mem, CV_NO_QUADSENS, "CVODES", "CVodeGetQuadSensErrWeights", MSGCV_NO_QUADSENSI);
+ return(CV_NO_QUADSENS);
+ }
+ Ns = cv_mem->cv_Ns;
+
+ if (errconQS)
+ for (is=0; is<Ns; is++)
+ N_VScale(ONE, ewtQS[is], eQSweight[is]);
+
+ return(CV_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int CVodeGetQuadSensStats(void *cvode_mem, long int *nfQSevals, long int *nQSetfails)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetQuadSensStats", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ if (quadr_sensi == FALSE) {
+ cvProcessError(cv_mem, CV_NO_QUADSENS, "CVODES", "CVodeGetQuadSensStats", MSGCV_NO_QUADSENSI);
+ return(CV_NO_QUADSENS);
+ }
+
+ *nfQSevals = nfQSe;
+ *nQSetfails = netfQS;
+
+ return(CV_SUCCESS);
+}
+
+
+/*
+ * =================================================================
+ * FSA optional output functions
+ * =================================================================
+ */
+
+/*
+ * 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)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetSensNumRhsEvals", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ if (sensi==FALSE) {
+ cvProcessError(cv_mem, CV_NO_SENS, "CVODES", "CVodeGetSensNumRhsEvals", MSGCV_NO_SENSI);
+ return(CV_NO_SENS);
+ }
+
+ *nfSevals = nfSe;
+
+ return(CV_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int CVodeGetNumRhsEvalsSens(void *cvode_mem, long int *nfevalsS)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetNumRhsEvalsSens", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ if (sensi==FALSE) {
+ cvProcessError(cv_mem, CV_NO_SENS, "CVODES", "CVodeGetNumRhsEvalsSens", MSGCV_NO_SENSI);
+ return(CV_NO_SENS);
+ }
+
+ *nfevalsS = nfeS;
+
+ return(CV_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int CVodeGetSensNumErrTestFails(void *cvode_mem, long int *nSetfails)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetSensNumErrTestFails", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ if (sensi==FALSE) {
+ cvProcessError(cv_mem, CV_NO_SENS, "CVODES", "CVodeGetSensNumErrTestFails", MSGCV_NO_SENSI);
+ return(CV_NO_SENS);
+ }
+
+ *nSetfails = netfS;
+
+ return(CV_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int CVodeGetSensNumLinSolvSetups(void *cvode_mem, long int *nlinsetupsS)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetSensNumLinSolvSetups", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ if (sensi==FALSE) {
+ cvProcessError(cv_mem, CV_NO_SENS, "CVODES", "CVodeGetSensNumLinSolvSetups", MSGCV_NO_SENSI);
+ return(CV_NO_SENS);
+ }
+
+ *nlinsetupsS = nsetupsS;
+
+ return(CV_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int CVodeGetSensErrWeights(void *cvode_mem, N_Vector *eSweight)
+{
+ CVodeMem cv_mem;
+ int is, Ns;
+
+ if (cvode_mem==NULL) {
+ cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetSensErrWeights", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ if (sensi==FALSE) {
+ cvProcessError(cv_mem, CV_NO_SENS, "CVODES", "CVodeGetSensErrWeights", MSGCV_NO_SENSI);
+ return(CV_NO_SENS);
+ }
+
+ Ns = cv_mem->cv_Ns;
+
+ for (is=0; is<Ns; is++)
+ N_VScale(ONE, ewtS[is], eSweight[is]);
+
+ return(CV_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int CVodeGetSensStats(void *cvode_mem, long int *nfSevals, long int *nfevalsS,
+ long int *nSetfails, long int *nlinsetupsS)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetSensStats", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ if (sensi==FALSE) {
+ cvProcessError(cv_mem, CV_NO_SENS, "CVODES", "CVodeGetSensStats", MSGCV_NO_SENSI);
+ return(CV_NO_SENS);
+ }
+
+ *nfSevals = nfSe;
+ *nfevalsS = nfeS;
+ *nSetfails = netfS;
+ *nlinsetupsS = nsetupsS;
+
+ return(CV_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int CVodeGetSensNumNonlinSolvIters(void *cvode_mem, long int *nSniters)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetSensNumNonlinSolvIters", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ if (sensi==FALSE) {
+ cvProcessError(cv_mem, CV_NO_SENS, "CVODES", "CVodeGetSensNumNonlinSolvIters", MSGCV_NO_SENSI);
+ return(CV_NO_SENS);
+ }
+
+ *nSniters = nniS;
+
+ return(CV_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int CVodeGetSensNumNonlinSolvConvFails(void *cvode_mem, long int *nSncfails)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetSensNumNonlinSolvConvFails", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ if (sensi==FALSE) {
+ cvProcessError(cv_mem, CV_NO_SENS, "CVODES", "CVodeGetSensNumNonlinSolvConvFails", MSGCV_NO_SENSI);
+ return(CV_NO_SENS);
+ }
+
+ *nSncfails = ncfnS;
+
+ return(CV_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int CVodeGetStgrSensNumNonlinSolvIters(void *cvode_mem, long int *nSTGR1niters)
+{
+ CVodeMem cv_mem;
+ int is, Ns;
+
+ if (cvode_mem==NULL) {
+ cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetStgrSensNumNonlinSolvIters", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ Ns = cv_mem->cv_Ns;
+
+ if (sensi==FALSE) {
+ 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];
+
+ return(CV_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int CVodeGetStgrSensNumNonlinSolvConvFails(void *cvode_mem, long int *nSTGR1ncfails)
+{
+ CVodeMem cv_mem;
+ int is, Ns;
+
+ if (cvode_mem==NULL) {
+ cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetStgrSensNumNonlinSolvConvFails", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ Ns = cv_mem->cv_Ns;
+
+ if (sensi==FALSE) {
+ 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];
+
+ return(CV_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int CVodeGetSensNonlinSolvStats(void *cvode_mem, long int *nSniters,
+ long int *nSncfails)
+{
+ CVodeMem cv_mem;
+
+ if (cvode_mem==NULL) {
+ cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetSensNonlinSolvstats", MSGCV_NO_MEM);
+ return(CV_MEM_NULL);
+ }
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ if (sensi==FALSE) {
+ cvProcessError(cv_mem, CV_NO_SENS, "CVODES", "CVodeGetSensNonlinSolvStats", MSGCV_NO_SENSI);
+ return(CV_NO_SENS);
+ }
+
+ *nSniters = nniS;
+ *nSncfails = ncfnS;
+
+ return(CV_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+char *CVodeGetReturnFlagName(long int flag)
+{
+ char *name;
+
+ name = (char *)malloc(24*sizeof(char));
+
+ switch(flag) {
+ case CV_SUCCESS:
+ sprintf(name,"CV_SUCCESS");
+ break;
+ case CV_TSTOP_RETURN:
+ sprintf(name,"CV_TSTOP_RETURN");
+ break;
+ case CV_ROOT_RETURN:
+ sprintf(name,"CV_ROOT_RETURN");
+ break;
+ case CV_TOO_MUCH_WORK:
+ sprintf(name,"CV_TOO_MUCH_WORK");
+ break;
+ case CV_TOO_MUCH_ACC:
+ sprintf(name,"CV_TOO_MUCH_ACC");
+ break;
+ case CV_ERR_FAILURE:
+ sprintf(name,"CV_ERR_FAILURE");
+ break;
+ case CV_CONV_FAILURE:
+ sprintf(name,"CV_CONV_FAILURE");
+ break;
+ case CV_LINIT_FAIL:
+ sprintf(name,"CV_LINIT_FAIL");
+ break;
+ case CV_LSETUP_FAIL:
+ sprintf(name,"CV_LSETUP_FAIL");
+ break;
+ case CV_LSOLVE_FAIL:
+ sprintf(name,"CV_LSOLVE_FAIL");
+ break;
+ case CV_RHSFUNC_FAIL:
+ sprintf(name,"CV_RHSFUNC_FAIL");
+ break;
+ case CV_FIRST_RHSFUNC_ERR:
+ sprintf(name,"CV_FIRST_RHSFUNC_ERR");
+ break;
+ case CV_REPTD_RHSFUNC_ERR:
+ sprintf(name,"CV_REPTD_RHSFUNC_ERR");
+ break;
+ case CV_UNREC_RHSFUNC_ERR:
+ sprintf(name,"CV_UNREC_RHSFUNC_ERR");
+ break;
+ case CV_RTFUNC_FAIL:
+ sprintf(name,"CV_RTFUNC_FAIL");
+ break;
+ case CV_MEM_FAIL:
+ sprintf(name,"CV_MEM_FAIL");
+ break;
+ case CV_MEM_NULL:
+ sprintf(name,"CV_MEM_NULL");
+ break;
+ case CV_ILL_INPUT:
+ sprintf(name,"CV_ILL_INPUT");
+ break;
+ case CV_NO_MALLOC:
+ sprintf(name,"CV_NO_MALLOC");
+ break;
+ case CV_BAD_K:
+ sprintf(name,"CV_BAD_K");
+ break;
+ case CV_BAD_T:
+ sprintf(name,"CV_BAD_T");
+ break;
+ case CV_BAD_DKY:
+ sprintf(name,"CV_BAD_DKY");
+ break;
+ case CV_NO_QUAD:
+ sprintf(name,"CV_NO_QUAD");
+ break;
+ case CV_QRHSFUNC_FAIL:
+ sprintf(name,"CV_QRHSFUNC_FAIL");
+ break;
+ case CV_FIRST_QRHSFUNC_ERR:
+ sprintf(name,"CV_FIRST_QRHSFUNC_ERR");
+ break;
+ case CV_REPTD_QRHSFUNC_ERR:
+ sprintf(name,"CV_REPTD_QRHSFUNC_ERR");
+ break;
+ case CV_UNREC_QRHSFUNC_ERR:
+ sprintf(name,"CV_UNREC_QRHSFUNC_ERR");
+ break;
+ case CV_BAD_IS:
+ sprintf(name,"CV_BAD_IS");
+ break;
+ case CV_NO_SENS:
+ sprintf(name,"CV_NO_SENS");
+ break;
+ case CV_SRHSFUNC_FAIL:
+ sprintf(name,"CV_SRHSFUNC_FAIL");
+ break;
+ case CV_FIRST_SRHSFUNC_ERR:
+ sprintf(name,"CV_FIRST_SRHSFUNC_ERR");
+ break;
+ case CV_REPTD_SRHSFUNC_ERR:
+ sprintf(name,"CV_REPTD_SRHSFUNC_ERR");
+ break;
+ case CV_UNREC_SRHSFUNC_ERR:
+ sprintf(name,"CV_UNREC_SRHSFUNC_ERR");
+ break;
+ case CV_TOO_CLOSE:
+ sprintf(name,"CV_TOO_CLOSE");
+ break;
+ case CV_NO_ADJ:
+ sprintf(name,"CV_NO_ADJ");
+ break;
+ case CV_NO_FWD:
+ sprintf(name,"CV_NO_FWD");
+ break;
+ case CV_NO_BCK:
+ sprintf(name,"CV_NO_BCK");
+ break;
+ case CV_BAD_TB0:
+ sprintf(name,"CV_BAD_TB0");
+ break;
+ case CV_REIFWD_FAIL:
+ sprintf(name,"CV_REIFWD_FAIL");
+ break;
+ case CV_FWD_FAIL:
+ sprintf(name,"CV_FWD_FAIL");
+ break;
+ case CV_GETY_BADT:
+ sprintf(name,"CV_GETY_BADT");
+ break;
+ default:
+ sprintf(name,"NONE");
+ }
+
+ return(name);
+}
+
diff --git a/src/cvodes/cvodes_lapack.c b/src/cvodes/cvodes_lapack.c
new file mode 100644
index 0000000..931ba86
--- /dev/null
+++ b/src/cvodes/cvodes_lapack.c
@@ -0,0 +1,828 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.15 $
+ * $Date: 2011/03/23 22:58:46 $
+ * -----------------------------------------------------------------
+ * Programmer: Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2006, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * 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 void 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 void cvLapackBandFree(CVodeMem cv_mem);
+
+/* CVSLAPACK lfreeB functions */
+static void cvLapackDenseFreeB(CVodeBMem cvB_mem);
+static void 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;
+ 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;
+ 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 = MIN(n-1, 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;
+
+ nje = 0;
+ nfeDQ = 0;
+ nstlj = 0;
+
+ /* 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 = ABS((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 void cvLapackDenseFree(CVodeMem cv_mem)
+{
+ CVDlsMem cvdls_mem;
+
+ cvdls_mem = (CVDlsMem) lmem;
+
+ DestroyMat(M);
+ DestroyArray(pivots);
+ DestroyMat(savedJ);
+ free(cvdls_mem);
+ cvdls_mem = NULL;
+}
+
+/*
+ * =================================================================
+ * 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;
+
+ nje = 0;
+ nfeDQ = 0;
+ nstlj = 0;
+
+ /* 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 = ABS((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 void cvLapackBandFree(CVodeMem cv_mem)
+{
+ CVDlsMem cvdls_mem;
+
+ cvdls_mem = (CVDlsMem) lmem;
+
+ DestroyMat(M);
+ DestroyArray(pivots);
+ DestroyMat(savedJ);
+ free(cvdls_mem);
+ cvdls_mem = NULL;
+}
+
+/*
+ * ================================================================
+ *
+ * PART II - backward problems
+ *
+ * ================================================================
+ */
+
+/*
+ * CVLapackDenseB is a wraper 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 void cvLapackDenseFreeB(CVodeBMem cvB_mem)
+{
+ CVDlsMemB cvdlsB_mem;
+
+ cvdlsB_mem = (CVDlsMemB) (cvB_mem->cv_lmem);
+
+ free(cvdlsB_mem);
+}
+
+/*
+ * CVLapackBandB is a wraper 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 void cvLapackBandFreeB(CVodeBMem cvB_mem)
+{
+ CVDlsMemB cvdlsB_mem;
+
+ cvdlsB_mem = (CVDlsMemB) (cvB_mem->cv_lmem);
+
+ free(cvdlsB_mem);
+}
diff --git a/src/cvodes/cvodes_spbcgs.c b/src/cvodes/cvodes_spbcgs.c
new file mode 100644
index 0000000..fe2df25
--- /dev/null
+++ b/src/cvodes/cvodes_spbcgs.c
@@ -0,0 +1,573 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.13 $
+ * $Date: 2011/03/23 22:58:46 $
+ * -----------------------------------------------------------------
+ * 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.
+ * -----------------------------------------------------------------
+ * 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 void CVSpbcgFree(CVodeMem cv_mem);
+
+/* CVSPBCG lfreeB function */
+
+static void 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;
+
+ 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 = RSqrt(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 */
+ npe = nli = nps = ncfl = nstlpre = 0;
+ njtimes = nfes = 0;
+
+ /* 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 = ABS((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 void 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;
+}
+
+
+/*
+ * ================================================================
+ *
+ * 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 void CVSpbcgFreeB(CVodeBMem cvB_mem)
+{
+ CVSpilsMemB cvspilsB_mem;
+
+ cvspilsB_mem = (CVSpilsMemB) (cvB_mem->cv_lmem);
+
+ free(cvspilsB_mem);
+}
diff --git a/src/cvodes/cvodes_spgmr.c b/src/cvodes/cvodes_spgmr.c
new file mode 100644
index 0000000..a8a8391
--- /dev/null
+++ b/src/cvodes/cvodes_spgmr.c
@@ -0,0 +1,579 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.13 $
+ * $Date: 2011/03/23 22:58:46 $
+ * -----------------------------------------------------------------
+ * Programmer(s): 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.
+ * -----------------------------------------------------------------
+ * 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 void CVSpgmrFree(CVodeMem cv_mem);
+
+/* CVSPGMR lfreeB function */
+
+static void 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;
+
+ 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 = RSqrt( 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 */
+ npe = nli = nps = ncfl = nstlpre = 0;
+ njtimes = nfes = 0;
+
+ /* 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 = ABS((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 void 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;
+}
+
+
+/*
+ * ================================================================
+ *
+ * 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 void CVSpgmrFreeB(CVodeBMem cvB_mem)
+{
+ CVSpilsMemB cvspilsB_mem;
+
+ cvspilsB_mem = (CVSpilsMemB) (cvB_mem->cv_lmem);
+
+ free(cvspilsB_mem);
+}
diff --git a/src/cvodes/cvodes_spils.c b/src/cvodes/cvodes_spils.c
new file mode 100644
index 0000000..295be45
--- /dev/null
+++ b/src/cvodes/cvodes_spils.c
@@ -0,0 +1,1183 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.12 $
+ * $Date: 2011/06/23 00:31:01 $
+ * -----------------------------------------------------------------
+ * Programmer(s):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.
+ * -----------------------------------------------------------------
+ * This is the implementation file for the CVSPILS linear solvers.
+ *
+ * Part II contains wrappers for using the CVODES iterative linear
+ * solvers on adjoint (backward) problems.
+ * -----------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "cvodes_impl.h"
+#include "cvodes_spils_impl.h"
+
+/* Private constants */
+
+#define ZERO RCONST(0.0)
+#define PT25 RCONST(0.25)
+#define ONE RCONST(1.0)
+
+/* Algorithmic constants */
+
+#define MAX_ITERS 3 /* max. number of attempts to recover in DQ J*v */
+
+/*
+ * =================================================================
+ * PRIVATE FUNCTION PROTOTYPES
+ * =================================================================
+ */
+
+/*
+ * cvSpilsPrecSetupBWrapper has type CVSpilsPrecSetupFn
+ * It wraps around the user-provided function of type CVSpilsPrecSetupFnB
+ */
+
+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);
+
+/*
+ * cvSpilsPrecSolveBWrapper has type CVSpilsPrecSolveFn
+ * It wraps around the user-provided function of type CVSpilsPrecSolveFnB
+ */
+
+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);
+
+/*
+ * cvSpilsJacTimesVecBWrapper has type CVSpilsJacTimesVecFn
+ * It wraps around the user-provided function of type CVSpilsJacTimesVecFnB
+ */
+
+static int cvSpilsJacTimesVecBWrapper(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
+ * -----------------------------------------------------------------
+ */
+
+
+/*
+ * -----------------------------------------------------------------
+ * CVSpilsSetPrecType
+ * -----------------------------------------------------------------
+ */
+
+int CVSpilsSetPrecType(void *cvode_mem, int pretype)
+{
+ CVodeMem cv_mem;
+ CVSpilsMem cvspils_mem;
+
+ /* Return immediately if cvode_mem is NULL */
+ if (cvode_mem == NULL) {
+ cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS", "CVSpilsSetPrecType", MSGS_CVMEM_NULL);
+ return(CVSPILS_MEM_NULL);
+ }
+ cv_mem = (CVodeMem) cvode_mem;
+
+ if (lmem == NULL) {
+ cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSPILS", "CVSpilsSetPrecType", MSGS_LMEM_NULL);
+ return(CVSPILS_LMEM_NULL);
+ }
+ 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);
+ return(CVSPILS_ILL_INPUT);
+ }
+
+ cvspils_mem->s_pretype = pretype;
+
+ 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);
+ }
+ cv_mem = (CVodeMem) cvode_mem;
+
+ if (lmem == NULL) {
+ cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSPILS", "CVSpilsSetGSType", MSGS_LMEM_NULL);
+ return(CVSPILS_LMEM_NULL);
+ }
+ cvspils_mem = (CVSpilsMem) 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);
+ return(CVSPILS_ILL_INPUT);
+ }
+
+ cvspils_mem->s_gstype = gstype;
+
+ return(CVSPILS_SUCCESS);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Function : CVSpilsSetMaxl
+ * -----------------------------------------------------------------
+ */
+
+int CVSpilsSetMaxl(void *cvode_mem, int maxl)
+{
+ CVodeMem cv_mem;
+ CVSpilsMem cvspils_mem;
+ int mxl;
+
+ /* Return immediately if cvode_mem is NULL */
+ if (cvode_mem == NULL) {
+ cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS", "CVSpilsSetMaxl", 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);
+ 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);
+ }
+
+ mxl = (maxl <= 0) ? CVSPILS_MAXL : maxl;
+ cvspils_mem->s_maxl = mxl;
+
+ /* spbcg_mem->l_max = mxl; */
+
+ return(CVSPILS_SUCCESS);
+}
+
+
+/*
+ * -----------------------------------------------------------------
+ * CVSpilsSetEpsLin
+ * -----------------------------------------------------------------
+ */
+
+int CVSpilsSetEpsLin(void *cvode_mem, realtype eplifac)
+{
+ CVodeMem cv_mem;
+ CVSpilsMem cvspils_mem;
+
+ /* Return immediately if cvode_mem is NULL */
+ if (cvode_mem == NULL) {
+ cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS", "CVSpilsSetEpsLin", 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);
+ 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->s_eplifac = (eplifac == ZERO) ? CVSPILS_EPLIN : eplifac;
+
+ return(CVSPILS_SUCCESS);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * CVSpilsSetPrecSetupFn
+ * -----------------------------------------------------------------
+ */
+
+int CVSpilsSetPreconditioner(void *cvode_mem,
+ CVSpilsPrecSetupFn pset, CVSpilsPrecSolveFn psolve)
+{
+ CVodeMem cv_mem;
+ CVSpilsMem cvspils_mem;
+
+ /* Return immediately if cvode_mem is NULL */
+ if (cvode_mem == 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", "CVSpilsSetPreconditioner", MSGS_LMEM_NULL);
+ return(CVSPILS_LMEM_NULL);
+ }
+ cvspils_mem = (CVSpilsMem) lmem;
+
+ cvspils_mem->s_pset = pset;
+ cvspils_mem->s_psolve = psolve;
+
+ 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);
+ }
+ 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;
+ }
+
+ return(CVSPILS_SUCCESS);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * CVSpilsGetWorkSpace
+ * -----------------------------------------------------------------
+ */
+
+int CVSpilsGetWorkSpace(void *cvode_mem, long int *lenrwLS, long int *leniwLS)
+{
+ CVodeMem cv_mem;
+ CVSpilsMem cvspils_mem;
+ int maxl;
+
+ /* Return immediately if cvode_mem is NULL */
+ if (cvode_mem == 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", "CVSpilsGetWorkSpace", 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;
+ }
+
+
+ return(CVSPILS_SUCCESS);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * CVSpilsGetNumPrecEvals
+ * -----------------------------------------------------------------
+ */
+
+int CVSpilsGetNumPrecEvals(void *cvode_mem, long int *npevals)
+{
+ CVodeMem cv_mem;
+ CVSpilsMem cvspils_mem;
+
+ /* Return immediately if cvode_mem is NULL */
+ if (cvode_mem == 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", "CVSpilsGetNumPrecEvals", MSGS_LMEM_NULL);
+ return(CVSPILS_LMEM_NULL);
+ }
+ cvspils_mem = (CVSpilsMem) lmem;
+
+ *npevals = npe;
+
+ return(CVSPILS_SUCCESS);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * CVSpilsGetNumPrecSolves
+ * -----------------------------------------------------------------
+ */
+
+int CVSpilsGetNumPrecSolves(void *cvode_mem, long int *npsolves)
+{
+ CVodeMem cv_mem;
+ CVSpilsMem cvspils_mem;
+
+ /* Return immediately if cvode_mem is NULL */
+ if (cvode_mem == 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", "CVSpilsGetNumPrecSolves", MSGS_LMEM_NULL);
+ return(CVSPILS_LMEM_NULL);
+ }
+ cvspils_mem = (CVSpilsMem) lmem;
+
+ *npsolves = nps;
+
+ return(CVSPILS_SUCCESS);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * CVSpilsGetNumLinIters
+ * -----------------------------------------------------------------
+ */
+
+int CVSpilsGetNumLinIters(void *cvode_mem, long int *nliters)
+{
+ CVodeMem cv_mem;
+ CVSpilsMem cvspils_mem;
+
+ /* Return immediately if cvode_mem is NULL */
+ if (cvode_mem == 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", "CVSpilsGetNumLinIters", MSGS_LMEM_NULL);
+ return(CVSPILS_LMEM_NULL);
+ }
+ cvspils_mem = (CVSpilsMem) lmem;
+
+ *nliters = nli;
+
+ return(CVSPILS_SUCCESS);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * CVSpilsGetNumConvFails
+ * -----------------------------------------------------------------
+ */
+
+int CVSpilsGetNumConvFails(void *cvode_mem, long int *nlcfails)
+{
+ CVodeMem cv_mem;
+ CVSpilsMem cvspils_mem;
+
+ /* Return immediately if cvode_mem is NULL */
+ if (cvode_mem == 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", "CVSpilsGetNumConvFails", MSGS_LMEM_NULL);
+ return(CVSPILS_LMEM_NULL);
+ }
+ cvspils_mem = (CVSpilsMem) lmem;
+
+ *nlcfails = ncfl;
+
+ 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 */
+ if (cvode_mem == 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);
+ return(CVSPILS_LMEM_NULL);
+ }
+ cvspils_mem = (CVSpilsMem) lmem;
+
+ *njvevals = 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 */
+ if (cvode_mem == 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);
+ return(CVSPILS_LMEM_NULL);
+ }
+ cvspils_mem = (CVSpilsMem) lmem;
+
+ *nfevalsLS = 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 */
+ if (cvode_mem == 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);
+ return(CVSPILS_LMEM_NULL);
+ }
+ cvspils_mem = (CVSpilsMem) lmem;
+
+ *flag = last_flag;
+
+ return(CVSPILS_SUCCESS);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * CVSpilsGetReturnFlagName
+ * -----------------------------------------------------------------
+ */
+
+char *CVSpilsGetReturnFlagName(long int flag)
+{
+ char *name;
+
+ name = (char *)malloc(30*sizeof(char));
+
+ switch(flag) {
+ case CVSPILS_SUCCESS:
+ sprintf(name,"CVSPILS_SUCCESS");
+ break;
+ case CVSPILS_MEM_NULL:
+ sprintf(name,"CVSPILS_MEM_NULL");
+ break;
+ case CVSPILS_LMEM_NULL:
+ sprintf(name,"CVSPILS_LMEM_NULL");
+ break;
+ case CVSPILS_ILL_INPUT:
+ sprintf(name,"CVSPILS_ILL_INPUT");
+ break;
+ case CVSPILS_MEM_FAIL:
+ sprintf(name,"CVSPILS_MEM_FAIL");
+ break;
+ case CVSPILS_PMEM_NULL:
+ sprintf(name,"CVSPILS_PMEM_NULL");
+ break;
+ case CVSPILS_NO_ADJ:
+ sprintf(name,"CVSPILS_NO_ADJ");
+ break;
+ case CVSPILS_LMEMB_NULL:
+ sprintf(name,"CVSPILS_LMEMB_NULL");
+ break;
+ default:
+ sprintf(name,"NONE");
+ }
+
+ return(name);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * CVSPILS private functions
+ * -----------------------------------------------------------------
+ */
+
+
+/* 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 P_data (cvspils_mem->s_P_data)
+
+/*
+ * -----------------------------------------------------------------
+ * 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)
+{
+ CVodeMem cv_mem;
+ CVSpilsMem cvspils_mem;
+ int retval;
+
+ cv_mem = (CVodeMem) cvode_mem;
+ cvspils_mem = (CVSpilsMem) lmem;
+
+ retval = jtimes(v, z, tn, ycur, fcur, j_data, ytemp);
+ njtimes++;
+ if (retval != 0) return(retval);
+
+ N_VLinearSum(ONE, v, -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)
+{
+ CVodeMem cv_mem;
+ CVSpilsMem cvspils_mem;
+ int retval;
+
+ cv_mem = (CVodeMem) cvode_mem;
+ cvspils_mem = (CVSpilsMem)lmem;
+
+ /* 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(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.
+ * -----------------------------------------------------------------
+ */
+
+int CVSpilsDQJtimes(N_Vector v, N_Vector Jv, realtype t,
+ N_Vector y, N_Vector fy,
+ void *data, 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;
+
+ /* Initialize perturbation to 1/||v|| */
+ sig = ONE/N_VWrmsNorm(v, ewt);
+
+ for (iter=0; iter<MAX_ITERS; iter++) {
+
+ /* Set work = y + sig*v */
+ N_VLinearSum(sig, v, ONE, y, work);
+
+ /* Set Jv = f(tn, y+sig*v) */
+ retval = f(t, work, Jv, user_data);
+ nfes++;
+ if (retval == 0) break;
+ if (retval < 0) return(-1);
+
+ sig *= PT25;
+ }
+
+ if (retval > 0) return(+1);
+
+ /* Replace Jv by (Jv - fy)/sig */
+ siginv = ONE/sig;
+ N_VLinearSum(siginv, Jv, -siginv, fy, Jv);
+
+ return(0);
+}
+
+/*
+ * ================================================================
+ *
+ * PART II - backward problems
+ *
+ * ================================================================
+ */
+
+/* Readability replacements */
+
+#define ytmp (ca_mem->ca_ytmp)
+#define yStmp (ca_mem->ca_yStmp)
+#define IMget (ca_mem->ca_IMget)
+
+#define pset_B (cvspilsB_mem->s_psetB)
+#define psolve_B (cvspilsB_mem->s_psolveB)
+#define jtimes_B (cvspilsB_mem->s_jtimesB)
+
+/*
+ * -----------------------------------------------------------------
+ * OPTIONAL INPUT and OUTPUT FUNCTIONS
+ * -----------------------------------------------------------------
+ */
+
+int CVSpilsSetPrecTypeB(void *cvode_mem, int which, int pretypeB)
+{
+ 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", "CVSpilsSetPrecTypeB", 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", "CVSpilsSetPrecTypeB", 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", "CVSpilsSetPrecTypeB", 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);
+
+ flag = CVSpilsSetPrecType(cvodeB_mem, pretypeB);
+
+ return(flag);
+}
+
+int CVSpilsSetGSTypeB(void *cvode_mem, int which, int gstypeB)
+{
+ 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);
+ 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", "CVSpilsSetGSTypeB", 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", "CVSpilsSetGSTypeB", 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);
+
+ flag = CVSpilsSetGSType(cvodeB_mem,gstypeB);
+
+ return(flag);
+}
+
+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", "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", "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", "CVSpilsSetEpsLinB", 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);
+
+ flag = CVSpilsSetEpsLin(cvodeB_mem,eplifacB);
+
+ return(flag);
+}
+
+int CVSpilsSetMaxlB(void *cvode_mem, int which, int maxlB)
+{
+ 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);
+ 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);
+ 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);
+ 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);
+
+ flag = CVSpilsSetMaxl(cvodeB_mem,maxlB);
+
+ return(flag);
+}
+
+int CVSpilsSetPreconditionerB(void *cvode_mem, int which,
+ CVSpilsPrecSetupFnB psetB,
+ CVSpilsPrecSolveFnB psolveB)
+{
+ CVodeMem cv_mem;
+ CVadjMem ca_mem;
+ CVodeBMem cvB_mem;
+ CVSpilsMemB cvspilsB_mem;
+ void *cvodeB_mem;
+ int flag;
+
+ /* Check if cvode_mem exists */
+ if (cvode_mem == NULL) {
+ cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS", "CVSpilsSetPreconsitionerB", 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", "CVSpilsSetPreconsitionerB", 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", "CVSpilsSetPreconsitionerB", 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);
+
+ if (cvB_mem->cv_lmem == NULL) {
+ cvProcessError(cv_mem, CVSPILS_LMEMB_NULL, "CVSPILS", "CVSpilsSetPreconditonerB", MSGS_LMEMB_NULL);
+ return(CVSPILS_LMEMB_NULL);
+ }
+ cvspilsB_mem = (CVSpilsMemB) (cvB_mem->cv_lmem);
+
+ pset_B = psetB;
+ psolve_B = psolveB;
+
+ flag = CVSpilsSetPreconditioner(cvodeB_mem, cvSpilsPrecSetupBWrapper, cvSpilsPrecSolveBWrapper);
+
+ return(flag);
+}
+
+int CVSpilsSetJacTimesVecFnB(void *cvode_mem, int which, CVSpilsJacTimesVecFnB jtvB)
+{
+ CVodeMem cv_mem;
+ CVadjMem ca_mem;
+ CVodeBMem cvB_mem;
+ CVSpilsMemB cvspilsB_mem;
+ void *cvodeB_mem;
+ int flag;
+
+ /* Check if cvode_mem exists */
+ if (cvode_mem == NULL) {
+ cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS", "CVSpilsSetJacTimesVecFnB", 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);
+ 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);
+ 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);
+
+ if (cvB_mem->cv_lmem == NULL) {
+ cvProcessError(cv_mem, CVSPILS_LMEMB_NULL, "CVSPILS", "CVSpilsSetJacTimesVecFnB", MSGS_LMEMB_NULL);
+ return(CVSPILS_LMEMB_NULL);
+ }
+ cvspilsB_mem = (CVSpilsMemB) (cvB_mem->cv_lmem);
+
+ jtimes_B = jtvB;
+
+ if (jtvB != NULL) {
+ flag = CVSpilsSetJacTimesVecFn(cvodeB_mem, cvSpilsJacTimesVecBWrapper);
+ } else {
+ flag = CVSpilsSetJacTimesVecFn(cvodeB_mem, NULL);
+ }
+
+ return(flag);
+}
+
+
+/*
+ * -----------------------------------------------------------------
+ * CVSPILS private functions
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * cvSpilsPrecSetupBWrapper
+ *
+ * This routine 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,
+ N_Vector tmp1B, N_Vector tmp2B, N_Vector tmp3B)
+{
+ CVodeMem cv_mem;
+ CVadjMem ca_mem;
+ CVodeBMem cvB_mem;
+ CVSpilsMemB cvspilsB_mem;
+ int retval, flag;
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ ca_mem = cv_mem->cv_adj_mem;
+
+ cvB_mem = ca_mem->ca_bckpbCrt;
+
+ cvspilsB_mem = (CVSpilsMemB) (cvB_mem->cv_lmem);
+
+ /* Forward solution from interpolation */
+ flag = IMget(cv_mem, t, ytmp, NULL);
+ if (flag != CV_SUCCESS) {
+ cvProcessError(cv_mem, -1, "CVSPILS", "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);
+
+ return(retval);
+}
+
+
+/*
+ * cvSpilsPrecSolveBWrapper
+ *
+ * This routine 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)
+{
+ CVodeMem cv_mem;
+ CVadjMem ca_mem;
+ CVodeBMem cvB_mem;
+ CVSpilsMemB cvspilsB_mem;
+ int retval, flag;
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ ca_mem = cv_mem->cv_adj_mem;
+
+ cvB_mem = ca_mem->ca_bckpbCrt;
+
+ cvspilsB_mem = (CVSpilsMemB) (cvB_mem->cv_lmem);
+
+ /* Forward solution from interpolation */
+ flag = IMget(cv_mem, t, ytmp, NULL);
+ if (flag != CV_SUCCESS) {
+ cvProcessError(cv_mem, -1, "CVSPILS", "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);
+
+ return(retval);
+}
+
+
+/*
+ * cvSpilsJacTimesVecBWrapper
+ *
+ * This routine 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)
+{
+ CVodeMem cv_mem;
+ CVadjMem ca_mem;
+ CVodeBMem cvB_mem;
+ CVSpilsMemB cvspilsB_mem;
+ int retval, flag;
+
+ cv_mem = (CVodeMem) cvode_mem;
+
+ ca_mem = cv_mem->cv_adj_mem;
+
+ cvB_mem = ca_mem->ca_bckpbCrt;
+
+ cvspilsB_mem = (CVSpilsMemB) (cvB_mem->cv_lmem);
+
+ /* Forward solution from interpolation */
+ flag = IMget(cv_mem, t, ytmp, NULL);
+ if (flag != CV_SUCCESS) {
+ cvProcessError(cv_mem, -1, "CVSPILS", "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);
+
+ return(retval);
+}
+
diff --git a/src/cvodes/cvodes_spils_impl.h b/src/cvodes/cvodes_spils_impl.h
new file mode 100644
index 0000000..137c38f
--- /dev/null
+++ b/src/cvodes/cvodes_spils_impl.h
@@ -0,0 +1,183 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.9 $
+ * $Date: 2010/12/01 22:30:42 $
+ * -----------------------------------------------------------------
+ * Programmer(s): 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.
+ * -----------------------------------------------------------------
+ * Common implementation header file for the scaled, preconditioned
+ * iterative linear solvers
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _CVSSPILS_IMPL_H
+#define _CVSSPILS_IMPL_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <cvodes/cvodes_spils.h>
+#include "cvodes_impl.h"
+
+/*
+ * =================================================================
+ * 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 */
+
+#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.
+ * -----------------------------------------------------------------
+ */
+
+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 */
+
+ /* Preconditioner computation
+ * (a) user-provided:
+ * - P_data == user_data
+ * - 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;
+ void (*s_pfree)(CVodeMem cv_mem);
+ void *s_P_data;
+
+ /* Jacobian times vector compuation
+ * (a) jtimes function provided by the user:
+ * - j_data == user_data
+ * - jtimesDQ == FALSE
+ * (b) internal jtimes
+ * - j_data == cvode_mem
+ * - jtimesDQ == TRUE
+ */
+ booleantype s_jtimesDQ;
+ CVSpilsJacTimesVecFn s_jtimes;
+ void *s_j_data;
+
+ long int s_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);
+
+int CVSpilsPSolve(void *cv_mem, N_Vector r, N_Vector z, 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);
+/*
+ * =================================================================
+ * PART II: B A C K W A R D P R O B L E M S
+ * =================================================================
+ */
+
+/*
+ * -----------------------------------------------------------------
+ * Types : CVSpilsMemRecB, CVSpilsMemB
+ * -----------------------------------------------------------------
+ * CVSpgmrB, CVSpbcgB, and CVSptfqmr attach such a structure to the
+ * lmemB filed of CVodeBMem
+ * -----------------------------------------------------------------
+ */
+
+typedef struct CVSpilsMemRecB {
+
+ CVSpilsJacTimesVecFnB s_jtimesB;
+ CVSpilsPrecSetupFnB s_psetB;
+ CVSpilsPrecSolveFnB s_psolveB;
+ void *s_P_dataB;
+
+} *CVSpilsMemB;
+
+
+/*
+ * =================================================================
+ * E R R O R M E S S A G E S
+ * =================================================================
+ */
+
+#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_JTIMES_FAILED "The Jacobian x vector routine failed in an unrecoverable manner."
+
+#define MSGS_NO_ADJ "Illegal attempt to call before calling CVodeAdjMalloc."
+#define MSGS_BAD_WHICH "Illegal value for which."
+#define MSGS_LMEMB_NULL "Linear solver memory is NULL for the backward integration."
+#define MSGS_BAD_TINTERP "Bad t for interpolation."
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/cvodes/cvodes_sptfqmr.c b/src/cvodes/cvodes_sptfqmr.c
new file mode 100644
index 0000000..cbb84ee
--- /dev/null
+++ b/src/cvodes/cvodes_sptfqmr.c
@@ -0,0 +1,570 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.13 $
+ * $Date: 2011/03/23 22:58:47 $
+ * -----------------------------------------------------------------
+ * 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.
+ * -----------------------------------------------------------------
+ * 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 void CVSptfqmrFree(CVodeMem cv_mem);
+
+/* CVSPTFQMR lfreeB function */
+
+static void 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;
+
+ 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 = RSqrt(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 */
+ npe = nli = nps = ncfl = nstlpre = 0;
+ njtimes = nfes = 0;
+
+ /* 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 = ABS((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 void 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;
+}
+
+/*
+ * ================================================================
+ *
+ * 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 void CVSptfqmrFreeB(CVodeBMem cvB_mem)
+{
+ CVSpilsMemB cvspilsB_mem;
+
+ cvspilsB_mem = (CVSpilsMemB) (cvB_mem->cv_lmem);
+
+ free(cvspilsB_mem);
+}
diff --git a/src/ida/CMakeLists.txt b/src/ida/CMakeLists.txt
new file mode 100644
index 0000000..438ee2d
--- /dev/null
+++ b/src/ida/CMakeLists.txt
@@ -0,0 +1,125 @@
+# ---------------------------------------------------------------
+# $Revision: 1.4 $
+# $Date: 2009/02/17 02:58:48 $
+# ---------------------------------------------------------------
+# Programmer: Radu Serban @ LLNL
+# ---------------------------------------------------------------
+# Copyright (c) 2007, The Regents of the University of California.
+# Produced at the Lawrence Livermore National Laboratory.
+# All rights reserved.
+# For details, see the LICENSE file.
+# ---------------------------------------------------------------
+# CMakeLists.txt file for the IDA library
+
+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_direct.c
+ ida_band.c
+ ida_dense.c
+ ida_spils.c
+ ida_spbcgs.c
+ ida_spgmr.c
+ ida_sptfqmr.c
+ ida_bbdpre.c
+ )
+
+# 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_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_bbdpre.h
+ ida_dense.h
+ ida_direct.h
+ ida.h
+ ida_spbcgs.h
+ ida_spgmr.h
+ ida_spils.h
+ ida_sptfqmr.h
+ )
+
+# 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(.)
+INCLUDE_DIRECTORIES(../sundials)
+
+# Define C preprocessor flag -DBUILD_SUNDIALS_LIBRARY
+ADD_DEFINITIONS(-DBUILD_SUNDIALS_LIBRARY)
+
+# Build the static library
+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})
+
+ # Set the library name and make sure it is not deleted
+ SET_TARGET_PROPERTIES(sundials_ida_static
+ PROPERTIES OUTPUT_NAME sundials_ida CLEAN_DIRECT_OUTPUT 1)
+
+ # Install the IDA library
+ INSTALL(TARGETS sundials_ida_static DESTINATION lib)
+
+ENDIF(BUILD_STATIC_LIBS)
+
+# Build the shared library
+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})
+
+ # Set the library name and make sure it is not deleted
+ SET_TARGET_PROPERTIES(sundials_ida_shared
+ PROPERTIES OUTPUT_NAME sundials_ida CLEAN_DIRECT_OUTPUT 1)
+
+ # Set VERSION and SOVERSION for shared libraries
+ SET_TARGET_PROPERTIES(sundials_ida_shared
+ PROPERTIES VERSION ${idalib_VERSION} SOVERSION ${idalib_SOVERSION})
+
+ # Install the IDA library
+ INSTALL(TARGETS sundials_ida_shared DESTINATION lib)
+
+ENDIF(BUILD_SHARED_LIBS)
+
+# Install the IDA header files
+INSTALL(FILES ${ida_HEADERS} ${ida_BL_HEADERS} DESTINATION include/ida)
+
+# Install the IDA implementation header file
+INSTALL(FILES ida_impl.h DESTINATION include/ida)
+
+#
+MESSAGE(STATUS "Added IDA module")
diff --git a/debian/copyright b/src/ida/LICENSE
similarity index 83%
copy from debian/copyright
copy to src/ida/LICENSE
index 98cde97..d50d177 100644
--- a/debian/copyright
+++ b/src/ida/LICENSE
@@ -1,22 +1,10 @@
-This package was debianized by Andrey Romanenko <andrey at enginum.com> on
-Wed, 20 Apr 2005 12:01:42 +0100.
+Copyright (c) 2002, The Regents of the University of California.
+Produced at the Lawrence Livermore National Laboratory.
+Written by Alan Hindmarsh, Allan Taylor, Radu Serban.
+UCRL-CODE-155952
+All rights reserved.
-It was downloaded from http://www.llnl.gov/CASC/sundials/
-
-Authors: Peter Brown, Aaron Collier, Keith Grant, Alan Hindmarsh,
- Steve Lee, Radu Serban, Dan Shumaker, Carol Woodward
-
-Copyright Holder: The Regents of the University of California.
-
-License:
-
-Copyright (c) 2002, The Regents of the University of California.
-Produced at the Lawrence Livermore National Laboratory
-Written by A.C. Hindmarsh and R. Serban.
-UCRL-CODE-155950
-All rights reserved.
-
-This file is part of CVODES v2.1.0.
+This file is part of IDA.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
diff --git a/src/ida/Makefile.in b/src/ida/Makefile.in
new file mode 100644
index 0000000..8c83d7a
--- /dev/null
+++ b/src/ida/Makefile.in
@@ -0,0 +1,169 @@
+# -----------------------------------------------------------------
+# $Revision: 1.12 $
+# $Date: 2009/03/25 23:10:50 $
+# -----------------------------------------------------------------
+# Programmer(s): Radu Serban and Aaron Collier @ LLNL
+# -----------------------------------------------------------------
+# Copyright (c) 2002, The Regents of the University of California.
+# Produced at the Lawrence Livermore National Laboratory.
+# All rights reserved.
+# For details, see the LICENSE file.
+# -----------------------------------------------------------------
+# Makefile for IDA module
+#
+# @configure_input@
+# -----------------------------------------------------------------
+
+SHELL = @SHELL@
+
+ at SET_MAKE@
+
+srcdir = @srcdir@
+builddir = @builddir@
+abs_builddir = @abs_builddir@
+top_builddir = @top_builddir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+includedir = @includedir@
+libdir = @libdir@
+
+INSTALL = @INSTALL@
+INSTALL_LIB = @INSTALL_PROGRAM@
+INSTALL_HEADER = @INSTALL_DATA@
+
+LIBTOOL = @LIBTOOL@
+LIBTOOL_DEPS = @LIBTOOL_DEPS@
+
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CC = @CC@
+CFLAGS = @CFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+
+LAPACK_ENABLED = @LAPACK_ENABLED@
+
+top_srcdir = $(srcdir)/../..
+
+INCLUDES = -I$(top_srcdir)/include -I$(top_builddir)/include
+
+LIB_REVISION = 2:0:0
+
+IDA_LIB = libsundials_ida.la
+
+IDA_SRC_FILES = ida.c ida_ic.c ida_io.c ida_direct.c ida_dense.c ida_band.c ida_spils.c ida_spbcgs.c ida_spgmr.c ida_sptfqmr.c ida_bbdpre.c
+IDA_BL_SRC_FILES = ida_lapack.c
+
+IDA_OBJ_FILES = $(IDA_SRC_FILES:.c=.o)
+IDA_BL_OBJ_FILES = $(IDA_BL_SRC_FILES:.c=.o)
+
+IDA_LIB_FILES = $(IDA_SRC_FILES:.c=.lo)
+IDA_BL_LIB_FILES = $(IDA_BL_SRC_FILES:.c=.lo)
+
+SHARED_LIB_FILES = $(top_builddir)/src/sundials/sundials_band.lo \
+ $(top_builddir)/src/sundials/sundials_dense.lo \
+ $(top_builddir)/src/sundials/sundials_direct.lo \
+ $(top_builddir)/src/sundials/sundials_iterative.lo \
+ $(top_builddir)/src/sundials/sundials_spgmr.lo \
+ $(top_builddir)/src/sundials/sundials_spbcgs.lo \
+ $(top_builddir)/src/sundials/sundials_sptfqmr.lo \
+ $(top_builddir)/src/sundials/sundials_math.lo \
+ $(top_builddir)/src/sundials/sundials_nvector.lo
+
+mkinstalldirs = $(SHELL) $(top_srcdir)/config/mkinstalldirs
+rminstalldirs = $(SHELL) $(top_srcdir)/config/rminstalldirs
+
+# ----------------------------------------------------------------------------------------------------------------------
+
+all: $(IDA_LIB)
+
+$(IDA_LIB): shared $(IDA_LIB_FILES)
+ @if test "X${LAPACK_ENABLED}" = "Xyes"; then \
+ make lib_with_bl; \
+ else \
+ make lib_without_bl; \
+ fi
+
+lib_without_bl: shared $(IDA_LIB_FILES)
+ $(LIBTOOL) --mode=link $(CC) $(CFLAGS) -o $(IDA_LIB) $(IDA_LIB_FILES) $(SHARED_LIB_FILES) -rpath $(libdir) $(LDFLAGS) $(LIBS) -version-info $(LIB_REVISION)
+
+lib_with_bl: shared $(IDA_LIB_FILES) $(IDA_BL_LIB_FILES)
+ $(LIBTOOL) --mode=link $(CC) $(CFLAGS) -o $(IDA_LIB) $(IDA_LIB_FILES) $(IDA_BL_LIB_FILES) $(SHARED_LIB_FILES) -rpath $(libdir) $(LDFLAGS) $(LIBS) -version-info $(LIB_REVISION)
+
+install: $(IDA_LIB)
+ $(mkinstalldirs) $(includedir)/ida
+ $(mkinstalldirs) $(libdir)
+ $(LIBTOOL) --mode=install $(INSTALL_LIB) $(IDA_LIB) $(libdir)
+ $(INSTALL_HEADER) $(top_srcdir)/include/ida/ida.h $(includedir)/ida/
+ $(INSTALL_HEADER) $(top_srcdir)/include/ida/ida_direct.h $(includedir)/ida/
+ $(INSTALL_HEADER) $(top_srcdir)/include/ida/ida_dense.h $(includedir)/ida/
+ $(INSTALL_HEADER) $(top_srcdir)/include/ida/ida_band.h $(includedir)/ida/
+ $(INSTALL_HEADER) $(top_srcdir)/include/ida/ida_spbcgs.h $(includedir)/ida/
+ $(INSTALL_HEADER) $(top_srcdir)/include/ida/ida_spgmr.h $(includedir)/ida/
+ $(INSTALL_HEADER) $(top_srcdir)/include/ida/ida_sptfqmr.h $(includedir)/ida/
+ $(INSTALL_HEADER) $(top_srcdir)/include/ida/ida_bbdpre.h $(includedir)/ida/
+ $(INSTALL_HEADER) $(top_srcdir)/include/ida/ida_spils.h $(includedir)/ida/
+ $(INSTALL_HEADER) $(top_srcdir)/src/ida/ida_impl.h $(includedir)/ida/
+ @if test "X${LAPACK_ENABLED}" = "Xyes"; then \
+ $(INSTALL_HEADER) $(top_srcdir)/include/ida/ida_lapack.h $(includedir)/ida/ ; \
+ fi
+
+uninstall:
+ $(LIBTOOL) --mode=uninstall rm -f $(libdir)/$(IDA_LIB)
+ rm -f $(includedir)/ida/ida.h
+ rm -f $(includedir)/ida/ida_direct.h
+ rm -f $(includedir)/ida/ida_dense.h
+ rm -f $(includedir)/ida/ida_band.h
+ rm -f $(includedir)/ida/ida_lapack.h
+ rm -f $(includedir)/ida/ida_spbcgs.h
+ rm -f $(includedir)/ida/ida_spgmr.h
+ rm -f $(includedir)/ida/ida_sptfqmr.h
+ rm -f $(includedir)/ida/ida_bbdpre.h
+ rm -f $(includedir)/ida/ida_spils.h
+ rm -f $(includedir)/ida/ida_impl.h
+ $(rminstalldirs) ${includedir}/ida
+
+shared:
+ @cd ${top_builddir}/src/sundials ; \
+ ${MAKE} ; \
+ cd ${abs_builddir}
+
+clean:
+ $(LIBTOOL) --mode=clean rm -f $(IDA_LIB)
+ rm -f $(IDA_LIB_FILES)
+ rm -f $(IDA_BL_LIB_FILES)
+ rm -f $(IDA_OBJ_FILES)
+ rm -f $(IDA_BL_OBJ_FILES)
+
+distclean: clean
+ rm -f Makefile
+
+ida.lo: $(srcdir)/ida.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/ida.c
+ida_ic.lo: $(srcdir)/ida_ic.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/ida_ic.c
+ida_io.lo: $(srcdir)/ida_io.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/ida_io.c
+ida_direct.lo: $(srcdir)/ida_direct.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/ida_direct.c
+ida_dense.lo: $(srcdir)/ida_dense.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/ida_dense.c
+ida_band.lo: $(srcdir)/ida_band.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/ida_band.c
+ida_lapack.lo: $(srcdir)/ida_lapack.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/ida_lapack.c
+ida_spils.lo: $(srcdir)/ida_spils.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/ida_spils.c
+ida_spbcgs.lo: $(srcdir)/ida_spbcgs.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/ida_spbcgs.c
+ida_spgmr.lo: $(srcdir)/ida_spgmr.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/ida_spgmr.c
+ida_sptfqmr.lo: $(srcdir)/ida_sptfqmr.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/ida_sptfqmr.c
+ida_bbdpre.lo: $(srcdir)/ida_bbdpre.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/ida_bbdpre.c
+
+libtool: $(top_builddir)/$(LIBTOOL_DEPS)
+ @cd ${top_builddir} ; \
+ ${SHELL} ./config.status --recheck ; \
+ cd ${abs_builddir}
diff --git a/src/ida/README b/src/ida/README
new file mode 100644
index 0000000..b8e6d8b
--- /dev/null
+++ b/src/ida/README
@@ -0,0 +1,395 @@
+ IDA
+ Release 2.7.0, March 2012
+ Alan C. Hindmarsh and Radu Serban
+ Center for Applied Scientific Computing, LLNL
+
+
+IDA is a package for the solution of differential-algebraic equation
+(DAE) systems. It is written in C, but derived from the package DASPK
+[4,5], which is written in FORTRAN.
+
+IDA can be used both on serial and parallel (MPI) computers. The main
+difference is in the NVECTOR module of vector kernels. The desired
+version is obtained when compiling the example files by linking the
+appropriate library of NVECTOR kernels. In the parallel version,
+communication between processors is done with the MPI (Message Passage
+Interface) system.
+
+When used with the serial NVECTOR module, IDA provides both direct
+(dense and band) linear solvers and preconditioned Krylov (iterative)
+linear solvers. Three different iterative solvers are available: scaled
+preconditioned GMRES (SPGMR), scaled preconditioned BiCGStab (SPBCG), and
+scaled preconditioned TFQMR (SPTFQMR). When IDA is used with the parallel
+NVECTOR module, only the Krylov linear solvers are available. For the
+latter case, in addition to the basic solver, the IDA package also contains
+a preconditioner module called IDABBDPRE, which provides a band-block-diagonal
+preconditioner.
+
+IDA is part of a software family called SUNDIALS: SUite of Nonlinear and
+DIfferential/ALgebraic equation Solvers [3]. This suite consists of CVODE,
+CVODES, IDA, IDAS, and KINSOL. The directory structure of the package supplied
+reflects this family relationship.
+
+For use with Fortran applications, a set of Fortran/C interface routines,
+called FIDA, is also supplied. These are written in C, but assume that
+the user calling program and all user-supplied routines are in Fortran.
+
+Several examples problem programs are included, covering both serial
+and parallel cases, both small and large problem sizes, and both
+linear and nonlinear problems.
+
+The notes below provide the location of documentation, directions for the
+installation of the IDA package, and relevant references. Following that
+is a brief history of revisions to the package.
+
+
+A. Documentation
+----------------
+
+/sundials/doc/ida/ contains PDF files for the IDA User Guide [1] (ida_guide.pdf)
+and the IDA Examples [2] (ida_examples.pdf) documents.
+
+
+B. Installation
+---------------
+
+For basic installation instructions see the file /sundials/INSTALL_NOTES.
+For complete installation instructions see the "IDA Installation Procedure"
+chapter in the IDA User Guide.
+
+
+C. References
+-------------
+
+[1] A. C. Hindmarsh, R. Serban, and A. Collier, "User Documentation for IDA v2.7.0,"
+ LLNL technical report UCRL-SM-208112, December 2011.
+
+[2] A. C. Hindmarsh, R. Serban, and A. Collier, "Example Programs for IDA v2.7.0,"
+ LLNL technical report UCRL-SM-208113, December 2011.
+
+[3] A. C. Hindmarsh, P. N. Brown, K. E. Grant, S. L. Lee, R. Serban,
+ D. E. Shumaker, and C. S. Woodward, "SUNDIALS, Suite of Nonlinear and
+ Differential/Algebraic Equation Solvers," ACM Trans. Math. Softw.,
+ 31(3), pp. 363-396, 2005.
+
+[4] P. N. Brown, A. C. Hindmarsh, and L. R. Petzold, Using Krylov Methods
+ in the Solution of Large-Scale Differential-Algebraic Systems,
+ SIAM J. Sci. Comp., 15 (1994), pp. 1467-1488.
+
+[5] P. N. Brown, A. C. Hindmarsh, and L. R. Petzold, Consistent Initial
+ Condition Calculation for Differential-Algebraic Systems,
+ SIAM J. Sci. Comp., 19 (1998), pp. 1495-1512.
+
+
+D. Releases
+-----------
+
+v. 2.6.0 - Mar. 2012
+v. 2.6.0 - May 2009
+v. 2.5.0 - Nov. 2006
+v. 2.4.0 - Mar. 2006
+v. 2.3.0 - Apr. 2005
+v. 2.2.2 - Mar. 2005
+v. 2.2.1 - Jan. 2005
+v. 2.2.0 - Dec. 2004
+v. 2.0 - Jul. 2002 (first SUNDIALS release)
+v. 1.0 - Feb. 1999 (date written)
+
+
+E. Revision History
+-------------------
+
+v. 2.6.0 (May 2009) ---> v. 2.7.0 (Mar. 2012)
+---------------------------------------------
+
+- Bug fixes
+ - after the solver memory is created, it is set to zero before being filled.
+ - to be consistent with IDAS, IDA uses the function IDAGetDky for
+ optional output retrieval.
+ - in each linear solver interface function, the linear solver memory is
+ freed on an error return, and the **Free function now includes a
+ line setting to NULL the main memory pointer to the linear solver memory.
+ - a memory leak was fixed in two of the IDASp***Free functions.
+ - in rootfinding functions IDARcheck1/IDARcheck2, when an exact zero is found,
+ the array glo at the left endpoint is adjusted instead of shifting tlo.
+
+- Changes to user interface
+ - One significant design change was made with this release: The problem
+ size and its relatives, bandwidth parameters, related internal indices,
+ pivot arrays, and the optional output lsflag, have all been
+ changed from type int to type long int, except for the
+ problem size and bandwidths in user calls to routines specifying
+ BLAS/LAPACK routines for the dense/band linear solvers. The function
+ NewIntArray is replaced by a pair NewIntArray/NewLintArray,
+ for int and long int arrays, respectively.
+ - in the installation files, we modified the treatment of the macro
+ SUNDIALS_USE_GENERIC_MATH, so that the parameter GENERIC_MATH_LIB
+ is either defined (with no value) or not defined.
+
+
+v. 2.5.0 (Nov. 2006) ---> v. 2.6.0 (May 2009)
+---------------------------------------------
+
+- New features
+ - added a new linear solver module based on Blas + Lapack for
+ both dense and banded matrices.
+ - added optional input to specify which direction of zero-crossing
+ is to be monitored while performing root-finding. The root information
+ array iroots (returned by IDAGetRootInfo) also encodes the
+ direction of zero-crossing.
+
+- Bug fixes
+ - in the rootfinding algorithm, fixed a bug resulting in unnecessary
+ evaluations of the root functions after reinitialization of the
+ solver right after a return at a root.
+
+- Changes to user interface
+ - renamed all **Malloc functions to **Init
+ - tolerances are now specified through separate functions instead of
+ the initialization functions IDAInit (former IDAMalloc) and
+ IDAReInit. Depending on the tolerance type, one of 3 functions
+ must be called before the first call to IDASolve.
+ - removed function inputs from argument lists of all re-initialization
+ functions.
+ - all user-supplied functions now receive the same pointer to user data
+ (instead of having different ones for the system evaluation, Jacobian
+ information functions, etc.)
+ - removed IDA_NORMAL_TSTOP and IDA_ONE_STEP_TSTOP named constants for the
+ itask argument to IDASolve. A tstop value is now both set and activated
+ through IDASetStopTime. Once tstop is reached it is also deactivated.
+ A new value can be then specified by calling again IDASetStopTime.
+ - common functionality for all direct linear solvers (dense, band, and
+ the new Lapack solver) has been collected into the DLS (Direct Linear
+ Solver) module, similar to the SPILS module for the iterative linear
+ solvers. All optional input and output functions for these linear
+ solver now have the prefix 'IDADls'. In addition, in order to include
+ the new Lapack-based linear solver, all dimensions for these linear
+ solvers (problem sizes, bandwidths, etc) are now of type 'int'
+ (instead of 'long int').
+ - the initialization function for the preconditioner module IDABBDPRE
+ was renamed IDABBDInit (from IDABBDAlloc) and it does not return
+ a pointer to preconditioner memory anymore. Instead, all preconditioner
+ module-related functions are now called with the main solver memory
+ pointer as their first argument. When using the IDABBDPRE module,
+ there is no need to use special functions to attach one of the SPILS
+ linear solvers (instead use one of IDASpgmr, IDASpbcg, or IDASptfqmr).
+ Moreover, there is no need to call a memory deallocation function for
+ the preconditioner module.
+ - minor changes to legality requirements for real optional inputs.
+ - added the error return IDA_RTFUNC_FAIL.
+ - changes corresponding to the above were made to the FCMIX interface.
+
+v. 2.4.0 (Mar. 2006) ---> v. 2.5.0 (Oct. 2006)
+----------------------------------------------
+
+- Bug fixes
+ - fixed wrong logic in final stopping tests: now we check if
+ tout was reached before checking if tstop was reached.
+ - added a roundoff factor when testing whether tn was just returned
+ (in root finding) to prevent an unnecessary return.
+ - fixed perturbation factor "underflow" issue in IDADenseDQJac and
+ IDABandDQJac routines which are used to compute a difference quotient
+ approximation to the system Jacobian (see IDA_P1).
+
+- Changes related to the build system
+ - reorganized source tree: header files in ${srcdir}/include/ida,
+ source files in ${srcdir}/src/ida, fcmix source files in
+ ${srcdir}/src/ida/fcmix, examples in ${srcdir}/examples/ida
+ - exported header files are installed unde ${includedir}/ida
+
+- Changes to user interface
+ - all included header files use relative paths from ${includedir}
+ - modified prototype and implementation of IDACalcIC (removed
+ arguments t0, yy0, yp0). IDACalcIC will always correct the
+ initial conditions passed through IDAMalloc (or IDAReInit)
+ which were stored in the Nordsieck history array
+ - added optional output IDAGetConsistentIC function (which can
+ only be called before any IDASolve calls) to obtain the corrected
+ initial conditions.
+
+v. 2.3.0 (Apr. 2005) ---> v. 2.4.0 (Mar. 2006)
+----------------------------------------------
+
+- New features
+ - added IDASPBCG interface module to allow IDA to interface with the
+ shared SPBCG (scaled preconditioned Bi-CGSTAB) linear solver module.
+ - added IDASPTFQMR interface module to allow IDA to interface with the
+ shared SPTFQMR (scaled preconditioned TFQMR) linear solver module.
+ - added support for SPBCG and SPTFQMR to the IDABBDPRE preconditioner module.
+ - added FIDA (Fortran interface to IDA).
+ - added rootfinding feature in IDA; modified irobx example problem.
+ - added support for interpreting failures in user-supplied functions.
+
+- Changes to user-callable functions
+ - changed argument of IDAFree and IDABBDPrecFree to be the address
+ of the respective memory block pointer, so that its NULL value is
+ propagated back to the calling function.
+ - added IDASPBCG module which defines appropriate IDSpbcg* functions to
+ allow IDA to interface with the shared SPBCG linear solver module.
+ - added IDABBDSpbcg function to IDABBDPRE module to support SPBCG linear
+ solver module.
+ - changed function type names (not the actual definition) to accomodate
+ all the Scaled Preconditioned Iterative Linear Solvers now available:
+ IDASpgmrJactimesVecFn -> IDASpilsJacTimesVecFn
+ IDASpgmrPrecSetupFn -> IDASpilsPrecSetupFn
+ IDASpgmrPrecSolveFn -> IDASpilsPrecSolveFn
+ - changed some names for IDABBDPRE function outputs
+ - added option for user-supplied error handler function.
+ - added IDAGetEstLocalErrors() to return estimated local errors.
+ - renamed all exported header files (except for ida.h, all header files
+ have the prefix 'ida_')
+ - changed naming scheme for IDA examples
+
+- Changes related to the build system
+ - the main IDA header file (ida.h) is still exported to the install include
+ directory. However, all other IDA header files are exported into an 'ida'
+ subdirectory of the install include directory.
+ - the IDA library now contains all shared object files (there is no separate
+ libsundials_shared library anymore)
+
+v. 2.2.2 (Mar. 2005) ---> v. 2.3.0 (Apr. 2005)
+----------------------------------------------
+
+- New features
+ - added option for user-provided error weight computation function
+ (of type IDAEwtFn specified through IDASetEwtFn).
+
+- Changes to user interface
+ - IDA now stores tolerances through values rather than references
+ (to resolve potential scoping issues).
+ - IDA now stores the constraints and id vectors (if defined) through
+ values ratherthan references.
+ - IDA now passes information back to the user through values rather
+ than references (error weights)
+ - IDAMalloc, IDAReInit, IDASetTolerances: added option itol=IDA_WF
+ to indicate user-supplied function for computing the error weights;
+ reltol is now declared as realtype. Note that it is now illegal to call
+ IDASetTolerances before IDAMalloc. It is now legal to deallocate
+ the absolute tolerance N_Vector right after its use.
+ - IDAGetErrorWeights: the user is now responsible for allocating space
+ for the N_Vector in which error weights will be copied.
+ - IDACalcIC takes as additional arguments (t0,y0,yp0). As a consequence,
+ it can be called at any time to correct a pair (y,y').
+ - Passing a value of 0 for the maximum step size or for maxsteps results
+ in the solver using the corresponding default value (infinity, and 500,
+ respectively)
+ - Several optional input functions were combined into a single one
+ (IDADenseSetJacFn and IDADenseSetJacData, IDABandSetJacFn and IDABandSetJacData,
+ IDASpgmrSetPrecSolveFn and IDASpgmrSetPrecSetFn and IDASpgmrSetPrecData,
+ IDASpgmrSetJacTimesVecFn and IDASpgmrSetJacData).
+
+v. 2.2.1 (Jan. 2005) ---> v. 2.2.2 (Mar. 2005)
+----------------------------------------------
+
+- Bug fixes
+ - changed implicit type conversion to explicit in check_flag() routine in
+ examples to avoid C++ compiler errors
+
+- Changes to documentation
+ - added section with numerical values of all input and output solver constants
+ - added more detailed notes on the type of absolute tolerances
+ - fixed several typos and removed reference to inexistent function IDASetMinStep
+ - added description of --with-mpi-flags option
+
+- Changes related to the build system
+ - fixed autoconf-related bug to allow configuration with the PGI Fortran compiler
+ - modified to use customized detection of the Fortran name mangling scheme
+ (autoconf's AC_F77_WRAPPERS routine is problematic on some platforms)
+ - added --with-mpi-flags as a configure option to allow user to specify
+ MPI-specific flags
+ - updated Makefiles for Fortran examples to avoid C++ compiler errors (now use
+ CC and MPICC to link)
+
+
+v. 2.2.0 (Dec. 2004) ---> v. 2.2.1 (Jan. 2005)
+----------------------------------------------
+
+- Changes related to the build system
+ - changed order of compiler directives in header files to avoid compilation
+ errors when using a C++ compiler.
+
+- Changes to documentation
+ - fixed various mistakes and typos in the user guide and example program
+ documents.
+
+v. 2.0 (Jul. 2002) ---> v. 2.2.0 (Dec. 2004)
+--------------------------------------------
+
+- New features
+ - added option to disable all error messages.
+
+- Bug fixes
+ - in the solution of the nonlinear system, the correction for small constraint
+ violation is to ee, not y.
+ - besides delaying the order increase until the 2nd step, we now also delay
+ doubling the step size, to avoid using information from times before t0.
+
+- Changes related to the NVECTOR module
+ (see also the file sundials/shared/README)
+ - removed machEnv, redefined table of vector operations (now contained
+ in the N_Vector structure itself).
+ - all IDA functions create new N_Vector variables through cloning, using
+ an N_Vector passed by the user as a template.
+
+- Changes to type names and IDA constants
+ - removed type 'integertype'; instead use int or long int, as appropriate.
+ - restructured the list of return values from the various IDA functions.
+ - changed all IDA constants (inputs and return values) to have the
+ prefix 'IDA_' (e.g. IDA_SUCCESS).
+ - renamed various function types to have the prefix 'IDA' (e.g. IDAResFn).
+
+- Changes to optional input/ouput
+ - added IDASet* and IDAGet* functions for optional inputs/outputs,
+ replacing the arrays iopt and ropt.
+ - added new optional inputs (e.g. maximum number of Newton iterations,
+ maximum number of convergence failures, etc).
+ - added new function IDAGetSolution for dense output.
+ - the value of the last return flag from any function within a linear
+ solver module can be obtained as an optional output (e.g. IDADenseGetLastFlag).
+
+- Changes to user-callable functions
+ - added new function IDACreate which initializes the IDA solver
+ object and returns a pointer to the IDA memory block.
+ - removed N (problem size) from all functions except the initialization
+ functions for the direct linear solvers (IDADense and IDABand).
+ - shortened argument lists of most IDA functions (the arguments that
+ were dropped can now be specified through IDASet* functions).
+ - removed reinitialization functions for band/dense/SPGMR linear
+ solvers (same functionality can be obtained using IDA*Set* functions).
+ - in IDABBDPRE, added a new function, IDABBDSpgmr to initialize the
+ SPGMR linear solver with the BBD preconditioner.
+ - function names changed in IDABBDPRE for uniformity.
+
+- Changes to user-supplied functions
+ - removed N (probem dimension) from argument lists.
+ - shortened argument lists for user dense/band/SPGMR Jacobian routines.
+ - in IDASPGMR, shortened argument lists for user preconditioner functions.
+ - in IDABBDPRE, added Nlocal, the local vector size, as an argument to
+ IDABBDLocalFn and IDABBDCommFn.
+
+v. 1.0 (Feb. 1999) ---> v. 2.0 (Jul. 2002)
+------------------------------------------
+
+YYYYMMDD
+
+19990212 DATE WRITTEN; initial internal release (incomplete).
+19990514 IDABBDPRE preconditioner module added.
+19990720 Initial condition calculation routines (IDACalcIC) added.
+19991208 In IDABBDPRE, user routine argument lists changed.
+19991217 Generic SPGMR module revised to correct scalings.
+20000316 In parallel NVECTOR, comm arg. to PVecInitMPI is non-NULL.
+20000808 Fixed bug in N_VMin. In IDACalcIC: added calculation of system
+ index in CALC_YA_YDP_INIT case, added scaling of fnorm when index = 0.
+20010110 Fixed two bugs in IDACalcIC and subordinate routines:
+ (1) Set hh in IDACalcIC independent of icopt, for lsetup.
+ (2) Set ypnew = yp0 in IDALineSrch in CALC_Y_INIT case.
+ Corrected #define ncfl0 line in idaspgmr.c.
+20011015 Fixed bug in IDAInterp (tn test).
+ Fixed minor bugs in error messages (missing arguments etc.)
+20011220 Default type 'integer' changed to 'long int' in llnltyps.h.
+20020313 Modified to work with new NVECTOR abstraction.
+20020626 Renamed types real, integer, boole as realtype, integertype,
+ and booleantype, and renamed related constants. Renamed files
+ llnlmath.*, llnltypes.h as sundialsmath.*, sundialstypes.h.
+20020703 Added reinitialization routines for IDA, for each linear
+ solver module, and for IDABBDPRE.
diff --git a/src/ida/fcmix/CMakeLists.txt b/src/ida/fcmix/CMakeLists.txt
new file mode 100644
index 0000000..d1a4ae5
--- /dev/null
+++ b/src/ida/fcmix/CMakeLists.txt
@@ -0,0 +1,43 @@
+# CMakeLists.txt file for the FIDA library
+
+# Add variable fida_SOURCES with the sources for the FIDA library
+SET(fida_SOURCES
+ fidaband.c
+ fidabbd.c
+ fida.c
+ fidadense.c
+ fidaewt.c
+ fidajtimes.c
+ fidapreco.c
+ fidaroot.c
+ )
+
+IF(LAPACK_FOUND)
+ SET(fida_BL_SOURCES fidalapack.c fidalapdense.c fidalapband.c)
+ELSE(LAPACK_FOUND)
+ SET(fida_BL_SOURCES "")
+ENDIF(LAPACK_FOUND)
+
+# Add source directories to include directories for access to
+# implementation only header files (both for fida and ida)
+INCLUDE_DIRECTORIES(.)
+INCLUDE_DIRECTORIES(..)
+
+# Define C preprocessor flag -DBUILD_SUNDIALS_LIBRARY
+ADD_DEFINITIONS(-DBUILD_SUNDIALS_LIBRARY)
+
+# Only build STATIC libraries (we cannot build shared libraries
+# for the FCMIX interfaces due to unresolved symbol errors
+# 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})
+
+# Set the library name and make sure it is not deleted
+SET_TARGET_PROPERTIES(sundials_fida_static
+ PROPERTIES OUTPUT_NAME sundials_fida CLEAN_DIRECT_OUTPUT 1)
+
+# Install the FIDA library
+INSTALL(TARGETS sundials_fida_static DESTINATION lib)
+#
+MESSAGE(STATUS "Added IDA FCMIX module")
diff --git a/src/ida/fcmix/Makefile.in b/src/ida/fcmix/Makefile.in
new file mode 100644
index 0000000..58a5e8d
--- /dev/null
+++ b/src/ida/fcmix/Makefile.in
@@ -0,0 +1,123 @@
+# -----------------------------------------------------------------
+# $Revision: 1.8 $
+# $Date: 2009/03/25 23:10:50 $
+# -----------------------------------------------------------------
+# Programmer(s): Aaron Collier @ 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.
+# -----------------------------------------------------------------
+# Makefile for FIDA module
+#
+# @configure_input@
+# -----------------------------------------------------------------
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+builddir = @builddir@
+abs_builddir = @abs_builddir@
+top_builddir = @top_builddir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+includedir = @includedir@
+libdir = @libdir@
+
+INSTALL = @INSTALL@
+INSTALL_LIB = @INSTALL_PROGRAM@
+INSTALL_HEADER = @INSTALL_DATA@
+
+LIBTOOL = @LIBTOOL@
+LIBTOOL_DEPS = @LIBTOOL_DEPS@
+
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CC = @CC@
+CFLAGS = @CFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+
+LAPACK_ENABLED = @LAPACK_ENABLED@
+
+top_srcdir = $(srcdir)/../../..
+
+INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/src/ida -I$(top_builddir)/include
+
+LIB_REVISION = 1:0:0
+
+FIDA_LIB = libsundials_fida.la
+
+FIDA_SRC_FILES = fida.c fidaband.c fidadense.c fidajtimes.c fidapreco.c fidaewt.c fidaroot.c fidabbd.c
+FIDA_BL_SRC_FILES = fidalapack.c fidalapdense.c fidalapband.c
+
+FIDA_OBJ_FILES = $(FIDA_SRC_FILES:.c=.o)
+FIDA_BL_OBJ_FILES = $(FIDA_BL_SRC_FILES:.c=.o)
+
+FIDA_LIB_FILES = $(FIDA_SRC_FILES:.c=.lo)
+FIDA_BL_LIB_FILES = $(FIDA_BL_SRC_FILES:.c=.lo)
+
+mkinstalldirs = $(SHELL) $(top_srcdir)/config/mkinstalldirs
+
+# ----------------------------------------------------------------------------------------------------------------------
+
+all: $(FIDA_LIB)
+
+$(FIDA_LIB): $(FIDA_LIB_FILES)
+ @if test "X${LAPACK_ENABLED}" = "Xyes"; then \
+ make lib_with_bl; \
+ else \
+ make lib_without_bl; \
+ fi
+
+lib_without_bl: $(FIDA_LIB_FILES)
+ $(LIBTOOL) --mode=link $(CC) $(CFLAGS) -o $(FIDA_LIB) $(FIDA_LIB_FILES) -rpath $(libdir) $(LDFLAGS) $(LIBS) -static -version-info $(LIB_REVISION)
+
+lib_with_bl: $(FIDA_LIB_FILES) $(FIDA_BL_LIB_FILES)
+ $(LIBTOOL) --mode=link $(CC) $(CFLAGS) -o $(FIDA_LIB) $(FIDA_LIB_FILES) $(FIDA_BL_LIB_FILES) -rpath $(libdir) $(LDFLAGS) $(LIBS) -static -version-info $(LIB_REVISION)
+
+install: $(FIDA_LIB)
+ $(mkinstalldirs) $(libdir)
+ $(LIBTOOL) --mode=install $(INSTALL_LIB) $(FIDA_LIB) $(libdir)
+
+uninstall:
+ $(LIBTOOL) --mode=uninstall rm -f $(libdir)/$(FIDA_LIB)
+
+clean:
+ $(LIBTOOL) --mode=clean rm -f $(FIDA_LIB)
+ rm -f $(FIDA_LIB_FILES)
+ rm -f $(FIDA_BL_LIB_FILES)
+ rm -f $(FIDA_OBJ_FILES)
+ rm -f $(FIDA_BL_OBJ_FILES)
+
+distclean: clean
+ rm -f Makefile
+
+fida.lo: $(srcdir)/fida.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/fida.c
+fidaewt.lo: $(srcdir)/fidaewt.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/fidaewt.c
+fidaband.lo: $(srcdir)/fidaband.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/fidaband.c
+fidadense.lo: $(srcdir)/fidadense.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/fidadense.c
+fidalapack.lo: $(srcdir)/fidalapack.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/fidalapack.c
+fidalapband.lo: $(srcdir)/fidalapband.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/fidalapband.c
+fidalapdense.lo: $(srcdir)/fidalapdense.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/fidalapdense.c
+fidajtimes.lo: $(srcdir)/fidajtimes.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/fidajtimes.c
+fidapreco.lo: $(srcdir)/fidapreco.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/fidapreco.c
+fidabbd.lo: $(srcdir)/fidabbd.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/fidabbd.c
+fidaroot.lo: $(srcdir)/fidaroot.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/fidaroot.c
+
+libtool: $(top_builddir)/$(LIBTOOL_DEPS)
+ @cd ${top_builddir} ; \
+ ${SHELL} ./config.status --recheck ; \
+ cd ${abs_builddir}
diff --git a/src/ida/fcmix/fida.c b/src/ida/fcmix/fida.c
new file mode 100644
index 0000000..9336f47
--- /dev/null
+++ b/src/ida/fcmix/fida.c
@@ -0,0 +1,752 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.10 $
+ * $Date: 2010/12/01 22:37:20 $
+ * -----------------------------------------------------------------
+ * 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.
+ * -----------------------------------------------------------------
+ * 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_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 */
+
+/*************************************************/
+
+/* Definitions for global variables shared amongst various routines */
+
+N_Vector F2C_IDA_ypvec, F2C_IDA_ewtvec;
+
+void *IDA_idamem;
+long int *IDA_iout;
+realtype *IDA_rout;
+int IDA_ls;
+int IDA_nrtfn;
+
+/*************************************************/
+
+/* private constant(s) */
+#define ZERO RCONST(0.0)
+
+/*************************************************/
+
+/* Prototype of user-supplied Fortran routine (IDAResFn) */
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+ extern void FIDA_RESFUN(realtype*, /* T */
+ realtype*, /* Y */
+ realtype*, /* YP */
+ realtype*, /* R */
+ long int*, /* IPAR */
+ realtype*, /* RPAR */
+ int*); /* IER */
+
+#ifdef __cplusplus
+}
+#endif
+
+/*************************************************/
+
+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)
+{
+ N_Vector Vatol;
+ FIDAUserData IDA_userdata;
+
+ *ier = 0;
+
+ /* Check for required vector operations */
+ 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");
+ return;
+ }
+
+ /* Initialize all pointers to NULL */
+ IDA_idamem = NULL;
+ Vatol = NULL;
+ F2C_IDA_ypvec = F2C_IDA_ewtvec = NULL;
+
+ /* Create IDA object */
+ IDA_idamem = IDACreate();
+ if (IDA_idamem == NULL) {
+ *ier = -1;
+ return;
+ }
+
+ /* Set and attach user data */
+ IDA_userdata = NULL;
+ IDA_userdata = (FIDAUserData) malloc(sizeof *IDA_userdata);
+ if (IDA_userdata == NULL) {
+ *ier = -1;
+ return;
+ }
+ IDA_userdata->rpar = rpar;
+ IDA_userdata->ipar = ipar;
+
+ *ier = IDASetUserData(IDA_idamem, IDA_userdata);
+ if(*ier != IDA_SUCCESS) {
+ free(IDA_userdata); IDA_userdata = NULL;
+ *ier = -1;
+ return;
+ }
+
+ /* Attach user's yy0 to F2C_IDA_vec */
+ N_VSetArrayPointer(yy0, F2C_IDA_vec);
+
+ /* Create F2C_IDA_ypvec and attach user's yp0 to it */
+ F2C_IDA_ypvec = NULL;
+ F2C_IDA_ypvec = N_VCloneEmpty(F2C_IDA_vec);
+ if (F2C_IDA_ypvec == NULL) {
+ free(IDA_userdata); IDA_userdata = NULL;
+ *ier = -1;
+ }
+ N_VSetArrayPointer(yp0, F2C_IDA_ypvec);
+
+ /* Call IDAInit */
+ *ier = IDAInit(IDA_idamem, FIDAresfn, *t0, F2C_IDA_vec, F2C_IDA_ypvec);
+
+ /* Reset data pointers */
+ N_VSetArrayPointer(NULL, F2C_IDA_vec);
+ N_VSetArrayPointer(NULL, F2C_IDA_ypvec);
+
+ /* On failure, clean-up and exit */
+ if (*ier != IDA_SUCCESS) {
+ N_VDestroy(F2C_IDA_ypvec);
+ free(IDA_userdata); IDA_userdata = NULL;
+ *ier = -1;
+ return;
+ }
+
+ /* Set tolerances */
+ switch (*iatol) {
+ case 1:
+ *ier = IDASStolerances(IDA_idamem, *rtol, *atol);
+ break;
+ case 2:
+ Vatol = NULL;
+ Vatol= N_VCloneEmpty(F2C_IDA_vec);
+ if (Vatol == NULL) {
+ free(IDA_userdata); IDA_userdata = NULL;
+ *ier = -1;
+ return;
+ }
+ N_VSetArrayPointer(atol, Vatol);
+ *ier = IDASVtolerances(IDA_idamem, *rtol, Vatol);
+ N_VDestroy(Vatol);
+ break;
+ }
+
+ /* On failure, clean-up and exit */
+ if (*ier != IDA_SUCCESS) {
+ free(IDA_userdata); IDA_userdata = NULL;
+ *ier = -1;
+ return;
+ }
+
+ /* Grab optional output arrays and store them in global variables */
+ IDA_iout = iout;
+ IDA_rout = rout;
+
+ /* Store the unit roundoff in rout for user access */
+ IDA_rout[5] = UNIT_ROUNDOFF;
+
+ /* Set F2C_IDA_ewtvec on NULL */
+ F2C_IDA_ewtvec = NULL;
+
+ return;
+}
+
+/*************************************************/
+
+void FIDA_REINIT(realtype *t0, realtype *yy0, realtype *yp0,
+ int *iatol, realtype *rtol, realtype *atol,
+ int *ier)
+{
+ N_Vector Vatol;
+
+ *ier = 0;
+
+ /* Initialize all pointers to NULL */
+ Vatol = NULL;
+
+ /* Attach user's yy0 to F2C_IDA_vec */
+ N_VSetArrayPointer(yy0, F2C_IDA_vec);
+
+ /* Attach user's yp0 to F2C_IDA_ypvec */
+ N_VSetArrayPointer(yp0, F2C_IDA_ypvec);
+
+ /* Call IDAReInit */
+ *ier = IDAReInit(IDA_idamem, *t0, F2C_IDA_vec, F2C_IDA_ypvec);
+
+ /* Reset data pointers */
+ N_VSetArrayPointer(NULL, F2C_IDA_vec);
+ N_VSetArrayPointer(NULL, F2C_IDA_ypvec);
+
+ /* On failure, exit */
+ if (*ier != IDA_SUCCESS) {
+ *ier = -1;
+ return;
+ }
+
+ /* Set tolerances */
+ switch (*iatol) {
+ case 1:
+ *ier = IDASStolerances(IDA_idamem, *rtol, *atol);
+ break;
+ case 2:
+ Vatol = NULL;
+ Vatol= N_VCloneEmpty(F2C_IDA_vec);
+ if (Vatol == NULL) {
+ *ier = -1;
+ return;
+ }
+ N_VSetArrayPointer(atol, Vatol);
+ *ier = IDASVtolerances(IDA_idamem, *rtol, Vatol);
+ N_VDestroy(Vatol);
+ break;
+ }
+
+ /* On failure, exit */
+ if (*ier != IDA_SUCCESS) {
+ *ier = -1;
+ return;
+ }
+
+ return;
+}
+
+/*************************************************/
+
+void FIDA_SETIIN(char key_name[], long int *ival, int *ier, int key_len)
+{
+ if (!strncmp(key_name,"MAX_ORD", (size_t)key_len))
+ *ier = IDASetMaxOrd(IDA_idamem, (int) *ival);
+ else if (!strncmp(key_name,"MAX_NSTEPS", (size_t)key_len))
+ *ier = IDASetMaxNumSteps(IDA_idamem, (int) *ival);
+ else if (!strncmp(key_name,"MAX_ERRFAIL", (size_t)key_len))
+ *ier = IDASetMaxErrTestFails(IDA_idamem, (int) *ival);
+ else if (!strncmp(key_name,"MAX_NITERS", (size_t)key_len))
+ *ier = IDASetMaxNonlinIters(IDA_idamem, (int) *ival);
+ else if (!strncmp(key_name,"MAX_CONVFAIL", (size_t)key_len))
+ *ier = IDASetMaxConvFails(IDA_idamem, (int) *ival);
+ else if (!strncmp(key_name,"SUPPRESS_ALG", (size_t)key_len))
+ *ier = IDASetSuppressAlg(IDA_idamem, (int) *ival);
+ else if (!strncmp(key_name,"MAX_NSTEPS_IC", (size_t)key_len))
+ *ier = IDASetMaxNumStepsIC(IDA_idamem, (int) *ival);
+ else if (!strncmp(key_name,"MAX_NITERS_IC", (size_t)key_len))
+ *ier = IDASetMaxNumItersIC(IDA_idamem, (int) *ival);
+ else if (!strncmp(key_name,"MAX_NJE_IC", (size_t)key_len))
+ *ier = IDASetMaxNumJacsIC(IDA_idamem, (int) *ival);
+ else if (!strncmp(key_name,"LS_OFF_IC", (size_t)key_len))
+ *ier = IDASetLineSearchOffIC(IDA_idamem, (int) *ival);
+ else {
+ *ier = -99;
+ printf("FIDASETIIN: Unrecognized key.\n\n");
+ }
+
+}
+
+/***************************************************************************/
+
+void FIDA_SETRIN(char key_name[], realtype *rval, int *ier, int key_len)
+{
+
+ if (!strncmp(key_name,"INIT_STEP", (size_t)key_len))
+ *ier = IDASetInitStep(IDA_idamem, *rval);
+ else if (!strncmp(key_name,"MAX_STEP", (size_t)key_len))
+ *ier = IDASetMaxStep(IDA_idamem, *rval);
+ else if (!strncmp(key_name,"STOP_TIME", (size_t)key_len))
+ *ier = IDASetStopTime(IDA_idamem, *rval);
+ else if (!strncmp(key_name,"NLCONV_COEF", (size_t)key_len))
+ *ier = IDASetNonlinConvCoef(IDA_idamem, *rval);
+ else if (!strncmp(key_name,"NLCONV_COEF_IC", (size_t)key_len))
+ *ier = IDASetNonlinConvCoefIC(IDA_idamem, *rval);
+ else if (!strncmp(key_name,"STEP_TOL_IC", (size_t)key_len))
+ *ier = IDASetStepToleranceIC(IDA_idamem, *rval);
+ else {
+ *ier = -99;
+ printf("FIDASETRIN: Unrecognized key.\n\n");
+ }
+
+}
+
+/*************************************************/
+
+void FIDA_SETVIN(char key_name[], realtype *vval, int *ier, int key_len)
+{
+ N_Vector Vec;
+
+ *ier = 0;
+
+ if (!strncmp(key_name,"ID_VEC", (size_t)key_len)) {
+ Vec = NULL;
+ Vec = N_VCloneEmpty(F2C_IDA_vec);
+ if (Vec == NULL) {
+ *ier = -1;
+ return;
+ }
+ N_VSetArrayPointer(vval, Vec);
+ IDASetId(IDA_idamem, Vec);
+ N_VDestroy(Vec);
+ } else if (!strncmp(key_name,"CONSTR_VEC", (size_t)key_len)) {
+ Vec = NULL;
+ Vec = N_VCloneEmpty(F2C_IDA_vec);
+ if (Vec == NULL) {
+ *ier = -1;
+ return;
+ }
+ N_VSetArrayPointer(vval, Vec);
+ IDASetConstraints(IDA_idamem, Vec);
+ N_VDestroy(Vec);
+ } else {
+ *ier = -99;
+ printf("FIDASETVIN: Unrecognized key.\n\n");
+ }
+
+}
+
+/*************************************************/
+
+void FIDA_TOLREINIT(int *iatol, realtype *rtol, realtype *atol, int *ier)
+{
+ int itol;
+ N_Vector Vatol=NULL;
+
+ *ier = 0;
+
+ itol = -1;
+ if (*iatol == 1) {
+ *ier = IDASStolerances(IDA_idamem, *rtol, *atol);
+ } else {
+ Vatol = NULL;
+ Vatol = N_VCloneEmpty(F2C_IDA_vec);
+ if (Vatol == NULL) {
+ *ier = -1;
+ return;
+ }
+ N_VSetArrayPointer(atol, Vatol);
+ *ier = IDASVtolerances(IDA_idamem, *rtol, Vatol);
+ N_VDestroy(Vatol);
+ }
+
+ return;
+}
+
+/*************************************************/
+
+void FIDA_CALCIC(int *icopt, realtype *tout1, int *ier)
+{
+ *ier = 0;
+ *ier = IDACalcIC(IDA_idamem, *icopt, *tout1);
+ return;
+}
+
+/*************************************************/
+
+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;
+ }
+
+ IDA_ls = IDA_LS_SPTFQMR;
+
+ 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;
+ }
+
+ 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;
+
+ 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) {
+ *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;
+
+ 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) {
+ *ier = IDASpilsSetIncrementFactor(IDA_idamem, *dqincfac);
+ if (*ier != IDASPILS_SUCCESS) return;
+ }
+
+ IDA_ls = IDA_LS_SPBCG;
+
+ 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;
+}
+
+/*************************************************/
+
+void FIDA_SOLVE(realtype *tout, realtype *tret, realtype *yret,
+ realtype *ypret, int *itask, int *ier)
+{
+ int klast, kcur;
+
+ *ier = 0;
+
+ /* Attach user data to vectors */
+ N_VSetArrayPointer(yret, F2C_IDA_vec);
+ N_VSetArrayPointer(ypret, F2C_IDA_ypvec);
+
+ *ier = IDASolve(IDA_idamem, *tout, tret, F2C_IDA_vec, F2C_IDA_ypvec, *itask);
+
+ /* Reset data pointers */
+ N_VSetArrayPointer(NULL, F2C_IDA_vec);
+ N_VSetArrayPointer(NULL, F2C_IDA_ypvec);
+
+ /* Set optional outputs */
+
+ IDAGetWorkSpace(IDA_idamem,
+ &IDA_iout[0], /* LENRW */
+ &IDA_iout[1]); /* LENIW */
+
+ IDAGetIntegratorStats(IDA_idamem,
+ &IDA_iout[2], /* NST */
+ &IDA_iout[3], /* NRE */
+ &IDA_iout[7], /* NSETUPS */
+ &IDA_iout[4], /* NETF */
+ &klast, /* KLAST */
+ &kcur, /* KCUR */
+ &IDA_rout[0], /* HINUSED */
+ &IDA_rout[1], /* HLAST */
+ &IDA_rout[2], /* HCUR */
+ &IDA_rout[3]); /* TCUR */
+ IDA_iout[8] = (long int) klast;
+ IDA_iout[9] = (long int) kcur;
+ IDAGetNonlinSolvStats(IDA_idamem,
+ &IDA_iout[6], /* NNI */
+ &IDA_iout[5]); /* NCFN */
+ IDAGetNumBacktrackOps(IDA_idamem,
+ &IDA_iout[10]); /* NBCKTRK */
+ IDAGetTolScaleFactor(IDA_idamem,
+ &IDA_rout[4]); /* TOLSFAC */
+
+ /* Root finding is on */
+ if (IDA_nrtfn != 0)
+ 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:
+ 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_SPGMR:
+ case IDA_LS_SPBCG:
+ case IDA_LS_SPTFQMR:
+ 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 */
+ IDASpilsGetNumJtimesEvals(IDA_idamem, &IDA_iout[16]); /* NJE */
+ IDASpilsGetNumPrecEvals(IDA_idamem, &IDA_iout[17]); /* NPE */
+ IDASpilsGetNumPrecSolves(IDA_idamem, &IDA_iout[18]); /* NPS */
+ IDASpilsGetNumLinIters(IDA_idamem, &IDA_iout[19]); /* NLI */
+ IDASpilsGetNumConvFails(IDA_idamem, &IDA_iout[20]); /* NCFL */
+ break;
+ }
+
+
+ return;
+}
+
+/*************************************************/
+
+void FIDA_GETDKY(realtype *t, int *k, realtype *dky, int *ier)
+{
+ /* Attach user data to vectors */
+ N_VSetArrayPointer(dky, F2C_IDA_vec);
+
+ *ier = 0;
+ *ier = IDAGetDky(IDA_idamem, *t, *k, F2C_IDA_vec);
+
+ /* Reset data pointers */
+ N_VSetArrayPointer(NULL, F2C_IDA_vec);
+
+ return;
+}
+
+/*************************************************/
+
+void FIDA_GETERRWEIGHTS(realtype *eweight, int *ier)
+{
+ /* Attach user data to vector */
+ N_VSetArrayPointer(eweight, F2C_IDA_vec);
+
+ *ier = 0;
+ *ier = IDAGetErrWeights(IDA_idamem, F2C_IDA_vec);
+
+ /* Reset data pointer */
+ N_VSetArrayPointer(NULL, F2C_IDA_vec);
+
+ return;
+}
+
+/*************************************************/
+
+void FIDA_GETESTLOCALERR(realtype *ele, int *ier)
+{
+ /* Attach user data to vector */
+ N_VSetArrayPointer(ele, F2C_IDA_vec);
+
+ *ier = 0;
+ *ier = IDAGetEstLocalErrors(IDA_idamem, F2C_IDA_vec);
+
+ /* Reset data pointers */
+ N_VSetArrayPointer(NULL, F2C_IDA_vec);
+
+ return;
+}
+
+/*************************************************/
+
+void FIDA_FREE(void)
+{
+ IDAMem ida_mem;
+
+ ida_mem = (IDAMem) IDA_idamem;
+
+ free(ida_mem->ida_user_data); ida_mem->ida_user_data = NULL;
+
+ IDAFree(&IDA_idamem);
+
+ /* Free F2C_IDA_vec */
+ 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)
+ N_VDestroy(F2C_IDA_ewtvec);
+
+ return;
+}
+
+/*************************************************/
+
+int FIDAresfn(realtype t, N_Vector yy, N_Vector yp,
+ N_Vector rr, void *user_data)
+{
+ int ier;
+ realtype *yy_data, *yp_data, *rr_data;
+ FIDAUserData IDA_userdata;
+
+ /* 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 */
+ yy_data = N_VGetArrayPointer(yy);
+ yp_data = N_VGetArrayPointer(yp);
+ rr_data = N_VGetArrayPointer(rr);
+
+ IDA_userdata = (FIDAUserData) user_data;
+
+ /* Call user-supplied routine */
+ FIDA_RESFUN(&t, yy_data, yp_data, rr_data,
+ IDA_userdata->ipar, IDA_userdata->rpar, &ier);
+
+ return(ier);
+}
diff --git a/src/ida/fcmix/fida.h b/src/ida/fcmix/fida.h
new file mode 100644
index 0000000..081d835
--- /dev/null
+++ b/src/ida/fcmix/fida.h
@@ -0,0 +1,727 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.9 $
+ * $Date: 2010/12/01 22:37:20 $
+ * -----------------------------------------------------------------
+ * 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.
+ * -----------------------------------------------------------------
+ * 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
+ *
+ * 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
+ *
+ * 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
+ * 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.
+ *
+ * (5) 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.
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * (6) Initialization: FNVINITS / FNVINITP , FIDAMALLOC, FIDAREINIT,
+ * FIDATOLREINIT, and FIDACALCIC
+ *
+ * (6.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.
+ *
+ * (6.1p) 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 = 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.
+ *
+ * (6.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.
+ *
+ * (6.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.
+ *
+ * (6.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.
+ *
+ * (6.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.
+ *
+ * (6.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.
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * (7) 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.
+ *
+ * (7.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
+ *
+ * (7.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
+ *
+ * (7.3) 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.
+ *
+ * (7.4) 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.
+ *
+ * (7.5) 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.
+ *
+ * (7.6) 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.
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * (8) 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.
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * (9) 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.
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * (10) 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
+ *
+ * =============================================================================
+ */
+
+#ifndef _FIDA_H
+#define _FIDA_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <ida/ida.h> /* definition of type IDAResFn */
+#include <sundials/sundials_direct.h> /* definition of type DlsMat */
+#include <sundials/sundials_nvector.h> /* definition of type N_Vector */
+#include <sundials/sundials_types.h> /* definition of type realtype */
+
+#if defined(SUNDIALS_F77_FUNC)
+
+#define FIDA_MALLOC SUNDIALS_F77_FUNC(fidamalloc, FIDAMALLOC)
+#define FIDA_REINIT SUNDIALS_F77_FUNC(fidareinit, FIDAREINIT)
+#define FIDA_SETIIN SUNDIALS_F77_FUNC(fidasetiin, FIDASETIIN)
+#define FIDA_SETRIN SUNDIALS_F77_FUNC(fidasetrin, FIDASETRIN)
+#define FIDA_SETVIN SUNDIALS_F77_FUNC(fidasetvin, FIDASETVIN)
+#define FIDA_TOLREINIT SUNDIALS_F77_FUNC(fidatolreinit, FIDATOLREINIT)
+#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_BANDSETJAC SUNDIALS_F77_FUNC(fidabandsetjac, FIDABANDSETJAC)
+#define FIDA_DENSE SUNDIALS_F77_FUNC(fidadense, FIDADENSE)
+#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_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_SPILSSETJAC SUNDIALS_F77_FUNC(fidaspilssetjac, FIDASPILSSETJAC)
+#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_GETDKY SUNDIALS_F77_FUNC(fidagetdky, FIDAGETDKY)
+#define FIDA_GETERRWEIGHTS SUNDIALS_F77_FUNC(fidageterrweights, FIDAGETERRWEIGHTS)
+#define FIDA_GETESTLOCALERR SUNDIALS_F77_FUNC(fidagetestlocalerr, FIDAGETESTLOCALERR)
+
+#else
+
+#define FIDA_MALLOC fidamalloc_
+#define FIDA_REINIT fidareinit_
+#define FIDA_SETIIN fidasetiin_
+#define FIDA_SETRIN fidasetrin_
+#define FIDA_SETVIN fidasetvin_
+#define FIDA_TOLREINIT fidatolreinit_
+#define FIDA_SOLVE fidasolve_
+#define FIDA_FREE fidafree_
+#define FIDA_CALCIC fidacalcic_
+#define FIDA_BAND fidaband_
+#define FIDA_BANDSETJAC fidabandsetjac_
+#define FIDA_DENSE fidadense_
+#define FIDA_DENSESETJAC fidadensesetjac_
+#define FIDA_LAPACKBAND fidalapackband_
+#define FIDA_LAPACKBANDSETJAC fidalapackbandsetjac_
+#define FIDA_LAPACKDENSE fidalapackdense_
+#define FIDA_LAPACKDENSESETJAC fidalapackdensesetjac_
+#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_SPILSSETJAC fidaspilssetjac_
+#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_EWT fidaewt_
+#define FIDA_GETDKY fidagetdky_
+#define FIDA_GETERRWEIGHTS fidageterrweights_
+#define FIDA_GETESTLOCALERR fidagetestlocalerr_
+
+#endif
+
+/* Type for user data */
+
+typedef struct {
+ realtype *rpar;
+ long int *ipar;
+} *FIDAUserData;
+
+/* Prototypes of exported functions */
+
+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);
+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, int key_len);
+
+void FIDA_SETRIN(char key_name[], realtype *rval, int *ier, int key_len);
+
+void FIDA_SETVIN(char key_name[], realtype *vval, int *ier, int key_len);
+
+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_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_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_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);
+void FIDA_GETERRWEIGHTS(realtype *eweight, int *ier);
+void FIDA_GETESTLOCALERR(realtype *ele, int *ier);
+
+/* Prototypes: Functions Called by the IDA Solver */
+
+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,
+ 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,
+ 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 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);
+
+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);
+
+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 */
+
+/* Linear solver IDs */
+
+enum { IDA_LS_DENSE = 1, IDA_LS_BAND = 2,
+ IDA_LS_LAPACKDENSE = 3, IDA_LS_LAPACKBAND = 4,
+ IDA_LS_SPGMR = 5, IDA_LS_SPBCG = 6, IDA_LS_SPTFQMR = 7 };
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/ida/fcmix/fidaband.c b/src/ida/fcmix/fidaband.c
new file mode 100644
index 0000000..7d7d50e
--- /dev/null
+++ b/src/ida/fcmix/fidaband.c
@@ -0,0 +1,117 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.6 $
+ * $Date: 2010/12/01 22:37:20 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Aaron Collier @ 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.
+ * -----------------------------------------------------------------
+ * Fortran/C interface routines for IDA/IDABAND, 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_band.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 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)
+{
+ 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/fidabbd.c b/src/ida/fcmix/fidabbd.c
new file mode 100644
index 0000000..c01daa6
--- /dev/null
+++ b/src/ida/fcmix/fidabbd.c
@@ -0,0 +1,150 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.6 $
+ * $Date: 2010/12/01 22:37:20 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Aaron Collier @ 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.
+ * -----------------------------------------------------------------
+ * 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>
+
+#include "fida.h" /* function names, prototypes, global variables */
+#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 */
+
+/*************************************************/
+
+/* private constant(s) */
+
+#define ZERO RCONST(0.0)
+
+/*************************************************/
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+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*);
+
+#ifdef __cplusplus
+}
+#endif
+
+/*************************************************/
+
+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);
+
+ return;
+}
+
+/*************************************************/
+
+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)
+{
+ realtype *yy_data, *yp_data, *gval_data;
+ int ier;
+ FIDAUserData IDA_userdata;
+
+ /* Initialize all pointers to NULL */
+ yy_data = yp_data = gval_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 */
+ yy_data = N_VGetArrayPointer(yy);
+ yp_data = N_VGetArrayPointer(yp);
+ gval_data = N_VGetArrayPointer(gval);
+
+ IDA_userdata = (FIDAUserData) user_data;
+
+ /* Call user-supplied routine */
+ FIDA_GLOCFN(&Nloc, &t, yy_data, yp_data, gval_data,
+ IDA_userdata->ipar, IDA_userdata->rpar, &ier);
+
+ return(ier);
+}
+
+/*************************************************/
+
+int FIDAcfn(long int Nloc, realtype t, N_Vector yy, N_Vector yp,
+ void *user_data)
+{
+ realtype *yy_data, *yp_data;
+ int ier;
+ FIDAUserData IDA_userdata;
+
+ /* Initialize all pointers to NULL */
+ yy_data = yp_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 */
+ yy_data = N_VGetArrayPointer(yy);
+ yp_data = N_VGetArrayPointer(yp);
+
+ IDA_userdata = (FIDAUserData) user_data;
+
+ /* 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)
+{
+ IDABBDPrecGetWorkSpace(IDA_idamem, lenrwbbd, leniwbbd);
+ IDABBDPrecGetNumGfnEvals(IDA_idamem, ngebbd);
+
+ return;
+}
diff --git a/src/ida/fcmix/fidabbd.h b/src/ida/fcmix/fidabbd.h
new file mode 100644
index 0000000..879b01f
--- /dev/null
+++ b/src/ida/fcmix/fidabbd.h
@@ -0,0 +1,338 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.9 $
+ * $Date: 2010/12/15 19:40:08 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Aaron Collier @ 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.
+ * -----------------------------------------------------------------
+ * 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
+ * FIDABBDSPGMR interfaces to IDABBDSpgmr and IDASpilsSet*
+ * FIDABBDSPBCG interfaces to IDABBDSpbcg and IDASpilsSet*
+ * FIDABBDSPTFQMR interfaces to IDABBDSptfqmr and IDASpilsSet*
+ * 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
+ *
+ * ==============================================================================
+ */
+
+#ifndef _FIDABBD_H
+#define _FIDABBD_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <sundials/sundials_nvector.h>
+#include <sundials/sundials_types.h>
+
+#if defined(SUNDIALS_F77_FUNC)
+
+#define FIDA_BBDINIT SUNDIALS_F77_FUNC(fidabbdinit, FIDABBDINIT)
+#define FIDA_BBDREINIT SUNDIALS_F77_FUNC(fidabbdreinit, FIDABBDREINIT)
+#define FIDA_BBDOPT SUNDIALS_F77_FUNC(fidabbdopt, FIDABBDOPT)
+#define FIDA_GLOCFN SUNDIALS_F77_FUNC(fidaglocfn, FIDAGLOCFN)
+#define FIDA_COMMFN SUNDIALS_F77_FUNC(fidacommfn, FIDACOMMFN)
+
+#else
+
+#define FIDA_BBDINIT fidabbdinit_
+#define FIDA_BBDREINIT fidabbdreinit_
+#define FIDA_BBDOPT fidabbdopt_
+#define FIDA_GLOCFN fidaglocfn_
+#define FIDA_COMMFN fidacommfn_
+
+#endif
+
+/* Prototypes of exported functions */
+
+void FIDA_BBDINIT(long int *Nloc, long int *mudq, long int *mldq,
+ long int *mu, long int *ml, realtype *dqrely, int *ier);
+
+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);
+
+/* 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);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/ida/fcmix/fidadense.c b/src/ida/fcmix/fidadense.c
new file mode 100644
index 0000000..60f3337
--- /dev/null
+++ b/src/ida/fcmix/fidadense.c
@@ -0,0 +1,115 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.6 $
+ * $Date: 2010/12/01 22:37:20 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Aaron Collier @ 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.
+ * -----------------------------------------------------------------
+ * Fortran/C interface routines for IDA/IDADENSE, 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_dense.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_DENSESETJAC(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 FIDADenseJac(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/fidaewt.c b/src/ida/fcmix/fidaewt.c
new file mode 100644
index 0000000..53ecf9c
--- /dev/null
+++ b/src/ida/fcmix/fidaewt.c
@@ -0,0 +1,87 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.3 $
+ * $Date: 2007/04/30 19:29:00 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Aaron Collier @ 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.
+ * -----------------------------------------------------------------
+ * Fortran/C interface routines for IDA, for the case of a
+ * user-supplied error weight calculation 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 */
+
+/*************************************************/
+
+/* Prototype of user-supplied Fortran routine */
+
+#ifdef __cplusplus /* wrapper to enable C++ usage (IDAEwtFn) */
+extern "C" {
+#endif
+
+ extern void FIDA_EWT(realtype*, realtype*, /* Y, EWT */
+ long int*, realtype*, /* IPAR, RPAR */
+ int*); /* IER */
+
+#ifdef __cplusplus
+}
+#endif
+
+/*************************************************/
+
+/*
+ * User-callable function to interface to IDASetEwtFn.
+ */
+
+void FIDA_EWTSET(int *flag, int *ier)
+{
+ *ier = 0;
+
+ if (*flag != 0) {
+ *ier = IDAWFtolerances(IDA_idamem, FIDAEwtSet);
+ }
+
+ return;
+}
+
+/*************************************************/
+
+/*
+ * C function to interface between IDA and a Fortran subroutine FIDAVEWT.
+ */
+
+int FIDAEwtSet(N_Vector y, N_Vector ewt, void *user_data)
+{
+ int ier;
+ realtype *y_data, *ewt_data;
+ FIDAUserData IDA_userdata;
+
+ /* Initialize all pointers to NULL */
+ y_data = ewt_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;
+
+ y_data = N_VGetArrayPointer(y);
+ ewt_data = N_VGetArrayPointer(ewt);
+
+ IDA_userdata = (FIDAUserData) user_data;
+
+ /* Call user-supplied routine */
+ FIDA_EWT(y_data, ewt_data, IDA_userdata->ipar, IDA_userdata->rpar, &ier);
+
+ return(ier);
+}
diff --git a/src/ida/fcmix/fidajtimes.c b/src/ida/fcmix/fidajtimes.c
new file mode 100644
index 0000000..cbd1adb
--- /dev/null
+++ b/src/ida/fcmix/fidajtimes.c
@@ -0,0 +1,116 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.3 $
+ * $Date: 2007/04/30 19:29:00 $
+ * -----------------------------------------------------------------
+ * 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.
+ * -----------------------------------------------------------------
+ * 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.
+ * -----------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "fida.h" /* actual fn. names, prototypes and global vars.*/
+#include "ida_impl.h" /* definition of IDAMem type */
+
+#include <ida/ida_spils.h>
+
+/*************************************************/
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+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 */
+
+#ifdef __cplusplus
+}
+#endif
+
+/*************************************************/
+
+void FIDA_SPILSSETJAC(int *flag, int *ier)
+{
+ *ier = 0;
+
+ if (*flag == 0) {
+
+ *ier = IDASpilsSetJacTimesVecFn(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 = IDASpilsSetJacTimesVecFn(IDA_idamem, FIDAJtimes);
+
+ }
+
+ return;
+}
+
+/*************************************************/
+
+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)
+{
+ realtype *yy_data, *yp_data, *rr_data, *vdata, *Jvdata, *ewtdata;
+ realtype *v1data, *v2data;
+ realtype h;
+ FIDAUserData IDA_userdata;
+ int ier;
+
+ /* Initialize all pointers to NULL */
+ yy_data = yp_data = rr_data = vdata = Jvdata = 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);
+
+ /* 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);
+ vdata = N_VGetArrayPointer(v);
+ Jvdata = N_VGetArrayPointer(Jv);
+ v1data = N_VGetArrayPointer(vtemp1);
+ v2data = N_VGetArrayPointer(vtemp2);
+
+ IDA_userdata = (FIDAUserData) user_data;
+
+ /* Call user-supplied routine */
+ FIDA_JTIMES(&t, yy_data, yp_data, rr_data, vdata, Jvdata,
+ &c_j, ewtdata, &h,
+ IDA_userdata->ipar, IDA_userdata->rpar,
+ v1data, v2data, &ier);
+
+ return(ier);
+}
diff --git a/src/ida/fcmix/fidalapack.c b/src/ida/fcmix/fidalapack.c
new file mode 100644
index 0000000..0ba0dfa
--- /dev/null
+++ b/src/ida/fcmix/fidalapack.c
@@ -0,0 +1,53 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.1 $
+ * $Date: 2006/11/22 00:12:50 $
+ * -----------------------------------------------------------------
+ * Programmer(s): 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.
+ * -----------------------------------------------------------------
+ * 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
new file mode 100644
index 0000000..cfb8faf
--- /dev/null
+++ b/src/ida/fcmix/fidalapband.c
@@ -0,0 +1,112 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.6 $
+ * $Date: 2010/12/01 22:37:20 $
+ * -----------------------------------------------------------------
+ * Programmer(s): 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.
+ * -----------------------------------------------------------------
+ * 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
new file mode 100644
index 0000000..a06cf87
--- /dev/null
+++ b/src/ida/fcmix/fidalapdense.c
@@ -0,0 +1,111 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.6 $
+ * $Date: 2010/12/01 22:37:20 $
+ * -----------------------------------------------------------------
+ * Programmer(s): 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.
+ * -----------------------------------------------------------------
+ * 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
new file mode 100644
index 0000000..61d9afa
--- /dev/null
+++ b/src/ida/fcmix/fidapreco.c
@@ -0,0 +1,159 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.4 $
+ * $Date: 2010/03/17 21:01:08 $
+ * -----------------------------------------------------------------
+ * 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.
+ * -----------------------------------------------------------------
+ * 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>
+
+#include "fida.h" /* actual fn. names, prototypes and global vars.*/
+#include "ida_impl.h" /* definition of IDAMem type */
+
+#include <ida/ida_spils.h>
+
+/*************************************************/
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+ extern void FIDA_PSET(realtype*, realtype*, realtype*, realtype*,
+ realtype*, realtype*, realtype*,
+ long int*, realtype*,
+ realtype*, realtype*, realtype*,
+ int*);
+
+ extern void FIDA_PSOL(realtype*, realtype*, realtype*, realtype*,
+ realtype*, realtype*, realtype*, realtype*,
+ realtype*,
+ long int*, realtype*,
+ realtype*, int*);
+
+#ifdef __cplusplus
+}
+#endif
+
+/*************************************************/
+
+void FIDA_SPILSSETPREC(int *flag, int *ier)
+{
+ *ier = 0;
+
+ if (*flag == 0) {
+
+ *ier = IDASpilsSetPreconditioner(IDA_idamem, NULL, NULL);
+
+ } else {
+
+ if (F2C_IDA_ewtvec == NULL) {
+ F2C_IDA_ewtvec = N_VClone(F2C_IDA_vec);
+ if (F2C_IDA_ewtvec == NULL) {
+ *ier = -1;
+ return;
+ }
+ }
+
+ *ier = IDASpilsSetPreconditioner(IDA_idamem, (IDASpilsPrecSetupFn) FIDAPSet,
+ (IDASpilsPrecSolveFn) FIDAPSol);
+ }
+
+ return;
+}
+
+/*************************************************/
+
+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 *yy_data, *yp_data, *rr_data, *ewtdata, *v1data, *v2data, *v3data;
+ 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
+ (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);
+
+ 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);
+
+ return(ier);
+}
+
+/*************************************************/
+
+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 *yy_data, *yp_data, *rr_data, *ewtdata, *rdata, *zdata, *v1data;
+ int ier;
+ FIDAUserData IDA_userdata;
+
+ /* Initialize all pointers to NULL */
+ yy_data = yp_data = rr_data = ewtdata = zdata = v1data = 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);
+
+ /* 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);
+ 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);
+
+ return(ier);
+}
diff --git a/src/ida/fcmix/fidaroot.c b/src/ida/fcmix/fidaroot.c
new file mode 100644
index 0000000..0548dbb
--- /dev/null
+++ b/src/ida/fcmix/fidaroot.c
@@ -0,0 +1,88 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.3 $
+ * $Date: 2007/04/30 19:29:00 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Aaron Collier and Alan C. Hindmarsh @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * The FIDAROOT module contains the routines necessary to use
+ * the rootfinding feature of the IDA module and to interface
+ * with the user-supplied Fortran subroutine.
+ * -----------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "fida.h" /* actual function names, prototypes and global vars.*/
+#include "fidaroot.h" /* prototypes of interfaces to IDA */
+#include "ida_impl.h" /* definition of IDAMeme type */
+
+/***************************************************************************/
+
+/* Prototype of the Fortran routine */
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+ extern void FIDA_ROOTFN(realtype*, /* T */
+ realtype*, /* Y */
+ realtype*, /* YP */
+ realtype*, /* G */
+ long int*, /* IPAR */
+ realtype*, /* RPAR */
+ int*); /* IER */
+#ifdef __cplusplus
+}
+#endif
+
+/***************************************************************************/
+
+void FIDA_ROOTINIT(int *nrtfn, int *ier)
+{
+ *ier = IDARootInit(IDA_idamem, *nrtfn, (IDARootFn) FIDArootfunc);
+ IDA_nrtfn = *nrtfn;
+
+ return;
+}
+
+/***************************************************************************/
+
+void FIDA_ROOTINFO(int *nrtfn, int *info, int *ier)
+{
+ *ier = IDAGetRootInfo(IDA_idamem, info);
+ return;
+}
+
+/***************************************************************************/
+
+void FIDA_ROOTFREE(void)
+{
+ IDARootInit(IDA_idamem, 0, NULL);
+
+ return;
+}
+
+/***************************************************************************/
+
+int FIDArootfunc(realtype t, N_Vector y, N_Vector yp, realtype *gout,
+ void *user_data)
+{
+ int ier;
+ realtype *ydata, *ypdata;
+ FIDAUserData IDA_userdata;
+
+ ydata = N_VGetArrayPointer(y);
+ ypdata = N_VGetArrayPointer(yp);
+
+ IDA_userdata = (FIDAUserData) user_data;
+
+ FIDA_ROOTFN(&t, ydata, ypdata, gout, IDA_userdata->ipar, IDA_userdata->rpar, &ier);
+
+ return(ier);
+}
diff --git a/src/ida/fcmix/fidaroot.h b/src/ida/fcmix/fidaroot.h
new file mode 100644
index 0000000..68538a1
--- /dev/null
+++ b/src/ida/fcmix/fidaroot.h
@@ -0,0 +1,142 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.5 $
+ * $Date: 2010/12/15 19:40:08 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Aaron Collier and Alan C. Hindmarsh @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * This is the Fortran interface include file for the rootfinding
+ * feature of IDA.
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * ==============================================================================
+ *
+ * FIDAROOT Interface Package
+ *
+ * The FIDAROOT interface package allows programs written in FORTRAN to
+ * use the rootfinding feature of the IDA solver module.
+ *
+ * The user-callable functions constituting the FIDAROOT package are the
+ * following: FIDAROOTINIT, FIDAROOTINFO, and FIDAROOTFREE. The corresponding
+ * IDA subroutine called by each interface function is given below.
+ *
+ * ------------------ ---------------------
+ * | FIDAROOT routine | | IDA function called |
+ * ------------------ ---------------------
+ * FIDAROOTINIT -> IDARootInit
+ * FIDAROOTINFO -> IDAGetRootInfo
+ * FIDAROOTFREE -> IDARootInit
+ *
+ * FIDAROOTFN is a user-supplied subroutine defining the functions whose
+ * roots are sought.
+ *
+ * ==============================================================================
+ *
+ * Usage of the FIDAROOT Interface Package
+ *
+ * 1. In order to use the rootfinding feature of the IDA package the user must
+ * define the following subroutine:
+ *
+ * SUBROUTINE FIDAROOTFN (T, Y, YP, G, IPAR, RPAR, IER)
+ * DIMENSION Y(*), YP(*), G(*)
+ *
+ * The arguments are:
+ * T = independent variable value t [input]
+ * 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]
+ * 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
+ * allocate and initialize memory for the FIDAROOT module by making the
+ * following call:
+ *
+ * CALL FIDAROOTINIT (NRTFN, IER)
+ *
+ * The arguments are:
+ * NRTFN = total number of root functions [input]
+ * IER = return completion flag (0 = success, -1 = IDA memory NULL and
+ * -14 = memory allocation error) [output]
+ *
+ * 3. After calling FIDA, to see whether a root was found, test the FIDA
+ * return flag IER. The value IER = 2 means one or more roots were found.
+ *
+ * 4. If a root was found, and if NRTFN > 1, then to determine which root
+ * functions G(*) were found to have a root, make the following call:
+ * CALL FIDAROOTINFO (NRTFN, INFO, IER)
+ * The arguments are:
+ * NRTFN = total number of root functions [input]
+ * INFO = integer array of length NRTFN, with values 0 or 1 [output]
+ * For i = 1,...,NRTFN, G(i) was found to have a root if INFO(i) = 1.
+ * IER = completion flag (0 = success, negative = failure)
+ *
+ * 5. The total number of calls made to the root function (FIDAROOTFN),
+ * NGE, can be obtained from IOUT(12).
+ *
+ * If the FIDA/IDA memory block is reinitialized to solve a different
+ * problem via a call to FIDAREINIT, then the counter variable NGE is cleared
+ * (reset to zero).
+ *
+ * 6. To free the memory resources allocated by a prior call to FIDAROOTINIT,
+ * make the following call:
+ * CALL FIDAROOTFREE
+ * See the IDA documentation for additional information.
+ *
+ * ==============================================================================
+ */
+
+#ifndef _FIDAROOT_H
+#define _FIDAROOT_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+/* header files */
+
+#include <sundials/sundials_nvector.h> /* definition of type N_Vector */
+#include <sundials/sundials_types.h> /* definition of SUNDIALS type realtype */
+
+/* Definitions of interface function names */
+
+#if defined(SUNDIALS_F77_FUNC)
+
+#define FIDA_ROOTINIT SUNDIALS_F77_FUNC(fidarootinit, FIDAROOTINIT)
+#define FIDA_ROOTINFO SUNDIALS_F77_FUNC(fidarootinfo, FIDAROOTINFO)
+#define FIDA_ROOTFREE SUNDIALS_F77_FUNC(fidarootfree, FIDAROOTFREE)
+#define FIDA_ROOTFN SUNDIALS_F77_FUNC(fidarootfn, FIDAROOTFN)
+
+#else
+
+#define FIDA_ROOTINIT fidarootinit_
+#define FIDA_ROOTINFO fidarootinfo_
+#define FIDA_ROOTFREE fidarootfree_
+#define FIDA_ROOTFN fidarootfn_
+
+#endif
+
+/* Prototypes of exported function */
+
+void FIDA_ROOTINIT(int *nrtfn, int *ier);
+void FIDA_ROOTINFO(int *nrtfn, int *info, int *ier);
+void FIDA_ROOTFREE(void);
+
+/* Prototype of function called by IDA module */
+
+int FIDArootfunc(realtype t, N_Vector y, N_Vector yp, realtype *gout,
+ void *user_data);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif
diff --git a/src/ida/ida.c b/src/ida/ida.c
new file mode 100644
index 0000000..7c05cae
--- /dev/null
+++ b/src/ida/ida.c
@@ -0,0 +1,3433 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.25 $
+ * $Date: 2012/03/06 21:58:52 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Alan Hindmarsh, Radu Serban and Aaron Collier @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * This is the implementation file for the main IDA solver.
+ * It is independent of the linear solver in use.
+ * -----------------------------------------------------------------
+ *
+ * EXPORTED FUNCTIONS
+ * ------------------
+ * Creation, allocation and re-initialization functions
+ * IDACreate
+ * IDAInit
+ * IDAReInit
+ * IDARootInit
+ * Main solver function
+ * IDASolve
+ * Interpolated output and extraction functions
+ * IDAGetDky
+ * Deallocation functions
+ * IDAFree
+ *
+ * PRIVATE FUNCTIONS
+ * -----------------
+ * IDACheckNvector
+ * Memory allocation/deallocation
+ * IDAAllocVectors
+ * IDAFreeVectors
+ * Initial setup
+ * IDAInitialSetup
+ * IDAEwtSet
+ * IDAEwtSetSS
+ * IDAEwtSetSV
+ * Stopping tests
+ * IDAStopTest1
+ * IDAStopTest2
+ * Error handler
+ * IDAHandleFailure
+ * Main IDAStep function
+ * IDAStep
+ * IDASetCoeffs
+ * Nonlinear solver functions
+ * IDANls
+ * IDAPredict
+ * IDANewtonIter
+ * Error test
+ * IDATestError
+ * IDARestore
+ * Handler for convergence and/or error test failures
+ * IDAHandleNFlag
+ * IDAReset
+ * Function called after a successful step
+ * IDACompleteStep
+ * Get solution
+ * IDAGetSolution
+ * Norm functions
+ * IDAWrmsNorm
+ * Functions for rootfinding
+ * IDARcheck1
+ * IDARcheck2
+ * IDARcheck3
+ * IDARootfind
+ * IDA Error message handling functions
+ * IDAProcessError
+ * IDAErrHandler
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * =================================================================
+ * IMPORTED HEADER FILES
+ * =================================================================
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+
+#include "ida_impl.h"
+#include <sundials/sundials_math.h>
+
+/*
+ * =================================================================
+ * MACRO DEFINITIONS
+ * =================================================================
+ */
+
+/* Macro: loop */
+#define loop for(;;)
+
+/*
+ * =================================================================
+ * IDAS PRIVATE CONSTANTS
+ * =================================================================
+ */
+
+#define ZERO RCONST(0.0) /* real 0.0 */
+#define HALF RCONST(0.5) /* real 0.5 */
+#define QUARTER RCONST(0.25) /* real 0.25 */
+#define TWOTHIRDS RCONST(0.667) /* real 2/3 */
+#define ONE RCONST(1.0) /* real 1.0 */
+#define ONEPT5 RCONST(1.5) /* real 1.5 */
+#define TWO RCONST(2.0) /* real 2.0 */
+#define FOUR RCONST(4.0) /* real 4.0 */
+#define FIVE RCONST(5.0) /* real 5.0 */
+#define TEN RCONST(10.0) /* real 10.0 */
+#define TWELVE RCONST(12.0) /* real 12.0 */
+#define TWENTY RCONST(20.0) /* real 20.0 */
+#define HUNDRED RCONST(100.0) /* real 100.0 */
+#define PT9 RCONST(0.9) /* real 0.9 */
+#define PT99 RCONST(0.99) /* real 0.99 */
+#define PT1 RCONST(0.1) /* real 0.1 */
+#define PT01 RCONST(0.01) /* real 0.01 */
+#define PT001 RCONST(0.001) /* real 0.001 */
+#define PT0001 RCONST(0.0001) /* real 0.0001 */
+
+/*
+ * =================================================================
+ * IDAS ROUTINE-SPECIFIC CONSTANTS
+ * =================================================================
+ */
+
+/*
+ * Control constants for lower-level functions used by IDASolve
+ * ------------------------------------------------------------
+ */
+
+/* IDAStep control constants */
+
+#define PREDICT_AGAIN 20
+
+/* Return values for lower level routines used by IDASolve */
+
+#define IDA_RES_RECVR +1
+#define IDA_LSETUP_RECVR +2
+#define IDA_LSOLVE_RECVR +3
+
+#define IDA_NCONV_RECVR +4
+#define IDA_CONSTR_RECVR +5
+#define CONTINUE_STEPS +99
+
+/* IDACompleteStep constants */
+
+#define UNSET -1
+#define LOWER +1
+#define RAISE +2
+#define MAINTAIN +3
+
+/* IDATestError constants */
+
+#define ERROR_TEST_FAIL +7
+
+/*
+ * Control constants for lower-level rootfinding functions
+ * -------------------------------------------------------
+ */
+
+#define RTFOUND +1
+#define CLOSERT +3
+
+/*
+ * Control constants for tolerances
+ * --------------------------------
+ */
+
+#define IDA_NN 0
+#define IDA_SS 1
+#define IDA_SV 2
+#define IDA_WF 3
+
+/*
+ * Algorithmic constants
+ * ---------------------
+ */
+
+#define MXNCF 10 /* max number of convergence failures allowed */
+#define MXNEF 10 /* max number of error test failures allowed */
+#define MAXNH 5 /* max. number of h tries in IC calc. */
+#define MAXNJ 4 /* max. number of J tries in IC calc. */
+#define MAXNI 10 /* max. Newton iterations in IC calc. */
+#define EPCON RCONST(0.33) /* Newton convergence test constant */
+
+/* IDANewtonIter constants */
+
+#define MAXIT 4
+#define RATEMAX RCONST(0.9)
+#define XRATE RCONST(0.25)
+
+/*
+ * =================================================================
+ * PRIVATE FUNCTION PROTOTYPES
+ * =================================================================
+ */
+
+static booleantype IDACheckNvector(N_Vector tmpl);
+
+/* Memory allocation/deallocation */
+
+static booleantype IDAAllocVectors(IDAMem IDA_mem, N_Vector tmpl);
+static void IDAFreeVectors(IDAMem IDA_mem);
+
+/* Initial setup */
+
+int IDAInitialSetup(IDAMem IDA_mem);
+static int IDAEwtSetSS(IDAMem IDA_mem, N_Vector ycur, N_Vector weight);
+static int IDAEwtSetSV(IDAMem IDA_mem, N_Vector ycur, N_Vector weight);
+
+/* Main IDAStep function */
+
+static int IDAStep(IDAMem IDA_mem);
+
+/* Function called at beginning of step */
+
+static void IDASetCoeffs(IDAMem IDA_mem, realtype *ck);
+
+/* Nonlinear solver functions */
+
+static void IDAPredict(IDAMem IDA_mem);
+static int IDANls(IDAMem IDA_mem);
+static int IDANewtonIter(IDAMem IDA_mem);
+
+/* Error test */
+
+static int IDATestError(IDAMem IDA_mem, realtype ck,
+ realtype *err_k, realtype *err_km1);
+
+/* Handling of convergence and/or error test failures */
+
+static void IDARestore(IDAMem IDA_mem, realtype saved_t);
+static int IDAHandleNFlag(IDAMem IDA_mem, int nflag, realtype err_k, realtype err_km1,
+ long int *ncfnPtr, int *ncfPtr, long int *netfPtr, int *nefPtr);
+static void IDAReset(IDAMem IDA_mem);
+
+/* Function called after a successful step */
+
+static void IDACompleteStep(IDAMem IDA_mem, realtype err_k, realtype err_km1);
+
+/* Function called to evaluate the solutions y(t) and y'(t) at t */
+
+int IDAGetSolution(void *ida_mem, realtype t, N_Vector yret, N_Vector ypret);
+
+/* Stopping tests and failure handling */
+
+static int IDAStopTest1(IDAMem IDA_mem, realtype tout,realtype *tret,
+ N_Vector yret, N_Vector ypret, int itask);
+static int IDAStopTest2(IDAMem IDA_mem, realtype tout, realtype *tret,
+ N_Vector yret, N_Vector ypret, int itask);
+static int IDAHandleFailure(IDAMem IDA_mem, int sflag);
+
+/* Functions for rootfinding */
+
+static int IDARcheck1(IDAMem IDA_mem);
+static int IDARcheck2(IDAMem IDA_mem);
+static int IDARcheck3(IDAMem IDA_mem);
+static int IDARootfind(IDAMem IDA_mem);
+
+/* Norm functions */
+
+realtype IDAWrmsNorm(IDAMem IDA_mem, N_Vector x, N_Vector w, booleantype mask);
+
+/*
+ * =================================================================
+ * EXPORTED FUNCTIONS IMPLEMENTATION
+ * =================================================================
+ */
+
+/*
+ * -----------------------------------------------------------------
+ * Creation, allocation and re-initialization functions
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * IDACreate
+ *
+ * IDACreate creates an internal memory block for a problem to
+ * be solved by IDA.
+ * If successful, IDACreate returns a pointer to the problem memory.
+ * This pointer should be passed to IDAInit.
+ * If an initialization error occurs, IDACreate prints an error
+ * message to standard err and returns NULL.
+ */
+
+void *IDACreate(void)
+{
+ IDAMem IDA_mem;
+
+ IDA_mem = NULL;
+ IDA_mem = (IDAMem) malloc(sizeof(struct IDAMemRec));
+ if (IDA_mem == NULL) {
+ IDAProcessError(NULL, 0, "IDA", "IDACreate", MSG_MEM_FAIL);
+ return (NULL);
+ }
+
+ /* Zero out ida_mem */
+ memset(IDA_mem, 0, sizeof(struct IDAMemRec));
+
+ /* Set unit roundoff in IDA_mem */
+ IDA_mem->ida_uround = UNIT_ROUNDOFF;
+
+ /* Set default values for integrator optional inputs */
+ 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_efun = NULL;
+ IDA_mem->ida_edata = NULL;
+ IDA_mem->ida_ehfun = IDAErrHandler;
+ IDA_mem->ida_eh_data = IDA_mem;
+ IDA_mem->ida_errfp = stderr;
+ IDA_mem->ida_maxord = MAXORD_DEFAULT;
+ IDA_mem->ida_mxstep = MXSTEP_DEFAULT;
+ IDA_mem->ida_hmax_inv = HMAX_INV_DEFAULT;
+ IDA_mem->ida_hin = ZERO;
+ IDA_mem->ida_epcon = EPCON;
+ IDA_mem->ida_maxnef = MXNEF;
+ IDA_mem->ida_maxncf = MXNCF;
+ IDA_mem->ida_maxcor = MAXIT;
+ IDA_mem->ida_suppressalg = FALSE;
+ IDA_mem->ida_id = NULL;
+ IDA_mem->ida_constraints = NULL;
+ IDA_mem->ida_constraintsSet = FALSE;
+ IDA_mem->ida_tstopset = FALSE;
+
+ /* set the saved value maxord_alloc */
+ IDA_mem->ida_maxord_alloc = MAXORD_DEFAULT;
+
+ /* Set default values for IC optional inputs */
+ IDA_mem->ida_epiccon = PT01 * EPCON;
+ IDA_mem->ida_maxnh = MAXNH;
+ IDA_mem->ida_maxnj = MAXNJ;
+ IDA_mem->ida_maxnit = MAXNI;
+ IDA_mem->ida_lsoff = FALSE;
+ IDA_mem->ida_steptol = RPowerR(IDA_mem->ida_uround, TWOTHIRDS);
+
+ /* Initialize lrw and liw */
+ IDA_mem->ida_lrw = 25 + 5*MXORDP1;
+ 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;
+
+ /* Return pointer to IDA memory block */
+ return((void *)IDA_mem);
+}
+
+/*-----------------------------------------------------------------*/
+
+#define lrw (IDA_mem->ida_lrw)
+#define liw (IDA_mem->ida_liw)
+
+/*-----------------------------------------------------------------*/
+
+/*
+ * IDAInit
+ *
+ * IDAInit allocates and initializes memory for a problem. All
+ * problem specification inputs are checked for errors. If any
+ * error occurs during initialization, it is reported to the
+ * error handler function.
+ */
+
+int IDAInit(void *ida_mem, IDAResFn res,
+ realtype t0, N_Vector yy0, N_Vector yp0)
+{
+ IDAMem IDA_mem;
+ booleantype nvectorOK, allocOK;
+ long int lrw1, liw1;
+
+ /* Check ida_mem */
+
+ if (ida_mem == NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDAInit", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+ IDA_mem = (IDAMem) ida_mem;
+
+ /* Check for legal input parameters */
+
+ if (yy0 == NULL) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDAInit", MSG_Y0_NULL);
+ return(IDA_ILL_INPUT);
+ }
+
+ if (yp0 == NULL) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDAInit", MSG_YP0_NULL);
+ return(IDA_ILL_INPUT);
+ }
+
+ if (res == NULL) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDAInit", MSG_RES_NULL);
+ return(IDA_ILL_INPUT);
+ }
+
+ /* Test if all required vector operations are implemented */
+
+ nvectorOK = IDACheckNvector(yy0);
+ if (!nvectorOK) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDAInit", MSG_BAD_NVECTOR);
+ return(IDA_ILL_INPUT);
+ }
+
+ /* Set space requirements for one N_Vector */
+
+ if (yy0->ops->nvspace != NULL) {
+ N_VSpace(yy0, &lrw1, &liw1);
+ } else {
+ lrw1 = 0;
+ liw1 = 0;
+ }
+ IDA_mem->ida_lrw1 = lrw1;
+ IDA_mem->ida_liw1 = liw1;
+
+ /* Allocate the vectors (using yy0 as a template) */
+
+ allocOK = IDAAllocVectors(IDA_mem, yy0);
+ if (!allocOK) {
+ IDAProcessError(IDA_mem, IDA_MEM_FAIL, "IDA", "IDAInit", MSG_MEM_FAIL);
+ return(IDA_MEM_FAIL);
+ }
+
+ /* All error checking is complete at this point */
+
+ /* Copy the input parameters into IDA memory block */
+
+ IDA_mem->ida_res = res;
+ IDA_mem->ida_tn = t0;
+
+ /* Set the linear solver addresses to NULL */
+
+ IDA_mem->ida_linit = NULL;
+ IDA_mem->ida_lsetup = NULL;
+ IDA_mem->ida_lsolve = NULL;
+ IDA_mem->ida_lperf = NULL;
+ IDA_mem->ida_lfree = NULL;
+ IDA_mem->ida_lmem = NULL;
+
+ /* Initialize the phi array */
+
+ N_VScale(ONE, yy0, IDA_mem->ida_phi[0]);
+ N_VScale(ONE, yp0, IDA_mem->ida_phi[1]);
+
+ /* Initialize all the counters and other optional output values */
+
+ IDA_mem->ida_nst = 0;
+ IDA_mem->ida_nre = 0;
+ IDA_mem->ida_ncfn = 0;
+ IDA_mem->ida_netf = 0;
+ IDA_mem->ida_nni = 0;
+ IDA_mem->ida_nsetups = 0;
+
+ IDA_mem->ida_kused = 0;
+ IDA_mem->ida_hused = ZERO;
+ IDA_mem->ida_tolsf = ONE;
+
+ IDA_mem->ida_nge = 0;
+
+ IDA_mem->ida_irfnd = 0;
+
+ /* Initialize root-finding variables */
+
+ IDA_mem->ida_glo = NULL;
+ IDA_mem->ida_ghi = NULL;
+ IDA_mem->ida_grout = NULL;
+ IDA_mem->ida_iroots = NULL;
+ IDA_mem->ida_rootdir = NULL;
+ IDA_mem->ida_gfun = NULL;
+ IDA_mem->ida_nrtfn = 0;
+ IDA_mem->ida_gactive = NULL;
+ IDA_mem->ida_mxgnull = 1;
+
+ /* Initial setup not done yet */
+
+ IDA_mem->ida_SetupDone = FALSE;
+
+ /* Problem memory has been successfully allocated */
+
+ IDA_mem->ida_MallocDone = TRUE;
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+#define lrw1 (IDA_mem->ida_lrw1)
+#define liw1 (IDA_mem->ida_liw1)
+
+/*-----------------------------------------------------------------*/
+
+/*
+ * IDAReInit
+ *
+ * IDAReInit re-initializes IDA's memory for a problem, assuming
+ * it has already beeen allocated in a prior IDAInit call.
+ * All problem specification inputs are checked for errors.
+ * The problem size Neq is assumed to be unchaged since the call
+ * to IDAInit, and the maximum order maxord must not be larger.
+ * If any error occurs during reinitialization, it is reported to
+ * the error handler function.
+ * The return value is IDA_SUCCESS = 0 if no errors occurred, or
+ * a negative value otherwise.
+ */
+
+int IDAReInit(void *ida_mem,
+ realtype t0, N_Vector yy0, N_Vector yp0)
+{
+ IDAMem IDA_mem;
+
+ /* Check for legal input parameters */
+
+ if (ida_mem == NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDAReInit", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+ IDA_mem = (IDAMem) ida_mem;
+
+ /* Check if problem was malloc'ed */
+
+ if (IDA_mem->ida_MallocDone == FALSE) {
+ IDAProcessError(IDA_mem, IDA_NO_MALLOC, "IDA", "IDAReInit", MSG_NO_MALLOC);
+ return(IDA_NO_MALLOC);
+ }
+
+ /* Check for legal input parameters */
+
+ if (yy0 == NULL) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDAReInit", MSG_Y0_NULL);
+ return(IDA_ILL_INPUT);
+ }
+
+ if (yp0 == NULL) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDAReInit", MSG_YP0_NULL);
+ return(IDA_ILL_INPUT);
+ }
+
+ /* Copy the input parameters into IDA memory block */
+
+ IDA_mem->ida_tn = t0;
+
+ /* Initialize the phi array */
+
+ N_VScale(ONE, yy0, IDA_mem->ida_phi[0]);
+ N_VScale(ONE, yp0, IDA_mem->ida_phi[1]);
+
+ /* Initialize all the counters and other optional output values */
+
+ IDA_mem->ida_nst = 0;
+ IDA_mem->ida_nre = 0;
+ IDA_mem->ida_ncfn = 0;
+ IDA_mem->ida_netf = 0;
+ IDA_mem->ida_nni = 0;
+ IDA_mem->ida_nsetups = 0;
+
+ IDA_mem->ida_kused = 0;
+ IDA_mem->ida_hused = ZERO;
+ IDA_mem->ida_tolsf = ONE;
+
+ IDA_mem->ida_nge = 0;
+
+ IDA_mem->ida_irfnd = 0;
+
+ /* Initial setup not done yet */
+
+ IDA_mem->ida_SetupDone = FALSE;
+
+ /* Problem has been successfully re-initialized */
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+/*
+ * IDASStolerances
+ * IDASVtolerances
+ * IDAWFtolerances
+ *
+ * These functions specify the integration tolerances. One of them
+ * MUST be called before the first call to IDA.
+ *
+ * IDASStolerances specifies scalar relative and absolute tolerances.
+ * IDASVtolerances specifies scalar relative tolerance and a vector
+ * absolute tolerance (a potentially different absolute tolerance
+ * for each vector component).
+ * IDAWFtolerances specifies a user-provides function (of type IDAEwtFn)
+ * which will be called to set the error weight vector.
+ */
+
+int IDASStolerances(void *ida_mem, realtype reltol, realtype abstol)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDASStolerances", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+ IDA_mem = (IDAMem) ida_mem;
+
+ if (IDA_mem->ida_MallocDone == FALSE) {
+ IDAProcessError(IDA_mem, IDA_NO_MALLOC, "IDA", "IDASStolerances", MSG_NO_MALLOC);
+ return(IDA_NO_MALLOC);
+ }
+
+ /* Check inputs */
+
+ if (reltol < ZERO) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASStolerances", MSG_BAD_RTOL);
+ return(IDA_ILL_INPUT);
+ }
+
+ if (abstol < ZERO) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASStolerances", MSG_BAD_ATOL);
+ return(IDA_ILL_INPUT);
+ }
+
+ /* Copy tolerances into memory */
+
+ IDA_mem->ida_rtol = reltol;
+ IDA_mem->ida_Satol = abstol;
+
+ IDA_mem->ida_itol = IDA_SS;
+
+ IDA_mem->ida_user_efun = FALSE;
+ IDA_mem->ida_efun = IDAEwtSet;
+ IDA_mem->ida_edata = NULL; /* will be set to ida_mem in InitialSetup; */
+
+ return(IDA_SUCCESS);
+}
+
+
+int IDASVtolerances(void *ida_mem, realtype reltol, N_Vector abstol)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDASVtolerances", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+ IDA_mem = (IDAMem) ida_mem;
+
+ if (IDA_mem->ida_MallocDone == FALSE) {
+ IDAProcessError(IDA_mem, IDA_NO_MALLOC, "IDA", "IDASVtolerances", MSG_NO_MALLOC);
+ return(IDA_NO_MALLOC);
+ }
+
+ /* Check inputs */
+
+ if (reltol < ZERO) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASVtolerances", MSG_BAD_RTOL);
+ return(IDA_ILL_INPUT);
+ }
+
+ if (N_VMin(abstol) < ZERO) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASVtolerances", MSG_BAD_ATOL);
+ return(IDA_ILL_INPUT);
+ }
+
+ /* Copy tolerances into memory */
+
+ 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_rtol = reltol;
+ N_VScale(ONE, abstol, IDA_mem->ida_Vatol);
+
+ IDA_mem->ida_itol = IDA_SV;
+
+ IDA_mem->ida_user_efun = FALSE;
+ IDA_mem->ida_efun = IDAEwtSet;
+ IDA_mem->ida_edata = NULL; /* will be set to ida_mem in InitialSetup; */
+
+ return(IDA_SUCCESS);
+}
+
+
+int IDAWFtolerances(void *ida_mem, IDAEwtFn efun)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDAWFtolerances", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+ IDA_mem = (IDAMem) ida_mem;
+
+ if (IDA_mem->ida_MallocDone == FALSE) {
+ 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_efun = efun;
+ IDA_mem->ida_edata = NULL; /* will be set to user_data in InitialSetup */
+
+ 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
+ *
+ * IDARootInit initializes a rootfinding problem to be solved
+ * during the integration of the DAE system. It loads the root
+ * function pointer and the number of root functions, and allocates
+ * workspace memory. The return value is IDA_SUCCESS = 0 if no
+ * errors occurred, or a negative value otherwise.
+ */
+
+int IDARootInit(void *ida_mem, int nrtfn, IDARootFn g)
+{
+ IDAMem IDA_mem;
+ int i, nrt;
+
+ /* Check ida_mem pointer */
+ if (ida_mem == NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDARootInit", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+ IDA_mem = (IDAMem) ida_mem;
+
+ nrt = (nrtfn < 0) ? 0 : nrtfn;
+
+ /* If rerunning IDARootInit() with a different number of root
+ functions (changing number of gfun components), then free
+ 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;
+
+ lrw -= 3 * (IDA_mem->ida_nrtfn);
+ liw -= 3 * (IDA_mem->ida_nrtfn);
+
+ }
+
+ /* If IDARootInit() was called with nrtfn == 0, then set ida_nrtfn to
+ zero and ida_gfun to NULL before returning */
+ if (nrt == 0) {
+ IDA_mem->ida_nrtfn = nrt;
+ gfun = NULL;
+ return(IDA_SUCCESS);
+ }
+
+ /* If rerunning IDARootInit() with the same number of root functions
+ (not changing number of gfun components), then check if the root
+ function argument has changed */
+ /* If g != NULL then return as currently reserved memory resources
+ will suffice */
+ if (nrt == IDA_mem->ida_nrtfn) {
+ if (g != 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;
+
+ lrw -= 3*nrt;
+ liw -= 3*nrt;
+
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDARootInit", MSG_ROOT_FUNC_NULL);
+ return(IDA_ILL_INPUT);
+ }
+ else {
+ gfun = g;
+ return(IDA_SUCCESS);
+ }
+ }
+ else return(IDA_SUCCESS);
+ }
+
+ /* Set variable values in IDA memory block */
+ IDA_mem->ida_nrtfn = nrt;
+ if (g == NULL) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDARootInit", MSG_ROOT_FUNC_NULL);
+ return(IDA_ILL_INPUT);
+ }
+ else gfun = g;
+
+ /* Allocate necessary memory and return */
+ glo = NULL;
+ glo = (realtype *) malloc(nrt*sizeof(realtype));
+ if (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;
+ 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;
+ 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;
+ 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;
+ 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;
+ 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;
+
+ /* Set default values for gactive (all active) */
+ for(i=0; i<nrt; i++) gactive[i] = TRUE;
+
+ lrw += 3*nrt;
+ 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
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * IDASolve
+ *
+ * This routine is the main driver of the IDA package.
+ *
+ * It integrates over an independent variable interval defined by the user,
+ * by calling IDAStep to take internal independent variable steps.
+ *
+ * The first time that IDASolve is called for a successfully initialized
+ * problem, it computes a tentative initial step size.
+ *
+ * IDASolve supports two modes, specified by itask:
+ * In the IDA_NORMAL mode, the solver steps until it passes tout and then
+ * interpolates to obtain y(tout) and yp(tout).
+ * In the IDA_ONE_STEP mode, it takes one internal step and returns.
+ *
+ * IDASolve returns integer values corresponding to success and failure as below:
+ *
+ * successful returns:
+ *
+ * IDA_SUCCESS
+ * IDA_TSTOP_RETURN
+ *
+ * failed returns:
+ *
+ * IDA_ILL_INPUT
+ * IDA_TOO_MUCH_WORK
+ * IDA_MEM_NULL
+ * IDA_TOO_MUCH_ACC
+ * IDA_CONV_FAIL
+ * IDA_LSETUP_FAIL
+ * IDA_LSOLVE_FAIL
+ * IDA_CONSTR_FAIL
+ * IDA_ERR_FAIL
+ * IDA_REP_RES_ERR
+ * IDA_RES_FAIL
+ */
+
+int IDASolve(void *ida_mem, realtype tout, realtype *tret,
+ N_Vector yret, N_Vector ypret, int itask)
+{
+ long int nstloc;
+ int sflag, istate, ier, irfndp, ir;
+ realtype tdist, troundoff, ypnorm, rh, nrm;
+ IDAMem IDA_mem;
+ booleantype inactive_roots;
+
+ /* Check for legal inputs in all cases. */
+
+ if (ida_mem == NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDASolve", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+ IDA_mem = (IDAMem) ida_mem;
+
+ /* Check if problem was malloc'ed */
+
+ if (IDA_mem->ida_MallocDone == FALSE) {
+ IDAProcessError(IDA_mem, IDA_NO_MALLOC, "IDA", "IDASolve", MSG_NO_MALLOC);
+ return(IDA_NO_MALLOC);
+ }
+
+ /* Check for legal arguments */
+
+ if (yret == NULL) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASolve", MSG_YRET_NULL);
+ return(IDA_ILL_INPUT);
+ }
+ yy = yret;
+
+ if (ypret == NULL) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASolve", MSG_YPRET_NULL);
+ return(IDA_ILL_INPUT);
+ }
+ yp = ypret;
+
+ if (tret == NULL) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASolve", MSG_TRET_NULL);
+ return(IDA_ILL_INPUT);
+ }
+
+ if ((itask != IDA_NORMAL) && (itask != IDA_ONE_STEP)) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASolve", MSG_BAD_ITASK);
+ return(IDA_ILL_INPUT);
+ }
+
+ if (itask == IDA_NORMAL) toutc = tout;
+ taskc = itask;
+
+ if (nst == 0) { /* This is the first call */
+
+ /* Check inputs to IDA for correctness and consistency */
+
+ if (IDA_mem->ida_SetupDone == FALSE) {
+ ier = IDAInitialSetup(IDA_mem);
+ if (ier != IDA_SUCCESS) return(IDA_ILL_INPUT);
+ IDA_mem->ida_SetupDone = TRUE;
+ }
+
+ /* 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 = ABS(tout - tn);
+ if (tdist == ZERO) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASolve", MSG_TOO_CLOSE);
+ return(IDA_ILL_INPUT);
+ }
+ troundoff = TWO*uround*(ABS(tn) + ABS(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) ) {
+ 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;
+ }
+
+ rh = ABS(hh)*hmax_inv;
+ if (rh > ONE) hh /= rh;
+
+ if (tstopset) {
+ if ( (tstop - tn)*hh < ZERO) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASolve", MSG_BAD_TSTOP, tstop, tn);
+ return(IDA_ILL_INPUT);
+ }
+ if ( (tn + hh - tstop)*hh > ZERO)
+ hh = (tstop - tn)*(ONE-FOUR*uround);
+ }
+
+ h0u = hh;
+ kk = 0; 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) {
+ ier = IDARcheck1(IDA_mem);
+ if (ier == IDA_RTFUNC_FAIL) {
+ IDAProcessError(IDA_mem, IDA_RTFUNC_FAIL, "IDA", "IDARcheck1", MSG_RTFUNC_FAILED, tn);
+ return(IDA_RTFUNC_FAIL);
+ }
+ }
+
+ N_VScale(hh, phi[1], phi[1]); /* set phi[1] = hh*y' */
+
+ /* Set the convergence test constants epsNewt and toldel */
+ epsNewt = epcon;
+ toldel = PT0001 * epsNewt;
+
+ } /* end of first-call block. */
+
+ /* Call lperf function and set nstloc for later performance testing. */
+
+ if (lperf != NULL) lperf(IDA_mem, 0);
+ nstloc = 0;
+
+ /* If not the first call, perform all stopping tests. */
+
+ if (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) {
+
+ irfndp = irfnd;
+
+ ier = IDARcheck2(IDA_mem);
+
+ if (ier == CLOSERT) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDARcheck2", MSG_CLOSE_ROOTS, tlo);
+ return(IDA_ILL_INPUT);
+ } else if (ier == IDA_RTFUNC_FAIL) {
+ IDAProcessError(IDA_mem, IDA_RTFUNC_FAIL, "IDA", "IDARcheck2", MSG_RTFUNC_FAILED, tlo);
+ return(IDA_RTFUNC_FAIL);
+ } else if (ier == RTFOUND) {
+ tretlast = *tret = tlo;
+ return(IDA_ROOT_RETURN);
+ }
+
+ /* If tn is distinct from tretlast (within roundoff),
+ check remaining interval for roots */
+ troundoff = HUNDRED*uround*(ABS(tn) + ABS(hh));
+ if ( ABS(tn - tretlast) > troundoff ) {
+ ier = IDARcheck3(IDA_mem);
+ if (ier == IDA_SUCCESS) { /* no root found */
+ irfnd = 0;
+ if ((irfndp == 1) && (itask == IDA_ONE_STEP)) {
+ tretlast = *tret = tn;
+ ier = IDAGetSolution(IDA_mem, tn, yret, ypret);
+ return(IDA_SUCCESS);
+ }
+ } else if (ier == RTFOUND) { /* a new root was found */
+ irfnd = 1;
+ tretlast = *tret = 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);
+ return(IDA_RTFUNC_FAIL);
+ }
+ }
+
+ } /* end of root stop check */
+
+
+ /* Now test for all other stop conditions. */
+
+ istate = IDAStopTest1(IDA_mem, tout, tret, yret, ypret, itask);
+ if (istate != CONTINUE_STEPS) return(istate);
+ }
+
+ /* Looping point for internal steps. */
+
+ loop {
+
+ /* Check for too many steps taken. */
+
+ if ( (mxstep>0) && (nstloc >= mxstep) ) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASolve", MSG_MAX_STEPS, tn);
+ istate = IDA_TOO_MUCH_WORK;
+ *tret = tretlast = 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);
+
+ /* Reset and check ewt (if not first call). */
+
+ if (nst > 0) {
+
+ ier = efun(phi[0], ewt, edata);
+
+ if (ier != 0) {
+
+ if (itol == IDA_WF)
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASolve", MSG_EWT_NOW_FAIL, tn);
+ else
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASolve", MSG_EWT_NOW_BAD, tn);
+
+ istate = IDA_ILL_INPUT;
+ ier = IDAGetSolution(IDA_mem, tn, yret, ypret);
+ *tret = tretlast = tn;
+ break;
+
+ }
+
+ }
+
+ /* 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);
+ istate = IDA_TOO_MUCH_ACC;
+ *tret = tretlast = tn;
+ if (nst > 0) ier = IDAGetSolution(IDA_mem, tn, yret, ypret);
+ break;
+ }
+
+ /* Call IDAStep to take a step. */
+
+ sflag = IDAStep(IDA_mem);
+
+ /* Process all failed-step cases, and exit loop. */
+
+ if (sflag != IDA_SUCCESS) {
+ istate = IDAHandleFailure(IDA_mem, sflag);
+ *tret = tretlast = tn;
+ ier = IDAGetSolution(IDA_mem, tn, yret, ypret);
+ break;
+ }
+
+ nstloc++;
+
+ /* After successful step, check for stop conditions; continue or break. */
+
+ /* First check for root in the last step taken. */
+
+ if (nrtfn > 0) {
+
+ ier = IDARcheck3(IDA_mem);
+
+ if (ier == RTFOUND) { /* A new root was found */
+ irfnd = 1;
+ istate = IDA_ROOT_RETURN;
+ tretlast = *tret = tlo;
+ break;
+ } else if (ier == IDA_RTFUNC_FAIL) { /* g failed */
+ IDAProcessError(IDA_mem, IDA_RTFUNC_FAIL, "IDA", "IDARcheck3", MSG_RTFUNC_FAILED, tlo);
+ istate = IDA_RTFUNC_FAIL;
+ break;
+ }
+
+ /* If we are at the end of the first step and we still have
+ * some event functions that are inactive, issue a warning
+ * 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;
+ break;
+ }
+ }
+ if ((IDA_mem->ida_mxgnull > 0) && inactive_roots) {
+ IDAProcessError(IDA_mem, IDA_WARNING, "IDA", "IDASolve", MSG_INACTIVE_ROOTS);
+ }
+ }
+
+ }
+
+ /* Now check all other stop conditions. */
+
+ istate = IDAStopTest2(IDA_mem, tout, tret, yret, ypret, itask);
+ if (istate != CONTINUE_STEPS) break;
+
+ } /* End of step loop */
+
+ return(istate);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Interpolated output
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * IDAGetDky
+ *
+ * This routine evaluates the k-th derivative of y(t) as the value of
+ * the k-th derivative of the interpolating polynomial at the independent
+ * variable t, and stores the results in the vector dky. It uses the current
+ * independent variable value, tn, and the method order last used, kused.
+ *
+ * The return values are:
+ * IDA_SUCCESS if t is legal, or
+ * IDA_BAD_T if t is not within the interval of the last step taken.
+ * IDA_BAD_DKY if the dky vector is NULL.
+ * IDA_BAD_K if the requested k is not in the range 0,1,...,order used
+ *
+ */
+
+int IDAGetDky(void *ida_mem, realtype t, int k, N_Vector dky)
+{
+ IDAMem IDA_mem;
+ realtype tfuzz, tp, delt, psij_1;
+ int i, j;
+ realtype cjk [MXORDP1];
+ realtype cjk_1[MXORDP1];
+
+ /* Check ida_mem */
+ if (ida_mem == NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDAGetDky", MSG_NO_MEM);
+ return (IDA_MEM_NULL);
+ }
+ IDA_mem = (IDAMem) ida_mem;
+
+ if (dky == NULL) {
+ IDAProcessError(IDA_mem, IDA_BAD_DKY, "IDA", "IDAGetDky", MSG_NULL_DKY);
+ return(IDA_BAD_DKY);
+ }
+
+ if ((k < 0) || (k > 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 * (ABS(tn) + ABS(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);
+ return(IDA_BAD_T);
+ }
+
+ /* Initialize the c_j^(k) and c_k^(k-1) */
+ for(i=0; i<MXORDP1; i++) {
+ cjk [i] = 0;
+ cjk_1[i] = 0;
+ }
+
+ delt = t-tn;
+
+ for(i=0; i<=k; i++) {
+
+ /* The below reccurence is used to compute the k-th derivative of the solution:
+ c_j^(k) = ( k * c_{j-1}^(k-1) + c_{j-1}^{k} (Delta+psi_{j-1}) ) / psi_j
+
+ Translated in indexes notation:
+ cjk[j] = ( k*cjk_1[j-1] + cjk[j-1]*(delt+psi[j-2]) ) / psi[j-1]
+
+ For k=0, j=1: c_1 = c_0^(-1) + (delt+psi[-1]) / psi[0]
+
+ In order to be able to deal with k=0 in the same way as for k>0, the
+ following conventions were adopted:
+ - c_0(t) = 1 , c_0^(-1)(t)=0
+ - psij_1 stands for psi[-1]=0 when j=1
+ for psi[j-2] when j>1
+ */
+ if(i==0) {
+
+ cjk[i] = 1;
+ psij_1 = 0;
+ }else {
+ /* i i-1 1
+ 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];
+ }
+
+ /* update c_j^(i) */
+
+ /*j does not need to go till kused */
+ 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];
+ }
+
+ /* save existing c_j^(i)'s */
+ for(j=i+1; j<=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++)
+ {
+ N_VLinearSum(ONE, dky, cjk[j], phi[j], dky);
+ }
+
+ return(IDA_SUCCESS);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Deallocation function
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * IDAFree
+ *
+ * This routine frees the problem memory allocated by IDAInit
+ * Such memory includes all the vectors allocated by IDAAllocVectors,
+ * and the memory lmem for the linear solver (deallocated by a call
+ * to lfree).
+ */
+
+void IDAFree(void **ida_mem)
+{
+ IDAMem IDA_mem;
+
+ if (*ida_mem == NULL) return;
+
+ IDA_mem = (IDAMem) (*ida_mem);
+
+ IDAFreeVectors(IDA_mem);
+
+ if (lfree != NULL) 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;
+ }
+
+ free(*ida_mem);
+ *ida_mem = NULL;
+}
+
+/*
+ * =================================================================
+ * PRIVATE FUNCTIONS
+ * =================================================================
+ */
+
+/*
+ * IDACheckNvector
+ *
+ * This routine checks if all required vector operations are present.
+ * If any of them is missing it returns FALSE.
+ */
+
+static booleantype IDACheckNvector(N_Vector tmpl)
+{
+ if ((tmpl->ops->nvclone == NULL) ||
+ (tmpl->ops->nvdestroy == NULL) ||
+ (tmpl->ops->nvlinearsum == NULL) ||
+ (tmpl->ops->nvconst == NULL) ||
+ (tmpl->ops->nvprod == NULL) ||
+ (tmpl->ops->nvscale == NULL) ||
+ (tmpl->ops->nvabs == NULL) ||
+ (tmpl->ops->nvinv == NULL) ||
+ (tmpl->ops->nvaddconst == NULL) ||
+ (tmpl->ops->nvwrmsnorm == NULL) ||
+ (tmpl->ops->nvmin == NULL))
+ return(FALSE);
+ else
+ return(TRUE);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Memory allocation/deallocation
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * IDAAllocVectors
+ *
+ * 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.
+ * This routine also sets the optional outputs lrw and liw, which are
+ * (respectively) the lengths of the real and integer work spaces
+ * allocated here.
+ */
+
+static booleantype IDAAllocVectors(IDAMem IDA_mem, N_Vector tmpl)
+{
+ int i, j, maxcol;
+
+ /* Allocate ewt, ee, delta, tempv1, tempv2 */
+
+ ewt = N_VClone(tmpl);
+ if (ewt == NULL) return(FALSE);
+
+ ee = N_VClone(tmpl);
+ if (ee == NULL) {
+ N_VDestroy(ewt);
+ return(FALSE);
+ }
+
+ delta = N_VClone(tmpl);
+ if (delta == NULL) {
+ N_VDestroy(ewt);
+ N_VDestroy(ee);
+ return(FALSE);
+ }
+
+ tempv1 = N_VClone(tmpl);
+ if (tempv1 == NULL) {
+ N_VDestroy(ewt);
+ N_VDestroy(ee);
+ N_VDestroy(delta);
+ return(FALSE);
+ }
+
+ tempv2= N_VClone(tmpl);
+ if (tempv2 == NULL) {
+ N_VDestroy(ewt);
+ N_VDestroy(ee);
+ N_VDestroy(delta);
+ N_VDestroy(tempv1);
+ return(FALSE);
+ }
+
+ savres = tempv1;
+
+ /* Allocate phi[0] ... phi[maxord]. Make sure phi[2] and phi[3] are
+ allocated (for use as temporary vectors), regardless of maxord. */
+
+ maxcol = MAX(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);
+ }
+ }
+
+ /* Update solver workspace lengths */
+ lrw += (maxcol + 6)*lrw1;
+ liw += (maxcol + 6)*liw1;
+
+ /* Store the value of maxord used here */
+ IDA_mem->ida_maxord_alloc = maxord;
+
+ return(TRUE);
+}
+
+/*
+ * IDAfreeVectors
+ *
+ * This routine frees the IDA vectors allocated for IDA.
+ */
+
+static void IDAFreeVectors(IDAMem IDA_mem)
+{
+ int j, maxcol;
+
+ N_VDestroy(ewt);
+ N_VDestroy(ee);
+ N_VDestroy(delta);
+ N_VDestroy(tempv1);
+ N_VDestroy(tempv2);
+ maxcol = MAX(IDA_mem->ida_maxord_alloc,3);
+ for(j=0; j <= maxcol; j++) N_VDestroy(phi[j]);
+
+ lrw -= (maxcol + 6)*lrw1;
+ liw -= (maxcol + 6)*liw1;
+
+ if (IDA_mem->ida_VatolMallocDone) {
+ N_VDestroy(Vatol);
+ lrw -= lrw1;
+ liw -= liw1;
+ }
+
+ if (IDA_mem->ida_constraintsMallocDone) {
+ N_VDestroy(constraints);
+ lrw -= lrw1;
+ liw -= liw1;
+ }
+
+ if (IDA_mem->ida_idMallocDone) {
+ N_VDestroy(id);
+ lrw -= lrw1;
+ liw -= liw1;
+ }
+
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Initial setup
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * IDAInitialSetup
+ *
+ * This routine is called by IDASolve once at the first step.
+ * It performs all checks on optional inputs and inputs to
+ * IDAInit/IDAReInit that could not be done before.
+ *
+ * If no merror is encountered, IDAInitialSetup returns IDA_SUCCESS.
+ * Otherwise, it returns an error flag and reported to the error
+ * handler function.
+ */
+
+int IDAInitialSetup(IDAMem IDA_mem)
+{
+ booleantype conOK;
+ int ier;
+
+ /* Test for more vector operations, depending on options */
+ if (suppressalg)
+ if (id->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)){
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDAInitialSetup", MSG_MISSING_ID);
+ return(IDA_ILL_INPUT);
+ }
+
+ /* Did the user specify tolerances? */
+ if (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;
+
+ /* Initial error weight vector */
+ ier = efun(phi[0], ewt, edata);
+ if (ier != 0) {
+ if (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);
+ return(IDA_ILL_INPUT);
+ }
+
+ /* Check to see if y0 satisfies constraints. */
+ if (constraintsSet) {
+ conOK = N_VConstrMask(constraints, phi[0], tempv2);
+ if (!conOK) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDAInitialSetup", MSG_Y0_FAIL_CONSTR);
+ return(IDA_ILL_INPUT);
+ }
+ }
+
+ /* Check that lsolve exists and call linit function if it exists. */
+ if (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 (ier != 0) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDAInitialSetup", MSG_LINIT_FAIL);
+ return(IDA_LINIT_FAIL);
+ }
+ }
+
+ return(IDA_SUCCESS);
+}
+
+/*
+ * IDAEwtSet
+ *
+ * This routine is responsible for loading the error weight vector
+ * ewt, according to itol, as follows:
+ * (1) ewt[i] = 1 / (rtol * ABS(ycur[i]) + atol), i=0,...,Neq-1
+ * if itol = IDA_SS
+ * (2) ewt[i] = 1 / (rtol * ABS(ycur[i]) + atol[i]), i=0,...,Neq-1
+ * if itol = IDA_SV
+ *
+ * IDAEwtSet returns 0 if ewt is successfully set as above to a
+ * positive vector and -1 otherwise. In the latter case, ewt is
+ * considered undefined.
+ *
+ * All the real work is done in the routines IDAEwtSetSS, IDAEwtSetSV.
+ */
+
+int IDAEwtSet(N_Vector ycur, N_Vector weight, void *data)
+{
+ IDAMem IDA_mem;
+ int flag = 0;
+
+ /* data points to IDA_mem here */
+
+ IDA_mem = (IDAMem) data;
+
+ switch(itol) {
+ case IDA_SS:
+ flag = IDAEwtSetSS(IDA_mem, ycur, weight);
+ break;
+ case IDA_SV:
+ flag = IDAEwtSetSV(IDA_mem, ycur, weight);
+ break;
+ }
+ return(flag);
+}
+
+/*
+ * IDAEwtSetSS
+ *
+ * This routine sets ewt as decribed above in the case itol=IDA_SS.
+ * It tests for non-positive components before inverting. IDAEwtSetSS
+ * returns 0 if ewt is successfully set to a positive vector
+ * and -1 otherwise. In the latter case, ewt is considered
+ * undefined.
+ */
+
+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);
+ return(0);
+}
+
+/*
+ * IDAEwtSetSV
+ *
+ * This routine sets ewt as decribed above in the case itol=IDA_SV.
+ * It tests for non-positive components before inverting. IDAEwtSetSV
+ * returns 0 if ewt is successfully set to a positive vector
+ * and -1 otherwise. In the latter case, ewt is considered
+ * undefined.
+ */
+
+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);
+ return(0);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Stopping tests
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * IDAStopTest1
+ *
+ * This routine tests for stop conditions before taking a step.
+ * The tests depend on the value of itask.
+ * The variable tretlast is the previously returned value of tret.
+ *
+ * The return values are:
+ * 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 tstop cases, this routine may adjust the stepsize hh to cause
+ * the next step to reach tstop exactly.
+ */
+
+static int IDAStopTest1(IDAMem IDA_mem, realtype tout, realtype *tret,
+ N_Vector yret, N_Vector ypret, int itask)
+{
+ int ier;
+ realtype troundoff;
+
+ switch (itask) {
+
+ case IDA_NORMAL:
+
+ if (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);
+ return(IDA_ILL_INPUT);
+ }
+ }
+
+ /* Test for tout = tretlast, and for tn past tout. */
+ if (tout == tretlast) {
+ *tret = tretlast = tout;
+ return(IDA_SUCCESS);
+ }
+ if ((tn - tout)*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;
+ return(IDA_SUCCESS);
+ }
+
+ if (tstopset) {
+ troundoff = HUNDRED*uround*(ABS(tn) + ABS(hh));
+ if (ABS(tn - tstop) <= troundoff) {
+ ier = IDAGetSolution(IDA_mem, tstop, yret, ypret);
+ if (ier != IDA_SUCCESS) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASolve", MSG_BAD_TSTOP, tstop, tn);
+ return(IDA_ILL_INPUT);
+ }
+ *tret = tretlast = tstop;
+ tstopset = FALSE;
+ return(IDA_TSTOP_RETURN);
+ }
+ if ((tn + hh - tstop)*hh > ZERO)
+ hh = (tstop - tn)*(ONE-FOUR*uround);
+ }
+
+ return(CONTINUE_STEPS);
+
+ case IDA_ONE_STEP:
+
+ if (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);
+ return(IDA_ILL_INPUT);
+ }
+ }
+
+ /* Test for tn past tretlast. */
+ if ((tn - tretlast)*hh > ZERO) {
+ ier = IDAGetSolution(IDA_mem, tn, yret, ypret);
+ *tret = tretlast = tn;
+ return(IDA_SUCCESS);
+ }
+
+ if (tstopset) {
+ troundoff = HUNDRED*uround*(ABS(tn) + ABS(hh));
+ if (ABS(tn - tstop) <= troundoff) {
+ ier = IDAGetSolution(IDA_mem, tstop, yret, ypret);
+ if (ier != IDA_SUCCESS) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASolve", MSG_BAD_TSTOP, tstop, tn);
+ return(IDA_ILL_INPUT);
+ }
+ *tret = tretlast = tstop;
+ tstopset = FALSE;
+ return(IDA_TSTOP_RETURN);
+ }
+ if ((tn + hh - tstop)*hh > ZERO)
+ hh = (tstop - tn)*(ONE-FOUR*uround);
+ }
+
+ return(CONTINUE_STEPS);
+
+ }
+ return(-99);
+}
+
+/*
+ * IDAStopTest2
+ *
+ * This routine tests for stop conditions after taking a step.
+ * The tests depend on the value of itask.
+ *
+ * The return values are:
+ * 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
+ *
+ * In the two cases with tstop, this routine may reset the stepsize hh
+ * to cause the next step to reach tstop exactly.
+ *
+ * In the two cases with ONE_STEP mode, no interpolation to tn is needed
+ * because yret and ypret already contain the current y and y' values.
+ *
+ * Note: No test is made for an error return from IDAGetSolution here,
+ * because the same test was made prior to the step.
+ */
+
+static int IDAStopTest2(IDAMem IDA_mem, realtype tout, realtype *tret,
+ N_Vector yret, N_Vector ypret, int itask)
+{
+ int ier;
+ realtype troundoff;
+
+ switch (itask) {
+
+ case IDA_NORMAL:
+
+ /* Test for tn past tout. */
+ if ((tn - tout)*hh >= ZERO) {
+ ier = IDAGetSolution(IDA_mem, tout, yret, ypret);
+ *tret = tretlast = tout;
+ return(IDA_SUCCESS);
+ }
+
+ if (tstopset) {
+ /* Test for tn at tstop and for tn near tstop */
+ troundoff = HUNDRED*uround*(ABS(tn) + ABS(hh));
+ if (ABS(tn - tstop) <= troundoff) {
+ ier = IDAGetSolution(IDA_mem, tstop, yret, ypret);
+ *tret = tretlast = tstop;
+ tstopset = FALSE;
+ return(IDA_TSTOP_RETURN);
+ }
+ if ((tn + hh - tstop)*hh > ZERO)
+ hh = (tstop - tn)*(ONE-FOUR*uround);
+ }
+
+ return(CONTINUE_STEPS);
+
+ case IDA_ONE_STEP:
+
+ if (tstopset) {
+ /* Test for tn at tstop and for tn near tstop */
+ troundoff = HUNDRED*uround*(ABS(tn) + ABS(hh));
+ if (ABS(tn - tstop) <= troundoff) {
+ ier = IDAGetSolution(IDA_mem, tstop, yret, ypret);
+ *tret = tretlast = tstop;
+ tstopset = FALSE;
+ return(IDA_TSTOP_RETURN);
+ }
+ if ((tn + hh - tstop)*hh > ZERO)
+ hh = (tstop - tn)*(ONE-FOUR*uround);
+ }
+
+ *tret = tretlast = tn;
+ return(IDA_SUCCESS);
+
+ }
+ return -99;
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Error handler
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * IDAHandleFailure
+ *
+ * This routine prints error messages for all cases of failure by
+ * IDAStep. It returns to IDASolve the value that it is to return to
+ * the user.
+ */
+
+static int IDAHandleFailure(IDAMem IDA_mem, int sflag)
+{
+ /* Depending on sflag, print error message and return error flag */
+ switch (sflag) {
+
+ case IDA_ERR_FAIL:
+ IDAProcessError(IDA_mem, IDA_ERR_FAIL, "IDA", "IDASolve", MSG_ERR_FAILS, tn, hh);
+ return(IDA_ERR_FAIL);
+
+ case IDA_CONV_FAIL:
+ IDAProcessError(IDA_mem, IDA_CONV_FAIL, "IDA", "IDASolve", MSG_CONV_FAILS, tn, hh);
+ return(IDA_CONV_FAIL);
+
+ case IDA_LSETUP_FAIL:
+ IDAProcessError(IDA_mem, IDA_LSETUP_FAIL, "IDA", "IDASolve", MSG_SETUP_FAILED, tn);
+ return(IDA_LSETUP_FAIL);
+
+ case IDA_LSOLVE_FAIL:
+ IDAProcessError(IDA_mem, IDA_LSOLVE_FAIL, "IDA", "IDASolve", MSG_SOLVE_FAILED, tn);
+ return(IDA_LSOLVE_FAIL);
+
+ case IDA_REP_RES_ERR:
+ IDAProcessError(IDA_mem, IDA_REP_RES_ERR, "IDA", "IDASolve", MSG_REP_RES_ERR, tn);
+ return(IDA_REP_RES_ERR);
+
+ case IDA_RES_FAIL:
+ IDAProcessError(IDA_mem, IDA_RES_FAIL, "IDA", "IDASolve", MSG_RES_NONRECOV, tn);
+ return(IDA_RES_FAIL);
+
+ case IDA_CONSTR_FAIL:
+ IDAProcessError(IDA_mem, IDA_CONSTR_FAIL, "IDA", "IDASolve", MSG_FAILED_CONSTR, tn);
+ return(IDA_CONSTR_FAIL);
+
+ }
+
+ return -99;
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Main IDAStep function
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * IDAStep
+ *
+ * This routine performs one internal IDA step, from tn to tn + hh.
+ * It calls other routines to do all the work.
+ *
+ * It solves a system of differential/algebraic equations of the form
+ * F(t,y,y') = 0, for one step. In IDA, tt is used for t,
+ * yy is used for y, and yp is used for y'. The function F is supplied as 'res'
+ * by the user.
+ *
+ * The methods used are modified divided difference, fixed leading
+ * coefficient forms of backward differentiation formulas.
+ * The code adjusts the stepsize and order to control the local error per step.
+ *
+ * The main operations done here are as follows:
+ * * initialize various quantities;
+ * * setting of multistep method coefficients;
+ * * solution of the nonlinear system for yy at t = tn + hh;
+ * * deciding on order reduction and testing the local error;
+ * * attempting to recover from failure in nonlinear solver or error test;
+ * * resetting stepsize and order for the next step.
+ * * updating phi and other state data if successful;
+ *
+ * On a failure in the nonlinear system solution or error test, the
+ * step may be reattempted, depending on the nature of the failure.
+ *
+ * Variables or arrays (all in the IDAMem structure) used in IDAStep are:
+ *
+ * tt -- Independent variable.
+ * yy -- Solution vector at tt.
+ * yp -- Derivative of solution vector after successful stelp.
+ * res -- User-supplied function to evaluate the residual. See the
+ * description given in file ida.h .
+ * lsetup -- Routine to prepare for the linear solver call. It may either
+ * save or recalculate quantities used by lsolve. (Optional)
+ * lsolve -- Routine to solve a linear system. A prior call to lsetup
+ * may be required.
+ * hh -- Appropriate step size for next step.
+ * ewt -- Vector of weights used in all convergence tests.
+ * phi -- Array of divided differences used by IDAStep. This array is composed
+ * of (maxord+1) nvectors (each of size Neq). (maxord+1) is the maximum
+ * order for the problem, maxord, plus 1.
+ *
+ * Return values are:
+ * IDA_SUCCESS IDA_RES_FAIL LSETUP_ERROR_NONRECVR
+ * IDA_LSOLVE_FAIL IDA_ERR_FAIL
+ * IDA_CONSTR_FAIL IDA_CONV_FAIL
+ * IDA_REP_RES_ERR
+ */
+
+static int IDAStep(IDAMem IDA_mem)
+{
+ realtype saved_t, ck;
+ realtype err_k, err_km1;
+ int ncf, nef;
+ int nflag, kflag;
+
+ saved_t = tn;
+ ncf = nef = 0;
+
+ if (nst == ZERO){
+ kk = 1;
+ kused = 0;
+ hused = ZERO;
+ psi[0] = hh;
+ cj = ONE/hh;
+ phase = 0;
+ ns = 0;
+ }
+
+ /* To prevent 'unintialized variable' warnings */
+ err_k = ZERO;
+ err_km1 = ZERO;
+
+ /* Looping point for attempts to take a step */
+
+ loop {
+
+ /*-----------------------
+ Set method coefficients
+ -----------------------*/
+
+ IDASetCoeffs(IDA_mem, &ck);
+
+ kflag = IDA_SUCCESS;
+
+ /*----------------------------------------------------
+ If tn is past tstop (by roundoff), reset it to tstop.
+ -----------------------------------------------------*/
+
+ tn = tn + hh;
+ if (tstopset) {
+ if ((tn - tstop)*hh > ZERO) tn = tstop;
+ }
+
+ /*-----------------------
+ Advance state variables
+ -----------------------*/
+
+ /* Nonlinear system solution */
+ nflag = IDANls(IDA_mem);
+
+ /* If NLS was successful, perform error test */
+ if (nflag == IDA_SUCCESS)
+ nflag = IDATestError(IDA_mem, ck, &err_k, &err_km1);
+
+ /* Test for convergence or error test failures */
+ if (nflag != IDA_SUCCESS) {
+
+ /* restore and decide what to do */
+ IDARestore(IDA_mem, saved_t);
+ kflag = IDAHandleNFlag(IDA_mem, nflag, err_k, err_km1,
+ &ncfn, &ncf, &netf, &nef);
+
+ /* exit on nonrecoverable failure */
+ if (kflag != PREDICT_AGAIN) return(kflag);
+
+ /* recoverable error; predict again */
+ if(nst==0) IDAReset(IDA_mem);
+ continue;
+
+ }
+
+ /* kflag == IDA_SUCCESS */
+ break;
+
+ }
+
+ /* Nonlinear system solve and error test were both successful;
+ update data, and consider change of step and/or order */
+
+ IDACompleteStep(IDA_mem, err_k, err_km1);
+
+ /*
+ Rescale ee vector to be the estimated local error
+ Notes:
+ (1) altering the value of ee is permissible since
+ it will be re-initialized to the zero vector by
+ IDASolve()->IDAStep()->IDANls()->IDANewtonIter()
+ before it is needed again
+ (2) the value of ee is only valid if IDAHandleNFlag()
+ returns either PREDICT_AGAIN or IDA_SUCCESS
+ */
+
+ N_VScale(ck, ee, ee);
+
+ return(IDA_SUCCESS);
+}
+
+/*
+ * IDASetCoeffs
+ *
+ * This routine computes the coefficients relevant to the current step.
+ * The counter ns counts the number of consecutive steps taken at
+ * constant stepsize h and order k, up to a maximum of k + 2.
+ * Then the first ns components of beta will be one, and on a step
+ * with ns = k + 2, the coefficients alpha, etc. need not be reset here.
+ * Also, IDACompleteStep prohibits an order increase until ns = k + 2.
+ */
+
+static void IDASetCoeffs(IDAMem IDA_mem, realtype *ck)
+{
+ int i;
+ realtype temp1, temp2, alpha0, alphas;
+
+ /* Set coefficients for the current stepsize h */
+
+ if (hh != hused || kk != kused) ns = 0;
+ ns = MIN(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;
+ }
+ psi[kk] = temp1;
+ }
+ /* compute alphas, alpha0 */
+ alphas = ZERO;
+ alpha0 = ZERO;
+ for(i=0;i<kk;i++){
+ alphas = alphas - ONE/(i+1);
+ alpha0 = alpha0 - alpha[i];
+ }
+
+ /* compute leading coefficient cj */
+ cjlast = cj;
+ cj = -alphas/hh;
+
+ /* compute variable stepsize error coefficient ck */
+
+ *ck = ABS(alpha[kk] + alphas - alpha0);
+ *ck = MAX(*ck, alpha[kk]);
+
+ /* change phi to phi-star */
+
+ for(i=ns;i<=kk;i++) N_VScale(beta[i], phi[i], phi[i]);
+
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Nonlinear solver functions
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * IDANls
+ *
+ * This routine attempts to solve the nonlinear system using the linear
+ * solver specified. NOTE: this routine uses N_Vector ee as the scratch
+ * vector tempv3 passed to lsetup.
+ *
+ * Possible return values:
+ *
+ * IDA_SUCCESS
+ *
+ * IDA_RES_RECVR IDA_RES_FAIL
+ * IDA_LSETUP_RECVR IDA_LSETUP_FAIL
+ * IDA_LSOLVE_RECVR IDA_LSOLVE_FAIL
+ *
+ * IDA_CONSTR_RECVR
+ * IDA_NCONV_RECVR
+ */
+
+static int IDANls(IDAMem IDA_mem)
+{
+ int retval;
+ booleantype constraintsPassed, callSetup, tryAgain;
+ realtype temp1, temp2, vnorm;
+ N_Vector tempv3;
+
+ callSetup = FALSE;
+
+ /* Initialize if the first time called */
+
+ if (nst == 0){
+ cjold = cj;
+ ss = TWENTY;
+ if (setupNonNull) callSetup = TRUE;
+ }
+
+ mm = tempv2;
+ tempv3 = ee;
+
+ /* Decide if lsetup is to be called */
+
+ if (setupNonNull){
+ cjratio = cj / cjold;
+ temp1 = (ONE - XRATE) / (ONE + XRATE);
+ temp2 = ONE/temp1;
+ {if (cjratio < temp1 || cjratio > temp2) callSetup = TRUE;}
+ {if (cj != cjlast) 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{
+
+ /* Compute predicted values for yy and yp, and compute residual there. */
+ IDAPredict(IDA_mem);
+
+ retval = res(tn, yy, yp, delta, user_data);
+ 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;
+ if (retval < 0) return(IDA_LSETUP_FAIL);
+ if (retval > 0) return(IDA_LSETUP_RECVR);
+ }
+
+ /* Call the Newton iteration routine. */
+
+ retval = IDANewtonIter(IDA_mem);
+
+ /* Retry the current step on recoverable failure with old Jacobian data. */
+
+ tryAgain = (retval>0)&&(setupNonNull) &&(!callSetup);
+
+ if (tryAgain){
+ callSetup = TRUE;
+ continue;
+ }
+ else break;
+
+ } /* end of loop */
+
+ if (retval != IDA_SUCCESS) return(retval);
+
+ /* 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 (constraintsPassed) return(IDA_SUCCESS);
+ else {
+ N_VCompare(ONEPT5, constraints, 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|| */
+
+ /* 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 */
+ 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 = MAX(rr,PT1);
+ return(IDA_CONSTR_RECVR);
+ }
+ }
+ }
+ return(IDA_SUCCESS);
+}
+
+
+/*
+ * IDAPredict
+ *
+ * This routine predicts the new values for vectors yy and yp.
+ */
+
+static void IDAPredict(IDAMem IDA_mem)
+{
+ int j;
+
+ N_VScale(ONE, phi[0], yy);
+ N_VConst(ZERO, yp);
+
+ for(j=1; j<=kk; j++) {
+ N_VLinearSum(ONE, phi[j], ONE, yy, yy);
+ N_VLinearSum(gamma[j], phi[j], ONE, yp, yp);
+ }
+}
+
+/*
+ * IDANewtonIter
+ *
+ * This routine performs the Newton iteration.
+ * It assumes that delta contains the initial residual vector on entry.
+ * If the iteration succeeds, it returns the value IDA_SUCCESS = 0.
+ * If not, it returns either:
+ * a positive value (for a recoverable failure), namely one of:
+ * IDA_RES_RECVR
+ * IDA_LSOLVE_RECVR
+ * IDA_NCONV_RECVR
+ * or
+ * a negative value (for a nonrecoverable failure), namely one of:
+ * IDA_RES_FAIL
+ * IDA_LSOLVE_FAIL
+ *
+ * NOTE: This routine uses N_Vector savres, which is preset to tempv1.
+ */
+
+static int IDANewtonIter(IDAMem IDA_mem)
+{
+ int mnewt, retval;
+ realtype delnrm, oldnrm, rate;
+
+ /* Initialize counter mnewt and cumulative correction vector ee. */
+ mnewt = 0;
+ N_VConst(ZERO, ee);
+
+ /* Initialize oldnrm to avoid compiler warning message */
+ oldnrm = ZERO;
+
+ /* Looping point for Newton iteration. Break out on any error. */
+ loop {
+
+ nni++;
+
+ /* Save a copy of the residual vector in savres. */
+ N_VScale(ONE, delta, savres);
+
+ /* Call the lsolve function to get correction vector delta. */
+ retval = lsolve(IDA_mem, delta, ewt, yy, yp, 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);
+
+ /* Test for convergence, first directly, then with rate estimate. */
+
+ if (mnewt == 0){
+ oldnrm = delnrm;
+ if (delnrm <= toldel) return(IDA_SUCCESS);
+ }
+ else {
+ rate = RPowerR( delnrm/oldnrm, ONE/mnewt );
+ if (rate > RATEMAX) return(IDA_NCONV_RECVR);
+ ss = rate/(ONE - rate);
+ }
+
+ if (ss*delnrm <= epsNewt) return(IDA_SUCCESS);
+
+ /* Not yet converged. Increment mnewt and test for max allowed. */
+ mnewt++;
+ if (mnewt >= 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++;
+ if (retval < 0) return(IDA_RES_FAIL);
+ if (retval > 0) return(IDA_RES_RECVR);
+
+ /* Loop for next iteration. */
+
+ } /* end of Newton iteration loop */
+
+ /* All error returns exit here. */
+ return(retval);
+
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Error test
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * IDATestError
+ *
+ * This routine estimates errors at orders k, k-1, k-2, decides
+ * whether or not to suggest an order decrease, and performs
+ * the local error test.
+ *
+ * IDATestError returns either IDA_SUCCESS or ERROR_TEST_FAIL.
+ */
+
+static int IDATestError(IDAMem IDA_mem, realtype ck,
+ realtype *err_k, realtype *err_km1)
+{
+ realtype err_km2; /* estimated error at k-2 */
+ realtype enorm_k, enorm_km1, enorm_km2; /* error norms */
+ 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);
+
+ knew = kk;
+
+ if ( 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);
+
+ if ( 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;
+
+ /* Decrease order if errors are reduced */
+ if (MAX(terr_km1, terr_km2) <= terr_k) knew = 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;
+
+ }
+
+ }
+
+ /* Perform error test */
+ if (ck * enorm_k > ONE) return(ERROR_TEST_FAIL);
+ else return(IDA_SUCCESS);
+}
+
+/*
+ * IDARestore
+ *
+ * This routine restores tn, psi, and phi in the event of a failure.
+ * It changes back phi-star to phi (changed in IDASetCoeffs)
+ */
+
+static void IDARestore(IDAMem IDA_mem, realtype saved_t)
+{
+ int j;
+
+ tn = saved_t;
+
+ for (j = 1; j <= kk; j++)
+ psi[j-1] = psi[j] - hh;
+
+ for (j = ns; j <= kk; j++)
+ N_VScale(ONE/beta[j], phi[j], phi[j]);
+
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Handler for convergence and/or error test failures
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * IDAHandleNFlag
+ *
+ * This routine handles failures indicated by the input variable nflag.
+ * Positive values indicate various recoverable failures while negative
+ * values indicate nonrecoverable failures. This routine adjusts the
+ * step size for recoverable failures.
+ *
+ * Possible nflag values (input):
+ *
+ * --convergence failures--
+ * IDA_RES_RECVR > 0
+ * IDA_LSOLVE_RECVR > 0
+ * IDA_CONSTR_RECVR > 0
+ * IDA_NCONV_RECVR > 0
+ * IDA_RES_FAIL < 0
+ * IDA_LSOLVE_FAIL < 0
+ * IDA_LSETUP_FAIL < 0
+ *
+ * --error test failure--
+ * ERROR_TEST_FAIL > 0
+ *
+ * Possible kflag values (output):
+ *
+ * --recoverable--
+ * PREDICT_AGAIN
+ *
+ * --nonrecoverable--
+ * IDA_CONSTR_FAIL
+ * IDA_REP_RES_ERR
+ * IDA_ERR_FAIL
+ * IDA_CONV_FAIL
+ * IDA_RES_FAIL
+ * IDA_LSETUP_FAIL
+ * IDA_LSOLVE_FAIL
+ */
+
+static int IDAHandleNFlag(IDAMem IDA_mem, int nflag, realtype err_k, realtype err_km1,
+ long int *ncfnPtr, int *ncfPtr, long int *netfPtr, int *nefPtr)
+{
+ realtype err_knew;
+
+ phase = 1;
+
+ if (nflag != ERROR_TEST_FAIL) {
+
+ /*-----------------------
+ Nonlinear solver failed
+ -----------------------*/
+
+ (*ncfPtr)++; /* local counter for convergence failures */
+ (*ncfnPtr)++; /* global counter for convergence failures */
+
+ if (nflag < 0) { /* nonrecoverable failure */
+
+ return(nflag);
+
+ } else { /* recoverable failure */
+
+ /* 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;
+
+ /* Test if there were too many convergence failures */
+ if (*ncfPtr < 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);
+ }
+
+ } else {
+
+ /*-----------------
+ Error Test failed
+ -----------------*/
+
+ (*nefPtr)++; /* local counter for error test failures */
+ (*netfPtr)++; /* global counter for error test failures */
+
+ if (*nefPtr == 1) {
+
+ /* 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;
+
+ kk = knew;
+ rr = PT9 * RPowerR( TWO * err_knew + PT0001,(-ONE/(kk+1)) );
+ rr = MAX(QUARTER, MIN(PT9,rr));
+ hh *=rr;
+ return(PREDICT_AGAIN);
+
+ } else if (*nefPtr == 2) {
+
+ /* 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;
+ return(PREDICT_AGAIN);
+
+ } else if (*nefPtr < 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;
+ return(PREDICT_AGAIN);
+
+ } else {
+
+ /* Too many error test failures */
+ return(IDA_ERR_FAIL);
+
+ }
+
+ }
+
+}
+
+/*
+ * IDAReset
+ *
+ * This routine is called only if we need to predict again at the
+ * very first step. In such a case, reset phi[1] and psi[0].
+ */
+
+static void IDAReset(IDAMem IDA_mem)
+{
+ psi[0] = hh;
+
+ N_VScale(rr, phi[1], phi[1]);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Function called after a successful step
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * IDACompleteStep
+ *
+ * This routine completes a successful step. It increments nst,
+ * saves the stepsize and order used, makes the final selection of
+ * stepsize and order for the next step, and updates the phi array.
+ */
+
+static void IDACompleteStep(IDAMem IDA_mem, realtype err_k, realtype err_km1)
+{
+ int j, kdiff, action;
+ realtype terr_k, terr_km1, terr_kp1;
+ realtype err_knew, err_kp1;
+ realtype enorm, tmp, hnew;
+
+ nst++;
+ kdiff = kk - kused;
+ kused = kk;
+ hused = hh;
+
+ if ( (knew == kk-1) || (kk == maxord) ) 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
+ the stepsize. During these steps, phase = 0. Thereafter, phase = 1, and
+ stepsize and order are set by the usual local error algorithm.
+
+ 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 = ABS(hnew)*hmax_inv) > ONE ) hnew /= tmp;
+ hh = hnew;
+ }
+
+ } else {
+
+ action = UNSET;
+
+ /* 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;}
+
+ /* 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);
+
+ /* 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;
+
+ if (kk == 1) {
+ if (terr_kp1 >= HALF * terr_k) {action = MAINTAIN; goto takeaction;}
+ else {action = RAISE; goto takeaction;}
+ } else {
+ terr_km1 = kk * err_km1;
+ if (terr_km1 <= MIN(terr_k, terr_kp1)) {action = LOWER; goto takeaction;}
+ else if (terr_kp1 >= terr_k) {action = MAINTAIN; goto takeaction;}
+ else {action = RAISE; goto takeaction;}
+ }
+
+ 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; }
+
+ /* 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 = RPowerR( (TWO * err_knew + PT0001) , (-ONE/(kk+1) ) );
+
+ if (rr >= TWO) {
+ hnew = TWO * hh;
+ if( (tmp = ABS(hnew)*hmax_inv) > ONE ) hnew /= tmp;
+ } else if (rr <= ONE ) {
+ rr = MAX(HALF, MIN(PT9,rr));
+ hnew = hh * rr;
+ }
+
+ 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]);
+ }
+
+ /* 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]);
+
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Interpolated output
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * IDAGetSolution
+ *
+ * This routine evaluates y(t) and y'(t) as the value and derivative of
+ * the interpolating polynomial at the independent variable t, and stores
+ * the results in the vectors yret and ypret. It uses the current
+ * independent variable value, tn, and the method order last used, kused.
+ * This function is called by IDASolve with t = tout, t = tn, or t = tstop.
+ *
+ * If kused = 0 (no step has been taken), or if t = tn, then the order used
+ * here is taken to be 1, giving yret = phi[0], ypret = phi[1]/psi[0].
+ *
+ * The return values are:
+ * IDA_SUCCESS if t is legal, or
+ * IDA_BAD_T if t is not within the interval of the last step taken.
+ */
+
+int IDAGetSolution(void *ida_mem, realtype t, N_Vector yret, N_Vector ypret)
+{
+ IDAMem IDA_mem;
+ realtype tfuzz, tp, delt, c, d, gam;
+ int j, kord;
+
+ if (ida_mem == NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDAGetSolution", MSG_NO_MEM);
+ return (IDA_MEM_NULL);
+ }
+ IDA_mem = (IDAMem) ida_mem;
+
+ /* Check t for legality. Here tn - hused is t_{n-1}. */
+
+ tfuzz = HUNDRED * uround * (ABS(tn) + ABS(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);
+ 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;
+
+ /* Accumulate multiples of columns phi[j] into yret and ypret. */
+
+ delt = t - tn;
+ c = ONE; d = ZERO;
+ gam = delt/psi[0];
+ for (j=1; j <= kord; j++) {
+ d = d*gam + c/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);
+ }
+ return(IDA_SUCCESS);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Norm function
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * IDAWrmsNorm
+ *
+ * Returns the WRMS norm of vector x with weights w.
+ * If mask = TRUE, 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 = suppressalg otherwise.
+ */
+
+realtype IDAWrmsNorm(IDAMem IDA_mem, N_Vector x, N_Vector w,
+ booleantype mask)
+{
+ realtype nrm;
+
+ if (mask) nrm = N_VWrmsNormMask(x, w, id);
+ else nrm = N_VWrmsNorm(x, w);
+
+ return(nrm);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Functions for rootfinding
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * IDARcheck1
+ *
+ * This routine completes the initialization of rootfinding memory
+ * information, and checks whether g has a zero both at and very near
+ * the initial point of the IVP.
+ *
+ * This routine returns an int equal to:
+ * IDA_RTFUNC_FAIL < 0 if the g function failed, or
+ * IDA_SUCCESS = 0 otherwise.
+ */
+
+static int IDARcheck1(IDAMem IDA_mem)
+{
+ int i, retval;
+ realtype smallh, hratio, tplus;
+ booleantype zroot;
+
+ for (i = 0; i < nrtfn; i++) iroots[i] = 0;
+ tlo = tn;
+ ttol = (ABS(tn) + ABS(hh))*uround*HUNDRED;
+
+ /* Evaluate g at initial t and check for zero values. */
+ retval = gfun (tlo, phi[0], phi[1], glo, user_data);
+ nge = 1;
+ if (retval != 0) return(IDA_RTFUNC_FAIL);
+
+ zroot = FALSE;
+ for (i = 0; i < nrtfn; i++) {
+ if (ABS(glo[i]) == ZERO) {
+ zroot = TRUE;
+ gactive[i] = FALSE;
+ }
+ }
+ if (!zroot) return(IDA_SUCCESS);
+
+ /* Some g_i is zero at t0; look at g at t0+(small increment). */
+ hratio = MAX(ttol/ABS(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++;
+ 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] && ABS(ghi[i]) != ZERO) {
+ gactive[i] = TRUE;
+ glo[i] = ghi[i];
+ }
+ }
+
+ return(IDA_SUCCESS);
+}
+
+/*
+ * IDARcheck2
+ *
+ * This routine checks for exact zeros of g at the last root found,
+ * if the last return was a root. It then checks for a close pair of
+ * zeros (an error condition), and for a new root at a nearby point.
+ * The array glo = g(tlo) at the left endpoint of the search interval
+ * is adjusted if necessary to assure that all g_i are nonzero
+ * there, before returning to do a root search in the interval.
+ *
+ * On entry, tlo = tretlast is the last value of tret returned by
+ * IDASolve. This may be the previous tn, the previous tout value,
+ * or the last root location.
+ *
+ * This routine returns an int equal to:
+ * IDA_RTFUNC_FAIL (<0) if the g function failed, or
+ * CLOSERT (>0) if a close pair of zeros was found, or
+ * RTFOUND (>0) if a new zero of g was found near tlo, or
+ * IDA_SUCCESS (=0) otherwise.
+ */
+
+static int IDARcheck2(IDAMem IDA_mem)
+{
+ int i, retval;
+ realtype smallh, hratio, tplus;
+ booleantype zroot;
+
+ if (irfnd == 0) return(IDA_SUCCESS);
+
+ (void) IDAGetSolution(IDA_mem, tlo, yy, yp);
+ retval = gfun (tlo, yy, yp, glo, user_data);
+ 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 (ABS(glo[i]) == ZERO) {
+ zroot = TRUE;
+ iroots[i] = 1;
+ }
+ }
+ if (!zroot) return(IDA_SUCCESS);
+
+ /* One or more g_i has a zero at tlo. Check g at tlo+smallh. */
+ ttol = (ABS(tn) + ABS(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);
+ } else {
+ (void) IDAGetSolution(IDA_mem, tplus, yy, yp);
+ }
+ retval = gfun (tplus, yy, yp, ghi, user_data);
+ 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 (ABS(ghi[i]) == ZERO) {
+ if (iroots[i] == 1) return(CLOSERT);
+ zroot = TRUE;
+ iroots[i] = 1;
+ } else {
+ if (iroots[i] == 1) glo[i] = ghi[i];
+ }
+ }
+ if (zroot) return(RTFOUND);
+ return(IDA_SUCCESS);
+}
+
+/*
+ * IDARcheck3
+ *
+ * This routine interfaces to IDARootfind to look for a root of g
+ * between tlo and either tn or tout, whichever comes first.
+ * Only roots beyond tlo in the direction of integration are sought.
+ *
+ * This routine returns an int equal to:
+ * IDA_RTFUNC_FAIL (<0) if the g function failed, or
+ * RTFOUND (>0) if a root of g was found, or
+ * IDA_SUCCESS (=0) otherwise.
+ */
+
+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;
+ }
+
+ /* Get y and y' at thi. */
+ (void) IDAGetSolution(IDA_mem, thi, yy, yp);
+
+
+ /* Set ghi = g(thi) and call IDARootfind to search (tlo,thi) for roots. */
+ retval = gfun (thi, yy, yp, ghi, user_data);
+ nge++;
+ if (retval != 0) return(IDA_RTFUNC_FAIL);
+
+ ttol = (ABS(tn) + ABS(hh))*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;
+ }
+ tlo = trout;
+ for (i = 0; i < nrtfn; i++) glo[i] = 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);
+ return(RTFOUND);
+
+}
+
+/*
+ * IDARootfind
+ *
+ * This routine solves for a root of g(t) between tlo and thi, if
+ * one exists. Only roots of odd multiplicity (i.e. with a change
+ * of sign in one of the g_i), or exact zeros, are found.
+ * Here the sign of tlo - thi is arbitrary, but if multiple roots
+ * are found, the one closest to tlo is returned.
+ *
+ * The method used is the Illinois algorithm, a modified secant method.
+ * Reference: Kathie L. Hiebert and Lawrence F. Shampine, Implicitly
+ * Defined Output Points for Solutions of ODEs, Sandia National
+ * Laboratory Report SAND80-0180, February 1980.
+ *
+ * This routine uses the following parameters for communication:
+ *
+ * nrtfn = number of functions g_i, or number of components of
+ * the vector-valued function g(t). Input only.
+ *
+ * gfun = user-defined function for g(t). Its form is
+ * (void) gfun(t, y, yp, gt, user_data)
+ *
+ * rootdir = in array specifying the direction of zero-crossings.
+ * If rootdir[i] > 0, search for roots of g_i only if
+ * g_i is increasing; if rootdir[i] < 0, search for
+ * roots of g_i only if g_i is decreasing; otherwise
+ * always search for roots of g_i.
+ *
+ * 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
+ * both at the I.C. and at a small perturbation of them.
+ * gactive[i] is then set back on TRUE only after the
+ * corresponding g function moves away from 0.0.
+ *
+ * nge = cumulative counter for gfun calls.
+ *
+ * ttol = a convergence tolerance for trout. Input only.
+ * When a root at trout is found, it is located only to
+ * within a tolerance of ttol. Typically, ttol should
+ * be set to a value on the order of
+ * 100 * UROUND * max (ABS(tlo), ABS(thi))
+ * where UROUND is the unit roundoff of the machine.
+ *
+ * tlo, thi = endpoints of the interval in which roots are sought.
+ * On input, and must be distinct, but tlo - thi may
+ * be of either sign. The direction of integration is
+ * assumed to be from tlo to thi. On return, tlo and thi
+ * are the endpoints of the final relevant interval.
+ *
+ * glo, ghi = arrays of length nrtfn containing the vectors g(tlo)
+ * and g(thi) respectively. Input and output. On input,
+ * none of the glo[i] should be zero.
+ *
+ * trout = root location, if a root was found, or thi if not.
+ * Output only. If a root was found other than an exact
+ * zero of g, trout is the endpoint thi of the final
+ * interval bracketing the root, with size at most ttol.
+ *
+ * grout = array of length nrtfn containing g(trout) on return.
+ *
+ * iroots = int array of length nrtfn with root information.
+ * Output only. If a root was found, iroots indicates
+ * which components g_i have a root at trout. For
+ * i = 0, ..., nrtfn-1, iroots[i] = 1 if g_i has a root
+ * and g_i is increasing, iroots[i] = -1 if g_i has a
+ * root and g_i is decreasing, and iroots[i] = 0 if g_i
+ * has no roots or g_i varies in the direction opposite
+ * to that indicated by rootdir[i].
+ *
+ * This routine returns an int equal to:
+ * IDA_RTFUNC_FAIL (<0) if the g function failed, or
+ * RTFOUND = 1 if a root of g was found, or
+ * IDA_SUCCESS = 0 otherwise.
+ *
+ */
+
+static int IDARootfind(IDAMem IDA_mem)
+{
+ realtype alph, tmid, gfrac, maxfrac, fracint, fracsub;
+ int i, retval, imax, side, sideprev;
+ booleantype zroot, sgnchg;
+
+ imax = 0;
+
+ /* 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 (ABS(ghi[i]) == ZERO) {
+ if(rootdir[i]*glo[i] <= ZERO) {
+ zroot = TRUE;
+ }
+ } else {
+ if ( (glo[i]*ghi[i] < ZERO) && (rootdir[i]*glo[i] <= ZERO) ) {
+ gfrac = ABS(ghi[i]/(ghi[i] - glo[i]));
+ if (gfrac > maxfrac) {
+ sgnchg = TRUE;
+ maxfrac = gfrac;
+ imax = i;
+ }
+ }
+ }
+ }
+
+ /* 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];
+ if (!zroot) return(IDA_SUCCESS);
+ for (i = 0; i < nrtfn; i++) {
+ iroots[i] = 0;
+ if(!gactive[i]) continue;
+ if (ABS(ghi[i]) == ZERO) iroots[i] = glo[i] > 0 ? -1:1;
+ }
+ return(RTFOUND);
+ }
+
+ /* Initialize alph to avoid compiler warning */
+ alph = ONE;
+
+ /* A sign change was found. Loop to locate nearest root. */
+
+ side = 0; sideprev = -1;
+ loop { /* Looping point */
+
+ /* Set weight alph.
+ On the first two passes, set alph = 1. Thereafter, reset alph
+ according to the side (low vs high) of the subinterval in which
+ the sign change was found in the previous two passes.
+ If the sides were opposite, set alph = 1.
+ 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. */
+
+ if (sideprev == side) {
+ alph = (side == 2) ? alph*TWO : alph*HALF;
+ } else {
+ alph = ONE;
+ }
+
+ /* 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 (ABS(tmid - tlo) < HALF*ttol) {
+ fracint = ABS(thi - tlo)/ttol;
+ fracsub = (fracint > FIVE) ? PT1 : HALF/fracint;
+ tmid = tlo + fracsub*(thi - tlo);
+ }
+ if (ABS(thi - tmid) < HALF*ttol) {
+ fracint = ABS(thi - tlo)/ttol;
+ fracsub = (fracint > FIVE) ? PT1 : HALF/fracint;
+ tmid = thi - fracsub*(thi - tlo);
+ }
+
+ (void) IDAGetSolution(IDA_mem, tmid, yy, yp);
+ retval = gfun (tmid, yy, yp, grout, user_data);
+ 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;
+ sideprev = side;
+ for (i = 0; i < nrtfn; i++) {
+ if(!gactive[i]) continue;
+ if (ABS(grout[i]) == ZERO) {
+ if(rootdir[i]*glo[i] <= ZERO) {
+ zroot = TRUE;
+ }
+ } else {
+ if ( (glo[i]*grout[i] < ZERO) && (rootdir[i]*glo[i] <= ZERO) ) {
+ gfrac = ABS(grout[i]/(grout[i] - glo[i]));
+ if (gfrac > maxfrac) {
+ sgnchg = TRUE;
+ maxfrac = gfrac;
+ imax = i;
+ }
+ }
+ }
+ }
+ if (sgnchg) {
+ /* Sign change found in (tlo,tmid); replace thi with tmid. */
+ thi = tmid;
+ for (i = 0; i < nrtfn; i++) ghi[i] = grout[i];
+ side = 1;
+ /* Stop at root thi if converged; otherwise loop. */
+ if (ABS(thi - tlo) <= 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];
+ 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];
+ side = 2;
+ /* Stop at root thi if converged; otherwise loop back. */
+ if (ABS(thi - tlo) <= 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 ( (ABS(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;
+ }
+ return(RTFOUND);
+}
+
+/*
+ * =================================================================
+ * IDA error message handling functions
+ * =================================================================
+ */
+
+/*
+ * IDAProcessError is a high level error handling function
+ * - if ida_mem==NULL it prints the error message to stderr
+ * - otherwise, it sets-up and calls the error hadling function
+ * 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, ...)
+{
+ va_list ap;
+ char msg[256];
+
+ /* Initialize the argument pointer variable
+ (msgfmt is the last required argument to IDAProcessError) */
+
+ va_start(ap, msgfmt);
+
+ if (IDA_mem == NULL) { /* We write to stderr */
+
+#ifndef NO_FPRINTF_OUTPUT
+ fprintf(stderr, "\n[%s ERROR] %s\n ", module, fname);
+ fprintf(stderr, msgfmt);
+ fprintf(stderr, "\n\n");
+#endif
+
+ } else { /* We can call ehfun */
+
+ /* Compose the message */
+
+ vsprintf(msg, msgfmt, ap);
+
+ /* Call ehfun */
+
+ ehfun(error_code, module, fname, msg, eh_data);
+
+ }
+
+ /* Finalize argument processing */
+
+ va_end(ap);
+
+ return;
+
+}
+
+/* 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)
+{
+ IDAMem IDA_mem;
+ char err_type[10];
+
+ /* data points to IDA_mem here */
+
+ IDA_mem = (IDAMem) data;
+
+ if (error_code == IDA_WARNING)
+ sprintf(err_type,"WARNING");
+ else
+ 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);
+ }
+#endif
+
+ return;
+}
diff --git a/src/ida/ida_band.c b/src/ida/ida_band.c
new file mode 100644
index 0000000..c7b84a0
--- /dev/null
+++ b/src/ida/ida_band.c
@@ -0,0 +1,319 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.13 $
+ * $Date: 2011/03/23 20:44:01 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Alan C. Hindmarsh and Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * 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;
+ int flag;
+
+ /* 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) flag = 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;
+
+ 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 = MIN(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;
+
+ /* Initialize nje and nreB */
+ 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
new file mode 100644
index 0000000..977a516
--- /dev/null
+++ b/src/ida/ida_bbdpre.c
@@ -0,0 +1,584 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.10 $
+ * $Date: 2011/03/23 20:44:01 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Alan C. Hindmarsh and Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * 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.
+ *
+ * NOTE: With only one processor in use, a banded matrix results
+ * rather than a block-diagonal matrix with banded blocks.
+ * Diagonal blocking occurs at the processor level.
+ * -----------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#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>
+
+#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);
+
+/* Prototype for IDABBDPrecFree */
+
+static void 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,
+ 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;
+ int flag;
+
+ if (ida_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 */
+ if (IDA_mem->ida_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);
+ return(IDASPILS_ILL_INPUT);
+ }
+
+ /* Allocate data memory. */
+ pdata = NULL;
+ pdata = (IBBDPrecData) malloc(sizeof *pdata);
+ if (pdata == NULL) {
+ IDAProcessError(IDA_mem, IDASPILS_MEM_FAIL, "IDABBDPRE", "IDABBDPrecInit", MSGBBD_MEM_FAIL);
+ return(IDASPILS_MEM_FAIL);
+ }
+
+ /* Set pointers to glocal and gcomm; load half-bandwidths. */
+ pdata->ida_mem = IDA_mem;
+ pdata->glocal = Gres;
+ pdata->gcomm = Gcomm;
+ pdata->mudq = MIN(Nlocal-1, MAX(0, mudq));
+ pdata->mldq = MIN(Nlocal-1, MAX(0, mldq));
+ muk = MIN(Nlocal-1, MAX(0, mukeep));
+ mlk = MIN(Nlocal-1, MAX(0, mlkeep));
+ pdata->mukeep = muk;
+ pdata->mlkeep = mlk;
+
+ /* Set extended upper half-bandwidth for PP (required for pivoting). */
+ storage_mu = MIN(Nlocal-1, muk+mlk);
+
+ /* Allocate memory for preconditioner matrix. */
+ pdata->PP = NULL;
+ pdata->PP = NewBandMat(Nlocal, muk, mlk, storage_mu);
+ if (pdata->PP == NULL) {
+ free(pdata); pdata = NULL;
+ 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);
+ free(pdata); pdata = NULL;
+ 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);
+ free(pdata); pdata = NULL;
+ IDAProcessError(IDA_mem, IDASPILS_MEM_FAIL, "IDABBDPRE", "IDABBDPrecInit", MSGBBD_MEM_FAIL);
+ return(IDASPILS_MEM_FAIL);
+ }
+ pdata->tempv4 = tempv4;
+
+ /* Set rel_yy based on input value dq_rel_yy (0 implies default). */
+ pdata->rel_yy = (dq_rel_yy > ZERO) ? dq_rel_yy : RSqrt(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->nge = 0;
+
+ /* Overwrite the pdata field in the SPILS memory */
+ idaspils_mem->s_pdata = pdata;
+
+ /* Attach the pfree function */
+ idaspils_mem->s_pfree = IDABBDPrecFree;
+
+ /* Attach preconditioner solve and setup functions */
+ flag = IDASpilsSetPreconditioner(ida_mem, IDABBDPrecSetup, IDABBDPrecSolve);
+
+ return(flag);
+}
+
+int IDABBDPrecReInit(void *ida_mem,
+ long int mudq, long int mldq,
+ realtype dq_rel_yy)
+{
+ IDAMem IDA_mem;
+ IDASpilsMem idaspils_mem;
+ IBBDPrecData pdata;
+ long int Nlocal;
+
+
+ if (ida_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 */
+ if (IDA_mem->ida_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);
+ return(IDASPILS_PMEM_NULL);
+ }
+ pdata = (IBBDPrecData) idaspils_mem->s_pdata;
+
+ /* Load half-bandwidths. */
+ Nlocal = pdata->n_local;
+ pdata->mudq = MIN(Nlocal-1, MAX(0, mudq));
+ pdata->mldq = MIN(Nlocal-1, MAX(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 : RSqrt(uround);
+
+ /* Re-initialize nge */
+ pdata->nge = 0;
+
+ return(IDASPILS_SUCCESS);
+}
+
+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);
+ 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);
+ 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);
+ return(IDASPILS_PMEM_NULL);
+ }
+ pdata = (IBBDPrecData) idaspils_mem->s_pdata;
+
+ *lenrwBBDP = pdata->rpwsize;
+ *leniwBBDP = pdata->ipwsize;
+
+ return(IDASPILS_SUCCESS);
+}
+
+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);
+ 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);
+ 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);
+ return(IDASPILS_PMEM_NULL);
+ }
+ pdata = (IBBDPrecData) idaspils_mem->s_pdata;
+
+ *ngevalsBBDP = pdata->nge;
+
+ return(IDASPILS_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 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 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)
+{
+ int retval;
+ long int ier;
+ IBBDPrecData pdata;
+ IDAMem IDA_mem;
+
+ 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);
+ if (retval < 0) {
+ IDAProcessError(IDA_mem, -1, "IDABBDPRE", "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);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * 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)
+{
+ IBBDPrecData pdata;
+ realtype *zd;
+
+ pdata = (IBBDPrecData) bbd_data;
+
+ /* Copy rvec to zvec, do the backsolve, and return. */
+ N_VScale(ONE, rvec, zvec);
+
+ zd = N_VGetArrayPointer(zvec);
+
+ BandGBTRS(PP, lpivots, zd);
+
+ return(0);
+}
+
+
+
+static void IDABBDPrecFree(IDAMem IDA_mem)
+{
+ IDASpilsMem idaspils_mem;
+ IBBDPrecData pdata;
+
+ if (IDA_mem->ida_lmem == NULL) return;
+ idaspils_mem = (IDASpilsMem) IDA_mem->ida_lmem;
+
+ if (idaspils_mem->s_pdata == NULL) return;
+ pdata = (IBBDPrecData) idaspils_mem->s_pdata;
+
+ DestroyMat(PP);
+ DestroyArray(lpivots);
+ N_VDestroy(tempv4);
+
+ free(pdata);
+ pdata = NULL;
+}
+
+
+#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).
+ * -----------------------------------------------------------------
+ */
+
+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;
+ realtype *ydata, *ypdata, *ytempdata, *yptempdata, *grefdata, *gtempdata;
+ realtype *cnsdata = NULL, *ewtdata;
+ realtype *col_j, conj, yj, ypj, ewtj;
+
+ 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);
+ 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 (retval != 0) return(retval);
+ }
+
+ retval = glocal(Nlocal, tt, yy, yp, gref, user_data);
+ nge++;
+ if (retval != 0) return(retval);
+
+
+ /* Set bandwidth and number of column groups for band differencing. */
+
+ width = mldq + mudq + 1;
+ ngroups = MIN(width, Nlocal);
+
+ /* Loop over groups. */
+ for(group = 1; group <= ngroups; group++) {
+
+ /* Loop over the components in this group. */
+ for(j = group-1; j < Nlocal; j += width) {
+ yj = ydata[j];
+ ypj = ypdata[j];
+ ewtj = ewtdata[j];
+
+ /* 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*MAX(ABS(yj), MAX( ABS(hh*ypj), ONE/ewtj));
+ if (hh*ypj < ZERO) inc = -inc;
+ inc = (yj + inc) - yj;
+
+ /* Adjust sign(inc) again if yj has an inequality constraint. */
+ if (constraints != NULL) {
+ conj = cnsdata[j];
+ if (ABS(conj) == ONE) {if ((yj+inc)*conj < ZERO) inc = -inc;}
+ else if (ABS(conj) == TWO) {if ((yj+inc)*conj <= ZERO) inc = -inc;}
+ }
+
+ /* Increment yj and ypj. */
+ ytempdata[j] += inc;
+ yptempdata[j] += cj*inc;
+
+ }
+
+ /* Evaluate G with incremented y and yp arguments. */
+
+ retval = glocal(Nlocal, tt, ytemp, yptemp, gtemp, user_data);
+ 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) {
+ yj = ytempdata[j] = ydata[j];
+ ypj = yptempdata[j] = ypdata[j];
+ ewtj = ewtdata[j];
+
+ /* Set increment inc as before .*/
+ inc = rel_yy*MAX(ABS(yj), MAX( ABS(hh*ypj), ONE/ewtj));
+ if (hh*ypj < ZERO) inc = -inc;
+ inc = (yj + inc) - yj;
+ if (constraints != NULL) {
+ conj = cnsdata[j];
+ if (ABS(conj) == ONE) {if ((yj+inc)*conj < ZERO) inc = -inc;}
+ else if (ABS(conj) == TWO) {if ((yj+inc)*conj <= ZERO) inc = -inc;}
+ }
+
+ /* Form difference quotients and load into PP. */
+ inc_inv = ONE/inc;
+ col_j = BAND_COL(PP,j);
+ i1 = MAX(0, j-mukeep);
+ i2 = MIN(j+mlkeep, Nlocal-1);
+ for(i = i1; i <= i2; i++) BAND_COL_ELEM(col_j,i,j) =
+ inc_inv * (gtempdata[i] - grefdata[i]);
+ }
+ }
+
+ return(0);
+}
+
diff --git a/src/ida/ida_bbdpre_impl.h b/src/ida/ida_bbdpre_impl.h
new file mode 100644
index 0000000..3affc14
--- /dev/null
+++ b/src/ida/ida_bbdpre_impl.h
@@ -0,0 +1,88 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.5 $
+ * $Date: 2010/12/01 22:35:26 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Alan C. Hindmarsh and Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * 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
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <ida/ida_bbdpre.h>
+#include <sundials/sundials_band.h>
+
+/*
+ * -----------------------------------------------------------------
+ * Definition of IBBDPrecData
+ * -----------------------------------------------------------------
+ */
+
+typedef struct IBBDPrecDataRec {
+
+ /* passed by user to IDABBDPrecAlloc and used by
+ IDABBDPrecSetup/IDABBDPrecSolve functions */
+
+ long int mudq, mldq, mukeep, mlkeep;
+ realtype rel_yy;
+ IDABBDLocalFn glocal;
+ IDABBDCommFn gcomm;
+
+ /* allocated for use by IDABBDPrecSetup */
+
+ 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;
+
+/*
+ * -----------------------------------------------------------------
+ * IDABBDPRE 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_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."
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/ida/ida_dense.c b/src/ida/ida_dense.c
new file mode 100644
index 0000000..a0e241e
--- /dev/null
+++ b/src/ida/ida_dense.c
@@ -0,0 +1,300 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.13 $
+ * $Date: 2011/03/23 20:44:01 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Alan C. Hindmarsh and Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * 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;
+ int flag;
+
+ /* 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) flag = 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;
+
+ 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;
+
+
+ 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
new file mode 100644
index 0000000..b53ca80
--- /dev/null
+++ b/src/ida/ida_direct.c
@@ -0,0 +1,544 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.6 $
+ * $Date: 2010/12/01 22:35:26 $
+ * -----------------------------------------------------------------
+ * Programmer: Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2006, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * This is the implementation file for an IDADLS linear solver.
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * =================================================================
+ * IMPORTED HEADER FILES
+ * =================================================================
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "ida_impl.h"
+#include "ida_direct_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)
+
+/*
+ * =================================================================
+ * 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)
+{
+ IDAMem IDA_mem;
+ IDADlsMem idadls_mem;
+
+ /* Return immediately if ida_mem is NULL */
+ if (ida_mem == NULL) {
+ IDAProcessError(NULL, IDADLS_MEM_NULL, "IDADLS", "IDADlsSetDenseJacFn", MSGD_IDAMEM_NULL);
+ return(IDADLS_MEM_NULL);
+ }
+ IDA_mem = (IDAMem) ida_mem;
+
+ if (lmem == NULL) {
+ IDAProcessError(IDA_mem, IDADLS_LMEM_NULL, "IDADLS", "IDADlsSetDenseJacFn", MSGD_LMEM_NULL);
+ return(IDADLS_LMEM_NULL);
+ }
+ idadls_mem = (IDADlsMem) lmem;
+
+ if (jac != NULL) {
+ jacDQ = FALSE;
+ djac = jac;
+ } else {
+ jacDQ = TRUE;
+ }
+
+ return(IDADLS_SUCCESS);
+}
+
+/*
+ * IDADlsSetBandJacFn specifies the band Jacobian function.
+ */
+int IDADlsSetBandJacFn(void *ida_mem, IDADlsBandJacFn jac)
+{
+ IDAMem IDA_mem;
+ IDADlsMem idadls_mem;
+
+ /* Return immediately if ida_mem is NULL */
+ if (ida_mem == NULL) {
+ IDAProcessError(NULL, IDADLS_MEM_NULL, "IDADLS", "IDADlsSetBandJacFn", 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);
+ return(IDADLS_LMEM_NULL);
+ }
+ idadls_mem = (IDADlsMem) lmem;
+
+ if (jac != NULL) {
+ jacDQ = FALSE;
+ bjac = jac;
+ } else {
+ jacDQ = TRUE;
+ }
+
+ 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)
+{
+ IDAMem IDA_mem;
+ IDADlsMem idadls_mem;
+
+ /* Return immediately if ida_mem is NULL */
+ if (ida_mem == 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);
+ 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;
+ }
+
+ return(IDADLS_SUCCESS);
+}
+
+/*
+ * 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 */
+ if (ida_mem == 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);
+ return(IDADLS_LMEM_NULL);
+ }
+ idadls_mem = (IDADlsMem) lmem;
+
+ *njevals = nje;
+
+ return(IDADLS_SUCCESS);
+}
+
+/*
+ * 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 */
+ if (ida_mem == NULL) {
+ IDAProcessError(NULL, IDADLS_MEM_NULL, "IDADLS", "IDADlsGetNumFctEvals", 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);
+ return(IDADLS_LMEM_NULL);
+ }
+ idadls_mem = (IDADlsMem) lmem;
+
+ *nrevalsLS = nreDQ;
+
+ return(IDADLS_SUCCESS);
+}
+
+/*
+ * IDADlsGetReturnFlagName returns the name associated with a IDALAPACK
+ * return value.
+ */
+char *IDADlsGetReturnFlagName(long int flag)
+{
+ char *name;
+
+ name = (char *)malloc(30*sizeof(char));
+
+ switch(flag) {
+ case IDADLS_SUCCESS:
+ sprintf(name,"IDADLS_SUCCESS");
+ break;
+ case IDADLS_MEM_NULL:
+ sprintf(name,"IDADLS_MEM_NULL");
+ break;
+ case IDADLS_LMEM_NULL:
+ sprintf(name,"IDADLS_LMEM_NULL");
+ break;
+ case IDADLS_ILL_INPUT:
+ sprintf(name,"IDADLS_ILL_INPUT");
+ break;
+ case IDADLS_MEM_FAIL:
+ sprintf(name,"IDADLS_MEM_FAIL");
+ break;
+ case IDADLS_JACFUNC_UNRECVR:
+ sprintf(name,"IDADLS_JACFUNC_UNRECVR");
+ break;
+ case IDADLS_JACFUNC_RECVR:
+ sprintf(name,"IDADLS_JACFUNC_RECVR");
+ break;
+ default:
+ sprintf(name,"NONE");
+ }
+
+ return(name);
+}
+
+/*
+ * IDADlsGetLastFlag returns the last flag set in a IDALAPACK function.
+ */
+int IDADlsGetLastFlag(void *ida_mem, long int *flag)
+{
+ IDAMem IDA_mem;
+ IDADlsMem idadls_mem;
+
+ /* Return immediately if ida_mem is NULL */
+ if (ida_mem == 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);
+ return(IDADLS_LMEM_NULL);
+ }
+ idadls_mem = (IDADlsMem) lmem;
+
+ *flag = 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)
+{
+ realtype inc, inc_inv, yj, ypj, srur, conj;
+ realtype *tmp2_data, *y_data, *yp_data, *ewt_data, *cns_data = NULL;
+ N_Vector rtemp, jthCol;
+ long int j;
+ int retval = 0;
+
+ IDAMem IDA_mem;
+ IDADlsMem idadls_mem;
+
+ /* data points to IDA_mem */
+ IDA_mem = (IDAMem) data;
+ idadls_mem = (IDADlsMem) lmem;
+
+ /* Save pointer to the array in tmp2 */
+ tmp2_data = N_VGetArrayPointer(tmp2);
+
+ /* Rename work vectors for readibility */
+ rtemp = tmp1;
+ jthCol = tmp2;
+
+ /* Obtain pointers to the data for ewt, yy, yp. */
+ ewt_data = N_VGetArrayPointer(ewt);
+ y_data = N_VGetArrayPointer(yy);
+ yp_data = N_VGetArrayPointer(yp);
+ if(constraints!=NULL) cns_data = N_VGetArrayPointer(constraints);
+
+ srur = RSqrt(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);
+ yj = y_data[j];
+ ypj = yp_data[j];
+
+ /* Set increment inc to y_j based on sqrt(uround)*abs(y_j), with
+ 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 = MAX( srur * MAX( ABS(yj), ABS(hh*ypj) ) , ONE/ewt_data[j] );
+
+ if (hh*ypj < ZERO) inc = -inc;
+ inc = (yj + inc) - yj;
+
+ /* Adjust sign(inc) again if y_j has an inequality constraint. */
+ if (constraints != NULL) {
+ conj = cns_data[j];
+ if (ABS(conj) == ONE) {if((yj+inc)*conj < ZERO) inc = -inc;}
+ else if (ABS(conj) == TWO) {if((yj+inc)*conj <= ZERO) inc = -inc;}
+ }
+
+ /* Increment y_j and yp_j, call res, and break on error return. */
+ y_data[j] += inc;
+ yp_data[j] += c_j*inc;
+
+ retval = res(tt, yy, yp, rtemp, user_data);
+ 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);
+
+ /* reset y_j, yp_j */
+ y_data[j] = yj;
+ yp_data[j] = ypj;
+ }
+
+ /* Restore original array pointer in tmp2 */
+ N_VSetArrayPointer(tmp2_data, tmp2);
+
+ 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)
+{
+ 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;
+ 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. */
+
+
+ yptemp= tmp3; /* Rename work vector for use as a temporary for yp. */
+
+ /* 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);
+
+ rtemp_data = N_VGetArrayPointer(rtemp);
+ ytemp_data = N_VGetArrayPointer(ytemp);
+ yptemp_data = N_VGetArrayPointer(yptemp);
+
+ if (constraints != NULL) cns_data = N_VGetArrayPointer(constraints);
+
+ /* Initialize ytemp and yptemp. */
+
+ N_VScale(ONE, yy, ytemp);
+ N_VScale(ONE, yp, yptemp);
+
+ /* Compute miscellaneous values for the Jacobian computation. */
+
+ srur = RSqrt(uround);
+ width = mlower + mupper + 1;
+ ngroups = MIN(width, N);
+
+ /* Loop over column groups. */
+ 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];
+ ewtj = ewt_data[j];
+
+ /* 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 = MAX( srur * MAX( ABS(yj), ABS(hh*ypj) ) , ONE/ewtj );
+
+ if (hh*ypj < ZERO) inc = -inc;
+ inc = (yj + inc) - yj;
+
+ /* Adjust sign(inc) again if yj has an inequality constraint. */
+
+ if (constraints != NULL) {
+ conj = cns_data[j];
+ if (ABS(conj) == ONE) {if((yj+inc)*conj < ZERO) inc = -inc;}
+ else if (ABS(conj) == TWO) {if((yj+inc)*conj <= ZERO) inc = -inc;}
+ }
+
+ /* Increment yj and ypj. */
+
+ ytemp_data[j] += inc;
+ yptemp_data[j] += cj*inc;
+ }
+
+ /* Call res routine with incremented arguments. */
+
+ retval = res(tt, ytemp, yptemp, rtemp, user_data);
+ 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);
+ ewtj = ewt_data[j];
+
+ /* Set increment inc exactly as above. */
+
+ inc = MAX( srur * MAX( ABS(yj), ABS(hh*ypj) ) , ONE/ewtj );
+ if (hh*ypj < ZERO) inc = -inc;
+ inc = (yj + inc) - yj;
+ if (constraints != NULL) {
+ conj = cns_data[j];
+ if (ABS(conj) == ONE) {if((yj+inc)*conj < ZERO) inc = -inc;}
+ else if (ABS(conj) == TWO) {if((yj+inc)*conj <= ZERO) inc = -inc;}
+ }
+
+ /* Load the difference quotient Jacobian elements for column j. */
+
+ inc_inv = ONE/inc;
+ i1 = MAX(0, j-mupper);
+ i2 = MIN(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]);
+ }
+
+ }
+
+ return(retval);
+
+}
diff --git a/src/ida/ida_direct_impl.h b/src/ida/ida_direct_impl.h
new file mode 100644
index 0000000..c887899
--- /dev/null
+++ b/src/ida/ida_direct_impl.h
@@ -0,0 +1,102 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.7 $
+ * $Date: 2010/12/01 22:35:26 $
+ * -----------------------------------------------------------------
+ * Programmer: Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2006, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * Implementation header file for the IDADLS linear solvers.
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _IDADLS_IMPL_H
+#define _IDADLS_IMPL_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <ida/ida_direct.h>
+
+/*
+ * =================================================================
+ * 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.
+ * -----------------------------------------------------------------
+ */
+
+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 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 */
+
+ DlsMat d_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 */
+
+ long int d_nje; /* nje = no. of calls to jac */
+
+ long int d_nreDQ; /* no. of calls to res due to DQ Jacobian approx.*/
+
+ long int d_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);
+
+/*
+ * =================================================================
+ * E R R O R M E S S A G E S
+ * =================================================================
+ */
+
+#define MSGD_IDAMEM_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_JACFUNC_FAILED "The Jacobian routine failed in an unrecoverable manner."
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/ida/ida_ic.c b/src/ida/ida_ic.c
new file mode 100644
index 0000000..43bafc2
--- /dev/null
+++ b/src/ida/ida_ic.c
@@ -0,0 +1,728 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.3 $
+ * $Date: 2007/04/30 19:29:00 $
+ * -----------------------------------------------------------------
+ * Programmers: Alan C. Hindmarsh, and Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California
+ * Produced at the Lawrence Livermore National Laboratory
+ * All rights reserved
+ * For details, see the LICENSE file
+ * -----------------------------------------------------------------
+ * This is the implementation file for the IC calculation for IDA.
+ * It is independent of the linear solver in use.
+ * -----------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "ida_impl.h"
+#include <sundials/sundials_math.h>
+
+/* Macro: loop */
+#define loop for(;;)
+
+/*
+ * =================================================================
+ * IDA Constants
+ * =================================================================
+ */
+
+/* Private Constants */
+
+#define ZERO RCONST(0.0) /* real 0.0 */
+#define HALF RCONST(0.5) /* real 0.5 */
+#define ONE RCONST(1.0) /* real 1.0 */
+#define TWO RCONST(2.0) /* real 2.0 */
+#define PT99 RCONST(0.99) /* real 0.99 */
+#define PT1 RCONST(0.1) /* real 0.1 */
+#define PT001 RCONST(0.001) /* real 0.001 */
+
+/* IDACalcIC control constants */
+
+#define ICRATEMAX RCONST(0.9) /* max. Newton conv. rate */
+#define ALPHALS RCONST(0.0001) /* alpha in linesearch conv. test */
+
+/* Return values for lower level routines used by IDACalcIC */
+
+#define IC_FAIL_RECOV 1
+#define IC_CONSTR_FAILED 2
+#define IC_LINESRCH_FAILED 3
+#define IC_CONV_FAIL 4
+#define IC_SLOW_CONVRG 5
+
+/*
+ * =================================================================
+ * Private Helper Functions Prototypes
+ * =================================================================
+ */
+
+extern int IDAInitialSetup(IDAMem IDA_mem);
+extern realtype IDAWrmsNorm(IDAMem IDA_mem, N_Vector x, N_Vector w,
+ booleantype mask);
+
+static int IDAnlsIC(IDAMem IDA_mem);
+static int IDANewtonIC(IDAMem IDA_mem);
+static int IDALineSrch(IDAMem IDA_mem, realtype *delnorm, realtype *fnorm);
+static int IDAfnorm(IDAMem IDA_mem, realtype *fnorm);
+static int IDANewyyp(IDAMem IDA_mem, realtype lambda);
+static int IDANewy(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 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
+ * =================================================================
+ */
+
+/*
+ * -----------------------------------------------------------------
+ * IDACalcIC
+ * -----------------------------------------------------------------
+ * IDACalcIC computes consistent initial conditions, given the
+ * user's initial guess for unknown components of yy0 and/or yp0.
+ *
+ * The return value is IDA_SUCCESS = 0 if no error occurred.
+ *
+ * The error return values (fully described in ida.h) are:
+ * IDA_MEM_NULL ida_mem is NULL
+ * IDA_NO_MALLOC ida_mem was not allocated
+ * IDA_ILL_INPUT bad value for icopt, tout1, or id
+ * IDA_LINIT_FAIL the linear solver linit routine failed
+ * IDA_BAD_EWT zero value of some component of ewt
+ * IDA_RES_FAIL res had a non-recoverable error
+ * IDA_FIRST_RES_FAIL res failed recoverably on the first call
+ * IDA_LSETUP_FAIL lsetup had a non-recoverable error
+ * IDA_LSOLVE_FAIL lsolve had a non-recoverable error
+ * IDA_NO_RECOVERY res, lsetup, or lsolve had a recoverable
+ * error, but IDACalcIC could not recover
+ * IDA_CONSTR_FAIL the inequality constraints could not be met
+ * IDA_LINESEARCH_FAIL the linesearch failed (on steptol test)
+ * IDA_CONV_FAIL the Newton iterations failed to converge
+ * -----------------------------------------------------------------
+ */
+
+int IDACalcIC(void *ida_mem, int icopt, realtype tout1)
+{
+ int ewtsetOK;
+ int ier, nwt, nh, mxnh, icret, retval=0;
+ realtype tdist, troundoff, minid, hic, ypnorm;
+ IDAMem IDA_mem;
+
+ /* Check if IDA memory exists */
+
+ if(ida_mem == NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDACalcIC", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+ IDA_mem = (IDAMem) ida_mem;
+
+ /* Check if problem was malloc'ed */
+
+ if(IDA_mem->ida_MallocDone == FALSE) {
+ IDAProcessError(IDA_mem, IDA_NO_MALLOC, "IDA", "IDACalcIC", MSG_NO_MALLOC);
+ return(IDA_NO_MALLOC);
+ }
+
+ /* Check inputs to IDA for correctness and consistency */
+
+ ier = IDAInitialSetup(IDA_mem);
+ if(ier != IDA_SUCCESS) return(IDA_ILL_INPUT);
+ IDA_mem->ida_SetupDone = TRUE;
+
+ /* Check legality of input arguments, and set IDA memory copies. */
+
+ if(icopt != IDA_YA_YDP_INIT && icopt != IDA_Y_INIT) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDACalcIC", MSG_IC_BAD_ICOPT);
+ return(IDA_ILL_INPUT);
+ }
+ IDA_mem->ida_icopt = icopt;
+
+ if(icopt == IDA_YA_YDP_INIT && (id == NULL)) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDACalcIC", MSG_IC_MISSING_ID);
+ return(IDA_ILL_INPUT);
+ }
+
+ tdist = ABS(tout1 - tn);
+ troundoff = TWO*uround*(ABS(tn) + ABS(tout1));
+ if(tdist < troundoff) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDACalcIC", MSG_IC_TOO_CLOSE);
+ return(IDA_ILL_INPUT);
+ }
+
+ /* 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);
+
+ /* 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);
+ if(minid < ZERO) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDACalcIC", MSG_IC_BAD_ID);
+ return(IDA_ILL_INPUT);
+ }
+ if(minid > HALF) IDA_mem->ida_sysindex = 0;
+ }
+
+ /* Set the test constant in the Newton convergence test */
+
+ IDA_mem->ida_epsNewt = epiccon;
+
+ /* Initializations:
+ cjratio = 1 (for use in direct linear solvers);
+ set nbacktr = 0; */
+
+ cjratio = ONE;
+ nbacktr = 0;
+
+ /* Set hic, hh, cj, and mxnh. */
+
+ hic = PT001*tdist;
+ ypnorm = IDAWrmsNorm(IDA_mem, yp0, ewt, suppressalg);
+ if(ypnorm > HALF/hic) hic = HALF/ypnorm;
+ if(tout1 < tn) hic = -hic;
+ hh = hic;
+ if(icopt == IDA_YA_YDP_INIT) {
+ cj = ONE/hic;
+ mxnh = maxnh;
+ }
+ else {
+ cj = ZERO;
+ mxnh = 1;
+ }
+
+ /* Loop over nwt = number of evaluations of ewt vector. */
+
+ for(nwt = 1; nwt <= 2; nwt++) {
+
+ /* Loop over nh = number of h values. */
+ for(nh = 1; nh <= mxnh; nh++) {
+
+ /* Call the IC nonlinear solver function. */
+ retval = IDAnlsIC(IDA_mem);
+
+ /* Cut h and loop on recoverable IDA_YA_YDP_INIT failure; else break. */
+ if(retval == IDA_SUCCESS) break;
+ 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);
+ }
+ hic *= PT1;
+ cj = ONE/hic;
+ 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);
+ if(ewtsetOK != 0) {
+ retval = IDA_BAD_EWT;
+ break;
+ }
+ N_VScale(ONE, yy0, phi[0]);
+ N_VScale(ONE, yp0, phi[1]);
+
+ } /* End of nwt loop */
+
+ /* Free temporary space */
+
+ N_VDestroy(yy0);
+ N_VDestroy(yp0);
+
+ /* Load the optional outputs. */
+
+ if(icopt == IDA_YA_YDP_INIT) hused = hic;
+
+ /* On any failure, print message and return proper flag. */
+
+ if(retval != IDA_SUCCESS) {
+ icret = IDAICFailFlag(IDA_mem, retval);
+ return(icret);
+ }
+
+ /* Otherwise return success flag. */
+
+ return(IDA_SUCCESS);
+
+}
+
+/*
+ * =================================================================
+ * PRIVATE FUNCTIONS IMPLEMENTATION
+ * =================================================================
+ */
+
+#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
+ * -----------------------------------------------------------------
+ * IDAnlsIC solves a nonlinear system for consistent initial
+ * conditions. It calls IDANewtonIC to do most of the work.
+ *
+ * The return value is IDA_SUCCESS = 0 if no error occurred.
+ * The error return values (positive) considered recoverable are:
+ * IC_FAIL_RECOV if res, lsetup, or lsolve failed recoverably
+ * IC_CONSTR_FAILED if the constraints could not be met
+ * IC_LINESRCH_FAILED if the linesearch failed (on steptol test)
+ * IC_CONV_FAIL if the Newton iterations failed to converge
+ * IC_SLOW_CONVRG if the iterations are converging slowly
+ * (failed the convergence test, but showed
+ * norm reduction or convergence rate < 1)
+ * The error return values (negative) considered non-recoverable are:
+ * IDA_RES_FAIL if res had a non-recoverable error
+ * IDA_FIRST_RES_FAIL if res failed recoverably on the first call
+ * IDA_LSETUP_FAIL if lsetup had a non-recoverable error
+ * IDA_LSOLVE_FAIL if lsolve had a non-recoverable error
+ * -----------------------------------------------------------------
+ */
+
+static int IDAnlsIC (IDAMem IDA_mem)
+{
+ int retval, nj;
+ N_Vector tv1, tv2, tv3;
+
+ tv1 = ee;
+ tv2 = tempv2;
+ tv3 = phi[2];
+
+ retval = res(t0, yy0, yp0, delta, user_data);
+ nre++;
+ if(retval < 0) return(IDA_RES_FAIL);
+ if(retval > 0) return(IDA_FIRST_RES_FAIL);
+
+ N_VScale(ONE, delta, savres);
+
+ /* Loop over nj = number of linear solve Jacobian setups. */
+
+ for(nj = 1; nj <= maxnj; nj++) {
+
+ /* If there is a setup routine, call it. */
+ if(setupNonNull) {
+ nsetups++;
+ retval = lsetup(IDA_mem, yy0, yp0, delta, tv1, tv2, tv3);
+ if(retval < 0) return(IDA_LSETUP_FAIL);
+ if(retval > 0) return(IC_FAIL_RECOV);
+ }
+
+ /* Call the Newton iteration routine, and return if successful. */
+ retval = IDANewtonIC(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);
+ continue;
+ } else {
+ return(retval);
+ }
+
+ } /* End of nj loop */
+
+ /* No convergence after maxnj tries; return with retval=IC_SLOW_CONVRG */
+ return(retval);
+
+}
+
+/*
+ * -----------------------------------------------------------------
+ * IDANewtonIC
+ * -----------------------------------------------------------------
+ * IDANewtonIC performs the Newton iteration to solve for consistent
+ * initial conditions. It calls IDALineSrch within each iteration.
+ * On return, savres contains the current residual vector.
+ *
+ * The return value is IDA_SUCCESS = 0 if no error occurred.
+ * The error return values (positive) considered recoverable are:
+ * IC_FAIL_RECOV if res or lsolve failed recoverably
+ * IC_CONSTR_FAILED if the constraints could not be met
+ * IC_LINESRCH_FAILED if the linesearch failed (on steptol test)
+ * IC_CONV_FAIL if the Newton iterations failed to converge
+ * IC_SLOW_CONVRG if the iterations appear to be converging slowly.
+ * They failed the convergence test, but showed
+ * an overall norm reduction (by a factor of < 0.1)
+ * or a convergence rate <= ICRATEMAX).
+ * The error return values (negative) considered non-recoverable are:
+ * IDA_RES_FAIL if res had a non-recoverable error
+ * IDA_LSOLVE_FAIL if lsolve had a non-recoverable error
+ * -----------------------------------------------------------------
+ */
+
+static int IDANewtonIC(IDAMem IDA_mem)
+{
+ int retval, mnewt;
+ realtype delnorm, fnorm, fnorm0, oldfnrm, rate;
+
+ /* Set pointer for vector delnew */
+ delnew = phi[2];
+
+ /* Call the linear solve function to get the Newton step, delta. */
+ retval = lsolve(IDA_mem, delta, ewt, yy0, yp0, 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*ABS(cj);
+ if(fnorm <= epsNewt) return(IDA_SUCCESS);
+ fnorm0 = fnorm;
+
+ /* Initialize rate to avoid compiler warning message */
+ rate = ZERO;
+
+ /* Newton iteration loop */
+
+ for(mnewt = 0; mnewt < maxnit; mnewt++) {
+
+ nni++;
+ delnorm = fnorm;
+ oldfnrm = fnorm;
+
+ /* Call the Linesearch function and return if it failed. */
+ retval = IDALineSrch(IDA_mem, &delnorm, &fnorm);
+ if(retval != IDA_SUCCESS) return(retval);
+
+ /* Set the observed convergence rate and test for convergence. */
+ rate = fnorm/oldfnrm;
+ if(fnorm <= epsNewt) return(IDA_SUCCESS);
+
+ /* If not converged, copy new step vector, and loop. */
+ N_VScale(ONE, delnew, delta);
+
+ } /* End of Newton iteration loop */
+
+ /* Return either IC_SLOW_CONVRG or recoverable fail flag. */
+ if(rate <= ICRATEMAX || fnorm < PT1*fnorm0) return(IC_SLOW_CONVRG);
+ return(IC_CONV_FAIL);
+
+}
+
+
+/*
+ * -----------------------------------------------------------------
+ * IDALineSrch
+ * -----------------------------------------------------------------
+ * IDALineSrch performs the Linesearch algorithm with the
+ * calculation of consistent initial conditions.
+ *
+ * On entry, yy0 and yp0 are the current values of y and y', the
+ * Newton step is delta, the current residual vector F is savres,
+ * delnorm is WRMS-norm(delta), and fnorm is the norm of the vector
+ * J-inverse F.
+ *
+ * On a successful return, yy0, yp0, and savres have been updated,
+ * delnew contains the current value of J-inverse F, and fnorm is
+ * WRMS-norm(delnew).
+ *
+ * The return value is IDA_SUCCESS = 0 if no error occurred.
+ * The error return values (positive) considered recoverable are:
+ * IC_FAIL_RECOV if res or lsolve failed recoverably
+ * IC_CONSTR_FAILED if the constraints could not be met
+ * IC_LINESRCH_FAILED if the linesearch failed (on steptol test)
+ * The error return values (negative) considered non-recoverable are:
+ * IDA_RES_FAIL if res had a non-recoverable error
+ * IDA_LSOLVE_FAIL if lsolve had a non-recoverable error
+ * -----------------------------------------------------------------
+ */
+
+static int IDALineSrch(IDAMem IDA_mem, realtype *delnorm, realtype *fnorm)
+{
+ booleantype conOK;
+ int retval;
+ realtype f1norm, fnormp, f1normp, ratio, lambda, minlam, slpi;
+ N_Vector mc;
+
+ /* 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;
+ f1norm = (*fnorm)*(*fnorm)*HALF;
+ ratio = ONE;
+
+ /* If there are constraints, check and reduce step if necessary. */
+ if(constraintsSet) {
+
+ /* Update y and check constraints. */
+ IDANewy(IDA_mem);
+ conOK = N_VConstrMask(constraints, ynew, mc);
+
+ if(!conOK) {
+ /* Not satisfied. Compute scaled step to satisfy constraints. */
+ N_VProd(mc, delta, dtemp);
+ ratio = PT99*N_VMinQuotient(yy0, dtemp);
+ (*delnorm) *= ratio;
+ if((*delnorm) <= steptol) return(IC_CONSTR_FAILED);
+ N_VScale(ratio, delta, delta);
+ }
+
+ } /* End of constraints check */
+
+ slpi = -TWO*f1norm*ratio;
+ minlam = steptol/(*delnorm);
+ lambda = ONE;
+
+ /* In IDA_Y_INIT case, set ypnew = yp0 (fixed) for linesearch. */
+ if(icopt == IDA_Y_INIT) N_VScale(ONE, yp0, ypnew);
+
+ /* Loop on linesearch variable lambda. */
+
+ loop {
+
+ /* 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;
+
+ /* 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++;
+
+ } /* 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);
+ *fnorm = fnormp;
+ return(IDA_SUCCESS);
+
+}
+
+/*
+ * -----------------------------------------------------------------
+ * IDAfnorm
+ * -----------------------------------------------------------------
+ * IDAfnorm computes the norm of the current function value, by
+ * evaluating the DAE residual function, calling the linear
+ * system solver, and computing a WRMS-norm.
+ *
+ * On return, savres contains the current residual vector F, and
+ * delnew contains J-inverse F.
+ *
+ * The return value is IDA_SUCCESS = 0 if no error occurred, or
+ * IC_FAIL_RECOV if res or lsolve failed recoverably, or
+ * IDA_RES_FAIL if res had a non-recoverable error, or
+ * IDA_LSOLVE_FAIL if lsolve had a non-recoverable error.
+ * -----------------------------------------------------------------
+ */
+
+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++;
+ if(retval < 0) return(IDA_RES_FAIL);
+ if(retval > 0) return(IC_FAIL_RECOV);
+
+ N_VScale(ONE, delnew, savres);
+
+ /* Call the linear solve function to get J-inverse F; return if failed. */
+ retval = lsolve(IDA_mem, delnew, ewt, ynew, ypnew, 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*ABS(cj);
+
+ return(IDA_SUCCESS);
+
+}
+
+/*
+ * -----------------------------------------------------------------
+ * IDANewyyp
+ * -----------------------------------------------------------------
+ * IDANewyyp updates the vectors ynew and ypnew from yy0 and yp0,
+ * using the current step vector lambda*delta, in a manner
+ * depending on icopt and the input id vector.
+ *
+ * The return value is always IDA_SUCCESS = 0.
+ * -----------------------------------------------------------------
+ */
+
+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);
+ return(IDA_SUCCESS);
+ }
+
+ /* IDA_Y_INIT case: ynew = yy0 - lambda*delta. (ypnew = yp0 preset.) */
+ N_VLinearSum(ONE, yy0, -lambda, delta, ynew);
+ return(IDA_SUCCESS);
+
+}
+
+/*
+ * -----------------------------------------------------------------
+ * IDANewy
+ * -----------------------------------------------------------------
+ * IDANewy updates the vector ynew from yy0,
+ * using the current step vector delta, in a manner
+ * depending on icopt and the input id vector.
+ *
+ * The return value is always IDA_SUCCESS = 0.
+ * -----------------------------------------------------------------
+ */
+
+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);
+ return(IDA_SUCCESS);
+ }
+
+ /* IDA_Y_INIT case: ynew = yy0 - delta. */
+ N_VLinearSum(ONE, yy0, -ONE, delta, ynew);
+ return(IDA_SUCCESS);
+
+}
+
+/*
+ * -----------------------------------------------------------------
+ * IDAICFailFlag
+ * -----------------------------------------------------------------
+ * IDAICFailFlag prints a message and sets the IDACalcIC return
+ * value appropriate to the flag retval returned by IDAnlsIC.
+ * -----------------------------------------------------------------
+ */
+
+static int IDAICFailFlag(IDAMem IDA_mem, int retval)
+{
+
+ /* Depending on retval, print error message and return error flag. */
+ switch(retval) {
+
+ case IDA_RES_FAIL:
+ IDAProcessError(IDA_mem, IDA_RES_FAIL, "IDA", "IDACalcIC", MSG_IC_RES_NONREC);
+ return(IDA_RES_FAIL);
+
+ case IDA_FIRST_RES_FAIL:
+ IDAProcessError(IDA_mem, IDA_FIRST_RES_FAIL, "IDA", "IDACalcIC", MSG_IC_RES_FAIL);
+ return(IDA_FIRST_RES_FAIL);
+
+ case IDA_LSETUP_FAIL:
+ IDAProcessError(IDA_mem, IDA_LSETUP_FAIL, "IDA", "IDACalcIC", MSG_IC_SETUP_FAIL);
+ return(IDA_LSETUP_FAIL);
+
+ case IDA_LSOLVE_FAIL:
+ IDAProcessError(IDA_mem, IDA_LSOLVE_FAIL, "IDA", "IDACalcIC", MSG_IC_SOLVE_FAIL);
+ return(IDA_LSOLVE_FAIL);
+
+ case IC_FAIL_RECOV:
+ IDAProcessError(IDA_mem, IDA_NO_RECOVERY, "IDA", "IDACalcIC", MSG_IC_NO_RECOVERY);
+ return(IDA_NO_RECOVERY);
+
+ case IC_CONSTR_FAILED:
+ IDAProcessError(IDA_mem, IDA_CONSTR_FAIL, "IDA", "IDACalcIC", MSG_IC_FAIL_CONSTR);
+ return(IDA_CONSTR_FAIL);
+
+ case IC_LINESRCH_FAILED:
+ IDAProcessError(IDA_mem, IDA_LINESEARCH_FAIL, "IDA", "IDACalcIC", MSG_IC_FAILED_LINS);
+ return(IDA_LINESEARCH_FAIL);
+
+ case IC_CONV_FAIL:
+ IDAProcessError(IDA_mem, IDA_CONV_FAIL, "IDA", "IDACalcIC", MSG_IC_CONV_FAILED);
+ return(IDA_CONV_FAIL);
+
+ case IC_SLOW_CONVRG:
+ IDAProcessError(IDA_mem, IDA_CONV_FAIL, "IDA", "IDACalcIC", MSG_IC_CONV_FAILED);
+ return(IDA_CONV_FAIL);
+
+ case IDA_BAD_EWT:
+ IDAProcessError(IDA_mem, IDA_BAD_EWT, "IDA", "IDACalcIC", MSG_IC_BAD_EWT);
+ return(IDA_BAD_EWT);
+
+ }
+ return -99;
+}
+
diff --git a/src/ida/ida_impl.h b/src/ida/ida_impl.h
new file mode 100644
index 0000000..331ac1f
--- /dev/null
+++ b/src/ida/ida_impl.h
@@ -0,0 +1,485 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.15 $
+ * $Date: 2009/09/09 22:25:05 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Allan G. Taylor, Alan C. Hindmarsh, Radu Serban,
+ * and Aaron Collier @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * This is the header file (private version) for the main IDA solver.
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _IDA_IMPL_H
+#define _IDA_IMPL_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <stdarg.h>
+
+#include <ida/ida.h>
+
+/*
+ * =================================================================
+ * M A I N I N T E G R A T O R M E M O R Y B L O C K
+ * =================================================================
+ */
+
+
+/* Basic IDA constants */
+
+#define HMAX_INV_DEFAULT RCONST(0.0) /* hmax_inv default value */
+#define MAXORD_DEFAULT 5 /* maxord default value */
+#define MXORDP1 6 /* max. number of N_Vectors in phi */
+#define MXSTEP_DEFAULT 500 /* mxstep default value */
+
+/*
+ * ----------------------------------------------------------------
+ * Types : struct IDAMemRec, IDAMem
+ * ----------------------------------------------------------------
+ * The type IDAMem is type pointer to struct IDAMemRec. This
+ * structure contains fields to keep track of problem state.
+ * ----------------------------------------------------------------
+ */
+
+typedef struct IDAMemRec {
+
+ realtype ida_uround; /* machine unit roundoff */
+
+ /* Problem Specification Data */
+
+ IDAResFn ida_res; /* F(t,y(t),y'(t))=0; the function F */
+ void *ida_user_data; /* user pointer passed to res */
+
+ int ida_itol; /* itol = IDA_SS, IDA_SV, IDA_WF, IDA_NN */
+ 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 */
+ 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
+ in local error tests */
+
+ /* Divided differences array and associated minor arrays */
+
+ N_Vector ida_phi[MXORDP1]; /* phi = (maxord+1) arrays of divided differences */
+
+ realtype ida_psi[MXORDP1]; /* differences in t (sums of recent step sizes) */
+ realtype ida_alpha[MXORDP1]; /* ratios of current stepsize to psi values */
+ realtype ida_beta[MXORDP1]; /* ratios of current to previous product of psi's */
+ realtype ida_sigma[MXORDP1]; /* product successive alpha values and factorial */
+ realtype ida_gamma[MXORDP1]; /* sum of reciprocals of psi values */
+
+ /* N_Vectors */
+
+ N_Vector ida_ewt; /* error weight vector */
+ N_Vector ida_yy; /* work space for y vector (= user's yret) */
+ N_Vector ida_yp; /* work space for y' vector (= user's ypret) */
+ N_Vector ida_delta; /* residual vector */
+ N_Vector ida_id; /* bit vector for diff./algebraic components */
+ N_Vector ida_constraints; /* vector of inequality constraint options */
+ N_Vector ida_savres; /* saved residual vector (= tempv1) */
+ N_Vector ida_ee; /* accumulated corrections to y vector, but
+ set equal to estimated local errors upon
+ successful return */
+ N_Vector ida_mm; /* mask vector in constraints tests (= tempv2) */
+ N_Vector ida_tempv1; /* work space vector */
+ N_Vector ida_tempv2; /* work space vector */
+ N_Vector ida_ynew; /* work vector for y in IDACalcIC (= tempv2) */
+ N_Vector ida_ypnew; /* work vector for yp in IDACalcIC (= ee) */
+ N_Vector ida_delnew; /* work vector for delta in IDACalcIC (= phi[2]) */
+ N_Vector ida_dtemp; /* work vector in IDACalcIC (= phi[3]) */
+
+ /* Variables for use by IDACalcIC*/
+
+ realtype ida_t0; /* initial t */
+ N_Vector ida_yy0; /* initial y vector (user-supplied). */
+ N_Vector ida_yp0; /* initial y' vector (user-supplied). */
+
+ int ida_icopt; /* IC calculation user option */
+ booleantype ida_lsoff; /* IC calculation linesearch turnoff option */
+ int ida_maxnh; /* max. number of h tries in IC calculation */
+ int ida_maxnj; /* max. number of J tries in IC calculation */
+ int ida_maxnit; /* max. number of Netwon iterations in IC calc. */
+ int ida_nbacktr; /* number of IC linesearch backtrack operations */
+ int ida_sysindex; /* computed system index (0 or 1) */
+ realtype ida_epiccon; /* IC nonlinear convergence test constant */
+ realtype ida_steptol; /* minimum Newton step size in IC calculation */
+ realtype ida_tscale; /* time scale factor = abs(tout1 - t0) */
+
+ /* Tstop information */
+
+ booleantype ida_tstopset;
+ realtype ida_tstop;
+
+ /* Step Data */
+
+ int ida_kk; /* current BDF method order */
+ int ida_kused; /* method order used on last successful step */
+ int ida_knew; /* order for next step from order decrease decision */
+ int ida_phase; /* flag to trigger step doubling in first few steps */
+ int ida_ns; /* counts steps at fixed stepsize and order */
+
+ realtype ida_hin; /* initial step */
+ realtype ida_h0u; /* actual initial stepsize */
+ realtype ida_hh; /* current step size h */
+ realtype ida_hused; /* step size used on last successful step */
+ realtype ida_rr; /* rr = hnext / hused */
+ realtype ida_tn; /* current internal value of t */
+ realtype ida_tretlast; /* value of tret previously returned by IDASolve */
+ realtype ida_cj; /* current value of scalar (-alphas/hh) in Jacobian */
+ realtype ida_cjlast; /* cj value saved from last successful step */
+ realtype ida_cjold; /* cj value saved from last call to lsetup */
+ realtype ida_cjratio; /* ratio of cj values: cj/cjold */
+ realtype ida_ss; /* scalar used in Newton iteration convergence test */
+ realtype ida_epsNewt; /* test constant in Newton convergence test */
+ realtype ida_epcon; /* coeficient of the Newton covergence test */
+ realtype ida_toldel; /* tolerance in direct test on Newton corrections */
+
+ /* Limits */
+
+ int ida_maxncf; /* max numer of convergence failures */
+ int ida_maxcor; /* max number of Newton corrections */
+ int ida_maxnef; /* max number of error test failures */
+
+ int ida_maxord; /* max value of method order k: */
+ int ida_maxord_alloc; /* value of maxord used when allocating memory */
+ long int ida_mxstep; /* max number of internal steps for one user call */
+ realtype ida_hmax_inv; /* inverse of max. step size hmax (default = 0.0) */
+
+ /* Counters */
+
+ long int ida_nst; /* number of internal steps taken */
+ long int ida_nre; /* number of function (res) calls */
+ long int ida_ncfn; /* number of corrector convergence failures */
+ long int ida_netf; /* number of error test failures */
+ long int ida_nni; /* number of Newton iterations performed */
+ long int ida_nsetups; /* number of lsetup calls */
+
+ /* 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 */
+ long int ida_lrw; /* number of realtype words in IDA work vectors */
+ long int ida_liw; /* no. of integer words in IDA work vectors */
+
+ realtype ida_tolsf; /* tolerance scale factor (saved value) */
+
+ /* Error handler function and error ouput file */
+
+ IDAErrHandlerFn ida_ehfun; /* Error messages are handled by ehfun */
+ void *ida_eh_data; /* dats pointer passed to ehfun */
+ FILE *ida_errfp; /* IDA error messages are sent to errfp */
+
+ /* 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_VatolMallocDone;
+ booleantype ida_constraintsMallocDone;
+ booleantype ida_idMallocDone;
+
+ booleantype ida_MallocDone; /* set to FALSE by IDACreate
+ set to TRUE by IDAMAlloc
+ tested by IDAReInit and IDASolve */
+
+ /* Linear Solver Data */
+
+ /* Linear Solver functions to be called */
+
+ int (*ida_linit)(struct IDAMemRec *idamem);
+
+ int (*ida_lsetup)(struct IDAMemRec *idamem, N_Vector yyp,
+ N_Vector ypp, N_Vector resp,
+ N_Vector tempv1, N_Vector tempv2, N_Vector tempv3);
+
+ int (*ida_lsolve)(struct IDAMemRec *idamem, N_Vector b, N_Vector weight,
+ N_Vector ycur, N_Vector ypcur, N_Vector rescur);
+
+ int (*ida_lperf)(struct IDAMemRec *idamem, int perftask);
+
+ int (*ida_lfree)(struct IDAMemRec *idamem);
+
+ /* Linear Solver specific memory */
+
+ void *ida_lmem;
+
+ /* Flag to indicate successful ida_linit call */
+
+ booleantype ida_linitOK;
+
+ /* Rootfinding Data */
+
+ IDARootFn ida_gfun; /* Function g for roots sought */
+ int ida_nrtfn; /* number of components of g */
+ int *ida_iroots; /* array for root information */
+ int *ida_rootdir; /* array specifying direction of zero-crossing */
+ realtype ida_tlo; /* nearest endpoint of interval in root search */
+ realtype ida_thi; /* farthest endpoint of interval in root search */
+ realtype ida_trout; /* t return value from rootfinder routine */
+ realtype *ida_glo; /* saved array of g values at t = tlo */
+ realtype *ida_ghi; /* saved array of g values at t = thi */
+ realtype *ida_grout; /* array of g values at t = trout */
+ realtype ida_toutc; /* copy of tout (if NORMAL mode) */
+ realtype ida_ttol; /* tolerance on root location */
+ int ida_taskc; /* copy of parameter itask */
+ int ida_irfnd; /* flag showing whether last step had a root */
+ long int ida_nge; /* counter for g evaluations */
+ booleantype *ida_gactive; /* array with active/inactive event functions */
+ int ida_mxgnull; /* number of warning messages about possible g==0 */
+
+
+} *IDAMem;
+
+/*
+ * =================================================================
+ * I N T E R F A C E T O L I N E A R S O L V E R S
+ * =================================================================
+ */
+
+/*
+ * -----------------------------------------------------------------
+ * int (*ida_linit)(IDAMem IDA_mem);
+ * -----------------------------------------------------------------
+ * The purpose of ida_linit is to allocate memory for the
+ * solver-specific fields in the structure *(idamem->ida_lmem) and
+ * perform any needed initializations of solver-specific memory,
+ * such as counters/statistics. An (*ida_linit) should return
+ * 0 if it has successfully initialized the IDA linear solver and
+ * a non-zero value otherwise. If an error does occur, an appropriate
+ * message should be sent to the error handler function.
+ * ----------------------------------------------------------------
+ */
+
+/*
+ * -----------------------------------------------------------------
+ * int (*ida_lsetup)(IDAMem IDA_mem, N_Vector yyp, N_Vector ypp,
+ * 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:
+ *
+ * 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.
+ *
+ * ypp - the predicted y' vector for the current IDA internal
+ * step.
+ *
+ * resp - F(tn, yyp, ypp).
+ *
+ * tempv1, tempv2, tempv3 - temporary N_Vectors provided for use
+ * by ida_lsetup.
+ *
+ * The ida_lsetup routine should return 0 if successful,
+ * a positive value for a recoverable error, and a negative value
+ * for an unrecoverable error.
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * -----------------------------------------------------------------
+ * int (*ida_lsolve)(IDAMem IDA_mem, N_Vector b, N_Vector weight,
+ * 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
+ * J = (dF/dy) + cj (dF/dy')
+ * evaluated at (tn,ycur,ypcur) and the RHS vector b is input.
+ * The N-vector ycur contains the solver's current approximation
+ * to y(tn), ypcur contains that for y'(tn), and the vector rescur
+ * contains the N-vector residual F(tn,ycur,ypcur).
+ * The solution is to be returned in the vector b.
+ *
+ * The ida_lsolve routine should return 0 if successful,
+ * a positive value for a recoverable error, and a negative value
+ * for an unrecoverable error.
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * -----------------------------------------------------------------
+ * int (*ida_lperf)(IDAMem IDA_mem, int perftask);
+ * -----------------------------------------------------------------
+ * ida_lperf is called two places in IDA where linear solver
+ * performance data is required by IDA. For perftask = 0, an
+ * initialization of performance variables is performed, while for
+ * perftask = 1, the performance is evaluated.
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * -----------------------------------------------------------------
+ * 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.
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * =================================================================
+ * I D A I N T E R N A L F U N C T I O N S
+ * =================================================================
+ */
+
+/* Prototype of internal ewtSet function */
+
+int IDAEwtSet(N_Vector ycur, N_Vector weight, void *data);
+
+/* High level error handler */
+
+void IDAProcessError(IDAMem IDA_mem,
+ int error_code, const char *module, const char *fname,
+ const char *msgfmt, ...);
+
+/* Prototype of internal errHandler function */
+
+void IDAErrHandler(int error_code, const char *module, const char *function,
+ char *msg, void *data);
+
+/*
+ * =================================================================
+ * I D A E R R O R M E S S A G E S
+ * =================================================================
+ */
+
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+
+#define MSG_TIME "t = %Lg, "
+#define MSG_TIME_H "t = %Lg and h = %Lg, "
+#define MSG_TIME_INT "t = %Lg is not between tcur - hu = %Lg and tcur = %Lg."
+#define MSG_TIME_TOUT "tout = %Lg"
+#define MSG_TIME_TSTOP "tstop = %Lg"
+
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+
+#define MSG_TIME "t = %lg, "
+#define MSG_TIME_H "t = %lg and h = %lg, "
+#define MSG_TIME_INT "t = %lg is not between tcur - hu = %lg and tcur = %lg."
+#define MSG_TIME_TOUT "tout = %lg"
+#define MSG_TIME_TSTOP "tstop = %lg"
+
+#else
+
+#define MSG_TIME "t = %g, "
+#define MSG_TIME_H "t = %g and h = %g, "
+#define MSG_TIME_INT "t = %g is not between tcur - hu = %g and tcur = %g."
+#define MSG_TIME_TOUT "tout = %g"
+#define MSG_TIME_TSTOP "tstop = %g"
+
+#endif
+
+/* General errors */
+
+#define MSG_MEM_FAIL "A memory request failed."
+#define MSG_NO_MEM "ida_mem = NULL illegal."
+#define MSG_NO_MALLOC "Attempt to call before IDAMalloc."
+#define MSG_BAD_NVECTOR "A required vector operation is not implemented."
+
+/* Initialization errors */
+
+#define MSG_Y0_NULL "y0 = NULL illegal."
+#define MSG_YP0_NULL "yp0 = NULL illegal."
+#define MSG_BAD_ITOL "Illegal value for itol. The legal values are IDA_SS, IDA_SV, and IDA_WF."
+#define MSG_RES_NULL "res = NULL illegal."
+#define MSG_BAD_RTOL "reltol < 0 illegal."
+#define MSG_ATOL_NULL "abstol = NULL illegal."
+#define MSG_BAD_ATOL "Some abstol component < 0.0 illegal."
+#define MSG_ROOT_FUNC_NULL "g = NULL illegal."
+
+#define MSG_MISSING_ID "id = NULL but suppressalg option on."
+#define MSG_NO_TOLS "No integration tolerances have been specified."
+#define MSG_FAIL_EWT "The user-provide EwtSet function failed."
+#define MSG_BAD_EWT "Some initial ewt component = 0.0 illegal."
+#define MSG_Y0_FAIL_CONSTR "y0 fails to satisfy constraints."
+#define MSG_LSOLVE_NULL "The linear solver's solve routine is NULL."
+#define MSG_LINIT_FAIL "The linear solver's init routine failed."
+
+/* IDACalcIC error messages */
+
+#define MSG_IC_BAD_ICOPT "icopt has an illegal value."
+#define MSG_IC_MISSING_ID "id = NULL conflicts with icopt."
+#define MSG_IC_TOO_CLOSE "tout1 too close to t0 to attempt initial condition calculation."
+#define MSG_IC_BAD_ID "id has illegal values."
+#define MSG_IC_BAD_EWT "Some initial ewt component = 0.0 illegal."
+#define MSG_IC_RES_NONREC "The residual function failed unrecoverably. "
+#define MSG_IC_RES_FAIL "The residual function failed at the first call. "
+#define MSG_IC_SETUP_FAIL "The linear solver setup failed unrecoverably."
+#define MSG_IC_SOLVE_FAIL "The linear solver solve failed unrecoverably."
+#define MSG_IC_NO_RECOVERY "The residual routine or the linear setup or solve routine had a recoverable error, but IDACalcIC was unable to recover."
+#define MSG_IC_FAIL_CONSTR "Unable to satisfy the inequality constraints."
+#define MSG_IC_FAILED_LINS "The linesearch algorithm failed with too small a step."
+#define MSG_IC_CONV_FAILED "Newton/Linesearch algorithm failed to converge."
+
+/* IDASolve error messages */
+
+#define MSG_YRET_NULL "yret = NULL illegal."
+#define MSG_YPRET_NULL "ypret = NULL illegal."
+#define MSG_TRET_NULL "tret = NULL illegal."
+#define MSG_BAD_ITASK "itask has an illegal value."
+#define MSG_TOO_CLOSE "tout too close to t0 to start integration."
+#define MSG_BAD_HINIT "Initial step is not towards tout."
+#define MSG_BAD_TSTOP "The value " MSG_TIME_TSTOP " is behind current " MSG_TIME "in the direction of integration."
+#define MSG_CLOSE_ROOTS "Root found at and very near " MSG_TIME "."
+#define MSG_MAX_STEPS "At " MSG_TIME ", mxstep steps taken before reaching tout."
+#define MSG_EWT_NOW_FAIL "At " MSG_TIME "the user-provide EwtSet function failed."
+#define MSG_EWT_NOW_BAD "At " MSG_TIME "some ewt component has become <= 0.0."
+#define MSG_TOO_MUCH_ACC "At " MSG_TIME "too much accuracy requested."
+
+#define MSG_BAD_K "Illegal value for k."
+#define MSG_NULL_DKY "dky = NULL illegal."
+#define MSG_BAD_T "Illegal value for t." MSG_TIME_INT
+#define MSG_BAD_TOUT "Trouble interpolating at " MSG_TIME_TOUT ". tout too far back in direction of integration."
+
+#define MSG_ERR_FAILS "At " MSG_TIME_H "the error test failed repeatedly or with |h| = hmin."
+#define MSG_CONV_FAILS "At " MSG_TIME_H "the corrector convergence failed repeatedly or with |h| = hmin."
+#define MSG_SETUP_FAILED "At " MSG_TIME "the linear solver setup failed unrecoverably."
+#define MSG_SOLVE_FAILED "At " MSG_TIME "the linear solver solve failed unrecoverably."
+#define MSG_REP_RES_ERR "At " MSG_TIME "repeated recoverable residual errors."
+#define MSG_RES_NONRECOV "At " MSG_TIME "the residual function failed unrecoverably."
+#define MSG_FAILED_CONSTR "At " MSG_TIME "unable to satisfy inequality constraints."
+#define MSG_RTFUNC_FAILED "At " MSG_TIME ", the rootfinding routine failed in an unrecoverable manner."
+#define MSG_NO_ROOT "Rootfinding was not initialized."
+#define MSG_INACTIVE_ROOTS "At the end of the first step, there are still some root functions identically 0. This warning will not be issued again."
+
+
+/* IDASet* / IDAGet* error messages */
+
+#define MSG_NEG_MAXORD "maxord <= 0 illegal."
+#define MSG_BAD_MAXORD "Illegal attempt to increase maximum order."
+#define MSG_NEG_HMAX "hmax < 0 illegal."
+#define MSG_NEG_EPCON "epcon <= 0.0 illegal."
+#define MSG_BAD_CONSTR "Illegal values in constraints vector."
+#define MSG_BAD_EPICCON "epiccon <= 0.0 illegal."
+#define MSG_BAD_MAXNH "maxnh <= 0 illegal."
+#define MSG_BAD_MAXNJ "maxnj <= 0 illegal."
+#define MSG_BAD_MAXNIT "maxnit <= 0 illegal."
+#define MSG_BAD_STEPTOL "steptol <= 0.0 illegal."
+
+#define MSG_TOO_LATE "IDAGetConsistentIC can only be called before IDASolve."
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/ida/ida_io.c b/src/ida/ida_io.c
new file mode 100644
index 0000000..d180dd5
--- /dev/null
+++ b/src/ida/ida_io.c
@@ -0,0 +1,1152 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.15 $
+ * $Date: 2010/12/01 22:35:26 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Alan Hindmarsh, Radu Serban and
+ * Aaron Collier @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California
+ * Produced at the Lawrence Livermore National Laboratory
+ * All rights reserved
+ * For details, see the LICENSE file
+ * -----------------------------------------------------------------
+ * This is the implementation file for the optional inputs and
+ * outputs for the IDA solver.
+ * -----------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "ida_impl.h"
+
+#include <sundials/sundials_math.h>
+
+#define ZERO RCONST(0.0)
+#define HALF RCONST(0.5)
+#define ONE RCONST(1.0)
+#define TWOPT5 RCONST(2.5)
+
+/*
+ * =================================================================
+ * IDA optional input functions
+ * =================================================================
+ */
+
+/*
+ * 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;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDASetErrHandlerFn", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ IDA_mem->ida_ehfun = ehfun;
+ IDA_mem->ida_eh_data = eh_data;
+
+ return(IDA_SUCCESS);
+}
+
+
+int IDASetErrFile(void *ida_mem, FILE *errfp)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDASetErrFile", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ IDA_mem->ida_errfp = errfp;
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDASetUserData(void *ida_mem, void *user_data)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDASetUserData", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ IDA_mem->ida_user_data = user_data;
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDASetMaxOrd(void *ida_mem, int maxord)
+{
+ IDAMem IDA_mem;
+ int maxord_alloc;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDASetMaxOrd", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ if (maxord <= 0) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASetMaxOrd", MSG_NEG_MAXORD);
+ return(IDA_ILL_INPUT);
+ }
+
+ /* Cannot increase maximum order beyond the value that
+ was used when allocating memory */
+ maxord_alloc = IDA_mem->ida_maxord_alloc;
+
+ if (maxord > maxord_alloc) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASetMaxOrd", MSG_BAD_MAXORD);
+ return(IDA_ILL_INPUT);
+ }
+
+ IDA_mem->ida_maxord = MIN(maxord,MAXORD_DEFAULT);
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDASetMaxNumSteps(void *ida_mem, long int mxsteps)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDASetMaxNumSteps", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ /* Passing mxsteps=0 sets the default. Passing mxsteps<0 disables the test. */
+
+ if (mxsteps == 0)
+ IDA_mem->ida_mxstep = MXSTEP_DEFAULT;
+ else
+ IDA_mem->ida_mxstep = mxsteps;
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDASetInitStep(void *ida_mem, realtype hin)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDASetInitStep", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ IDA_mem->ida_hin = hin;
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDASetMaxStep(void *ida_mem, realtype hmax)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDASetMaxStep", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ if (hmax < 0) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASetMaxStep", MSG_NEG_HMAX);
+ return(IDA_ILL_INPUT);
+ }
+
+ /* Passing 0 sets hmax = infinity */
+ if (hmax == ZERO) {
+ IDA_mem->ida_hmax_inv = HMAX_INV_DEFAULT;
+ return(IDA_SUCCESS);
+ }
+
+ IDA_mem->ida_hmax_inv = ONE/hmax;
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDASetStopTime(void *ida_mem, realtype tstop)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDASetStopTime", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ /* If IDASolve was called at least once, test if tstop is legal
+ * (i.e. if it was not already passed).
+ * If IDASetStopTime is called before the first call to IDASolve,
+ * tstop will be checked in IDASolve. */
+ if (IDA_mem->ida_nst > 0) {
+
+ if ( (tstop - IDA_mem->ida_tn) * IDA_mem->ida_hh < ZERO ) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASetStopTime", MSG_BAD_TSTOP, IDA_mem->ida_tn);
+ return(IDA_ILL_INPUT);
+ }
+
+ }
+
+ IDA_mem->ida_tstop = tstop;
+ IDA_mem->ida_tstopset = TRUE;
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDASetNonlinConvCoef(void *ida_mem, realtype epcon)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDASetNonlinConvCoef", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ if (epcon <= ZERO) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASetNonlinConvCoef", MSG_NEG_EPCON);
+ return(IDA_ILL_INPUT);
+ }
+
+ IDA_mem->ida_epcon = epcon;
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDASetMaxErrTestFails(void *ida_mem, int maxnef)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDASetMaxErrTestFails", MSG_NO_MEM);
+ return (IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ IDA_mem->ida_maxnef = maxnef;
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDASetMaxConvFails(void *ida_mem, int maxncf)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDASetMaxConvFails", MSG_NO_MEM);
+ return (IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ IDA_mem->ida_maxncf = maxncf;
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDASetMaxNonlinIters(void *ida_mem, int maxcor)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDASetMaxNonlinIters", MSG_NO_MEM);
+ return (IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ IDA_mem->ida_maxcor = maxcor;
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDASetSuppressAlg(void *ida_mem, booleantype suppressalg)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDASetSuppressAlg", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ IDA_mem->ida_suppressalg = suppressalg;
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDASetId(void *ida_mem, N_Vector id)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDASetId", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ if (id == NULL) {
+ if (IDA_mem->ida_idMallocDone) {
+ N_VDestroy(IDA_mem->ida_id);
+ lrw -= lrw1;
+ liw -= liw1;
+ }
+ IDA_mem->ida_idMallocDone = FALSE;
+ return(IDA_SUCCESS);
+ }
+
+ if ( !(IDA_mem->ida_idMallocDone) ) {
+ IDA_mem->ida_id = N_VClone(id);
+ lrw += lrw1;
+ liw += liw1;
+ IDA_mem->ida_idMallocDone = TRUE;
+ }
+
+ /* Load the id vector */
+
+ N_VScale(ONE, id, IDA_mem->ida_id);
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDASetConstraints(void *ida_mem, N_Vector constraints)
+{
+ IDAMem IDA_mem;
+ realtype temptest;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDASetConstraints", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ if (constraints == NULL) {
+ if (IDA_mem->ida_constraintsMallocDone) {
+ N_VDestroy(IDA_mem->ida_constraints);
+ lrw -= lrw1;
+ liw -= liw1;
+ }
+ IDA_mem->ida_constraintsMallocDone = FALSE;
+ IDA_mem->ida_constraintsSet = FALSE;
+ return(IDA_SUCCESS);
+ }
+
+ /* Test if required vector ops. are defined */
+
+ if (constraints->ops->nvdiv == NULL ||
+ constraints->ops->nvmaxnorm == NULL ||
+ constraints->ops->nvcompare == NULL ||
+ constraints->ops->nvconstrmask == NULL ||
+ constraints->ops->nvminquotient == NULL) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASetConstraints", MSG_BAD_NVECTOR);
+ return(IDA_ILL_INPUT);
+ }
+
+ /* Check the constraints vector */
+
+ temptest = N_VMaxNorm(constraints);
+ if((temptest > TWOPT5) || (temptest < HALF)){
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASetConstraints", MSG_BAD_CONSTR);
+ return(IDA_ILL_INPUT);
+ }
+
+ if ( !(IDA_mem->ida_constraintsMallocDone) ) {
+ IDA_mem->ida_constraints = N_VClone(constraints);
+ lrw += lrw1;
+ liw += liw1;
+ IDA_mem->ida_constraintsMallocDone = TRUE;
+ }
+
+ /* Load the constraints vector */
+
+ N_VScale(ONE, constraints, IDA_mem->ida_constraints);
+
+ IDA_mem->ida_constraintsSet = TRUE;
+
+ return(IDA_SUCCESS);
+}
+
+/*
+ * IDASetRootDirection
+ *
+ * Specifies the direction of zero-crossings to be monitored.
+ * The default is to monitor both crossings.
+ */
+
+int IDASetRootDirection(void *ida_mem, int *rootdir)
+{
+ IDAMem IDA_mem;
+ int i, nrt;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDASetRootDirection", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ nrt = IDA_mem->ida_nrtfn;
+ if (nrt==0) {
+ IDAProcessError(NULL, IDA_ILL_INPUT, "IDA", "IDASetRootDirection", MSG_NO_ROOT);
+ return(IDA_ILL_INPUT);
+ }
+
+ for(i=0; i<nrt; i++) IDA_mem->ida_rootdir[i] = rootdir[i];
+
+ return(IDA_SUCCESS);
+}
+
+/*
+ * IDASetNoInactiveRootWarn
+ *
+ * Disables issuing a warning if some root function appears
+ * to be identically zero at the beginning of the integration
+ */
+
+int IDASetNoInactiveRootWarn(void *ida_mem)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDASetNoInactiveRootWarn", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ IDA_mem->ida_mxgnull = 0;
+
+ return(IDA_SUCCESS);
+}
+
+
+/*
+ * =================================================================
+ * IDA IC optional input functions
+ * =================================================================
+ */
+
+int IDASetNonlinConvCoefIC(void *ida_mem, realtype epiccon)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDASetNonlinConvCoefIC", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ if (epiccon <= ZERO) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASetNonlinConvCoefIC", MSG_BAD_EPICCON);
+ return(IDA_ILL_INPUT);
+ }
+
+ IDA_mem->ida_epiccon = epiccon;
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDASetMaxNumStepsIC(void *ida_mem, int maxnh)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDASetMaxNumStepsIC", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ if (maxnh <= 0) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASetMaxNumStepsIC", MSG_BAD_MAXNH);
+ return(IDA_ILL_INPUT);
+ }
+
+ IDA_mem->ida_maxnh = maxnh;
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDASetMaxNumJacsIC(void *ida_mem, int maxnj)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDASetMaxNumJacsIC", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ if (maxnj <= 0) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASetMaxNumJacsIC", MSG_BAD_MAXNJ);
+ return(IDA_ILL_INPUT);
+ }
+
+ IDA_mem->ida_maxnj = maxnj;
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDASetMaxNumItersIC(void *ida_mem, int maxnit)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDASetMaxNumItersIC", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ if (maxnit <= 0) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASetMaxNumItersIC", MSG_BAD_MAXNIT);
+ return(IDA_ILL_INPUT);
+ }
+
+ IDA_mem->ida_maxnit = maxnit;
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDASetLineSearchOffIC(void *ida_mem, booleantype lsoff)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDASetLineSearchOffIC", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ IDA_mem->ida_lsoff = lsoff;
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDASetStepToleranceIC(void *ida_mem, realtype steptol)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDASetStepToleranceIC", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ if (steptol <= ZERO) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASetStepToleranceIC", MSG_BAD_STEPTOL);
+ return(IDA_ILL_INPUT);
+ }
+
+ IDA_mem->ida_steptol = steptol;
+
+ return(IDA_SUCCESS);
+}
+
+/*
+ * =================================================================
+ * 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
+ * =================================================================
+ */
+
+int IDAGetNumSteps(void *ida_mem, long int *nsteps)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDAGetNumSteps", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ *nsteps = nst;
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDAGetNumResEvals(void *ida_mem, long int *nrevals)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDAGetNumResEvals", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ *nrevals = nre;
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDAGetNumLinSolvSetups(void *ida_mem, long int *nlinsetups)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDAGetNumLinSolvSetups", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ *nlinsetups = nsetups;
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDAGetNumErrTestFails(void *ida_mem, long int *netfails)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDAGetNumErrTestFails", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ *netfails = netf;
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDAGetNumBacktrackOps(void *ida_mem, long int *nbacktracks)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDAGetNumBacktrackOps", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ *nbacktracks = nbacktr;
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDAGetConsistentIC(void *ida_mem, N_Vector yy0, N_Vector yp0)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem == NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDAGetConsistentIC", MSG_NO_MEM);
+ return (IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ if (IDA_mem->ida_kused != 0) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDAGetConsistentIC", MSG_TOO_LATE);
+ return(IDA_ILL_INPUT);
+ }
+
+ if(yy0 != NULL) N_VScale(ONE, IDA_mem->ida_phi[0], yy0);
+ if(yp0 != NULL) N_VScale(ONE, IDA_mem->ida_phi[1], yp0);
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDAGetLastOrder(void *ida_mem, int *klast)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDAGetLastOrder", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ *klast = kused;
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDAGetCurrentOrder(void *ida_mem, int *kcur)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDAGetCurrentOrder", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ *kcur = kk;
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDAGetActualInitStep(void *ida_mem, realtype *hinused)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDAGetActualInitStep", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ *hinused = h0u;
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDAGetLastStep(void *ida_mem, realtype *hlast)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDAGetLastStep", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ *hlast = hused;
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDAGetCurrentStep(void *ida_mem, realtype *hcur)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDAGetCurrentStep", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ *hcur = hh;
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDAGetCurrentTime(void *ida_mem, realtype *tcur)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDAGetCurrentTime", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ *tcur = tn;
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDAGetTolScaleFactor(void *ida_mem, realtype *tolsfact)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDAGetTolScaleFactor", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ *tolsfact = tolsf;
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDAGetErrWeights(void *ida_mem, N_Vector eweight)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem == NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDAGetErrWeights", MSG_NO_MEM);
+ return (IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ N_VScale(ONE, ewt, eweight);
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDAGetEstLocalErrors(void *ida_mem, N_Vector ele)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem == NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDAGetEstLocalErrors", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+ IDA_mem = (IDAMem) ida_mem;
+
+ N_VScale(ONE, ee, ele);
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDAGetWorkSpace(void *ida_mem, long int *lenrw, long int *leniw)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDAGetWorkSpace", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ *leniw = liw;
+ *lenrw = lrw;
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDAGetIntegratorStats(void *ida_mem, long int *nsteps, long int *nrevals,
+ long int *nlinsetups, long int *netfails,
+ int *klast, int *kcur, realtype *hinused, realtype *hlast,
+ realtype *hcur, realtype *tcur)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDAGetIntegratorStats", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ 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;
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDAGetNumGEvals(void *ida_mem, long int *ngevals)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDAGetNumGEvals", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ *ngevals = nge;
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDAGetRootInfo(void *ida_mem, int *rootsfound)
+{
+ IDAMem IDA_mem;
+ int i, nrt;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDAGetRootInfo", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ nrt = IDA_mem->ida_nrtfn;
+
+ for (i=0; i<nrt; i++) rootsfound[i] = iroots[i];
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDAGetNumNonlinSolvIters(void *ida_mem, long int *nniters)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDAGetNumNonlinSolvIters", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ *nniters = nni;
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDAGetNumNonlinSolvConvFails(void *ida_mem, long int *nncfails)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDAGetNumNonlinSolvConvFails", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ *nncfails = ncfn;
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDAGetNonlinSolvStats(void *ida_mem, long int *nniters, long int *nncfails)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDAGetNonlinSolvStats", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ *nniters = nni;
+ *nncfails = ncfn;
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+char *IDAGetReturnFlagName(long int flag)
+{
+ char *name;
+
+ name = (char *)malloc(24*sizeof(char));
+
+ switch(flag) {
+ case IDA_SUCCESS:
+ sprintf(name,"IDA_SUCCESS");
+ break;
+ case IDA_TSTOP_RETURN:
+ sprintf(name,"IDA_TSTOP_RETURN");
+ break;
+ case IDA_ROOT_RETURN:
+ sprintf(name,"IDA_ROOT_RETURN");
+ break;
+ case IDA_TOO_MUCH_WORK:
+ sprintf(name,"IDA_TOO_MUCH_WORK");
+ break;
+ case IDA_TOO_MUCH_ACC:
+ sprintf(name,"IDA_TOO_MUCH_ACC");
+ break;
+ case IDA_ERR_FAIL:
+ sprintf(name,"IDA_ERR_FAIL");
+ break;
+ case IDA_CONV_FAIL:
+ sprintf(name,"IDA_CONV_FAIL");
+ break;
+ case IDA_LINIT_FAIL:
+ sprintf(name,"IDA_LINIT_FAIL");
+ break;
+ case IDA_LSETUP_FAIL:
+ sprintf(name,"IDA_LSETUP_FAIL");
+ break;
+ case IDA_LSOLVE_FAIL:
+ sprintf(name,"IDA_LSOLVE_FAIL");
+ break;
+ case IDA_CONSTR_FAIL:
+ sprintf(name,"IDA_CONSTR_FAIL");
+ break;
+ case IDA_RES_FAIL:
+ sprintf(name,"IDA_RES_FAIL");
+ break;
+ case IDA_FIRST_RES_FAIL:
+ sprintf(name,"IDA_FIRST_RES_FAIL");
+ break;
+ case IDA_REP_RES_ERR:
+ sprintf(name,"IDA_REP_RES_ERR");
+ break;
+ case IDA_RTFUNC_FAIL:
+ sprintf(name,"IDA_RTFUNC_FAIL");
+ break;
+ case IDA_MEM_FAIL:
+ sprintf(name,"IDA_MEM_FAIL");
+ break;
+ case IDA_MEM_NULL:
+ sprintf(name,"IDA_MEM_NULL");
+ break;
+ case IDA_ILL_INPUT:
+ sprintf(name,"IDA_ILL_INPUT");
+ break;
+ case IDA_NO_MALLOC:
+ sprintf(name,"IDA_NO_MALLOC");
+ break;
+ case IDA_BAD_T:
+ sprintf(name,"IDA_BAD_T");
+ break;
+ case IDA_BAD_EWT:
+ sprintf(name,"IDA_BAD_EWT");
+ break;
+ case IDA_NO_RECOVERY:
+ sprintf(name,"IDA_NO_RECOVERY");
+ break;
+ case IDA_LINESEARCH_FAIL:
+ sprintf(name,"IDA_LINESEARCH_FAIL");
+ break;
+
+ default:
+ sprintf(name,"NONE");
+ }
+
+ return(name);
+}
+
diff --git a/src/ida/ida_lapack.c b/src/ida/ida_lapack.c
new file mode 100644
index 0000000..86530ea
--- /dev/null
+++ b/src/ida/ida_lapack.c
@@ -0,0 +1,558 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.12 $
+ * $Date: 2011/03/23 23:16:14 $
+ * -----------------------------------------------------------------
+ * Programmer: Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2006, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * 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;
+ 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 = MIN(n-1, 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;
+
+ 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_spbcgs.c b/src/ida/ida_spbcgs.c
new file mode 100644
index 0000000..c1e27ea
--- /dev/null
+++ b/src/ida/ida_spbcgs.c
@@ -0,0 +1,477 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.7 $
+ * $Date: 2011/05/25 20:20:25 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Aaron Collier and Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2004, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * 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 flag, 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) flag = 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;
+
+ /* 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 = RSqrt(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 */
+ npe = nli = nps = ncfl = 0;
+ njtimes = nres = 0;
+
+ /* 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
new file mode 100644
index 0000000..2fd21e9
--- /dev/null
+++ b/src/ida/ida_spgmr.c
@@ -0,0 +1,476 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.7 $
+ * $Date: 2011/05/25 20:20:25 $
+ * -----------------------------------------------------------------
+ * Programmers: Alan C. Hindmarsh, and Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California
+ * Produced at the Lawrence Livermore National Laboratory
+ * All rights reserved
+ * For details, see the LICENSE file
+ * -----------------------------------------------------------------
+ * 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 flag, 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) flag = 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;
+
+ /* 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 = RSqrt( 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 */
+ npe = nli = nps = ncfl = 0;
+ njtimes = nres = 0;
+
+ /* 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
new file mode 100644
index 0000000..813c10a
--- /dev/null
+++ b/src/ida/ida_spils.c
@@ -0,0 +1,637 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.5 $
+ * $Date: 2010/12/01 22:35:26 $
+ * -----------------------------------------------------------------
+ * Programmers: Alan C. Hindmarsh and Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California
+ * Produced at the Lawrence Livermore National Laboratory
+ * All rights reserved
+ * For details, see the LICENSE file
+ * -----------------------------------------------------------------
+ * This is the common implementation file for the IDA Scaled
+ * Preconditioned Linear Solver modules.
+ * -----------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "ida_impl.h"
+#include "ida_spils_impl.h"
+
+/* Private constants */
+
+#define ZERO RCONST(0.0)
+#define PT25 RCONST(0.25)
+#define PT05 RCONST(0.05)
+#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)
+{
+ IDAMem IDA_mem;
+ IDASpilsMem idaspils_mem;
+
+ /* Return immediately if ida_mem is NULL */
+ if (ida_mem == NULL) {
+ IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASPILS", "IDASpilsSetGSType", 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);
+ }
+ idaspils_mem = (IDASpilsMem) lmem;
+
+ if (ils_type != SPILS_SPGMR) {
+ IDAProcessError(IDA_mem, IDASPILS_ILL_INPUT, "IDASPILS", "IDASpilsSetGSType", MSGS_BAD_LSTYPE);
+ 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);
+ 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);
+ }
+ IDA_mem = (IDAMem) ida_mem;
+
+ if (lmem == NULL) {
+ IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASPILS", "IDASpilsSetMaxRestarts", MSGS_LMEM_NULL);
+ return(IDASPILS_LMEM_NULL);
+ }
+ idaspils_mem = (IDASpilsMem) lmem;
+
+ if (ils_type != SPILS_SPGMR) {
+ IDAProcessError(IDA_mem, IDASPILS_ILL_INPUT, "IDASPILS", "IDASpilsSetMaxRestarts", MSGS_BAD_LSTYPE);
+ return(IDASPILS_ILL_INPUT);
+ }
+
+ /* Check for legal maxrs */
+ if (maxrs < 0) {
+ IDAProcessError(IDA_mem, IDASPILS_ILL_INPUT, "IDASPILS", "IDASpilsSetMaxRestarts", MSGS_NEG_MAXRS);
+ return(IDASPILS_ILL_INPUT);
+ }
+
+ 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);
+ }
+ 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 = (IDASpilsMem) lmem;
+
+ if (ils_type == SPILS_SPGMR) {
+ IDAProcessError(IDA_mem, IDASPILS_ILL_INPUT, "IDASPILS", "IDASpilsSetMaxl", MSGS_BAD_LSTYPE);
+ return(IDASPILS_ILL_INPUT);
+ }
+
+ idaspils_mem->s_maxl = (maxl <= 0) ? IDA_SPILS_MAXL : maxl;
+
+ return(IDASPILS_SUCCESS);
+}
+
+int IDASpilsSetEpsLin(void *ida_mem, realtype eplifac)
+{
+ IDAMem IDA_mem;
+ IDASpilsMem idaspils_mem;
+
+ /* Return immediately if ida_mem is NULL */
+ if (ida_mem == 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);
+ return(IDASPILS_LMEM_NULL);
+ }
+ idaspils_mem = (IDASpilsMem) lmem;
+
+ /* Check for legal maxrs */
+ if (eplifac < ZERO) {
+ IDAProcessError(IDA_mem, IDASPILS_ILL_INPUT, "IDASPILS", "IDASpilsSetEpsLin", MSGS_NEG_EPLIFAC);
+ return(IDASPILS_ILL_INPUT);
+ }
+
+ if (eplifac == ZERO)
+ idaspils_mem->s_eplifac = PT05;
+ else
+ idaspils_mem->s_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 */
+ if (ida_mem == 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);
+ return(IDASPILS_LMEM_NULL);
+ }
+ idaspils_mem = (IDASpilsMem) lmem;
+
+ /* Check for legal maxrs */
+ if (dqincfac <= ZERO) {
+ IDAProcessError(IDA_mem, IDASPILS_ILL_INPUT, "IDASPILS", "IDASpilsSetIncrementFactor", MSGS_NEG_DQINCFAC);
+ return(IDASPILS_ILL_INPUT);
+ }
+
+ idaspils_mem->s_dqincfac = dqincfac;
+
+ return(IDASPILS_SUCCESS);
+}
+
+int IDASpilsSetPreconditioner(void *ida_mem,
+ IDASpilsPrecSetupFn pset, IDASpilsPrecSolveFn psolve)
+{
+ IDAMem IDA_mem;
+ IDASpilsMem idaspils_mem;
+
+ /* Return immediately if ida_mem is NULL */
+ if (ida_mem == 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);
+ return(IDASPILS_LMEM_NULL);
+ }
+ idaspils_mem = (IDASpilsMem) lmem;
+
+ idaspils_mem->s_pset = pset;
+ idaspils_mem->s_psolve = psolve;
+
+ 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, "IDASPILS", "IDASpilsSetJacTimesVecFn", 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);
+ return(IDASPILS_LMEM_NULL);
+ }
+ idaspils_mem = (IDASpilsMem) lmem;
+
+ if (jtv != NULL) {
+ jtimesDQ = FALSE;
+ jtimes = jtv;
+ } else {
+ jtimesDQ = TRUE;
+ }
+
+ return(IDASPILS_SUCCESS);
+}
+
+int IDASpilsGetWorkSpace(void *ida_mem, long int *lenrwLS, long int *leniwLS)
+{
+ IDAMem IDA_mem;
+ IDASpilsMem idaspils_mem;
+ int maxl;
+
+ /* Return immediately if ida_mem is NULL */
+ if (ida_mem == 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);
+ return(IDASPILS_LMEM_NULL);
+ }
+ idaspils_mem = (IDASpilsMem) 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;
+ }
+
+ return(IDASPILS_SUCCESS);
+}
+
+int IDASpilsGetNumPrecEvals(void *ida_mem, long int *npevals)
+{
+ IDAMem IDA_mem;
+ IDASpilsMem idaspils_mem;
+
+ /* Return immediately if ida_mem is NULL */
+ if (ida_mem == 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);
+ return(IDASPILS_LMEM_NULL);
+ }
+ idaspils_mem = (IDASpilsMem) lmem;
+
+ *npevals = 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 */
+ if (ida_mem == 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);
+ return(IDASPILS_LMEM_NULL);
+ }
+ idaspils_mem = (IDASpilsMem) lmem;
+
+ *npsolves = 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 */
+ if (ida_mem == 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);
+ return(IDASPILS_LMEM_NULL);
+ }
+ idaspils_mem = (IDASpilsMem) lmem;
+
+ *nliters = 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 */
+ if (ida_mem == NULL) {
+ IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASPILS", "IDASpilsGetNumConvFails", MSGS_IDAMEM_NULL);
+ return(IDASPILS_MEM_NULL);
+ }
+ IDA_mem = (IDAMem) ida_mem;
+
+ if (lmem == NULL) {
+ IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASPILS", "IDASpilsGetNumConvFails", MSGS_LMEM_NULL);
+ return(IDASPILS_LMEM_NULL);
+ }
+ idaspils_mem = (IDASpilsMem) lmem;
+
+ *nlcfails = ncfl;
+
+ return(IDASPILS_SUCCESS);
+}
+
+int IDASpilsGetNumJtimesEvals(void *ida_mem, long int *njvevals)
+{
+ IDAMem IDA_mem;
+ IDASpilsMem idaspils_mem;
+
+ /* Return immediately if ida_mem is NULL */
+ if (ida_mem == 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);
+ return(IDASPILS_LMEM_NULL);
+ }
+ idaspils_mem = (IDASpilsMem) lmem;
+
+ *njvevals = 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 */
+ if (ida_mem == 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);
+ return(IDASPILS_LMEM_NULL);
+ }
+ idaspils_mem = (IDASpilsMem) lmem;
+
+ *nrevalsLS = 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 */
+ if (ida_mem == 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);
+ return(IDASPILS_LMEM_NULL);
+ }
+ idaspils_mem = (IDASpilsMem) lmem;
+
+ *flag = last_flag;
+
+ return(IDASPILS_SUCCESS);
+}
+
+char *IDASpilsGetReturnFlagName(long int flag)
+{
+ char *name;
+
+ name = (char *)malloc(30*sizeof(char));
+
+ switch(flag) {
+ case IDASPILS_SUCCESS:
+ sprintf(name,"IDASPILS_SUCCESS");
+ break;
+ case IDASPILS_MEM_NULL:
+ sprintf(name,"IDASPILS_MEM_NULL");
+ break;
+ case IDASPILS_LMEM_NULL:
+ sprintf(name,"IDASPILS_LMEM_NULL");
+ break;
+ case IDASPILS_ILL_INPUT:
+ sprintf(name,"IDASPILS_ILL_INPUT");
+ break;
+ case IDASPILS_MEM_FAIL:
+ sprintf(name,"IDASPILS_MEM_FAIL");
+ break;
+ case IDASPILS_PMEM_NULL:
+ sprintf(name,"IDASPILS_PMEM_NULL");
+ break;
+ default:
+ sprintf(name,"NONE");
+ }
+
+ return(name);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * IDASPILS private functions
+ * -----------------------------------------------------------------
+ */
+
+#define psolve (idaspils_mem->s_psolve)
+#define pdata (idaspils_mem->s_pdata)
+#define dqincfac (idaspils_mem->s_dqincfac)
+
+/*
+ * 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.
+ */
+
+int IDASpilsAtimes(void *ida_mem, N_Vector v, N_Vector z)
+{
+ IDAMem IDA_mem;
+ IDASpilsMem idaspils_mem;
+ int jtflag;
+
+ IDA_mem = (IDAMem) ida_mem;
+ idaspils_mem = (IDASpilsMem) lmem;
+
+ jtflag = jtimes(tn, ycur, ypcur, rcur, v, z, cj, jdata, ytemp, yptemp);
+ 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)
+{
+ IDAMem IDA_mem;
+ IDASpilsMem idaspils_mem;
+ int retval;
+
+ 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 */
+
+ 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)
+{
+ IDAMem IDA_mem;
+ IDASpilsMem idaspils_mem;
+ N_Vector y_tmp, yp_tmp;
+ realtype sig, 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;
+ }
+
+ /* Rename work1 and work2 for readibility */
+ y_tmp = work1;
+ yp_tmp = work2;
+
+ for (iter=0; iter<MAX_ITERS; iter++) {
+
+ /* Set y_tmp = yy + sig*v, yp_tmp = yp + cj*sig*v. */
+ N_VLinearSum(sig, v, ONE, yy, y_tmp);
+ 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++;
+ if (retval == 0) break;
+ if (retval < 0) return(-1);
+
+ sig *= PT25;
+ }
+
+ if (retval > 0) return(+1);
+
+ /* Set Jv to [Jv - rr]/sig and return. */
+ siginv = ONE/sig;
+ N_VLinearSum(siginv, Jv, -siginv, rr, Jv);
+
+ return(0);
+
+}
diff --git a/src/ida/ida_spils_impl.h b/src/ida/ida_spils_impl.h
new file mode 100644
index 0000000..457b8c7
--- /dev/null
+++ b/src/ida/ida_spils_impl.h
@@ -0,0 +1,188 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.5 $
+ * $Date: 2010/12/01 22:35:26 $
+ * -----------------------------------------------------------------
+ * Programmers: Alan C. Hindmarsh and Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * This is the common header file (private version) for the Scaled
+ * Preconditioned Iterative Linear Solver modules.
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _IDASPILS_IMPL_H
+#define _IDASPILS_IMPL_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <ida/ida_spils.h>
+#include "ida_impl.h"
+
+/* 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
+ * -----------------------------------------------------------------
+ */
+
+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 */
+
+ /* 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;
+ void (*s_pfree)(IDAMem IDA_mem);
+ void *s_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;
+
+} *IDASpilsMem;
+
+
+/*
+ * -----------------------------------------------------------------
+ * 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);
+
+/* 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,
+ realtype c_j, void *data,
+ N_Vector work1, N_Vector work2);
+
+
+
+/*
+ * -----------------------------------------------------------------
+ * Error and Warning Messages
+ * -----------------------------------------------------------------
+ */
+
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+
+#define MSGS_TIME "at t = %Lg, "
+#define MSGS_FRMT "%Le."
+
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+
+#define MSGS_TIME "at t = %lg, "
+#define MSGS_FRMT "%le."
+
+#else
+
+#define MSGS_TIME "at t = %g, "
+#define MSGS_FRMT "%e."
+
+#endif
+
+
+/* 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."
+#define MSGS_BAD_LSTYPE "Incompatible linear solver type."
+#define MSGS_LMEM_NULL "Linear solver memory is NULL."
+#define MSGS_BAD_GSTYPE "gstype has an illegal value."
+#define MSGS_NEG_MAXRS "maxrs < 0 illegal."
+#define MSGS_NEG_EPLIFAC "eplifac < 0.0 illegal."
+#define MSGS_NEG_DQINCFAC "dqincfac < 0.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."
+
+/* 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
+
+#endif
diff --git a/src/ida/ida_sptfqmr.c b/src/ida/ida_sptfqmr.c
new file mode 100644
index 0000000..65bd102
--- /dev/null
+++ b/src/ida/ida_sptfqmr.c
@@ -0,0 +1,477 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.6 $
+ * $Date: 2007/11/26 16:20:00 $
+ * -----------------------------------------------------------------
+ * 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.
+ * -----------------------------------------------------------------
+ * 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 flag, 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) flag = 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;
+
+ /* 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 = RSqrt(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 */
+ npe = nli = nps = ncfl = 0;
+ njtimes = nres = 0;
+
+ /* 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/idas/CMakeLists.txt b/src/idas/CMakeLists.txt
new file mode 100644
index 0000000..e87faff
--- /dev/null
+++ b/src/idas/CMakeLists.txt
@@ -0,0 +1,127 @@
+# ---------------------------------------------------------------
+# $Revision: 1.4 $
+# $Date: 2009/02/17 02:58:48 $
+# ---------------------------------------------------------------
+# Programmer: Radu Serban @ LLNL
+# ---------------------------------------------------------------
+# Copyright (c) 2007, The Regents of the University of California.
+# Produced at the Lawrence Livermore National Laboratory.
+# All rights reserved.
+# For details, see the LICENSE file.
+# ---------------------------------------------------------------
+# CMakeLists.txt file for the IDAS library
+
+INSTALL(CODE "MESSAGE(\"\nInstall IDAS\n\")")
+
+# Add variable idas_SOURCES with the sources for the IDAS library
+SET(idas_SOURCES
+ idas.c
+ idaa.c
+ idas_io.c
+ idas_ic.c
+ idaa_io.c
+ idas_direct.c
+ idas_band.c
+ idas_dense.c
+ idas_spils.c
+ idas_spbcgs.c
+ idas_spgmr.c
+ idas_sptfqmr.c
+ idas_bbdpre.c
+ )
+
+# 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_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 idas_HEADERS with the exported IDAS header files
+SET(idas_HEADERS
+ idas_band.h
+ idas_bbdpre.h
+ idas_dense.h
+ idas_direct.h
+ idas.h
+ idas_spbcgs.h
+ idas_spgmr.h
+ idas_spils.h
+ idas_sptfqmr.h
+ )
+
+# 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)
+
+# Add source directories to include directories for access to
+# implementation only header files.
+INCLUDE_DIRECTORIES(.)
+INCLUDE_DIRECTORIES(../sundials)
+
+# Define C preprocessor flag -DBUILD_SUNDIALS_LIBRARY
+ADD_DEFINITIONS(-DBUILD_SUNDIALS_LIBRARY)
+
+# Build the static library
+IF(BUILD_STATIC_LIBS)
+
+ # Add the build target for the static IDAS library
+ ADD_LIBRARY(sundials_idas_static STATIC
+ ${idas_SOURCES} ${idas_BL_SOURCES} ${shared_SOURCES})
+
+ # Set the library name and make sure it is not deleted
+ SET_TARGET_PROPERTIES(sundials_idas_static
+ PROPERTIES OUTPUT_NAME sundials_idas CLEAN_DIRECT_OUTPUT 1)
+
+ # Install the IDA library
+ INSTALL(TARGETS sundials_idas_static DESTINATION lib)
+
+ENDIF(BUILD_STATIC_LIBS)
+
+# Build the shared library
+IF(BUILD_SHARED_LIBS)
+
+ # Add the build target for the IDAS library
+ ADD_LIBRARY(sundials_idas_shared SHARED
+ ${idas_SOURCES} ${idas_BL_SOURCES} ${shared_SOURCES})
+
+ # Set the library name and make sure it is not deleted
+ SET_TARGET_PROPERTIES(sundials_idas_shared
+ PROPERTIES OUTPUT_NAME sundials_idas CLEAN_DIRECT_OUTPUT 1)
+
+ # Set VERSION and SOVERSION for shared libraries
+ SET_TARGET_PROPERTIES(sundials_idas_shared
+ PROPERTIES VERSION ${idaslib_VERSION} SOVERSION ${idaslib_SOVERSION})
+
+ # Install the IDAS library
+ INSTALL(TARGETS sundials_idas_shared DESTINATION lib)
+
+ENDIF(BUILD_SHARED_LIBS)
+
+# Install the IDAS header files
+INSTALL(FILES ${idas_HEADERS} ${idas_BL_HEADERS} DESTINATION include/idas)
+
+# Install the IDAS implementation header file
+INSTALL(FILES idas_impl.h DESTINATION include/idas)
+
+#
+MESSAGE(STATUS "Added IDAS module")
diff --git a/debian/copyright b/src/idas/LICENSE
similarity index 81%
copy from debian/copyright
copy to src/idas/LICENSE
index 98cde97..3232487 100644
--- a/debian/copyright
+++ b/src/idas/LICENSE
@@ -1,22 +1,10 @@
-This package was debianized by Andrey Romanenko <andrey at enginum.com> on
-Wed, 20 Apr 2005 12:01:42 +0100.
+Copyright (c) 2006, The Regents of the University of California.
+Produced at the Lawrence Livermore National Laboratory.
+Written by Radu Serban.
+UCRL-CODE-000000
+All rights reserved.
-It was downloaded from http://www.llnl.gov/CASC/sundials/
-
-Authors: Peter Brown, Aaron Collier, Keith Grant, Alan Hindmarsh,
- Steve Lee, Radu Serban, Dan Shumaker, Carol Woodward
-
-Copyright Holder: The Regents of the University of California.
-
-License:
-
-Copyright (c) 2002, The Regents of the University of California.
-Produced at the Lawrence Livermore National Laboratory
-Written by A.C. Hindmarsh and R. Serban.
-UCRL-CODE-155950
-All rights reserved.
-
-This file is part of CVODES v2.1.0.
+This file is part of IDAS.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
diff --git a/src/idas/Makefile.in b/src/idas/Makefile.in
new file mode 100644
index 0000000..1bd573e
--- /dev/null
+++ b/src/idas/Makefile.in
@@ -0,0 +1,173 @@
+# -----------------------------------------------------------------
+# $Revision: 1.12 $
+# $Date: 2009/03/25 23:10:50 $
+# -----------------------------------------------------------------
+# Programmer(s): Radu Serban and Aaron Collier @ LLNL
+# -----------------------------------------------------------------
+# Copyright (c) 2002, The Regents of the University of California.
+# Produced at the Lawrence Livermore National Laboratory.
+# All rights reserved.
+# For details, see the LICENSE file.
+# -----------------------------------------------------------------
+# Makefile for IDA module
+#
+# @configure_input@
+# -----------------------------------------------------------------
+
+SHELL = @SHELL@
+
+ at SET_MAKE@
+
+srcdir = @srcdir@
+builddir = @builddir@
+abs_builddir = @abs_builddir@
+top_builddir = @top_builddir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+includedir = @includedir@
+libdir = @libdir@
+
+INSTALL = @INSTALL@
+INSTALL_LIB = @INSTALL_PROGRAM@
+INSTALL_HEADER = @INSTALL_DATA@
+
+LIBTOOL = @LIBTOOL@
+LIBTOOL_DEPS = @LIBTOOL_DEPS@
+
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CC = @CC@
+CFLAGS = @CFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+
+LAPACK_ENABLED = @LAPACK_ENABLED@
+
+top_srcdir = $(srcdir)/../..
+
+INCLUDES = -I$(top_srcdir)/include -I$(top_builddir)/include
+
+LIB_REVISION = 0:0:0
+
+IDAS_LIB = libsundials_idas.la
+
+IDAS_SRC_FILES = idas.c idaa.c idas_ic.c idas_io.c idaa_io.c idas_direct.c idas_dense.c idas_band.c idas_spils.c idas_spbcgs.c idas_spgmr.c idas_sptfqmr.c idas_bbdpre.c
+IDAS_BL_SRC_FILES = idas_lapack.c
+
+IDAS_OBJ_FILES = $(IDAS_SRC_FILES:.c=.o)
+IDAS_BL_OBJ_FILES = $(IDAS_BL_SRC_FILES:.c=.o)
+
+IDAS_LIB_FILES = $(IDAS_SRC_FILES:.c=.lo)
+IDAS_BL_LIB_FILES = $(IDAS_BL_SRC_FILES:.c=.lo)
+
+SHARED_LIB_FILES = $(top_builddir)/src/sundials/sundials_band.lo \
+ $(top_builddir)/src/sundials/sundials_dense.lo \
+ $(top_builddir)/src/sundials/sundials_direct.lo \
+ $(top_builddir)/src/sundials/sundials_iterative.lo \
+ $(top_builddir)/src/sundials/sundials_spgmr.lo \
+ $(top_builddir)/src/sundials/sundials_spbcgs.lo \
+ $(top_builddir)/src/sundials/sundials_sptfqmr.lo \
+ $(top_builddir)/src/sundials/sundials_math.lo \
+ $(top_builddir)/src/sundials/sundials_nvector.lo
+
+mkinstalldirs = $(SHELL) $(top_srcdir)/config/mkinstalldirs
+rminstalldirs = $(SHELL) $(top_srcdir)/config/rminstalldirs
+
+# ----------------------------------------------------------------------------------------------------------------------
+
+all: $(IDAS_LIB)
+
+$(IDAS_LIB): shared $(IDAS_LIB_FILES)
+ @if test "X${LAPACK_ENABLED}" = "Xyes"; then \
+ make lib_with_bl; \
+ else \
+ make lib_without_bl; \
+ fi
+
+lib_without_bl: shared $(IDAS_LIB_FILES)
+ $(LIBTOOL) --mode=link $(CC) $(CFLAGS) -o $(IDAS_LIB) $(IDAS_LIB_FILES) $(SHARED_LIB_FILES) -rpath $(libdir) $(LDFLAGS) $(LIBS) -version-info $(LIB_REVISION)
+
+lib_with_bl: shared $(IDAS_LIB_FILES) $(IDAS_BL_LIB_FILES)
+ $(LIBTOOL) --mode=link $(CC) $(CFLAGS) -o $(IDAS_LIB) $(IDAS_LIB_FILES) $(IDAS_BL_LIB_FILES) $(SHARED_LIB_FILES) -rpath $(libdir) $(LDFLAGS) $(LIBS) -version-info $(LIB_REVISION)
+
+install: $(IDAS_LIB)
+ $(mkinstalldirs) $(includedir)/idas
+ $(mkinstalldirs) $(libdir)
+ $(LIBTOOL) --mode=install $(INSTALL_LIB) $(IDAS_LIB) $(libdir)
+ $(INSTALL_HEADER) $(top_srcdir)/include/idas/idas.h $(includedir)/idas/
+ $(INSTALL_HEADER) $(top_srcdir)/include/idas/idas_direct.h $(includedir)/idas/
+ $(INSTALL_HEADER) $(top_srcdir)/include/idas/idas_dense.h $(includedir)/idas/
+ $(INSTALL_HEADER) $(top_srcdir)/include/idas/idas_band.h $(includedir)/idas/
+ $(INSTALL_HEADER) $(top_srcdir)/include/idas/idas_spbcgs.h $(includedir)/idas/
+ $(INSTALL_HEADER) $(top_srcdir)/include/idas/idas_spgmr.h $(includedir)/idas/
+ $(INSTALL_HEADER) $(top_srcdir)/include/idas/idas_sptfqmr.h $(includedir)/idas/
+ $(INSTALL_HEADER) $(top_srcdir)/include/idas/idas_bbdpre.h $(includedir)/idas/
+ $(INSTALL_HEADER) $(top_srcdir)/include/idas/idas_spils.h $(includedir)/idas/
+ $(INSTALL_HEADER) $(top_srcdir)/src/idas/idas_impl.h $(includedir)/idas/
+ @if test "X${LAPACK_ENABLED}" = "Xyes"; then \
+ $(INSTALL_HEADER) $(top_srcdir)/include/idas/idas_lapack.h $(includedir)/idas/ ; \
+ fi
+
+uninstall:
+ $(LIBTOOL) --mode=uninstall rm -f $(libdir)/$(IDAS_LIB)
+ rm -f $(includedir)/idas/idas.h
+ rm -f $(includedir)/idas/idas_direct.h
+ rm -f $(includedir)/idas/idas_dense.h
+ rm -f $(includedir)/idas/idas_band.h
+ rm -f $(includedir)/idas/idas_lapack.h
+ rm -f $(includedir)/idas/idas_spbcgs.h
+ rm -f $(includedir)/idas/idas_spgmr.h
+ rm -f $(includedir)/idas/idas_sptfqmr.h
+ rm -f $(includedir)/idas/idas_bbdpre.h
+ rm -f $(includedir)/idas/idas_spils.h
+ rm -f $(includedir)/idas/idas_impl.h
+ $(rminstalldirs) ${includedir}/idas
+
+shared:
+ @cd ${top_builddir}/src/sundials ; \
+ ${MAKE} ; \
+ cd ${abs_builddir}
+
+clean:
+ $(LIBTOOL) --mode=clean rm -f $(IDAS_LIB)
+ rm -f $(IDAS_LIB_FILES)
+ rm -f $(IDAS_BL_LIB_FILES)
+ rm -f $(IDAS_OBJ_FILES)
+ rm -f $(IDAS_BL_OBJ_FILES)
+
+distclean: clean
+ rm -f Makefile
+
+idas.lo: $(srcdir)/idas.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/idas.c
+idaa.lo: $(srcdir)/idaa.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/idaa.c
+idas_ic.lo: $(srcdir)/idas_ic.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/idas_ic.c
+idas_io.lo: $(srcdir)/idas_io.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/idas_io.c
+idaa_io.lo: $(srcdir)/idaa_io.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/idaa_io.c
+idas_direct.lo: $(srcdir)/idas_direct.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/idas_direct.c
+idas_dense.lo: $(srcdir)/idas_dense.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/idas_dense.c
+idas_band.lo: $(srcdir)/idas_band.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/idas_band.c
+idas_lapack.lo: $(srcdir)/idas_lapack.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/idas_lapack.c
+idas_spils.lo: $(srcdir)/idas_spils.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/idas_spils.c
+idas_spbcgs.lo: $(srcdir)/idas_spbcgs.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/idas_spbcgs.c
+idas_spgmr.lo: $(srcdir)/idas_spgmr.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/idas_spgmr.c
+idas_sptfqmr.lo: $(srcdir)/idas_sptfqmr.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/idas_sptfqmr.c
+idas_bbdpre.lo: $(srcdir)/idas_bbdpre.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/idas_bbdpre.c
+
+libtool: $(top_builddir)/$(LIBTOOL_DEPS)
+ @cd ${top_builddir} ; \
+ ${SHELL} ./config.status --recheck ; \
+ cd ${abs_builddir}
diff --git a/src/idas/README b/src/idas/README
new file mode 100644
index 0000000..9f92eac
--- /dev/null
+++ b/src/idas/README
@@ -0,0 +1,112 @@
+ IDAS
+ Release 1.1.0, March 2012
+ Radu Serban
+ Center for Applied Scientific Computing, LLNL
+
+
+IDAS is a package for the solution of differential-algebraic equation (DAE)
+systems with sensitivity analysis capabilities (both forward and adjoint modes).
+It is written in ANSI standard C.
+
+IDAS can be used both on serial and parallel (MPI) computers. The main
+difference is in the NVECTOR module of vector kernels. The desired
+version is obtained when compiling the example files by linking the
+appropriate library of NVECTOR kernels. In the parallel version,
+communication between processors is done with the MPI (Message Passage
+Interface) system.
+
+When used with the serial NVECTOR module, IDAS provides both direct
+(dense and band) linear solvers and preconditioned Krylov (iterative)
+linear solvers. Three different iterative solvers are available: scaled
+preconditioned GMRES (SPGMR), scaled preconditioned BiCGStab (SPBCG), and
+scaled preconditioned TFQMR (SPTFQMR). When IDAS is used with the parallel
+NVECTOR module, only the Krylov linear solvers are available. For the
+latter case, in addition to the basic solver, the IDA package also contains
+a preconditioner module called IDABBDPRE, which provides a band-block-diagonal
+preconditioner.
+
+IDAS is part of a software family called SUNDIALS: SUite of Nonlinear and
+DIfferential/ALgebraic equation Solvers [3]. This suite consists of CVODE,
+CVODES, IDA, IDAS, and KINSOL. The directory structure of the package supplied
+reflects this family relationship.
+
+Several examples problem programs are included, covering both serial
+and parallel cases, both small and large problem sizes, and both
+linear and nonlinear problems.
+
+The notes below provide the location of documentation, directions for the
+installation of the IDAS package, and relevant references. Following that
+is a brief history of revisions to the package.
+
+
+A. Documentation
+----------------
+
+/sundials/doc/idas/ contains PDF files for the IDAS User Guide [1] (idas_guide.pdf)
+and the IDAS Examples [2] (idas_examples.pdf) documents.
+
+
+B. Installation
+---------------
+
+For basic installation instructions see the file /sundials/INSTALL_NOTES.
+For complete installation instructions see the "IDAS Installation Procedure"
+chapter in the IDAS User Guide.
+
+
+C. References
+-------------
+
+[1] R. Serban and C. Petra, "User Documentation for IDAS v1.1.0,"
+ LLNL technical report UCRL-SM-234051, December 2011.
+
+[2] R. Serban, "Example Programs for IDAS v1.1.0,"
+ LLNL technical report LLNL-TR-437091, December 2011.
+
+[3] A. C. Hindmarsh, P. N. Brown, K. E. Grant, S. L. Lee, R. Serban,
+ D. E. Shumaker, and C. S. Woodward, "SUNDIALS, Suite of Nonlinear and
+ Differential/Algebraic Equation Solvers," ACM Trans. Math. Softw.,
+ 31(3), pp. 363-396, 2005.
+
+
+D. Releases
+-----------
+
+v. 1.1.0 - Mar. 2012
+v. 1.0.0 - May 2009
+
+
+E. Revision History
+-------------------
+
+v. 1.6.0 (May 2009) ---> v. 1.1.0 (Mar. 2012)
+---------------------------------------------
+
+- Bug fixes
+ - errors in the logic for the integration of backward problems were
+ identified and fixed.
+ - a missing vector pointer setting was added in IDASensLineSrch.
+ - in IDACompleteStep, conditionals around lines loading a new column of three
+ auxiliary divided difference arrays, for a possible order increase, were fixed.
+ - after the solver memory is created, it is set to zero before being filled.
+ - in each linear solver interface function, the linear solver memory is
+ freed on an error return, and the **Free function now includes a
+ line setting to NULL the main memory pointer to the linear solver memory.
+ - a memory leak was fixed in two of the IDASp***Free functions.
+ - in rootfinding functions IDARcheck1/IDARcheck2, when an exact zero is found,
+ the array glo at the left endpoint is adjusted instead of shifting tlo.
+
+- Changes to user interface
+ - One significant design change was made with this release: The problem
+ size and its relatives, bandwidth parameters, related internal indices,
+ pivot arrays, and the optional output lsflag, have all been
+ changed from type int to type long int, except for the
+ problem size and bandwidths in user calls to routines specifying
+ BLAS/LAPACK routines for the dense/band linear solvers. The function
+ NewIntArray is replaced by a pair NewIntArray/NewLintArray,
+ for int and long int arrays, respectively.
+ - in a minor change to the user interface, the type of the index
+ which in IDAS was changed from long int to int.
+ - in the installation files, we modified the treatment of the macro
+ SUNDIALS_USE_GENERIC_MATH, so that the parameter GENERIC_MATH_LIB
+ is either defined (with no value) or not defined.
diff --git a/src/idas/idaa.c b/src/idas/idaa.c
new file mode 100644
index 0000000..1377edd
--- /dev/null
+++ b/src/idas/idaa.c
@@ -0,0 +1,3315 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.15 $
+ * $Date: 2011/12/07 23:28:51 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * This is the implementation file for the IDAA adjoint integrator.
+ * -----------------------------------------------------------------
+ */
+
+/*=================================================================*/
+/* Import Header Files */
+/*=================================================================*/
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "idas_impl.h"
+#include <sundials/sundials_math.h>
+
+/*=================================================================*/
+/* Macros */
+/*=================================================================*/
+
+#define loop for(;;)
+
+/*=================================================================*/
+/* IDAA Private Constants */
+/*=================================================================*/
+
+#define ZERO RCONST(0.0) /* real 0.0 */
+#define ONE RCONST(1.0) /* real 1.0 */
+#define TWO RCONST(2.0) /* real 2.0 */
+#define HUNDRED RCONST(100.0) /* real 100.0 */
+#define FUZZ_FACTOR RCONST(1000000.0) /* fuzz factor for IDAAgetY */
+
+
+/*=================================================================*/
+/* Private Functions Prototypes */
+/*=================================================================*/
+
+static CkpntMem IDAAckpntInit(IDAMem IDA_mem);
+static CkpntMem IDAAckpntNew(IDAMem IDA_mem);
+static void IDAAckpntCopyVectors(IDAMem IDA_mem, CkpntMem ck_mem);
+static booleantype IDAAckpntAllocVectors(IDAMem IDA_mem, CkpntMem ck_mem);
+static void IDAAckpntDelete(CkpntMem *ck_memPtr);
+
+static void IDAAbckpbDelete(IDABMem *IDAB_memPtr);
+
+static booleantype IDAAdataMalloc(IDAMem IDA_mem);
+static void IDAAdataFree(IDAMem IDA_mem);
+static int IDAAdataStore(IDAMem IDA_mem, CkpntMem ck_mem);
+
+static int IDAAckpntGet(IDAMem IDA_mem, CkpntMem ck_mem);
+
+static booleantype IDAAhermiteMalloc(IDAMem IDA_mem);
+static void IDAAhermiteFree(IDAMem IDA_mem);
+static int IDAAhermiteStorePnt(IDAMem IDA_mem, DtpntMem d);
+static int IDAAhermiteGetY(IDAMem IDA_mem, realtype t,
+ N_Vector yy, N_Vector yp,
+ N_Vector *yyS, N_Vector *ypS);
+
+static booleantype IDAApolynomialMalloc(IDAMem IDA_mem);
+static void IDAApolynomialFree(IDAMem IDA_mem);
+static int IDAApolynomialStorePnt(IDAMem IDA_mem, DtpntMem d);
+static int IDAApolynomialGetY(IDAMem IDA_mem, realtype t,
+ N_Vector yy, N_Vector yp,
+ N_Vector *yyS, N_Vector *ypS);
+
+static int IDAAfindIndex(IDAMem ida_mem, realtype t,
+ long int *indx, booleantype *newpoint);
+
+static int IDAAres(realtype tt,
+ N_Vector yyB, N_Vector ypB,
+ N_Vector resvalB, void *ida_mem);
+
+static int IDAArhsQ(realtype tt,
+ N_Vector yyB, N_Vector ypB,
+ N_Vector rrQB, void *ida_mem);
+
+static int IDAAGettnSolutionYp(IDAMem IDA_mem, N_Vector yp);
+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 */
+/*=================================================================*/
+
+/*
+ * IDAAdjInit
+ *
+ * This routine allocates space for the global IDAA memory
+ * structure.
+ */
+
+
+int IDAAdjInit(void *ida_mem, long int steps, int interp)
+{
+ IDAadjMem IDAADJ_mem;
+ IDAMem IDA_mem;
+
+ /* Check arguments */
+
+ if (ida_mem == NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAA", "IDAAdjInit", MSGAM_NULL_IDAMEM);
+ return(IDA_MEM_NULL);
+ }
+ IDA_mem = (IDAMem)ida_mem;
+
+ if (steps <= 0) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAA", "IDAAdjInit", MSGAM_BAD_STEPS);
+ return(IDA_ILL_INPUT);
+ }
+
+ if ( (interp != IDA_HERMITE) && (interp != IDA_POLYNOMIAL) ) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAA", "IDAAdjInit", MSGAM_BAD_INTERP);
+ return(IDA_ILL_INPUT);
+ }
+
+ /* Allocate memory block for IDAadjMem. */
+ IDAADJ_mem = (IDAadjMem) malloc(sizeof(struct IDAadjMemRec));
+ if (IDAADJ_mem == NULL) {
+ IDAProcessError(IDA_mem, IDA_MEM_FAIL, "IDAA", "IDAAdjInit", MSGAM_MEM_FAIL);
+ return(IDA_MEM_FAIL);
+ }
+
+ /* Attach IDAS memory for forward runs */
+ IDA_mem->ida_adj_mem = IDAADJ_mem;
+
+ /* Initialization of check points. */
+ IDAADJ_mem->ck_mem = NULL;
+ IDAADJ_mem->ia_nckpnts = 0;
+ IDAADJ_mem->ia_ckpntData = NULL;
+
+
+ /* Initialization of interpolation data. */
+ IDAADJ_mem->ia_interpType = interp;
+ IDAADJ_mem->ia_nsteps = steps;
+
+ /* Allocate space for the array of Data Point structures. */
+ if (IDAAdataMalloc(IDA_mem) == FALSE) {
+ free(IDAADJ_mem); IDAADJ_mem = NULL;
+ IDAProcessError(IDA_mem, IDA_MEM_FAIL, "IDAA", "IDAAdjInit", MSGAM_MEM_FAIL);
+ return(IDA_MEM_FAIL);
+ }
+
+ /* Attach functions for the appropriate interpolation module */
+ switch(interp) {
+
+ case IDA_HERMITE:
+ IDAADJ_mem->ia_malloc = IDAAhermiteMalloc;
+ IDAADJ_mem->ia_free = IDAAhermiteFree;
+ IDAADJ_mem->ia_getY = IDAAhermiteGetY;
+ IDAADJ_mem->ia_storePnt = IDAAhermiteStorePnt;
+ break;
+
+ case IDA_POLYNOMIAL:
+
+ IDAADJ_mem->ia_malloc = IDAApolynomialMalloc;
+ IDAADJ_mem->ia_free = IDAApolynomialFree;
+ IDAADJ_mem->ia_getY = IDAApolynomialGetY;
+ IDAADJ_mem->ia_storePnt = IDAApolynomialStorePnt;
+ break;
+ }
+
+ /* The interpolation module has not been initialized yet */
+ IDAADJ_mem->ia_mallocDone = FALSE;
+
+ /* By default we will store but not interpolate sensitivities
+ * - storeSensi will be set in IDASolveF to FALSE if FSA is not enabled
+ * or if the user forced this through IDASetAdjNoSensi
+ * - interpSensi will be set in IDASolveB to TRUE if storeSensi is TRUE
+ * 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.*/
+
+ IDAADJ_mem->ia_storeSensi = TRUE;
+ IDAADJ_mem->ia_interpSensi = FALSE;
+ IDAADJ_mem->ia_noInterp = FALSE;
+
+ /* Initialize backward problems. */
+ IDAADJ_mem->IDAB_mem = NULL;
+ IDAADJ_mem->ia_bckpbCrt = NULL;
+ 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;
+
+ /* Adjoint module initialized and allocated. */
+ IDA_mem->ida_adj = TRUE;
+ IDA_mem->ida_adjMallocDone = TRUE;
+
+ return(IDA_SUCCESS);
+}
+
+/*
+ * IDAAdjReInit
+ *
+ * IDAAdjReInit reinitializes the IDAS memory structure for ASA
+ */
+
+int IDAAdjReInit(void *ida_mem)
+{
+ IDAadjMem IDAADJ_mem;
+ IDAMem IDA_mem;
+
+ /* Check arguments */
+
+ if (ida_mem == NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAA", "IDAAdjReInit", MSGAM_NULL_IDAMEM);
+ return(IDA_MEM_NULL);
+ }
+ IDA_mem = (IDAMem)ida_mem;
+
+ /* Was ASA previously initialized? */
+ if(IDA_mem->ida_adjMallocDone == FALSE) {
+ IDAProcessError(IDA_mem, IDA_NO_ADJ, "IDAA", "IDAAdjReInit", MSGAM_NO_ADJ);
+ return(IDA_NO_ADJ);
+ }
+
+ IDAADJ_mem = IDA_mem->ida_adj_mem;
+
+ /* Free all stored checkpoints. */
+ while (IDAADJ_mem->ck_mem != NULL)
+ IDAAckpntDelete(&(IDAADJ_mem->ck_mem));
+
+ IDAADJ_mem->ck_mem = NULL;
+ IDAADJ_mem->ia_nckpnts = 0;
+ 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;
+
+ return(IDA_SUCCESS);
+}
+
+/*
+ * IDAAdjFree
+ *
+ * IDAAdjFree routine frees the memory allocated by IDAAdjInit.
+*/
+
+
+void IDAAdjFree(void *ida_mem)
+{
+ IDAMem IDA_mem;
+ IDAadjMem IDAADJ_mem;
+
+ if (ida_mem == NULL) return;
+ IDA_mem = (IDAMem) ida_mem;
+
+ if(IDA_mem->ida_adjMallocDone) {
+
+ /* Data for adjoint. */
+ IDAADJ_mem = IDA_mem->ida_adj_mem;
+
+ /* Delete check points one by one */
+ while (IDAADJ_mem->ck_mem != NULL) {
+ IDAAckpntDelete(&(IDAADJ_mem->ck_mem));
+ }
+
+ IDAAdataFree(IDA_mem);
+
+ /* Free all backward problems. */
+ while (IDAADJ_mem->IDAB_mem != NULL)
+ IDAAbckpbDelete( &(IDAADJ_mem->IDAB_mem) );
+
+ /* Free IDAA memory. */
+ free(IDAADJ_mem);
+
+ IDA_mem->ida_adj_mem = NULL;
+ }
+}
+
+/*
+ * =================================================================
+ * PRIVATE FUNCTIONS FOR BACKWARD PROBLEMS
+ * =================================================================
+ */
+
+static void IDAAbckpbDelete(IDABMem *IDAB_memPtr)
+{
+ IDABMem IDAB_mem = (*IDAB_memPtr);
+ void * ida_mem;
+
+ if (IDAB_mem == NULL) return;
+
+ /* Move head to the next element in list. */
+ *IDAB_memPtr = IDAB_mem->ida_next;
+
+ /* IDAB_mem is going to be deallocated. */
+
+ /* Free IDAS memory for this backward problem. */
+ ida_mem = (void *)IDAB_mem->IDA_mem;
+ IDAFree(&ida_mem);
+
+ /* Free linear solver memory. */
+ if (IDAB_mem->ida_lfree != NULL) IDAB_mem->ida_lfree(IDAB_mem);
+
+ /* Free preconditioner memory. */
+ if (IDAB_mem->ida_pfree != NULL) IDAB_mem->ida_pfree(IDAB_mem);
+
+ /* Free any workspace vectors. */
+ N_VDestroy(IDAB_mem->ida_yy);
+ N_VDestroy(IDAB_mem->ida_yp);
+
+ /* Free the node itself. */
+ free(IDAB_mem);
+ IDAB_mem = NULL;
+}
+
+/*=================================================================*/
+/* Wrappers for IDAA */
+/*=================================================================*/
+
+/*
+ * IDASolveF
+ *
+ * This routine integrates to tout and returns solution into yout.
+ * In the same time, it stores check point data every 'steps' steps.
+ *
+ * IDASolveF can be called repeatedly by the user. The last tout
+ * will be used as the starting time for the backward integration.
+ *
+ * ncheckPtr points to the number of check points stored so far.
+*/
+
+int IDASolveF(void *ida_mem, realtype tout, realtype *tret,
+ N_Vector yret, N_Vector ypret, int itask, int *ncheckPtr)
+{
+ IDAadjMem IDAADJ_mem;
+ IDAMem IDA_mem;
+ CkpntMem tmp;
+ DtpntMem *dt_mem;
+ int flag, i;
+ booleantype iret, allocOK;
+
+ /* Is the mem OK? */
+ if (ida_mem == NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAA", "IDASolveF", MSGAM_NULL_IDAMEM);
+ return(IDA_MEM_NULL);
+ }
+ IDA_mem = (IDAMem) ida_mem;
+
+ /* Is ASA initialized ? */
+ if (IDA_mem->ida_adjMallocDone == FALSE) {
+ IDAProcessError(IDA_mem, IDA_NO_ADJ, "IDAA", "IDASolveF", MSGAM_NO_ADJ);
+ return(IDA_NO_ADJ);
+ }
+ IDAADJ_mem = IDA_mem->ida_adj_mem;
+
+ /* Check for yret != NULL */
+ if (yret == NULL) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAA", "IDASolveF", MSG_YRET_NULL);
+ return(IDA_ILL_INPUT);
+ }
+
+ /* Check for ypret != NULL */
+ if (ypret == NULL) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAA", "IDASolveF", MSG_YPRET_NULL);
+ return(IDA_ILL_INPUT);
+ }
+ /* Check for tret != NULL */
+ if (tret == NULL) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAA", "IDASolveF", MSG_TRET_NULL);
+ return(IDA_ILL_INPUT);
+ }
+
+ /* Check for valid itask */
+ if ( (itask != IDA_NORMAL) && (itask != IDA_ONE_STEP) ) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAA", "IDASolveF", MSG_BAD_ITASK);
+ return(IDA_ILL_INPUT);
+ }
+
+ /* All memory checks done, proceed ... */
+
+ dt_mem = IDAADJ_mem->dt_mem;
+
+ /* If tstop is enabled, store some info */
+ if (IDA_mem->ida_tstopset) {
+ IDAADJ_mem->ia_tstopIDAFcall = TRUE;
+ 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;
+
+ /* On the first step:
+ * - set tinitial
+ * - initialize list of check points
+ * - if needed, initialize the interpolation module
+ * - load dt_mem[0]
+ * On subsequent steps, test if taking a new step is necessary.
+ */
+ if ( IDAADJ_mem->ia_firstIDAFcall ) {
+
+ tinitial = 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) {
+ /* Do we need to store sensitivities? */
+ if (!sensi) storeSensi = FALSE;
+
+ /* Allocate space for interpolation data */
+ allocOK = IDAADJ_mem->ia_malloc(IDA_mem);
+ if (!allocOK) {
+ IDAProcessError(IDA_mem, IDA_MEM_FAIL, "IDAA", "IDASolveF", MSG_MEM_FAIL);
+ return(IDA_MEM_FAIL);
+ }
+
+ /* 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];
+ }
+
+ mallocDone = TRUE;
+ }
+
+ dt_mem[0]->t = IDAADJ_mem->ck_mem->ck_t0;
+ IDAADJ_mem->ia_storePnt(IDA_mem, dt_mem[0]);
+
+ IDAADJ_mem->ia_firstIDAFcall = FALSE;
+
+ } else if ( (tn-tout)*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;
+
+ return(flag);
+ }
+ /* Integrate to tout while loading check points */
+ loop {
+
+ /* Perform one step of the integration */
+
+ flag = IDASolve(IDA_mem, tout, tret, yret, ypret, IDA_ONE_STEP);
+
+ if (flag < 0) break;
+
+ /* Test if a new check point is needed */
+
+ if ( nst % nsteps == 0 ) {
+
+ IDAADJ_mem->ck_mem->ck_t1 = *tret;
+
+ /* Create a new check point, load it, and append it to the list */
+ tmp = IDAAckpntNew(IDA_mem);
+ if (tmp == NULL) {
+ flag = IDA_MEM_FAIL;
+ break;
+ }
+
+ tmp->ck_next = IDAADJ_mem->ck_mem;
+ IDAADJ_mem->ck_mem = tmp;
+ nckpnts++;
+
+ forceSetup = TRUE;
+
+ /* Reset i=0 and load dt_mem[0] */
+ dt_mem[0]->t = IDAADJ_mem->ck_mem->ck_t0;
+ IDAADJ_mem->ia_storePnt(IDA_mem, dt_mem[0]);
+
+ } else {
+
+ /* Load next point in dt_mem */
+ dt_mem[nst%nsteps]->t = *tret;
+ IDAADJ_mem->ia_storePnt(IDA_mem, dt_mem[nst%nsteps]);
+ }
+
+ /* Set t1 field of the current ckeck point structure
+ for the case in which there will be no future
+ check points */
+ IDAADJ_mem->ck_mem->ck_t1 = *tret;
+
+ /* tfinal is now set to *t */
+ 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 ) {
+ *tret = tout;
+ IDAGetSolution(IDA_mem, tout, yret, ypret);
+ /* Reset tretlast in IDA_mem so that IDAGetQuad and IDAGetSens
+ * evaluate quadratures and/or sensitivities at the proper time */
+ IDA_mem->ida_tretlast = tout;
+ break;
+ }
+ }
+
+ /* Get ncheck from IDAADJ_mem */
+ *ncheckPtr = nckpnts;
+
+ /* Data is available for the last interval */
+ newData = TRUE;
+ ckpntData = IDAADJ_mem->ck_mem;
+ np = nst % nsteps + 1;
+
+ return(flag);
+}
+
+
+
+
+/*
+ * =================================================================
+ * FUNCTIONS FOR BACKWARD PROBLEMS
+ * =================================================================
+ */
+
+int IDACreateB(void *ida_mem, int *which)
+{
+ IDAMem IDA_mem;
+ void* ida_memB;
+ IDABMem new_IDAB_mem;
+ IDAadjMem IDAADJ_mem;
+
+ /* Is the mem OK? */
+ if (ida_mem == NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAA", "IDACreateB", MSGAM_NULL_IDAMEM);
+ return(IDA_MEM_NULL);
+ }
+ IDA_mem = (IDAMem) ida_mem;
+
+ /* Is ASA initialized ? */
+ if (IDA_mem->ida_adjMallocDone == FALSE) {
+ IDAProcessError(IDA_mem, IDA_NO_ADJ, "IDAA", "IDACreateB", MSGAM_NO_ADJ);
+ return(IDA_NO_ADJ);
+ }
+ IDAADJ_mem = IDA_mem->ida_adj_mem;
+
+ /* Allocate a new IDABMem struct. */
+ new_IDAB_mem = (IDABMem) malloc( sizeof( struct IDABMemRec ) );
+ if (new_IDAB_mem == NULL) {
+ IDAProcessError(IDA_mem, IDA_MEM_FAIL, "IDAA", "IDACreateB", MSG_MEM_FAIL);
+ return(IDA_MEM_FAIL);
+ }
+
+ /* Allocate the IDAMem struct needed by this backward problem. */
+ ida_memB = IDACreate();
+ if (ida_memB == NULL) {
+ IDAProcessError(IDA_mem, IDA_MEM_FAIL, "IDAA", "IDACreateB", MSG_MEM_FAIL);
+ return(IDA_MEM_FAIL);
+ }
+
+ /* Save ida_mem in ida_memB as user data. */
+ IDASetUserData(ida_memB, ida_mem);
+
+ /* Set same error output and handler for ida_memB. */
+ IDASetErrHandlerFn(ida_memB, IDA_mem->ida_ehfun, IDA_mem->ida_eh_data);
+ IDASetErrFile(ida_memB, IDA_mem->ida_errfp);
+
+ /* Initialize fields in the IDABMem struct. */
+ new_IDAB_mem->ida_index = IDAADJ_mem->ia_nbckpbs;
+ new_IDAB_mem->IDA_mem = (IDAMem) ida_memB;
+
+ new_IDAB_mem->ida_res = NULL;
+ new_IDAB_mem->ida_resS = NULL;
+ new_IDAB_mem->ida_rhsQ = NULL;
+ new_IDAB_mem->ida_rhsQS = NULL;
+
+
+ new_IDAB_mem->ida_user_data = NULL;
+
+ new_IDAB_mem->ida_lmem = NULL;
+ new_IDAB_mem->ida_lfree = NULL;
+ new_IDAB_mem->ida_pmem = NULL;
+ new_IDAB_mem->ida_pfree = NULL;
+
+ 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;
+
+ /* Attach the new object to the beginning of the linked list IDAADJ_mem->IDAB_mem. */
+ new_IDAB_mem->ida_next = IDAADJ_mem->IDAB_mem;
+ IDAADJ_mem->IDAB_mem = new_IDAB_mem;
+
+ /* Return the assigned index. This id is used as identificator and has to be passed
+ to IDAInitB and other ***B functions that set the optional inputs for this
+ backward problem. */
+ *which = IDAADJ_mem->ia_nbckpbs;
+
+ /*Increase the counter of the backward problems stored. */
+ IDAADJ_mem->ia_nbckpbs++;
+
+ return(IDA_SUCCESS);
+
+}
+
+int IDAInitB(void *ida_mem, int which, IDAResFnB resB,
+ realtype tB0, N_Vector yyB0, N_Vector ypB0)
+{
+ IDAadjMem IDAADJ_mem;
+ IDAMem IDA_mem;
+ IDABMem IDAB_mem;
+ void * ida_memB;
+ int flag;
+
+ if (ida_mem == NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAA", "IDAInitB", MSGAM_NULL_IDAMEM);
+ return(IDA_MEM_NULL);
+ }
+ IDA_mem = (IDAMem) ida_mem;
+
+ /* Is ASA initialized ? */
+ if (IDA_mem->ida_adjMallocDone == FALSE) {
+ 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) ) {
+ IDAProcessError(IDA_mem, IDA_BAD_TB0, "IDAA", "IDAInitB", MSGAM_BAD_TB0);
+ return(IDA_BAD_TB0);
+ }
+
+ /* Check the value of which */
+ if ( which >= nbckpbs ) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAA", "IDAInitB", MSGAM_BAD_WHICH);
+ return(IDA_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;
+
+ /* Call the IDAInit for this backward problem. */
+ flag = IDAInit(ida_memB, IDAAres, tB0, yyB0, ypB0);
+ if (IDA_SUCCESS != flag) return(flag);
+
+ /* Copy residual function in IDAB_mem. */
+ IDAB_mem->ida_res = resB;
+ IDAB_mem->ida_res_withSensi = FALSE;
+
+ /* Initialized the initial time field. */
+ IDAB_mem->ida_t0 = tB0;
+
+ /* Allocate and initialize space workspace vectors. */
+ IDAB_mem->ida_yy = N_VClone(yyB0);
+ IDAB_mem->ida_yp = N_VClone(yyB0);
+ N_VScale(ONE, yyB0, IDAB_mem->ida_yy);
+ N_VScale(ONE, ypB0, IDAB_mem->ida_yp);
+
+ return(flag);
+
+}
+
+int IDAInitBS(void *ida_mem, int which, IDAResFnBS resS,
+ realtype tB0, N_Vector yyB0, N_Vector ypB0)
+{
+ IDAadjMem IDAADJ_mem;
+ IDAMem IDA_mem;
+ IDABMem IDAB_mem;
+ void * ida_memB;
+ int flag;
+
+ if (ida_mem == NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAA", "IDAInitBS", MSGAM_NULL_IDAMEM);
+ return(IDA_MEM_NULL);
+ }
+ IDA_mem = (IDAMem) ida_mem;
+
+ /* Is ASA initialized ? */
+ if (IDA_mem->ida_adjMallocDone == FALSE) {
+ 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) ) {
+ IDAProcessError(IDA_mem, IDA_BAD_TB0, "IDAA", "IDAInitBS", MSGAM_BAD_TB0);
+ return(IDA_BAD_TB0);
+ }
+
+ /* Were sensitivities active during the forward integration? */
+ if (!storeSensi) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAA", "IDAInitBS", MSGAM_BAD_SENSI);
+ return(IDA_ILL_INPUT);
+ }
+
+ /* Check the value of which */
+ if ( which >= nbckpbs ) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAA", "IDAInitBS", MSGAM_BAD_WHICH);
+ return(IDA_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;
+
+ /* Allocate and set the IDAS object */
+ flag = IDAInit(ida_memB, IDAAres, tB0, yyB0, ypB0);
+
+ if (flag != IDA_SUCCESS) return(flag);
+
+ /* Copy residual function pointer in IDAB_mem. */
+ IDAB_mem->ida_res_withSensi = TRUE;
+ IDAB_mem->ida_resS = resS;
+
+ /* Allocate space and initialize the yy and yp vectors. */
+ IDAB_mem->ida_t0 = tB0;
+ IDAB_mem->ida_yy = N_VClone(yyB0);
+ IDAB_mem->ida_yp = N_VClone(ypB0);
+ N_VScale(ONE, yyB0, IDAB_mem->ida_yy);
+ N_VScale(ONE, ypB0, IDAB_mem->ida_yp);
+
+ return(IDA_SUCCESS);
+}
+
+
+int IDAReInitB(void *ida_mem, int which,
+ realtype tB0, N_Vector yyB0, N_Vector ypB0)
+{
+
+ IDAadjMem IDAADJ_mem;
+ IDAMem IDA_mem;
+ IDABMem IDAB_mem;
+ void * ida_memB;
+ int flag;
+
+ if (ida_mem == NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAA", "IDAReInitB", MSGAM_NULL_IDAMEM);
+ return(IDA_MEM_NULL);
+ }
+ IDA_mem = (IDAMem) ida_mem;
+
+ /* Is ASA initialized ? */
+ if (IDA_mem->ida_adjMallocDone == FALSE) {
+ 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) ) {
+ IDAProcessError(IDA_mem, IDA_BAD_TB0, "IDAA", "IDAReInitB", MSGAM_BAD_TB0);
+ return(IDA_BAD_TB0);
+ }
+
+ /* Check the value of which */
+ if ( which >= nbckpbs ) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAA", "IDAReInitB", MSGAM_BAD_WHICH);
+ return(IDA_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;
+
+
+ /* Call the IDAReInit for this backward problem. */
+ flag = IDAReInit(ida_memB, tB0, yyB0, ypB0);
+ return(flag);
+}
+
+int IDASStolerancesB(void *ida_mem, int which,
+ realtype relTolB, realtype absTolB)
+{
+ IDAMem IDA_mem;
+ IDAadjMem IDAADJ_mem;
+ IDABMem IDAB_mem;
+ void *ida_memB;
+
+ /* Is ida_mem valid? */
+ if (ida_mem == NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAA", "IDASStolerancesB", MSGAM_NULL_IDAMEM);
+ return IDA_MEM_NULL;
+ }
+ IDA_mem = (IDAMem) ida_mem;
+
+ /* Is ASA initialized? */
+ if (IDA_mem->ida_adjMallocDone == FALSE) {
+ 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 ) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAA", "IDASStolerancesB", MSGAM_BAD_WHICH);
+ return(IDA_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;
+
+ /* Set tolerances and return. */
+ return IDASStolerances(ida_memB, relTolB, absTolB);
+
+}
+int IDASVtolerancesB(void *ida_mem, int which,
+ realtype relTolB, N_Vector absTolB)
+{
+ IDAMem IDA_mem;
+ IDAadjMem IDAADJ_mem;
+ IDABMem IDAB_mem;
+ void *ida_memB;
+
+ /* Is ida_mem valid? */
+ if (ida_mem == NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAA", "IDASVtolerancesB", MSGAM_NULL_IDAMEM);
+ return IDA_MEM_NULL;
+ }
+ IDA_mem = (IDAMem) ida_mem;
+
+ /* Is ASA initialized? */
+ if (IDA_mem->ida_adjMallocDone == FALSE) {
+ 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 ) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAA", "IDASVtolerancesB", MSGAM_BAD_WHICH);
+ return(IDA_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;
+
+ /* Set tolerances and return. */
+ return IDASVtolerances(ida_memB, relTolB, absTolB);
+}
+
+int IDAQuadSStolerancesB(void *ida_mem, int which,
+ realtype reltolQB, realtype abstolQB)
+{
+ IDAMem IDA_mem;
+ IDAadjMem IDAADJ_mem;
+ IDABMem IDAB_mem;
+ void *ida_memB;
+
+ /* Is ida_mem valid? */
+ if (ida_mem == NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAA", "IDAQuadSStolerancesB", MSGAM_NULL_IDAMEM);
+ return IDA_MEM_NULL;
+ }
+ IDA_mem = (IDAMem) ida_mem;
+
+ /* Is ASA initialized? */
+ if (IDA_mem->ida_adjMallocDone == FALSE) {
+ 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 ) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAA", "IDAQuadSStolerancesB", MSGAM_BAD_WHICH);
+ return(IDA_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;
+
+ return IDAQuadSStolerances(ida_memB, reltolQB, abstolQB);
+}
+
+
+int IDAQuadSVtolerancesB(void *ida_mem, int which,
+ realtype reltolQB, N_Vector abstolQB)
+{
+ IDAMem IDA_mem;
+ IDAadjMem IDAADJ_mem;
+ IDABMem IDAB_mem;
+ void *ida_memB;
+
+ /* Is ida_mem valid? */
+ if (ida_mem == NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAA", "IDAQuadSVtolerancesB", MSGAM_NULL_IDAMEM);
+ return IDA_MEM_NULL;
+ }
+ IDA_mem = (IDAMem) ida_mem;
+
+ /* Is ASA initialized? */
+ if (IDA_mem->ida_adjMallocDone == FALSE) {
+ 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 ) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAA", "IDAQuadSVtolerancesB", MSGAM_BAD_WHICH);
+ return(IDA_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;
+
+ return IDAQuadSVtolerances(ida_memB, reltolQB, abstolQB);
+}
+
+
+int IDAQuadInitB(void *ida_mem, int which, IDAQuadRhsFnB rhsQB, N_Vector yQB0)
+{
+ IDAMem IDA_mem;
+ IDAadjMem IDAADJ_mem;
+ IDABMem IDAB_mem;
+ void *ida_memB;
+ int flag;
+
+ /* Is ida_mem valid? */
+ if (ida_mem == NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAA", "IDAQuadInitB", MSGAM_NULL_IDAMEM);
+ return IDA_MEM_NULL;
+ }
+ IDA_mem = (IDAMem) ida_mem;
+
+ /* Is ASA initialized? */
+ if (IDA_mem->ida_adjMallocDone == FALSE) {
+ 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 ) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAA", "IDAQuadInitB", MSGAM_BAD_WHICH);
+ return(IDA_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 = IDAQuadInit(ida_memB, IDAArhsQ, yQB0);
+ if (IDA_SUCCESS != flag) return flag;
+
+ IDAB_mem->ida_rhsQ_withSensi = FALSE;
+ IDAB_mem->ida_rhsQ = rhsQB;
+
+ return(flag);
+}
+
+
+int IDAQuadInitBS(void *ida_mem, int which,
+ IDAQuadRhsFnBS rhsQS, N_Vector yQB0)
+{
+ IDAadjMem IDAADJ_mem;
+ IDAMem IDA_mem;
+ IDABMem IDAB_mem;
+ void * ida_memB;
+ int flag;
+
+ if (ida_mem == NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAA", "IDAQuadInitBS", MSGAM_NULL_IDAMEM);
+ return(IDA_MEM_NULL);
+ }
+ IDA_mem = (IDAMem) ida_mem;
+
+ /* Is ASA initialized ? */
+ if (IDA_mem->ida_adjMallocDone == FALSE) {
+ 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 ) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAA", "IDAQuadInitBS", MSGAM_BAD_WHICH);
+ return(IDA_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;
+
+ /* Allocate and set the IDAS object */
+ flag = IDAQuadInit(ida_memB, IDAArhsQ, yQB0);
+
+ 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_rhsQS = rhsQS;
+
+ return(IDA_SUCCESS);
+}
+
+
+int IDAQuadReInitB(void *ida_mem, int which, N_Vector yQB0)
+{
+ IDAMem IDA_mem;
+ IDAadjMem IDAADJ_mem;
+ IDABMem IDAB_mem;
+ void *ida_memB;
+
+ /* Is ida_mem valid? */
+ if (ida_mem == NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAA", "IDAQuadInitB", MSGAM_NULL_IDAMEM);
+ return IDA_MEM_NULL;
+ }
+ IDA_mem = (IDAMem) ida_mem;
+
+ /* Is ASA initialized? */
+ if (IDA_mem->ida_adjMallocDone == FALSE) {
+ 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 ) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAA", "IDAQuadInitB", MSGAM_BAD_WHICH);
+ return(IDA_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;
+
+ return IDAQuadReInit(ida_mem, yQB0);
+}
+
+
+/*
+ * ----------------------------------------------------------------
+ * Function : IDACalcICB
+ * ----------------------------------------------------------------
+ * IDACalcIC calculates corrected initial conditions for a DAE
+ * backward system (index-one in semi-implicit form).
+ * It uses Newton iteration combined with a Linesearch algorithm.
+ * Calling IDACalcICB is optional. It is only necessary when the
+ * initial conditions do not solve the given system. I.e., if
+ * yB0 and ypB0 are known to satisfy the backward problem, then
+ * a call to IDACalcIC is NOT necessary (for index-one problems).
+*/
+
+int IDACalcICB(void *ida_mem, int which, realtype tout1,
+ N_Vector yy0, N_Vector yp0)
+{
+ IDAMem IDA_mem;
+ IDAadjMem IDAADJ_mem;
+ IDABMem IDAB_mem;
+ void *ida_memB;
+ int flag;
+
+ /* Is ida_mem valid? */
+ if (ida_mem == NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAA", "IDACalcICB", MSGAM_NULL_IDAMEM);
+ return IDA_MEM_NULL;
+ }
+ IDA_mem = (IDAMem) ida_mem;
+
+ /* Is ASA initialized? */
+ if (IDA_mem->ida_adjMallocDone == FALSE) {
+ 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 ) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAA", "IDACalcICB", MSGAM_BAD_WHICH);
+ return(IDA_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;
+
+ /* The wrapper for user supplied res function requires ia_bckpbCrt from
+ IDAAdjMem to be set to curent problem. */
+ IDAADJ_mem->ia_bckpbCrt = IDAB_mem;
+
+ /* 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);
+
+ /* Set noInterp flag to true, so IDAARes will use user provided values for
+ y and y' and will not call the interpolation routine(s). */
+ noInterp = TRUE;
+
+ flag = IDACalcIC(ida_memB, IDA_YA_YDP_INIT, tout1);
+
+ /* Set interpolation on in IDAARes. */
+ noInterp = FALSE;
+
+ return(flag);
+}
+
+/*
+ * ----------------------------------------------------------------
+ * Function : IDACalcICBS
+ * ----------------------------------------------------------------
+ * IDACalcIC calculates corrected initial conditions for a DAE
+ * backward system (index-one in semi-implicit form) that also
+ * dependes on the sensivities.
+ *
+ * It calls IDACalcIC for the 'which' backward problem.
+*/
+
+int IDACalcICBS(void *ida_mem, int which, realtype tout1,
+ N_Vector yy0, N_Vector yp0,
+ N_Vector *yyS0, N_Vector *ypS0)
+{
+ IDAMem IDA_mem;
+ IDAadjMem IDAADJ_mem;
+ IDABMem IDAB_mem;
+ void *ida_memB;
+ int flag, is;
+
+ /* Is ida_mem valid? */
+ if (ida_mem == NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAA", "IDACalcICBS", MSGAM_NULL_IDAMEM);
+ return IDA_MEM_NULL;
+ }
+ IDA_mem = (IDAMem) ida_mem;
+
+ /* Is ASA initialized? */
+ if (IDA_mem->ida_adjMallocDone == FALSE) {
+ 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) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAA", "IDACalcICBS", MSGAM_BAD_SENSI);
+ return(IDA_ILL_INPUT);
+ }
+
+ /* Check the value of which */
+ if ( which >= nbckpbs ) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAA", "IDACalcICBS", MSGAM_BAD_WHICH);
+ return(IDA_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;
+
+ /* Was InitBS called for this problem? */
+ if (!IDAB_mem->ida_res_withSensi) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAA", "IDACalcICBS", MSGAM_NO_INITBS);
+ return(IDA_ILL_INPUT);
+ }
+
+ /* The wrapper for user supplied res function requires ia_bckpbCrt from
+ IDAAdjMem to be set to curent problem. */
+ IDAADJ_mem->ia_bckpbCrt = IDAB_mem;
+
+ /* Save (y, y') and (y_p, y'_p) in yyTmp, ypTmp and yySTmp, ypSTmp.The wrapper
+ 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);
+
+ for (is=0; is<Ns; is++) {
+ N_VScale(ONE, yyS0[is], yySTmp[is]);
+ N_VScale(ONE, ypS0[is], ypSTmp[is]);
+ }
+
+ /* Set noInterp flag to true, so IDAARes will use user provided values for
+ y and y' and will not call the interpolation routine(s). */
+ noInterp = TRUE;
+
+ flag = IDACalcIC(ida_memB, IDA_YA_YDP_INIT, tout1);
+
+ /* Set interpolation on in IDAARes. */
+ noInterp = FALSE;
+
+ return(flag);
+}
+
+
+/*
+ * IDASolveB
+ *
+ * This routine performs the backward integration from tB0
+ * to tinitial through a sequence of forward-backward runs in
+ * between consecutive check points. It returns the values of
+ * the adjoint variables and any existing quadrature variables
+ * at tinitial.
+ *
+ * On a successful return, IDASolveB returns IDA_SUCCESS.
+ *
+ * NOTE that IDASolveB DOES NOT return the solution for the
+ * backward problem(s). Use IDAGetB to extract the solution
+ * for any given backward problem.
+ *
+ * If there are multiple backward problems and multiple check points,
+ * IDASolveB may not succeed in getting all problems to take one step
+ * when called in ONE_STEP mode.
+ */
+
+int IDASolveB(void *ida_mem, realtype tBout, int itaskB)
+{
+ IDAMem IDA_mem;
+ IDAadjMem IDAADJ_mem;
+ CkpntMem ck_mem;
+ IDABMem IDAB_mem, tmp_IDAB_mem;
+ int flag, sign;
+ realtype tfuzz, tBret, tBn;
+ booleantype gotCkpnt, reachedTBout, isActive;
+
+ /* Is the mem OK? */
+ if (ida_mem == NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAA", "IDASolveB", MSGAM_NULL_IDAMEM);
+ return(IDA_MEM_NULL);
+ }
+ IDA_mem = (IDAMem) ida_mem;
+
+ /* Is ASA initialized ? */
+ if (IDA_mem->ida_adjMallocDone == FALSE) {
+ 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 ) {
+ IDAProcessError(IDA_mem, IDA_NO_BCK, "IDAA", "IDASolveB", MSGAM_NO_BCK);
+ return(IDA_NO_BCK);
+ }
+ IDAB_mem = IDAADJ_mem->IDAB_mem;
+
+ /* Check whether IDASolveF has been called */
+ if ( IDAADJ_mem->ia_firstIDAFcall ) {
+ IDAProcessError(IDA_mem, IDA_NO_FWD, "IDAA", "IDASolveB", MSGAM_NO_FWD);
+ return(IDA_NO_FWD);
+ }
+ sign = (tfinal - tinitial > ZERO) ? 1 : -1;
+
+ /* If this is the first call, loop over all backward problems and
+ * - check that tB0 is valid
+ * - check that tBout is ahead of tB0 in the backward direction
+ * - check whether we need to interpolate forward sensitivities
+ */
+ if (IDAADJ_mem->ia_firstIDABcall) {
+
+ /* First IDABMem struct. */
+ tmp_IDAB_mem = IDAB_mem;
+
+ while (tmp_IDAB_mem != NULL) {
+
+ tBn = tmp_IDAB_mem->IDA_mem->ida_tn;
+
+ if ( (sign*(tBn-tinitial) < ZERO) || (sign*(tfinal-tBn) < ZERO) ) {
+ IDAProcessError(IDA_mem, IDA_BAD_TB0, "IDAA", "IDASolveB",
+ MSGAM_BAD_TB0, tmp_IDAB_mem->ida_index);
+ return(IDA_BAD_TB0);
+ }
+
+ if (sign*(tBn-tBout) <= ZERO) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAA", "IDASolveB", MSGAM_BAD_TBOUT,
+ tmp_IDAB_mem->ida_index);
+ return(IDA_ILL_INPUT);
+ }
+
+ if ( tmp_IDAB_mem->ida_res_withSensi ||
+ tmp_IDAB_mem->ida_rhsQ_withSensi ) interpSensi = TRUE;
+
+ /* Advance in list. */
+ tmp_IDAB_mem = tmp_IDAB_mem->ida_next;
+ }
+
+ if ( interpSensi && !storeSensi) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAA", "IDASolveB", MSGAM_BAD_SENSI);
+ return(IDA_ILL_INPUT);
+ }
+
+ IDAADJ_mem->ia_firstIDABcall = FALSE;
+ }
+
+ /* Check for valid itask */
+ if ( (itaskB != IDA_NORMAL) && (itaskB != IDA_ONE_STEP) ) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAA", "IDASolveB", MSG_BAD_ITASK);
+ return(IDA_ILL_INPUT);
+ }
+
+ /* Check if tBout is legal */
+ if ( (sign*(tBout-tinitial) < ZERO) || (sign*(tfinal-tBout) < ZERO) ) {
+ tfuzz = HUNDRED*uround*(ABS(tinitial) + ABS(tfinal));
+ if ( (sign*(tBout-tinitial) < ZERO) && (ABS(tBout-tinitial) < tfuzz) ) {
+ tBout = tinitial;
+ } else {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAA", "IDASolveB", MSGAM_BAD_TBOUT);
+ return(IDA_ILL_INPUT);
+ }
+ }
+
+ /* Loop through the check points and stop as soon as a backward
+ * problem has its tn value behind the current check point's t0_
+ * value (in the backward direction) */
+
+ ck_mem = IDAADJ_mem->ck_mem;
+
+ gotCkpnt = FALSE;
+
+ loop {
+ 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;
+ break;
+ }
+
+ if ( (itaskB == IDA_NORMAL) && (tBn == t0_) && (sign*(tBout-t0_) >= ZERO) ) {
+ gotCkpnt = TRUE;
+ break;
+ }
+
+ tmp_IDAB_mem = tmp_IDAB_mem->ida_next;
+ }
+
+ if (gotCkpnt) break;
+
+ if (ck_mem->ck_next == NULL) break;
+
+ ck_mem = ck_mem->ck_next;
+ }
+
+ /* Loop while propagating backward problems */
+ loop {
+
+ /* Store interpolation data if not available.
+ This is the 2nd forward integration pass */
+ if (ck_mem != ckpntData) {
+
+ flag = IDAAdataStore(IDA_mem, ck_mem);
+ if (flag != IDA_SUCCESS) break;
+ }
+
+ /* Starting with the current check point from above, loop over check points
+ while propagating backward problems */
+
+ tmp_IDAB_mem = IDAB_mem;
+ while (tmp_IDAB_mem != NULL) {
+
+ /* Decide if current backward problem is "active" in this check point */
+ isActive = TRUE;
+
+ 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 ( isActive ) {
+ /* Store the address of current backward problem memory
+ * in IDAADJ_mem to be used in the wrapper functions */
+ IDAADJ_mem->ia_bckpbCrt = tmp_IDAB_mem;
+
+ /* Integrate current backward problem */
+ IDASetStopTime(tmp_IDAB_mem->IDA_mem, t0_);
+ flag = IDASolve(tmp_IDAB_mem->IDA_mem, tBout, &tBret,
+ tmp_IDAB_mem->ida_yy, tmp_IDAB_mem->ida_yp,
+ itaskB);
+
+ /* Set the time at which we will report solution and/or quadratures */
+ tmp_IDAB_mem->ida_tout = tBret;
+
+ /* If an error occurred, exit while loop */
+ if (flag < 0) break;
+
+ } else {
+
+ flag = IDA_SUCCESS;
+ tmp_IDAB_mem->ida_tout = tBn;
+ }
+
+ /* Move to next backward problem */
+ tmp_IDAB_mem = tmp_IDAB_mem->ida_next;
+ } /* End of while: iteration through backward problems. */
+
+ /* If an error occurred, return now */
+ if (flag <0) {
+ IDAProcessError(IDA_mem, flag, "IDAA", "IDASolveB",
+ MSGAM_BACK_ERROR, tmp_IDAB_mem->ida_index);
+ return(flag);
+ }
+
+ /* If in IDA_ONE_STEP mode, return now (flag = IDA_SUCCESS) */
+ if (itaskB == IDA_ONE_STEP) break;
+
+ /* If all backward problems have succesfully reached tBout, return now */
+ reachedTBout = TRUE;
+
+ tmp_IDAB_mem = IDAB_mem;
+ while(tmp_IDAB_mem != NULL) {
+ if ( sign*(tmp_IDAB_mem->ida_tout - tBout) > ZERO ) {
+ reachedTBout = FALSE;
+ break;
+ }
+ tmp_IDAB_mem = tmp_IDAB_mem->ida_next;
+ }
+
+ if ( reachedTBout ) break;
+
+ /* Move check point in linked list to next one */
+ ck_mem = ck_mem->ck_next;
+
+ } /* End of loop. */
+
+ return(flag);
+}
+
+
+/*
+ * IDAGetB
+ *
+ * IDAGetB returns the state variables at the same time (also returned
+ * in tret) as that at which IDASolveBreturned the solution.
+ */
+
+SUNDIALS_EXPORT int IDAGetB(void* ida_mem, int which, realtype *tret,
+ N_Vector yy, N_Vector yp)
+{
+ IDAMem IDA_mem;
+ IDAadjMem IDAADJ_mem;
+ IDABMem IDAB_mem;
+
+ /* Is ida_mem valid? */
+ if (ida_mem == NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAA", "IDAGetB", MSGAM_NULL_IDAMEM);
+ return IDA_MEM_NULL;
+ }
+ IDA_mem = (IDAMem) ida_mem;
+
+ /* Is ASA initialized? */
+ if (IDA_mem->ida_adjMallocDone == FALSE) {
+ 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 ) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAA", "IDAGetB", MSGAM_BAD_WHICH);
+ return(IDA_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;
+ }
+
+ N_VScale(ONE, IDAB_mem->ida_yy, yy);
+ N_VScale(ONE, IDAB_mem->ida_yp, yp);
+ *tret = IDAB_mem->ida_tout;
+
+ return(IDA_SUCCESS);
+}
+
+
+
+/*
+ * IDAGetQuadB
+ *
+ * IDAGetQuadB returns the quadrature variables at the same
+ * time (also returned in tret) as that at which IDASolveB
+ * returned the solution.
+ */
+
+int IDAGetQuadB(void *ida_mem, int which, realtype *tret, N_Vector qB)
+{
+ IDAMem IDA_mem;
+ IDAadjMem IDAADJ_mem;
+ IDABMem IDAB_mem;
+ void *ida_memB;
+ int flag;
+ long int nstB;
+
+ /* Is ida_mem valid? */
+ if (ida_mem == NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAA", "IDAGetQuadB", MSGAM_NULL_IDAMEM);
+ return IDA_MEM_NULL;
+ }
+ IDA_mem = (IDAMem) ida_mem;
+
+ /* Is ASA initialized? */
+ if (IDA_mem->ida_adjMallocDone == FALSE) {
+ 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 ) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAA", "IDAGetQuadB", MSGAM_BAD_WHICH);
+ return(IDA_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;
+
+ /* If the integration for this backward problem has not started yet,
+ * simply return the current value of qB (i.e. the final conditions) */
+
+ flag = IDAGetNumSteps(ida_memB, &nstB);
+ if (IDA_SUCCESS != flag) return(flag);
+
+ if (nstB == 0) {
+ N_VScale(ONE, IDAB_mem->IDA_mem->ida_phiQ[0], qB);
+ *tret = IDAB_mem->ida_tout;
+ } else {
+ flag = IDAGetQuad(ida_memB, tret, qB);
+ }
+ return(flag);
+}
+
+/*=================================================================*/
+/* Private Functions Implementation */
+/*=================================================================*/
+
+/*
+ * IDAAckpntInit
+ *
+ * This routine initializes the check point linked list with
+ * information from the initial time.
+*/
+
+static CkpntMem IDAAckpntInit(IDAMem IDA_mem)
+{
+ CkpntMem ck_mem;
+
+ /* Allocate space for ckdata */
+ ck_mem = (CkpntMem) malloc(sizeof(struct CkpntMemRec));
+ if (NULL==ck_mem) return(NULL);
+
+ t0_ = tn;
+ nst_ = 0;
+ kk_ = 1;
+ hh_ = ZERO;
+
+ /* Test if we need to carry quadratures */
+ quadr_ = quadr && errconQ;
+
+ /* Test if we need to carry sensitivities */
+ sensi_ = sensi;
+ if(sensi_) Ns_ = Ns;
+
+ /* Test if we need to carry quadrature sensitivities */
+ quadr_sensi_ = quadr_sensi && errconQS;
+
+ /* Alloc 3: current order, i.e. 1, + 2. */
+ phi_alloc_ = 3;
+
+ if (!IDAAckpntAllocVectors(IDA_mem, ck_mem)) {
+ free(ck_mem); ck_mem = NULL;
+ return(NULL);
+ }
+ /* Save phi* vectors from IDA_mem to ck_mem. */
+ IDAAckpntCopyVectors(IDA_mem, ck_mem);
+
+ /* Next in list */
+ next_ = NULL;
+
+ return(ck_mem);
+}
+
+/*
+ * IDAAckpntNew
+ *
+ * This routine allocates space for a new check point and sets
+ * its data from current values in IDA_mem.
+*/
+
+static CkpntMem IDAAckpntNew(IDAMem IDA_mem)
+{
+ CkpntMem ck_mem;
+ int j;
+
+ /* Allocate space for ckdata */
+ 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;
+
+ 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];
+ }
+
+ /* Test if we need to carry quadratures */
+ quadr_ = quadr && errconQ;
+
+ /* Test if we need to carry sensitivities */
+ sensi_ = sensi;
+ if(sensi_) Ns_ = Ns;
+
+ /* Test if we need to carry quadrature sensitivities */
+ quadr_sensi_ = quadr_sensi && errconQS;
+
+ phi_alloc_ = kk+2 < MXORDP1 ? kk+2 : MXORDP1;
+
+ if (!IDAAckpntAllocVectors(IDA_mem, ck_mem)) {
+ free(ck_mem); ck_mem = NULL;
+ return(NULL);
+ }
+
+ /* Save phi* vectors from IDA_mem to ck_mem. */
+ IDAAckpntCopyVectors(IDA_mem, ck_mem);
+
+ return(ck_mem);
+}
+
+/* IDAAckpntDelete
+ *
+ * This routine deletes the first check point in list.
+*/
+
+static void IDAAckpntDelete(CkpntMem *ck_memPtr)
+{
+ CkpntMem tmp;
+ int j;
+
+ if (*ck_memPtr != NULL) {
+ /* store head of list */
+ tmp = *ck_memPtr;
+ /* move head of list */
+ *ck_memPtr = (*ck_memPtr)->ck_next;
+
+ /* free N_Vectors in tmp */
+ for (j=0; j<tmp->ck_phi_alloc; j++)
+ N_VDestroy(tmp->ck_phi[j]);
+
+ /* free N_Vectors for quadratures in tmp */
+ if (tmp->ck_quadr) {
+ for (j=0; j<tmp->ck_phi_alloc; j++)
+ N_VDestroy(tmp->ck_phiQ[j]);
+ }
+
+ /* Free sensitivity related data. */
+ if (tmp->ck_sensi) {
+ for (j=0; j<tmp->ck_phi_alloc; j++)
+ N_VDestroyVectorArray(tmp->ck_phiS[j], tmp->ck_Ns);
+ }
+
+ if (tmp->ck_quadr_sensi) {
+ for (j=0; j<tmp->ck_phi_alloc; j++)
+ N_VDestroyVectorArray(tmp->ck_phiQS[j], tmp->ck_Ns);
+ }
+
+ free(tmp); tmp=NULL;
+ }
+}
+
+/*
+ * IDAAckpntAllocVectors
+ *
+ * Allocate checkpoint's phi, phiQ, phiS, phiQS vectors needed to save
+ * current state of IDAMem.
+ *
+ */
+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; j++) N_VDestroy(phi_[jj]);
+ return(FALSE);
+ }
+ }
+
+ /* 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; j++) N_VDestroy(phiQ_[jj]);
+
+ for(jj=0; jj<phi_alloc_; j++) N_VDestroy(phi_[jj]);
+
+ return(FALSE);
+ }
+ }
+ }
+
+ /* Do we need to carry sensitivities? */
+ if(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);
+
+ if (quadr_)
+ for (jj=0; jj<phi_alloc_; jj++) N_VDestroy(phiQ_[jj]);
+
+ for (jj=0; jj<phi_alloc_; jj++) N_VDestroy(phi_[jj]);
+
+ return(FALSE);
+ }
+ }
+ }
+
+ /* Do we need to carry quadrature sensitivities? */
+ if (quadr_sensi_) {
+
+ for (j=0; j<phi_alloc_; j++) {
+ phiQS_[j] = N_VCloneVectorArray(Ns, tempvQ);
+ if (phiQS_[j] == NULL) {
+
+ for (jj=0; jj<j; jj++) N_VDestroyVectorArray(phiQS_[jj], Ns);
+
+ for (jj=0; jj<phi_alloc_; jj++) N_VDestroyVectorArray(phiS_[jj], Ns);
+
+ if (quadr_)
+ for (jj=0; jj<phi_alloc_; jj++) N_VDestroy(phiQ_[jj]);
+
+ for (jj=0; jj<phi_alloc_; jj++) N_VDestroy(phi_[jj]);
+
+ return(FALSE);
+ }
+ }
+ }
+ return(TRUE);
+}
+
+/*
+ * IDAAckpntCopyVectors
+ *
+ * Copy phi* vectors from IDAMem in the corresponding vectors from checkpoint
+ *
+ */
+static void IDAAckpntCopyVectors(IDAMem IDA_mem, CkpntMem ck_mem)
+{
+ int j, is;
+
+ /* Save phi* arrays from IDA_mem */
+
+ for (j=0; j<phi_alloc_; j++) N_VScale(ONE, phi[j], phi_[j]);
+
+ if (quadr_) {
+ for (j=0; j<phi_alloc_; j++) N_VScale(ONE, phiQ[j], 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(quadr_sensi_) {
+ for (is=0; is<Ns; is++)
+ for (j=0; j<phi_alloc_; j++)
+ N_VScale(ONE, phiQS[j][is], phiQS_[j][is]);
+
+ }
+}
+
+/*
+ * IDAAdataMalloc
+ *
+ * This routine allocates memory for storing information at all
+ * intermediate points between two consecutive check points.
+ * This data is then used to interpolate the forward solution
+ * at any other time.
+*/
+
+static booleantype IDAAdataMalloc(IDAMem IDA_mem)
+{
+ IDAadjMem IDAADJ_mem;
+ DtpntMem *dt_mem;
+ long int i, j;
+
+ 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);
+
+ for (i=0; i<=nsteps; i++) {
+
+ dt_mem[i] = (DtpntMem)malloc(sizeof(struct DtpntMemRec));
+
+ /* On failure, free any allocated memory and return NULL. */
+ if (dt_mem[i] == NULL) {
+
+ for(j=0; j<i; j++)
+ free(dt_mem[j]);
+
+ free(dt_mem);
+ return(FALSE);
+ }
+ dt_mem[i]->content = NULL;
+ }
+ /* Attach the allocated dt_mem to IDAADJ_mem. */
+ IDAADJ_mem->dt_mem = dt_mem;
+ return(TRUE);
+}
+
+/*
+ * IDAAdataFree
+ *
+ * This routine frees the memory allocated for data storage.
+ */
+
+static void IDAAdataFree(IDAMem IDA_mem)
+{
+ IDAadjMem IDAADJ_mem;
+ long int i;
+
+ IDAADJ_mem = IDA_mem->ida_adj_mem;
+
+ if (IDAADJ_mem == NULL) return;
+
+ /* Destroy data points by calling the interpolation's 'free' routine. */
+ IDAADJ_mem->ia_free(IDA_mem);
+
+ for (i=0; i<=nsteps; i++) {
+ free(IDAADJ_mem->dt_mem[i]);
+ IDAADJ_mem->dt_mem[i] = NULL;
+ }
+
+ free(IDAADJ_mem->dt_mem);
+ IDAADJ_mem->dt_mem = NULL;
+}
+
+
+/*
+ * IDAAdataStore
+ *
+ * This routine integrates the forward model starting at the check
+ * point ck_mem and stores y and yprime at all intermediate
+ * steps.
+ *
+ * Return values:
+ * - the flag that IDASolve may return on error
+ * - IDA_REIFWD_FAIL if no check point is available for this hot start
+ * - IDA_SUCCESS
+ */
+
+static int IDAAdataStore(IDAMem IDA_mem, CkpntMem ck_mem)
+{
+ IDAadjMem IDAADJ_mem;
+ DtpntMem *dt_mem;
+ realtype t;
+ long int i;
+ int flag, sign;
+
+ IDAADJ_mem = IDA_mem->ida_adj_mem;
+ dt_mem = IDAADJ_mem->dt_mem;
+
+ /* Initialize IDA_mem with data from ck_mem. */
+ flag = IDAAckpntGet(IDA_mem, ck_mem);
+ if (flag != IDA_SUCCESS)
+ return(IDA_REIFWD_FAIL);
+
+ /* Set first structure in dt_mem[0] */
+ dt_mem[0]->t = t0_;
+ IDAADJ_mem->ia_storePnt(IDA_mem, dt_mem[0]);
+
+ /* Decide whether TSTOP must be activated */
+ if (IDAADJ_mem->ia_tstopIDAFcall) {
+ IDASetStopTime(IDA_mem, IDAADJ_mem->ia_tstopIDAF);
+ }
+
+ sign = (tfinal - 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);
+ 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 );
+
+ /* New data is now available. */
+ ckpntData = ck_mem;
+ newData = TRUE;
+ np = i;
+
+ return(IDA_SUCCESS);
+}
+
+/*
+ * CVAckpntGet
+ *
+ * This routine prepares IDAS for a hot restart from
+ * the check point ck_mem
+ */
+
+static int IDAAckpntGet(IDAMem IDA_mem, CkpntMem ck_mem)
+{
+ int flag, j, is;
+
+ if (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);
+
+ flag = IDAReInit(IDA_mem, t0_, phi_[0], phi_[1]);
+ if (flag != IDA_SUCCESS) return(flag);
+
+ if (quadr_) {
+ flag = IDAQuadReInit(IDA_mem, phiQ_[0]);
+ if (flag != IDA_SUCCESS) return(flag);
+ }
+
+ if (sensi_) {
+ flag = IDASensReInit(IDA_mem, IDA_mem->ida_ism, phiS_[0], phiS_[1]);
+ if (flag != IDA_SUCCESS) return(flag);
+ }
+
+ if (quadr_sensi_) {
+ flag = IDAQuadSensReInit(IDA_mem, 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_;
+
+
+ /* Copy the arrays from check point data structure */
+ for (j=0; j<phi_alloc_; j++) N_VScale(ONE, phi_[j], phi[j]);
+
+ if(quadr_) {
+ for (j=0; j<phi_alloc_; j++) N_VScale(ONE, phiQ_[j], 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 (quadr_sensi_) {
+ for (is=0; is<Ns; is++) {
+ for (j=0; j<phi_alloc_; j++) N_VScale(ONE, phiQS_[j][is], 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];
+ }
+
+ /* Force a call to setup */
+ forceSetup = TRUE;
+ }
+
+ return(IDA_SUCCESS);
+}
+
+
+/*
+ * -----------------------------------------------------------------
+ * Functions specific to cubic Hermite interpolation
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * IDAAhermiteMalloc
+ *
+ * This routine allocates memory for storing information at all
+ * intermediate points between two consecutive check points.
+ * This data is then used to interpolate the forward solution
+ * at any other time.
+ */
+
+static booleantype IDAAhermiteMalloc(IDAMem IDA_mem)
+{
+ IDAadjMem IDAADJ_mem;
+ DtpntMem *dt_mem;
+ HermiteDataMem content;
+ long int i, ii=0;
+ booleantype allocOK;
+
+ allocOK = TRUE;
+
+ IDAADJ_mem = IDA_mem->ida_adj_mem;
+
+ /* Allocate space for the vectors yyTmp and ypTmp. */
+ yyTmp = N_VClone(tempv);
+ if (yyTmp == NULL) {
+ return(FALSE);
+ }
+ ypTmp = N_VClone(tempv);
+ if (ypTmp == NULL) {
+ return(FALSE);
+ }
+
+ /* Allocate space for sensitivities temporary vectors. */
+ if (storeSensi) {
+
+ yySTmp = N_VCloneVectorArray(Ns, tempv);
+ if (yySTmp == NULL) {
+ N_VDestroy(yyTmp);
+ N_VDestroy(ypTmp);
+ return(FALSE);
+ }
+
+ ypSTmp = N_VCloneVectorArray(Ns, tempv);
+ if (ypSTmp == NULL) {
+ N_VDestroy(yyTmp);
+ N_VDestroy(ypTmp);
+ N_VDestroyVectorArray(yySTmp, Ns);
+ return(FALSE);
+
+ }
+ }
+
+ /* Allocate space for the content field of the dt structures */
+
+ dt_mem = IDAADJ_mem->dt_mem;
+
+ for (i=0; i<=nsteps; i++) {
+
+ content = NULL;
+ content = (HermiteDataMem) malloc(sizeof(struct HermiteDataMemRec));
+ if (content == NULL) {
+ ii = i;
+ allocOK = FALSE;
+ break;
+ }
+
+ content->y = N_VClone(tempv);
+ if (content->y == NULL) {
+ free(content); content = NULL;
+ ii = i;
+ allocOK = FALSE;
+ break;
+ }
+
+ content->yd = N_VClone(tempv);
+ if (content->yd == NULL) {
+ N_VDestroy(content->y);
+ free(content); content = NULL;
+ ii = i;
+ allocOK = FALSE;
+ break;
+ }
+
+ if (storeSensi) {
+
+ content->yS = N_VCloneVectorArray(Ns, tempv);
+ if (content->yS == NULL) {
+ N_VDestroy(content->y);
+ N_VDestroy(content->yd);
+ free(content); content = NULL;
+ ii = i;
+ allocOK = FALSE;
+ break;
+ }
+
+ content->ySd = N_VCloneVectorArray(Ns, tempv);
+ if (content->ySd == NULL) {
+ N_VDestroy(content->y);
+ N_VDestroy(content->yd);
+ N_VDestroyVectorArray(content->yS, Ns);
+ free(content); content = NULL;
+ ii = i;
+ allocOK = FALSE;
+ break;
+ }
+ }
+
+ dt_mem[i]->content = content;
+
+ }
+
+ /* If an error occurred, deallocate and return */
+
+ if (!allocOK) {
+
+ N_VDestroy(yyTmp);
+ N_VDestroy(ypTmp);
+
+ if (storeSensi) {
+ N_VDestroyVectorArray(yySTmp, Ns);
+ N_VDestroyVectorArray(ypSTmp, Ns);
+ }
+
+ for (i=0; i<ii; i++) {
+ content = (HermiteDataMem) (dt_mem[i]->content);
+ N_VDestroy(content->y);
+ N_VDestroy(content->yd);
+
+ if (storeSensi) {
+ N_VDestroyVectorArray(content->yS, Ns);
+ N_VDestroyVectorArray(content->ySd, Ns);
+ }
+
+ free(dt_mem[i]->content); dt_mem[i]->content = NULL;
+ }
+
+ }
+
+ return(allocOK);
+}
+
+/*
+ * IDAAhermiteFree
+ *
+ * This routine frees the memory allocated for data storage.
+ */
+
+static void IDAAhermiteFree(IDAMem IDA_mem)
+{
+ IDAadjMem IDAADJ_mem;
+ DtpntMem *dt_mem;
+ HermiteDataMem content;
+ long int i;
+
+ IDAADJ_mem = IDA_mem->ida_adj_mem;
+
+ N_VDestroy(yyTmp);
+ N_VDestroy(ypTmp);
+
+ if (storeSensi) {
+ N_VDestroyVectorArray(yySTmp, Ns);
+ N_VDestroyVectorArray(ypSTmp, Ns);
+ }
+
+ dt_mem = IDAADJ_mem->dt_mem;
+
+ for (i=0; i<=nsteps; i++) {
+
+ content = (HermiteDataMem) (dt_mem[i]->content);
+ /* content might be NULL, if IDAAdjInit was called but IDASolveF was not. */
+ if(content) {
+
+ N_VDestroy(content->y);
+ N_VDestroy(content->yd);
+
+ if (storeSensi) {
+ N_VDestroyVectorArray(content->yS, Ns);
+ N_VDestroyVectorArray(content->ySd, Ns);
+ }
+ free(dt_mem[i]->content);
+ dt_mem[i]->content = NULL;
+ }
+ }
+}
+
+/*
+ * IDAAhermiteStorePnt
+ *
+ * This routine stores a new point (y,yd) in the structure d for use
+ * in the cubic Hermite interpolation.
+ * Note that the time is already stored.
+ */
+
+static int IDAAhermiteStorePnt(IDAMem IDA_mem, DtpntMem d)
+{
+ IDAadjMem IDAADJ_mem;
+ HermiteDataMem content;
+ int is;
+
+ IDAADJ_mem = IDA_mem->ida_adj_mem;
+
+ content = (HermiteDataMem) d->content;
+
+ /* Load solution(s) */
+ N_VScale(ONE, phi[0], content->y);
+
+ if (storeSensi) {
+ for (is=0; is<Ns; is++)
+ N_VScale(ONE, phiS[0][is], content->yS[is]);
+ }
+
+ /* Load derivative(s). */
+ IDAAGettnSolutionYp(IDA_mem, content->yd);
+
+ if (storeSensi) {
+ IDAAGettnSolutionYpS(IDA_mem, content->ySd);
+ }
+
+ return(0);
+}
+
+
+/*
+ * IDAAhermiteGetY
+ *
+ * This routine uses cubic piece-wise Hermite interpolation for
+ * the forward solution vector.
+ * It is typically called by the wrapper routines before calling
+ * user provided routines (fB, djacB, bjacB, jtimesB, psolB) but
+ * can be directly called by the user through IDAGetAdjY
+ */
+
+static int IDAAhermiteGetY(IDAMem IDA_mem, realtype t,
+ N_Vector yy, N_Vector yp,
+ N_Vector *yyS, N_Vector *ypS)
+{
+ IDAadjMem IDAADJ_mem;
+ DtpntMem *dt_mem;
+ HermiteDataMem content0, content1;
+
+ realtype t0, t1, delta;
+ realtype factor1, factor2, factor3;
+
+ N_Vector y0, yd0, y1, yd1;
+ N_Vector *yS0, *ySd0, *yS1, *ySd1;
+
+ int flag, is, NS;
+ long int indx;
+ booleantype newpoint;
+
+
+ IDAADJ_mem = IDA_mem->ida_adj_mem;
+ dt_mem = IDAADJ_mem->dt_mem;
+
+ /* Local value of Ns */
+ NS = interpSensi ? Ns : 0;
+
+ /* Get the index in dt_mem */
+ flag = IDAAfindIndex(IDA_mem, t, &indx, &newpoint);
+ if (flag != IDA_SUCCESS) return(flag);
+
+ /* If we are beyond the left limit but close enough,
+ then return y at the left limit. */
+
+ if (indx == 0) {
+ content0 = (HermiteDataMem) (dt_mem[0]->content);
+ N_VScale(ONE, content0->y, yy);
+ N_VScale(ONE, content0->yd, yp);
+
+ for (is=0; is<NS; is++) {
+ N_VScale(ONE, content0->yS[is], yyS[is]);
+ N_VScale(ONE, content0->ySd[is],ypS[is]);
+ }
+ return(IDA_SUCCESS);
+ }
+
+ /* Extract stuff from the appropriate data points */
+ t0 = dt_mem[indx-1]->t;
+ t1 = dt_mem[indx]->t;
+ delta = t1 - t0;
+
+ content0 = (HermiteDataMem) (dt_mem[indx-1]->content);
+ y0 = content0->y;
+ yd0 = content0->yd;
+ if (interpSensi) {
+ yS0 = content0->yS;
+ ySd0 = content0->ySd;
+ }
+
+ if (newpoint) {
+
+ /* Recompute Y0 and Y1 */
+ content1 = (HermiteDataMem) (dt_mem[indx]->content);
+
+ 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]);
+
+
+ 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]);
+ }
+
+ }
+
+ /* Perform the actual interpolation. */
+
+ /* For y. */
+ factor1 = t - t0;
+
+ factor2 = factor1/delta;
+ factor2 = factor2*factor2;
+
+ 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);
+
+ /* 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]);
+ }
+
+ /*For y'. */
+ factor1 = factor1/delta/delta; /* factor1 = 2(t-t0)/(t1-t0)^2 */
+ 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);
+
+ /* 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]);
+ }
+
+ return(IDA_SUCCESS);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Functions specific to Polynomial interpolation
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * IDAApolynomialMalloc
+ *
+ * This routine allocates memory for storing information at all
+ * intermediate points between two consecutive check points.
+ * This data is then used to interpolate the forward solution
+ * at any other time.
+ *
+ * Information about the first derivative is stored only for the first
+ * data point.
+ */
+
+static booleantype IDAApolynomialMalloc(IDAMem IDA_mem)
+{
+ IDAadjMem IDAADJ_mem;
+ DtpntMem *dt_mem;
+ PolynomialDataMem content;
+ long int i, ii=0;
+ booleantype allocOK;
+
+ allocOK = TRUE;
+
+ IDAADJ_mem = IDA_mem->ida_adj_mem;
+
+ /* Allocate space for the vectors yyTmp and ypTmp */
+ yyTmp = N_VClone(tempv);
+ if (yyTmp == NULL) {
+ return(FALSE);
+ }
+ ypTmp = N_VClone(tempv);
+ if (ypTmp == NULL) {
+ return(FALSE);
+ }
+
+ if (storeSensi) {
+
+ yySTmp = N_VCloneVectorArray(Ns, tempv);
+ if (yySTmp == NULL) {
+ N_VDestroy(yyTmp);
+ N_VDestroy(ypTmp);
+ return(FALSE);
+ }
+
+ ypSTmp = N_VCloneVectorArray(Ns, tempv);
+ if (ypSTmp == NULL) {
+ N_VDestroy(yyTmp);
+ N_VDestroy(ypTmp);
+ N_VDestroyVectorArray(yySTmp, Ns);
+ return(FALSE);
+
+ }
+ }
+
+ /* Allocate space for the content field of the dt structures */
+ dt_mem = IDAADJ_mem->dt_mem;
+
+ for (i=0; i<=nsteps; i++) {
+
+ content = NULL;
+ content = (PolynomialDataMem) malloc(sizeof(struct PolynomialDataMemRec));
+ if (content == NULL) {
+ ii = i;
+ allocOK = FALSE;
+ break;
+ }
+
+ content->y = N_VClone(tempv);
+ if (content->y == NULL) {
+ free(content); content = NULL;
+ ii = i;
+ allocOK = FALSE;
+ break;
+ }
+
+ /* Allocate space for yp also. Needed for the most left point interpolation. */
+ if (i == 0) {
+ content->yd = N_VClone(tempv);
+
+ /* Memory allocation failure ? */
+ if (content->yd == NULL) {
+ N_VDestroy(content->y);
+ free(content); content = NULL;
+ ii = i;
+ allocOK = FALSE;
+ }
+ } else {
+ /* Not the first data point. */
+ content->yd = NULL;
+ }
+
+ if (storeSensi) {
+
+ content->yS = N_VCloneVectorArray(Ns, tempv);
+ if (content->yS == NULL) {
+ N_VDestroy(content->y);
+ if (content->yd) N_VDestroy(content->yd);
+ free(content); content = NULL;
+ ii = i;
+ allocOK = FALSE;
+ break;
+ }
+
+ if (i==0) {
+ content->ySd = N_VCloneVectorArray(Ns, tempv);
+ if (content->ySd == NULL) {
+ N_VDestroy(content->y);
+ if (content->yd) N_VDestroy(content->yd);
+ N_VDestroyVectorArray(content->yS, Ns);
+ free(content); content = NULL;
+ ii = i;
+ allocOK = FALSE;
+ }
+ } else {
+ content->ySd = NULL;
+ }
+ }
+
+ dt_mem[i]->content = content;
+ }
+
+ /* If an error occurred, deallocate and return */
+ if (!allocOK) {
+
+ N_VDestroy(yyTmp);
+ N_VDestroy(ypTmp);
+ if (storeSensi) {
+
+ N_VDestroyVectorArray(yySTmp, Ns);
+ N_VDestroyVectorArray(ypSTmp, Ns);
+ }
+
+ for (i=0; i<ii; i++) {
+ content = (PolynomialDataMem) (dt_mem[i]->content);
+ N_VDestroy(content->y);
+
+ if (content->yd) N_VDestroy(content->yd);
+
+ if (storeSensi) {
+
+ N_VDestroyVectorArray(content->yS, Ns);
+
+ if (content->ySd)
+ N_VDestroyVectorArray(content->ySd, Ns);
+ }
+ free(dt_mem[i]->content); dt_mem[i]->content = NULL;
+ }
+
+ }
+ return(allocOK);
+}
+
+/*
+ * IDAApolynomialFree
+ *
+ * This routine frees the memory allocated for data storage.
+ */
+
+static void IDAApolynomialFree(IDAMem IDA_mem)
+{
+ IDAadjMem IDAADJ_mem;
+ DtpntMem *dt_mem;
+ PolynomialDataMem content;
+ long int i;
+
+ IDAADJ_mem = IDA_mem->ida_adj_mem;
+
+ N_VDestroy(yyTmp);
+ N_VDestroy(ypTmp);
+
+ if (storeSensi) {
+ N_VDestroyVectorArray(yySTmp, Ns);
+ N_VDestroyVectorArray(ypSTmp, Ns);
+ }
+
+ dt_mem = IDAADJ_mem->dt_mem;
+
+ for (i=0; i<=nsteps; i++) {
+
+ content = (PolynomialDataMem) (dt_mem[i]->content);
+
+ /* content might be NULL, if IDAAdjInit was called but IDASolveF was not. */
+ if(content) {
+ N_VDestroy(content->y);
+
+ if (content->yd) N_VDestroy(content->yd);
+
+ if (storeSensi) {
+
+ N_VDestroyVectorArray(content->yS, Ns);
+
+ if (content->ySd)
+ N_VDestroyVectorArray(content->ySd, Ns);
+ }
+ free(dt_mem[i]->content); dt_mem[i]->content = NULL;
+ }
+ }
+}
+
+/*
+ * IDAApolynomialStorePnt
+ *
+ * This routine stores a new point y in the structure d for use
+ * in the Polynomial interpolation.
+ *
+ * Note that the time is already stored. Information about the
+ * first derivative is available only for the first data point,
+ * in which case content->yp is non-null.
+ */
+
+static int IDAApolynomialStorePnt(IDAMem IDA_mem, DtpntMem d)
+{
+ IDAadjMem IDAADJ_mem;
+ PolynomialDataMem content;
+ int is;
+
+ IDAADJ_mem = IDA_mem->ida_adj_mem;
+ content = (PolynomialDataMem) d->content;
+
+ N_VScale(ONE, 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) {
+
+ for (is=0; is<Ns; is++)
+ N_VScale(ONE, 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;
+
+ return(0);
+}
+
+/*
+ * IDAApolynomialGetY
+ *
+ * This routine uses polynomial interpolation for the forward solution vector.
+ * It is typically called by the wrapper routines before calling
+ * user provided routines (fB, djacB, bjacB, jtimesB, psolB)) but
+ * can be directly called by the user through CVodeGetAdjY.
+ */
+
+static int IDAApolynomialGetY(IDAMem IDA_mem, realtype t,
+ N_Vector yy, N_Vector yp,
+ N_Vector *yyS, N_Vector *ypS)
+{
+ IDAadjMem IDAADJ_mem;
+ DtpntMem *dt_mem;
+ PolynomialDataMem content;
+
+ int flag, dir, order, i, j, is, NS;
+ long int indx, base;
+ booleantype newpoint;
+ realtype delt, factor, Psi, Psiprime;
+
+ IDAADJ_mem = IDA_mem->ida_adj_mem;
+ dt_mem = IDAADJ_mem->dt_mem;
+
+ /* Local value of Ns */
+
+ NS = interpSensi ? Ns : 0;
+
+ /* Get the index in dt_mem */
+
+ flag = IDAAfindIndex(IDA_mem, t, &indx, &newpoint);
+ if (flag != IDA_SUCCESS) return(flag);
+
+ /* If we are beyond the left limit but close enough,
+ then return y at the left limit. */
+
+ if (indx == 0) {
+ content = (PolynomialDataMem) (dt_mem[0]->content);
+ N_VScale(ONE, content->y, yy);
+ N_VScale(ONE, content->yd, yp);
+
+
+ for (is=0; is<NS; is++) {
+ N_VScale(ONE, content->yS[is], yyS[is]);
+ N_VScale(ONE, content->ySd[is], ypS[is]);
+ }
+
+ return(IDA_SUCCESS);
+ }
+
+ /* Scaling factor */
+ delt = ABS(dt_mem[indx]->t - dt_mem[indx-1]->t);
+
+ /* Find the direction of the forward integration */
+ dir = (tfinal - 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 */
+
+ if (dir == 1) {
+ base = indx;
+ content = (PolynomialDataMem) (dt_mem[base]->content);
+ order = content->order;
+ if(indx < order) base += order-indx;
+ } else {
+ base = indx-1;
+ content = (PolynomialDataMem) (dt_mem[base]->content);
+ order = content->order;
+ if (np-indx > order) base -= indx+order-np;
+ }
+
+ /* Recompute Y (divided differences for Newton polynomial) if needed */
+
+ if (newpoint) {
+
+ /* Store 0-th order DD */
+ if (dir == 1) {
+ for(j=0;j<=order;j++) {
+ 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]);
+
+ }
+ } else {
+ for(j=0;j<=order;j++) {
+ 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]);
+
+ }
+ }
+
+ /* 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]);
+
+ for (is=0; is<NS; is++)
+ N_VLinearSum(factor, YS[j][is], -factor, YS[j-1][is], YS[j][is]);
+
+ }
+ }
+ }
+
+ /* Perform the actual interpolation for yy using nested multiplications */
+ N_VScale(ONE, Y[order], yy);
+
+ for (is=0; is<NS; is++)
+ N_VScale(ONE, 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);
+
+ for (is=0; is<NS; is++)
+ N_VLinearSum(factor, yyS[is], ONE, YS[i][is], yyS[is]);
+
+ }
+
+ /* Perform the actual interpolation for yp.
+
+ Writing p(t) = y0 + (t-t0)*f[t0,t1] + ... + (t-t0)(t-t1)...(t-tn)*f[t0,t1,...tn],
+ denote psi_k(t) = (t-t0)(t-t1)...(t-tk).
+
+ The formula used for p'(t) is:
+ - p'(t) = f[t0,t1] + psi_1'(t)*f[t0,t1,t2] + ... + psi_n'(t)*f[t0,t1,...,tn]
+
+ We reccursively compute psi_k'(t) from:
+ - psi_k'(t) = (t-tk)*psi_{k-1}'(t) + psi_{k-1}
+
+ psi_k is rescaled with 1/delt each time is computed, because the Newton DDs from Y were
+ scaled with delt.
+ */
+
+ Psi = ONE; Psiprime = ZERO;
+ N_VConst(ZERO, yp);
+
+ for (is=0; is<NS; is++)
+ N_VConst(ZERO, ypS[is]);
+
+ for(i=1; i<=order; i++) {
+ factor = (t-T[i-1])/delt;
+
+ Psiprime = Psi/delt + factor * Psiprime;
+ Psi = Psi * factor;
+
+ N_VLinearSum(ONE, yp, Psiprime, Y[i], yp);
+
+ for (is=0; is<NS; is++)
+ N_VLinearSum(ONE, ypS[is], Psiprime, YS[i][is], ypS[is]);
+ }
+
+ return(IDA_SUCCESS);
+}
+
+/*
+ * IDAAGetSolutionYp
+ *
+ * Evaluates the first derivative of the solution at the last time returned by
+ * IDASolve (tretlast).
+ *
+ * The function implements the same algorithm as in IDAGetSolution but in the
+ * particular case when t=tn (i.e. delta=0).
+ *
+ * This function was implemented to avoid calls to IDAGetSolution which computes
+ * y by doing a loop that is not necessary for this particular situation.
+ */
+
+static int IDAAGettnSolutionYp(IDAMem IDA_mem, N_Vector yp)
+{
+ int j, kord;
+ realtype C, D, gam;
+
+ if (nst==0) {
+
+ /* If no integration was done, return the yp supplied by user.*/
+ N_VScale(ONE, phi[1], yp);
+
+ return(0);
+ }
+
+ /* Compute yp as in IDAGetSolution for this particular case when t=tn. */
+ N_VConst(ZERO, yp);
+
+ kord = kused;
+ if(kused==0) kord=1;
+
+ C = ONE; D = ZERO;
+ gam = ZERO;
+ for (j=1; j <= kord; j++) {
+ D = D*gam + C/psi[j-1];
+ C = C*gam;
+ gam = psi[j-1]/psi[j];
+ N_VLinearSum(ONE, yp, D, phi[j], yp);
+ }
+
+ return(0);
+}
+
+
+/*
+ * IDAAGettnSolutionYpS
+ *
+ * Same as IDAAGettnSolutionYp, but for first derivative of the sensitivities.
+ *
+ */
+
+static int IDAAGettnSolutionYpS(IDAMem IDA_mem, N_Vector *ypS)
+{
+ int j, kord, is;
+ realtype C, D, gam;
+
+ if (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]);
+
+ return(0);
+ }
+
+ for (is=0; is<Ns; is++)
+ N_VConst(ZERO, ypS[is]);
+
+ kord = kused;
+ if(kused==0) kord=1;
+
+ C = ONE; D = ZERO;
+ gam = ZERO;
+ for (j=1; j <= kord; j++) {
+ D = D*gam + C/psi[j-1];
+ C = C*gam;
+ gam = psi[j-1]/psi[j];
+
+ for (is=0; is<Ns; is++)
+ N_VLinearSum(ONE, ypS[is], D, phiS[j][is], ypS[is]);
+ }
+
+ return(0);
+}
+
+
+
+/*
+ * IDAAfindIndex
+ *
+ * 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 t is beyond the leftmost limit, but close enough, indx=0.
+ *
+ * Returns IDA_SUCCESS if successful and IDA_GETY_BADT if unable to
+ * find indx (t is too far beyond limits).
+ */
+
+static int IDAAfindIndex(IDAMem ida_mem, realtype t,
+ long int *indx, booleantype *newpoint)
+{
+ IDAadjMem IDAADJ_mem;
+ IDAMem IDA_mem;
+ static long int ilast;
+ DtpntMem *dt_mem;
+ int sign;
+ booleantype to_left, to_right;
+
+ IDA_mem = (IDAMem) ida_mem;
+ IDAADJ_mem = IDA_mem->ida_adj_mem;
+ dt_mem = IDAADJ_mem->dt_mem;
+
+ *newpoint = FALSE;
+
+ /* Find the direction of integration */
+ sign = (tfinal - tinitial > ZERO) ? 1 : -1;
+
+ /* If this is the first time we use new data */
+ if (newData) {
+ ilast = np-1;
+ *newpoint = TRUE;
+ newData = FALSE;
+ }
+
+ /* Search for indx starting from ilast */
+ to_left = ( sign*(t - dt_mem[ilast-1]->t) < ZERO);
+ to_right = ( sign*(t - dt_mem[ilast]->t) > ZERO);
+
+ if ( to_left ) {
+ /* look for a new indx to the left */
+
+ *newpoint = TRUE;
+
+ *indx = ilast;
+ loop {
+ if ( *indx == 0 ) break;
+ if ( sign*(t - dt_mem[*indx-1]->t) <= ZERO ) (*indx)--;
+ else break;
+ }
+
+ if ( *indx == 0 )
+ ilast = 1;
+ else
+ ilast = *indx;
+
+ if ( *indx == 0 ) {
+ /* t is beyond leftmost limit. Is it too far? */
+ if ( ABS(t - dt_mem[0]->t) > FUZZ_FACTOR * uround ) {
+ return(IDA_GETY_BADT);
+ }
+ }
+
+ } else if ( to_right ) {
+ /* look for a new indx to the right */
+
+ *newpoint = TRUE;
+
+ *indx = ilast;
+ loop {
+ if ( sign*(t - dt_mem[*indx]->t) > ZERO) (*indx)++;
+ else break;
+ }
+
+ ilast = *indx;
+
+ } else {
+ /* ilast is still OK */
+
+ *indx = ilast;
+
+ }
+ return(IDA_SUCCESS);
+}
+
+
+/*
+ * IDAGetAdjY
+ *
+ * This routine returns the interpolated forward solution at time t.
+ * The user must allocate space for y.
+ */
+
+int IDAGetAdjY(void *ida_mem, realtype t, N_Vector yy, N_Vector yp)
+{
+ IDAMem IDA_mem;
+ IDAadjMem IDAADJ_mem;
+ int flag;
+
+ if (ida_mem == NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAA", "IDAGetAdjY", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+ IDA_mem = (IDAMem) ida_mem;
+ IDAADJ_mem = IDA_mem->ida_adj_mem;
+
+ flag = IDAADJ_mem->ia_getY(IDA_mem, t, yy, yp, NULL, NULL);
+
+ return(flag);
+}
+
+/*=================================================================*/
+/* Wrappers for adjoint system */
+/*=================================================================*/
+
+/*
+ * IDAAres
+ *
+ * This routine interfaces to the RhsFnB routine provided by
+ * the user.
+*/
+
+static int IDAAres(realtype tt,
+ N_Vector yyB, N_Vector ypB, N_Vector rrB,
+ void *ida_mem)
+{
+ IDAadjMem IDAADJ_mem;
+ IDABMem IDAB_mem;
+ IDAMem IDA_mem;
+ int flag, retval;
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ IDAADJ_mem = IDA_mem->ida_adj_mem;
+
+ /* Get the current backward problem. */
+ 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);
+ else
+ flag = IDAADJ_mem->ia_getY(ida_mem, tt, yyTmp, ypTmp, NULL, NULL);
+
+ if (flag != IDA_SUCCESS) {
+ IDAProcessError(IDA_mem, -1, "IDAA", "IDAAres", MSGAM_BAD_TINTERP, tt);
+ return(-1);
+ }
+ }
+
+ /* Call the user supplied residual. */
+ if(IDAB_mem->ida_res_withSensi) {
+ retval = IDAB_mem->ida_resS(tt, yyTmp, ypTmp,
+ yySTmp, 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);
+ }
+ return(retval);
+}
+
+/*
+ *IDAArhsQ
+ *
+ * This routine interfaces to the IDAQuadRhsFnB routine provided by
+ * the user.
+ *
+ * It is passed to IDAQuadInit calls for backward problem, so it must
+ * be of IDAQuadRhsFn type.
+*/
+
+static int IDAArhsQ(realtype tt,
+ N_Vector yyB, N_Vector ypB,
+ N_Vector resvalQB, void *ida_mem)
+{
+ IDAMem IDA_mem;
+ IDAadjMem IDAADJ_mem;
+ IDABMem IDAB_mem;
+ int retval, flag;
+
+ IDA_mem = (IDAMem) ida_mem;
+ IDAADJ_mem = IDA_mem->ida_adj_mem;
+
+ /* Get current backward problem. */
+ IDAB_mem = IDAADJ_mem->ia_bckpbCrt;
+
+ 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);
+ } else {
+ flag = IDAADJ_mem->ia_getY(IDA_mem, tt, yyTmp, ypTmp, NULL, NULL);
+ }
+
+ if (flag != IDA_SUCCESS) {
+ IDAProcessError(IDA_mem, -1, "IDAA", "IDAArhsQ", MSGAM_BAD_TINTERP, tt);
+ return(-1);
+ }
+ }
+
+ /* Call user's adjoint quadrature RHS routine */
+ if (IDAB_mem->ida_rhsQ_withSensi) {
+ retval = IDAB_mem->ida_rhsQS(tt, yyTmp, ypTmp, yySTmp, ypSTmp,
+ yyB, ypB,
+ resvalQB, IDAB_mem->ida_user_data);
+ } else {
+ retval = IDAB_mem->ida_rhsQ(tt,
+ yyTmp, ypTmp,
+ yyB, ypB,
+ resvalQB, IDAB_mem->ida_user_data);
+ }
+ return(retval);
+}
+
+
diff --git a/src/idas/idaa_io.c b/src/idas/idaa_io.c
new file mode 100644
index 0000000..6952073
--- /dev/null
+++ b/src/idas/idaa_io.c
@@ -0,0 +1,727 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.2 $
+ * $Date: 2010/12/01 22:41:48 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Radu Serban and Cosmin Petra @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2006, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * This is the implementation file for the optional input and output
+ * functions for the adjoint module in the IDAS solver.
+ * -----------------------------------------------------------------
+ */
+
+
+/*
+ * =================================================================
+ * IMPORTED HEADER FILES
+ * =================================================================
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "idas_impl.h"
+#include <sundials/sundials_types.h>
+
+/*
+ * =================================================================
+ * IDAA PRIVATE CONSTANTS
+ * =================================================================
+ */
+
+#define ONE RCONST(1.0)
+
+/*
+ * -----------------------------------------------------------------
+ * Readibility Constants
+ * -----------------------------------------------------------------
+ */
+#define nbckpbs (IDAADJ_mem->ia_nbckpbs)
+
+/*
+ * -----------------------------------------------------------------
+ * Optional input functions for ASA
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * -----------------------------------------------------------------
+ * IDAAdjSetNoSensi
+ * -----------------------------------------------------------------
+ * Disables the forward sensitivity analysis in IDASolveF.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int IDAAdjSetNoSensi(void *ida_mem)
+{
+ IDAMem IDA_mem;
+ IDAadjMem IDAADJ_mem;
+
+ /* Is ida_mem valid? */
+ if (ida_mem == NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAA", "IDAAdjSetNoSensi", MSGAM_NULL_IDAMEM);
+ return IDA_MEM_NULL;
+ }
+ IDA_mem = (IDAMem) ida_mem;
+
+ /* Is ASA initialized? */
+ if (IDA_mem->ida_adjMallocDone == FALSE) {
+ 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;
+
+ return(IDA_SUCCESS);
+}
+
+int IDASetUserDataB(void *ida_mem, int which, void *user_dataB)
+{
+ IDAMem IDA_mem;
+ IDAadjMem IDAADJ_mem;
+ IDABMem IDAB_mem;
+
+ /* Is ida_mem valid? */
+ if (ida_mem == NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAA", "IDASetUserDataB", MSGAM_NULL_IDAMEM);
+ return IDA_MEM_NULL;
+ }
+ IDA_mem = (IDAMem) ida_mem;
+
+ /* Is ASA initialized? */
+ if (IDA_mem->ida_adjMallocDone == FALSE) {
+ 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 ) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAA", "IDASetUserDataB", MSGAM_BAD_WHICH);
+ return(IDA_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;
+ }
+
+ /* Set user data for this backward problem. */
+ IDAB_mem->ida_user_data = user_dataB;
+
+ return(IDA_SUCCESS);
+}
+
+int IDASetMaxOrdB(void *ida_mem, int which, int maxordB)
+{
+ IDAMem IDA_mem;
+ IDAadjMem IDAADJ_mem;
+ IDABMem IDAB_mem;
+ void *ida_memB;
+
+ /* Is ida_mem valid? */
+ if (ida_mem == NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAA", "IDASetMaxOrdB", MSGAM_NULL_IDAMEM);
+ return IDA_MEM_NULL;
+ }
+ IDA_mem = (IDAMem) ida_mem;
+
+ /* Is ASA initialized? */
+ if (IDA_mem->ida_adjMallocDone == FALSE) {
+ 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 ) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAA", "IDASetMaxOrdB", MSGAM_BAD_WHICH);
+ return(IDA_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;
+
+ return IDASetMaxOrd(ida_memB, maxordB);
+}
+
+int IDASetMaxNumStepsB(void *ida_mem, int which, long int mxstepsB)
+{
+ IDAMem IDA_mem;
+ IDAadjMem IDAADJ_mem;
+ IDABMem IDAB_mem;
+ void *ida_memB;
+
+ /* Is ida_mem valid? */
+ if (ida_mem == NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAA", "IDASetMaxNumStepsB", MSGAM_NULL_IDAMEM);
+ return IDA_MEM_NULL;
+ }
+ IDA_mem = (IDAMem) ida_mem;
+
+ /* Is ASA initialized? */
+ if (IDA_mem->ida_adjMallocDone == FALSE) {
+ 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 ) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAA", "IDASetMaxNumStepsB", MSGAM_BAD_WHICH);
+ return(IDA_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;
+
+ return IDASetMaxNumSteps(ida_memB, mxstepsB);
+}
+
+int IDASetInitStepB(void *ida_mem, int which, realtype hinB)
+{
+ IDAMem IDA_mem;
+ IDAadjMem IDAADJ_mem;
+ IDABMem IDAB_mem;
+ void *ida_memB;
+
+ /* Is ida_mem valid? */
+ if (ida_mem == NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAA", "IDASetInitStepB", MSGAM_NULL_IDAMEM);
+ return IDA_MEM_NULL;
+ }
+ IDA_mem = (IDAMem) ida_mem;
+
+ /* Is ASA initialized? */
+ if (IDA_mem->ida_adjMallocDone == FALSE) {
+ 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 ) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAA", "IDASetInitStepB", MSGAM_BAD_WHICH);
+ return(IDA_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;
+
+ return IDASetInitStep(ida_memB, hinB);
+}
+
+int IDASetMaxStepB(void *ida_mem, int which, realtype hmaxB)
+{
+ IDAMem IDA_mem;
+ IDAadjMem IDAADJ_mem;
+ IDABMem IDAB_mem;
+ void *ida_memB;
+
+ /* Is ida_mem valid? */
+ if (ida_mem == NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAA", "IDASetMaxStepB", MSGAM_NULL_IDAMEM);
+ return IDA_MEM_NULL;
+ }
+ IDA_mem = (IDAMem) ida_mem;
+
+ /* Is ASA initialized? */
+ if (IDA_mem->ida_adjMallocDone == FALSE) {
+ 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 ) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAA", "IDASetMaxStepB", MSGAM_BAD_WHICH);
+ return(IDA_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;
+
+ return IDASetMaxStep(ida_memB, hmaxB);
+}
+
+int IDASetSuppressAlgB(void *ida_mem, int which, booleantype suppressalgB)
+{
+ IDAMem IDA_mem;
+ IDAadjMem IDAADJ_mem;
+ IDABMem IDAB_mem;
+ void *ida_memB;
+
+ /* Is ida_mem valid? */
+ if (ida_mem == NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAA", "IDASetSuppressAlgB", MSGAM_NULL_IDAMEM);
+ return IDA_MEM_NULL;
+ }
+ IDA_mem = (IDAMem) ida_mem;
+
+ /* Is ASA initialized? */
+ if (IDA_mem->ida_adjMallocDone == FALSE) {
+ 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 ) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAA", "IDASetSuppressAlgB", MSGAM_BAD_WHICH);
+ return(IDA_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;
+
+ return IDASetSuppressAlg(ida_memB, suppressalgB);
+}
+
+int IDASetIdB(void *ida_mem, int which, N_Vector idB)
+{
+ IDAMem IDA_mem;
+ IDAadjMem IDAADJ_mem;
+ IDABMem IDAB_mem;
+ void *ida_memB;
+
+ /* Is ida_mem valid? */
+ if (ida_mem == NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAA", "IDASetIdB", MSGAM_NULL_IDAMEM);
+ return IDA_MEM_NULL;
+ }
+ IDA_mem = (IDAMem) ida_mem;
+
+ /* Is ASA initialized? */
+ if (IDA_mem->ida_adjMallocDone == FALSE) {
+ 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 ) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAA", "IDASetIdB", MSGAM_BAD_WHICH);
+ return(IDA_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;
+
+ return IDASetId(ida_memB, idB);
+}
+
+int IDASetConstraintsB(void *ida_mem, int which, N_Vector constraintsB)
+{
+ IDAMem IDA_mem;
+ IDAadjMem IDAADJ_mem;
+ IDABMem IDAB_mem;
+ void *ida_memB;
+
+ /* Is ida_mem valid? */
+ if (ida_mem == NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAA", "IDASetConstraintsB", MSGAM_NULL_IDAMEM);
+ return IDA_MEM_NULL;
+ }
+ IDA_mem = (IDAMem) ida_mem;
+
+ /* Is ASA initialized? */
+ if (IDA_mem->ida_adjMallocDone == FALSE) {
+ 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 ) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAA", "IDASetConstraintsB", MSGAM_BAD_WHICH);
+ return(IDA_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;
+
+ return IDASetConstraints(ida_memB, constraintsB);
+}
+/*
+ * ----------------------------------------------------------------
+ * Input quadrature functions for ASA
+ * ----------------------------------------------------------------
+ */
+
+int IDASetQuadErrConB(void *ida_mem, int which, int errconQB)
+{
+ IDAMem IDA_mem;
+ IDAadjMem IDAADJ_mem;
+ IDABMem IDAB_mem;
+ void *ida_memB;
+
+ /* Is ida_mem valid? */
+ if (ida_mem == NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAA", "IDASetQuadErrConB", MSGAM_NULL_IDAMEM);
+ return IDA_MEM_NULL;
+ }
+ IDA_mem = (IDAMem) ida_mem;
+
+ /* Is ASA initialized? */
+ if (IDA_mem->ida_adjMallocDone == FALSE) {
+ 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 ) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAA", "IDASetQuadErrConB", MSGAM_BAD_WHICH);
+ return(IDA_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;
+
+ return IDASetQuadErrCon(ida_memB, errconQB);
+
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Optional output functions for backward integration
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * IDAGetAdjIDABmem
+ *
+ * This function returns a (void *) pointer to the IDAS
+ * memory allocated for the backward problem. This pointer can
+ * then be used to call any of the IDAGet* IDAS routines to
+ * extract optional output for the backward integration phase.
+ */
+
+SUNDIALS_EXPORT void *IDAGetAdjIDABmem(void *ida_mem, int which)
+{
+ IDAMem IDA_mem;
+ IDAadjMem IDAADJ_mem;
+ IDABMem IDAB_mem;
+ void *ida_memB;
+
+ /* Is ida_mem valid? */
+ if (ida_mem == NULL) {
+ IDAProcessError(NULL, 0, "IDAA", "IDAGetAdjIDABmem", MSGAM_NULL_IDAMEM);
+ return(NULL);
+ }
+ IDA_mem = (IDAMem) ida_mem;
+
+ /* Is ASA initialized? */
+ if (IDA_mem->ida_adjMallocDone == FALSE) {
+ 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 ) {
+ IDAProcessError(IDA_mem, 0, "IDAA", "IDAGetAdjIDABmem", MSGAM_BAD_WHICH);
+ return(NULL);
+ }
+
+ /* 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;
+
+ return(ida_memB);
+}
+
+/*
+ * IDAGetAdjCheckPointsInfo
+ *
+ * Loads an array of nckpnts structures of type IDAadjCheckPointRec
+ * defined below.
+ *
+ * The user must allocate space for ckpnt (ncheck+1).
+ */
+
+int IDAGetAdjCheckPointsInfo(void *ida_mem, IDAadjCheckPointRec *ckpnt)
+{
+ IDAMem IDA_mem;
+ IDAadjMem IDAADJ_mem;
+ CkpntMem ck_mem;
+ int i;
+
+ /* Is ida_mem valid? */
+ if (ida_mem == NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAA", "IDAGetAdjCheckPointsInfo", MSGAM_NULL_IDAMEM);
+ return(IDA_MEM_NULL);
+ }
+ IDA_mem = (IDAMem) ida_mem;
+
+ /* Is ASA initialized? */
+ if (IDA_mem->ida_adjMallocDone == FALSE) {
+ IDAProcessError(IDA_mem, IDA_NO_ADJ, "IDAA", "IDAGetAdjCheckPointsInfo", MSGAM_NO_ADJ);
+ return(IDA_NO_ADJ);
+ }
+ IDAADJ_mem = IDA_mem->ida_adj_mem;
+
+ i=0;
+ ck_mem = IDAADJ_mem->ck_mem;
+ while (ck_mem != NULL) {
+
+ ckpnt[i].my_addr = (void *) ck_mem;
+ 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_kk;
+ ckpnt[i].step = ck_mem->ck_hh;
+
+ ck_mem = ck_mem->ck_next;
+ i++;
+ }
+
+ return(IDA_SUCCESS);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * IDAGetAdjDataPointHermite
+ * -----------------------------------------------------------------
+ * Returns the 2 vectors stored for cubic Hermite interpolation at
+ * the data point 'which'. The user must allocate space for yy and
+ * yd.
+ *
+ * Returns IDA_MEM_NULL if ida_mem is NULL, IDA_ILL_INPUT if the
+ * interpolation type previously specified is not IDA_HERMITE or
+ * IDA_SUCCESS otherwise.
+ *
+ */
+int IDAGetAdjDataPointHermite(void *ida_mem, int which,
+ realtype *t, N_Vector yy, N_Vector yd)
+
+{
+ IDAMem IDA_mem;
+ IDAadjMem IDAADJ_mem;
+ DtpntMem *dt_mem;
+ HermiteDataMem content;
+
+ /* Is ida_mem valid? */
+ if (ida_mem == NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAA", "IDAGetAdjDataPointHermite", MSGAM_NULL_IDAMEM);
+ return(IDA_MEM_NULL);
+ }
+ IDA_mem = (IDAMem) ida_mem;
+
+ /* Is ASA initialized? */
+ if (IDA_mem->ida_adjMallocDone == FALSE) {
+ IDAProcessError(IDA_mem, IDA_NO_ADJ, "IDAA", "IDAGetAdjDataPointHermite", MSGAM_NO_ADJ);
+ return(IDA_NO_ADJ);
+ }
+ IDAADJ_mem = IDA_mem->ida_adj_mem;
+
+ dt_mem = IDAADJ_mem->dt_mem;
+
+ if (IDAADJ_mem->ia_interpType != IDA_HERMITE) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAA", "IDAGetAdjDataPointHermite", MSGAM_WRONG_INTERP);
+ return(IDA_ILL_INPUT);
+ }
+
+ *t = dt_mem[which]->t;
+ content = (HermiteDataMem) dt_mem[which]->content;
+
+ if (yy != NULL) N_VScale(ONE, content->y, yy);
+ if (yd != NULL) N_VScale(ONE, content->yd, yd);
+
+ return(IDA_SUCCESS);
+}
+
+/*
+ * IDAGetAdjDataPointPolynomial
+ *
+ * Returns the vector stored for polynomial interpolation at the
+ * data point 'which'. The user must allocate space for y.
+ *
+ * Returns IDA_MEM_NULL if ida_mem is NULL, IDA_ILL_INPUT if the
+ * interpolation type previously specified is not IDA_POLYNOMIAL or
+ * IDA_SUCCESS otherwise.
+ */
+
+
+int IDAGetAdjDataPointPolynomial(void *ida_mem, int which,
+ realtype *t, int *order, N_Vector y)
+{
+ IDAMem IDA_mem;
+ IDAadjMem IDAADJ_mem;
+ DtpntMem *dt_mem;
+ PolynomialDataMem content;
+ /* Is ida_mem valid? */
+ if (ida_mem == NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAA", "IDAGetAdjDataPointPolynomial", MSGAM_NULL_IDAMEM);
+ return(IDA_MEM_NULL);
+ }
+ IDA_mem = (IDAMem) ida_mem;
+
+ /* Is ASA initialized? */
+ if (IDA_mem->ida_adjMallocDone == FALSE) {
+ IDAProcessError(IDA_mem, IDA_NO_ADJ, "IDAA", "IDAGetAdjDataPointPolynomial", MSGAM_NO_ADJ);
+ return(IDA_NO_ADJ);
+ }
+ IDAADJ_mem = IDA_mem->ida_adj_mem;
+
+ dt_mem = IDAADJ_mem->dt_mem;
+
+ if (IDAADJ_mem->ia_interpType != IDA_POLYNOMIAL) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAA", "IDAGetAdjDataPointPolynomial", MSGAM_WRONG_INTERP);
+ return(IDA_ILL_INPUT);
+ }
+
+ *t = dt_mem[which]->t;
+ content = (PolynomialDataMem) dt_mem[which]->content;
+
+ if (y != NULL) N_VScale(ONE, content->y, y);
+
+ *order = content->order;
+
+ return(IDA_SUCCESS);
+}
+
+/*
+ * IDAGetAdjCurrentCheckPoint
+ *
+ * Returns the address of the 'active' check point.
+ */
+
+SUNDIALS_EXPORT int IDAGetAdjCurrentCheckPoint(void *ida_mem, void **addr)
+{
+ IDAMem IDA_mem;
+ IDAadjMem IDAADJ_mem;
+
+ if (ida_mem == NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAA", "IDAGetAdjCurrentCheckPoint", MSGAM_NULL_IDAMEM);
+ return(IDA_MEM_NULL);
+ }
+ IDA_mem = (IDAMem) ida_mem;
+
+ /* Is ASA initialized? */
+ if (IDA_mem->ida_adjMallocDone == FALSE) {
+ IDAProcessError(IDA_mem, IDA_NO_ADJ, "IDAA", "IDAGetAdjCurrentCheckPoint", MSGAM_NO_ADJ);
+ return(IDA_NO_ADJ);
+ }
+ IDAADJ_mem = IDA_mem->ida_adj_mem;
+
+ *addr = (void *) IDAADJ_mem->ia_ckpntData;
+
+ return(IDA_SUCCESS);
+}
+
+
+/* IDAGetConsistenICB
+ *
+ * Returns the consistent initial conditions computed by IDACalcICB or
+ * IDACalcICBS
+ *
+ * It must be preceded by a successful call to IDACalcICB or IDACalcICBS
+ * for 'which' backward problem.
+ */
+
+int IDAGetConsistentICB(void *ida_mem, int which, N_Vector yyB0_mod, N_Vector ypB0_mod)
+{
+ IDAMem IDA_mem;
+ IDAadjMem IDAADJ_mem;
+ IDABMem IDAB_mem;
+ void *ida_memB;
+ int flag;
+
+ /* Is ida_mem valid? */
+ if (ida_mem == NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAA", "IDAGetConsistenICB", MSGAM_NULL_IDAMEM);
+ return IDA_MEM_NULL;
+ }
+ IDA_mem = (IDAMem) ida_mem;
+
+ /* Is ASA initialized? */
+ if (IDA_mem->ida_adjMallocDone == FALSE) {
+ IDAProcessError(IDA_mem, IDA_NO_ADJ, "IDAA", "IDAGetConsistenICB", MSGAM_NO_ADJ);
+ return(IDA_NO_ADJ);
+ }
+ IDAADJ_mem = IDA_mem->ida_adj_mem;
+
+ /* Check the value of which */
+ if ( which >= nbckpbs ) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAA", "IDAGetConsistenICB", MSGAM_BAD_WHICH);
+ return(IDA_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 = IDAGetConsistentIC(ida_memB, yyB0_mod, ypB0_mod);
+
+ return(flag);
+}
+
diff --git a/src/idas/idas.c b/src/idas/idas.c
new file mode 100644
index 0000000..dab8af2
--- /dev/null
+++ b/src/idas/idas.c
@@ -0,0 +1,7231 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.39 $
+ * $Date: 2012/03/06 21:58:55 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * This is the implementation file for the main IDAS solver.
+ * It is independent of the linear solver in use.
+ * -----------------------------------------------------------------
+ *
+ * EXPORTED FUNCTIONS
+ * ------------------
+ * Creation, allocation and re-initialization functions
+ * IDACreate
+ * IDAInit
+ * IDAReInit
+ * IDAQuadInit
+ * IDAQuadReInit
+ * IDAQuadSStolerances
+ * IDAQuadSVtolerances
+ * IDASensInit
+ * IDASensReInit
+ * IDASensToggleOff
+ * IDASensSStolerances
+ * IDASensSVtolerances
+ * IDASensEEtolerances
+ * IDAQuadSensInit
+ * IDAQuadSensReInit
+ * IDARootInit
+ *
+ * Main solver function
+ * IDASolve
+ *
+ * Interpolated output and extraction functions
+ * IDAGetDky
+ * IDAGetQuad
+ * IDAGetQuadDky
+ * IDAGetSens
+ * IDAGetSens1
+ * IDAGetSensDky
+ * IDAGetSensDky1
+ *
+ * Deallocation functions
+ * IDAFree
+ * IDAQuadFree
+ * IDASensFree
+ * IDAQuadSensFree
+ *
+ * PRIVATE FUNCTIONS
+ * -----------------
+ * IDACheckNvector
+ * Memory allocation/deallocation
+ * IDAAllocVectors
+ * IDAFreeVectors
+ * IDAQuadAllocVectors
+ * IDAQuadFreeVectors
+ * IDASensAllocVectors
+ * IDASensFreeVectors
+ * IDAQuadSensAllocVectors
+ * IDAQuadSensFreeVectors
+ * Initial setup
+ * IDAInitialSetup
+ * IDAEwtSet
+ * IDAEwtSetSS
+ * IDAEwtSetSV
+ * IDAQuadEwtSet
+ * IDAQuadEwtSetSS
+ * IDAQuadEwtSetSV
+ * IDASensEwtSet
+ * IDASensEwtSetEE
+ * IDASensEwtSetSS
+ * IDASensEwtSetSV
+ * IDAQuadSensEwtSet
+ * IDAQuadSensEwtSetEE
+ * IDAQuadSensEwtSetSS
+ * IDAQuadSensEwtSetSV
+ * Stopping tests
+ * IDAStopTest1
+ * IDAStopTest2
+ * Error handler
+ * IDAHandleFailure
+ * Main IDAStep function
+ * IDAStep
+ * IDASetCoeffs
+ * Nonlinear solver functions
+ * IDANls
+ * IDAPredict
+ * IDANewtonIter
+ * IDAQuadNls
+ * IDAQuadSensNls
+ * IDAQuadPredict
+ * IDAQuadSensPredict
+ * IDASensNls
+ * IDASensPredict
+ * IDASensNewtonIter
+ * Error test
+ * IDATestError
+ * IDAQuadTestError
+ * IDASensTestError
+ * IDAQuadSensTestError
+ * IDARestore
+ * Handler for convergence and/or error test failures
+ * IDAHandleNFlag
+ * IDAReset
+ * Function called after a successful step
+ * IDACompleteStep
+ * Get solution
+ * IDAGetSolution
+ * Norm functions
+ * IDAWrmsNorm
+ * IDASensWrmsNorm
+ * IDAQuadSensWrmsNorm
+ * IDAQuadWrmsNormUpdate
+ * IDASensWrmsNormUpdate
+ * IDAQuadSensWrmsNormUpdate
+ * Functions for rootfinding
+ * IDARcheck1
+ * IDARcheck2
+ * IDARcheck3
+ * IDARootfind
+ * IDA Error message handling functions
+ * IDAProcessError
+ * IDAErrHandler
+ * Internal DQ approximations for sensitivity RHS
+ * IDASensResDQ
+ * IDASensRes1DQ
+ * IDAQuadSensResDQ
+ * IDAQuadSensRes1DQ
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * =================================================================
+ * IMPORTED HEADER FILES
+ * =================================================================
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+
+#include "idas_impl.h"
+#include <sundials/sundials_math.h>
+#include <sundials/sundials_types.h>
+
+/*
+ * =================================================================
+ * MACRO DEFINITIONS
+ * =================================================================
+ */
+
+/* Macro: loop */
+#define loop for(;;)
+
+/*
+ * =================================================================
+ * IDAS PRIVATE CONSTANTS
+ * =================================================================
+ */
+
+#define ZERO RCONST(0.0) /* real 0.0 */
+#define HALF RCONST(0.5) /* real 0.5 */
+#define QUARTER RCONST(0.25) /* real 0.25 */
+#define TWOTHIRDS RCONST(0.667) /* real 2/3 */
+#define ONE RCONST(1.0) /* real 1.0 */
+#define ONEPT5 RCONST(1.5) /* real 1.5 */
+#define TWO RCONST(2.0) /* real 2.0 */
+#define FOUR RCONST(4.0) /* real 4.0 */
+#define FIVE RCONST(5.0) /* real 5.0 */
+#define TEN RCONST(10.0) /* real 10.0 */
+#define TWELVE RCONST(12.0) /* real 12.0 */
+#define TWENTY RCONST(20.0) /* real 20.0 */
+#define HUNDRED RCONST(100.0) /* real 100.0 */
+#define PT9 RCONST(0.9) /* real 0.9 */
+#define PT99 RCONST(0.99) /* real 0.99 */
+#define PT1 RCONST(0.1) /* real 0.1 */
+#define PT01 RCONST(0.01) /* real 0.01 */
+#define PT001 RCONST(0.001) /* real 0.001 */
+#define PT0001 RCONST(0.0001) /* real 0.0001 */
+
+/*
+ * =================================================================
+ * IDAS ROUTINE-SPECIFIC CONSTANTS
+ * =================================================================
+ */
+
+/*
+ * Control constants for lower-level functions used by IDASolve
+ * ------------------------------------------------------------
+ */
+
+/* IDAStep control constants */
+
+#define PREDICT_AGAIN 20
+
+/* Return values for lower level routines used by IDASolve */
+
+#define IDA_RES_RECVR +1
+#define IDA_LSETUP_RECVR +2
+#define IDA_LSOLVE_RECVR +3
+
+#define IDA_NCONV_RECVR +4
+#define IDA_CONSTR_RECVR +5
+
+#define IDA_QRHS_RECVR +10
+#define IDA_SRES_RECVR +11
+#define IDA_QSRHS_RECVR +12
+
+#define CONTINUE_STEPS +99
+
+/* IDACompleteStep constants */
+
+#define UNSET -1
+#define LOWER 1
+#define RAISE 2
+#define MAINTAIN 3
+
+/* IDATestError constants */
+
+#define ERROR_TEST_FAIL +7
+
+/*
+ * Control constants for lower-level rootfinding functions
+ * -------------------------------------------------------
+ */
+
+#define RTFOUND 1
+#define CLOSERT 3
+
+/*
+ * Control constants for sensitivity DQ
+ * ------------------------------------
+ */
+
+#define CENTERED1 +1
+#define CENTERED2 +2
+#define FORWARD1 +3
+#define FORWARD2 +4
+
+/*
+ * Algorithmic constants
+ * ---------------------
+ */
+
+#define MXNCF 10 /* max number of convergence failures allowed */
+#define MXNEF 10 /* max number of error test failures allowed */
+#define MAXNH 5 /* max. number of h tries in IC calc. */
+#define MAXNJ 4 /* max. number of J tries in IC calc. */
+#define MAXNI 10 /* max. Newton iterations in IC calc. */
+#define EPCON RCONST(0.33) /* Newton convergence test constant */
+
+/* IDANewtonIter constants */
+
+#define MAXIT 4
+#define RATEMAX RCONST(0.9)
+#define XRATE RCONST(0.25)
+
+/*
+ * =================================================================
+ * PRIVATE FUNCTION PROTOTYPES
+ * =================================================================
+ */
+
+static booleantype IDACheckNvector(N_Vector tmpl);
+
+/* Memory allocation/deallocation */
+
+static booleantype IDAAllocVectors(IDAMem IDA_mem, N_Vector tmpl);
+static void IDAFreeVectors(IDAMem IDA_mem);
+
+static booleantype IDAQuadAllocVectors(IDAMem IDA_mem, N_Vector tmpl);
+static void IDAQuadFreeVectors(IDAMem IDA_mem);
+
+static booleantype IDASensAllocVectors(IDAMem IDA_mem, N_Vector tmpl);
+static void IDASensFreeVectors(IDAMem IDA_mem);
+
+static booleantype IDAQuadSensAllocVectors(IDAMem ida_mem, N_Vector tmpl);
+static void IDAQuadSensFreeVectors(IDAMem ida_mem);
+
+/* Initial setup */
+
+int IDAInitialSetup(IDAMem IDA_mem);
+
+static int IDAEwtSetSS(IDAMem IDA_mem, N_Vector ycur, N_Vector weight);
+static int IDAEwtSetSV(IDAMem IDA_mem, N_Vector ycur, N_Vector weight);
+
+static int IDAQuadEwtSet(IDAMem IDA_mem, N_Vector qcur, N_Vector weightQ);
+static int IDAQuadEwtSetSS(IDAMem IDA_mem, N_Vector qcur, N_Vector weightQ);
+static int IDAQuadEwtSetSV(IDAMem IDA_mem, N_Vector qcur, N_Vector weightQ);
+
+/* Used in IC for sensitivities. */
+int IDASensEwtSet(IDAMem IDA_mem, N_Vector *yScur, N_Vector *weightS);
+static int IDASensEwtSetEE(IDAMem IDA_mem, N_Vector *yScur, N_Vector *weightS);
+static int IDASensEwtSetSS(IDAMem IDA_mem, N_Vector *yScur, N_Vector *weightS);
+static int IDASensEwtSetSV(IDAMem IDA_mem, N_Vector *yScur, N_Vector *weightS);
+
+int IDAQuadSensEwtSet(IDAMem IDA_mem, N_Vector *yQScur, N_Vector *weightQS);
+static int IDAQuadSensEwtSetEE(IDAMem IDA_mem, N_Vector *yScur, N_Vector *weightS);
+static int IDAQuadSensEwtSetSS(IDAMem IDA_mem, N_Vector *yScur, N_Vector *weightS);
+static int IDAQuadSensEwtSetSV(IDAMem IDA_mem, N_Vector *yScur, N_Vector *weightS);
+
+/* Main IDAStep function */
+
+static int IDAStep(IDAMem IDA_mem);
+
+/* Function called at beginning of step */
+
+static void IDASetCoeffs(IDAMem IDA_mem, realtype *ck);
+
+/* Nonlinear solver functions */
+
+static void IDAPredict(IDAMem IDA_mem);
+static void IDAQuadPredict(IDAMem IDA_mem);
+static void IDASensPredict(IDAMem IDA_mem, int is, N_Vector yySens, N_Vector ypSens);
+static void IDAQuadSensPredict(IDAMem IDA_mem, N_Vector *yQS, N_Vector *ypQS);
+
+static int IDANls(IDAMem IDA_mem);
+static int IDANewtonIter(IDAMem IDA_mem);
+
+static int IDASensNls(IDAMem IDA_mem);
+static int IDASensNewtonIter(IDAMem IDA_mem);
+
+static int IDAQuadNls(IDAMem IDA_mem);
+static int IDAQuadSensNls(IDAMem IDA_mem);
+
+/* Error tests */
+
+static int IDATestError(IDAMem IDA_mem, realtype ck,
+ realtype *err_k, realtype *err_km1, realtype *err_km2);
+static int IDAQuadTestError(IDAMem IDA_mem, realtype ck,
+ realtype *err_k, realtype *err_km1, realtype *err_km2);
+static int IDASensTestError(IDAMem IDA_mem, realtype ck,
+ realtype *err_k, realtype *err_km1, realtype *err_km2);
+static int IDAQuadSensTestError(IDAMem IDA_mem, realtype ck,
+ realtype *err_k, realtype *err_km1, realtype *err_km2);
+
+/* Handling of convergence and/or error test failures */
+
+static void IDARestore(IDAMem IDA_mem, realtype saved_t);
+static int IDAHandleNFlag(IDAMem IDA_mem, int nflag, realtype err_k, realtype err_km1,
+ long int *ncfnPtr, int *ncfPtr, long int *netfPtr, int *nefPtr);
+static void IDAReset(IDAMem IDA_mem);
+
+/* Function called after a successful step */
+
+static void IDACompleteStep(IDAMem IDA_mem, realtype err_k, realtype err_km1);
+
+/* Function called to evaluate the solutions y(t) and y'(t) at t. Also used in IDAA */
+int IDAGetSolution(void *ida_mem, realtype t, N_Vector yret, N_Vector ypret);
+
+/* Stopping tests and failure handling */
+
+static int IDAStopTest1(IDAMem IDA_mem, realtype tout,realtype *tret,
+ N_Vector yret, N_Vector ypret, int itask);
+static int IDAStopTest2(IDAMem IDA_mem, realtype tout, realtype *tret,
+ N_Vector yret, N_Vector ypret, int itask);
+static int IDAHandleFailure(IDAMem IDA_mem, int sflag);
+
+/* Norm functions. Some of them are used also for IC, so they are global.*/
+
+realtype IDAWrmsNorm(IDAMem IDA_mem, N_Vector x, N_Vector w,
+ booleantype mask);
+
+realtype IDASensWrmsNorm(IDAMem IDA_mem, N_Vector *xS, N_Vector *wS,
+ booleantype mask);
+
+realtype IDASensWrmsNormUpdate(IDAMem IDA_mem, realtype old_nrm,
+ N_Vector *xS, N_Vector *wS,
+ booleantype mask);
+static realtype IDAQuadWrmsNormUpdate(IDAMem IDA_mem, realtype old_nrm,
+ N_Vector xQ, N_Vector wQ);
+
+static realtype IDAQuadSensWrmsNorm(IDAMem IDA_mem, N_Vector *xQS, N_Vector *wQS);
+static realtype IDAQuadSensWrmsNormUpdate(IDAMem IDA_mem, realtype old_nrm,
+ N_Vector *xQS, N_Vector *wQS);
+
+/* Functions for rootfinding */
+
+static int IDARcheck1(IDAMem IDA_mem);
+static int IDARcheck2(IDAMem IDA_mem);
+static int IDARcheck3(IDAMem IDA_mem);
+static int IDARootfind(IDAMem IDA_mem);
+
+/* Sensitivity residual DQ function */
+
+static int IDASensRes1DQ(int Ns, realtype t,
+ N_Vector yy, N_Vector yp, N_Vector resval,
+ int iS,
+ N_Vector yyS, N_Vector ypS, N_Vector resvalS,
+ void *user_dataS,
+ N_Vector ytemp, N_Vector yptemp, N_Vector restemp);
+
+static int IDAQuadSensRhsInternalDQ(int Ns, realtype t,
+ N_Vector yy, N_Vector yp,
+ N_Vector *yyS, N_Vector *ypS,
+ N_Vector rrQ, N_Vector *resvalQS,
+ void *ida_mem,
+ N_Vector yytmp, N_Vector yptmp, N_Vector tmpQS);
+
+static int IDAQuadSensRhs1InternalDQ(IDAMem IDA_mem, int is, realtype t,
+ N_Vector yy, N_Vector y,
+ N_Vector yyS, N_Vector ypS,
+ N_Vector resvalQ, N_Vector resvalQS,
+ N_Vector yytmp, N_Vector yptmp, N_Vector tmpQS);
+/*
+ * =================================================================
+ * EXPORTED FUNCTIONS IMPLEMENTATION
+ * =================================================================
+ */
+
+/*
+ * -----------------------------------------------------------------
+ * Creation, allocation and re-initialization functions
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * IDACreate
+ *
+ * IDACreate creates an internal memory block for a problem to
+ * be solved by IDA.
+ * If successful, IDACreate returns a pointer to the problem memory.
+ * This pointer should be passed to IDAInit.
+ * If an initialization error occurs, IDACreate prints an error
+ * message to standard err and returns NULL.
+ */
+
+void *IDACreate(void)
+{
+ IDAMem IDA_mem;
+
+ IDA_mem = NULL;
+ IDA_mem = (IDAMem) malloc(sizeof(struct IDAMemRec));
+ if (IDA_mem == NULL) {
+ IDAProcessError(NULL, 0, "IDAS", "IDACreate", MSG_MEM_FAIL);
+ return (NULL);
+ }
+
+ /* Zero out ida_mem */
+ memset(IDA_mem, 0, sizeof(struct IDAMemRec));
+
+ /* Set unit roundoff in IDA_mem */
+ IDA_mem->ida_uround = UNIT_ROUNDOFF;
+
+ /* Set default values for integrator optional inputs */
+ 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_efun = NULL;
+ IDA_mem->ida_edata = NULL;
+ IDA_mem->ida_ehfun = IDAErrHandler;
+ IDA_mem->ida_eh_data = IDA_mem;
+ IDA_mem->ida_errfp = stderr;
+ IDA_mem->ida_maxord = MAXORD_DEFAULT;
+ IDA_mem->ida_mxstep = MXSTEP_DEFAULT;
+ IDA_mem->ida_hmax_inv = HMAX_INV_DEFAULT;
+ IDA_mem->ida_hin = ZERO;
+ IDA_mem->ida_epcon = EPCON;
+ IDA_mem->ida_maxnef = MXNEF;
+ IDA_mem->ida_maxncf = MXNCF;
+ IDA_mem->ida_maxcor = MAXIT;
+ IDA_mem->ida_suppressalg = FALSE;
+ IDA_mem->ida_id = NULL;
+ IDA_mem->ida_constraints = NULL;
+ IDA_mem->ida_constraintsSet = FALSE;
+ IDA_mem->ida_tstopset = FALSE;
+
+ /* set the saved value maxord_alloc */
+ IDA_mem->ida_maxord_alloc = MAXORD_DEFAULT;
+
+ /* Set default values for IC optional inputs */
+ IDA_mem->ida_epiccon = PT01 * EPCON;
+ IDA_mem->ida_maxnh = MAXNH;
+ IDA_mem->ida_maxnj = MAXNJ;
+ IDA_mem->ida_maxnit = MAXNI;
+ IDA_mem->ida_lsoff = FALSE;
+ IDA_mem->ida_steptol = RPowerR(IDA_mem->ida_uround, TWOTHIRDS);
+
+ /* Set default values for quad. optional inputs */
+ IDA_mem->ida_quadr = FALSE;
+ IDA_mem->ida_rhsQ = NULL;
+ IDA_mem->ida_errconQ = FALSE;
+ IDA_mem->ida_itolQ = IDA_NN;
+
+ /* Set default values for sensi. optional inputs */
+ IDA_mem->ida_sensi = FALSE;
+ IDA_mem->ida_user_dataS = (void *)IDA_mem;
+ IDA_mem->ida_resS = IDASensResDQ;
+ IDA_mem->ida_resSDQ = TRUE;
+ 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_maxcorS = MAXIT;
+ IDA_mem->ida_itolS = IDA_EE;
+
+ /* Defaults for sensi. quadr. optional inputs. */
+ IDA_mem->ida_quadr_sensi = FALSE;
+ 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_itolQS = IDA_EE;
+
+ /* Set defaults for ASA. */
+ IDA_mem->ida_adj = FALSE;
+ IDA_mem->ida_adj_mem = NULL;
+
+ /* Initialize lrw and liw */
+ IDA_mem->ida_lrw = 25 + 5*MXORDP1;
+ 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_VatolQMallocDone = FALSE;
+ IDA_mem->ida_quadMallocDone = FALSE;
+
+ IDA_mem->ida_VatolSMallocDone = FALSE;
+ IDA_mem->ida_SatolSMallocDone = FALSE;
+ IDA_mem->ida_sensMallocDone = FALSE;
+
+ IDA_mem->ida_VatolQSMallocDone = FALSE;
+ IDA_mem->ida_SatolQSMallocDone = FALSE;
+ IDA_mem->ida_quadSensMallocDone = FALSE;
+
+ IDA_mem->ida_adjMallocDone = FALSE;
+
+ /* Return pointer to IDA memory block */
+ return((void *)IDA_mem);
+}
+
+/*-----------------------------------------------------------------*/
+
+#define lrw (IDA_mem->ida_lrw)
+#define liw (IDA_mem->ida_liw)
+
+/*-----------------------------------------------------------------*/
+
+/*
+ * IDAInit
+ *
+ * IDAInit allocates and initializes memory for a problem. All
+ * problem specification inputs are checked for errors. If any
+ * error occurs during initialization, it is reported to the
+ * error handler function.
+ */
+
+int IDAInit(void *ida_mem, IDAResFn res,
+ realtype t0, N_Vector yy0, N_Vector yp0)
+{
+ IDAMem IDA_mem;
+ booleantype nvectorOK, allocOK;
+ long int lrw1, liw1;
+
+ /* Check ida_mem */
+
+ if (ida_mem == NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDAInit", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+ IDA_mem = (IDAMem) ida_mem;
+
+ /* Check for legal input parameters */
+
+ if (yy0 == NULL) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDAInit", MSG_Y0_NULL);
+ return(IDA_ILL_INPUT);
+ }
+
+ if (yp0 == NULL) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDAInit", MSG_YP0_NULL);
+ return(IDA_ILL_INPUT);
+ }
+
+ if (res == NULL) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDAInit", MSG_RES_NULL);
+ return(IDA_ILL_INPUT);
+ }
+
+ /* Test if all required vector operations are implemented */
+
+ nvectorOK = IDACheckNvector(yy0);
+ if (!nvectorOK) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDAInit", MSG_BAD_NVECTOR);
+ return(IDA_ILL_INPUT);
+ }
+
+ /* Set space requirements for one N_Vector */
+
+ if (yy0->ops->nvspace != NULL) {
+ N_VSpace(yy0, &lrw1, &liw1);
+ } else {
+ lrw1 = 0;
+ liw1 = 0;
+ }
+ IDA_mem->ida_lrw1 = lrw1;
+ IDA_mem->ida_liw1 = liw1;
+
+ /* Allocate the vectors (using yy0 as a template) */
+
+ allocOK = IDAAllocVectors(IDA_mem, yy0);
+ if (!allocOK) {
+ IDAProcessError(IDA_mem, IDA_MEM_FAIL, "IDAS", "IDAInit", MSG_MEM_FAIL);
+ return(IDA_MEM_FAIL);
+ }
+
+ /* All error checking is complete at this point */
+
+ /* Copy the input parameters into IDA memory block */
+
+ IDA_mem->ida_res = res;
+ IDA_mem->ida_tn = t0;
+
+ /* Set the linear solver addresses to NULL */
+
+ IDA_mem->ida_linit = NULL;
+ IDA_mem->ida_lsetup = NULL;
+ IDA_mem->ida_lsolve = NULL;
+ IDA_mem->ida_lperf = NULL;
+ IDA_mem->ida_lfree = NULL;
+ IDA_mem->ida_lmem = NULL;
+
+ /* Set forceSetup to FALSE */
+
+ IDA_mem->ida_forceSetup = FALSE;
+
+ /* Initialize the phi array */
+
+ N_VScale(ONE, yy0, IDA_mem->ida_phi[0]);
+ N_VScale(ONE, yp0, IDA_mem->ida_phi[1]);
+
+ /* Initialize all the counters and other optional output values */
+
+ IDA_mem->ida_nst = 0;
+ IDA_mem->ida_nre = 0;
+ IDA_mem->ida_ncfn = 0;
+ IDA_mem->ida_netf = 0;
+ IDA_mem->ida_nni = 0;
+ IDA_mem->ida_nsetups = 0;
+
+ IDA_mem->ida_kused = 0;
+ IDA_mem->ida_hused = ZERO;
+ IDA_mem->ida_tolsf = ONE;
+
+ IDA_mem->ida_nge = 0;
+
+ IDA_mem->ida_irfnd = 0;
+
+ /* Initialize counters specific to IC calculation. */
+ IDA_mem->ida_nbacktr = 0;
+
+ /* Initialize root-finding variables */
+
+ IDA_mem->ida_glo = NULL;
+ IDA_mem->ida_ghi = NULL;
+ IDA_mem->ida_grout = NULL;
+ IDA_mem->ida_iroots = NULL;
+ IDA_mem->ida_rootdir = NULL;
+ IDA_mem->ida_gfun = NULL;
+ IDA_mem->ida_nrtfn = 0;
+ IDA_mem->ida_gactive = NULL;
+ IDA_mem->ida_mxgnull = 1;
+
+ /* Initial setup not done yet */
+
+ IDA_mem->ida_SetupDone = FALSE;
+
+ /* Problem memory has been successfully allocated */
+
+ IDA_mem->ida_MallocDone = TRUE;
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+#define lrw1 (IDA_mem->ida_lrw1)
+#define liw1 (IDA_mem->ida_liw1)
+
+/*-----------------------------------------------------------------*/
+
+/*
+ * IDAReInit
+ *
+ * IDAReInit re-initializes IDA's memory for a problem, assuming
+ * it has already beeen allocated in a prior IDAInit call.
+ * All problem specification inputs are checked for errors.
+ * The problem size Neq is assumed to be unchaged since the call
+ * to IDAInit, and the maximum order maxord must not be larger.
+ * If any error occurs during reinitialization, it is reported to
+ * the error handler function.
+ * The return value is IDA_SUCCESS = 0 if no errors occurred, or
+ * a negative value otherwise.
+ */
+
+int IDAReInit(void *ida_mem,
+ realtype t0, N_Vector yy0, N_Vector yp0)
+{
+ IDAMem IDA_mem;
+
+ /* Check for legal input parameters */
+
+ if (ida_mem == NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDAReInit", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+ IDA_mem = (IDAMem) ida_mem;
+
+ /* Check if problem was malloc'ed */
+
+ if (IDA_mem->ida_MallocDone == FALSE) {
+ IDAProcessError(IDA_mem, IDA_NO_MALLOC, "IDAS", "IDAReInit", MSG_NO_MALLOC);
+ return(IDA_NO_MALLOC);
+ }
+
+ /* Check for legal input parameters */
+
+ if (yy0 == NULL) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDAReInit", MSG_Y0_NULL);
+ return(IDA_ILL_INPUT);
+ }
+
+ if (yp0 == NULL) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDAReInit", MSG_YP0_NULL);
+ return(IDA_ILL_INPUT);
+ }
+
+ /* Copy the input parameters into IDA memory block */
+
+ IDA_mem->ida_tn = t0;
+
+ /* Set forceSetup to FALSE */
+
+ IDA_mem->ida_forceSetup = FALSE;
+
+ /* Initialize the phi array */
+
+ N_VScale(ONE, yy0, IDA_mem->ida_phi[0]);
+ N_VScale(ONE, yp0, IDA_mem->ida_phi[1]);
+
+ /* Initialize all the counters and other optional output values */
+
+ IDA_mem->ida_nst = 0;
+ IDA_mem->ida_nre = 0;
+ IDA_mem->ida_ncfn = 0;
+ IDA_mem->ida_netf = 0;
+ IDA_mem->ida_nni = 0;
+ IDA_mem->ida_nsetups = 0;
+
+ IDA_mem->ida_kused = 0;
+ IDA_mem->ida_hused = ZERO;
+ IDA_mem->ida_tolsf = ONE;
+
+ IDA_mem->ida_nge = 0;
+
+ IDA_mem->ida_irfnd = 0;
+
+ /* Initial setup not done yet */
+
+ IDA_mem->ida_SetupDone = FALSE;
+
+ /* Problem has been successfully re-initialized */
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+/*
+ * IDASStolerances
+ * IDASVtolerances
+ * IDAWFtolerances
+ *
+ * These functions specify the integration tolerances. One of them
+ * MUST be called before the first call to IDA.
+ *
+ * IDASStolerances specifies scalar relative and absolute tolerances.
+ * IDASVtolerances specifies scalar relative tolerance and a vector
+ * absolute tolerance (a potentially different absolute tolerance
+ * for each vector component).
+ * IDAWFtolerances specifies a user-provides function (of type IDAEwtFn)
+ * which will be called to set the error weight vector.
+ */
+
+int IDASStolerances(void *ida_mem, realtype reltol, realtype abstol)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDASStolerances", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+ IDA_mem = (IDAMem) ida_mem;
+
+ if (IDA_mem->ida_MallocDone == FALSE) {
+ IDAProcessError(IDA_mem, IDA_NO_MALLOC, "IDAS", "IDASStolerances", MSG_NO_MALLOC);
+ return(IDA_NO_MALLOC);
+ }
+
+ /* Check inputs */
+ if (reltol < ZERO) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDASStolerances", MSG_BAD_RTOL);
+ return(IDA_ILL_INPUT);
+ }
+
+ if (abstol < ZERO) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDASStolerances", MSG_BAD_ATOL);
+ return(IDA_ILL_INPUT);
+ }
+
+ /* Copy tolerances into memory */
+ IDA_mem->ida_rtol = reltol;
+ IDA_mem->ida_Satol = abstol;
+
+ IDA_mem->ida_itol = IDA_SS;
+
+ IDA_mem->ida_user_efun = FALSE;
+ IDA_mem->ida_efun = IDAEwtSet;
+ IDA_mem->ida_edata = NULL; /* will be set to ida_mem in InitialSetup */
+
+ return(IDA_SUCCESS);
+}
+
+
+int IDASVtolerances(void *ida_mem, realtype reltol, N_Vector abstol)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDASVtolerances", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+ IDA_mem = (IDAMem) ida_mem;
+
+ if (IDA_mem->ida_MallocDone == FALSE) {
+ IDAProcessError(IDA_mem, IDA_NO_MALLOC, "IDAS", "IDASVtolerances", MSG_NO_MALLOC);
+ return(IDA_NO_MALLOC);
+ }
+
+ /* Check inputs */
+
+ if (reltol < ZERO) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDASVtolerances", MSG_BAD_RTOL);
+ return(IDA_ILL_INPUT);
+ }
+
+ if (N_VMin(abstol) < ZERO) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDASVtolerances", MSG_BAD_ATOL);
+ return(IDA_ILL_INPUT);
+ }
+
+ /* Copy tolerances into memory */
+
+ 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_rtol = reltol;
+ N_VScale(ONE, abstol, IDA_mem->ida_Vatol);
+
+ IDA_mem->ida_itol = IDA_SV;
+
+ IDA_mem->ida_user_efun = FALSE;
+ IDA_mem->ida_efun = IDAEwtSet;
+ IDA_mem->ida_edata = NULL; /* will be set to ida_mem in InitialSetup */
+
+ return(IDA_SUCCESS);
+}
+
+
+int IDAWFtolerances(void *ida_mem, IDAEwtFn efun)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDAWFtolerances", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+ IDA_mem = (IDAMem) ida_mem;
+
+ if (IDA_mem->ida_MallocDone == FALSE) {
+ 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_efun = efun;
+ IDA_mem->ida_edata = NULL; /* will be set to user_data in InitialSetup */
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+/*
+ * IDAQuadMalloc
+ *
+ * IDAQuadMalloc allocates and initializes quadrature related
+ * memory for a problem. All problem specification inputs are
+ * checked for errors. If any error occurs during initialization,
+ * it is reported to the file whose file pointer is errfp.
+ * The return value is IDA_SUCCESS = 0 if no errors occurred, or
+ * a negative value otherwise.
+ */
+
+int IDAQuadInit(void *ida_mem, IDAQuadRhsFn rhsQ, N_Vector yQ0)
+{
+ IDAMem IDA_mem;
+ booleantype allocOK;
+ long int lrw1Q, liw1Q;
+ int i;
+
+ /* Check ida_mem */
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDAQuadInit", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+ IDA_mem = (IDAMem) ida_mem;
+
+ /* Set space requirements for one N_Vector */
+ N_VSpace(yQ0, &lrw1Q, &liw1Q);
+ IDA_mem->ida_lrw1Q = lrw1Q;
+ IDA_mem->ida_liw1Q = liw1Q;
+
+ /* Allocate the vectors (using yQ0 as a template) */
+ allocOK = IDAQuadAllocVectors(IDA_mem, yQ0);
+ if (!allocOK) {
+ IDAProcessError(IDA_mem, IDA_MEM_FAIL, "IDAS", "IDAQuadInit", MSG_MEM_FAIL);
+ return(IDA_MEM_FAIL);
+ }
+
+ /* Initialize phiQ in the history array */
+ N_VScale(ONE, yQ0, IDA_mem->ida_phiQ[0]);
+
+ for(i=1; i<=IDA_mem->ida_maxord; i++)
+ N_VConst(ZERO, IDA_mem->ida_phiQ[i]);
+
+ /* Copy the input parameters into IDAS state */
+ IDA_mem->ida_rhsQ = rhsQ;
+
+ /* Initialize counters */
+ IDA_mem->ida_nrQe = 0;
+ IDA_mem->ida_netfQ = 0;
+
+ /* Quadrature integration turned ON */
+ IDA_mem->ida_quadr = TRUE;
+ IDA_mem->ida_quadMallocDone = TRUE;
+
+ /* Quadrature initialization was successfull */
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+#define lrw1Q (IDA_mem->ida_lrw1Q)
+#define liw1Q (IDA_mem->ida_liw1Q)
+
+/*-----------------------------------------------------------------*/
+
+/*
+ * IDAQuadReInit
+ *
+ * IDAQuadReInit re-initializes IDAS's quadrature related memory
+ * for a problem, assuming it has already been allocated in prior
+ * calls to IDAInit and IDAQuadMalloc.
+ * All problem specification inputs are checked for errors.
+ * If any error occurs during initialization, it is reported to the
+ * file whose file pointer is errfp.
+ * The return value is IDA_SUCCESS = 0 if no errors occurred, or
+ * a negative value otherwise.
+ */
+
+int IDAQuadReInit(void *ida_mem, N_Vector yQ0)
+{
+ IDAMem IDA_mem;
+ int i;
+
+ /* Check ida_mem */
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDAQuadReInit", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+ IDA_mem = (IDAMem) ida_mem;
+
+ /* Ckeck if quadrature was initialized */
+ if (IDA_mem->ida_quadMallocDone == FALSE) {
+ IDAProcessError(IDA_mem, IDA_NO_QUAD, "IDAS", "IDAQuadReInit", MSG_NO_QUAD);
+ return(IDA_NO_QUAD);
+ }
+
+ /* Initialize phiQ in the history array */
+ N_VScale(ONE, yQ0, IDA_mem->ida_phiQ[0]);
+
+ for(i=1; i<=IDA_mem->ida_maxord; i++)
+ N_VConst(ZERO, IDA_mem->ida_phiQ[i]);
+
+ /* Initialize counters */
+ IDA_mem->ida_nrQe = 0;
+ IDA_mem->ida_netfQ = 0;
+
+ /* Quadrature integration turned ON */
+ IDA_mem->ida_quadr = TRUE;
+
+ /* Quadrature re-initialization was successfull */
+ return(IDA_SUCCESS);
+}
+
+
+/*
+ * IDAQuadSStolerances
+ * IDAQuadSVtolerances
+ *
+ *
+ * These functions specify the integration tolerances for quadrature
+ * variables. One of them MUST be called before the first call to
+ * IDA IF error control on the quadrature variables is enabled
+ * (see IDASetQuadErrCon).
+ *
+ * IDASStolerances specifies scalar relative and absolute tolerances.
+ * IDASVtolerances specifies scalar relative tolerance and a vector
+ * absolute tolerance (a potentially different absolute tolerance
+ * for each vector component).
+ */
+int IDAQuadSStolerances(void *ida_mem, realtype reltolQ, realtype abstolQ)
+{
+ IDAMem IDA_mem;
+
+ /*Check ida mem*/
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDAQuadSStolerances", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+ IDA_mem = (IDAMem) ida_mem;
+
+ /* Ckeck if quadrature was initialized */
+ if (IDA_mem->ida_quadMallocDone == FALSE) {
+ IDAProcessError(IDA_mem, IDA_NO_QUAD, "IDAS", "IDAQuadSStolerances", MSG_NO_QUAD);
+ return(IDA_NO_QUAD);
+ }
+
+ /* Test user-supplied tolerances */
+ if (reltolQ < ZERO) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDAQuadSStolerances", MSG_BAD_RTOLQ);
+ return(IDA_ILL_INPUT);
+ }
+
+ if (abstolQ < ZERO) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDAQuadSStolerances", MSG_BAD_ATOLQ);
+ return(IDA_ILL_INPUT);
+ }
+
+ /* Copy tolerances into memory */
+ IDA_mem->ida_itolQ = IDA_SS;
+
+ IDA_mem->ida_rtolQ = reltolQ;
+ IDA_mem->ida_SatolQ = abstolQ;
+
+
+ return (IDA_SUCCESS);
+}
+
+int IDAQuadSVtolerances(void *ida_mem, realtype reltolQ, N_Vector abstolQ)
+{
+ IDAMem IDA_mem;
+
+ /*Check ida mem*/
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDAQuadSVtolerances", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+ IDA_mem = (IDAMem) ida_mem;
+
+ /* Ckeck if quadrature was initialized */
+ if (IDA_mem->ida_quadMallocDone == FALSE) {
+ IDAProcessError(IDA_mem, IDA_NO_QUAD, "IDAS", "IDAQuadSVtolerances", MSG_NO_QUAD);
+ return(IDA_NO_QUAD);
+ }
+
+ /* Test user-supplied tolerances */
+ if (reltolQ < ZERO) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDAQuadSVtolerances", MSG_BAD_RTOLQ);
+ return(IDA_ILL_INPUT);
+ }
+
+ if (abstolQ == NULL) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDAQuadSVtolerances", MSG_NULL_ATOLQ);
+ return(IDA_ILL_INPUT);
+ }
+
+ if (N_VMin(abstolQ)<ZERO) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDAQuadSVtolerances", MSG_BAD_ATOLQ);
+ return(IDA_ILL_INPUT);
+ }
+
+ /* Copy tolerances into memory */
+ IDA_mem->ida_itolQ = IDA_SV;
+ IDA_mem->ida_rtolQ = reltolQ;
+
+ /* clone the absolute tolerances vector (if necessary) */
+ if (FALSE == IDA_mem->ida_VatolQMallocDone) {
+ IDA_mem->ida_VatolQ = N_VClone(abstolQ);
+ lrw += lrw1Q;
+ liw += liw1Q;
+ IDA_mem->ida_VatolQMallocDone = TRUE;
+ }
+
+ N_VScale(ONE, abstolQ, IDA_mem->ida_VatolQ);
+
+ return(IDA_SUCCESS);
+}
+
+/*
+ * IDASenMalloc
+ *
+ * IDASensInit allocates and initializes sensitivity related
+ * memory for a problem. All problem specification inputs are
+ * checked for errors. If any error occurs during initialization,
+ * it is reported to the file whose file pointer is errfp.
+ * The return value is IDA_SUCCESS = 0 if no errors occurred, or
+ * a negative value otherwise.
+ */
+
+int IDASensInit(void *ida_mem, int Ns, int ism,
+ IDASensResFn fS,
+ N_Vector *yS0, N_Vector *ypS0)
+
+{
+ IDAMem IDA_mem;
+ booleantype allocOK;
+ int is;
+
+ /* Check ida_mem */
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDASensInit", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+ IDA_mem = (IDAMem) ida_mem;
+
+ /* Check if Ns is legal */
+ if (Ns<=0) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDASensInit", MSG_BAD_NS);
+ return(IDA_ILL_INPUT);
+ }
+ IDA_mem->ida_Ns = Ns;
+
+ /* Check if ism is legal */
+ if ((ism!=IDA_SIMULTANEOUS) && (ism!=IDA_STAGGERED)) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDASensInit", MSG_BAD_ISM);
+ return(IDA_ILL_INPUT);
+ }
+ IDA_mem->ida_ism = ism;
+
+ /* Check if yS0 and ypS0 are non-null */
+ if (yS0 == NULL) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDASensInit", MSG_NULL_YYS0);
+ return(IDA_ILL_INPUT);
+ }
+ if (ypS0 == NULL) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDASensInit", MSG_NULL_YPS0);
+ return(IDA_ILL_INPUT);
+ }
+
+ /* Store sensitivity RHS-related data */
+
+ if (fS != NULL) {
+ IDA_mem->ida_resS = fS;
+ IDA_mem->ida_user_dataS = IDA_mem->ida_user_data;
+ IDA_mem->ida_resSDQ = FALSE;
+ } else {
+ IDA_mem->ida_resS = IDASensResDQ;
+ IDA_mem->ida_user_dataS = ida_mem;
+ IDA_mem->ida_resSDQ = TRUE;
+ }
+
+ /* Allocate the vectors (using yS0[0] as a template) */
+
+ allocOK = IDASensAllocVectors(IDA_mem, yS0[0]);
+ if (!allocOK) {
+ IDAProcessError(IDA_mem, IDA_MEM_FAIL, "IDAS", "IDASensInit", MSG_MEM_FAIL);
+ return(IDA_MEM_FAIL);
+ }
+
+ /*----------------------------------------------
+ All error checking is complete at this point
+ -----------------------------------------------*/
+
+ /* Initialize the phiS array */
+ for (is=0; is<Ns; is++) {
+ N_VScale(ONE, yS0[is], IDA_mem->ida_phiS[0][is]);
+ N_VScale(ONE, ypS0[is], IDA_mem->ida_phiS[1][is]);
+ }
+
+ /* Initialize all sensitivity related counters */
+ IDA_mem->ida_nrSe = 0;
+ IDA_mem->ida_nreS = 0;
+ IDA_mem->ida_ncfnS = 0;
+ IDA_mem->ida_netfS = 0;
+ IDA_mem->ida_nniS = 0;
+ IDA_mem->ida_nsetupsS = 0;
+
+ /* Set default values for plist and pbar */
+ for (is=0; is<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_sensMallocDone = TRUE;
+
+ /* Sensitivity initialization was successfull */
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+#define Ns (IDA_mem->ida_Ns)
+
+/*-----------------------------------------------------------------*/
+
+/*
+ * IDASensReInit
+ *
+ * IDASensReInit re-initializes IDAS's sensitivity related memory
+ * for a problem, assuming it has already been allocated in prior
+ * calls to IDAInit and IDASensInit.
+ * All problem specification inputs are checked for errors.
+ * The number of sensitivities Ns is assumed to be unchanged since
+ * the previous call to IDASensInit.
+ * If any error occurs during initialization, it is reported to the
+ * file whose file pointer is errfp.
+ * The return value is IDA_SUCCESS = 0 if no errors occurred, or
+ * a negative value otherwise.
+ */
+
+int IDASensReInit(void *ida_mem, int ism, N_Vector *yS0, N_Vector *ypS0)
+{
+ IDAMem IDA_mem;
+ int is;
+
+ /* Check ida_mem */
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDASensReInit", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+ IDA_mem = (IDAMem) ida_mem;
+
+ /* Was sensitivity initialized? */
+ if (IDA_mem->ida_sensMallocDone == FALSE) {
+ IDAProcessError(IDA_mem, IDA_NO_SENS, "IDAS", "IDASensReInit", MSG_NO_SENSI);
+ return(IDA_NO_SENS);
+ }
+
+ /* Check if ism is legal */
+ if ((ism!=IDA_SIMULTANEOUS) && (ism!=IDA_STAGGERED)) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDASensReInit", MSG_BAD_ISM);
+ return(IDA_ILL_INPUT);
+ }
+ IDA_mem->ida_ism = ism;
+
+ /* Check if yS0 and ypS0 are non-null */
+ if (yS0 == NULL) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDASensReInit", MSG_NULL_YYS0);
+ return(IDA_ILL_INPUT);
+ }
+ if (ypS0 == NULL) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDASensReInit", MSG_NULL_YPS0);
+ return(IDA_ILL_INPUT);
+ }
+
+ /*----------------------------------------------
+ All error checking is complete at this point
+ -----------------------------------------------*/
+
+ /* Initialize the phiS array */
+ for (is=0; is<Ns; is++) {
+ N_VScale(ONE, yS0[is], IDA_mem->ida_phiS[0][is]);
+ N_VScale(ONE, ypS0[is], IDA_mem->ida_phiS[1][is]);
+ }
+
+ /* Initialize all sensitivity related counters */
+ IDA_mem->ida_nrSe = 0;
+ IDA_mem->ida_nreS = 0;
+ IDA_mem->ida_ncfnS = 0;
+ IDA_mem->ida_netfS = 0;
+ IDA_mem->ida_nniS = 0;
+ IDA_mem->ida_nsetupsS = 0;
+
+ /* Set default values for plist and pbar */
+ for (is=0; is<Ns; is++) {
+ IDA_mem->ida_plist[is] = is;
+ IDA_mem->ida_pbar[is] = ONE;
+ }
+
+ /* Sensitivities will be computed */
+ IDA_mem->ida_sensi = TRUE;
+
+ /* Sensitivity re-initialization was successfull */
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+/*
+ * IDASensSStolerances
+ * IDASensSVtolerances
+ * IDASensEEtolerances
+ *
+ * These functions specify the integration tolerances for sensitivity
+ * variables. One of them MUST be called before the first call to IDASolve.
+ *
+ * IDASensSStolerances specifies scalar relative and absolute tolerances.
+ * IDASensSVtolerances specifies scalar relative tolerance and a vector
+ * absolute tolerance for each sensitivity vector (a potentially different
+ * absolute tolerance for each vector component).
+ * IDASensEEtolerances specifies that tolerances for sensitivity variables
+ * should be estimated from those provided for the state variables.
+ */
+
+
+int IDASensSStolerances(void *ida_mem, realtype reltolS, realtype *abstolS)
+{
+ IDAMem IDA_mem;
+ int is;
+
+ /* Check ida_mem pointer */
+ if (ida_mem == NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDASensSStolerances", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+ IDA_mem = (IDAMem) ida_mem;
+
+ /* Was sensitivity initialized? */
+
+ if (IDA_mem->ida_sensMallocDone == FALSE) {
+ IDAProcessError(IDA_mem, IDA_NO_SENS, "IDAS", "IDASensSStolerances", MSG_NO_SENSI);
+ return(IDA_NO_SENS);
+ }
+
+ /* Test user-supplied tolerances */
+
+ if (reltolS < ZERO) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDASensSStolerances", MSG_BAD_RTOLS);
+ return(IDA_ILL_INPUT);
+ }
+
+ if (abstolS == NULL) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDASensSStolerances", MSG_NULL_ATOLS);
+ return(IDA_ILL_INPUT);
+ }
+
+ for (is=0; is<Ns; is++)
+ if (abstolS[is] < ZERO) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDASensSStolerances", MSG_BAD_ATOLS);
+ return(IDA_ILL_INPUT);
+ }
+
+ /* Copy tolerances into memory */
+
+ IDA_mem->ida_itolS = IDA_SS;
+
+ IDA_mem->ida_rtolS = reltolS;
+
+ 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;
+ }
+
+ for (is=0; is<Ns; is++)
+ IDA_mem->ida_SatolS[is] = abstolS[is];
+
+ return(IDA_SUCCESS);
+}
+
+
+int IDASensSVtolerances(void *ida_mem, realtype reltolS, N_Vector *abstolS)
+{
+ IDAMem IDA_mem;
+ int is;
+
+ /* Check ida_mem pointer */
+ if (ida_mem == NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDASensSVtolerances", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+ IDA_mem = (IDAMem) ida_mem;
+
+ /* Was sensitivity initialized? */
+
+ if (IDA_mem->ida_sensMallocDone == FALSE) {
+ IDAProcessError(IDA_mem, IDA_NO_SENS, "IDAS", "IDASensSVtolerances", MSG_NO_SENSI);
+ return(IDA_NO_SENS);
+ }
+
+ /* Test user-supplied tolerances */
+
+ if (reltolS < ZERO) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDASensSVtolerances", MSG_BAD_RTOLS);
+ return(IDA_ILL_INPUT);
+ }
+
+ if (abstolS == NULL) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDASensSVtolerances", MSG_NULL_ATOLS);
+ return(IDA_ILL_INPUT);
+ }
+
+ for (is=0; is<Ns; is++) {
+ if (N_VMin(abstolS[is])<ZERO) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDASensSStolerances", MSG_BAD_ATOLS);
+ return(IDA_ILL_INPUT);
+ }
+ }
+
+ 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;
+ }
+
+ for (is=0; is<Ns; is++)
+ N_VScale(ONE, abstolS[is], IDA_mem->ida_VatolS[is]);
+
+ return(IDA_SUCCESS);
+}
+
+int IDASensEEtolerances(void *ida_mem)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDASensEEtolerances", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+ IDA_mem = (IDAMem) ida_mem;
+
+ /* Was sensitivity initialized? */
+
+ if (IDA_mem->ida_sensMallocDone == FALSE) {
+ IDAProcessError(IDA_mem, IDA_NO_SENS, "IDAS", "IDASensEEtolerances", MSG_NO_SENSI);
+ return(IDA_NO_SENS);
+ }
+
+ IDA_mem->ida_itolS = IDA_EE;
+
+ return(IDA_SUCCESS);
+}
+
+
+int IDAQuadSensInit(void *ida_mem, IDAQuadSensRhsFn rhsQS, N_Vector *yQS0)
+{
+ IDAMem IDA_mem;
+ booleantype allocOK;
+ int is;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDAQuadSensInit", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+ IDA_mem = (IDAMem) ida_mem;
+
+ /* Check if sensitivity analysis is active */
+ if (!IDA_mem->ida_sensi) {
+ IDAProcessError(NULL, IDA_NO_SENS, "IDAS", "IDAQuadSensInit", MSG_NO_SENSI);
+ return(IDA_NO_SENS);
+ }
+
+ /* Verifiy yQS0 parameter. */
+ if (yQS0==NULL) {
+ IDAProcessError(NULL, IDA_ILL_INPUT, "IDAS", "IDAQuadSensInit", MSG_NULL_YQS0);
+ return(IDA_ILL_INPUT);
+ }
+
+ /* Allocate vector needed for quadratures' sensitivities. */
+ allocOK = IDAQuadSensAllocVectors(IDA_mem, yQS0[0]);
+ if (!allocOK) {
+ IDAProcessError(NULL, IDA_MEM_FAIL, "IDAS", "IDAQuadSensInit", MSG_MEM_FAIL);
+ return(IDA_MEM_FAIL);
+ }
+
+ /* Error checking complete. */
+ if (rhsQS == NULL) {
+ IDA_mem->ida_rhsQSDQ = TRUE;
+ IDA_mem->ida_rhsQS = IDAQuadSensRhsInternalDQ;
+
+ IDA_mem->ida_user_dataQS = ida_mem;
+ } else {
+ IDA_mem->ida_rhsQSDQ = FALSE;
+ 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++)
+ N_VScale(ONE, yQS0[is], IDA_mem->ida_phiQS[0][is]);
+
+ /* Initialize all sensitivities related counters. */
+ IDA_mem->ida_nrQSe = 0;
+ IDA_mem->ida_nrQeS = 0;
+ 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;
+
+ return(IDA_SUCCESS);
+}
+
+int IDAQuadSensReInit(void *ida_mem, N_Vector *yQS0)
+{
+ IDAMem IDA_mem;
+ int is;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDAQuadSensReInit", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+ IDA_mem = (IDAMem) ida_mem;
+
+ /* Check if sensitivity analysis is active */
+ if (!IDA_mem->ida_sensi) {
+ IDAProcessError(IDA_mem, IDA_NO_SENS, "IDAS", "IDAQuadSensReInit", MSG_NO_SENSI);
+ return(IDA_NO_SENS);
+ }
+
+ /* Was sensitivity for quadrature already initialized? */
+ if (!IDA_mem->ida_quadSensMallocDone) {
+ IDAProcessError(IDA_mem, IDA_NO_QUADSENS, "IDAS", "IDAQuadSensReInit", MSG_NO_QUADSENSI);
+ return(IDA_NO_QUADSENS);
+ }
+
+ /* Verifiy yQS0 parameter. */
+ if (yQS0==NULL) {
+ IDAProcessError(NULL, IDA_ILL_INPUT, "IDAS", "IDAQuadSensReInit", MSG_NULL_YQS0);
+ return(IDA_ILL_INPUT);
+ }
+
+ /* Error checking complete at this point. */
+
+ /* Initialize phiQS[0] in the history array */
+ for (is=0; is<Ns; is++)
+ N_VScale(ONE, yQS0[is], IDA_mem->ida_phiQS[0][is]);
+
+ /* Initialize all sensitivities related counters. */
+ IDA_mem->ida_nrQSe = 0;
+ IDA_mem->ida_nrQeS = 0;
+ IDA_mem->ida_netfQS = 0;
+
+ /* Everything allright, set the flags and return with success. */
+ IDA_mem->ida_quadr_sensi = TRUE;
+
+ return(IDA_SUCCESS);
+}
+
+/*
+ * IDAQuadSensSStolerances
+ * IDAQuadSensSVtolerances
+ * IDAQuadSensEEtolerances
+ *
+ * These functions specify the integration tolerances for quadrature
+ * sensitivity variables. One of them MUST be called before the first
+ * call to IDAS IF these variables are included in the error test.
+ *
+ * IDAQuadSensSStolerances specifies scalar relative and absolute tolerances.
+ * IDAQuadSensSVtolerances specifies scalar relative tolerance and a vector
+ * absolute tolerance for each quadrature sensitivity vector (a potentially
+ * different absolute tolerance for each vector component).
+ * IDAQuadSensEEtolerances specifies that tolerances for sensitivity variables
+ * should be estimated from those provided for the quadrature variables.
+ * In this case, tolerances for the quadrature variables must be
+ * specified through a call to one of IDAQuad**tolerances.
+ */
+
+int IDAQuadSensSStolerances(void *ida_mem, realtype reltolQS, realtype *abstolQS)
+{
+ IDAMem IDA_mem;
+ int is;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDAQuadSensSStolerances", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+ IDA_mem = (IDAMem) ida_mem;
+
+ /* Check if sensitivity analysis is active */
+ if (!IDA_mem->ida_sensi) {
+ IDAProcessError(IDA_mem, IDA_NO_SENS, "IDAS", "IDAQuadSensSStolerances", MSG_NO_SENSI);
+ return(IDA_NO_SENS);
+ }
+
+ /* Was sensitivity for quadrature already initialized? */
+ if (!IDA_mem->ida_quadSensMallocDone) {
+ IDAProcessError(IDA_mem, IDA_NO_QUADSENS, "IDAS", "IDAQuadSensSStolerances", MSG_NO_QUADSENSI);
+ return(IDA_NO_QUADSENS);
+ }
+
+ /* Test user-supplied tolerances */
+
+ if (reltolQS < ZERO) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDAQuadSensSStolerances", MSG_BAD_RELTOLQS);
+ return(IDA_ILL_INPUT);
+ }
+
+ if (abstolQS == NULL) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDAQuadSensSStolerances", MSG_NULL_ABSTOLQS);
+ return(IDA_ILL_INPUT);
+ }
+
+ for (is=0; is<Ns; is++)
+ if (abstolQS[is] < ZERO) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDAQuadSensSStolerances", MSG_BAD_ABSTOLQS);
+ return(IDA_ILL_INPUT);
+ }
+
+ /* Save data. */
+ IDA_mem->ida_itolQS = IDA_SS;
+ 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;
+ }
+
+ for (is=0; is<Ns; is++)
+ IDA_mem->ida_SatolQS[is] = abstolQS[is];
+
+ return(IDA_SUCCESS);
+}
+
+int IDAQuadSensSVtolerances(void *ida_mem, realtype reltolQS, N_Vector *abstolQS)
+{
+ IDAMem IDA_mem;
+ int is;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDAQuadSensSVtolerances", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+ IDA_mem = (IDAMem) ida_mem;
+
+ /* Check if sensitivity analysis is active */
+ if (!IDA_mem->ida_sensi) {
+ IDAProcessError(IDA_mem, IDA_NO_SENS, "IDAS", "IDAQuadSensSVtolerances", MSG_NO_SENSI);
+ return(IDA_NO_SENS);
+ }
+
+ /* Was sensitivity for quadrature already initialized? */
+ if (!IDA_mem->ida_quadSensMallocDone) {
+ IDAProcessError(IDA_mem, IDA_NO_QUADSENS, "IDAS", "IDAQuadSensSVtolerances", MSG_NO_QUADSENSI);
+ return(IDA_NO_QUADSENS);
+ }
+
+ /* Test user-supplied tolerances */
+
+ if (reltolQS < ZERO) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDAQuadSensSVtolerances", MSG_BAD_RELTOLQS);
+ return(IDA_ILL_INPUT);
+ }
+
+ if (abstolQS == NULL) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDAQuadSensSVtolerances", MSG_NULL_ABSTOLQS);
+ return(IDA_ILL_INPUT);
+ }
+
+ for (is=0; is<Ns; is++)
+ if (N_VMin(abstolQS[is]) < ZERO) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDAQuadSensSVtolerances", MSG_BAD_ABSTOLQS);
+ return(IDA_ILL_INPUT);
+ }
+
+ /* Save data. */
+ IDA_mem->ida_itolQS = IDA_SV;
+ 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;
+ }
+
+ for (is=0; is<Ns; is++)
+ N_VScale(ONE, abstolQS[is], IDA_mem->ida_VatolQS[is]);
+
+ return(IDA_SUCCESS);
+}
+
+int IDAQuadSensEEtolerances(void *ida_mem)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDAQuadSensEEtolerances", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+ IDA_mem = (IDAMem) ida_mem;
+
+ /* Check if sensitivity analysis is active */
+ if (!IDA_mem->ida_sensi) {
+ IDAProcessError(IDA_mem, IDA_NO_SENS, "IDAS", "IDAQuadSensEEtolerances", MSG_NO_SENSI);
+ return(IDA_NO_SENS);
+ }
+
+ /* Was sensitivity for quadrature already initialized? */
+ if (!IDA_mem->ida_quadSensMallocDone) {
+ IDAProcessError(IDA_mem, IDA_NO_QUADSENS, "IDAS", "IDAQuadSensEEtolerances", MSG_NO_QUADSENSI);
+ return(IDA_NO_QUADSENS);
+ }
+
+ IDA_mem->ida_itolQS = IDA_EE;
+
+ return(IDA_SUCCESS);
+}
+
+/*
+ * IDASensToggleOff
+ *
+ * IDASensToggleOff deactivates sensitivity calculations.
+ * It does NOT deallocate sensitivity-related memory.
+ */
+int IDASensToggleOff(void *ida_mem)
+{
+ IDAMem IDA_mem;
+
+ /* Check ida_mem */
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDASensToggleOff", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+ IDA_mem = (IDAMem) ida_mem;
+
+ /* Disable sensitivities */
+ IDA_mem->ida_sensi = FALSE;
+ IDA_mem->ida_quadr_sensi = FALSE;
+
+ 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
+ *
+ * IDARootInit initializes a rootfinding problem to be solved
+ * during the integration of the DAE system. It loads the root
+ * function pointer and the number of root functions, and allocates
+ * workspace memory. The return value is IDA_SUCCESS = 0 if no
+ * errors occurred, or a negative value otherwise.
+ */
+
+int IDARootInit(void *ida_mem, int nrtfn, IDARootFn g)
+{
+ IDAMem IDA_mem;
+ int i, nrt;
+
+ /* Check ida_mem pointer */
+ if (ida_mem == NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDARootInit", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+ IDA_mem = (IDAMem) ida_mem;
+
+ nrt = (nrtfn < 0) ? 0 : nrtfn;
+
+ /* If rerunning IDARootInit() with a different number of root
+ functions (changing number of gfun components), then free
+ 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;
+
+ lrw -= 3 * (IDA_mem->ida_nrtfn);
+ liw -= 3 * (IDA_mem->ida_nrtfn);
+
+ }
+
+ /* If IDARootInit() was called with nrtfn == 0, then set ida_nrtfn to
+ zero and ida_gfun to NULL before returning */
+ if (nrt == 0) {
+ IDA_mem->ida_nrtfn = nrt;
+ gfun = NULL;
+ return(IDA_SUCCESS);
+ }
+
+ /* If rerunning IDARootInit() with the same number of root functions
+ (not changing number of gfun components), then check if the root
+ function argument has changed */
+ /* If g != NULL then return as currently reserved memory resources
+ will suffice */
+ if (nrt == IDA_mem->ida_nrtfn) {
+ if (g != 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;
+
+ lrw -= 3*nrt;
+ liw -= 3*nrt;
+
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDARootInit", MSG_ROOT_FUNC_NULL);
+ return(IDA_ILL_INPUT);
+ }
+ else {
+ gfun = g;
+ return(IDA_SUCCESS);
+ }
+ }
+ else return(IDA_SUCCESS);
+ }
+
+ /* Set variable values in IDA memory block */
+ IDA_mem->ida_nrtfn = nrt;
+ if (g == NULL) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDARootInit", MSG_ROOT_FUNC_NULL);
+ return(IDA_ILL_INPUT);
+ }
+ else gfun = g;
+
+ /* Allocate necessary memory and return */
+ glo = NULL;
+ glo = (realtype *) malloc(nrt*sizeof(realtype));
+ if (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;
+ 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;
+ 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;
+ 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;
+ 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;
+ 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;
+
+ /* Set default values for gactive (all active) */
+ for(i=0; i<nrt; i++) gactive[i] = TRUE;
+
+ lrw += 3*nrt;
+ 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)
+
+
+/*
+ * -----------------------------------------------------------------
+ * Main solver function
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * IDASolve
+ *
+ * This routine is the main driver of the IDA package.
+ *
+ * It integrates over an independent variable interval defined by the user,
+ * by calling IDAStep to take internal independent variable steps.
+ *
+ * The first time that IDASolve is called for a successfully initialized
+ * problem, it computes a tentative initial step size.
+ *
+ * IDASolve supports two modes, specified by itask:
+ * In the IDA_NORMAL mode, the solver steps until it passes tout and then
+ * interpolates to obtain y(tout) and yp(tout).
+ * In the IDA_ONE_STEP mode, it takes one internal step and returns.
+ *
+ * IDASolve returns integer values corresponding to success and failure as below:
+ *
+ * successful returns:
+ *
+ * IDA_SUCCESS
+ * IDA_TSTOP_RETURN
+ *
+ * failed returns:
+ *
+ * IDA_ILL_INPUT
+ * IDA_TOO_MUCH_WORK
+ * IDA_MEM_NULL
+ * IDA_TOO_MUCH_ACC
+ * IDA_CONV_FAIL
+ * IDA_LSETUP_FAIL
+ * IDA_LSOLVE_FAIL
+ * IDA_CONSTR_FAIL
+ * IDA_ERR_FAIL
+ * IDA_REP_RES_ERR
+ * IDA_RES_FAIL
+ */
+
+int IDASolve(void *ida_mem, realtype tout, realtype *tret,
+ N_Vector yret, N_Vector ypret, int itask)
+{
+ long int nstloc;
+ int sflag, istate, ier, irfndp, is, ir;
+ realtype tdist, troundoff, ypnorm, rh, nrm;
+ IDAMem IDA_mem;
+ booleantype inactive_roots;
+
+ /* Check for legal inputs in all cases. */
+ if (ida_mem == NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDASolve", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+ IDA_mem = (IDAMem) ida_mem;
+
+ /* Check if problem was malloc'ed */
+ if (IDA_mem->ida_MallocDone == FALSE) {
+ IDAProcessError(IDA_mem, IDA_NO_MALLOC, "IDAS", "IDASolve", MSG_NO_MALLOC);
+ return(IDA_NO_MALLOC);
+ }
+
+ /* Check for legal arguments */
+ if (yret == NULL) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDASolve", MSG_YRET_NULL);
+ return(IDA_ILL_INPUT);
+ }
+ yy = yret;
+
+ if (ypret == NULL) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDASolve", MSG_YPRET_NULL);
+ return(IDA_ILL_INPUT);
+ }
+ yp = ypret;
+
+ if (tret == NULL) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDASolve", MSG_TRET_NULL);
+ return(IDA_ILL_INPUT);
+ }
+
+ if ((itask != IDA_NORMAL) && (itask != IDA_ONE_STEP)) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDASolve", MSG_BAD_ITASK);
+ return(IDA_ILL_INPUT);
+ }
+
+ if (itask == IDA_NORMAL) toutc = tout;
+ taskc = itask;
+
+ /* Sensitivity-specific tests (if using internal DQ functions) */
+ if (sensi && resSDQ) {
+ /* Make sure we have the right 'user data' */
+ user_dataS = ida_mem;
+ /* Test if we have the problem parameters */
+ if(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;
+ /* Test if we have the problem parameters */
+ if(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 */
+
+ /* Check inputs to IDA for correctness and consistency */
+ if (IDA_mem->ida_SetupDone == FALSE) {
+ ier = IDAInitialSetup(IDA_mem);
+ if (ier != IDA_SUCCESS) return(ier);
+ IDA_mem->ida_SetupDone = TRUE;
+ }
+
+ /* 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 = ABS(tout - tn);
+ if (tdist == ZERO) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDASolve", MSG_TOO_CLOSE);
+ return(IDA_ILL_INPUT);
+ }
+ troundoff = TWO*uround*(ABS(tn) + ABS(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) ) {
+ 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;
+ }
+
+ rh = ABS(hh)*hmax_inv;
+ if (rh > ONE) hh /= rh;
+
+ if (tstopset) {
+ if ( (tstop - tn)*hh < ZERO) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDASolve", MSG_BAD_TSTOP, tstop, tn);
+ return(IDA_ILL_INPUT);
+ }
+ if ( (tn + hh - tstop)*hh > ZERO)
+ hh = (tstop - tn)*(ONE-FOUR*uround);
+ }
+
+ h0u = hh;
+ kk = 0; 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) {
+ ier = IDARcheck1(IDA_mem);
+ if (ier == IDA_RTFUNC_FAIL) {
+ IDAProcessError(IDA_mem, IDA_RTFUNC_FAIL, "IDAS", "IDARcheck1", MSG_RTFUNC_FAILED, tn);
+ return(IDA_RTFUNC_FAIL);
+ }
+ }
+
+ N_VScale(hh, phi[1], phi[1]); /* set phi[1] = hh*y' */
+
+ if (quadr)
+ N_VScale(hh, phiQ[1], 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 (quadr_sensi)
+ for (is=0; is<Ns; is++)
+ N_VScale(hh, phiQS[1][is], phiQS[1][is]); /* set phiQS[1][i] = hh*yQS_i' */
+
+
+ /* Set the convergence test constants epsNewt and toldel */
+ epsNewt = epcon;
+ toldel = PT0001 * epsNewt;
+
+ } /* end of first-call block. */
+
+ /* Call lperf function and set nstloc for later performance testing. */
+
+ if (lperf != NULL) lperf(IDA_mem, 0);
+ nstloc = 0;
+
+ /* If not the first call, perform all stopping tests. */
+
+ if (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) {
+
+ irfndp = irfnd;
+
+ ier = IDARcheck2(IDA_mem);
+
+ if (ier == CLOSERT) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDARcheck2", MSG_CLOSE_ROOTS, tlo);
+ return(IDA_ILL_INPUT);
+ } else if (ier == IDA_RTFUNC_FAIL) {
+ IDAProcessError(IDA_mem, IDA_RTFUNC_FAIL, "IDAS", "IDARcheck2", MSG_RTFUNC_FAILED, tlo);
+ return(IDA_RTFUNC_FAIL);
+ } else if (ier == RTFOUND) {
+ tretlast = *tret = tlo;
+ return(IDA_ROOT_RETURN);
+ }
+
+ /* If tn is distinct from tretlast (within roundoff),
+ check remaining interval for roots */
+ troundoff = HUNDRED*uround*(ABS(tn) + ABS(hh));
+ if ( ABS(tn - tretlast) > troundoff ) {
+ ier = IDARcheck3(IDA_mem);
+ if (ier == IDA_SUCCESS) { /* no root found */
+ irfnd = 0;
+ if ((irfndp == 1) && (itask == IDA_ONE_STEP)) {
+ tretlast = *tret = tn;
+ ier = IDAGetSolution(IDA_mem, tn, yret, ypret);
+ return(IDA_SUCCESS);
+ }
+ } else if (ier == RTFOUND) { /* a new root was found */
+ irfnd = 1;
+ tretlast = *tret = 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);
+ return(IDA_RTFUNC_FAIL);
+ }
+ }
+
+ } /* end of root stop check */
+
+
+ /* Now test for all other stop conditions. */
+
+ istate = IDAStopTest1(IDA_mem, tout, tret, yret, ypret, itask);
+ if (istate != CONTINUE_STEPS) return(istate);
+ }
+
+ /* Looping point for internal steps. */
+
+ loop {
+
+ /* Check for too many steps taken. */
+
+ if ( (mxstep>0) && (nstloc >= mxstep) ) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDASolve", MSG_MAX_STEPS, tn);
+ istate = IDA_TOO_MUCH_WORK;
+ *tret = tretlast = 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);
+
+ /* Reset and check ewt, ewtQ, ewtS and ewtQS (if not first call). */
+
+ if (nst > 0) {
+
+ ier = efun(phi[0], ewt, 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);
+ istate = IDA_ILL_INPUT;
+ ier = IDAGetSolution(IDA_mem, tn, yret, ypret);
+ *tret = tretlast = tn;
+ break;
+ }
+
+ if (quadr && errconQ) {
+ ier = IDAQuadEwtSet(IDA_mem, phiQ[0], ewtQ);
+ if (ier != 0) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDASolve", MSG_EWTQ_NOW_BAD, tn);
+ istate = IDA_ILL_INPUT;
+ ier = IDAGetSolution(IDA_mem, tn, yret, ypret);
+ *tret = tretlast = tn;
+ break;
+ }
+ }
+
+ if (sensi) {
+ ier = IDASensEwtSet(IDA_mem, phiS[0], ewtS);
+ if (ier != 0) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDASolve", MSG_EWTS_NOW_BAD, tn);
+ istate = IDA_ILL_INPUT;
+ ier = IDAGetSolution(IDA_mem, tn, yret, ypret);
+ *tret = tretlast = tn;
+ break;
+ }
+ }
+
+ if (quadr_sensi && errconQS) {
+ ier = IDAQuadSensEwtSet(IDA_mem, phiQS[0], ewtQS);
+ if (ier != 0) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDASolve", MSG_EWTQS_NOW_BAD, tn);
+ istate = IDA_ILL_INPUT;
+ ier = IDAGetSolution(IDA_mem, tn, yret, ypret);
+ tretlast = *tret = tn;
+ break;
+ }
+ }
+
+ }
+
+ /* 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);
+ istate = IDA_TOO_MUCH_ACC;
+ *tret = tretlast = tn;
+ if (nst > 0) ier = IDAGetSolution(IDA_mem, tn, yret, ypret);
+ break;
+ }
+
+ /* Call IDAStep to take a step. */
+
+ sflag = IDAStep(IDA_mem);
+
+ /* Process all failed-step cases, and exit loop. */
+
+ if (sflag != IDA_SUCCESS) {
+ istate = IDAHandleFailure(IDA_mem, sflag);
+ *tret = tretlast = tn;
+ ier = IDAGetSolution(IDA_mem, tn, yret, ypret);
+ break;
+ }
+
+ nstloc++;
+
+ /* If tstop is set and was reached, reset tn = tstop */
+ if (tstopset) {
+ troundoff = HUNDRED*uround*(ABS(tn) + ABS(hh));
+ if (ABS(tn - tstop) <= troundoff) tn = tstop;
+ }
+
+ /* After successful step, check for stop conditions; continue or break. */
+
+ /* First check for root in the last step taken. */
+
+ if (nrtfn > 0) {
+
+ ier = IDARcheck3(IDA_mem);
+
+ if (ier == RTFOUND) { /* A new root was found */
+ irfnd = 1;
+ istate = IDA_ROOT_RETURN;
+ tretlast = *tret = tlo;
+ break;
+ } else if (ier == IDA_RTFUNC_FAIL) { /* g failed */
+ IDAProcessError(IDA_mem, IDA_RTFUNC_FAIL, "IDAS", "IDARcheck3", MSG_RTFUNC_FAILED, tlo);
+ istate = IDA_RTFUNC_FAIL;
+ break;
+ }
+
+ /* If we are at the end of the first step and we still have
+ * some event functions that are inactive, issue a warning
+ * 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;
+ break;
+ }
+ }
+ if ((IDA_mem->ida_mxgnull > 0) && inactive_roots) {
+ IDAProcessError(IDA_mem, IDA_WARNING, "IDAS", "IDASolve", MSG_INACTIVE_ROOTS);
+ }
+ }
+
+ }
+
+ /* Now check all other stop conditions. */
+
+ istate = IDAStopTest2(IDA_mem, tout, tret, yret, ypret, itask);
+ if (istate != CONTINUE_STEPS) break;
+
+ } /* End of step loop */
+
+ return(istate);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Interpolated output and extraction functions
+ * -----------------------------------------------------------------
+ */
+
+
+
+/*
+ * IDAGetDky
+ *
+ * This routine evaluates the k-th derivative of y(t) as the value of
+ * the k-th derivative of the interpolating polynomial at the independent
+ * variable t, and stores the results in the vector dky. It uses the current
+ * independent variable value, tn, and the method order last used, kused.
+ *
+ * The return values are:
+ * IDA_SUCCESS if t is legal, or
+ * IDA_BAD_T if t is not within the interval of the last step taken.
+ * IDA_BAD_DKY if the dky vector is NULL.
+ * IDA_BAD_K if the requested k is not in the range 0,1,...,order used
+ *
+ */
+
+int IDAGetDky(void *ida_mem, realtype t, int k, N_Vector dky)
+{
+ IDAMem IDA_mem;
+ realtype tfuzz, tp, delt, psij_1;
+ int i, j;
+ realtype cjk [MXORDP1];
+ realtype cjk_1[MXORDP1];
+
+ /* Check ida_mem */
+ if (ida_mem == NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDAGetDky", MSG_NO_MEM);
+ return (IDA_MEM_NULL);
+ }
+ IDA_mem = (IDAMem) ida_mem;
+
+ if (dky == NULL) {
+ IDAProcessError(IDA_mem, IDA_BAD_DKY, "IDAS", "IDAGetDky", MSG_NULL_DKY);
+ return(IDA_BAD_DKY);
+ }
+
+ if ((k < 0) || (k > 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 * (ABS(tn) + ABS(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);
+ return(IDA_BAD_T);
+ }
+
+ /* Initialize the c_j^(k) and c_k^(k-1) */
+ for(i=0; i<MXORDP1; i++) {
+ cjk [i] = 0;
+ cjk_1[i] = 0;
+ }
+
+ delt = t-tn;
+
+ for(i=0; i<=k; i++) {
+
+ /* The below reccurence is used to compute the k-th derivative of the solution:
+ c_j^(k) = ( k * c_{j-1}^(k-1) + c_{j-1}^{k} (Delta+psi_{j-1}) ) / psi_j
+
+ Translated in indexes notation:
+ cjk[j] = ( k*cjk_1[j-1] + cjk[j-1]*(delt+psi[j-2]) ) / psi[j-1]
+
+ For k=0, j=1: c_1 = c_0^(-1) + (delt+psi[-1]) / psi[0]
+
+ In order to be able to deal with k=0 in the same way as for k>0, the
+ following conventions were adopted:
+ - c_0(t) = 1 , c_0^(-1)(t)=0
+ - psij_1 stands for psi[-1]=0 when j=1
+ for psi[j-2] when j>1
+ */
+ if(i==0) {
+
+ cjk[i] = 1;
+ psij_1 = 0;
+ }else {
+ /* i i-1 1
+ 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];
+ }
+
+ /* update c_j^(i) */
+
+ /*j does not need to go till kused */
+ 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];
+ }
+
+ /* save existing c_j^(i)'s */
+ for(j=i+1; j<=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++)
+ {
+ N_VLinearSum(ONE, dky, cjk[j], phi[j], dky);
+ }
+
+ return(IDA_SUCCESS);
+}
+
+/*
+ * IDAGetQuad
+ *
+ * The following function can be called to obtain the quadrature
+ * variables after a successful integration step.
+ *
+ * This is just a wrapper that calls IDAGetQuadDky with k=0.
+ */
+
+int IDAGetQuad(void *ida_mem, realtype *ptret, N_Vector yQout)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem == NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDAGetQuad", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+ IDA_mem = (IDAMem)ida_mem;
+
+ *ptret = tretlast;
+
+ return IDAGetQuadDky(ida_mem, tretlast, 0, yQout);
+}
+
+/*
+ * IDAGetQuadDky
+ *
+ * Returns the quadrature variables (or their
+ * derivatives up to the current method order) at any time within
+ * the last integration step (dense output).
+ */
+int IDAGetQuadDky(void *ida_mem, realtype t, int k, N_Vector dkyQ)
+{
+ IDAMem IDA_mem;
+ realtype tfuzz, tp, delt, psij_1;
+ int i, j;
+ realtype cjk [MXORDP1];
+ realtype cjk_1[MXORDP1];
+
+ /* Check ida_mem */
+ if (ida_mem == NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDAGetQuadDky", MSG_NO_MEM);
+ return (IDA_MEM_NULL);
+ }
+ IDA_mem = (IDAMem) ida_mem;
+
+ /* Ckeck if quadrature was initialized */
+ if (quadr != TRUE) {
+ IDAProcessError(IDA_mem, IDA_NO_QUAD, "IDAS", "IDAGetQuadDky", MSG_NO_QUAD);
+ return(IDA_NO_QUAD);
+ }
+
+ if (dkyQ == NULL) {
+ IDAProcessError(IDA_mem, IDA_BAD_DKY, "IDAS", "IDAGetQuadDky", MSG_NULL_DKY);
+ return(IDA_BAD_DKY);
+ }
+
+ if ((k < 0) || (k > 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);
+ return(IDA_BAD_T);
+ }
+
+ /* Initialize the c_j^(k) and c_k^(k-1) */
+ for(i=0; i<MXORDP1; i++) {
+ cjk [i] = 0;
+ cjk_1[i] = 0;
+ }
+ delt = t-tn;
+
+ for(i=0; i<=k; i++) {
+
+ if(i==0) {
+ cjk[i] = 1;
+ psij_1 = 0;
+ }else {
+ cjk[i] = cjk[i-1]*i/psi[i-1];
+ psij_1 = psi[i-1];
+ }
+
+ /* update c_j^(i) */
+ 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];
+ }
+
+ /* save existing c_j^(i)'s */
+ for(j=i+1; j<=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++)
+ {
+ N_VLinearSum(ONE, dkyQ, cjk[j], phiQ[j], dkyQ);
+ }
+
+ return(IDA_SUCCESS);
+}
+
+
+/*
+ * IDAGetSens
+ *
+ * This routine extracts sensitivity solution into yySout at the
+ * time at which IDASolve returned the solution.
+ * This is just a wrapper that calls IDAGetSensDky1 with k=0 and
+ * is=0, 1, ... ,NS-1.
+ */
+
+int IDAGetSens(void *ida_mem, realtype *ptret, N_Vector *yySout)
+{
+ IDAMem IDA_mem;
+ int is, ierr;
+
+ /* Check ida_mem */
+ if (ida_mem == NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDAGetSens", MSG_NO_MEM);
+ return (IDA_MEM_NULL);
+ }
+ IDA_mem = (IDAMem) ida_mem;
+
+ /*Check the parameters */
+ if (yySout == NULL) {
+ IDAProcessError(IDA_mem, IDA_BAD_DKY, "IDAS", "IDAGetSens", MSG_NULL_DKY);
+ return(IDA_BAD_DKY);
+ }
+
+ /* Is the sensibility enabled? */
+ if (sensi==FALSE) {
+ IDAProcessError(IDA_mem, IDA_NO_SENS, "IDAS", "IDAGetSens", MSG_NO_SENSI);
+ return(IDA_NO_SENS);
+ }
+
+ *ptret = tretlast;
+
+ for(is=0; is<Ns; is++)
+ if( IDA_SUCCESS != (ierr = IDAGetSensDky1(ida_mem, *ptret, 0, is, yySout[is])) ) break;
+
+ return(ierr);
+}
+
+/*
+ * IDAGetSensDky
+ *
+ * Computes the k-th derivative of all sensitivities of the y function at
+ * time t. It repeatedly calls IDAGetSensDky. The argument dkyS must be
+ * a pointer to N_Vector and must be allocated by the user to hold at
+ * least Ns vectors.
+ */
+int IDAGetSensDky(void *ida_mem, realtype t, int k, N_Vector *dkySout)
+{
+ int is, ier;
+ IDAMem IDA_mem;
+
+ /* Check all inputs for legality */
+
+ if (ida_mem == NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDAGetSensDky", MSG_NO_MEM);
+ return (IDA_MEM_NULL);
+ }
+ IDA_mem = (IDAMem) ida_mem;
+
+ if (sensi==FALSE) {
+ IDAProcessError(IDA_mem, IDA_NO_SENS, "IDAS", "IDAGetSensDky", MSG_NO_SENSI);
+ return(IDA_NO_SENS);
+ }
+
+ if (dkySout == NULL) {
+ IDAProcessError(IDA_mem, IDA_BAD_DKY, "IDAS", "IDAGetSensDky", MSG_NULL_DKY);
+ return(IDA_BAD_DKY);
+ }
+
+ if ((k < 0) || (k > kk)) {
+ IDAProcessError(IDA_mem, IDA_BAD_K, "IDAS", "IDAGetSensDky", MSG_BAD_K);
+ return(IDA_BAD_K);
+ }
+
+ for (is=0; is<Ns; is++) {
+ ier = IDAGetSensDky1(ida_mem, t, k, is, dkySout[is]);
+ if (ier!=IDA_SUCCESS) break;
+ }
+
+ return(ier);
+}
+
+
+/*
+ * IDAGetSens1
+ *
+ * This routine extracts the is-th sensitivity solution into ySout
+ * at the time at which IDASolve returned the solution.
+ * This is just a wrapper that calls IDASensDky1 with k=0.
+ */
+
+int IDAGetSens1(void *ida_mem, realtype *ptret, int is, N_Vector yySret)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem == NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDAGetSens1", MSG_NO_MEM);
+ return (IDA_MEM_NULL);
+ }
+ IDA_mem = (IDAMem) ida_mem;
+
+ *ptret = tretlast;
+
+ return IDAGetSensDky1(ida_mem, *ptret, 0, is, yySret);
+}
+
+/*
+ * IDAGetSensDky1
+ *
+ * IDASensDky1 computes the kth derivative of the yS[is] function
+ * at time t, where tn-hu <= t <= tn, tn denotes the current
+ * internal time reached, and hu is the last internal step size
+ * successfully used by the solver. The user may request
+ * is=0, 1, ..., Ns-1 and k=0, 1, ..., kk, where kk is the current
+ * order. The derivative vector is returned in dky. This vector
+ * must be allocated by the caller. It is only legal to call this
+ * function after a successful return from IDASolve with sensitivity
+ * computation enabled.
+ */
+int IDAGetSensDky1(void *ida_mem, realtype t, int k, int is, N_Vector dkyS)
+{
+ IDAMem IDA_mem;
+ realtype tfuzz, tp, delt, psij_1;
+ int i, j;
+ realtype cjk [MXORDP1];
+ realtype cjk_1[MXORDP1];
+
+ /* Check all inputs for legality */
+ if (ida_mem == NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDAGetSensDky1", MSG_NO_MEM);
+ return (IDA_MEM_NULL);
+ }
+ IDA_mem = (IDAMem) ida_mem;
+
+ if (sensi==FALSE) {
+ IDAProcessError(IDA_mem, IDA_NO_SENS, "IDAS", "IDAGetSensDky1", MSG_NO_SENSI);
+ return(IDA_NO_SENS);
+ }
+
+ if (dkyS == NULL) {
+ IDAProcessError(IDA_mem, IDA_BAD_DKY, "IDAS", "IDAGetSensDky1", MSG_NULL_DKY);
+ return(IDA_BAD_DKY);
+ }
+
+ /* Is the requested sensitivity index valid? */
+ if(is<0 || is >= Ns) {
+ IDAProcessError(IDA_mem, IDA_BAD_IS, "IDAS", "IDAGetSensDky1", MSG_BAD_IS);
+ }
+
+ /* Is the requested order valid? */
+ if ((k < 0) || (k > 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 * (ABS(tn) + ABS(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);
+ return(IDA_BAD_T);
+ }
+
+ /* Initialize the c_j^(k) and c_k^(k-1) */
+ for(i=0; i<MXORDP1; i++) {
+ cjk [i] = 0;
+ cjk_1[i] = 0;
+ }
+
+ delt = t - tn;
+
+ for(i=0; i<=k; i++) {
+
+ if(i==0) {
+ cjk[i] = 1;
+ psij_1 = 0;
+ }else {
+ cjk[i] = cjk[i-1]*i/psi[i-1];
+ psij_1 = 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];
+ }
+
+ /* Update cjk_1 for the next step */
+ for(j=i+1; j<=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++)
+ {
+ N_VLinearSum(ONE, dkyS, cjk[j], phiS[j][is], dkyS);
+ }
+
+ return(IDA_SUCCESS);
+}
+
+/*
+ * IDAGetQuadSens
+ *
+ * This routine extracts quadrature sensitivity solution into yyQSout at the
+ * time at which IDASolve returned the solution.
+ * This is just a wrapper that calls IDAGetQuadSensDky1 with k=0 and
+ * is=0, 1, ... ,NS-1.
+ */
+
+int IDAGetQuadSens(void *ida_mem, realtype *ptret, N_Vector *yyQSout)
+{
+ IDAMem IDA_mem;
+ int is, ierr;
+
+ /* Check ida_mem */
+ if (ida_mem == NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDAGetQuadSens", MSG_NO_MEM);
+ return (IDA_MEM_NULL);
+ }
+ IDA_mem = (IDAMem) ida_mem;
+
+ /*Check the parameters */
+ if (yyQSout == NULL) {
+ IDAProcessError(IDA_mem, IDA_BAD_DKY, "IDAS", "IDAGetQuadSens", MSG_NULL_DKY);
+ return(IDA_BAD_DKY);
+ }
+
+ /* Is the sensibility enabled? */
+ if (quadr_sensi==FALSE) {
+ IDAProcessError(IDA_mem, IDA_NO_SENS, "IDAS", "IDAGetQuadSens", MSG_NO_QUADSENSI);
+ return(IDA_NO_SENS);
+ }
+
+ *ptret = tretlast;
+
+ for(is=0; is<Ns; is++)
+ if( IDA_SUCCESS != (ierr = IDAGetQuadSensDky1(ida_mem, *ptret, 0, is, yyQSout[is])) ) break;
+
+ return(ierr);
+}
+
+/*
+ * IDAGetQuadSensDky
+ *
+ * Computes the k-th derivative of all quadratures sensitivities of the y function at
+ * time t. It repeatedly calls IDAGetQuadSensDky. The argument dkyS must be
+ * a pointer to N_Vector and must be allocated by the user to hold at
+ * least Ns vectors.
+ */
+int IDAGetQuadSensDky(void *ida_mem, realtype t, int k, N_Vector *dkyQSout)
+{
+ int is, ier;
+ IDAMem IDA_mem;
+
+ /* Check all inputs for legality */
+
+ if (ida_mem == NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDAGetQuadSensDky", MSG_NO_MEM);
+ return (IDA_MEM_NULL);
+ }
+ IDA_mem = (IDAMem) ida_mem;
+
+ if (sensi==FALSE) {
+ IDAProcessError(IDA_mem, IDA_NO_SENS, "IDAS", "IDAGetQuadSensDky", MSG_NO_SENSI);
+ return(IDA_NO_SENS);
+ }
+
+ if (quadr_sensi==FALSE) {
+ IDAProcessError(IDA_mem, IDA_NO_QUADSENS, "IDAS", "IDAGetQuadSensDky", MSG_NO_QUADSENSI);
+ return(IDA_NO_QUADSENS);
+ }
+
+ if (dkyQSout == NULL) {
+ IDAProcessError(IDA_mem, IDA_BAD_DKY, "IDAS", "IDAGetQuadSensDky", MSG_NULL_DKY);
+ return(IDA_BAD_DKY);
+ }
+
+ if ((k < 0) || (k > kk)) {
+ IDAProcessError(IDA_mem, IDA_BAD_K, "IDAS", "IDAGetQuadSensDky", MSG_BAD_K);
+ return(IDA_BAD_K);
+ }
+
+ for (is=0; is<Ns; is++) {
+ ier = IDAGetQuadSensDky1(ida_mem, t, k, is, dkyQSout[is]);
+ if (ier!=IDA_SUCCESS) break;
+ }
+
+ return(ier);
+}
+
+
+/*
+ * IDAGetQuadSens1
+ *
+ * This routine extracts the is-th quadrature sensitivity solution into yQSout
+ * at the time at which IDASolve returned the solution.
+ * This is just a wrapper that calls IDASensDky1 with k=0.
+ */
+
+int IDAGetQuadSens1(void *ida_mem, realtype *ptret, int is, N_Vector yyQSret)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem == NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDAGetQuadSens1", MSG_NO_MEM);
+ return (IDA_MEM_NULL);
+ }
+ IDA_mem = (IDAMem) ida_mem;
+
+ if (sensi==FALSE) {
+ IDAProcessError(IDA_mem, IDA_NO_SENS, "IDAS", "IDAGetQuadSens1", MSG_NO_SENSI);
+ return(IDA_NO_SENS);
+ }
+
+ if (quadr_sensi==FALSE) {
+ IDAProcessError(IDA_mem, IDA_NO_QUADSENS, "IDAS", "IDAGetQuadSens1", MSG_NO_QUADSENSI);
+ return(IDA_NO_QUADSENS);
+ }
+
+ if (yyQSret == NULL) {
+ IDAProcessError(IDA_mem, IDA_BAD_DKY, "IDAS", "IDAGetQuadSens1", MSG_NULL_DKY);
+ return(IDA_BAD_DKY);
+ }
+
+ *ptret = tretlast;
+
+ return IDAGetQuadSensDky1(ida_mem, *ptret, 0, is, yyQSret);
+}
+
+/*
+ * IDAGetQuadSensDky1
+ *
+ * IDAGetQuadSensDky1 computes the kth derivative of the yS[is] function
+ * at time t, where tn-hu <= t <= tn, tn denotes the current
+ * internal time reached, and hu is the last internal step size
+ * successfully used by the solver. The user may request
+ * is=0, 1, ..., Ns-1 and k=0, 1, ..., kk, where kk is the current
+ * order. The derivative vector is returned in dky. This vector
+ * must be allocated by the caller. It is only legal to call this
+ * function after a successful return from IDASolve with sensitivity
+ * computation enabled.
+ */
+int IDAGetQuadSensDky1(void *ida_mem, realtype t, int k, int is, N_Vector dkyQS)
+{
+ IDAMem IDA_mem;
+ realtype tfuzz, tp, delt, psij_1;
+ int i, j;
+ realtype cjk [MXORDP1];
+ realtype cjk_1[MXORDP1];
+
+ /* Check all inputs for legality */
+ if (ida_mem == NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDAGetQuadSensDky1", MSG_NO_MEM);
+ return (IDA_MEM_NULL);
+ }
+ IDA_mem = (IDAMem) ida_mem;
+
+ if (sensi==FALSE) {
+ IDAProcessError(IDA_mem, IDA_NO_SENS, "IDAS", "IDAGetQuadSensDky1", MSG_NO_SENSI);
+ return(IDA_NO_SENS);
+ }
+
+ if (quadr_sensi==FALSE) {
+ IDAProcessError(IDA_mem, IDA_NO_QUADSENS, "IDAS", "IDAGetQuadSensDky1", MSG_NO_QUADSENSI);
+ return(IDA_NO_QUADSENS);
+ }
+
+
+ if (dkyQS == NULL) {
+ IDAProcessError(IDA_mem, IDA_BAD_DKY, "IDAS", "IDAGetQuadSensDky1", MSG_NULL_DKY);
+ return(IDA_BAD_DKY);
+ }
+
+ /* Is the requested sensitivity index valid*/
+ if(is<0 || is >= Ns) {
+ IDAProcessError(IDA_mem, IDA_BAD_IS, "IDAS", "IDAGetQuadSensDky1", MSG_BAD_IS);
+ }
+
+ /* Is the requested order valid? */
+ if ((k < 0) || (k > 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 * (ABS(tn) + ABS(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);
+ return(IDA_BAD_T);
+ }
+
+ /* Initialize the c_j^(k) and c_k^(k-1) */
+ for(i=0; i<MXORDP1; i++) {
+ cjk [i] = 0;
+ cjk_1[i] = 0;
+ }
+
+ delt = t - tn;
+
+ for(i=0; i<=k; i++) {
+
+ if(i==0) {
+ cjk[i] = 1;
+ psij_1 = 0;
+ }else {
+ cjk[i] = cjk[i-1]*i/psi[i-1];
+ psij_1 = 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];
+ }
+
+ /* Update cjk_1 for the next step */
+ for(j=i+1; j<=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++)
+ {
+ N_VLinearSum(ONE, dkyQS, cjk[j], phiQS[j][is], dkyQS);
+ }
+
+ return(IDA_SUCCESS);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Deallocation functions
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * IDAFree
+ *
+ * This routine frees the problem memory allocated by IDAInit
+ * Such memory includes all the vectors allocated by IDAAllocVectors,
+ * and the memory lmem for the linear solver (deallocated by a call
+ * to lfree).
+ */
+
+void IDAFree(void **ida_mem)
+{
+ IDAMem IDA_mem;
+
+ if (*ida_mem == NULL) return;
+
+ IDA_mem = (IDAMem) (*ida_mem);
+
+ IDAFreeVectors(IDA_mem);
+
+ IDAQuadFree(IDA_mem);
+
+ IDASensFree(IDA_mem);
+
+ IDAQuadSensFree(IDA_mem);
+
+ IDAAdjFree(IDA_mem);
+
+ if (lfree != NULL) 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;
+ }
+
+ free(*ida_mem);
+ *ida_mem = NULL;
+}
+
+/*
+ * IDAQuadFree
+ *
+ * IDAQuadFree frees the problem memory in ida_mem allocated
+ * for quadrature integration. Its only argument is the pointer
+ * ida_mem returned by IDACreate.
+ */
+
+void IDAQuadFree(void *ida_mem)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem == NULL) return;
+ IDA_mem = (IDAMem) ida_mem;
+
+ if(quadMallocDone) {
+ IDAQuadFreeVectors(IDA_mem);
+ quadMallocDone = FALSE;
+ quadr = FALSE;
+ }
+}
+
+/*
+ * IDASensFree
+ *
+ * IDASensFree frees the problem memory in ida_mem allocated
+ * for sensitivity analysis. Its only argument is the pointer
+ * ida_mem returned by IDACreate.
+ */
+
+void IDASensFree(void *ida_mem)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem == NULL) return;
+ IDA_mem = (IDAMem) ida_mem;
+
+ if(sensMallocDone) {
+ IDASensFreeVectors(IDA_mem);
+ sensMallocDone = FALSE;
+ sensi = FALSE;
+ }
+}
+
+/*
+ * IDAQuadSensFree
+ *
+ * IDAQuadSensFree frees the problem memory in ida_mem allocated
+ * for quadrature sensitivity analysis. Its only argument is the
+ * pointer ida_mem returned by IDACreate.
+ */
+void IDAQuadSensFree(void* ida_mem)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) return;
+ IDA_mem = (IDAMem) ida_mem;
+
+ if (quadSensMallocDone) {
+ IDAQuadSensFreeVectors(IDA_mem);
+ quadSensMallocDone=FALSE;
+ quadr_sensi = FALSE;
+ }
+}
+
+/*
+ * =================================================================
+ * PRIVATE FUNCTIONS
+ * =================================================================
+ */
+
+/*
+ * IDACheckNvector
+ *
+ * This routine checks if all required vector operations are present.
+ * If any of them is missing it returns FALSE.
+ */
+
+static booleantype IDACheckNvector(N_Vector tmpl)
+{
+ if ((tmpl->ops->nvclone == NULL) ||
+ (tmpl->ops->nvdestroy == NULL) ||
+ (tmpl->ops->nvlinearsum == NULL) ||
+ (tmpl->ops->nvconst == NULL) ||
+ (tmpl->ops->nvprod == NULL) ||
+ (tmpl->ops->nvscale == NULL) ||
+ (tmpl->ops->nvabs == NULL) ||
+ (tmpl->ops->nvinv == NULL) ||
+ (tmpl->ops->nvaddconst == NULL) ||
+ (tmpl->ops->nvwrmsnorm == NULL) ||
+ (tmpl->ops->nvmin == NULL))
+ return(FALSE);
+ else
+ return(TRUE);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Memory allocation/deallocation
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * IDAAllocVectors
+ *
+ * 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.
+ * This routine also sets the optional outputs lrw and liw, which are
+ * (respectively) the lengths of the real and integer work spaces
+ * allocated here.
+ */
+
+static booleantype IDAAllocVectors(IDAMem IDA_mem, N_Vector tmpl)
+{
+ int i, j, maxcol;
+
+ /* Allocate ewt, ee, delta, tempv1, tempv2 */
+
+ ewt = N_VClone(tmpl);
+ if (ewt == NULL) return(FALSE);
+
+ ee = N_VClone(tmpl);
+ if (ee == NULL) {
+ N_VDestroy(ewt);
+ return(FALSE);
+ }
+
+ delta = N_VClone(tmpl);
+ if (delta == NULL) {
+ N_VDestroy(ewt);
+ N_VDestroy(ee);
+ return(FALSE);
+ }
+
+ tempv1 = N_VClone(tmpl);
+ if (tempv1 == NULL) {
+ N_VDestroy(ewt);
+ N_VDestroy(ee);
+ N_VDestroy(delta);
+ return(FALSE);
+ }
+
+ tempv2= N_VClone(tmpl);
+ if (tempv2 == NULL) {
+ N_VDestroy(ewt);
+ N_VDestroy(ee);
+ N_VDestroy(delta);
+ N_VDestroy(tempv1);
+ return(FALSE);
+ }
+
+ savres = tempv1;
+
+ /* Allocate phi[0] ... phi[maxord]. Make sure phi[2] and phi[3] are
+ allocated (for use as temporary vectors), regardless of maxord. */
+
+ maxcol = MAX(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);
+ }
+ }
+
+ /* Update solver workspace lengths */
+ lrw += (maxcol + 6)*lrw1;
+ liw += (maxcol + 6)*liw1;
+
+ /* Store the value of maxord used here */
+ IDA_mem->ida_maxord_alloc = maxord;
+
+ return(TRUE);
+}
+
+/*
+ * IDAfreeVectors
+ *
+ * This routine frees the IDA vectors allocated for IDA.
+ */
+
+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;
+ maxcol = MAX(IDA_mem->ida_maxord_alloc,3);
+ for(j=0; j <= maxcol; j++) { N_VDestroy(phi[j]); phi[j] = NULL;}
+
+ lrw -= (maxcol + 6)*lrw1;
+ liw -= (maxcol + 6)*liw1;
+
+ if (IDA_mem->ida_VatolMallocDone) {
+ N_VDestroy(Vatol); Vatol = NULL;
+ lrw -= lrw1;
+ liw -= liw1;
+ }
+
+ if (IDA_mem->ida_constraintsMallocDone) {
+ N_VDestroy(constraints); constraints = NULL;
+ lrw -= lrw1;
+ liw -= liw1;
+ }
+
+ if (IDA_mem->ida_idMallocDone) {
+ N_VDestroy(id); id = NULL;
+ lrw -= lrw1;
+ liw -= liw1;
+ }
+
+}
+
+/*
+ * IDAQuadAllocVectors
+ *
+ * NOTE: Space for ewtQ is allocated even when errconQ=FALSE,
+ * 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
+ * IDAQuadReInit.
+ */
+
+static booleantype IDAQuadAllocVectors(IDAMem IDA_mem, N_Vector tmpl)
+{
+ int i, j;
+
+ /* Allocate yyQ */
+ yyQ = N_VClone(tmpl);
+ if (yyQ == NULL) {
+ return (FALSE);
+ }
+
+ /* Allocate ypQ */
+ ypQ = N_VClone(tmpl);
+ if (ypQ == NULL) {
+ N_VDestroy(yyQ);
+ return (FALSE);
+ }
+
+ /* Allocate ewtQ */
+ ewtQ = N_VClone(tmpl);
+ if (ewtQ == NULL) {
+ N_VDestroy(yyQ);
+ N_VDestroy(ypQ);
+ return (FALSE);
+ }
+
+ /* 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);
+ }
+ }
+
+ lrw += (maxord+4)*lrw1Q;
+ liw += (maxord+4)*liw1Q;
+
+ return(TRUE);
+}
+
+
+
+/*
+ * IDAQuadFreeVectors
+ *
+ * This routine frees the IDAS vectors allocated in IDAQuadAllocVectors.
+ */
+
+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;}
+
+ lrw -= (maxord+5)*lrw1Q;
+ liw -= (maxord+5)*liw1Q;
+
+ if (IDA_mem->ida_VatolQMallocDone) {
+ N_VDestroy(VatolQ); VatolQ = NULL;
+ lrw -= lrw1Q;
+ liw -= liw1Q;
+ }
+
+ IDA_mem->ida_VatolQMallocDone = FALSE;
+}
+
+/*
+ * IDASensAllocVectors
+ *
+ * Allocates space for the N_Vectors, plist, and pbar required for FSA.
+ */
+
+static booleantype IDASensAllocVectors(IDAMem IDA_mem, N_Vector tmpl)
+{
+ int j, maxcol;
+
+ tmpS1 = tempv1;
+ tmpS2 = tempv2;
+
+ /* Allocate space for workspace vectors */
+
+ tmpS3 = N_VClone(tmpl);
+ if (tmpS3==NULL) {
+ return(FALSE);
+ }
+
+ ewtS = N_VCloneVectorArray(Ns, tmpl);
+ if (ewtS==NULL) {
+ N_VDestroy(tmpS3);
+ return(FALSE);
+ }
+
+ eeS = N_VCloneVectorArray(Ns, tmpl);
+ if (eeS==NULL) {
+ N_VDestroy(tmpS3);
+ N_VDestroyVectorArray(ewtS, Ns);
+ return(FALSE);
+ }
+
+ yyS = N_VCloneVectorArray(Ns, tmpl);
+ if (yyS==NULL) {
+ N_VDestroyVectorArray(eeS, Ns);
+ N_VDestroyVectorArray(ewtS, Ns);
+ N_VDestroy(tmpS3);
+ return(FALSE);
+ }
+
+ 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);
+ }
+
+ 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);
+ }
+
+ /* Update solver workspace lengths */
+ lrw += (3*Ns+1)*lrw1;
+ liw += (3*Ns+1)*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 = MAX(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);
+ }
+ }
+
+ /* Update solver workspace lengths */
+ lrw += maxcol*Ns*lrw1;
+ liw += maxcol*Ns*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);
+ }
+
+ /* Update solver workspace lengths */
+ lrw += Ns;
+ liw += Ns;
+
+ return(TRUE);
+}
+
+/*
+ * IDASensFreeVectors
+ *
+ * Frees memory allocated by IDASensAllocVectors.
+ */
+
+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);
+
+ maxcol = MAX(IDA_mem->ida_maxord_alloc, 4);
+ for (j=0; j<=maxcol; j++)
+ N_VDestroyVectorArray(phiS[j], Ns);
+
+ free(pbar); pbar = NULL;
+ free(plist); plist = NULL;
+
+ lrw -= ( (maxcol+3)*Ns + 1 ) * lrw1 + Ns;
+ liw -= ( (maxcol+3)*Ns + 1 ) * liw1 + Ns;
+
+ if (IDA_mem->ida_VatolSMallocDone) {
+ N_VDestroyVectorArray(VatolS, Ns);
+ lrw -= Ns*lrw1;
+ liw -= Ns*liw1;
+ IDA_mem->ida_VatolSMallocDone = FALSE;
+ }
+ if (IDA_mem->ida_SatolSMallocDone) {
+ free(SatolS); SatolS = NULL;
+ lrw -= Ns;
+ IDA_mem->ida_SatolSMallocDone = FALSE;
+ }
+
+}
+
+
+/*
+ * IDAQuadSensAllocVectors
+ *
+ * Create (through duplication) N_Vectors used for quadrature sensitivity analysis,
+ * using the N_Vector 'tmpl' as a template.
+ */
+
+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);
+ }
+
+ /* Allocate ewtQS */
+ ewtQS = N_VCloneVectorArray(Ns, tmpl);
+ if (ewtQS == NULL) {
+ N_VDestroyVectorArray(yyQS, Ns);
+ return(FALSE);
+ }
+
+ /* Allocate tempvQS */
+ tempvQS = N_VCloneVectorArray(Ns, tmpl);
+ if (tempvQS == NULL) {
+ N_VDestroyVectorArray(yyQS, Ns);
+ N_VDestroyVectorArray(ewtQS, Ns);
+ return(FALSE);
+ }
+
+ eeQS = N_VCloneVectorArray(Ns, tmpl);
+ if (eeQS == NULL) {
+ N_VDestroyVectorArray(yyQS, Ns);
+ N_VDestroyVectorArray(ewtQS, Ns);
+ N_VDestroyVectorArray(tempvQS, Ns);
+ return(FALSE);
+ }
+
+ savrhsQ = N_VClone(tmpl);
+ if (savrhsQ == NULL) {
+ N_VDestroyVectorArray(yyQS, Ns);
+ N_VDestroyVectorArray(ewtQS, Ns);
+ N_VDestroyVectorArray(tempvQS, Ns);
+ N_VDestroyVectorArray(eeQS, Ns);
+ }
+
+ maxcol = MAX(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);
+ }
+ }
+
+ /* Update solver workspace lengths */
+ lrw += (maxcol + 5)*Ns*lrw1Q;
+ liw += (maxcol + 5)*Ns*liw1Q;
+
+ return(TRUE);
+}
+
+
+/*
+ * IDAQuadSensFreeVectors
+ *
+ * This routine frees the IDAS vectors allocated in IDAQuadSensAllocVectors.
+ */
+
+static void IDAQuadSensFreeVectors(IDAMem IDA_mem)
+{
+ int j, maxcol;
+
+ maxcol = MAX(maxord, 4);
+
+ N_VDestroyVectorArray(yyQS, Ns);
+ N_VDestroyVectorArray(ewtQS, Ns);
+ N_VDestroyVectorArray(eeQS, Ns);
+ N_VDestroyVectorArray(tempvQS, Ns);
+ N_VDestroy(savrhsQ);
+
+ for (j=0; j<=maxcol; j++) N_VDestroyVectorArray(phiQS[j], Ns);
+
+ lrw -= (maxcol + 5)*Ns*lrw1Q;
+ liw -= (maxcol + 5)*Ns*liw1Q;
+
+ if (IDA_mem->ida_VatolQSMallocDone) {
+ N_VDestroyVectorArray(VatolQS, Ns);
+ lrw -= Ns*lrw1Q;
+ liw -= Ns*liw1Q;
+ }
+ if (IDA_mem->ida_SatolQSMallocDone) {
+ free(SatolQS); SatolQS = NULL;
+ lrw -= Ns;
+ }
+ IDA_mem->ida_VatolQSMallocDone = FALSE;
+ IDA_mem->ida_SatolQSMallocDone = FALSE;
+}
+
+
+/*
+ * -----------------------------------------------------------------
+ * Initial setup
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * IDAInitialSetup
+ *
+ * This routine is called by IDASolve once at the first step.
+ * It performs all checks on optional inputs and inputs to
+ * IDAInit/IDAReInit that could not be done before.
+ *
+ * If no merror is encountered, IDAInitialSetup returns IDA_SUCCESS.
+ * Otherwise, it returns an error flag and reported to the error
+ * handler function.
+ */
+
+int IDAInitialSetup(IDAMem IDA_mem)
+{
+ booleantype conOK;
+ int ier, retval;
+
+ /* Test for more vector operations, depending on options */
+ if (suppressalg)
+ if (id->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)){
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDAInitialSetup", MSG_MISSING_ID);
+ return(IDA_ILL_INPUT);
+ }
+
+ /* Did the user specify tolerances? */
+ if (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;
+
+ /* Initial error weight vectors */
+ ier = efun(phi[0], ewt, edata);
+ if (ier != 0) {
+ if (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) {
+
+ /* Evaluate quadrature rhs and set phiQ[1] */
+ retval = rhsQ(tn, phi[0], phi[1], phiQ[1], user_data);
+ nrQe++;
+ if (retval < 0) {
+ IDAProcessError(IDA_mem, IDA_QRHS_FAIL, "IDAS", "IDAInitialSetup", MSG_QRHSFUNC_FAILED);
+ return(IDA_QRHS_FAIL);
+ } else if (retval > 0) {
+ IDAProcessError(IDA_mem, IDA_FIRST_QRHS_ERR, "IDAS", "IDAInitialSetup", MSG_QRHSFUNC_FIRST);
+ return(IDA_FIRST_QRHS_ERR);
+ }
+
+ if (errconQ) {
+
+ /* Did the user specify tolerances? */
+ if (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);
+ if (ier != 0) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDAInitialSetup", MSG_BAD_EWTQ);
+ return(IDA_ILL_INPUT);
+ }
+ }
+ } else {
+ errconQ = FALSE;
+ }
+
+ if (sensi) {
+
+ /* Did the user specify tolerances? */
+ if (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);
+ if (ier != 0) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDAInitialSetup", MSG_BAD_EWTS);
+ return(IDA_ILL_INPUT);
+ }
+ } else {
+ errconS = FALSE;
+ }
+
+ if (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++;
+ if (retval < 0) {
+ IDAProcessError(IDA_mem, IDA_QSRHS_FAIL, "IDAS", "IDAInitialSetup", MSG_QSRHSFUNC_FAILED);
+ return(IDA_QRHS_FAIL);
+ } else if (retval > 0) {
+ IDAProcessError(IDA_mem, IDA_FIRST_QSRHS_ERR, "IDAS", "IDAInitialSetup", MSG_QSRHSFUNC_FIRST);
+ return(IDA_FIRST_QSRHS_ERR);
+ }
+
+ /* 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) {
+
+ /* Test if quadratures are defined, so we can use fQ */
+ if (!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) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDAInitialSetup", MSG_NULL_P);
+ return(IDA_ILL_INPUT);
+ }
+ }
+
+ if (errconQS) {
+ /* Did the user specify tolerances? */
+ if (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) ) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDAInitialSetup", MSG_NO_TOLQ);
+ return(IDA_ILL_INPUT);
+ }
+
+ /* Load ewtS */
+ ier = IDAQuadSensEwtSet(IDA_mem, phiQS[0], ewtQS);
+ if (ier != 0) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDAInitialSetup", MSG_BAD_EWTQS);
+ return(IDA_ILL_INPUT);
+ }
+ }
+ } else {
+ errconQS = FALSE;
+ }
+
+ /* Check to see if y0 satisfies constraints. */
+ if (constraintsSet) {
+
+ if (sensi && (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);
+ if (!conOK) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDAInitialSetup", MSG_Y0_FAIL_CONSTR);
+ return(IDA_ILL_INPUT);
+ }
+ }
+
+ /* Check that lsolve exists and call linit function if it exists. */
+ if (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 (retval != 0) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDAInitialSetup", MSG_LINIT_FAIL);
+ return(IDA_LINIT_FAIL);
+ }
+ }
+
+ return(IDA_SUCCESS);
+}
+
+/*
+ * IDAEwtSet
+ *
+ * This routine is responsible for loading the error weight vector
+ * ewt, according to itol, as follows:
+ * (1) ewt[i] = 1 / (rtol * ABS(ycur[i]) + atol), i=0,...,Neq-1
+ * if itol = IDA_SS
+ * (2) ewt[i] = 1 / (rtol * ABS(ycur[i]) + atol[i]), i=0,...,Neq-1
+ * if itol = IDA_SV
+ *
+ * IDAEwtSet returns 0 if ewt is successfully set as above to a
+ * positive vector and -1 otherwise. In the latter case, ewt is
+ * considered undefined.
+ *
+ * All the real work is done in the routines IDAEwtSetSS, IDAEwtSetSV.
+ */
+
+int IDAEwtSet(N_Vector ycur, N_Vector weight, void *data)
+{
+ IDAMem IDA_mem;
+ int flag = 0;
+
+ /* data points to IDA_mem here */
+
+ IDA_mem = (IDAMem) data;
+
+ switch(itol) {
+ case IDA_SS:
+ flag = IDAEwtSetSS(IDA_mem, ycur, weight);
+ break;
+ case IDA_SV:
+ flag = IDAEwtSetSV(IDA_mem, ycur, weight);
+ break;
+ }
+ return(flag);
+}
+
+/*
+ * IDAEwtSetSS
+ *
+ * This routine sets ewt as decribed above in the case itol=IDA_SS.
+ * It tests for non-positive components before inverting. IDAEwtSetSS
+ * returns 0 if ewt is successfully set to a positive vector
+ * and -1 otherwise. In the latter case, ewt is considered
+ * undefined.
+ */
+
+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);
+ return(0);
+}
+
+/*
+ * IDAEwtSetSV
+ *
+ * This routine sets ewt as decribed above in the case itol=IDA_SV.
+ * It tests for non-positive components before inverting. IDAEwtSetSV
+ * returns 0 if ewt is successfully set to a positive vector
+ * and -1 otherwise. In the latter case, ewt is considered
+ * undefined.
+ */
+
+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);
+ return(0);
+}
+
+/*
+ * IDAQuadEwtSet
+ *
+ */
+
+static int IDAQuadEwtSet(IDAMem IDA_mem, N_Vector qcur, N_Vector weightQ)
+{
+ int flag=0;
+
+ switch (itolQ) {
+ case IDA_SS:
+ flag = IDAQuadEwtSetSS(IDA_mem, qcur, weightQ);
+ break;
+ case IDA_SV:
+ flag = IDAQuadEwtSetSV(IDA_mem, qcur, weightQ);
+ break;
+ }
+
+ return(flag);
+
+}
+
+/*
+ * IDAQuadEwtSetSS
+ *
+ */
+
+static int IDAQuadEwtSetSS(IDAMem IDA_mem, N_Vector qcur, N_Vector weightQ)
+{
+ N_Vector tempvQ;
+
+ /* Use ypQ as temporary storage */
+ tempvQ = ypQ;
+
+ N_VAbs(qcur, tempvQ);
+ N_VScale(rtolQ, tempvQ, tempvQ);
+ N_VAddConst(tempvQ, SatolQ, tempvQ);
+ if (N_VMin(tempvQ) <= ZERO) return(-1);
+ N_VInv(tempvQ, weightQ);
+
+ return(0);
+}
+
+/*
+ * IDAQuadEwtSetSV
+ *
+ */
+
+static int IDAQuadEwtSetSV(IDAMem IDA_mem, N_Vector qcur, N_Vector weightQ)
+{
+ N_Vector tempvQ;
+
+ /* Use ypQ as temporary storage */
+ tempvQ = ypQ;
+
+ N_VAbs(qcur, tempvQ);
+ N_VLinearSum(rtolQ, tempvQ, ONE, VatolQ, tempvQ);
+ if (N_VMin(tempvQ) <= ZERO) return(-1);
+ N_VInv(tempvQ, weightQ);
+
+ return(0);
+}
+
+/*
+ * IDASensEwtSet
+ *
+ */
+
+int IDASensEwtSet(IDAMem IDA_mem, N_Vector *yScur, N_Vector *weightS)
+{
+ int flag=0;
+
+ switch (itolS) {
+ case IDA_EE:
+ flag = IDASensEwtSetEE(IDA_mem, yScur, weightS);
+ break;
+ case IDA_SS:
+ flag = IDASensEwtSetSS(IDA_mem, yScur, weightS);
+ break;
+ case IDA_SV:
+ flag = IDASensEwtSetSV(IDA_mem, yScur, weightS);
+ break;
+ }
+
+ return(flag);
+
+}
+
+/*
+ * IDASensEwtSetEE
+ *
+ * In this case, the error weight vector for the i-th sensitivity is set to
+ *
+ * ewtS_i = pbar_i * efun(pbar_i*yS_i)
+ *
+ * In other words, the scaled sensitivity pbar_i * yS_i has the same error
+ * weight vector calculation as the solution vector.
+ *
+ */
+
+static int IDASensEwtSetEE(IDAMem IDA_mem, N_Vector *yScur, N_Vector *weightS)
+{
+ int is;
+ N_Vector pyS;
+ int flag;
+
+ /* Use tempv1 as temporary storage for the scaled sensitivity */
+ pyS = tempv1;
+
+ for (is=0; is<Ns; is++) {
+ N_VScale(pbar[is], yScur[is], pyS);
+ flag = efun(pyS, weightS[is], edata);
+ if (flag != 0) return(-1);
+ N_VScale(pbar[is], weightS[is], weightS[is]);
+ }
+
+ return(0);
+}
+
+/*
+ * IDASensEwtSetSS
+ *
+ */
+
+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]);
+ }
+ return(0);
+}
+
+/*
+ * IDASensEwtSetSV
+ *
+ */
+
+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]);
+ }
+
+ return(0);
+}
+
+/*
+ * IDAQuadSensEwtSet
+ *
+ */
+
+int IDAQuadSensEwtSet(IDAMem IDA_mem, N_Vector *yQScur, N_Vector *weightQS)
+{
+ int flag=0;
+
+ switch (itolQS) {
+ case IDA_EE:
+ flag = IDAQuadSensEwtSetEE(IDA_mem, yQScur, weightQS);
+ break;
+ case IDA_SS:
+ flag = IDAQuadSensEwtSetSS(IDA_mem, yQScur, weightQS);
+ break;
+ case IDA_SV:
+ flag = IDAQuadSensEwtSetSV(IDA_mem, yQScur, weightQS);
+ break;
+ }
+
+ return(flag);
+}
+
+/*
+ * IDAQuadSensEwtSetEE
+ *
+ * In this case, the error weight vector for the i-th quadrature sensitivity
+ * is set to
+ *
+ * ewtQS_i = pbar_i * IDAQuadEwtSet(pbar_i*yQS_i)
+ *
+ * In other words, the scaled sensitivity pbar_i * yQS_i has the same error
+ * weight vector calculation as the quadrature vector.
+ *
+ */
+static int IDAQuadSensEwtSetEE(IDAMem IDA_mem, N_Vector *yQScur, N_Vector *weightQS)
+{
+ int is;
+ N_Vector pyS;
+ int flag;
+
+ /* Use tempvQS[0] as temporary storage for the scaled sensitivity */
+ pyS = tempvQS[0];
+
+ for (is=0; is<Ns; is++) {
+ N_VScale(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]);
+ }
+
+ return(0);
+}
+
+static int IDAQuadSensEwtSetSS(IDAMem IDA_mem, N_Vector *yQScur, N_Vector *weightQS)
+{
+ int is;
+ N_Vector tempvQ;
+
+ /* Use ypQ as temporary storage */
+ tempvQ = ypQ;
+
+ for (is=0; is<Ns; is++) {
+ N_VAbs(yQScur[is], tempvQ);
+ N_VScale(rtolQS, tempvQ, tempvQ);
+ N_VAddConst(tempvQ, SatolQS[is], tempvQ);
+ if (N_VMin(tempvQ) <= ZERO) return(-1);
+ N_VInv(tempvQ, weightQS[is]);
+ }
+
+ return(0);
+}
+
+static int IDAQuadSensEwtSetSV(IDAMem IDA_mem, N_Vector *yQScur, N_Vector *weightQS)
+{
+ int is;
+ N_Vector tempvQ;
+
+ /* Use ypQ as temporary storage */
+ tempvQ = ypQ;
+
+ for (is=0; is<Ns; is++) {
+ N_VAbs(yQScur[is], tempvQ);
+ N_VLinearSum(rtolQS, tempvQ, ONE, VatolQS[is], tempvQ);
+ if (N_VMin(tempvQ) <= ZERO) return(-1);
+ N_VInv(tempvQ, weightQS[is]);
+ }
+
+ return(0);
+}
+
+
+/*
+ * -----------------------------------------------------------------
+ * Stopping tests
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * IDAStopTest1
+ *
+ * This routine tests for stop conditions before taking a step.
+ * The tests depend on the value of itask.
+ * The variable tretlast is the previously returned value of tret.
+ *
+ * The return values are:
+ * 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 tstop cases, this routine may adjust the stepsize hh to cause
+ * the next step to reach tstop exactly.
+ */
+
+static int IDAStopTest1(IDAMem IDA_mem, realtype tout, realtype *tret,
+ N_Vector yret, N_Vector ypret, int itask)
+{
+ int ier;
+ realtype troundoff;
+
+ switch (itask) {
+
+ case IDA_NORMAL:
+
+ if (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);
+ return(IDA_ILL_INPUT);
+ }
+ }
+
+ /* Test for tout = tretlast, and for tn past tout. */
+ if (tout == tretlast) {
+ *tret = tretlast = tout;
+ return(IDA_SUCCESS);
+ }
+ if ((tn - tout)*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;
+ return(IDA_SUCCESS);
+ }
+
+ if (tstopset) {
+ troundoff = HUNDRED*uround*(ABS(tn) + ABS(hh));
+ if (ABS(tn - tstop) <= troundoff) {
+ ier = IDAGetSolution(IDA_mem, tstop, yret, ypret);
+ if (ier != IDA_SUCCESS) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASolve", MSG_BAD_TSTOP, tstop, tn);
+ return(IDA_ILL_INPUT);
+ }
+ *tret = tretlast = tstop;
+ tstopset = FALSE;
+ return(IDA_TSTOP_RETURN);
+ }
+ if ((tn + hh - tstop)*hh > ZERO)
+ hh = (tstop - tn)*(ONE-FOUR*uround);
+ }
+
+ return(CONTINUE_STEPS);
+
+ case IDA_ONE_STEP:
+
+ if (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);
+ return(IDA_ILL_INPUT);
+ }
+ }
+
+ /* Test for tn past tretlast. */
+ if ((tn - tretlast)*hh > ZERO) {
+ ier = IDAGetSolution(IDA_mem, tn, yret, ypret);
+ *tret = tretlast = tn;
+ return(IDA_SUCCESS);
+ }
+
+ if (tstopset) {
+ troundoff = HUNDRED*uround*(ABS(tn) + ABS(hh));
+ if (ABS(tn - tstop) <= troundoff) {
+ ier = IDAGetSolution(IDA_mem, tstop, yret, ypret);
+ if (ier != IDA_SUCCESS) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASolve", MSG_BAD_TSTOP, tstop, tn);
+ return(IDA_ILL_INPUT);
+ }
+ *tret = tretlast = tstop;
+ tstopset = FALSE;
+ return(IDA_TSTOP_RETURN);
+ }
+ if ((tn + hh - tstop)*hh > ZERO)
+ hh = (tstop - tn)*(ONE-FOUR*uround);
+ }
+
+ return(CONTINUE_STEPS);
+
+ }
+ return(-99);
+}
+
+/*
+ * IDAStopTest2
+ *
+ * This routine tests for stop conditions after taking a step.
+ * The tests depend on the value of itask.
+ *
+ * The return values are:
+ * 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
+ *
+ * In the two cases with tstop, this routine may reset the stepsize hh
+ * to cause the next step to reach tstop exactly.
+ *
+ * In the two cases with ONE_STEP mode, no interpolation to tn is needed
+ * because yret and ypret already contain the current y and y' values.
+ *
+ * Note: No test is made for an error return from IDAGetSolution here,
+ * because the same test was made prior to the step.
+ */
+
+static int IDAStopTest2(IDAMem IDA_mem, realtype tout, realtype *tret,
+ N_Vector yret, N_Vector ypret, int itask)
+{
+ int ier;
+ realtype troundoff;
+
+ switch (itask) {
+
+ case IDA_NORMAL:
+
+ /* Test for tn past tout. */
+ if ((tn - tout)*hh >= ZERO) {
+ ier = IDAGetSolution(IDA_mem, tout, yret, ypret);
+ *tret = tretlast = tout;
+ return(IDA_SUCCESS);
+ }
+
+ if (tstopset) {
+ /* Test for tn at tstop and for tn near tstop */
+ troundoff = HUNDRED*uround*(ABS(tn) + ABS(hh));
+ if (ABS(tn - tstop) <= troundoff) {
+ ier = IDAGetSolution(IDA_mem, tstop, yret, ypret);
+ *tret = tretlast = tstop;
+ tstopset = FALSE;
+ return(IDA_TSTOP_RETURN);
+ }
+ if ((tn + hh - tstop)*hh > ZERO)
+ hh = (tstop - tn)*(ONE-FOUR*uround);
+ }
+
+ return(CONTINUE_STEPS);
+
+ case IDA_ONE_STEP:
+
+ if (tstopset) {
+ /* Test for tn at tstop and for tn near tstop */
+ troundoff = HUNDRED*uround*(ABS(tn) + ABS(hh));
+ if (ABS(tn - tstop) <= troundoff) {
+ ier = IDAGetSolution(IDA_mem, tstop, yret, ypret);
+ *tret = tretlast = tstop;
+ tstopset = FALSE;
+ return(IDA_TSTOP_RETURN);
+ }
+ if ((tn + hh - tstop)*hh > ZERO)
+ hh = (tstop - tn)*(ONE-FOUR*uround);
+ }
+
+ *tret = tretlast = tn;
+ return(IDA_SUCCESS);
+
+ }
+ return -99;
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Error handler
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * IDAHandleFailure
+ *
+ * This routine prints error messages for all cases of failure by
+ * IDAStep. It returns to IDASolve the value that it is to return to
+ * the user.
+ */
+
+static int IDAHandleFailure(IDAMem IDA_mem, int sflag)
+{
+ /* Depending on sflag, print error message and return error flag */
+ switch (sflag) {
+
+ case IDA_ERR_FAIL:
+ IDAProcessError(IDA_mem, IDA_ERR_FAIL, "IDAS", "IDASolve", MSG_ERR_FAILS, tn, hh);
+ return(IDA_ERR_FAIL);
+
+ case IDA_CONV_FAIL:
+ IDAProcessError(IDA_mem, IDA_CONV_FAIL, "IDAS", "IDASolve", MSG_CONV_FAILS, tn, hh);
+ return(IDA_CONV_FAIL);
+
+ case IDA_LSETUP_FAIL:
+ IDAProcessError(IDA_mem, IDA_LSETUP_FAIL, "IDAS", "IDASolve", MSG_SETUP_FAILED, tn);
+ return(IDA_LSETUP_FAIL);
+
+ case IDA_LSOLVE_FAIL:
+ IDAProcessError(IDA_mem, IDA_LSOLVE_FAIL, "IDAS", "IDASolve", MSG_SOLVE_FAILED, tn);
+ return(IDA_LSOLVE_FAIL);
+
+ case IDA_REP_RES_ERR:
+ IDAProcessError(IDA_mem, IDA_REP_RES_ERR, "IDAS", "IDASolve", MSG_REP_RES_ERR, tn);
+ return(IDA_REP_RES_ERR);
+
+ case IDA_RES_FAIL:
+ IDAProcessError(IDA_mem, IDA_RES_FAIL, "IDAS", "IDASolve", MSG_RES_NONRECOV, tn);
+ return(IDA_RES_FAIL);
+
+ case IDA_CONSTR_FAIL:
+ IDAProcessError(IDA_mem, IDA_CONSTR_FAIL, "IDAS", "IDASolve", MSG_FAILED_CONSTR, tn);
+ return(IDA_CONSTR_FAIL);
+
+ }
+
+ return -99;
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Main IDAStep function
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * IDAStep
+ *
+ * This routine performs one internal IDA step, from tn to tn + hh.
+ * It calls other routines to do all the work.
+ *
+ * It solves a system of differential/algebraic equations of the form
+ * F(t,y,y') = 0, for one step. In IDA, tt is used for t,
+ * yy is used for y, and yp is used for y'. The function F is supplied as 'res'
+ * by the user.
+ *
+ * The methods used are modified divided difference, fixed leading
+ * coefficient forms of backward differentiation formulas.
+ * The code adjusts the stepsize and order to control the local error per step.
+ *
+ * The main operations done here are as follows:
+ * * initialize various quantities;
+ * * setting of multistep method coefficients;
+ * * solution of the nonlinear system for yy at t = tn + hh;
+ * * deciding on order reduction and testing the local error;
+ * * attempting to recover from failure in nonlinear solver or error test;
+ * * resetting stepsize and order for the next step.
+ * * updating phi and other state data if successful;
+ *
+ * On a failure in the nonlinear system solution or error test, the
+ * step may be reattempted, depending on the nature of the failure.
+ *
+ * Variables or arrays (all in the IDAMem structure) used in IDAStep are:
+ *
+ * tt -- Independent variable.
+ * yy -- Solution vector at tt.
+ * yp -- Derivative of solution vector after successful stelp.
+ * res -- User-supplied function to evaluate the residual. See the
+ * description given in file ida.h .
+ * lsetup -- Routine to prepare for the linear solver call. It may either
+ * save or recalculate quantities used by lsolve. (Optional)
+ * lsolve -- Routine to solve a linear system. A prior call to lsetup
+ * may be required.
+ * hh -- Appropriate step size for next step.
+ * ewt -- Vector of weights used in all convergence tests.
+ * phi -- Array of divided differences used by IDAStep. This array is composed
+ * of (maxord+1) nvectors (each of size Neq). (maxord+1) is the maximum
+ * order for the problem, maxord, plus 1.
+ *
+ * Return values are:
+ * IDA_SUCCESS IDA_RES_FAIL LSETUP_ERROR_NONRECVR
+ * IDA_LSOLVE_FAIL IDA_ERR_FAIL
+ * IDA_CONSTR_FAIL IDA_CONV_FAIL
+ * IDA_REP_RES_ERR
+ */
+
+static int IDAStep(IDAMem IDA_mem)
+{
+ realtype saved_t, ck;
+ realtype err_k, err_km1, err_km2;
+ int ncf, nef;
+ int nflag, kflag;
+ int retval;
+ booleantype sensi_stg;
+
+ /* Are we computing sensitivities with the staggered approach? */
+ sensi_stg = (sensi && (ism==IDA_STAGGERED));
+
+ saved_t = tn;
+ ncf = nef = 0;
+
+ if (nst == ZERO){
+ kk = 1;
+ kused = 0;
+ hused = ZERO;
+ psi[0] = hh;
+ cj = ONE/hh;
+ phase = 0;
+ ns = 0;
+ }
+
+ /* To prevent 'unintialized variable' warnings */
+ err_k = ZERO;
+ err_km1 = ZERO;
+ err_km2 = ZERO;
+
+ /* Looping point for attempts to take a step */
+
+ loop {
+
+ /*-----------------------
+ Set method coefficients
+ -----------------------*/
+
+ IDASetCoeffs(IDA_mem, &ck);
+
+ kflag = IDA_SUCCESS;
+
+ /*----------------------------------------------------
+ If tn is past tstop (by roundoff), reset it to tstop.
+ -----------------------------------------------------*/
+
+ tn = tn + hh;
+ if (tstopset) {
+ if ((tn - tstop)*hh > ZERO) tn = tstop;
+ }
+
+ /*-----------------------
+ Advance state variables
+ -----------------------*/
+
+ /* Nonlinear system solution */
+ nflag = IDANls(IDA_mem);
+
+ /* If NLS was successful, perform error test */
+ if (nflag == IDA_SUCCESS)
+ nflag = IDATestError(IDA_mem, ck, &err_k, &err_km1, &err_km2);
+
+ /* Test for convergence or error test failures */
+ if (nflag != IDA_SUCCESS) {
+
+ /* restore and decide what to do */
+ IDARestore(IDA_mem, saved_t);
+ kflag = IDAHandleNFlag(IDA_mem, nflag, err_k, err_km1,
+ &ncfn, &ncf, &netf, &nef);
+
+ /* exit on nonrecoverable failure */
+ if (kflag != PREDICT_AGAIN) return(kflag);
+
+ /* recoverable error; predict again */
+ if(nst==0) IDAReset(IDA_mem);
+ continue;
+
+ }
+
+ /*----------------------------
+ Advance quadrature variables
+ ----------------------------*/
+ if (quadr) {
+
+ nflag = IDAQuadNls(IDA_mem);
+
+ /* If NLS was successful, perform error test */
+ if (errconQ && (nflag == IDA_SUCCESS))
+ nflag = IDAQuadTestError(IDA_mem, ck, &err_k, &err_km1, &err_km2);
+
+ /* Test for convergence or error test failures */
+ if (nflag != IDA_SUCCESS) {
+
+ /* restore and decide what to do */
+ IDARestore(IDA_mem, saved_t);
+ kflag = IDAHandleNFlag(IDA_mem, nflag, err_k, err_km1,
+ &ncfnQ, &ncf, &netfQ, &nef);
+
+ /* exit on nonrecoverable failure */
+ if (kflag != PREDICT_AGAIN) return(kflag);
+
+ /* recoverable error; predict again */
+ if(nst==0) IDAReset(IDA_mem);
+ continue;
+ }
+ }
+
+ /*--------------------------------------------------
+ Advance sensitivity variables (Staggered approach)
+ --------------------------------------------------*/
+ if (sensi_stg) {
+
+ /* Evaluate res at converged y, needed for future evaluations of sens. RHS
+ If res() fails recoverably, treat it as a convergence failure and
+ attempt the step again */
+
+ retval = res(tn, yy, yp, delta, user_data);
+
+ if (retval < 0) return(IDA_RES_FAIL);
+ else if (retval > 0) continue;
+
+ nflag = IDASensNls(IDA_mem);
+
+ /* If NLS was successful, perform error test */
+ if (errconS && (nflag == IDA_SUCCESS))
+ nflag = IDASensTestError(IDA_mem, ck, &err_k, &err_km1, &err_km2);
+
+ /* Test for convergence or error test failures */
+ if (nflag != IDA_SUCCESS) {
+
+ /* restore and decide what to do */
+ IDARestore(IDA_mem, saved_t);
+ kflag = IDAHandleNFlag(IDA_mem, nflag, err_k, err_km1,
+ &ncfnQ, &ncf, &netfQ, &nef);
+
+ /* exit on nonrecoverable failure */
+ if (kflag != PREDICT_AGAIN) return(kflag);
+
+ /* recoverable error; predict again */
+ if(nst==0) IDAReset(IDA_mem);
+ continue;
+ }
+ }
+
+ /*-------------------------------------------
+ Advance quadrature sensitivity variables
+ -------------------------------------------*/
+ if (quadr_sensi) {
+
+ nflag = IDAQuadSensNls(IDA_mem);
+
+ /* If NLS was successful, perform error test */
+ if (errconQS && (nflag == IDA_SUCCESS))
+ nflag = IDAQuadSensTestError(IDA_mem, ck, &err_k, &err_km1, &err_km2);
+
+ /* Test for convergence or error test failures */
+ if (nflag != IDA_SUCCESS) {
+
+ /* restore and decide what to do */
+ IDARestore(IDA_mem, saved_t);
+ kflag = IDAHandleNFlag(IDA_mem, nflag, err_k, err_km1,
+ &ncfnQ, &ncf, &netfQ, &nef);
+
+ /* exit on nonrecoverable failure */
+ if (kflag != PREDICT_AGAIN) return(kflag);
+
+ /* recoverable error; predict again */
+ if(nst==0) IDAReset(IDA_mem);
+ continue;
+ }
+ }
+
+ /* kflag == IDA_SUCCESS */
+ break;
+
+ } /* end loop */
+
+ /* Nonlinear system solve and error test were both successful;
+ update data, and consider change of step and/or order */
+
+ IDACompleteStep(IDA_mem, err_k, err_km1);
+
+ /*
+ Rescale ee vector to be the estimated local error
+ Notes:
+ (1) altering the value of ee is permissible since
+ it will be re-initialized to the zero vector by
+ IDASolve()->IDAStep()->IDANls()->IDANewtonIter()
+ before it is needed again
+ (2) the value of ee is only valid if IDAHandleNFlag()
+ returns either PREDICT_AGAIN or IDA_SUCCESS
+ */
+
+ N_VScale(ck, ee, ee);
+
+ return(IDA_SUCCESS);
+}
+
+/*
+ * IDAGetSolution
+ *
+ * This routine evaluates y(t) and y'(t) as the value and derivative of
+ * the interpolating polynomial at the independent variable t, and stores
+ * the results in the vectors yret and ypret. It uses the current
+ * independent variable value, tn, and the method order last used, kused.
+ * This function is called by IDASolve with t = tout, t = tn, or t = tstop.
+ *
+ * If kused = 0 (no step has been taken), or if t = tn, then the order used
+ * here is taken to be 1, giving yret = phi[0], ypret = phi[1]/psi[0].
+ *
+ * The return values are:
+ * IDA_SUCCESS if t is legal, or
+ * IDA_BAD_T if t is not within the interval of the last step taken.
+ */
+
+int IDAGetSolution(void *ida_mem, realtype t, N_Vector yret, N_Vector ypret)
+{
+ IDAMem IDA_mem;
+ realtype tfuzz, tp, delt, c, d, gam;
+ int j, kord;
+
+ if (ida_mem == NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDAGetSolution", MSG_NO_MEM);
+ return (IDA_MEM_NULL);
+ }
+ IDA_mem = (IDAMem) ida_mem;
+
+ /* Check t for legality. Here tn - hused is t_{n-1}. */
+
+ tfuzz = HUNDRED * uround * (ABS(tn) + ABS(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);
+ 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;
+
+ /* Accumulate multiples of columns phi[j] into yret and ypret. */
+
+ delt = t - tn;
+ c = ONE; d = ZERO;
+ gam = delt/psi[0];
+ for (j=1; j <= kord; j++) {
+ d = d*gam + c/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);
+ }
+ return(IDA_SUCCESS);
+}
+
+
+/*
+ * IDASetCoeffs
+ *
+ * This routine computes the coefficients relevant to the current step.
+ * The counter ns counts the number of consecutive steps taken at
+ * constant stepsize h and order k, up to a maximum of k + 2.
+ * Then the first ns components of beta will be one, and on a step
+ * with ns = k + 2, the coefficients alpha, etc. need not be reset here.
+ * Also, IDACompleteStep prohibits an order increase until ns = k + 2.
+ */
+
+static void IDASetCoeffs(IDAMem IDA_mem, realtype *ck)
+{
+ int i, is;
+ realtype temp1, temp2, alpha0, alphas;
+
+ /* Set coefficients for the current stepsize h */
+
+ if (hh != hused || kk != kused) ns = 0;
+ ns = MIN(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;
+ }
+ psi[kk] = temp1;
+ }
+ /* compute alphas, alpha0 */
+ alphas = ZERO;
+ alpha0 = ZERO;
+ for(i=0;i<kk;i++){
+ alphas = alphas - ONE/(i+1);
+ alpha0 = alpha0 - alpha[i];
+ }
+
+ /* compute leading coefficient cj */
+ cjlast = cj;
+ cj = -alphas/hh;
+
+ /* compute variable stepsize error coefficient ck */
+
+ *ck = ABS(alpha[kk] + alphas - alpha0);
+ *ck = MAX(*ck, alpha[kk]);
+
+ /* change phi to phi-star */
+
+ for(i=ns;i<=kk;i++) N_VScale(beta[i], phi[i], phi[i]);
+
+ if (quadr)
+ for(i=ns;i<=kk;i++)
+ N_VScale(beta[i], phiQ[i], 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 (quadr_sensi)
+ for(is=0;is<Ns;is++)
+ for(i=ns;i<=kk;i++)
+ N_VScale(beta[i], phiQS[i][is], phiQS[i][is]);
+
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Nonlinear solver functions
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * IDANls
+ *
+ * This routine attempts to solve the nonlinear system using the linear
+ * solver specified. NOTE: this routine uses N_Vector ee as the scratch
+ * vector tempv3 passed to lsetup.
+ *
+ * Possible return values:
+ *
+ * IDA_SUCCESS
+ *
+ * IDA_RES_RECVR IDA_RES_FAIL
+ * IDA_SRES_RECVR IDA_SRES_FAIL
+ * IDA_LSETUP_RECVR IDA_LSETUP_FAIL
+ * IDA_LSOLVE_RECVR IDA_LSOLVE_FAIL
+ *
+ * IDA_CONSTR_RECVR
+ * IDA_NCONV_RECVR
+ */
+
+static int IDANls(IDAMem IDA_mem)
+{
+ int retval, is;
+ booleantype constraintsPassed, callSetup, tryAgain;
+ realtype temp1, temp2, vnorm;
+ N_Vector tempv3;
+ booleantype sensi_sim;
+
+ /* Are we computing sensitivities with the IDA_SIMULTANEOUS approach? */
+ sensi_sim = (sensi && (ism==IDA_SIMULTANEOUS));
+
+ callSetup = FALSE;
+
+ /* Initialize if the first time called */
+ if (nst == 0){
+ cjold = cj;
+ ss = TWENTY;
+ ssS = TWENTY;
+ if (setupNonNull) callSetup = TRUE;
+ }
+
+ mm = tempv2;
+ tempv3 = ee;
+
+ /* Decide if lsetup is to be called */
+ if (setupNonNull){
+ cjratio = cj / 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;}
+ }
+
+ /* 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{
+
+ /* Compute predicted values for yy and yp, and compute residual there. */
+ IDAPredict(IDA_mem);
+ retval = res(tn, yy, yp, delta, user_data);
+ 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++;
+ 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;
+
+ retval = lsetup(IDA_mem, yy, yp, delta, tempv1, tempv2, tempv3);
+
+ cjold = cj;
+ cjratio = ONE;
+ ss = TWENTY;
+ ssS = TWENTY;
+ if (retval < 0) return(IDA_LSETUP_FAIL);
+ if (retval > 0) return(IDA_LSETUP_RECVR);
+ }
+
+ /* Call the Newton iteration routine. */
+ retval = IDANewtonIter(IDA_mem);
+
+ /* Retry the current step on recoverable failure with old Jacobian data. */
+ tryAgain = (retval>0)&&(setupNonNull) &&(!callSetup);
+
+ if (tryAgain){
+ callSetup = TRUE;
+ continue;
+ }
+ else break;
+
+ } /* end of loop */
+
+ if (retval != IDA_SUCCESS) return(retval);
+
+ /* 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 (constraintsPassed) return(IDA_SUCCESS);
+ else {
+ N_VCompare(ONEPT5, constraints, 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|| */
+
+ /* 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 */
+ 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 = MAX(rr,PT1);
+ return(IDA_CONSTR_RECVR);
+ }
+ }
+ }
+
+ return(IDA_SUCCESS);
+}
+
+
+/*
+ * IDAPredict
+ *
+ * This routine predicts the new values for vectors yy and yp.
+ */
+
+static void IDAPredict(IDAMem IDA_mem)
+{
+ int j;
+
+ N_VScale(ONE, phi[0], yy);
+ N_VConst(ZERO, yp);
+
+ for(j=1; j<=kk; j++) {
+ N_VLinearSum(ONE, phi[j], ONE, yy, yy);
+ N_VLinearSum(gamma[j], phi[j], ONE, yp, yp);
+ }
+}
+
+/*
+ * IDANewtonIter
+ *
+ * This routine performs the Newton iteration.
+ * It assumes that delta contains the initial residual vector on entry.
+ * If the iteration succeeds, it returns the value IDA_SUCCESS = 0.
+ * If not, it returns either:
+ * a positive value (for a recoverable failure), namely one of:
+ * IDA_RES_RECVR
+ * IDA_SRES_RECVR
+ * IDA_LSOLVE_RECVR
+ * IDA_NCONV_RECVR
+ * or
+ * a negative value (for a nonrecoverable failure), namely one of:
+ * IDA_RES_FAIL
+ * IDA_SRES_FAIL
+ * IDA_LSOLVE_FAIL
+ *
+ * NOTE: This routine uses N_Vector savres, which is preset to tempv1.
+ */
+
+static int IDANewtonIter(IDAMem IDA_mem)
+{
+ int mnewt, retval, is;
+ realtype delnrm, oldnrm, rate;
+ booleantype sensi_sim;
+
+ sensi_sim = (sensi && (ism==IDA_SIMULTANEOUS));
+
+ /* Initialize counter mnewt and cumulative correction vectors ee and eeS. */
+ mnewt = 0;
+ N_VConst(ZERO, ee);
+ if (sensi_sim)
+ for(is=0;is<Ns;is++) N_VConst(ZERO, eeS[is]);
+
+ /* Initialize oldnrm to avoid compiler warning message */
+ oldnrm = ZERO;
+
+ /* Looping point for Newton iteration. Break out on any error. */
+ loop {
+
+ nni++;
+
+ /* Save a copy of the residual vector in savres. */
+ N_VScale(ONE, delta, savres);
+
+ /* Call the lsolve function to get correction vector delta. */
+ retval = lsolve(IDA_mem, delta, ewt, yy, yp, 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);
+ 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);
+
+ /* 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]);
+ }
+ delnrm = IDASensWrmsNormUpdate(IDA_mem, delnrm, deltaS, ewtS, FALSE);
+ }
+
+ /* Test for convergence, first directly, then with rate estimate. */
+
+ if (mnewt == 0){
+ oldnrm = delnrm;
+ if (delnrm <= toldel) return(IDA_SUCCESS);
+ }
+ else {
+ rate = RPowerR( delnrm/oldnrm, ONE/mnewt );
+ if (rate > RATEMAX) return(IDA_NCONV_RECVR);
+ ss = rate/(ONE - rate);
+ }
+
+ if (ss*delnrm <= epsNewt) return(IDA_SUCCESS);
+
+ /* Not yet converged. Increment mnewt and test for max allowed. */
+ mnewt++;
+ if (mnewt >= 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++;
+ 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++;
+ if(retval < 0) return(IDA_SRES_FAIL);
+ if(retval > 0) return(IDA_SRES_RECVR);
+ }
+
+ /* Loop for next iteration. */
+
+ } /* end of Newton iteration loop */
+
+ /* All error returns exit here. */
+ return(retval);
+
+}
+
+/*
+ * IDAQuadNls
+ *
+ * This routine solves for the quadrature variables at the new step.
+ * It does not solve a nonlinear system, but rather updates the
+ * quadrature variables. The name for this function is just for
+ * uniformity purposes.
+ *
+ */
+
+static int IDAQuadNls(IDAMem IDA_mem)
+{
+ int retval;
+
+ /* Predict: load yyQ and ypQ */
+ IDAQuadPredict(IDA_mem);
+
+ /* Compute correction eeQ */
+ retval = rhsQ(tn, yy, yp, eeQ, user_data);
+ nrQe++;
+ if (retval < 0) return(IDA_QRHS_FAIL);
+ else if (retval > 0) return(IDA_QRHS_RECVR);
+
+ if (quadr_sensi)
+ N_VScale(ONE, eeQ, savrhsQ);
+
+ N_VLinearSum(ONE, eeQ, -ONE, ypQ, eeQ);
+ N_VScale(ONE/cj, eeQ, eeQ);
+
+ /* Apply correction: yyQ = yyQ + eeQ */
+ N_VLinearSum(ONE, yyQ, ONE, eeQ, yyQ);
+
+ return(IDA_SUCCESS);
+}
+
+/*
+ * IDAQuadPredict
+ *
+ * This routine predicts the new value for vectors yyQ and ypQ
+ */
+
+static void IDAQuadPredict(IDAMem IDA_mem)
+{
+ int j;
+
+ N_VScale(ONE, phiQ[0], yyQ);
+ N_VConst(ZERO, ypQ);
+
+ for(j=1; j<=kk; j++) {
+ N_VLinearSum(ONE, phiQ[j], ONE, yyQ, yyQ);
+ N_VLinearSum(gamma[j], phiQ[j], ONE, ypQ, ypQ);
+ }
+}
+
+/*
+ * IDASensNls
+ *
+ * This routine attempts to solve, one by one, all the sensitivity
+ * linear systems using nonlinear iterations and the linear solver
+ * specified (Staggered approach).
+ */
+
+static int IDASensNls(IDAMem IDA_mem)
+{
+ booleantype callSetup, tryAgain;
+ int is, retval;
+
+ callSetup = FALSE;
+
+ /* 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(is=0;is<Ns;is++)
+ IDASensPredict(IDA_mem, is, yyS[is], 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++;
+ 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;
+ if (retval < 0) return(IDA_LSETUP_FAIL);
+ if (retval > 0) return(IDA_LSETUP_RECVR);
+ }
+
+ /* Call the Newton iteration routine */
+ retval = IDASensNewtonIter(IDA_mem);
+
+ /* Retry the current step on recoverable failure with old Jacobian data */
+ tryAgain = (retval>0) && (setupNonNull) && (!callSetup);
+
+ if (tryAgain) {
+ callSetup = TRUE;
+ continue;
+ }
+ else break;
+
+ }
+
+ if (retval != IDA_SUCCESS)
+ ncfnS++;
+
+ return(retval);
+
+}
+
+/*
+ * IDASensPredict
+ *
+ * This routine loads the predicted values for the is-th sensitivity
+ * in the vectors yySens and ypSens.
+ *
+ * When ism=IDA_STAGGERED, yySens = yyS[is] and ypSens = ypS[is]
+ */
+
+static void IDASensPredict(IDAMem IDA_mem, int is,
+ N_Vector yySens, N_Vector ypSens)
+{
+ int j;
+
+ N_VScale(ONE, 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);
+ }
+
+}
+
+/*
+ * IDASensNewtonIter
+ *
+ * This routine performs the Newton iteration for sensitivity variables
+ * in the staggered case.
+ * It assumes that deltaS contains the initial sensitivity residual
+ * vectors on entry.
+ *
+ * If the iteration succeeds, it returns the value IDA_SUCCESS = 0.
+ * If not, it returns either:
+ * a positive value (for a recoverable failure), namely one of:
+ * IDA_RES_RECVR
+ * IDA_LSOLVE_RECVR
+ * IDA_NCONV_RECVR
+ * or
+ * a negative value (for a nonrecoverable failure), namely one of:
+ * IDA_RES_FAIL
+ * IDA_LSOLVE_FAIL
+ */
+
+static int IDASensNewtonIter(IDAMem IDA_mem)
+{
+ int mnewt, is, retval;
+ realtype delSnrm, delSnrm1, rateS;
+
+ mnewt = 0; /* local Newton iteration counter */
+ for(is=0;is<Ns;is++)
+ N_VConst(ZERO, eeS[is]); /* cumulative sensi. corrections */
+
+ loop {
+
+ nniS++;
+
+ for(is=0;is<Ns;is++) {
+
+ retval = lsolve(IDA_mem, deltaS[is], ewtS[is], yy, yp, 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]);
+
+ }
+
+ delSnrm = IDASensWrmsNorm(IDA_mem, deltaS, ewtS, FALSE);
+
+ if (mnewt == 0) {
+ if (delSnrm <= toldel) return(IDA_SUCCESS);
+ delSnrm1 = delSnrm;
+ } else {
+ rateS = RPowerR(delSnrm/delSnrm1, ONE/mnewt);
+ if (rateS > RATEMAX) return(IDA_NCONV_RECVR);
+ ssS = rateS/(ONE - rateS);
+ }
+
+ if (ssS * delSnrm <= 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 (retval < 0) return(IDA_SRES_FAIL);
+ if (retval > 0) return(IDA_SRES_RECVR);
+
+ }
+
+ return(retval);
+}
+
+
+/*
+ * IDAQuadSensNls
+ *
+ * This routine solves for the snesitivity quadrature variables at the
+ * new step. It does not solve a nonlinear system, but rather updates
+ * the sensitivity variables. The name for this function is just for
+ * uniformity purposes.
+ *
+ */
+
+static int IDAQuadSensNls(IDAMem IDA_mem)
+{
+ int retval, is;
+ N_Vector *ypQS;
+
+ /* Predict: load yyQS and ypQS for each sensitivity. Store
+ 1st order information in tempvQS. */
+
+ ypQS = tempvQS;
+ IDAQuadSensPredict(IDA_mem, yyQS, ypQS);
+
+ /* Compute correction eeQS */
+ retval = rhsQS(Ns, tn, yy, yp, yyS, ypS, savrhsQ, eeQS, user_dataQS, tmpS1, tmpS2, tmpS3);
+ 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]);
+ }
+
+ /* Apply correction: yyQS[is] = yyQ[is] + eeQ[is] */
+ for (is=0; is<Ns; is++) {
+ N_VLinearSum(ONE, yyQS[is], ONE, eeQS[is], yyQS[is]);
+ }
+
+ return(IDA_SUCCESS);
+}
+
+/*
+ * IDAQuadSensPredict
+ *
+ * This routine predicts the new value for vectors yyQS and ypQS
+ */
+
+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]);
+ 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]);
+ }
+ }
+}
+
+
+/*
+ * -----------------------------------------------------------------
+ * Error test
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * IDATestError
+ *
+ * This routine estimates errors at orders k, k-1, k-2, decides
+ * whether or not to suggest an order reduction, and performs
+ * the local error test.
+ *
+ * IDATestError returns either IDA_SUCCESS or ERROR_TEST_FAIL.
+ */
+
+static int IDATestError(IDAMem IDA_mem, realtype ck,
+ realtype *err_k, realtype *err_km1, realtype *err_km2)
+{
+ realtype enorm_k, enorm_km1, enorm_km2; /* error norms */
+ 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);
+
+ knew = kk;
+
+ if ( 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);
+
+ if ( 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);
+
+ /* Reduce order if errors are reduced */
+
+ if (MAX(terr_km1, terr_km2) <= terr_k) knew = 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;
+
+ }
+
+ }
+
+ /* Perform error test */
+
+ if (ck * enorm_k > ONE) return(ERROR_TEST_FAIL);
+ else return(IDA_SUCCESS);
+
+}
+
+/*
+ * IDAQuadTestError
+ *
+ * This routine estimates quadrature errors and updates errors at
+ * orders k, k-1, k-2, decides whether or not to suggest an order reduction,
+ * and performs the local error test.
+ *
+ * IDAQuadTestError returns the updated local error estimate at orders k,
+ * k-1, and k-2. These are norms of type MAX(|err|,|errQ|).
+ *
+ * The return flag can be either IDA_SUCCESS or ERROR_TEST_FAIL.
+ */
+
+static int IDAQuadTestError(IDAMem IDA_mem, realtype ck,
+ realtype *err_k, realtype *err_km1, realtype *err_km2)
+{
+ realtype enormQ;
+ realtype errQ_k, errQ_km1, errQ_km2;
+ realtype terr_k, terr_km1, terr_km2;
+ N_Vector tempv;
+ booleantype check_for_reduction = FALSE;
+
+ /* Rename ypQ */
+ tempv = ypQ;
+
+ /* Update error for order k. */
+ enormQ = N_VWrmsNorm(eeQ, ewtQ);
+ errQ_k = sigma[kk] * enormQ;
+ if (errQ_k > *err_k) {
+ *err_k = errQ_k;
+ check_for_reduction = TRUE;
+ }
+ terr_k = (kk+1) * (*err_k);
+
+ if ( 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);
+ if (errQ_km1 > *err_km1) {
+ *err_km1 = errQ_km1;
+ check_for_reduction = TRUE;
+ }
+ terr_km1 = kk * (*err_km1);
+
+ /* Has an order decrease already been decided in IDATestError? */
+ if (knew != kk) check_for_reduction = FALSE;
+
+ if (check_for_reduction) {
+
+ if ( 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);
+ if (errQ_km2 > *err_km2) {
+ *err_km2 = errQ_km2;
+ }
+ terr_km2 = (kk-1) * (*err_km2);
+
+ /* Decrease order if errors are reduced */
+ if (MAX(terr_km1, terr_km2) <= terr_k) knew = 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;
+
+ }
+
+ }
+
+ }
+
+ /* Perform error test */
+ if (ck * enormQ > ONE) return(ERROR_TEST_FAIL);
+ else return(IDA_SUCCESS);
+
+}
+
+/*
+ * IDASensTestError
+ *
+ * This routine estimates sensitivity errors and updates errors at
+ * orders k, k-1, k-2, decides whether or not to suggest an order reduction,
+ * and performs the local error test. (Used only in staggered approach).
+ *
+ * IDASensTestError returns the updated local error estimate at orders k,
+ * k-1, and k-2. These are norms of type MAX(|err|,|errQ|,|errS|).
+ *
+ * The return flag can be either IDA_SUCCESS or ERROR_TEST_FAIL.
+ */
+
+static int IDASensTestError(IDAMem IDA_mem, realtype ck,
+ realtype *err_k, realtype *err_km1, realtype *err_km2)
+{
+ realtype enormS;
+ realtype errS_k, errS_km1, errS_km2;
+ realtype terr_k, terr_km1, terr_km2;
+ N_Vector *tempv;
+ booleantype check_for_reduction = FALSE;
+ int is;
+
+ /* Rename deltaS */
+ tempv = deltaS;
+
+ /* Update error for order k. */
+ enormS = IDASensWrmsNorm(IDA_mem, eeS, ewtS, suppressalg);
+ errS_k = sigma[kk] * enormS;
+ if (errS_k > *err_k) {
+ *err_k = errS_k;
+ check_for_reduction = TRUE;
+ }
+ terr_k = (kk+1) * (*err_k);
+
+ if ( 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);
+ if (errS_km1 > *err_km1) {
+ *err_km1 = errS_km1;
+ check_for_reduction = TRUE;
+ }
+ terr_km1 = kk * (*err_km1);
+
+ /* Has an order decrease already been decided in IDATestError? */
+ if (knew != kk) check_for_reduction = FALSE;
+
+ if (check_for_reduction) {
+
+ if ( 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);
+ if (errS_km2 > *err_km2) {
+ *err_km2 = errS_km2;
+ }
+ terr_km2 = (kk-1) * (*err_km2);
+
+ /* Decrease order if errors are reduced */
+ if (MAX(terr_km1, terr_km2) <= terr_k) knew = 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;
+
+ }
+
+ }
+
+ }
+
+ /* Perform error test */
+ if (ck * enormS > ONE) return(ERROR_TEST_FAIL);
+ else return(IDA_SUCCESS);
+
+}
+
+/*
+ * IDAQuadSensTestError
+ *
+ * This routine estimates quadrature sensitivity errors and updates
+ * errors at orders k, k-1, k-2, decides whether or not to suggest
+ * an order reduction and performs the local error test. (Used
+ * only in staggered approach).
+ *
+ * IDAQuadSensTestError returns the updated local error estimate at
+ * orders k, k-1, and k-2. These are norms of type
+ * MAX(|err|,|errQ|,|errS|,|errQS|).
+ *
+ * The return flag can be either IDA_SUCCESS or ERROR_TEST_FAIL.
+ */
+
+static int IDAQuadSensTestError(IDAMem IDA_mem, realtype ck,
+ realtype *err_k, realtype *err_km1, realtype *err_km2)
+{
+ realtype enormQS;
+ realtype errQS_k, errQS_km1, errQS_km2;
+ realtype terr_k, terr_km1, terr_km2;
+ N_Vector *tempv;
+ booleantype check_for_reduction = FALSE;
+ int is;
+
+ tempv = yyQS;
+
+ enormQS = IDAQuadSensWrmsNorm(IDA_mem, eeQS, ewtQS);
+ errQS_k = sigma[kk] * enormQS;
+
+ if (errQS_k > *err_k) {
+ *err_k = errQS_k;
+ check_for_reduction = TRUE;
+ }
+ terr_k = (kk+1) * (*err_k);
+
+ if ( 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]);
+
+ errQS_km1 = sigma[kk-1] * IDAQuadSensWrmsNorm(IDA_mem, tempv, ewtQS);
+
+ if (errQS_km1 > *err_km1) {
+ *err_km1 = errQS_km1;
+ check_for_reduction = TRUE;
+ }
+ terr_km1 = kk * (*err_km1);
+
+ /* Has an order decrease already been decided in IDATestError? */
+ if (knew != kk) check_for_reduction = FALSE;
+
+ if (check_for_reduction) {
+ if ( 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]);
+
+ errQS_km2 = sigma[kk-2] * IDAQuadSensWrmsNorm(IDA_mem, tempv, ewtQS);
+ if (errQS_km2 > *err_km2) {
+ *err_km2 = errQS_km2;
+ }
+ terr_km2 = (kk-1) * (*err_km2);
+
+ /* Decrease order if errors are reduced */
+ if (MAX(terr_km1, terr_km2) <= terr_k) knew = 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;
+ }
+ }
+ }
+
+ /* Perform error test */
+ if (ck * enormQS > ONE) return(ERROR_TEST_FAIL);
+ else return(IDA_SUCCESS);
+}
+/*
+ * IDARestore
+ *
+ * This routine restores tn, psi, and phi in the event of a failure.
+ * It changes back phi-star to phi (changed in IDASetCoeffs)
+ */
+
+static void IDARestore(IDAMem IDA_mem, realtype saved_t)
+{
+ int j;
+ int is;
+
+ tn = saved_t;
+
+ for (j = 1; j <= kk; j++)
+ psi[j-1] = psi[j] - hh;
+
+ for (j = ns; j <= kk; j++)
+ N_VScale(ONE/beta[j], phi[j], phi[j]);
+
+ if (quadr)
+ for (j = ns; j <= kk; j++)
+ N_VScale(ONE/beta[j], phiQ[j], 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 (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]);
+
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Handler for convergence and/or error test failures
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * IDAHandleNFlag
+ *
+ * This routine handles failures indicated by the input variable nflag.
+ * Positive values indicate various recoverable failures while negative
+ * values indicate nonrecoverable failures. This routine adjusts the
+ * step size for recoverable failures.
+ *
+ * Possible nflag values (input):
+ *
+ * --convergence failures--
+ * IDA_RES_RECVR > 0
+ * IDA_LSOLVE_RECVR > 0
+ * IDA_CONSTR_RECVR > 0
+ * IDA_NCONV_RECVR > 0
+ * IDA_QRHS_RECVR > 0
+ * IDA_QSRHS_RECVR > 0
+ * IDA_RES_FAIL < 0
+ * IDA_LSOLVE_FAIL < 0
+ * IDA_LSETUP_FAIL < 0
+ * IDA_QRHS_FAIL < 0
+ *
+ * --error test failure--
+ * ERROR_TEST_FAIL > 0
+ *
+ * Possible kflag values (output):
+ *
+ * --recoverable--
+ * PREDICT_AGAIN
+ *
+ * --nonrecoverable--
+ * IDA_CONSTR_FAIL
+ * IDA_REP_RES_ERR
+ * IDA_ERR_FAIL
+ * IDA_CONV_FAIL
+ * IDA_RES_FAIL
+ * IDA_LSETUP_FAIL
+ * IDA_LSOLVE_FAIL
+ * IDA_QRHS_FAIL
+ * IDA_REP_QRHS_ERR
+ */
+
+static int IDAHandleNFlag(IDAMem IDA_mem, int nflag, realtype err_k, realtype err_km1,
+ long int *ncfnPtr, int *ncfPtr, long int *netfPtr, int *nefPtr)
+{
+ realtype err_knew;
+
+ phase = 1;
+
+ if (nflag != ERROR_TEST_FAIL) {
+
+ /*-----------------------
+ Nonlinear solver failed
+ -----------------------*/
+
+ (*ncfPtr)++; /* local counter for convergence failures */
+ (*ncfnPtr)++; /* global counter for convergence failures */
+
+ if (nflag < 0) { /* nonrecoverable failure */
+
+ return(nflag);
+
+ } else { /* recoverable failure */
+
+ /* 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;
+
+ /* Test if there were too many convergence failures */
+ if (*ncfPtr < 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);
+ else if (nflag == IDA_QSRHS_RECVR) return(IDA_REP_QSRHS_ERR);
+ else if (nflag == IDA_CONSTR_RECVR) return(IDA_CONSTR_FAIL);
+ else return(IDA_CONV_FAIL);
+ }
+
+ } else {
+
+ /*-----------------
+ Error Test failed
+ -----------------*/
+
+ (*nefPtr)++; /* local counter for error test failures */
+ (*netfPtr)++; /* global counter for error test failures */
+
+ if (*nefPtr == 1) {
+
+ /* 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;
+
+ kk = knew;
+ rr = PT9 * RPowerR( TWO * err_knew + PT0001,(-ONE/(kk+1)) );
+ rr = MAX(QUARTER, MIN(PT9,rr));
+ hh *=rr;
+ return(PREDICT_AGAIN);
+
+ } else if (*nefPtr == 2) {
+
+ /* 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;
+ return(PREDICT_AGAIN);
+
+ } else if (*nefPtr < 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;
+ return(PREDICT_AGAIN);
+
+ } else {
+
+ /* Too many error test failures */
+ return(IDA_ERR_FAIL);
+
+ }
+
+ }
+
+}
+
+/*
+ * IDAReset
+ *
+ * This routine is called only if we need to predict again at the
+ * very first step. In such a case, reset phi[1] and psi[0].
+ */
+
+static void IDAReset(IDAMem IDA_mem)
+{
+ int is;
+
+ psi[0] = hh;
+
+ N_VScale(rr, phi[1], phi[1]);
+
+ if (quadr)
+ N_VScale(rr, phiQ[1], phiQ[1]);
+
+ if (sensi)
+ for(is=0;is<Ns;is++)
+ N_VScale(rr, phiS[1][is], phiS[1][is]);
+
+ if (quadr_sensi)
+ for(is=0;is<Ns;is++)
+ N_VScale(rr, phiQS[1][is], phiQS[1][is]);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Function called after a successful step
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * IDACompleteStep
+ *
+ * This routine completes a successful step. It increments nst,
+ * saves the stepsize and order used, makes the final selection of
+ * stepsize and order for the next step, and updates the phi array.
+ * Its return value is IDA_SUCCESS = 0.
+ */
+
+static void IDACompleteStep(IDAMem IDA_mem, realtype err_k, realtype err_km1)
+{
+ int j, is, kdiff, action;
+ realtype terr_k, terr_km1, terr_kp1;
+ realtype err_knew, err_kp1;
+ realtype enorm, tmp, hnew;
+ N_Vector tempvQ, *tempvS;
+
+ nst++;
+ kdiff = kk - kused;
+ kused = kk;
+ hused = hh;
+
+ if ( (knew == kk-1) || (kk == maxord) ) 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
+ the stepsize. During these steps, phase = 0. Thereafter, phase = 1, and
+ stepsize and order are set by the usual local error algorithm.
+
+ 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 = ABS(hnew)*hmax_inv) > ONE ) hnew /= tmp;
+ hh = hnew;
+ }
+
+ } else {
+
+ action = UNSET;
+
+ /* 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;}
+
+ /* 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);
+
+ if (errconQ) {
+ tempvQ = ypQ;
+ N_VLinearSum (ONE, eeQ, -ONE, phiQ[kk+1], tempvQ);
+ enorm = IDAQuadWrmsNormUpdate(IDA_mem, enorm, tempvQ, 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 (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);
+ }
+ err_kp1= enorm/(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;
+
+ if (kk == 1) {
+ if (terr_kp1 >= HALF * terr_k) {action = MAINTAIN; goto takeaction;}
+ else {action = RAISE; goto takeaction;}
+ } else {
+ terr_km1 = kk * err_km1;
+ if (terr_km1 <= MIN(terr_k, terr_kp1)) {action = LOWER; goto takeaction;}
+ else if (terr_kp1 >= terr_k) {action = MAINTAIN; goto takeaction;}
+ else {action = RAISE; goto takeaction;}
+ }
+
+ 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; }
+
+ /* 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 = RPowerR( (TWO * err_knew + PT0001) , (-ONE/(kk+1) ) );
+
+ if (rr >= TWO) {
+ hnew = TWO * hh;
+ if( (tmp = ABS(hnew)*hmax_inv) > ONE ) hnew /= tmp;
+ } else if (rr <= ONE ) {
+ rr = MAX(HALF, MIN(PT9,rr));
+ hnew = hh * rr;
+ }
+
+ hh = hnew;
+
+ } /* end of phase if block */
+
+ /* Save ee etc. for possible order increase on next step */
+
+ if (kused < maxord) {
+
+ N_VScale(ONE, ee, phi[kused+1]);
+
+ if (quadr)
+ N_VScale(ONE, eeQ, phiQ[kused+1]);
+
+ if (sensi)
+ for (is=0; is<Ns; is++)
+ N_VScale(ONE, eeS[is], phiS[kused+1][is]);
+
+ if (quadr_sensi)
+ for (is=0; is<Ns; is++)
+ N_VScale(ONE, eeQS[is], phiQS[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]);
+ }
+ }
+
+ 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]);
+ }
+ }
+
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Norm functions
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * IDAWrmsNorm
+ *
+ * Returns the WRMS norm of vector x with weights w.
+ * If mask = TRUE, 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 = suppressalg otherwise.
+ */
+
+realtype IDAWrmsNorm(IDAMem IDA_mem, N_Vector x, N_Vector w,
+ booleantype mask)
+{
+ realtype nrm;
+
+ if (mask) nrm = N_VWrmsNormMask(x, w, id);
+ else nrm = N_VWrmsNorm(x, w);
+
+ return(nrm);
+}
+
+/*
+ * IDASensWrmsNorm
+ *
+ * This routine returns the maximum over the weighted root mean
+ * square norm of xS with weight vectors wS:
+ *
+ * max { wrms(xS[0],wS[0]) ... wrms(xS[Ns-1],wS[Ns-1]) }
+ *
+ * Called by IDASensUpdateNorm or directly in the IDA_STAGGERED approach
+ * during the NLS solution and before the error test.
+ *
+ * Declared global for use in the computation of IC for sensitivities.
+ */
+
+realtype IDASensWrmsNorm(IDAMem IDA_mem, N_Vector *xS, N_Vector *wS,
+ booleantype mask)
+{
+ int is;
+ realtype nrm, snrm;
+
+ nrm = IDAWrmsNorm(IDA_mem, xS[0], wS[0], mask);
+ for (is=1; is<Ns; is++) {
+ snrm = IDAWrmsNorm(IDA_mem, xS[is], wS[is], mask);
+ if ( snrm > nrm ) nrm = snrm;
+ }
+
+ return (nrm);
+}
+
+/*
+ * IDAQuadSensWrmsNorm
+ *
+ * This routine returns the maximum over the weighted root mean
+ * square norm of xQS with weight vectors wQS:
+ *
+ * max { wrms(xQS[0],wQS[0]) ... wrms(xQS[Ns-1],wQS[Ns-1]) }
+ */
+
+static realtype IDAQuadSensWrmsNorm(IDAMem IDA_mem, N_Vector *xQS, N_Vector *wQS)
+{
+ int is;
+ realtype nrm, snrm;
+
+ nrm = N_VWrmsNorm(xQS[0], wQS[0]);
+ for (is=1; is<Ns; is++) {
+ snrm = N_VWrmsNorm(xQS[is], wQS[is]);
+ if ( snrm > nrm ) nrm = snrm;
+ }
+ return (nrm);
+}
+
+/*
+ * IDAQuadWrmsNormUpdate
+ *
+ * Updates the norm old_nrm to account for all quadratures.
+ */
+
+static realtype IDAQuadWrmsNormUpdate(IDAMem IDA_mem, realtype old_nrm,
+ N_Vector xQ, N_Vector wQ)
+{
+ realtype qnrm;
+
+ qnrm = N_VWrmsNorm(xQ, wQ);
+ if (old_nrm > qnrm) return(old_nrm);
+ else return(qnrm);
+}
+
+/*
+ * IDASensWrmsNormUpdate
+ *
+ * Updates the norm old_nrm to account for all sensitivities.
+ *
+ * This function is declared global since it is used for finding
+ * IC for sensitivities,
+ */
+
+realtype IDASensWrmsNormUpdate(IDAMem IDA_mem, realtype old_nrm,
+ N_Vector *xS, N_Vector *wS,
+ booleantype mask)
+{
+ realtype snrm;
+
+ snrm = IDASensWrmsNorm(IDA_mem, xS, wS, mask);
+ if (old_nrm > snrm) return(old_nrm);
+ else return(snrm);
+}
+
+static realtype IDAQuadSensWrmsNormUpdate(IDAMem IDA_mem, realtype old_nrm,
+ N_Vector *xQS, N_Vector *wQS)
+{
+ realtype qsnrm;
+ int is;
+
+ qsnrm = old_nrm;
+
+ for (is=0; is<Ns; is++) {
+ old_nrm = N_VWrmsNorm(xQS[is], wQS[is]);
+ if(old_nrm > qsnrm) qsnrm = old_nrm;
+ }
+ return(qsnrm);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Functions for rootfinding
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * IDARcheck1
+ *
+ * This routine completes the initialization of rootfinding memory
+ * information, and checks whether g has a zero both at and very near
+ * the initial point of the IVP.
+ *
+ * This routine returns an int equal to:
+ * IDA_RTFUNC_FAIL < 0 if the g function failed, or
+ * IDA_SUCCESS = 0 otherwise.
+ */
+
+static int IDARcheck1(IDAMem IDA_mem)
+{
+ int i, retval;
+ realtype smallh, hratio, tplus;
+ booleantype zroot;
+
+ for (i = 0; i < nrtfn; i++) iroots[i] = 0;
+ tlo = tn;
+ ttol = (ABS(tn) + ABS(hh))*uround*HUNDRED;
+
+ /* Evaluate g at initial t and check for zero values. */
+ retval = gfun (tlo, phi[0], phi[1], glo, user_data);
+ nge = 1;
+ if (retval != 0) return(IDA_RTFUNC_FAIL);
+
+ zroot = FALSE;
+ for (i = 0; i < nrtfn; i++) {
+ if (ABS(glo[i]) == ZERO) {
+ zroot = TRUE;
+ gactive[i] = FALSE;
+ }
+ }
+ if (!zroot) return(IDA_SUCCESS);
+
+ /* Some g_i is zero at t0; look at g at t0+(small increment). */
+ hratio = MAX(ttol/ABS(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++;
+ 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] && ABS(ghi[i]) != ZERO) {
+ gactive[i] = TRUE;
+ glo[i] = ghi[i];
+ }
+ }
+ return(IDA_SUCCESS);
+}
+
+/*
+ * IDARcheck2
+ *
+ * This routine checks for exact zeros of g at the last root found,
+ * if the last return was a root. It then checks for a close pair of
+ * zeros (an error condition), and for a new root at a nearby point.
+ * The array glo = g(tlo) at the left endpoint of the search interval
+ * is adjusted if necessary to assure that all g_i are nonzero
+ * there, before returning to do a root search in the interval.
+ *
+ * On entry, tlo = tretlast is the last value of tret returned by
+ * IDASolve. This may be the previous tn, the previous tout value,
+ * or the last root location.
+ *
+ * This routine returns an int equal to:
+ * IDA_RTFUNC_FAIL (<0) if the g function failed, or
+ * CLOSERT (>0) if a close pair of zeros was found, or
+ * RTFOUND (>0) if a new zero of g was found near tlo, or
+ * IDA_SUCCESS (=0) otherwise.
+ */
+
+static int IDARcheck2(IDAMem IDA_mem)
+{
+ int i, retval;
+ realtype smallh, hratio, tplus;
+ booleantype zroot;
+
+ if (irfnd == 0) return(IDA_SUCCESS);
+
+ (void) IDAGetSolution(IDA_mem, tlo, yy, yp);
+ retval = gfun (tlo, yy, yp, glo, user_data);
+ 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 (ABS(glo[i]) == ZERO) {
+ zroot = TRUE;
+ iroots[i] = 1;
+ }
+ }
+ if (!zroot) return(IDA_SUCCESS);
+
+ /* One or more g_i has a zero at tlo. Check g at tlo+smallh. */
+ ttol = (ABS(tn) + ABS(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);
+ } else {
+ (void) IDAGetSolution(IDA_mem, tplus, yy, yp);
+ }
+ retval = gfun (tplus, yy, yp, ghi, user_data);
+ 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 (ABS(ghi[i]) == ZERO) {
+ if (iroots[i] == 1) return(CLOSERT);
+ zroot = TRUE;
+ iroots[i] = 1;
+ } else {
+ if (iroots[i] == 1) glo[i] = ghi[i];
+ }
+ }
+ if (zroot) return(RTFOUND);
+ return(IDA_SUCCESS);
+}
+
+/*
+ * IDARcheck3
+ *
+ * This routine interfaces to IDARootfind to look for a root of g
+ * between tlo and either tn or tout, whichever comes first.
+ * Only roots beyond tlo in the direction of integration are sought.
+ *
+ * This routine returns an int equal to:
+ * IDA_RTFUNC_FAIL (<0) if the g function failed, or
+ * RTFOUND (>0) if a root of g was found, or
+ * IDA_SUCCESS (=0) otherwise.
+ */
+
+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;
+ }
+
+ /* Get y and y' at thi. */
+ (void) IDAGetSolution(IDA_mem, thi, yy, yp);
+
+
+ /* Set ghi = g(thi) and call IDARootfind to search (tlo,thi) for roots. */
+ retval = gfun (thi, yy, yp, ghi, user_data);
+ nge++;
+ if (retval != 0) return(IDA_RTFUNC_FAIL);
+
+ ttol = (ABS(tn) + ABS(hh))*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;
+ }
+ tlo = trout;
+ for (i = 0; i < nrtfn; i++) glo[i] = 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);
+ return(RTFOUND);
+
+}
+
+/*
+ * IDARootfind
+ *
+ * This routine solves for a root of g(t) between tlo and thi, if
+ * one exists. Only roots of odd multiplicity (i.e. with a change
+ * of sign in one of the g_i), or exact zeros, are found.
+ * Here the sign of tlo - thi is arbitrary, but if multiple roots
+ * are found, the one closest to tlo is returned.
+ *
+ * The method used is the Illinois algorithm, a modified secant method.
+ * Reference: Kathie L. Hiebert and Lawrence F. Shampine, Implicitly
+ * Defined Output Points for Solutions of ODEs, Sandia National
+ * Laboratory Report SAND80-0180, February 1980.
+ *
+ * This routine uses the following parameters for communication:
+ *
+ * nrtfn = number of functions g_i, or number of components of
+ * the vector-valued function g(t). Input only.
+ *
+ * gfun = user-defined function for g(t). Its form is
+ * (void) gfun(t, y, yp, gt, user_data)
+ *
+ * rootdir = in array specifying the direction of zero-crossings.
+ * If rootdir[i] > 0, search for roots of g_i only if
+ * g_i is increasing; if rootdir[i] < 0, search for
+ * roots of g_i only if g_i is decreasing; otherwise
+ * always search for roots of g_i.
+ *
+ * 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
+ * both at the I.C. and at a small perturbation of them.
+ * gactive[i] is then set back on TRUE only after the
+ * corresponding g function moves away from 0.0.
+ *
+ * nge = cumulative counter for gfun calls.
+ *
+ * ttol = a convergence tolerance for trout. Input only.
+ * When a root at trout is found, it is located only to
+ * within a tolerance of ttol. Typically, ttol should
+ * be set to a value on the order of
+ * 100 * UROUND * max (ABS(tlo), ABS(thi))
+ * where UROUND is the unit roundoff of the machine.
+ *
+ * tlo, thi = endpoints of the interval in which roots are sought.
+ * On input, and must be distinct, but tlo - thi may
+ * be of either sign. The direction of integration is
+ * assumed to be from tlo to thi. On return, tlo and thi
+ * are the endpoints of the final relevant interval.
+ *
+ * glo, ghi = arrays of length nrtfn containing the vectors g(tlo)
+ * and g(thi) respectively. Input and output. On input,
+ * none of the glo[i] should be zero.
+ *
+ * trout = root location, if a root was found, or thi if not.
+ * Output only. If a root was found other than an exact
+ * zero of g, trout is the endpoint thi of the final
+ * interval bracketing the root, with size at most ttol.
+ *
+ * grout = array of length nrtfn containing g(trout) on return.
+ *
+ * iroots = int array of length nrtfn with root information.
+ * Output only. If a root was found, iroots indicates
+ * which components g_i have a root at trout. For
+ * i = 0, ..., nrtfn-1, iroots[i] = 1 if g_i has a root
+ * and g_i is increasing, iroots[i] = -1 if g_i has a
+ * root and g_i is decreasing, and iroots[i] = 0 if g_i
+ * has no roots or g_i varies in the direction opposite
+ * to that indicated by rootdir[i].
+ *
+ * This routine returns an int equal to:
+ * IDA_RTFUNC_FAIL (<0) if the g function failed, or
+ * RTFOUND = 1 if a root of g was found, or
+ * IDA_SUCCESS = 0 otherwise.
+ *
+ */
+
+static int IDARootfind(IDAMem IDA_mem)
+{
+ realtype alph, tmid, gfrac, maxfrac, fracint, fracsub;
+ int i, retval, imax, side, sideprev;
+ booleantype zroot, sgnchg;
+
+ imax = 0;
+
+ /* 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 (ABS(ghi[i]) == ZERO) {
+ if(rootdir[i]*glo[i] <= ZERO) {
+ zroot = TRUE;
+ }
+ } else {
+ if ( (glo[i]*ghi[i] < ZERO) && (rootdir[i]*glo[i] <= ZERO) ) {
+ gfrac = ABS(ghi[i]/(ghi[i] - glo[i]));
+ if (gfrac > maxfrac) {
+ sgnchg = TRUE;
+ maxfrac = gfrac;
+ imax = i;
+ }
+ }
+ }
+ }
+
+ /* 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];
+ if (!zroot) return(IDA_SUCCESS);
+ for (i = 0; i < nrtfn; i++) {
+ iroots[i] = 0;
+ if(!gactive[i]) continue;
+ if (ABS(ghi[i]) == ZERO) iroots[i] = glo[i] > 0 ? -1:1;
+ }
+ return(RTFOUND);
+ }
+
+ /* Initialize alph to avoid compiler warning */
+ alph = ONE;
+
+ /* A sign change was found. Loop to locate nearest root. */
+
+ side = 0; sideprev = -1;
+ loop { /* Looping point */
+
+ /* Set weight alph.
+ On the first two passes, set alph = 1. Thereafter, reset alph
+ according to the side (low vs high) of the subinterval in which
+ the sign change was found in the previous two passes.
+ If the sides were opposite, set alph = 1.
+ 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. */
+
+ if (sideprev == side) {
+ alph = (side == 2) ? alph*TWO : alph*HALF;
+ } else {
+ alph = ONE;
+ }
+
+ /* 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 (ABS(tmid - tlo) < HALF*ttol) {
+ fracint = ABS(thi - tlo)/ttol;
+ fracsub = (fracint > FIVE) ? PT1 : HALF/fracint;
+ tmid = tlo + fracsub*(thi - tlo);
+ }
+ if (ABS(thi - tmid) < HALF*ttol) {
+ fracint = ABS(thi - tlo)/ttol;
+ fracsub = (fracint > FIVE) ? PT1 : HALF/fracint;
+ tmid = thi - fracsub*(thi - tlo);
+ }
+
+ (void) IDAGetSolution(IDA_mem, tmid, yy, yp);
+ retval = gfun (tmid, yy, yp, grout, user_data);
+ 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;
+ sideprev = side;
+ for (i = 0; i < nrtfn; i++) {
+ if(!gactive[i]) continue;
+ if (ABS(grout[i]) == ZERO) {
+ if(rootdir[i]*glo[i] <= ZERO) {
+ zroot = TRUE;
+ }
+ } else {
+ if ( (glo[i]*grout[i] < ZERO) && (rootdir[i]*glo[i] <= ZERO) ) {
+ gfrac = ABS(grout[i]/(grout[i] - glo[i]));
+ if (gfrac > maxfrac) {
+ sgnchg = TRUE;
+ maxfrac = gfrac;
+ imax = i;
+ }
+ }
+ }
+ }
+ if (sgnchg) {
+ /* Sign change found in (tlo,tmid); replace thi with tmid. */
+ thi = tmid;
+ for (i = 0; i < nrtfn; i++) ghi[i] = grout[i];
+ side = 1;
+ /* Stop at root thi if converged; otherwise loop. */
+ if (ABS(thi - tlo) <= 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];
+ 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];
+ side = 2;
+ /* Stop at root thi if converged; otherwise loop back. */
+ if (ABS(thi - tlo) <= 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 ( (ABS(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;
+ }
+ return(RTFOUND);
+}
+
+/*
+ * =================================================================
+ * Internal DQ approximations for sensitivity RHS
+ * =================================================================
+ */
+
+#undef Ns
+#undef yy
+#undef yp
+#undef yyS
+#undef ypS
+#undef user_dataS
+
+/*
+ * IDASensResDQ
+ *
+ * IDASensRhsDQ computes the residuals of the sensitivity equations
+ * by finite differences. It is of type IDASensResFn.
+ * Returns 0 if successful, <0 if an unrecoverable failure occurred,
+ * >0 for a recoverable error.
+ */
+
+int IDASensResDQ(int Ns, realtype t,
+ N_Vector yy, N_Vector yp, N_Vector resval,
+ N_Vector *yyS, N_Vector *ypS, N_Vector *resvalS,
+ void *user_dataS,
+ N_Vector ytemp, N_Vector yptemp, N_Vector restemp)
+{
+ int retval, is;
+
+ for (is=0; is<Ns; is++) {
+ retval = IDASensRes1DQ(Ns, t,
+ yy, yp, resval,
+ is, yyS[is], ypS[is], resvalS[is],
+ user_dataS,
+ ytemp, yptemp, restemp);
+ if (retval != 0) return(retval);
+ }
+ return(0);
+}
+
+/*
+ * IDASensRes1DQ
+ *
+ * IDASensRes1DQ computes the residual of the is-th sensitivity
+ * equation by finite differences.
+ *
+ * Returns 0 if successful or the return value of res if res fails
+ * (<0 if res fails unrecoverably, >0 if res has a recoverable error).
+ */
+
+static int IDASensRes1DQ(int Ns, realtype t,
+ N_Vector yy, N_Vector yp, N_Vector resval,
+ int is,
+ N_Vector yyS, N_Vector ypS, N_Vector resvalS,
+ void *user_dataS,
+ N_Vector ytemp, N_Vector yptemp, N_Vector restemp)
+{
+ IDAMem IDA_mem;
+ int method;
+ int which;
+ int retval;
+ realtype psave, pbari;
+ realtype del , rdel;
+ realtype Delp, rDelp, r2Delp;
+ realtype Dely, rDely, r2Dely;
+ realtype Del , rDel , r2Del ;
+ realtype norms, ratio;
+
+ /* user_dataS points to IDA_mem */
+ IDA_mem = (IDAMem) user_dataS;
+
+ /* Set base perturbation del */
+ del = RSqrt(MAX(rtol, uround));
+ rdel = ONE/del;
+
+ pbari = pbar[is];
+
+ which = plist[is];
+
+ psave = p[which];
+
+ Delp = pbari * del;
+ rDelp = ONE/Delp;
+ norms = N_VWrmsNorm(yyS, ewt) * pbari;
+ rDely = MAX(norms, rdel) / pbari;
+ Dely = ONE/rDely;
+
+ if (DQrhomax == ZERO) {
+ /* No switching */
+ method = (DQtype==IDA_CENTERED) ? CENTERED1 : FORWARD1;
+ } else {
+ /* switch between simultaneous/separate DQ */
+ ratio = Dely * rDelp;
+ if ( MAX(ONE/ratio, ratio) <= DQrhomax )
+ method = (DQtype==IDA_CENTERED) ? CENTERED1 : FORWARD1;
+ else
+ method = (DQtype==IDA_CENTERED) ? CENTERED2 : FORWARD2;
+ }
+
+ switch (method) {
+
+ case CENTERED1:
+
+ Del = MIN(Dely, Delp);
+ r2Del = HALF/Del;
+
+ /* Forward perturb y, y' and parameter */
+ N_VLinearSum(Del, yyS, ONE, yy, ytemp);
+ N_VLinearSum(Del, ypS, ONE, yp, yptemp);
+ p[which] = psave + Del;
+
+ /* Save residual in resvalS */
+ retval = res(t, ytemp, yptemp, resvalS, user_data);
+ 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;
+
+ /* Save residual in restemp */
+ retval = res(t, ytemp, yptemp, restemp, user_data);
+ nreS++;
+ if (retval != 0) return(retval);
+
+ /* Estimate the residual for the i-th sensitivity equation */
+ N_VLinearSum(r2Del, resvalS, -r2Del, restemp, resvalS);
+
+ break;
+
+ case CENTERED2:
+
+ r2Delp = HALF/Delp;
+ r2Dely = HALF/Dely;
+
+ /* Forward perturb y and y' */
+ N_VLinearSum(Dely, yyS, ONE, yy, ytemp);
+ N_VLinearSum(Dely, ypS, ONE, yp, yptemp);
+
+ /* Save residual in resvalS */
+ retval = res(t, ytemp, yptemp, resvalS, user_data);
+ nreS++;
+ if (retval != 0) return(retval);
+
+ /* Backward perturb y and y' */
+ N_VLinearSum(-Dely, yyS, ONE, yy, ytemp);
+ N_VLinearSum(-Dely, ypS, ONE, yp, yptemp);
+
+ /* Save residual in restemp */
+ retval = res(t, ytemp, yptemp, restemp, user_data);
+ 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;
+
+ /* Save residual in ytemp */
+ retval = res(t, yy, yp, ytemp, user_data);
+ nreS++;
+ if (retval != 0) return(retval);
+
+ /* Backward perturb parameter */
+ p[which] = psave - Delp;
+
+ /* Save residual in yptemp */
+ retval = res(t, yy, yp, yptemp, user_data);
+ nreS++;
+ if (retval != 0) return(retval);
+
+ /* Save the second difference quotient in restemp */
+ N_VLinearSum(r2Delp, ytemp, -r2Delp, yptemp, restemp);
+
+ /* Add the difference quotients for the sensitivity residual */
+ N_VLinearSum(ONE, resvalS, ONE, restemp, resvalS);
+
+ break;
+
+ case FORWARD1:
+
+ Del = MIN(Dely, Delp);
+ rDel = ONE/Del;
+
+ /* Forward perturb y, y' and parameter */
+ N_VLinearSum(Del, yyS, ONE, yy, ytemp);
+ N_VLinearSum(Del, ypS, ONE, yp, yptemp);
+ p[which] = psave + Del;
+
+ /* Save residual in resvalS */
+ retval = res(t, ytemp, yptemp, resvalS, user_data);
+ nreS++;
+ if (retval != 0) return(retval);
+
+ /* Estimate the residual for the i-th sensitivity equation */
+ N_VLinearSum(rDel, resvalS, -rDel, resval, resvalS);
+
+ break;
+
+ case FORWARD2:
+
+ /* Forward perturb y and y' */
+ N_VLinearSum(Dely, yyS, ONE, yy, ytemp);
+ N_VLinearSum(Dely, ypS, ONE, yp, yptemp);
+
+ /* Save residual in resvalS */
+ retval = res(t, ytemp, yptemp, resvalS, user_data);
+ 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;
+
+ /* Save residual in restemp */
+ retval = res(t, yy, yp, restemp, user_data);
+ nreS++;
+ if (retval != 0) return(retval);
+
+ /* Save the second difference quotient in restemp */
+ N_VLinearSum(rDelp, restemp, -rDelp, resval, restemp);
+
+ /* Add the difference quotients for the sensitivity residual */
+ N_VLinearSum(ONE, resvalS, ONE, restemp, resvalS);
+
+ break;
+
+ }
+
+ /* Restore original value of parameter */
+ p[which] = psave;
+
+ return(0);
+
+}
+
+
+/* IDAQuadSensRhsInternalDQ - internal IDAQuadSensRhsFn
+ *
+ * IDAQuadSensRhsInternalDQ computes right hand side of all quadrature
+ * sensitivity equations by finite differences. All work is actually
+ * done in IDAQuadSensRhs1InternalDQ.
+ */
+
+static int IDAQuadSensRhsInternalDQ(int Ns, realtype t,
+ N_Vector yy, N_Vector yp,
+ N_Vector *yyS, N_Vector *ypS,
+ N_Vector rrQ, N_Vector *resvalQS,
+ void *ida_mem,
+ N_Vector yytmp, N_Vector yptmp, N_Vector tmpQS)
+{
+ IDAMem IDA_mem;
+ int is, retval;
+
+ /* cvode_mem is passed here as user data */
+ IDA_mem = (IDAMem) ida_mem;
+
+ for (is=0; is<Ns; is++) {
+ retval = IDAQuadSensRhs1InternalDQ(IDA_mem, is, t,
+ yy, yp, yyS[is], ypS[is],
+ rrQ, resvalQS[is],
+ yytmp, yptmp, tmpQS);
+ if (retval!=0) return(retval);
+ }
+
+ return(0);
+}
+
+static int IDAQuadSensRhs1InternalDQ(IDAMem IDA_mem, int is, realtype t,
+ N_Vector yy, N_Vector yp,
+ N_Vector yyS, N_Vector ypS,
+ N_Vector resvalQ, N_Vector resvalQS,
+ N_Vector yytmp, N_Vector yptmp, N_Vector tmpQS)
+{
+ int retval, method;
+ int nfel = 0, which;
+ realtype psave, pbari;
+ realtype del , rdel;
+ realtype Delp, rDelp;
+ realtype Dely, rDely;
+ realtype Del , r2Del ;
+ realtype norms;
+
+ del = RSqrt(MAX(rtol, uround));
+ rdel = ONE/del;
+
+ pbari = pbar[is];
+
+ which = plist[is];
+
+ psave = p[which];
+
+ Delp = pbari * del;
+ rDelp = ONE/Delp;
+ norms = N_VWrmsNorm(yyS, ewt) * pbari;
+ rDely = MAX(norms, rdel) / pbari;
+ Dely = ONE/rDely;
+
+ method = (DQtype==IDA_CENTERED) ? CENTERED1 : FORWARD1;
+
+ switch(method) {
+
+ case CENTERED1:
+
+ Del = MIN(Dely, Delp);
+ r2Del = HALF/Del;
+
+ N_VLinearSum(ONE, yy, Del, yyS, yytmp);
+ N_VLinearSum(ONE, yp, Del, ypS, yptmp);
+ p[which] = psave + Del;
+
+ retval = rhsQ(t, yytmp, yptmp, resvalQS, 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;
+
+ retval = rhsQ(t, yytmp, yptmp, tmpQS, user_data);
+ nfel++;
+ if (retval != 0) return(retval);
+
+ N_VLinearSum(r2Del, resvalQS, -r2Del, tmpQS, resvalQS);
+
+ break;
+
+ case FORWARD1:
+
+ Del = MIN(Dely, Delp);
+ rdel = ONE/Del;
+
+ N_VLinearSum(ONE, yy, Del, yyS, yytmp);
+ N_VLinearSum(ONE, yp, Del, ypS, yptmp);
+ p[which] = psave + Del;
+
+ retval = rhsQ(t, yytmp, yptmp, resvalQS, user_data);
+ nfel++;
+ if (retval != 0) return(retval);
+
+ N_VLinearSum(rdel, resvalQS, -rdel, resvalQ, resvalQS);
+
+ break;
+ }
+
+ p[which] = psave;
+ /* Increment counter nrQeS */
+ nrQeS += nfel;
+
+ return(0);
+}
+
+
+/*
+ * =================================================================
+ * IDA Error message handling functions
+ * =================================================================
+ */
+
+/*
+ * IDAProcessError is a high level error handling function
+ * - if ida_mem==NULL it prints the error message to stderr
+ * - otherwise, it sets-up and calls the error hadling function
+ * 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, ...)
+{
+ va_list ap;
+ char msg[256];
+
+ /* Initialize the argument pointer variable
+ (msgfmt is the last required argument to IDAProcessError) */
+
+ va_start(ap, msgfmt);
+
+ if (IDA_mem == NULL) { /* We write to stderr */
+
+#ifndef NO_FPRINTF_OUTPUT
+ fprintf(stderr, "\n[%s ERROR] %s\n ", module, fname);
+ fprintf(stderr, msgfmt);
+ fprintf(stderr, "\n\n");
+#endif
+
+ } else {
+ /* We can call ehfun */
+
+ /* Compose the message */
+ vsprintf(msg, msgfmt, ap);
+
+ /* Call ehfun */
+ ehfun(error_code, module, fname, msg, eh_data);
+ }
+
+ /* Finalize argument processing */
+ va_end(ap);
+
+ return;
+
+}
+
+/* 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)
+{
+ IDAMem IDA_mem;
+ char err_type[10];
+
+ /* data points to IDA_mem here */
+
+ IDA_mem = (IDAMem) data;
+
+ if (error_code == IDA_WARNING)
+ sprintf(err_type,"WARNING");
+ else
+ 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);
+ }
+#endif
+
+ return;
+}
diff --git a/src/idas/idas_band.c b/src/idas/idas_band.c
new file mode 100644
index 0000000..5589249
--- /dev/null
+++ b/src/idas/idas_band.c
@@ -0,0 +1,424 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.14 $
+ * $Date: 2011/03/23 21:12:45 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Alan C. Hindmarsh and Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * 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 void 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;
+ int flag;
+
+ /* 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) flag = 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;
+
+ 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 = MIN(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 */
+ 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, "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 for the IDAS data of the backward problem. */
+ 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 void IDABandFreeB(IDABMem IDAB_mem)
+{
+ IDADlsMemB idadlsB_mem;
+
+ idadlsB_mem = (IDADlsMemB) IDAB_mem->ida_lmem;
+
+ free(idadlsB_mem);
+}
+
diff --git a/src/idas/idas_bbdpre.c b/src/idas/idas_bbdpre.c
new file mode 100644
index 0000000..774cb9f
--- /dev/null
+++ b/src/idas/idas_bbdpre.c
@@ -0,0 +1,828 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.11 $
+ * $Date: 2011/03/23 21:12:45 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Alan C. Hindmarsh and Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * 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.
+ *
+ * NOTE: With only one processor in use, a banded matrix results
+ * rather than a block-diagonal matrix with banded blocks.
+ * Diagonal blocking occurs at the processor level.
+ * -----------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#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>
+
+#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);
+
+/* Prototype for IDABBDPrecFree */
+
+static void 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(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);
+
+/* Prototype for the pfree routine for backward problems. */
+
+static void 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
+ * -----------------------------------------------------------------
+ */
+
+int IDABBDPrecInit(void *ida_mem, long int Nlocal,
+ long int mudq, long int mldq,
+ long int mukeep, long int 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;
+ int flag;
+
+ if (ida_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 */
+ if (IDA_mem->ida_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);
+ return(IDASPILS_ILL_INPUT);
+ }
+
+ /* Allocate data memory. */
+ pdata = NULL;
+ pdata = (IBBDPrecData) malloc(sizeof *pdata);
+ if (pdata == NULL) {
+ IDAProcessError(IDA_mem, IDASPILS_MEM_FAIL, "IDABBDPRE", "IDABBDPrecInit", MSGBBD_MEM_FAIL);
+ return(IDASPILS_MEM_FAIL);
+ }
+
+ /* Set pointers to glocal and gcomm; load half-bandwidths. */
+ pdata->ida_mem = IDA_mem;
+ pdata->glocal = Gres;
+ pdata->gcomm = Gcomm;
+ pdata->mudq = MIN(Nlocal-1, MAX(0, mudq));
+ pdata->mldq = MIN(Nlocal-1, MAX(0, mldq));
+ muk = MIN(Nlocal-1, MAX(0, mukeep));
+ mlk = MIN(Nlocal-1, MAX(0, mlkeep));
+ pdata->mukeep = muk;
+ pdata->mlkeep = mlk;
+
+ /* Set extended upper half-bandwidth for PP (required for pivoting). */
+ storage_mu = MIN(Nlocal-1, muk+mlk);
+
+ /* Allocate memory for preconditioner matrix. */
+ pdata->PP = NULL;
+ pdata->PP = NewBandMat(Nlocal, muk, mlk, storage_mu);
+ if (pdata->PP == NULL) {
+ free(pdata); pdata = NULL;
+ 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);
+ free(pdata); pdata = NULL;
+ 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);
+ free(pdata); pdata = NULL;
+ IDAProcessError(IDA_mem, IDASPILS_MEM_FAIL, "IDABBDPRE", "IDABBDPrecInit", MSGBBD_MEM_FAIL);
+ return(IDASPILS_MEM_FAIL);
+ }
+ pdata->tempv4 = tempv4;
+
+ /* Set rel_yy based on input value dq_rel_yy (0 implies default). */
+ pdata->rel_yy = (dq_rel_yy > ZERO) ? dq_rel_yy : RSqrt(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->nge = 0;
+
+ /* Overwrite the pdata field in the SPILS memory */
+ idaspils_mem->s_pdata = pdata;
+
+ /* Attach the pfree function */
+ idaspils_mem->s_pfree = IDABBDPrecFree;
+
+ /* Attach preconditioner solve and setup functions */
+ flag = IDASpilsSetPreconditioner(ida_mem, IDABBDPrecSetup, IDABBDPrecSolve);
+
+ return(flag);
+}
+
+int IDABBDPrecReInit(void *ida_mem,
+ long int mudq, long int mldq,
+ realtype dq_rel_yy)
+{
+ IDAMem IDA_mem;
+ IDASpilsMem idaspils_mem;
+ IBBDPrecData pdata;
+ long int Nlocal;
+
+ if (ida_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 */
+ if (IDA_mem->ida_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);
+ return(IDASPILS_PMEM_NULL);
+ }
+ pdata = (IBBDPrecData) idaspils_mem->s_pdata;
+
+ /* Load half-bandwidths. */
+ Nlocal = pdata->n_local;
+ pdata->mudq = MIN(Nlocal-1, MAX(0, mudq));
+ pdata->mldq = MIN(Nlocal-1, MAX(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 : RSqrt(uround);
+
+ /* Re-initialize nge */
+ pdata->nge = 0;
+
+ return(IDASPILS_SUCCESS);
+}
+
+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);
+ 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);
+ 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);
+ return(IDASPILS_PMEM_NULL);
+ }
+ pdata = (IBBDPrecData) idaspils_mem->s_pdata;
+
+ *lenrwBBDP = pdata->rpwsize;
+ *leniwBBDP = pdata->ipwsize;
+
+ return(IDASPILS_SUCCESS);
+}
+
+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);
+ 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);
+ 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);
+ return(IDASPILS_PMEM_NULL);
+ }
+ pdata = (IBBDPrecData) idaspils_mem->s_pdata;
+
+ *ngevalsBBDP = pdata->nge;
+
+ return(IDASPILS_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 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).
+ * -----------------------------------------------------------------
+ */
+
+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)
+{
+ int retval;
+ long int ier;
+ IBBDPrecData pdata;
+ IDAMem IDA_mem;
+
+ 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);
+ if (retval < 0) {
+ IDAProcessError(IDA_mem, -1, "IDABBDPRE", "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);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * 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)
+{
+ IBBDPrecData pdata;
+ realtype *zd;
+
+ pdata = (IBBDPrecData) bbd_data;
+
+ /* Copy rvec to zvec, do the backsolve, and return. */
+ N_VScale(ONE, rvec, zvec);
+
+ zd = N_VGetArrayPointer(zvec);
+
+ BandGBTRS(PP, lpivots, zd);
+
+ return(0);
+}
+
+
+static void IDABBDPrecFree(IDAMem IDA_mem)
+{
+ IDASpilsMem idaspils_mem;
+ IBBDPrecData pdata;
+
+ if (IDA_mem->ida_lmem == NULL) return;
+ idaspils_mem = (IDASpilsMem) IDA_mem->ida_lmem;
+
+ if (idaspils_mem->s_pdata == NULL) return;
+ pdata = (IBBDPrecData) idaspils_mem->s_pdata;
+
+ DestroyMat(PP);
+ DestroyArray(lpivots);
+ N_VDestroy(tempv4);
+
+ free(pdata);
+ pdata = NULL;
+}
+
+
+#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).
+ * -----------------------------------------------------------------
+ */
+
+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;
+ realtype *ydata, *ypdata, *ytempdata, *yptempdata, *grefdata, *gtempdata;
+ realtype *cnsdata = NULL, *ewtdata;
+ realtype *col_j, conj, yj, ypj, ewtj;
+
+ 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);
+ 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 (retval != 0) return(retval);
+ }
+
+ retval = glocal(Nlocal, tt, yy, yp, gref, user_data);
+ nge++;
+ if (retval != 0) return(retval);
+
+
+ /* Set bandwidth and number of column groups for band differencing. */
+
+ width = mldq + mudq + 1;
+ ngroups = MIN(width, Nlocal);
+
+ /* Loop over groups. */
+ for(group = 1; group <= ngroups; group++) {
+
+ /* Loop over the components in this group. */
+ for(j = group-1; j < Nlocal; j += width) {
+ yj = ydata[j];
+ ypj = ypdata[j];
+ ewtj = ewtdata[j];
+
+ /* 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*MAX(ABS(yj), MAX( ABS(hh*ypj), ONE/ewtj));
+ if (hh*ypj < ZERO) inc = -inc;
+ inc = (yj + inc) - yj;
+
+ /* Adjust sign(inc) again if yj has an inequality constraint. */
+ if (constraints != NULL) {
+ conj = cnsdata[j];
+ if (ABS(conj) == ONE) {if ((yj+inc)*conj < ZERO) inc = -inc;}
+ else if (ABS(conj) == TWO) {if ((yj+inc)*conj <= ZERO) inc = -inc;}
+ }
+
+ /* Increment yj and ypj. */
+ ytempdata[j] += inc;
+ yptempdata[j] += cj*inc;
+
+ }
+
+ /* Evaluate G with incremented y and yp arguments. */
+
+ retval = glocal(Nlocal, tt, ytemp, yptemp, gtemp, user_data);
+ 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) {
+ yj = ytempdata[j] = ydata[j];
+ ypj = yptempdata[j] = ypdata[j];
+ ewtj = ewtdata[j];
+
+ /* Set increment inc as before .*/
+ inc = rel_yy*MAX(ABS(yj), MAX( ABS(hh*ypj), ONE/ewtj));
+ if (hh*ypj < ZERO) inc = -inc;
+ inc = (yj + inc) - yj;
+ if (constraints != NULL) {
+ conj = cnsdata[j];
+ if (ABS(conj) == ONE) {if ((yj+inc)*conj < ZERO) inc = -inc;}
+ else if (ABS(conj) == TWO) {if ((yj+inc)*conj <= ZERO) inc = -inc;}
+ }
+
+ /* Form difference quotients and load into PP. */
+ inc_inv = ONE/inc;
+ col_j = BAND_COL(PP,j);
+ i1 = MAX(0, j-mukeep);
+ i2 = MIN(j+mlkeep, Nlocal-1);
+ for(i = i1; i <= i2; i++) BAND_COL_ELEM(col_j,i,j) =
+ inc_inv * (gtempdata[i] - grefdata[i]);
+ }
+ }
+
+ return(0);
+}
+
+
+/*
+ * ================================================================
+ *
+ * PART II - backward problems
+ *
+ * ================================================================
+ */
+
+/* Readability replacements */
+
+#define yyTmp (IDAADJ_mem->ia_yyTmp)
+#define ypTmp (IDAADJ_mem->ia_ypTmp)
+#define noInterp (IDAADJ_mem->ia_noInterp)
+
+/*
+ * ----------------------------------------------------------------
+ * 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)
+{
+ IDAMem IDA_mem;
+ IDAadjMem IDAADJ_mem;
+ IDABMem IDAB_mem;
+ IDABBDPrecDataB idabbdB_mem;
+ void *ida_memB;
+ int flag;
+
+ /* Check if ida_mem is allright. */
+ if (ida_mem == NULL) {
+ IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDABBDPRE", "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);
+ 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);
+ 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;
+ }
+ /* ida_mem corresponding to 'which' problem. */
+ 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);
+ if (flag != IDA_SUCCESS) return(flag);
+
+ /* Allocate memory for IDABBDPrecDataB to store the user-provided
+ * 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);
+ return(IDASPILS_MEM_FAIL);
+ }
+
+ idabbdB_mem->glocalB = glocalB;
+ idabbdB_mem->gcommB = gcommB;
+
+
+ /* Attach pmem */
+ 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)
+{
+ IDAMem IDA_mem;
+ IDAadjMem IDAADJ_mem;
+ IDABMem IDAB_mem;
+ void *ida_memB;
+ int flag;
+
+ /* Check if ida_mem is allright. */
+ if (ida_mem == NULL) {
+ IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDABBDPRE", "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);
+ 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);
+ 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;
+ }
+ /* ida_mem corresponding to 'which' backward problem. */
+ ida_memB = (void *) IDAB_mem->IDA_mem;
+
+ flag = IDABBDPrecReInit(ida_memB, mudqB, mldqB, dq_rel_yyB);
+ return(flag);
+}
+
+static void IDABBDPrecFreeB(IDABMem IDAB_mem)
+{
+ free(IDAB_mem->ida_pmem);
+ IDAB_mem->ida_pmem = NULL;
+}
+
+/*
+ * ----------------------------------------------------------------
+ * Wrapper functions
+ * ----------------------------------------------------------------
+ */
+
+/*
+ * IDAAglocal
+ *
+ * This routine interfaces to the IDALocalFnB routine
+ * provided by the user.
+ */
+
+static int IDAAglocal(long int NlocalB, realtype tt,
+ N_Vector yyB, N_Vector ypB, N_Vector gvalB,
+ void *ida_mem)
+{
+ IDAMem IDA_mem;
+ IDAadjMem IDAADJ_mem;
+ IDABMem IDAB_mem;
+ IDABBDPrecDataB idabbdB_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 the preconditioner's memory. */
+ 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 (flag != IDA_SUCCESS) {
+ IDAProcessError(IDA_mem, -1, "IDABBDPRE", "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);
+
+}
+
+/*
+ * 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)
+{
+ IDAMem IDA_mem;
+ IDAadjMem IDAADJ_mem;
+ IDABMem IDAB_mem;
+ IDABBDPrecDataB idabbdB_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 the preconditioner's memory. */
+ idabbdB_mem = (IDABBDPrecDataB) IDAB_mem->ida_pmem;
+ 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 (flag != IDA_SUCCESS) {
+ IDAProcessError(IDA_mem, -1, "IDABBDPRE", "IDAAgcomm", MSGBBD_BAD_T);
+ return(-1);
+ }
+ }
+
+ /* Call user's adjoint CommFnB routine */
+ return idabbdB_mem->gcommB(NlocalB, tt, yyTmp,
+ ypTmp, yyB, ypB,
+ IDAB_mem->ida_user_data);
+}
diff --git a/src/idas/idas_bbdpre_impl.h b/src/idas/idas_bbdpre_impl.h
new file mode 100644
index 0000000..2794ad2
--- /dev/null
+++ b/src/idas/idas_bbdpre_impl.h
@@ -0,0 +1,110 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.6 $
+ * $Date: 2010/12/01 22:39:18 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Alan C. Hindmarsh and Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * 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
+ * and an IDASPILS linear solver.
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _IDASBBDPRE_IMPL_H
+#define _IDASBBDPRE_IMPL_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <idas/idas_bbdpre.h>
+#include <sundials/sundials_band.h>
+
+/*
+ * -----------------------------------------------------------------
+ * Definition of IBBDPrecData
+ * -----------------------------------------------------------------
+ */
+
+typedef struct IBBDPrecDataRec {
+
+ /* passed by user to IDABBDPrecAlloc and used by
+ IDABBDPrecSetup/IDABBDPrecSolve functions */
+
+ long int mudq, mldq, mukeep, mlkeep;
+ realtype rel_yy;
+ IDABBDLocalFn glocal;
+ IDABBDCommFn gcomm;
+
+ /* allocated for use by IDABBDPrecSetup */
+
+ 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;
+
+/*
+ * -----------------------------------------------------------------
+ * Type: IDABBDPrecDataB
+ * -----------------------------------------------------------------
+ */
+
+typedef struct IDABBDPrecDataRecB{
+
+ /* BBD user functions (glocB and cfnB) for backward run */
+ IDABBDLocalFnB glocalB;
+ IDABBDCommFnB gcommB;
+
+ /* BBD prec data */
+ /* //!void *bbd_dataB; */
+
+} *IDABBDPrecDataB;
+
+
+/*
+ * -----------------------------------------------------------------
+ * IDABBDPRE 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_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."
+
+#define MSGBBD_AMEM_NULL "idaadj_mem = NULL illegal."
+#define MSGBBD_PDATAB_NULL "IDABBDPRE memory is NULL for the backward integration."
+#define MSGBBD_BAD_T "Bad t for interpolation."
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/idas/idas_dense.c b/src/idas/idas_dense.c
new file mode 100644
index 0000000..f7415ed
--- /dev/null
+++ b/src/idas/idas_dense.c
@@ -0,0 +1,404 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.14 $
+ * $Date: 2011/03/23 21:12:45 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Alan C. Hindmarsh and Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * 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 void 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;
+ int flag;
+
+ /* 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) flag = 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;
+
+ 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;
+
+
+ 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, "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 Jacob 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 the IDAS data of the backward problem. */
+ 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 void IDADenseFreeB(IDABMem IDAB_mem)
+{
+ IDADlsMemB idadlsB_mem;
+
+ idadlsB_mem = (IDADlsMemB) IDAB_mem->ida_lmem;
+
+ free(idadlsB_mem);
+}
+
diff --git a/src/idas/idas_direct.c b/src/idas/idas_direct.c
new file mode 100644
index 0000000..80f309f
--- /dev/null
+++ b/src/idas/idas_direct.c
@@ -0,0 +1,799 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.7 $
+ * $Date: 2010/12/01 22:39:19 $
+ * -----------------------------------------------------------------
+ * Programmer: Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2006, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * This is the implementation file for an IDASDLS linear solver.
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * =================================================================
+ * IMPORTED HEADER FILES
+ * =================================================================
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "idas_impl.h"
+#include "idas_direct_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 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 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);
+
+/*
+ * =================================================================
+ * 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)
+{
+ IDAMem IDA_mem;
+ IDADlsMem idadls_mem;
+
+ /* Return immediately if ida_mem is NULL */
+ if (ida_mem == NULL) {
+ IDAProcessError(NULL, IDADLS_MEM_NULL, "IDASDLS", "IDADlsSetDenseJacFn", MSGD_IDAMEM_NULL);
+ return(IDADLS_MEM_NULL);
+ }
+ IDA_mem = (IDAMem) ida_mem;
+
+ if (lmem == NULL) {
+ IDAProcessError(IDA_mem, IDADLS_LMEM_NULL, "IDASDLS", "IDADlsSetDenseJacFn", MSGD_LMEM_NULL);
+ return(IDADLS_LMEM_NULL);
+ }
+ idadls_mem = (IDADlsMem) lmem;
+
+ if (jac != NULL) {
+ jacDQ = FALSE;
+ djac = jac;
+ } else {
+ jacDQ = TRUE;
+ }
+
+ return(IDADLS_SUCCESS);
+}
+
+/*
+ * IDADlsSetBandJacFn specifies the band Jacobian function.
+ */
+int IDADlsSetBandJacFn(void *ida_mem, IDADlsBandJacFn jac)
+{
+ IDAMem IDA_mem;
+ IDADlsMem idadls_mem;
+
+ /* Return immediately if ida_mem is NULL */
+ if (ida_mem == NULL) {
+ IDAProcessError(NULL, IDADLS_MEM_NULL, "IDASDLS", "IDADlsSetBandJacFn", 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);
+ return(IDADLS_LMEM_NULL);
+ }
+ idadls_mem = (IDADlsMem) lmem;
+
+ if (jac != NULL) {
+ jacDQ = FALSE;
+ bjac = jac;
+ } else {
+ jacDQ = TRUE;
+ }
+
+ 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)
+{
+ IDAMem IDA_mem;
+ IDADlsMem idadls_mem;
+
+ /* Return immediately if ida_mem is NULL */
+ if (ida_mem == 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);
+ 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;
+ }
+
+ return(IDADLS_SUCCESS);
+}
+
+/*
+ * 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 */
+ if (ida_mem == 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);
+ return(IDADLS_LMEM_NULL);
+ }
+ idadls_mem = (IDADlsMem) lmem;
+
+ *njevals = nje;
+
+ return(IDADLS_SUCCESS);
+}
+
+/*
+ * 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 */
+ if (ida_mem == NULL) {
+ IDAProcessError(NULL, IDADLS_MEM_NULL, "IDASDLS", "IDADlsGetNumFctEvals", 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);
+ return(IDADLS_LMEM_NULL);
+ }
+ idadls_mem = (IDADlsMem) lmem;
+
+ *nrevalsLS = nreDQ;
+
+ return(IDADLS_SUCCESS);
+}
+
+/*
+ * IDADlsGetReturnFlagName returns the name associated with a IDALAPACK
+ * return value.
+ */
+char *IDADlsGetReturnFlagName(long int flag)
+{
+ char *name;
+
+ name = (char *)malloc(30*sizeof(char));
+
+ switch(flag) {
+ case IDADLS_SUCCESS:
+ sprintf(name,"IDADLS_SUCCESS");
+ break;
+ case IDADLS_MEM_NULL:
+ sprintf(name,"IDADLS_MEM_NULL");
+ break;
+ case IDADLS_LMEM_NULL:
+ sprintf(name,"IDADLS_LMEM_NULL");
+ break;
+ case IDADLS_ILL_INPUT:
+ sprintf(name,"IDADLS_ILL_INPUT");
+ break;
+ case IDADLS_MEM_FAIL:
+ sprintf(name,"IDADLS_MEM_FAIL");
+ break;
+ case IDADLS_JACFUNC_UNRECVR:
+ sprintf(name,"IDADLS_JACFUNC_UNRECVR");
+ break;
+ case IDADLS_JACFUNC_RECVR:
+ sprintf(name,"IDADLS_JACFUNC_RECVR");
+ break;
+ default:
+ sprintf(name,"NONE");
+ }
+
+ return(name);
+}
+
+/*
+ * IDADlsGetLastFlag returns the last flag set in a IDALAPACK function.
+ */
+int IDADlsGetLastFlag(void *ida_mem, long int *flag)
+{
+ IDAMem IDA_mem;
+ IDADlsMem idadls_mem;
+
+ /* Return immediately if ida_mem is NULL */
+ if (ida_mem == 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);
+ return(IDADLS_LMEM_NULL);
+ }
+ idadls_mem = (IDADlsMem) lmem;
+
+ *flag = 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)
+{
+ realtype inc, inc_inv, yj, ypj, srur, conj;
+ realtype *tmp2_data, *y_data, *yp_data, *ewt_data, *cns_data = NULL;
+ N_Vector rtemp, jthCol;
+ long int j;
+ int retval = 0;
+
+ IDAMem IDA_mem;
+ IDADlsMem idadls_mem;
+
+ /* data points to IDA_mem */
+ IDA_mem = (IDAMem) data;
+ idadls_mem = (IDADlsMem) lmem;
+
+ /* Save pointer to the array in tmp2 */
+ tmp2_data = N_VGetArrayPointer(tmp2);
+
+ /* Rename work vectors for readibility */
+ rtemp = tmp1;
+ jthCol = tmp2;
+
+ /* Obtain pointers to the data for ewt, yy, yp. */
+ ewt_data = N_VGetArrayPointer(ewt);
+ y_data = N_VGetArrayPointer(yy);
+ yp_data = N_VGetArrayPointer(yp);
+ if(constraints!=NULL) cns_data = N_VGetArrayPointer(constraints);
+
+ srur = RSqrt(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);
+ yj = y_data[j];
+ ypj = yp_data[j];
+
+ /* Set increment inc to y_j based on sqrt(uround)*abs(y_j), with
+ 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 = MAX( srur * MAX( ABS(yj), ABS(hh*ypj) ) , ONE/ewt_data[j] );
+
+ if (hh*ypj < ZERO) inc = -inc;
+ inc = (yj + inc) - yj;
+
+ /* Adjust sign(inc) again if y_j has an inequality constraint. */
+ if (constraints != NULL) {
+ conj = cns_data[j];
+ if (ABS(conj) == ONE) {if((yj+inc)*conj < ZERO) inc = -inc;}
+ else if (ABS(conj) == TWO) {if((yj+inc)*conj <= ZERO) inc = -inc;}
+ }
+
+ /* Increment y_j and yp_j, call res, and break on error return. */
+ y_data[j] += inc;
+ yp_data[j] += c_j*inc;
+
+ retval = res(tt, yy, yp, rtemp, user_data);
+
+ 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);
+
+ /* reset y_j, yp_j */
+ y_data[j] = yj;
+ yp_data[j] = ypj;
+ }
+
+ /* Restore original array pointer in tmp2 */
+ N_VSetArrayPointer(tmp2_data, tmp2);
+
+ 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)
+{
+ 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;
+ 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. */
+
+
+ yptemp= tmp3; /* Rename work vector for use as a temporary for yp. */
+
+ /* 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);
+
+ rtemp_data = N_VGetArrayPointer(rtemp);
+ ytemp_data = N_VGetArrayPointer(ytemp);
+ yptemp_data = N_VGetArrayPointer(yptemp);
+
+ if (constraints != NULL) cns_data = N_VGetArrayPointer(constraints);
+
+ /* Initialize ytemp and yptemp. */
+
+ N_VScale(ONE, yy, ytemp);
+ N_VScale(ONE, yp, yptemp);
+
+ /* Compute miscellaneous values for the Jacobian computation. */
+
+ srur = RSqrt(uround);
+ width = mlower + mupper + 1;
+ ngroups = MIN(width, N);
+
+ /* Loop over column groups. */
+ 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];
+ ewtj = ewt_data[j];
+
+ /* 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 = MAX( srur * MAX( ABS(yj), ABS(hh*ypj) ) , ONE/ewtj );
+
+ if (hh*ypj < ZERO) inc = -inc;
+ inc = (yj + inc) - yj;
+
+ /* Adjust sign(inc) again if yj has an inequality constraint. */
+
+ if (constraints != NULL) {
+ conj = cns_data[j];
+ if (ABS(conj) == ONE) {if((yj+inc)*conj < ZERO) inc = -inc;}
+ else if (ABS(conj) == TWO) {if((yj+inc)*conj <= ZERO) inc = -inc;}
+ }
+
+ /* Increment yj and ypj. */
+
+ ytemp_data[j] += inc;
+ yptemp_data[j] += cj*inc;
+ }
+
+ /* Call res routine with incremented arguments. */
+
+ retval = res(tt, ytemp, yptemp, rtemp, user_data);
+ 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);
+ ewtj = ewt_data[j];
+
+ /* Set increment inc exactly as above. */
+
+ inc = MAX( srur * MAX( ABS(yj), ABS(hh*ypj) ) , ONE/ewtj );
+ if (hh*ypj < ZERO) inc = -inc;
+ inc = (yj + inc) - yj;
+ if (constraints != NULL) {
+ conj = cns_data[j];
+ if (ABS(conj) == ONE) {if((yj+inc)*conj < ZERO) inc = -inc;}
+ else if (ABS(conj) == TWO) {if((yj+inc)*conj <= ZERO) inc = -inc;}
+ }
+
+ /* Load the difference quotient Jacobian elements for column j. */
+
+ inc_inv = ONE/inc;
+ i1 = MAX(0, j-mupper);
+ i2 = MIN(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]);
+ }
+
+ }
+
+ return(retval);
+
+}
+
+
+/*
+ * =================================================================
+ * BACKWARD INTEGRATION SUPPORT
+ * =================================================================
+ */
+
+/* Additional readability replacements */
+#define yyTmp (IDAADJ_mem->ia_yyTmp)
+#define ypTmp (IDAADJ_mem->ia_ypTmp)
+#define noInterp (IDAADJ_mem->ia_noInterp)
+
+/*
+ * -----------------------------------------------------------------
+ * EXPORTED FUNCTIONS
+ * -----------------------------------------------------------------
+ */
+
+int IDADlsSetDenseJacFnB(void *ida_mem, int which, IDADlsDenseJacFnB jacB)
+{
+ 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);
+ 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);
+ }
+ 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);
+ }
+
+ /* 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, IDADLS_LMEMB_NULL,
+ "IDASDLS", "IDADlsSetDenseJacFnB", MSGD_LMEMB_NULL);
+ return(IDADLS_LMEMB_NULL);
+ }
+ idadlsB_mem = (IDADlsMemB) IDAB_mem->ida_lmem;
+
+ idadlsB_mem->d_djacB = jacB;
+
+ if (jacB != NULL) {
+ flag = IDADlsSetDenseJacFn(ida_memB, idaDlsDenseJacBWrapper);
+ } else {
+ flag = IDADlsSetDenseJacFn(ida_memB, NULL);
+ }
+
+ return(flag);
+}
+
+int IDADlsSetBandJacFnB(void *ida_mem, int which, IDADlsBandJacFnB jacB)
+{
+ 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", "IDADlsSetBandJacFnB", 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);
+ 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);
+ 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 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", "IDADlsSetBandJacFnB", MSGD_LMEMB_NULL);
+ return(IDADLS_LMEMB_NULL);
+ }
+ idadlsB_mem = (IDADlsMemB) IDAB_mem->ida_lmem;
+
+ idadlsB_mem->d_bjacB = jacB;
+
+ if (jacB != NULL) {
+ flag = IDADlsSetBandJacFn(ida_memB, idaDlsBandJacBWrapper);
+ } else {
+ flag = IDADlsSetBandJacFn(ida_memB, NULL);
+ }
+
+ return(flag);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * 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)
+{
+ 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. */
+ 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", "idaDlsDenseJacWrapper", 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);
+}
+
+/*
+ * 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. */
+ IDAB_mem = IDAADJ_mem->ia_bckpbCrt;
+
+ /* Get linear solver's data for this backward problem. */
+ 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", "idaDlsBandJacWrapper", 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);
+ return(flag);
+}
+
diff --git a/src/idas/idas_direct_impl.h b/src/idas/idas_direct_impl.h
new file mode 100644
index 0000000..34c482b
--- /dev/null
+++ b/src/idas/idas_direct_impl.h
@@ -0,0 +1,139 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.7 $
+ * $Date: 2010/12/01 22:39:18 $
+ * -----------------------------------------------------------------
+ * Programmer: Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2006, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * Implementation header file for the IDADLS linear solvers.
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _IDASDLS_IMPL_H
+#define _IDASDLS_IMPL_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <idas/idas_direct.h>
+
+/*
+ * =================================================================
+ * 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.
+ * -----------------------------------------------------------------
+ */
+
+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 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 */
+
+ DlsMat d_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 */
+
+ long int d_nje; /* nje = no. of calls to jac */
+
+ long int d_nreDQ; /* no. of calls to res due to DQ Jacobian approx.*/
+
+ long int d_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);
+
+/*
+ * =================================================================
+ * 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
+ * -----------------------------------------------------------------
+ */
+
+typedef struct IDADlsMemRecB {
+
+ int d_typeB;
+
+ IDADlsDenseJacFnB d_djacB;
+ IDADlsBandJacFnB d_bjacB;
+
+} *IDADlsMemB;
+
+
+/*
+ * =================================================================
+ * E R R O R M E S S A G E S
+ * =================================================================
+ */
+
+#define MSGD_IDAMEM_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_JACFUNC_FAILED "The Jacobian 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."
+#define MSGD_BAD_T "Bad t for interpolation."
+#define MSGD_BAD_WHICH "Illegal value for which."
+#define MSGD_NO_ADJ "Illegal attempt to call before calling IDAAdjInit."
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/idas/idas_ic.c b/src/idas/idas_ic.c
new file mode 100644
index 0000000..d9c1aa5
--- /dev/null
+++ b/src/idas/idas_ic.c
@@ -0,0 +1,1350 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.6 $
+ * $Date: 2011/04/26 22:51:51 $
+ * -----------------------------------------------------------------
+ * Programmers: Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California
+ * Produced at the Lawrence Livermore National Laboratory
+ * All rights reserved
+ * For details, see the LICENSE file
+ * -----------------------------------------------------------------
+ * This is the implementation file for the IC calculation for IDAS.
+ * It is independent of the linear solver in use.
+ * -----------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "idas_impl.h"
+#include <sundials/sundials_math.h>
+
+/* Macro: loop */
+#define loop for(;;)
+
+/*
+ * =================================================================
+ * IDA Constants
+ * =================================================================
+ */
+
+/* Private Constants */
+
+#define ZERO RCONST(0.0) /* real 0.0 */
+#define HALF RCONST(0.5) /* real 0.5 */
+#define ONE RCONST(1.0) /* real 1.0 */
+#define TWO RCONST(2.0) /* real 2.0 */
+#define PT99 RCONST(0.99) /* real 0.99 */
+#define PT1 RCONST(0.1) /* real 0.1 */
+#define PT001 RCONST(0.001) /* real 0.001 */
+
+/* IDACalcIC control constants */
+
+#define ICRATEMAX RCONST(0.9) /* max. Newton conv. rate */
+#define ALPHALS RCONST(0.0001) /* alpha in linesearch conv. test */
+
+/* Return values for lower level routines used by IDACalcIC */
+
+#define IC_FAIL_RECOV 1
+#define IC_CONSTR_FAILED 2
+#define IC_LINESRCH_FAILED 3
+#define IC_CONV_FAIL 4
+#define IC_SLOW_CONVRG 5
+
+/*
+ * =================================================================
+ * Private Helper Functions Prototypes
+ * =================================================================
+ */
+
+extern int IDAInitialSetup(IDAMem IDA_mem);
+extern realtype IDAWrmsNorm(IDAMem IDA_mem, N_Vector x,
+ N_Vector w, booleantype mask);
+extern realtype IDASensWrmsNorm(IDAMem IDA_mem, N_Vector *xS,
+ N_Vector *wS, booleantype mask);
+extern realtype IDASensWrmsNormUpdate(IDAMem IDA_mem, realtype old_nrm,
+ N_Vector *xS, N_Vector *wS,
+ booleantype mask);
+
+extern int IDASensEwtSet(IDAMem IDA_mem, N_Vector *yScur, N_Vector *weightS);
+
+static int IDANlsIC(IDAMem IDA_mem);
+
+static int IDANewtonIC(IDAMem IDA_mem);
+static int IDALineSrch(IDAMem IDA_mem, realtype *delnorm, realtype *fnorm);
+static int IDAfnorm(IDAMem IDA_mem, realtype *fnorm);
+static int IDANewyyp(IDAMem IDA_mem, realtype lambda);
+static int IDANewy(IDAMem IDA_mem);
+
+static int IDASensNewtonIC(IDAMem IDA_mem);
+static int IDASensLineSrch(IDAMem IDA_mem, realtype *delnorm, realtype *fnorm);
+static int IDASensNewyyp(IDAMem IDA_mem, realtype lambda);
+static int IDASensfnorm(IDAMem IDA_mem, realtype *fnorm);
+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 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)
+
+/*
+ * =================================================================
+ * EXPORTED FUNCTIONS IMPLEMENTATION
+ * =================================================================
+ */
+
+/*
+ * -----------------------------------------------------------------
+ * IDACalcIC
+ * -----------------------------------------------------------------
+ * IDACalcIC computes consistent initial conditions, given the
+ * user's initial guess for unknown components of yy0 and/or yp0.
+ *
+ * The return value is IDA_SUCCESS = 0 if no error occurred.
+ *
+ * The error return values (fully described in ida.h) are:
+ * IDA_MEM_NULL ida_mem is NULL
+ * IDA_NO_MALLOC ida_mem was not allocated
+ * IDA_ILL_INPUT bad value for icopt, tout1, or id
+ * IDA_LINIT_FAIL the linear solver linit routine failed
+ * IDA_BAD_EWT zero value of some component of ewt
+ * IDA_RES_FAIL res had a non-recoverable error
+ * IDA_FIRST_RES_FAIL res failed recoverably on the first call
+ * IDA_LSETUP_FAIL lsetup had a non-recoverable error
+ * IDA_LSOLVE_FAIL lsolve had a non-recoverable error
+ * IDA_NO_RECOVERY res, lsetup, or lsolve had a recoverable
+ * error, but IDACalcIC could not recover
+ * IDA_CONSTR_FAIL the inequality constraints could not be met
+ * IDA_LINESEARCH_FAIL the linesearch failed (on steptol test)
+ * IDA_CONV_FAIL the Newton iterations failed to converge
+ * -----------------------------------------------------------------
+ */
+
+int IDACalcIC(void *ida_mem, int icopt, realtype tout1)
+{
+ int ewtsetOK;
+ int ier, nwt, nh, mxnh, icret, retval=0;
+ int is;
+ realtype tdist, troundoff, minid, hic, ypnorm;
+ IDAMem IDA_mem;
+ booleantype sensi_stg, sensi_sim;
+
+ /* Check if IDA memory exists */
+
+ if(ida_mem == NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDACalcIC", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+ IDA_mem = (IDAMem) ida_mem;
+
+ /* Check if problem was malloc'ed */
+
+ if(IDA_mem->ida_MallocDone == FALSE) {
+ IDAProcessError(IDA_mem, IDA_NO_MALLOC, "IDAS", "IDACalcIC", MSG_NO_MALLOC);
+ return(IDA_NO_MALLOC);
+ }
+
+ /* Check inputs to IDA for correctness and consistency */
+
+ ier = IDAInitialSetup(IDA_mem);
+ if(ier != IDA_SUCCESS) return(IDA_ILL_INPUT);
+ IDA_mem->ida_SetupDone = TRUE;
+
+ /* Check legality of input arguments, and set IDA memory copies. */
+
+ if(icopt != IDA_YA_YDP_INIT && icopt != IDA_Y_INIT) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDACalcIC", MSG_IC_BAD_ICOPT);
+ return(IDA_ILL_INPUT);
+ }
+ IDA_mem->ida_icopt = icopt;
+
+ if(icopt == IDA_YA_YDP_INIT && (id == NULL)) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDACalcIC", MSG_IC_MISSING_ID);
+ return(IDA_ILL_INPUT);
+ }
+
+ tdist = ABS(tout1 - tn);
+ troundoff = TWO*uround*(ABS(tn) + ABS(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));
+
+ /* 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);
+
+ if (sensi) {
+
+ /* Allocate temporary space required for sensitivity IC: yyS0 and ypS0. */
+ yyS0 = N_VCloneVectorArray(Ns, ee);
+ ypS0 = N_VCloneVectorArray(Ns, 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]);
+ }
+
+ /* Initialize work space vectors needed for sensitivities. */
+ savresS = phiS[2];
+ delnewS = phiS[3];
+ yyS0new = phiS[4];
+ ypS0new = eeS;
+ }
+
+ /* 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);
+ if(minid < ZERO) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDACalcIC", MSG_IC_BAD_ID);
+ return(IDA_ILL_INPUT);
+ }
+ if(minid > HALF) IDA_mem->ida_sysindex = 0;
+ }
+
+ /* Set the test constant in the Newton convergence test */
+
+ IDA_mem->ida_epsNewt = epiccon;
+
+ /* Initializations:
+ cjratio = 1 (for use in direct linear solvers);
+ set nbacktr = 0; */
+
+ cjratio = ONE;
+ nbacktr = 0;
+
+ /* Set hic, hh, cj, and mxnh. */
+
+ hic = PT001*tdist;
+ ypnorm = IDAWrmsNorm(IDA_mem, yp0, ewt, suppressalg);
+
+ if (sensi_sim)
+ ypnorm = IDASensWrmsNormUpdate(IDA_mem, ypnorm, ypS0, ewtS, FALSE);
+
+ if(ypnorm > HALF/hic) hic = HALF/ypnorm;
+ if(tout1 < tn) hic = -hic;
+ hh = hic;
+ if(icopt == IDA_YA_YDP_INIT) {
+ cj = ONE/hic;
+ mxnh = maxnh;
+ }
+ else {
+ cj = ZERO;
+ mxnh = 1;
+ }
+
+ /* Loop over nwt = number of evaluations of ewt vector. */
+
+ for(nwt = 1; nwt <= 2; nwt++) {
+
+ /* Loop over nh = number of h values. */
+ for(nh = 1; nh <= mxnh; nh++) {
+
+ /* Call the IC nonlinear solver function. */
+ retval = IDANlsIC(IDA_mem);
+
+ /* Cut h and loop on recoverable IDA_YA_YDP_INIT failure; else break. */
+ if(retval == IDA_SUCCESS) break;
+ 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);
+ 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]);
+ }
+ }
+ }
+ hic *= PT1;
+ cj = ONE/hic;
+ 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);
+ if(ewtsetOK != 0) {
+ retval = IDA_BAD_EWT;
+ break;
+ }
+ N_VScale(ONE, yy0, phi[0]);
+ N_VScale(ONE, yp0, phi[1]);
+
+ if (sensi_sim) {
+
+ /* Reevaluate ewtS. */
+ ewtsetOK = IDASensEwtSet(IDA_mem, yyS0, 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]);
+ }
+ }
+
+ } /* End of nwt loop */
+
+ /* Load the optional outputs. */
+
+ if(icopt == IDA_YA_YDP_INIT) hused = hic;
+
+ /* On any failure, free memory, print error message and return */
+
+ if(retval != IDA_SUCCESS) {
+ N_VDestroy(yy0);
+ N_VDestroy(yp0);
+
+ if(sensi) {
+ N_VDestroyVectorArray(yyS0, Ns);
+ N_VDestroyVectorArray(ypS0, Ns);
+ }
+
+ icret = IDAICFailFlag(IDA_mem, retval);
+ return(icret);
+ }
+
+ /* Unless using the STAGGERED approach for sensitivities, return now */
+
+ if (!sensi_stg) {
+
+ N_VDestroy(yy0);
+ N_VDestroy(yp0);
+
+ if(sensi) {
+ N_VDestroyVectorArray(yyS0, Ns);
+ N_VDestroyVectorArray(ypS0, Ns);
+ }
+
+ return(IDA_SUCCESS);
+ }
+
+ /* Find consistent I.C. for sensitivities using a staggered approach */
+
+
+ /* Evaluate res at converged y, needed for future evaluations of sens. RHS
+ If res() fails recoverably, treat it as a convergence failure and
+ attempt the step again */
+
+ retval = res(t0, yy0, yp0, delta, user_data);
+ nre++;
+ if(retval < 0)
+ /* res function failed unrecoverably. */
+ return(IDA_RES_FAIL);
+
+ if(retval > 0)
+ /* res function failed recoverably but no recovery possible. */
+ return(IDA_FIRST_RES_FAIL);
+
+ /* Loop over nwt = number of evaluations of ewt vector. */
+ for(nwt = 1; nwt <= 2; nwt++) {
+
+ /* Loop over nh = number of h values. */
+ for(nh = 1; nh <= mxnh; nh++) {
+
+ retval = IDASensNlsIC(IDA_mem);
+ if(retval == IDA_SUCCESS) break;
+
+ /* Increment the number of the sensitivity related corrector convergence failures. */
+ 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]);
+ }
+ }
+ hic *= PT1;
+ cj = ONE/hic;
+ hh = hic;
+
+ } /* End of nh loop */
+
+ /* Break on failure */
+ if(retval != IDA_SUCCESS) break;
+
+ /* Since it was successful, reevaluate ewtS with the new values of yyS0, save
+ yyS0 and ypS0 in phiS[0] and phiS[1] and loop one more time to check and
+ maybe correct the new sensitivities IC with respect to the new weights. */
+
+ /* Reevaluate ewtS. */
+ ewtsetOK = IDASensEwtSet(IDA_mem, yyS0, 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]);
+ }
+
+ } /* End of nwt loop */
+
+
+ /* Load the optional outputs. */
+ if(icopt == IDA_YA_YDP_INIT) hused = hic;
+
+ /* Free temporary space */
+ N_VDestroy(yy0);
+ N_VDestroy(yp0);
+
+ /* Here sensi is TRUE, so deallocate sensitivity temporary vectors. */
+ N_VDestroyVectorArray(yyS0, Ns);
+ N_VDestroyVectorArray(ypS0, Ns);
+
+
+ /* On any failure, print message and return proper flag. */
+ if(retval != IDA_SUCCESS) {
+ icret = IDAICFailFlag(IDA_mem, retval);
+ return(icret);
+ }
+
+ /* Otherwise return success flag. */
+
+ return(IDA_SUCCESS);
+
+}
+
+/*
+ * =================================================================
+ * PRIVATE FUNCTIONS IMPLEMENTATION
+ * =================================================================
+ */
+
+#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
+ * -----------------------------------------------------------------
+ * IDANlsIC solves a nonlinear system for consistent initial
+ * conditions. It calls IDANewtonIC to do most of the work.
+ *
+ * The return value is IDA_SUCCESS = 0 if no error occurred.
+ * The error return values (positive) considered recoverable are:
+ * IC_FAIL_RECOV if res, lsetup, or lsolve failed recoverably
+ * IC_CONSTR_FAILED if the constraints could not be met
+ * IC_LINESRCH_FAILED if the linesearch failed (on steptol test)
+ * IC_CONV_FAIL if the Newton iterations failed to converge
+ * IC_SLOW_CONVRG if the iterations are converging slowly
+ * (failed the convergence test, but showed
+ * norm reduction or convergence rate < 1)
+ * The error return values (negative) considered non-recoverable are:
+ * IDA_RES_FAIL if res had a non-recoverable error
+ * IDA_FIRST_RES_FAIL if res failed recoverably on the first call
+ * IDA_LSETUP_FAIL if lsetup had a non-recoverable error
+ * IDA_LSOLVE_FAIL if lsolve had a non-recoverable error
+ * -----------------------------------------------------------------
+ */
+
+static int IDANlsIC(IDAMem IDA_mem)
+{
+ int retval, nj, is;
+ N_Vector tv1, tv2, tv3;
+ booleantype sensi_sim;
+
+ /* Are we computing sensitivities with the IDA_SIMULTANEOUS approach? */
+ sensi_sim = (sensi && (ism==IDA_SIMULTANEOUS));
+
+ tv1 = ee;
+ tv2 = tempv2;
+ tv3 = phi[2];
+
+ /* Evaluate RHS. */
+ retval = res(t0, yy0, yp0, delta, user_data);
+ nre++;
+ if(retval < 0) return(IDA_RES_FAIL);
+ if(retval > 0) return(IDA_FIRST_RES_FAIL);
+
+ /* Save the residual. */
+ N_VScale(ONE, delta, 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++;
+ 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]);
+ }
+
+ /* Loop over nj = number of linear solve Jacobian setups. */
+ for(nj = 1; nj <= maxnj; nj++) {
+
+ /* If there is a setup routine, call it. */
+ if(setupNonNull) {
+ nsetups++;
+ retval = lsetup(IDA_mem, yy0, yp0, delta, tv1, tv2, tv3);
+ if(retval < 0) return(IDA_LSETUP_FAIL);
+ if(retval > 0) return(IC_FAIL_RECOV);
+ }
+
+ /* Call the Newton iteration routine, and return if successful. */
+ retval = IDANewtonIC(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(sensi_sim)
+ for(is=0; is<Ns; is++)
+ N_VScale(ONE, savresS[is], deltaS[is]);
+
+ continue;
+ } else {
+ return(retval);
+ }
+
+ } /* End of nj loop */
+
+ /* No convergence after maxnj tries; return with retval=IC_SLOW_CONVRG */
+ return(retval);
+
+}
+
+/*
+ * -----------------------------------------------------------------
+ * IDANewtonIC
+ * -----------------------------------------------------------------
+ * IDANewtonIC performs the Newton iteration to solve for consistent
+ * initial conditions. It calls IDALineSrch within each iteration.
+ * On return, savres contains the current residual vector.
+ *
+ * The return value is IDA_SUCCESS = 0 if no error occurred.
+ * The error return values (positive) considered recoverable are:
+ * IC_FAIL_RECOV if res or lsolve failed recoverably
+ * IC_CONSTR_FAILED if the constraints could not be met
+ * IC_LINESRCH_FAILED if the linesearch failed (on steptol test)
+ * IC_CONV_FAIL if the Newton iterations failed to converge
+ * IC_SLOW_CONVRG if the iterations appear to be converging slowly.
+ * They failed the convergence test, but showed
+ * an overall norm reduction (by a factor of < 0.1)
+ * or a convergence rate <= ICRATEMAX).
+ * The error return values (negative) considered non-recoverable are:
+ * IDA_RES_FAIL if res had a non-recoverable error
+ * IDA_LSOLVE_FAIL if lsolve had a non-recoverable error
+ * -----------------------------------------------------------------
+ */
+
+static int IDANewtonIC(IDAMem IDA_mem)
+{
+ int retval, mnewt, is;
+ realtype delnorm, fnorm, fnorm0, oldfnrm, rate;
+ booleantype sensi_sim;
+
+ /* Are we computing sensitivities with the IDA_SIMULTANEOUS approach? */
+ sensi_sim = (sensi && (ism==IDA_SIMULTANEOUS));
+
+ /* Set pointer for vector delnew */
+ delnew = phi[2];
+
+ /* Call the linear solve function to get the Newton step, delta. */
+ retval = lsolve(IDA_mem, delta, ewt, yy0, yp0, 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);
+
+ /* 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);
+ 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);
+ }
+
+ /* Test for convergence. Return now if the norm is small. */
+ if(sysindex == 0) fnorm *= tscale*ABS(cj);
+ if(fnorm <= epsNewt) return(IDA_SUCCESS);
+ fnorm0 = fnorm;
+
+ /* Initialize rate to avoid compiler warning message */
+ rate = ZERO;
+
+ /* Newton iteration loop */
+
+ for(mnewt = 0; mnewt < maxnit; mnewt++) {
+
+ nni++;
+ delnorm = fnorm;
+ oldfnrm = fnorm;
+
+ /* Call the Linesearch function and return if it failed. */
+ retval = IDALineSrch(IDA_mem, &delnorm, &fnorm);
+ if(retval != IDA_SUCCESS) return(retval);
+
+ /* Set the observed convergence rate and test for convergence. */
+ rate = fnorm/oldfnrm;
+ if(fnorm <= epsNewt) return(IDA_SUCCESS);
+
+ /* If not converged, copy new step vector, and loop. */
+ N_VScale(ONE, delnew, delta);
+
+ if(sensi_sim) {
+ /* Update the iteration's step for sensitivities. */
+ for(is=0; is<Ns; is++)
+ N_VScale(ONE, delnewS[is], deltaS[is]);
+ }
+
+ } /* End of Newton iteration loop */
+
+ /* Return either IC_SLOW_CONVRG or recoverable fail flag. */
+ if(rate <= ICRATEMAX || fnorm < PT1*fnorm0) return(IC_SLOW_CONVRG);
+ return(IC_CONV_FAIL);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * IDALineSrch
+ * -----------------------------------------------------------------
+ * IDALineSrch performs the Linesearch algorithm with the
+ * calculation of consistent initial conditions.
+ *
+ * On entry, yy0 and yp0 are the current values of y and y', the
+ * Newton step is delta, the current residual vector F is savres,
+ * delnorm is WRMS-norm(delta), and fnorm is the norm of the vector
+ * J-inverse F.
+ *
+ * On a successful return, yy0, yp0, and savres have been updated,
+ * delnew contains the current value of J-inverse F, and fnorm is
+ * WRMS-norm(delnew).
+ *
+ * The return value is IDA_SUCCESS = 0 if no error occurred.
+ * The error return values (positive) considered recoverable are:
+ * IC_FAIL_RECOV if res or lsolve failed recoverably
+ * IC_CONSTR_FAILED if the constraints could not be met
+ * IC_LINESRCH_FAILED if the linesearch failed (on steptol test)
+ * The error return values (negative) considered non-recoverable are:
+ * IDA_RES_FAIL if res had a non-recoverable error
+ * IDA_LSOLVE_FAIL if lsolve had a non-recoverable error
+ * -----------------------------------------------------------------
+ */
+
+static int IDALineSrch(IDAMem IDA_mem, realtype *delnorm, realtype *fnorm)
+{
+ booleantype conOK;
+ int retval, is;
+ realtype f1norm, fnormp, f1normp, ratio, lambda, minlam, slpi;
+ N_Vector mc;
+ booleantype sensi_sim;
+
+ /* 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;
+ f1norm = (*fnorm)*(*fnorm)*HALF;
+ ratio = ONE;
+
+ /* If there are constraints, check and reduce step if necessary. */
+ if(constraintsSet) {
+
+ /* Update y and check constraints. */
+ IDANewy(IDA_mem);
+ conOK = N_VConstrMask(constraints, ynew, mc);
+
+ if(!conOK) {
+ /* Not satisfied. Compute scaled step to satisfy constraints. */
+ N_VProd(mc, delta, dtemp);
+ ratio = PT99*N_VMinQuotient(yy0, dtemp);
+ (*delnorm) *= ratio;
+ if((*delnorm) <= steptol) return(IC_CONSTR_FAILED);
+ N_VScale(ratio, delta, delta);
+ }
+
+ } /* End of constraints check */
+
+ slpi = -TWO*f1norm*ratio;
+ minlam = steptol/(*delnorm);
+ lambda = ONE;
+
+ /* Are we computing sensitivities with the IDA_SIMULTANEOUS approach? */
+ sensi_sim = (sensi && (ism==IDA_SIMULTANEOUS));
+
+ /* In IDA_Y_INIT case, set ypnew = yp0 (fixed) for linesearch. */
+ if(icopt == IDA_Y_INIT) {
+ N_VScale(ONE, yp0, ypnew);
+
+ /* do the same for sensitivities. */
+ if(sensi_sim) {
+ for(is=0; is<Ns; is++)
+ N_VScale(ONE, ypS0[is], ypS0new[is]);
+ }
+ }
+
+ /* Loop on linesearch variable lambda. */
+
+ loop {
+
+ /* 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;
+
+ /* 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++;
+
+ } /* End of breakout linesearch loop */
+
+ /* Update yy0, yp0. */
+ N_VScale(ONE, ynew, yy0);
+
+ if(sensi_sim) {
+ /* Update yyS0 and ypS0. */
+ for(is=0; is<Ns; is++)
+ N_VScale(ONE, yyS0new[is], yyS0[is]);
+ }
+
+ if(icopt == IDA_YA_YDP_INIT) {
+ N_VScale(ONE, ypnew, yp0);
+
+ if(sensi_sim)
+ for(is=0; is<Ns; is++)
+ N_VScale(ONE, ypS0new[is], ypS0[is]);
+
+ }
+ /* Update fnorm, then return. */
+ *fnorm = fnormp;
+ return(IDA_SUCCESS);
+
+}
+
+/*
+ * -----------------------------------------------------------------
+ * IDAfnorm
+ * -----------------------------------------------------------------
+ * IDAfnorm computes the norm of the current function value, by
+ * evaluating the DAE residual function, calling the linear
+ * system solver, and computing a WRMS-norm.
+ *
+ * On return, savres contains the current residual vector F, and
+ * delnew contains J-inverse F.
+ *
+ * The return value is IDA_SUCCESS = 0 if no error occurred, or
+ * IC_FAIL_RECOV if res or lsolve failed recoverably, or
+ * IDA_RES_FAIL if res had a non-recoverable error, or
+ * IDA_LSOLVE_FAIL if lsolve had a non-recoverable error.
+ * -----------------------------------------------------------------
+ */
+
+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++;
+ if(retval < 0) return(IDA_RES_FAIL);
+ if(retval > 0) return(IC_FAIL_RECOV);
+
+ N_VScale(ONE, delnew, savres);
+
+ /* Call the linear solve function to get J-inverse F; return if failed. */
+ retval = lsolve(IDA_mem, delnew, ewt, ynew, ypnew, 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);
+
+
+ /* Are we computing SENSITIVITIES with the IDA_SIMULTANEOUS approach? */
+
+ if(sensi && (ism==IDA_SIMULTANEOUS)) {
+
+ /* Evaluate the residual for sensitivities. */
+ retval = resS(Ns, t0,
+ ynew, ypnew, savres,
+ yyS0new, ypS0new, delnewS,
+ user_dataS, tmpS1, tmpS2, tmpS3);
+ 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]);
+
+ /* Call the linear solve function to get J-inverse deltaS. */
+ for(is=0; is<Ns; is++) {
+
+ retval = lsolve(IDA_mem, delnewS[is], ewtS[is], ynew, ypnew, 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);
+ }
+
+ /* Rescale norm if index = 0. */
+ if(sysindex == 0) (*fnorm) *= tscale*ABS(cj);
+
+ return(IDA_SUCCESS);
+
+}
+
+/*
+ * -----------------------------------------------------------------
+ * IDANewyyp
+ * -----------------------------------------------------------------
+ * IDANewyyp updates the vectors ynew and ypnew from yy0 and yp0,
+ * using the current step vector lambda*delta, in a manner
+ * depending on icopt and the input id vector.
+ *
+ * The return value is always IDA_SUCCESS = 0.
+ * -----------------------------------------------------------------
+ */
+
+static int IDANewyyp(IDAMem IDA_mem, realtype lambda)
+{
+ int retval;
+
+ retval = IDA_SUCCESS;
+
+ /* 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);
+
+ }else if(icopt == IDA_Y_INIT) {
+
+ /* IDA_Y_INIT case: ynew = yy0 - lambda*delta. (ypnew = yp0 preset.) */
+ N_VLinearSum(ONE, yy0, -lambda, delta, ynew);
+ }
+
+ if(sensi && (ism==IDA_SIMULTANEOUS))
+ retval = IDASensNewyyp(IDA_mem, lambda);
+
+ return(retval);
+
+}
+
+/*
+ * -----------------------------------------------------------------
+ * IDANewy
+ * -----------------------------------------------------------------
+ * IDANewy updates the vector ynew from yy0,
+ * using the current step vector delta, in a manner
+ * depending on icopt and the input id vector.
+ *
+ * The return value is always IDA_SUCCESS = 0.
+ * -----------------------------------------------------------------
+ */
+
+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);
+ return(IDA_SUCCESS);
+ }
+
+ /* IDA_Y_INIT case: ynew = yy0 - delta. */
+ N_VLinearSum(ONE, yy0, -ONE, delta, ynew);
+ return(IDA_SUCCESS);
+
+}
+/*
+ * -----------------------------------------------------------------
+ * Sensitivity I.C. functions
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * -----------------------------------------------------------------
+ * IDASensNlsIC
+ * -----------------------------------------------------------------
+ * IDASensNlsIC solves nonlinear systems forsensitivities consistent
+ * initial conditions. It mainly relies on IDASensNewtonIC.
+ *
+ * The return value is IDA_SUCCESS = 0 if no error occurred.
+ * The error return values (positive) considered recoverable are:
+ * IC_FAIL_RECOV if res, lsetup, or lsolve failed recoverably
+ * IC_CONSTR_FAILED if the constraints could not be met
+ * IC_LINESRCH_FAILED if the linesearch failed (on steptol test)
+ * IC_CONV_FAIL if the Newton iterations failed to converge
+ * IC_SLOW_CONVRG if the iterations are converging slowly
+ * (failed the convergence test, but showed
+ * norm reduction or convergence rate < 1)
+ * The error return values (negative) considered non-recoverable are:
+ * IDA_RES_FAIL if res had a non-recoverable error
+ * IDA_FIRST_RES_FAIL if res failed recoverably on the first call
+ * IDA_LSETUP_FAIL if lsetup had a non-recoverable error
+ * IDA_LSOLVE_FAIL if lsolve had a non-recoverable error
+ * -----------------------------------------------------------------
+ */
+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++;
+ 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]);
+
+ /* Loop over nj = number of linear solve Jacobian setups. */
+
+ for(nj = 1; nj <= 2; nj++) {
+
+ /* Call the Newton iteration routine */
+ retval = IDASensNewtonIC(IDA_mem);
+ if(retval == IDA_SUCCESS) return(IDA_SUCCESS);
+
+ /* 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) {
+
+ /* Restore deltaS. */
+ for(is=0; is<Ns; is++) N_VScale(ONE, savresS[is], deltaS[is]);
+
+ nsetupsS++;
+ retval = lsetup(IDA_mem, yy0, yp0, delta, tmpS1, tmpS2, tmpS3);
+ if(retval < 0) return(IDA_LSETUP_FAIL);
+ if(retval > 0) return(IC_FAIL_RECOV);
+
+ continue;
+ } else {
+ return(retval);
+ }
+ }
+
+ return(IDA_SUCCESS);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * IDASensNewtonIC
+ * -----------------------------------------------------------------
+ * IDANewtonIC performs the Newton iteration to solve for
+ * sensitivities consistent initial conditions. It calls
+ * IDASensLineSrch within each iteration.
+ * On return, savresS contains the current residual vectors.
+ *
+ * The return value is IDA_SUCCESS = 0 if no error occurred.
+ * The error return values (positive) considered recoverable are:
+ * IC_FAIL_RECOV if res or lsolve failed recoverably
+ * IC_CONSTR_FAILED if the constraints could not be met
+ * IC_LINESRCH_FAILED if the linesearch failed (on steptol test)
+ * IC_CONV_FAIL if the Newton iterations failed to converge
+ * IC_SLOW_CONVRG if the iterations appear to be converging slowly.
+ * They failed the convergence test, but showed
+ * an overall norm reduction (by a factor of < 0.1)
+ * or a convergence rate <= ICRATEMAX).
+ * The error return values (negative) considered non-recoverable are:
+ * IDA_RES_FAIL if res had a non-recoverable error
+ * IDA_LSOLVE_FAIL if lsolve had a non-recoverable error
+ * -----------------------------------------------------------------
+ */
+static int IDASensNewtonIC(IDAMem IDA_mem)
+{
+ int retval, is, mnewt;
+ realtype delnorm, fnorm, fnorm0, oldfnrm, rate;
+
+ for(is=0;is<Ns;is++) {
+
+ /* Call the linear solve function to get the Newton step, delta. */
+ retval = lsolve(IDA_mem, deltaS[is], ewtS[is], yy0, yp0, 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*ABS(cj);
+ if(fnorm <= epsNewt) return(IDA_SUCCESS);
+ fnorm0 = fnorm;
+
+ rate = ZERO;
+
+ /* Newton iteration loop */
+ for(mnewt = 0; mnewt < maxnit; mnewt++) {
+
+ nniS++;
+ delnorm = fnorm;
+ oldfnrm = fnorm;
+
+ /* Call the Linesearch function and return if it failed. */
+ retval = IDASensLineSrch(IDA_mem, &delnorm, &fnorm);
+ if(retval != IDA_SUCCESS) return(retval);
+
+ /* Set the observed convergence rate and test for convergence. */
+ rate = fnorm/oldfnrm;
+ if(fnorm <= 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]);
+
+ } /* End of Newton iteration loop */
+
+ /* Return either IC_SLOW_CONVRG or recoverable fail flag. */
+ if(rate <= ICRATEMAX || fnorm < PT1*fnorm0) return(IC_SLOW_CONVRG);
+ return(IC_CONV_FAIL);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * IDASensLineSrch
+ * -----------------------------------------------------------------
+ * IDASensLineSrch performs the Linesearch algorithm with the
+ * calculation of consistent initial conditions for sensitivities
+ * systems.
+ *
+ * On entry, yyS0 and ypS0 contain the current values, the Newton
+ * steps are contained in deltaS, the current residual vectors FS are
+ * savresS, delnorm is sens-WRMS-norm(deltaS), and fnorm is
+ * max { WRMS-norm( J-inverse FS[is] ) : is=1,2,...,Ns }
+ *
+ * On a successful return, yy0, yp0, and savres have been updated,
+ * delnew contains the current values of J-inverse FS, and fnorm is
+ * max { WRMS-norm(delnewS[is]) : is = 1,2,...Ns }
+ *
+ * The return value is IDA_SUCCESS = 0 if no error occurred.
+ * The error return values (positive) considered recoverable are:
+ * IC_FAIL_RECOV if res or lsolve failed recoverably
+ * IC_CONSTR_FAILED if the constraints could not be met
+ * IC_LINESRCH_FAILED if the linesearch failed (on steptol test)
+ * The error return values (negative) considered non-recoverable are:
+ * IDA_RES_FAIL if res had a non-recoverable error
+ * IDA_LSOLVE_FAIL if lsolve had a non-recoverable error
+ * -----------------------------------------------------------------
+ */
+
+static int IDASensLineSrch(IDAMem IDA_mem, realtype *delnorm, realtype *fnorm)
+{
+ int is, retval;
+ realtype f1norm, fnormp, f1normp, slpi, minlam;
+ realtype lambda, ratio;
+
+ /* Set work space pointer. */
+ dtemp = phi[3];
+
+ f1norm = (*fnorm)*(*fnorm)*HALF;
+
+ /* Initialize local variables. */
+ ratio = ONE;
+ slpi = -TWO*f1norm*ratio;
+ minlam = steptol/(*delnorm);
+ lambda = ONE;
+
+ loop {
+ /* Get new iteration in (ySnew, ypSnew). */
+ IDASensNewyyp(IDA_mem, lambda);
+
+ /* Get the norm of new function value. */
+ retval = IDASensfnorm(IDA_mem, &fnormp);
+ if (retval!=IDA_SUCCESS) return retval;
+
+ /* If lsoff option is on, break out. */
+ if(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++;
+ }
+
+ /* Update yyS0, ypS0 and fnorm and return. */
+ for(is=0; is<Ns; is++) {
+ N_VScale(ONE, yyS0new[is], yyS0[is]);
+ }
+
+ if (icopt == IDA_YA_YDP_INIT)
+ for(is=0; is<Ns; is++)
+ N_VScale(ONE, ypS0new[is], ypS0[is]);
+
+ *fnorm = fnormp;
+ return(IDA_SUCCESS);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * IDASensfnorm
+ * -----------------------------------------------------------------
+ * IDASensfnorm computes the norm of the current function value, by
+ * evaluating the sensitivity residual function, calling the linear
+ * system solver, and computing a WRMS-norm.
+ *
+ * On return, savresS contains the current residual vectors FS, and
+ * delnewS contains J-inverse FS.
+ *
+ * The return value is IDA_SUCCESS = 0 if no error occurred, or
+ * IC_FAIL_RECOV if res or lsolve failed recoverably, or
+ * IDA_RES_FAIL if res had a non-recoverable error, or
+ * IDA_LSOLVE_FAIL if lsolve had a non-recoverable error.
+ * -----------------------------------------------------------------
+ */
+
+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++;
+ 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]);
+
+ /* Call linear solve function */
+ for(is=0; is<Ns; is++) {
+
+ retval = lsolve(IDA_mem, delnewS[is], ewtS[is], yy0, yp0, 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*ABS(cj);
+
+ return(IDA_SUCCESS);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * IDASensNewyyp
+ * -----------------------------------------------------------------
+ * IDASensNewyyp computes the Newton updates for each of the
+ * sensitivities systems using the current step vector lambda*delta,
+ * in a manner depending on icopt and the input id vector.
+ *
+ * The return value is always IDA_SUCCESS = 0.
+ * -----------------------------------------------------------------
+ */
+
+static int IDASensNewyyp(IDAMem IDA_mem, realtype lambda)
+{
+ int is;
+
+ if(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++) {
+
+ /* 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]);
+ } /* 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]);
+ } /* end loop is */
+ return(IDA_SUCCESS);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * IDAICFailFlag
+ * -----------------------------------------------------------------
+ * IDAICFailFlag prints a message and sets the IDACalcIC return
+ * value appropriate to the flag retval returned by IDANlsIC.
+ * -----------------------------------------------------------------
+ */
+
+static int IDAICFailFlag(IDAMem IDA_mem, int retval)
+{
+
+ /* Depending on retval, print error message and return error flag. */
+ switch(retval) {
+
+ case IDA_RES_FAIL:
+ IDAProcessError(IDA_mem, IDA_RES_FAIL, "IDAS", "IDACalcIC", MSG_IC_RES_NONREC);
+ return(IDA_RES_FAIL);
+
+ case IDA_FIRST_RES_FAIL:
+ IDAProcessError(IDA_mem, IDA_FIRST_RES_FAIL, "IDAS", "IDACalcIC", MSG_IC_RES_FAIL);
+ return(IDA_FIRST_RES_FAIL);
+
+ case IDA_LSETUP_FAIL:
+ IDAProcessError(IDA_mem, IDA_LSETUP_FAIL, "IDAS", "IDACalcIC", MSG_IC_SETUP_FAIL);
+ return(IDA_LSETUP_FAIL);
+
+ case IDA_LSOLVE_FAIL:
+ IDAProcessError(IDA_mem, IDA_LSOLVE_FAIL, "IDAS", "IDACalcIC", MSG_IC_SOLVE_FAIL);
+ return(IDA_LSOLVE_FAIL);
+
+ case IC_FAIL_RECOV:
+ IDAProcessError(IDA_mem, IDA_NO_RECOVERY, "IDAS", "IDACalcIC", MSG_IC_NO_RECOVERY);
+ return(IDA_NO_RECOVERY);
+
+ case IC_CONSTR_FAILED:
+ IDAProcessError(IDA_mem, IDA_CONSTR_FAIL, "IDAS", "IDACalcIC", MSG_IC_FAIL_CONSTR);
+ return(IDA_CONSTR_FAIL);
+
+ case IC_LINESRCH_FAILED:
+ IDAProcessError(IDA_mem, IDA_LINESEARCH_FAIL, "IDAS", "IDACalcIC", MSG_IC_FAILED_LINS);
+ return(IDA_LINESEARCH_FAIL);
+
+ case IC_CONV_FAIL:
+ IDAProcessError(IDA_mem, IDA_CONV_FAIL, "IDAS", "IDACalcIC", MSG_IC_CONV_FAILED);
+ return(IDA_CONV_FAIL);
+
+ case IC_SLOW_CONVRG:
+ IDAProcessError(IDA_mem, IDA_CONV_FAIL, "IDAS", "IDACalcIC", MSG_IC_CONV_FAILED);
+ return(IDA_CONV_FAIL);
+
+ case IDA_BAD_EWT:
+ IDAProcessError(IDA_mem, IDA_BAD_EWT, "IDAS", "IDACalcIC", MSG_IC_BAD_EWT);
+ return(IDA_BAD_EWT);
+
+ }
+ return -99;
+}
diff --git a/src/idas/idas_impl.h b/src/idas/idas_impl.h
new file mode 100644
index 0000000..72b3bf7
--- /dev/null
+++ b/src/idas/idas_impl.h
@@ -0,0 +1,1055 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.23 $
+ * $Date: 2011/04/27 20:39:34 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * This is the header file (private version) for the main IDAS solver.
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _IDAS_IMPL_H
+#define _IDAS_IMPL_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <stdarg.h>
+
+#include <idas/idas.h>
+#include <sundials/sundials_nvector.h>
+#include <sundials/sundials_types.h>
+
+/*
+ * =================================================================
+ * M A I N I N T E G R A T O R M E M O R Y B L O C K
+ * =================================================================
+ */
+
+
+/* Basic IDA constants */
+
+#define HMAX_INV_DEFAULT RCONST(0.0) /* hmax_inv default value */
+#define MAXORD_DEFAULT 5 /* maxord default value */
+#define MXORDP1 6 /* max. number of N_Vectors in phi */
+#define MXSTEP_DEFAULT 500 /* mxstep default value */
+
+/* itol */
+#define IDA_NN 0
+#define IDA_SS 1
+#define IDA_SV 2
+#define IDA_WF 3
+#define IDA_EE 4
+
+/*
+ * -----------------------------------------------------------------
+ * Types: struct IDAMemRec, IDAMem
+ * -----------------------------------------------------------------
+ * The type IDAMem is type pointer to struct IDAMemRec.
+ * This structure contains fields to keep track of problem state.
+ * -----------------------------------------------------------------
+ */
+
+typedef struct IDAMemRec {
+
+ realtype ida_uround; /* machine unit roundoff */
+
+ /*--------------------------
+ Problem Specification Data
+ --------------------------*/
+
+ IDAResFn ida_res; /* F(t,y(t),y'(t))=0; the function F */
+ void *ida_user_data; /* user pointer passed to res */
+
+ int ida_itol; /* itol = IDA_SS, IDA_SV, IDA_WF, IDA_NN */
+ 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 */
+ IDAEwtFn ida_efun; /* function to set ewt */
+ void *ida_edata; /* user pointer passed to efun */
+
+ /*-----------------------
+ Quadrature Related Data
+ -----------------------*/
+
+ booleantype ida_quadr;
+
+ IDAQuadRhsFn ida_rhsQ;
+ void *ida_user_dataQ;
+
+ booleantype ida_errconQ;
+
+ int ida_itolQ;
+ realtype ida_rtolQ;
+ realtype ida_SatolQ; /* scalar absolute tolerance for quadratures */
+ N_Vector ida_VatolQ; /* vector absolute tolerance for quadratures */
+
+ /*------------------------
+ Sensitivity Related Data
+ ------------------------*/
+
+ booleantype ida_sensi;
+ int ida_Ns;
+ int ida_ism;
+
+ IDASensResFn ida_resS;
+ void *ida_user_dataS;
+ booleantype ida_resSDQ;
+
+ realtype *ida_p;
+ realtype *ida_pbar;
+ int *ida_plist;
+ int ida_DQtype;
+ realtype ida_DQrhomax;
+
+ booleantype ida_errconS; /* TRUE if sensitivities in err. control */
+
+ int ida_itolS;
+ realtype ida_rtolS; /* relative tolerance for sensitivities */
+ realtype *ida_SatolS; /* scalar absolute tolerances for sensi. */
+ N_Vector *ida_VatolS; /* vector absolute tolerances for sensi. */
+
+ /*-----------------------------------
+ Quadrature Sensitivity Related Data
+ -----------------------------------*/
+
+ booleantype ida_quadr_sensi; /* TRUE 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 */
+
+ booleantype ida_errconQS; /* TRUE if yQS are considered in err. con. */
+
+ int ida_itolQS;
+ realtype ida_rtolQS; /* relative tolerance for yQS */
+ realtype *ida_SatolQS; /* scalar absolute tolerances for yQS */
+ N_Vector *ida_VatolQS; /* vector absolute tolerances for yQS */
+
+ /*-----------------------------------------------
+ Divided differences array and associated arrays
+ -----------------------------------------------*/
+
+ N_Vector ida_phi[MXORDP1]; /* phi = (maxord+1) arrays of divided differences */
+
+ realtype ida_psi[MXORDP1]; /* differences in t (sums of recent step sizes) */
+ realtype ida_alpha[MXORDP1]; /* ratios of current stepsize to psi values */
+ realtype ida_beta[MXORDP1]; /* ratios of current to previous product of psi's */
+ realtype ida_sigma[MXORDP1]; /* product successive alpha values and factorial */
+ realtype ida_gamma[MXORDP1]; /* sum of reciprocals of psi values */
+
+ /*-------------------------
+ N_Vectors for integration
+ -------------------------*/
+
+ N_Vector ida_ewt; /* error weight vector */
+ N_Vector ida_yy; /* work space for y vector (= user's yret) */
+ N_Vector ida_yp; /* work space for y' vector (= user's ypret) */
+ N_Vector ida_delta; /* residual vector */
+ N_Vector ida_id; /* bit vector for diff./algebraic components */
+ N_Vector ida_constraints; /* vector of inequality constraint options */
+ N_Vector ida_savres; /* saved residual vector (= tempv1) */
+ N_Vector ida_ee; /* accumulated corrections to y vector, but
+ set equal to estimated local errors upon
+ successful return */
+ N_Vector ida_mm; /* mask vector in constraints tests (= tempv2) */
+ N_Vector ida_tempv1; /* work space vector */
+ N_Vector ida_tempv2; /* work space vector */
+ N_Vector ida_ynew; /* work vector for y in IDACalcIC (= tempv2) */
+ N_Vector ida_ypnew; /* work vector for yp in IDACalcIC (= ee) */
+ N_Vector ida_delnew; /* work vector for delta in IDACalcIC (= phi[2]) */
+ N_Vector ida_dtemp; /* work vector in IDACalcIC (= phi[3]) */
+
+
+ /*----------------------------
+ Quadrature Related N_Vectors
+ ----------------------------*/
+
+ N_Vector ida_phiQ[MXORDP1];
+ N_Vector ida_yyQ;
+ N_Vector ida_ypQ;
+ N_Vector ida_ewtQ;
+ N_Vector ida_eeQ;
+
+ /*---------------------------
+ Sensitivity Related Vectors
+ ---------------------------*/
+
+ N_Vector *ida_phiS[MXORDP1];
+ N_Vector *ida_ewtS;
+
+ N_Vector *ida_eeS; /* cumulative sensitivity corrections */
+
+ N_Vector *ida_yyS; /* allocated and used for: */
+ N_Vector *ida_ypS; /* ism = SIMULTANEOUS */
+ N_Vector *ida_deltaS; /* ism = STAGGERED */
+
+ N_Vector ida_tmpS1; /* work space vectors | tmpS1 = tempv1 */
+ N_Vector ida_tmpS2; /* for resS | tmpS2 = tempv2 */
+ N_Vector ida_tmpS3; /* | tmpS3 = allocated */
+
+ N_Vector *ida_savresS; /* work vector in IDACalcIC for stg (= phiS[2]) */
+ N_Vector *ida_delnewS; /* work vector in IDACalcIC for stg (= phiS[3]) */
+
+ N_Vector *ida_yyS0; /* initial yS, ypS vectors allocated and */
+ N_Vector *ida_ypS0; /* deallocated in IDACalcIC function */
+
+ N_Vector *ida_yyS0new; /* work vector in IDASensLineSrch (= phiS[4]) */
+ N_Vector *ida_ypS0new; /* work vector in IDASensLineSrch (= eeS) */
+
+ /*--------------------------------------
+ Quadrature Sensitivity Related Vectors
+ --------------------------------------*/
+
+ N_Vector *ida_phiQS[MXORDP1];/* Mod. div. diffs. for quadr. sensitivities */
+ N_Vector *ida_ewtQS; /* error weight vectors for sensitivities */
+
+ N_Vector *ida_eeQS; /* cumulative quadr.sensi.corrections */
+
+ N_Vector *ida_yyQS; /* Unlike yS, yQS is not allocated by the user */
+ N_Vector *ida_tempvQS; /* temporary storage vector (~ tempv) */
+ N_Vector ida_savrhsQ; /* saved quadr. rhs (needed for rhsQS calls) */
+
+ /*------------------------------
+ Variables for use by IDACalcIC
+ ------------------------------*/
+
+ realtype ida_t0; /* initial t */
+ N_Vector ida_yy0; /* initial y vector (user-supplied). */
+ N_Vector ida_yp0; /* initial y' vector (user-supplied). */
+
+ int ida_icopt; /* IC calculation user option */
+ booleantype ida_lsoff; /* IC calculation linesearch turnoff option */
+ int ida_maxnh; /* max. number of h tries in IC calculation */
+ int ida_maxnj; /* max. number of J tries in IC calculation */
+ int ida_maxnit; /* max. number of Netwon iterations in IC calc. */
+ int ida_nbacktr; /* number of IC linesearch backtrack operations */
+ int ida_sysindex; /* computed system index (0 or 1) */
+ realtype ida_epiccon; /* IC nonlinear convergence test constant */
+ realtype ida_steptol; /* minimum Newton step size in IC calculation */
+ realtype ida_tscale; /* time scale factor = abs(tout1 - t0) */
+
+ /* Tstop information */
+
+ booleantype ida_tstopset;
+ realtype ida_tstop;
+
+ /* Step Data */
+
+ int ida_kk; /* current BDF method order */
+ int ida_knew; /* order for next step from order decrease decision */
+ int ida_phase; /* flag to trigger step doubling in first few steps */
+ int ida_ns; /* counts steps at fixed stepsize and order */
+
+ realtype ida_hin; /* initial step */
+ realtype ida_hh; /* current step size h */
+ realtype ida_rr; /* rr = hnext / hused */
+ realtype ida_tn; /* current internal value of t */
+ realtype ida_tretlast; /* value of tret previously returned by IDASolve */
+ realtype ida_cj; /* current value of scalar (-alphas/hh) in Jacobian */
+ realtype ida_cjlast; /* cj value saved from last successful step */
+ realtype ida_cjold; /* cj value saved from last call to lsetup */
+ realtype ida_cjratio; /* ratio of cj values: cj/cjold */
+ realtype ida_ss; /* scalar used in Newton iteration convergence test */
+ realtype ida_epsNewt; /* test constant in Newton convergence test */
+ realtype ida_epcon; /* coeficient of the Newton covergence test */
+ realtype ida_toldel; /* tolerance in direct test on Newton corrections */
+
+ realtype ida_ssS; /* scalar ss for staggered sensitivities */
+
+ /*------
+ Limits
+ ------*/
+
+ int ida_maxncf; /* max numer of convergence failures */
+ int ida_maxcor; /* max number of Newton corrections */
+ int ida_maxnef; /* max number of error test failures */
+
+ int ida_maxord; /* max value of method order k: */
+ int ida_maxord_alloc; /* value of maxord used when allocating memory */
+ long int ida_mxstep; /* max number of internal steps for one user call */
+ realtype ida_hmax_inv; /* inverse of max. step size hmax (default = 0.0) */
+
+ int ida_maxcorS; /* max number of Newton corrections for sensitivity
+ systems (staggered method) */
+
+ /*--------
+ Counters
+ --------*/
+
+ long int ida_nst; /* number of internal steps taken */
+
+ long int ida_nre; /* number of function (res) calls */
+ long int ida_nrQe;
+ long int ida_nrSe;
+ long int ida_nrQSe; /* number of fQS calls */
+ long int ida_nreS;
+ long int ida_nrQeS; /* number of fQ calls from sensi DQ */
+
+
+ long int ida_ncfn; /* number of corrector convergence failures */
+ long int ida_ncfnQ;
+ long int ida_ncfnS;
+
+ long int ida_netf; /* number of error test failures */
+ long int ida_netfQ;
+ long int ida_netfS;
+ long int ida_netfQS; /* number of quadr. sensi. error test failures */
+
+ long int ida_nni; /* number of Newton iterations performed */
+ long int ida_nniS;
+
+ long int ida_nsetups; /* number of lsetup calls */
+ long int ida_nsetupsS;
+
+ /*---------------------------
+ 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 */
+
+
+ /*-------------------------------------------
+ Error handler function and error ouput file
+ -------------------------------------------*/
+
+ IDAErrHandlerFn ida_ehfun; /* Error messages are handled by ehfun */
+ void *ida_eh_data; /* dats pointer passed to ehfun */
+ FILE *ida_errfp; /* IDA error messages are sent to errfp */
+
+ /* 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_VatolMallocDone;
+ booleantype ida_constraintsMallocDone;
+ booleantype ida_idMallocDone;
+
+ booleantype ida_MallocDone; /* set to FALSE by IDACreate
+ set to TRUE by IDAInit
+ tested by IDAReInit and IDASolve */
+
+ booleantype ida_VatolQMallocDone;
+ booleantype ida_quadMallocDone;
+
+ booleantype ida_VatolSMallocDone;
+ booleantype ida_SatolSMallocDone;
+ booleantype ida_sensMallocDone;
+
+ booleantype ida_VatolQSMallocDone;
+ booleantype ida_SatolQSMallocDone;
+ booleantype ida_quadSensMallocDone;
+
+ /*------------------
+ Linear Solver Data
+ ------------------*/
+
+ /* Linear Solver functions to be called */
+
+ int (*ida_linit)(struct IDAMemRec *idamem);
+
+ int (*ida_lsetup)(struct IDAMemRec *idamem, N_Vector yyp,
+ N_Vector ypp, N_Vector resp,
+ N_Vector tempv1, N_Vector tempv2, N_Vector tempv3);
+
+ int (*ida_lsolve)(struct IDAMemRec *idamem, N_Vector b, N_Vector weight,
+ N_Vector ycur, N_Vector ypcur, N_Vector rescur);
+
+ int (*ida_lperf)(struct IDAMemRec *idamem, int perftask);
+
+ int (*ida_lfree)(struct IDAMemRec *idamem);
+
+ /* Linear Solver specific memory */
+
+ void *ida_lmem;
+
+ /* Flag to request a call to the setup routine */
+
+ booleantype ida_forceSetup;
+
+ /* Flag to indicate successful ida_linit call */
+
+ booleantype ida_linitOK;
+
+ /*------------
+ 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) */
+
+ /*----------------
+ Rootfinding Data
+ ----------------*/
+
+ IDARootFn ida_gfun; /* Function g for roots sought */
+ int ida_nrtfn; /* number of components of g */
+ int *ida_iroots; /* array for root information */
+ int *ida_rootdir; /* array specifying direction of zero-crossing */
+ realtype ida_tlo; /* nearest endpoint of interval in root search */
+ realtype ida_thi; /* farthest endpoint of interval in root search */
+ realtype ida_trout; /* t return value from rootfinder routine */
+ realtype *ida_glo; /* saved array of g values at t = tlo */
+ realtype *ida_ghi; /* saved array of g values at t = thi */
+ realtype *ida_grout; /* array of g values at t = trout */
+ realtype ida_toutc; /* copy of tout (if NORMAL mode) */
+ realtype ida_ttol; /* tolerance on root location */
+ int ida_taskc; /* copy of parameter itask */
+ int ida_irfnd; /* flag showing whether last step had a root */
+ long int ida_nge; /* counter for g evaluations */
+ booleantype *ida_gactive; /* array with active/inactive event functions */
+ int ida_mxgnull; /* number of warning messages about possible g==0 */
+
+ /*------------------------
+ Adjoint sensitivity data
+ ------------------------*/
+
+ booleantype ida_adj; /* TRUE if performing ASA */
+
+ struct IDAadjMemRec *ida_adj_mem; /* Pointer to adjoint memory structure */
+
+ booleantype ida_adjMallocDone;
+
+} *IDAMem;
+
+/*
+ * =================================================================
+ * A D J O I N T M O D U L E M E M O R Y B L O C K
+ * =================================================================
+ */
+
+/*
+ * -----------------------------------------------------------------
+ * Forward references for pointers to various structures
+ * -----------------------------------------------------------------
+ */
+
+typedef struct IDAadjMemRec *IDAadjMem;
+typedef struct CkpntMemRec *CkpntMem;
+typedef struct DtpntMemRec *DtpntMem;
+typedef struct IDABMemRec *IDABMem;
+
+/*
+ * -----------------------------------------------------------------
+ * Types for functions provided by an interpolation module
+ * -----------------------------------------------------------------
+ * IDAAMMallocFn: Type for a function that initializes the content
+ * field of the structures in the dt array
+ * IDAAMFreeFn: Type for a function that deallocates the content
+ * field of the structures in the dt array
+ * IDAAGetYFn: Function type for a function that returns the
+ * interpolated forward solution.
+ * IDAAStorePnt: Function type for a function that stores a new
+ * point in the structure d
+ * -----------------------------------------------------------------
+ */
+
+typedef booleantype (*IDAAMMallocFn)(IDAMem IDA_mem);
+typedef void (*IDAAMFreeFn)(IDAMem IDA_mem);
+typedef int (*IDAAGetYFn)(IDAMem IDA_mem, realtype t,
+ N_Vector yy, N_Vector yp,
+ N_Vector *yyS, N_Vector *ypS);
+typedef int (*IDAAStorePntFn)(IDAMem IDA_mem, DtpntMem d);
+
+/*
+ * -----------------------------------------------------------------
+ * Types : struct CkpntMemRec, CkpntMem
+ * -----------------------------------------------------------------
+ * The type CkpntMem is type pointer to struct CkpntMemRec.
+ * This structure contains fields to store all information at a
+ * check point that is needed to 'hot' start IDAS.
+ * -----------------------------------------------------------------
+ */
+
+struct CkpntMemRec {
+
+ /* Integration limits */
+ realtype ck_t0;
+ realtype ck_t1;
+
+ /* Modified divided difference array */
+ N_Vector ck_phi[MXORDP1];
+
+ /* Do we need to carry quadratures? */
+ booleantype ck_quadr;
+
+ /* Modified divided difference array for quadratures */
+ N_Vector ck_phiQ[MXORDP1];
+
+ /* Do we need to carry sensitivities? */
+ booleantype ck_sensi;
+
+ /* number of sensitivities */
+ int ck_Ns;
+
+ /* Modified divided difference array for sensitivities */
+ N_Vector *ck_phiS[MXORDP1];
+
+ /* Do we need to carry quadrature sensitivities? */
+ booleantype ck_quadr_sensi;
+
+ /* Modified divided difference array for quadrature sensitivities */
+ N_Vector *ck_phiQS[MXORDP1];
+
+
+ /* Step data */
+ long int ck_nst;
+ realtype ck_tretlast;
+ long int ck_ns;
+ int ck_kk;
+ int ck_kused;
+ int ck_knew;
+ int ck_phase;
+
+ realtype ck_hh;
+ realtype ck_hused;
+ realtype ck_rr;
+ realtype ck_cj;
+ realtype ck_cjlast;
+ realtype ck_cjold;
+ realtype ck_cjratio;
+ realtype ck_ss;
+ realtype ck_ssS;
+
+ realtype ck_psi[MXORDP1];
+ realtype ck_alpha[MXORDP1];
+ realtype ck_beta[MXORDP1];
+ realtype ck_sigma[MXORDP1];
+ realtype ck_gamma[MXORDP1];
+
+ /* How many phi, phiS, phiQ and phiQS were allocated? */
+ int ck_phi_alloc;
+
+ /* Pointer to next structure in list */
+ struct CkpntMemRec *ck_next;
+};
+
+/*
+ * -----------------------------------------------------------------
+ * Type : struct DtpntMemRec
+ * -----------------------------------------------------------------
+ * This structure contains fields to store all information at a
+ * data point that is needed to interpolate solution of forward
+ * simulations. Its content field is interpType-dependent.
+ * -----------------------------------------------------------------
+ */
+
+struct DtpntMemRec {
+ realtype t; /* time */
+ void *content; /* interpType-dependent content */
+};
+
+/* Data for cubic Hermite interpolation */
+typedef struct HermiteDataMemRec {
+ N_Vector y;
+ N_Vector yd;
+ N_Vector *yS;
+ N_Vector *ySd;
+} *HermiteDataMem;
+
+/* Data for polynomial interpolation */
+typedef struct PolynomialDataMemRec {
+ N_Vector y;
+ N_Vector *yS;
+
+ /* yd and ySd store the derivative(s) only for the first dt
+ point. NULL otherwise. */
+ N_Vector yd;
+ N_Vector *ySd;
+ int order;
+} *PolynomialDataMem;
+
+/*
+ * -----------------------------------------------------------------
+ * Type : struct IDABMemRec
+ * -----------------------------------------------------------------
+ * The type IDABMemRec is a pointer to a structure which stores all
+ * information for ONE backward problem.
+ * The IDAadjMem struct contains a linked list of IDABMem pointers
+ * -----------------------------------------------------------------
+ */
+struct IDABMemRec {
+
+ /* Index of this backward problem */
+ int ida_index;
+
+ /* Time at which the backward problem is initialized. */
+ realtype ida_t0;
+
+ /* Memory for this backward problem */
+ IDAMem IDA_mem;
+
+ /* Flags to indicate that this backward problem's RHS or quad RHS
+ * require forward sensitivities */
+ booleantype ida_res_withSensi;
+ booleantype ida_rhsQ_withSensi;
+
+ /* Residual function for backward run */
+ IDAResFnB ida_res;
+ IDAResFnBS ida_resS;
+
+ /* Right hand side quadrature function (fQB) for backward run */
+ IDAQuadRhsFnB ida_rhsQ;
+ IDAQuadRhsFnBS ida_rhsQS;
+
+ /* User user_data */
+ void *ida_user_data;
+
+ /* Linear solver's data and functions */
+
+ /* Memory block for a linear solver's interface to IDAA */
+ void *ida_lmem;
+
+ /* Function to free any memory allocated by the linear solver */
+ void (*ida_lfree)(IDABMem IDAB_mem);
+
+ /* Memory block for a preconditioner's module interface to IDAA */
+ void *ida_pmem;
+
+ /* Function to free any memory allocated by the preconditioner module */
+ void (*ida_pfree)(IDABMem IDAB_mem);
+
+ /* Time at which to extract solution / quadratures */
+ realtype ida_tout;
+
+ /* Workspace Nvectors */
+ N_Vector ida_yy;
+ N_Vector ida_yp;
+
+ /* Link to next structure in list. */
+ struct IDABMemRec *ida_next;
+};
+
+
+/*
+ * -----------------------------------------------------------------
+ * Type : struct IDAadjMemRec
+ * -----------------------------------------------------------------
+ * The type IDAadjMem is type pointer to struct IDAadjMemRec.
+ * This structure contins fields to store all information
+ * necessary for adjoint sensitivity analysis.
+ * -----------------------------------------------------------------
+ */
+
+struct IDAadjMemRec {
+
+ /* --------------------
+ * Forward problem data
+ * -------------------- */
+
+ /* Integration interval */
+ realtype ia_tinitial, ia_tfinal;
+
+ /* Flag for first call to IDASolveF */
+ booleantype ia_firstIDAFcall;
+
+ /* Flag if IDASolveF was called with TSTOP */
+ booleantype ia_tstopIDAFcall;
+ realtype ia_tstopIDAF;
+
+ /* ----------------------
+ * Backward problems data
+ * ---------------------- */
+
+ /* Storage for backward problems */
+ struct IDABMemRec *IDAB_mem;
+
+ /* Number of backward problems. */
+ int ia_nbckpbs;
+
+ /* Address of current backward problem (iterator). */
+ struct IDABMemRec *ia_bckpbCrt;
+
+ /* Flag for first call to IDASolveB */
+ booleantype ia_firstIDABcall;
+
+ /* ----------------
+ * Check point data
+ * ---------------- */
+
+ /* Storage for check point information */
+ struct CkpntMemRec *ck_mem;
+
+ /* address of the check point structure for which data is available */
+ struct CkpntMemRec *ia_ckpntData;
+
+ /* Number of checkpoints. */
+ int ia_nckpnts;
+
+ /* ------------------
+ * Interpolation data
+ * ------------------ */
+
+ /* Number of steps between 2 check points */
+ long int ia_nsteps;
+
+ /* Storage for data from forward runs */
+ struct DtpntMemRec **dt_mem;
+
+ /* Actual number of data points saved in current dt_mem */
+ /* Commonly, np = nsteps+1 */
+ long int ia_np;
+
+ /* Interpolation type */
+ int ia_interpType;
+
+
+ /* Functions set by the interpolation module */
+ IDAAStorePntFn ia_storePnt; /* store a new interpolation point */
+ IDAAGetYFn ia_getY; /* interpolate forward solution */
+ IDAAMMallocFn ia_malloc; /* allocate new data point */
+ IDAAMFreeFn ia_free; /* destroys data point */
+
+ /* Flags controlling the interpolation module */
+ booleantype ia_mallocDone; /* IM initialized? */
+ booleantype ia_newData; /* new data available in dt_mem? */
+ booleantype ia_storeSensi; /* store sensitivities? */
+ booleantype ia_interpSensi; /* interpolate sensitivities? */
+
+ booleantype ia_noInterp; /* interpolations are temporarly */
+ /* disabled ( IDACalcICB ) */
+
+ /* Workspace for polynomial interpolation */
+ N_Vector ia_Y[MXORDP1]; /* pointers phi[i] */
+ N_Vector *ia_YS[MXORDP1]; /* pointers phiS[i] */
+ realtype ia_T[MXORDP1];
+
+ /* Workspace for wrapper functions */
+ N_Vector ia_yyTmp, ia_ypTmp;
+ N_Vector *ia_yySTmp, *ia_ypSTmp;
+
+};
+
+
+/*
+ * =================================================================
+ * I N T E R F A C E T O L I N E A R S O L V E R S
+ * =================================================================
+ */
+
+/*
+ * -----------------------------------------------------------------
+ * int (*ida_linit)(IDAMem IDA_mem);
+ * -----------------------------------------------------------------
+ * The purpose of ida_linit is to allocate memory for the
+ * solver-specific fields in the structure *(idamem->ida_lmem) and
+ * perform any needed initializations of solver-specific memory,
+ * such as counters/statistics. An (*ida_linit) should return
+ * 0 if it has successfully initialized the IDA linear solver and
+ * a non-zero value otherwise. If an error does occur, an
+ * appropriate message should be issued.
+ * ----------------------------------------------------------------
+ */
+
+/*
+ * -----------------------------------------------------------------
+ * int (*ida_lsetup)(IDAMem IDA_mem, N_Vector yyp, N_Vector ypp,
+ * 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:
+ *
+ * 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.
+ *
+ * ypp - the predicted y' vector for the current IDA internal
+ * step.
+ *
+ * resp - F(tn, yyp, ypp).
+ *
+ * tempv1, tempv2, tempv3 - temporary N_Vectors provided for use
+ * by ida_lsetup.
+ *
+ * The ida_lsetup routine should return 0 if successful,
+ * a positive value for a recoverable error, and a negative value
+ * for an unrecoverable error.
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * -----------------------------------------------------------------
+ * int (*ida_lsolve)(IDAMem IDA_mem, N_Vector b, N_Vector weight,
+ * 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
+ * J = (dF/dy) + cj (dF/dy')
+ * evaluated at (tn,ycur,ypcur) and the RHS vector b is input.
+ * The N-vector ycur contains the solver's current approximation
+ * to y(tn), ypcur contains that for y'(tn), and the vector rescur
+ * contains the N-vector residual F(tn,ycur,ypcur).
+ * The solution is to be returned in the vector b.
+ *
+ * The ida_lsolve routine should return 0 if successful,
+ * a positive value for a recoverable error, and a negative value
+ * for an unrecoverable error.
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * -----------------------------------------------------------------
+ * int (*ida_lperf)(IDAMem IDA_mem, int perftask);
+ * -----------------------------------------------------------------
+ * ida_lperf is called two places in IDAS where linear solver
+ * performance data is required by IDAS. For perftask = 0, an
+ * initialization of performance variables is performed, while for
+ * perftask = 1, the performance is evaluated.
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * =================================================================
+ * I D A S I N T E R N A L F U N C T I O N S
+ * =================================================================
+ */
+
+/* Prototype of internal ewtSet function */
+
+int IDAEwtSet(N_Vector ycur, N_Vector weight, void *data);
+
+/* High level error handler */
+
+void IDAProcessError(IDAMem IDA_mem,
+ int error_code, const char *module, const char *fname,
+ const char *msgfmt, ...);
+
+/* Prototype of internal errHandler function */
+
+void IDAErrHandler(int error_code, const char *module, const char *function,
+ char *msg, void *data);
+
+/* Prototype for internal sensitivity residual DQ function */
+
+int IDASensResDQ(int Ns, realtype t,
+ N_Vector yy, N_Vector yp, N_Vector resval,
+ N_Vector *yyS, N_Vector *ypS, N_Vector *resvalS,
+ void *user_dataS,
+ N_Vector ytemp, N_Vector yptemp, N_Vector restemp);
+
+/*
+ * =================================================================
+ * I D A S E R R O R M E S S A G E S
+ * =================================================================
+ */
+
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+
+#define MSG_TIME "t = %Lg, "
+#define MSG_TIME_H "t = %Lg and h = %Lg, "
+#define MSG_TIME_INT "t = %Lg is not between tcur - hu = %Lg and tcur = %Lg."
+#define MSG_TIME_TOUT "tout = %Lg"
+#define MSG_TIME_TSTOP "tstop = %Lg"
+
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+
+#define MSG_TIME "t = %lg, "
+#define MSG_TIME_H "t = %lg and h = %lg, "
+#define MSG_TIME_INT "t = %lg is not between tcur - hu = %lg and tcur = %lg."
+#define MSG_TIME_TOUT "tout = %lg"
+#define MSG_TIME_TSTOP "tstop = %lg"
+
+#else
+
+#define MSG_TIME "t = %g, "
+#define MSG_TIME_H "t = %g and h = %g, "
+#define MSG_TIME_INT "t = %g is not between tcur - hu = %g and tcur = %g."
+#define MSG_TIME_TOUT "tout = %g"
+#define MSG_TIME_TSTOP "tstop = %g"
+
+#endif
+
+/* General errors */
+
+#define MSG_MEM_FAIL "A memory request failed."
+#define MSG_NO_MEM "ida_mem = NULL illegal."
+#define MSG_NO_MALLOC "Attempt to call before IDAMalloc."
+#define MSG_BAD_NVECTOR "A required vector operation is not implemented."
+
+/* Initialization errors */
+
+#define MSG_Y0_NULL "y0 = NULL illegal."
+#define MSG_YP0_NULL "yp0 = NULL illegal."
+#define MSG_BAD_ITOL "Illegal value for itol. The legal values are IDA_SS, IDA_SV, and IDA_WF."
+#define MSG_RES_NULL "res = NULL illegal."
+#define MSG_BAD_RTOL "rtol < 0 illegal."
+#define MSG_ATOL_NULL "atol = NULL illegal."
+#define MSG_BAD_ATOL "Some atol component < 0.0 illegal."
+#define MSG_ROOT_FUNC_NULL "g = NULL illegal."
+
+#define MSG_MISSING_ID "id = NULL but suppressalg option on."
+#define MSG_NO_TOLS "No integration tolerances have been specified."
+#define MSG_FAIL_EWT "The user-provide EwtSet function failed."
+#define MSG_BAD_EWT "Some initial ewt component = 0.0 illegal."
+#define MSG_Y0_FAIL_CONSTR "y0 fails to satisfy constraints."
+#define MSG_BAD_ISM_CONSTR "Constraints can not be enforced while forward sensitivity is used with simultaneous method."
+#define MSG_LSOLVE_NULL "The linear solver's solve routine is NULL."
+#define MSG_LINIT_FAIL "The linear solver's init routine failed."
+
+#define MSG_NO_QUAD "Illegal attempt to call before calling IDAQuadInit."
+#define MSG_BAD_EWTQ "Initial ewtQ has component(s) equal to zero (illegal)."
+#define MSG_BAD_ITOLQ "Illegal value for itolQ. The legal values are IDA_SS and IDA_SV."
+#define MSG_NO_TOLQ "No integration tolerances for quadrature variables have been specified."
+#define MSG_NULL_ATOLQ "atolQ = NULL illegal."
+#define MSG_BAD_RTOLQ "rtolQ < 0 illegal."
+#define MSG_BAD_ATOLQ "atolQ has negative component(s) (illegal)."
+
+#define MSG_NO_SENSI "Illegal attempt to call before calling IDASensInit."
+#define MSG_BAD_EWTS "Initial ewtS has component(s) equal to zero (illegal)."
+#define MSG_BAD_ITOLS "Illegal value for itolS. The legal values are IDA_SS, IDA_SV, and IDA_EE."
+#define MSG_NULL_ATOLS "atolS = NULL illegal."
+#define MSG_BAD_RTOLS "rtolS < 0 illegal."
+#define MSG_BAD_ATOLS "atolS has negative component(s) (illegal)."
+#define MSG_BAD_PBAR "pbar has zero component(s) (illegal)."
+#define MSG_BAD_PLIST "plist has negative component(s) (illegal)."
+#define MSG_BAD_NS "NS <= 0 illegal."
+#define MSG_NULL_YYS0 "yyS0 = NULL illegal."
+#define MSG_NULL_YPS0 "ypS0 = NULL illegal."
+#define MSG_BAD_ISM "Illegal value for ism. Legal values are: IDA_SIMULTANEOUS and IDA_STAGGERED."
+#define MSG_BAD_IS "Illegal value for is."
+#define MSG_NULL_DKYA "dkyA = NULL illegal."
+#define MSG_BAD_DQTYPE "Illegal value for DQtype. Legal values are: IDA_CENTERED and IDA_FORWARD."
+#define MSG_BAD_DQRHO "DQrhomax < 0 illegal."
+
+#define MSG_NULL_ABSTOLQS "abstolQS = NULL illegal parameter."
+#define MSG_BAD_RELTOLQS "reltolQS < 0 illegal parameter."
+#define MSG_BAD_ABSTOLQS "abstolQS has negative component(s) (illegal)."
+#define MSG_NO_QUADSENSI "Forward sensitivity analysis for quadrature variables was not activated."
+#define MSG_NULL_YQS0 "yQS0 = NULL illegal parameter."
+
+
+/* IDACalcIC error messages */
+
+#define MSG_IC_BAD_ICOPT "icopt has an illegal value."
+#define MSG_IC_MISSING_ID "id = NULL conflicts with icopt."
+#define MSG_IC_TOO_CLOSE "tout1 too close to t0 to attempt initial condition calculation."
+#define MSG_IC_BAD_ID "id has illegal values."
+#define MSG_IC_BAD_EWT "Some initial ewt component = 0.0 illegal."
+#define MSG_IC_RES_NONREC "The residual function failed unrecoverably. "
+#define MSG_IC_RES_FAIL "The residual function failed at the first call. "
+#define MSG_IC_SETUP_FAIL "The linear solver setup failed unrecoverably."
+#define MSG_IC_SOLVE_FAIL "The linear solver solve failed unrecoverably."
+#define MSG_IC_NO_RECOVERY "The residual routine or the linear setup or solve routine had a recoverable error, but IDACalcIC was unable to recover."
+#define MSG_IC_FAIL_CONSTR "Unable to satisfy the inequality constraints."
+#define MSG_IC_FAILED_LINS "The linesearch algorithm failed with too small a step."
+#define MSG_IC_CONV_FAILED "Newton/Linesearch algorithm failed to converge."
+
+/* IDASolve error messages */
+
+#define MSG_YRET_NULL "yret = NULL illegal."
+#define MSG_YPRET_NULL "ypret = NULL illegal."
+#define MSG_TRET_NULL "tret = NULL illegal."
+#define MSG_BAD_ITASK "itask has an illegal value."
+#define MSG_TOO_CLOSE "tout too close to t0 to start integration."
+#define MSG_BAD_HINIT "Initial step is not towards tout."
+#define MSG_BAD_TSTOP "The value " MSG_TIME_TSTOP " is behind current " MSG_TIME "in the direction of integration."
+#define MSG_CLOSE_ROOTS "Root found at and very near " MSG_TIME "."
+#define MSG_MAX_STEPS "At " MSG_TIME ", mxstep steps taken before reaching tout."
+#define MSG_EWT_NOW_FAIL "At " MSG_TIME "the user-provide EwtSet function failed."
+#define MSG_EWT_NOW_BAD "At " MSG_TIME "some ewt component has become <= 0.0."
+#define MSG_TOO_MUCH_ACC "At " MSG_TIME "too much accuracy requested."
+
+#define MSG_BAD_T "Illegal value for t. " MSG_TIME_INT
+#define MSG_BAD_TOUT "Trouble interpolating at " MSG_TIME_TOUT ". tout too far back in direction of integration."
+
+#define MSG_BAD_K "Illegal value for k."
+#define MSG_NULL_DKY "dky = NULL illegal."
+#define MSG_NULL_DKYP "dkyp = NULL illegal."
+
+#define MSG_ERR_FAILS "At " MSG_TIME_H "the error test failed repeatedly or with |h| = hmin."
+#define MSG_CONV_FAILS "At " MSG_TIME_H "the corrector convergence failed repeatedly or with |h| = hmin."
+#define MSG_SETUP_FAILED "At " MSG_TIME "the linear solver setup failed unrecoverably."
+#define MSG_SOLVE_FAILED "At " MSG_TIME "the linear solver solve failed unrecoverably."
+#define MSG_REP_RES_ERR "At " MSG_TIME "repeated recoverable residual errors."
+#define MSG_RES_NONRECOV "At " MSG_TIME "the residual function failed unrecoverably."
+#define MSG_FAILED_CONSTR "At " MSG_TIME "unable to satisfy inequality constraints."
+#define MSG_RTFUNC_FAILED "At " MSG_TIME ", the rootfinding routine failed in an unrecoverable manner."
+#define MSG_NO_ROOT "Rootfinding was not initialized."
+#define MSG_INACTIVE_ROOTS "At the end of the first step, there are still some root functions identically 0. This warning will not be issued again."
+
+#define MSG_EWTQ_NOW_BAD "At " MSG_TIME ", a component of ewtQ has become <= 0."
+#define MSG_QRHSFUNC_FAILED "At " MSG_TIME ", the quadrature right-hand side routine failed in an unrecoverable manner."
+#define MSG_QRHSFUNC_UNREC "At " MSG_TIME ", the quadrature right-hand side failed in a recoverable manner, but no recovery is possible."
+#define MSG_QRHSFUNC_REPTD "At " MSG_TIME "repeated recoverable quadrature right-hand side function errors."
+#define MSG_QRHSFUNC_FIRST "The quadrature right-hand side routine failed at the first call."
+
+#define MSG_NULL_P "p = NULL when using internal DQ for sensitivity residual is illegal."
+#define MSG_EWTS_NOW_BAD "At " MSG_TIME ", a component of ewtS has become <= 0."
+#define MSG_SRHSFUNC_FAILED "At " MSG_TIME ", the sensitivity residual routine failed in an unrecoverable manner."
+#define MSG_SRHSFUNC_UNREC "At " MSG_TIME ", the sensitivity residual failed in a recoverable manner, but no recovery is possible."
+#define MSG_SRHSFUNC_REPTD "At " MSG_TIME "repeated recoverable sensitivity residual function errors."
+
+#define MSG_NO_TOLQS "No integration tolerances for quadrature sensitivity variables have been specified."
+#define MSG_NULL_RHSQ "IDAS is expected to use DQ to evaluate the RHS of quad. sensi., but quadratures were not initialized."
+#define MSG_BAD_EWTQS "Initial ewtQS has component(s) equal to zero (illegal)."
+#define MSG_EWTQS_NOW_BAD "At " MSG_TIME ", a component of ewtQS has become <= 0."
+#define MSG_QSRHSFUNC_FAILED "At " MSG_TIME ", the sensitivity quadrature right-hand side routine failed in an unrecoverable manner."
+#define MSG_QSRHSFUNC_FIRST "The quadrature right-hand side routine failed at the first call."
+
+/* IDASet* / IDAGet* error messages */
+#define MSG_NEG_MAXORD "maxord<=0 illegal."
+#define MSG_BAD_MAXORD "Illegal attempt to increase maximum order."
+#define MSG_NEG_HMAX "hmax < 0 illegal."
+#define MSG_NEG_EPCON "epcon <= 0.0 illegal."
+#define MSG_BAD_CONSTR "Illegal values in constraints vector."
+#define MSG_BAD_EPICCON "epiccon <= 0.0 illegal."
+#define MSG_BAD_MAXNH "maxnh <= 0 illegal."
+#define MSG_BAD_MAXNJ "maxnj <= 0 illegal."
+#define MSG_BAD_MAXNIT "maxnit <= 0 illegal."
+#define MSG_BAD_STEPTOL "steptol <= 0.0 illegal."
+
+#define MSG_TOO_LATE "IDAGetConsistentIC can only be called before IDASolve."
+
+/*
+ * =================================================================
+ * I D A A E R R O R M E S S A G E S
+ * =================================================================
+ */
+
+#define MSGAM_NULL_IDAMEM "ida_mem = NULL illegal."
+#define MSGAM_NO_ADJ "Illegal attempt to call before calling IDAadjInit."
+#define MSGAM_BAD_INTERP "Illegal value for interp."
+#define MSGAM_BAD_STEPS "Steps nonpositive illegal."
+#define MSGAM_BAD_WHICH "Illegal value for which."
+#define MSGAM_NO_BCK "No backward problems have been defined yet."
+#define MSGAM_NO_FWD "Illegal attempt to call before calling IDASolveF."
+#define MSGAM_BAD_TB0 "The initial time tB0 is outside the interval over which the forward problem was solved."
+#define MSGAM_BAD_SENSI "At least one backward problem requires sensitivities, but they were not stored for interpolation."
+#define MSGAM_BAD_ITASKB "Illegal value for itaskB. Legal values are IDA_NORMAL and IDA_ONE_STEP."
+#define MSGAM_BAD_TBOUT "The final time tBout is outside the interval over which the forward problem was solved."
+#define MSGAM_BACK_ERROR "Error occured while integrating backward problem # %d"
+#define MSGAM_BAD_TINTERP "Bad t = %g for interpolation."
+#define MSGAM_BAD_T "Bad t for interpolation."
+#define MSGAM_WRONG_INTERP "This function cannot be called for the specified interp type."
+#define MSGAM_MEM_FAIL "A memory request failed."
+#define MSGAM_NO_INITBS "Illegal attempt to call before calling IDAInitBS."
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/idas/idas_io.c b/src/idas/idas_io.c
new file mode 100644
index 0000000..557efeb
--- /dev/null
+++ b/src/idas/idas_io.c
@@ -0,0 +1,1895 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.26 $
+ * $Date: 2010/12/01 22:39:19 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Radu Serban and Cosmin Petra @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California
+ * Produced at the Lawrence Livermore National Laboratory
+ * All rights reserved
+ * For details, see the LICENSE file
+ * -----------------------------------------------------------------
+ * This is the implementation file for the optional inputs and
+ * outputs for the IDAS solver.
+ * -----------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "idas_impl.h"
+#include <sundials/sundials_math.h>
+#include <sundials/sundials_types.h>
+
+#define ZERO RCONST(0.0)
+#define HALF RCONST(0.5)
+#define ONE RCONST(1.0)
+#define TWOPT5 RCONST(2.5)
+
+/*
+ * =================================================================
+ * IDA optional input functions
+ * =================================================================
+ */
+
+/*
+ * 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;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDASetErrHandlerFn", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ IDA_mem->ida_ehfun = ehfun;
+ IDA_mem->ida_eh_data = eh_data;
+
+ return(IDA_SUCCESS);
+}
+
+
+int IDASetErrFile(void *ida_mem, FILE *errfp)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDASetErrFile", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ IDA_mem->ida_errfp = errfp;
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDASetUserData(void *ida_mem, void *user_data)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDASetUserData", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ IDA_mem->ida_user_data = user_data;
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDASetMaxOrd(void *ida_mem, int maxord)
+{
+ IDAMem IDA_mem;
+ int maxord_alloc;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDASetMaxOrd", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ if (maxord <= 0) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDASetMaxOrd", MSG_NEG_MAXORD);
+ return(IDA_ILL_INPUT);
+ }
+
+ /* Cannot increase maximum order beyond the value that
+ was used when allocating memory */
+ maxord_alloc = IDA_mem->ida_maxord_alloc;
+
+ if (maxord > maxord_alloc) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDASetMaxOrd", MSG_BAD_MAXORD);
+ return(IDA_ILL_INPUT);
+ }
+
+ IDA_mem->ida_maxord = MIN(maxord,MAXORD_DEFAULT);
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDASetMaxNumSteps(void *ida_mem, long int mxsteps)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDASetMaxNumSteps", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ /* Passing mxsteps=0 sets the default. Passing mxsteps<0 disables the test. */
+
+ if (mxsteps == 0)
+ IDA_mem->ida_mxstep = MXSTEP_DEFAULT;
+ else
+ IDA_mem->ida_mxstep = mxsteps;
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDASetInitStep(void *ida_mem, realtype hin)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDASetInitStep", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ IDA_mem->ida_hin = hin;
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDASetMaxStep(void *ida_mem, realtype hmax)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDASetMaxStep", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ if (hmax < 0) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDASetMaxStep", MSG_NEG_HMAX);
+ return(IDA_ILL_INPUT);
+ }
+
+ /* Passing 0 sets hmax = infinity */
+ if (hmax == ZERO) {
+ IDA_mem->ida_hmax_inv = HMAX_INV_DEFAULT;
+ return(IDA_SUCCESS);
+ }
+
+ IDA_mem->ida_hmax_inv = ONE/hmax;
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDASetStopTime(void *ida_mem, realtype tstop)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDASetStopTime", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ /* If IDASolve was called at least once, test if tstop is legal
+ * (i.e. if it was not already passed).
+ * If IDASetStopTime is called before the first call to IDASolve,
+ * tstop will be checked in IDASolve. */
+ if (IDA_mem->ida_nst > 0) {
+
+ if ( (tstop - IDA_mem->ida_tn) * IDA_mem->ida_hh < ZERO ) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASetStopTime", MSG_BAD_TSTOP, IDA_mem->ida_tn);
+ return(IDA_ILL_INPUT);
+ }
+
+ }
+
+ IDA_mem->ida_tstop = tstop;
+ IDA_mem->ida_tstopset = TRUE;
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDASetNonlinConvCoef(void *ida_mem, realtype epcon)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDASetNonlinConvCoef", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ if (epcon <= ZERO) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDASetNonlinConvCoef", MSG_NEG_EPCON);
+ return(IDA_ILL_INPUT);
+ }
+
+ IDA_mem->ida_epcon = epcon;
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDASetMaxErrTestFails(void *ida_mem, int maxnef)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDASetMaxErrTestFails", MSG_NO_MEM);
+ return (IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ IDA_mem->ida_maxnef = maxnef;
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDASetMaxConvFails(void *ida_mem, int maxncf)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDASetMaxConvFails", MSG_NO_MEM);
+ return (IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ IDA_mem->ida_maxncf = maxncf;
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDASetMaxNonlinIters(void *ida_mem, int maxcor)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDASetMaxNonlinIters", MSG_NO_MEM);
+ return (IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ IDA_mem->ida_maxcor = maxcor;
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDASetSuppressAlg(void *ida_mem, booleantype suppressalg)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDASetSuppressAlg", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ IDA_mem->ida_suppressalg = suppressalg;
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDASetId(void *ida_mem, N_Vector id)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDASetId", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ if (id == NULL) {
+ if (IDA_mem->ida_idMallocDone) {
+ N_VDestroy(IDA_mem->ida_id);
+ lrw -= lrw1;
+ liw -= liw1;
+ }
+ IDA_mem->ida_idMallocDone = FALSE;
+ return(IDA_SUCCESS);
+ }
+
+ if ( !(IDA_mem->ida_idMallocDone) ) {
+ IDA_mem->ida_id = N_VClone(id);
+ lrw += lrw1;
+ liw += liw1;
+ IDA_mem->ida_idMallocDone = TRUE;
+ }
+
+ /* Load the id vector */
+
+ N_VScale(ONE, id, IDA_mem->ida_id);
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDASetConstraints(void *ida_mem, N_Vector constraints)
+{
+ IDAMem IDA_mem;
+ realtype temptest;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDASetConstraints", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ if (constraints == NULL) {
+ if (IDA_mem->ida_constraintsMallocDone) {
+ N_VDestroy(IDA_mem->ida_constraints);
+ lrw -= lrw1;
+ liw -= liw1;
+ }
+ IDA_mem->ida_constraintsMallocDone = FALSE;
+ IDA_mem->ida_constraintsSet = FALSE;
+ return(IDA_SUCCESS);
+ }
+
+ /* Test if required vector ops. are defined */
+
+ if (constraints->ops->nvdiv == NULL ||
+ constraints->ops->nvmaxnorm == NULL ||
+ constraints->ops->nvcompare == NULL ||
+ constraints->ops->nvconstrmask == NULL ||
+ constraints->ops->nvminquotient == NULL) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDASetConstraints", MSG_BAD_NVECTOR);
+ return(IDA_ILL_INPUT);
+ }
+
+ /* Check the constraints vector */
+
+ temptest = N_VMaxNorm(constraints);
+ if((temptest > TWOPT5) || (temptest < HALF)){
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDASetConstraints", MSG_BAD_CONSTR);
+ return(IDA_ILL_INPUT);
+ }
+
+ if ( !(IDA_mem->ida_constraintsMallocDone) ) {
+ IDA_mem->ida_constraints = N_VClone(constraints);
+ lrw += lrw1;
+ liw += liw1;
+ IDA_mem->ida_constraintsMallocDone = TRUE;
+ }
+
+ /* Load the constraints vector */
+
+ N_VScale(ONE, constraints, IDA_mem->ida_constraints);
+
+ IDA_mem->ida_constraintsSet = TRUE;
+
+ return(IDA_SUCCESS);
+}
+
+/*
+ * IDASetRootDirection
+ *
+ * Specifies the direction of zero-crossings to be monitored.
+ * The default is to monitor both crossings.
+ */
+
+int IDASetRootDirection(void *ida_mem, int *rootdir)
+{
+ IDAMem IDA_mem;
+ int i, nrt;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDASetRootDirection", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ nrt = IDA_mem->ida_nrtfn;
+ if (nrt==0) {
+ IDAProcessError(NULL, IDA_ILL_INPUT, "IDAS", "IDASetRootDirection", MSG_NO_ROOT);
+ return(IDA_ILL_INPUT);
+ }
+
+ for(i=0; i<nrt; i++) IDA_mem->ida_rootdir[i] = rootdir[i];
+
+ return(IDA_SUCCESS);
+}
+
+/*
+ * IDASetNoInactiveRootWarn
+ *
+ * Disables issuing a warning if some root function appears
+ * to be identically zero at the beginning of the integration
+ */
+
+int IDASetNoInactiveRootWarn(void *ida_mem)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDASetNoInactiveRootWarn", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ IDA_mem->ida_mxgnull = 0;
+
+ return(IDA_SUCCESS);
+}
+
+
+/*
+ * =================================================================
+ * IDA IC optional input functions
+ * =================================================================
+ */
+
+int IDASetNonlinConvCoefIC(void *ida_mem, realtype epiccon)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDASetNonlinConvCoefIC", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ if (epiccon <= ZERO) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDASetNonlinConvCoefIC", MSG_BAD_EPICCON);
+ return(IDA_ILL_INPUT);
+ }
+
+ IDA_mem->ida_epiccon = epiccon;
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDASetMaxNumStepsIC(void *ida_mem, int maxnh)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDASetMaxNumStepsIC", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ if (maxnh <= 0) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDASetMaxNumStepsIC", MSG_BAD_MAXNH);
+ return(IDA_ILL_INPUT);
+ }
+
+ IDA_mem->ida_maxnh = maxnh;
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDASetMaxNumJacsIC(void *ida_mem, int maxnj)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDASetMaxNumJacsIC", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ if (maxnj <= 0) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDASetMaxNumJacsIC", MSG_BAD_MAXNJ);
+ return(IDA_ILL_INPUT);
+ }
+
+ IDA_mem->ida_maxnj = maxnj;
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDASetMaxNumItersIC(void *ida_mem, int maxnit)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDASetMaxNumItersIC", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ if (maxnit <= 0) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDASetMaxNumItersIC", MSG_BAD_MAXNIT);
+ return(IDA_ILL_INPUT);
+ }
+
+ IDA_mem->ida_maxnit = maxnit;
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDASetLineSearchOffIC(void *ida_mem, booleantype lsoff)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDASetLineSearchOffIC", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ IDA_mem->ida_lsoff = lsoff;
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDASetStepToleranceIC(void *ida_mem, realtype steptol)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDASetStepToleranceIC", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ if (steptol <= ZERO) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDASetStepToleranceIC", MSG_BAD_STEPTOL);
+ return(IDA_ILL_INPUT);
+ }
+
+ IDA_mem->ida_steptol = steptol;
+
+ return(IDA_SUCCESS);
+}
+
+/*
+ * =================================================================
+ * Quadrature optional input functions
+ * =================================================================
+ */
+
+/*
+ * Readability constants
+ */
+
+#define lrw1Q (IDA_mem->ida_lrw1Q)
+#define liw1Q (IDA_mem->ida_liw1Q)
+
+/*-----------------------------------------------------------------*/
+
+int IDASetQuadErrCon(void *ida_mem, booleantype errconQ)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDASetQuadErrCon", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+ IDA_mem = (IDAMem) ida_mem;
+
+ if (IDA_mem->ida_quadMallocDone == FALSE) {
+ IDAProcessError(NULL, IDA_NO_QUAD, "IDAS", "IDASetQuadErrCon", MSG_NO_QUAD);
+ return(IDA_NO_QUAD);
+ }
+
+ IDA_mem->ida_errconQ = errconQ;
+
+ return (IDA_SUCCESS);
+}
+
+/*
+ * =================================================================
+ * FSA optional input functions
+ * =================================================================
+ */
+
+int IDASetSensDQMethod(void *ida_mem, int DQtype, realtype DQrhomax)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDASetSensDQMethod", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ if ( (DQtype != IDA_CENTERED) && (DQtype != IDA_FORWARD) ) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDASetSensDQMethod", MSG_BAD_DQTYPE);
+ return(IDA_ILL_INPUT);
+ }
+
+ if (DQrhomax < ZERO ) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDASetSensDQMethod", MSG_BAD_DQRHO);
+ return(IDA_ILL_INPUT);
+ }
+
+ IDA_mem->ida_DQtype = DQtype;
+ IDA_mem->ida_DQrhomax = DQrhomax;
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDASetSensErrCon(void *ida_mem, booleantype errconS)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDASetSensErrCon", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+ IDA_mem->ida_errconS = errconS;
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDASetSensMaxNonlinIters(void *ida_mem, int maxcorS)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDASetSensMaxNonlinIters", MSG_NO_MEM);
+ return (IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ IDA_mem->ida_maxcorS = maxcorS;
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDASetSensParams(void *ida_mem, realtype *p, realtype *pbar, int *plist)
+{
+ IDAMem IDA_mem;
+ int Ns, is;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDASetSensParams", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ /* Was sensitivity initialized? */
+
+ if (IDA_mem->ida_sensMallocDone == FALSE) {
+ IDAProcessError(IDA_mem, IDA_NO_SENS, "IDAS", "IDASetSensParams", MSG_NO_SENSI);
+ return(IDA_NO_SENS);
+ }
+
+ Ns = IDA_mem->ida_Ns;
+
+ /* Parameters */
+
+ IDA_mem->ida_p = p;
+
+ /* pbar */
+
+ if (pbar != NULL)
+ for (is=0; is<Ns; is++) {
+ if (pbar[is] == ZERO) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDASetSensParams", MSG_BAD_PBAR);
+ return(IDA_ILL_INPUT);
+ }
+ IDA_mem->ida_pbar[is] = ABS(pbar[is]);
+ }
+ else
+ for (is=0; is<Ns; is++)
+ IDA_mem->ida_pbar[is] = ONE;
+
+ /* plist */
+
+ if (plist != NULL)
+ for (is=0; is<Ns; is++) {
+ if ( plist[is] < 0 ) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDASetSensParams", MSG_BAD_PLIST);
+ return(IDA_ILL_INPUT);
+ }
+ IDA_mem->ida_plist[is] = plist[is];
+ }
+ else
+ for (is=0; is<Ns; is++)
+ IDA_mem->ida_plist[is] = is;
+
+ return(IDA_SUCCESS);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Function: IDASetQuadSensErrCon
+ * -----------------------------------------------------------------
+ * IDASetQuadSensErrCon specifies if quadrature sensitivity variables
+ * are considered or not in the error control.
+ * -----------------------------------------------------------------
+ */
+int IDASetQuadSensErrCon(void *ida_mem, booleantype errconQS)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDASetQuadSensErrCon", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+ IDA_mem = (IDAMem) ida_mem;
+
+ /* Was sensitivity initialized? */
+ if (IDA_mem->ida_sensMallocDone == FALSE) {
+ 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) {
+ IDAProcessError(IDA_mem, IDA_NO_QUADSENS, "IDAS", "IDASetQuadSensErrCon", MSG_NO_SENSI);
+ return(IDA_NO_QUADSENS);
+ }
+
+ IDA_mem->ida_errconQS = errconQS;
+
+ return(IDA_SUCCESS);
+}
+
+/*
+ * =================================================================
+ * IDA optional output functions
+ * =================================================================
+ */
+
+/*
+ * 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;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDAGetNumSteps", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ *nsteps = nst;
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDAGetNumResEvals(void *ida_mem, long int *nrevals)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDAGetNumResEvals", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ *nrevals = nre;
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDAGetNumLinSolvSetups(void *ida_mem, long int *nlinsetups)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDAGetNumLinSolvSetups", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ *nlinsetups = nsetups;
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDAGetNumErrTestFails(void *ida_mem, long int *netfails)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDAGetNumErrTestFails", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ *netfails = netf;
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDAGetNumBacktrackOps(void *ida_mem, long int *nbacktracks)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDAGetNumBacktrackOps", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ *nbacktracks = nbacktr;
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDAGetConsistentIC(void *ida_mem, N_Vector yy0, N_Vector yp0)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem == NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDAGetConsistentIC", MSG_NO_MEM);
+ return (IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ if (IDA_mem->ida_kused != 0) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDAGetConsistentIC", MSG_TOO_LATE);
+ return(IDA_ILL_INPUT);
+ }
+
+ if(yy0 != NULL) N_VScale(ONE, IDA_mem->ida_phi[0], yy0);
+ if(yp0 != NULL) N_VScale(ONE, IDA_mem->ida_phi[1], yp0);
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDAGetLastOrder(void *ida_mem, int *klast)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDAGetLastOrder", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ *klast = kused;
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDAGetCurrentOrder(void *ida_mem, int *kcur)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDAGetCurrentOrder", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ *kcur = kk;
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDAGetActualInitStep(void *ida_mem, realtype *hinused)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDAGetActualInitStep", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ *hinused = h0u;
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDAGetLastStep(void *ida_mem, realtype *hlast)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDAGetLastStep", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ *hlast = hused;
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDAGetCurrentStep(void *ida_mem, realtype *hcur)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDAGetCurrentStep", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ *hcur = hh;
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDAGetCurrentTime(void *ida_mem, realtype *tcur)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDAGetCurrentTime", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ *tcur = tn;
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDAGetTolScaleFactor(void *ida_mem, realtype *tolsfact)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDAGetTolScaleFactor", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ *tolsfact = tolsf;
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDAGetErrWeights(void *ida_mem, N_Vector eweight)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem == NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDAGetErrWeights", MSG_NO_MEM);
+ return (IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ N_VScale(ONE, ewt, eweight);
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDAGetEstLocalErrors(void *ida_mem, N_Vector ele)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem == NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDAGetEstLocalErrors", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+ IDA_mem = (IDAMem) ida_mem;
+
+ N_VScale(ONE, ee, ele);
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDAGetWorkSpace(void *ida_mem, long int *lenrw, long int *leniw)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDAGetWorkSpace", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ *leniw = liw;
+ *lenrw = lrw;
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDAGetIntegratorStats(void *ida_mem, long int *nsteps, long int *nrevals,
+ long int *nlinsetups, long int *netfails,
+ int *klast, int *kcur, realtype *hinused, realtype *hlast,
+ realtype *hcur, realtype *tcur)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDAGetIntegratorStats", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ 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;
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDAGetNumGEvals(void *ida_mem, long int *ngevals)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDAGetNumGEvals", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ *ngevals = nge;
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDAGetRootInfo(void *ida_mem, int *rootsfound)
+{
+ IDAMem IDA_mem;
+ int i, nrt;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDAGetRootInfo", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ nrt = IDA_mem->ida_nrtfn;
+
+ for (i=0; i<nrt; i++) rootsfound[i] = iroots[i];
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDAGetNumNonlinSolvIters(void *ida_mem, long int *nniters)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDAGetNumNonlinSolvIters", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ *nniters = nni;
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDAGetNumNonlinSolvConvFails(void *ida_mem, long int *nncfails)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDAGetNumNonlinSolvConvFails", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ *nncfails = ncfn;
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDAGetNonlinSolvStats(void *ida_mem, long int *nniters, long int *nncfails)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDAGetNonlinSolvStats", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ *nniters = nni;
+ *nncfails = ncfn;
+
+ return(IDA_SUCCESS);
+}
+
+/*
+ * =================================================================
+ * Quadrature optional output functions
+ * =================================================================
+ */
+
+/*
+ * 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)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDAGetQuadNumRhsEvals", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ if (quadr==FALSE) {
+ IDAProcessError(IDA_mem, IDA_NO_QUAD, "IDAS", "IDAGetQuadNumRhsEvals", MSG_NO_QUAD);
+ return(IDA_NO_QUAD);
+ }
+
+ *nrQevals = nrQe;
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDAGetQuadNumErrTestFails(void *ida_mem, long int *nQetfails)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDAGetQuadNumErrTestFails", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ if (quadr==FALSE) {
+ IDAProcessError(IDA_mem, IDA_NO_QUAD, "IDAS", "IDAGetQuadNumErrTestFails", MSG_NO_QUAD);
+ return(IDA_NO_QUAD);
+ }
+
+ *nQetfails = netfQ;
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDAGetQuadErrWeights(void *ida_mem, N_Vector eQweight)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDAGetQuadErrWeights", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ if (quadr==FALSE) {
+ IDAProcessError(IDA_mem, IDA_NO_QUAD, "IDAS", "IDAGetQuadErrWeights", MSG_NO_QUAD);
+ return(IDA_NO_QUAD);
+ }
+
+ if(errconQ) N_VScale(ONE, ewtQ, eQweight);
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDAGetQuadStats(void *ida_mem, long int *nrQevals, long int *nQetfails)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDAGetQuadStats", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ if (quadr==FALSE) {
+ IDAProcessError(IDA_mem, IDA_NO_QUAD, "IDAS", "IDAGetQuadStats", MSG_NO_QUAD);
+ return(IDA_NO_QUAD);
+ }
+
+ *nrQevals = nrQe;
+ *nQetfails = netfQ;
+
+ return(IDA_SUCCESS);
+}
+
+
+/*
+ * =================================================================
+ * Quadrature FSA optional output functions
+ * =================================================================
+ */
+
+/*
+ * 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)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDAGetQuadSensNumRhsEvals", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ if (quadr_sensi == FALSE) {
+ IDAProcessError(IDA_mem, IDA_NO_QUADSENS, "IDAS", "IDAGetQuadSensNumRhsEvals", MSG_NO_QUADSENSI);
+ return(IDA_NO_QUADSENS);
+ }
+
+ *nrhsQSevals = nrQSe;
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDAGetQuadSensNumErrTestFails(void *ida_mem, long int *nQSetfails)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDAGetQuadSensNumErrTestFails", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ if (quadr_sensi == FALSE) {
+ IDAProcessError(IDA_mem, IDA_NO_QUADSENS, "IDAS", "IDAGetQuadSensNumErrTestFails", MSG_NO_QUADSENSI);
+ return(IDA_NO_QUADSENS);
+ }
+
+ *nQSetfails = netfQS;
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDAGetQuadSensErrWeights(void *ida_mem, N_Vector *eQSweight)
+{
+ IDAMem IDA_mem;
+ int is, Ns;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDAGetQuadSensErrWeights", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ if (quadr_sensi == FALSE) {
+ IDAProcessError(IDA_mem, IDA_NO_QUADSENS, "IDAS", "IDAGetQuadSensErrWeights", MSG_NO_QUADSENSI);
+ return(IDA_NO_QUADSENS);
+ }
+ Ns = IDA_mem->ida_Ns;
+
+ if (errconQS)
+ for (is=0; is<Ns; is++)
+ N_VScale(ONE, ewtQS[is], eQSweight[is]);
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDAGetQuadSensStats(void *ida_mem, long int *nrhsQSevals, long int *nQSetfails)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDAGetQuadSensStats", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ if (quadr_sensi == FALSE) {
+ IDAProcessError(IDA_mem, IDA_NO_QUADSENS, "IDAS", "IDAGetQuadSensStats", MSG_NO_QUADSENSI);
+ return(IDA_NO_QUADSENS);
+ }
+
+ *nrhsQSevals = nrQSe;
+ *nQSetfails = netfQS;
+
+ return(IDA_SUCCESS);
+}
+
+
+
+/*
+ * =================================================================
+ * FSA optional output functions
+ * =================================================================
+ */
+
+/*
+ * 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)
+{
+ IDAMem IDA_mem;
+ int is;
+
+ if (ida_mem == NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDAGetSensConsistentIC", MSG_NO_MEM);
+ return (IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ if (sensi==FALSE) {
+ IDAProcessError(IDA_mem, IDA_NO_SENS, "IDAS", "IDAGetSensConsistentIC", MSG_NO_SENSI);
+ return(IDA_NO_SENS);
+ }
+
+ if (IDA_mem->ida_kused != 0) {
+ IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDAGetSensConsistentIC", MSG_TOO_LATE);
+ return(IDA_ILL_INPUT);
+ }
+
+ if(yyS0 != NULL) {
+ for (is=0; is<Ns; is++)
+ N_VScale(ONE, IDA_mem->ida_phiS[0][is], yyS0[is]);
+ }
+
+ if(ypS0 != NULL) {
+ for (is=0; is<Ns; is++)
+ N_VScale(ONE, IDA_mem->ida_phiS[1][is], ypS0[is]);
+ }
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDAGetSensNumResEvals(void *ida_mem, long int *nrSevals)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDAGeSensNumResEvals", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ if (sensi==FALSE) {
+ IDAProcessError(IDA_mem, IDA_NO_SENS, "IDAS", "IDAGetSensNumResEvals", MSG_NO_SENSI);
+ return(IDA_NO_SENS);
+ }
+
+ *nrSevals = nrSe;
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDAGetNumResEvalsSens(void *ida_mem, long int *nrevalsS)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDAGetNumResEvalsSens", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ if (sensi==FALSE) {
+ IDAProcessError(IDA_mem, IDA_NO_SENS, "IDAS", "IDAGetNumResEvalsSens", MSG_NO_SENSI);
+ return(IDA_NO_SENS);
+ }
+
+ *nrevalsS = nreS;
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDAGetSensNumErrTestFails(void *ida_mem, long int *nSetfails)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDAGetSensNumErrTestFails", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ if (sensi==FALSE) {
+ IDAProcessError(IDA_mem, IDA_NO_SENS, "IDAS", "IDAGetSensNumErrTestFails", MSG_NO_SENSI);
+ return(IDA_NO_SENS);
+ }
+
+ *nSetfails = netfS;
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDAGetSensNumLinSolvSetups(void *ida_mem, long int *nlinsetupsS)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDAGetSensNumLinSolvSetups", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ if (sensi==FALSE) {
+ IDAProcessError(IDA_mem, IDA_NO_SENS, "IDAS", "IDAGetSensNumLinSolvSetups", MSG_NO_SENSI);
+ return(IDA_NO_SENS);
+ }
+
+ *nlinsetupsS = nsetupsS;
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDAGetSensErrWeights(void *ida_mem, N_Vector_S eSweight)
+{
+ IDAMem IDA_mem;
+ int is;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDAGetSensErrWeights", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ if (sensi==FALSE) {
+ 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]);
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDAGetSensStats(void *ida_mem, long int *nrSevals, long int *nrevalsS,
+ long int *nSetfails, long int *nlinsetupsS)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDAGetSensStats", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ if (sensi==FALSE) {
+ IDAProcessError(IDA_mem, IDA_NO_SENS, "IDAS", "IDAGetSensStats", MSG_NO_SENSI);
+ return(IDA_NO_SENS);
+ }
+
+ *nrSevals = nrSe;
+ *nrevalsS = nreS;
+ *nSetfails = netfS;
+ *nlinsetupsS = nsetupsS;
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDAGetSensNumNonlinSolvIters(void *ida_mem, long int *nSniters)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDAGetSensNumNonlinSolvIters", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ if (sensi==FALSE) {
+ IDAProcessError(IDA_mem, IDA_NO_SENS, "IDAS", "IDAGetSensNumNonlinSolvIters", MSG_NO_SENSI);
+ return(IDA_NO_SENS);
+ }
+
+ *nSniters = nniS;
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDAGetSensNumNonlinSolvConvFails(void *ida_mem, long int *nSncfails)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDAGetSensNumNonlinSolvConvFails", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ if (sensi==FALSE) {
+ IDAProcessError(IDA_mem, IDA_NO_SENS, "IDAS", "IDAGetSensNumNonlinSolvConvFails", MSG_NO_SENSI);
+ return(IDA_NO_SENS);
+ }
+
+ *nSncfails = ncfnS;
+
+ return(IDA_SUCCESS);
+}
+
+/*-----------------------------------------------------------------*/
+
+int IDAGetSensNonlinSolvStats(void *ida_mem, long int *nSniters, long int *nSncfails)
+{
+ IDAMem IDA_mem;
+
+ if (ida_mem==NULL) {
+ IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDAGetSensNonlinSolvstats", MSG_NO_MEM);
+ return(IDA_MEM_NULL);
+ }
+
+ IDA_mem = (IDAMem) ida_mem;
+
+ if (sensi==FALSE) {
+ IDAProcessError(IDA_mem, IDA_NO_SENS, "IDAS", "IDAGetSensNonlinSolvStats", MSG_NO_SENSI);
+ return(IDA_NO_SENS);
+ }
+
+ *nSniters = nniS;
+ *nSncfails = ncfnS;
+
+ return(IDA_SUCCESS);
+}
+
+/*
+ * =================================================================
+ * IDAGetReturnFlagName
+ * =================================================================
+ */
+
+
+char *IDAGetReturnFlagName(long int flag)
+{
+ char *name;
+
+ name = (char *)malloc(24*sizeof(char));
+
+ switch(flag) {
+ case IDA_SUCCESS:
+ sprintf(name,"IDA_SUCCESS");
+ break;
+ case IDA_TSTOP_RETURN:
+ sprintf(name,"IDA_TSTOP_RETURN");
+ break;
+ case IDA_ROOT_RETURN:
+ sprintf(name,"IDA_ROOT_RETURN");
+ break;
+ case IDA_TOO_MUCH_WORK:
+ sprintf(name,"IDA_TOO_MUCH_WORK");
+ break;
+ case IDA_TOO_MUCH_ACC:
+ sprintf(name,"IDA_TOO_MUCH_ACC");
+ break;
+ case IDA_ERR_FAIL:
+ sprintf(name,"IDA_ERR_FAIL");
+ break;
+ case IDA_CONV_FAIL:
+ sprintf(name,"IDA_CONV_FAIL");
+ break;
+ case IDA_LINIT_FAIL:
+ sprintf(name,"IDA_LINIT_FAIL");
+ break;
+ case IDA_LSETUP_FAIL:
+ sprintf(name,"IDA_LSETUP_FAIL");
+ break;
+ case IDA_LSOLVE_FAIL:
+ sprintf(name,"IDA_LSOLVE_FAIL");
+ break;
+ case IDA_CONSTR_FAIL:
+ sprintf(name,"IDA_CONSTR_FAIL");
+ break;
+ case IDA_RES_FAIL:
+ sprintf(name,"IDA_RES_FAIL");
+ break;
+ case IDA_FIRST_RES_FAIL:
+ sprintf(name,"IDA_FIRST_RES_FAIL");
+ break;
+ case IDA_REP_RES_ERR:
+ sprintf(name,"IDA_REP_RES_ERR");
+ break;
+ case IDA_RTFUNC_FAIL:
+ sprintf(name,"IDA_RTFUNC_FAIL");
+ break;
+ case IDA_MEM_FAIL:
+ sprintf(name,"IDA_MEM_FAIL");
+ break;
+ case IDA_MEM_NULL:
+ sprintf(name,"IDA_MEM_NULL");
+ break;
+ case IDA_ILL_INPUT:
+ sprintf(name,"IDA_ILL_INPUT");
+ break;
+ case IDA_NO_MALLOC:
+ sprintf(name,"IDA_NO_MALLOC");
+ break;
+ case IDA_BAD_T:
+ sprintf(name,"IDA_BAD_T");
+ break;
+ case IDA_BAD_K:
+ sprintf(name,"IDA_BAD_K");
+ break;
+ case IDA_BAD_DKY:
+ sprintf(name,"IDA_BAD_DKY");
+ break;
+ case IDA_BAD_EWT:
+ sprintf(name,"IDA_BAD_EWT");
+ break;
+ case IDA_NO_RECOVERY:
+ sprintf(name,"IDA_NO_RECOVERY");
+ break;
+ case IDA_LINESEARCH_FAIL:
+ sprintf(name,"IDA_LINESEARCH_FAIL");
+ break;
+ case IDA_NO_SENS:
+ sprintf(name,"IDA_NO_SENS");
+ break;
+ case IDA_SRES_FAIL:
+ sprintf(name, "IDA_SRES_FAIL");
+ break;
+ case IDA_REP_SRES_ERR:
+ sprintf(name, "IDA_REP_SRES_ERR");
+ break;
+ case IDA_BAD_IS:
+ sprintf(name,"IDA_BAD_IS");
+ break;
+ case IDA_NO_QUAD:
+ sprintf(name,"IDA_NO_QUAD");
+ break;
+ case IDA_NO_QUADSENS:
+ sprintf(name, "IDA_NO_QUADSENS");
+ break;
+ case IDA_QSRHS_FAIL:
+ sprintf(name, "IDA_QSRHS_FAIL");
+
+ /* IDAA flags follow below. */
+ case IDA_NO_ADJ:
+ sprintf(name, "IDA_NO_ADJ");
+ break;
+ case IDA_BAD_TB0:
+ sprintf(name, "IDA_BAD_TB0");
+ break;
+ case IDA_REIFWD_FAIL:
+ sprintf(name, "IDA_REIFWD_FAIL");
+ break;
+ case IDA_FWD_FAIL:
+ sprintf(name, "IDA_FWD_FAIL");
+ break;
+ case IDA_GETY_BADT:
+ sprintf(name, "IDA_GETY_BADT");
+ break;
+ case IDA_NO_BCK:
+ sprintf(name, "IDA_NO_BCK");
+ break;
+ case IDA_NO_FWD:
+ sprintf(name,"IDA_NO_FWD");
+ break;
+ default:
+ sprintf(name,"NONE");
+ }
+
+ return(name);
+}
+
diff --git a/src/idas/idas_lapack.c b/src/idas/idas_lapack.c
new file mode 100644
index 0000000..20d7640
--- /dev/null
+++ b/src/idas/idas_lapack.c
@@ -0,0 +1,562 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.12 $
+ * $Date: 2011/03/23 23:25:35 $
+ * -----------------------------------------------------------------
+ * Programmer: Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2006, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * 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);
+
+/*
+ * =================================================================
+ * 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;
+ 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;
+ 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 = MIN(n-1, 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;
+
+ 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, "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;
+
+ 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, "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);
+}
+
diff --git a/src/idas/idas_spbcgs.c b/src/idas/idas_spbcgs.c
new file mode 100644
index 0000000..a69f843
--- /dev/null
+++ b/src/idas/idas_spbcgs.c
@@ -0,0 +1,590 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.8 $
+ * $Date: 2011/05/25 20:46:33 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Aaron Collier and Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2004, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * 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 void 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 flag, 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) flag = 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;
+
+ /* 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 = RSqrt(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 */
+ npe = nli = nps = ncfl = 0;
+ njtimes = nres = 0;
+
+ /* 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;
+ void *ida_memB;
+ 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;
+ }
+ /* ida_mem corresponding to 'which' problem. */
+ ida_memB = (void *) IDAB_mem->IDA_mem;
+
+
+ /* 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 void IDASpbcgFreeB(IDABMem IDAB_mem)
+{
+ IDASpilsMemB idaspilsB_mem;
+
+ idaspilsB_mem = (IDASpilsMemB) IDAB_mem->ida_lmem;
+
+ free(idaspilsB_mem);
+}
diff --git a/src/idas/idas_spgmr.c b/src/idas/idas_spgmr.c
new file mode 100644
index 0000000..7242be4
--- /dev/null
+++ b/src/idas/idas_spgmr.c
@@ -0,0 +1,582 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.8 $
+ * $Date: 2011/05/25 20:46:33 $
+ * -----------------------------------------------------------------
+ * Programmers: Alan C. Hindmarsh, and Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California
+ * Produced at the Lawrence Livermore National Laboratory
+ * All rights reserved
+ * For details, see the LICENSE file
+ * -----------------------------------------------------------------
+ * 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 void 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 flag, 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) flag = 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;
+
+ /* 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 = RSqrt( 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 */
+ npe = nli = nps = ncfl = 0;
+ njtimes = nres = 0;
+
+ /* 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;
+ void *ida_memB;
+ 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;
+ }
+ /* ida_mem corresponding to 'which' problem. */
+ ida_memB = (void *) IDAB_mem->IDA_mem;
+
+
+ /* 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 void IDASpgmrFreeB(IDABMem IDAB_mem)
+{
+ IDASpilsMemB idaspilsB_mem;
+
+ idaspilsB_mem = (IDASpilsMemB) IDAB_mem->ida_lmem;
+
+ free(idaspilsB_mem);
+}
diff --git a/src/idas/idas_spils.c b/src/idas/idas_spils.c
new file mode 100644
index 0000000..74f7d3f
--- /dev/null
+++ b/src/idas/idas_spils.c
@@ -0,0 +1,1129 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.8 $
+ * $Date: 2010/12/01 22:39:19 $
+ * -----------------------------------------------------------------
+ * Programmers: Alan C. Hindmarsh and Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California
+ * Produced at the Lawrence Livermore National Laboratory
+ * All rights reserved
+ * For details, see the LICENSE file
+ * -----------------------------------------------------------------
+ * This is the common implementation file for the IDAS Scaled
+ * Preconditioned Linear Solver modules.
+ * -----------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "idas_spils_impl.h"
+#include "idas_impl.h"
+
+/* Private constants */
+
+#define ZERO RCONST(0.0)
+#define PT25 RCONST(0.25)
+#define PT05 RCONST(0.05)
+#define ONE RCONST(1.0)
+
+/* Algorithmic constants */
+
+#define MAX_ITERS 3 /* max. number of attempts to recover in DQ J*v */
+
+/*
+ * =================================================================
+ * PRIVATE FUNCTION PROTOTYPES
+ * =================================================================
+ */
+
+static int IDAAspilsPrecSetup(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 IDAAspilsPrecSolve(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);
+
+static int IDAAspilsJacTimesVec(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
+ * -----------------------------------------------------------------
+ */
+
+int IDASpilsSetGSType(void *ida_mem, int gstype)
+{
+ IDAMem IDA_mem;
+ IDASpilsMem idaspils_mem;
+
+ /* Return immediately if ida_mem is NULL */
+ if (ida_mem == NULL) {
+ IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASSPILS", "IDASpilsSetGSType", MSGS_IDAMEM_NULL);
+ return(IDASPILS_MEM_NULL);
+ }
+ IDA_mem = (IDAMem) ida_mem;
+
+ if (lmem == NULL) {
+ IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASSPILS", "IDASpilsSetGSType", MSGS_LMEM_NULL);
+ return(IDASPILS_LMEM_NULL);
+ }
+ idaspils_mem = (IDASpilsMem) lmem;
+
+ if (ils_type != SPILS_SPGMR) {
+ IDAProcessError(IDA_mem, IDASPILS_ILL_INPUT, "IDASSPILS", "IDASpilsSetGSType", MSGS_BAD_LSTYPE);
+ 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);
+ }
+
+ 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, "IDASSPILS", "IDASpilsSetMaxRestarts", 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);
+ return(IDASPILS_LMEM_NULL);
+ }
+ idaspils_mem = (IDASpilsMem) 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);
+ return(IDASPILS_ILL_INPUT);
+ }
+
+ 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, "IDASSPILS", "IDASpilsSetMaxl", 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);
+ return(IDASPILS_LMEM_NULL);
+ }
+ idaspils_mem = (IDASpilsMem) lmem;
+
+ if (ils_type == SPILS_SPGMR) {
+ IDAProcessError(IDA_mem, IDASPILS_ILL_INPUT, "IDASSPILS", "IDASpilsSetMaxl", MSGS_BAD_LSTYPE);
+ return(IDASPILS_ILL_INPUT);
+ }
+
+ idaspils_mem->s_maxl = (maxl <= 0) ? IDA_SPILS_MAXL : maxl;
+
+ return(IDASPILS_SUCCESS);
+}
+
+int IDASpilsSetEpsLin(void *ida_mem, realtype eplifac)
+{
+ IDAMem IDA_mem;
+ IDASpilsMem idaspils_mem;
+
+ /* Return immediately if ida_mem is NULL */
+ if (ida_mem == 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", "IDASpilsSetEpsLin", MSGS_LMEM_NULL);
+ return(IDASPILS_LMEM_NULL);
+ }
+ idaspils_mem = (IDASpilsMem) lmem;
+
+ /* Check for legal maxrs */
+ if (eplifac < ZERO) {
+ IDAProcessError(IDA_mem, IDASPILS_ILL_INPUT, "IDASSPILS", "IDASpilsSetEpsLin", MSGS_NEG_EPLIFAC);
+ return(IDASPILS_ILL_INPUT);
+ }
+
+ if (eplifac == ZERO)
+ idaspils_mem->s_eplifac = PT05;
+ else
+ idaspils_mem->s_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 */
+ if (ida_mem == 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", "IDASpilsSetIncrementFactor", MSGS_LMEM_NULL);
+ return(IDASPILS_LMEM_NULL);
+ }
+ idaspils_mem = (IDASpilsMem) lmem;
+
+ /* 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_dqincfac = dqincfac;
+
+ return(IDASPILS_SUCCESS);
+}
+
+int IDASpilsSetPreconditioner(void *ida_mem,
+ IDASpilsPrecSetupFn pset, IDASpilsPrecSolveFn psolve)
+{
+ IDAMem IDA_mem;
+ IDASpilsMem idaspils_mem;
+
+ /* Return immediately if ida_mem is NULL */
+ if (ida_mem == 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", "IDASpilsSetPreconditioner", MSGS_LMEM_NULL);
+ return(IDASPILS_LMEM_NULL);
+ }
+ idaspils_mem = (IDASpilsMem) lmem;
+
+ idaspils_mem->s_pset = pset;
+ idaspils_mem->s_psolve = psolve;
+
+ 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);
+ }
+ 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;
+ }
+
+ return(IDASPILS_SUCCESS);
+}
+
+int IDASpilsGetWorkSpace(void *ida_mem, long int *lenrwLS, long int *leniwLS)
+{
+ IDAMem IDA_mem;
+ IDASpilsMem idaspils_mem;
+ int maxl;
+
+ /* Return immediately if ida_mem is NULL */
+ if (ida_mem == 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", "IDASpilsGetWorkSpace", MSGS_LMEM_NULL);
+ return(IDASPILS_LMEM_NULL);
+ }
+ idaspils_mem = (IDASpilsMem) 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;
+ }
+
+ return(IDASPILS_SUCCESS);
+}
+
+int IDASpilsGetNumPrecEvals(void *ida_mem, long int *npevals)
+{
+ IDAMem IDA_mem;
+ IDASpilsMem idaspils_mem;
+
+ /* Return immediately if ida_mem is NULL */
+ if (ida_mem == 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", "IDASpilsGetNumPrecEvals", MSGS_LMEM_NULL);
+ return(IDASPILS_LMEM_NULL);
+ }
+ idaspils_mem = (IDASpilsMem) lmem;
+
+ *npevals = 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 */
+ if (ida_mem == 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", "IDASpilsGetNumPrecSolves", MSGS_LMEM_NULL);
+ return(IDASPILS_LMEM_NULL);
+ }
+ idaspils_mem = (IDASpilsMem) lmem;
+
+ *npsolves = 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 */
+ if (ida_mem == 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", "IDASpilsGetNumLinIters", MSGS_LMEM_NULL);
+ return(IDASPILS_LMEM_NULL);
+ }
+ idaspils_mem = (IDASpilsMem) lmem;
+
+ *nliters = 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 */
+ if (ida_mem == 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", "IDASpilsGetNumConvFails", MSGS_LMEM_NULL);
+ return(IDASPILS_LMEM_NULL);
+ }
+ idaspils_mem = (IDASpilsMem) lmem;
+
+ *nlcfails = ncfl;
+
+ return(IDASPILS_SUCCESS);
+}
+
+int IDASpilsGetNumJtimesEvals(void *ida_mem, long int *njvevals)
+{
+ IDAMem IDA_mem;
+ IDASpilsMem idaspils_mem;
+
+ /* Return immediately if ida_mem is NULL */
+ if (ida_mem == 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);
+ return(IDASPILS_LMEM_NULL);
+ }
+ idaspils_mem = (IDASpilsMem) lmem;
+
+ *njvevals = 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 */
+ if (ida_mem == 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);
+ return(IDASPILS_LMEM_NULL);
+ }
+ idaspils_mem = (IDASpilsMem) lmem;
+
+ *nrevalsLS = 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 */
+ if (ida_mem == 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);
+ return(IDASPILS_LMEM_NULL);
+ }
+ idaspils_mem = (IDASpilsMem) lmem;
+
+ *flag = last_flag;
+
+ return(IDASPILS_SUCCESS);
+}
+
+char *IDASpilsGetReturnFlagName(long int flag)
+{
+ char *name;
+
+ name = (char *)malloc(30*sizeof(char));
+
+ switch(flag) {
+ case IDASPILS_SUCCESS:
+ sprintf(name,"IDASPILS_SUCCESS");
+ break;
+ case IDASPILS_MEM_NULL:
+ sprintf(name,"IDASPILS_MEM_NULL");
+ break;
+ case IDASPILS_LMEM_NULL:
+ sprintf(name,"IDASPILS_LMEM_NULL");
+ break;
+ case IDASPILS_ILL_INPUT:
+ sprintf(name,"IDASPILS_ILL_INPUT");
+ break;
+ case IDASPILS_MEM_FAIL:
+ sprintf(name,"IDASPILS_MEM_FAIL");
+ break;
+ case IDASPILS_PMEM_NULL:
+ sprintf(name,"IDASPILS_PMEM_NULL");
+ break;
+ default:
+ sprintf(name,"NONE");
+ }
+
+ return(name);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * IDASPILS private functions
+ * -----------------------------------------------------------------
+ */
+
+#define psolve (idaspils_mem->s_psolve)
+#define pdata (idaspils_mem->s_pdata)
+#define dqincfac (idaspils_mem->s_dqincfac)
+
+/*
+ * 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.
+ */
+
+int IDASpilsAtimes(void *ida_mem, N_Vector v, N_Vector z)
+{
+ IDAMem IDA_mem;
+ IDASpilsMem idaspils_mem;
+ int jtflag;
+
+ IDA_mem = (IDAMem) ida_mem;
+ idaspils_mem = (IDASpilsMem) lmem;
+
+ jtflag = jtimes(tn, ycur, ypcur, rcur, v, z, cj, jdata, ytemp, yptemp);
+ 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)
+{
+ IDAMem IDA_mem;
+ IDASpilsMem idaspils_mem;
+ int retval;
+
+ 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 */
+
+ 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)
+{
+ IDAMem IDA_mem;
+ IDASpilsMem idaspils_mem;
+ N_Vector y_tmp, yp_tmp;
+ realtype sig, 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;
+ }
+
+ /* Rename work1 and work2 for readibility */
+ y_tmp = work1;
+ yp_tmp = work2;
+
+ for (iter=0; iter<MAX_ITERS; iter++) {
+
+ /* Set y_tmp = yy + sig*v, yp_tmp = yp + cj*sig*v. */
+ N_VLinearSum(sig, v, ONE, yy, y_tmp);
+ 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++;
+ if (retval == 0) break;
+ if (retval < 0) return(-1);
+
+ sig *= PT25;
+ }
+
+ if (retval > 0) return(+1);
+
+ /* Set Jv to [Jv - rr]/sig and return. */
+ siginv = ONE/sig;
+ N_VLinearSum(siginv, Jv, -siginv, rr, Jv);
+
+ return(0);
+
+}
+
+
+/*
+ * ================================================================
+ *
+ * PART II - backward problems
+ *
+ * ================================================================
+ */
+
+/* Readability replacements */
+
+#define yyTmp (IDAADJ_mem->ia_yyTmp)
+#define ypTmp (IDAADJ_mem->ia_ypTmp)
+#define noInterp (IDAADJ_mem->ia_noInterp)
+
+/*
+ * -----------------------------------------------------------------
+ * OPTIONAL INPUT and OUTPUT FUNCTIONS
+ * -----------------------------------------------------------------
+ */
+
+int IDASpilsSetGSTypeB(void *ida_mem, int which, int gstypeB)
+{
+ 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", "IDASpilsSetGSTypeB", 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);
+ }
+ 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);
+ }
+
+ /* 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;
+
+ /* Call the corresponding Set* function for the backward problem. */
+ return IDASpilsSetGSType(ida_memB, gstypeB);
+}
+
+int IDASpilsSetMaxRestartsB(void *ida_mem, int which, int maxrsB)
+{
+ 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);
+ 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);
+ }
+ 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", "IDASpilsSetMaxRestartsB", 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;
+ }
+ /* ida_mem corresponding to 'which' problem. */
+ ida_memB = (void *) IDAB_mem->IDA_mem;
+
+ /* Call the corresponding Set* function for the backward problem. */
+ return IDASpilsSetMaxRestarts(ida_memB,maxrsB);
+}
+
+int IDASpilsSetEpsLinB(void *ida_mem, int which, realtype eplifacB)
+{
+ 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", "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", "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", "IDASpilsSetEpsLinB", 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;
+ }
+ /* 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);
+}
+
+int IDASpilsSetMaxlB(void *ida_mem, int which, int maxlB)
+{
+ 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", "IDASpilsSetMaxlB", 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);
+ 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);
+ 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;
+ }
+ /* 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);
+}
+
+int IDASpilsSetIncrementFactorB(void *ida_mem, int which, realtype dqincfacB)
+{
+ 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",
+ "IDASpilsSetIncrementFactorB", 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",
+ "IDASpilsSetIncrementFactorB", 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",
+ "IDASpilsSetIncrementFactorB", 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;
+ }
+ /* ida_mem corresponding to 'which' problem. */
+ ida_memB = (void *) IDAB_mem->IDA_mem;
+
+ /* Call the corresponding Set* function for the backward problem. */
+ return IDASpilsSetIncrementFactor(ida_memB, dqincfacB);
+}
+
+int IDASpilsSetPreconditionerB(void *ida_mem, int which,
+ IDASpilsPrecSetupFnB psetB, IDASpilsPrecSolveFnB psolveB)
+{
+ IDAadjMem IDAADJ_mem;
+ IDAMem IDA_mem;
+ IDABMem IDAB_mem;
+ void *ida_memB;
+ IDASpilsMemB idaspilsB_mem;
+
+ /* Check if ida_mem is allright. */
+ if (ida_mem == NULL) {
+ IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASSPILS",
+ "IDASpilsSetPreconditionerB", 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",
+ "IDASpilsSetPreconditionerB", 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",
+ "IDASpilsSetPreconditionerB", 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;
+ }
+ /* ida_mem corresponding to 'which' problem. */
+ ida_memB = (void *) IDAB_mem->IDA_mem;
+
+ if ( IDAB_mem->ida_lmem == NULL) {
+ IDAProcessError(IDA_mem, IDASPILS_LMEMB_NULL, "IDASSPILS",
+ "IDASpilsSetPreconditionerB", MSGS_LMEMB_NULL);
+ return(IDASPILS_ILL_INPUT);
+ }
+
+ /* Get the IDASpilsMemB data. */
+ idaspilsB_mem = (IDASpilsMemB) IDAB_mem->ida_lmem;
+
+ /* Set preconditioners for the backward problem. */
+ idaspilsB_mem->s_psetB = psetB;
+ idaspilsB_mem->s_psolveB = psolveB;
+
+ return IDASpilsSetPreconditioner(ida_memB, IDAAspilsPrecSetup, IDAAspilsPrecSolve);
+}
+
+int IDASpilsSetJacTimesVecFnB(void *ida_mem, int which, IDASpilsJacTimesVecFnB jtvB)
+{
+ IDAadjMem IDAADJ_mem;
+ IDAMem IDA_mem;
+ IDABMem IDAB_mem;
+ IDASpilsMemB idaspilsB_mem;
+ void *ida_memB;
+ int flag;
+
+ /* Check if ida_mem is allright. */
+ if (ida_mem == NULL) {
+ IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASSPILS",
+ "IDASpilsSetJacTimesVecFnB", 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",
+ "IDASpilsSetJacTimesVecFnB", 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",
+ "IDASpilsSetJacTimesVecFnB", 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;
+ }
+ /* ida_mem corresponding to 'which' problem. */
+ ida_memB = (void *) IDAB_mem->IDA_mem;
+
+ if ( IDAB_mem->ida_lmem == NULL) {
+ IDAProcessError(IDA_mem, IDASPILS_LMEMB_NULL, "IDASSPILS",
+ "IDASpilsSetJacTimesVecFnB", MSGS_LMEMB_NULL);
+ return(IDASPILS_ILL_INPUT);
+ }
+
+ 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(IDAB_mem, IDAAspilsJacTimesVec);
+ } else {
+ flag = IDASpilsSetJacTimesVecFn(IDAB_mem, NULL);
+ }
+ return(flag);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * IDASSPILS private functions
+ *
+ * Those routines are interfaces the routines provided by user for
+ * backward problems.
+ *
+ * -----------------------------------------------------------------
+ */
+
+static int IDAAspilsPrecSetup(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)
+{
+ IDAMem IDA_mem;
+ IDAadjMem IDAADJ_mem;
+ IDASpilsMemB idaspilsB_mem;
+ IDABMem IDAB_mem;
+ int flag;
+
+ IDA_mem = (IDAMem) ida_mem;
+ IDAADJ_mem = IDA_mem->ida_adj_mem;
+ IDAB_mem = IDAADJ_mem->ia_bckpbCrt;
+ 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 (flag != IDA_SUCCESS) {
+ IDAProcessError(IDA_mem, -1, "IDASSPILS", "IDAAspilsPrecSetup", 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);
+ return(flag);
+}
+
+static int IDAAspilsPrecSolve(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)
+{
+ IDAMem IDA_mem;
+ IDAadjMem IDAADJ_mem;
+ IDASpilsMemB idaspilsB_mem;
+ IDABMem IDAB_mem;
+ int flag;
+
+ IDA_mem = (IDAMem) ida_mem;
+ IDAADJ_mem = IDA_mem->ida_adj_mem;
+ IDAB_mem = IDAADJ_mem->ia_bckpbCrt;
+ 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 (flag != IDA_SUCCESS) {
+ IDAProcessError(IDA_mem, -1, "IDASSPILS", "IDAAspilsPrecSolve", 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);
+ return(flag);
+}
+
+static int IDAAspilsJacTimesVec(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)
+{
+ IDAMem IDA_mem;
+ IDAadjMem IDAADJ_mem;
+ IDASpilsMemB idaspilsB_mem;
+ IDABMem IDAB_mem;
+ int flag;
+
+ IDA_mem = (IDAMem) ida_mem;
+ IDAADJ_mem = IDA_mem->ida_adj_mem;
+ IDAB_mem = IDAADJ_mem->ia_bckpbCrt;
+ 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 (flag != IDA_SUCCESS) {
+ IDAProcessError(IDA_mem, -1, "IDASSPILS", "IDAAspilsJacTimesVec", MSGS_BAD_T);
+ return(-1);
+ }
+ }
+ /* Call user's adjoint psolveB routine */
+ flag = idaspilsB_mem->s_jtimesB(tt, yyTmp, ypTmp,
+ yyB, ypB, rrB,
+ vB, JvB,
+ c_jB, IDAB_mem->ida_user_data,
+ tmp1B, tmp2B);
+ return(flag);
+}
diff --git a/src/idas/idas_spils_impl.h b/src/idas/idas_spils_impl.h
new file mode 100644
index 0000000..0944d54
--- /dev/null
+++ b/src/idas/idas_spils_impl.h
@@ -0,0 +1,224 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.9 $
+ * $Date: 2010/12/01 22:39:18 $
+ * -----------------------------------------------------------------
+ * Programmers: Alan C. Hindmarsh and Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * This is the common header file (private version) for the Scaled
+ * Preconditioned Iterative Linear Solver modules.
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _IDASSPILS_IMPL_H
+#define _IDASSPILS_IMPL_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <idas/idas_spils.h>
+#include "idas_impl.h"
+
+/* 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
+ * -----------------------------------------------------------------
+ */
+
+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 */
+
+ /* 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;
+ void (*s_pfree)(IDAMem IDA_mem);
+ void *s_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;
+
+} *IDASpilsMem;
+
+
+/*
+ * -----------------------------------------------------------------
+ * 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);
+
+/* 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,
+ realtype c_j, void *data,
+ N_Vector work1, N_Vector work2);
+
+
+
+/*
+ * -----------------------------------------------------------------
+ * Error and Warning Messages
+ * -----------------------------------------------------------------
+ */
+
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+
+#define MSGS_TIME "at t = %Lg, "
+#define MSGS_FRMT "%Le."
+
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+
+#define MSGS_TIME "at t = %lg, "
+#define MSGS_FRMT "%le."
+
+#else
+
+#define MSGS_TIME "at t = %g, "
+#define MSGS_FRMT "%e."
+
+#endif
+
+
+/* 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."
+#define MSGS_BAD_LSTYPE "Incompatible linear solver type."
+#define MSGS_LMEM_NULL "Linear solver memory is NULL."
+#define MSGS_BAD_GSTYPE "gstype has an illegal value."
+#define MSGS_NEG_MAXRS "maxrs < 0 illegal."
+#define MSGS_NEG_EPLIFAC "eplifac < 0.0 illegal."
+#define MSGS_NEG_DQINCFAC "dqincfac < 0.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."
+
+/* 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
+ * -----------------------------------------------------------------
+ */
+
+typedef struct IDASpilsMemRecB {
+
+ IDASpilsJacTimesVecFnB s_jtimesB;
+ IDASpilsPrecSetupFnB s_psetB;
+ IDASpilsPrecSolveFnB s_psolveB;
+ void *s_P_dataB;
+
+} *IDASpilsMemB;
+
+/*
+ * -----------------------------------------------------------------
+ * 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."
+#define MSGS_NO_ADJ "Illegal attempt to call before calling IDAAdjInit."
+
+#define MSGS_LMEMB_NULL "Linear solver memory is NULL for the backward integration."
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/idas/idas_sptfqmr.c b/src/idas/idas_sptfqmr.c
new file mode 100644
index 0000000..a4f1186
--- /dev/null
+++ b/src/idas/idas_sptfqmr.c
@@ -0,0 +1,583 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.7 $
+ * $Date: 2007/11/26 16:20:01 $
+ * -----------------------------------------------------------------
+ * 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.
+ * -----------------------------------------------------------------
+ * 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 void 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 flag, 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) flag = 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;
+
+ /* 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 = RSqrt(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 */
+ npe = nli = nps = ncfl = 0;
+ njtimes = nres = 0;
+
+ /* 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;
+ void *ida_memB;
+ 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;
+ }
+ /* ida_mem corresponding to 'which' problem. */
+ ida_memB = (void *) IDAB_mem->IDA_mem;
+
+
+ /* 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 void IDASptfqmrFreeB(IDABMem IDAB_mem)
+{
+ IDASpilsMemB idaspilsB_mem;
+
+ idaspilsB_mem = (IDASpilsMemB) IDAB_mem->ida_lmem;
+
+ free(idaspilsB_mem);
+}
diff --git a/src/kinsol/CMakeLists.txt b/src/kinsol/CMakeLists.txt
new file mode 100644
index 0000000..5a209fe
--- /dev/null
+++ b/src/kinsol/CMakeLists.txt
@@ -0,0 +1,124 @@
+# ---------------------------------------------------------------
+# $Revision: 1.4 $
+# $Date: 2009/02/17 02:58:48 $
+# ---------------------------------------------------------------
+# Programmer: Radu Serban @ LLNL
+# ---------------------------------------------------------------
+# Copyright (c) 2007, The Regents of the University of California.
+# Produced at the Lawrence Livermore National Laboratory.
+# All rights reserved.
+# For details, see the LICENSE file.
+# ---------------------------------------------------------------
+# CMakeLists.txt file for the KINSOL library
+
+INSTALL(CODE "MESSAGE(\"\nInstall KINSOL\n\")")
+
+# Add variable kinsol_SOURCES with the sources for the KINSOL library
+SET(kinsol_SOURCES
+ kinsol.c
+ kinsol_io.c
+ kinsol_direct.c
+ kinsol_band.c
+ kinsol_dense.c
+ kinsol_spils.c
+ kinsol_spbcgs.c
+ kinsol_spgmr.c
+ kinsol_sptfqmr.c
+ kinsol_bbdpre.c
+ )
+
+# 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_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 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_spgmr.h
+ kinsol_spils.h
+ kinsol_sptfqmr.h
+ )
+
+# 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)
+
+# Add source directories to include directories for access to
+# implementation only header files.
+INCLUDE_DIRECTORIES(.)
+INCLUDE_DIRECTORIES(../sundials)
+
+# Define C preprocessor flag -DBUILD_SUNDIALS_LIBRARY
+ADD_DEFINITIONS(-DBUILD_SUNDIALS_LIBRARY)
+
+# Build the static library
+IF(BUILD_STATIC_LIBS)
+
+ # Add the build target for the static KINSOL library
+ ADD_LIBRARY(sundials_kinsol_static STATIC
+ ${kinsol_SOURCES} ${kinsol_BL_SOURCES} ${shared_SOURCES})
+
+ # Set the library name and make sure it is not deleted
+ SET_TARGET_PROPERTIES(sundials_kinsol_static
+ PROPERTIES OUTPUT_NAME sundials_kinsol CLEAN_DIRECT_OUTPUT 1)
+
+ # Install the KINSOL library
+ INSTALL(TARGETS sundials_kinsol_static DESTINATION lib)
+
+ENDIF(BUILD_STATIC_LIBS)
+
+# Build the shared library
+IF(BUILD_SHARED_LIBS)
+
+ # Add the build target for the KINSOL library
+ ADD_LIBRARY(sundials_kinsol_shared SHARED
+ ${kinsol_SOURCES} ${kinsol_BL_SOURCES} ${shared_SOURCES})
+
+ # Set the library name and make sure it is not deleted
+ SET_TARGET_PROPERTIES(sundials_kinsol_shared
+ PROPERTIES OUTPUT_NAME sundials_kinsol CLEAN_DIRECT_OUTPUT 1)
+
+ # Set VERSION and SOVERSION for shared libraries
+ SET_TARGET_PROPERTIES(sundials_kinsol_shared
+ PROPERTIES VERSION ${kinsollib_VERSION} SOVERSION ${kinsollib_SOVERSION})
+
+ # Install the KINSOL library
+ INSTALL(TARGETS sundials_kinsol_shared DESTINATION lib)
+
+ENDIF(BUILD_SHARED_LIBS)
+
+# Install the KINSOL header files
+INSTALL(FILES ${kinsol_HEADERS} ${kinsol_BL_HEADERS} DESTINATION include/kinsol)
+
+# Install the KINSOL implementation header file
+INSTALL(FILES kinsol_impl.h DESTINATION include/kinsol)
+
+#
+MESSAGE(STATUS "Added KINSOL module")
diff --git a/debian/copyright b/src/kinsol/LICENSE
similarity index 83%
copy from debian/copyright
copy to src/kinsol/LICENSE
index 98cde97..b42049f 100644
--- a/debian/copyright
+++ b/src/kinsol/LICENSE
@@ -1,22 +1,10 @@
-This package was debianized by Andrey Romanenko <andrey at enginum.com> on
-Wed, 20 Apr 2005 12:01:42 +0100.
+Copyright (c) 2002, The Regents of the University of California.
+Produced at the Lawrence Livermore National Laboratory.
+Written by Alan Hindmarsh, Allan Taylor, Radu Serban.
+UCRL-CODE-155953
+All rights reserved.
-It was downloaded from http://www.llnl.gov/CASC/sundials/
-
-Authors: Peter Brown, Aaron Collier, Keith Grant, Alan Hindmarsh,
- Steve Lee, Radu Serban, Dan Shumaker, Carol Woodward
-
-Copyright Holder: The Regents of the University of California.
-
-License:
-
-Copyright (c) 2002, The Regents of the University of California.
-Produced at the Lawrence Livermore National Laboratory
-Written by A.C. Hindmarsh and R. Serban.
-UCRL-CODE-155950
-All rights reserved.
-
-This file is part of CVODES v2.1.0.
+This file is part of KINSOL.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
diff --git a/src/kinsol/Makefile.in b/src/kinsol/Makefile.in
new file mode 100644
index 0000000..6bd0992
--- /dev/null
+++ b/src/kinsol/Makefile.in
@@ -0,0 +1,167 @@
+# -----------------------------------------------------------------
+# $Revision: 1.12 $
+# $Date: 2009/03/25 23:10:50 $
+# -----------------------------------------------------------------
+# Programmer(s): Radu Serban and Aaron Collier @ LLNL
+# -----------------------------------------------------------------
+# Copyright (c) 2002, The Regents of the University of California.
+# Produced at the Lawrence Livermore National Laboratory.
+# All rights reserved.
+# For details, see the LICENSE file.
+# -----------------------------------------------------------------
+# Makefile for KINSOL module
+#
+# @configure_input@
+# -----------------------------------------------------------------
+
+SHELL = @SHELL@
+
+ at SET_MAKE@
+
+srcdir = @srcdir@
+builddir = @builddir@
+abs_builddir = @abs_builddir@
+top_builddir = @top_builddir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+includedir = @includedir@
+libdir = @libdir@
+
+INSTALL = @INSTALL@
+INSTALL_LIB = @INSTALL_PROGRAM@
+INSTALL_HEADER = @INSTALL_DATA@
+
+LIBTOOL = @LIBTOOL@
+LIBTOOL_DEPS = @LIBTOOL_DEPS@
+
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CC = @CC@
+CFLAGS = @CFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+
+LAPACK_ENABLED = @LAPACK_ENABLED@
+
+top_srcdir = $(srcdir)/../..
+
+INCLUDES = -I$(top_srcdir)/include -I$(top_builddir)/include
+
+LIB_REVISION = 1:0:0
+
+KINSOL_LIB = libsundials_kinsol.la
+
+KINSOL_SRC_FILES = kinsol.c kinsol_io.c kinsol_direct.c kinsol_dense.c kinsol_band.c kinsol_spils.c kinsol_spgmr.c kinsol_spbcgs.c kinsol_sptfqmr.c kinsol_bbdpre.c
+KINSOL_BL_SRC_FILES = kinsol_lapack.c
+
+KINSOL_OBJ_FILES = $(KINSOL_SRC_FILES:.c=.o)
+KINSOL_BL_OBJ_FILES = $(KINSOL_BL_SRC_FILES:.c=.o)
+
+KINSOL_LIB_FILES = $(KINSOL_SRC_FILES:.c=.lo)
+KINSOL_BL_LIB_FILES = $(KINSOL_BL_SRC_FILES:.c=.lo)
+
+SHARED_LIB_FILES = $(top_builddir)/src/sundials/sundials_band.lo \
+ $(top_builddir)/src/sundials/sundials_dense.lo \
+ $(top_builddir)/src/sundials/sundials_direct.lo \
+ $(top_builddir)/src/sundials/sundials_iterative.lo \
+ $(top_builddir)/src/sundials/sundials_spgmr.lo \
+ $(top_builddir)/src/sundials/sundials_spbcgs.lo \
+ $(top_builddir)/src/sundials/sundials_sptfqmr.lo \
+ $(top_builddir)/src/sundials/sundials_math.lo \
+ $(top_builddir)/src/sundials/sundials_nvector.lo
+
+mkinstalldirs = $(SHELL) $(top_srcdir)/config/mkinstalldirs
+rminstalldirs = $(SHELL) $(top_srcdir)/config/rminstalldirs
+
+# ----------------------------------------------------------------------------------------------------------------------
+
+all: $(KINSOL_LIB)
+
+$(KINSOL_LIB): shared $(KINSOL_LIB_FILES)
+ @if test "X${LAPACK_ENABLED}" = "Xyes"; then \
+ make lib_with_bl; \
+ else \
+ make lib_without_bl; \
+ fi
+
+lib_without_bl: shared $(KINSOL_LIB_FILES)
+ $(LIBTOOL) --mode=link $(CC) $(CFLAGS) -o $(KINSOL_LIB) $(KINSOL_LIB_FILES) $(SHARED_LIB_FILES) -rpath $(libdir) $(LDFLAGS) $(LIBS) -version-info $(LIB_REVISION)
+
+lib_with_bl: shared $(KINSOL_LIB_FILES) $(KINSOL_BL_LIB_FILES)
+ $(LIBTOOL) --mode=link $(CC) $(CFLAGS) -o $(KINSOL_LIB) $(KINSOL_LIB_FILES) $(KINSOL_BL_LIB_FILES) $(SHARED_LIB_FILES) -rpath $(libdir) $(LDFLAGS) $(LIBS) -version-info $(LIB_REVISION)
+
+install: $(KINSOL_LIB)
+ $(mkinstalldirs) $(includedir)/kinsol
+ $(mkinstalldirs) $(libdir)
+ $(LIBTOOL) --mode=install $(INSTALL_LIB) $(KINSOL_LIB) $(libdir)
+ $(INSTALL_HEADER) $(top_srcdir)/include/kinsol/kinsol.h $(includedir)/kinsol/
+ $(INSTALL_HEADER) $(top_srcdir)/include/kinsol/kinsol_direct.h $(includedir)/kinsol/
+ $(INSTALL_HEADER) $(top_srcdir)/include/kinsol/kinsol_dense.h $(includedir)/kinsol/
+ $(INSTALL_HEADER) $(top_srcdir)/include/kinsol/kinsol_band.h $(includedir)/kinsol/
+ $(INSTALL_HEADER) $(top_srcdir)/include/kinsol/kinsol_spgmr.h $(includedir)/kinsol/
+ $(INSTALL_HEADER) $(top_srcdir)/include/kinsol/kinsol_spbcgs.h $(includedir)/kinsol/
+ $(INSTALL_HEADER) $(top_srcdir)/include/kinsol/kinsol_sptfqmr.h $(includedir)/kinsol/
+ $(INSTALL_HEADER) $(top_srcdir)/include/kinsol/kinsol_bbdpre.h $(includedir)/kinsol/
+ $(INSTALL_HEADER) $(top_srcdir)/include/kinsol/kinsol_spils.h $(includedir)/kinsol/
+ $(INSTALL_HEADER) $(top_srcdir)/src/kinsol/kinsol_impl.h $(includedir)/kinsol/
+ @if test "X${LAPACK_ENABLED}" = "Xyes"; then \
+ $(INSTALL_HEADER) $(top_srcdir)/include/kinsol/kinsol_lapack.h $(includedir)/kinsol/ ; \
+ fi
+
+uninstall:
+ $(LIBTOOL) --mode=uninstall rm -f $(libdir)/$(KINSOL_LIB)
+ rm -f $(includedir)/kinsol/kinsol.h
+ rm -f $(includedir)/kinsol/kinsol_direct.h
+ rm -f $(includedir)/kinsol/kinsol_dense.h
+ rm -f $(includedir)/kinsol/kinsol_band.h
+ rm -f $(includedir)/kinsol/kinsol_lapack.h
+ rm -f $(includedir)/kinsol/kinsol_spgmr.h
+ rm -f $(includedir)/kinsol/kinsol_spbcgs.h
+ rm -f $(includedir)/kinsol/kinsol_sptfqmr.h
+ rm -f $(includedir)/kinsol/kinsol_bbdpre.h
+ rm -f $(includedir)/kinsol/kinsol_spils.h
+ rm -f $(includedir)/kinsol/kinsol_impl.h
+ $(rminstalldirs) ${includedir}/kinsol
+
+shared:
+ @cd ${top_builddir}/src/sundials ; \
+ ${MAKE} ; \
+ cd ${abs_builddir}
+
+clean:
+ $(LIBTOOL) --mode=clean rm -f $(KINSOL_LIB)
+ rm -f $(KINSOL_LIB_FILES)
+ rm -f $(KINSOL_BL_LIB_FILES)
+ rm -f $(KINSOL_OBJ_FILES)
+ rm -f $(KINSOL_BL_OBJ_FILES)
+
+distclean: clean
+ rm -f Makefile
+
+kinsol.lo: $(srcdir)/kinsol.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/kinsol.c
+kinsol_io.lo: $(srcdir)/kinsol_io.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/kinsol_io.c
+kinsol_direct.lo: $(srcdir)/kinsol_direct.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/kinsol_direct.c
+kinsol_dense.lo: $(srcdir)/kinsol_dense.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/kinsol_dense.c
+kinsol_band.lo: $(srcdir)/kinsol_band.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/kinsol_band.c
+kinsol_lapack.lo: $(srcdir)/kinsol_lapack.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/kinsol_lapack.c
+kinsol_spils.lo: $(srcdir)/kinsol_spils.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/kinsol_spils.c
+kinsol_spgmr.lo: $(srcdir)/kinsol_spgmr.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/kinsol_spgmr.c
+kinsol_spbcgs.lo: $(srcdir)/kinsol_spbcgs.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/kinsol_spbcgs.c
+kinsol_sptfqmr.lo: $(srcdir)/kinsol_sptfqmr.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/kinsol_sptfqmr.c
+kinsol_bbdpre.lo: $(srcdir)/kinsol_bbdpre.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/kinsol_bbdpre.c
+
+libtool: $(top_builddir)/$(LIBTOOL_DEPS)
+ @cd ${top_builddir} ; \
+ ${SHELL} ./config.status --recheck ; \
+ cd ${abs_builddir}
diff --git a/src/kinsol/README b/src/kinsol/README
new file mode 100644
index 0000000..ba660e5
--- /dev/null
+++ b/src/kinsol/README
@@ -0,0 +1,397 @@
+ KINSOL
+ Release 2.7.0, March 2012
+ Aaron Collier, Alan C. Hindmarsh, and Radu Serban
+ Center for Applied Scientific Computing, LLNL
+
+KINSOL is a solver for nonlinear algebraic systems which can be
+described as F(u) = 0. It is newly rewritten in the C language and based
+on the previous Fortran package NKSOL [4], written by Peter Brown and
+Youcef Saad.
+
+KINSOL can be used both on serial and parallel (MPI) computers.
+The difference is only in the NVECTOR module of vector functions.
+The desired version is obtained when compiling the example files
+by linking with the appropriate library of NVECTOR functions. In the
+parallel version, communication between processes is done via the MPI
+(Message Passage Interface) system.
+
+When used with the serial NVECTOR module, KINSOL provides both direct (dense
+and band) and preconditioned Krylov (iterative) linear solvers. Three different
+iterative solvers are available: scaled preconditioned GMRES (SPGMR), scaled
+preconditioned BiCGStab (SPBCG), and scaled preconditioned TFQMR (SPTFQMR).
+When used with the parallel NVECTOR module, KINSOL provides a
+preconditioner module called KINBBDPRE, which provides a
+band-block-diagonal preconditioner for use with the Krylov linear
+solvers. However, within KINSOL any NVECTOR module may be combined
+with an appropriate user-supplied preconditioning module for
+acceleration of the Krylov solvers.
+
+KINSOL is part of a software family called SUNDIALS: SUite of Nonlinear
+and DIfferential/ALgebraic equation Solvers. This suite consists of
+CVODE, KINSOL, and IDA, and variants of these. The directory
+structure of the package supplied reflects this family relationship.
+
+For use with Fortran applications, a set of Fortran/C interface routines,
+called FKINSOL, is also supplied. These are written in C, but assume that
+the user calling program and all user-supplied routines are in Fortran.
+
+The notes below provide the location of documentation, directions for the
+installation of the KINSOL package, and relevant references. Following that
+is a brief history of revisions to the package.
+
+
+A. Documentation
+----------------
+
+/sundials/doc/kinsol/ contains PDF files for the KINSOL User Guide [1] (kin_guide.pdf)
+and the KINSOL Examples [2] (kin_examples.pdf) documents.
+
+
+B. Installation
+---------------
+
+For basic installation instructions see the file /sundials/INSTALL_NOTES.
+For complete installation instructions see the "KINSOL Installation Procedure"
+chapter in the KINSOL User Guide [1].
+
+
+C. References
+-------------
+
+[1] A. M. Collier, A. C. Hindmarsh, R. Serban, and C. S. Woodward,
+ "User Documentation for KINSOL v2.7.0," LLNL technical report
+ UCRL-SM-208116, December 2011.
+
+[2] A. M. Collier and R. Serban, "Example Programs for KINSOL v2.7.0,"
+ LLNL technical report UCRL-SM-208114, December 2011.
+
+[3] A. C. Hindmarsh, P. N. Brown, K. E. Grant, S. L. Lee, R. Serban,
+ D. E. Shumaker, and C. S. Woodward, "SUNDIALS, Suite of Nonlinear and
+ Differential/Algebraic Equation Solvers," ACM Trans. Math. Softw.,
+ 31(3), pp. 363-396, 2005.
+
+[4] Peter N. Brown and Youcef Saad, "Hybrid Krylov Methods for
+ Nonlinear Systems of Equations," SIAM J. Sci. Stat. Comput.,
+ Vol 11, no 3, pp. 450-481, May 1990.
+
+[5] A. G. Taylor and A. C. Hindmarsh, "User Documentation for KINSOL,
+ A Nonlinear Solver for Sequential and Parallel Computers," LLNL
+ technical report UCRL-ID-131185, July 1998.
+
+
+D. Releases
+-----------
+
+v. 2.7.0 - Mar. 2012
+v. 2.6.0 - May 2009
+v. 2.5.0 - Nov. 2006
+v. 2.4.0 - Mar. 2006
+v. 2.3.0 - Apr. 2005
+v. 2.2.2 - Mar. 2005
+v. 2.2.1 - Jan. 2005
+v. 2.2.0 - Dec. 2004
+v. 2.0 - Jul. 2002 (first SUNDIALS release)
+v. 1.0 - Aug. 1998 (date written)
+
+
+E. Revision History
+-------------------
+
+v. 2.6.0 (May 2009) ---> v. 2.7.0 (Mar. 2012)
+---------------------------------------------
+
+- Bug fixes
+ - Three major logic bugs were fixed -- involving updating the solution
+ vector, updating the linesearch parameter, and a missing error return.
+ - Three minor errors were fixed -- involving setting etachoice in the
+ Matlab/KINSOL interface, a missing error case in KINPrintInfo,
+ and avoiding an exponential overflow in the evaluation of omega.
+ - In each linear solver interface function, the linear solver memory is
+ freed on an error return, and the **Free function now includes a
+ line setting to NULL the main memory pointer to the linear solver memory.
+
+- Changes to user interface
+ - One significant design change was made with this release: The problem
+ size and its relatives, bandwidth parameters, related internal indices,
+ pivot arrays, and the optional output lsflag, have all been
+ changed from type int to type long int, except for the
+ problem size and bandwidths in user calls to routines specifying
+ BLAS/LAPACK routines for the dense/band linear solvers. The function
+ NewIntArray is replaced by a pair NewIntArray/NewLintArray,
+ for int and long int arrays, respectively.
+ - in the installation files, we modified the treatment of the macro
+ SUNDIALS_USE_GENERIC_MATH, so that the parameter GENERIC_MATH_LIB
+ is either defined (with no value) or not defined.
+
+
+v. 2.5.0 (Nov. 2006) ---> v. 2.6.0 (May 2009)
+---------------------------------------------
+
+- New features
+ - added a new linear solver module based on Blas + Lapack for
+ both dense and banded matrices.
+
+- Bug fixes
+ - added logic to ensure omega is updated every iteration.
+ - fixed difference-quotient Jacobian memory reset bug.
+
+- Changes to user interface
+ - renamed all **Malloc functions to **Init
+ - all user-supplied functions now receive the same pointer to user data
+ (instead of having different ones for the system evaluation, Jacobian
+ information functions, etc.
+ - common functionality for all direct linear solvers (dense, band, and
+ the new Lapack solver) has been collected into the DLS (Direct Linear
+ Solver) module, similar to the SPILS module for the iterative linear
+ solvers. All optional input and output functions for these linear
+ solver now have the prefix 'KINDls'. In addition, in order to include
+ the new Lapack-based linear solver, all dimensions for these linear
+ solvers (problem sizes, bandwidths, etc) are now of type 'int'
+ (instead of 'long int').
+ - the initialization function for the preconditioner module KINBBDPRE
+ was renamed KINBBDInit (from KINBBDAlloc) and it does not return
+ a pointer to preconditioner memory anymore. Instead, all preconditioner
+ module-related functions are now called with the main solver memory
+ pointer as their first argument. When using the KINBBDPRE module,
+ there is no need to use special functions to attach one of the SPILS
+ linear solvers (instead use one of KINSpgmr, KINSpbcg, or KINSptfqmr).
+ Moreover, there is no need to call a memory deallocation function for
+ the preconditioner module.
+ - changes corresponding to the above were made to the FCMIX interface.
+
+v. 2.4.0 (Mar. 2006) ---> v. 2.5.0 (Oct. 2006)
+----------------------------------------------
+
+- Changes related to the build system
+ - reorganized source tree: header files in ${srcdir}/include/kinsol,
+ source files in ${srcdir}/src/kinsol, fcmix source files in
+ ${srcdir}/src/kinsol/fcmix, examples in ${srcdir}/examples/kinsol
+ - exported header files are installed unde ${includedir}/kinsol
+
+- Changes to user interface
+ - all included header files use relative paths from ${includedir}
+
+v. 2.3.0 (Apr. 2005) ---> v. 2.4.0 (Mar. 2006)
+----------------------------------------------
+
+- New features
+ - added direct linear solvers (dense and band, provided
+ through the KINDENSE and KINBAND modules, respectively) thus adding
+ modified (and exact) Newton methods to KINSOL.
+ - added KINSPBCG interface module to allow KINSOL to interface with the
+ shared SPBCG (scaled preconditioned Bi-CGSTAB) linear solver module.
+ - added KINSPTFQMR interface module to allow KINSOL to interface with
+ the shared SPTFQMR (scaled preconditioned TFQMR) linear solver module
+ - added support for SPBCG and SPTFQMR to the KINBBDPRE preconditioner module.
+ - added option to KINBBDPRE preconditioner module to allow specification
+ of different half-bandwidths for difference quotient approximation and
+ retained matrix.
+ - added support for interpreting failures in user-supplied functions.
+
+- Bug fixes
+ - corrected a bug in the preconditioner logic that caused the initial call
+ to the preconditioner setup routine (controlled by KINSetNoInitSetup) to
+ be skipped during subsequent calls to KINSol
+
+- Changes to underlying algorithms
+ - modified the KINBBDPRE preconditioner module to allow the use of
+ different half-bandwidths for the difference quotient approximation
+ and the retained matrix.
+ - added nonlinear residual monitoring scheme to control Jacobian updating
+ when a direct linear solver is used (modified Newton iteration)
+
+- Changes to user interface
+ - changed argument of KINFree and KINBBDPrecFree to be the address of
+ the respective memory block pointer, so that its NULL value is
+ propagated back to the calling function.
+ - modified the argument list of KINBBDPrecAlloc to allow specification
+ of the upper and lower half-bandwidths to be used in the computation
+ of the local Jacobian blocks (mudq, mldq), and the half-bandwidths
+ of the retained banded approximation to the local Jacobian block
+ (mukeep, mlkeep).
+ - added KINSPBCG module which defines appropriate KINSpbcg* functions to
+ allow KINSOL to interface with the shared SPBCG linear solver module.
+ - added KINBBDSpbcg function to KINBBDPRE module to support SPBCG linear
+ solver module.
+ - changed function type names (not the actual definitions) to accomodate
+ all the Scaled Preconditioned Iterative Linear Solvers now available:
+ KINSpgmrJactimesVecFn -> KINSpilsJacTimesVecFn
+ KINSpgmrPrecSetupFn -> KINSpilsPrecSetupFn
+ KINSpgmrPrecSolveFn -> KINSpilsPrecSolveFn
+ - changed function types so that all user-supplied functions return
+ an integer flag (not all of them currently used).
+ - changed some names for KINBBDPRE function outputs
+ - added option for user-supplied error handler function.
+ - added option for user-supplied info handler function.
+ - renamed all exported header files (except for kinsol.h, all header files
+ have the prefix 'kinsol_')
+ - changed naming scheme for KINSOL examples
+
+- Changes to the FKINSOL module
+ - modified argument list of FKINBBDINIT to accomadate changes made
+ to KINBBDPRE module, so now user must specify the upper and lower
+ half-bandwidths for the difference quotient approximation (mudq, mldq)
+ and the retained matrix (mukeep, mlkeep).
+ - added support for KINSPBCG/SPBCG (added FKIN*SPBCG* functions).
+ - added support for KINSPTFQMR/SPTFQMR (added FKIN*SPTFQMR* functions).
+ - added support for KINDENSE/DENSE (added FKIN*DENSE* functions).
+ - added support for KINBAND/BAND (added FKIN*DENSE* functions).
+ - Optional inputs are now set using routines FKINSETIIN (integer inputs),
+ FKINSETRIN (real inputs), and FKINSETVIN (vector inputs) through pairs
+ key-value. Optional outputs are still obtained from two arrays (IOUT and
+ ROUT), owned by the user and passed as arguments to FKINMALLOC.
+
+- Changes related to the build system
+ - updated configure script and Makefiles for Fortran examples to avoid C++
+ compiler errors (now use CC and MPICC to link only if necessary)
+ - the main KINSOL header file (kinsol.h) is still exported to the install include
+ directory. However, all other KINSOL header files are exported into an 'kinsol'
+ subdirectory of the install include directory.
+ - the KINSOL library now contains all shared object files (there is no separate
+ libsundials_shared library anymore)
+
+v. 2.2.2 (Mar. 2005) ---> v. 2.3.0 (Apr. 2005)
+----------------------------------------------
+
+- Changes to user interface
+ - KINSOL now stores an actual copy of the constraints vector rather than
+ just a pointer in order to resolve potential scoping issues
+ - several optional input functions were combined into a single function:
+ - KINSpgmrSetPrecSetupFn, KINSpgmrSetPrecSolveFn and KINSpgmrSetPrecData
+ were combined into KINSpgmrSetPreconditioner
+ - KINSpgmrSetJacTimesVecFn and KINSpgmrSetJacData were combined into
+ KINSpgmrSetJacTimesVecFn
+
+- Changes to FKINSOL module:
+ - FKINSPGMRSETPSET and FKINSPGMRSETPSOL were combined into FKINSPGMRSETPREC
+ - due to changes to the main solver, if FKPSOL is provided, then FKPSET
+ must also be defined, even if it is empty
+
+v. 2.2.1 (Jan. 2005) ---> v. 2.2.2 (Mar. 2005)
+----------------------------------------------
+
+- Bug fixes
+ - fixed bug in computation of the scaled step length
+ - fixed bug in logic for disabling the call to the preconditioner setup function
+ at the first iteration
+ - modified FCMIX files to avoid C++ compiler errors
+ - changed implicit type conversion to explicit in check_flag() routine in
+ examples to avoid C++ compiler errors
+
+- Changes to documentation
+ - added section with numerical values of all input and output solver constants
+ - added description of --with-mpi-flags option
+
+- Changes related to the build system
+ - fixed autoconf-related bug to allow configuration with the PGI Fortran compiler
+ - modified to use customized detection of the Fortran name mangling scheme
+ (autoconf's AC_F77_WRAPPERS routine is problematic on some platforms)
+ - added --with-mpi-flags as a configure option to allow user to specify
+ MPI-specific flags
+ - updated Makefiles for Fortran examples to avoid C++ compiler errors (now use
+ CC and MPICC to link)
+
+v. 2.2.0 (Dec. 2004) ---> v. 2.2.1 (Jan. 2005)
+----------------------------------------------
+
+- Changes related to the build system
+ - changed order of compiler directives in header files to avoid compilation
+ errors when using a C++ compiler.
+
+v. 2.0 (Jul. 2002) ---> v. 2.2.0 (Dec. 2004)
+--------------------------------------------
+
+- New feature
+ - added option to disable all error messages.
+
+- Bug fixes
+ - fixed constraints-related bug.
+ - fixed bug in implementation of line-search method related to
+ beta-condition.
+ - corrected value of ealpha variable (related to forcing term).
+
+- Changes related to NVECTOR module
+ (see also the file sundials/shared/README)
+ - removed machEnv, redefined table of vector operations (now contained
+ in the N_Vector structure itself).
+ - all KINSOL functions create new N_Vector variables through cloning,
+ using an N_Vector passed by the user as a template.
+
+- Changes to type names and KINSOL constants
+ - removed type 'integertype'; instead use 'int' or 'long int', as
+ appropriate.
+ - restructured the list of return values from the various KINSOL
+ functions.
+ - changed all KINSOL constants (inputs and return values) to have
+ the prefix 'KIN_' (e.g. KIN_SUCCESS).
+ - renamed function type 'SysFn' to 'KINSysFn'.
+
+- Changes to underlying algorithms
+ - modified line-search backtracking scheme to use cubic interpolation
+ after the first backtrack, if possible.
+ - changed implementation of constraints:
+ if constraints[i] =
+ 0 u[i] NOT constrained
+ +1 u[i] >= 0
+ -1 u[i] <= 0
+ +2 u[i] > 0
+ -2 u[i] < 0
+ where u is the solution vector (see the KINSOL User Guide [1] for
+ additional details).
+
+- Changes to optional input/output
+ - added KINSet* and KINGet* functions for optional inputs/outputs,
+ replacing the arrays iopt and ropt.
+ - added new optional inputs (e.g. maximum number of nonlinear iterations
+ between calls to preconditioner setup routine, etc.).
+ - the value of the last return flag from any function within the SPGMR
+ linear solver module can be obtained as an optional output using
+ KINSpgmrGetLastFlag.
+
+- Changes to user-callable functions
+ - added new function KINCreate which initializes the KINSOL solver object
+ and returns a pointer to the KINSOL memory block.
+ - removed N (problem size) from all functions.
+ - shortened argument lists of most KINSOL functions (the arguments that
+ were dropped can now be specified through KINSet* functions).
+ - removed reinitialization functions for SPGMR linear solver (same
+ functionality can be obtained using KINSpgmrSet* functions).
+
+- Changes to user-supplied functions
+ - removed N (problem dimension) from argument lists.
+ - in KINSPGMR, shortened argument lists for user preconditioner functions.
+
+- Changes to the FKINSOL module
+ - revised to use underscore and precision flags at compile time (from
+ configure); example sources are preprocessed accordingly.
+ - use KIN*Set* and KIN*Get* functions from KINSOL (although the optional
+ I/O is still communicated to the user of FKINSOL through arrays IOPT
+ and ROPT).
+ - added new optional inputs and outputs (e.g. last return flag from the
+ linear solver, etc.).
+
+v. 1.0 (Aug. 1998) ---> v. 2.0 (Jul. 2002)
+------------------------------------------
+
+YYYYMMDD
+
+19980802 DATE WRITTEN - KINSOL released.
+19981203 Implemented serial Fortran/C interface (fkinsols.c).
+19990301 Fixed bug in nbktrk.
+19990325 Removed machEnv as an argument to KINSol.
+19991229 Fixed preconditioner evaluation logic;
+ revised SPGMR module to treat scalings correctly.
+20000324 Upgraded serial and parallel versions of NVECTOR module.
+20000706 Fixed bug in use of vtemp1 in KINSpgmrSolve call to KINAtimes etc.
+20000808 Fixed bug in N_VMin routine.
+20010118 Minor corrections, notably:
+ In fkinsol.h, KINUAtimes prototype fixed. In fkinsols.c and
+ fkinsolp.c, N_Vector's disposed with N_VDISPOSE after KINSol call.
+ In all fkin*.c, #include lines for header files corrected.
+20011212 Corrected 4 N_VDISPOSE arguments in FKINSOL.
+20011212 Added missing error flag print in KINSol, and changed 5 return
+ values in KINStop to enum-defined expressions.
+20011220 Default type 'integer' changed to 'long int' in llnltyps.h.
+20011221 In FKINSOL, corrected type (integer) for Neq in KINPreco, KINPSol.
+20020313 Modified to work with new NVECTOR abstraction.
+20020627 Modified to reflect type name changes.
diff --git a/src/kinsol/fcmix/CMakeLists.txt b/src/kinsol/fcmix/CMakeLists.txt
new file mode 100644
index 0000000..bbfe4c4
--- /dev/null
+++ b/src/kinsol/fcmix/CMakeLists.txt
@@ -0,0 +1,42 @@
+# CMakeLists.txt file for the FKINSOL library
+
+# Add variable fcvode_SOURCES with the sources for the FCVODE library
+SET(fkinsol_SOURCES
+ fkinband.c
+ fkinbbd.c
+ fkindense.c
+ fkinjtimes.c
+ fkinpreco.c
+ fkinsol.c
+ )
+
+IF(LAPACK_FOUND)
+ SET(fkinsol_BL_SOURCES fkinlapack.c fkinlapdense.c fkinlapband.c)
+ELSE(LAPACK_FOUND)
+ SET(fkinsol_BL_SOURCES "")
+ENDIF(LAPACK_FOUND)
+
+# Add source directories to include directories for access to
+# implementation only header files (both for fkinsol and kinsol)
+INCLUDE_DIRECTORIES(.)
+INCLUDE_DIRECTORIES(..)
+
+# Define C preprocessor flag -DBUILD_SUNDIALS_LIBRARY
+ADD_DEFINITIONS(-DBUILD_SUNDIALS_LIBRARY)
+
+# Only build STATIC libraries (we cannot build shared libraries
+# for the FCMIX interfaces due to unresolved symbol errors
+# 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})
+
+# Set the library name and make sure it is not deleted
+SET_TARGET_PROPERTIES(sundials_fkinsol_static
+ PROPERTIES OUTPUT_NAME sundials_fkinsol CLEAN_DIRECT_OUTPUT 1)
+
+# Install the FKINSOL library
+INSTALL(TARGETS sundials_fkinsol_static DESTINATION lib)
+
+#
+MESSAGE(STATUS "Added KINSOL FCMIX module")
diff --git a/src/kinsol/fcmix/Makefile.in b/src/kinsol/fcmix/Makefile.in
new file mode 100644
index 0000000..6330fc8
--- /dev/null
+++ b/src/kinsol/fcmix/Makefile.in
@@ -0,0 +1,119 @@
+# -----------------------------------------------------------------
+# $Revision: 1.9 $
+# $Date: 2009/03/25 23:10:50 $
+# -----------------------------------------------------------------
+# Programmer(s): Radu Serban and Aaron Collier @ LLNL
+# -----------------------------------------------------------------
+# Copyright (c) 2002, The Regents of the University of California.
+# Produced at the Lawrence Livermore National Laboratory.
+# All rights reserved.
+# For details, see the LICENSE file.
+# -----------------------------------------------------------------
+# Makefile for FKINSOL module
+#
+# @configure_input@
+# -----------------------------------------------------------------
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+builddir = @builddir@
+abs_builddir = @abs_builddir@
+top_builddir = @top_builddir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+includedir = @includedir@
+libdir = @libdir@
+
+INSTALL = @INSTALL@
+INSTALL_LIB = @INSTALL_PROGRAM@
+INSTALL_HEADER = @INSTALL_DATA@
+
+LIBTOOL = @LIBTOOL@
+LIBTOOL_DEPS = @LIBTOOL_DEPS@
+
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CC = @CC@
+CFLAGS = @CFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+
+LAPACK_ENABLED = @LAPACK_ENABLED@
+
+top_srcdir = $(srcdir)/../../..
+
+INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/src/kinsol -I$(top_builddir)/include
+
+LIB_REVISION = 0:1:0
+
+FKINSOL_LIB = libsundials_fkinsol.la
+
+FKINSOL_SRC_FILES = fkinsol.c fkindense.c fkinband.c fkinpreco.c fkinjtimes.c fkinbbd.c
+FKINSOL_BL_SRC_FILES = fkinlapack.c fkinlapdense.c fkinlapband.c
+
+FKINSOL_OBJ_FILES = $(FKINSOL_SRC_FILES:.c=.o)
+FKINSOL_BL_OBJ_FILES = $(FKINSOL_BL_SRC_FILES:.c=.o)
+
+FKINSOL_LIB_FILES = $(FKINSOL_SRC_FILES:.c=.lo)
+FKINSOL_BL_LIB_FILES = $(FKINSOL_BL_SRC_FILES:.c=.lo)
+
+mkinstalldirs = $(SHELL) $(top_srcdir)/config/mkinstalldirs
+
+# ----------------------------------------------------------------------------------------------------------------------
+
+all: $(FKINSOL_LIB)
+
+$(FKINSOL_LIB): $(FKINSOL_LIB_FILES)
+ @if test "X${LAPACK_ENABLED}" = "Xyes"; then \
+ make lib_with_bl; \
+ else \
+ make lib_without_bl; \
+ fi
+
+lib_without_bl: $(FKINSOL_LIB_FILES)
+ $(LIBTOOL) --mode=link $(CC) $(CFLAGS) -o $(FKINSOL_LIB) $(FKINSOL_LIB_FILES) -rpath $(libdir) $(LDFLAGS) $(LIBS) -static -version-info $(LIB_REVISION)
+
+lib_with_bl: $(FKINSOL_LIB_FILES) $(FKINSOL_BL_LIB_FILES)
+ $(LIBTOOL) --mode=link $(CC) $(CFLAGS) -o $(FKINSOL_LIB) $(FKINSOL_LIB_FILES) $(FKINSOL_BL_LIB_FILES) -rpath $(libdir) $(LDFLAGS) $(LIBS) -static -version-info $(LIB_REVISION)
+
+install: $(FKINSOL_LIB)
+ $(mkinstalldirs) $(libdir)
+ $(LIBTOOL) --mode=install $(INSTALL_LIB) $(FKINSOL_LIB) $(libdir)
+
+uninstall:
+ $(LIBTOOL) --mode=uninstall rm -f $(libdir)/$(FKINSOL_LIB)
+
+clean:
+ $(LIBTOOL) --mode=clean rm -f $(FKINSOL_LIB)
+ rm -f $(FKINSOL_LIB_FILES)
+ rm -f $(FKINSOL_BL_LIB_FILES)
+ rm -f $(FKINSOL_OBJ_FILES)
+ rm -f $(FKINSOL_BL_OBJ_FILES)
+
+distclean: clean
+ rm -f Makefile
+
+fkinsol.lo: $(srcdir)/fkinsol.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/fkinsol.c
+fkinpreco.lo: $(srcdir)/fkinpreco.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/fkinpreco.c
+fkinjtimes.lo: $(srcdir)/fkinjtimes.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/fkinjtimes.c
+fkinbbd.lo: $(srcdir)/fkinbbd.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/fkinbbd.c
+fkindense.lo: $(srcdir)/fkindense.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/fkindense.c
+fkinband.lo: $(srcdir)/fkinband.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/fkinband.c
+fkinlapack.lo: $(srcdir)/fkinlapack.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/fkinlapack.c
+fkinlapdense.lo: $(srcdir)/fkinlapdense.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/fkinlapdense.c
+fkinlapband.lo: $(srcdir)/fkinlapband.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/fkinlapband.c
+
+libtool: $(top_builddir)/$(LIBTOOL_DEPS)
+ @cd ${top_builddir} ; \
+ ${SHELL} ./config.status --recheck ; \
+ cd ${abs_builddir}
diff --git a/src/kinsol/fcmix/fkinband.c b/src/kinsol/fcmix/fkinband.c
new file mode 100644
index 0000000..b87ee37
--- /dev/null
+++ b/src/kinsol/fcmix/fkinband.c
@@ -0,0 +1,111 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.7 $
+ * $Date: 2010/12/01 22:45:33 $
+ * -----------------------------------------------------------------
+ * Programmer(s): 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.
+ * -----------------------------------------------------------------
+ * 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_band.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_BANDSETJAC
+ * ----------------------------------------------------------------
+ */
+
+void FKIN_BANDSETJAC(int *flag, int *ier)
+{
+ if (*flag == 0) {
+ *ier = KINDlsSetBandJacFn(KIN_kinmem, NULL);
+ }
+ else {
+ *ier = KINDlsSetBandJacFn(KIN_kinmem, FKINBandJac);
+ }
+
+ return;
+}
+
+/*
+ * ----------------------------------------------------------------
+ * Function : FKINBandJac
+ * ----------------------------------------------------------------
+ * C function FKINBandJac interfaces between KINSOL and a Fortran
+ * subroutine FKBJAC for solution of a linear system with band
+ * Jacobian approximation. Addresses are passed to FKBJAC for
+ * the banded Jacobian and vector data.
+ * Auxiliary data is assumed to be communicated by common blocks.
+ * ----------------------------------------------------------------
+ */
+
+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)
+{
+ 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/fkinbbd.c b/src/kinsol/fcmix/fkinbbd.c
new file mode 100644
index 0000000..a220d0a
--- /dev/null
+++ b/src/kinsol/fcmix/fkinbbd.c
@@ -0,0 +1,138 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.5 $
+ * $Date: 2010/12/01 22:45:33 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Allan Taylor, Alan Hindmarsh, Radu Serban, and
+ * Aaron Collier @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * This module contains the routines necessary to interface with
+ * the KINBBDPRE module and user-supplied Fortran routines. Generic
+ * 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>
+
+#include "fkinsol.h" /* standard interfaces and global variables */
+#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 */
+
+/*
+ * ----------------------------------------------------------------
+ * private constants
+ * ----------------------------------------------------------------
+ */
+
+#define ZERO RCONST(0.0)
+
+/*
+ * ----------------------------------------------------------------
+ * prototypes of the user-supplied fortran routines
+ * ----------------------------------------------------------------
+ */
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+extern void FK_LOCFN(long int*, realtype*, realtype*, int*);
+extern void FK_COMMFN(long int*, realtype*, int*);
+
+#ifdef __cplusplus
+}
+#endif
+
+/*
+ * ----------------------------------------------------------------
+ * Function : FKIN_BBDINIT
+ * ----------------------------------------------------------------
+ */
+
+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);
+
+ return;
+}
+
+/*
+ * ----------------------------------------------------------------
+ * Function : FKINgloc
+ * ----------------------------------------------------------------
+ * C function FKINgloc is the interface between the KINBBDPRE
+ * module and the Fortran subroutine FK_LOCFN.
+ * ----------------------------------------------------------------
+ */
+
+int FKINgloc(long int Nloc, N_Vector uu, N_Vector gval, void *user_data)
+{
+ realtype *uloc, *gloc;
+ int ier;
+
+ uloc = gloc = NULL;
+
+ uloc = N_VGetArrayPointer(uu);
+ gloc = N_VGetArrayPointer(gval);
+
+ FK_LOCFN(&Nloc, uloc, gloc, &ier);
+
+ N_VSetArrayPointer(gloc, gval);
+
+ return(0);
+}
+
+/*
+ * ----------------------------------------------------------------
+ * Function : FKINgcomm
+ * ----------------------------------------------------------------
+ * C function FKINgcomm is the interface between the KINBBDPRE
+ * module and the Fortran subroutine FK_COMMFN.
+ * ----------------------------------------------------------------
+ */
+
+int FKINgcomm(long int Nloc, N_Vector uu, void *user_data)
+{
+ realtype *uloc;
+ int ier;
+
+ uloc = NULL;
+
+ uloc = N_VGetArrayPointer(uu);
+
+ FK_COMMFN(&Nloc, uloc, &ier);
+
+ return(0);
+}
+
+/*
+ * ----------------------------------------------------------------
+ * Function : FKIN_BBDOPT
+ * ----------------------------------------------------------------
+ * C function FKIN_BBDOPT is used to access optional outputs
+ * realated to the BBD preconditioner.
+ * ----------------------------------------------------------------
+ */
+
+void FKIN_BBDOPT(long int *lenrpw, long int *lenipw, long int *nge)
+{
+ KINBBDPrecGetWorkSpace(KIN_kinmem, lenrpw, lenipw);
+ KINBBDPrecGetNumGfnEvals(KIN_kinmem, nge);
+
+ return;
+}
+
diff --git a/src/kinsol/fcmix/fkinbbd.h b/src/kinsol/fcmix/fkinbbd.h
new file mode 100644
index 0000000..a55f871
--- /dev/null
+++ b/src/kinsol/fcmix/fkinbbd.h
@@ -0,0 +1,303 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.8 $
+ * $Date: 2010/12/15 19:40:08 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Allan Taylor, Alan Hindmarsh, Radu Serban, and
+ * Aaron Collier @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * 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), 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.
+
+ 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
+ FKINBBDOPT : accesses optional outputs
+ FKINBBDFREE : interfaces to KINBBDPrecFree
+
+ In addition to the Fortran system function FKFUN, and optional Jacobian vector
+ product routine FKJTIMES, the following are the user-supplied functions
+ 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
+
+ Note: The names of all user-supplied routines here are fixed, in order to
+ maximize portability for the resulting mixed-language program.
+
+ Note: The names used within this interface package make use of the preprocessor
+ to expand them appropriately for different machines/platforms. Later in this
+ file, each name is expanded appropriately. For example, FKIN_BBDINIT is
+ replaced with either fkinbbdinit, fkinbbdinit_, or fkinbbdinit__ depending
+ upon the platform.
+
+ ==============================================================================
+
+ Usage of the FKINSOL/FKINBBD Interface Packages
+
+ The usage of combined interface packages FKINSOL and FKINBBD requires calls
+ to several interface functions, and a few 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 have been omitted, and the user is referred to the KINSOL User
+ Guide for more complete information.
+
+ (1) User-supplied system function routine: FKFUN
+
+ The user must in all cases supply the following Fortran routine:
+
+ SUBROUTINE FKFUN (UU, FVAL, IER)
+ DIMENSION UU(*), FVAL(*)
+
+ It must set the FVAL array to f(u), the system function, as a function
+ of the array UU = u. Here UU and FVAL are vectors (distributed in the
+ parallel case). IER is a return flag (currently not used).
+
+ (2) Optional user-supplied Jacobian-vector product routine: FKJTIMES
+
+ As an option, the user may supply a routine that computes the product
+ of the system Jacobian and a given vector. The user-supplied function
+ must have the following form:
+
+ SUBROUTINE FKJTIMES (V, Z, NEWU, UU, IER)
+ DIMENSION V(*), Z(*), UU(*)
+
+ This must set the array Z to the product J*V, where J is the Jacobian
+ matrix J = dF/du, and V is a given array. Here UU is an array containing
+ the current value of the unknown vector u, and NEWU is an input integer
+ indicating whether UU has changed since FKJTIMES was last called
+ (1 = yes, 0 = no). If FKJTIMES computes and saves Jacobian data, then
+ no such computation is necessary when NEWU = 0. Here V, Z, and UU are
+ arrays of length NLOC - the local length of all distributed vectors.
+ FKJTIMES should return IER = 0 if successful, or a nonzero IER otherwise.
+
+ (3) User-supplied routines to define preconditoner: FKLOCFN and FKCOMMFN
+
+ The routines in the KINBBDPRE (kinbbdpre.c) module provide a preconditioner
+ matrix for KINSOL that is block-diagonal with banded blocks. The blocking
+ corresponds to the distribution of the dependent variable vector u
+ amongst the processes. Each preconditioner block is generated from the
+ Jacobian of the local part (associated with the current process) of a given
+ function g(u) approximating f(u). The blocks are generated by a difference
+ quotient scheme (independently by each process), utilizing the assumed
+ banded structure with given half-bandwidths.
+
+ (3.1) Local approximate function: FKLOCFN
+
+ The user must supply a subroutine of the following form:
+
+ SUBROUTINE FKLOCFN (NLOC, ULOC, GLOC, IER)
+ DIMENSION ULOC(*), GLOC(*)
+
+ The routine is used to compute the function g(u) which approximates the
+ system function f(u). This function is to be computed locally, i.e.
+ without inter-process communication. Note: The case where g is
+ mathematically identical to f is allowed. It takes as input the local
+ vector length (NLOC) and the local real solution array ULOC. It is to
+ compute the local part of g(u) and store the result in the realtype
+ array GLOC. IER is a return flag (currently not used).
+
+ (3.2) Communication function: FKCOMMFN
+
+ The user must also supply a subroutine of the following form:
+
+ SUBROUTINE FKCOMMFN (NLOC, ULOC, IER)
+ DIMENSION ULOC(*)
+
+ The routine is used to perform all inter-process communication necessary
+ to evaluate the approximate system function g described above. This
+ function takes as input the local vector length (NLOC), and the local real
+ dependent variable array ULOC. It is expected to save communicated data in
+ work space defined by the user, and made available to FKLOCFN. Each call
+ to the FKCOMMFN function is preceded by a call to FKFUN with the same
+ arguments. Thus FKCOMMFN can omit any communications done by FKFUN if
+ relevant to the evaluation of g. IER is a return flag (currently not
+ used).
+
+ (4) Initialization: FNVINITP, FKINMALLOC, FKINBBDINIT, and FKINBBDSP*
+
+ (4.1) To initialize the parallel machine environment, the user must make the
+ following call:
+
+ CALL FNVINITP (5, NLOCAL, NGLOBAL, IER)
+
+ The arguments are:
+ NLOCAL = local size of vectors associated with process
+ 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, and
+ -1 = failure.
+
+ (4.2) To allocate internal memory for KINSOL, make the following call:
+
+ CALL FKINMALLOC (MSBPRE, FNORMTOL, SCSTEPTOL, CONSTRAINTS,
+ OPTIN, IOPT, ROPT, IER)
+
+ The arguments are:
+ MSBPRE = maximum number of preconditioning solve calls without
+ calling the preconditioning setup routine
+ Note: 0 indicates default (10).
+ FNORMTOL = tolerance on the norm of f(u) to accept convergence
+ SCSTEPTOL = tolerance on minimum scaled step size
+ CONSTRAINTS = array of constraint values on components of the
+ solution vector UU
+ INOPT = integer used as a flag to indicate whether possible
+ 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)
+ 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 3 SPILS linear solvers. Make one of the
+ following calls (see fkinsol.h) for more details.
+ CALL FKINSPGMR (MAXL, MAXLRST, IER)
+ CALL FKINSPBCG (MAXL, IER)
+ CALL FKINSPTFQMR (MAXL, IER)
+
+ (4.4) To allocate memory and initialize data associated with the BBD
+ preconditioner, make the following call:
+
+ CALL FKINBBDINIT (NLOCAL, MU, ML, IER)
+
+ 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.
+
+ (5) To solve the system, make the following call:
+
+ CALL FKINSOL (UU, GLOBALSTRAT, USCALE, FSCALE, IER)
+
+ The arguments are:
+ UU = array containing the initial guess when called and the
+ solution upon termination
+ GLOBALSTRAT = (INTEGER) a number defining the global strategy choice:
+ 1 = inexact Newton, 2 = line search.
+ USCALE = array of scaling factors for the UU vector
+ FSCALE = array of scaling factors for the FVAL (function) vector
+ IER = integer error flag as returned by KINSOL.
+
+ Note: See the KINSOL documentation for further information.
+
+ (6) Optional outputs: FKINBBDOPT
+
+ In addition to the optional inputs and outputs available with the FKINSOL
+ interface package, there are optional outputs specific to the KINBBDPRE
+ module. These are accessed by making the following call:
+
+ CALL FKINBBDOPT (LENRPW, LENIPW, NGE)
+
+ The arguments returned are:
+ LENRPW = length of real preconditioner work space, in realtype words
+ Note: This size is local to the current process.
+ LENIPW = length of integer preconditioner work space, in integer words
+ Note: This size is local to the current process.
+ NGE = number of g(u) evaluations (calls to FKLOCFN)
+
+ (7) Memory freeing: FKINFREE
+
+ To the free the internal memory created by the calls to FNVINITP
+ and FKINMALLOC, make the following call:
+
+ CALL FKINFREE
+
+*******************************************************************************/
+
+#ifndef _FKINBBD_H
+#define _FKINBBD_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+/*
+ * -----------------------------------------------------------------
+ * header files
+ * -----------------------------------------------------------------
+ */
+
+#include <sundials/sundials_nvector.h> /* definition of type N_Vector */
+#include <sundials/sundials_types.h> /* definition of type realtype */
+
+/*
+ * -----------------------------------------------------------------
+ * generic names are translated through the define statements below
+ * -----------------------------------------------------------------
+ */
+
+#if defined(SUNDIALS_F77_FUNC)
+
+#define FKIN_BBDINIT SUNDIALS_F77_FUNC(fkinbbdinit, FKINBBDINIT)
+#define FKIN_BBDOPT SUNDIALS_F77_FUNC(fkinbbdopt, FKINBBDOPT)
+#define FK_COMMFN SUNDIALS_F77_FUNC(fkcommfn, FKCOMMFN)
+#define FK_LOCFN SUNDIALS_F77_FUNC(fklocfn, FKLOCFN)
+
+#else
+
+#define FKIN_BBDINIT fkinbbdinit_
+#define FKIN_BBDOPT fkinbbdopt_
+#define FK_COMMFN fkcommfn_
+#define FK_LOCFN fklocfn_
+
+#endif
+
+/*
+ * -----------------------------------------------------------------
+ * Prototypes: exported functions
+ * -----------------------------------------------------------------
+ */
+
+void FKIN_BBDINIT(long int *nlocal, long int *mudq, long int *mldq,
+ long int *mu, long int *ml, int *ier);
+void FKIN_BBDOPT(long int *lenrpw, long int *lenipw, long int *nge);
+
+/*
+ * -----------------------------------------------------------------
+ * Prototypes: FKINgloc and FKINgcomm
+ * -----------------------------------------------------------------
+ */
+
+int FKINgloc(long int Nloc, N_Vector uu, N_Vector gval, void *user_data);
+int FKINgcomm(long int Nloc, N_Vector uu, void *user_data);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/kinsol/fcmix/fkindense.c b/src/kinsol/fcmix/fkindense.c
new file mode 100644
index 0000000..408f00a
--- /dev/null
+++ b/src/kinsol/fcmix/fkindense.c
@@ -0,0 +1,100 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.7 $
+ * $Date: 2010/12/01 22:45:33 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Aaron Collier @ 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.
+ * -----------------------------------------------------------------
+ * Fortran/C interface routines for KINSOL/KINDENSE, 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_dense.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_DENSESETJAC
+ * ----------------------------------------------------------------
+ */
+
+void FKIN_DENSESETJAC(int *flag, int *ier)
+{
+ if (*flag == 0) {
+ *ier = KINDlsSetDenseJacFn(KIN_kinmem, NULL);
+ }
+ else {
+ *ier = KINDlsSetDenseJacFn(KIN_kinmem, FKINDenseJac);
+ }
+ return;
+}
+
+/*
+ * ----------------------------------------------------------------
+ * Function : FKINDenseJac
+ * ----------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------
+ */
+
+int FKINDenseJac(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/fkinjtimes.c b/src/kinsol/fcmix/fkinjtimes.c
new file mode 100644
index 0000000..6cdb992
--- /dev/null
+++ b/src/kinsol/fcmix/fkinjtimes.c
@@ -0,0 +1,82 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.3 $
+ * $Date: 2007/04/30 19:29:01 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Allan Taylor, Alan Hindmarsh and
+ * Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * Routines used to interface between KINSOL and a Fortran
+ * user-supplied routine FKJTIMES (Jacobian J times vector v).
+ * -----------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "fkinsol.h"
+#include "kinsol_impl.h"
+
+#include <kinsol/kinsol_spils.h>
+
+/*
+ * ----------------------------------------------------------------
+ * 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*);
+
+#ifdef __cplusplus
+}
+#endif
+
+/*
+ * ----------------------------------------------------------------
+ * Function : FKIN_SPILSSETJAC
+ * ----------------------------------------------------------------
+ */
+
+void FKIN_SPILSSETJAC(int *flag, int *ier)
+{
+ if ((*flag) == 0) KINSpilsSetJacTimesVecFn(KIN_kinmem, NULL);
+ else KINSpilsSetJacTimesVecFn(KIN_kinmem, FKINJtimes);
+
+ return;
+}
+
+/*
+ * ----------------------------------------------------------------
+ * 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)
+{
+ int retcode;
+ realtype *vdata, *Jvdata, *uudata;
+
+ vdata = Jvdata = uudata = NULL;
+
+ vdata = N_VGetArrayPointer(v);
+ uudata = N_VGetArrayPointer(uu);
+ Jvdata = N_VGetArrayPointer(Jv);
+
+ FK_JTIMES(vdata, Jvdata, (int *) new_uu, uudata, &retcode);
+
+ return(retcode);
+}
diff --git a/src/kinsol/fcmix/fkinlapack.c b/src/kinsol/fcmix/fkinlapack.c
new file mode 100644
index 0000000..7c24f14
--- /dev/null
+++ b/src/kinsol/fcmix/fkinlapack.c
@@ -0,0 +1,42 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.1 $
+ * $Date: 2006/11/22 00:12:51 $
+ * -----------------------------------------------------------------
+ * Programmer: Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * 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
new file mode 100644
index 0000000..2948627
--- /dev/null
+++ b/src/kinsol/fcmix/fkinlapband.c
@@ -0,0 +1,112 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.6 $
+ * $Date: 2010/12/01 22:45:33 $
+ * -----------------------------------------------------------------
+ * Programmer: 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.
+ * -----------------------------------------------------------------
+ * 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
new file mode 100644
index 0000000..37ce649
--- /dev/null
+++ b/src/kinsol/fcmix/fkinlapdense.c
@@ -0,0 +1,100 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.6 $
+ * $Date: 2010/12/01 22:45:33 $
+ * -----------------------------------------------------------------
+ * Programmer: 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.
+ * -----------------------------------------------------------------
+ * 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
new file mode 100644
index 0000000..abc6184
--- /dev/null
+++ b/src/kinsol/fcmix/fkinpreco.c
@@ -0,0 +1,134 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.3 $
+ * $Date: 2007/04/30 19:29:01 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Allan Taylor, Alan Hindmarsh and
+ * Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * This file contains the interfaces between KINSOL and the
+ * user-supplied Fortran routines FK_PSET and FK_PSOL.
+ *
+ * The C function FKINPSet is used to interface between KINSOL and
+ * the Fortran user-supplied preconditioner setup routine.
+ *
+ * The C function FKINPSol is used to interface between KINSOL and
+ * 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>
+
+#include "fkinsol.h"
+#include "kinsol_impl.h"
+
+#include <kinsol/kinsol_spils.h>
+
+/*
+ * ----------------------------------------------------------------
+ * 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*);
+
+#ifdef __cplusplus
+}
+#endif
+
+/*
+ * ----------------------------------------------------------------
+ * Function : FKIN_SPILSSETPREC
+ * ----------------------------------------------------------------
+ */
+
+void FKIN_SPILSSETPREC(int *flag, int *ier)
+{
+ if ((*flag) == 0) {
+ *ier = KINSpilsSetPreconditioner(KIN_kinmem, NULL, NULL);
+ } else {
+ *ier = KINSpilsSetPreconditioner(KIN_kinmem, FKINPSet, FKINPSol);
+ }
+
+ return;
+}
+
+/*
+ * ----------------------------------------------------------------
+ * 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)
+{
+ realtype *udata, *uscaledata, *fdata, *fscaledata, *vtemp1data, *vtemp2data;
+ int retcode;
+
+ udata = uscaledata = fdata = fscaledata = vtemp1data = vtemp2data = NULL;
+
+ 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 */
+
+ return(retcode);
+}
+
+/*
+ * ----------------------------------------------------------------
+ * 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)
+{
+ realtype *udata, *uscaledata, *fdata, *fscaledata, *vvdata, *ftemdata;
+ int retcode;
+
+ udata = uscaledata = fdata = fscaledata = vvdata = ftemdata = NULL;
+
+ 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);
+
+ return(retcode);
+}
diff --git a/src/kinsol/fcmix/fkinsol.c b/src/kinsol/fcmix/fkinsol.c
new file mode 100644
index 0000000..933fa08
--- /dev/null
+++ b/src/kinsol/fcmix/fkinsol.c
@@ -0,0 +1,395 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.5 $
+ * $Date: 2010/12/01 22:45:33 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Allan Taylor, Alan Hindmarsh, Radu Serban, and
+ * Aaron Collier @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * This is the implementation file for the Fortran interface to
+ * the KINSOL package. See fkinsol.h for usage.
+ *
+ * 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 <kinsol/kinsol_band.h> /* prototypes of KINBAND interface routines */
+#include <kinsol/kinsol_dense.h> /* prototypes of KINDENSE 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 */
+
+/*
+ * ----------------------------------------------------------------
+ * definitions of global variables shared amongst various routines
+ * ----------------------------------------------------------------
+ */
+
+void *KIN_kinmem;
+long int *KIN_iout;
+realtype *KIN_rout;
+int KIN_ls;
+
+/*
+ * ----------------------------------------------------------------
+ * private constants
+ * ----------------------------------------------------------------
+ */
+
+#define ZERO RCONST(0.0)
+
+/*
+ * ----------------------------------------------------------------
+ * prototype of user-supplied fortran routine
+ * ----------------------------------------------------------------
+ */
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+extern void FK_FUN(realtype*, realtype*, int*);
+
+#ifdef __cplusplus
+}
+#endif
+
+/*
+ * ----------------------------------------------------------------
+ * Function : FKIN_MALLOC
+ * ----------------------------------------------------------------
+ */
+
+void FKIN_MALLOC(long int *iout, realtype *rout, int *ier)
+{
+
+ /* check for required vector operations */
+ 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");
+ return;
+ }
+
+ /* Initialize pointers to NULL */
+ KIN_kinmem = NULL;
+
+ /* Create KINSOL object */
+ KIN_kinmem = KINCreate();
+ if (KIN_kinmem == NULL) {
+ *ier = -1;
+ return;
+ }
+
+ /* Call KINInit */
+ *ier = 0;
+ *ier = KINInit(KIN_kinmem, FKINfunc, F2C_KINSOL_vec);
+
+ /* On failure, exit */
+ if (*ier != KIN_SUCCESS) {
+ *ier = -1;
+ return;
+ }
+
+ /* Grab optional output arrays and store them in global variables */
+ KIN_iout = iout;
+ KIN_rout = rout;
+
+ return;
+}
+
+/*
+ * ----------------------------------------------------------------
+ * Function : FKIN_SETIIN
+ * ----------------------------------------------------------------
+ */
+
+void FKIN_SETIIN(char key_name[], long int *ival, int *ier, int key_len)
+{
+ if (!strncmp(key_name,"PRNT_LEVEL", (size_t)key_len))
+ *ier = KINSetPrintLevel(KIN_kinmem, (int) *ival);
+ else if (!strncmp(key_name,"MAX_NITERS", (size_t)key_len))
+ *ier = KINSetNumMaxIters(KIN_kinmem, (int) *ival);
+ else if (!strncmp(key_name,"ETA_FORM", (size_t)key_len))
+ *ier = KINSetEtaForm(KIN_kinmem, (int) *ival);
+ else if (!strncmp(key_name,"MAX_SETUPS", (size_t)key_len))
+ *ier = KINSetMaxSetupCalls(KIN_kinmem, (int) *ival);
+ else if (!strncmp(key_name,"MAX_SP_SETUPS", (size_t)key_len))
+ *ier = KINSetMaxSubSetupCalls(KIN_kinmem, (int) *ival);
+ else if (!strncmp(key_name,"NO_INIT_SETUP", (size_t)key_len))
+ *ier = KINSetNoInitSetup(KIN_kinmem, (int) *ival);
+ else if (!strncmp(key_name,"NO_MIN_EPS", (size_t)key_len))
+ *ier = KINSetNoMinEps(KIN_kinmem, (int) *ival);
+ else if (!strncmp(key_name,"NO_RES_MON", (size_t)key_len))
+ *ier = KINSetNoResMon(KIN_kinmem, (int) *ival);
+ else {
+ *ier = -99;
+ printf("FKINSETIIN: Unrecognized key.\n\n");
+ }
+
+}
+
+/*
+ * ----------------------------------------------------------------
+ * Function : FKIN_SETRIN
+ * ----------------------------------------------------------------
+ */
+
+void FKIN_SETRIN(char key_name[], realtype *rval, int *ier, int key_len)
+{
+
+ if (!strncmp(key_name,"FNORM_TOL", (size_t)key_len))
+ *ier = KINSetFuncNormTol(KIN_kinmem, *rval);
+ else if (!strncmp(key_name,"SSTEP_TOL", (size_t)key_len))
+ *ier = KINSetScaledStepTol(KIN_kinmem, *rval);
+ else if (!strncmp(key_name,"MAX_STEP", (size_t)key_len))
+ *ier = KINSetMaxNewtonStep(KIN_kinmem, *rval);
+ else if (!strncmp(key_name,"RERR_FUNC", (size_t)key_len))
+ *ier = KINSetRelErrFunc(KIN_kinmem, *rval);
+ else if (!strncmp(key_name,"ETA_CONST", (size_t)key_len))
+ *ier = KINSetEtaConstValue(KIN_kinmem, *rval);
+ else if (!strncmp(key_name,"ETA_PARAMS", (size_t)key_len))
+ *ier = KINSetEtaParams(KIN_kinmem, rval[0], rval[1]);
+ else if (!strncmp(key_name,"RMON_CONST", (size_t)key_len))
+ *ier = KINSetResMonConstValue(KIN_kinmem, *rval);
+ else if (!strncmp(key_name,"RMON_PARAMS", (size_t)key_len))
+ *ier = KINSetResMonParams(KIN_kinmem, rval[0], rval[1]);
+ else {
+ *ier = -99;
+ printf("FKINSETRIN: Unrecognized key.\n\n");
+ }
+
+}
+
+/*
+ * ----------------------------------------------------------------
+ * Function : FKIN_SETVIN
+ * ----------------------------------------------------------------
+ */
+
+void FKIN_SETVIN(char key_name[], realtype *vval, int *ier, int key_len)
+{
+ N_Vector Vec;
+
+ if (!strncmp(key_name,"CONSTR_VEC", (size_t)key_len)) {
+ Vec = NULL;
+ Vec = N_VCloneEmpty(F2C_KINSOL_vec);
+ if (Vec == NULL) {
+ *ier = -1;
+ return;
+ }
+ N_VSetArrayPointer(vval, Vec);
+ KINSetConstraints(KIN_kinmem, Vec);
+ N_VDestroy(Vec);
+ } else {
+ *ier = -99;
+ printf("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
+ * ----------------------------------------------------------------
+ */
+
+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;
+}
+
+/*
+ * ----------------------------------------------------------------
+ * Function : FKIN_SOL
+ * ----------------------------------------------------------------
+ */
+
+void FKIN_SOL(realtype *uu, int *globalstrategy,
+ realtype *uscale , realtype *fscale, int *ier)
+
+{
+ int lsflag;
+ N_Vector uuvec, uscalevec, fscalevec;
+
+ *ier = 0;
+ uuvec = uscalevec = fscalevec = NULL;
+
+ uuvec = F2C_KINSOL_vec;
+ N_VSetArrayPointer(uu, uuvec);
+
+ uscalevec = NULL;
+ uscalevec = N_VCloneEmpty(F2C_KINSOL_vec);
+ if (uscalevec == NULL) {
+ *ier = -4; /* KIN_MEM_FAIL */
+ return;
+ }
+ N_VSetArrayPointer(uscale, uscalevec);
+
+ fscalevec = NULL;
+ fscalevec = N_VCloneEmpty(F2C_KINSOL_vec);
+ if (fscalevec == NULL) {
+ N_VDestroy(uscalevec);
+ *ier = -4; /* KIN_MEM_FAIL */
+ return;
+ }
+ N_VSetArrayPointer(fscale, fscalevec);
+
+ /* Call main solver function */
+ *ier = KINSol(KIN_kinmem, uuvec, *globalstrategy, uscalevec, fscalevec);
+
+ N_VSetArrayPointer(NULL, uuvec);
+
+ N_VSetArrayPointer(NULL, uscalevec);
+ N_VDestroy(uscalevec);
+
+ N_VSetArrayPointer(NULL, fscalevec);
+ N_VDestroy(fscalevec);
+
+ /* load optional outputs into iout[] and rout[] */
+ KINGetWorkSpace(KIN_kinmem, &KIN_iout[0], &KIN_iout[1]); /* LENRW & LENIW */
+ KINGetNumNonlinSolvIters(KIN_kinmem, &KIN_iout[2]); /* NNI */
+ KINGetNumFuncEvals(KIN_kinmem, &KIN_iout[3]); /* NFE */
+ KINGetNumBetaCondFails(KIN_kinmem, &KIN_iout[4]); /* NBCF */
+ KINGetNumBacktrackOps(KIN_kinmem, &KIN_iout[5]); /* NBCKTRK */
+
+ KINGetFuncNorm(KIN_kinmem, &KIN_rout[0]); /* FNORM */
+ KINGetStepLength(KIN_kinmem, &KIN_rout[1]); /* SSTEP */
+
+ switch(KIN_ls) {
+
+ case KIN_LS_DENSE:
+ case KIN_LS_BAND:
+ case KIN_LS_LAPACKDENSE:
+ case KIN_LS_LAPACKBAND:
+ 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_SPTFQMR:
+ case KIN_LS_SPBCG:
+ case KIN_LS_SPGMR:
+ 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 */
+ KINSpilsGetNumJtimesEvals(KIN_kinmem, &KIN_iout[10]); /* NJE */
+ KINSpilsGetNumPrecEvals(KIN_kinmem, &KIN_iout[11]); /* NPE */
+ KINSpilsGetNumPrecSolves(KIN_kinmem, &KIN_iout[12]); /* NPS */
+ KINSpilsGetNumLinIters(KIN_kinmem, &KIN_iout[13]); /* NLI */
+ KINSpilsGetNumConvFails(KIN_kinmem, &KIN_iout[14]); /* NCFL */
+ break;
+
+ }
+
+ return;
+}
+
+/*
+ * ----------------------------------------------------------------
+ * Function : FKIN_FREE
+ * ----------------------------------------------------------------
+ */
+
+void FKIN_FREE(void)
+{
+
+ /* call KINFree: KIN_kinmem is the pointer to the KINSOL memory block */
+
+ KINFree(&KIN_kinmem);
+
+ N_VSetArrayPointer(NULL , F2C_KINSOL_vec);
+ N_VDestroy(F2C_KINSOL_vec);
+
+ 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'.
+ * ----------------------------------------------------------------
+ */
+
+int FKINfunc(N_Vector uu, N_Vector fval, void *user_data)
+{
+ realtype *udata, *fdata;
+ int ier;
+
+ udata = N_VGetArrayPointer(uu);
+ fdata = N_VGetArrayPointer(fval);
+
+ FK_FUN(udata, fdata, &ier);
+
+ return(0);
+}
diff --git a/src/kinsol/fcmix/fkinsol.h b/src/kinsol/fcmix/fkinsol.h
new file mode 100644
index 0000000..609acf9
--- /dev/null
+++ b/src/kinsol/fcmix/fkinsol.h
@@ -0,0 +1,586 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.8 $
+ * $Date: 2010/12/01 22:45:33 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Allan Taylor, Alan Hindmarsh, Radu Serban, and
+ * Aaron Collier @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * This is the header file for the FKINSOL Interface Package.
+ * See below for usage details.
+ * -----------------------------------------------------------------
+ */
+
+/***************************************************************************
+
+ FKINSOL Interface Package
+
+ The FKINSOL Interface Package is a package of C functions which support the
+ use of the KINSOL solver for the solution of nonlinear systems f(u) = 0,
+ in a mixed Fortran/C setting. While KINSOL 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 KINSOL for both the serial and the parallel NVECTOR
+ implementations.
+
+ The user-callable functions, with the corresponding KINSOL functions,
+ are as follows:
+
+ FNVINITS and FNVINITP initialize serial and parallel vector
+ computations, respectively
+ FKINMALLOC interfaces to KINInit
+ FKINSETIIN, FKINSETRIN, FKINSETVIN interface to KINSet* functions
+ FKINDENSE interfaces to KINDense
+ FKINSPTFQMR interfaces to KINSptfqmr
+ FKINSPGMR interfaces to KINSpgmr
+ FKINSPBCG interfaces to KINSpbcg
+ FKINSOL interfaces to KINSol and KINGet* functions
+ FKINFREE interfaces to KINFree
+
+ 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
+ FKBJAC : called by the interface function FKINBandJac of type
+ KINBandJacFn
+ FKJTIMES : called by the interface function FKINJtimes of type
+ KINSpilsJacTimesVecFn
+ FKPSOL : called by the interface function FKINPSol of type
+ KINSpilsPrecSolveFn
+ FKPSET : called by the interface function FKINPSet of type
+ KINSpilsPrecSetupFn
+
+ In contrast to the case of direct use of KINSOL, the names of all
+ user-supplied routines here are fixed, in order to maximize portability for
+ the resulting mixed-language program.
+
+ =========================================================================
+
+ Usage of the FKINSOL Interface Package
+
+ The usage of FKINSOL requires calls to several interface functions, and
+ to a few 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 KINSOL manual
+ 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 KINSOL package.
+
+ The number labels on the instructions below end with "s" for instructions
+ that apply to the serial version of KINSOL only, and end with "p" for
+ those that apply to the parallel version only.
+
+ (1) User-supplied system routine: FKFUN
+
+ The user must in all cases supply the following Fortran routine:
+
+ SUBROUTINE FKFUN (UU, FVAL, IER)
+ DIMENSION UU(*), FVAL(*)
+
+ It must set the FVAL array to f(u), the system function, as a
+ function of the array UU = u. Here UU and FVAL are arrays representing
+ vectors, which are distributed vectors in the parallel case.
+ IER is a return flag (currently not used).
+
+ (2s) Optional user-supplied dense Jacobian approximation routine: FKDJAC
+
+ 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 FKDJAC(N, UU, FU, DJAC, WK1, WK2, IER)
+ DIMENSION UU(*), FU(*), DJAC(N,*), WK1(*), WK2(*)
+
+ This routine must compute the Jacobian and store it columnwise in DJAC.
+ FKDJAC should return IER = 0 if successful, or a nonzero IER otherwise.
+
+ (3s) Optional user-supplied band Jacobian approximation routine: FKBJAC
+
+ 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 FKBJAC(N, MU, ML, MDIM, UU, FU, BJAC, WK1, WK2, IER)
+ DIMENSION UU(*), FU(*), BJAC(MDIM,*), WK1(*), WK2(*)
+
+ This routine must load the MDIM by N array BJAC with the Jacobian matrix.
+ FKBJAC should return IER = 0 if successful, or a nonzero IER otherwise.
+
+ (4) Optional user-supplied Jacobian-vector product routine: FKJTIMES
+
+ As an option, the user may supply a routine that computes the product
+ of the system Jacobian and a given vector. This has the following form:
+
+ SUBROUTINE FKJTIMES(V, Z, NEWU, UU, IER)
+ DIMENSION V(*), Z(*), UU(*)
+
+ This must set the array Z to the product J*V, where J is the Jacobian
+ matrix J = dF/du, and V is a given array. Here UU is an array containing
+ the current value of the unknown vector u. NEWU is an input integer
+ indicating whether UU has changed since FKJTIMES was last called
+ (1 = yes, 0 = no). If FKJTIMES computes and saves Jacobian data, then
+ no such computation is necessary when NEWU = 0. Here V, Z, and UU are
+ arrays of length NEQ, the problem size, or the local length of all
+ distributed vectors in the parallel case. FKJTIMES should return IER = 0
+ if successful, or a nonzero IER otherwise.
+
+ (5) Initialization: FNVINITS/FNVINITP and FKINMALLOC
+
+ (5.1s) To initialize the serial machine environment, the user must make
+ the following call:
+
+ CALL FNVINITS (3, NEQ, IER)
+
+ The arguments are:
+ NEQ = size of vectors
+ IER = return completion flag. Values are 0 = success, -1 = failure.
+
+ (5.1p) To initialize the parallel machine environment, the user must make
+ the following call:
+
+ CALL FNVINITP (3, NLOCAL, NGLOBAL, IER)
+
+ The arguments are:
+ NLOCAL = local size of vectors for this process
+ 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.
+
+ (5.2) To allocate internal memory, make the following call:
+
+ CALL FKINMALLOC(IOUT, ROUT, IER)
+
+ 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)
+ ROUT = array of length at least 2 for real optional outputs
+ IER = return completion flag. Values are 0 = success, and
+ -1 = failure.
+
+ Note: See printed message for details in case of failure.
+
+ (5.3) To set various integer optional inputs, make the folowing call:
+
+ CALL FKINSETIIN(KEY, VALUE, IER)
+
+ to set the optional input specified by the character key KEY to the
+ integer value VALUE.
+ KEY is one of the following: PRNT_LEVEL, MAX_NITERS, ETA_FORM,
+ MAX_SETUPS, MAX_SP_SETUPS, NO_INIT_SETUP, NO_MIN_EPS, NO_RES_MON.
+
+ To set various real optional inputs, make the folowing call:
+
+ CALL FKINSETRIN(KEY, VALUE, IER)
+
+ to set the optional input specified by the character key KEY to the
+ real value VALUE.
+ KEY is one of the following: FNORM_TOL, SSTEP_TOL, MAX_STEP, RERR_FUNC,
+ ETA_CONST, ETA_PARAMS, RMON_CONST, RMON_PARAMS.
+ Note that if KEY is ETA_PARAMS or RMON_PARAMS, then VALUE must be an
+ array of dimension 2.
+
+ To set the vector of constraints on the solution, make the following call:
+
+ CALL FKINSETVIN(KEY, ARRAY, IER)
+
+ where ARRAY is an array of reals and KEY is 'CONSTR_VEC'.
+
+ FKINSETIIN, FKINSETRIN, and FKINSETVIN return IER=0 if successful and
+ IER<0 if an error occured.
+
+ (6) Specification of linear system solution method:
+
+ The solution method in KINSOL involves the solution of linear systems
+ related to the Jacobian J = dF/du of the nonlinear system.
+
+ (6.1s) DENSE treatment of the linear systems (NVECTOR_SERIAL only):
+
+ 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 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):
+
+ 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.3) SPTFQMR treatment of the linear systems:
+
+ For the Scaled Preconditioned TFQMR solution of the linear systems,
+ the user must make the call:
+
+ CALL FKINSPTFQMR(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.
+
+ Note: See printed message for details in case of failure.
+
+ (6.4) SPBCG treatment of the linear systems:
+
+ For the Scaled Preconditioned Bi-CGSTAB solution of the linear systems,
+ the user must make the call:
+
+ CALL FKINSPBCG(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.
+
+ Note: See printed message for details in case of failure.
+
+ (6.5) SPGMR treatment of the linear systems:
+
+ For the Scaled Preconditioned GMRES solution of the linear systems,
+ the user must make the call:
+
+ CALL FKINSPGMR(MAXL, MAXLRST, 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 only).
+ IER = return completion flag. Values are 0 = succes, and
+ -1 = failure.
+
+ Note: See printed message for details in case of failure.
+
+ (6.6) Specifying user-provided functions for the iterative linear solvers
+
+ If the user program includes the FKJTIMES routine for the evaluation
+ of the Jacobian-vector product, the following call must be made:
+
+ CALL FKINSPILSSETJAC(FLAG, IER)
+
+ The argument FLAG = 0 specifies using the internal finite differences
+ approximation to the Jacobian-vector product, while FLAG = 1 specifies
+ that FKJTIMES is provided.
+
+ Usage of the user-supplied routines FKPSET and FKPSOL for the setup and
+ solution of the preconditioned linear system is specified by calling:
+
+ CALL FKINSPILSSETPREC(FLAG, IER)
+
+ where FLAG = 0 indicates no FKPSET or FKPSOL (default) and FLAG = 1
+ 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(*)
+
+ 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.
+
+ 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(*)
+
+ Typically this routine will use only UU, FVAL, VTEM and FTEM.
+ 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
+ routine supplied must also account for scaling on either coordinate
+ or function value.
+
+ (7) The solver: FKINSOL
+
+ Solving the nonlinear system is accomplished by making the following
+ call:
+
+ CALL FKINSOL (UU, GLOBALSTRAT, USCALE, FSCALE, IER)
+
+ The arguments are:
+ UU = array containing the initial guess on input, and the
+ solution on return
+ GLOBALSTRAT = (INTEGER) a number defining the global strategy choice:
+ 0 = No globalization, 1 = LineSearch
+ USCALE = array of scaling factors for the UU vector
+ FSCALE = array of scaling factors for the FVAL (function) vector
+ IER = INTEGER error flag as returned by KINSOL:
+ 0 means success,
+ 1 means initial guess satisfies f(u) = 0 (approx.),
+ 2 means apparent stalling (small step),
+ a value < 0 means other error or failure.
+
+ Note: See KINSOL documentation for detailed information.
+
+ (8) Memory freeing: FKINFREE
+
+ To the free the internal memory created by the calls to FKINMALLOC
+ and either FNVINITS or FNVINITP, make the following call:
+
+ CALL FKINFREE
+
+ (9) Optional outputs: IOUT/ROUT
+
+ The optional outputs available by way of IOUT and ROUT have the
+ following names, locations, and descriptions. For further details see
+ the KINSOL documentation.
+
+ LENRW = IOUT(1) = real workspace size
+ LENRW = IOUT(2) = real workspace size
+ NNI = IOUT(3) = number of Newton iterations
+ NFE = IOUT(4) = number of f evaluations
+ NBCF = IOUT(5) = number of line search beta condition failures
+ NBKTRK = IOUT(6) = number of line search backtracks
+
+ FNORM = ROUT(1) = final scaled norm of f(u)
+ STEPL = ROUT(2) = scaled last step length
+
+ The following optional outputs are specific to the SPGMR/SPBCG/SPTFQMR
+ module:
+
+ LRW = IOUT( 7) = real workspace size for the linear solver module
+ LIW = IOUT( 8) = integer workspace size for the linear solver module
+ LSTF = IOUT( 9) = last flag returned by linear solver
+ NFE = IOUT(10) = number of f evaluations for DQ Jacobian
+ NJE = IOUT(11) = number of Jacobian-vector product evaluations
+ NPE = IOUT(12) = number of preconditioner evaluations
+ NPS = IOUT(13) = number of preconditioner solves
+ NLI = IOUT(14) = number of linear (Krylov) iterations
+ NCFL = IOUT(15) = number of linear convergence failures
+
+ The following optional outputs are specific to the DENSE/BAND module:
+
+ LRW = IOUT( 7) = real workspace size for the linear solver module
+ LIW = IOUT( 8) = integer workspace size for the linear solver module
+ LSTF = IOUT( 9) = last flag returned by linear solver
+ NFE = IOUT(10) = number of f evaluations for DQ Jacobian
+ NJE = IOUT(11) = number of Jacobian evaluations
+
+*******************************************************************************/
+
+#ifndef _FKINSOL_H
+#define _FKINSOL_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+/*
+ * -----------------------------------------------------------------
+ * header files
+ * -----------------------------------------------------------------
+ */
+
+#include <kinsol/kinsol.h>
+#include <sundials/sundials_direct.h> /* definition of type DlsMat */
+#include <sundials/sundials_nvector.h> /* definition of type N_Vector */
+#include <sundials/sundials_types.h> /* definition of type realtype */
+
+/*
+ * -----------------------------------------------------------------
+ * generic names are translated through the define statements below
+ * -----------------------------------------------------------------
+ */
+
+#if defined(SUNDIALS_F77_FUNC)
+
+#define FKIN_MALLOC SUNDIALS_F77_FUNC(fkinmalloc, FKINMALLOC)
+#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_DENSESETJAC SUNDIALS_F77_FUNC(fkindensesetjac, FKINDENSESETJAC)
+#define FKIN_BAND SUNDIALS_F77_FUNC(fkinband, FKINBAND)
+#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_SPTFQMR SUNDIALS_F77_FUNC(fkinsptfqmr, FKINSPTFQMR)
+#define FKIN_SPBCG SUNDIALS_F77_FUNC(fkinspbcg, FKINSPBCG)
+#define FKIN_SPGMR SUNDIALS_F77_FUNC(fkinspgmr, FKINSPGMR)
+#define FKIN_SPILSSETJAC SUNDIALS_F77_FUNC(fkinspilssetjac, FKINSPILSSETJAC)
+#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)
+
+#else
+
+#define FKIN_MALLOC fkinmalloc_
+#define FKIN_SETIIN fkinsetiin_
+#define FKIN_SETRIN fkinsetrin_
+#define FKIN_SETVIN fkinsetvin_
+#define FKIN_DENSE fkindense_
+#define FKIN_DENSESETJAC fkindensesetjac_
+#define FKIN_BAND fkinband_
+#define FKIN_BANDSETJAC fkinbandsetjac_
+#define FKIN_LAPACKDENSE fkinlapackdense_
+#define FKIN_LAPACKDENSESETJAC fkinlapackdensesetjac_
+#define FKIN_LAPACKBAND fkinlapackband_
+#define FKIN_LAPACKBANDSETJAC fkinlapackbandsetjac_
+#define FKIN_SPTFQMR fkinsptfqmr_
+#define FKIN_SPBCG fkinspbcg_
+#define FKIN_SPGMR fkinspgmr_
+#define FKIN_SPILSSETJAC fkinspilssetjac_
+#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_
+
+#endif
+
+/*
+ * -----------------------------------------------------------------
+ * Prototypes : exported functions
+ * -----------------------------------------------------------------
+ */
+
+void FKIN_MALLOC(long int *iout, realtype *rout, int *ier);
+
+void FKIN_SETIIN(char key_name[], long int *ival, int *ier, int key_len);
+void FKIN_SETRIN(char key_name[], realtype *rval, int *ier, int key_len);
+void FKIN_SETVIN(char key_name[], realtype *vval, int *ier, int key_len);
+
+void FKIN_DENSE(long int *neq, 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_SPTFQMR(int *maxl, int *ier);
+void FKIN_SPBCG(int *maxl, int *ier);
+void FKIN_SPGMR(int *maxl, int *maxlrst, int *ier);
+
+void FKIN_SPILSSETJAC(int *flag, int *ier);
+void FKIN_SPILSSETPREC(int *flag, int *ier);
+
+void FKIN_SOL(realtype *uu, int *globalstrategy,
+ realtype *uscale , realtype *fscale, int *ier);
+
+void FKIN_FREE(void);
+
+/*
+ * -----------------------------------------------------------------
+ * 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 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 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 FKINPSet(N_Vector uu, N_Vector uscale,
+ N_Vector fval, N_Vector fscale,
+ void *user_data,
+ N_Vector vtemp1, N_Vector vtemp2);
+
+int FKINPSol(N_Vector uu, N_Vector uscale,
+ N_Vector fval, N_Vector fscale,
+ N_Vector vv, void *user_data,
+ N_Vector vtemp);
+
+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
+ * -----------------------------------------------------------------
+ */
+
+extern N_Vector F2C_KINSOL_vec;
+extern void *KIN_kinmem;
+extern long int *KIN_iout;
+extern realtype *KIN_rout;
+extern int KIN_ls;
+
+/* Linear solver IDs */
+
+enum { KIN_LS_SPGMR = 1, KIN_LS_SPBCG = 2, KIN_LS_SPTFQMR = 3,
+ KIN_LS_DENSE = 4, KIN_LS_BAND = 5,
+ KIN_LS_LAPACKDENSE = 6, KIN_LS_LAPACKBAND = 7 };
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/kinsol/kinsol.c b/src/kinsol/kinsol.c
new file mode 100644
index 0000000..c4bd15d
--- /dev/null
+++ b/src/kinsol/kinsol.c
@@ -0,0 +1,1936 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.11 $
+ * $Date: 2011/07/13 22:29:01 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Allan Taylor, Alan Hindmarsh, Radu Serban, and
+ * Aaron Collier @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * This is the implementation file for the main KINSol solver.
+ * It is independent of the KINSol linear solver in use.
+ * -----------------------------------------------------------------
+ *
+ * EXPORTED FUNCTIONS
+ * ------------------
+ * Creation and allocation functions
+ * KINCreate
+ * KINInit
+ * Main solver function
+ * KINSol
+ * Deallocation function
+ * KINFree
+ *
+ * PRIVATE FUNCTIONS
+ * -----------------
+ * KINCheckNvector
+ * Memory allocation/deallocation
+ * KINAllocVectors
+ * KINFreeVectors
+ * Initial setup
+ * KINSolInit
+ * Step functions
+ * KINLinSolDrv
+ * KINFullNewton
+ * KINLineSearch
+ * KINConstraint
+ * Stopping tests
+ * KINStop
+ * KINForcingTerm
+ * Norm functions
+ * KINScFNorm
+ * KINScSNorm
+ * KINSOL Verbose output functions
+ * KINPrintInfo
+ * KINInfoHandler
+ * KINSOL Error Handling functions
+ * KINProcessError
+ * KINErrHandler
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * =================================================================
+ * IMPORTED HEADER FILES
+ * =================================================================
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+
+#include <math.h>
+
+#include "kinsol_impl.h"
+#include <sundials/sundials_math.h>
+
+/*
+ * =================================================================
+ * MACRO DEFINITIONS
+ * =================================================================
+ */
+
+/* Macro: loop */
+#define loop for(;;)
+
+/*
+ * =================================================================
+ * KINSOL PRIVATE CONSTANTS
+ * =================================================================
+ */
+
+#define HALF RCONST(0.5)
+#define ZERO RCONST(0.0)
+#define ONE RCONST(1.0)
+#define ONEPT5 RCONST(1.5)
+#define TWO RCONST(2.0)
+#define THREE RCONST(3.0)
+#define FIVE RCONST(5.0)
+#define TWELVE RCONST(12.0)
+#define POINT1 RCONST(0.1)
+#define POINT01 RCONST(0.01)
+#define POINT99 RCONST(0.99)
+#define THOUSAND RCONST(1000.0)
+#define ONETHIRD RCONST(0.3333333333333333)
+#define TWOTHIRDS RCONST(0.6666666666666667)
+#define POINT9 RCONST(0.9)
+#define POINT0001 RCONST(0.0001)
+
+/*
+ * =================================================================
+ * KINSOL ROUTINE-SPECIFIC CONSTANTS
+ * =================================================================
+ */
+
+/*
+ * Control constants for lower-level functions used by KINSol
+ * ----------------------------------------------------------
+ *
+ * KINStop return value requesting more iterations
+ * RETRY_ITERATION
+ * CONTINUE_ITERATIONS
+ *
+ * KINFullNewton and KINLineSearch return values:
+ * KIN_SUCCESS
+ * KIN_SYSFUNC_FAIL
+ * STEP_TOO_SMALL
+ *
+ * KINConstraint return values:
+ * KIN_SUCCESS
+ * CONSTR_VIOLATED
+ */
+
+#define RETRY_ITERATION -998
+#define CONTINUE_ITERATIONS -999
+#define STEP_TOO_SMALL -997
+#define CONSTR_VIOLATED -996
+
+/*
+ * Algorithmic constants
+ * ---------------------
+ *
+ * MAX_RECVR max. no. of attempts to correct a recoverable func error
+ */
+
+#define MAX_RECVR 5
+
+/*
+ * Keys for KINPrintInfo
+ * ---------------------
+ */
+
+#define PRNT_RETVAL 1
+#define PRNT_NNI 2
+#define PRNT_TOL 3
+#define PRNT_FMAX 4
+#define PRNT_PNORM 5
+#define PRNT_PNORM1 6
+#define PRNT_FNORM 7
+#define PRNT_LAM 8
+#define PRNT_ALPHA 9
+#define PRNT_BETA 10
+#define PRNT_ALPHABETA 11
+#define PRNT_ADJ 12
+
+/*
+ * =================================================================
+ * PRIVATE FUNCTION PROTOTYPES
+ * =================================================================
+ */
+
+static booleantype KINCheckNvector(N_Vector tmpl);
+static booleantype KINAllocVectors(KINMem kin_mem, N_Vector tmpl);
+static int KINSolInit(KINMem kin_mem, int strategy);
+static int KINConstraint(KINMem kin_mem );
+static void KINForcingTerm(KINMem kin_mem, realtype fnormp);
+static void KINFreeVectors(KINMem kin_mem);
+
+static int KINFullNewton(KINMem kin_mem, realtype *fnormp,
+ realtype *f1normp, booleantype *maxStepTaken);
+static int KINLineSearch(KINMem kin_mem, realtype *fnormp,
+ realtype *f1normp, booleantype *maxStepTaken);
+
+static int KINLinSolDrv(KINMem kinmem);
+static realtype KINScFNorm(KINMem kin_mem, N_Vector v, N_Vector scale);
+static realtype KINScSNorm(KINMem kin_mem, N_Vector v, N_Vector u);
+static int KINStop(KINMem kin_mem, int strategy, booleantype maxStepTaken, int sflag);
+
+/*
+ * =================================================================
+ * EXPORTED FUNCTIONS IMPLEMENTATION
+ * =================================================================
+ */
+
+/*
+ * -----------------------------------------------------------------
+ * Creation and allocation functions
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * Function : KINCreate
+ *
+ * KINCreate creates an internal memory block for a problem to
+ * be solved by KINSOL. If successful, KINCreate returns a pointer
+ * to the problem memory. This pointer should be passed to
+ * KINInit. If an initialization error occurs, KINCreate prints
+ * an error message to standard error and returns NULL.
+ */
+
+void *KINCreate(void)
+{
+ KINMem kin_mem;
+ realtype uround;
+
+ kin_mem = NULL;
+ kin_mem = (KINMem) malloc(sizeof(struct KINMemRec));
+ if (kin_mem == NULL) {
+ KINProcessError(kin_mem, 0, "KINSOL", "KINCreate", MSG_MEM_FAIL);
+ return(NULL);
+ }
+
+ /* Zero out kin_mem */
+ memset(kin_mem, 0, sizeof(struct KINMemRec));
+
+ /* set uround (unit roundoff) */
+
+ kin_mem->kin_uround = uround = UNIT_ROUNDOFF;
+
+ /* set default values for solver optional inputs */
+
+ kin_mem->kin_func = NULL;
+ kin_mem->kin_user_data = NULL;
+ kin_mem->kin_constraints = NULL;
+ kin_mem->kin_uscale = NULL;
+ kin_mem->kin_fscale = NULL;
+ kin_mem->kin_constraintsSet = FALSE;
+ kin_mem->kin_ehfun = KINErrHandler;
+ kin_mem->kin_eh_data = kin_mem;
+ kin_mem->kin_errfp = stderr;
+ kin_mem->kin_ihfun = KINInfoHandler;
+ kin_mem->kin_ih_data = kin_mem;
+ 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_msbset = MSBSET_DEFAULT;
+ kin_mem->kin_noResMon = FALSE;
+ kin_mem->kin_msbset_sub = MSBSET_SUB_DEFAULT;
+ kin_mem->kin_update_fnorm_sub = FALSE;
+ kin_mem->kin_mxnbcf = MXNBCF_DEFAULT;
+ kin_mem->kin_sthrsh = TWO;
+ kin_mem->kin_noMinEps = FALSE;
+ kin_mem->kin_mxnewtstep = ZERO;
+ kin_mem->kin_sqrt_relfunc = RSqrt(uround);
+ kin_mem->kin_scsteptol = RPowerR(uround,TWOTHIRDS);
+ kin_mem->kin_fnormtol = RPowerR(uround,ONETHIRD);
+ kin_mem->kin_etaflag = KIN_ETACHOICE1;
+ 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_omega = ZERO; /* default to using min/max */
+ kin_mem->kin_omega_min = OMEGA_MIN;
+ kin_mem->kin_omega_max = OMEGA_MAX;
+
+ /* initialize lrw and liw */
+
+ kin_mem->kin_lrw = 17;
+ kin_mem->kin_liw = 22;
+
+ /* NOTE: needed since KINInit could be called after KINSetConstraints */
+
+ kin_mem->kin_lrw1 = 0;
+ kin_mem->kin_liw1 = 0;
+
+ return((void *) kin_mem);
+}
+
+#define errfp (kin_mem->kin_errfp)
+#define liw (kin_mem->kin_liw)
+#define lrw (kin_mem->kin_lrw)
+
+/*
+ * Function : KINInit
+ *
+ * KINInit allocates memory for a problem or execution of KINSol.
+ * If memory is successfully allocated, KIN_SUCCESS is returned.
+ * Otherwise, an error message is printed and an error flag
+ * returned.
+ */
+
+int KINInit(void *kinmem, KINSysFn func, N_Vector tmpl)
+{
+ long int liw1, lrw1;
+ KINMem kin_mem;
+ booleantype allocOK, nvectorOK;
+
+ /* check kinmem */
+
+ if (kinmem == NULL) {
+ KINProcessError(NULL, KIN_MEM_NULL, "KINSOL", "KINInit", MSG_NO_MEM);
+ return(KIN_MEM_NULL);
+ }
+ kin_mem = (KINMem) kinmem;
+
+ if (func == NULL) {
+ KINProcessError(kin_mem, KIN_ILL_INPUT, "KINSOL", "KINInit", MSG_FUNC_NULL);
+ return(KIN_ILL_INPUT);
+ }
+
+ /* check if all required vector operations are implemented */
+
+ nvectorOK = KINCheckNvector(tmpl);
+ if (!nvectorOK) {
+ KINProcessError(kin_mem, KIN_ILL_INPUT, "KINSOL", "KINInit", MSG_BAD_NVECTOR);
+ return(KIN_ILL_INPUT);
+ }
+
+ /* set space requirements for one N_Vector */
+
+ if (tmpl->ops->nvspace != NULL) {
+ N_VSpace(tmpl, &lrw1, &liw1);
+ kin_mem->kin_lrw1 = lrw1;
+ kin_mem->kin_liw1 = liw1;
+ }
+ else {
+ kin_mem->kin_lrw1 = 0;
+ kin_mem->kin_liw1 = 0;
+ }
+
+ /* allocate necessary vectors */
+
+ allocOK = KINAllocVectors(kin_mem, tmpl);
+ if (!allocOK) {
+ KINProcessError(kin_mem, KIN_MEM_FAIL, "KINSOL", "KINInit", MSG_MEM_FAIL);
+ free(kin_mem); kin_mem = NULL;
+ return(KIN_MEM_FAIL);
+ }
+
+ /* copy the input parameter into KINSol state */
+
+ kin_mem->kin_func = func;
+
+ /* set the linear solver addresses to NULL */
+
+ kin_mem->kin_linit = NULL;
+ kin_mem->kin_lsetup = NULL;
+ kin_mem->kin_lsolve = NULL;
+ kin_mem->kin_lfree = NULL;
+ kin_mem->kin_lmem = NULL;
+
+ /* problem memory has been successfully allocated */
+
+ kin_mem->kin_MallocDone = TRUE;
+
+ 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 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 res_norm (kin_mem->kin_res_norm)
+#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)
+
+/*
+ * -----------------------------------------------------------------
+ * Main solver function
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * Function : KINSol
+ *
+ * KINSol (main KINSOL driver routine) manages the computational
+ * process of computing an approximate solution of the nonlinear
+ * system F(uu) = 0. The KINSol routine calls the following
+ * subroutines:
+ *
+ * KINSolInit checks if initial guess satisfies user-supplied
+ * constraints and initializes linear solver
+ *
+ * KINLinSolDrv interfaces with linear solver to find a
+ * solution of the system J(uu)*x = b (calculate
+ * Newton step)
+ *
+ * KINFullNewton/KINLineSearch implement the global strategy
+ *
+ * KINForcingTerm computes the forcing term (eta)
+ *
+ * KINStop determines if an approximate solution has been found
+ */
+
+int KINSol(void *kinmem, N_Vector u, int strategy,
+ N_Vector u_scale, N_Vector f_scale)
+{
+ realtype fnormp, f1normp, epsmin;
+ KINMem kin_mem;
+ int ret, sflag;
+ booleantype maxStepTaken;
+
+ /* intialize to avoid compiler warning messages */
+
+ maxStepTaken = FALSE;
+ f1normp = fnormp = -ONE;
+
+ /* initialize epsmin to avoid compiler warning message */
+
+ epsmin = ZERO;
+
+ /* check for kinmem non-NULL */
+
+ if (kinmem == NULL) {
+ KINProcessError(NULL, KIN_MEM_NULL, "KINSOL", "KINSol", MSG_NO_MEM);
+ return(KIN_MEM_NULL);
+ }
+ kin_mem = (KINMem) kinmem;
+
+ if(kin_mem->kin_MallocDone == FALSE) {
+ 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;
+
+ /* initialize solver */
+
+ ret = KINSolInit(kin_mem, strategy);
+ if (ret != KIN_SUCCESS) return(ret);
+
+ 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 eps is to be bounded from below, set the bound */
+
+ if (inexact_ls && !noMinEps) epsmin = POINT01 * 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;
+
+ loop{
+
+ retry_nni = FALSE;
+
+ 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 = MAX(epsmin, eps);
+ }
+
+ repeat_nni:
+
+ /* call KINLinSolDrv to calculate the (approximate) Newton step, pp */
+
+ ret = KINLinSolDrv(kin_mem);
+ if (ret != KIN_SUCCESS) break;
+
+ /* call the appropriate routine to calculate an acceptable step pp */
+
+ sflag = 0;
+
+ if (strategy == KIN_NONE) {
+
+ /* Full Newton Step*/
+ sflag = KINFullNewton(kin_mem, &fnormp, &f1normp, &maxStepTaken);
+
+ /* if sysfunc failed unrecoverably, stop */
+ if ((sflag == KIN_SYSFUNC_FAIL) || (sflag == KIN_REPTD_SYSFUNC_ERR)) {
+ ret = sflag;
+ break;
+ }
+
+ } else if (strategy == KIN_LINESEARCH) {
+
+ /* Line Search */
+ sflag = KINLineSearch(kin_mem, &fnormp, &f1normp, &maxStepTaken);
+
+ /* if sysfunc failed unrecoverably, stop */
+ if ((sflag == KIN_SYSFUNC_FAIL) || (sflag == KIN_REPTD_SYSFUNC_ERR)) {
+ ret = sflag;
+ break;
+ }
+
+ /* if too many beta condition failures, then stop iteration */
+ if (nbcf > mxnbcf) {
+ ret = KIN_LINESEARCH_BCFAIL;
+ break;
+ }
+
+ }
+
+ /* evaluate eta by calling the forcing term routine */
+
+ if (callForcingTerm) KINForcingTerm(kin_mem, fnormp);
+
+ fnorm = fnormp;
+
+ /* call KINStop to check if tolerances where met by this iteration */
+
+ ret = KINStop(kin_mem, strategy, maxStepTaken, sflag);
+
+ if (ret == RETRY_ITERATION) {
+ retry_nni = TRUE;
+ goto repeat_nni;
+ }
+
+ /* update uu after the iteration */
+
+ N_VScale(ONE, unew, uu);
+
+ 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 (ret != CONTINUE_ITERATIONS) break;
+
+ fflush(errfp);
+
+ } /* end of loop; return */
+
+ if (printfl > 0)
+ KINPrintInfo(kin_mem, PRNT_RETVAL, "KINSOL", "KINSol", INFO_RETVAL, ret);
+
+ switch(ret) {
+ case KIN_SYSFUNC_FAIL:
+ KINProcessError(kin_mem, KIN_SYSFUNC_FAIL, "KINSOL", "KINSol", MSG_SYSFUNC_FAILED);
+ break;
+ case KIN_REPTD_SYSFUNC_ERR:
+ KINProcessError(kin_mem, KIN_REPTD_SYSFUNC_ERR, "KINSOL", "KINSol", MSG_SYSFUNC_REPTD);
+ break;
+ case KIN_LSETUP_FAIL:
+ KINProcessError(kin_mem, KIN_LSETUP_FAIL, "KINSOL", "KINSol", MSG_LSETUP_FAILED);
+ break;
+ case KIN_LSOLVE_FAIL:
+ KINProcessError(kin_mem, KIN_LSOLVE_FAIL, "KINSOL", "KINSol", MSG_LSOLVE_FAILED);
+ break;
+ case KIN_LINSOLV_NO_RECOVERY:
+ KINProcessError(kin_mem, KIN_LINSOLV_NO_RECOVERY, "KINSOL", "KINSol", MSG_LINSOLV_NO_RECOVERY);
+ break;
+ case KIN_LINESEARCH_NONCONV:
+ KINProcessError(kin_mem, KIN_LINESEARCH_NONCONV, "KINSOL", "KINSol", MSG_LINESEARCH_NONCONV);
+ break;
+ case KIN_LINESEARCH_BCFAIL:
+ KINProcessError(kin_mem, KIN_LINESEARCH_BCFAIL, "KINSOL", "KINSol", MSG_LINESEARCH_BCFAIL);
+ break;
+ case KIN_MAXITER_REACHED:
+ KINProcessError(kin_mem, KIN_MAXITER_REACHED, "KINSOL", "KINSol", MSG_MAXITER_REACHED);
+ break;
+ case KIN_MXNEWT_5X_EXCEEDED:
+ KINProcessError(kin_mem, KIN_MXNEWT_5X_EXCEEDED, "KINSOL", "KINSol", MSG_MXNEWT_5X_EXCEEDED);
+ break;
+ }
+
+ return(ret);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Deallocation function
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * Function : KINFree
+ *
+ * This routine frees the problem memory allocated by KINInit.
+ * Such memory includes all the vectors allocated by
+ * KINAllocVectors, and the memory lmem for the linear solver
+ * (deallocated by a call to lfree).
+ */
+
+void KINFree(void **kinmem)
+{
+ KINMem kin_mem;
+
+ if (*kinmem == NULL) return;
+
+ kin_mem = (KINMem) (*kinmem);
+ KINFreeVectors(kin_mem);
+
+ /* call lfree if non-NULL */
+
+ if (lfree != NULL) lfree(kin_mem);
+
+ free(*kinmem);
+ *kinmem = NULL;
+}
+
+/*
+ * =================================================================
+ * PRIVATE FUNCTIONS
+ * =================================================================
+ */
+
+/*
+ * Function : KINCheckNvector
+ *
+ * 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.
+ */
+
+static booleantype KINCheckNvector(N_Vector tmpl)
+{
+ if ((tmpl->ops->nvclone == NULL) ||
+ (tmpl->ops->nvdestroy == NULL) ||
+ (tmpl->ops->nvlinearsum == NULL) ||
+ (tmpl->ops->nvprod == NULL) ||
+ (tmpl->ops->nvdiv == NULL) ||
+ (tmpl->ops->nvscale == NULL) ||
+ (tmpl->ops->nvabs == NULL) ||
+ (tmpl->ops->nvinv == NULL) ||
+ (tmpl->ops->nvmaxnorm == NULL) ||
+ (tmpl->ops->nvmin == NULL) ||
+ (tmpl->ops->nvwl2norm == NULL)) return(FALSE);
+ else return(TRUE);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Memory allocation/deallocation
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * Function : KINAllocVectors
+ *
+ * This routine allocates the KINSol vectors. If all memory
+ * allocations are successful, KINAllocVectors returns TRUE.
+ * Otherwise all allocated memory is freed and KINAllocVectors
+ * returns FALSE.
+ */
+
+static booleantype KINAllocVectors(KINMem kin_mem, N_Vector tmpl)
+{
+ /* allocate unew, fval, pp, vtemp1 and vtemp2 */
+
+ unew = N_VClone(tmpl);
+ if (unew == NULL) return(FALSE);
+
+ fval = N_VClone(tmpl);
+ if (fval == NULL) {
+ N_VDestroy(unew);
+ return(FALSE);
+ }
+
+ pp = N_VClone(tmpl);
+ if (pp == NULL) {
+ N_VDestroy(unew);
+ N_VDestroy(fval);
+ return(FALSE);
+ }
+
+ vtemp1 = N_VClone(tmpl);
+ if (vtemp1 == NULL) {
+ N_VDestroy(unew);
+ N_VDestroy(fval);
+ N_VDestroy(pp);
+ return(FALSE);
+ }
+
+ vtemp2 = N_VClone(tmpl);
+ if (vtemp2 == NULL) {
+ N_VDestroy(unew);
+ N_VDestroy(fval);
+ N_VDestroy(pp);
+ N_VDestroy(vtemp1);
+ return(FALSE);
+ }
+
+ /* update solver workspace lengths */
+
+ liw += 5*liw1;
+ lrw += 5*lrw1;
+
+ return(TRUE);
+}
+
+/*
+ * KINFreeVectors
+ *
+ * This routine frees the KINSol vectors allocated by
+ * KINAllocVectors.
+ */
+
+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);
+
+ lrw -= 5*lrw1;
+ liw -= 5*liw1;
+
+ if (kin_mem->kin_constraintsSet) {
+ if (constraints != NULL) N_VDestroy(constraints);
+ lrw -= lrw1;
+ liw -= liw1;
+ }
+
+ return;
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Initial setup
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * KINSolInit
+ *
+ * KINSolInit initializes the problem for the specific input
+ * received in this call to KINSol (which calls KINSolInit). All
+ * problem specification inputs are checked for errors. If any error
+ * occurs during initialization, it is reported to the file whose
+ * file pointer is errfp.
+ *
+ * The possible return values for KINSolInit are:
+ * KIN_SUCCESS : indicates a normal initialization
+ *
+ * KINS_ILL_INPUT : indicates that an input error has been found
+ *
+ * KIN_INITIAL_GUESS_OK : indicates that the guess uu
+ * satisfied the system func(uu) = 0
+ * within the tolerances specified
+ */
+
+static int KINSolInit(KINMem kin_mem, int strategy)
+{
+ int retval;
+ realtype fmax;
+
+ /* check for illegal input parameters */
+
+ if (uu == NULL) {
+ KINProcessError(kin_mem, KIN_ILL_INPUT, "KINSOL", "KINSolInit", MSG_UU_NULL);
+ return(KIN_ILL_INPUT);
+ }
+
+ if ((strategy != KIN_NONE) && (strategy != KIN_LINESEARCH)) {
+ KINProcessError(kin_mem, KIN_ILL_INPUT, "KINSOL", "KINSolInit", MSG_BAD_GLSTRAT);
+ return(KIN_ILL_INPUT);
+ }
+
+ if (uscale == NULL) {
+ KINProcessError(kin_mem, KIN_ILL_INPUT, "KINSOL", "KINSolInit", MSG_BAD_USCALE);
+ return(KIN_ILL_INPUT);
+ }
+
+ if (N_VMin(uscale) <= ZERO){
+ KINProcessError(kin_mem, KIN_ILL_INPUT, "KINSOL", "KINSolInit", MSG_USCALE_NONPOSITIVE);
+ return(KIN_ILL_INPUT);
+ }
+
+ if (fscale == NULL) {
+ KINProcessError(kin_mem, KIN_ILL_INPUT, "KINSOL", "KINSolInit", MSG_BAD_FSCALE);
+ return(KIN_ILL_INPUT);
+ }
+
+ if (N_VMin(fscale) <= ZERO){
+ KINProcessError(kin_mem, KIN_ILL_INPUT, "KINSOL", "KINSolInit", MSG_FSCALE_NONPOSITIVE);
+ return(KIN_ILL_INPUT);
+ }
+
+ /* set the constraints flag */
+
+ if (constraints == NULL)
+ constraintsSet = FALSE;
+ else {
+ constraintsSet = TRUE;
+ if ((constraints->ops->nvconstrmask == NULL) ||
+ (constraints->ops->nvminquotient == NULL)) {
+ KINProcessError(kin_mem, KIN_ILL_INPUT, "KINSOL", "KINSolInit", MSG_BAD_NVECTOR);
+ return(KIN_ILL_INPUT);
+ }
+ }
+
+ /* check the initial guess uu against the constraints */
+
+ if (constraintsSet) {
+ if (!N_VConstrMask(constraints, uu, vtemp1)) {
+ KINProcessError(kin_mem, KIN_ILL_INPUT, "KINSOL", "KINSolInit", MSG_INITIAL_CNSTRNT);
+ return(KIN_ILL_INPUT);
+ }
+ }
+
+ /* all error checking is complete at this point */
+
+ if (printfl > 0)
+ KINPrintInfo(kin_mem, PRNT_TOL, "KINSOL", "KINSolInit", INFO_TOL, scsteptol, fnormtol);
+
+ /* calculate the default value for mxnewtstep (maximum Newton step) */
+
+ if (mxnewtstep == ZERO)
+ mxnewtstep = THOUSAND * N_VWL2Norm(uu, uscale);
+ if (mxnewtstep < ONE) mxnewtstep = ONE;
+
+
+ /* additional set-up for inexact linear solvers */
+
+ if (inexact_ls) {
+
+ /* set up the coefficients for the eta calculation */
+
+ callForcingTerm = (etaflag != KIN_ETACONSTANT);
+
+ /* this value is always used for choice #1 */
+
+ if (etaflag == KIN_ETACHOICE1) ealpha = (ONE + RSqrt(FIVE)) * HALF;
+
+ /* initial value for eta set to 0.5 for other than the KIN_ETACONSTANT option */
+
+ if (etaflag != KIN_ETACONSTANT) eta = HALF;
+
+ /* disable residual monitoring if using an inexact linear solver */
+
+ noResMon = TRUE;
+
+ } else {
+
+ callForcingTerm = FALSE;
+
+ }
+
+ /* initialize counters */
+
+ nfe = nnilset = nnilset_sub = nni = nbcf = nbktrk = 0;
+
+ /* see if the system func(uu) = 0 is satisfied by the initial guess uu */
+
+ retval = func(uu, fval, user_data); nfe++;
+ if (retval < 0) {
+ KINProcessError(kin_mem, KIN_SYSFUNC_FAIL, "KINSOL", "KINSolInit", MSG_SYSFUNC_FAILED);
+ return(KIN_SYSFUNC_FAIL);
+ } else if (retval > 0) {
+ KINProcessError(kin_mem, KIN_FIRST_SYSFUNC_ERR, "KINSOL", "KINSolInit", MSG_SYSFUNC_FIRST);
+ return(KIN_FIRST_SYSFUNC_ERR);
+ }
+
+ fmax = KINScFNorm(kin_mem, fval, fscale);
+
+ if (printfl > 1)
+ KINPrintInfo(kin_mem, PRNT_FMAX, "KINSOL", "KINSolInit", INFO_FMAX, fmax);
+
+ if (fmax <= (POINT01 * fnormtol)) return(KIN_INITIAL_GUESS_OK);
+
+ /* initialize the linear solver if linit != NULL */
+
+ if (linit != NULL) {
+ retval = linit(kin_mem);
+ if (retval != 0) {
+ KINProcessError(kin_mem, KIN_LINIT_FAIL, "KINSOL", "KINSolInit", MSG_LINIT_FAIL);
+ return(KIN_LINIT_FAIL);
+ }
+ }
+
+ /* initialize the L2 (Euclidean) norms of f for the linear iteration steps */
+
+ fnorm = N_VWL2Norm(fval, fscale);
+ f1norm = HALF * fnorm * fnorm;
+
+ fnorm_sub = fnorm;
+
+ if (printfl > 0)
+ KINPrintInfo(kin_mem, PRNT_NNI, "KINSOL", "KINSolInit", INFO_NNI, nni, nfe, fnorm);
+
+ /* problem has now been successfully initialized */
+
+ return(KIN_SUCCESS);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Step functions
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * KINLinSolDrv
+ *
+ * This routine handles the process of solving for the approximate
+ * solution of the Newton equations in the Newton iteration.
+ * Subsequent routines handle the nonlinear aspects of its
+ * application.
+ */
+
+static int KINLinSolDrv(KINMem kin_mem)
+{
+ N_Vector x, b;
+ int retval;
+
+ if ((nni - nnilset) >= msbset) {
+ sthrsh = TWO;
+ update_fnorm_sub = TRUE;
+ }
+
+ loop{
+
+ jacCurrent = FALSE;
+
+ if ((sthrsh > ONEPT5) && setupNonNull) {
+ retval = lsetup(kin_mem);
+ jacCurrent = TRUE;
+ nnilset = nni;
+ nnilset_sub = nni;
+ if (retval != 0) return(KIN_LSETUP_FAIL);
+ }
+
+ /* rename vectors for readability */
+
+ b = unew;
+ x = pp;
+
+ /* load b with the current value of -fval */
+
+ N_VScale(-ONE, fval, b);
+
+ /* call the generic 'lsolve' routine to solve the system Jx = b */
+
+ retval = lsolve(kin_mem, x, b, &res_norm);
+
+ if (retval == 0) return(KIN_SUCCESS);
+ else if (retval < 0) return(KIN_LSOLVE_FAIL);
+ else if ((!setupNonNull) || (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;
+
+ }
+}
+
+/*
+ * KINFullNewton
+ *
+ * This routine is the main driver for the Full Newton
+ * algorithm. Its purpose is to compute unew = uu + pp in the
+ * direction pp from uu, taking the full Newton step. The
+ * step may be constrained if the constraint conditions are
+ * violated, or if the norm of pp is greater than mxnewtstep.
+ */
+
+static int KINFullNewton(KINMem kin_mem, realtype *fnormp, realtype *f1normp,
+ booleantype *maxStepTaken)
+{
+ realtype pnorm, ratio;
+ booleantype fOK;
+ int ircvr, retval;
+
+ *maxStepTaken = FALSE;
+ pnorm = N_VWL2Norm(pp, uscale);
+ ratio = ONE;
+ if (pnorm > mxnewtstep) {
+ ratio = mxnewtstep / pnorm;
+ N_VScale(ratio, pp, pp);
+ pnorm = mxnewtstep;
+ }
+
+ if (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) {
+ 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)
+ KINPrintInfo(kin_mem, PRNT_PNORM, "KINSOL", "KINFullNewton", INFO_PNORM, pnorm);
+ if (pnorm <= scsteptol) {
+ N_VLinearSum(ONE, uu, ONE, pp, unew);
+ return(STEP_TOO_SMALL);}
+ }
+ }
+
+ /* Attempt (at most MAX_RECVR times) to evaluate function at the new iterate */
+
+ fOK = FALSE;
+
+ for (ircvr = 1; ircvr <= MAX_RECVR; ircvr++) {
+
+ /* compute the iterate unew = uu + pp */
+ N_VLinearSum(ONE, uu, ONE, pp, unew);
+
+ /* evaluate func(unew) and its norm, and return */
+ retval = func(unew, fval, user_data); nfe++;
+
+ /* if func was successful, accept pp */
+ if (retval == 0) {fOK = TRUE; 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);
+ pnorm *= HALF;
+ stepl = pnorm;
+ }
+
+ /* If func() failed recoverably MAX_RECVR times, give up */
+
+ if (!fOK) return(KIN_REPTD_SYSFUNC_ERR);
+
+ /* Evaluate function norms */
+
+ *fnormp = N_VWL2Norm(fval,fscale);
+ *f1normp = HALF * (*fnormp) * (*fnormp);
+
+ /* scale sfdotJp and sJpnorm by ratio for later use in KINForcingTerm */
+
+ sfdotJp *= ratio;
+ sJpnorm *= ratio;
+
+ if (printfl > 1)
+ KINPrintInfo(kin_mem, PRNT_FNORM, "KINSOL", "KINFullNewton", INFO_FNORM, *fnormp);
+
+ if (pnorm > (POINT99 * mxnewtstep)) *maxStepTaken = TRUE;
+
+ return(KIN_SUCCESS);
+}
+
+/*
+ * KINLineSearch
+ *
+ * The routine KINLineSearch implements the LineSearch algorithm.
+ * Its purpose is to find unew = uu + rl * pp in the direction pp
+ * from uu so that:
+ * t
+ * func(unew) <= func(uu) + alpha * g (unew - uu) (alpha = 1.e-4)
+ *
+ * and
+ * t
+ * func(unew) >= func(uu) + beta * g (unew - uu) (beta = 0.9)
+ *
+ * where 0 < rlmin <= rl <= rlmax.
+ *
+ * Note:
+ * mxnewtstep
+ * rlmax = ---------------- if uu+pp is feasible
+ * ||uscale*pp||_L2
+ *
+ * rlmax = 1 otherwise
+ *
+ * and
+ *
+ * scsteptol
+ * rlmin = --------------------------
+ * || pp ||
+ * || -------------------- ||_L-infinity
+ * || (1/uscale + ABS(uu)) ||
+ *
+ *
+ * If the system function fails unrecoverably at any time, KINLineSearch
+ * returns KIN_SYSFUNC_FAIL which will halt the solver.
+ *
+ * We attempt to corect recoverable system function failures only before
+ * the alpha-condition loop; i.e. when the solution is updated with the
+ * full Newton step (possibly reduced due to constraint violations).
+ * Once we find a feasible pp, we assume that any update up to pp is
+ * feasible.
+ *
+ * If the step size is limited due to constraint violations and/or
+ * recoverable system function failures, we set rlmax=1 to ensure
+ * that the update remains feasible during the attempts to enforce
+ * the beta-condition (this is not an isse while enforcing the alpha
+ * condition, as rl can only decrease from 1 at that stage)
+ */
+
+static int KINLineSearch(KINMem kin_mem, realtype *fnormp, realtype *f1normp,
+ booleantype *maxStepTaken)
+{
+ realtype pnorm, ratio, slpi, rlmin, rlength, rl, rlmax, rldiff;
+ realtype rltmp, rlprev, pt1trl, f1nprv, rllo, rlinc, alpha, beta;
+ realtype alpha_cond, beta_cond, rl_a, tmp1, rl_b, tmp2, disc;
+ int ircvr, nbktrk_l, retval;
+ booleantype firstBacktrack, fOK;
+
+ /* Initializations */
+
+ nbktrk_l = 0; /* local backtracking counter */
+ ratio = ONE; /* step change ratio */
+ alpha = POINT0001;
+ beta = POINT9;
+
+ firstBacktrack = TRUE;
+ *maxStepTaken = FALSE;
+
+ rlprev = f1nprv = ZERO;
+
+ /* Compute length of Newton step */
+
+ pnorm = N_VWL2Norm(pp, uscale);
+ rlmax = mxnewtstep / pnorm;
+ 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;
+ rlmax = ONE;
+ stepl = pnorm;
+ }
+
+ /* If constraint checking is activated, check and correct violations */
+
+ stepmul = ONE;
+
+ if(constraintsSet){
+ retval = KINConstraint(kin_mem);
+ if(retval == CONSTR_VIOLATED){
+ /* Apply stepmul set in KINConstraint */
+ N_VScale(stepmul, pp, pp);
+ ratio *= stepmul;
+ pnorm *= 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);
+ return(STEP_TOO_SMALL);}
+ }
+ }
+
+ /* Attempt (at most MAX_RECVR times) to evaluate function at the new iterate */
+
+ fOK = FALSE;
+
+ for (ircvr = 1; ircvr <= MAX_RECVR; ircvr++) {
+
+ /* compute the iterate unew = uu + pp */
+ N_VLinearSum(ONE, uu, ONE, pp, unew);
+
+ /* evaluate func(unew) and its norm, and return */
+ retval = func(unew, fval, user_data); nfe++;
+
+ /* if func was successful, accept pp */
+ if (retval == 0) {fOK = TRUE; 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);
+ ratio *= HALF;
+ pnorm *= HALF;
+ rlmax = ONE;
+ stepl = pnorm;
+
+ }
+
+ /* If func() failed recoverably MAX_RECVR times, give up */
+
+ if (!fOK) return(KIN_REPTD_SYSFUNC_ERR);
+
+ /* Evaluate function norms */
+
+ *fnormp = N_VWL2Norm(fval, 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;
+ rl = ONE;
+
+ if (printfl > 2)
+ KINPrintInfo(kin_mem, PRNT_LAM, "KINSOL", "KINLineSearch", INFO_LAM, rlmin, f1norm, pnorm);
+
+ /* Loop until the ALPHA condition is satisfied. Terminate if rl becomes too small */
+
+ loop {
+
+ /* Evaluate test quantity */
+
+ alpha_cond = f1norm + (alpha * slpi * rl);
+
+ if (printfl > 2)
+ KINPrintInfo(kin_mem, PRNT_ALPHA, "KINSOL", "KINLinesearch",
+ INFO_ALPHA, *fnormp, *f1normp, alpha_cond, rl);
+
+ /* If ALPHA condition is satisfied, break out from loop */
+
+ if ((*f1normp) <= alpha_cond) break;
+
+ /* Backtracking. Use quadratic fit the first time and cubic fit afterwards. */
+
+ if (firstBacktrack) {
+
+ rltmp = -slpi / (TWO * ((*f1normp) - f1norm - slpi));
+ firstBacktrack = FALSE;
+
+ } else {
+
+ tmp1 = (*f1normp) - f1norm - (rl * slpi);
+ tmp2 = f1nprv - 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);
+ rl_a *= tmp1;
+ rl_b *= tmp1;
+ disc = (rl_b * rl_b) - (THREE * rl_a * slpi);
+
+ if (ABS(rl_a) < uround) { /* cubic is actually just a quadratic (rl_a ~ 0) */
+ rltmp = -slpi / (TWO * rl_b);
+ } else { /* real cubic */
+ rltmp = (-rl_b + RSqrt(disc)) / (THREE * rl_a);
+ }
+ }
+ if (rltmp > (HALF * rl)) rltmp = HALF * rl;
+
+ /* Set new rl (do not allow a reduction by a factor larger than 10) */
+
+ rlprev = rl;
+ f1nprv = (*f1normp);
+ pt1trl = POINT1 * rl;
+ rl = MAX(pt1trl, rltmp);
+ nbktrk_l++;
+
+ /* Update unew and re-evaluate function */
+
+ N_VLinearSum(ONE, uu, rl, pp, unew);
+
+ retval = func(unew, fval, user_data); nfe++;
+ if (retval != 0) return(KIN_SYSFUNC_FAIL);
+
+ *fnormp = N_VWL2Norm(fval, fscale);
+ *f1normp = HALF * (*fnormp) * (*fnormp) ;
+
+ /* Check if rl (lambda) is too small */
+
+ if (rl < rlmin) {
+ /* 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);
+ return(STEP_TOO_SMALL);
+ }
+
+ } /* end ALPHA condition loop */
+
+
+ /* ALPHA condition is satisfied. Now check the BETA condition */
+
+ beta_cond = f1norm + (beta * slpi * rl);
+
+ if ((*f1normp) < beta_cond) {
+
+ /* BETA condition not satisfied */
+
+ if ((rl == ONE) && (pnorm < mxnewtstep)) {
+
+ do {
+
+ rlprev = rl;
+ f1nprv = *f1normp;
+ rl = MIN((TWO * rl), rlmax);
+ nbktrk_l++;
+
+ N_VLinearSum(ONE, uu, rl, pp, unew);
+ retval = func(unew, fval, user_data); nfe++;
+ if (retval != 0) return(KIN_SYSFUNC_FAIL);
+ *fnormp = N_VWL2Norm(fval, fscale);
+ *f1normp = HALF * (*fnormp) * (*fnormp);
+
+ alpha_cond = f1norm + (alpha * slpi * rl);
+ beta_cond = f1norm + (beta * slpi * rl);
+
+ if (printfl > 2)
+ KINPrintInfo(kin_mem, PRNT_BETA, "KINSOL", "KINLineSearch",
+ INFO_BETA, *f1normp, beta_cond, rl);
+
+ } while (((*f1normp) <= alpha_cond) &&
+ ((*f1normp) < beta_cond) && (rl < rlmax));
+
+ } /* enf if (rl == ONE) block */
+
+ if ((rl < ONE) || ((rl > ONE) && (*f1normp > alpha_cond))) {
+
+ rllo = MIN(rl, rlprev);
+ rldiff = ABS(rlprev - rl);
+
+ do {
+
+ rlinc = HALF * rldiff;
+ rl = rllo + rlinc;
+ nbktrk_l++;
+
+ N_VLinearSum(ONE, uu, rl, pp, unew);
+ retval = func(unew, fval, user_data); nfe++;
+ if (retval != 0) return(KIN_SYSFUNC_FAIL);
+ *fnormp = N_VWL2Norm(fval, fscale);
+ *f1normp = HALF * (*fnormp) * (*fnormp);
+
+ alpha_cond = f1norm + (alpha * slpi * rl);
+ beta_cond = f1norm + (beta * slpi * rl);
+
+ if (printfl > 2)
+ KINPrintInfo(kin_mem, PRNT_ALPHABETA, "KINSOL", "KINLineSearch",
+ INFO_ALPHABETA, *f1normp, alpha_cond, beta_cond, rl);
+
+ if ((*f1normp) > alpha_cond) rldiff = rlinc;
+ else if (*f1normp < beta_cond) {
+ rllo = rl;
+ rldiff = rldiff - rlinc;
+ }
+
+ } while ((*f1normp > alpha_cond) ||
+ ((*f1normp < beta_cond) && (rldiff >= rlmin)));
+
+ if ((*f1normp) < beta_cond) {
+
+ /* beta condition could not be 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++;
+ if (retval != 0) return(KIN_SYSFUNC_FAIL);
+ *fnormp = N_VWL2Norm(fval, fscale);
+ *f1normp = HALF * (*fnormp) * (*fnormp);
+
+ /* increment beta-condition failures counter */
+
+ nbcf++;
+
+ }
+
+ } /* end of if (rl < ONE) block */
+
+ } /* end of if (f1normp < beta_cond) block */
+
+ /* Update number of backtracking operations */
+
+ nbktrk += nbktrk_l;
+
+ if (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;
+
+ if ((rl * pnorm) > (POINT99 * mxnewtstep)) *maxStepTaken = TRUE;
+
+ return(KIN_SUCCESS);
+}
+
+/*
+ * Function : KINConstraint
+ *
+ * This routine checks if the proposed solution vector uu + pp
+ * violates any constraints. If a constraint is violated, then the
+ * scalar stepmul is determined such that uu + stepmul * pp does
+ * not violate any constraints.
+ *
+ * Note: This routine is called by the functions
+ * KINLineSearch and KINFullNewton.
+ */
+
+static int KINConstraint(KINMem kin_mem)
+{
+ N_VLinearSum(ONE, uu, ONE, pp, 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);
+
+ /* vtemp1[i] = ABS(pp[i]) */
+
+ N_VAbs(pp, vtemp1);
+
+ /* consider vtemp1[i] only if vtemp2[i] = 1 (constraint violated) */
+
+ N_VProd(vtemp2, vtemp1, vtemp1);
+
+ N_VAbs(uu, vtemp2);
+ stepmul = POINT9 * N_VMinQuotient(vtemp2, vtemp1);
+
+ return(CONSTR_VIOLATED);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Stopping tests
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * KINStop
+ *
+ * This routine checks the current iterate unew to see if the
+ * system func(unew) = 0 is satisfied by a variety of tests.
+ *
+ * strategy is one of KIN_NONE or KIN_LINESEARCH
+ * sflag is one of KIN_SUCCESS, STEP_TOO_SMALL
+ */
+
+static int KINStop(KINMem kin_mem, int strategy, booleantype maxStepTaken, int sflag)
+{
+ realtype fmax, rlength, omexp;
+ N_Vector delta;
+
+ /* Check for too small a step */
+
+ if (sflag == STEP_TOO_SMALL) {
+
+ if (setupNonNull && !jacCurrent) {
+ /* If the Jacobian is out of date, update it and retry */
+ sthrsh = TWO;
+ return(CONTINUE_ITERATIONS);
+ } else {
+ /* Give up */
+ if (strategy == KIN_NONE) return(KIN_STEP_LT_STPTOL);
+ else return(KIN_LINESEARCH_NONCONV);
+ }
+
+ }
+
+ /* Check tolerance on scaled function norm at the current iterate */
+
+ fmax = KINScFNorm(kin_mem, fval, fscale);
+
+ if (printfl > 1)
+ KINPrintInfo(kin_mem, PRNT_FMAX, "KINSOL", "KINStop", INFO_FMAX, fmax);
+
+ if (fmax <= 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);
+
+ if (rlength <= scsteptol) {
+
+ if (setupNonNull && !jacCurrent) {
+ /* If the Jacobian is out of date, update it and retry */
+ sthrsh = TWO;
+ return(CONTINUE_ITERATIONS);
+ } else {
+ /* give up */
+ return(KIN_STEP_LT_STPTOL);
+ }
+
+ }
+
+ /* Check if the maximum number of iterations is reached */
+
+ if (nni >= 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 (ncscmx == 5) return(KIN_MXNEWT_5X_EXCEEDED);
+
+ /* Proceed according to the type of linear solver used */
+
+ if (inexact_ls) {
+
+ /* We're doing inexact Newton.
+ Load threshold for reevaluating the Jacobian. */
+
+ sthrsh = rlength;
+
+ } else if (!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) {
+
+ /* Residual monitoring needed */
+
+ nnilset_sub = nni;
+
+ /* If indicated, estimate new OMEGA value */
+ if (eval_omega) {
+ omexp = MAX(ZERO,(fnorm/fnormtol)-ONE);
+ omega = (omexp > TWELVE)? omega_max : MIN(omega_min*EXP(omexp), omega_max);
+ }
+ /* Check if making satisfactory progress */
+
+ if (fnorm > omega*fnorm_sub) {
+ /* Insuficient progress */
+ if (setupNonNull && !jacCurrent) {
+ /* If the Jacobian is out of date, update it and retry */
+ sthrsh = TWO;
+ return(RETRY_ITERATION);
+ } else {
+ /* Otherwise, we cannot do anything, so just return. */
+ }
+ } else {
+ /* Sufficient progress */
+ fnorm_sub = fnorm;
+ sthrsh = ONE;
+ }
+
+ } else {
+
+ /* 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 made it to here, then the iteration process is not finished
+ so return CONTINUE_ITERATIONS flag */
+
+ return(CONTINUE_ITERATIONS);
+}
+
+/*
+ * KINForcingTerm
+ *
+ * This routine computes eta, the scaling factor in the linear
+ * convergence stopping tolerance eps when choice #1 or choice #2
+ * forcing terms are used. Eta is computed here for all but the
+ * first iterative step, which is set to the default in routine
+ * KINSolInit.
+ *
+ * This routine was written by Homer Walker of Utah State
+ * University with subsequent modifications by Allan Taylor @ LLNL.
+ *
+ * It is based on the concepts of the paper 'Choosing the forcing
+ * terms in an inexact Newton method', SIAM J Sci Comput, 17
+ * (1996), pp 16 - 32, or Utah State University Research Report
+ * 6/94/75 of the same title.
+ */
+
+static void KINForcingTerm(KINMem kin_mem, realtype fnormp)
+{
+ realtype eta_max, eta_min, eta_safe, linmodel_norm;
+
+ eta_max = POINT9;
+ eta_min = POINT0001;
+ eta_safe = HALF;
+
+ /* choice #1 forcing term */
+
+ if (etaflag == KIN_ETACHOICE1) {
+
+ /* compute the norm of f + Jp , scaled L2 norm */
+
+ linmodel_norm = RSqrt((fnorm * fnorm) + (TWO * sfdotJp) + (sJpnorm * sJpnorm));
+
+ /* form the safeguarded for choice #1 */
+
+ eta_safe = RPowerR(eta, ealpha);
+ eta = ABS(fnormp - linmodel_norm) / fnorm;
+ }
+
+ /* choice #2 forcing term */
+
+ if (etaflag == KIN_ETACHOICE2) {
+ eta_safe = egamma * RPowerR(eta, ealpha);
+ eta = egamma * RPowerR((fnormp / fnorm), ealpha);
+ }
+
+ /* apply safeguards */
+
+ if(eta_safe < POINT1) eta_safe = ZERO;
+ eta = MAX(eta, eta_safe);
+ eta = MAX(eta, eta_min);
+ eta = MIN(eta, eta_max);
+
+ return;
+}
+
+
+/*
+ * -----------------------------------------------------------------
+ * Norm functions
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * Function : KINScFNorm
+ *
+ * This routine computes the max norm for scaled vectors. The
+ * scaling vector is scale, and the vector of which the norm is to
+ * be determined is vv. The returned value, fnormval, is the
+ * resulting scaled vector norm. This routine uses N_Vector
+ * functions from the vector module.
+ */
+
+static realtype KINScFNorm(KINMem kin_mem, N_Vector v, N_Vector scale)
+{
+ N_VProd(scale, v, vtemp1);
+ return(N_VMaxNorm(vtemp1));
+}
+
+/*
+ * Function : KINScSNorm
+ *
+ * This routine computes the max norm of the scaled steplength, ss.
+ * Here ucur is the current step and usc is the u scale factor.
+ */
+
+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);
+
+ length = N_VMaxNorm(vtemp1);
+
+ return(length);
+}
+
+/*
+ * =================================================================
+ * KINSOL Verbose output functions
+ * =================================================================
+ */
+
+/*
+ * KINPrintInfo
+ *
+ * KINPrintInfo is a high level error handling function
+ * Based on the value info_code, it composes the info message and
+ * passes it to the info handler function.
+ */
+
+#define ihfun (kin_mem->kin_ihfun)
+#define ih_data (kin_mem->kin_ih_data)
+
+void KINPrintInfo(KINMem kin_mem,
+ int info_code, const char *module, const char *fname,
+ const char *msgfmt, ...)
+{
+ va_list ap;
+ char msg[256], msg1[40];
+ char retstr[30];
+ int ret;
+
+ /* Initialize argument processing
+ (msgfrmt is the last required argument) */
+
+ va_start(ap, msgfmt);
+
+ if (info_code == PRNT_RETVAL) {
+
+ /* If info_code = PRNT_RETVAL, decode the numeric value */
+
+ ret = va_arg(ap, int);
+
+ switch(ret) {
+ case KIN_SUCCESS:
+ sprintf(retstr, "KIN_SUCCESS");
+ break;
+ case KIN_SYSFUNC_FAIL:
+ sprintf(retstr, "KIN_SYSFUNC_FAIL");
+ break;
+ case KIN_STEP_LT_STPTOL:
+ sprintf(retstr, "KIN_STEP_LT_STPTOL");
+ break;
+ case KIN_LINESEARCH_NONCONV:
+ sprintf(retstr, "KIN_LINESEARCH_NONCONV");
+ break;
+ case KIN_LINESEARCH_BCFAIL:
+ sprintf(retstr, "KIN_LINESEARCH_BCFAIL");
+ break;
+ case KIN_MAXITER_REACHED:
+ sprintf(retstr, "KIN_MAXITER_REACHED");
+ break;
+ case KIN_MXNEWT_5X_EXCEEDED:
+ sprintf(retstr, "KIN_MXNEWT_5X_EXCEEDED");
+ break;
+ case KIN_LINSOLV_NO_RECOVERY:
+ sprintf(retstr, "KIN_LINSOLV_NO_RECOVERY");
+ break;
+ case KIN_LSETUP_FAIL:
+ sprintf(retstr, "KIN_PRECONDSET_FAILURE");
+ break;
+ case KIN_LSOLVE_FAIL:
+ sprintf(retstr, "KIN_PRECONDSOLVE_FAILURE");
+ break;
+ }
+
+ /* Compose the message */
+
+ sprintf(msg1, msgfmt, ret);
+ sprintf(msg,"%s (%s)",msg1,retstr);
+
+
+ } else {
+
+ /* Compose the message */
+
+ vsprintf(msg, msgfmt, ap);
+
+ }
+
+ /* call the info message handler */
+
+ ihfun(module, fname, msg, ih_data);
+
+ /* finalize argument processing */
+
+ va_end(ap);
+
+ return;
+}
+
+
+/*
+ * KINInfoHandler
+ *
+ * This is the default KINSOL info handling function.
+ * It sends the info message to the stream pointed to by kin_infofp
+ */
+
+#define infofp (kin_mem->kin_infofp)
+
+void KINInfoHandler(const char *module, const char *function,
+ char *msg, void *data)
+{
+ KINMem kin_mem;
+
+ /* data points to kin_mem here */
+
+ kin_mem = (KINMem) data;
+
+#ifndef NO_FPRINTF_OUTPUT
+ if (infofp != NULL) {
+ fprintf(infofp,"\n[%s] %s\n",module, function);
+ fprintf(infofp," %s\n",msg);
+ }
+#endif
+
+}
+
+/*
+ * =================================================================
+ * KINSOL Error Handling functions
+ * =================================================================
+ */
+
+/*
+ * KINProcessError
+ *
+ * Thi is a high level error handling function
+ * - if cv_mem==NULL it prints the error message to stderr
+ * - otherwise, it sets-up and calls the error hadling function
+ * pointed to by cv_ehfun
+ */
+
+#define ehfun (kin_mem->kin_ehfun)
+#define eh_data (kin_mem->kin_eh_data)
+
+void KINProcessError(KINMem kin_mem,
+ int error_code, const char *module, const char *fname,
+ const char *msgfmt, ...)
+{
+ va_list ap;
+ char msg[256];
+
+ /* Initialize the argument pointer variable
+ (msgfmt is the last required argument to KINProcessError) */
+
+ va_start(ap, msgfmt);
+
+ if (kin_mem == NULL) { /* We write to stderr */
+
+#ifndef NO_FPRINTF_OUTPUT
+ fprintf(stderr, "\n[%s ERROR] %s\n ", module, fname);
+ fprintf(stderr, msgfmt);
+ fprintf(stderr, "\n\n");
+#endif
+
+ } else { /* We can call ehfun */
+
+ /* Compose the message */
+
+ vsprintf(msg, msgfmt, ap);
+
+ /* Call ehfun */
+
+ ehfun(error_code, module, fname, msg, eh_data);
+
+ }
+
+ /* Finalize argument processing */
+
+ va_end(ap);
+
+ return;
+
+}
+
+/*
+ * KINErrHandler
+ *
+ * This is the default error handling function.
+ * 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)
+{
+ KINMem kin_mem;
+ char err_type[10];
+
+ /* data points to kin_mem here */
+
+ kin_mem = (KINMem) data;
+
+ if (error_code == KIN_WARNING)
+ sprintf(err_type,"WARNING");
+ else
+ 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);
+ }
+#endif
+
+ return;
+}
+
diff --git a/src/kinsol/kinsol_band.c b/src/kinsol/kinsol_band.c
new file mode 100644
index 0000000..f975a5e
--- /dev/null
+++ b/src/kinsol/kinsol_band.c
@@ -0,0 +1,346 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.11 $
+ * $Date: 2011/03/23 23:37:59 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * 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 *res_norm);
+static void 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 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 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;
+
+ 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 = MIN(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;
+
+ nje = 0;
+ nfeDQ = 0;
+
+ if (jacDQ) {
+ bjac = kinDlsBandDQJac;
+ J_data = kin_mem;
+ } else {
+ J_data = kin_mem->kin_user_data;
+ }
+
+ 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
+ * M = I - gamma*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.
+ * -----------------------------------------------------------------
+ */
+
+static int kinBandsolve(KINMem kin_mem, N_Vector x, N_Vector b, realtype *res_norm)
+{
+ 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 terms Jpnorm and sfdotJp for use in the global strategy
+ routines and in KINForcingTerm. Both of these terms are subsequently
+ corrected if the step is reduced by constraints or the line search.
+
+ sJpnorm is the norm of the scaled product (scaled by fscale) of
+ the current Jacobian matrix J and the step vector p.
+
+ sfdotJp is the dot product of the scaled f vector and the scaled
+ vector J*p, where the scaling uses fscale. */
+
+ sJpnorm = N_VWL2Norm(b,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 void kinBandFree(KINMem kin_mem)
+{
+ KINDlsMem kindls_mem;
+
+ kindls_mem = (KINDlsMem) lmem;
+
+ DestroyMat(J);
+ DestroyArray(lpivots);
+ free(kindls_mem); kindls_mem = NULL;
+}
+
diff --git a/src/kinsol/kinsol_bbdpre.c b/src/kinsol/kinsol_bbdpre.c
new file mode 100644
index 0000000..54fa840
--- /dev/null
+++ b/src/kinsol/kinsol_bbdpre.c
@@ -0,0 +1,538 @@
+/*
+ *-----------------------------------------------------------------
+ * $Revision: 1.7 $
+ * $Date: 2010/12/01 22:43:33 $
+ *-----------------------------------------------------------------
+ * Programmer(s): Allan Taylor, Alan Hindmarsh, Radu Serban, and
+ * Aaron Collier @ LLNL
+ *-----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ *-----------------------------------------------------------------
+ * 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.
+ *
+ * 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
+ *-----------------------------------------------------------------
+ */
+
+#define ZERO RCONST(0.0)
+#define ONE RCONST(1.0)
+
+/* Prototypes for 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);
+
+static int KINBBDPrecSolve(N_Vector uu, N_Vector uscale,
+ N_Vector fval, N_Vector fscale,
+ N_Vector vv, void *p_data,
+ N_Vector vtemp);
+
+/* Prototype for KINBBDPrecFree */
+
+static void 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,
+ realtype dq_rel_uu,
+ KINLocalFn gloc, KINCommFn gcomm)
+{
+ KBBDPrecData pdata;
+ KINSpilsMem kinspils_mem;
+ KINMem kin_mem;
+ N_Vector vtemp3;
+ long int muk, mlk, storage_mu;
+ int flag;
+
+ pdata = NULL;
+
+ if (kinmem == NULL) {
+ KINProcessError(NULL, 0, "KINBBDPRE", "KINBBDPrecInit", MSGBBD_MEM_NULL);
+ return(KINSPILS_MEM_NULL);
+ }
+ kin_mem = (KINMem) kinmem;
+
+ /* Test if one of the SPILS linear solvers has been attached */
+ if (kin_mem->kin_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);
+ return(KINSPILS_ILL_INPUT);
+ }
+
+ pdata = NULL;
+ pdata = (KBBDPrecData) malloc(sizeof *pdata); /* allocate data memory */
+ if (pdata == NULL) {
+ 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 */
+
+ pdata->kin_mem = kinmem;
+ pdata->gloc = gloc;
+ pdata->gcomm = gcomm;
+ pdata->mudq = MIN(Nlocal-1, MAX(0, mudq));
+ pdata->mldq = MIN(Nlocal-1, MAX(0, mldq));
+ muk = MIN(Nlocal-1, MAX(0,mukeep));
+ mlk = MIN(Nlocal-1, MAX(0,mlkeep));
+ pdata->mukeep = muk;
+ pdata->mlkeep = mlk;
+
+ /* allocate memory for preconditioner matrix */
+
+ storage_mu = MIN(Nlocal-1, muk+mlk);
+ pdata->PP = NULL;
+ pdata->PP = NewBandMat(Nlocal, muk, mlk, storage_mu);
+ if (pdata->PP == NULL) {
+ free(pdata); pdata = NULL;
+ KINProcessError(kin_mem, KINSPILS_MEM_FAIL, "KINBBDPRE", "KINBBDPrecInit", MSGBBD_MEM_FAIL);
+ return(KINSPILS_MEM_FAIL);
+ }
+
+ /* allocate memory for lpivots */
+
+ pdata->lpivots = NULL;
+ pdata->lpivots = NewLintArray(Nlocal);
+ if (pdata->lpivots == NULL) {
+ DestroyMat(pdata->PP);
+ free(pdata); pdata = NULL;
+ KINProcessError(kin_mem, KINSPILS_MEM_FAIL, "KINBBDPRE", "KINBBDPrecInit", MSGBBD_MEM_FAIL);
+ return(KINSPILS_MEM_FAIL);
+ }
+
+ /* allocate vtemp3 for use by KBBDDQJac routine */
+
+ vtemp3 = NULL;
+ vtemp3 = N_VClone(kin_mem->kin_vtemp1);
+ if (vtemp3 == NULL) {
+ DestroyArray(pdata->lpivots);
+ DestroyMat(pdata->PP);
+ free(pdata); pdata = NULL;
+ 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 */
+
+ if (dq_rel_uu > ZERO) pdata->rel_uu = dq_rel_uu;
+ else pdata->rel_uu = RSqrt(uround); /* using dq_rel_uu = 0.0 means use default */
+
+ /* store Nlocal to be used by the preconditioner routines */
+
+ pdata->n_local = Nlocal;
+
+ /* set work space sizes and initialize nge */
+
+ pdata->rpwsize = Nlocal * (storage_mu*mlk + 1) + 1;
+ pdata->ipwsize = Nlocal + 1;
+ pdata->nge = 0;
+
+ /* Overwrite the P_data field in the SPILS memory */
+ kinspils_mem->s_P_data = pdata;
+
+ /* Attach the pfree function */
+ kinspils_mem->s_pfree = KINBBDPrecFree;
+
+ /* Attach preconditioner solve and setup functions */
+ flag = KINSpilsSetPreconditioner(kinmem, KINBBDPrecSetup, KINBBDPrecSolve);
+
+ return(flag);
+}
+
+/*
+ *-----------------------------------------------------------------
+ * Function : 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);
+ 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);
+ 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);
+ return(KINSPILS_PMEM_NULL);
+ }
+ pdata = (KBBDPrecData) kinspils_mem->s_P_data;
+
+ *lenrwBBDP = pdata->rpwsize;
+ *leniwBBDP = pdata->ipwsize;
+
+ return(KINSPILS_SUCCESS);
+}
+
+/*
+ *-----------------------------------------------------------------
+ * Function : 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);
+ 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);
+ 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);
+ return(KINSPILS_PMEM_NULL);
+ }
+ pdata = (KBBDPrecData) kinspils_mem->s_P_data;
+
+ *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.
+ *-----------------------------------------------------------------
+ */
+
+static int KINBBDPrecSetup(N_Vector uu, N_Vector uscale,
+ N_Vector fval, N_Vector fscale,
+ void *bbd_data,
+ N_Vector vtemp1, N_Vector vtemp2)
+{
+ 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);
+ if (retval != 0) {
+ KINProcessError(kin_mem, -1, "KINBBDPRE", "KINBBDPrecSetup", MSGBBD_FUNC_FAILED);
+ return(-1);
+ }
+
+ nge += (1 + MIN(mldq+mudq+1, Nlocal));
+
+ /* do LU factorization of P in place (in PP) */
+
+ ier = BandGBTRF(PP, lpivots);
+
+ /* return 0 if the LU was complete, else return 1 */
+
+ if (ier > 0) return(1);
+ else return(0);
+}
+
+/*
+ *-----------------------------------------------------------------
+ * 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.
+ *-----------------------------------------------------------------
+ */
+
+static int KINBBDPrecSolve(N_Vector uu, N_Vector uscale,
+ N_Vector fval, N_Vector fscale,
+ N_Vector vv, void *bbd_data,
+ N_Vector vtemp)
+{
+ KBBDPrecData pdata;
+ realtype *vd;
+
+ pdata = (KBBDPrecData) bbd_data;
+
+ /* do the backsolve and return */
+
+ vd = N_VGetArrayPointer(vv);
+ BandGBTRS(PP, lpivots, vd);
+
+ return(0);
+}
+
+
+static void KINBBDPrecFree(KINMem kin_mem)
+{
+ KINSpilsMem kinspils_mem;
+ KBBDPrecData pdata;
+
+ if (kin_mem->kin_lmem == NULL) return;
+ kinspils_mem = (KINSpilsMem) kin_mem->kin_lmem;
+
+ if (kinspils_mem->s_P_data == NULL) return;
+ pdata = (KBBDPrecData) kinspils_mem->s_P_data;
+
+ N_VDestroy(vtemp3);
+ DestroyMat(PP);
+ DestroyArray(lpivots);
+
+ free(pdata);
+ pdata = NULL;
+}
+
+
+
+/*
+ *-----------------------------------------------------------------
+ * 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)
+
+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;
+ int retval;
+
+ kin_mem = (KINMem) pdata->kin_mem;
+
+ /* 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);
+ if (retval != 0) return(retval);
+ }
+
+ retval = gloc(Nlocal, uu, gu, user_data);
+ if (retval != 0) return(retval);
+
+ /* set bandwidth and number of column groups for band differencing */
+
+ width = mldq + mudq + 1;
+ ngroups = MIN(width, Nlocal);
+
+ /* 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 * MAX(ABS(udata[j]), (ONE / uscdata[j]));
+ utempdata[j] += inc;
+ }
+
+ /* evaluate g with incremented u */
+
+ retval = gloc(Nlocal, utemp, gtemp, user_data);
+ if (retval != 0) return(retval);
+
+ /* restore utemp, then form and load difference quotients */
+
+ for (j = group - 1; j < Nlocal; j += width) {
+ utempdata[j] = udata[j];
+ col_j = BAND_COL(PP,j);
+ inc = rel_uu * MAX(ABS(udata[j]) , (ONE / uscdata[j]));
+ inc_inv = ONE / inc;
+ i1 = MAX(0, (j - mukeep));
+ i2 = MIN((j + mlkeep), (Nlocal - 1));
+ for (i = i1; i <= i2; i++)
+ BAND_COL_ELEM(col_j, i, j) = inc_inv * (gtempdata[i] - gudata[i]);
+ }
+ }
+
+ return(0);
+}
diff --git a/src/kinsol/kinsol_bbdpre_impl.h b/src/kinsol/kinsol_bbdpre_impl.h
new file mode 100644
index 0000000..5775bce
--- /dev/null
+++ b/src/kinsol/kinsol_bbdpre_impl.h
@@ -0,0 +1,89 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.4 $
+ * $Date: 2010/12/01 22:43:33 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Allan Taylor, Alan Hindmarsh, Radu Serban, and
+ * Aaron Collier @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * KINBBDPRE module header file (private version)
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _KINBBDPRE_IMPL_H
+#define _KINBBDPRE_IMPL_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <kinsol/kinsol_bbdpre.h>
+#include <sundials/sundials_band.h>
+#include "kinsol_impl.h"
+
+/*
+ * -----------------------------------------------------------------
+ * 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;
+
+ /* available for optional output */
+
+ long int rpwsize;
+ long int ipwsize;
+ long int nge;
+
+ /* pointer to KINSol memory */
+
+ void *kin_mem;
+
+} *KBBDPrecData;
+
+/*
+ *-----------------------------------------------------------------
+ * KINBBDPRE error messages
+ *-----------------------------------------------------------------
+ */
+
+#define MSGBBD_MEM_NULL "KINSOL 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_FUNC_FAILED "The gloc or cfn routine failed in an unrecoverable manner."
+#define MSGBBD_PMEM_NULL "BBD peconditioner memory is NULL. IDABBDPrecInit must be called."
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/kinsol/kinsol_dense.c b/src/kinsol/kinsol_dense.c
new file mode 100644
index 0000000..70f0e03
--- /dev/null
+++ b/src/kinsol/kinsol_dense.c
@@ -0,0 +1,329 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.11 $
+ * $Date: 2010/12/01 22:43:33 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * 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 *res_norm);
+static void 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 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 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;
+
+ 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;
+
+ nje = 0;
+ nfeDQ = 0;
+
+ if (jacDQ) {
+ djac = kinDlsDenseDQJac;
+ J_data = kin_mem;
+ } else {
+ J_data = kin_mem->kin_user_data;
+ }
+
+ 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.
+ * -----------------------------------------------------------------
+ */
+
+static int kinDenseSolve(KINMem kin_mem, N_Vector x, N_Vector b, realtype *res_norm)
+{
+ 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 terms Jpnorm and sfdotJp for use in the global strategy
+ routines and in KINForcingTerm. Both of these terms are subsequently
+ corrected if the step is reduced by constraints or the line search.
+
+ sJpnorm is the norm of the scaled product (scaled by fscale) of
+ the current Jacobian matrix J and the step vector p.
+
+ sfdotJp is the dot product of the scaled f vector and the scaled
+ vector J*p, where the scaling uses fscale. */
+
+ sJpnorm = N_VWL2Norm(b,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 void kinDenseFree(KINMem kin_mem)
+{
+ KINDlsMem kindls_mem;
+
+ kindls_mem = (KINDlsMem) lmem;
+
+ DestroyMat(J);
+ DestroyArray(lpivots);
+ free(kindls_mem); kindls_mem = NULL;
+}
+
diff --git a/src/kinsol/kinsol_direct.c b/src/kinsol/kinsol_direct.c
new file mode 100644
index 0000000..8365aaf
--- /dev/null
+++ b/src/kinsol/kinsol_direct.c
@@ -0,0 +1,491 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.6 $
+ * $Date: 2010/12/01 22:43:33 $
+ * -----------------------------------------------------------------
+ * Programmer: Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2006, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * This is the implementation file for the KINDLS linear solvers
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * =================================================================
+ * IMPORTED HEADER FILES
+ * =================================================================
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "kinsol_impl.h"
+#include "kinsol_direct_impl.h"
+#include <sundials/sundials_math.h>
+
+/*
+ * =================================================================
+ * FUNCTION SPECIFIC CONSTANTS
+ * =================================================================
+ */
+
+/* Constant for DQ Jacobian approximation */
+#define MIN_INC_MULT RCONST(1000.0)
+
+#define ZERO RCONST(0.0)
+#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
+ * -----------------------------------------------------------------
+ */
+
+int KINDlsSetDenseJacFn(void *kinmem, KINDlsDenseJacFn jac)
+{
+ KINMem kin_mem;
+ KINDlsMem kindls_mem;
+
+ /* Return immediately if kinmem is NULL */
+ if (kinmem == NULL) {
+ KINProcessError(NULL, KINDLS_MEM_NULL, "KINDLS", "KINDlsSetDenseJacFn", MSGD_KINMEM_NULL);
+ return(KINDLS_MEM_NULL);
+ }
+ kin_mem = (KINMem) kinmem;
+
+ if (lmem == NULL) {
+ KINProcessError(kin_mem, KINDLS_LMEM_NULL, "KINDLS", "KINDlsSetDenseJacFn", MSGD_LMEM_NULL);
+ return(KINDLS_LMEM_NULL);
+ }
+ kindls_mem = (KINDlsMem) lmem;
+
+ if (jac != NULL) {
+ jacDQ = FALSE;
+ djac = jac;
+ } else {
+ jacDQ = TRUE;
+ }
+
+ return(KINDLS_SUCCESS);
+}
+
+int KINDlsSetBandJacFn(void *kinmem, KINDlsBandJacFn jac)
+{
+ KINMem kin_mem;
+ KINDlsMem kindls_mem;
+
+ /* Return immediately if kinmem is NULL */
+ if (kinmem == NULL) {
+ KINProcessError(NULL, KINDLS_MEM_NULL, "KINDLS", "KINDlsSetBandJacFn", 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);
+ return(KINDLS_LMEM_NULL);
+ }
+ kindls_mem = (KINDlsMem) lmem;
+
+ if (jac != NULL) {
+ jacDQ = FALSE;
+ bjac = jac;
+ } else {
+ jacDQ = TRUE;
+ }
+
+ return(KINDLS_SUCCESS);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * KINDlsGetWorkSpace
+ * -----------------------------------------------------------------
+ */
+
+int KINDlsGetWorkSpace(void *kinmem, long int *lenrwLS, long int *leniwLS)
+{
+ KINMem kin_mem;
+ KINDlsMem kindls_mem;
+
+ /* Return immediately if kinmem is NULL */
+ if (kinmem == NULL) {
+ KINProcessError(NULL, KINDLS_MEM_NULL, "KINDLS", "KINBandGetWorkSpace", 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);
+ return(KINDLS_LMEM_NULL);
+ }
+ kindls_mem = (KINDlsMem) lmem;
+
+ if (mtype == SUNDIALS_DENSE) {
+ *lenrwLS = n*n;
+ *leniwLS = n;
+ } else if (mtype == SUNDIALS_BAND) {
+ *lenrwLS = n*(smu + mu + 2*ml + 2);
+ *leniwLS = n;
+ }
+
+ return(KINDLS_SUCCESS);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * KINDlsGetNumJacEvals
+ * -----------------------------------------------------------------
+ */
+
+int KINDlsGetNumJacEvals(void *kinmem, long int *njevals)
+{
+ KINMem kin_mem;
+ KINDlsMem kindls_mem;
+
+ /* Return immediately if kinmem is NULL */
+ if (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);
+ return(KINDLS_LMEM_NULL);
+ }
+ kindls_mem = (KINDlsMem) lmem;
+
+ *njevals = nje;
+
+ return(KINDLS_SUCCESS);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * KINDlsGetNumFuncEvals
+ * -----------------------------------------------------------------
+ */
+
+int KINDlsGetNumFuncEvals(void *kinmem, long int *nfevalsLS)
+{
+ KINMem kin_mem;
+ KINDlsMem kindls_mem;
+
+ /* Return immediately if kinmem is NULL */
+ if (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);
+ return(KINDLS_LMEM_NULL);
+ }
+ kindls_mem = (KINDlsMem) lmem;
+
+ *nfevalsLS = nfeDQ;
+
+ return(KINDLS_SUCCESS);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * KINDlsGetLastFlag
+ * -----------------------------------------------------------------
+ */
+
+int KINDlsGetLastFlag(void *kinmem, long int *flag)
+{
+ KINMem kin_mem;
+ KINDlsMem kindls_mem;
+
+ /* Return immediately if kinmem is NULL */
+ if (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);
+ return(KINDLS_LMEM_NULL);
+ }
+ kindls_mem = (KINDlsMem) lmem;
+
+ *flag = last_flag;
+
+ return(KINDLS_SUCCESS);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * KINDlsGetReturnFlagName
+ * -----------------------------------------------------------------
+ */
+
+char *KINDlsGetReturnFlagName(long int flag)
+{
+ char *name;
+
+ name = (char *)malloc(30*sizeof(char));
+
+ switch(flag) {
+ case KINDLS_SUCCESS:
+ sprintf(name, "KINDLS_SUCCESS");
+ break;
+ case KINDLS_MEM_NULL:
+ sprintf(name, "KINDLS_MEM_NULL");
+ break;
+ case KINDLS_LMEM_NULL:
+ sprintf(name, "KINDLS_LMEM_NULL");
+ break;
+ case KINDLS_ILL_INPUT:
+ sprintf(name, "KINDLS_ILL_INPUT");
+ break;
+ case KINDLS_MEM_FAIL:
+ sprintf(name, "KINDLS_MEM_FAIL");
+ break;
+ default:
+ sprintf(name, "NONE");
+ }
+
+ return(name);
+}
+
+/*
+ * =================================================================
+ * DQ JACOBIAN APPROXIMATIONS
+ * =================================================================
+ */
+
+
+
+/*
+ * -----------------------------------------------------------------
+ * 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.
+ * -----------------------------------------------------------------
+ */
+
+int kinDlsDenseDQJac(long int N,
+ N_Vector u, N_Vector fu,
+ DlsMat Jac, void *data,
+ N_Vector tmp1, N_Vector tmp2)
+{
+ realtype inc, inc_inv, ujsaved, ujscale, sign;
+ realtype *tmp2_data, *u_data, *uscale_data;
+ N_Vector ftemp, jthCol;
+ int retval = 0;
+ long int j;
+
+ KINMem kin_mem;
+ KINDlsMem kindls_mem;
+
+ /* data points to kin_mem */
+ kin_mem = (KINMem) data;
+ kindls_mem = (KINDlsMem) lmem;
+
+ /* Save pointer to the array in tmp2 */
+ tmp2_data = N_VGetArrayPointer(tmp2);
+
+ /* Rename work vectors for readibility */
+ ftemp = tmp1;
+ jthCol = tmp2;
+
+ /* Obtain pointers to the data for u and uscale */
+ u_data = N_VGetArrayPointer(u);
+ uscale_data = N_VGetArrayPointer(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);
+
+ ujsaved = u_data[j];
+ ujscale = ONE/uscale_data[j];
+ sign = (ujsaved >= ZERO) ? ONE : -ONE;
+ inc = sqrt_relfunc*MAX(ABS(ujsaved), ujscale)*sign;
+ u_data[j] += inc;
+
+ retval = func(u, ftemp, user_data);
+ nfeDQ++;
+ if (retval != 0) break;
+
+ u_data[j] = ujsaved;
+
+ inc_inv = ONE/inc;
+ N_VLinearSum(inc_inv, ftemp, -inc_inv, fu, jthCol);
+
+ }
+
+ /* Restore original array pointer in tmp2 */
+ N_VSetArrayPointer(tmp2_data, tmp2);
+
+ 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)
+{
+ realtype inc, inc_inv;
+ N_Vector futemp, utemp;
+ int retval;
+ long int group, i, j, width, ngroups, i1, i2;
+ realtype *col_j, *fu_data, *futemp_data, *u_data, *utemp_data, *uscale_data;
+
+ KINMem kin_mem;
+ KINDlsMem kindls_mem;
+
+ /* data points to kinmem */
+ kin_mem = (KINMem) data;
+ kindls_mem = (KINDlsMem) lmem;
+
+ /* Rename work vectors for use as temporary values of u and fu */
+ futemp = tmp1;
+ utemp = tmp2;
+
+ /* Obtain pointers to the data for ewt, fy, futemp, y, ytemp */
+ 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);
+
+ /* Load utemp with u */
+ N_VScale(ONE, u, utemp);
+
+ /* Set bandwidth and number of column groups for band differencing */
+ width = mlower + mupper + 1;
+ ngroups = MIN(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*MAX(ABS(u_data[j]), ABS(uscale_data[j]));
+ utemp_data[j] += inc;
+ }
+
+ /* Evaluate f with incremented u */
+ retval = func(utemp, futemp, user_data);
+ if (retval != 0) return(-1);
+
+ /* 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*MAX(ABS(u_data[j]), ABS(uscale_data[j]));
+ inc_inv = ONE/inc;
+ i1 = MAX(0, j-mupper);
+ i2 = MIN(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]);
+ }
+ }
+
+ /* Increment counter nfeDQ */
+ nfeDQ += ngroups;
+
+ return(0);
+}
diff --git a/src/kinsol/kinsol_direct_impl.h b/src/kinsol/kinsol_direct_impl.h
new file mode 100644
index 0000000..c46a500
--- /dev/null
+++ b/src/kinsol/kinsol_direct_impl.h
@@ -0,0 +1,98 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.6 $
+ * $Date: 2010/12/01 22:43:33 $
+ * -----------------------------------------------------------------
+ * Programmer: Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2006, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * Common implementation header file for the KINDLS linear solvers.
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _KINDLS_IMPL_H
+#define _KINDLS_IMPL_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <kinsol/kinsol_direct.h>
+
+
+/*
+ * -----------------------------------------------------------------
+ * 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 */
+
+ 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) */
+
+ 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 d_nje; /* no. of calls to jac */
+
+ long int d_nfeDQ; /* no. of calls to F due to DQ Jacobian approx. */
+
+ long int d_last_flag; /* last error return flag */
+
+} *KINDlsMem;
+
+
+/*
+ * -----------------------------------------------------------------
+ * Prototypes of internal functions
+ * -----------------------------------------------------------------
+ */
+
+int kinDlsDenseDQJac(long int N,
+ N_Vector u, N_Vector fu,
+ DlsMat Jac, void *data,
+ 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);
+
+/*
+ * -----------------------------------------------------------------
+ * Error Messages
+ * -----------------------------------------------------------------
+ */
+
+#define MSGD_KINMEM_NULL "KINSOL memory is NULL."
+#define MSGD_BAD_NVECTOR "A required vector operation is not implemented."
+#define MSGD_MEM_FAIL "A memory request failed."
+#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."
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/kinsol/kinsol_impl.h b/src/kinsol/kinsol_impl.h
new file mode 100644
index 0000000..9943c00
--- /dev/null
+++ b/src/kinsol/kinsol_impl.h
@@ -0,0 +1,459 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.7 $
+ * $Date: 2009/03/29 23:28:01 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Allan Taylor, Alan Hindmarsh, Radu Serban, and
+ * Aaron Collier @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * KINSOL solver module header file (private version)
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _KINSOL_IMPL_H
+#define _KINSOL_IMPL_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <stdarg.h>
+
+#include <kinsol/kinsol.h>
+
+/*
+ * =================================================================
+ * M A I N S O L V E R M E M O R Y B L O C K
+ * =================================================================
+ */
+
+/* KINSOL default constants */
+
+#define PRINTFL_DEFAULT 0
+#define MXITER_DEFAULT 200
+#define MXNBCF_DEFAULT 10
+#define MSBSET_DEFAULT 10
+#define MSBSET_SUB_DEFAULT 5
+
+#define OMEGA_MIN RCONST(0.00001)
+#define OMEGA_MAX RCONST(0.9)
+
+/*
+ * -----------------------------------------------------------------
+ * Types : struct KINMemRec and struct *KINMem
+ * -----------------------------------------------------------------
+ * A variable declaration of type struct *KINMem denotes a
+ * pointer to a data structure of type struct KINMemRec. The
+ * KINMemRec structure contains numerous fields that must be
+ * accessible by KINSOL solver module routines.
+ * -----------------------------------------------------------------
+ */
+
+typedef struct KINMemRec {
+
+ realtype kin_uround; /* machine epsilon (or unit roundoff error)
+ (defined in sundials_types.h) */
+
+ /* problem specification data */
+
+ KINSysFn kin_func; /* nonlinear system function implementation */
+ void *kin_user_data; /* work space available to func routine */
+ realtype kin_fnormtol; /* stopping tolerance on L2-norm of function
+ value */
+ realtype kin_scsteptol; /* scaled step length tolerance */
+ int kin_globalstrategy; /* choices are KIN_NONE and KIN_LINESEARCH */
+ int kin_printfl; /* level of verbosity of output */
+ long int kin_mxiter; /* maximum number of nonlinear iterations */
+ long int kin_msbset; /* maximum number of nonlinear iterations that
+ may be performed between calls to the
+ linear solver setup routine (lsetup) */
+ long int kin_msbset_sub; /* subinterval length for residual monitoring */
+ long int kin_mxnbcf; /* maximum number of beta condition failures */
+ int kin_etaflag; /* choices are KIN_ETACONSTANT, KIN_ETACHOICE1
+ 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.
+ used by the linear solver is current */
+ booleantype kin_callForcingTerm; /* flag set if using either KIN_ETACHOICE1
+ or KIN_ETACHOICE2 */
+ booleantype kin_noResMon; /* flag indicating if the nonlinear
+ residual monitoring scheme should be
+ used */
+ booleantype kin_retry_nni; /* flag indicating if nonlinear iteration
+ should be retried (set by residual
+ monitoring algorithm) */
+ booleantype kin_update_fnorm_sub; /* flag indicating if the fnorm associated
+ with the subinterval needs to be
+ updated (set by residual monitoring
+ algorithm) */
+
+ realtype kin_mxnewtstep; /* maximum allowable scaled step length */
+ realtype kin_sqrt_relfunc; /* relative error bound for func(u) */
+ realtype kin_stepl; /* scaled length of current step */
+ realtype kin_stepmul; /* step scaling factor */
+ realtype kin_eps; /* current value of eps */
+ realtype kin_eta; /* current value of eta */
+ realtype kin_eta_gamma; /* gamma value used in eta calculation
+ (choice #2) */
+ realtype kin_eta_alpha; /* alpha value used in eta calculation
+ (choice #2) */
+ booleantype kin_noInitSetup; /* flag controlling whether or not the KINSol
+ routine makes an initial call to the
+ linear solver setup routine (lsetup) */
+ realtype kin_sthrsh; /* threshold value for calling the linear
+ solver setup routine */
+
+ /* counters */
+
+ long int kin_nni; /* number of nonlinear iterations */
+ long int kin_nfe; /* number of calls made to func routine */
+ long int kin_nnilset; /* value of nni counter when the linear solver
+ setup was last called */
+ long int kin_nnilset_sub; /* value of nni counter when the linear solver
+ setup was last called (subinterval) */
+ long int kin_nbcf; /* number of times the beta-condition could not
+ be met in KINLineSearch */
+ long int kin_nbktrk; /* number of backtracks performed by
+ KINLineSearch */
+ long int kin_ncscmx; /* number of consecutive steps of size
+ mxnewtstep taken */
+
+ /* vectors */
+
+ N_Vector kin_uu; /* solution vector/current iterate (initially
+ contains initial guess, but holds approximate
+ solution upon completion if no errors occurred) */
+ N_Vector kin_unew; /* next iterate (unew = uu+pp) */
+ N_Vector kin_fval; /* vector containing result of nonlinear system
+ function evaluated at a given iterate
+ (fval = func(uu)) */
+ N_Vector kin_uscale; /* iterate scaling vector */
+ N_Vector kin_fscale; /* fval scaling vector */
+ N_Vector kin_pp; /* incremental change vector (pp = unew-uu) */
+ N_Vector kin_constraints; /* constraints vector */
+ N_Vector kin_vtemp1; /* scratch vector #1 */
+ N_Vector kin_vtemp2; /* scratch vector #2 */
+
+ /* space requirements for vector storage */
+
+ long int 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
+ a single N_Vecotr */
+ long int kin_lrw; /* total number of realtype-sized memory blocks
+ needed for all KINSOL work vectors */
+ long int kin_liw; /* total number of int-sized memory blocks needed
+ for all KINSOL work vectors */
+
+ /* linear solver data */
+
+ /* function prototypes (pointers) */
+
+ int (*kin_linit)(struct KINMemRec *kin_mem);
+
+ int (*kin_lsetup)(struct KINMemRec *kin_mem);
+
+ int (*kin_lsolve)(struct KINMemRec *kin_mem, N_Vector xx, N_Vector bb,
+ realtype *res_norm );
+
+ void (*kin_lfree)(struct KINMemRec *kin_mem);
+
+ 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) */
+
+ void *kin_lmem; /* pointer to linear solver memory block */
+
+ realtype kin_fnorm; /* value of L2-norm of fscale*fval */
+ realtype kin_f1norm; /* f1norm = 0.5*(fnorm)^2 */
+ realtype kin_res_norm; /* value of L2-norm of residual (set by the linear
+ solver) */
+ realtype kin_sfdotJp; /* value of scaled func(u) vector (fscale*fval)
+ dotted with scaled J(u)*pp vector */
+ realtype kin_sJpnorm; /* value of L2-norm of fscale*(J(u)*pp) */
+
+ realtype kin_fnorm_sub; /* value of L2-norm of fscale*fval (subinterval) */
+ booleantype kin_eval_omega; /* flag indicating that omega must be evaluated. */
+ realtype kin_omega; /* constant value for real scalar used in test to
+ determine if reduction of norm of nonlinear
+ residual is sufficient. Unless a valid constant
+ value is specified by the user, omega is estimated
+ from omega_min and omega_max at each iteration. */
+ realtype kin_omega_min; /* lower bound on omega */
+ realtype kin_omega_max; /* upper bound on omega */
+
+ /*
+ * -----------------------------------------------------------------
+ * Note: The KINLineSearch subroutine scales the values of the
+ * variables sfdotJp and sJpnorm by a factor rl (lambda) that is
+ * chosen by the line search algorithm such that the sclaed Newton
+ * step satisfies the following conditions:
+ *
+ * F(u_k+1) <= F(u_k) + alpha*(F(u_k)^T * J(u_k))*p*rl
+ *
+ * F(u_k+1) >= F(u_k) + beta*(F(u_k)^T * J(u_k))*p*rl
+ *
+ * where alpha = 1.0e-4, beta = 0.9, u_k+1 = u_k + rl*p,
+ * 0 < rl <= 1, J denotes the system Jacobian, and F represents
+ * the nonliner system function.
+ * -----------------------------------------------------------------
+ */
+
+ booleantype kin_MallocDone; /* flag indicating if KINMalloc has been
+ called yet */
+
+ /* message files */
+ /*-------------------------------------------
+ Error handler function and error ouput file
+ -------------------------------------------*/
+
+ KINErrHandlerFn kin_ehfun; /* Error messages are handled by ehfun */
+ void *kin_eh_data; /* dats pointer passed to ehfun */
+ FILE *kin_errfp; /* KINSOL error messages are sent to errfp */
+
+ KINInfoHandlerFn kin_ihfun; /* Info messages are handled by ihfun */
+ void *kin_ih_data; /* dats pointer passed to ihfun */
+ FILE *kin_infofp; /* where KINSol info messages are sent */
+
+} *KINMem;
+
+/*
+ * =================================================================
+ * I N T E R F A C E T O L I N E A R S O L V E R
+ * =================================================================
+ */
+
+/*
+ * -----------------------------------------------------------------
+ * Function : int (*kin_linit)(KINMem kin_mem)
+ * -----------------------------------------------------------------
+ * kin_linit initializes solver-specific data structures (including
+ * variables used as counters or for storing statistical information),
+ * 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
+ * (predefined constant) and the kin_lsetup routine should be
+ * appropriately defined.
+ *
+ * kinmem pointer to an internal memory block allocated during
+ * prior calls to KINCreate and KINMalloc
+ *
+ * If the necessary variables have been successfully initialized,
+ * then the kin_linit function should return 0 (zero). Otherwise,
+ * the subroutine should indicate a failure has occurred by
+ * returning a non-zero integer value.
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * -----------------------------------------------------------------
+ * Function : int (*kin_lsetup)(KINMem kin_mem)
+ * -----------------------------------------------------------------
+ * kin_lsetup interfaces with the user-supplied pset subroutine (the
+ * preconditioner setup routine), and updates relevant variable
+ * values (see KINSpgmrSetup/KINSpbcgSetup). Simply stated, the
+ * kin_lsetup routine prepares the linear solver for a subsequent
+ * call to the user-supplied kin_lsolve function.
+ *
+ * kinmem pointer to an internal memory block allocated during
+ * prior calls to KINCreate and KINMalloc
+ *
+ * If successful, the kin_lsetup routine should return 0 (zero).
+ * Otherwise it should return a non-zero value.
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * -----------------------------------------------------------------
+ * Function : int (*kin_lsolve)(KINMem kin_mem, N_Vector xx,
+ * N_Vector bb, realtype *res_norm)
+ * -----------------------------------------------------------------
+ * kin_lsolve interfaces with the subroutine implementing the
+ * numerical method to be used to solve the linear system J*xx = bb,
+ * and must increment the relevant counter variable values in
+ * addition to computing certain values used by the global strategy
+ * and forcing term routines (see KINInexactNewton, KINLineSearch,
+ * KINForcingTerm, and KINSpgmrSolve/KINSpbcgSolve).
+ *
+ * kinmem pointer to an internal memory block allocated during
+ * prior calls to KINCreate and KINMalloc
+ *
+ * xx vector (type N_Vector) set to initial guess by kin_lsolve
+ * routine prior to calling the linear solver, but which upon
+ * return contains an approximate solution of the linear
+ * system J*xx = bb, where J denotes the system Jacobian
+ *
+ * bb vector (type N_Vector) set to -func(u) (negative of the
+ * value of the system function evaluated at the current
+ * iterate) by KINLinSolDrv before kin_lsolve is called
+ *
+ * res_norm holds the value of the L2-norm (Euclidean norm) of
+ * the residual vector upon return
+ *
+ * If successful, the kin_lsolve routine should return 0 (zero).
+ * Otherwise it should return a positive value if a re-evaluation
+ * of the lsetup function could recover, or a negative value if
+ * no such recovery is possible.
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * -----------------------------------------------------------------
+ * Function : void (*kin_lfree)(KINMem kin_mem)
+ * -----------------------------------------------------------------
+ * kin_lfree is called by KINFree and should free (deallocate) all
+ * system memory resources allocated for the linear solver module
+ * (see KINSpgmrFree/KINSpbcgFree).
+ *
+ * kinmem pointer to an internal memory block allocated during
+ * prior calls to KINCreate and KINMalloc
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * =================================================================
+ * K I N S O L I N T E R N A L F U N C T I O N S
+ * =================================================================
+ */
+
+
+/* High level error handler */
+
+void KINProcessError(KINMem kin_mem,
+ int error_code, const char *module, const char *fname,
+ const char *msgfmt, ...);
+
+/* Prototype of internal errHandler function */
+
+void KINErrHandler(int error_code, const char *module, const char *function,
+ char *msg, void *user_data);
+
+
+/* High level info handler */
+
+void KINPrintInfo(KINMem kin_mem,
+ int info_code, const char *module, const char *fname,
+ const char *msgfmt, ...);
+
+/* Prototype of internal infoHandler function */
+
+void KINInfoHandler(const char *module, const char *function,
+ char *msg, void *user_data);
+
+/*
+ * =================================================================
+ * K I N S O L E R R O R M E S S A G E S
+ * =================================================================
+ */
+
+#define MSG_MEM_FAIL "A memory request failed."
+#define MSG_NO_MEM "kinsol_mem = NULL illegal."
+#define MSG_BAD_NVECTOR "A required vector operation is not implemented."
+#define MSG_FUNC_NULL "func = NULL illegal."
+#define MSG_NO_MALLOC "Attempt to call before KINMalloc illegal."
+
+#define MSG_BAD_PRINTFL "Illegal value for printfl."
+#define MSG_BAD_MXITER "Illegal value for mxiter."
+#define MSG_BAD_MSBSET "Illegal msbset < 0."
+#define MSG_BAD_MSBSETSUB "Illegal msbsetsub < 0."
+#define MSG_BAD_ETACHOICE "Illegal value for etachoice."
+#define MSG_BAD_ETACONST "eta out of range."
+#define MSG_BAD_GAMMA "gamma out of range."
+#define MSG_BAD_ALPHA "alpha out of range."
+#define MSG_BAD_MXNEWTSTEP "Illegal mxnewtstep < 0."
+#define MSG_BAD_RELFUNC "relfunc < 0 illegal."
+#define MSG_BAD_FNORMTOL "fnormtol < 0 illegal."
+#define MSG_BAD_SCSTEPTOL "scsteptol < 0 illegal."
+#define MSG_BAD_MXNBCF "mxbcf < 0 illegal."
+#define MSG_BAD_CONSTRAINTS "Illegal values in constraints vector."
+#define MSG_BAD_OMEGA "scalars < 0 illegal."
+
+#define MSG_LSOLV_NO_MEM "The linear solver memory pointer is NULL."
+#define MSG_UU_NULL "uu = NULL illegal."
+#define MSG_BAD_GLSTRAT "Illegal value for global strategy."
+#define MSG_BAD_USCALE "uscale = NULL illegal."
+#define MSG_USCALE_NONPOSITIVE "uscale has nonpositive elements."
+#define MSG_BAD_FSCALE "fscale = NULL illegal."
+#define MSG_FSCALE_NONPOSITIVE "fscale has nonpositive elements."
+#define MSG_INITIAL_CNSTRNT "Initial guess does NOT meet constraints."
+#define MSG_LINIT_FAIL "The linear solver's init routine failed."
+
+#define MSG_SYSFUNC_FAILED "The system function failed in an unrecoverable manner."
+#define MSG_SYSFUNC_FIRST "The system function failed at the first call."
+#define MSG_LSETUP_FAILED "The linear solver's setup function failed in an unrecoverable manner."
+#define MSG_LSOLVE_FAILED "The linear solver's solve function failed in an unrecoverable manner."
+#define MSG_LINSOLV_NO_RECOVERY "The linear solver's solve function failed recoverably, but the Jacobian data is already current."
+#define MSG_LINESEARCH_NONCONV "The line search algorithm was unable to find an iterate sufficiently distinct from the current iterate."
+#define MSG_LINESEARCH_BCFAIL "The line search algorithm was unable to satisfy the beta-condition for nbcfails iterations."
+#define MSG_MAXITER_REACHED "The maximum number of iterations was reached before convergence."
+#define MSG_MXNEWT_5X_EXCEEDED "Five consecutive steps have been taken that satisfy a scaled step length test."
+#define MSG_SYSFUNC_REPTD "Unable to correct repeated recoverable system function errors."
+
+/*
+ * =================================================================
+ * K I N S O L I N F O M E S S A G E S
+ * =================================================================
+ */
+
+#define INFO_RETVAL "Return value: %d"
+#define INFO_ADJ "no. of lambda adjustments = %ld"
+
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+
+#define INFO_NNI "nni = %4ld nfe = %6ld fnorm = %26.16Lg"
+#define INFO_TOL "scsteptol = %12.3Lg fnormtol = %12.3Lg"
+#define INFO_FMAX "scaled f norm (for stopping) = %12.3Lg"
+#define INFO_PNORM "pnorm = %12.4Le"
+#define INFO_PNORM1 "(ivio=1) pnorm = %12.4Le"
+#define INFO_FNORM "fnorm(L2) = %20.8Le"
+#define INFO_LAM "min_lam = %11.4Le f1norm = %11.4Le pnorm = %11.4Le"
+#define INFO_ALPHA "fnorm = %15.8Le f1norm = %15.8Le alpha_cond = %15.8Le lam = %15.8Le"
+#define INFO_BETA "f1norm = %15.8Le beta_cond = %15.8Le lam = %15.8Le"
+#define INFO_ALPHABETA "f1norm = %15.8Le alpha_cond = %15.8Le beta_cond = %15.8Le lam = %15.8Le"
+
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+
+#define INFO_NNI "nni = %4ld nfe = %6ld fnorm = %26.16lg"
+#define INFO_TOL "scsteptol = %12.3lg fnormtol = %12.3lg"
+#define INFO_FMAX "scaled f norm (for stopping) = %12.3lg"
+#define INFO_PNORM "pnorm = %12.4le"
+#define INFO_PNORM1 "(ivio=1) pnorm = %12.4le"
+#define INFO_FNORM "fnorm(L2) = %20.8le"
+#define INFO_LAM "min_lam = %11.4le f1norm = %11.4le pnorm = %11.4le"
+#define INFO_ALPHA "fnorm = %15.8le f1norm = %15.8le alpha_cond = %15.8le lam = %15.8le"
+#define INFO_BETA "f1norm = %15.8le beta_cond = %15.8le lam = %15.8le"
+#define INFO_ALPHABETA "f1norm = %15.8le alpha_cond = %15.8le beta_cond = %15.8le lam = %15.8le"
+
+#else
+
+#define INFO_NNI "nni = %4ld nfe = %6ld fnorm = %26.16g"
+#define INFO_TOL "scsteptol = %12.3g fnormtol = %12.3g"
+#define INFO_FMAX "scaled f norm (for stopping) = %12.3g"
+#define INFO_PNORM "pnorm = %12.4e"
+#define INFO_PNORM1 "(ivio=1) pnorm = %12.4e"
+#define INFO_FNORM "fnorm(L2) = %20.8e"
+#define INFO_LAM "min_lam = %11.4e f1norm = %11.4e pnorm = %11.4e"
+#define INFO_ALPHA "fnorm = %15.8e f1norm = %15.8e alpha_cond = %15.8e lam = %15.8e"
+#define INFO_BETA "f1norm = %15.8e beta_cond = %15.8e lam = %15.8e"
+#define INFO_ALPHABETA "f1norm = %15.8e alpha_cond = %15.8e beta_cond = %15.8e lam = %15.8e"
+
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/kinsol/kinsol_io.c b/src/kinsol/kinsol_io.c
new file mode 100644
index 0000000..ec3a933
--- /dev/null
+++ b/src/kinsol/kinsol_io.c
@@ -0,0 +1,1000 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.8 $
+ * $Date: 2010/12/01 22:43:33 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Allan Taylor, Alan Hindmarsh, Radu Serban, and
+ * Aaron Collier @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * This is the implementation file for the optional input and output
+ * functions for the KINSOL solver.
+ * -----------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "kinsol_impl.h"
+#include <sundials/sundials_types.h>
+#include <sundials/sundials_math.h>
+
+#define ZERO RCONST(0.0)
+#define POINT1 RCONST(0.1)
+#define ONETHIRD RCONST(0.3333333333333333)
+#define HALF RCONST(0.5)
+#define TWOTHIRDS RCONST(0.6666666666666667)
+#define POINT9 RCONST(0.9)
+#define ONE RCONST(1.0)
+#define TWO RCONST(2.0)
+#define TWOPT5 RCONST(2.5)
+
+#define liw (kin_mem->kin_liw)
+#define lrw (kin_mem->kin_lrw)
+#define liw1 (kin_mem->kin_liw1)
+#define lrw1 (kin_mem->kin_lrw1)
+
+/*
+ * =================================================================
+ * KINSOL optional input functions
+ * =================================================================
+ */
+
+/*
+ * -----------------------------------------------------------------
+ * KINSetErrHandlerFn
+ * -----------------------------------------------------------------
+ */
+
+int KINSetErrHandlerFn(void *kinmem, KINErrHandlerFn ehfun, void *eh_data)
+{
+ KINMem kin_mem;
+
+ if (kinmem == NULL) {
+ KINProcessError(NULL, KIN_MEM_NULL, "KINSOL", "KINSetErrHandlerFn", MSG_NO_MEM);
+ return(KIN_MEM_NULL);
+ }
+
+ kin_mem = (KINMem) kinmem;
+
+ kin_mem->kin_ehfun = ehfun;
+ kin_mem->kin_eh_data = eh_data;
+
+ return(KIN_SUCCESS);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Function : KINSetErrFile
+ * -----------------------------------------------------------------
+ */
+
+int KINSetErrFile(void *kinmem, FILE *errfp)
+{
+ KINMem kin_mem;
+
+ if (kinmem == NULL) {
+ KINProcessError(NULL, KIN_MEM_NULL, "KINSOL", "KINSetErrFile", MSG_NO_MEM);
+ return(KIN_MEM_NULL);
+ }
+
+ kin_mem = (KINMem) kinmem;
+ kin_mem->kin_errfp = errfp;
+
+ return(KIN_SUCCESS);
+}
+
+#define errfp (kin_mem->kin_errfp)
+
+/*
+ * -----------------------------------------------------------------
+ * Function : KINSetPrintLevel
+ * -----------------------------------------------------------------
+ */
+
+int KINSetPrintLevel(void *kinmem, int printfl)
+{
+ KINMem kin_mem;
+
+ if (kinmem == NULL) {
+ KINProcessError(NULL, KIN_MEM_NULL, "KINSOL", "KINSetPrintLevel", MSG_NO_MEM);
+ return(KIN_MEM_NULL);
+ }
+
+ kin_mem = (KINMem) kinmem;
+
+ if ((printfl < 0) || (printfl > 3)) {
+ KINProcessError(NULL, KIN_ILL_INPUT, "KINSOL", "KINSetPrintLevel", MSG_BAD_PRINTFL);
+ return(KIN_ILL_INPUT);
+ }
+
+ kin_mem->kin_printfl = printfl;
+
+ return(KIN_SUCCESS);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * KINSetInfoHandlerFn
+ * -----------------------------------------------------------------
+ */
+
+int KINSetInfoHandlerFn(void *kinmem, KINInfoHandlerFn ihfun, void *ih_data)
+{
+ KINMem kin_mem;
+
+ if (kinmem == NULL) {
+ KINProcessError(NULL, KIN_MEM_NULL, "KINSOL", "KINSetInfoHandlerFn", MSG_NO_MEM);
+ return(KIN_MEM_NULL);
+ }
+
+ kin_mem = (KINMem) kinmem;
+
+ kin_mem->kin_ihfun = ihfun;
+ kin_mem->kin_ih_data = ih_data;
+
+ return(KIN_SUCCESS);
+}
+
+
+/*
+ * -----------------------------------------------------------------
+ * Function : KINSetInfoFile
+ * -----------------------------------------------------------------
+ */
+
+int KINSetInfoFile(void *kinmem, FILE *infofp)
+{
+ KINMem kin_mem;
+
+ if (kinmem == NULL) {
+ KINProcessError(NULL, KIN_MEM_NULL, "KINSOL", "KINSetInfoFile", MSG_NO_MEM);
+ return(KIN_MEM_NULL);
+ }
+
+ kin_mem = (KINMem) kinmem;
+ kin_mem->kin_infofp = infofp;
+
+ return(KIN_SUCCESS);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Function : KINSetUserData
+ * -----------------------------------------------------------------
+ */
+
+int KINSetUserData(void *kinmem, void *user_data)
+{
+ KINMem kin_mem;
+
+ if (kinmem == NULL) {
+ KINProcessError(NULL, KIN_MEM_NULL, "KINSOL", "KINSetUserData", MSG_NO_MEM);
+ return(KIN_MEM_NULL);
+ }
+
+ kin_mem = (KINMem) kinmem;
+ kin_mem->kin_user_data = user_data;
+
+ return(KIN_SUCCESS);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Function : KINSetNumMaxIters
+ * -----------------------------------------------------------------
+ */
+
+int KINSetNumMaxIters(void *kinmem, long int mxiter)
+{
+ KINMem kin_mem;
+
+ if (kinmem == NULL) {
+ KINProcessError(NULL, KIN_MEM_NULL, "KINSOL", "KINSetNumMaxIters", MSG_NO_MEM);
+ return(KIN_MEM_NULL);
+ }
+
+ kin_mem = (KINMem) kinmem;
+
+ if (mxiter < 0) {
+ KINProcessError(NULL, KIN_ILL_INPUT, "KINSOL", "KINSetNumMaxIters", MSG_BAD_MXITER);
+ return(KIN_ILL_INPUT);
+ }
+
+ if (mxiter == 0)
+ kin_mem->kin_mxiter = MXITER_DEFAULT;
+ else
+ kin_mem->kin_mxiter = mxiter;
+
+ return(KIN_SUCCESS);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Function : KINSetNoInitSetup
+ * -----------------------------------------------------------------
+ */
+
+int KINSetNoInitSetup(void *kinmem, booleantype noInitSetup)
+{
+ KINMem kin_mem;
+
+ if (kinmem == NULL) {
+ KINProcessError(NULL, KIN_MEM_NULL, "KINSOL", "KINSetNoInitSetup", MSG_NO_MEM);
+ return(KIN_MEM_NULL);
+ }
+
+ kin_mem = (KINMem) kinmem;
+ kin_mem->kin_noInitSetup = noInitSetup;
+
+ return(KIN_SUCCESS);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Function : KINSetNoResMon
+ * -----------------------------------------------------------------
+ */
+
+int KINSetNoResMon(void *kinmem, booleantype noResMon)
+{
+ KINMem kin_mem;
+
+ if (kinmem == NULL) {
+ KINProcessError(NULL, KIN_MEM_NULL, "KINSOL", "KINSetNoResMon", MSG_NO_MEM);
+ return(KIN_MEM_NULL);
+ }
+
+ kin_mem = (KINMem) kinmem;
+ kin_mem->kin_noResMon = noResMon;
+
+ return(KIN_SUCCESS);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Function : KINSetMaxSetupCalls
+ * -----------------------------------------------------------------
+ */
+
+int KINSetMaxSetupCalls(void *kinmem, long int msbset)
+{
+ KINMem kin_mem;
+
+ if (kinmem == NULL) {
+ KINProcessError(NULL, KIN_MEM_NULL, "KINSOL", "KINSetMaxSetupCalls", MSG_NO_MEM);
+ return(KIN_MEM_NULL);
+ }
+
+ kin_mem = (KINMem) kinmem;
+
+ if (msbset < 0) {
+ KINProcessError(NULL, KIN_ILL_INPUT, "KINSOL", "KINSetMaxSetupCalls", MSG_BAD_MSBSET);
+ return(KIN_ILL_INPUT);
+ }
+
+ if (msbset == 0)
+ kin_mem->kin_msbset = MSBSET_DEFAULT;
+ else
+ kin_mem->kin_msbset = msbset;
+
+ return(KIN_SUCCESS);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Function : KINSetMaxSubSetupCalls
+ * -----------------------------------------------------------------
+ */
+
+int KINSetMaxSubSetupCalls(void *kinmem, long int msbsetsub)
+{
+ KINMem kin_mem;
+
+ if (kinmem == NULL) {
+ KINProcessError(NULL, KIN_MEM_NULL, "KINSOL", "KINSetMaxSubSetupCalls", MSG_NO_MEM);
+ return(KIN_MEM_NULL);
+ }
+
+ kin_mem = (KINMem) kinmem;
+
+ if (msbsetsub < 0) {
+ KINProcessError(NULL, KIN_ILL_INPUT, "KINSOL", "KINSetMaxSubSetupCalls", MSG_BAD_MSBSETSUB);
+ return(KIN_ILL_INPUT);
+ }
+
+ if (msbsetsub == 0)
+ kin_mem->kin_msbset_sub = MSBSET_SUB_DEFAULT;
+ else
+ kin_mem->kin_msbset_sub = msbsetsub;
+
+ return(KIN_SUCCESS);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Function : KINSetEtaForm
+ * -----------------------------------------------------------------
+ */
+
+int KINSetEtaForm(void *kinmem, int etachoice)
+{
+ KINMem kin_mem;
+
+ if (kinmem == NULL) {
+ KINProcessError(NULL, KIN_MEM_NULL, "KINSOL", "KINSetEtaForm", MSG_NO_MEM);
+ return(KIN_MEM_NULL);
+ }
+
+ kin_mem = (KINMem) kinmem;
+
+ if ((etachoice != KIN_ETACONSTANT) &&
+ (etachoice != KIN_ETACHOICE1) &&
+ (etachoice != KIN_ETACHOICE2)) {
+ KINProcessError(NULL, KIN_ILL_INPUT, "KINSOL", "KINSetEtaForm", MSG_BAD_ETACHOICE);
+ return(KIN_ILL_INPUT);
+ }
+
+ kin_mem->kin_etaflag = etachoice;
+
+ return(KIN_SUCCESS);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Function : KINSetEtaConstValue
+ * -----------------------------------------------------------------
+ */
+
+int KINSetEtaConstValue(void *kinmem, realtype eta)
+{
+ KINMem kin_mem;
+
+ if (kinmem == NULL) {
+ KINProcessError(NULL, KIN_MEM_NULL, "KINSOL", "KINSetEtaConstValue", MSG_NO_MEM);
+ return(KIN_MEM_NULL);
+ }
+
+ kin_mem = (KINMem) kinmem;
+
+ if ((eta < ZERO) || (eta > ONE)) {
+ KINProcessError(NULL, KIN_ILL_INPUT, "KINSOL", "KINSetEtaConstValue", MSG_BAD_ETACONST);
+ return(KIN_ILL_INPUT);
+ }
+
+ if (eta == ZERO)
+ kin_mem->kin_eta = POINT1;
+ else
+ kin_mem->kin_eta = eta;
+
+ return(KIN_SUCCESS);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Function : KINSetEtaParams
+ * -----------------------------------------------------------------
+ */
+
+int KINSetEtaParams(void *kinmem, realtype egamma, realtype ealpha)
+{
+ KINMem kin_mem;
+
+ if (kinmem == NULL) {
+ KINProcessError(NULL, KIN_MEM_NULL, "KINSOL", "KINSetEtaParams", MSG_NO_MEM);
+ return(KIN_MEM_NULL);
+ }
+
+ kin_mem = (KINMem) kinmem;
+
+ if ((ealpha <= ONE) || (ealpha > TWO))
+ if (ealpha != ZERO) {
+ KINProcessError(NULL, KIN_ILL_INPUT, "KINSOL", "KINSetEtaParams", MSG_BAD_ALPHA);
+ return(KIN_ILL_INPUT);
+ }
+
+ if (ealpha == ZERO)
+ kin_mem->kin_eta_alpha = TWO;
+ else
+ kin_mem->kin_eta_alpha = ealpha;
+
+ if ((egamma <= ZERO) || (egamma > ONE))
+ if (egamma != ZERO) {
+ KINProcessError(NULL, KIN_ILL_INPUT, "KINSOL", "KINSetEtaParams", MSG_BAD_GAMMA);
+ return(KIN_ILL_INPUT);
+ }
+
+ if (egamma == ZERO)
+ kin_mem->kin_eta_gamma = POINT9;
+ else
+ kin_mem->kin_eta_gamma = egamma;
+
+ return(KIN_SUCCESS);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Function : KINSetResMonParams
+ * -----------------------------------------------------------------
+ */
+
+int KINSetResMonParams(void *kinmem, realtype omegamin, realtype omegamax)
+{
+ KINMem kin_mem;
+
+ if (kinmem == NULL) {
+ KINProcessError(NULL, KIN_MEM_NULL, "KINSOL", "KINSetResMonParams", MSG_NO_MEM);
+ return(KIN_MEM_NULL);
+ }
+
+ kin_mem = (KINMem) kinmem;
+
+ /* check omegamin */
+
+ if (omegamin < ZERO) {
+ KINProcessError(NULL, KIN_ILL_INPUT, "KINSOL", "KINSetResMonParams", MSG_BAD_OMEGA);
+ return(KIN_ILL_INPUT);
+ }
+
+ if (omegamin == ZERO)
+ kin_mem->kin_omega_min = OMEGA_MIN;
+ else
+ kin_mem->kin_omega_min = omegamin;
+
+ /* check omegamax */
+
+ if (omegamax < ZERO) {
+ KINProcessError(NULL, KIN_ILL_INPUT, "KINSOL", "KINSetResMonParams", MSG_BAD_OMEGA);
+ return(KIN_ILL_INPUT);
+ }
+
+ if (omegamax == ZERO) {
+
+ if (kin_mem->kin_omega_min > OMEGA_MAX) {
+ KINProcessError(NULL, KIN_ILL_INPUT, "KINSOL", "KINSetResMonParams", MSG_BAD_OMEGA);
+ return(KIN_ILL_INPUT);
+ }
+ else kin_mem->kin_omega_max = OMEGA_MAX;
+
+ } else {
+
+ if (kin_mem->kin_omega_min > omegamax) {
+ KINProcessError(NULL, KIN_ILL_INPUT, "KINSOL", "KINSetResMonParams", MSG_BAD_OMEGA);
+ return(KIN_ILL_INPUT);
+ }
+ else kin_mem->kin_omega_max = omegamax;
+
+ }
+
+ return(KIN_SUCCESS);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Function : KINSetResMonConstValue
+ * -----------------------------------------------------------------
+ */
+
+int KINSetResMonConstValue(void *kinmem, realtype omegaconst)
+{
+ KINMem kin_mem;
+
+ if (kinmem == NULL) {
+ KINProcessError(NULL, KIN_MEM_NULL, "KINSOL", "KINSetResMonConstValue", MSG_NO_MEM);
+ return(KIN_MEM_NULL);
+ }
+
+ kin_mem = (KINMem) kinmem;
+
+ /* check omegaconst */
+
+ if (omegaconst < ZERO) {
+ KINProcessError(NULL, KIN_ILL_INPUT, "KINSOL", "KINSetResMonConstValue", MSG_BAD_OMEGA);
+ return(KIN_ILL_INPUT);
+ }
+
+ /* Load omega value. A value of 0 will force using omega_min and omega_max */
+ kin_mem->kin_omega = omegaconst;
+
+ return(KIN_SUCCESS);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Function : KINSetNoMinEps
+ * -----------------------------------------------------------------
+ */
+
+int KINSetNoMinEps(void *kinmem, booleantype noMinEps)
+{
+ KINMem kin_mem;
+
+ if (kinmem == NULL) {
+ KINProcessError(NULL, KIN_MEM_NULL, "KINSOL", "KINSetNoMinEps", MSG_NO_MEM);
+ return(KIN_MEM_NULL);
+ }
+
+ kin_mem = (KINMem) kinmem;
+ kin_mem->kin_noMinEps = noMinEps;
+
+ return(KIN_SUCCESS);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Function : KINSetMaxNewtonStep
+ * -----------------------------------------------------------------
+ */
+
+int KINSetMaxNewtonStep(void *kinmem, realtype mxnewtstep)
+{
+ KINMem kin_mem;
+
+ if (kinmem == NULL) {
+ KINProcessError(NULL, KIN_MEM_NULL, "KINSOL", "KINSetMaxNewtonStep", MSG_NO_MEM);
+ return(KIN_MEM_NULL);
+ }
+
+ kin_mem = (KINMem) kinmem;
+
+ if (mxnewtstep < ZERO) {
+ KINProcessError(NULL, KIN_ILL_INPUT, "KINSOL", "KINSetMaxNewtonStep", MSG_BAD_MXNEWTSTEP);
+ return(KIN_ILL_INPUT);
+ }
+
+ /* Note: passing a value of 0.0 will use the default
+ value (computed in KINSolinit) */
+
+ kin_mem->kin_mxnewtstep = mxnewtstep;
+
+ return(KIN_SUCCESS);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Function : KINSetMaxBetaFails
+ * -----------------------------------------------------------------
+ */
+
+int KINSetMaxBetaFails(void *kinmem, long int mxnbcf)
+{
+ KINMem kin_mem;
+
+ if (kinmem == NULL) {
+ KINProcessError(NULL, KIN_MEM_NULL, "KINSOL", "KINSetMaxBetaFails", MSG_NO_MEM);
+ return(KIN_MEM_NULL);
+ }
+
+ kin_mem = (KINMem) kinmem;
+
+ if (mxnbcf < 0) {
+ KINProcessError(NULL, KIN_ILL_INPUT, "KINSOL", "KINSetMaxBetaFails", MSG_BAD_MXNBCF);
+ return(KIN_ILL_INPUT);
+ }
+
+ if (mxnbcf == 0)
+ kin_mem->kin_mxnbcf = MXNBCF_DEFAULT;
+ else
+ kin_mem->kin_mxnbcf = mxnbcf;
+
+ return(KIN_SUCCESS);
+
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Function : KINSetRelErrFunc
+ * -----------------------------------------------------------------
+ */
+
+int KINSetRelErrFunc(void *kinmem, realtype relfunc)
+{
+ KINMem kin_mem;
+ realtype uround;
+
+ if (kinmem == NULL) {
+ KINProcessError(NULL, KIN_MEM_NULL, "KINSOL", "KINSetRelErrFunc", MSG_NO_MEM);
+ return(KIN_MEM_NULL);
+ }
+
+ kin_mem = (KINMem) kinmem;
+
+ if (relfunc < ZERO) {
+ KINProcessError(NULL, KIN_ILL_INPUT, "KINSOL", "KINSetRelErrFunc", MSG_BAD_RELFUNC);
+ return(KIN_ILL_INPUT);
+ }
+
+ if (relfunc == ZERO) {
+ uround = kin_mem->kin_uround;
+ kin_mem->kin_sqrt_relfunc = RSqrt(uround);
+ } else {
+ kin_mem->kin_sqrt_relfunc = RSqrt(relfunc);
+ }
+
+ return(KIN_SUCCESS);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Function : KINSetFuncNormTol
+ * -----------------------------------------------------------------
+ */
+
+int KINSetFuncNormTol(void *kinmem, realtype fnormtol)
+{
+ KINMem kin_mem;
+ realtype uround;
+
+ if (kinmem == NULL) {
+ KINProcessError(NULL, KIN_MEM_NULL, "KINSOL", "KINSetFuncNormTol", MSG_NO_MEM);
+ return(KIN_MEM_NULL);
+ }
+
+ kin_mem = (KINMem) kinmem;
+
+ if (fnormtol < ZERO) {
+ KINProcessError(NULL, KIN_ILL_INPUT, "KINSOL", "KINSetFuncNormTol", MSG_BAD_FNORMTOL);
+ return(KIN_ILL_INPUT);
+ }
+
+ if (fnormtol == ZERO) {
+ uround = kin_mem->kin_uround;
+ kin_mem->kin_fnormtol = RPowerR(uround,ONETHIRD);
+ } else {
+ kin_mem->kin_fnormtol = fnormtol;
+ }
+
+ return(KIN_SUCCESS);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Function : KINSetScaledStepTol
+ * -----------------------------------------------------------------
+ */
+
+int KINSetScaledStepTol(void *kinmem, realtype scsteptol)
+{
+ KINMem kin_mem;
+ realtype uround;
+
+ if (kinmem == NULL) {
+ KINProcessError(NULL, KIN_MEM_NULL, "KINSOL", "KINSetScaledStepTol", MSG_NO_MEM);
+ return(KIN_MEM_NULL);
+ }
+
+ kin_mem = (KINMem) kinmem;
+
+ if (scsteptol < ZERO) {
+ KINProcessError(NULL, KIN_ILL_INPUT, "KINSOL", "KINSetScaledStepTol", MSG_BAD_SCSTEPTOL);
+ return(KIN_ILL_INPUT);
+ }
+
+ if (scsteptol == ZERO) {
+ uround = kin_mem->kin_uround;
+ kin_mem->kin_scsteptol = RPowerR(uround,TWOTHIRDS);
+ } else {
+ kin_mem->kin_scsteptol = scsteptol;
+ }
+
+ return(KIN_SUCCESS);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Function : KINSetConstraints
+ * -----------------------------------------------------------------
+ */
+
+int KINSetConstraints(void *kinmem, N_Vector constraints)
+{
+ KINMem kin_mem;
+ realtype temptest;
+
+ if (kinmem == NULL) {
+ KINProcessError(NULL, KIN_MEM_NULL, "KINSOL", "KINSetConstraints", MSG_NO_MEM);
+ return(KIN_MEM_NULL);
+ }
+
+ kin_mem = (KINMem) kinmem;
+
+ if (constraints == NULL) {
+ if (kin_mem->kin_constraintsSet) {
+ N_VDestroy(kin_mem->kin_constraints);
+ lrw -= lrw1;
+ liw -= liw1;
+ }
+ kin_mem->kin_constraintsSet = FALSE;
+ return(KIN_SUCCESS);
+ }
+
+ /* Check the constraints vector */
+
+ temptest = N_VMaxNorm(constraints);
+ if (temptest > TWOPT5){
+ KINProcessError(NULL, KIN_ILL_INPUT, "KINSOL", "KINSetConstraints", MSG_BAD_CONSTRAINTS);
+ return(KIN_ILL_INPUT);
+ }
+
+ if (!kin_mem->kin_constraintsSet) {
+ kin_mem->kin_constraints = N_VClone(constraints);
+ lrw += lrw1;
+ liw += liw1;
+ kin_mem->kin_constraintsSet = TRUE;
+ }
+
+ /* Load the constraint vector */
+
+ N_VScale(ONE, constraints, kin_mem->kin_constraints);
+
+ return(KIN_SUCCESS);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Function : KINSetSysFunc
+ * -----------------------------------------------------------------
+ */
+
+int KINSetSysFunc(void *kinmem, KINSysFn func)
+{
+ KINMem kin_mem;
+
+ if (kinmem == NULL) {
+ KINProcessError(NULL, KIN_MEM_NULL, "KINSOL", "KINSetSysFunc", MSG_NO_MEM);
+ return(KIN_MEM_NULL);
+ }
+
+ kin_mem = (KINMem) kinmem;
+
+ if (func == NULL) {
+ KINProcessError(NULL, KIN_ILL_INPUT, "KINSOL", "KINSetSysFunc", MSG_FUNC_NULL);
+ return(KIN_ILL_INPUT);
+ }
+
+ kin_mem->kin_func = func;
+
+ return(KIN_SUCCESS);
+}
+
+/*
+ * =================================================================
+ * Readability constants
+ * =================================================================
+ */
+
+#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 stepl (kin_mem->kin_stepl)
+#define fnorm (kin_mem->kin_fnorm)
+#define liw (kin_mem->kin_liw)
+#define lrw (kin_mem->kin_lrw)
+
+/*
+ * =================================================================
+ * KINSOL optional input functions
+ * =================================================================
+ */
+
+/*
+ * -----------------------------------------------------------------
+ * Function : KINGetWorkSpace
+ * -----------------------------------------------------------------
+ */
+
+int KINGetWorkSpace(void *kinmem, long int *lenrw, long int *leniw)
+{
+ KINMem kin_mem;
+
+ if (kinmem == NULL) {
+ KINProcessError(NULL, KIN_MEM_NULL, "KINSOL", "KINGetWorkSpace", MSG_NO_MEM);
+ return(KIN_MEM_NULL);
+ }
+
+ kin_mem = (KINMem) kinmem;
+
+ *lenrw = lrw;
+ *leniw = liw;
+
+ return(KIN_SUCCESS);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Function : KINGetNumNonlinSolvIters
+ * -----------------------------------------------------------------
+ */
+
+int KINGetNumNonlinSolvIters(void *kinmem, long int *nniters)
+{
+ KINMem kin_mem;
+
+ if (kinmem == NULL) {
+ KINProcessError(NULL, KIN_MEM_NULL, "KINSOL", "KINGetNumNonlinSolvIters", MSG_NO_MEM);
+ return(KIN_MEM_NULL);
+ }
+
+ kin_mem = (KINMem) kinmem;
+ *nniters = nni;
+
+ return(KIN_SUCCESS);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Function : KINGetNumFuncEvals
+ * -----------------------------------------------------------------
+ */
+
+int KINGetNumFuncEvals(void *kinmem, long int *nfevals)
+{
+ KINMem kin_mem;
+
+ if (kinmem == NULL) {
+ KINProcessError(NULL, KIN_MEM_NULL, "KINSOL", "KINGetNumFuncEvals", MSG_NO_MEM);
+ return(KIN_MEM_NULL);
+ }
+
+ kin_mem = (KINMem) kinmem;
+ *nfevals = nfe;
+
+ return(KIN_SUCCESS);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Function : KINGetNumBetaCondFails
+ * -----------------------------------------------------------------
+ */
+
+int KINGetNumBetaCondFails(void *kinmem, long int *nbcfails)
+{
+ KINMem kin_mem;
+
+ if (kinmem == NULL) {
+ KINProcessError(NULL, KIN_MEM_NULL, "KINSOL", "KINGetNumBetaCondFails", MSG_NO_MEM);
+ return(KIN_MEM_NULL);
+ }
+
+ kin_mem = (KINMem) kinmem;
+ *nbcfails = nbcf;
+
+ return(KIN_SUCCESS);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Function : KINGetNumBacktrackOps
+ * -----------------------------------------------------------------
+ */
+
+int KINGetNumBacktrackOps(void *kinmem, long int *nbacktr)
+{
+ KINMem kin_mem;
+
+ if (kinmem == NULL) {
+ KINProcessError(NULL, KIN_MEM_NULL, "KINSOL", "KINGetNumBacktrackOps", MSG_NO_MEM);
+ return(KIN_MEM_NULL);
+ }
+
+ kin_mem = (KINMem) kinmem;
+ *nbacktr = nbktrk;
+
+ return(KIN_SUCCESS);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Function : KINGetFuncNorm
+ * -----------------------------------------------------------------
+ */
+
+int KINGetFuncNorm(void *kinmem, realtype *funcnorm)
+{
+ KINMem kin_mem;
+
+ if (kinmem == NULL) {
+ KINProcessError(NULL, KIN_MEM_NULL, "KINSOL", "KINGetFuncNorm", MSG_NO_MEM);
+ return(KIN_MEM_NULL);
+ }
+
+ kin_mem = (KINMem) kinmem;
+ *funcnorm = fnorm;
+
+ return(KIN_SUCCESS);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Function : KINGetStepLength
+ * -----------------------------------------------------------------
+ */
+
+int KINGetStepLength(void *kinmem, realtype *steplength)
+{
+ KINMem kin_mem;
+
+ if (kinmem == NULL) {
+ KINProcessError(NULL, KIN_MEM_NULL, "KINSOL", "KINGetStepLength", MSG_NO_MEM);
+ return(KIN_MEM_NULL);
+ }
+
+ kin_mem = (KINMem) kinmem;
+ *steplength = stepl;
+
+ return(KIN_SUCCESS);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Function : KINGetReturnFlagName
+ * -----------------------------------------------------------------
+ */
+
+char *KINGetReturnFlagName(long int flag)
+{
+ char *name;
+
+ name = (char *)malloc(24*sizeof(char));
+
+ switch(flag) {
+ case KIN_SUCCESS:
+ sprintf(name, "KIN_SUCCESS");
+ break;
+ case KIN_INITIAL_GUESS_OK:
+ sprintf(name, "KIN_INITIAL_GUESS_OK");
+ break;
+ case KIN_STEP_LT_STPTOL:
+ sprintf(name, "KIN_STEP_LT_STPTOL");
+ break;
+ case KIN_WARNING:
+ sprintf(name, "KIN_WARNING");
+ break;
+ case KIN_MEM_NULL:
+ sprintf(name, "KIN_MEM_NULL");
+ break;
+ case KIN_ILL_INPUT:
+ sprintf(name, "KIN_ILL_INPUT");
+ break;
+ case KIN_NO_MALLOC:
+ sprintf(name, "KIN_NO_MALLOC");
+ break;
+ case KIN_MEM_FAIL:
+ sprintf(name, "KIN_MEM_FAIL");
+ break;
+ case KIN_LINESEARCH_NONCONV:
+ sprintf(name, "KIN_LINESEARCH_NONCONV");
+ break;
+ case KIN_MAXITER_REACHED:
+ sprintf(name, "KIN_MAXITER_REACHED");
+ break;
+ case KIN_MXNEWT_5X_EXCEEDED:
+ sprintf(name, "KIN_MXNEWT_5X_EXCEEDED");
+ break;
+ case KIN_LINESEARCH_BCFAIL:
+ sprintf(name, "KIN_LINESEARCH_BCFAIL");
+ break;
+ case KIN_LINSOLV_NO_RECOVERY:
+ sprintf(name, "KIN_LINSOLV_NO_RECOVERY");
+ break;
+ case KIN_LINIT_FAIL:
+ sprintf(name, "KIN_LINIT_FAIL");
+ break;
+ case KIN_LSETUP_FAIL:
+ sprintf(name, "KIN_LSETUP_FAIL");
+ break;
+ case KIN_LSOLVE_FAIL:
+ sprintf(name, "KIN_LSOLVE_FAIL");
+ break;
+ default:
+ sprintf(name, "NONE");
+ }
+
+ return(name);
+}
diff --git a/src/kinsol/kinsol_lapack.c b/src/kinsol/kinsol_lapack.c
new file mode 100644
index 0000000..08fa4b3
--- /dev/null
+++ b/src/kinsol/kinsol_lapack.c
@@ -0,0 +1,611 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.11 $
+ * $Date: 2011/02/16 22:43:28 $
+ * -----------------------------------------------------------------
+ * Programmer: Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2006, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * 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 *res_norm);
+static void 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 *res_norm);
+static void 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 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
+ * =================================================================
+ */
+
+/*
+ * -----------------------------------------------------------------
+ * 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;
+
+ 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;
+
+ 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 = MIN(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, "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;
+
+ nje = 0;
+ nfeDQ = 0;
+
+ 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.
+ * -----------------------------------------------------------------
+ */
+
+static int kinLapackDenseSolve(KINMem kin_mem, N_Vector x, N_Vector b, realtype *res_norm)
+{
+ 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 terms Jpnorm and sfdotJp for use in the global strategy
+ * routines and in KINForcingTerm. Both of these terms are subsequently
+ * corrected if the step is reduced by constraints or the line search.
+ *
+ * sJpnorm is the norm of the scaled product (scaled by fscale) of
+ * the current Jacobian matrix J and the step vector p.
+ *
+ * sfdotJp is the dot product of the scaled f vector and the scaled
+ * vector J*p, where the scaling uses fscale.
+ */
+ sJpnorm = N_VWL2Norm(b,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 void kinLapackDenseFree(KINMem kin_mem)
+{
+ KINDlsMem kindls_mem;
+
+ kindls_mem = (KINDlsMem) lmem;
+
+ DestroyMat(J);
+ DestroyArray(pivots);
+ free(kindls_mem); kindls_mem = NULL;
+}
+
+
+/*
+ * =================================================================
+ * 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;
+
+ nje = 0;
+ nfeDQ = 0;
+
+ 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.
+ * -----------------------------------------------------------------
+ */
+
+static int kinLapackBandSolve(KINMem kin_mem, N_Vector x, N_Vector b, realtype *res_norm)
+{
+ 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 terms Jpnorm and sfdotJp for use in the global strategy
+ * routines and in KINForcingTerm. Both of these terms are subsequently
+ * corrected if the step is reduced by constraints or the line search.
+ *
+ * sJpnorm is the norm of the scaled product (scaled by fscale) of
+ * the current Jacobian matrix J and the step vector p.
+ *
+ * sfdotJp is the dot product of the scaled f vector and the scaled
+ * vector J*p, where the scaling uses fscale.
+ */
+ sJpnorm = N_VWL2Norm(b,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 void kinLapackBandFree(KINMem kin_mem)
+{
+ KINDlsMem kindls_mem;
+
+ kindls_mem = (KINDlsMem) lmem;
+
+ DestroyMat(J);
+ DestroyArray(pivots);
+ free(kindls_mem); kindls_mem = NULL;
+}
diff --git a/src/kinsol/kinsol_spbcgs.c b/src/kinsol/kinsol_spbcgs.c
new file mode 100644
index 0000000..70a4a7e
--- /dev/null
+++ b/src/kinsol/kinsol_spbcgs.c
@@ -0,0 +1,426 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.5 $
+ * $Date: 2007/11/26 16:20:01 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Aaron Collier and Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2004, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * 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 *res_norm);
+static void 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 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 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;
+
+ /* 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 */
+
+ npe = nli = nps = ncfl = 0;
+ njtimes = nfes = 0;
+
+ /* 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;
+ }
+
+ /* 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 *res_norm)
+{
+ KINSpilsMem kinspils_mem;
+ SpbcgMem spbcg_mem;
+ int ret, nli_inc, nps_inc;
+
+ 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++;
+
+ /* Compute the terms sJpnorm and sfdotJp for use in the global strategy
+ routines and in KINForcingTerm. Both of these terms are subsequently
+ corrected if the step is reduced by constraints or the line search.
+
+ sJpnorm is the norm of the scaled product (scaled by fscale) of
+ the current Jacobian matrix J and the step vector p.
+
+ 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) ret = SPBCG_SUCCESS;
+ else if (ret > 0) ret = SPBCG_ATIMES_FAIL_REC;
+ else if (ret < 0) ret = SPBCG_ATIMES_FAIL_UNREC;
+
+ 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);
+
+ /* Interpret return value from SpbcgSolve */
+
+ last_flag = ret;
+
+ switch(ret) {
+
+ case SPBCG_SUCCESS:
+ case SPBCG_RES_REDUCED:
+ return(0);
+ break;
+ 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;
+ }
+
+ return(0);
+
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Function : KINSpbcgFree
+ * -----------------------------------------------------------------
+ * Frees memory specific to the SPBCG linear solver module.
+ * -----------------------------------------------------------------
+ */
+
+static void 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;
+}
diff --git a/src/kinsol/kinsol_spgmr.c b/src/kinsol/kinsol_spgmr.c
new file mode 100644
index 0000000..7f34d37
--- /dev/null
+++ b/src/kinsol/kinsol_spgmr.c
@@ -0,0 +1,427 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.5 $
+ * $Date: 2007/11/26 16:20:01 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Radu Serban and Aaron Collier @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * 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 *res_norm);
+static void 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 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 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;
+
+ /* 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 */
+
+ npe = nli = nps = ncfl = 0;
+ njtimes = nfes = 0;
+
+ /* 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;
+ }
+
+ 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 *res_norm)
+{
+ KINSpilsMem kinspils_mem;
+ SpgmrMem spgmr_mem;
+ int ret, nli_inc, nps_inc;
+
+ 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++;
+
+ /* Compute the terms sJpnorm and sfdotJp for use in the global strategy
+ routines and in KINForcingTerm. Both of these terms are subsequently
+ corrected if the step is reduced by constraints or the line search.
+
+ sJpnorm is the norm of the scaled product (scaled by fscale) of
+ the current Jacobian matrix J and the step vector p.
+
+ 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) ret = SPGMR_SUCCESS;
+ else if (ret > 0) ret = SPGMR_ATIMES_FAIL_REC;
+ else if (ret < 0) ret = SPGMR_ATIMES_FAIL_UNREC;
+
+ 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);
+
+ /* Interpret return value from SpgmrSolve */
+
+ last_flag = ret;
+
+ switch(ret) {
+
+ case SPGMR_SUCCESS:
+ case SPGMR_RES_REDUCED:
+ return(0);
+ break;
+ 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;
+ }
+
+ return(0);
+
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Function : KINSpgmrFree
+ * -----------------------------------------------------------------
+ * This routine frees memory specific to the SPGMR linear solver.
+ * -----------------------------------------------------------------
+ */
+
+static void 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;
+}
diff --git a/src/kinsol/kinsol_spils.c b/src/kinsol/kinsol_spils.c
new file mode 100644
index 0000000..4191730
--- /dev/null
+++ b/src/kinsol/kinsol_spils.c
@@ -0,0 +1,623 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.6 $
+ * $Date: 2011/06/23 00:36:18 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Radu Serban and Aaron Collier @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * This is the implementation file for the KINSPILS linear solvers.
+ * -----------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+
+#include "kinsol_impl.h"
+#include "kinsol_spils_impl.h"
+
+#include <sundials/sundials_math.h>
+
+/*
+ * -----------------------------------------------------------------
+ * 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
+ * -----------------------------------------------------------------
+ */
+
+int KINSpilsSetMaxRestarts(void *kinmem, int maxrs)
+{
+ KINMem kin_mem;
+ KINSpilsMem kinspils_mem;
+
+ /* return immediately if kinmem is NULL */
+
+ if (kinmem == NULL) {
+ KINProcessError(NULL, KINSPILS_MEM_NULL, "KINSPILS", "KINSpilsSetMaxRestarts", MSGS_KINMEM_NULL);
+ return(KINSPILS_MEM_NULL);
+ }
+ kin_mem = (KINMem) kinmem;
+
+ if (lmem == NULL) {
+ KINProcessError(kin_mem, KINSPILS_LMEM_NULL, "KINSPILS", "KINSpilsSetMaxRestarts", MSGS_LMEM_NULL);
+ return(KINSPILS_LMEM_NULL);
+ }
+ kinspils_mem = (KINSpilsMem) lmem;
+
+ /* check for legal maxrs */
+
+ if (maxrs < 0) {
+ KINProcessError(kin_mem, KINSPILS_ILL_INPUT, "KINSPILS", "KINSpilsSetMaxRestarts", MSGS_NEG_MAXRS);
+ return(KINSPILS_ILL_INPUT);
+ }
+ kinspils_mem->s_maxlrst = maxrs;
+
+ return(KINSPILS_SUCCESS);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Function : KINSpilsSetPreconditioner
+ * -----------------------------------------------------------------
+ */
+
+int KINSpilsSetPreconditioner(void *kinmem,
+ KINSpilsPrecSetupFn pset, KINSpilsPrecSolveFn psolve)
+{
+ KINMem kin_mem;
+ KINSpilsMem kinspils_mem;
+
+ /* return immediately if kinmem is NULL */
+
+ if (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);
+ return(KINSPILS_LMEM_NULL);
+ }
+ kinspils_mem = (KINSpilsMem) lmem;
+
+ kinspils_mem->s_pset = pset;
+ kinspils_mem->s_psolve = psolve;
+
+ return(KINSPILS_SUCCESS);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Function : KINSpilsSetJacTimesVecFn
+ * -----------------------------------------------------------------
+ */
+
+int KINSpilsSetJacTimesVecFn(void *kinmem, KINSpilsJacTimesVecFn jtv)
+
+{
+ KINMem kin_mem;
+ KINSpilsMem kinspils_mem;
+
+ /* return immediately if kinmem is NULL */
+
+ if (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);
+ return(KINSPILS_LMEM_NULL);
+ }
+ kinspils_mem = (KINSpilsMem) lmem;
+
+ if (jtv != NULL) {
+ jtimesDQ = FALSE;
+ jtimes = jtv;
+ } else {
+ jtimesDQ = TRUE;
+ }
+
+ return(KINSPILS_SUCCESS);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Function : KINSpilsGetWorkSpace
+ * -----------------------------------------------------------------
+ */
+
+int KINSpilsGetWorkSpace(void *kinmem, long int *lenrwSG, long int *leniwSG)
+{
+ KINMem kin_mem;
+ KINSpilsMem kinspils_mem;
+ int maxl;
+
+ /* return immediately if kinmem is NULL */
+
+ if (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);
+ return(KINSPILS_LMEM_NULL);
+ }
+ kinspils_mem = (KINSpilsMem) lmem;
+
+ maxl = kinspils_mem->s_maxl;
+
+ 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;
+ }
+
+
+ return(KINSPILS_SUCCESS);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Function : KINSpilsGetNumPrecEvals
+ * -----------------------------------------------------------------
+ */
+
+int KINSpilsGetNumPrecEvals(void *kinmem, long int *npevals)
+{
+ KINMem kin_mem;
+ KINSpilsMem kinspils_mem;
+
+ /* return immediately if kinmem is NULL */
+
+ if (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);
+ return(KINSPILS_LMEM_NULL);
+ }
+ kinspils_mem = (KINSpilsMem) lmem;
+ *npevals = npe;
+
+ return(KINSPILS_SUCCESS);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Function : KINSpilsGetNumPrecSolves
+ * -----------------------------------------------------------------
+ */
+
+int KINSpilsGetNumPrecSolves(void *kinmem, long int *npsolves)
+{
+ KINMem kin_mem;
+ KINSpilsMem kinspils_mem;
+
+ /* return immediately if kinmem is NULL */
+
+ if (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);
+ return(KINSPILS_LMEM_NULL);
+ }
+ kinspils_mem = (KINSpilsMem) lmem;
+ *npsolves = nps;
+
+ return(KINSPILS_SUCCESS);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Function : KINSpilsGetNumLinIters
+ * -----------------------------------------------------------------
+ */
+
+int KINSpilsGetNumLinIters(void *kinmem, long int *nliters)
+{
+ KINMem kin_mem;
+ KINSpilsMem kinspils_mem;
+
+ /* return immediately if kinmem is NULL */
+
+ if (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);
+ return(KINSPILS_LMEM_NULL);
+ }
+ kinspils_mem = (KINSpilsMem) lmem;
+ *nliters = nli;
+
+ return(KINSPILS_SUCCESS);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Function : KINSpilsGetNumConvFails
+ * -----------------------------------------------------------------
+ */
+
+int KINSpilsGetNumConvFails(void *kinmem, long int *nlcfails)
+{
+ KINMem kin_mem;
+ KINSpilsMem kinspils_mem;
+
+ /* return immediately if kinmem is NULL */
+
+ if (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);
+ return(KINSPILS_LMEM_NULL);
+ }
+ kinspils_mem = (KINSpilsMem) lmem;
+ *nlcfails = ncfl;
+
+ return(KINSPILS_SUCCESS);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Function : KINSpilsGetNumJtimesEvals
+ * -----------------------------------------------------------------
+ */
+
+int KINSpilsGetNumJtimesEvals(void *kinmem, long int *njvevals)
+{
+ KINMem kin_mem;
+ KINSpilsMem kinspils_mem;
+
+ /* return immediately if kinmem is NULL */
+
+ if (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);
+ return(KINSPILS_LMEM_NULL);
+ }
+ kinspils_mem = (KINSpilsMem) lmem;
+ *njvevals = njtimes;
+
+ return(KINSPILS_SUCCESS);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Function : KINSpilsGetNumFuncEvals
+ * -----------------------------------------------------------------
+ */
+
+int KINSpilsGetNumFuncEvals(void *kinmem, long int *nfevalsS)
+{
+ KINMem kin_mem;
+ KINSpilsMem kinspils_mem;
+
+ /* return immediately if kinmem is NULL */
+
+ if (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);
+ return(KINSPILS_LMEM_NULL);
+ }
+ kinspils_mem = (KINSpilsMem) lmem;
+ *nfevalsS = nfes;
+
+ return(KINSPILS_SUCCESS);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Function : KINSpilsGetLastFlag
+ * -----------------------------------------------------------------
+ */
+
+int KINSpilsGetLastFlag(void *kinmem, long int *flag)
+{
+ KINMem kin_mem;
+ KINSpilsMem kinspils_mem;
+
+ /* return immediately if kinmem is NULL */
+
+ if (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);
+ return(KINSPILS_LMEM_NULL);
+ }
+ kinspils_mem = (KINSpilsMem) lmem;
+
+ *flag = last_flag;
+
+ return(KINSPILS_SUCCESS);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Function : KINSpilsGetReturnFlagName
+ * -----------------------------------------------------------------
+ */
+
+char *KINSpilsGetReturnFlagName(long int flag)
+{
+ char *name;
+
+ name = (char *)malloc(30*sizeof(char));
+
+ switch(flag) {
+ case KINSPILS_SUCCESS:
+ sprintf(name, "KINSPILS_SUCCESS");
+ break;
+ case KINSPILS_MEM_NULL:
+ sprintf(name, "KINSPILS_MEM_NULL");
+ break;
+ case KINSPILS_LMEM_NULL:
+ sprintf(name, "KINSPILS_LMEM_NULL");
+ break;
+ case KINSPILS_ILL_INPUT:
+ sprintf(name, "KINSPILS_ILL_INPUT");
+ break;
+ case KINSPILS_MEM_FAIL:
+ sprintf(name, "KINSPILS_MEM_FAIL");
+ break;
+ case KINSPILS_PMEM_NULL:
+ sprintf(name, "KINSPILS_PMEM_NULL");
+ break;
+ default:
+ sprintf(name, "NONE");
+ }
+
+ 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.
+ * -----------------------------------------------------------------
+ */
+
+int KINSpilsAtimes(void *kinsol_mem, N_Vector v, N_Vector z)
+{
+ KINMem kin_mem;
+ KINSpilsMem kinspils_mem;
+ int ret;
+
+ kin_mem = (KINMem) kinsol_mem;
+ kinspils_mem = (KINSpilsMem) lmem;
+
+ ret = jtimes(v, z, uu, &new_uu, J_data);
+ njtimes++;
+
+ return(ret);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * 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)
+{
+ KINMem kin_mem;
+ KINSpilsMem kinspils_mem;
+ int ret;
+
+ kin_mem = (KINMem) kinsol_mem;
+ kinspils_mem = (KINSpilsMem) 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 */
+
+ ret = psolve(uu, uscale, fval, fscale, z, P_data, vtemp1);
+
+ return(ret);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * 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)
+{
+ 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;
+
+ /* scale the vector v and put Du*v into vtemp1 */
+
+ N_VProd(v, uscale, vtemp1);
+
+ /* scale u and put into Jv (used as a temporary storage) */
+
+ N_VProd(u, uscale, Jv);
+
+ /* compute dot product (Du*u).(Du*v) */
+
+ sutsv = N_VDotProd(Jv, vtemp1);
+
+ /* compute dot product (Du*v).(Du*v) */
+
+ vtv = N_VDotProd(vtemp1, vtemp1);
+
+ sq1norm = N_VL1Norm(vtemp1);
+
+ sign = (sutsv >= ZERO) ? ONE : -ONE ;
+
+ /* this expression for sigma is from p. 469, Brown and Saad paper */
+
+ sigma = sign*sqrt_relfunc*MAX(ABS(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);
+
+ /* call the system function to calculate func(u+sigma*v) */
+
+ retval = func(vtemp1, vtemp2, user_data);
+ nfes++;
+ if (retval != 0) return(retval);
+
+ /* finish the computation of the difference quotient */
+
+ N_VLinearSum(sigma_inv, vtemp2, -sigma_inv, fval, Jv);
+
+ return(0);
+}
+
diff --git a/src/kinsol/kinsol_spils_impl.h b/src/kinsol/kinsol_spils_impl.h
new file mode 100644
index 0000000..6950bc0
--- /dev/null
+++ b/src/kinsol/kinsol_spils_impl.h
@@ -0,0 +1,180 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.5 $
+ * $Date: 2010/12/01 22:43:33 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Radu Serban and Aaron Collier @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * Common implementation header file for the scaled, preconditioned
+ * linear solver modules.
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _KINSPILS_IMPL_H
+#define _KINSPILS_IMPL_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <kinsol/kinsol_spils.h>
+#include "kinsol_impl.h"
+
+/* Types of iterative linear solvers */
+
+#define SPILS_SPGMR 1
+#define SPILS_SPBCG 2
+#define SPILS_SPTFQMR 3
+
+/*
+ * -----------------------------------------------------------------
+ * 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 */
+
+ 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 */
+
+ /* miscellaneous */
+
+ void *s_spils_mem; /* pointer to generic linear solver memory block */
+
+ long int s_last_flag; /* last flag returned */
+
+
+ /* 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;
+ void (*s_pfree)(KINMem kin_mem);
+ void *s_P_data;
+
+ /* 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;
+
+} *KINSpilsMem;
+
+
+/*
+ * -----------------------------------------------------------------
+ * Prototypes of internal functions
+ * -----------------------------------------------------------------
+ */
+
+/* KINSpgmr Atimes and PSolve routines called by generic SPGMR 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);
+
+/* difference quotient approximation for jacobian times vector */
+
+int KINSpilsDQJtimes(N_Vector v, N_Vector Jv,
+ N_Vector u, booleantype *new_u,
+ void *data);
+
+/*
+ * -----------------------------------------------------------------
+ * KINSPILS error messages
+ * -----------------------------------------------------------------
+ */
+
+#define MSGS_KINMEM_NULL "KINSOL memory is NULL."
+#define MSGS_MEM_FAIL "A memory request failed."
+#define MSGS_BAD_NVECTOR "A required vector operation is not implemented."
+#define MSGS_LMEM_NULL "Linear solver memory is NULL."
+#define MSGS_NEG_MAXRS "maxrs < 0 illegal."
+
+
+/*
+ * -----------------------------------------------------------------
+ * KINSPILS info messages
+ * -----------------------------------------------------------------
+ */
+
+#define INFO_NLI "nli_inc = %d"
+
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+
+#define INFO_EPS "residual norm = %12.3Lg eps = %12.3Lg"
+
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+
+#define INFO_EPS "residual norm = %12.3lg eps = %12.3lg"
+
+#else
+
+#define INFO_EPS "residual norm = %12.3g eps = %12.3g"
+
+#endif
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/kinsol/kinsol_sptfqmr.c b/src/kinsol/kinsol_sptfqmr.c
new file mode 100644
index 0000000..3ab6228
--- /dev/null
+++ b/src/kinsol/kinsol_sptfqmr.c
@@ -0,0 +1,428 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.5 $
+ * $Date: 2007/11/26 16:20:01 $
+ * -----------------------------------------------------------------
+ * 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.
+ * -----------------------------------------------------------------
+ * 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 *res_norm);
+static void 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 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 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;
+
+ /* 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;
+ SptfqmrMem sptfqmr_mem;
+
+ kinspils_mem = (KINSpilsMem) lmem;
+ sptfqmr_mem = (SptfqmrMem) spils_mem;
+
+ /* initialize counters */
+
+ npe = nli = nps = ncfl = 0;
+ njtimes = nfes = 0;
+
+ /* 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;
+ }
+
+ /* Set maxl in the SPTFQMR memory in case it was changed by the user */
+ sptfqmr_mem->l_max = maxl;
+
+ 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 *res_norm)
+{
+ KINSpilsMem kinspils_mem;
+ SptfqmrMem sptfqmr_mem;
+ int ret, nli_inc, nps_inc;
+
+ 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++;
+
+ /* Compute the terms sJpnorm and sfdotJp for use in the global strategy
+ routines and in KINForcingTerm. Both of these terms are subsequently
+ corrected if the step is reduced by constraints or the line search.
+
+ sJpnorm is the norm of the scaled product (scaled by fscale) of
+ the current Jacobian matrix J and the step vector p.
+
+ 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) ret = SPTFQMR_SUCCESS;
+ else if (ret > 0) ret = SPTFQMR_ATIMES_FAIL_REC;
+ else if (ret < 0) ret = SPTFQMR_ATIMES_FAIL_UNREC;
+
+ 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);
+
+ /* Interpret return value from SptfqmrSolve */
+
+ last_flag = ret;
+
+ switch(ret) {
+
+ case SPTFQMR_SUCCESS:
+ case SPTFQMR_RES_REDUCED:
+ return(0);
+ break;
+ case SPTFQMR_PSOLVE_FAIL_REC:
+ return(1);
+ break;
+ 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;
+ }
+
+ return(0);
+
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Function : KINSptfqmrFree
+ * -----------------------------------------------------------------
+ * Frees memory specific to the SPTFQMR linear solver module.
+ * -----------------------------------------------------------------
+ */
+
+static void 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;
+}
diff --git a/src/nvec_par/CMakeLists.txt b/src/nvec_par/CMakeLists.txt
new file mode 100644
index 0000000..f5e359f
--- /dev/null
+++ b/src/nvec_par/CMakeLists.txt
@@ -0,0 +1,89 @@
+# ---------------------------------------------------------------
+# $Revision: 1.3 $
+# $Date: 2009/02/17 02:58:48 $
+# ---------------------------------------------------------------
+# Programmer: Radu Serban @ LLNL
+# ---------------------------------------------------------------
+# Copyright (c) 2007, The Regents of the University of California.
+# Produced at the Lawrence Livermore National Laboratory.
+# All rights reserved.
+# For details, see the LICENSE file.
+# ---------------------------------------------------------------
+# CMakeLists.txt file for the parallel NVECTOR library
+
+INSTALL(CODE "MESSAGE(\"\nInstall NVECTOR_PARALLEL\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 nvecparallel_SOURCES with the sources for the NVECPARALLEL lib
+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)
+
+# 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)
+
+# 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 NVECPARALLEL library
+# - Set the library name and make sure it is not deleted
+# - Install the NVECSERIAL library
+IF(BUILD_STATIC_LIBS)
+ ADD_LIBRARY(sundials_nvecparallel_static STATIC ${nvecparallel_SOURCES} ${shared_SOURCES})
+ SET_TARGET_PROPERTIES(sundials_nvecparallel_static
+ PROPERTIES OUTPUT_NAME sundials_nvecparallel CLEAN_DIRECT_OUTPUT 1)
+ INSTALL(TARGETS sundials_nvecparallel_static DESTINATION lib)
+ENDIF(BUILD_STATIC_LIBS)
+
+# Rules for building and installing the shared library:
+# - Add the build target for the NVECPARALLEL 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)
+ ADD_LIBRARY(sundials_nvecparallel_shared SHARED ${nvecparallel_SOURCES} ${shared_SOURCES})
+ SET_TARGET_PROPERTIES(sundials_nvecparallel_shared
+ PROPERTIES OUTPUT_NAME sundials_nvecparallel CLEAN_DIRECT_OUTPUT 1)
+ SET_TARGET_PROPERTIES(sundials_nvecparallel_shared
+ PROPERTIES VERSION ${nveclib_VERSION} SOVERSION ${nveclib_SOVERSION})
+ INSTALL(TARGETS sundials_nvecparallel_shared DESTINATION lib)
+ENDIF(BUILD_SHARED_LIBS)
+
+# Install the NVECPARALLEL header files
+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})
+ 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/Makefile.in b/src/nvec_par/Makefile.in
new file mode 100644
index 0000000..bd7ea4f
--- /dev/null
+++ b/src/nvec_par/Makefile.in
@@ -0,0 +1,128 @@
+# -----------------------------------------------------------------
+# $Revision: 1.8 $
+# $Date: 2007/01/29 17:36:28 $
+# -----------------------------------------------------------------
+# Programmer(s): Radu Serban and Aaron Collier @ LLNL
+# -----------------------------------------------------------------
+# Copyright (c) 2002, The Regents of the University of California.
+# Produced at the Lawrence Livermore National Laboratory.
+# All rights reserved.
+# For details, see the LICENSE file.
+# -----------------------------------------------------------------
+# Makefile for parallel NVECTOR module
+#
+# @configure_input@
+# -----------------------------------------------------------------
+
+SHELL = @SHELL@
+
+ at SET_MAKE@
+
+srcdir = @srcdir@
+builddir = @builddir@
+abs_builddir = @abs_builddir@
+top_builddir = @top_builddir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+includedir = @includedir@
+libdir = @libdir@
+
+INSTALL = @INSTALL@
+INSTALL_LIB = @INSTALL_PROGRAM@
+INSTALL_HEADER = @INSTALL_DATA@
+
+LIBTOOL = @LIBTOOL@
+LIBTOOL_DEPS = @LIBTOOL_DEPS@
+
+MPICC = @MPICC@
+MPI_INC_DIR = @MPI_INC_DIR@
+MPI_LIB_DIR = @MPI_LIB_DIR@
+MPI_LIBS = @MPI_LIBS@
+MPI_FLAGS = @MPI_FLAGS@
+CPPFLAGS = @CPPFLAGS@
+CFLAGS = @CFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+
+FCMIX_ENABLED = @FCMIX_ENABLED@
+
+top_srcdir = $(srcdir)/../..
+
+INCLUDES = -I$(top_srcdir)/include -I$(top_builddir)/include -I$(MPI_INC_DIR)
+
+LIB_REVISION = 0:2:0
+
+NVECPAR_LIB = libsundials_nvecparallel.la
+NVECPAR_LIB_FILES = nvector_parallel.lo
+
+FNVECPAR_LIB = libsundials_fnvecparallel.la
+FNVECPAR_LIB_FILES = fnvector_parallel.lo
+
+SHARED_LIB_FILES = $(top_builddir)/src/sundials/sundials_math.lo
+
+mkinstalldirs = $(SHELL) $(top_srcdir)/config/mkinstalldirs
+rminstalldirs = $(SHELL) $(top_srcdir)/config/rminstalldirs
+
+all: $(NVECPAR_LIB) $(FNVECPAR_LIB)
+
+$(NVECPAR_LIB): shared $(NVECPAR_LIB_FILES)
+ $(LIBTOOL) --mode=link $(MPICC) $(CFLAGS) $(MPI_FLAGS) -o $(NVECPAR_LIB) $(NVECPAR_LIB_FILES) $(SHARED_LIB_FILES) $(LDFLAGS) -L$(MPI_LIB_DIR) $(MPI_LIBS) $(LIBS) -rpath $(libdir) -version-info $(LIB_REVISION)
+
+$(FNVECPAR_LIB): $(FNVECPAR_LIB_FILES)
+ @if test "X${FCMIX_ENABLED}" = "Xyes"; then \
+ echo "${LIBTOOL} --mode=link ${MPICC} ${CFLAGS} ${MPI_FLAGS} -o ${FNVECPAR_LIB} ${FNVECPAR_LIB_FILES} ${SHARED_LIB_FILES} ${LDFLAGS} -L${MPI_LIB_DIR} ${MPI_LIBS} ${LIBS} -rpath ${libdir} -version-info ${LIB_REVISION}" ; \
+ ${LIBTOOL} --mode=link ${MPICC} ${CFLAGS} ${MPI_FLAGS} -o ${FNVECPAR_LIB} ${FNVECPAR_LIB_FILES} ${SHARED_LIB_FILES} ${LDFLAGS} -L${MPI_LIB_DIR} ${MPI_LIBS} ${LIBS} -rpath ${libdir} -version-info ${LIB_REVISION} ; \
+ fi
+
+install: $(NVECPAR_LIB) $(FNVECPAR_LIB)
+ $(mkinstalldirs) $(includedir)/nvector
+ $(mkinstalldirs) $(libdir)
+ $(LIBTOOL) --mode=install $(INSTALL_LIB) $(NVECPAR_LIB) $(libdir)
+ $(INSTALL_HEADER) $(top_srcdir)/include/nvector/nvector_parallel.h $(includedir)/nvector/
+ @if test "X${FCMIX_ENABLED}" = "Xyes"; then \
+ echo "${LIBTOOL} --mode=install ${INSTALL_LIB} ${FNVECPAR_LIB} ${libdir}" ; \
+ ${LIBTOOL} --mode=install ${INSTALL_LIB} ${FNVECPAR_LIB} ${libdir} ; \
+ fi
+
+uninstall:
+ $(LIBTOOL) --mode=uninstall rm -f $(libdir)/$(NVECPAR_LIB)
+ @if test "X${FCMIX_ENABLED}" = "Xyes"; then \
+ echo "${LIBTOOL} --mode=uninstall rm -f ${libdir}/${FNVECPAR_LIB}" ; \
+ ${LIBTOOL} --mode=uninstall rm -f ${libdir}/${FNVECPAR_LIB} ; \
+ fi
+ rm -f $(includedir)/nvector/nvector_parallel.h
+ $(rminstalldirs) ${includedir}/nvector
+
+shared:
+ @cd ${top_builddir}/src/sundials ; \
+ ${MAKE} ; \
+ cd ${abs_builddir}
+
+clean:
+ $(LIBTOOL) --mode=clean rm -f $(NVECPAR_LIB)
+ rm -f $(NVECPAR_LIB_FILES)
+ rm -f nvector_parallel.o
+ @if test "X${FCMIX_ENABLED}" = "Xyes"; then \
+ echo "${LIBTOOL} --mode=clean rm -f ${FNVECPAR_LIB}" ; \
+ ${LIBTOOL} --mode=clean rm -f ${FNVECPAR_LIB} ; \
+ echo "rm -f ${FNVECPAR_LIB_FILES}" ; \
+ rm -f ${FNVECPAR_LIB_FILES} ; \
+ echo "rm -f fnvector_parallel.o" ; \
+ rm -f fnvector_parallel.o ; \
+ fi
+
+distclean: clean
+ rm -f Makefile
+
+nvector_parallel.lo: $(srcdir)/nvector_parallel.c
+ $(LIBTOOL) --mode=compile $(MPICC) $(CPPFLAGS) $(MPI_FLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/nvector_parallel.c
+fnvector_parallel.lo: $(srcdir)/fnvector_parallel.c
+ @if test "X${FCMIX_ENABLED}" = "Xyes"; then \
+ echo "${LIBTOOL} --mode=compile ${MPICC} ${CPPFLAGS} ${MPI_FLAGS} $(INCLUDES) ${CFLAGS} -c ${srcdir}/fnvector_parallel.c" ; \
+ ${LIBTOOL} --mode=compile ${MPICC} ${CPPFLAGS} ${MPI_FLAGS} $(INCLUDES) ${CFLAGS} -c ${srcdir}/fnvector_parallel.c ; \
+ fi
+
+libtool: $(top_builddir)/$(LIBTOOL_DEPS)
+ @cd ${top_builddir} ; \
+ ${SHELL} ./config.status --recheck ; \
+ cd ${abs_builddir}
diff --git a/src/nvec_par/README b/src/nvec_par/README
new file mode 100644
index 0000000..b9bb47e
--- /dev/null
+++ b/src/nvec_par/README
@@ -0,0 +1,143 @@
+ NVECTOR_PARALLEL
+ Release 2.5.0, March 2012
+
+
+MPI parallel implementation of the NVECTOR module for SUNDIALS.
+
+NVECTOR_PARALLEL defines the content field of N_Vector to be a structure
+containing the global and local lengths of the vector, a pointer to the
+beginning of a contiguous local data array, an MPI communicator, and a
+boolean flag indicating ownership of the data array.
+
+NVECTOR_PARALLEL defines seven macros to provide access to the content of
+a parallel N_Vector, several constructors for variables of type N_Vector,
+a constructor for an array of variables of type N_Vector, and destructors
+for N_Vector and N_Vector array.
+
+NVECTOR_PARALLEL provides implementations for all vector operations defined
+by the generic NVECTOR module in the table of operations.
+
+
+A. Documentation
+----------------
+
+The MPI parallel NVECTOR implementation is fully described in the user documentation
+for any of the SUNDIALS solvers [1-5]. 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_NOTES.
+For complete installation instructions see any of the user guides.
+
+
+C. References
+-------------
+
+[1] A. C. Hindmarsh and R. Serban, "User Documentation for CVODE v2.7.0,"
+ LLNL technical report UCRL-MA-208108, December 2011.
+
+[2] A. C. Hindmarsh and R. Serban, "User Documentation for CVODES v2.7.0,"
+ LLNL technical report UCRL-MA-208111, December 2011.
+
+[3] A. C. Hindmarsh and R. Serban, "User Documentation for IDA v2.7.0,"
+ LLNL technical report UCRL-MA-208112, December 2011.
+
+[4] R. Serban and C. Petra, "User Documentation for IDAS v1.1.0,"
+ LLNL technical report UCRL-SM-234051, December 2011.
+
+[5] A. M. Collier, A. C. Hindmarsh, R. Serban,and C. S. Woodward, "User
+ Documentation for KINSOL v2.7.0," LLNL technical report UCRL-MA-208116,
+ December 2011.
+
+
+D. Releases
+-----------
+
+v. 2.5.0 - Mar. 2012
+v. 2.4.0 - May 2009
+v. 2.3.0 - Nov. 2006
+v. 2.2.0 - Mar. 2006
+v. 2.1.1 - May 2005
+v. 2.1.0 - Apr. 2005
+v. 2.0.2 - Mar. 2005
+v. 2.0.1 - Jan. 2005
+v. 2.0 - Dec. 2004
+v. 1.0 - Jul. 2002 (first SUNDIALS release)
+
+
+E. Revision History
+-------------------
+
+v. 2.4.0 (May 2009) ---> v. 2.5.0 (Mar. 2012)
+---------------------------------------------
+
+- Bug fix:
+ - consistently updated to using SUNDIALS_F77_FUNC in fcmix header files.
+
+v. 2.3.0 (Nov. 2006) ---> v. 2.4.0 (May 2009)
+---------------------------------------------
+
+- none
+
+v. 2.2.0 (Mar. 2006) ---> v. 2.3.0 (Nov. 2006)
+----------------------------------------------
+
+- Changes related to the build system
+ - reorganized source tree. Header files in ${srcdir}/include/nvector;
+ sources in ${srcdir}/src/nvec_par
+ - exported header files in ${includedir}/sundials
+
+v. 2.1.1 (May 2005) ---> v. 2.2.0 (Mar. 2006)
+---------------------------------------------
+
+- none
+
+v. 2.1.0 (Apr. 2005) ---> v. 2.1.1 (May 2005)
+---------------------------------------------
+
+- Changes to user interface
+ - added argument to initialization routines to allow user to specify a
+ different MPI communicator
+
+- Changes to data structures
+ - added N_VCloneEmpty to global vector operations table
+
+v. 2.0.2 (Mar. 2005) ---> v. 2.1.0 (Apr. 2005)
+----------------------------------------------
+
+- none
+
+v. 2.0.1 (Jan. 2005) ---> v. 2.0.2 (Mar. 2005)
+----------------------------------------------
+
+- Changes related to the build system
+ - fixed autoconf-related bug to allow configuration with the PGI Fortran compiler
+ - modified to use customized detection of the Fortran name mangling scheme
+ (autoconf's AC_F77_WRAPPERS routine is problematic on some platforms)
+ - added --with-mpi-flags as a configure option to allow user to specify
+ MPI-specific flags
+ - updated Makefiles for Fortran examples to avoid C++ compiler errors (now use
+ CC and MPICC to link)
+
+v. 2.0 (Dec. 2004) ---> v. 2.0.1 (Jan. 2005)
+--------------------------------------------
+
+- Changes related to the build system
+ - changed order of compiler directives in header files to avoid compilation
+ errors when using a C++ compiler.
+
+v. 1.0 (Jul. 2002) ---> v. 2.0 (Dec. 2004)
+------------------------------------------
+
+- Revised to correspond to new generic NVECTOR module
+ (see sundials/shared/README).
+- Extended the list of user-callable functions provided by NVECTOR_PARALLEL
+ outside the table of vector operations.
+- Revised parallel N_VMin and N_VMinQuotient to use BIG_REAL if
+ local N is 0 or no quotients found.
+- Revised the F/C interface to use underscore flags for name mapping
+ and to use precision flag from configure.
+- Revised F/C routine NVECTOR names for uniformity.
diff --git a/src/nvec_par/fnvector_parallel.c b/src/nvec_par/fnvector_parallel.c
new file mode 100644
index 0000000..6ece6b9
--- /dev/null
+++ b/src/nvec_par/fnvector_parallel.c
@@ -0,0 +1,182 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.1 $
+ * $Date: 2006/07/05 15:32:37 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * This file (companion of nvector_parallel.h) contains the
+ * implementation needed for the Fortran initialization of parallel
+ * vector operations.
+ * -----------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "fnvector_parallel.h"
+
+/* Define global vector variables */
+
+N_Vector F2C_CVODE_vec;
+N_Vector F2C_CVODE_vecQ;
+N_Vector *F2C_CVODE_vecS;
+N_Vector F2C_CVODE_vecB;
+N_Vector F2C_CVODE_vecQB;
+
+N_Vector F2C_IDA_vec;
+N_Vector F2C_IDA_vecQ;
+N_Vector *F2C_IDA_vecS;
+N_Vector F2C_IDA_vecB;
+N_Vector F2C_IDA_vecQB;
+
+N_Vector F2C_KINSOL_vec;
+
+#ifndef SUNDIALS_MPI_COMM_F2C
+#define MPI_Fint int
+#endif
+
+/* Fortran callable interfaces */
+
+void FNV_INITP(MPI_Fint *comm, int *code, long int *L, long int *N, int *ier)
+{
+ MPI_Comm F2C_comm;
+
+#ifdef SUNDIALS_MPI_COMM_F2C
+ F2C_comm = MPI_Comm_f2c(*comm);
+#else
+ F2C_comm = MPI_COMM_WORLD;
+#endif
+
+ *ier = 0;
+
+ switch(*code) {
+ case FCMIX_CVODE:
+ F2C_CVODE_vec = NULL;
+ F2C_CVODE_vec = N_VNewEmpty_Parallel(F2C_comm, *L, *N);
+ if (F2C_CVODE_vec == NULL) *ier = -1;
+ break;
+ case FCMIX_IDA:
+ F2C_IDA_vec = NULL;
+ F2C_IDA_vec = N_VNewEmpty_Parallel(F2C_comm, *L, *N);
+ if (F2C_IDA_vec == NULL) *ier = -1;
+ break;
+ case FCMIX_KINSOL:
+ F2C_KINSOL_vec = NULL;
+ F2C_KINSOL_vec = N_VNewEmpty_Parallel(F2C_comm, *L, *N);
+ if (F2C_KINSOL_vec == NULL) *ier = -1;
+ break;
+ default:
+ *ier = -1;
+ }
+}
+
+void FNV_INITP_Q(MPI_Fint *comm, int *code, long int *Lq, long int *Nq, int *ier)
+{
+ MPI_Comm F2C_comm;
+
+#ifdef SUNDIALS_MPI_COMM_F2C
+ F2C_comm = MPI_Comm_f2c(*comm);
+#else
+ F2C_comm = MPI_COMM_WORLD;
+#endif
+
+ *ier = 0;
+
+ switch(*code) {
+ case FCMIX_CVODE:
+ F2C_CVODE_vecQ = NULL;
+ F2C_CVODE_vecQ = N_VNewEmpty_Parallel(F2C_comm, *Lq, *Nq);
+ if (F2C_CVODE_vecQ == NULL) *ier = -1;
+ break;
+ case FCMIX_IDA:
+ F2C_IDA_vecQ = NULL;
+ F2C_IDA_vecQ = N_VNewEmpty_Parallel(F2C_comm, *Lq, *Nq);
+ if (F2C_IDA_vecQ == NULL) *ier = -1;
+ break;
+ default:
+ *ier = -1;
+ }
+}
+
+void FNV_INITP_B(MPI_Fint *comm, int *code, long int *LB, long int *NB, int *ier)
+{
+ MPI_Comm F2C_comm;
+
+#ifdef SUNDIALS_MPI_COMM_F2C
+ F2C_comm = MPI_Comm_f2c(*comm);
+#else
+ F2C_comm = MPI_COMM_WORLD;
+#endif
+
+ *ier = 0;
+
+ switch(*code) {
+ case FCMIX_CVODE:
+ F2C_CVODE_vecB = NULL;
+ F2C_CVODE_vecB = N_VNewEmpty_Parallel(F2C_comm, *LB, *NB);
+ if (F2C_CVODE_vecB == NULL) *ier = -1;
+ break;
+ case FCMIX_IDA:
+ F2C_IDA_vecB = NULL;
+ F2C_IDA_vecB = N_VNewEmpty_Parallel(F2C_comm, *LB, *NB);
+ if (F2C_IDA_vecB == NULL) *ier = -1;
+ break;
+ default:
+ *ier = -1;
+ }
+}
+
+void FNV_INITP_QB(MPI_Fint *comm, int *code, long int *LqB, long int *NqB, int *ier)
+{
+ MPI_Comm F2C_comm;
+
+#ifdef SUNDIALS_MPI_COMM_F2C
+ F2C_comm = MPI_Comm_f2c(*comm);
+#else
+ F2C_comm = MPI_COMM_WORLD;
+#endif
+
+
+ *ier = 0;
+
+ switch(*code) {
+ case FCMIX_CVODE:
+ F2C_CVODE_vecQB = NULL;
+ F2C_CVODE_vecQB = N_VNewEmpty_Parallel(F2C_comm, *LqB, *NqB);
+ if (F2C_CVODE_vecQB == NULL) *ier = -1;
+ break;
+ case FCMIX_IDA:
+ F2C_IDA_vecQB = NULL;
+ F2C_IDA_vecQB = N_VNewEmpty_Parallel(F2C_comm, *LqB, *NqB);
+ if (F2C_IDA_vecQB == NULL) *ier = -1;
+ break;
+ default:
+ *ier = -1;
+ }
+}
+
+void FNV_INITP_S(int *code, int *Ns, int *ier)
+{
+ *ier = 0;
+
+ switch(*code) {
+ case FCMIX_CVODE:
+ F2C_CVODE_vecS = NULL;
+ F2C_CVODE_vecS = (N_Vector *) N_VCloneVectorArrayEmpty_Parallel(*Ns, F2C_CVODE_vec);
+ if (F2C_CVODE_vecS == NULL) *ier = -1;
+ break;
+ case FCMIX_IDA:
+ F2C_IDA_vecS = NULL;
+ F2C_IDA_vecS = (N_Vector *) N_VCloneVectorArrayEmpty_Parallel(*Ns, F2C_IDA_vec);
+ if (F2C_IDA_vecS == NULL) *ier = -1;
+ break;
+ default:
+ *ier = -1;
+ }
+}
diff --git a/src/nvec_par/fnvector_parallel.h b/src/nvec_par/fnvector_parallel.h
new file mode 100644
index 0000000..9d5b06f
--- /dev/null
+++ b/src/nvec_par/fnvector_parallel.h
@@ -0,0 +1,92 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.4 $
+ * $Date: 2010/12/15 19:40:08 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Radu Serban and Aaron Collier @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * This file (companion of nvector_parallel.c) contains the
+ * definitions needed for the initialization of parallel
+ * vector operations in Fortran.
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _FNVECTOR_PARALLEL_H
+#define _FNVECTOR_PARALLEL_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <nvector/nvector_parallel.h>
+#include <sundials/sundials_fnvector.h>
+
+#if defined(SUNDIALS_F77_FUNC)
+#define FNV_INITP SUNDIALS_F77_FUNC(fnvinitp, FNVINITP)
+#else
+#define FNV_INITP fnvinitp_
+#endif
+
+#if defined(SUNDIALS_F77_FUNC_)
+
+#define FNV_INITP_Q SUNDIALS_F77_FUNC_(fnvinitp_q, FNVINITP_Q)
+#define FNV_INITP_S SUNDIALS_F77_FUNC_(fnvinitp_s, FNVINITP_S)
+#define FNV_INITP_B SUNDIALS_F77_FUNC_(fnvinitp_b, FNVINITP_B)
+#define FNV_INITP_QB SUNDIALS_F77_FUNC_(fnvinitp_qb, FNVINITP_QB)
+
+#else
+
+#define FNV_INITP_Q fnvinitp_q_
+#define FNV_INITP_S fnvinitp_s_
+#define FNV_INITP_B fnvinitp_b_
+#define FNV_INITP_QB fnvinitp_qb_
+
+#endif
+
+/* Declarations of global variables */
+
+extern N_Vector F2C_CVODE_vec;
+extern N_Vector F2C_CVODE_vecQ;
+extern N_Vector *F2C_CVODE_vecS;
+extern N_Vector F2C_CVODE_vecB;
+extern N_Vector F2C_CVODE_vecQB;
+
+extern N_Vector F2C_IDA_vec;
+extern N_Vector F2C_IDA_vecQ;
+extern N_Vector *F2C_IDA_vecS;
+extern N_Vector F2C_IDA_vecB;
+extern N_Vector F2C_IDA_vecQB;
+
+extern N_Vector F2C_KINSOL_vec;
+
+/*
+ * Prototypes of exported functions
+ *
+ * FNV_INITP - initializes parallel vector operations for main problem
+ * FNV_INITP_Q - initializes parallel vector operations for quadratures
+ * FNV_INITP_S - initializes parallel vector operations for sensitivities
+ * FNV_INITP_B - initializes parallel vector operations for adjoint problem
+ * FNV_INITP_QB - initializes parallel vector operations for adjoint quadratures
+ *
+ */
+
+#ifndef SUNDIALS_MPI_COMM_F2C
+#define MPI_Fint int
+#endif
+
+void FNV_INITP(MPI_Fint *comm, int *code, long int *L, long int *N, int *ier);
+void FNV_INITP_Q(MPI_Fint *comm, int *code, long int *Lq, long int *Nq, int *ier);
+void FNV_INITP_B(MPI_Fint *comm, int *code, long int *LB, long int *NB, int *ier);
+void FNV_INITP_QB(MPI_Fint *comm, int *code, long int *LqB, long int *NqB, int *ier);
+void FNV_INITP_S(int *code, int *Ns, int *ier);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/nvec_par/nvector_parallel.c b/src/nvec_par/nvector_parallel.c
new file mode 100644
index 0000000..8a53fab
--- /dev/null
+++ b/src/nvec_par/nvector_parallel.c
@@ -0,0 +1,1152 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.1 $
+ * $Date: 2006/07/05 15:32:37 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh, Radu Serban,
+ * and Aaron Collier @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * This is the implementation file for a parallel MPI implementation
+ * of the NVECTOR package.
+ * -----------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <nvector/nvector_parallel.h>
+#include <sundials/sundials_math.h>
+
+#define ZERO RCONST(0.0)
+#define HALF RCONST(0.5)
+#define ONE RCONST(1.0)
+#define ONEPT5 RCONST(1.5)
+
+/* Error Message */
+
+#define BAD_N1 "N_VNew_Parallel -- Sum of local vector lengths differs from "
+#define BAD_N2 "input global length. \n\n"
+#define BAD_N BAD_N1 BAD_N2
+
+/* Private function prototypes */
+
+/* Reduction operations add/max/min over the processor group */
+static realtype VAllReduce_Parallel(realtype d, int op, MPI_Comm comm);
+/* z=x */
+static void VCopy_Parallel(N_Vector x, N_Vector z);
+/* z=x+y */
+static void VSum_Parallel(N_Vector x, N_Vector y, N_Vector z);
+/* z=x-y */
+static void VDiff_Parallel(N_Vector x, N_Vector y, N_Vector z);
+/* z=-x */
+static void VNeg_Parallel(N_Vector x, N_Vector z);
+/* z=c(x+y) */
+static void VScaleSum_Parallel(realtype c, N_Vector x, N_Vector y, N_Vector z);
+/* z=c(x-y) */
+static void VScaleDiff_Parallel(realtype c, N_Vector x, N_Vector y, N_Vector z);
+/* z=ax+y */
+static void VLin1_Parallel(realtype a, N_Vector x, N_Vector y, N_Vector z);
+/* z=ax-y */
+static void VLin2_Parallel(realtype a, N_Vector x, N_Vector y, N_Vector z);
+/* y <- ax+y */
+static void Vaxpy_Parallel(realtype a, N_Vector x, N_Vector y);
+/* x <- ax */
+static void VScaleBy_Parallel(realtype a, N_Vector x);
+
+/*
+ * -----------------------------------------------------------------
+ * exported functions
+ * -----------------------------------------------------------------
+ */
+
+/* ----------------------------------------------------------------
+ * Function to create a new parallel vector with empty data array
+ */
+
+N_Vector N_VNewEmpty_Parallel(MPI_Comm comm,
+ long int local_length,
+ long int global_length)
+{
+ N_Vector v;
+ N_Vector_Ops ops;
+ N_VectorContent_Parallel content;
+ long int 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);
+ 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->nvclone = N_VClone_Parallel;
+ ops->nvcloneempty = N_VCloneEmpty_Parallel;
+ ops->nvdestroy = N_VDestroy_Parallel;
+ ops->nvspace = N_VSpace_Parallel;
+ ops->nvgetarraypointer = N_VGetArrayPointer_Parallel;
+ ops->nvsetarraypointer = N_VSetArrayPointer_Parallel;
+ ops->nvlinearsum = N_VLinearSum_Parallel;
+ ops->nvconst = N_VConst_Parallel;
+ ops->nvprod = N_VProd_Parallel;
+ ops->nvdiv = N_VDiv_Parallel;
+ ops->nvscale = N_VScale_Parallel;
+ ops->nvabs = N_VAbs_Parallel;
+ ops->nvinv = N_VInv_Parallel;
+ ops->nvaddconst = N_VAddConst_Parallel;
+ ops->nvdotprod = N_VDotProd_Parallel;
+ ops->nvmaxnorm = N_VMaxNorm_Parallel;
+ ops->nvwrmsnormmask = N_VWrmsNormMask_Parallel;
+ ops->nvwrmsnorm = N_VWrmsNorm_Parallel;
+ ops->nvmin = N_VMin_Parallel;
+ ops->nvwl2norm = N_VWL2Norm_Parallel;
+ ops->nvl1norm = N_VL1Norm_Parallel;
+ ops->nvcompare = N_VCompare_Parallel;
+ ops->nvinvtest = N_VInvTest_Parallel;
+ ops->nvconstrmask = N_VConstrMask_Parallel;
+ ops->nvminquotient = N_VMinQuotient_Parallel;
+
+ /* Create content */
+ content = NULL;
+ content = (N_VectorContent_Parallel) malloc(sizeof(struct _N_VectorContent_Parallel));
+ if (content == NULL) { free(ops); free(v); return(NULL); }
+
+ /* Attach lengths and communicator */
+ content->local_length = local_length;
+ content->global_length = global_length;
+ content->comm = comm;
+ content->own_data = FALSE;
+ content->data = NULL;
+
+ /* Attach content and ops */
+ v->content = content;
+ v->ops = ops;
+
+ return(v);
+}
+
+/* ----------------------------------------------------------------
+ * Function to create a new parallel vector
+ */
+
+N_Vector N_VNew_Parallel(MPI_Comm comm,
+ long int local_length,
+ long int global_length)
+{
+ N_Vector v;
+ realtype *data;
+
+ v = NULL;
+ v = N_VNewEmpty_Parallel(comm, local_length, global_length);
+ if (v == NULL) return(NULL);
+
+ /* Create data */
+ if(local_length > 0) {
+
+ /* Allocate memory */
+ data = NULL;
+ data = (realtype *) malloc(local_length * sizeof(realtype));
+ if(data == NULL) { N_VDestroy_Parallel(v); return(NULL); }
+
+ /* Attach data */
+ NV_OWN_DATA_P(v) = TRUE;
+ NV_DATA_P(v) = data;
+
+ }
+
+ return(v);
+}
+
+/* ----------------------------------------------------------------
+ * Function to create a parallel N_Vector with user data component
+ */
+
+N_Vector N_VMake_Parallel(MPI_Comm comm,
+ long int local_length,
+ long int global_length,
+ realtype *v_data)
+{
+ N_Vector v;
+
+ v = NULL;
+ v = N_VNewEmpty_Parallel(comm, local_length, global_length);
+ if (v == NULL) return(NULL);
+
+ if (local_length > 0) {
+ /* Attach data */
+ NV_OWN_DATA_P(v) = FALSE;
+ NV_DATA_P(v) = v_data;
+ }
+
+ return(v);
+}
+
+/* ----------------------------------------------------------------
+ * Function to create an array of new parallel vectors.
+ */
+
+N_Vector *N_VCloneVectorArray_Parallel(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_Parallel(w);
+ if (vs[j] == NULL) {
+ N_VDestroyVectorArray_Parallel(vs, j-1);
+ return(NULL);
+ }
+ }
+
+ return(vs);
+}
+
+/* ----------------------------------------------------------------
+ * Function to create an array of new parallel vectors with empty
+ * (NULL) data array.
+ */
+
+N_Vector *N_VCloneVectorArrayEmpty_Parallel(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_Parallel(w);
+ if (vs[j] == NULL) {
+ N_VDestroyVectorArray_Parallel(vs, j-1);
+ return(NULL);
+ }
+ }
+
+ return(vs);
+}
+
+/* ----------------------------------------------------------------
+ * Function to free an array created with N_VCloneVectorArray_Parallel
+ */
+
+void N_VDestroyVectorArray_Parallel(N_Vector *vs, int count)
+{
+ int j;
+
+ for (j = 0; j < count; j++) N_VDestroy_Parallel(vs[j]);
+
+ free(vs); vs = NULL;
+
+ return;
+}
+
+/* ----------------------------------------------------------------
+ * Function to print a parallel vector
+ */
+
+void N_VPrint_Parallel(N_Vector x)
+{
+ long int i, N;
+ realtype *xd;
+
+ xd = NULL;
+
+ N = NV_LOCLENGTH_P(x);
+ xd = NV_DATA_P(x);
+
+ for (i = 0; i < N; i++) {
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("%Lg\n", xd[i]);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("%lg\n", xd[i]);
+#else
+ printf("%g\n", xd[i]);
+#endif
+ }
+ printf("\n");
+
+ return;
+}
+
+/*
+ * -----------------------------------------------------------------
+ * implementation of vector operations
+ * -----------------------------------------------------------------
+ */
+
+N_Vector N_VCloneEmpty_Parallel(N_Vector w)
+{
+ N_Vector v;
+ N_Vector_Ops ops;
+ N_VectorContent_Parallel content;
+
+ 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->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 */
+ content = NULL;
+ content = (N_VectorContent_Parallel) malloc(sizeof(struct _N_VectorContent_Parallel));
+ if (content == NULL) { free(ops); free(v); return(NULL); }
+
+ /* Attach lengths and communicator */
+ 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->data = NULL;
+
+ /* Attach content and ops */
+ v->content = content;
+ v->ops = ops;
+
+ return(v);
+}
+
+N_Vector N_VClone_Parallel(N_Vector w)
+{
+ N_Vector v;
+ realtype *data;
+ long int local_length;
+
+ v = NULL;
+ v = N_VCloneEmpty_Parallel(w);
+ if (v == NULL) return(NULL);
+
+ local_length = NV_LOCLENGTH_P(w);
+
+ /* Create data */
+ if(local_length > 0) {
+
+ /* Allocate memory */
+ data = NULL;
+ data = (realtype *) malloc(local_length * sizeof(realtype));
+ if(data == NULL) { N_VDestroy_Parallel(v); return(NULL); }
+
+ /* Attach data */
+ NV_OWN_DATA_P(v) = TRUE;
+ NV_DATA_P(v) = data;
+ }
+
+ return(v);
+}
+
+void N_VDestroy_Parallel(N_Vector v)
+{
+ if ((NV_OWN_DATA_P(v) == TRUE) && (NV_DATA_P(v) != NULL)) {
+ free(NV_DATA_P(v));
+ NV_DATA_P(v) = NULL;
+ }
+ free(v->content); v->content = NULL;
+ free(v->ops); v->ops = NULL;
+ free(v); v = NULL;
+
+ return;
+}
+
+void N_VSpace_Parallel(N_Vector v, long int *lrw, long int *liw)
+{
+ MPI_Comm comm;
+ int npes;
+
+ comm = NV_COMM_P(v);
+ MPI_Comm_size(comm, &npes);
+
+ *lrw = NV_GLOBLENGTH_P(v);
+ *liw = 2*npes;
+
+ return;
+}
+
+realtype *N_VGetArrayPointer_Parallel(N_Vector v)
+{
+ return((realtype *) NV_DATA_P(v));
+}
+
+void N_VSetArrayPointer_Parallel(realtype *v_data, N_Vector v)
+{
+ if (NV_LOCLENGTH_P(v) > 0) NV_DATA_P(v) = v_data;
+
+ return;
+}
+
+void N_VLinearSum_Parallel(realtype a, N_Vector x, realtype b, N_Vector y, N_Vector z)
+{
+ long int i, N;
+ realtype c, *xd, *yd, *zd;
+ N_Vector v1, v2;
+ booleantype test;
+
+ xd = yd = zd = NULL;
+
+ if ((b == ONE) && (z == y)) { /* BLAS usage: axpy y <- ax+y */
+ Vaxpy_Parallel(a, x, y);
+ return;
+ }
+
+ if ((a == ONE) && (z == x)) { /* BLAS usage: axpy x <- by+x */
+ Vaxpy_Parallel(b, y, x);
+ return;
+ }
+
+ /* Case: a == b == 1.0 */
+
+ if ((a == ONE) && (b == ONE)) {
+ VSum_Parallel(x, y, z);
+ return;
+ }
+
+ /* Cases: (1) a == 1.0, b = -1.0, (2) a == -1.0, b == 1.0 */
+
+ if ((test = ((a == ONE) && (b == -ONE))) || ((a == -ONE) && (b == ONE))) {
+ v1 = test ? y : x;
+ v2 = test ? x : y;
+ VDiff_Parallel(v2, v1, z);
+ return;
+ }
+
+ /* Cases: (1) a == 1.0, b == other or 0.0, (2) a == other or 0.0, b == 1.0 */
+ /* if a or b is 0.0, then user should have called N_VScale */
+
+ if ((test = (a == ONE)) || (b == ONE)) {
+ c = test ? b : a;
+ v1 = test ? y : x;
+ v2 = test ? x : y;
+ VLin1_Parallel(c, v1, v2, z);
+ return;
+ }
+
+ /* Cases: (1) a == -1.0, b != 1.0, (2) a != 1.0, b == -1.0 */
+
+ if ((test = (a == -ONE)) || (b == -ONE)) {
+ c = test ? b : a;
+ v1 = test ? y : x;
+ v2 = test ? x : y;
+ VLin2_Parallel(c, v1, v2, z);
+ return;
+ }
+
+ /* Case: a == b */
+ /* catches case both a and b are 0.0 - user should have called N_VConst */
+
+ if (a == b) {
+ VScaleSum_Parallel(a, x, y, z);
+ return;
+ }
+
+ /* Case: a == -b */
+
+ if (a == -b) {
+ VScaleDiff_Parallel(a, x, y, z);
+ return;
+ }
+
+ /* Do all cases not handled above:
+ (1) a == other, b == 0.0 - user should have called N_VScale
+ (2) a == 0.0, b == other - user should have called N_VScale
+ (3) a,b == other, a !=b, a != -b */
+
+ N = NV_LOCLENGTH_P(x);
+ xd = NV_DATA_P(x);
+ yd = NV_DATA_P(y);
+ zd = NV_DATA_P(z);
+
+ for (i = 0; i < N; i++)
+ zd[i] = (a*xd[i])+(b*yd[i]);
+
+ return;
+}
+
+void N_VConst_Parallel(realtype c, N_Vector z)
+{
+ long int i, N;
+ realtype *zd;
+
+ zd = NULL;
+
+ N = NV_LOCLENGTH_P(z);
+ zd = NV_DATA_P(z);
+
+ for (i = 0; i < N; i++) zd[i] = c;
+
+ return;
+}
+
+void N_VProd_Parallel(N_Vector x, N_Vector y, N_Vector z)
+{
+ long int i, N;
+ realtype *xd, *yd, *zd;
+
+ xd = yd = zd = NULL;
+
+ N = NV_LOCLENGTH_P(x);
+ xd = NV_DATA_P(x);
+ yd = NV_DATA_P(y);
+ zd = NV_DATA_P(z);
+
+ for (i = 0; i < N; i++)
+ zd[i] = xd[i]*yd[i];
+
+ return;
+}
+
+void N_VDiv_Parallel(N_Vector x, N_Vector y, N_Vector z)
+{
+ long int i, N;
+ realtype *xd, *yd, *zd;
+
+ xd = yd = zd = NULL;
+
+ N = NV_LOCLENGTH_P(x);
+ xd = NV_DATA_P(x);
+ yd = NV_DATA_P(y);
+ zd = NV_DATA_P(z);
+
+ for (i = 0; i < N; i++)
+ zd[i] = xd[i]/yd[i];
+
+ return;
+}
+
+void N_VScale_Parallel(realtype c, N_Vector x, N_Vector z)
+{
+ long int i, N;
+ realtype *xd, *zd;
+
+ xd = zd = NULL;
+
+ if (z == x) { /* BLAS usage: scale x <- cx */
+ VScaleBy_Parallel(c, x);
+ return;
+ }
+
+ if (c == ONE) {
+ VCopy_Parallel(x, z);
+ } else if (c == -ONE) {
+ VNeg_Parallel(x, z);
+ } else {
+ N = NV_LOCLENGTH_P(x);
+ xd = NV_DATA_P(x);
+ zd = NV_DATA_P(z);
+ for (i = 0; i < N; i++)
+ zd[i] = c*xd[i];
+ }
+
+ return;
+}
+
+void N_VAbs_Parallel(N_Vector x, N_Vector z)
+{
+ long int i, N;
+ realtype *xd, *zd;
+
+ xd = zd = NULL;
+
+ N = NV_LOCLENGTH_P(x);
+ xd = NV_DATA_P(x);
+ zd = NV_DATA_P(z);
+
+ for (i = 0; i < N; i++)
+ zd[i] = ABS(xd[i]);
+
+ return;
+}
+
+void N_VInv_Parallel(N_Vector x, N_Vector z)
+{
+ long int i, N;
+ realtype *xd, *zd;
+
+ xd = zd = NULL;
+
+ N = NV_LOCLENGTH_P(x);
+ xd = NV_DATA_P(x);
+ zd = NV_DATA_P(z);
+
+ for (i = 0; i < N; i++)
+ zd[i] = ONE/xd[i];
+
+ return;
+}
+
+void N_VAddConst_Parallel(N_Vector x, realtype b, N_Vector z)
+{
+ long int i, N;
+ realtype *xd, *zd;
+
+ xd = zd = NULL;
+
+ N = NV_LOCLENGTH_P(x);
+ xd = NV_DATA_P(x);
+ zd = NV_DATA_P(z);
+
+ for (i = 0; i < N; i++) zd[i] = xd[i]+b;
+
+ return;
+}
+
+realtype N_VDotProd_Parallel(N_Vector x, N_Vector y)
+{
+ long int i, N;
+ realtype sum, *xd, *yd, gsum;
+ MPI_Comm comm;
+
+ sum = ZERO;
+ xd = yd = NULL;
+
+ N = NV_LOCLENGTH_P(x);
+ xd = NV_DATA_P(x);
+ yd = NV_DATA_P(y);
+ comm = NV_COMM_P(x);
+
+ for (i = 0; i < N; i++) sum += xd[i]*yd[i];
+
+ gsum = VAllReduce_Parallel(sum, 1, comm);
+
+ return(gsum);
+}
+
+realtype N_VMaxNorm_Parallel(N_Vector x)
+{
+ long int i, N;
+ realtype max, *xd, gmax;
+ MPI_Comm comm;
+
+ xd = NULL;
+
+ N = NV_LOCLENGTH_P(x);
+ xd = NV_DATA_P(x);
+ comm = NV_COMM_P(x);
+
+ max = ZERO;
+
+ for (i = 0; i < N; i++) {
+ if (ABS(xd[i]) > max) max = ABS(xd[i]);
+ }
+
+ gmax = VAllReduce_Parallel(max, 2, comm);
+
+ return(gmax);
+}
+
+realtype N_VWrmsNorm_Parallel(N_Vector x, N_Vector w)
+{
+ long int i, N, N_global;
+ realtype sum, prodi, *xd, *wd, gsum;
+ MPI_Comm comm;
+
+ sum = ZERO;
+ xd = wd = NULL;
+
+ N = NV_LOCLENGTH_P(x);
+ N_global = NV_GLOBLENGTH_P(x);
+ xd = NV_DATA_P(x);
+ wd = NV_DATA_P(w);
+ comm = NV_COMM_P(x);
+
+ for (i = 0; i < N; i++) {
+ prodi = xd[i]*wd[i];
+ sum += SQR(prodi);
+ }
+
+ gsum = VAllReduce_Parallel(sum, 1, comm);
+
+ return(RSqrt(gsum/N_global));
+}
+
+realtype N_VWrmsNormMask_Parallel(N_Vector x, N_Vector w, N_Vector id)
+{
+ long int i, N, N_global;
+ realtype sum, prodi, *xd, *wd, *idd, gsum;
+ MPI_Comm comm;
+
+ sum = ZERO;
+ xd = wd = idd = NULL;
+
+ N = NV_LOCLENGTH_P(x);
+ N_global = NV_GLOBLENGTH_P(x);
+ xd = NV_DATA_P(x);
+ wd = NV_DATA_P(w);
+ idd = NV_DATA_P(id);
+ comm = NV_COMM_P(x);
+
+ for (i = 0; i < N; i++) {
+ if (idd[i] > ZERO) {
+ prodi = xd[i]*wd[i];
+ sum += SQR(prodi);
+ }
+ }
+
+ gsum = VAllReduce_Parallel(sum, 1, comm);
+
+ return(RSqrt(gsum/N_global));
+}
+
+realtype N_VMin_Parallel(N_Vector x)
+{
+ long int i, N;
+ realtype min, *xd, gmin;
+ MPI_Comm comm;
+
+ xd = NULL;
+
+ N = NV_LOCLENGTH_P(x);
+ comm = NV_COMM_P(x);
+
+ min = BIG_REAL;
+
+ if (N > 0) {
+
+ xd = NV_DATA_P(x);
+
+ min = xd[0];
+
+ for (i = 1; i < N; i++) {
+ if (xd[i] < min) min = xd[i];
+ }
+
+ }
+
+ gmin = VAllReduce_Parallel(min, 3, comm);
+
+ return(gmin);
+}
+
+realtype N_VWL2Norm_Parallel(N_Vector x, N_Vector w)
+{
+ long int i, N;
+ realtype sum, prodi, *xd, *wd, gsum;
+ MPI_Comm comm;
+
+ sum = ZERO;
+ xd = wd = NULL;
+
+ N = NV_LOCLENGTH_P(x);
+ xd = NV_DATA_P(x);
+ wd = NV_DATA_P(w);
+ comm = NV_COMM_P(x);
+
+ for (i = 0; i < N; i++) {
+ prodi = xd[i]*wd[i];
+ sum += SQR(prodi);
+ }
+
+ gsum = VAllReduce_Parallel(sum, 1, comm);
+
+ return(RSqrt(gsum));
+}
+
+realtype N_VL1Norm_Parallel(N_Vector x)
+{
+ long int i, N;
+ realtype sum, gsum, *xd;
+ MPI_Comm comm;
+
+ sum = ZERO;
+ xd = NULL;
+
+ N = NV_LOCLENGTH_P(x);
+ xd = NV_DATA_P(x);
+ comm = NV_COMM_P(x);
+
+ for (i = 0; i<N; i++)
+ sum += ABS(xd[i]);
+
+ gsum = VAllReduce_Parallel(sum, 1, comm);
+
+ return(gsum);
+}
+
+void N_VCompare_Parallel(realtype c, N_Vector x, N_Vector z)
+{
+ long int i, N;
+ realtype *xd, *zd;
+
+ xd = zd = NULL;
+
+ N = NV_LOCLENGTH_P(x);
+ xd = NV_DATA_P(x);
+ zd = NV_DATA_P(z);
+
+ for (i = 0; i < N; i++) {
+ zd[i] = (ABS(xd[i]) >= c) ? ONE : ZERO;
+ }
+
+ return;
+}
+
+booleantype N_VInvTest_Parallel(N_Vector x, N_Vector z)
+{
+ long int i, N;
+ realtype *xd, *zd, val, gval;
+ MPI_Comm comm;
+
+ xd = zd = NULL;
+
+ N = NV_LOCLENGTH_P(x);
+ xd = NV_DATA_P(x);
+ zd = NV_DATA_P(z);
+ comm = NV_COMM_P(x);
+
+ val = ONE;
+ for (i = 0; i < N; i++) {
+ if (xd[i] == ZERO)
+ val = ZERO;
+ else
+ zd[i] = ONE/xd[i];
+ }
+
+ gval = VAllReduce_Parallel(val, 3, comm);
+
+ if (gval == ZERO)
+ return(FALSE);
+ else
+ return(TRUE);
+}
+
+booleantype N_VConstrMask_Parallel(N_Vector c, N_Vector x, N_Vector m)
+{
+ long int i, N;
+ realtype temp;
+ realtype *cd, *xd, *md;
+ MPI_Comm comm;
+
+ cd = xd = md = NULL;
+
+ N = NV_LOCLENGTH_P(x);
+ xd = NV_DATA_P(x);
+ cd = NV_DATA_P(c);
+ md = NV_DATA_P(m);
+ comm = NV_COMM_P(x);
+
+ temp = ONE;
+
+ 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) { temp = ZERO; md[i] = ONE; }
+ continue;
+ }
+ if (cd[i] > HALF || cd[i] < -HALF) {
+ if (xd[i]*cd[i] < ZERO ) { temp = ZERO; md[i] = ONE; }
+ }
+ }
+
+ temp = VAllReduce_Parallel(temp, 3, comm);
+
+ if (temp == ONE) return(TRUE);
+ else return(FALSE);
+}
+
+realtype N_VMinQuotient_Parallel(N_Vector num, N_Vector denom)
+{
+ booleantype notEvenOnce;
+ long int i, N;
+ realtype *nd, *dd, min;
+ MPI_Comm comm;
+
+ nd = dd = NULL;
+
+ N = NV_LOCLENGTH_P(num);
+ nd = NV_DATA_P(num);
+ dd = NV_DATA_P(denom);
+ comm = NV_COMM_P(num);
+
+ notEvenOnce = TRUE;
+ min = BIG_REAL;
+
+ for (i = 0; i < N; i++) {
+ if (dd[i] == ZERO) continue;
+ else {
+ if (!notEvenOnce) min = MIN(min, nd[i]/dd[i]);
+ else {
+ min = nd[i]/dd[i];
+ notEvenOnce = FALSE;
+ }
+ }
+ }
+
+ return(VAllReduce_Parallel(min, 3, comm));
+}
+
+/*
+ * -----------------------------------------------------------------
+ * private functions
+ * -----------------------------------------------------------------
+ */
+
+static realtype VAllReduce_Parallel(realtype d, int op, MPI_Comm comm)
+{
+ /*
+ * This function does a global reduction. The operation is
+ * sum if op = 1,
+ * max if op = 2,
+ * min if op = 3.
+ * The operation is over all processors in the communicator
+ */
+
+ realtype out;
+
+ switch (op) {
+ case 1: MPI_Allreduce(&d, &out, 1, PVEC_REAL_MPI_TYPE, MPI_SUM, comm);
+ break;
+
+ case 2: MPI_Allreduce(&d, &out, 1, PVEC_REAL_MPI_TYPE, MPI_MAX, comm);
+ break;
+
+ case 3: MPI_Allreduce(&d, &out, 1, PVEC_REAL_MPI_TYPE, MPI_MIN, comm);
+ break;
+
+ default: break;
+ }
+
+ return(out);
+}
+
+static void VCopy_Parallel(N_Vector x, N_Vector z)
+{
+ long int i, N;
+ realtype *xd, *zd;
+
+ xd = zd = NULL;
+
+ N = NV_LOCLENGTH_P(x);
+ xd = NV_DATA_P(x);
+ zd = NV_DATA_P(z);
+
+ for (i = 0; i < N; i++)
+ zd[i] = xd[i];
+
+ return;
+}
+
+static void VSum_Parallel(N_Vector x, N_Vector y, N_Vector z)
+{
+ long int i, N;
+ realtype *xd, *yd, *zd;
+
+ xd = yd = zd = NULL;
+
+ N = NV_LOCLENGTH_P(x);
+ xd = NV_DATA_P(x);
+ yd = NV_DATA_P(y);
+ zd = NV_DATA_P(z);
+
+ for (i = 0; i < N; i++)
+ zd[i] = xd[i]+yd[i];
+
+ return;
+}
+
+static void VDiff_Parallel(N_Vector x, N_Vector y, N_Vector z)
+{
+ long int i, N;
+ realtype *xd, *yd, *zd;
+
+ xd = yd = zd = NULL;
+
+ N = NV_LOCLENGTH_P(x);
+ xd = NV_DATA_P(x);
+ yd = NV_DATA_P(y);
+ zd = NV_DATA_P(z);
+
+ for (i = 0; i < N; i++)
+ zd[i] = xd[i]-yd[i];
+
+ return;
+}
+
+static void VNeg_Parallel(N_Vector x, N_Vector z)
+{
+ long int i, N;
+ realtype *xd, *zd;
+
+ xd = zd = NULL;
+
+ N = NV_LOCLENGTH_P(x);
+ xd = NV_DATA_P(x);
+ zd = NV_DATA_P(z);
+
+ for (i = 0; i < N; i++)
+ zd[i] = -xd[i];
+
+ return;
+}
+
+static void VScaleSum_Parallel(realtype c, N_Vector x, N_Vector y, N_Vector z)
+{
+ long int i, N;
+ realtype *xd, *yd, *zd;
+
+ xd = yd = zd = NULL;
+
+ N = NV_LOCLENGTH_P(x);
+ xd = NV_DATA_P(x);
+ yd = NV_DATA_P(y);
+ zd = NV_DATA_P(z);
+
+ for (i = 0; i < N; i++)
+ zd[i] = c*(xd[i]+yd[i]);
+
+ return;
+}
+
+static void VScaleDiff_Parallel(realtype c, N_Vector x, N_Vector y, N_Vector z)
+{
+ long int i, N;
+ realtype *xd, *yd, *zd;
+
+ xd = yd = zd = NULL;
+
+ N = NV_LOCLENGTH_P(x);
+ xd = NV_DATA_P(x);
+ yd = NV_DATA_P(y);
+ zd = NV_DATA_P(z);
+
+ for (i = 0; i < N; i++)
+ zd[i] = c*(xd[i]-yd[i]);
+
+ return;
+}
+
+static void VLin1_Parallel(realtype a, N_Vector x, N_Vector y, N_Vector z)
+{
+ long int i, N;
+ realtype *xd, *yd, *zd;
+
+ xd = yd = zd = NULL;
+
+ N = NV_LOCLENGTH_P(x);
+ xd = NV_DATA_P(x);
+ yd = NV_DATA_P(y);
+ zd = NV_DATA_P(z);
+
+ for (i = 0; i < N; i++)
+ zd[i] = (a*xd[i])+yd[i];
+
+ return;
+}
+
+static void VLin2_Parallel(realtype a, N_Vector x, N_Vector y, N_Vector z)
+{
+ long int i, N;
+ realtype *xd, *yd, *zd;
+
+ xd = yd = zd = NULL;
+
+ N = NV_LOCLENGTH_P(x);
+ xd = NV_DATA_P(x);
+ yd = NV_DATA_P(y);
+ zd = NV_DATA_P(z);
+
+ for (i = 0; i < N; i++)
+ zd[i] = (a*xd[i])-yd[i];
+
+ return;
+}
+
+static void Vaxpy_Parallel(realtype a, N_Vector x, N_Vector y)
+{
+ long int i, N;
+ realtype *xd, *yd;
+
+ xd = yd = NULL;
+
+ N = NV_LOCLENGTH_P(x);
+ xd = NV_DATA_P(x);
+ yd = NV_DATA_P(y);
+
+ if (a == ONE) {
+ for (i = 0; i < N; i++)
+ yd[i] += xd[i];
+ return;
+ }
+
+ if (a == -ONE) {
+ for (i = 0; i < N; i++)
+ yd[i] -= xd[i];
+ return;
+ }
+
+ for (i = 0; i < N; i++)
+ yd[i] += a*xd[i];
+
+ return;
+}
+
+static void VScaleBy_Parallel(realtype a, N_Vector x)
+{
+ long int i, N;
+ realtype *xd;
+
+ xd = NULL;
+
+ N = NV_LOCLENGTH_P(x);
+ xd = NV_DATA_P(x);
+
+ for (i = 0; i < N; i++)
+ xd[i] *= a;
+
+ return;
+}
diff --git a/src/nvec_ser/CMakeLists.txt b/src/nvec_ser/CMakeLists.txt
new file mode 100644
index 0000000..9c97be5
--- /dev/null
+++ b/src/nvec_ser/CMakeLists.txt
@@ -0,0 +1,82 @@
+# ---------------------------------------------------------------
+# $Revision: 1.3 $
+# $Date: 2009/02/17 02:58:48 $
+# ---------------------------------------------------------------
+# Programmer: Radu Serban @ LLNL
+# ---------------------------------------------------------------
+# Copyright (c) 2007, The Regents of the University of California.
+# Produced at the Lawrence Livermore National Laboratory.
+# All rights reserved.
+# For details, see the LICENSE file.
+# ---------------------------------------------------------------
+# CMakeLists.txt file for the serial NVECTOR library
+
+INSTALL(CODE "MESSAGE(\"\nInstall NVECTOR_SERIAL\n\")")
+
+# Add variable nvecserial_SOURCES with the sources for the NVECSERIAL lib
+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)
+
+# 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)
+
+# 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 NVECSERIAL library
+# - Set the library name and make sure it is not deleted
+# - Install the NVECSERIAL library
+IF(BUILD_STATIC_LIBS)
+ ADD_LIBRARY(sundials_nvecserial_static STATIC ${nvecserial_SOURCES} ${shared_SOURCES})
+ SET_TARGET_PROPERTIES(sundials_nvecserial_static
+ PROPERTIES OUTPUT_NAME sundials_nvecserial CLEAN_DIRECT_OUTPUT 1)
+ INSTALL(TARGETS sundials_nvecserial_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)
+ ADD_LIBRARY(sundials_nvecserial_shared SHARED ${nvecserial_SOURCES} ${shared_SOURCES})
+ SET_TARGET_PROPERTIES(sundials_nvecserial_shared
+ PROPERTIES OUTPUT_NAME sundials_nvecserial CLEAN_DIRECT_OUTPUT 1)
+ SET_TARGET_PROPERTIES(sundials_nvecserial_shared
+ PROPERTIES VERSION ${nveclib_VERSION} SOVERSION ${nveclib_SOVERSION})
+ INSTALL(TARGETS sundials_nvecserial_shared DESTINATION lib)
+ENDIF(BUILD_SHARED_LIBS)
+
+# Install the NVECSERIAL header files
+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})
+ 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)
+
+#
+MESSAGE(STATUS "Added NVECTOR_SERIAL module")
diff --git a/src/nvec_ser/Makefile.in b/src/nvec_ser/Makefile.in
new file mode 100644
index 0000000..fe8a6dc
--- /dev/null
+++ b/src/nvec_ser/Makefile.in
@@ -0,0 +1,125 @@
+# -----------------------------------------------------------------
+# $Revision: 1.8 $
+# $Date: 2007/01/29 17:36:28 $
+# -----------------------------------------------------------------
+# Programmer(s): Radu Serban and Aaron Collier @ LLNL
+# -----------------------------------------------------------------
+# Copyright (c) 2002, The Regents of the University of California.
+# Produced at the Lawrence Livermore National Laboratory.
+# All rights reserved.
+# For details, see the LICENSE file.
+# -----------------------------------------------------------------
+# Makefile for serial NVECTOR module
+#
+# @configure_input@
+# -----------------------------------------------------------------
+
+SHELL = @SHELL@
+
+ at SET_MAKE@
+
+srcdir = @srcdir@
+builddir = @builddir@
+abs_builddir = @abs_builddir@
+top_builddir = @top_builddir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+includedir = @includedir@
+libdir = @libdir@
+
+INSTALL = @INSTALL@
+INSTALL_LIB = @INSTALL_PROGRAM@
+INSTALL_HEADER = @INSTALL_DATA@
+
+LIBTOOL = @LIBTOOL@
+LIBTOOL_DEPS = @LIBTOOL_DEPS@
+
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CC = @CC@
+CFLAGS = @CFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+
+FCMIX_ENABLED = @FCMIX_ENABLED@
+
+top_srcdir = $(srcdir)/../..
+
+INCLUDES = -I$(top_srcdir)/include -I$(top_builddir)/include
+
+LIB_REVISION = 0:2:0
+
+NVECSER_LIB = libsundials_nvecserial.la
+NVECSER_LIB_FILES = nvector_serial.lo
+
+FNVECSER_LIB = libsundials_fnvecserial.la
+FNVECSER_LIB_FILES = fnvector_serial.lo
+
+SHARED_LIB_FILES = $(top_builddir)/src/sundials/sundials_math.lo
+
+mkinstalldirs = $(SHELL) $(top_srcdir)/config/mkinstalldirs
+rminstalldirs = $(SHELL) $(top_srcdir)/config/rminstalldirs
+
+all: $(NVECSER_LIB) $(FNVECSER_LIB)
+
+$(NVECSER_LIB): shared $(NVECSER_LIB_FILES)
+ $(LIBTOOL) --mode=link $(CC) $(CFLAGS) -o $(NVECSER_LIB) $(NVECSER_LIB_FILES) $(SHARED_LIB_FILES) -rpath $(libdir) $(LDFLAGS) $(LIBS) -version-info $(LIB_REVISION)
+
+$(FNVECSER_LIB): $(FNVECSER_LIB_FILES)
+ @if test "X${FCMIX_ENABLED}" = "Xyes"; then \
+ echo "${LIBTOOL} --mode=link ${CC} ${CFLAGS} -o ${FNVECSER_LIB} ${FNVECSER_LIB_FILES} ${SHARED_LIB_FILES} -rpath ${libdir} $(LDFLAGS) ${LIBS} -version-info ${LIB_REVISION}" ; \
+ ${LIBTOOL} --mode=link ${CC} ${CFLAGS} -o ${FNVECSER_LIB} ${FNVECSER_LIB_FILES} ${SHARED_LIB_FILES} -rpath ${libdir} $(LDFLAGS) ${LIBS} -version-info ${LIB_REVISION} ; \
+ fi
+
+install: $(NVECSER_LIB) $(FNVECSER_LIB)
+ $(mkinstalldirs) $(includedir)/nvector
+ $(mkinstalldirs) $(libdir)
+ $(LIBTOOL) --mode=install $(INSTALL_LIB) $(NVECSER_LIB) $(libdir)
+ $(INSTALL_HEADER) $(top_srcdir)/include/nvector/nvector_serial.h $(includedir)/nvector/
+ @if test "X${FCMIX_ENABLED}" = "Xyes"; then \
+ echo "${LIBTOOL} --mode=install ${INSTALL_LIB} ${FNVECSER_LIB} ${libdir}" ; \
+ ${LIBTOOL} --mode=install ${INSTALL_LIB} ${FNVECSER_LIB} ${libdir} ; \
+ fi
+
+uninstall:
+ $(LIBTOOL) --mode=uninstall rm -f $(libdir)/$(NVECSER_LIB)
+ @if test "X${FCMIX_ENABLED}" = "Xyes"; then \
+ echo "${LIBTOOL} --mode=uninstall rm -f ${libdir}/${FNVECSER_LIB}" ; \
+ ${LIBTOOL} --mode=uninstall rm -f ${libdir}/${FNVECSER_LIB} ; \
+ fi
+ rm -f $(includedir)/nvector/nvector_serial.h
+ $(rminstalldirs) ${includedir}/nvector
+
+shared:
+ @cd ${top_builddir}/src/sundials ; \
+ ${MAKE} ; \
+ cd ${abs_builddir}
+
+clean:
+ $(LIBTOOL) --mode=clean rm -f $(NVECSER_LIB)
+ rm -f $(NVECSER_LIB_FILES)
+ rm -f nvector_serial.o
+ @if test "X${FCMIX_ENABLED}" = "Xyes"; then \
+ echo "${LIBTOOL} --mode=clean rm -f ${FNVECSER_LIB}" ; \
+ ${LIBTOOL} --mode=clean rm -f ${FNVECSER_LIB} ; \
+ echo "rm -f ${FNVECSER_LIB_FILES}" ; \
+ rm -f ${FNVECSER_LIB_FILES} ; \
+ echo "rm -f fnvector_serial.o" ; \
+ rm -f fnvector_serial.o ; \
+ fi
+
+distclean: clean
+ rm -f Makefile
+
+nvector_serial.lo: $(srcdir)/nvector_serial.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/nvector_serial.c
+fnvector_serial.lo: $(srcdir)/fnvector_serial.c
+ @if test "X${FCMIX_ENABLED}" = "Xyes"; then \
+ echo "${LIBTOOL} --mode=compile ${CC} ${CPPFLAGS} $(INCLUDES) ${CFLAGS} -c ${srcdir}/fnvector_serial.c" ; \
+ ${LIBTOOL} --mode=compile ${CC} ${CPPFLAGS} $(INCLUDES) ${CFLAGS} -c ${srcdir}/fnvector_serial.c ; \
+ fi
+
+libtool: $(top_builddir)/$(LIBTOOL_DEPS)
+ @cd ${top_builddir} ; \
+ ${SHELL} ./config.status --recheck ; \
+ cd ${abs_builddir}
diff --git a/src/nvec_ser/README b/src/nvec_ser/README
new file mode 100644
index 0000000..ab838a6
--- /dev/null
+++ b/src/nvec_ser/README
@@ -0,0 +1,139 @@
+ NVECTOR_SERIAL
+ Release 2.5.0, March 2012
+
+
+Serial implementation of the NVECTOR module for SUNDIALS.
+
+NVECTOR_SERIAL defines the content field of N_Vector to be a structure
+containing the length of the vector, a pointer to the beginning of a
+contiguous data array, and a boolean flag indicating ownership of the
+data array.
+
+NVECTOR_SERIAL defines five macros to provide access to the content of
+a serial N_Vector, several constructors for variables of type N_Vector,
+a constructor for an array of variables of type N_Vector, and destructors
+for N_Vector and N_Vector array.
+
+NVECTOR_SERIAL provides implementations for all vector operations defined
+by the generic NVECTOR module in the table of operations.
+
+
+A. Documentation
+----------------
+
+The serial NVECTOR implementation is fully described in the user documentation
+for any of the SUNDIALS solvers [1-5]. 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_NOTES.
+For complete installation instructions see any of the user guides.
+
+
+C. References
+-------------
+
+[1] A. C. Hindmarsh and R. Serban, "User Documentation for CVODE v2.7.0,"
+ LLNL technical report UCRL-MA-208108, December 2011.
+
+[2] A. C. Hindmarsh and R. Serban, "User Documentation for CVODES v2.7.0,"
+ LLNL technical report UCRL-MA-208111, December 2011.
+
+[3] A. C. Hindmarsh and R. Serban, "User Documentation for IDA v2.7.0,"
+ LLNL technical report UCRL-MA-208112, December 2011.
+
+[4] R. Serban and C. Petra, "User Documentation for IDAS v1.1.0,"
+ LLNL technical report UCRL-SM-234051, December 2011.
+
+[5] A. M. Collier, A. C. Hindmarsh, R. Serban,and C. S. Woodward, "User
+ Documentation for KINSOL v2.7.0," LLNL technical report UCRL-MA-208116,
+ December 2011.
+
+
+D. Releases
+-----------
+
+v. 2.5.0 - Mar. 2012
+v. 2.4.0 - May 2009
+v. 2.3.0 - Nov. 2006
+v. 2.2.0 - Mar. 2006
+v. 2.1.1 - May 2005
+v. 2.1.0 - Apr. 2005
+v. 2.0.2 - Mar. 2005
+v. 2.0.1 - Jan. 2005
+v. 2.0 - Dec. 2004
+v. 1.0 - Jul. 2002 (first SUNDIALS release)
+
+
+E. Revision History
+-------------------
+
+v. 2.4.0 (May 2009) ---> v. 2.5.0 (Mar. 2012)
+---------------------------------------------
+
+- Bug fix:
+ - consistently updated to using SUNDIALS_F77_FUNC in fcmix header files.
+
+v. 2.3.0 (Nov. 2006) ---> v. 2.4.0 (May 2009)
+---------------------------------------------
+
+- none
+
+
+v. 2.2.0 (Mar. 2006) ---> v. 2.3.0 (Nov. 2006)
+----------------------------------------------
+
+- Changes related to the build system
+ - reorganized source tree. Header files in ${srcdir}/include/nvector;
+ sources in ${srcdir}/src/nvec_ser
+ - exported header files in ${includedir}/sundials
+
+
+v. 2.1.1 (May 2005) ---> v. 2.2.0 (Mar. 2006)
+---------------------------------------------
+
+- none
+
+v. 2.1.0 (Apr. 2005) ---> v. 2.1.1 (May 2005)
+---------------------------------------------
+
+- Changes to data structures
+ - added N_VCloneEmpty to global vector operations table
+
+v. 2.0.2 (Mar. 2005) ---> v. 2.1.0 (Apr. 2005)
+----------------------------------------------
+
+- none
+
+v. 2.0.1 (Jan. 2005) ---> v. 2.0.2 (Mar. 2005)
+----------------------------------------------
+
+- Changes related to the build system
+ - fixed autoconf-related bug to allow configuration with the PGI Fortran compiler
+ - modified to use customized detection of the Fortran name mangling scheme
+ (autoconf's AC_F77_WRAPPERS routine is problematic on some platforms)
+ - added --with-mpi-flags as a configure option to allow user to specify
+ MPI-specific flags
+ - updated Makefiles for Fortran examples to avoid C++ compiler errors (now use
+ CC and MPICC to link)
+
+v. 2.0 (Dec. 2004) ---> v. 2.0.1 (Jan. 2005)
+--------------------------------------------
+
+- Changes related to the build system
+ - changed order of compiler directives in header files to avoid compilation
+ errors when using a C++ compiler.
+
+v. 1.0 (Jul. 2002) ---> v. 2.0 (Dec. 2004)
+------------------------------------------
+
+- Revised to correspond to new generic NVECTOR module
+ (see sundials/shared/README).
+- Extended the list of user-callable functions provided by NVECTOR_SERIAL
+ outside the table of vector operations.
+- Revised the F/C interface to use underscore flags for name mapping
+ and to use precision flag from configure.
+- Revised F/C routine NVECTOR names for uniformity.
diff --git a/src/nvec_ser/fnvector_serial.c b/src/nvec_ser/fnvector_serial.c
new file mode 100644
index 0000000..8f83c80
--- /dev/null
+++ b/src/nvec_ser/fnvector_serial.c
@@ -0,0 +1,147 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.1 $
+ * $Date: 2006/07/05 15:32:37 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * This file (companion of nvector_serial.h) contains the
+ * implementation needed for the Fortran initialization of serial
+ * vector operations.
+ * -----------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "fnvector_serial.h"
+
+/* Define global vector variables */
+
+N_Vector F2C_CVODE_vec;
+N_Vector F2C_CVODE_vecQ;
+N_Vector *F2C_CVODE_vecS;
+N_Vector F2C_CVODE_vecB;
+N_Vector F2C_CVODE_vecQB;
+
+N_Vector F2C_IDA_vec;
+N_Vector F2C_IDA_vecQ;
+N_Vector *F2C_IDA_vecS;
+N_Vector F2C_IDA_vecB;
+N_Vector F2C_IDA_vecQB;
+
+N_Vector F2C_KINSOL_vec;
+
+/* Fortran callable interfaces */
+
+void FNV_INITS(int *code, long int *N, int *ier)
+{
+ *ier = 0;
+
+ switch(*code) {
+ case FCMIX_CVODE:
+ F2C_CVODE_vec = NULL;
+ F2C_CVODE_vec = N_VNewEmpty_Serial(*N);
+ if (F2C_CVODE_vec == NULL) *ier = -1;
+ break;
+ case FCMIX_IDA:
+ F2C_IDA_vec = NULL;
+ F2C_IDA_vec = N_VNewEmpty_Serial(*N);
+ if (F2C_IDA_vec == NULL) *ier = -1;
+ break;
+ case FCMIX_KINSOL:
+ F2C_KINSOL_vec = NULL;
+ F2C_KINSOL_vec = N_VNewEmpty_Serial(*N);
+ if (F2C_KINSOL_vec == NULL) *ier = -1;
+ break;
+ default:
+ *ier = -1;
+ }
+}
+
+void FNV_INITS_Q(int *code, long int *Nq, int *ier)
+{
+ *ier = 0;
+
+ switch(*code) {
+ case FCMIX_CVODE:
+ F2C_CVODE_vecQ = NULL;
+ F2C_CVODE_vecQ = N_VNewEmpty_Serial(*Nq);
+ if (F2C_CVODE_vecQ == NULL) *ier = -1;
+ break;
+ case FCMIX_IDA:
+ F2C_IDA_vecQ = NULL;
+ F2C_IDA_vecQ = N_VNewEmpty_Serial(*Nq);
+ if (F2C_IDA_vecQ == NULL) *ier = -1;
+ break;
+ default:
+ *ier = -1;
+ }
+}
+
+void FNV_INITS_B(int *code, long int *NB, int *ier)
+{
+ *ier = 0;
+
+ switch(*code) {
+ case FCMIX_CVODE:
+ F2C_CVODE_vecB = NULL;
+ F2C_CVODE_vecB = N_VNewEmpty_Serial(*NB);
+ if (F2C_CVODE_vecB == NULL) *ier = -1;
+ break;
+ case FCMIX_IDA:
+ F2C_IDA_vecB = NULL;
+ F2C_IDA_vecB = N_VNewEmpty_Serial(*NB);
+ if (F2C_IDA_vecB == NULL) *ier = -1;
+ break;
+ default:
+ *ier = -1;
+ }
+}
+
+void FNV_INITS_QB(int *code, long int *NqB, int *ier)
+{
+ *ier = 0;
+
+ switch(*code) {
+ case FCMIX_CVODE:
+ F2C_CVODE_vecQB = NULL;
+ F2C_CVODE_vecQB = N_VNewEmpty_Serial(*NqB);
+ if (F2C_CVODE_vecQB == NULL) *ier = -1;
+ break;
+ case FCMIX_IDA:
+ F2C_IDA_vecQB = NULL;
+ F2C_IDA_vecQB = N_VNewEmpty_Serial(*NqB);
+ if (F2C_IDA_vecQB == NULL) *ier = -1;
+ break;
+ default:
+ *ier = -1;
+ }
+}
+
+void FNV_INITS_S(int *code, int *Ns, int *ier)
+{
+ *ier = 0;
+
+ switch(*code) {
+ case FCMIX_CVODE:
+ F2C_CVODE_vecS = NULL;
+ F2C_CVODE_vecS = (N_Vector *) N_VCloneVectorArrayEmpty_Serial(*Ns, F2C_CVODE_vec);
+ if (F2C_CVODE_vecS == NULL) *ier = -1;
+ break;
+ case FCMIX_IDA:
+ F2C_IDA_vecS = NULL;
+ F2C_IDA_vecS = (N_Vector *) N_VCloneVectorArrayEmpty_Serial(*Ns, F2C_IDA_vec);
+ if (F2C_IDA_vecS == NULL) *ier = -1;
+ break;
+ default:
+ *ier = -1;
+ }
+}
+
+
diff --git a/src/nvec_ser/fnvector_serial.h b/src/nvec_ser/fnvector_serial.h
new file mode 100644
index 0000000..4f49b21
--- /dev/null
+++ b/src/nvec_ser/fnvector_serial.h
@@ -0,0 +1,88 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.4 $
+ * $Date: 2010/12/15 19:40:08 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Radu Serban and Aaron Collier @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * This file (companion of nvector_serial.h) contains the
+ * definitions needed for the initialization of serial
+ * vector operations in Fortran.
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _FNVECTOR_SERIAL_H
+#define _FNVECTOR_SERIAL_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <nvector/nvector_serial.h>
+#include <sundials/sundials_fnvector.h>
+
+#if defined(SUNDIALS_F77_FUNC)
+#define FNV_INITS SUNDIALS_F77_FUNC(fnvinits, FNVINITS)
+#else
+#define FNV_INITS fnvinits_
+#endif
+
+#if defined(SUNDIALS_F77_FUNC_)
+
+#define FNV_INITS_Q SUNDIALS_F77_FUNC_(fnvinits_q, FNVINITS_Q)
+#define FNV_INITS_S SUNDIALS_F77_FUNC_(fnvinits_s, FNVINITS_S)
+#define FNV_INITS_B SUNDIALS_F77_FUNC_(fnvinits_b, FNVINITS_B)
+#define FNV_INITS_QB SUNDIALS_F77_FUNC_(fnvinits_qb, FNVINITS_QB)
+
+#else
+
+#define FNV_INITS_Q fnvinits_q_
+#define FNV_INITS_S fnvinits_s_
+#define FNV_INITS_B fnvinits_b_
+#define FNV_INITS_QB fnvinits_qb_
+
+#endif
+
+/* Declarations of global variables */
+
+extern N_Vector F2C_CVODE_vec;
+extern N_Vector F2C_CVODE_vecQ;
+extern N_Vector *F2C_CVODE_vecS;
+extern N_Vector F2C_CVODE_vecB;
+extern N_Vector F2C_CVODE_vecQB;
+
+extern N_Vector F2C_IDA_vec;
+extern N_Vector F2C_IDA_vecQ;
+extern N_Vector *F2C_IDA_vecS;
+extern N_Vector F2C_IDA_vecB;
+extern N_Vector F2C_IDA_vecQB;
+
+extern N_Vector F2C_KINSOL_vec;
+
+/*
+ * Prototypes of exported functions
+ *
+ * FNV_INITS - initializes serial vector operations for main problem
+ * FNV_INITS_Q - initializes serial vector operations for quadratures
+ * FNV_INITS_S - initializes serial vector operations for sensitivities
+ * FNV_INITS_B - initializes serial vector operations for adjoint problem
+ * FNV_INITS_QB - initializes serial vector operations for adjoint quadratures
+ *
+ */
+
+void FNV_INITS(int *code, long int *neq, int *ier);
+void FNV_INITS_Q(int *code, long int *Nq, int *ier);
+void FNV_INITS_S(int *code, int *Ns, int *ier);
+void FNV_INITS_B(int *code, long int *NB, int *ier);
+void FNV_INITS_QB(int *code, long int *NqB, int *ier);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/nvec_ser/nvector_serial.c b/src/nvec_ser/nvector_serial.c
new file mode 100644
index 0000000..c890253
--- /dev/null
+++ b/src/nvec_ser/nvector_serial.c
@@ -0,0 +1,1034 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.1 $
+ * $Date: 2006/07/05 15:32:37 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh, Radu Serban,
+ * and Aaron Collier @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * This is the implementation file for a serial implementation
+ * of the NVECTOR package.
+ * -----------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <nvector/nvector_serial.h>
+#include <sundials/sundials_math.h>
+
+#define ZERO RCONST(0.0)
+#define HALF RCONST(0.5)
+#define ONE RCONST(1.0)
+#define ONEPT5 RCONST(1.5)
+
+/* Private function prototypes */
+/* z=x */
+static void VCopy_Serial(N_Vector x, N_Vector z);
+/* z=x+y */
+static void VSum_Serial(N_Vector x, N_Vector y, N_Vector z);
+/* z=x-y */
+static void VDiff_Serial(N_Vector x, N_Vector y, N_Vector z);
+/* z=-x */
+static void VNeg_Serial(N_Vector x, N_Vector z);
+/* z=c(x+y) */
+static void VScaleSum_Serial(realtype c, N_Vector x, N_Vector y, N_Vector z);
+/* z=c(x-y) */
+static void VScaleDiff_Serial(realtype c, N_Vector x, N_Vector y, N_Vector z);
+/* z=ax+y */
+static void VLin1_Serial(realtype a, N_Vector x, N_Vector y, N_Vector z);
+/* z=ax-y */
+static void VLin2_Serial(realtype a, N_Vector x, N_Vector y, N_Vector z);
+/* y <- ax+y */
+static void Vaxpy_Serial(realtype a, N_Vector x, N_Vector y);
+/* x <- ax */
+static void VScaleBy_Serial(realtype a, N_Vector x);
+
+/*
+ * -----------------------------------------------------------------
+ * exported functions
+ * -----------------------------------------------------------------
+ */
+
+/* ----------------------------------------------------------------------------
+ * Function to create a new empty serial vector
+ */
+
+N_Vector N_VNewEmpty_Serial(long int length)
+{
+ N_Vector v;
+ N_Vector_Ops ops;
+ N_VectorContent_Serial 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->nvclone = N_VClone_Serial;
+ ops->nvcloneempty = N_VCloneEmpty_Serial;
+ ops->nvdestroy = N_VDestroy_Serial;
+ ops->nvspace = N_VSpace_Serial;
+ ops->nvgetarraypointer = N_VGetArrayPointer_Serial;
+ ops->nvsetarraypointer = N_VSetArrayPointer_Serial;
+ ops->nvlinearsum = N_VLinearSum_Serial;
+ ops->nvconst = N_VConst_Serial;
+ ops->nvprod = N_VProd_Serial;
+ ops->nvdiv = N_VDiv_Serial;
+ ops->nvscale = N_VScale_Serial;
+ ops->nvabs = N_VAbs_Serial;
+ ops->nvinv = N_VInv_Serial;
+ ops->nvaddconst = N_VAddConst_Serial;
+ ops->nvdotprod = N_VDotProd_Serial;
+ ops->nvmaxnorm = N_VMaxNorm_Serial;
+ ops->nvwrmsnormmask = N_VWrmsNormMask_Serial;
+ ops->nvwrmsnorm = N_VWrmsNorm_Serial;
+ ops->nvmin = N_VMin_Serial;
+ ops->nvwl2norm = N_VWL2Norm_Serial;
+ ops->nvl1norm = N_VL1Norm_Serial;
+ ops->nvcompare = N_VCompare_Serial;
+ ops->nvinvtest = N_VInvTest_Serial;
+ ops->nvconstrmask = N_VConstrMask_Serial;
+ ops->nvminquotient = N_VMinQuotient_Serial;
+
+ /* Create content */
+ content = NULL;
+ content = (N_VectorContent_Serial) malloc(sizeof(struct _N_VectorContent_Serial));
+ if (content == NULL) { free(ops); free(v); return(NULL); }
+
+ content->length = length;
+ content->own_data = FALSE;
+ content->data = NULL;
+
+ /* Attach content and ops */
+ v->content = content;
+ v->ops = ops;
+
+ return(v);
+}
+
+/* ----------------------------------------------------------------------------
+ * Function to create a new serial vector
+ */
+
+N_Vector N_VNew_Serial(long int length)
+{
+ N_Vector v;
+ realtype *data;
+
+ v = NULL;
+ v = N_VNewEmpty_Serial(length);
+ if (v == NULL) return(NULL);
+
+ /* Create data */
+ if (length > 0) {
+
+ /* Allocate memory */
+ data = NULL;
+ data = (realtype *) malloc(length * sizeof(realtype));
+ if(data == NULL) { N_VDestroy_Serial(v); return(NULL); }
+
+ /* Attach data */
+ NV_OWN_DATA_S(v) = TRUE;
+ NV_DATA_S(v) = data;
+
+ }
+
+ return(v);
+}
+
+/* ----------------------------------------------------------------------------
+ * Function to create a serial N_Vector with user data component
+ */
+
+N_Vector N_VMake_Serial(long int length, realtype *v_data)
+{
+ N_Vector v;
+
+ v = NULL;
+ v = N_VNewEmpty_Serial(length);
+ if (v == NULL) return(NULL);
+
+ if (length > 0) {
+ /* Attach data */
+ NV_OWN_DATA_S(v) = FALSE;
+ NV_DATA_S(v) = v_data;
+ }
+
+ return(v);
+}
+
+/* ----------------------------------------------------------------------------
+ * Function to create an array of new serial vectors.
+ */
+
+N_Vector *N_VCloneVectorArray_Serial(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_Serial(w);
+ if (vs[j] == NULL) {
+ N_VDestroyVectorArray_Serial(vs, j-1);
+ return(NULL);
+ }
+ }
+
+ return(vs);
+}
+
+/* ----------------------------------------------------------------------------
+ * Function to create an array of new serial vectors with NULL data array.
+ */
+
+N_Vector *N_VCloneVectorArrayEmpty_Serial(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_Serial(w);
+ if (vs[j] == NULL) {
+ N_VDestroyVectorArray_Serial(vs, j-1);
+ return(NULL);
+ }
+ }
+
+ return(vs);
+}
+
+/* ----------------------------------------------------------------------------
+ * Function to free an array created with N_VCloneVectorArray_Serial
+ */
+
+void N_VDestroyVectorArray_Serial(N_Vector *vs, int count)
+{
+ int j;
+
+ for (j = 0; j < count; j++) N_VDestroy_Serial(vs[j]);
+
+ free(vs); vs = NULL;
+
+ return;
+}
+
+/* ----------------------------------------------------------------------------
+ * Function to print the a serial vector
+ */
+
+void N_VPrint_Serial(N_Vector x)
+{
+ long int i, N;
+ realtype *xd;
+
+ xd = NULL;
+
+ N = NV_LENGTH_S(x);
+ xd = NV_DATA_S(x);
+
+ for (i = 0; i < N; i++) {
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("%11.8Lg\n", xd[i]);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("%11.8lg\n", xd[i]);
+#else
+ printf("%11.8g\n", xd[i]);
+#endif
+ }
+ printf("\n");
+
+ return;
+}
+
+/*
+ * -----------------------------------------------------------------
+ * implementation of vector operations
+ * -----------------------------------------------------------------
+ */
+
+N_Vector N_VCloneEmpty_Serial(N_Vector w)
+{
+ N_Vector v;
+ N_Vector_Ops ops;
+ N_VectorContent_Serial content;
+
+ 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->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 */
+ content = NULL;
+ content = (N_VectorContent_Serial) malloc(sizeof(struct _N_VectorContent_Serial));
+ if (content == NULL) { free(ops); free(v); return(NULL); }
+
+ content->length = NV_LENGTH_S(w);
+ content->own_data = FALSE;
+ content->data = NULL;
+
+ /* Attach content and ops */
+ v->content = content;
+ v->ops = ops;
+
+ return(v);
+}
+
+N_Vector N_VClone_Serial(N_Vector w)
+{
+ N_Vector v;
+ realtype *data;
+ long int length;
+
+ v = NULL;
+ v = N_VCloneEmpty_Serial(w);
+ if (v == NULL) return(NULL);
+
+ length = NV_LENGTH_S(w);
+
+ /* Create data */
+ if (length > 0) {
+
+ /* Allocate memory */
+ data = NULL;
+ data = (realtype *) malloc(length * sizeof(realtype));
+ if(data == NULL) { N_VDestroy_Serial(v); return(NULL); }
+
+ /* Attach data */
+ NV_OWN_DATA_S(v) = TRUE;
+ NV_DATA_S(v) = data;
+
+ }
+
+ return(v);
+}
+
+void N_VDestroy_Serial(N_Vector v)
+{
+ if (NV_OWN_DATA_S(v) == TRUE) {
+ free(NV_DATA_S(v));
+ NV_DATA_S(v) = NULL;
+ }
+ free(v->content); v->content = NULL;
+ free(v->ops); v->ops = NULL;
+ free(v); v = NULL;
+
+ return;
+}
+
+void N_VSpace_Serial(N_Vector v, long int *lrw, long int *liw)
+{
+ *lrw = NV_LENGTH_S(v);
+ *liw = 1;
+
+ return;
+}
+
+realtype *N_VGetArrayPointer_Serial(N_Vector v)
+{
+ return((realtype *) NV_DATA_S(v));
+}
+
+void N_VSetArrayPointer_Serial(realtype *v_data, N_Vector v)
+{
+ if (NV_LENGTH_S(v) > 0) NV_DATA_S(v) = v_data;
+
+ return;
+}
+
+void N_VLinearSum_Serial(realtype a, N_Vector x, realtype b, N_Vector y, N_Vector z)
+{
+ long int i, N;
+ realtype c, *xd, *yd, *zd;
+ N_Vector v1, v2;
+ booleantype test;
+
+ xd = yd = zd = NULL;
+
+ if ((b == ONE) && (z == y)) { /* BLAS usage: axpy y <- ax+y */
+ Vaxpy_Serial(a,x,y);
+ return;
+ }
+
+ if ((a == ONE) && (z == x)) { /* BLAS usage: axpy x <- by+x */
+ Vaxpy_Serial(b,y,x);
+ return;
+ }
+
+ /* Case: a == b == 1.0 */
+
+ if ((a == ONE) && (b == ONE)) {
+ VSum_Serial(x, y, z);
+ return;
+ }
+
+ /* Cases: (1) a == 1.0, b = -1.0, (2) a == -1.0, b == 1.0 */
+
+ if ((test = ((a == ONE) && (b == -ONE))) || ((a == -ONE) && (b == ONE))) {
+ v1 = test ? y : x;
+ v2 = test ? x : y;
+ VDiff_Serial(v2, v1, z);
+ return;
+ }
+
+ /* Cases: (1) a == 1.0, b == other or 0.0, (2) a == other or 0.0, b == 1.0 */
+ /* if a or b is 0.0, then user should have called N_VScale */
+
+ if ((test = (a == ONE)) || (b == ONE)) {
+ c = test ? b : a;
+ v1 = test ? y : x;
+ v2 = test ? x : y;
+ VLin1_Serial(c, v1, v2, z);
+ return;
+ }
+
+ /* Cases: (1) a == -1.0, b != 1.0, (2) a != 1.0, b == -1.0 */
+
+ if ((test = (a == -ONE)) || (b == -ONE)) {
+ c = test ? b : a;
+ v1 = test ? y : x;
+ v2 = test ? x : y;
+ VLin2_Serial(c, v1, v2, z);
+ return;
+ }
+
+ /* Case: a == b */
+ /* catches case both a and b are 0.0 - user should have called N_VConst */
+
+ if (a == b) {
+ VScaleSum_Serial(a, x, y, z);
+ return;
+ }
+
+ /* Case: a == -b */
+
+ if (a == -b) {
+ VScaleDiff_Serial(a, x, y, z);
+ return;
+ }
+
+ /* Do all cases not handled above:
+ (1) a == other, b == 0.0 - user should have called N_VScale
+ (2) a == 0.0, b == other - user should have called N_VScale
+ (3) a,b == other, a !=b, a != -b */
+
+ N = NV_LENGTH_S(x);
+ xd = NV_DATA_S(x);
+ yd = NV_DATA_S(y);
+ zd = NV_DATA_S(z);
+
+ for (i = 0; i < N; i++)
+ zd[i] = (a*xd[i])+(b*yd[i]);
+
+ return;
+}
+
+void N_VConst_Serial(realtype c, N_Vector z)
+{
+ long int i, N;
+ realtype *zd;
+
+ zd = NULL;
+
+ N = NV_LENGTH_S(z);
+ zd = NV_DATA_S(z);
+
+ for (i = 0; i < N; i++) zd[i] = c;
+
+ return;
+}
+
+void N_VProd_Serial(N_Vector x, N_Vector y, N_Vector z)
+{
+ long int i, N;
+ realtype *xd, *yd, *zd;
+
+ xd = yd = zd = NULL;
+
+ N = NV_LENGTH_S(x);
+ xd = NV_DATA_S(x);
+ yd = NV_DATA_S(y);
+ zd = NV_DATA_S(z);
+
+ for (i = 0; i < N; i++)
+ zd[i] = xd[i]*yd[i];
+
+ return;
+}
+
+void N_VDiv_Serial(N_Vector x, N_Vector y, N_Vector z)
+{
+ long int i, N;
+ realtype *xd, *yd, *zd;
+
+ xd = yd = zd = NULL;
+
+ N = NV_LENGTH_S(x);
+ xd = NV_DATA_S(x);
+ yd = NV_DATA_S(y);
+ zd = NV_DATA_S(z);
+
+ for (i = 0; i < N; i++)
+ zd[i] = xd[i]/yd[i];
+
+ return;
+}
+
+void N_VScale_Serial(realtype c, N_Vector x, N_Vector z)
+{
+ long int i, N;
+ realtype *xd, *zd;
+
+ xd = zd = NULL;
+
+ if (z == x) { /* BLAS usage: scale x <- cx */
+ VScaleBy_Serial(c, x);
+ return;
+ }
+
+ if (c == ONE) {
+ VCopy_Serial(x, z);
+ } else if (c == -ONE) {
+ VNeg_Serial(x, z);
+ } else {
+ N = NV_LENGTH_S(x);
+ xd = NV_DATA_S(x);
+ zd = NV_DATA_S(z);
+ for (i = 0; i < N; i++)
+ zd[i] = c*xd[i];
+ }
+
+ return;
+}
+
+void N_VAbs_Serial(N_Vector x, N_Vector z)
+{
+ long int i, N;
+ realtype *xd, *zd;
+
+ xd = zd = NULL;
+
+ N = NV_LENGTH_S(x);
+ xd = NV_DATA_S(x);
+ zd = NV_DATA_S(z);
+
+ for (i = 0; i < N; i++)
+ zd[i] = ABS(xd[i]);
+
+ return;
+}
+
+void N_VInv_Serial(N_Vector x, N_Vector z)
+{
+ long int i, N;
+ realtype *xd, *zd;
+
+ xd = zd = NULL;
+
+ N = NV_LENGTH_S(x);
+ xd = NV_DATA_S(x);
+ zd = NV_DATA_S(z);
+
+ for (i = 0; i < N; i++)
+ zd[i] = ONE/xd[i];
+
+ return;
+}
+
+void N_VAddConst_Serial(N_Vector x, realtype b, N_Vector z)
+{
+ long int i, N;
+ realtype *xd, *zd;
+
+ xd = zd = NULL;
+
+ N = NV_LENGTH_S(x);
+ xd = NV_DATA_S(x);
+ zd = NV_DATA_S(z);
+
+ for (i = 0; i < N; i++)
+ zd[i] = xd[i]+b;
+
+ return;
+}
+
+realtype N_VDotProd_Serial(N_Vector x, N_Vector y)
+{
+ long int i, N;
+ realtype sum, *xd, *yd;
+
+ sum = ZERO;
+ xd = yd = NULL;
+
+ N = NV_LENGTH_S(x);
+ xd = NV_DATA_S(x);
+ yd = NV_DATA_S(y);
+
+ for (i = 0; i < N; i++)
+ sum += xd[i]*yd[i];
+
+ return(sum);
+}
+
+realtype N_VMaxNorm_Serial(N_Vector x)
+{
+ long int i, N;
+ realtype max, *xd;
+
+ max = ZERO;
+ xd = NULL;
+
+ N = NV_LENGTH_S(x);
+ xd = NV_DATA_S(x);
+
+ for (i = 0; i < N; i++) {
+ if (ABS(xd[i]) > max) max = ABS(xd[i]);
+ }
+
+ return(max);
+}
+
+realtype N_VWrmsNorm_Serial(N_Vector x, N_Vector w)
+{
+ long int i, N;
+ realtype sum, prodi, *xd, *wd;
+
+ sum = ZERO;
+ xd = wd = NULL;
+
+ N = NV_LENGTH_S(x);
+ xd = NV_DATA_S(x);
+ wd = NV_DATA_S(w);
+
+ for (i = 0; i < N; i++) {
+ prodi = xd[i]*wd[i];
+ sum += SQR(prodi);
+ }
+
+ return(RSqrt(sum/N));
+}
+
+realtype N_VWrmsNormMask_Serial(N_Vector x, N_Vector w, N_Vector id)
+{
+ long int i, N;
+ realtype sum, prodi, *xd, *wd, *idd;
+
+ sum = ZERO;
+ xd = wd = idd = NULL;
+
+ N = NV_LENGTH_S(x);
+ xd = NV_DATA_S(x);
+ wd = NV_DATA_S(w);
+ idd = NV_DATA_S(id);
+
+ for (i = 0; i < N; i++) {
+ if (idd[i] > ZERO) {
+ prodi = xd[i]*wd[i];
+ sum += SQR(prodi);
+ }
+ }
+
+ return(RSqrt(sum / N));
+}
+
+realtype N_VMin_Serial(N_Vector x)
+{
+ long int i, N;
+ realtype min, *xd;
+
+ xd = NULL;
+
+ N = NV_LENGTH_S(x);
+ xd = NV_DATA_S(x);
+
+ min = xd[0];
+
+ for (i = 1; i < N; i++) {
+ if (xd[i] < min) min = xd[i];
+ }
+
+ return(min);
+}
+
+realtype N_VWL2Norm_Serial(N_Vector x, N_Vector w)
+{
+ long int i, N;
+ realtype sum, prodi, *xd, *wd;
+
+ sum = ZERO;
+ xd = wd = NULL;
+
+ N = NV_LENGTH_S(x);
+ xd = NV_DATA_S(x);
+ wd = NV_DATA_S(w);
+
+ for (i = 0; i < N; i++) {
+ prodi = xd[i]*wd[i];
+ sum += SQR(prodi);
+ }
+
+ return(RSqrt(sum));
+}
+
+realtype N_VL1Norm_Serial(N_Vector x)
+{
+ long int i, N;
+ realtype sum, *xd;
+
+ sum = ZERO;
+ xd = NULL;
+
+ N = NV_LENGTH_S(x);
+ xd = NV_DATA_S(x);
+
+ for (i = 0; i<N; i++)
+ sum += ABS(xd[i]);
+
+ return(sum);
+}
+
+void N_VCompare_Serial(realtype c, N_Vector x, N_Vector z)
+{
+ long int i, N;
+ realtype *xd, *zd;
+
+ xd = zd = NULL;
+
+ N = NV_LENGTH_S(x);
+ xd = NV_DATA_S(x);
+ zd = NV_DATA_S(z);
+
+ for (i = 0; i < N; i++) {
+ zd[i] = (ABS(xd[i]) >= c) ? ONE : ZERO;
+ }
+
+ return;
+}
+
+booleantype N_VInvTest_Serial(N_Vector x, N_Vector z)
+{
+ long int i, N;
+ realtype *xd, *zd;
+
+ xd = zd = NULL;
+
+ N = NV_LENGTH_S(x);
+ xd = NV_DATA_S(x);
+ zd = NV_DATA_S(z);
+
+ for (i = 0; i < N; i++) {
+ if (xd[i] == ZERO) return(FALSE);
+ zd[i] = ONE/xd[i];
+ }
+
+ return(TRUE);
+}
+
+booleantype N_VConstrMask_Serial(N_Vector c, N_Vector x, N_Vector m)
+{
+ long int i, N;
+ booleantype test;
+ realtype *cd, *xd, *md;
+
+ cd = xd = md = NULL;
+
+ N = NV_LENGTH_S(x);
+ xd = NV_DATA_S(x);
+ cd = NV_DATA_S(c);
+ md = NV_DATA_S(m);
+
+ test = TRUE;
+
+ 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; }
+ continue;
+ }
+ if ( cd[i] > HALF || cd[i] < -HALF) {
+ if (xd[i]*cd[i] < ZERO ) { test = FALSE; md[i] = ONE; }
+ }
+ }
+
+ return(test);
+}
+
+realtype N_VMinQuotient_Serial(N_Vector num, N_Vector denom)
+{
+ booleantype notEvenOnce;
+ long int i, N;
+ realtype *nd, *dd, min;
+
+ nd = dd = NULL;
+
+ N = NV_LENGTH_S(num);
+ nd = NV_DATA_S(num);
+ dd = NV_DATA_S(denom);
+
+ notEvenOnce = TRUE;
+ min = BIG_REAL;
+
+ for (i = 0; i < N; i++) {
+ if (dd[i] == ZERO) continue;
+ else {
+ if (!notEvenOnce) min = MIN(min, nd[i]/dd[i]);
+ else {
+ min = nd[i]/dd[i];
+ notEvenOnce = FALSE;
+ }
+ }
+ }
+
+ return(min);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * private functions
+ * -----------------------------------------------------------------
+ */
+
+static void VCopy_Serial(N_Vector x, N_Vector z)
+{
+ long int i, N;
+ realtype *xd, *zd;
+
+ xd = zd = NULL;
+
+ N = NV_LENGTH_S(x);
+ xd = NV_DATA_S(x);
+ zd = NV_DATA_S(z);
+
+ for (i = 0; i < N; i++)
+ zd[i] = xd[i];
+
+ return;
+}
+
+static void VSum_Serial(N_Vector x, N_Vector y, N_Vector z)
+{
+ long int i, N;
+ realtype *xd, *yd, *zd;
+
+ xd = yd = zd = NULL;
+
+ N = NV_LENGTH_S(x);
+ xd = NV_DATA_S(x);
+ yd = NV_DATA_S(y);
+ zd = NV_DATA_S(z);
+
+ for (i = 0; i < N; i++)
+ zd[i] = xd[i]+yd[i];
+
+ return;
+}
+
+static void VDiff_Serial(N_Vector x, N_Vector y, N_Vector z)
+{
+ long int i, N;
+ realtype *xd, *yd, *zd;
+
+ xd = yd = zd = NULL;
+
+ N = NV_LENGTH_S(x);
+ xd = NV_DATA_S(x);
+ yd = NV_DATA_S(y);
+ zd = NV_DATA_S(z);
+
+ for (i = 0; i < N; i++)
+ zd[i] = xd[i]-yd[i];
+
+ return;
+}
+
+static void VNeg_Serial(N_Vector x, N_Vector z)
+{
+ long int i, N;
+ realtype *xd, *zd;
+
+ xd = zd = NULL;
+
+ N = NV_LENGTH_S(x);
+ xd = NV_DATA_S(x);
+ zd = NV_DATA_S(z);
+
+ for (i = 0; i < N; i++)
+ zd[i] = -xd[i];
+
+ return;
+}
+
+static void VScaleSum_Serial(realtype c, N_Vector x, N_Vector y, N_Vector z)
+{
+ long int i, N;
+ realtype *xd, *yd, *zd;
+
+ xd = yd = zd = NULL;
+
+ N = NV_LENGTH_S(x);
+ xd = NV_DATA_S(x);
+ yd = NV_DATA_S(y);
+ zd = NV_DATA_S(z);
+
+ for (i = 0; i < N; i++)
+ zd[i] = c*(xd[i]+yd[i]);
+
+ return;
+}
+
+static void VScaleDiff_Serial(realtype c, N_Vector x, N_Vector y, N_Vector z)
+{
+ long int i, N;
+ realtype *xd, *yd, *zd;
+
+ xd = yd = zd = NULL;
+
+ N = NV_LENGTH_S(x);
+ xd = NV_DATA_S(x);
+ yd = NV_DATA_S(y);
+ zd = NV_DATA_S(z);
+
+ for (i = 0; i < N; i++)
+ zd[i] = c*(xd[i]-yd[i]);
+
+ return;
+}
+
+static void VLin1_Serial(realtype a, N_Vector x, N_Vector y, N_Vector z)
+{
+ long int i, N;
+ realtype *xd, *yd, *zd;
+
+ xd = yd = zd = NULL;
+
+ N = NV_LENGTH_S(x);
+ xd = NV_DATA_S(x);
+ yd = NV_DATA_S(y);
+ zd = NV_DATA_S(z);
+
+ for (i = 0; i < N; i++)
+ zd[i] = (a*xd[i])+yd[i];
+
+ return;
+}
+
+static void VLin2_Serial(realtype a, N_Vector x, N_Vector y, N_Vector z)
+{
+ long int i, N;
+ realtype *xd, *yd, *zd;
+
+ xd = yd = zd = NULL;
+
+ N = NV_LENGTH_S(x);
+ xd = NV_DATA_S(x);
+ yd = NV_DATA_S(y);
+ zd = NV_DATA_S(z);
+
+ for (i = 0; i < N; i++)
+ zd[i] = (a*xd[i])-yd[i];
+
+ return;
+}
+
+static void Vaxpy_Serial(realtype a, N_Vector x, N_Vector y)
+{
+ long int i, N;
+ realtype *xd, *yd;
+
+ xd = yd = NULL;
+
+ N = NV_LENGTH_S(x);
+ xd = NV_DATA_S(x);
+ yd = NV_DATA_S(y);
+
+ if (a == ONE) {
+ for (i = 0; i < N; i++)
+ yd[i] += xd[i];
+ return;
+ }
+
+ if (a == -ONE) {
+ for (i = 0; i < N; i++)
+ yd[i] -= xd[i];
+ return;
+ }
+
+ for (i = 0; i < N; i++)
+ yd[i] += a*xd[i];
+
+ return;
+}
+
+static void VScaleBy_Serial(realtype a, N_Vector x)
+{
+ long int i, N;
+ realtype *xd;
+
+ xd = NULL;
+
+ N = NV_LENGTH_S(x);
+ xd = NV_DATA_S(x);
+
+ for (i = 0; i < N; i++)
+ xd[i] *= a;
+
+ return;
+}
diff --git a/src/sundials/CMakeLists.txt b/src/sundials/CMakeLists.txt
new file mode 100644
index 0000000..459dcdf
--- /dev/null
+++ b/src/sundials/CMakeLists.txt
@@ -0,0 +1,45 @@
+# ---------------------------------------------------------------
+# $Revision: 1.4 $
+# $Date: 2009/02/17 02:52:53 $
+# ---------------------------------------------------------------
+# Programmer: Radu Serban @ LLNL
+# ---------------------------------------------------------------
+# Copyright (c) 2007, The Regents of the University of California.
+# Produced at the Lawrence Livermore National Laboratory.
+# All rights reserved.
+# For details, see the LICENSE file.
+# ---------------------------------------------------------------
+# CMakeLists.txt file for the generic SUNDIALS modules
+
+# From here we only install the generic SUNDIALS headers.
+# The implementations themselves are incorporated in the individual SUNDIALS solver libraries.
+
+INSTALL(CODE "MESSAGE(\"\nInstall shared components\n\")")
+
+# Add variable sundials_HEADERS with the exported SUNDIALS header files
+SET(sundials_HEADERS
+ sundials_band.h
+ sundials_dense.h
+ sundials_direct.h
+ sundials_iterative.h
+ sundials_math.h
+ sundials_nvector.h
+ sundials_fnvector.h
+ sundials_spbcgs.h
+ sundials_spgmr.h
+ sundials_sptfqmr.h
+ sundials_types.h
+ )
+
+# Add prefix with complete path to the SUNDIALS header files
+ADD_PREFIX(${sundials_SOURCE_DIR}/include/sundials/ sundials_HEADERS)
+
+# Install the SUNDIALS header files
+INSTALL(FILES ${sundials_HEADERS} DESTINATION include/sundials)
+
+# If Blas/Lapack support was enabled, install the Lapack interface headers
+IF(LAPACK_FOUND)
+ SET(sundials_BL_HEADERS sundials_lapack.h)
+ ADD_PREFIX(${sundials_SOURCE_DIR}/include/sundials/ sundials_BL_HEADERS)
+ INSTALL(FILES ${sundials_BL_HEADERS} DESTINATION include/sundials)
+ENDIF(LAPACK_FOUND)
diff --git a/src/sundials/Makefile.in b/src/sundials/Makefile.in
new file mode 100644
index 0000000..f750ba1
--- /dev/null
+++ b/src/sundials/Makefile.in
@@ -0,0 +1,137 @@
+# -----------------------------------------------------------------
+# $Revision: 1.12 $
+# $Date: 2009/02/17 02:52:53 $
+# -----------------------------------------------------------------
+# Programmer(s): Radu Serban and Aaron Collier @ LLNL
+# -----------------------------------------------------------------
+# Copyright (c) 2002, The Regents of the University of California.
+# Produced at the Lawrence Livermore National Laboratory.
+# All rights reserved.
+# For details, see the LICENSE file.
+# -----------------------------------------------------------------
+# Makefile for SHARED module
+#
+# @configure_input@
+# -----------------------------------------------------------------
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+builddir = @builddir@
+abs_builddir = @abs_builddir@
+top_builddir = @top_builddir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+includedir = @includedir@
+libdir = @libdir@
+bindir = @bindir@
+
+INSTALL = @INSTALL@
+INSTALL_PROG = @INSTALL_PROGRAM@
+INSTALL_HEADER = @INSTALL_DATA@
+
+LIBTOOL = @LIBTOOL@
+LIBTOOL_DEPS = @LIBTOOL_DEPS@
+
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CC = @CC@
+CFLAGS = @CFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+
+LAPACK_ENABLED = @LAPACK_ENABLED@
+
+top_srcdir = $(srcdir)/../..
+
+INCLUDES = -I$(top_srcdir)/include -I$(top_builddir)/include
+
+SHARED_SRC_FILES = sundials_direct.c sundials_band.c sundials_dense.c sundials_iterative.c sundials_math.c sundials_nvector.c sundials_spgmr.c sundials_spbcgs.c sundials_sptfqmr.c
+
+SHARED_OBJ_FILES = $(SHARED_SRC_FILES:.c=.o)
+
+SHARED_LIB_FILES = $(SHARED_SRC_FILES:.c=.lo)
+
+mkinstalldirs = $(SHELL) $(top_srcdir)/config/mkinstalldirs
+rminstalldirs = $(SHELL) $(top_srcdir)/config/rminstalldirs
+
+# ----------------------------------------------------------------------------------------------------------------------
+
+
+all:
+ @if test "X${LAPACK_ENABLED}" = "Xyes"; then \
+ make lib_with_bl; \
+ else \
+ make lib_without_bl; \
+ fi
+
+lib_without_bl: $(SHARED_LIB_FILES)
+
+lib_with_bl: $(SHARED_LIB_FILES)
+
+install:
+ $(mkinstalldirs) $(includedir)/sundials
+ $(INSTALL_HEADER) $(top_srcdir)/include/sundials/sundials_direct.h $(includedir)/sundials/
+ $(INSTALL_HEADER) $(top_srcdir)/include/sundials/sundials_band.h $(includedir)/sundials/
+ $(INSTALL_HEADER) $(top_srcdir)/include/sundials/sundials_dense.h $(includedir)/sundials/
+ $(INSTALL_HEADER) $(top_srcdir)/include/sundials/sundials_iterative.h $(includedir)/sundials/
+ $(INSTALL_HEADER) $(top_srcdir)/include/sundials/sundials_spgmr.h $(includedir)/sundials/
+ $(INSTALL_HEADER) $(top_srcdir)/include/sundials/sundials_spbcgs.h $(includedir)/sundials/
+ $(INSTALL_HEADER) $(top_srcdir)/include/sundials/sundials_sptfqmr.h $(includedir)/sundials/
+ $(INSTALL_HEADER) $(top_srcdir)/include/sundials/sundials_math.h $(includedir)/sundials/
+ $(INSTALL_HEADER) $(top_srcdir)/include/sundials/sundials_types.h $(includedir)/sundials/
+ $(INSTALL_HEADER) $(top_srcdir)/include/sundials/sundials_nvector.h $(includedir)/sundials/
+ $(INSTALL_HEADER) $(top_srcdir)/include/sundials/sundials_fnvector.h $(includedir)/sundials/
+ $(INSTALL_HEADER) $(top_builddir)/include/sundials/sundials_config.h $(includedir)/sundials/
+ @if test "X${LAPACK_ENABLED}" = "Xyes"; then \
+ $(INSTALL_HEADER) $(top_srcdir)/include/sundials/sundials_lapack.h $(includedir)/sundials/ ; \
+ fi
+
+uninstall:
+ rm -f $(includedir)/sundials/sundials_direct.h
+ rm -f $(includedir)/sundials/sundials_band.h
+ rm -f $(includedir)/sundials/sundials_dense.h
+ rm -f $(includedir)/sundials/sundials_lapack.h
+ rm -f $(includedir)/sundials/sundials_iterative.h
+ rm -f $(includedir)/sundials/sundials_spgmr.h
+ rm -f $(includedir)/sundials/sundials_spbcgs.h
+ rm -f $(includedir)/sundials/sundials_sptfqmr.h
+ rm -f $(includedir)/sundials/sundials_math.h
+ rm -f $(includedir)/sundials/sundials_types.h
+ rm -f $(includedir)/sundials/sundials_nvector.h
+ rm -f $(includedir)/sundials/sundials_fnvector.h
+ rm -f $(includedir)/sundials/sundials_config.h
+ $(rminstalldirs) $(includedir)/sundials
+
+clean:
+ rm -f $(SHARED_LIB_FILES)
+ rm -f $(SHARED_OBJ_FILES)
+ rm -rf .libs
+
+distclean: clean
+ rm -f $(top_builddir)/include/sundials/sundials_config.h
+ rm -f Makefile
+
+sundials_direct.lo: $(srcdir)/sundials_direct.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/sundials_direct.c
+sundials_band.lo: $(srcdir)/sundials_band.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/sundials_band.c
+sundials_dense.lo: $(srcdir)/sundials_dense.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/sundials_dense.c
+sundials_iterative.lo: $(srcdir)/sundials_iterative.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/sundials_iterative.c
+sundials_spgmr.lo: $(srcdir)/sundials_spgmr.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/sundials_spgmr.c
+sundials_spbcgs.lo: $(srcdir)/sundials_spbcgs.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/sundials_spbcgs.c
+sundials_sptfqmr.lo: $(srcdir)/sundials_sptfqmr.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/sundials_sptfqmr.c
+sundials_math.lo: $(srcdir)/sundials_math.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/sundials_math.c
+sundials_nvector.lo: $(srcdir)/sundials_nvector.c
+ $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/sundials_nvector.c
+
+libtool: $(top_builddir)/$(LIBTOOL_DEPS)
+ @cd ${top_builddir} ; \
+ ${SHELL} ./config.status --recheck ; \
+ cd ${abs_builddir}
diff --git a/src/sundials/README b/src/sundials/README
new file mode 100644
index 0000000..0b6bd8c
--- /dev/null
+++ b/src/sundials/README
@@ -0,0 +1,215 @@
+ SUNDIALS
+ Shared Module
+ Release 2.5.0, March 2012
+
+
+The family of solvers referred to as SUNDIALS consists of solvers
+CVODE (ODE), CVODES (ODE with sensitivity analysis capabilities),
+IDA (DAE), IDAS (DAE with sensitivity analysis 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 linear solver modules (band, dense, lapack, spgmr, bcg, tfqmr)
+- definitions of SUNDIALS types (realtype, booleantype)
+- common math functions (RpowerI, RPowerR, RSqrt, RAbs,...)
+
+
+A. Documentation
+----------------
+All shared submodules are fully described in the user documentation for any of
+the SUNDIALS solvers [1-5]. 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 the file /sundials/INSTALL_NOTES.
+For complete installation instructions see any of the user guides.
+
+
+C. References
+-------------
+
+[1] A. C. Hindmarsh and R. Serban, "User Documentation for CVODE v2.7.0,"
+ LLNL technical report UCRL-MA-208108, December 2011.
+
+[2] A. C. Hindmarsh and R. Serban, "User Documentation for CVODES v2.7.0,"
+ LLNL technical report UCRL-MA-208111, December 2011.
+
+[3] A. C. Hindmarsh and R. Serban, "User Documentation for IDA v2.7.0,"
+ LLNL technical report UCRL-MA-208112, December 2011.
+
+[4] R. Serban and C. Petra, "User Documentation for IDAS v1.1.0,"
+ LLNL technical report UCRL-SM-234051, December 2011.
+
+[5] A. M. Collier, A. C. Hindmarsh, R. Serban,and C. S. Woodward, "User
+ Documentation for KINSOL v2.7.0," LLNL technical report UCRL-MA-208116,
+ December 2011.
+
+
+D. Releases
+-----------
+
+v. 2.5.0 - Mar. 2012
+v. 2.4.0 - May 2009
+v. 2.3.0 - Nov. 2006
+v. 2.2.0 - Mar. 2006
+v. 2.1.1 - May. 2005
+v. 2.1.0 - Apr. 2005
+v. 2.0.2 - Mar. 2005
+v. 2.0.1 - Jan. 2005
+v. 2.0 - Dec. 2004
+v. 1.0 - Jul. 2002 (first SUNDIALS release)
+v. 0.0 - Mar. 2002
+
+
+E. Revision History
+-------------------
+
+v. 2.4.0 (May 2009) ---> v. 2.5.0 (Mar. 2012)
+---------------------------------------------
+
+- Changes to user interface
+ - One significant design change was made with this release: The problem
+ size and its relatives, bandwidth parameters, related internal indices,
+ pivot arrays, and the optional output lsflag, have all been
+ changed from type int to type long int, except for the
+ problem size and bandwidths in user calls to routines specifying
+ BLAS/LAPACK routines for the dense/band linear solvers. The function
+ NewIntArray is replaced by a pair NewIntArray/NewLintArray,
+ for int and long int arrays, respectively.
+
+v. 2.3.0 (Nov. 2006) ---> v. 2.4.0 (May 2009)
+---------------------------------------------
+
+- New features
+ - added a new generic linear solver module based on Blas + Lapack
+ for both dense and banded matrices.
+
+- Changes to user interface
+ - common functionality for all direct linear solvers (dense, band, and
+ the new Lapack solver) has been collected into the DLS (Direct Linear
+ Solver) module, implemented in the files sundials_direct.h and
+ sundials_direct.c (similar to the SPILS module for the iterative linear
+ solvers).
+ - in order to include the new Lapack-based linear solver, all dimensions
+ for the above linear solvers (problem sizes, bandwidths,... including
+ the underlying matrix data types) are now of type 'int' (and not 'long int').
+
+
+v. 2.2.0 (Mar. 2006) ---> v. 2.3.0 (Nov. 2006)
+----------------------------------------------
+
+- Changes to the user interface
+ - modified sundials_dense and sundials_smalldense to work with
+ rectangular m by n matrices (m <= n).
+
+- Changes related to the build system
+ - reorganized source tree
+ - exported header files are installed in solver-specific subdirectories
+ of ${includedir}
+ - sundialsTB is distributed only as part of the SUNDIALS tarball
+
+v. 2.1.1 (May 2005) ---> v. 2.2.0 (Mar. 2006)
+---------------------------------------------
+
+- New features
+ - added SPBCG (scaled preconditioned Bi-CGStab) linear solver module
+ - added SPTFQMR (scaled preconditioned TFQMR) linear solver module
+
+- Changes related to the build system
+ - updated configure script and Makefiles for Fortran examples to avoid C++
+ compiler errors (now use CC and MPICC to link only if necessary)
+ - SUNDIALS shared header files are installed under a 'sundials' subdirectory
+ of the install include directory
+ - the shared object files are now linked into each SUNDIALS library rather
+ than into a separate libsundials_shared library
+
+- Changes to the user interface
+ - added prefix 'sundials_' to all shared header files
+
+v. 2.1.0 (Apr. 2005) ---> v. 2.1.1 (May.2005)
+---------------------------------------------
+
+- Changes to data structures
+ - added N_VCloneEmpty to global vector operations table
+
+v. 2.0.2 (Mar. 2005) ---> v. 2.1.0 (Apr. 2005)
+----------------------------------------------
+
+- none
+
+v. 2.0.1 (Jan. 2005) ---> v. 2.0.2 (Mar. 2005)
+----------------------------------------------
+
+- Changes related to the build system
+ - fixed autoconf-related bug to allow configuration with the PGI Fortran compiler
+ - modified to use customized detection of the Fortran name mangling scheme
+ (autoconf's AC_F77_WRAPPERS routine is problematic on some platforms)
+ - added --with-mpi-flags as a configure option to allow user to specify
+ MPI-specific flags
+ - updated Makefiles for Fortran examples to avoid C++ compiler errors (now use
+ CC and MPICC to link)
+
+v. 2.0 (Dec. 2004) ---> v. 2.0.1 (Jan. 2005)
+--------------------------------------------
+
+- Changes related to the build system
+ - changed order of compiler directives in header files to avoid compilation
+ errors when using a C++ compiler.
+
+v. 1.0 (Jul. 2002) ---> v. 2.0 (Dec. 2004)
+------------------------------------------
+
+- Changes to the generic NVECTOR module
+ - removed machEnv, redefined table of vector operations (now contained
+ in the N_Vector structure itself).
+ - all SUNDIALS functions create new N_Vector variables through cloning, using
+ an N_Vector passed by the user as a template.
+ - a particular NVECTOR implementation is supposed to provide user-callable
+ constructor and destructor functions.
+ - removed from structure of vector operations the following functions:
+ N_VNew, N_VNew_S, N_VFree, N_VFree_S, N_VMake, N_VDispose, N_VGetData,
+ N_VSetData, N_VConstrProdPos, and N_VOneMask.
+ - added in structure of vector operations the following functions:
+ N_VClone, N_VDestroy, N_VSpace, N_VGetArrayPointer, N_VSetArrayPointer,
+ and N_VWrmsNormMask.
+ - Note that nvec_ser and nvec_par are now separate modules outside the
+ shared SUNDIALS module.
+
+- Changes to the generic linear solvers
+ - in SPGMR, added a dummy N_Vector argument to be used as a template
+ for cloning.
+ - in SPGMR, removed N (problem dimension) from argument list of SpgmrMalloc.
+ - iterative.{c,h} replace iterativ.{c,h}
+ - modified constant names in iterative.h (preconditioner types are prefixed
+ with 'PREC_').
+ - changed numerical values for MODIFIED_GS (from 0 to 1) and CLASSICAL_GS
+ (from 1 to 2).
+
+- Changes to sundialsmath submodule
+ - replaced internal routine for estimation of unit roundoff with definition
+ of unit roundoff from float.h
+ - modified functions to call appropriate math routines given the precision
+ level specified by the user.
+
+- Changes to sundialstypes submodule
+ - removed type 'integertype'.
+ - added definitions for 'BIG_REAL', 'SMALL_REAL', and 'UNIT_ROUNDOFF' using
+ values from float.h based on the precision.
+ - changed definition of macro RCONST to depend on precision.
+
+v 0.0 (Mar. 2002) ---> v. 1.0 (Jul. 2002)
+-----------------------------------------
+
+20020321 Defined and implemented generic NVECTOR module, and separate serial/
+ parallel NVECTOR modules, including serial/parallel F/C interfaces.
+ Modified dense and band backsolve routines to take real* type for
+ RHS and solution vector.
+20020329 Named the DenseMat, BandMat, and SpgmrMemRec structures.
+20020626 Changed type names to realtype, integertype, booleantype.
+ Renamed llnltypes and llnlmath files.
+
diff --git a/src/sundials/sundials_band.c b/src/sundials/sundials_band.c
new file mode 100644
index 0000000..b9286ab
--- /dev/null
+++ b/src/sundials/sundials_band.c
@@ -0,0 +1,235 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.7 $
+ * $Date: 2010/12/01 22:46:56 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Alan C. Hindmarsh and Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * This is the implementation file for a generic BAND linear
+ * solver package.
+ * -----------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <sundials/sundials_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)
+
+/*
+ * -----------------------------------------------------
+ * Functions working on DlsMat
+ * -----------------------------------------------------
+ */
+
+long int BandGBTRF(DlsMat A, long int *p)
+{
+ return(bandGBTRF(A->cols, A->M, A->mu, A->ml, A->s_mu, p));
+}
+
+void BandGBTRS(DlsMat A, long int *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)
+{
+ bandCopy(A->cols, B->cols, A->M, A->s_mu, B->s_mu, copymu, copyml);
+}
+
+void BandScale(realtype c, DlsMat A)
+{
+ bandScale(c, A->cols, A->M, A->mu, A->ml, A->s_mu);
+}
+
+/*
+ * -----------------------------------------------------
+ * Functions working on realtype**
+ * -----------------------------------------------------
+ */
+
+long int bandGBTRF(realtype **a, long int n, long int mu, long int ml, long int smu, long int *p)
+{
+ long int c, r, num_rows;
+ long int 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;
+
+ /* zero out the first smu - mu rows of the rectangular array a */
+
+ num_rows = smu - mu;
+ if (num_rows > 0) {
+ for (c=0; c < n; c++) {
+ a_c = a[c];
+ for (r=0; r < num_rows; r++) {
+ a_c[r] = ZERO;
+ }
+ }
+ }
+
+ /* k = elimination step number */
+
+ for (k=0; k < n-1; k++, p++) {
+
+ col_k = a[k];
+ diag_k = col_k + smu;
+ sub_diag_k = diag_k + 1;
+ last_row_k = MIN(n-1,k+ml);
+
+ /* find l = pivot row number */
+
+ l=k;
+ max = ABS(*diag_k);
+ for (i=k+1, kptr=sub_diag_k; i <= last_row_k; i++, kptr++) {
+ if (ABS(*kptr) > max) {
+ l=i;
+ max = ABS(*kptr);
+ }
+ }
+ storage_l = ROW(l, k, smu);
+ *p = l;
+
+ /* check for zero pivot element */
+
+ if (col_k[storage_l] == ZERO) return(k+1);
+
+ /* swap a(l,k) and a(k,k) if necessary */
+
+ if ( (swap = (l != k) )) {
+ temp = col_k[storage_l];
+ col_k[storage_l] = *diag_k;
+ *diag_k = temp;
+ }
+
+ /* Scale the elements below the diagonal in */
+ /* column k by -1.0 / a(k,k). After the above swap, */
+ /* a(k,k) holds the pivot element. This scaling */
+ /* stores the pivot row multipliers -a(i,k)/a(k,k) */
+ /* in a(i,k), i=k+1, ..., MIN(n-1,k+ml). */
+
+ mult = -ONE / (*diag_k);
+ for (i=k+1, kptr = sub_diag_k; i <= last_row_k; i++, kptr++)
+ (*kptr) *= mult;
+
+ /* row_i = row_i - [a(i,k)/a(k,k)] row_k, i=k+1, ..., MIN(n-1,k+ml) */
+ /* row k is the pivot row after swapping with row l. */
+ /* The computation is done one column at a time, */
+ /* column j=k+1, ..., MIN(k+smu,n-1). */
+
+ last_col_k = MIN(k+smu,n-1);
+ for (j=k+1; j <= last_col_k; j++) {
+
+ col_j = a[j];
+ storage_l = ROW(l,j,smu);
+ storage_k = ROW(k,j,smu);
+ a_kj = col_j[storage_l];
+
+ /* Swap the elements a(k,j) and a(k,l) if l!=k. */
+
+ if (swap) {
+ col_j[storage_l] = col_j[storage_k];
+ col_j[storage_k] = a_kj;
+ }
+
+ /* a(i,j) = a(i,j) - [a(i,k)/a(k,k)]*a(k,j) */
+ /* a_kj = a(k,j), *kptr = - a(i,k)/a(k,k), *jptr = a(i,j) */
+
+ if (a_kj != ZERO) {
+ for (i=k+1, kptr=sub_diag_k, jptr=col_j+ROW(k+1,j,smu);
+ i <= last_row_k;
+ i++, kptr++, jptr++)
+ (*jptr) += a_kj * (*kptr);
+ }
+ }
+ }
+
+ /* set the last pivot row to be n-1 and check for a zero pivot */
+
+ *p = n-1;
+ if (a[n-1][smu] == ZERO) return(n);
+
+ /* return 0 to indicate success */
+
+ return(0);
+}
+
+void bandGBTRS(realtype **a, long int n, long int smu, long int ml, long int *p, realtype *b)
+{
+ long int k, l, i, first_row_k, last_row_k;
+ realtype mult, *diag_k;
+
+ /* Solve Ly = Pb, store solution y in b */
+
+ for (k=0; k < n-1; k++) {
+ l = p[k];
+ mult = b[l];
+ if (l != k) {
+ b[l] = b[k];
+ b[k] = mult;
+ }
+ diag_k = a[k]+smu;
+ last_row_k = MIN(n-1,k+ml);
+ for (i=k+1; i <= last_row_k; i++)
+ b[i] += mult * diag_k[i-k];
+ }
+
+ /* Solve Ux = y, store solution x in b */
+
+ for (k=n-1; k >= 0; k--) {
+ diag_k = a[k]+smu;
+ first_row_k = MAX(0,k-smu);
+ b[k] /= (*diag_k);
+ mult = -b[k];
+ for (i=first_row_k; i <= k-1; i++)
+ b[i] += mult*diag_k[i-k];
+ }
+}
+
+void bandCopy(realtype **a, realtype **b, long int n, long int a_smu, long int b_smu,
+ long int copymu, long int copyml)
+{
+ long int i, j, copySize;
+ realtype *a_col_j, *b_col_j;
+
+ copySize = copymu + copyml + 1;
+
+ for (j=0; j < n; j++) {
+ a_col_j = a[j]+a_smu-copymu;
+ b_col_j = b[j]+b_smu-copymu;
+ for (i=0; i < copySize; i++)
+ b_col_j[i] = a_col_j[i];
+ }
+}
+
+void bandScale(realtype c, realtype **a, long int n, long int mu, long int ml, long int smu)
+{
+ long int i, j, colSize;
+ realtype *col_j;
+
+ colSize = mu + ml + 1;
+
+ for(j=0; j < n; j++) {
+ col_j = a[j]+smu-mu;
+ for (i=0; i < colSize; i++)
+ col_j[i] *= c;
+ }
+}
+
+void bandAddIdentity(realtype **a, long int n, long int smu)
+{
+ long int j;
+
+ for(j=0; j < n; j++)
+ a[j][smu] += ONE;
+}
diff --git a/src/sundials/sundials_dense.c b/src/sundials/sundials_dense.c
new file mode 100644
index 0000000..4fa3bb0
--- /dev/null
+++ b/src/sundials/sundials_dense.c
@@ -0,0 +1,373 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.7 $
+ * $Date: 2010/12/01 22:46:56 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh and
+ * Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * This is the implementation file for a generic package of dense
+ * matrix operations.
+ * -----------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <sundials/sundials_dense.h>
+#include <sundials/sundials_math.h>
+
+#define ZERO RCONST(0.0)
+#define ONE RCONST(1.0)
+#define TWO RCONST(2.0)
+
+/*
+ * -----------------------------------------------------
+ * Functions working on DlsMat
+ * -----------------------------------------------------
+ */
+
+long int DenseGETRF(DlsMat A, long int *p)
+{
+ return(denseGETRF(A->cols, A->M, A->N, p));
+}
+
+void DenseGETRS(DlsMat A, long int *p, realtype *b)
+{
+ denseGETRS(A->cols, A->N, p, b);
+}
+
+long int DensePOTRF(DlsMat A)
+{
+ return(densePOTRF(A->cols, A->M));
+}
+
+void DensePOTRS(DlsMat A, realtype *b)
+{
+ densePOTRS(A->cols, A->M, b);
+}
+
+int DenseGEQRF(DlsMat A, realtype *beta, realtype *wrk)
+{
+ return(denseGEQRF(A->cols, A->M, A->N, beta, wrk));
+}
+
+int DenseORMQR(DlsMat A, realtype *beta, realtype *vn, realtype *vm, realtype *wrk)
+{
+ return(denseORMQR(A->cols, A->M, A->N, beta, vn, vm, wrk));
+}
+
+void DenseCopy(DlsMat A, DlsMat B)
+{
+ denseCopy(A->cols, B->cols, A->M, A->N);
+}
+
+void DenseScale(realtype c, DlsMat A)
+{
+ denseScale(c, A->cols, A->M, A->N);
+}
+
+long int denseGETRF(realtype **a, long int m, long int n, long int *p)
+{
+ long int i, j, k, l;
+ realtype *col_j, *col_k;
+ realtype temp, mult, a_kj;
+
+ /* k-th elimination step number */
+ for (k=0; k < n; k++) {
+
+ col_k = a[k];
+
+ /* find l = pivot row number */
+ l=k;
+ for (i=k+1; i < m; i++)
+ if (ABS(col_k[i]) > ABS(col_k[l])) l=i;
+ p[k] = l;
+
+ /* check for zero pivot element */
+ if (col_k[l] == ZERO) return(k+1);
+
+ /* swap a(k,1:n) and a(l,1:n) if necessary */
+ if ( l!= k ) {
+ for (i=0; i<n; i++) {
+ temp = a[i][l];
+ a[i][l] = a[i][k];
+ a[i][k] = temp;
+ }
+ }
+
+ /* Scale the elements below the diagonal in
+ * column k by 1.0/a(k,k). After the above swap
+ * a(k,k) holds the pivot element. This scaling
+ * stores the pivot row multipliers a(i,k)/a(k,k)
+ * in a(i,k), i=k+1, ..., m-1.
+ */
+ mult = ONE/col_k[k];
+ for(i=k+1; i < m; i++) col_k[i] *= mult;
+
+ /* row_i = row_i - [a(i,k)/a(k,k)] row_k, i=k+1, ..., m-1 */
+ /* row k is the pivot row after swapping with row l. */
+ /* The computation is done one column at a time, */
+ /* column j=k+1, ..., n-1. */
+
+ for (j=k+1; j < n; j++) {
+
+ col_j = a[j];
+ a_kj = col_j[k];
+
+ /* a(i,j) = a(i,j) - [a(i,k)/a(k,k)]*a(k,j) */
+ /* a_kj = a(k,j), col_k[i] = - a(i,k)/a(k,k) */
+
+ if (a_kj != ZERO) {
+ for (i=k+1; i < m; i++)
+ col_j[i] -= a_kj * col_k[i];
+ }
+ }
+ }
+
+ /* return 0 to indicate success */
+
+ return(0);
+}
+
+void denseGETRS(realtype **a, long int n, long int *p, realtype *b)
+{
+ long int i, k, pk;
+ realtype *col_k, tmp;
+
+ /* Permute b, based on pivot information in p */
+ for (k=0; k<n; k++) {
+ pk = p[k];
+ if(pk != k) {
+ tmp = b[k];
+ b[k] = b[pk];
+ b[pk] = tmp;
+ }
+ }
+
+ /* Solve Ly = b, store solution y in b */
+ for (k=0; k<n-1; k++) {
+ col_k = a[k];
+ for (i=k+1; i<n; i++) b[i] -= col_k[i]*b[k];
+ }
+
+ /* Solve Ux = y, store solution x in b */
+ for (k = n-1; k > 0; k--) {
+ col_k = a[k];
+ b[k] /= col_k[k];
+ for (i=0; i<k; i++) b[i] -= col_k[i]*b[k];
+ }
+ b[0] /= a[0][0];
+
+}
+
+/*
+ * Cholesky decomposition of a symmetric positive-definite matrix
+ * A = C^T*C: gaxpy version.
+ * 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)
+{
+ realtype *a_col_j, *a_col_k;
+ realtype a_diag;
+ long int i, j, k;
+
+ for (j=0; j<m; j++) {
+
+ a_col_j = a[j];
+
+ if (j>0) {
+ for(i=j; i<m; i++) {
+ for(k=0;k<j;k++) {
+ a_col_k = a[k];
+ a_col_j[i] -= a_col_k[i]*a_col_k[j];
+ }
+ }
+ }
+
+ a_diag = a_col_j[j];
+ if (a_diag <= ZERO) return(j+1);
+ a_diag = RSqrt(a_diag);
+
+ for(i=j; i<m; i++) a_col_j[i] /= a_diag;
+
+ }
+
+ return(0);
+}
+
+/*
+ * Solution of Ax=b, with A s.p.d., based on the Cholesky decomposition
+ * obtained with denPOTRF.; A = C*C^T, C lower triangular
+ *
+ */
+void densePOTRS(realtype **a, long int m, realtype *b)
+{
+ realtype *col_j, *col_i;
+ long int i, j;
+
+ /* Solve C y = b, forward substitution - column version.
+ Store solution y in b */
+ for (j=0; j < m-1; j++) {
+ col_j = a[j];
+ b[j] /= col_j[j];
+ for (i=j+1; i < m; i++)
+ b[i] -= b[j]*col_j[i];
+ }
+ col_j = a[m-1];
+ b[m-1] /= col_j[m-1];
+
+ /* Solve C^T x = y, backward substitution - row version.
+ Store solution x in b */
+ col_j = a[m-1];
+ b[m-1] /= col_j[m-1];
+ for (i=m-2; i>=0; i--) {
+ col_i = a[i];
+ for (j=i+1; j<m; j++)
+ b[i] -= col_i[j]*b[j];
+ b[i] /= col_i[i];
+ }
+
+}
+
+/*
+ * QR factorization of a rectangular matrix A of size m by n (m >= n)
+ * using Householder reflections.
+ *
+ * On exit, the elements on and above the diagonal of A contain the n by n
+ * upper triangular matrix R; the elements below the diagonal, with the array beta,
+ * represent the orthogonal matrix Q as a product of elementary reflectors .
+ *
+ * v (of length m) must be provided as workspace.
+ *
+ */
+
+int denseGEQRF(realtype **a, long int m, long int n, realtype *beta, realtype *v)
+{
+ realtype ajj, s, mu, v1, v1_2;
+ realtype *col_j, *col_k;
+ long int i, j, k;
+
+ /* For each column...*/
+ for(j=0; j<n; j++) {
+
+ col_j = a[j];
+
+ ajj = col_j[j];
+
+ /* Compute the j-th Householder vector (of length m-j) */
+ v[0] = ONE;
+ s = ZERO;
+ for(i=1; i<m-j; i++) {
+ v[i] = col_j[i+j];
+ s += v[i]*v[i];
+ }
+
+ if(s != ZERO) {
+ mu = RSqrt(ajj*ajj+s);
+ v1 = (ajj <= ZERO) ? ajj-mu : -s/(ajj+mu);
+ v1_2 = v1*v1;
+ beta[j] = TWO * v1_2 / (s + v1_2);
+ for(i=1; i<m-j; i++) v[i] /= v1;
+ } else {
+ beta[j] = ZERO;
+ }
+
+ /* Update upper triangle of A (load R) */
+ for(k=j; k<n; k++) {
+ col_k = a[k];
+ s = ZERO;
+ for(i=0; i<m-j; i++) s += col_k[i+j]*v[i];
+ s *= beta[j];
+ for(i=0; i<m-j; i++) col_k[i+j] -= s*v[i];
+ }
+
+ /* Update A (load Householder vector) */
+ if(j<m-1) {
+ for(i=1; i<m-j; i++) col_j[i+j] = v[i];
+ }
+
+ }
+
+
+ return(0);
+}
+
+/*
+ * Computes vm = Q * vn, where the orthogonal matrix Q is stored as
+ * elementary reflectors in the m by n matrix A and in the vector beta.
+ * (NOTE: It is assumed that an QR factorization has been previously
+ * computed with denGEQRF).
+ *
+ * vn (IN) has length n, vm (OUT) has length m, and it's assumed that m >= n.
+ *
+ * v (of length m) must be provided as workspace.
+ */
+int denseORMQR(realtype **a, long int m, long int n, realtype *beta,
+ realtype *vn, realtype *vm, realtype *v)
+{
+ realtype *col_j, s;
+ long int i, j;
+
+ /* Initialize vm */
+ for(i=0; i<n; i++) vm[i] = vn[i];
+ for(i=n; i<m; i++) vm[i] = ZERO;
+
+ /* Accumulate (backwards) corrections into vm */
+ for(j=n-1; j>=0; j--) {
+
+ col_j = a[j];
+
+ v[0] = ONE;
+ s = vm[j];
+ for(i=1; i<m-j; i++) {
+ v[i] = col_j[i+j];
+ s += v[i]*vm[i+j];
+ }
+ s *= beta[j];
+
+ for(i=0; i<m-j; i++) vm[i+j] -= s * v[i];
+
+ }
+
+ return(0);
+}
+
+void denseCopy(realtype **a, realtype **b, long int m, long int n)
+{
+ long int i, j;
+ realtype *a_col_j, *b_col_j;
+
+ for (j=0; j < n; j++) {
+ a_col_j = a[j];
+ b_col_j = b[j];
+ for (i=0; i < m; i++)
+ b_col_j[i] = a_col_j[i];
+ }
+
+}
+
+void denseScale(realtype c, realtype **a, long int m, long int n)
+{
+ long int i, j;
+ realtype *col_j;
+
+ for (j=0; j < n; j++) {
+ col_j = a[j];
+ for (i=0; i < m; i++)
+ col_j[i] *= c;
+ }
+}
+
+void denseAddIdentity(realtype **a, long int n)
+{
+ long int i;
+
+ for (i=0; i < n; i++) a[i][i] += ONE;
+}
diff --git a/src/sundials/sundials_direct.c b/src/sundials/sundials_direct.c
new file mode 100644
index 0000000..67a6000
--- /dev/null
+++ b/src/sundials/sundials_direct.c
@@ -0,0 +1,355 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.4 $
+ * $Date: 2010/12/01 22:46:56 $
+ * -----------------------------------------------------------------
+ * Programmer: Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * This is the implementation file for operations to be used by a
+ * generic direct linear solver.
+ * -----------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <sundials/sundials_direct.h>
+#include <sundials/sundials_math.h>
+
+#define ZERO RCONST(0.0)
+#define ONE RCONST(1.0)
+
+DlsMat NewDenseMat(long int M, long int N)
+{
+ DlsMat A;
+ long int j;
+
+ if ( (M <= 0) || (N <= 0) ) return(NULL);
+
+ A = NULL;
+ A = (DlsMat) malloc(sizeof *A);
+ if (A==NULL) return (NULL);
+
+ A->data = (realtype *) malloc(M * N * sizeof(realtype));
+ if (A->data == NULL) {
+ free(A); A = NULL;
+ return(NULL);
+ }
+ A->cols = (realtype **) malloc(N * sizeof(realtype *));
+ if (A->cols == NULL) {
+ free(A->data); A->data = NULL;
+ free(A); A = NULL;
+ return(NULL);
+ }
+
+ for (j=0; j < N; j++) A->cols[j] = A->data + j * M;
+
+ A->M = M;
+ A->N = N;
+ A->ldim = M;
+ A->ldata = M*N;
+
+ A->type = SUNDIALS_DENSE;
+
+ return(A);
+}
+
+realtype **newDenseMat(long int m, long int n)
+{
+ long int j;
+ realtype **a;
+
+ if ( (n <= 0) || (m <= 0) ) return(NULL);
+
+ a = NULL;
+ a = (realtype **) malloc(n * sizeof(realtype *));
+ if (a == NULL) return(NULL);
+
+ a[0] = NULL;
+ a[0] = (realtype *) malloc(m * n * sizeof(realtype));
+ if (a[0] == NULL) {
+ free(a); a = NULL;
+ return(NULL);
+ }
+
+ for (j=1; j < n; j++) a[j] = a[0] + j * m;
+
+ return(a);
+}
+
+
+DlsMat NewBandMat(long int N, long int mu, long int ml, long int smu)
+{
+ DlsMat A;
+ long int j, colSize;
+
+ if (N <= 0) return(NULL);
+
+ A = NULL;
+ A = (DlsMat) malloc(sizeof *A);
+ if (A == NULL) return (NULL);
+
+ colSize = smu + ml + 1;
+ A->data = NULL;
+ A->data = (realtype *) malloc(N * colSize * sizeof(realtype));
+ if (A->data == NULL) {
+ free(A); A = NULL;
+ return(NULL);
+ }
+
+ A->cols = NULL;
+ A->cols = (realtype **) malloc(N * sizeof(realtype *));
+ if (A->cols == NULL) {
+ free(A->data);
+ free(A); A = NULL;
+ return(NULL);
+ }
+
+ for (j=0; j < N; j++) A->cols[j] = A->data + j * colSize;
+
+ A->M = N;
+ A->N = N;
+ A->mu = mu;
+ A->ml = ml;
+ A->s_mu = smu;
+ A->ldim = colSize;
+ A->ldata = N * colSize;
+
+ A->type = SUNDIALS_BAND;
+
+ return(A);
+}
+
+realtype **newBandMat(long int n, long int smu, long int ml)
+{
+ realtype **a;
+ long int j, colSize;
+
+ if (n <= 0) return(NULL);
+
+ a = NULL;
+ a = (realtype **) malloc(n * sizeof(realtype *));
+ if (a == NULL) return(NULL);
+
+ colSize = smu + ml + 1;
+ a[0] = NULL;
+ a[0] = (realtype *) malloc(n * colSize * sizeof(realtype));
+ if (a[0] == NULL) {
+ free(a); a = NULL;
+ return(NULL);
+ }
+
+ for (j=1; j < n; j++) a[j] = a[0] + j * colSize;
+
+ return(a);
+}
+
+void DestroyMat(DlsMat A)
+{
+ free(A->data); A->data = NULL;
+ free(A->cols);
+ free(A); A = NULL;
+}
+
+void destroyMat(realtype **a)
+{
+ free(a[0]); a[0] = NULL;
+ free(a); a = NULL;
+}
+
+int *NewIntArray(int N)
+{
+ int *vec;
+
+ if (N <= 0) return(NULL);
+
+ vec = NULL;
+ vec = (int *) malloc(N * sizeof(int));
+
+ return(vec);
+}
+
+int *newIntArray(int n)
+{
+ int *v;
+
+ if (n <= 0) return(NULL);
+
+ v = NULL;
+ v = (int *) malloc(n * sizeof(int));
+
+ return(v);
+}
+
+long int *NewLintArray(long int N)
+{
+ long int *vec;
+
+ if (N <= 0) return(NULL);
+
+ vec = NULL;
+ vec = (long int *) malloc(N * sizeof(long int));
+
+ return(vec);
+}
+
+long int *newLintArray(long int n)
+{
+ long int *v;
+
+ if (n <= 0) return(NULL);
+
+ v = NULL;
+ v = (long int *) malloc(n * sizeof(long int));
+
+ return(v);
+}
+
+realtype *NewRealArray(long int N)
+{
+ realtype *vec;
+
+ if (N <= 0) return(NULL);
+
+ vec = NULL;
+ vec = (realtype *) malloc(N * sizeof(realtype));
+
+ return(vec);
+}
+
+realtype *newRealArray(long int m)
+{
+ realtype *v;
+
+ if (m <= 0) return(NULL);
+
+ v = NULL;
+ v = (realtype *) malloc(m * sizeof(realtype));
+
+ return(v);
+}
+
+void DestroyArray(void *V)
+{
+ free(V);
+ V = NULL;
+}
+
+void destroyArray(void *v)
+{
+ free(v);
+ v = NULL;
+}
+
+
+void AddIdentity(DlsMat A)
+{
+ long int i;
+
+ switch (A->type) {
+
+ case SUNDIALS_DENSE:
+ for (i=0; i<A->N; i++) A->cols[i][i] += ONE;
+ break;
+
+ case SUNDIALS_BAND:
+ for (i=0; i<A->M; i++) A->cols[i][A->s_mu] += ONE;
+ break;
+
+ }
+
+}
+
+
+void SetToZero(DlsMat A)
+{
+ long int i, j, colSize;
+ realtype *col_j;
+
+ switch (A->type) {
+
+ case SUNDIALS_DENSE:
+
+ for (j=0; j<A->N; j++) {
+ col_j = A->cols[j];
+ for (i=0; i<A->M; i++)
+ col_j[i] = ZERO;
+ }
+
+ break;
+
+ case SUNDIALS_BAND:
+
+ colSize = A->mu + A->ml + 1;
+ for (j=0; j<A->M; j++) {
+ col_j = A->cols[j] + A->s_mu - A->mu;
+ for (i=0; i<colSize; i++)
+ col_j[i] = ZERO;
+ }
+
+ break;
+
+ }
+
+}
+
+
+void PrintMat(DlsMat A)
+{
+ long int i, j, start, finish;
+ realtype **a;
+
+ switch (A->type) {
+
+ case SUNDIALS_DENSE:
+
+ printf("\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));
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("%12lg ", DENSE_ELEM(A,i,j));
+#else
+ printf("%12g ", DENSE_ELEM(A,i,j));
+#endif
+ }
+ printf("\n");
+ }
+ printf("\n");
+
+ break;
+
+ case SUNDIALS_BAND:
+
+ a = A->cols;
+ printf("\n");
+ for (i=0; i < A->N; i++) {
+ start = MAX(0,i-A->ml);
+ finish = MIN(A->N-1,i+A->mu);
+ for (j=0; j < start; j++) printf("%12s ","");
+ for (j=start; j <= finish; j++) {
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+ printf("%12Lg ", a[j][i-j+A->s_mu]);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ printf("%12lg ", a[j][i-j+A->s_mu]);
+#else
+ printf("%12g ", a[j][i-j+A->s_mu]);
+#endif
+ }
+ printf("\n");
+ }
+ printf("\n");
+
+ break;
+
+ }
+
+}
+
+
diff --git a/src/sundials/sundials_iterative.c b/src/sundials/sundials_iterative.c
new file mode 100644
index 0000000..41ccc17
--- /dev/null
+++ b/src/sundials/sundials_iterative.c
@@ -0,0 +1,288 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.1 $
+ * $Date: 2006/07/05 15:32:38 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh and
+ * Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * This is the implementation file for the iterative.h header
+ * file. It contains the implementation of functions that may be
+ * useful for many different iterative solvers of A x = b.
+ * -----------------------------------------------------------------
+ */
+
+#include <stdio.h>
+
+#include <sundials/sundials_iterative.h>
+#include <sundials/sundials_math.h>
+
+#define FACTOR RCONST(1000.0)
+#define ZERO RCONST(0.0)
+#define ONE RCONST(1.0)
+
+/*
+ * -----------------------------------------------------------------
+ * Function : ModifiedGS
+ * -----------------------------------------------------------------
+ * This implementation of ModifiedGS is a slight modification of a
+ * previous modified Gram-Schmidt routine (called mgs) written by
+ * Milo Dorr.
+ * -----------------------------------------------------------------
+ */
+
+int ModifiedGS(N_Vector *v, realtype **h, int k, int p,
+ realtype *new_vk_norm)
+{
+ int i, k_minus_1, i0;
+ realtype new_norm_2, new_product, vk_norm, temp;
+
+ vk_norm = RSqrt(N_VDotProd(v[k],v[k]));
+ k_minus_1 = k - 1;
+ i0 = MAX(k-p, 0);
+
+ /* Perform modified Gram-Schmidt */
+
+ for (i=i0; i < k; i++) {
+ h[i][k_minus_1] = N_VDotProd(v[i], v[k]);
+ N_VLinearSum(ONE, v[k], -h[i][k_minus_1], v[i], v[k]);
+ }
+
+ /* Compute the norm of the new vector at v[k] */
+
+ *new_vk_norm = RSqrt(N_VDotProd(v[k], v[k]));
+
+ /* If the norm of the new vector at v[k] is less than
+ FACTOR (== 1000) times unit roundoff times the norm of the
+ input vector v[k], then the vector will be reorthogonalized
+ in order to ensure that nonorthogonality is not being masked
+ by a very small vector length. */
+
+ temp = FACTOR * vk_norm;
+ if ((temp + (*new_vk_norm)) != temp) return(0);
+
+ new_norm_2 = ZERO;
+
+ for (i=i0; i < k; i++) {
+ new_product = N_VDotProd(v[i], v[k]);
+ temp = FACTOR * h[i][k_minus_1];
+ if ((temp + new_product) == temp) continue;
+ h[i][k_minus_1] += new_product;
+ N_VLinearSum(ONE, v[k],-new_product, v[i], v[k]);
+ new_norm_2 += SQR(new_product);
+ }
+
+ if (new_norm_2 != ZERO) {
+ new_product = SQR(*new_vk_norm) - new_norm_2;
+ *new_vk_norm = (new_product > ZERO) ? RSqrt(new_product) : ZERO;
+ }
+
+ return(0);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Function : ClassicalGS
+ * -----------------------------------------------------------------
+ * This implementation of ClassicalGS was contributed by Homer Walker
+ * and Peter Brown.
+ * -----------------------------------------------------------------
+ */
+
+int ClassicalGS(N_Vector *v, realtype **h, int k, int p,
+ realtype *new_vk_norm, N_Vector temp, realtype *s)
+{
+ int i, k_minus_1, i0;
+ realtype vk_norm;
+
+ k_minus_1 = k - 1;
+
+ /* Perform Classical Gram-Schmidt */
+
+ vk_norm = RSqrt(N_VDotProd(v[k], v[k]));
+
+ i0 = MAX(k-p, 0);
+ for (i=i0; i < k; i++) {
+ h[i][k_minus_1] = N_VDotProd(v[i], v[k]);
+ }
+
+ for (i=i0; i < k; i++) {
+ N_VLinearSum(ONE, v[k], -h[i][k_minus_1], v[i], v[k]);
+ }
+
+ /* Compute the norm of the new vector at v[k] */
+
+ *new_vk_norm = RSqrt(N_VDotProd(v[k], v[k]));
+
+ /* Reorthogonalize if necessary */
+
+ if ((FACTOR * (*new_vk_norm)) < vk_norm) {
+
+ for (i=i0; i < k; i++) {
+ s[i] = N_VDotProd(v[i], v[k]);
+ }
+
+ if (i0 < k) {
+ N_VScale(s[i0], v[i0], temp);
+ h[i0][k_minus_1] += s[i0];
+ }
+ for (i=i0+1; i < k; i++) {
+ N_VLinearSum(s[i], v[i], ONE, temp, temp);
+ h[i][k_minus_1] += s[i];
+ }
+ N_VLinearSum(ONE, v[k], -ONE, temp, v[k]);
+
+ *new_vk_norm = RSqrt(N_VDotProd(v[k],v[k]));
+ }
+
+ return(0);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Function : QRfact
+ * -----------------------------------------------------------------
+ * This implementation of QRfact is a slight modification of a
+ * previous routine (called qrfact) written by Milo Dorr.
+ * -----------------------------------------------------------------
+ */
+
+int QRfact(int n, realtype **h, realtype *q, int job)
+{
+ realtype c, s, temp1, temp2, temp3;
+ int i, j, k, q_ptr, n_minus_1, code=0;
+
+ switch (job) {
+ case 0:
+
+ /* Compute a new factorization of H */
+
+ code = 0;
+ for (k=0; k < n; k++) {
+
+ /* Multiply column k by the previous k-1 Givens rotations */
+
+ for (j=0; j < k-1; j++) {
+ i = 2*j;
+ temp1 = h[j][k];
+ temp2 = h[j+1][k];
+ c = q[i];
+ s = q[i+1];
+ h[j][k] = c*temp1 - s*temp2;
+ h[j+1][k] = s*temp1 + c*temp2;
+ }
+
+ /* Compute the Givens rotation components c and s */
+
+ q_ptr = 2*k;
+ temp1 = h[k][k];
+ temp2 = h[k+1][k];
+ if( temp2 == ZERO) {
+ c = ONE;
+ s = ZERO;
+ } else if (ABS(temp2) >= ABS(temp1)) {
+ temp3 = temp1/temp2;
+ s = -ONE/RSqrt(ONE+SQR(temp3));
+ c = -s*temp3;
+ } else {
+ temp3 = temp2/temp1;
+ c = ONE/RSqrt(ONE+SQR(temp3));
+ s = -c*temp3;
+ }
+ q[q_ptr] = c;
+ q[q_ptr+1] = s;
+ if( (h[k][k] = c*temp1 - s*temp2) == ZERO) code = k+1;
+ }
+ break;
+
+ default:
+
+ /* Update the factored H to which a new column has been added */
+
+ n_minus_1 = n - 1;
+ code = 0;
+
+ /* Multiply the new column by the previous n-1 Givens rotations */
+
+ for (k=0; k < n_minus_1; k++) {
+ i = 2*k;
+ temp1 = h[k][n_minus_1];
+ temp2 = h[k+1][n_minus_1];
+ c = q[i];
+ s = q[i+1];
+ h[k][n_minus_1] = c*temp1 - s*temp2;
+ h[k+1][n_minus_1] = s*temp1 + c*temp2;
+ }
+
+ /* Compute new Givens rotation and multiply it times the last two
+ entries in the new column of H. Note that the second entry of
+ this product will be 0, so it is not necessary to compute it. */
+
+ temp1 = h[n_minus_1][n_minus_1];
+ temp2 = h[n][n_minus_1];
+ if (temp2 == ZERO) {
+ c = ONE;
+ s = ZERO;
+ } else if (ABS(temp2) >= ABS(temp1)) {
+ temp3 = temp1/temp2;
+ s = -ONE/RSqrt(ONE+SQR(temp3));
+ c = -s*temp3;
+ } else {
+ temp3 = temp2/temp1;
+ c = ONE/RSqrt(ONE+SQR(temp3));
+ s = -c*temp3;
+ }
+ q_ptr = 2*n_minus_1;
+ q[q_ptr] = c;
+ q[q_ptr+1] = s;
+ if ((h[n_minus_1][n_minus_1] = c*temp1 - s*temp2) == ZERO)
+ code = n;
+ }
+
+ return (code);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Function : QRsol
+ * -----------------------------------------------------------------
+ * This implementation of QRsol is a slight modification of a
+ * previous routine (called qrsol) written by Milo Dorr.
+ * -----------------------------------------------------------------
+ */
+
+int QRsol(int n, realtype **h, realtype *q, realtype *b)
+{
+ realtype c, s, temp1, temp2;
+ int i, k, q_ptr, code=0;
+
+ /* Compute Q*b */
+
+ for (k=0; k < n; k++) {
+ q_ptr = 2*k;
+ c = q[q_ptr];
+ s = q[q_ptr+1];
+ temp1 = b[k];
+ temp2 = b[k+1];
+ b[k] = c*temp1 - s*temp2;
+ b[k+1] = s*temp1 + c*temp2;
+ }
+
+ /* Solve R*x = Q*b */
+
+ for (k=n-1; k >= 0; k--) {
+ if (h[k][k] == ZERO) {
+ code = k + 1;
+ break;
+ }
+ b[k] /= h[k][k];
+ for (i=0; i < k; i++) b[i] -= b[k]*h[i][k];
+ }
+
+ return (code);
+}
diff --git a/src/sundials/sundials_math.c b/src/sundials/sundials_math.c
new file mode 100644
index 0000000..8bc9d59
--- /dev/null
+++ b/src/sundials/sundials_math.c
@@ -0,0 +1,94 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.1 $
+ * $Date: 2006/07/05 15:32:38 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh and
+ * Aaron Collier @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * This is the implementation file for a simple C-language math
+ * library.
+ * -----------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+
+#include <sundials/sundials_math.h>
+
+#define ZERO RCONST(0.0)
+#define ONE RCONST(1.0)
+
+realtype RPowerI(realtype base, int exponent)
+{
+ int i, expt;
+ realtype prod;
+
+ prod = ONE;
+ expt = abs(exponent);
+ for(i = 1; i <= expt; i++) prod *= base;
+ if (exponent < 0) prod = ONE/prod;
+ return(prod);
+}
+
+realtype RPowerR(realtype base, realtype exponent)
+{
+ if (base <= ZERO) return(ZERO);
+
+#if defined(SUNDIALS_USE_GENERIC_MATH)
+ return((realtype) pow((double) base, (double) exponent));
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ return(pow(base, exponent));
+#elif defined(SUNDIALS_SINGLE_PRECISION)
+ return(powf(base, exponent));
+#elif defined(SUNDIALS_EXTENDED_PRECISION)
+ return(powl(base, exponent));
+#endif
+}
+
+realtype RSqrt(realtype x)
+{
+ if (x <= ZERO) return(ZERO);
+
+#if defined(SUNDIALS_USE_GENERIC_MATH)
+ return((realtype) sqrt((double) x));
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ return(sqrt(x));
+#elif defined(SUNDIALS_SINGLE_PRECISION)
+ return(sqrtf(x));
+#elif defined(SUNDIALS_EXTENDED_PRECISION)
+ return(sqrtl(x));
+#endif
+}
+
+realtype RAbs(realtype x)
+{
+#if defined(SUNDIALS_USE_GENERIC_MATH)
+ return((realtype) fabs((double) x));
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ return(fabs(x));
+#elif defined(SUNDIALS_SINGLE_PRECISION)
+ return(fabsf(x));
+#elif defined(SUNDIALS_EXTENDED_PRECISION)
+ return(fabsl(x));
+#endif
+}
+
+realtype RExp(realtype x)
+{
+#if defined(SUNDIALS_USE_GENERIC_MATH)
+ return((realtype) exp((double) x));
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+ return(exp(x));
+#elif defined(SUNDIALS_SINGLE_PRECISION)
+ return(expf(x));
+#elif defined(SUNDIALS_EXTENDED_PRECISION)
+ return(expl(x));
+#endif
+}
diff --git a/src/sundials/sundials_nvector.c b/src/sundials/sundials_nvector.c
new file mode 100644
index 0000000..e8e1b83
--- /dev/null
+++ b/src/sundials/sundials_nvector.c
@@ -0,0 +1,233 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.3 $
+ * $Date: 2007/04/06 20:33:30 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Radu Serban and Aaron Collier @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * This is the implementation file for a generic NVECTOR package.
+ * It contains the implementation of the N_Vector operations listed
+ * in nvector.h.
+ * -----------------------------------------------------------------
+ */
+
+#include <stdlib.h>
+
+#include <sundials/sundials_nvector.h>
+
+/*
+ * -----------------------------------------------------------------
+ * Functions in the 'ops' structure
+ * -----------------------------------------------------------------
+ */
+
+N_Vector N_VClone(N_Vector w)
+{
+ N_Vector v = NULL;
+ v = w->ops->nvclone(w);
+ return(v);
+}
+
+N_Vector N_VCloneEmpty(N_Vector w)
+{
+ N_Vector v = NULL;
+ v = w->ops->nvcloneempty(w);
+ return(v);
+}
+
+void N_VDestroy(N_Vector v)
+{
+ if (v==NULL) return;
+ v->ops->nvdestroy(v);
+ return;
+}
+
+void N_VSpace(N_Vector v, long int *lrw, long int *liw)
+{
+ v->ops->nvspace(v, lrw, liw);
+ return;
+}
+
+realtype *N_VGetArrayPointer(N_Vector v)
+{
+ return((realtype *) v->ops->nvgetarraypointer(v));
+}
+
+void N_VSetArrayPointer(realtype *v_data, N_Vector v)
+{
+ v->ops->nvsetarraypointer(v_data, v);
+ return;
+}
+
+void N_VLinearSum(realtype a, N_Vector x, realtype b, N_Vector y, N_Vector z)
+{
+ z->ops->nvlinearsum(a, x, b, y, z);
+ return;
+}
+
+void N_VConst(realtype c, N_Vector z)
+{
+ z->ops->nvconst(c, z);
+ return;
+}
+
+void N_VProd(N_Vector x, N_Vector y, N_Vector z)
+{
+ z->ops->nvprod(x, y, z);
+ return;
+}
+
+void N_VDiv(N_Vector x, N_Vector y, N_Vector z)
+{
+ z->ops->nvdiv(x, y, z);
+ return;
+}
+
+void N_VScale(realtype c, N_Vector x, N_Vector z)
+{
+ z->ops->nvscale(c, x, z);
+ return;
+}
+
+void N_VAbs(N_Vector x, N_Vector z)
+{
+ z->ops->nvabs(x, z);
+ return;
+}
+
+void N_VInv(N_Vector x, N_Vector z)
+{
+ z->ops->nvinv(x, z);
+ return;
+}
+
+void N_VAddConst(N_Vector x, realtype b, N_Vector z)
+{
+ z->ops->nvaddconst(x, b, z);
+ return;
+}
+
+realtype N_VDotProd(N_Vector x, N_Vector y)
+{
+ return((realtype) y->ops->nvdotprod(x, y));
+}
+
+realtype N_VMaxNorm(N_Vector x)
+{
+ return((realtype) x->ops->nvmaxnorm(x));
+}
+
+realtype N_VWrmsNorm(N_Vector x, N_Vector w)
+{
+ return((realtype) x->ops->nvwrmsnorm(x, w));
+}
+
+realtype N_VWrmsNormMask(N_Vector x, N_Vector w, N_Vector id)
+{
+ return((realtype) x->ops->nvwrmsnormmask(x, w, id));
+}
+
+realtype N_VMin(N_Vector x)
+{
+ return((realtype) x->ops->nvmin(x));
+}
+
+realtype N_VWL2Norm(N_Vector x, N_Vector w)
+{
+ return((realtype) x->ops->nvwl2norm(x, w));
+}
+
+realtype N_VL1Norm(N_Vector x)
+{
+ return((realtype) x->ops->nvl1norm(x));
+}
+
+void N_VCompare(realtype c, N_Vector x, N_Vector z)
+{
+ z->ops->nvcompare(c, x, z);
+ return;
+}
+
+booleantype N_VInvTest(N_Vector x, N_Vector z)
+{
+ return((booleantype) z->ops->nvinvtest(x, z));
+}
+
+booleantype N_VConstrMask(N_Vector c, N_Vector x, N_Vector m)
+{
+ return((booleantype) x->ops->nvconstrmask(c, x, m));
+}
+
+realtype N_VMinQuotient(N_Vector num, N_Vector denom)
+{
+ return((realtype) num->ops->nvminquotient(num, denom));
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Additional functions exported by the generic NVECTOR:
+ * N_VCloneEmptyVectorArray
+ * N_VCloneVectorArray
+ * N_VDestroyVectorArray
+ * -----------------------------------------------------------------
+ */
+
+N_Vector *N_VCloneEmptyVectorArray(int count, N_Vector w)
+{
+ N_Vector *vs = NULL;
+ int j;
+
+ if (count <= 0) return(NULL);
+
+ vs = (N_Vector *) malloc(count * sizeof(N_Vector));
+ if(vs == NULL) return(NULL);
+
+ for (j = 0; j < count; j++) {
+ vs[j] = N_VCloneEmpty(w);
+ if (vs[j] == NULL) {
+ N_VDestroyVectorArray(vs, j-1);
+ return(NULL);
+ }
+ }
+
+ return(vs);
+}
+
+N_Vector *N_VCloneVectorArray(int count, N_Vector w)
+{
+ N_Vector *vs = NULL;
+ int j;
+
+ if (count <= 0) return(NULL);
+
+ vs = (N_Vector *) malloc(count * sizeof(N_Vector));
+ if(vs == NULL) return(NULL);
+
+ for (j = 0; j < count; j++) {
+ vs[j] = N_VClone(w);
+ if (vs[j] == NULL) {
+ N_VDestroyVectorArray(vs, j-1);
+ return(NULL);
+ }
+ }
+
+ return(vs);
+}
+
+void N_VDestroyVectorArray(N_Vector *vs, int count)
+{
+ int j;
+
+ if (vs==NULL) return;
+
+ for (j = 0; j < count; j++) N_VDestroy(vs[j]);
+
+ free(vs); vs = NULL;
+
+ return;
+}
diff --git a/src/sundials/sundials_spbcgs.c b/src/sundials/sundials_spbcgs.c
new file mode 100644
index 0000000..b73bf26
--- /dev/null
+++ b/src/sundials/sundials_spbcgs.c
@@ -0,0 +1,379 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.2 $
+ * $Date: 2007/04/06 20:33:30 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Peter Brown and Aaron Collier @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2004, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * This is the implementation file for the scaled, preconditioned
+ * Bi-CGSTAB (SPBCG) iterative linear solver.
+ * -----------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <sundials/sundials_spbcgs.h>
+#include <sundials/sundials_math.h>
+
+/*
+ * -----------------------------------------------------------------
+ * private constants
+ * -----------------------------------------------------------------
+ */
+
+#define ZERO RCONST(0.0)
+#define ONE RCONST(1.0)
+
+/*
+ * -----------------------------------------------------------------
+ * Function : SpbcgMalloc
+ * -----------------------------------------------------------------
+ */
+
+SpbcgMem SpbcgMalloc(int l_max, N_Vector vec_tmpl)
+{
+ SpbcgMem mem;
+ N_Vector r_star, r, p, q, u, Ap, vtemp;
+
+ /* Check the input parameters */
+
+ if (l_max <= 0) return(NULL);
+
+ /* Get arrays to hold temporary vectors */
+
+ r_star = N_VClone(vec_tmpl);
+ if (r_star == NULL) {
+ return(NULL);
+ }
+
+ r = N_VClone(vec_tmpl);
+ if (r == NULL) {
+ N_VDestroy(r_star);
+ return(NULL);
+ }
+
+ p = N_VClone(vec_tmpl);
+ if (p == NULL) {
+ N_VDestroy(r_star);
+ N_VDestroy(r);
+ return(NULL);
+ }
+
+ q = N_VClone(vec_tmpl);
+ if (q == NULL) {
+ N_VDestroy(r_star);
+ N_VDestroy(r);
+ N_VDestroy(p);
+ return(NULL);
+ }
+
+ u = N_VClone(vec_tmpl);
+ if (u == NULL) {
+ N_VDestroy(r_star);
+ N_VDestroy(r);
+ N_VDestroy(p);
+ N_VDestroy(q);
+ return(NULL);
+ }
+
+ Ap = N_VClone(vec_tmpl);
+ if (Ap == NULL) {
+ N_VDestroy(r_star);
+ N_VDestroy(r);
+ N_VDestroy(p);
+ N_VDestroy(q);
+ N_VDestroy(u);
+ return(NULL);
+ }
+
+ vtemp = N_VClone(vec_tmpl);
+ if (vtemp == NULL) {
+ N_VDestroy(r_star);
+ N_VDestroy(r);
+ N_VDestroy(p);
+ N_VDestroy(q);
+ N_VDestroy(u);
+ N_VDestroy(Ap);
+ return(NULL);
+ }
+
+ /* Get memory for an SpbcgMemRec containing SPBCG matrices and vectors */
+
+ mem = NULL;
+ mem = (SpbcgMem) malloc(sizeof(SpbcgMemRec));
+ if (mem == NULL) {
+ N_VDestroy(r_star);
+ N_VDestroy(r);
+ N_VDestroy(p);
+ N_VDestroy(q);
+ N_VDestroy(u);
+ N_VDestroy(Ap);
+ N_VDestroy(vtemp);
+ return(NULL);
+ }
+
+ /* Set the fields of mem */
+
+ mem->l_max = l_max;
+ mem->r_star = r_star;
+ mem->r = r;
+ mem->p = p;
+ mem->q = q;
+ mem->u = u;
+ mem->Ap = Ap;
+ mem->vtemp = vtemp;
+
+ /* Return the pointer to SPBCG memory */
+
+ return(mem);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Function : SpbcgSolve
+ * -----------------------------------------------------------------
+ */
+
+int SpbcgSolve(SpbcgMem mem, void *A_data, N_Vector x, N_Vector b,
+ int pretype, realtype delta, void *P_data, N_Vector sx,
+ N_Vector sb, ATimesFn atimes, PSolveFn psolve,
+ realtype *res_norm, int *nli, int *nps)
+{
+ 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;
+
+ if (mem == NULL) return(SPBCG_MEM_NULL);
+
+ /* Make local copies of mem variables */
+
+ l_max = mem->l_max;
+ r_star = mem->r_star;
+ r = mem->r;
+ p = mem->p;
+ q = mem->q;
+ u = mem->u;
+ Ap = mem->Ap;
+ vtemp = mem->vtemp;
+
+ *nli = *nps = 0; /* Initialize counters */
+ converged = FALSE; /* Initialize converged flag */
+
+ if ((pretype != PREC_LEFT) && (pretype != PREC_RIGHT) && (pretype != PREC_BOTH)) pretype = PREC_NONE;
+
+ preOnLeft = ((pretype == PREC_BOTH) || (pretype == PREC_LEFT));
+ preOnRight = ((pretype == PREC_BOTH) || (pretype == PREC_RIGHT));
+
+ 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)
+ return((ier < 0) ? SPBCG_ATIMES_FAIL_UNREC : SPBCG_ATIMES_FAIL_REC);
+ 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, PREC_LEFT);
+ (*nps)++;
+ if (ier != 0) return((ier < 0) ? SPBCG_PSOLVE_FAIL_UNREC : SPBCG_PSOLVE_FAIL_REC);
+ }
+ 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 = RSqrt(beta_denom);
+ if (r_norm <= delta) return(SPBCG_SUCCESS);
+
+ /* 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, PREC_RIGHT);
+ (*nps)++;
+ if (ier != 0) return((ier < 0) ? SPBCG_PSOLVE_FAIL_UNREC : SPBCG_PSOLVE_FAIL_REC);
+ }
+
+ /* Apply A: Ap = A P2_inv sx_inv p */
+
+ ier = atimes(A_data, vtemp, Ap );
+ if (ier != 0)
+ return((ier < 0) ? SPBCG_ATIMES_FAIL_UNREC : SPBCG_ATIMES_FAIL_REC);
+
+ /* Apply left preconditioner: vtemp = P1_inv A P2_inv sx_inv p */
+
+ if (preOnLeft) {
+ ier = psolve(P_data, Ap, vtemp, PREC_LEFT);
+ (*nps)++;
+ if (ier != 0) return((ier < 0) ? SPBCG_PSOLVE_FAIL_UNREC : SPBCG_PSOLVE_FAIL_REC);
+ }
+ 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 = ((N_VDotProd(r, r_star) / 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, PREC_RIGHT);
+ (*nps)++;
+ if (ier != 0) return((ier < 0) ? SPBCG_PSOLVE_FAIL_UNREC : SPBCG_PSOLVE_FAIL_REC);
+ }
+
+ /* Apply A: u = A P2_inv sx_inv u */
+
+ ier = atimes(A_data, vtemp, u );
+ if (ier != 0)
+ return((ier < 0) ? SPBCG_ATIMES_FAIL_UNREC : SPBCG_ATIMES_FAIL_REC);
+
+ /* Apply left preconditioner: vtemp = P1_inv A P2_inv sx_inv p */
+
+ if (preOnLeft) {
+ ier = psolve(P_data, u, vtemp, PREC_LEFT);
+ (*nps)++;
+ if (ier != 0) return((ier < 0) ? SPBCG_PSOLVE_FAIL_UNREC : SPBCG_PSOLVE_FAIL_REC);
+ }
+ 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 = RSqrt(N_VDotProd(r, r));
+ if (rho <= delta) {
+ converged = TRUE;
+ 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 == TRUE) || (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);
+ (*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);
+ else return(SPBCG_RES_REDUCED);
+ }
+ else return(SPBCG_CONV_FAIL);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Function : SpbcgFree
+ * -----------------------------------------------------------------
+ */
+
+void SpbcgFree(SpbcgMem mem)
+{
+
+ if (mem == NULL) return;
+
+ N_VDestroy(mem->r_star);
+ N_VDestroy(mem->r);
+ N_VDestroy(mem->p);
+ N_VDestroy(mem->q);
+ N_VDestroy(mem->u);
+ N_VDestroy(mem->Ap);
+ N_VDestroy(mem->vtemp);
+
+ free(mem); mem = NULL;
+}
diff --git a/src/sundials/sundials_spgmr.c b/src/sundials/sundials_spgmr.c
new file mode 100644
index 0000000..7efd187
--- /dev/null
+++ b/src/sundials/sundials_spgmr.c
@@ -0,0 +1,458 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.2 $
+ * $Date: 2007/04/06 20:33:30 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh and
+ * Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Copyright (c) 2002, The Regents of the University of California.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * -----------------------------------------------------------------
+ * This is the implementation file for the scaled preconditioned
+ * GMRES (SPGMR) iterative linear solver.
+ * -----------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <sundials/sundials_spgmr.h>
+#include <sundials/sundials_math.h>
+
+/*
+ * -----------------------------------------------------------------
+ * private constants
+ * -----------------------------------------------------------------
+ */
+
+#define ZERO RCONST(0.0)
+#define ONE RCONST(1.0)
+
+/*
+ * -----------------------------------------------------------------
+ * Function : SpgmrMalloc
+ * -----------------------------------------------------------------
+ */
+
+SpgmrMem SpgmrMalloc(int l_max, N_Vector vec_tmpl)
+{
+ SpgmrMem mem;
+ N_Vector *V, xcor, vtemp;
+ realtype **Hes, *givens, *yg;
+ int k, i;
+
+ /* Check the input parameters. */
+
+ if (l_max <= 0) return(NULL);
+
+ /* Get memory for the Krylov basis vectors V[0], ..., V[l_max]. */
+
+ V = N_VCloneVectorArray(l_max+1, vec_tmpl);
+ if (V == NULL) return(NULL);
+
+ /* Get memory for the Hessenberg matrix Hes. */
+
+ Hes = NULL;
+ Hes = (realtype **) malloc((l_max+1)*sizeof(realtype *));
+ if (Hes == NULL) {
+ N_VDestroyVectorArray(V, l_max+1);
+ return(NULL);
+ }
+
+ for (k = 0; k <= l_max; k++) {
+ Hes[k] = NULL;
+ Hes[k] = (realtype *) malloc(l_max*sizeof(realtype));
+ if (Hes[k] == NULL) {
+ for (i = 0; i < k; i++) {free(Hes[i]); Hes[i] = NULL;}
+ free(Hes); Hes = NULL;
+ N_VDestroyVectorArray(V, l_max+1);
+ return(NULL);
+ }
+ }
+
+ /* Get memory for Givens rotation components. */
+
+ givens = NULL;
+ givens = (realtype *) malloc(2*l_max*sizeof(realtype));
+ if (givens == NULL) {
+ for (i = 0; i <= l_max; i++) {free(Hes[i]); Hes[i] = NULL;}
+ free(Hes); Hes = NULL;
+ N_VDestroyVectorArray(V, l_max+1);
+ return(NULL);
+ }
+
+ /* Get memory to hold the correction to z_tilde. */
+
+ xcor = N_VClone(vec_tmpl);
+ if (xcor == NULL) {
+ free(givens); givens = NULL;
+ for (i = 0; i <= l_max; i++) {free(Hes[i]); Hes[i] = NULL;}
+ free(Hes); Hes = NULL;
+ N_VDestroyVectorArray(V, l_max+1);
+ return(NULL);
+ }
+
+ /* Get memory to hold SPGMR y and g vectors. */
+
+ yg = NULL;
+ yg = (realtype *) malloc((l_max+1)*sizeof(realtype));
+ if (yg == NULL) {
+ N_VDestroy(xcor);
+ free(givens); givens = NULL;
+ for (i = 0; i <= l_max; i++) {free(Hes[i]); Hes[i] = NULL;}
+ free(Hes); Hes = NULL;
+ N_VDestroyVectorArray(V, l_max+1);
+ return(NULL);
+ }
+
+ /* Get an array to hold a temporary vector. */
+
+ vtemp = N_VClone(vec_tmpl);
+ if (vtemp == NULL) {
+ free(yg); yg = NULL;
+ N_VDestroy(xcor);
+ free(givens); givens = NULL;
+ for (i = 0; i <= l_max; i++) {free(Hes[i]); Hes[i] = NULL;}
+ free(Hes); Hes = NULL;
+ N_VDestroyVectorArray(V, l_max+1);
+ return(NULL);
+ }
+
+ /* Get memory for an SpgmrMemRec containing SPGMR matrices and vectors. */
+
+ mem = NULL;
+ mem = (SpgmrMem) malloc(sizeof(SpgmrMemRec));
+ if (mem == NULL) {
+ N_VDestroy(vtemp);
+ free(yg); yg = NULL;
+ N_VDestroy(xcor);
+ free(givens); givens = NULL;
+ for (i = 0; i <= l_max; i++) {free(Hes[i]); Hes[i] = NULL;}
+ free(Hes); Hes = NULL;
+ N_VDestroyVectorArray(V, l_max+1);
+ return(NULL);
+ }
+
+ /* Set the fields of mem. */
+
+ mem->l_max = l_max;
+ mem->V = V;
+ mem->Hes = Hes;
+ mem->givens = givens;
+ mem->xcor = xcor;
+ mem->yg = yg;
+ mem->vtemp = vtemp;
+
+ /* Return the pointer to SPGMR memory. */
+
+ return(mem);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Function : SpgmrSolve
+ * -----------------------------------------------------------------
+ */
+
+int SpgmrSolve(SpgmrMem mem, void *A_data, N_Vector x, N_Vector b,
+ int pretype, int gstype, realtype delta, int max_restarts,
+ void *P_data, N_Vector s1, N_Vector s2, ATimesFn atimes,
+ PSolveFn psolve, realtype *res_norm, int *nli, int *nps)
+{
+ N_Vector *V, xcor, vtemp;
+ realtype **Hes, *givens, *yg;
+ 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;
+
+ if (mem == NULL) return(SPGMR_MEM_NULL);
+
+ /* Initialize some variables */
+
+ l_plus_1 = 0;
+ krydim = 0;
+
+ /* Make local copies of mem variables. */
+
+ l_max = mem->l_max;
+ V = mem->V;
+ Hes = mem->Hes;
+ givens = mem->givens;
+ xcor = mem->xcor;
+ yg = mem->yg;
+ vtemp = mem->vtemp;
+
+ *nli = *nps = 0; /* Initialize counters */
+ converged = FALSE; /* Initialize converged flag */
+
+ if (max_restarts < 0) max_restarts = 0;
+
+ if ((pretype != PREC_LEFT) && (pretype != PREC_RIGHT) && (pretype != PREC_BOTH))
+ pretype = PREC_NONE;
+
+ preOnLeft = ((pretype == PREC_LEFT) || (pretype == PREC_BOTH));
+ preOnRight = ((pretype == PREC_RIGHT) || (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)
+ return((ier < 0) ? SPGMR_ATIMES_FAIL_UNREC : SPGMR_ATIMES_FAIL_REC);
+ 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, PREC_LEFT);
+ (*nps)++;
+ if (ier != 0)
+ return((ier < 0) ? SPGMR_PSOLVE_FAIL_UNREC : SPGMR_PSOLVE_FAIL_REC);
+ } 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 = RSqrt(N_VDotProd(V[0], V[0]));
+ if (r_norm <= delta)
+ return(SPGMR_SUCCESS);
+
+ /* 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, PREC_RIGHT);
+ (*nps)++;
+ if (ier != 0)
+ return((ier < 0) ? SPGMR_PSOLVE_FAIL_UNREC : SPGMR_PSOLVE_FAIL_REC);
+ }
+
+ /* Apply A: V[l+1] = A P2_inv s2_inv V[l]. */
+
+ ier = atimes(A_data, vtemp, V[l_plus_1] );
+ if (ier != 0)
+ return((ier < 0) ? SPGMR_ATIMES_FAIL_UNREC : SPGMR_ATIMES_FAIL_REC);
+
+ /* 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);
+ (*nps)++;
+ if (ier != 0)
+ return((ier < 0) ? SPGMR_PSOLVE_FAIL_UNREC : SPGMR_PSOLVE_FAIL_REC);
+ } 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)
+ return(SPGMR_GS_FAIL);
+ } else {
+ if (ModifiedGS(V, Hes, l_plus_1, l_max, &(Hes[l_plus_1][l])) != 0)
+ return(SPGMR_GS_FAIL);
+ }
+
+ /* Update the QR factorization of Hes. */
+
+ if(QRfact(krydim, Hes, givens, l) != 0 )
+ return(SPGMR_QRFACT_FAIL);
+
+ /* Update residual norm estimate; break if convergence test passes. */
+
+ rotation_product *= givens[2*l+1];
+ *res_norm = rho = ABS(rotation_product*r_norm);
+
+ if (rho <= delta) { converged = TRUE; 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)
+ return(SPGMR_QRSOL_FAIL);
+
+ /* 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, PREC_RIGHT);
+ (*nps)++;
+ if (ier != 0)
+ return((ier < 0) ? SPGMR_PSOLVE_FAIL_UNREC : SPGMR_PSOLVE_FAIL_REC);
+ } 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);
+
+ return(SPGMR_SUCCESS);
+ }
+
+ /* 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 = ABS(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, PREC_RIGHT);
+ (*nps)++;
+ if (ier != 0)
+ return((ier < 0) ? SPGMR_PSOLVE_FAIL_UNREC : SPGMR_PSOLVE_FAIL_REC);
+ } 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);
+
+ return(SPGMR_RES_REDUCED);
+ }
+
+ return(SPGMR_CONV_FAIL);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Function : SpgmrFree
+ * -----------------------------------------------------------------
+ */
+
+void SpgmrFree(SpgmrMem mem)
+{
+ int i, l_max;
+ realtype **Hes, *givens, *yg;
+
+ if (mem == NULL) return;
+
+ l_max = mem->l_max;
+ Hes = mem->Hes;
+ givens = mem->givens;
+ yg = mem->yg;
+
+ for (i = 0; i <= l_max; i++) {free(Hes[i]); Hes[i] = NULL;}
+ free(Hes); Hes = NULL;
+ free(mem->givens); givens = NULL;
+ free(mem->yg); yg = NULL;
+
+ N_VDestroyVectorArray(mem->V, l_max+1);
+ N_VDestroy(mem->xcor);
+ N_VDestroy(mem->vtemp);
+
+ free(mem); mem = NULL;
+}
diff --git a/src/sundials/sundials_sptfqmr.c b/src/sundials/sundials_sptfqmr.c
new file mode 100644
index 0000000..626ca00
--- /dev/null
+++ b/src/sundials/sundials_sptfqmr.c
@@ -0,0 +1,516 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.2 $
+ * $Date: 2007/04/06 20:33:30 $
+ * -----------------------------------------------------------------
+ * Programmer(s): Aaron Collier @ 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.
+ * -----------------------------------------------------------------
+ * This is the implementation file for the scaled preconditioned
+ * Transpose-Free Quasi-Minimal Residual (SPTFQMR) linear solver.
+ * -----------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <sundials/sundials_sptfqmr.h>
+#include <sundials/sundials_math.h>
+
+/*
+ * -----------------------------------------------------------------
+ * private constants
+ * -----------------------------------------------------------------
+ */
+
+#define ZERO RCONST(0.0)
+#define ONE RCONST(1.0)
+
+/*
+ * -----------------------------------------------------------------
+ * Function : SptfqmrMalloc
+ * -----------------------------------------------------------------
+ */
+
+SptfqmrMem SptfqmrMalloc(int l_max, N_Vector vec_tmpl)
+{
+ SptfqmrMem mem;
+ N_Vector *r;
+ N_Vector q, d, v, p, u;
+ N_Vector r_star, vtemp1, vtemp2, vtemp3;
+
+ /* Check the input parameters */
+ if ((l_max <= 0) || (vec_tmpl == NULL)) return(NULL);
+
+ /* Allocate space for vectors */
+
+ r_star = N_VClone(vec_tmpl);
+ if (r_star == NULL) return(NULL);
+
+ q = N_VClone(vec_tmpl);
+ if (q == NULL) {
+ N_VDestroy(r_star);
+ return(NULL);
+ }
+
+ d = N_VClone(vec_tmpl);
+ if (d == NULL) {
+ N_VDestroy(r_star);
+ N_VDestroy(q);
+ return(NULL);
+ }
+
+ v = N_VClone(vec_tmpl);
+ if (v == NULL) {
+ N_VDestroy(r_star);
+ N_VDestroy(q);
+ N_VDestroy(d);
+ return(NULL);
+ }
+
+ p = N_VClone(vec_tmpl);
+ if (p == NULL) {
+ N_VDestroy(r_star);
+ N_VDestroy(q);
+ N_VDestroy(d);
+ N_VDestroy(v);
+ return(NULL);
+ }
+
+ r = N_VCloneVectorArray(2, vec_tmpl);
+ if (r == NULL) {
+ N_VDestroy(r_star);
+ N_VDestroy(q);
+ N_VDestroy(d);
+ N_VDestroy(v);
+ N_VDestroy(p);
+ return(NULL);
+ }
+
+ u = N_VClone(vec_tmpl);
+ if (u == NULL) {
+ N_VDestroy(r_star);
+ N_VDestroy(q);
+ N_VDestroy(d);
+ N_VDestroy(v);
+ N_VDestroy(p);
+ N_VDestroyVectorArray(r, 2);
+ return(NULL);
+ }
+
+ vtemp1 = N_VClone(vec_tmpl);
+ if (vtemp1 == NULL) {
+ N_VDestroy(r_star);
+ N_VDestroy(q);
+ N_VDestroy(d);
+ N_VDestroy(v);
+ N_VDestroy(p);
+ N_VDestroyVectorArray(r, 2);
+ N_VDestroy(u);
+ return(NULL);
+ }
+
+ vtemp2 = N_VClone(vec_tmpl);
+ if (vtemp2 == NULL) {
+ N_VDestroy(r_star);
+ N_VDestroy(q);
+ N_VDestroy(d);
+ N_VDestroy(v);
+ N_VDestroy(p);
+ N_VDestroyVectorArray(r, 2);
+ N_VDestroy(u);
+ N_VDestroy(vtemp1);
+ return(NULL);
+ }
+
+ vtemp3 = N_VClone(vec_tmpl);
+ if (vtemp3 == NULL) {
+ N_VDestroy(r_star);
+ N_VDestroy(q);
+ N_VDestroy(d);
+ N_VDestroy(v);
+ N_VDestroy(p);
+ N_VDestroyVectorArray(r, 2);
+ N_VDestroy(u);
+ N_VDestroy(vtemp1);
+ N_VDestroy(vtemp2);
+ return(NULL);
+ }
+
+ /* Allocate memory for SptfqmrMemRec */
+ mem = NULL;
+ mem = (SptfqmrMem) malloc(sizeof(SptfqmrMemRec));
+ if (mem == NULL) {
+ N_VDestroy(r_star);
+ N_VDestroy(q);
+ N_VDestroy(d);
+ N_VDestroy(v);
+ N_VDestroy(p);
+ N_VDestroyVectorArray(r, 2);
+ N_VDestroy(u);
+ N_VDestroy(vtemp1);
+ N_VDestroy(vtemp2);
+ N_VDestroy(vtemp3);
+ return(NULL);
+ }
+
+ /* Intialize SptfqmrMemRec data structure */
+ mem->l_max = l_max;
+ mem->r_star = r_star;
+ mem->q = q;
+ mem->d = d;
+ mem->v = v;
+ mem->p = p;
+ mem->r = r;
+ mem->u = u;
+ mem->vtemp1 = vtemp1;
+ mem->vtemp2 = vtemp2;
+ mem->vtemp3 = vtemp3;
+
+ /* Return pointer to SPTFQMR memory block */
+ return(mem);
+}
+
+#define l_max (mem->l_max)
+#define r_star (mem->r_star)
+#define q_ (mem->q)
+#define d_ (mem->d)
+#define v_ (mem->v)
+#define p_ (mem->p)
+#define r_ (mem->r)
+#define u_ (mem->u)
+#define vtemp1 (mem->vtemp1)
+#define vtemp2 (mem->vtemp2)
+#define vtemp3 (mem->vtemp3)
+
+/*
+ * -----------------------------------------------------------------
+ * Function : SptfqmrSolve
+ * -----------------------------------------------------------------
+ */
+
+int SptfqmrSolve(SptfqmrMem mem, void *A_data, N_Vector x, N_Vector b,
+ int pretype, realtype delta, void *P_data, N_Vector sx,
+ N_Vector sb, ATimesFn atimes, PSolveFn psolve,
+ realtype *res_norm, int *nli, int *nps)
+{
+ 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;
+
+ /* Exit immediately if memory pointer is NULL */
+ if (mem == NULL) return(SPTFQMR_MEM_NULL);
+
+ temp_val = r_curr_norm = -ONE; /* Initialize to avoid compiler warnings */
+
+ *nli = *nps = 0; /* Initialize counters */
+ converged = FALSE; /* Initialize convergence flag */
+ b_ok = FALSE;
+
+ if ((pretype != PREC_LEFT) &&
+ (pretype != PREC_RIGHT) &&
+ (pretype != PREC_BOTH)) pretype = PREC_NONE;
+
+ preOnLeft = ((pretype == PREC_BOTH) || (pretype == PREC_LEFT));
+ preOnRight = ((pretype == PREC_BOTH) || (pretype == PREC_RIGHT));
+
+ 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)
+ return((ier < 0) ? SPTFQMR_ATIMES_FAIL_UNREC : SPTFQMR_ATIMES_FAIL_REC);
+ 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, PREC_LEFT);
+ (*nps)++;
+ if (ier != 0)
+ return((ier < 0) ? SPTFQMR_PSOLVE_FAIL_UNREC : SPTFQMR_PSOLVE_FAIL_REC);
+ }
+ 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 = RSqrt(rho[0]);
+ if (r_init_norm <= delta) return(SPTFQMR_SUCCESS);
+
+ /* 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, PREC_RIGHT);
+ (*nps)++;
+ if (ier != 0) return((ier < 0) ? SPTFQMR_PSOLVE_FAIL_UNREC : SPTFQMR_PSOLVE_FAIL_REC);
+ }
+ ier = atimes(A_data, vtemp1, v_);
+ if (ier != 0)
+ return((ier < 0) ? SPTFQMR_ATIMES_FAIL_UNREC : SPTFQMR_ATIMES_FAIL_REC);
+ if (preOnLeft) {
+ ier = psolve(P_data, v_, vtemp1, PREC_LEFT);
+ (*nps)++;
+ if (ier != 0) return((ier < 0) ? SPTFQMR_PSOLVE_FAIL_UNREC : SPTFQMR_PSOLVE_FAIL_REC);
+ }
+ 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], PREC_RIGHT);
+ (*nps)++;
+ if (ier != 0) return((ier < 0) ? SPTFQMR_PSOLVE_FAIL_UNREC : SPTFQMR_PSOLVE_FAIL_REC);
+ }
+ ier = atimes(A_data, r_[1], vtemp1);
+ 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);
+ (*nps)++;
+ if (ier != 0) return((ier < 0) ? SPTFQMR_PSOLVE_FAIL_UNREC : SPTFQMR_PSOLVE_FAIL_REC);
+ }
+ 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 = RSqrt(N_VDotProd(r_[1], r_[1]));
+ omega = RSqrt(RSqrt(N_VDotProd(r_[0], r_[0]))*temp_val);
+ N_VLinearSum(ONE, u_, SQR(v_bar)*eta/alpha, d_, d_);
+ }
+ else {
+ omega = temp_val;
+ N_VLinearSum(ONE, q_, SQR(v_bar)*eta/alpha, d_, d_);
+ }
+
+ /* v_bar = omega/tau */
+ v_bar = omega/tau;
+
+ /* c = (1+v_bar^2)^(-1/2) */
+ c = ONE / RSqrt(ONE+SQR(v_bar));
+
+ /* tau = tau*v_bar*c */
+ tau = tau*v_bar*c;
+
+ /* eta = c^2*alpha */
+ eta = SQR(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*RSqrt(m+1);
+
+ /* Exit inner loop if iteration has converged based upon approximation
+ to norm of current residual */
+ if (r_curr_norm <= delta) {
+ converged = TRUE;
+ 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, PREC_RIGHT);
+ (*nps)++;
+ if (ier != 0) return((ier < 0) ? SPTFQMR_PSOLVE_FAIL_UNREC : SPTFQMR_PSOLVE_FAIL_UNREC);
+ N_VScale(ONE, vtemp2, vtemp1);
+ }
+ ier = atimes(A_data, vtemp1, vtemp2);
+ if (ier != 0)
+ return((ier < 0) ? SPTFQMR_ATIMES_FAIL_UNREC : SPTFQMR_ATIMES_FAIL_REC);
+ if (preOnLeft) {
+ ier = psolve(P_data, vtemp2, vtemp1, PREC_LEFT);
+ (*nps)++;
+ if (ier != 0) return((ier < 0) ? SPTFQMR_PSOLVE_FAIL_UNREC : SPTFQMR_PSOLVE_FAIL_REC);
+ }
+ 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 = TRUE;
+ if (preOnLeft) {
+ ier = psolve(P_data, b, vtemp3, PREC_LEFT);
+ (*nps)++;
+ if (ier != 0) return((ier < 0) ? SPTFQMR_PSOLVE_FAIL_UNREC : SPTFQMR_PSOLVE_FAIL_REC);
+ }
+ 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 = RSqrt(N_VDotProd(vtemp1, vtemp1));
+
+ /* Exit inner loop if inequality condition is satisfied
+ (meaning exit if we have converged) */
+ if (r_curr_norm <= delta) {
+ converged = TRUE;
+ break;
+ }
+
+ }
+
+ } /* END inner loop */
+
+ /* If converged, then exit outer loop as well */
+ if (converged == TRUE) 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_, SQR(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, PREC_RIGHT);
+ (*nps)++;
+ if (ier != 0) return((ier < 0) ? SPTFQMR_PSOLVE_FAIL_UNREC : SPTFQMR_PSOLVE_FAIL_REC);
+ }
+ ier = atimes(A_data, vtemp1, v_);
+ if (ier != 0)
+ return((ier < 0) ? SPTFQMR_ATIMES_FAIL_UNREC : SPTFQMR_ATIMES_FAIL_REC);
+ if (preOnLeft) {
+ ier = psolve(P_data, v_, vtemp1, PREC_LEFT);
+ (*nps)++;
+ if (ier != 0) return((ier < 0) ? SPTFQMR_PSOLVE_FAIL_UNREC : SPTFQMR_PSOLVE_FAIL_REC);
+ }
+ 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 == TRUE) || (r_curr_norm < r_init_norm)) {
+ if (scale_x) N_VDiv(x, sx, x);
+ if (preOnRight) {
+ ier = psolve(P_data, x, vtemp1, 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);
+ else return(SPTFQMR_RES_REDUCED);
+ }
+ /* Otherwise, return error code */
+ else return(SPTFQMR_CONV_FAIL);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * Function : SptfqmrFree
+ * -----------------------------------------------------------------
+ */
+
+void SptfqmrFree(SptfqmrMem mem)
+{
+
+ if (mem == NULL) return;
+
+ N_VDestroy(r_star);
+ N_VDestroy(q_);
+ N_VDestroy(d_);
+ N_VDestroy(v_);
+ N_VDestroy(p_);
+ N_VDestroyVectorArray(r_, 2);
+ N_VDestroy(u_);
+ N_VDestroy(vtemp1);
+ N_VDestroy(vtemp2);
+ N_VDestroy(vtemp3);
+
+ free(mem); mem = NULL;
+}
diff --git a/sundialsTB/Contents.m b/sundialsTB/Contents.m
new file mode 100644
index 0000000..6076ead
--- /dev/null
+++ b/sundialsTB/Contents.m
@@ -0,0 +1,6 @@
+% sundialsTB v.2.4.0 - Matlab interfaces to SUNDIALS solvers
+%
+% sundialsTB provides interfaces to the CVODES, IDAS, and KINSOL
+% solvers in SUNDIALS.
+%
+% See also cvodes, idas, kinsol, nvector, putils
diff --git a/debian/copyright b/sundialsTB/LICENSE
similarity index 81%
rename from debian/copyright
rename to sundialsTB/LICENSE
index 98cde97..9993068 100644
--- a/debian/copyright
+++ b/sundialsTB/LICENSE
@@ -1,22 +1,11 @@
-This package was debianized by Andrey Romanenko <andrey at enginum.com> on
-Wed, 20 Apr 2005 12:01:42 +0100.
-
-It was downloaded from http://www.llnl.gov/CASC/sundials/
-
-Authors: Peter Brown, Aaron Collier, Keith Grant, Alan Hindmarsh,
- Steve Lee, Radu Serban, Dan Shumaker, Carol Woodward
-
-Copyright Holder: The Regents of the University of California.
-
-License:
-
-Copyright (c) 2002, The Regents of the University of California.
-Produced at the Lawrence Livermore National Laboratory
-Written by A.C. Hindmarsh and R. Serban.
-UCRL-CODE-155950
-All rights reserved.
-
-This file is part of CVODES v2.1.0.
+Copyright (c) 2005, The Regents of the University of California.
+Produced at the Lawrence Livermore National Laboratory.
+Written by Radu Serban, radu at llnl.gov
+
+UCRL-CODE-155978
+All rights reserved.
+
+This file is part of sundialsTB.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
diff --git a/sundialsTB/README b/sundialsTB/README
new file mode 100644
index 0000000..19b3fda
--- /dev/null
+++ b/sundialsTB/README
@@ -0,0 +1,219 @@
+ sundialsTB
+ A MATLAB interface to SUNDIALS
+ Release 2.5.0, March 2012
+
+ Radu Serban
+ Center for Applied Scientific Computing, LLNL
+
+
+sundialsTB provides a MATLAB interface to the following SUNDIALS solvers:
+ CVODES: a variable-order, variable-step ODE solver with sensitivity
+ analysis capabilities
+ IDAS: a variable-order, variable-sttp DAE and implicit ODE solver
+ KINSOL: a nonlinear system solver
+
+The core of each MATLAB interface in sundialsTB is a single mex file
+which interfaces to the various user-callable functions for that solver.
+However, this mex file should not be called directly, but rather through
+the user-callable functions provided for each MATLAB interface.
+
+The distribution file also contains a user guide, as well as several examples.
+
+sundialsTB v. 2.5.0 requires SUNDIALS v 2.5.0 and, optionally (for parallel
+support), MPITB with LAM 7.1.1 for MPI-2 features.
+
+SUNDIALS: http://www.llnl.gov/CASC/sundials
+MPITB: http://atc.ugr.es/javier-bin/mpitb_eng
+LAM: http://www.lam-mpi.org/
+
+
+A. Documentation
+----------------
+
+/sundialsTB/doc contains a PDF file for the sundialsTB User Guide.
+
+
+B. Installation
+---------------
+
+B.1. Compilation and installation of sundialsTB
+
+As of version 2.3.0, sundialsTB is distributed only with the complete SUNDIALS
+package and, on *nix systems (or under cygwin in Windows), the Matlab toolbox
+can be configured, built, and installed using the main SUNDIALS configure script.
+For details see the SUNDIALS file INSTALL_NOTES.
+
+For systems that do not support configure scripts (or if the configure script
+fails to configure sundialsTB), we provide a Matlab script (install_STB.m) which
+can be used to build and install sundialsTB from within Matlab. In the sequel,
+we assume that the SUNDIALS package was unpacked under the directory 'srcdir'.
+The sundialsTB files are therefore in 'srcdir'/sundialsTB.
+
+To facilitate the compilation of sundialsTB on platforms that do not have
+a make system, we rely on Matlab's mex command. Compilation of sundialsTB
+is done by running from under Matlab the install_STB.m script which is
+present in the sundialsTB top directory.
+
+1. Launch matlab in sundialsTB:
+ % cd 'srcdir'/sundialsTB
+ % matlab
+
+2. Run the install_STB matlab script.
+
+ Note that parallel support will be compiled into the MEX files only if
+ ALL of the following conditions are met:
+ - $LAMHOME is defined
+ - $MPITB_ROOT is defined
+ - 'srcdir'/src/nvec_par exists
+
+ After the MEX files are generated, you will be asked if you wish to install
+ the sundialsTB toolbox. If you answer yes, you will be then asked for the
+ installation directory (called in the sequel 'instdir').
+ To install sundialsTB for all Matlab users (not usual), assuming Matlab is
+ installed under /usr/local/matlab7, specify
+ 'instdir' = /usr/local/matlab7/toolbox
+ To install sundialsTB for just one user (usual configuration), install
+ sundialsTB under a directory of your choice (typically under your 'matlab'
+ working directory). In other words, specify
+ 'instdir' = /home/user/matlab
+
+
+B.2. Configuring Matlab's startup
+
+After a successful installation, a sundialsTB.m startup script is generated
+in 'instdir'/sundialsTB. This file must be called by Matlab at initialization.
+
+If sundialsTB was installed for all Matlab users (not usual), add the sundialsTB
+startup to the system-wide startup file (by linking or copying):
+
+ % cd /usr/local/matlab7/toolbox/local
+ % ln -s ../sundialsTB/startup_STB.m .
+
+ and add these lines to your original local startup.m
+
+ % SUNDIALS Toolbox startup M-file, if it exists.
+ if exist('startup_STB','file')
+ startup_STB
+ end
+
+If sundialsTB was installed for just one user (usual configuration) and
+assuming you do not need to keep any previously existing startup.m, link
+or copy the startup_STB.m script to your working 'matlab' directory:
+
+ % cd ~/matlab
+ % ln -s sundialsTB/startup_STB.m startup.m
+
+If you already have a startup.m, use the method described above, first linking
+(or copying) startup_STB.m to the destination subdir and then editing
+~/matlab/startup.m to run startup_STB.m
+
+B.3. Testing the installation
+
+If everything went fine, you should now be able to try one of the CVODES, IDAS,
+or KINSOL examples (in matlab, type 'help cvodes', 'help idas', or 'help kinsol'
+to see a list of all examples available). For example, cd to the CVODES serial
+example directory:
+ % cd 'instdir'/sundialsTB/cvode/examples_ser
+and then launch matlab and execute cvdx.
+
+
+C. References
+-------------
+
+[1] R. Serban, "sundialsTB, a MATLAB Interface to SUNDIALS",
+ LLNL technical report UCRL-SM-212121, May 2005.
+
+[2] A. C. Hindmarsh, P. N. Brown, K. E. Grant, S. L. Lee, R. Serban,
+ D. E. Shumaker, and C. S. Woodward, "SUNDIALS, Suite of Nonlinear and
+ Differential/Algebraic Equation Solvers," ACM Trans. Math. Softw.,
+ 31(3), pp. 363-396, 2005.
+
+
+D. Releases
+-----------
+
+v. 2.5.0 - Mar. 2012
+v. 2.4.0 - May 2009
+v. 2.3.0 - Nov. 2006
+v. 2.2.0 - Mar. 2006
+v. 2.1.1 - May. 2005 (first sundialsTB release)
+
+E. Revision History
+-------------------
+
+v. 2.4.0 (May 2009) ---> v. 2.5.0 (Mar. 2012)
+---------------------------------------------------------
+
+- Minor bug fixes:
+ - in kimOpts.c, fixed lines setting etachoice.
+ - in cvm.c and idm.c, fixed size of rootsfound array; added lines to free
+ rootsfound and ckpnt arrays when done using each.
+ - in all .c files, changed mxCreateScalarDouble to mxCreateDoubleScalar.
+ - in all .c files, changed problem sizes, bandwidths, etc. from type int
+ to type long int.
+
+
+- Minor fixes to documentation
+
+v. 2.3.0 (Nov. 2006) ---> v. 2.4.0 (May 2009)
+---------------------------------------------------------
+
+- New features
+ - Updated IDAS monitoring functionality.
+ - Added functionality to reinitialize adjoint module.
+ - Added functions to allow changing optional inputs during integration.
+ - Added option to disable error message output.
+
+- Bug fixes
+ - Minor fixes to installation files.
+ - Bug fix in argument order in IDAS dense and band Jacobian interfaces.
+ - Fixed bug in CVODES reinitialization.
+ - Fixed a bug in initialization of backward quadratures in IDAS.
+
+- Changes to user interface
+ - Updated interfaces to linear solvers corresponding to DLS/SPILS split.
+ - Added several missing wrapper functions.
+ - Changed CVODES API to require LMM and ITER.
+ - Added return flags to all interface functions.
+
+-Other
+ - Added CVODES examples showing integration over a discontinuity.
+ - Added two KINSOL examples.
+ - Relocated user function type files to function_types subdirectories.
+ - Reorganized IDAS files to expose Sensitivity Analysis abilities.
+
+v. 2.2.0 (Mar. 2006) ---> v. 2.3.0 (Nov. 2006)
+---------------------------------------------------------
+
+- New features
+ - added IDAS module, a MEX interface to the SUNDIALS IDA integrator.
+ - startup_STB.m is automatically created from a template.
+
+- Bug fixes
+ - install_STB.m was modified to be more robust w.r.t. file naming
+ conventions omn different platforms.
+
+- Changes to user interface
+ - updated to reflect changes to the SUNDIALS libraries in v.2.3.0
+
+v. 2.1.1 (May. 2005) ---> v. 2.2.0 (Mar. 2006)
+---------------------------------------------------------
+
+- New features
+ - modified installation procedure to use a Matlab script
+ - added sample Matlab startup file
+ - expanded CVodeMonitor
+ - added interface to KINSOL's performance monitoring function
+ ('Verbose' option to KINSetOptions)
+
+- Bug fixes
+ - fixed bug in interface to quadrature integration which was causing
+ a segmentatin violation when monitoring was turned on.
+
+- Changes to user interface
+ - updated to reflect changes to the SUNDIALS libraries in v.2.2.0
+ - changed the interface for sensitivity analysis (both forward and
+ adjoint) to follow more closely the CVODES calling sequence
+ - optional inputs for forward sensitivity analysis are now provided
+ through a separate function, CVodeSetFSAOptions
+ - removed NVM mex interface
\ No newline at end of file
diff --git a/sundialsTB/cvodes/CVode.m b/sundialsTB/cvodes/CVode.m
new file mode 100644
index 0000000..777e5bd
--- /dev/null
+++ b/sundialsTB/cvodes/CVode.m
@@ -0,0 +1,55 @@
+function [varargout] = CVode(tout, itask)
+%CVode integrates the ODE.
+%
+% Usage: [STATUS, T, Y] = CVode ( TOUT, ITASK )
+% [STATUS, T, Y, YS] = CVode ( TOUT, ITASK )
+% [STATUS, T, Y, YQ] = CVode (TOUT, ITASK )
+% [STATUS, T, Y, YQ, YS] = CVode ( TOUT, ITASK )
+%
+% If ITASK is 'Normal', then the solver integrates from its current internal
+% T value to a point at or beyond TOUT, then interpolates to T = TOUT and returns
+% Y(TOUT). If ITASK is 'OneStep', then the solver takes one internal time step
+% and returns in Y the solution at the new internal time. In this case, TOUT
+% is used only during the first call to CVode to determine the direction of
+% integration and the rough scale of the problem. In either case, the time
+% reached by the solver is returned in T.
+%
+% If quadratures were computed (see CVodeQuadInit), CVode will return their
+% values at T in the vector YQ.
+%
+% If sensitivity calculations were enabled (see CVodeSensInit), CVode will
+% return their values at T in the matrix YS. Each row in the matrix YS
+% represents the sensitivity vector with respect to one of the problem parameters.
+%
+% In ITASK =' Normal' mode, to obtain solutions at specific times T0,T1,...,TFINAL
+% (all increasing or all decreasing) use TOUT = [T0 T1 ... TFINAL]. In this case
+% the output arguments Y and YQ are matrices, each column representing the solution
+% vector at the corresponding time returned in the vector T. If computed, the
+% sensitivities are eturned in the 3-dimensional array YS, with YS(:,:,I) representing
+% the sensitivity vectors at the time T(I).
+%
+% On return, STATUS is one of the following:
+% 0: successful CVode return.
+% 1: CVode succeded and returned at tstop.
+% 2: CVode succeeded and found one or more roots.
+% -1: an error occurred (see printed message).
+%
+% See also CVodeSetOptions, CVodeGetStats
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2007, The Regents of the University of California.
+% $Revision: 1.7 $Date: 2011/06/01 22:06:42 $
+
+mode = 20;
+
+if nargin ~= 2
+ error('Wrong number of input arguments');
+end
+
+if nargout < 3 || nargout > 5
+ error('Wrong number of output arguments');
+end
+
+varargout = cell (nargout, 1);
+
+[varargout{:}] = cvm(mode,tout,itask);
diff --git a/sundialsTB/cvodes/CVodeAdjInit.m b/sundialsTB/cvodes/CVodeAdjInit.m
new file mode 100644
index 0000000..06f0045
--- /dev/null
+++ b/sundialsTB/cvodes/CVodeAdjInit.m
@@ -0,0 +1,23 @@
+function status = CVodeAdjInit(steps, interp)
+%CVodeAdjInit allocates and initializes memory for ASA with CVODES.
+%
+% Usage: CVodeAdjInit(STEPS, INTEPR)
+%
+% STEPS specifies the (maximum) number of integration steps between two
+% consecutive check points.
+% INTERP Specifies the type of interpolation used for estimating the forward
+% solution during the backward integration phase. INTERP should be
+% 'Hermite', indicating cubic Hermite interpolation, or 'Polynomial',
+% indicating variable order polynomial interpolation.
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2007, The Regents of the University of California.
+% $Revision: 1.2 $Date: 2007/12/05 21:58:17 $
+
+mode = 4;
+
+if nargin ~= 2
+ error('Wrong number of input arguments');
+end
+
+status = cvm(mode,steps,interp);
diff --git a/sundialsTB/cvodes/CVodeAdjReInit.m b/sundialsTB/cvodes/CVodeAdjReInit.m
new file mode 100644
index 0000000..1f72dce
--- /dev/null
+++ b/sundialsTB/cvodes/CVodeAdjReInit.m
@@ -0,0 +1,13 @@
+function status = CVodeAdjReInit()
+%CVodeAdjReInit re-initializes memory for ASA with CVODES.
+%
+% Usage: CVodeAdjReInit
+%
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2007, The Regents of the University of California.
+% $Revision: 1.2 $Date: 2007/12/05 21:58:17 $
+
+mode = 14;
+
+status = cvm(mode);
diff --git a/sundialsTB/cvodes/CVodeB.m b/sundialsTB/cvodes/CVodeB.m
new file mode 100644
index 0000000..9bea87b
--- /dev/null
+++ b/sundialsTB/cvodes/CVodeB.m
@@ -0,0 +1,49 @@
+function [varargout] = CVodeB(tout,itask)
+%CVodeB integrates all backwards ODEs currently defined.
+%
+% Usage: [STATUS, T, YB] = CVodeB ( TOUT, ITASK )
+% [STATUS, T, YB, YQB] = CVodeB ( TOUT, ITASK )
+%
+% If ITASK is 'Normal', then the solver integrates from its current internal
+% T value to a point at or beyond TOUT, then interpolates to T = TOUT and returns
+% YB(TOUT). If ITASK is 'OneStep', then the solver takes one internal time step
+% and returns in YB the solution at the new internal time. In this case, TOUT
+% is used only during the first call to CVodeB to determine the direction of
+% integration and the rough scale of the problem. In either case, the time
+% reached by the solver is returned in T.
+%
+% If quadratures were computed (see CVodeQuadInitB), CVodeB will return their
+% values at T in the vector YQB.
+%
+% In ITASK =' Normal' mode, to obtain solutions at specific times T0,T1,...,TFINAL
+% (all increasing or all decreasing) use TOUT = [T0 T1 ... TFINAL]. In this case
+% the output arguments YB and YQB are matrices, each column representing the solution
+% vector at the corresponding time returned in the vector T.
+%
+% If more than one backward problem was defined, the return arguments are cell
+% arrays, with T{IDXB}, YB{IDXB}, and YQB{IDXB} corresponding to the backward
+% problem with index IDXB (as returned by CVodeInitB).
+%
+% On return, STATUS is one of the following:
+% 0: successful CVodeB return.
+% 1: CVodeB succeded and return at a tstop value (internally set).
+% -1: an error occurred (see printed message).
+%
+% See also CVodeSetOptions, CVodeGetStatsB
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2007, The Regents of the University of California.
+% $Revision: 1.7 $Date: 2011/06/01 22:30:55 $
+
+mode = 21;
+
+if nargin ~= 2
+ error('Wrong number of input arguments');
+end
+
+if nargout < 3 || nargout > 4
+ error('Wrong number of output arguments');
+end
+
+varargout = cell (nargout, 1);
+[varargout{:}] = cvm(mode,tout,itask);
diff --git a/sundialsTB/cvodes/CVodeFree.m b/sundialsTB/cvodes/CVodeFree.m
new file mode 100644
index 0000000..7648eca
--- /dev/null
+++ b/sundialsTB/cvodes/CVodeFree.m
@@ -0,0 +1,11 @@
+function CVodeFree()
+%CVodeFree deallocates memory for the CVODES solver.
+%
+% Usage: CVodeFree
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2007, The Regents of the University of California.
+% $Revision: 1.4 $Date: 2007/05/11 18:51:31 $
+
+mode = 40;
+cvm(mode);
diff --git a/sundialsTB/cvodes/CVodeGet.m b/sundialsTB/cvodes/CVodeGet.m
new file mode 100644
index 0000000..a83e88f
--- /dev/null
+++ b/sundialsTB/cvodes/CVodeGet.m
@@ -0,0 +1,36 @@
+function [output, status] = CVodeGet(key, varargin)
+%CVodeGet extracts data from the CVODES solver memory.
+%
+% Usage: RET = CVodeGet ( KEY [, P1 [, P2] ... ])
+%
+% CVodeGet returns internal CVODES information based on KEY. For some values
+% of KEY, additional arguments may be required and/or more than one output is
+% returned.
+%
+% KEY is a string and should be one of:
+% o DerivSolution - Returns a vector containing the K-th order derivative
+% of the solution at time T. The time T and order K must be passed through
+% the input arguments P1 and P2, respectively:
+% DKY = CVodeGet('DerivSolution', T, K)
+% o ErrorWeights - Returns a vector containing the current error weights.
+% EWT = CVodeGet('ErrorWeights')
+% o CheckPointsInfo - Returns an array of structures with check point information.
+% CK = CVodeGet('CheckPointInfo)
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2007, The Regents of the University of California.
+% $Revision: 1.6 $Date: 2007/12/05 21:58:17 $
+
+mode = 32;
+
+if strcmp(key, 'DerivSolution')
+ t = varargin{1};
+ k = varargin{2};
+ [output, status] = cvm(mode, 1, t, k);
+elseif strcmp(key, 'ErrorWeights')
+ [output, status] = cvm(mode, 2);
+elseif strcmp(key, 'CheckPointsInfo')
+ [output, status] = cvm(mode, 4);
+else
+ error('CVodeGet:: Unrecognized key');
+end
\ No newline at end of file
diff --git a/sundialsTB/cvodes/CVodeGetStats.m b/sundialsTB/cvodes/CVodeGetStats.m
new file mode 100644
index 0000000..9ef850b
--- /dev/null
+++ b/sundialsTB/cvodes/CVodeGetStats.m
@@ -0,0 +1,86 @@
+function [si, status] = CVodeGetStats()
+%CVodeGetStats returns run statistics for the CVODES solver.
+%
+% Usage: STATS = CVodeGetStats
+%
+%Fields in the structure STATS
+%
+%o nst - number of integration steps
+%o nfe - number of right-hand side function evaluations
+%o nsetups - number of linear solver setup calls
+%o netf - number of error test failures
+%o nni - number of nonlinear solver iterations
+%o ncfn - number of convergence test failures
+%o qlast - last method order used
+%o qcur - current method order
+%o h0used - actual initial step size used
+%o hlast - last step size used
+%o hcur - current step size
+%o tcur - current time reached by the integrator
+%o RootInfo - strucutre with rootfinding information
+%o QuadInfo - structure with quadrature integration statistics
+%o LSInfo - structure with linear solver statistics
+%o FSAInfo - structure with forward sensitivity solver statistics
+%
+%If rootfinding was requested, the structure RootInfo has the following fields
+%
+%o nge - number of calls to the rootfinding function
+%o roots - array of integers (a value of 1 in the i-th component means that the
+% i-th rootfinding function has a root (upon a return with status=2 from
+% CVode).
+%
+%If quadratures were present, the structure QuadInfo has the following fields
+%
+%o nfQe - number of quadrature integrand function evaluations
+%o netfQ - number of error test failures for quadrature variables
+%
+%The structure LSinfo has different fields, depending on the linear solver used.
+%
+% Fields in LSinfo for the 'Dense' linear solver
+%
+%o name - 'Dense'
+%o njeD - number of Jacobian evaluations
+%o nfeD - number of right-hand side function evaluations for difference-quotient
+% Jacobian approximation
+%
+% Fields in LSinfo for the 'Diag' linear solver
+%
+%o name - 'Diag'
+%o nfeDI - number of right-hand side function evaluations for difference-quotient
+% Jacobian approximation
+%
+% Fields in LSinfo for the 'Band' linear solver
+%
+%o name - 'Band'
+%o njeB - number of Jacobian evaluations
+%o nfeB - number of right-hand side function evaluations for difference-quotient
+% Jacobian approximation
+%
+% Fields in LSinfo for the 'GMRES' and 'BiCGStab' linear solvers
+%
+%o name - 'GMRES' or 'BiCGStab'
+%o nli - number of linear solver iterations
+%o npe - number of preconditioner setups
+%o nps - number of preconditioner solve function calls
+%o ncfl - number of linear system convergence test failures
+%o njeSG - number of Jacobian-vector product evaluations
+%o nfeSG - number of right-hand side function evaluations for difference-quotient
+% Jacobian-vector product approximation
+%
+%If forward sensitivities were computed, the structure FSAInfo has the
+%following fields
+%
+%o nfSe - number of sensitivity right-hand side evaluations
+%o nfeS - number of right-hand side evaluations for difference-quotient
+% sensitivity right-hand side approximation
+%o nsetupsS - number of linear solver setups triggered by sensitivity variables
+%o netfS - number of error test failures for sensitivity variables
+%o nniS - number of nonlinear solver iterations for sensitivity variables
+%o ncfnS - number of convergence test failures due to sensitivity variables
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2007, The Regents of the University of California.
+% $Revision: 1.5 $Date: 2007/12/05 21:58:17 $
+
+mode = 30;
+[si, status] = cvm(mode);
diff --git a/sundialsTB/cvodes/CVodeGetStatsB.m b/sundialsTB/cvodes/CVodeGetStatsB.m
new file mode 100644
index 0000000..7b28595
--- /dev/null
+++ b/sundialsTB/cvodes/CVodeGetStatsB.m
@@ -0,0 +1,76 @@
+function [si, status] = CVodeGetStatsB(idxB)
+%CVodeGetStatsB returns run statistics for the backward CVODES solver.
+%
+% Usage: STATS = CVodeGetStatsB( IDXB )
+%
+% IDXB is the index of the backward problem, returned by
+% CVodeInitB.
+%
+%Fields in the structure STATS
+%
+%o nst - number of integration steps
+%o nfe - number of right-hand side function evaluations
+%o nsetups - number of linear solver setup calls
+%o netf - number of error test failures
+%o nni - number of nonlinear solver iterations
+%o ncfn - number of convergence test failures
+%o qlast - last method order used
+%o qcur - current method order
+%o h0used - actual initial step size used
+%o hlast - last step size used
+%o hcur - current step size
+%o tcur - current time reached by the integrator
+%o QuadInfo - structure with quadrature integration statistics
+%o LSInfo - structure with linear solver statistics
+%
+%The structure LSinfo has different fields, depending on the linear solver used.
+%
+%If quadratures were present, the structure QuadInfo has the following fields
+%
+%o nfQe - number of quadrature integrand function evaluations
+%o netfQ - number of error test failures for quadrature variables
+%
+% Fields in LSinfo for the 'Dense' linear solver
+%
+%o name - 'Dense'
+%o njeD - number of Jacobian evaluations
+%o nfeD - number of right-hand side function evaluations for difference-quotient
+% Jacobian approximation
+%
+% Fields in LSinfo for the 'Diag' linear solver
+%
+%o name - 'Diag'
+%o nfeDI - number of right-hand side function evaluations for difference-quotient
+% Jacobian approximation
+%
+% Fields in LSinfo for the 'Band' linear solver
+%
+%o name - 'Band'
+%o njeB - number of Jacobian evaluations
+%o nfeB - number of right-hand side function evaluations for difference-quotient
+% Jacobian approximation
+%
+% Fields in LSinfo for the 'GMRES' and 'BiCGStab' linear solvers
+%
+%o name - 'GMRES' or 'BiCGStab'
+%o nli - number of linear solver iterations
+%o npe - number of preconditioner setups
+%o nps - number of preconditioner solve function calls
+%o ncfl - number of linear system convergence test failures
+%o njeSG - number of Jacobian-vector product evaluations
+%o nfeSG - number of right-hand side function evaluations for difference-quotient
+% Jacobian-vector product approximation
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2007, The Regents of the University of California.
+% $Revision: 1.5 $Date: 2007/12/05 21:58:17 $
+
+mode = 31;
+
+if nargin ~= 1
+ error('Wrong number of input arguments');
+end
+
+idxB = idxB-1;
+[si, status] = cvm(mode, idxB);
+
diff --git a/sundialsTB/cvodes/CVodeInit.m b/sundialsTB/cvodes/CVodeInit.m
new file mode 100644
index 0000000..88128af
--- /dev/null
+++ b/sundialsTB/cvodes/CVodeInit.m
@@ -0,0 +1,42 @@
+function status = CVodeInit(fct, lmm, nls, t0, y0, options)
+%CVodeInit allocates and initializes memory for CVODES.
+%
+% Usage: CVodeInit ( ODEFUN, LMM, NLS, T0, Y0 [, OPTIONS ] )
+%
+% ODEFUN is a function defining the ODE right-hand side: y' = f(t,y).
+% This function must return a vector containing the current
+% value of the righ-hand side.
+% LMM is the Linear Multistep Method ('Adams' or 'BDF')
+% NLS is the type of nonlinear solver used ('Functional' or 'Newton')
+% T0 is the initial value of t.
+% Y0 is the initial condition vector y(t0).
+% OPTIONS is an (optional) set of integration options, created with
+% the CVodeSetOptions function.
+%
+% See also: CVodeSetOptions, CVRhsFn
+%
+% NOTES:
+% 1) The 'Functional' nonlinear solver is best suited for non-stiff
+% problems, in conjunction with the 'Adams' linear multistep method,
+% while 'Newton' is better suited for stiff problems, using the 'BDF'
+% method.
+% 2) When using the 'Newton' nonlinear solver, a linear solver is also
+% required. The default one is 'Dense', indicating the use of direct
+% dense linear algebra (LU factorization). A different linear solver
+% can be specified through the option 'LinearSolver' to CVodeSetOptions.
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2007, The Regents of the University of California.
+% $Revision: 1.4 $Date: 2007/12/05 21:58:17 $
+
+mode = 1;
+
+if nargin < 5
+ error('Too few input arguments');
+end
+
+if nargin < 6
+ options = [];
+end
+
+status = cvm(mode, fct, lmm, nls, t0, y0, options);
diff --git a/sundialsTB/cvodes/CVodeInitB.m b/sundialsTB/cvodes/CVodeInitB.m
new file mode 100644
index 0000000..59110db
--- /dev/null
+++ b/sundialsTB/cvodes/CVodeInitB.m
@@ -0,0 +1,37 @@
+function [idxB, status] = CVodeInitB(fctB, lmmB, nlsB, tB0, yB0, optionsB)
+%CVodeInitB allocates and initializes backward memory for CVODES.
+%
+% Usage: IDXB = CVodeInitB ( FCTB, LMMB, NLSB, TB0, YB0 [, OPTIONSB] )
+%
+% FCTB is a function defining the adjoint ODE right-hand side.
+% This function must return a vector containing the current
+% value of the adjoint ODE righ-hand side.
+% LMMB is the Linear Multistep Method ('Adams' or 'BDF')
+% NLSB is the type of nonlinear solver used ('Functional' or 'Newton')
+% TB0 is the final value of t.
+% YB0 is the final condition vector yB(tB0).
+% OPTIONSB is an (optional) set of integration options, created with
+% the CVodeSetOptions function.
+%
+% CVodeInitB returns the index IDXB associated with this backward
+% problem. This index must be passed as an argument to any subsequent
+% functions related to this backward problem.
+%
+% See also: CVodeSetOptions, CVodeInit, CVRhsFnB
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2007, The Regents of the University of California.
+% $Revision: 1.3 $Date: 2007/12/05 21:58:18 $
+
+mode = 5;
+
+if nargin < 5
+ error('Too few input arguments');
+end
+
+if nargin < 6
+ optionsB = [];
+end
+
+[idxB, status] = cvm(mode, fctB, lmmB, nlsB, tB0, yB0, optionsB);
+idxB = idxB+1;
diff --git a/sundialsTB/cvodes/CVodeMonitor.m b/sundialsTB/cvodes/CVodeMonitor.m
new file mode 100644
index 0000000..edef5bf
--- /dev/null
+++ b/sundialsTB/cvodes/CVodeMonitor.m
@@ -0,0 +1,796 @@
+function [new_data] = CVodeMonitor(call, T, Y, YQ, YS, data)
+%CVodeMonitor is the default CVODES monitoring function.
+% To use it, set the Monitor property in CVodeSetOptions to
+% 'CVodeMonitor' or to @CVodeMonitor and 'MonitorData' to mondata
+% (defined as a structure).
+%
+% With default settings, this function plots the evolution of the step
+% size, method order, and various counters.
+%
+% Various properties can be changed from their default values by passing
+% to CVodeSetOptions, through the property 'MonitorData', a structure
+% MONDATA with any of the following fields. If a field is not defined,
+% the corresponding default value is used.
+%
+% Fields in MONDATA structure:
+% o stats [ {true} | false ]
+% If true, report the evolution of the step size and method order.
+% o cntr [ {true} | false ]
+% If true, report the evolution of the following counters:
+% nst, nfe, nni, netf, ncfn (see CVodeGetStats)
+% o mode [ {'graphical'} | 'text' | 'both' ]
+% In graphical mode, plot the evolutions of the above quantities.
+% In text mode, print a table.
+% o sol [ true | {false} ]
+% If true, plot solution components.
+% o sensi [ true | {false} ]
+% If true and if FSA is enabled, plot sensitivity components.
+% o select [ array of integers ]
+% To plot only particular solution components, specify their indeces in
+% the field select. If not defined, but sol=true, all components are plotted.
+% o updt [ integer | {50} ]
+% Update frequency. Data is posted in blocks of dimension n.
+% o skip [ integer | {0} ]
+% Number of integrations steps to skip in collecting data to post.
+% o post [ {true} | false ]
+% If false, disable all posting. This option is necessary to disable
+% monitoring on some processors when running in parallel.
+%
+% See also CVodeSetOptions, CVMonitorFn
+%
+% NOTES:
+% 1. The argument mondata is REQUIRED. Even if only the default options
+% are desired, set mondata=struct; and pass it to CVodeSetOptions.
+% 2. The yQ argument is currently ignored.
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2007, The Regents of the University of California.
+% $Revision: 1.6 $Date: 2007/08/21 17:42:38 $
+
+if (nargin ~= 6)
+ error('Monitor data not defined.');
+end
+
+new_data = [];
+
+if call == 0
+
+% Initialize unspecified fields to default values.
+ data = initialize_data(data);
+
+% Open figure windows
+ if data.post
+
+ if data.grph
+ if data.stats | data.cntr
+ data.hfg = figure;
+ end
+% Number of subplots in figure hfg
+ if data.stats
+ data.npg = data.npg + 2;
+ end
+ if data.cntr
+ data.npg = data.npg + 1;
+ end
+ end
+
+ if data.text
+ if data.cntr | data.stats
+ data.hft = figure;
+ end
+ end
+
+ if data.sol | data.sensi
+ data.hfs = figure;
+ end
+
+ end
+
+% Initialize other private data
+ data.i = 0;
+ data.n = 1;
+ data.t = zeros(1,data.updt);
+ if data.stats
+ data.h = zeros(1,data.updt);
+ data.q = zeros(1,data.updt);
+ end
+ if data.cntr
+ data.nst = zeros(1,data.updt);
+ data.nfe = zeros(1,data.updt);
+ data.nni = zeros(1,data.updt);
+ data.netf = zeros(1,data.updt);
+ data.ncfn = zeros(1,data.updt);
+ end
+
+ data.first = true; % the next one will be the first call = 1
+ data.initialized = false; % the graphical windows were not initalized
+
+ new_data = data;
+
+ return;
+
+else
+
+% If this is the first call ~= 0,
+% use Y and YS for additional initializations
+
+ if data.first
+
+ if isempty(YS)
+ data.sensi = false;
+ end
+
+ if data.sol | data.sensi
+
+ if isempty(data.select)
+
+ data.N = length(Y);
+ data.select = [1:data.N];
+
+ else
+
+ data.N = length(data.select);
+
+ end
+
+ if data.sol
+ data.y = zeros(data.N,data.updt);
+ data.nps = data.nps + 1;
+ end
+
+ if data.sensi
+ data.Ns = size(YS,2);
+ data.ys = zeros(data.N, data.Ns, data.updt);
+ data.nps = data.nps + data.Ns;
+ end
+
+ end
+
+ data.first = false;
+
+ end
+
+% Extract variables from data
+
+ hfg = data.hfg;
+ hft = data.hft;
+ hfs = data.hfs;
+ npg = data.npg;
+ nps = data.nps;
+ i = data.i;
+ n = data.n;
+ t = data.t;
+ N = data.N;
+ Ns = data.Ns;
+ y = data.y;
+ ys = data.ys;
+ h = data.h;
+ q = data.q;
+ nst = data.nst;
+ nfe = data.nfe;
+ nni = data.nni;
+ netf = data.netf;
+ ncfn = data.ncfn;
+
+end
+
+
+% Load current statistics?
+
+if call == 1
+
+ if i ~= 0
+ i = i-1;
+ data.i = i;
+ new_data = data;
+ return;
+ end
+
+ si = CVodeGetStats;
+
+ t(n) = si.tcur;
+
+ if data.stats
+ h(n) = si.hlast;
+ q(n) = si.qlast;
+ end
+
+ if data.cntr
+ nst(n) = si.nst;
+ nfe(n) = si.nfe;
+ nni(n) = si.nni;
+ netf(n) = si.netf;
+ ncfn(n) = si.ncfn;
+ end
+
+ if data.sol
+ for j = 1:N
+ y(j,n) = Y(data.select(j));
+ end
+ end
+
+ if data.sensi
+ for k = 1:Ns
+ for j = 1:N
+ ys(j,k,n) = YS(data.select(j),k);
+ end
+ end
+ end
+
+end
+
+% Is it time to post?
+
+if data.post & (n == data.updt | call==2)
+
+ if call == 2
+ n = n-1;
+ end
+
+ if ~data.initialized
+
+ if (data.stats | data.cntr) & data.grph
+ graphical_init(n, hfg, npg, data.stats, data.cntr, ...
+ t, h, q, nst, nfe, nni, netf, ncfn);
+ end
+
+ if (data.stats | data.cntr) & data.text
+ text_init(n, hft, data.stats, data.cntr, ...
+ t, h, q, nst, nfe, nni, netf, ncfn);
+ end
+
+ if data.sol | data.sensi
+ sol_init(n, hfs, nps, data.sol, data.sensi, ...
+ N, Ns, t, y, ys);
+ end
+
+ data.initialized = true;
+
+ else
+
+ if (data.stats | data.cntr) & data.grph
+ graphical_update(n, hfg, npg, data.stats, data.cntr, ...
+ t, h, q, nst, nfe, nni, netf, ncfn);
+ end
+
+ if (data.stats | data.cntr) & data.text
+ text_update(n, hft, data.stats, data.cntr, ...
+ t, h, q, nst, nfe, nni, netf, ncfn);
+ end
+
+ if data.sol
+ sol_update(n, hfs, nps, data.sol, data.sensi, N, Ns, t, y, ys);
+ end
+
+ end
+
+ if call == 2
+
+ if (data.stats | data.cntr) & data.grph
+ graphical_final(hfg, npg, data.cntr, data.stats);
+ end
+
+ if data.sol | data.sensi
+ sol_final(hfs, nps, data.sol, data.sensi, N, Ns);
+ end
+
+ return;
+
+ end
+
+ n = 1;
+
+else
+
+ n = n + 1;
+
+end
+
+
+% Save updated values in data
+
+data.i = data.skip;
+data.n = n;
+data.npg = npg;
+data.t = t;
+data.y = y;
+data.ys = ys;
+data.h = h;
+data.q = q;
+data.nst = nst;
+data.nfe = nfe;
+data.nni = nni;
+data.netf = netf;
+data.ncfn = ncfn;
+
+new_data = data;
+
+return;
+
+%-------------------------------------------------------------------------
+
+function data = initialize_data(data)
+
+if ~isfield(data,'mode')
+ data.mode = 'graphical';
+end
+if ~isfield(data,'updt')
+ data.updt = 50;
+end
+if ~isfield(data,'skip')
+ data.skip = 0;
+end
+if ~isfield(data,'stats')
+ data.stats = true;
+end
+if ~isfield(data,'cntr')
+ data.cntr = true;
+end
+if ~isfield(data,'sol')
+ data.sol = false;
+end
+if ~isfield(data,'sensi')
+ data.sensi = false;
+end
+if ~isfield(data,'select')
+ data.select = [];
+end
+if ~isfield(data,'post')
+ data.post = true;
+end
+
+data.grph = true;
+data.text = true;
+if strcmp(data.mode,'graphical')
+ data.text = false;
+end
+if strcmp(data.mode,'text')
+ data.grph = false;
+end
+
+if ~data.sol & ~data.sensi
+ data.select = [];
+end
+
+% Other initializations
+data.npg = 0;
+data.nps = 0;
+data.hfg = 0;
+data.hft = 0;
+data.hfs = 0;
+data.h = 0;
+data.q = 0;
+data.nst = 0;
+data.nfe = 0;
+data.nni = 0;
+data.netf = 0;
+data.ncfn = 0;
+data.N = 0;
+data.Ns = 0;
+data.y = 0;
+data.ys = 0;
+
+%-------------------------------------------------------------------------
+
+function [] = graphical_init(n, hfg, npg, stats, cntr, ...
+ t, h, q, nst, nfe, nni, netf, ncfn)
+
+fig_name = 'CVODES run statistics';
+
+% If this is a parallel job, look for the MPI rank in the global
+% workspace and append it to the figure name
+
+global sundials_MPI_rank
+
+if ~isempty(sundials_MPI_rank)
+ fig_name = sprintf('%s (PE %d)',fig_name,sundials_MPI_rank);
+end
+
+figure(hfg);
+set(hfg,'Name',fig_name);
+set(hfg,'color',[1 1 1]);
+pl = 0;
+
+% Time label and figure title
+
+tlab = '\rightarrow t \rightarrow';
+
+% Step size and order
+if stats
+ pl = pl+1;
+ subplot(npg,1,pl)
+ semilogy(t(1:n),abs(h(1:n)),'-');
+ hold on;
+ box on;
+ grid on;
+ xlabel(tlab);
+ ylabel('|Step size|');
+
+ pl = pl+1;
+ subplot(npg,1,pl)
+ plot(t(1:n),q(1:n),'-');
+ hold on;
+ box on;
+ grid on;
+ xlabel(tlab);
+ ylabel('Order');
+end
+
+% Counters
+if cntr
+ pl = pl+1;
+ subplot(npg,1,pl)
+ plot(t(1:n),nst(1:n),'k-');
+ hold on;
+ plot(t(1:n),nfe(1:n),'b-');
+ plot(t(1:n),nni(1:n),'r-');
+ plot(t(1:n),netf(1:n),'g-');
+ plot(t(1:n),ncfn(1:n),'c-');
+ box on;
+ grid on;
+ xlabel(tlab);
+ ylabel('Counters');
+end
+
+drawnow;
+
+%-------------------------------------------------------------------------
+
+function [] = graphical_update(n, hfg, npg, stats, cntr, ...
+ t, h, q, nst, nfe, nni, netf, ncfn)
+
+figure(hfg);
+pl = 0;
+
+% Step size and order
+if stats
+ pl = pl+1;
+ subplot(npg,1,pl)
+ hc = get(gca,'Children');
+ xd = [get(hc,'XData') t(1:n)];
+ yd = [get(hc,'YData') abs(h(1:n))];
+ set(hc, 'XData', xd, 'YData', yd);
+
+ pl = pl+1;
+ subplot(npg,1,pl)
+ hc = get(gca,'Children');
+ xd = [get(hc,'XData') t(1:n)];
+ yd = [get(hc,'YData') q(1:n)];
+ set(hc, 'XData', xd, 'YData', yd);
+end
+
+% Counters
+if cntr
+ pl = pl+1;
+ subplot(npg,1,pl)
+ hc = get(gca,'Children');
+% Attention: Children are loaded in reverse order!
+ xd = [get(hc(1),'XData') t(1:n)];
+ yd = [get(hc(1),'YData') ncfn(1:n)];
+ set(hc(1), 'XData', xd, 'YData', yd);
+ yd = [get(hc(2),'YData') netf(1:n)];
+ set(hc(2), 'XData', xd, 'YData', yd);
+ yd = [get(hc(3),'YData') nni(1:n)];
+ set(hc(3), 'XData', xd, 'YData', yd);
+ yd = [get(hc(4),'YData') nfe(1:n)];
+ set(hc(4), 'XData', xd, 'YData', yd);
+ yd = [get(hc(5),'YData') nst(1:n)];
+ set(hc(5), 'XData', xd, 'YData', yd);
+end
+
+drawnow;
+
+%-------------------------------------------------------------------------
+
+function [] = graphical_final(hfg,npg,stats,cntr)
+
+figure(hfg);
+pl = 0;
+
+if stats
+ pl = pl+1;
+ subplot(npg,1,pl)
+ hc = get(gca,'Children');
+ xd = get(hc,'XData');
+ set(gca,'XLim',sort([xd(1) xd(end)]));
+
+ pl = pl+1;
+ subplot(npg,1,pl)
+ ylim = get(gca,'YLim');
+ ylim(1) = ylim(1) - 1;
+ ylim(2) = ylim(2) + 1;
+ set(gca,'YLim',ylim);
+ set(gca,'XLim',sort([xd(1) xd(end)]));
+end
+
+if cntr
+ pl = pl+1;
+ subplot(npg,1,pl)
+ hc = get(gca,'Children');
+ xd = get(hc(1),'XData');
+ set(gca,'XLim',sort([xd(1) xd(end)]));
+ legend('nst','nfe','nni','netf','ncfn',2);
+end
+
+%-------------------------------------------------------------------------
+
+function [] = text_init(n,hft,stats,cntr,t,h,q,nst,nfe,nni,netf,ncfn)
+
+fig_name = 'CVODES run statistics';
+
+% If this is a parallel job, look for the MPI rank in the global
+% workspace and append it to the figure name
+
+global sundials_MPI_rank
+
+if ~isempty(sundials_MPI_rank)
+ fig_name = sprintf('%s (PE %d)',fig_name,sundials_MPI_rank);
+end
+
+figure(hft);
+set(hft,'Name',fig_name);
+set(hft,'color',[1 1 1]);
+set(hft,'MenuBar','none');
+set(hft,'Resize','off');
+
+% Create text box
+
+margins=[10 10 50 50]; % left, right, top, bottom
+pos=get(hft,'position');
+tbpos=[margins(1) margins(4) pos(3)-margins(1)-margins(2) ...
+ pos(4)-margins(3)-margins(4)];
+tbpos(tbpos<1)=1;
+
+htb=uicontrol(hft,'style','listbox','position',tbpos,'tag','textbox');
+set(htb,'BackgroundColor',[1 1 1]);
+set(htb,'SelectionHighlight','off');
+set(htb,'FontName','courier');
+
+% Create table head
+
+tpos = [tbpos(1) tbpos(2)+tbpos(4)+10 tbpos(3) 20];
+ht=uicontrol(hft,'style','text','position',tpos,'tag','text');
+set(ht,'BackgroundColor',[1 1 1]);
+set(ht,'HorizontalAlignment','left');
+set(ht,'FontName','courier');
+newline = ' time step order | nst nfe nni netf ncfn';
+set(ht,'String',newline);
+
+% Create OK button
+
+bsize=[60,28];
+badjustpos=[0,25];
+bpos=[pos(3)/2-bsize(1)/2+badjustpos(1) -bsize(2)/2+badjustpos(2)...
+ bsize(1) bsize(2)];
+bpos=round(bpos);
+bpos(bpos<1)=1;
+hb=uicontrol(hft,'style','pushbutton','position',bpos,...
+ 'string','Close','tag','okaybutton');
+set(hb,'callback','close');
+
+% Save handles
+
+handles=guihandles(hft);
+guidata(hft,handles);
+
+for i = 1:n
+ newline = '';
+ if stats
+ newline = sprintf('%10.3e %10.3e %1d |',t(i),h(i),q(i));
+ end
+ if cntr
+ newline = sprintf('%s %5d %5d %5d %5d %5d',...
+ newline,nst(i),nfe(i),nni(i),netf(i),ncfn(i));
+ end
+ string = get(handles.textbox,'String');
+ string{end+1}=newline;
+ set(handles.textbox,'String',string);
+end
+
+drawnow
+
+%-------------------------------------------------------------------------
+
+function [] = text_update(n,hft,stats,cntr,t,h,q,nst,nfe,nni,netf,ncfn)
+
+figure(hft);
+
+handles=guidata(hft);
+
+for i = 1:n
+ if stats
+ newline = sprintf('%10.3e %10.3e %1d |',t(i),h(i),q(i));
+ end
+ if cntr
+ newline = sprintf('%s %5d %5d %5d %5d %5d',...
+ newline,nst(i),nfe(i),nni(i),netf(i),ncfn(i));
+ end
+ string = get(handles.textbox,'String');
+ string{end+1}=newline;
+ set(handles.textbox,'String',string);
+end
+
+drawnow
+
+%-------------------------------------------------------------------------
+
+function [] = sol_init(n, hfs, nps, sol, sensi, N, Ns, t, y, ys)
+
+fig_name = 'CVODES solution';
+
+% If this is a parallel job, look for the MPI rank in the global
+% workspace and append it to the figure name
+
+global sundials_MPI_rank
+
+if ~isempty(sundials_MPI_rank)
+ fig_name = sprintf('%s (PE %d)',fig_name,sundials_MPI_rank);
+end
+
+
+figure(hfs);
+set(hfs,'Name',fig_name);
+set(hfs,'color',[1 1 1]);
+
+% Time label
+
+tlab = '\rightarrow t \rightarrow';
+
+% Get number of colors in colormap
+map = colormap;
+ncols = size(map,1);
+
+% Initialize current subplot counter
+pl = 0;
+
+if sol
+
+ pl = pl+1;
+ subplot(nps,1,pl);
+ hold on;
+
+ for i = 1:N
+ hp = plot(t(1:n),y(i,1:n),'-');
+ ic = 1+(i-1)*floor(ncols/N);
+ set(hp,'Color',map(ic,:));
+ end
+ box on;
+ grid on;
+ xlabel(tlab);
+ ylabel('y');
+ title('Solution');
+
+end
+
+if sensi
+
+ for is = 1:Ns
+
+ pl = pl+1;
+ subplot(nps,1,pl);
+ hold on;
+
+ ys_crt = ys(:,is,1:n);
+ for i = 1:N
+ hp = plot(t(1:n),ys_crt(i,1:n),'-');
+ ic = 1+(i-1)*floor(ncols/N);
+ set(hp,'Color',map(ic,:));
+ end
+ box on;
+ grid on;
+ xlabel(tlab);
+ str = sprintf('s_{%d}',is); ylabel(str);
+ str = sprintf('Sensitivity %d',is); title(str);
+
+ end
+
+end
+
+
+drawnow;
+
+%-------------------------------------------------------------------------
+
+function [] = sol_update(n, hfs, nps, sol, sensi, N, Ns, t, y, ys)
+
+figure(hfs);
+
+pl = 0;
+
+if sol
+
+ pl = pl+1;
+ subplot(nps,1,pl);
+
+ hc = get(gca,'Children');
+ xd = [get(hc(1),'XData') t(1:n)];
+% Attention: Children are loaded in reverse order!
+ for i = 1:N
+ yd = [get(hc(i),'YData') y(N-i+1,1:n)];
+ set(hc(i), 'XData', xd, 'YData', yd);
+ end
+
+end
+
+if sensi
+
+ for is = 1:Ns
+
+ pl = pl+1;
+ subplot(nps,1,pl);
+
+ ys_crt = ys(:,is,:);
+
+ hc = get(gca,'Children');
+ xd = [get(hc(1),'XData') t(1:n)];
+% Attention: Children are loaded in reverse order!
+ for i = 1:N
+ yd = [get(hc(i),'YData') ys_crt(N-i+1,1:n)];
+ set(hc(i), 'XData', xd, 'YData', yd);
+ end
+
+ end
+
+end
+
+
+drawnow;
+
+
+%-------------------------------------------------------------------------
+
+function [] = sol_final(hfs, nps, sol, sensi, N, Ns)
+
+figure(hfs);
+
+pl = 0;
+
+if sol
+
+ pl = pl +1;
+ subplot(nps,1,pl);
+
+ hc = get(gca,'Children');
+ xd = get(hc(1),'XData');
+ set(gca,'XLim',sort([xd(1) xd(end)]));
+
+ ylim = get(gca,'YLim');
+ addon = 0.1*abs(ylim(2)-ylim(1));
+ ylim(1) = ylim(1) + sign(ylim(1))*addon;
+ ylim(2) = ylim(2) + sign(ylim(2))*addon;
+ set(gca,'YLim',ylim);
+
+ for i = 1:N
+ cstring{i} = sprintf('y_{%d}',i);
+ end
+ legend(cstring);
+
+end
+
+if sensi
+
+ for is = 1:Ns
+
+ pl = pl+1;
+ subplot(nps,1,pl);
+
+ hc = get(gca,'Children');
+ xd = get(hc(1),'XData');
+ set(gca,'XLim',sort([xd(1) xd(end)]));
+
+ ylim = get(gca,'YLim');
+ addon = 0.1*abs(ylim(2)-ylim(1));
+ ylim(1) = ylim(1) + sign(ylim(1))*addon;
+ ylim(2) = ylim(2) + sign(ylim(2))*addon;
+ set(gca,'YLim',ylim);
+
+ for i = 1:N
+ cstring{i} = sprintf('s%d_{%d}',is,i);
+ end
+ legend(cstring);
+
+ end
+
+end
+
+drawnow
diff --git a/sundialsTB/cvodes/CVodeMonitorB.m b/sundialsTB/cvodes/CVodeMonitorB.m
new file mode 100644
index 0000000..075eacc
--- /dev/null
+++ b/sundialsTB/cvodes/CVodeMonitorB.m
@@ -0,0 +1,697 @@
+function [new_data] = CVodeMonitorB(call, idxB, T, Y, YQ, data)
+%CVodeMonitorB is the default CVODES monitoring function for backward problems.
+% To use it, set the Monitor property in CVodeSetOptions to
+% 'CVodeMonitorB' or to @CVodeMonitorB and 'MonitorData' to mondata
+% (defined as a structure).
+%
+% With default settings, this function plots the evolution of the step
+% size, method order, and various counters.
+%
+% Various properties can be changed from their default values by passing
+% to CVodeSetOptions, through the property 'MonitorData', a structure
+% MONDATA with any of the following fields. If a field is not defined,
+% the corresponding default value is used.
+%
+% Fields in MONDATA structure:
+% o stats [ {true} | false ]
+% If true, report the evolution of the step size and method order.
+% o cntr [ {true} | false ]
+% If true, report the evolution of the following counters:
+% nst, nfe, nni, netf, ncfn (see CVodeGetStats)
+% o mode [ {'graphical'} | 'text' | 'both' ]
+% In graphical mode, plot the evolutions of the above quantities.
+% In text mode, print a table.
+% o sol [ true | {false} ]
+% If true, plot solution components.
+% o select [ array of integers ]
+% To plot only particular solution components, specify their indeces in
+% the field select. If not defined, but sol=true, all components are plotted.
+% o updt [ integer | {50} ]
+% Update frequency. Data is posted in blocks of dimension n.
+% o skip [ integer | {0} ]
+% Number of integrations steps to skip in collecting data to post.
+% o post [ {true} | false ]
+% If false, disable all posting. This option is necessary to disable
+% monitoring on some processors when running in parallel.
+%
+% See also CVodeSetOptions, CVMonitorFnB
+%
+% NOTES:
+% 1. The argument mondata is REQUIRED. Even if only the default options
+% are desired, set mondata=struct; and pass it to CVodeSetOptions.
+% 2. The yQ argument is currently ignored.
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2007, The Regents of the University of California.
+% $Revision: 1.1 $Date: 2007/05/11 18:51:32 $
+
+
+if (nargin ~= 6)
+ error('Monitor data not defined.');
+end
+
+
+new_data = [];
+
+if call == 0
+
+% Initialize unspecified fields to default values.
+ data = initialize_data(data);
+
+% Open figure windows
+ if data.post
+
+ if data.grph
+ if data.stats | data.cntr
+ data.hfg = figure;
+ end
+% Number of subplots in figure hfg
+ if data.stats
+ data.npg = data.npg + 2;
+ end
+ if data.cntr
+ data.npg = data.npg + 1;
+ end
+ end
+
+ if data.text
+ if data.cntr | data.stats
+ data.hft = figure;
+ end
+ end
+
+ if data.sol
+ data.hfs = figure;
+ end
+
+ end
+
+% Initialize other private data
+ data.i = 0;
+ data.n = 1;
+ data.t = zeros(1,data.updt);
+ if data.stats
+ data.h = zeros(1,data.updt);
+ data.q = zeros(1,data.updt);
+ end
+ if data.cntr
+ data.nst = zeros(1,data.updt);
+ data.nfe = zeros(1,data.updt);
+ data.nni = zeros(1,data.updt);
+ data.netf = zeros(1,data.updt);
+ data.ncfn = zeros(1,data.updt);
+ end
+
+ data.first = true; % the next one will be the first call = 1
+ data.initialized = false; % the graphical windows were not initalized
+
+ new_data = data;
+
+ return;
+
+else
+
+% If this is the first call ~= 0,
+% use Y for additional initializations
+
+ if data.first
+
+ if data.sol
+
+ if isempty(data.select)
+
+ data.N = length(Y);
+ data.select = [1:data.N];
+
+ else
+
+ data.N = length(data.select);
+
+ end
+
+ if data.sol
+ data.y = zeros(data.N,data.updt);
+ data.nps = data.nps + 1;
+ end
+
+ end
+
+ data.first = false;
+
+ end
+
+% Extract variables from data
+
+ hfg = data.hfg;
+ hft = data.hft;
+ hfs = data.hfs;
+ npg = data.npg;
+ nps = data.nps;
+ i = data.i;
+ n = data.n;
+ t = data.t;
+ N = data.N;
+ y = data.y;
+ h = data.h;
+ q = data.q;
+ nst = data.nst;
+ nfe = data.nfe;
+ nni = data.nni;
+ netf = data.netf;
+ ncfn = data.ncfn;
+
+end
+
+
+% Load current statistics?
+
+if call == 1
+
+ if i ~= 0
+ i = i-1;
+ data.i = i;
+ new_data = data;
+ return;
+ end
+
+ si = CVodeGetStatsB(idxB);
+
+ t(n) = si.tcur;
+
+ if data.stats
+ h(n) = si.hlast;
+ q(n) = si.qlast;
+ end
+
+ if data.cntr
+ nst(n) = si.nst;
+ nfe(n) = si.nfe;
+ nni(n) = si.nni;
+ netf(n) = si.netf;
+ ncfn(n) = si.ncfn;
+ end
+
+ if data.sol
+ for j = 1:N
+ y(j,n) = Y(data.select(j));
+ end
+ end
+
+end
+
+% Is it time to post?
+
+if data.post & (n == data.updt | call==2)
+
+ if call == 2
+ n = n-1;
+ end
+
+ if ~data.initialized
+
+ if (data.stats | data.cntr) & data.grph
+ graphical_init(n, hfg, npg, data.stats, data.cntr, ...
+ t, h, q, nst, nfe, nni, netf, ncfn);
+ end
+
+ if (data.stats | data.cntr) & data.text
+ text_init(n, hft, data.stats, data.cntr, ...
+ t, h, q, nst, nfe, nni, netf, ncfn);
+ end
+
+ if data.sol
+ sol_init(n, hfs, nps, data.sol, ...
+ N, t, y);
+ end
+
+ data.initialized = true;
+
+ else
+
+ if (data.stats | data.cntr) & data.grph
+ graphical_update(n, hfg, npg, data.stats, data.cntr, ...
+ t, h, q, nst, nfe, nni, netf, ncfn);
+ end
+
+ if (data.stats | data.cntr) & data.text
+ text_update(n, hft, data.stats, data.cntr, ...
+ t, h, q, nst, nfe, nni, netf, ncfn);
+ end
+
+ if data.sol
+ sol_update(n, hfs, nps, data.sol, N, t, y);
+ end
+
+ end
+
+ if call == 2
+
+ if (data.stats | data.cntr) & data.grph
+ graphical_final(hfg, npg, data.cntr, data.stats);
+ end
+
+ if data.sol
+ sol_final(hfs, nps, data.sol, N);
+ end
+
+ return;
+
+ end
+
+ n = 1;
+
+else
+
+ n = n + 1;
+
+end
+
+
+% Save updated values in data
+
+data.i = data.skip;
+data.n = n;
+data.npg = npg;
+data.t = t;
+data.y = y;
+data.h = h;
+data.q = q;
+data.nst = nst;
+data.nfe = nfe;
+data.nni = nni;
+data.netf = netf;
+data.ncfn = ncfn;
+
+new_data = data;
+
+return;
+
+%-------------------------------------------------------------------------
+
+function data = initialize_data(data)
+
+if ~isfield(data,'mode')
+ data.mode = 'graphical';
+end
+if ~isfield(data,'updt')
+ data.updt = 50;
+end
+if ~isfield(data,'skip')
+ data.skip = 0;
+end
+if ~isfield(data,'stats')
+ data.stats = true;
+end
+if ~isfield(data,'cntr')
+ data.cntr = true;
+end
+if ~isfield(data,'sol')
+ data.sol = false;
+end
+if ~isfield(data,'select')
+ data.select = [];
+end
+if ~isfield(data,'post')
+ data.post = true;
+end
+
+data.grph = true;
+data.text = true;
+if strcmp(data.mode,'graphical')
+ data.text = false;
+end
+if strcmp(data.mode,'text')
+ data.grph = false;
+end
+
+if ~data.sol
+ data.select = [];
+end
+
+% Other initializations
+data.npg = 0;
+data.nps = 0;
+data.hfg = 0;
+data.hft = 0;
+data.hfs = 0;
+data.h = 0;
+data.q = 0;
+data.nst = 0;
+data.nfe = 0;
+data.nni = 0;
+data.netf = 0;
+data.ncfn = 0;
+data.N = 0;
+data.y = 0;
+
+%-------------------------------------------------------------------------
+
+function [] = graphical_init(n, hfg, npg, stats, cntr, ...
+ t, h, q, nst, nfe, nni, netf, ncfn)
+
+fig_name = 'CVODES run statistics';
+
+% If this is a parallel job, look for the MPI rank in the global
+% workspace and append it to the figure name
+
+global sundials_MPI_rank
+
+if ~isempty(sundials_MPI_rank)
+ fig_name = sprintf('%s (PE %d)',fig_name,sundials_MPI_rank);
+end
+
+figure(hfg);
+set(hfg,'Name',fig_name);
+set(hfg,'color',[1 1 1]);
+pl = 0;
+
+% Time label and figure title
+
+tlab = '\leftarrow t \leftarrow';
+
+% Step size and order
+if stats
+ pl = pl+1;
+ subplot(npg,1,pl)
+ semilogy(t(1:n),abs(h(1:n)),'-');
+ hold on;
+ box on;
+ grid on;
+ xlabel(tlab);
+ ylabel('|Step size|');
+
+ pl = pl+1;
+ subplot(npg,1,pl)
+ plot(t(1:n),q(1:n),'-');
+ hold on;
+ box on;
+ grid on;
+ xlabel(tlab);
+ ylabel('Order');
+end
+
+% Counters
+if cntr
+ pl = pl+1;
+ subplot(npg,1,pl)
+ plot(t(1:n),nst(1:n),'k-');
+ hold on;
+ plot(t(1:n),nfe(1:n),'b-');
+ plot(t(1:n),nni(1:n),'r-');
+ plot(t(1:n),netf(1:n),'g-');
+ plot(t(1:n),ncfn(1:n),'c-');
+ box on;
+ grid on;
+ xlabel(tlab);
+ ylabel('Counters');
+end
+
+drawnow;
+
+%-------------------------------------------------------------------------
+
+function [] = graphical_update(n, hfg, npg, stats, cntr, ...
+ t, h, q, nst, nfe, nni, netf, ncfn)
+
+figure(hfg);
+pl = 0;
+
+% Step size and order
+if stats
+ pl = pl+1;
+ subplot(npg,1,pl)
+ hc = get(gca,'Children');
+ xd = [get(hc,'XData') t(1:n)];
+ yd = [get(hc,'YData') abs(h(1:n))];
+ set(hc, 'XData', xd, 'YData', yd);
+
+ pl = pl+1;
+ subplot(npg,1,pl)
+ hc = get(gca,'Children');
+ xd = [get(hc,'XData') t(1:n)];
+ yd = [get(hc,'YData') q(1:n)];
+ set(hc, 'XData', xd, 'YData', yd);
+end
+
+% Counters
+if cntr
+ pl = pl+1;
+ subplot(npg,1,pl)
+ hc = get(gca,'Children');
+% Attention: Children are loaded in reverse order!
+ xd = [get(hc(1),'XData') t(1:n)];
+ yd = [get(hc(1),'YData') ncfn(1:n)];
+ set(hc(1), 'XData', xd, 'YData', yd);
+ yd = [get(hc(2),'YData') netf(1:n)];
+ set(hc(2), 'XData', xd, 'YData', yd);
+ yd = [get(hc(3),'YData') nni(1:n)];
+ set(hc(3), 'XData', xd, 'YData', yd);
+ yd = [get(hc(4),'YData') nfe(1:n)];
+ set(hc(4), 'XData', xd, 'YData', yd);
+ yd = [get(hc(5),'YData') nst(1:n)];
+ set(hc(5), 'XData', xd, 'YData', yd);
+end
+
+drawnow;
+
+%-------------------------------------------------------------------------
+
+function [] = graphical_final(hfg,npg,stats,cntr)
+
+figure(hfg);
+pl = 0;
+
+if stats
+ pl = pl+1;
+ subplot(npg,1,pl)
+ hc = get(gca,'Children');
+ xd = get(hc,'XData');
+ set(gca,'XLim',sort([xd(1) xd(end)]));
+
+ pl = pl+1;
+ subplot(npg,1,pl)
+ ylim = get(gca,'YLim');
+ ylim(1) = ylim(1) - 1;
+ ylim(2) = ylim(2) + 1;
+ set(gca,'YLim',ylim);
+ set(gca,'XLim',sort([xd(1) xd(end)]));
+end
+
+if cntr
+ pl = pl+1;
+ subplot(npg,1,pl)
+ hc = get(gca,'Children');
+ xd = get(hc(1),'XData');
+ set(gca,'XLim',sort([xd(1) xd(end)]));
+ legend('nst','nfe','nni','netf','ncfn',2);
+end
+
+%-------------------------------------------------------------------------
+
+function [] = text_init(n,hft,stats,cntr,t,h,q,nst,nfe,nni,netf,ncfn)
+
+fig_name = 'CVODES run statistics';
+
+% If this is a parallel job, look for the MPI rank in the global
+% workspace and append it to the figure name
+
+global sundials_MPI_rank
+
+if ~isempty(sundials_MPI_rank)
+ fig_name = sprintf('%s (PE %d)',fig_name,sundials_MPI_rank);
+end
+
+figure(hft);
+set(hft,'Name',fig_name);
+set(hft,'color',[1 1 1]);
+set(hft,'MenuBar','none');
+set(hft,'Resize','off');
+
+% Create text box
+
+margins=[10 10 50 50]; % left, right, top, bottom
+pos=get(hft,'position');
+tbpos=[margins(1) margins(4) pos(3)-margins(1)-margins(2) ...
+ pos(4)-margins(3)-margins(4)];
+tbpos(tbpos<1)=1;
+
+htb=uicontrol(hft,'style','listbox','position',tbpos,'tag','textbox');
+set(htb,'BackgroundColor',[1 1 1]);
+set(htb,'SelectionHighlight','off');
+set(htb,'FontName','courier');
+
+% Create table head
+
+tpos = [tbpos(1) tbpos(2)+tbpos(4)+10 tbpos(3) 20];
+ht=uicontrol(hft,'style','text','position',tpos,'tag','text');
+set(ht,'BackgroundColor',[1 1 1]);
+set(ht,'HorizontalAlignment','left');
+set(ht,'FontName','courier');
+newline = ' time step order | nst nfe nni netf ncfn';
+set(ht,'String',newline);
+
+% Create OK button
+
+bsize=[60,28];
+badjustpos=[0,25];
+bpos=[pos(3)/2-bsize(1)/2+badjustpos(1) -bsize(2)/2+badjustpos(2)...
+ bsize(1) bsize(2)];
+bpos=round(bpos);
+bpos(bpos<1)=1;
+hb=uicontrol(hft,'style','pushbutton','position',bpos,...
+ 'string','Close','tag','okaybutton');
+set(hb,'callback','close');
+
+% Save handles
+
+handles=guihandles(hft);
+guidata(hft,handles);
+
+for i = 1:n
+ newline = '';
+ if stats
+ newline = sprintf('%10.3e %10.3e %1d |',t(i),h(i),q(i));
+ end
+ if cntr
+ newline = sprintf('%s %5d %5d %5d %5d %5d',...
+ newline,nst(i),nfe(i),nni(i),netf(i),ncfn(i));
+ end
+ string = get(handles.textbox,'String');
+ string{end+1}=newline;
+ set(handles.textbox,'String',string);
+end
+
+drawnow
+
+%-------------------------------------------------------------------------
+
+function [] = text_update(n,hft,stats,cntr,t,h,q,nst,nfe,nni,netf,ncfn)
+
+figure(hft);
+
+handles=guidata(hft);
+
+for i = 1:n
+ if stats
+ newline = sprintf('%10.3e %10.3e %1d |',t(i),h(i),q(i));
+ end
+ if cntr
+ newline = sprintf('%s %5d %5d %5d %5d %5d',...
+ newline,nst(i),nfe(i),nni(i),netf(i),ncfn(i));
+ end
+ string = get(handles.textbox,'String');
+ string{end+1}=newline;
+ set(handles.textbox,'String',string);
+end
+
+drawnow
+
+%-------------------------------------------------------------------------
+
+function [] = sol_init(n, hfs, nps, sol, N, t, y)
+
+fig_name = 'CVODES solution';
+
+% If this is a parallel job, look for the MPI rank in the global
+% workspace and append it to the figure name
+
+global sundials_MPI_rank
+
+if ~isempty(sundials_MPI_rank)
+ fig_name = sprintf('%s (PE %d)',fig_name,sundials_MPI_rank);
+end
+
+
+figure(hfs);
+set(hfs,'Name',fig_name);
+set(hfs,'color',[1 1 1]);
+
+% Time label
+
+tlab = '\leftarrow t \leftarrow';
+
+% Get number of colors in colormap
+map = colormap;
+ncols = size(map,1);
+
+% Initialize current subplot counter
+pl = 0;
+
+if sol
+
+ pl = pl+1;
+ subplot(nps,1,pl);
+ hold on;
+
+ for i = 1:N
+ hp = plot(t(1:n),y(i,1:n),'-');
+ ic = 1+(i-1)*floor(ncols/N);
+ set(hp,'Color',map(ic,:));
+ end
+ box on;
+ grid on;
+ xlabel(tlab);
+ ylabel('y');
+ title('Solution');
+
+end
+
+drawnow;
+
+%-------------------------------------------------------------------------
+
+function [] = sol_update(n, hfs, nps, sol, N, t, y)
+
+figure(hfs);
+
+pl = 0;
+
+if sol
+
+ pl = pl+1;
+ subplot(nps,1,pl);
+
+ hc = get(gca,'Children');
+ xd = [get(hc(1),'XData') t(1:n)];
+% Attention: Children are loaded in reverse order!
+ for i = 1:N
+ yd = [get(hc(i),'YData') y(N-i+1,1:n)];
+ set(hc(i), 'XData', xd, 'YData', yd);
+ end
+
+end
+
+drawnow;
+
+
+%-------------------------------------------------------------------------
+
+function [] = sol_final(hfs, nps, sol, N)
+
+figure(hfs);
+
+pl = 0;
+
+if sol
+
+ pl = pl +1;
+ subplot(nps,1,pl);
+
+ hc = get(gca,'Children');
+ xd = get(hc(1),'XData');
+ set(gca,'XLim',sort([xd(1) xd(end)]));
+
+ ylim = get(gca,'YLim');
+ addon = 0.1*abs(ylim(2)-ylim(1));
+ ylim(1) = ylim(1) + sign(ylim(1))*addon;
+ ylim(2) = ylim(2) + sign(ylim(2))*addon;
+ set(gca,'YLim',ylim);
+
+ for i = 1:N
+ cstring{i} = sprintf('y_{%d}',i);
+ end
+ legend(cstring);
+
+end
+
+drawnow
diff --git a/sundialsTB/cvodes/CVodeMonitorB_octave.m b/sundialsTB/cvodes/CVodeMonitorB_octave.m
new file mode 100644
index 0000000..66a0e2c
--- /dev/null
+++ b/sundialsTB/cvodes/CVodeMonitorB_octave.m
@@ -0,0 +1,545 @@
+function [new_data] = CVodeMonitorB(call, idxB, T, Y, YQ, data)
+%CVodeMonitorB is the default CVODES monitoring function for backward problems.
+% To use it, set the Monitor property in CVodeSetOptions to
+% 'CVodeMonitorB' or to @CVodeMonitorB and 'MonitorData' to mondata
+% (defined as a structure).
+%
+% With default settings, this function plots the evolution of the step
+% size, method order, and various counters.
+%
+% Various properties can be changed from their default values by passing
+% to CVodeSetOptions, through the property 'MonitorData', a structure
+% MONDATA with any of the following fields. If a field is not defined,
+% the corresponding default value is used.
+%
+% Fields in MONDATA structure:
+% o stats [ {true} | false ]
+% If true, report the evolution of the step size and method order.
+% o cntr [ {true} | false ]
+% If true, report the evolution of the following counters:
+% nst, nfe, nni, netf, ncfn (see CVodeGetStats)
+% o sol [ true | {false} ]
+% If true, plot solution components.
+% o select [ array of integers ]
+% To plot only particular solution components, specify their indeces in
+% the field select. If not defined, but sol=true, all components are plotted.
+% o updt [ integer | {50} ]
+% Update frequency. Data is posted in blocks of dimension n.
+% o skip [ integer | {0} ]
+% Number of integrations steps to skip in collecting data to post.
+% o post [ {true} | false ]
+% If false, disable all posting. This option is necessary to disable
+% monitoring on some processors when running in parallel.
+%
+% See also CVodeSetOptions, CVMonitorFnB
+%
+% NOTES:
+% 1. The argument mondata is REQUIRED. Even if only the default options
+% are desired, set mondata=struct; and pass it to CVodeSetOptions.
+% 2. The yQ argument is currently ignored.
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2007, The Regents of the University of California.
+% $Revision: 1.1 $Date: 2007/08/21 17:42:38 $
+
+
+if (nargin ~= 6)
+ error('Monitor data not defined.');
+end
+
+
+new_data = [];
+
+if call == 0
+
+% Initialize unspecified fields to default values.
+ data = initialize_data(data);
+
+% Open figure windows
+ if data.post
+
+ if data.stats | data.cntr
+ data.hfg = figure;
+ end
+% Number of subplots in figure hfg
+ if data.stats
+ data.npg = data.npg + 2;
+ end
+ if data.cntr
+ data.npg = data.npg + 1;
+ end
+
+ if data.sol
+ data.hfs = figure;
+ end
+
+ end
+
+% Initialize other private data
+ data.i = 0;
+ data.n = 1;
+ data.t = zeros(1,data.updt);
+ if data.stats
+ data.h = zeros(1,data.updt);
+ data.q = zeros(1,data.updt);
+ end
+ if data.cntr
+ data.nst = zeros(1,data.updt);
+ data.nfe = zeros(1,data.updt);
+ data.nni = zeros(1,data.updt);
+ data.netf = zeros(1,data.updt);
+ data.ncfn = zeros(1,data.updt);
+ end
+
+ data.first = true; % the next one will be the first call = 1
+ data.initialized = false; % the graphical windows were not initalized
+
+ new_data = data;
+
+ return;
+
+else
+
+% If this is the first call ~= 0,
+% use Y for additional initializations
+
+ if data.first
+
+ if data.sol
+
+ if isempty(data.select)
+
+ data.N = length(Y);
+ data.select = [1:data.N];
+
+ else
+
+ data.N = length(data.select);
+
+ end
+
+ if data.sol
+ data.y = zeros(data.N,data.updt);
+ data.nps = data.nps + 1;
+ end
+
+ end
+
+ data.first = false;
+
+ end
+
+% Extract variables from data
+
+ hfg = data.hfg;
+ hft = data.hft;
+ hfs = data.hfs;
+ npg = data.npg;
+ nps = data.nps;
+ i = data.i;
+ n = data.n;
+ t = data.t;
+ N = data.N;
+ y = data.y;
+ h = data.h;
+ q = data.q;
+ nst = data.nst;
+ nfe = data.nfe;
+ nni = data.nni;
+ netf = data.netf;
+ ncfn = data.ncfn;
+
+end
+
+
+% Load current statistics?
+
+if call == 1
+
+ if i ~= 0
+ i = i-1;
+ data.i = i;
+ new_data = data;
+ return;
+ end
+
+ si = CVodeGetStatsB(idxB);
+
+ t(n) = si.tcur;
+
+ if data.stats
+ h(n) = si.hlast;
+ q(n) = si.qlast;
+ end
+
+ if data.cntr
+ nst(n) = si.nst;
+ nfe(n) = si.nfe;
+ nni(n) = si.nni;
+ netf(n) = si.netf;
+ ncfn(n) = si.ncfn;
+ end
+
+ if data.sol
+ for j = 1:N
+ y(j,n) = Y(data.select(j));
+ end
+ end
+
+end
+
+% Is it time to post?
+
+if data.post & (n == data.updt | call==2)
+
+ if call == 2
+ n = n-1;
+ end
+
+ if ~data.initialized
+
+ if (data.stats | data.cntr)
+ graphical_init(n, hfg, npg, data.stats, data.cntr, ...
+ t, h, q, nst, nfe, nni, netf, ncfn);
+ end
+
+ if data.sol
+ sol_init(n, hfs, nps, data.sol, ...
+ N, t, y);
+ end
+
+ data.initialized = true;
+
+ else
+
+ if (data.stats | data.cntr)
+ graphical_update(n, hfg, npg, data.stats, data.cntr, ...
+ t, h, q, nst, nfe, nni, netf, ncfn);
+ end
+
+ if data.sol
+ sol_update(n, hfs, nps, data.sol, N, t, y);
+ end
+
+ end
+
+ if call == 2
+
+ if (data.stats | data.cntr)
+ graphical_final(hfg, npg, data.cntr, data.stats);
+ end
+
+ if data.sol
+ sol_final(hfs, nps, data.sol, N);
+ end
+
+ return;
+
+ end
+
+ n = 1;
+
+else
+
+ n = n + 1;
+
+end
+
+
+% Save updated values in data
+
+data.i = data.skip;
+data.n = n;
+data.npg = npg;
+data.t = t;
+data.y = y;
+data.h = h;
+data.q = q;
+data.nst = nst;
+data.nfe = nfe;
+data.nni = nni;
+data.netf = netf;
+data.ncfn = ncfn;
+
+new_data = data;
+
+return;
+
+%-------------------------------------------------------------------------
+
+function data = initialize_data(data)
+
+if ~isfield(data,'updt')
+ data.updt = 50;
+end
+if ~isfield(data,'skip')
+ data.skip = 0;
+end
+if ~isfield(data,'stats')
+ data.stats = true;
+end
+if ~isfield(data,'cntr')
+ data.cntr = true;
+end
+if ~isfield(data,'sol')
+ data.sol = false;
+end
+if ~isfield(data,'select')
+ data.select = [];
+end
+if ~isfield(data,'post')
+ data.post = true;
+end
+
+if ~data.sol
+ data.select = [];
+end
+
+% Other initializations
+data.npg = 0;
+data.nps = 0;
+data.hfg = 0;
+data.hft = 0;
+data.hfs = 0;
+data.h = 0;
+data.q = 0;
+data.nst = 0;
+data.nfe = 0;
+data.nni = 0;
+data.netf = 0;
+data.ncfn = 0;
+data.N = 0;
+data.y = 0;
+
+%-------------------------------------------------------------------------
+
+function [] = graphical_init(n, hfg, npg, stats, cntr, ...
+ t, h, q, nst, nfe, nni, netf, ncfn)
+
+figure(hfg);
+pl = 0;
+
+% Time label and figure title
+
+tlab = '<- t <-';
+
+% Step size and order
+if stats
+ pl = pl+1;
+ subplot(npg,1,pl)
+ semilogy(t(1:n),abs(h(1:n)),'-');
+ hold on;
+ box on;
+ grid on;
+ xlabel(tlab);
+ ylabel('|Step size|');
+
+ pl = pl+1;
+ subplot(npg,1,pl)
+ plot(t(1:n),q(1:n),'-');
+ hold on;
+ box on;
+ grid on;
+ xlabel(tlab);
+ ylabel('Order');
+end
+
+% Counters
+if cntr
+ pl = pl+1;
+ subplot(npg,1,pl)
+ plot(t(1:n),nst(1:n),'k-');
+ hold on;
+ plot(t(1:n),nfe(1:n),'b-');
+ plot(t(1:n),nni(1:n),'r-');
+ plot(t(1:n),netf(1:n),'g-');
+ plot(t(1:n),ncfn(1:n),'c-');
+ box on;
+ grid on;
+ xlabel(tlab);
+ ylabel('Counters');
+end
+
+drawnow;
+
+%-------------------------------------------------------------------------
+
+function [] = graphical_update(n, hfg, npg, stats, cntr, ...
+ t, h, q, nst, nfe, nni, netf, ncfn)
+
+figure(hfg);
+pl = 0;
+
+% Step size and order
+if stats
+ pl = pl+1;
+ subplot(npg,1,pl)
+ hc = get(gca,'Children');
+ xd = [get(hc,'XData') ; t(1:n)'];
+ yd = [get(hc,'YData') ; abs(h(1:n)')];
+ set(hc, 'XData', xd, 'YData', yd);
+
+ pl = pl+1;
+ subplot(npg,1,pl)
+ hc = get(gca,'Children');
+ xd = [get(hc,'XData') ; t(1:n)'];
+ yd = [get(hc,'YData') ; q(1:n)'];
+ set(hc, 'XData', xd, 'YData', yd);
+end
+
+% Counters
+if cntr
+
+ pl = pl+1;
+
+ subplot(npg,1,pl)
+ hc = get(gca,'Children');
+
+ xd = [get(hc(1),'XData') ; t(1:n)'];
+
+ yd = [get(hc(5),'YData') ; ncfn(1:n)'];
+ set(hc(5), 'XData', xd, 'YData', yd);
+
+ yd = [get(hc(4),'YData') ; netf(1:n)'];
+ set(hc(4), 'XData', xd, 'YData', yd);
+
+ yd = [get(hc(3),'YData') ; nni(1:n)'];
+ set(hc(3), 'XData', xd, 'YData', yd);
+
+ yd = [get(hc(2),'YData') ; nfe(1:n)'];
+ set(hc(2), 'XData', xd, 'YData', yd);
+
+ yd = [get(hc(1),'YData') ; nst(1:n)'];
+ set(hc(1), 'XData', xd, 'YData', yd);
+
+end
+
+drawnow;
+
+%-------------------------------------------------------------------------
+
+function [] = graphical_final(hfg,npg,stats,cntr)
+
+figure(hfg);
+pl = 0;
+
+if stats
+ pl = pl+1;
+ subplot(npg,1,pl)
+ hc = get(gca,'Children');
+ xd = get(hc,'XData');
+ set(gca,'XLim',sort([xd(1) xd(end)]));
+
+ pl = pl+1;
+ subplot(npg,1,pl)
+ ylim = get(gca,'YLim');
+ ylim(1) = ylim(1) - 1;
+ ylim(2) = ylim(2) + 1;
+ set(gca,'YLim',ylim);
+ set(gca,'XLim',sort([xd(1) xd(end)]));
+end
+
+if cntr
+ pl = pl+1;
+ subplot(npg,1,pl)
+ hc = get(gca,'Children');
+ xd = get(hc(1),'XData');
+ set(gca,'XLim',sort([xd(1) xd(end)]));
+ legend('nst','nfe','nni','netf','ncfn',2);
+end
+
+%-------------------------------------------------------------------------
+
+function [] = sol_init(n, hfs, nps, sol, N, t, y)
+
+figure(hfs);
+
+% Time label
+
+tlab = '<- t <-';
+
+% Get number of colors in colormap
+map = colormap;
+ncols = size(map,1);
+
+% Initialize current subplot counter
+pl = 0;
+
+if sol
+
+ pl = pl+1;
+ subplot(nps,1,pl);
+ hold on;
+
+ for i = 1:N
+ hp = plot(t(1:n),y(i,1:n),'-');
+ ic = 1+(i-1)*floor(ncols/N);
+ set(hp,'Color',map(ic,:));
+ end
+ box on;
+ grid on;
+ xlabel(tlab);
+ ylabel('y');
+ title('Solution');
+
+end
+
+drawnow;
+
+%-------------------------------------------------------------------------
+
+function [] = sol_update(n, hfs, nps, sol, N, t, y)
+
+figure(hfs);
+
+pl = 0;
+
+if sol
+
+ pl = pl+1;
+ subplot(nps,1,pl);
+
+ hc = get(gca,'Children');
+ xd = [get(hc(1),'XData') ; t(1:n)'];
+
+ for i = 1:N
+ yd = [get(hc(i),'YData') ; y(i,1:n)'];
+ set(hc(i), 'XData', xd, 'YData', yd);
+ end
+
+end
+
+drawnow;
+
+
+%-------------------------------------------------------------------------
+
+function [] = sol_final(hfs, nps, sol, N)
+
+figure(hfs);
+
+pl = 0;
+
+if sol
+
+ pl = pl +1;
+ subplot(nps,1,pl);
+
+ hc = get(gca,'Children');
+ xd = get(hc(1),'XData');
+ set(gca,'XLim',sort([xd(1) xd(end)]));
+
+ ylim = get(gca,'YLim');
+ addon = 0.1*abs(ylim(2)-ylim(1));
+ ylim(1) = ylim(1) + sign(ylim(1))*addon;
+ ylim(2) = ylim(2) + sign(ylim(2))*addon;
+ set(gca,'YLim',ylim);
+
+ for i = 1:N
+ cstring{i} = sprintf('y_{%d}',i);
+ end
+ legend(cstring);
+
+end
+
+drawnow
diff --git a/sundialsTB/cvodes/CVodeMonitor_octave.m b/sundialsTB/cvodes/CVodeMonitor_octave.m
new file mode 100644
index 0000000..c960ea0
--- /dev/null
+++ b/sundialsTB/cvodes/CVodeMonitor_octave.m
@@ -0,0 +1,637 @@
+function [new_data] = CVodeMonitor(call, T, Y, YQ, YS, data)
+%CVodeMonitor is the default CVODES monitoring function.
+% To use it, set the Monitor property in CVodeSetOptions to
+% 'CVodeMonitor' or to @CVodeMonitor and 'MonitorData' to mondata
+% (defined as a structure).
+%
+% With default settings, this function plots the evolution of the step
+% size, method order, and various counters.
+%
+% Various properties can be changed from their default values by passing
+% to CVodeSetOptions, through the property 'MonitorData', a structure
+% MONDATA with any of the following fields. If a field is not defined,
+% the corresponding default value is used.
+%
+% Fields in MONDATA structure:
+% o stats [ {true} | false ]
+% If true, report the evolution of the step size and method order.
+% o cntr [ {true} | false ]
+% If true, report the evolution of the following counters:
+% nst, nfe, nni, netf, ncfn (see CVodeGetStats)
+% o sol [ true | {false} ]
+% If true, plot solution components.
+% o sensi [ true | {false} ]
+% If true and if FSA is enabled, plot sensitivity components.
+% o select [ array of integers ]
+% To plot only particular solution components, specify their indeces in
+% the field select. If not defined, but sol=true, all components are plotted.
+% o updt [ integer | {50} ]
+% Update frequency. Data is posted in blocks of dimension n.
+% o skip [ integer | {0} ]
+% Number of integrations steps to skip in collecting data to post.
+% o post [ {true} | false ]
+% If false, disable all posting. This option is necessary to disable
+% monitoring on some processors when running in parallel.
+%
+% See also CVodeSetOptions, CVMonitorFn
+%
+% NOTES:
+% 1. The argument mondata is REQUIRED. Even if only the default options
+% are desired, set mondata=struct; and pass it to CVodeSetOptions.
+% 2. The yQ argument is currently ignored.
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2007, The Regents of the University of California.
+% $Revision: 1.1 $Date: 2007/08/21 17:42:38 $
+
+% NOTES:
+% - Unlike Matlab, Octave loads children in the normal order
+% - Unlike Matlab, Octave stores 'XData' and 'YData' as column vectors
+
+if (nargin ~= 6)
+ error('Monitor data not defined.');
+end
+
+new_data = [];
+
+if call == 0
+
+% Initialize unspecified fields to default values.
+ data = initialize_data(data);
+
+% Open figure windows
+ if data.post
+
+ if data.stats | data.cntr
+ data.hfg = figure;
+ end
+% Number of subplots in figure hfg
+ if data.stats
+ data.npg = data.npg + 2;
+ end
+ if data.cntr
+ data.npg = data.npg + 1;
+ end
+
+ if data.sol | data.sensi
+ data.hfs = figure;
+ end
+
+ end
+
+% Initialize other private data
+ data.i = 0;
+ data.n = 1;
+ data.t = zeros(1,data.updt);
+ if data.stats
+ data.h = zeros(1,data.updt);
+ data.q = zeros(1,data.updt);
+ end
+ if data.cntr
+ data.nst = zeros(1,data.updt);
+ data.nfe = zeros(1,data.updt);
+ data.nni = zeros(1,data.updt);
+ data.netf = zeros(1,data.updt);
+ data.ncfn = zeros(1,data.updt);
+ end
+
+ data.first = true; % the next one will be the first call = 1
+ data.initialized = false; % the graphical windows were not initalized
+
+ new_data = data;
+
+ return;
+
+else
+
+% If this is the first call ~= 0,
+% use Y and YS for additional initializations
+
+ if data.first
+
+ if isempty(YS)
+ data.sensi = false;
+ end
+
+ if data.sol | data.sensi
+
+ if isempty(data.select)
+
+ data.N = length(Y);
+ data.select = [1:data.N];
+
+ else
+
+ data.N = length(data.select);
+
+ end
+
+ if data.sol
+ data.y = zeros(data.N,data.updt);
+ data.nps = data.nps + 1;
+ end
+
+ if data.sensi
+ data.Ns = size(YS,2);
+ data.ys = zeros(data.N, data.Ns, data.updt);
+ data.nps = data.nps + data.Ns;
+ end
+
+ end
+
+ data.first = false;
+
+ end
+
+% Extract variables from data
+
+ hfg = data.hfg;
+ hft = data.hft;
+ hfs = data.hfs;
+ npg = data.npg;
+ nps = data.nps;
+ i = data.i;
+ n = data.n;
+ t = data.t;
+ N = data.N;
+ Ns = data.Ns;
+ y = data.y;
+ ys = data.ys;
+ h = data.h;
+ q = data.q;
+ nst = data.nst;
+ nfe = data.nfe;
+ nni = data.nni;
+ netf = data.netf;
+ ncfn = data.ncfn;
+
+end
+
+
+% Load current statistics?
+
+if call == 1
+
+ if i ~= 0
+ i = i-1;
+ data.i = i;
+ new_data = data;
+ return;
+ end
+
+ si = CVodeGetStats;
+
+ t(n) = si.tcur;
+
+ if data.stats
+ h(n) = si.hlast;
+ q(n) = si.qlast;
+ end
+
+ if data.cntr
+ nst(n) = si.nst;
+ nfe(n) = si.nfe;
+ nni(n) = si.nni;
+ netf(n) = si.netf;
+ ncfn(n) = si.ncfn;
+ end
+
+ if data.sol
+ for j = 1:N
+ y(j,n) = Y(data.select(j));
+ end
+ end
+
+ if data.sensi
+ for k = 1:Ns
+ for j = 1:N
+ ys(j,k,n) = YS(data.select(j),k);
+ end
+ end
+ end
+
+end
+
+% Is it time to post?
+
+if data.post & (n == data.updt | call==2)
+
+ if call == 2
+ n = n-1;
+ end
+
+ if ~data.initialized
+
+ if (data.stats | data.cntr)
+ graphical_init(n, hfg, npg, data.stats, data.cntr, ...
+ t, h, q, nst, nfe, nni, netf, ncfn);
+ end
+
+ if data.sol | data.sensi
+ sol_init(n, hfs, nps, data.sol, data.sensi, ...
+ N, Ns, t, y, ys);
+ end
+
+ data.initialized = true;
+
+ else
+
+ if (data.stats | data.cntr)
+ graphical_update(n, hfg, npg, data.stats, data.cntr, ...
+ t, h, q, nst, nfe, nni, netf, ncfn);
+ end
+
+ if data.sol
+ sol_update(n, hfs, nps, data.sol, data.sensi, N, Ns, t, y, ys);
+ end
+
+ end
+
+ if call == 2
+
+ if (data.stats | data.cntr)
+ graphical_final(hfg, npg, data.cntr, data.stats);
+ end
+
+ if data.sol | data.sensi
+ sol_final(hfs, nps, data.sol, data.sensi, N, Ns);
+ end
+
+ return;
+
+ end
+
+ n = 1;
+
+else
+
+ n = n + 1;
+
+end
+
+
+% Save updated values in data
+
+data.i = data.skip;
+data.n = n;
+data.npg = npg;
+data.t = t;
+data.y = y;
+data.ys = ys;
+data.h = h;
+data.q = q;
+data.nst = nst;
+data.nfe = nfe;
+data.nni = nni;
+data.netf = netf;
+data.ncfn = ncfn;
+
+new_data = data;
+
+return;
+
+%-------------------------------------------------------------------------
+
+function data = initialize_data(data)
+
+if ~isfield(data,'updt')
+ data.updt = 50;
+end
+if ~isfield(data,'skip')
+ data.skip = 0;
+end
+if ~isfield(data,'stats')
+ data.stats = true;
+end
+if ~isfield(data,'cntr')
+ data.cntr = true;
+end
+if ~isfield(data,'sol')
+ data.sol = false;
+end
+if ~isfield(data,'sensi')
+ data.sensi = false;
+end
+if ~isfield(data,'select')
+ data.select = [];
+end
+if ~isfield(data,'post')
+ data.post = true;
+end
+
+if ~data.sol & ~data.sensi
+ data.select = [];
+end
+
+% Other initializations
+data.npg = 0;
+data.nps = 0;
+data.hfg = 0;
+data.hft = 0;
+data.hfs = 0;
+data.h = 0;
+data.q = 0;
+data.nst = 0;
+data.nfe = 0;
+data.nni = 0;
+data.netf = 0;
+data.ncfn = 0;
+data.N = 0;
+data.Ns = 0;
+data.y = 0;
+data.ys = 0;
+
+%-------------------------------------------------------------------------
+
+function [] = graphical_init(n, hfg, npg, stats, cntr, ...
+ t, h, q, nst, nfe, nni, netf, ncfn)
+
+figure(hfg);
+pl = 0;
+
+% Time label and figure title
+
+tlab = '-> t ->';
+
+% Step size and order
+if stats
+ pl = pl+1;
+ subplot(npg,1,pl)
+ semilogy(t(1:n),abs(h(1:n)),'-');
+ hold on;
+ box on;
+ grid on;
+ xlabel(tlab);
+ ylabel('|Step size|');
+
+ pl = pl+1;
+ subplot(npg,1,pl)
+ plot(t(1:n),q(1:n),'-');
+ hold on;
+ box on;
+ grid on;
+ xlabel(tlab);
+ ylabel('Order');
+end
+
+% Counters
+if cntr
+ pl = pl+1;
+ subplot(npg,1,pl)
+ plot(t(1:n),nst(1:n),'k-');
+ hold on;
+ plot(t(1:n),nfe(1:n),'b-');
+ plot(t(1:n),nni(1:n),'r-');
+ plot(t(1:n),netf(1:n),'g-');
+ plot(t(1:n),ncfn(1:n),'c-');
+ box on;
+ grid on;
+ xlabel(tlab);
+ ylabel('Counters');
+end
+
+drawnow;
+
+%-------------------------------------------------------------------------
+
+function [] = graphical_update(n, hfg, npg, stats, cntr, ...
+ t, h, q, nst, nfe, nni, netf, ncfn)
+
+figure(hfg);
+pl = 0;
+
+% Step size and order
+if stats
+ pl = pl+1;
+ subplot(npg,1,pl)
+ hc = get(gca,'Children');
+ xd = [get(hc,'XData') ; t(1:n)'];
+ yd = [get(hc,'YData') ; abs(h(1:n)')];
+ set(hc, 'XData', xd, 'YData', yd);
+
+ pl = pl+1;
+ subplot(npg,1,pl)
+ hc = get(gca,'Children');
+ xd = [get(hc,'XData') ; t(1:n)'];
+ yd = [get(hc,'YData') ; q(1:n)'];
+ set(hc, 'XData', xd, 'YData', yd);
+end
+
+% Counters
+if cntr
+ pl = pl+1;
+ subplot(npg,1,pl)
+ hc = get(gca,'Children');
+ xd = [get(hc(1),'XData') ; t(1:n)'];
+ yd = [get(hc(1),'YData') ; ncfn(1:n)'];
+ set(hc(1), 'XData', xd, 'YData', yd);
+ yd = [get(hc(2),'YData') ; netf(1:n)'];
+ set(hc(2), 'XData', xd, 'YData', yd);
+ yd = [get(hc(3),'YData') ; nni(1:n)'];
+ set(hc(3), 'XData', xd, 'YData', yd);
+ yd = [get(hc(4),'YData') ; nfe(1:n)'];
+ set(hc(4), 'XData', xd, 'YData', yd);
+ yd = [get(hc(5),'YData') ; nst(1:n)'];
+ set(hc(5), 'XData', xd, 'YData', yd);
+end
+
+drawnow;
+
+%-------------------------------------------------------------------------
+
+function [] = graphical_final(hfg,npg,stats,cntr)
+
+figure(hfg);
+pl = 0;
+
+if stats
+ pl = pl+1;
+ subplot(npg,1,pl)
+ hc = get(gca,'Children');
+ xd = get(hc,'XData');
+ set(gca,'XLim',sort([xd(1) xd(end)]));
+
+ pl = pl+1;
+ subplot(npg,1,pl)
+ ylim = get(gca,'YLim');
+ ylim(1) = ylim(1) - 1;
+ ylim(2) = ylim(2) + 1;
+ set(gca,'YLim',ylim);
+ set(gca,'XLim',sort([xd(1) xd(end)]));
+end
+
+if cntr
+ pl = pl+1;
+ subplot(npg,1,pl)
+ hc = get(gca,'Children');
+ xd = get(hc(1),'XData');
+ set(gca,'XLim',sort([xd(1) xd(end)]));
+ legend('nst','nfe','nni','netf','ncfn',2);
+end
+
+%-------------------------------------------------------------------------
+
+function [] = sol_init(n, hfs, nps, sol, sensi, N, Ns, t, y, ys)
+
+figure(hfs);
+
+% Time label
+
+tlab = '-> t ->';
+
+% Get number of colors in colormap
+map = colormap;
+ncols = size(map,1);
+
+% Initialize current subplot counter
+pl = 0;
+
+if sol
+
+ pl = pl+1;
+ subplot(nps,1,pl);
+ hold on;
+
+ for i = 1:N
+ hp = plot(t(1:n),y(i,1:n),'-');
+ ic = 1+(i-1)*floor(ncols/N);
+ set(hp,'Color',map(ic,:));
+ end
+ box on;
+ grid on;
+ xlabel(tlab);
+ ylabel('y');
+ title('Solution');
+
+end
+
+if sensi
+
+ for is = 1:Ns
+
+ pl = pl+1;
+ subplot(nps,1,pl);
+ hold on;
+
+ ys_crt = ys(:,is,1:n);
+ for i = 1:N
+ hp = plot(t(1:n),ys_crt(i,1:n),'-');
+ ic = 1+(i-1)*floor(ncols/N);
+ set(hp,'Color',map(ic,:));
+ end
+ box on;
+ grid on;
+ xlabel(tlab);
+ str = sprintf('s_{%d}',is); ylabel(str);
+ str = sprintf('Sensitivity %d',is); title(str);
+
+ end
+
+end
+
+
+drawnow;
+
+%-------------------------------------------------------------------------
+
+function [] = sol_update(n, hfs, nps, sol, sensi, N, Ns, t, y, ys)
+
+figure(hfs);
+
+pl = 0;
+
+if sol
+
+ pl = pl+1;
+ subplot(nps,1,pl);
+
+ hc = get(gca,'Children');
+ xd = [get(hc(1),'XData') ; t(1:n)'];
+ for i = 1:N
+ yd = [get(hc(i),'YData') ; y(i,1:n)'];
+ set(hc(i), 'XData', xd, 'YData', yd);
+ end
+
+end
+
+if sensi
+
+ for is = 1:Ns
+
+ pl = pl+1;
+ subplot(nps,1,pl);
+
+ ys_crt = ys(:,is,:);
+
+ hc = get(gca,'Children');
+ xd = [get(hc(1),'XData') ; t(1:n)'];
+ for i = 1:N
+ yd = [get(hc(i),'YData') ; ys_crt(i,1:n)'];
+ set(hc(i), 'XData', xd, 'YData', yd);
+ end
+
+ end
+
+end
+
+
+drawnow;
+
+
+%-------------------------------------------------------------------------
+
+function [] = sol_final(hfs, nps, sol, sensi, N, Ns)
+
+figure(hfs);
+
+pl = 0;
+
+if sol
+
+ pl = pl +1;
+ subplot(nps,1,pl);
+
+ hc = get(gca,'Children');
+ xd = get(hc(1),'XData');
+ set(gca,'XLim',sort([xd(1) xd(end)]));
+
+ ylim = get(gca,'YLim');
+ addon = 0.1*abs(ylim(2)-ylim(1));
+ ylim(1) = ylim(1) + sign(ylim(1))*addon;
+ ylim(2) = ylim(2) + sign(ylim(2))*addon;
+ set(gca,'YLim',ylim);
+
+ for i = 1:N
+ cstring{i} = sprintf('y_{%d}',i);
+ end
+ legend(cstring);
+
+end
+
+if sensi
+
+ for is = 1:Ns
+
+ pl = pl+1;
+ subplot(nps,1,pl);
+
+ hc = get(gca,'Children');
+ xd = get(hc(1),'XData');
+ set(gca,'XLim',sort([xd(1) xd(end)]));
+
+ ylim = get(gca,'YLim');
+ addon = 0.1*abs(ylim(2)-ylim(1));
+ ylim(1) = ylim(1) + sign(ylim(1))*addon;
+ ylim(2) = ylim(2) + sign(ylim(2))*addon;
+ set(gca,'YLim',ylim);
+
+ for i = 1:N
+ cstring{i} = sprintf('s%d_{%d}',is,i);
+ end
+ legend(cstring);
+
+ end
+
+end
+
+drawnow
diff --git a/sundialsTB/cvodes/CVodeQuadInit.m b/sundialsTB/cvodes/CVodeQuadInit.m
new file mode 100644
index 0000000..810e522
--- /dev/null
+++ b/sundialsTB/cvodes/CVodeQuadInit.m
@@ -0,0 +1,28 @@
+function status = CVodeQuadInit(fctQ, yQ0, options)
+%CVodeQuadInit allocates and initializes memory for quadrature integration.
+%
+% Usage: CVodeQuadInit ( QFUN, YQ0 [, OPTIONS ] )
+%
+% QFUN is a function defining the righ-hand sides of the quadrature
+% ODEs yQ' = fQ(t,y).
+% YQ0 is the initial conditions vector yQ(t0).
+% OPTIONS is an (optional) set of QUAD options, created with
+% the CVodeSetQuadOptions function.
+%
+% See also: CVodeSetQuadOptions, CVQuadRhsFn
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2007, The Regents of the University of California.
+% $Revision: 1.3 $Date: 2007/12/05 21:58:18 $
+
+mode = 2;
+
+if nargin < 2
+ error('Too few input arguments');
+end
+
+if nargin < 3
+ options = [];
+end
+
+status = cvm(mode, fctQ, yQ0, options);
diff --git a/sundialsTB/cvodes/CVodeQuadInitB.m b/sundialsTB/cvodes/CVodeQuadInitB.m
new file mode 100644
index 0000000..992d725
--- /dev/null
+++ b/sundialsTB/cvodes/CVodeQuadInitB.m
@@ -0,0 +1,32 @@
+function status = CVodeQuadInitB(idxB, fctQB, yQB0, optionsB)
+%CVodeQuadInitB allocates and initializes memory for backward quadrature integration.
+%
+% Usage: CVodeQuadInitB ( IDXB, QBFUN, YQB0 [, OPTIONS ] )
+%
+% IDXB is the index of the backward problem, returned by
+% CVodeInitB.
+% QBFUN is a function defining the righ-hand sides of the
+% backward ODEs yQB' = fQB(t,y,yB).
+% YQB0 is the final conditions vector yQB(tB0).
+% OPTIONS is an (optional) set of QUAD options, created with
+% the CVodeSetQuadOptions function.
+%
+% See also: CVodeInitB, CVodeSetQuadOptions, CVQuadRhsFnB
+%
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2007, The Regents of the University of California.
+% $Revision: 1.3 $Date: 2007/12/05 21:58:18 $
+
+mode = 6;
+
+if nargin < 3
+ error('Too few input arguments');
+end
+
+if nargin < 4
+ optionsB = [];
+end
+
+idxB = idxB-1;
+status = cvm(mode, idxB, fctQB, yQB0, optionsB);
diff --git a/sundialsTB/cvodes/CVodeQuadReInit.m b/sundialsTB/cvodes/CVodeQuadReInit.m
new file mode 100644
index 0000000..eef6173
--- /dev/null
+++ b/sundialsTB/cvodes/CVodeQuadReInit.m
@@ -0,0 +1,28 @@
+function status = CVodeQuadReInit(yQ0, options)
+%CVodeQuadReInit reinitializes CVODES's quadrature-related memory
+% assuming it has already been allocated in prior calls to CVodeInit
+% and CVodeQuadInit.
+%
+% Usage: CVodeQuadReInit ( YQ0 [, OPTIONS ] )
+%
+% YQ0 Initial conditions for quadrature variables yQ(t0).
+% OPTIONS is an (optional) set of QUAD options, created with
+% the CVodeSetQuadOptions function.
+%
+% See also: CVodeSetQuadOptions, CVodeQuadInit
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2007, The Regents of the University of California.
+% $Revision: 1.2 $Date: 2007/12/05 21:58:18 $
+
+mode = 12;
+
+if nargin < 1
+ error('Too few input arguments');
+end
+
+if nargin < 2
+ options = [];
+end
+
+status = cvm(mode, yQ0, options);
diff --git a/sundialsTB/cvodes/CVodeQuadReInitB.m b/sundialsTB/cvodes/CVodeQuadReInitB.m
new file mode 100644
index 0000000..5e821d0
--- /dev/null
+++ b/sundialsTB/cvodes/CVodeQuadReInitB.m
@@ -0,0 +1,30 @@
+function status = CVodeQuadReInitB(idxB, yQB0, optionsB)
+%CVodeQuadReInitB reinitializes memory for backward quadrature integration.
+%
+% Usage: CVodeQuadReInitB ( IDXB, YS0 [, OPTIONS ] )
+%
+% IDXB is the index of the backward problem, returned by
+% CVodeInitB.
+% YQB0 is the final conditions vector yQB(tB0).
+% OPTIONS is an (optional) set of QUAD options, created with
+% the CVodeSetQuadOptions function.
+%
+% See also: CVodeSetQuadOptions, CVodeReInitB, CVodeQuadInitB
+%
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2007, The Regents of the University of California.
+% $Revision: 1.2 $Date: 2007/12/05 21:58:18 $
+
+mode = 16;
+
+if nargin < 2
+ error('Too few input arguments');
+end
+
+if nargin < 3
+ optionsB = [];
+end
+
+idxB = idxB-1;
+status = cvm(mode, idxB, yQB0, optionsB);
diff --git a/sundialsTB/cvodes/CVodeQuadSetOptions.m b/sundialsTB/cvodes/CVodeQuadSetOptions.m
new file mode 100644
index 0000000..2e506c0
--- /dev/null
+++ b/sundialsTB/cvodes/CVodeQuadSetOptions.m
@@ -0,0 +1,64 @@
+function options = CVodeQuadSetOptions(varargin)
+%CVodeQuadSetOptions creates an options structure for quadrature integration with CVODES.
+%
+% Usage: OPTIONS = CVodeQuadSetOptions('NAME1',VALUE1,'NAME2',VALUE2,...)
+% OPTIONS = CVodeQuadSetOptions(OLDOPTIONS,'NAME1',VALUE1,...)
+%
+% OPTIONS = CVodeQuadSetOptions('NAME1',VALUE1,'NAME2',VALUE2,...) creates
+% a CVODES options structure OPTIONS in which the named properties have
+% the specified values. Any unspecified properties have default values.
+% It is sufficient to type only the leading characters that uniquely
+% identify the property. Case is ignored for property names.
+%
+% OPTIONS = CVodeQuadSetOptions(OLDOPTIONS,'NAME1',VALUE1,...) alters an
+% existing options structure OLDOPTIONS.
+%
+% CVodeQuadSetOptions with no input arguments displays all property names
+% and their possible values.
+%
+%CVodeQuadSetOptions properties
+%(See also the CVODES User Guide)
+%
+%ErrControl - Error control strategy for quadrature variables [ {false} | true ]
+% Specifies whether quadrature variables are included in the error test.
+%RelTol - Relative tolerance for quadrature variables [ scalar {1e-4} ]
+% Specifies the relative tolerance for quadrature variables. This parameter is
+% used only if ErrControl = true.
+%AbsTol - Absolute tolerance for quadrature variables [ scalar or vector {1e-6} ]
+% Specifies the absolute tolerance for quadrature variables. This parameter is
+% used only if ErrControl = true.
+%
+%SensDependent - Backward problem depending on sensitivities [ {false} | true ]
+% Specifies whether the backward problem quadrature right-hand side depends
+% on forward sensitivites. If TRUE, the right-hand side function provided for
+% this backward problem must have the appropriate type (see CVQuadRhsFnB).
+%
+%
+% See also
+% CVodeQuadInit, CVodeQuadReInit.
+% CVodeQuadInitB, CVodeQuadReInitB
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2007, The Regents of the University of California.
+% $Revision: 1.3 $Date: 2007/08/21 17:42:38 $
+
+% If called without input and output arguments, print out the possible keywords
+
+if (nargin == 0) && (nargout == 0)
+ fprintf(' ErrControl: [ {false} | true ]\n');
+ fprintf(' RelTol: [ positive scalar {1e-4} ]\n');
+ fprintf(' AbsTol: [ positive scalar or vector {1e-6} ]\n');
+ fprintf('\n');
+ fprintf(' SensDependent: [ {false} | true ]\n');
+ fprintf('\n');
+ return;
+end
+
+KeyNames = {
+ 'ErrControl'
+ 'RelTol'
+ 'AbsTol'
+ 'SensDependent'
+ };
+
+options = cvm_options(KeyNames,varargin{:});
diff --git a/sundialsTB/cvodes/CVodeReInit.m b/sundialsTB/cvodes/CVodeReInit.m
new file mode 100644
index 0000000..330dbad
--- /dev/null
+++ b/sundialsTB/cvodes/CVodeReInit.m
@@ -0,0 +1,32 @@
+function status = CVodeReInit(t0, y0, options)
+%CVodeReInit reinitializes memory for CVODES
+% where a prior call to CVodeInit has been made with the same
+% problem size N. CVodeReInit performs the same input checking
+% and initializations that CVodeInit does, but it does no
+% memory allocation, assuming that the existing internal memory
+% is sufficient for the new problem.
+%
+% Usage: CVodeReInit ( T0, Y0 [, OPTIONS ] )
+%
+% T0 is the initial value of t.
+% Y0 is the initial condition vector y(t0).
+% OPTIONS is an (optional) set of integration options, created with
+% the CVodeSetOptions function.
+%
+% See also: CVodeSetOptions, CVodeInit
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2007, The Regents of the University of California.
+% $Revision: 1.4 $Date: 2007/12/05 21:58:18 $
+
+mode = 11;
+
+if nargin < 2
+ error('Too few input arguments');
+end
+
+if nargin < 3
+ options = [];
+end
+
+status = cvm(mode, t0, y0, options);
diff --git a/sundialsTB/cvodes/CVodeReInitB.m b/sundialsTB/cvodes/CVodeReInitB.m
new file mode 100644
index 0000000..293d75a
--- /dev/null
+++ b/sundialsTB/cvodes/CVodeReInitB.m
@@ -0,0 +1,36 @@
+function status = CVodeReInitB(idxB, tB0, yB0, optionsB)
+%CVodeReInitB re-initializes backward memory for CVODES.
+% where a prior call to CVodeInitB has been made with the same
+% problem size NB. CVodeReInitB performs the same input checking
+% and initializations that CVodeInitB does, but it does no
+% memory allocation, assuming that the existing internal memory
+% is sufficient for the new problem.
+%
+% Usage: CVodeReInitB ( IDXB, TB0, YB0 [, OPTIONSB] )
+%
+% IDXB is the index of the backward problem, returned by
+% CVodeInitB.
+% TB0 is the final value of t.
+% YB0 is the final condition vector yB(tB0).
+% OPTIONSB is an (optional) set of integration options, created with
+% the CVodeSetOptions function.
+%
+% See also: CVodeSetOptions, CVodeInitB
+%
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2007, The Regents of the University of California.
+% $Revision: 1.4 $Date: 2007/12/05 21:58:18 $
+
+mode = 15;
+
+if nargin < 3
+ error('Too few input arguments');
+end
+
+if nargin < 4
+ optionsB = [];
+end
+
+idxB = idxB-1;
+status = cvm(mode,idxB,tB0,yB0,optionsB);
diff --git a/sundialsTB/cvodes/CVodeSensInit.m b/sundialsTB/cvodes/CVodeSensInit.m
new file mode 100644
index 0000000..d5424ba
--- /dev/null
+++ b/sundialsTB/cvodes/CVodeSensInit.m
@@ -0,0 +1,33 @@
+function status = CVodeSensInit(Ns,fctS,yS0,options)
+%CVodeSensInit allocates and initializes memory for FSA with CVODES.
+%
+% Usage: CVodeSensInit ( NS, SFUN, YS0 [, OPTIONS ] )
+%
+% NS is the number of parameters with respect to which sensitivities
+% are desired
+% SFUN is a function defining the righ-hand sides of the sensitivity
+% ODEs yS' = fS(t,y,yS).
+% YS0 Initial conditions for sensitivity variables.
+% YS0 must be a matrix with N rows and Ns columns, where N is the problem
+% dimension and Ns the number of sensitivity systems.
+% OPTIONS is an (optional) set of FSA options, created with
+% the CVodeSetFSAOptions function.
+%
+% See also CVodeSensSetOptions, CVodeInit, CVSensRhsFn
+%
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2007, The Regents of the University of California.
+% $Revision: 1.3 $Date: 2007/12/05 21:58:18 $
+
+mode = 3;
+
+if nargin < 3
+ error('Too few input arguments');
+end
+
+if nargin < 4
+ options = [];
+end
+
+status = cvm(mode, Ns, fctS, yS0, options);
diff --git a/sundialsTB/cvodes/CVodeSensReInit.m b/sundialsTB/cvodes/CVodeSensReInit.m
new file mode 100644
index 0000000..549cd5f
--- /dev/null
+++ b/sundialsTB/cvodes/CVodeSensReInit.m
@@ -0,0 +1,32 @@
+function status = CVodeSensReInit(yS0, options)
+%CVodeSensReInit reinitializes CVODES's FSA-related memory
+% assuming it has already been allocated in prior calls to CVodeInit
+% and CVodeSensInit.
+% The number of sensitivities Ns is assumed to be unchanged since the
+% previous call to CVodeSensInit.
+%
+% Usage: CVodeSensReInit ( YS0 [, OPTIONS ] )
+%
+% YS0 Initial conditions for sensitivity variables.
+% YS0 must be a matrix with N rows and Ns columns, where N is the problem
+% dimension and Ns the number of sensitivity systems.
+% OPTIONS is an (optional) set of FSA options, created with
+% the CVodeSensSetOptions function.
+%
+% See also: CVodeSensSetOptions, CVodeReInit, CVodeSensInit
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2007, The Regents of the University of California.
+% $Revision: 1.4 $Date: 2007/12/05 21:58:18 $
+
+mode = 13;
+
+if nargin < 1
+ error('Too few input arguments');
+end
+
+if nargin < 2
+ options = [];
+end
+
+status = cvm(mode, yS0, options);
diff --git a/sundialsTB/cvodes/CVodeSensSetOptions.m b/sundialsTB/cvodes/CVodeSensSetOptions.m
new file mode 100644
index 0000000..613e828
--- /dev/null
+++ b/sundialsTB/cvodes/CVodeSensSetOptions.m
@@ -0,0 +1,112 @@
+function options = CVodeSensSetOptions(varargin)
+%CVodeSensSetOptions creates an options structure for FSA with CVODES.
+%
+% Usage: OPTIONS = CVodeSensSetOptions('NAME1',VALUE1,'NAME2',VALUE2,...)
+% OPTIONS = CVodeSensSetOptions(OLDOPTIONS,'NAME1',VALUE1,...)
+%
+% OPTIONS = CVodeSensSetOptions('NAME1',VALUE1,'NAME2',VALUE2,...) creates
+% a CVODES options structure OPTIONS in which the named properties have
+% the specified values. Any unspecified properties have default values.
+% It is sufficient to type only the leading characters that uniquely
+% identify the property. Case is ignored for property names.
+%
+% OPTIONS = CVodeSensSetOptions(OLDOPTIONS,'NAME1',VALUE1,...) alters an
+% existing options structure OLDOPTIONS.
+%
+% CVodeSensSetOptions with no input arguments displays all property names
+% and their possible values.
+%
+%CVodeSensSetOptions properties
+%(See also the CVODES User Guide)
+%
+%method - FSA solution method [ 'Simultaneous' | {'Staggered'} ]
+% Specifies the FSA method for treating the nonlinear system solution for
+% sensitivity variables. In the simultaneous case, the nonlinear systems
+% for states and all sensitivities are solved simultaneously. In the
+% Staggered case, the nonlinear system for states is solved first and then
+% the nonlinear systems for all sensitivities are solved at the same time.
+%ParamField - Problem parameters [ string ]
+% Specifies the name of the field in the user data structure (specified through
+% the 'UserData' field with CVodeSetOptions) in which the nominal values of the problem
+% parameters are stored. This property is used only if CVODES will use difference
+% quotient approximations to the sensitivity right-hand sides (see CVSensRhsFn).
+%ParamList - Parameters with respect to which FSA is performed [ integer vector ]
+% Specifies a list of Ns parameters with respect to which sensitivities are to
+% be computed. This property is used only if CVODES will use difference-quotient
+% approximations to the sensitivity right-hand sides. Its length must be Ns,
+% consistent with the number of columns of yS0 (see CVodeSensInit).
+%ParamScales - Order of magnitude for problem parameters [ vector ]
+% Provides order of magnitude information for the parameters with respect to
+% which sensitivities are computed. This information is used if CVODES
+% approximates the sensitivity right-hand sides or if CVODES estimates integration
+% tolerances for the sensitivity variables (see RelTol and AbsTol).
+%RelTol - Relative tolerance for sensitivity variables [ positive scalar ]
+% Specifies the scalar relative tolerance for the sensitivity variables.
+% See also AbsTol.
+%AbsTol - Absolute tolerance for sensitivity variables [ row-vector or matrix ]
+% Specifies the absolute tolerance for sensitivity variables. AbsTol must be
+% either a row vector of dimension Ns, in which case each of its components is
+% used as a scalar absolute tolerance for the coresponding sensitivity vector,
+% or a N x Ns matrix, in which case each of its columns is used as a vector
+% of absolute tolerances for the corresponding sensitivity vector.
+% By default, CVODES estimates the integration tolerances for sensitivity
+% variables, based on those for the states and on the order of magnitude
+% information for the problem parameters specified through ParamScales.
+%ErrControl - Error control strategy for sensitivity variables [ false | {true} ]
+% Specifies whether sensitivity variables are included in the error control test.
+% Note that sensitivity variables are always included in the nonlinear system
+% convergence test.
+%DQtype - Type of DQ approx. of the sensi. RHS [{Centered} | Forward ]
+% Specifies whether to use centered (second-order) or forward (first-order)
+% difference quotient approximations of the sensitivity eqation right-hand
+% sides. This property is used only if a user-defined sensitivity right-hand
+% side function was not provided.
+%DQparam - Cut-off parameter for the DQ approx. of the sensi. RHS [ scalar | {0.0} ]
+% Specifies the value which controls the selection of the difference-quotient
+% scheme used in evaluating the sensitivity right-hand sides (switch between
+% simultaneous or separate evaluations of the two components in the sensitivity
+% right-hand side). The default value 0.0 indicates the use of simultaenous approximation
+% exclusively (centered or forward, depending on the value of DQtype.
+% For DQparam >= 1, CVODES uses a simultaneous approximation if the estimated
+% DQ perturbations for states and parameters are within a factor of DQparam,
+% and separate approximations otherwise. Note that a value DQparam < 1
+% will inhibit switching! This property is used only if a user-defined sensitivity
+% right-hand side function was not provided.
+%
+% See also
+% CVodeSensInit, CVodeSensReInit
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2007, The Regents of the University of California.
+% $Revision: 1.3 $Date: 2007/08/21 17:42:38 $
+
+% If called without input and output arguments, print out the possible keywords
+
+if (nargin == 0) & (nargout == 0)
+ fprintf(' method: [ Simultaneous | {Staggered} ]\n');
+ fprintf(' ParamField: [ string ]\n');
+ fprintf(' ParamList: [ integer vector ]\n');
+ fprintf(' ParamScales: [ vector ]\n');
+ fprintf(' RelTol: [ positive scalar ]\n');
+ fprintf(' AbsTol: [ row-vector or matrix ]\n');
+ fprintf(' ErrControl: [ false | {true} ]\n');
+ fprintf(' DQtype: [ {Centered} | {Forward} ]\n');
+ fprintf(' DQparam: [ scalar | {0.0} ]\n');
+ fprintf('\n');
+ return;
+end
+
+KeyNames = {
+ 'method'
+ 'ParamField'
+ 'ParamList'
+ 'ParamScales'
+ 'RelTol'
+ 'AbsTol'
+ 'ErrControl'
+ 'DQtype'
+ 'DQparam'
+ };
+
+options = cvm_options(KeyNames,varargin{:});
+
diff --git a/sundialsTB/cvodes/CVodeSensToggleOff.m b/sundialsTB/cvodes/CVodeSensToggleOff.m
new file mode 100644
index 0000000..658ff48
--- /dev/null
+++ b/sundialsTB/cvodes/CVodeSensToggleOff.m
@@ -0,0 +1,16 @@
+function status = CVodeSensToggleOff()
+% CVodeSensToggleOff deactivates sensitivity calculations.
+% It does NOT deallocate sensitivity-related memory so that
+% sensitivity computations can be later toggled ON (through
+% CVodeSensReInit).
+%
+% Usage: CVodeSensToggleOff
+%
+% See also: CVodeSensInit, CVodeSensReInit
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2007, The Regents of the University of California.
+% $Revision: 1.3 $Date: 2007/12/05 21:58:18 $
+
+mode = 18;
+status = cvm(mode);
diff --git a/sundialsTB/cvodes/CVodeSet.m b/sundialsTB/cvodes/CVodeSet.m
new file mode 100644
index 0000000..50ff082
--- /dev/null
+++ b/sundialsTB/cvodes/CVodeSet.m
@@ -0,0 +1,52 @@
+function status = CVodeSet(varargin)
+%CVodeSet changes optional input values during the integration.
+%
+% Usage: CVodeSet('NAME1',VALUE1,'NAME2',VALUE2,...)
+%
+% CVodeSet can be used to change some of the optional inputs during
+% the integration, i.e., without need for a solver reinitialization.
+% The property names accepted by CVodeSet are a subset of those valid
+% for CVodeSetOptions. Any unspecified properties are left unchanged.
+%
+% CVodeSet with no input arguments displays all property names.
+%
+%CVodeSet properties
+%(See also the CVODES User Guide)
+%
+%UserData - problem data passed unmodified to all user functions.
+% Set VALUE to be the new user data.
+%RelTol - Relative tolerance
+% Set VALUE to the new relative tolerance
+%AbsTol - absolute tolerance
+% Set VALUE to be either the new scalar absolute tolerance or
+% a vector of absolute tolerances, one for each solution component.
+%StopTime - Stopping time
+% Set VALUE to be a new value for the independent variable past which
+% the solution is not to proceed.
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2007, The Regents of the University of California.
+% $Revision: 1.2 $Date: 2007/12/05 21:58:18 $
+
+if (nargin == 0)
+ fprintf(' UserData\n');
+ fprintf('\n');
+ fprintf(' RelTol\n');
+ fprintf(' AbsTol\n');
+ fprintf(' StopTime\n');
+ fprintf('\n');
+ return;
+end
+
+KeyNames = {
+ 'UserData'
+ 'RelTol'
+ 'AbsTol'
+ 'StopTime'
+ };
+
+options = cvm_options(KeyNames,varargin{:});
+
+mode = 33;
+
+status = cvm(mode, options);
diff --git a/sundialsTB/cvodes/CVodeSetB.m b/sundialsTB/cvodes/CVodeSetB.m
new file mode 100644
index 0000000..cae4ad8
--- /dev/null
+++ b/sundialsTB/cvodes/CVodeSetB.m
@@ -0,0 +1,48 @@
+function status = CVodeSetB(idxB, varargin)
+%CVodeSetB changes optional input values during the integration.
+%
+% Usage: CVodeSetB( IDXB, 'NAME1',VALUE1,'NAME2',VALUE2,... )
+%
+% CVodeSetB can be used to change some of the optional inputs for
+% the backward problem identified by IDXB during the backward
+% integration, i.e., without need for a solver reinitialization.
+% The property names accepted by CVodeSet are a subset of those valid
+% for CVodeSetOptions. Any unspecified properties are left unchanged.
+%
+% CVodeSetB with no input arguments displays all property names.
+%
+%CVodeSetB properties
+%(See also the CVODES User Guide)
+%
+%UserData - problem data passed unmodified to all user functions.
+% Set VALUE to be the new user data.
+%RelTol - Relative tolerance
+% Set VALUE to the new relative tolerance
+%AbsTol - absolute tolerance
+% Set VALUE to be either the new scalar absolute tolerance or
+% a vector of absolute tolerances, one for each solution component.
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2007, The Regents of the University of California.
+% $Revision: 1.2 $Date: 2007/12/05 21:58:18 $
+
+if (nargin == 0)
+ fprintf(' UserData\n');
+ fprintf('\n');
+ fprintf(' RelTol\n');
+ fprintf(' AbsTol\n');
+ fprintf('\n');
+ return;
+end
+
+KeyNames = {
+ 'UserData'
+ 'RelTol'
+ 'AbsTol'
+ };
+
+options = cvm_options(KeyNames,varargin{:});
+
+mode = 34;
+
+status = cvm(mode, idxB, options);
diff --git a/sundialsTB/cvodes/CVodeSetOptions.m b/sundialsTB/cvodes/CVodeSetOptions.m
new file mode 100644
index 0000000..e2f87a7
--- /dev/null
+++ b/sundialsTB/cvodes/CVodeSetOptions.m
@@ -0,0 +1,300 @@
+function options = CVodeSetOptions(varargin)
+%CVodeSetOptions creates an options structure for CVODES.
+%
+% Usage: OPTIONS = CVodeSetOptions('NAME1',VALUE1,'NAME2',VALUE2,...)
+% OPTIONS = CVodeSetOptions(OLDOPTIONS,'NAME1',VALUE1,...)
+%
+% OPTIONS = CVodeSetOptions('NAME1',VALUE1,'NAME2',VALUE2,...) creates
+% a CVODES options structure OPTIONS in which the named properties have
+% the specified values. Any unspecified properties have default values.
+% It is sufficient to type only the leading characters that uniquely
+% identify the property. Case is ignored for property names.
+%
+% OPTIONS = CVodeSetOptions(OLDOPTIONS,'NAME1',VALUE1,...) alters an
+% existing options structure OLDOPTIONS.
+%
+% CVodeSetOptions with no input arguments displays all property names
+% and their possible values.
+%
+%CVodeSetOptions properties
+%(See also the CVODES User Guide)
+%
+%UserData - User data passed unmodified to all functions [ empty ]
+% If UserData is not empty, all user provided functions will be
+% passed the problem data as their last input argument. For example,
+% the RHS function must be defined as YD = ODEFUN(T,Y,DATA).
+%
+%LMM - Linear Multistep Method [ 'Adams' | {'BDF'} ]
+% This property specifies whether the Adams method is to be used instead
+% of the default Backward Differentiation Formulas (BDF) method.
+% The Adams method is recommended for non-stiff problems, while BDF is
+% recommended for stiff problems.
+%NonlinearSolver - Type of nonlinear solver used [ Functional | {Newton} ]
+% The 'Functional' nonlinear solver is best suited for non-stiff
+% problems, in conjunction with the 'Adams' linear multistep method,
+% while 'Newton' is better suited for stiff problems, using the 'BDF'
+% method.
+%RelTol - Relative tolerance [ positive scalar | {1e-4} ]
+% RelTol defaults to 1e-4 and is applied to all components of the solution
+% vector. See AbsTol.
+%AbsTol - Absolute tolerance [ positive scalar or vector | {1e-6} ]
+% The relative and absolute tolerances define a vector of error weights
+% with components
+% ewt(i) = 1/(RelTol*|y(i)| + AbsTol) if AbsTol is a scalar
+% ewt(i) = 1/(RelTol*|y(i)| + AbsTol(i)) if AbsTol is a vector
+% This vector is used in all error and convergence tests, which
+% use a weighted RMS norm on all error-like vectors v:
+% WRMSnorm(v) = sqrt( (1/N) sum(i=1..N) (v(i)*ewt(i))^2 ),
+% where N is the problem dimension.
+%MaxNumSteps - Maximum number of steps [positive integer | {500}]
+% CVode will return with an error after taking MaxNumSteps internal steps
+% in its attempt to reach the next output time.
+%InitialStep - Suggested initial stepsize [ positive scalar ]
+% By default, CVode estimates an initial stepsize h0 at the initial time
+% t0 as the solution of
+% WRMSnorm(h0^2 ydd / 2) = 1
+% where ydd is an estimated second derivative of y(t0).
+%MaxStep - Maximum stepsize [ positive scalar | {inf} ]
+% Defines an upper bound on the integration step size.
+%MinStep - Minimum stepsize [ positive scalar | {0.0} ]
+% Defines a lower bound on the integration step size.
+%MaxOrder - Maximum method order [ 1-12 for Adams, 1-5 for BDF | {5} ]
+% Defines an upper bound on the linear multistep method order.
+%StopTime - Stopping time [ scalar ]
+% Defines a value for the independent variable past which the solution
+% is not to proceed.
+%RootsFn - Rootfinding function [ function ]
+% To detect events (roots of functions), set this property to the event
+% function. See CVRootFn.
+%NumRoots - Number of root functions [ integer | {0} ]
+% Set NumRoots to the number of functions for which roots are monitored.
+% If NumRoots is 0, rootfinding is disabled.
+%StabilityLimDet - Stability limit detection algorithm [ {false} | true ]
+% Flag used to turn on or off the stability limit detection algorithm
+% within CVODES. This property can be used only with the BDF method.
+% In this case, if the order is 3 or greater and if the stability limit
+% is detected, the method order is reduced.
+%
+%LinearSolver - Linear solver type [{Dense}|Diag|Band|GMRES|BiCGStab|TFQMR]
+% Specifies the type of linear solver to be used for the Newton nonlinear
+% solver (see NonlinearSolver). Valid choices are: Dense (direct, dense
+% Jacobian), Band (direct, banded Jacobian), Diag (direct, diagonal Jacobian),
+% GMRES (iterative, scaled preconditioned GMRES), BiCGStab (iterative, scaled
+% preconditioned stabilized BiCG), TFQMR (iterative, scaled transpose-free QMR).
+% The GMRES, BiCGStab, and TFQMR are matrix-free linear solvers.
+%JacobianFn - Jacobian function [ function ]
+% This propeerty is overloaded. Set this value to a function that returns
+% Jacobian information consistent with the linear solver used (see Linsolver).
+% If not specified, CVODES uses difference quotient approximations.
+% For the Dense linear solver, JacobianFn must be of type CVDenseJacFn and
+% must return a dense Jacobian matrix. For the Band linear solver, JacobianFn
+% must be of type CVBandJacFn and must return a banded Jacobian matrix.
+% For the iterative linear solvers, GMRES, BiCGStab, and TFQMR, JacobianFn must
+% be of type CVJacTimesVecFn and must return a Jacobian-vector product. This
+% property is not used for the Diag linear solver.
+% If these options are for a backward problem, the corresponding funciton types
+% are CVDenseJacFnB for the Dense linear solver, CVBandJacFnB for he band linear
+% solver, and CVJacTimesVecFnB for the iterative linear solvers.
+%KrylovMaxDim - Maximum number of Krylov subspace vectors [ integer | {5} ]
+% Specifies the maximum number of vectors in the Krylov subspace. This property
+% is used only if an iterative linear solver, GMRES, BiCGStab, or TFQMR is used
+% (see LinSolver).
+%GramSchmidtType - Gram-Schmidt orthogonalization [ Classical | {Modified} ]
+% Specifies the type of Gram-Schmidt orthogonalization (classical or modified).
+% This property is used only if the GMRES linear solver is used (see LinSolver).
+%PrecType - Preconditioner type [ Left | Right | Both | {None} ]
+% Specifies the type of user preconditioning to be done if an iterative linear
+% solver, GMRES, BiCGStab, or TFQMR is used (see LinSolver). PrecType must be
+% one of the following: 'None', 'Left', 'Right', or 'Both', corresponding to no
+% preconditioning, left preconditioning only, right preconditioning only, and
+% both left and right preconditioning, respectively.
+%PrecModule - Preconditioner module [ BandPre | BBDPre | {UserDefined} ]
+% If PrecModule = 'UserDefined', then the user must provide at least a
+% preconditioner solve function (see PrecSolveFn)
+% CVODES provides the following two general-purpose preconditioner modules:
+% BandPre provide a band matrix preconditioner based on difference quotients
+% of the ODE right-hand side function. The user must specify the lower and
+% upper half-bandwidths through the properties LowerBwidth and UpperBwidth,
+% respectively.
+% BBDPre can be only used with parallel vectors. It 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) (see GlocalFn). The blocks are generated by a difference quotient
+% scheme on each processor independently. This scheme utilizes an assumed
+% banded structure with given half-bandwidths, mldq and mudq (specified through
+% LowerBwidthDQ and UpperBwidthDQ, respectively). However, the banded Jacobian
+% block kept by the scheme has half-bandwiths ml and mu (specified through
+% LowerBwidth and UpperBwidth), which may be smaller.
+%PrecSetupFn - Preconditioner setup function [ function ]
+% If PrecType is not 'None', PrecSetupFn specifies an optional function which,
+% together with PrecSolve, defines left and right preconditioner matrices
+% (either of which can be trivial), such that the product P1*P2 is an
+% aproximation to the Newton matrix. PrecSetupFn must be of type CVPrecSetupFn
+% or CVPrecSetupFnB for forward and backward problems, respectively.
+%PrecSolveFn - Preconditioner solve function [ function ]
+% If PrecType is not 'None', PrecSolveFn specifies a required function which
+% must solve a linear system Pz = r, for given r. PrecSolveFn must be of type
+% CVPrecSolveFn or CVPrecSolveFnB for forward and backward problems, respectively.
+%GlocalFn - Local right-hand side approximation funciton for BBDPre [ function ]
+% If PrecModule is BBDPre, GlocalFn specifies a required function that
+% evaluates a local approximation to the ODE right-hand side. GlocalFn must
+% be of type CVGlocFn or CVGlocFnB for forward and backward problems, respectively.
+%GcommFn - Inter-process communication function for BBDPre [ function ]
+% If PrecModule is BBDPre, GcommFn specifies an optional function
+% to perform any inter-process communication required for the evaluation of
+% GlocalFn. GcommFn must be of type CVGcommFn or CVGcommFnB for forward and
+% backward problems, respectively.
+%LowerBwidth - Jacobian/preconditioner lower bandwidth [ integer | {0} ]
+% This property is overloaded. If the Band linear solver is used (see LinSolver),
+% it specifies the lower half-bandwidth of the band Jacobian approximation.
+% If one of the three iterative linear solvers, GMRES, BiCGStab, or TFQMR is used
+% (see LinSolver) and if the BBDPre preconditioner module in CVODES is used
+% (see PrecModule), it specifies the lower half-bandwidth of the retained
+% banded approximation of the local Jacobian block. If the BandPre preconditioner
+% module (see PrecModule) is used, it specifies the lower half-bandwidth of
+% the band preconditioner matrix. LowerBwidth defaults to 0 (no sub-diagonals).
+%UpperBwidth - Jacobian/preconditioner upper bandwidth [ integer | {0} ]
+% This property is overloaded. If the Band linear solver is used (see LinSolver),
+% it specifies the upper half-bandwidth of the band Jacobian approximation.
+% If one of the three iterative linear solvers, GMRES, BiCGStab, or TFQMR is used
+% (see LinSolver) and if the BBDPre preconditioner module in CVODES is used
+% (see PrecModule), it specifies the upper half-bandwidth of the retained
+% banded approximation of the local Jacobian block. If the BandPre
+% preconditioner module (see PrecModule) is used, it specifies the upper
+% half-bandwidth of the band preconditioner matrix. UpperBwidth defaults to
+% 0 (no super-diagonals).
+%LowerBwidthDQ - BBDPre preconditioner DQ lower bandwidth [ integer | {0} ]
+% Specifies the lower half-bandwidth used in the difference-quotient Jacobian
+% approximation for the BBDPre preconditioner (see PrecModule).
+%UpperBwidthDQ - BBDPre preconditioner DQ upper bandwidth [ integer | {0} ]
+% Specifies the upper half-bandwidth used in the difference-quotient Jacobian
+% approximation for the BBDPre preconditioner (see PrecModule).
+%
+%MonitorFn - User-provied monitoring function [ function ]
+% Specifies a function that is called after each successful integration step.
+% This function must have type CVMonitorFn or CVMonitorFnB, depending on
+% whether these options are for a forward or a backward problem, respectively.
+% Sample monitoring functions CVodeMonitor and CvodeMonitorB are provided
+% with CVODES.
+%MonitorData - User-provied data for the monitoring function [ struct ]
+% Specifies a data structure that is passed to the MonitorFn function every
+% time it is called.
+%
+%SensDependent - Backward problem depending on sensitivities [ {false} | true ]
+% Specifies whether the backward problem right-hand side depends on
+% forward sensitivites. If TRUE, the right-hand side function provided for
+% this backward problem must have the appropriate type (see CVRhsFnB).
+%
+%ErrorMessages - Post error/warning messages [ {true} | false ]
+% Note that any errors in CVodeInit will result in a Matlab error, thus
+% stoping execution. Only subsequent calls to CVODES functions will respect
+% the value specified for 'ErrorMessages'.
+%
+%NOTES:
+%
+% The properties listed above that can only be used for forward problems
+% are: StopTime, RootsFn, and NumRoots.
+%
+% The property SensDependent is relevant only for backward problems.
+%
+%
+% See also
+% CVodeInit, CVodeReInit, CVodeInitB, CVodeReInitB
+% CVRhsFn, CVRootFn,
+% CVDenseJacFn, CVBandJacFn, CVJacTimesVecFn
+% CVPrecSetupFn, CVPrecSolveFn
+% CVGlocalFn, CVGcommFn
+% CVMonitorFn
+% CVRhsFnB,
+% CVDenseJacFnB, CVBandJacFnB, CVJacTimesVecFnB
+% CVPrecSetupFnB, CVPrecSolveFnB
+% CVGlocalFnB, CVGcommFnB
+% CVMonitorFnB
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2007, The Regents of the University of California.
+% $Revision: 1.9 $Date: 2007/12/05 21:58:18 $
+
+% If called without input and output arguments, print out the possible keywords
+
+if (nargin == 0) && (nargout == 0)
+ fprintf(' UserData: [ empty ]\n');
+ fprintf('\n');
+ fprintf(' LMM: [ Adams | {BDF} ]\n');
+ fprintf(' NonlinearSolver: [ Functional | {Newton} ]\n');
+ fprintf(' RelTol: [ positive scalar | {1e-4} ]\n');
+ fprintf(' AbsTol: [ positive scalar or vector | {1e-6} ]\n');
+ fprintf(' MaxNumSteps: [ positive integer | {500} ]\n');
+ fprintf(' InitialStep: [ positive scalar ]\n');
+ fprintf(' MaxStep: [ positive scalar | {inf} ]\n');
+ fprintf(' MinStep: [ positive scalar | {0.0} ]\n');
+ fprintf(' MaxOrder: [ 1-12 for Adams, 1-5 for BDF | {5} ]\n');
+ fprintf(' StopTime: [ scalar ]\n');
+ fprintf(' RootsFn: [ function ]\n');
+ fprintf(' NumRoots: [ integer | {0} ]\n');
+ fprintf(' StabilityLimDet: [ {false} | true ]\n');
+ fprintf('\n');
+ fprintf(' LinearSolver: [ {Dense} | Diag | Band | GMRES | BiCGStab | TFQMR ]\n');
+ fprintf(' JacobianFn: [ function ]\n');
+ fprintf(' KrylovMaxDim: [ integer | {5} ]\n');
+ fprintf(' GramSchmidtType: [ Classical | {Modified} ]\n');
+ fprintf(' PrecType: [ Left | Right | Both | {None} ]\n');
+ fprintf(' PrecModule: [ BandPre | BBDPre | {UserDefined} ]\n');
+ fprintf(' PrecSetupFn: [ function ]\n');
+ fprintf(' PrecSolveFn: [ function ]\n');
+ fprintf(' GlocalFn: [ function ]\n');
+ fprintf(' GcommFn: [ function ]\n');
+ fprintf(' LowerBwidth: [ integer | {0} ]\n');
+ fprintf(' UpperBwidth: [ integer | {0} ]\n');
+ fprintf(' LowerBwidthDQ: [ integer | {0} ]\n');
+ fprintf(' UpperBwidthDQ: [ integer | {0} ]\n');
+ fprintf('\n');
+ fprintf(' MonitorFn: [ function ]\n');
+ fprintf(' MonitorData: [ struct ]\n');
+ fprintf('\n');
+ fprintf(' SensDependent: [ {false} | true ]\n');
+ fprintf('\n');
+ fprintf(' ErrorMessages: [ false | {true} ]\n');
+ fprintf('\n');
+ return;
+end
+
+KeyNames = {
+ 'UserData'
+ 'LMM'
+ 'NonlinearSolver'
+ 'RelTol'
+ 'AbsTol'
+ 'MaxNumSteps'
+ 'InitialStep'
+ 'MaxStep'
+ 'MinStep'
+ 'MaxOrder'
+ 'StopTime'
+ 'RootsFn'
+ 'NumRoots'
+ 'StabilityLimDet'
+ 'LinearSolver'
+ 'JacobianFn'
+ 'PrecType'
+ 'PrecModule'
+ 'PrecSetupFn'
+ 'PrecSolveFn'
+ 'KrylovMaxDim'
+ 'GramSchmidtType'
+ 'GlocalFn'
+ 'GcommFn'
+ 'LowerBwidth'
+ 'UpperBwidth'
+ 'LowerBwidthDQ'
+ 'UpperBwidthDQ'
+ 'MonitorFn'
+ 'MonitorData'
+ 'SensDependent'
+ 'ErrorMessages'
+ };
+
+options = cvm_options(KeyNames,varargin{:});
+
diff --git a/sundialsTB/cvodes/Contents.m b/sundialsTB/cvodes/Contents.m
new file mode 100644
index 0000000..c82947a
--- /dev/null
+++ b/sundialsTB/cvodes/Contents.m
@@ -0,0 +1,115 @@
+% CVODES, an ODE integrator with sensitivity analysis capabilities
+%
+% The Matlab interface to the SUNDIALS solver CVODES provides access
+% to all functionality of the underlying solver, including IVP simulation
+% and sensitvity analysis (both forward and adjoint).
+%
+% The interface consists of several user-callable functions. In addition,
+% the user must provide several required and optional user-supplied
+% functions which define the problem to be solved. The user-callable
+% functions and the types of user-supplied functions are listed below.
+% For completness, some functions appear more than once.
+%
+% Functions for ODE integration
+%
+% CVodeSetOptions - create an options structure for an ODE problem.
+% CVodeQuadSetOptions - create an options structure for quadrature integration.
+% CVodeInit - allocate and initialize memory for CVODES.
+% CVodeQuadInit - allocate and initialize memory for quadrature integration.
+% CVodeReInit - reinitialize memory for CVODES.
+% CVodeQuadReInit - reinitialize memory for quadrature integration.
+% CVode - integrate the ODE problem.
+% CVodeGetStats - return statistics for the CVODES solver.
+% CVodeGet - extract data from CVODES memory.
+% CVodeFree - deallocate memory for the CVODES solver.
+%
+% Functions for forward sensitivity analysis
+%
+% CVodeSetOptions - create an options structure for an ODE problem.
+% CVodeQuadSetOptions - create an options structure for quadrature integration.
+% CVodeSensSetOptions - create an options structure for FSA.
+% CVodeInit - allocate and initialize memory for CVODES.
+% CVodeQuadInit - allocate and initialize memory for quadrature integration.
+% CVodeSensInit - allocate and initialize memory for FSA.
+% CVodeReInit - reinitialize memory for CVODES.
+% CVodeQuadReInit - reinitialize memory for quadrature integration.
+% CVodeSensReInit - reinitialize memory for FSA.
+% CVodeSensToggleOff - temporarily deactivates FSA.
+% CVode - integrate the ODE problem.
+% CVodeGetStats - return statistics for the CVODES solver.
+% CVodeGet - extract data from CVODES memory.
+% CVodeFree - deallocate memory for the CVODES solver.
+%
+% Functions for adjoint sensitivity analysis
+%
+% CVodeSetOptions - create an options structure for an ODE problem.
+% CVodeQuadSetOptions - create an options structure for quadrature integration.
+% CVodeInit - allocate and initialize memory for the forward problem.
+% CVodeQuadInit - allocate and initialize memory for forward quadrature integration.
+% CVodeQuadReInit - reinitialize memory for forward quadrature integration.
+% CVodeReInit - reinitialize memory for the forward problem.
+% CVodeAdjInit - allocate and initialize memory for ASA.
+% CVodeInitB - allocate and initialize a backward problem.
+% CVodeAdjReInit - reinitialize memory for ASA.
+% CVodeReInitB - reinitialize a backward problem.
+% CVode - integrate the forward ODE problem.
+% CVodeB - integrate the backward problems.
+% CVodeGetStats - return statistics for the integration of the forward problem.
+% CVodeGetStatsB - return statistics for the integration of a backward problem.
+% CVodeGet - extract data from CVODES memory.
+% CVodeFree - deallocate memory for the CVODES solver.
+%
+% User-supplied function types for forward problems
+%
+% CVRhsFn - RHS function
+% CVRootFn - root-finding function
+% CVQuadRhsFn - quadrature RHS function
+% CVSensRhsFn - sensitivity RHS function
+% CVDenseJacFn - dense Jacobian function
+% CVBandJacFn - banded Jacobian function
+% CVJacTimesVecFn - Jacobian times vector function
+% CVPrecSetupFn - preconditioner setup function
+% CVPrecSolveFn - preconditioner solve function
+% CVGlocalFn - RHS approximation function (BBDPre)
+% CVGcomFn - communication function (BBDPre)
+% CVMonitorFn - monitoring function
+%
+% User-supplied function types for backward problems
+%
+% CVRhsFnB - RHS function
+% CVQuadRhsFnB - quadrature RHS function
+% CVDenseJacFnB - dense Jacobian function
+% CVBandJacFnB - banded Jacobian function
+% CVJacTimesVecFnB - Jacobian times vector function
+% CVPrecSetupFnB - preconditioner setup function
+% CVPrecSolveFnB - preconditioner solve function
+% CVGlocalFnB - RHS approximation function (BBDPre)
+% CVGcomFnB - communication function (BBDPre)
+% CVMonitorFnB - monitoring function
+%
+% Serial examples provided with the toolbox
+%
+% mcvsRoberts_dns - chemical kinetics problem
+% mcvsRoberts_FSA_dns - FSA for the robertson problem
+% mcvsRoberts_ASAi_dns - ASA for the robertson problem
+% mcvsAdvDiff_bnd - advection-diffusion PDE
+% mcvsDiurnal_kry - 2D, 2-species, time dependent PDE
+% mcvsPleiades_non - nonstiff celestial mechanics problem
+% mcvsVanDPol_dns - Van der Pol problem
+% mcvsPollut_FSA_dns - FSA for pollution chemical kinetics
+% mcvsOzone_FSA_dns - FSA for ozone chemical kinetics
+% mcvsDiscRHS_dns - integration over RHS discontinuities
+% mcvsDiscSOL_dns - integration over solution discontinuities
+% mcvsHessian_FSA_ASA - illustration for computing Hessian information
+% (forward-over-adjoint approach)
+%
+% Parallel examples provided with the toolbox
+%
+% mcvsDecoupl_non_p - diagonal ODE example
+% mcvsAdvDiff_FSA_non_p - FSA for 1D adv-diff problem (Adams, Functional)
+% mcvsAtmDisp_kry_bbd_p - 3D adv-diff with distributed source problem
+% (BDF, Newton, GMRES, BBDPre preconditioner)
+% Use the mpirun function to run any of the parallel examples
+%
+% See also nvector, putils
+
diff --git a/sundialsTB/cvodes/cvm/Contents.m b/sundialsTB/cvodes/cvm/Contents.m
new file mode 100644
index 0000000..b53c72b
--- /dev/null
+++ b/sundialsTB/cvodes/cvm/Contents.m
@@ -0,0 +1,3 @@
+% MEX binding of CVODES functions
+%
+%-- Radu Serban @ LLNL -- April 2005
diff --git a/sundialsTB/cvodes/cvm/cvm_bjac.m b/sundialsTB/cvodes/cvm/cvm_bjac.m
new file mode 100644
index 0000000..669572a
--- /dev/null
+++ b/sundialsTB/cvodes/cvm/cvm_bjac.m
@@ -0,0 +1,12 @@
+function [J, flag, new_data] = cvm_bjac(t, y, fy, fct, data)
+
+%
+% Wrapper around the actual user-provided Matlab function
+%
+
+if isempty(data)
+ [J, flag] = feval(fct,t,y,fy);
+ new_data = [];
+else
+ [J, flag, new_data] = feval(fct,t,y,fy,data);
+end
diff --git a/sundialsTB/cvodes/cvm/cvm_bjacB.m b/sundialsTB/cvodes/cvm/cvm_bjacB.m
new file mode 100644
index 0000000..1644c4b
--- /dev/null
+++ b/sundialsTB/cvodes/cvm/cvm_bjacB.m
@@ -0,0 +1,12 @@
+function [JB, flag, new_data] = cvm_bjacB(t, y, yB, fyB, fct, data)
+
+%
+% Wrapper around the actual user-provided Matlab function
+%
+
+if isempty(data)
+ [JB, flag] = feval(fct,t,y,yB,fyB);
+ new_data = [];
+else
+ [JB, flag, new_data] = feval(fct,t,y,yB,fyB,data);
+end
diff --git a/sundialsTB/cvodes/cvm/cvm_djac.m b/sundialsTB/cvodes/cvm/cvm_djac.m
new file mode 100644
index 0000000..211d527
--- /dev/null
+++ b/sundialsTB/cvodes/cvm/cvm_djac.m
@@ -0,0 +1,13 @@
+function [J, flag, new_data] = cvm_djac(t, y, fy, fct, data)
+
+%
+% Wrapper around the actual user-provided Matlab function
+%
+
+if isempty(data)
+ [J, flag] = feval(fct,t,y,fy);
+ new_data = [];
+else
+ [J, flag, new_data] = feval(fct,t,y,fy,data);
+end
+
diff --git a/sundialsTB/cvodes/cvm/cvm_djacB.m b/sundialsTB/cvodes/cvm/cvm_djacB.m
new file mode 100644
index 0000000..fe47177
--- /dev/null
+++ b/sundialsTB/cvodes/cvm/cvm_djacB.m
@@ -0,0 +1,12 @@
+function [JB, flag, new_data] = cvm_djacB(t, y, yB, fyB, fct, data)
+
+%
+% Wrapper around the actual user-provided Matlab function
+%
+
+if isempty(data)
+ [JB, flag] = feval(fct,t,y,yB,fyB);
+ new_data = [];
+else
+ [JB, flag, new_data] = feval(fct,t,y,yB,fyB,data);
+end
diff --git a/sundialsTB/cvodes/cvm/cvm_gcom.m b/sundialsTB/cvodes/cvm/cvm_gcom.m
new file mode 100644
index 0000000..2730647
--- /dev/null
+++ b/sundialsTB/cvodes/cvm/cvm_gcom.m
@@ -0,0 +1,12 @@
+function [flag, new_data] = cvm_gcom(t, y, fct, data)
+
+%
+% Wrapper around the actual user-provided Matlab function
+%
+
+if isempty(data)
+ flag = feval(fct,t,y);
+ new_data = [];
+else
+ [flag, new_data] = feval(fct,t,y,data);
+end
diff --git a/sundialsTB/cvodes/cvm/cvm_gcomB.m b/sundialsTB/cvodes/cvm/cvm_gcomB.m
new file mode 100644
index 0000000..83f02e1
--- /dev/null
+++ b/sundialsTB/cvodes/cvm/cvm_gcomB.m
@@ -0,0 +1,12 @@
+function [flag, new_data] = cvm_gcomB(t, y, yB, fct, data)
+
+%
+% Wrapper around the actual user-provided Matlab function
+%
+
+if isempty(data)
+ flag = feval(fct,t,y,yB);
+ new_data = [];
+else
+ [flag, new_data] = feval(fct,t,y,yB,data);
+end
diff --git a/sundialsTB/cvodes/cvm/cvm_gloc.m b/sundialsTB/cvodes/cvm/cvm_gloc.m
new file mode 100644
index 0000000..f1b3b77
--- /dev/null
+++ b/sundialsTB/cvodes/cvm/cvm_gloc.m
@@ -0,0 +1,12 @@
+function [fl, flag, new_data] = cvm_gloc(t, y, fct, data)
+
+%
+% Wrapper around the actual user-provided Matlab function
+%
+
+if isempty(data)
+ [fl, flag] = feval(fct,t,y);
+ new_data = [];
+else
+ [fl, flag, new_data] = feval(fct,t,y,data);
+end
diff --git a/sundialsTB/cvodes/cvm/cvm_glocB.m b/sundialsTB/cvodes/cvm/cvm_glocB.m
new file mode 100644
index 0000000..c563ba5
--- /dev/null
+++ b/sundialsTB/cvodes/cvm/cvm_glocB.m
@@ -0,0 +1,12 @@
+function [flB, flag, new_data] = cvm_glocB(t, y, yB, fct, data)
+
+%
+% Wrapper around the actual user-provided Matlab function
+%
+
+if isempty(data)
+ [flB, flag] = feval(fct,t,y,yB);
+ new_data = [];
+else
+ [flB, flag, new_data] = feval(fct,t,y,yB,data);
+end
diff --git a/sundialsTB/cvodes/cvm/cvm_jtv.m b/sundialsTB/cvodes/cvm/cvm_jtv.m
new file mode 100644
index 0000000..2567da9
--- /dev/null
+++ b/sundialsTB/cvodes/cvm/cvm_jtv.m
@@ -0,0 +1,12 @@
+function [Jv, flag, new_data] = cvm_jtv(t, y, fy, v, fct, data)
+
+%
+% Wrapper around the actual user-provided Matlab function
+%
+
+if isempty(data)
+ [Jv, flag] = feval(fct,t,y,fy,v);
+ new_data = [];
+else
+ [Jv, flag, new_data] = feval(fct,t,y,fy,v,data);
+end
diff --git a/sundialsTB/cvodes/cvm/cvm_jtvB.m b/sundialsTB/cvodes/cvm/cvm_jtvB.m
new file mode 100644
index 0000000..3b5b922
--- /dev/null
+++ b/sundialsTB/cvodes/cvm/cvm_jtvB.m
@@ -0,0 +1,12 @@
+function [JvB, flag, new_data] = cvm_jtvB(t, y, yB, fyB, vB, fct, data)
+
+%
+% Wrapper around the actual user-provided Matlab function
+%
+
+if isempty(data)
+ [JvB, flag] = feval(fct,t,y,yB,fyB,vB);
+ new_data =[];
+else
+ [JvB, flag, new_data] = feval(fct,t,y,yB,fyB,vB,data);
+end
diff --git a/sundialsTB/cvodes/cvm/cvm_monitor.m b/sundialsTB/cvodes/cvm/cvm_monitor.m
new file mode 100644
index 0000000..26655c5
--- /dev/null
+++ b/sundialsTB/cvodes/cvm/cvm_monitor.m
@@ -0,0 +1,17 @@
+function new_mondata = cvm_monitor(call, t, y, yQ, Ns, yS, fct, mondata)
+
+%
+% Wrapper around the actual user-provided Matlab function
+%
+
+N = length(y);
+
+yS = reshape(yS,N,Ns);
+
+if isempty(mondata)
+ feval(fct, call, t, y, yQ, yS);
+ new_mondata = [];
+else
+ new_mondata = feval(fct, call, t, y, yQ, yS, mondata);
+end
+
diff --git a/sundialsTB/cvodes/cvm/cvm_monitorB.m b/sundialsTB/cvodes/cvm/cvm_monitorB.m
new file mode 100644
index 0000000..53908c8
--- /dev/null
+++ b/sundialsTB/cvodes/cvm/cvm_monitorB.m
@@ -0,0 +1,15 @@
+function [new_mondata] = cvm_monitorB(call, idxB, t, y, yQ, fct, mondata)
+
+%
+% Wrapper around the actual user-provided Matlab function
+%
+
+N = length(y);
+
+idxB = idxB+1;
+if isempty(mondata)
+ feval(fct, call, idxB, t, y, yQ);
+ new_mondata = [];
+else
+ new_mondata = feval(fct, call, idxB, t, y, yQ, mondata);
+end
diff --git a/sundialsTB/cvodes/cvm/cvm_options.m b/sundialsTB/cvodes/cvm/cvm_options.m
new file mode 100644
index 0000000..1a0f2bc
--- /dev/null
+++ b/sundialsTB/cvodes/cvm/cvm_options.m
@@ -0,0 +1,66 @@
+function options = cvm_options(KeyNames, varargin)
+
+m = length(KeyNames);
+
+% Initialize the output options structure
+
+options = [];
+for i = 1:m
+ options.(KeyNames{i}) = [];
+end
+
+% If the first argument is an options structure, read its non-empty fields
+% and update options. Store in j the start of key-value pairs.
+
+arg = varargin{1};
+
+if isa(arg,'struct')
+ for i = 1:m
+ if isfield(arg,KeyNames{i})
+ options.(KeyNames{i}) = arg.(KeyNames{i});
+ end
+ end
+ j = 2;
+else
+ j = 1;
+end
+
+% The remaining input arguments must be key-value pairs
+
+if rem(nargin-j,2) ~= 0
+ error('Arguments must be key-value pairs.');
+end
+
+% Process each key-value pair
+
+np = (nargin-j)/2;
+
+keynames = lower(KeyNames);
+
+for i = 1:np
+
+ % Get the key
+ key = varargin{j};
+
+ % key must be a string
+ if ~isstr(key)
+ error(sprintf('Argument %d is not a string property name.', j));
+ end
+
+ % Get the index in keynames that exactly matches the current key
+ % (modulo the case)
+ ik = strmatch(lower(key), keynames, 'exact');
+ if isempty(ik)
+ error(sprintf('Unrecognized property "%s"', key));
+ end
+
+ % Get the value
+ val = varargin{j+1};
+
+ % Set the proper field in options
+ options.(KeyNames{ik}) = val;
+
+ % move to next pair
+ j = j+2;
+
+end
diff --git a/sundialsTB/cvodes/cvm/cvm_pset.m b/sundialsTB/cvodes/cvm/cvm_pset.m
new file mode 100644
index 0000000..b4dfe80
--- /dev/null
+++ b/sundialsTB/cvodes/cvm/cvm_pset.m
@@ -0,0 +1,12 @@
+function [jcur, flag, new_data] = cvm_pset(t, y, fy, jok, gm, fct, data)
+
+%
+% Wrapper around the actual user-provided Matlab function
+%
+
+if isempty(data)
+ [jcur, flag] = feval(fct,t,y,fy,jok,gm);
+ new_data = [];
+else
+ [jcur, flag, new_data] = feval(fct,t,y,fy,jok,gm,data);
+end
diff --git a/sundialsTB/cvodes/cvm/cvm_psetB.m b/sundialsTB/cvodes/cvm/cvm_psetB.m
new file mode 100644
index 0000000..e356b53
--- /dev/null
+++ b/sundialsTB/cvodes/cvm/cvm_psetB.m
@@ -0,0 +1,12 @@
+function [jcurB, flag, new_data] = cvm_psetB(t, y, yB, fyB, jokB, gmB, fct, data)
+
+%
+% Wrapper around the actual user-provided Matlab function
+%
+
+if isempty(data)
+ [jcurB, flag] = feval(fct,t,y,yB,fyB,jokB,gmB);
+ new_data = [];
+else
+ [jcurB, flag, new_data] = feval(fct,t,y,yB,fyB,jokB,gmB,data);
+end
diff --git a/sundialsTB/cvodes/cvm/cvm_psol.m b/sundialsTB/cvodes/cvm/cvm_psol.m
new file mode 100644
index 0000000..52fee12
--- /dev/null
+++ b/sundialsTB/cvodes/cvm/cvm_psol.m
@@ -0,0 +1,12 @@
+function [z, flag, new_data] = cvm_psol(t, y, fy, r, fct, data)
+
+%
+% Wrapper around the actual user-provided Matlab function
+%
+
+if isempty(data)
+ [z, flag] = feval(fct,t,y,fy,r);
+ new_data = [];
+else
+ [z, flag, new_data] = feval(fct,t,y,fy,r,data);
+end
diff --git a/sundialsTB/cvodes/cvm/cvm_psolB.m b/sundialsTB/cvodes/cvm/cvm_psolB.m
new file mode 100644
index 0000000..ba21ec9
--- /dev/null
+++ b/sundialsTB/cvodes/cvm/cvm_psolB.m
@@ -0,0 +1,12 @@
+function [zB, flag, new_data] = cvm_psolB(t, y, yB, fyB, rB, fct, data)
+
+%
+% Wrapper around the actual user-provided Matlab function
+%
+
+if isempty(data)
+ [zB, flag] = feval(fct,t,y,yB,fyB,rB);
+ new_data = [];
+else
+ [zB, flag, new_data] = feval(fct,t,y,yB,fyB,rB,data);
+end
diff --git a/sundialsTB/cvodes/cvm/cvm_rhs.m b/sundialsTB/cvodes/cvm/cvm_rhs.m
new file mode 100644
index 0000000..a38928d
--- /dev/null
+++ b/sundialsTB/cvodes/cvm/cvm_rhs.m
@@ -0,0 +1,13 @@
+function [yd, flag, new_data] = cvm_rhs(t, y, fct, data)
+
+%
+% Wrapper around the actual user-provided Matlab function
+%
+
+if isempty(data)
+ [yd, flag] = feval(fct,t,y);
+ new_data = [];
+else
+ [yd, flag, new_data] = feval(fct,t,y,data);
+end
+
diff --git a/sundialsTB/cvodes/cvm/cvm_rhsB.m b/sundialsTB/cvodes/cvm/cvm_rhsB.m
new file mode 100644
index 0000000..0447c48
--- /dev/null
+++ b/sundialsTB/cvodes/cvm/cvm_rhsB.m
@@ -0,0 +1,48 @@
+function [yBd, flag, new_data] = cvm_rhsB(type, varargin)
+
+%
+% Wrapper around the actual user-provided Matlab function
+%
+
+switch type
+
+ case 0
+
+ % Not dependent on yS
+
+ t = varargin{1};
+ y = varargin{2};
+ yB = varargin{3};
+ fct = varargin{4};
+ data = varargin{5};
+
+ if isempty(data)
+ [yBd, flag] = feval(fct,t,y,yB);
+ new_data = [];
+ else
+ [yBd, flag, new_data] = feval(fct,t,y,yB,data);
+ end
+
+ case 1
+
+ % Dependent on yS
+
+ t = varargin{1};
+ y = varargin{2};
+ Ns = varargin{3};
+ yS = varargin{4};
+ yB = varargin{5};
+ fct = varargin{6};
+ data = varargin{7};
+
+ N = length(y);
+ yS = reshape(yS,N,Ns);
+
+ if isempty(data)
+ [yBd, flag] = feval(fct,t,y,yS,yB);
+ new_data = [];
+ else
+ [yBd, flag, new_data] = feval(fct,t,y,yS,yB,data);
+ end
+
+end
diff --git a/sundialsTB/cvodes/cvm/cvm_rhsQ.m b/sundialsTB/cvodes/cvm/cvm_rhsQ.m
new file mode 100644
index 0000000..9975c50
--- /dev/null
+++ b/sundialsTB/cvodes/cvm/cvm_rhsQ.m
@@ -0,0 +1,13 @@
+function [qd, flag, new_data] = cvm_rhsQ(t, y, fct, data)
+
+%
+% Wrapper around the actual user-provided Matlab function
+%
+
+if isempty(data)
+ [qd, flag] = feval(fct,t,y);
+ new_data =[];
+else
+ [qd, flag, new_data] = feval(fct,t,y,data);
+end
+
diff --git a/sundialsTB/cvodes/cvm/cvm_rhsQB.m b/sundialsTB/cvodes/cvm/cvm_rhsQB.m
new file mode 100644
index 0000000..c109a10
--- /dev/null
+++ b/sundialsTB/cvodes/cvm/cvm_rhsQB.m
@@ -0,0 +1,49 @@
+function [qBd, flag, new_data] = cvm_rhsQB(type, varargin)
+
+%
+% Wrapper around the actual user-provided Matlab function
+%
+
+switch type
+
+ case 0
+
+ % Not dependent on yS
+
+ t = varargin{1};
+ y = varargin{2};
+ yB = varargin{3};
+ fct = varargin{4};
+ data = varargin{5};
+
+ if isempty(data)
+ [qBd, flag] = feval(fct,t,y,yB);
+ new_data = [];
+ else
+ [qBd, flag, new_data] = feval(fct,t,y,yB,data);
+ end
+
+ case 1
+
+ % Dependent on yS
+
+ t = varargin{1};
+ y = varargin{2};
+ Ns = varargin{3};
+ yS = varargin{4};
+ yB = varargin{5};
+ fct = varargin{6};
+ data = varargin{7};
+
+ N = length(y);
+ yS = reshape(yS,N,Ns);
+
+ if isempty(data)
+ [qBd, flag] = feval(fct,t,y,yS,yB);
+ new_data = [];
+ else
+ [qBd, flag, new_data] = feval(fct,t,y,yS,yB,data);
+ end
+
+
+end
\ No newline at end of file
diff --git a/sundialsTB/cvodes/cvm/cvm_rhsS.m b/sundialsTB/cvodes/cvm/cvm_rhsS.m
new file mode 100644
index 0000000..f90f33b
--- /dev/null
+++ b/sundialsTB/cvodes/cvm/cvm_rhsS.m
@@ -0,0 +1,17 @@
+function [ySd, flag, new_data] = cvm_rhsS(t, y, yd, Ns, yS, fct, data)
+
+%
+% Wrapper around the actual user-provided Matlab function
+%
+
+N = length(y);
+yS = reshape(yS,N,Ns);
+
+if isempty(data)
+ [ySd, flag] = feval(fct,t,y,yd,yS);
+ new_data = [];
+else
+ [ySd, flag, new_data] = feval(fct,t,y,yd,yS,data);
+end
+
+ySd = reshape(ySd,N*Ns,1);
\ No newline at end of file
diff --git a/sundialsTB/cvodes/cvm/cvm_root.m b/sundialsTB/cvodes/cvm/cvm_root.m
new file mode 100644
index 0000000..820d9b3
--- /dev/null
+++ b/sundialsTB/cvodes/cvm/cvm_root.m
@@ -0,0 +1,13 @@
+function [g, flag, new_data] = cvm_root(t, y, fct, data)
+
+%
+% Wrapper around the actual user-provided Matlab function
+%
+
+if isempty(data)
+ [g, flag] = feval(fct,t,y);
+ new_data = [];
+else
+ [g, flag, new_data] = feval(fct,t,y,data);
+end
+
diff --git a/sundialsTB/cvodes/cvm/src/cvm.c b/sundialsTB/cvodes/cvm/src/cvm.c
new file mode 100644
index 0000000..aa7f8c7
--- /dev/null
+++ b/sundialsTB/cvodes/cvm/src/cvm.c
@@ -0,0 +1,3662 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.26 $
+ * $Date: 2012/03/07 21:48:00 $
+ * -----------------------------------------------------------------
+ * Programmer: 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 sundials-x.y.z/src/cvodes/LICENSE.
+ * -----------------------------------------------------------------
+ * MEX implementation for CVODES Matlab interface.
+ * -----------------------------------------------------------------
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include "cvm.h"
+#include "nvm.h"
+
+/*
+ * ---------------------------------------------------------------------------------
+ * Global interface data variable
+ * ---------------------------------------------------------------------------------
+ */
+
+cvmInterfaceData cvmData = NULL;
+
+/*
+ * ---------------------------------------------------------------------------------
+ * Static function prototypes
+ * ---------------------------------------------------------------------------------
+ */
+
+static void cvmInitCVODESdata();
+static void cvmPersistCVODESdata();
+static void cvmFinalCVODESdata();
+
+static void cvmInitPbData(cvmPbData pb);
+static void cvmPersistPbData(cvmPbData pb);
+static void cvmFinalPbData(cvmPbData pb);
+
+
+static int CVM_Initialization(int action, int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]);
+static int CVM_QuadInitialization(int action, int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]);
+static int CVM_SensInitialization(int action, int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]);
+static int CVM_AdjInitialization(int action, int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]);
+
+static int CVM_InitializationB(int action, int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]);
+static int CVM_QuadInitializationB(int action, int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]);
+
+static int CVM_SensToggleOff(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]);
+
+static int CVM_Solve(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]);
+static int CVM_SolveB(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]);
+
+static int cvmSolveB_one(mxArray *plhs[], int NtoutB, double *toutB, int itaskB);
+static int cvmSolveB_more(mxArray *plhs[], int NtoutB, double *toutB, int itaskB,
+ booleantype any_quadrB, booleantype any_monB);
+
+
+static int CVM_Stats(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]);
+static int CVM_StatsB(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]);
+
+
+static int CVM_Set(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]);
+static int CVM_SetB(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]);
+
+static int CVM_Get(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]);
+
+
+static int CVM_Free(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]);
+
+/*
+ * ---------------------------------------------------------------------------------
+ * Main entry point
+ * ---------------------------------------------------------------------------------
+ */
+
+void mexFunction(int nlhs, mxArray *plhs[],
+ int nrhs, const mxArray *prhs[] )
+{
+ int mode;
+ /*
+ Modes:
+
+ 1 - initialize CVODES solver
+ 2 - initialize quadratures
+ 3 - initialize forward sensitivity calculations
+ 4 - initialize adjoint sensitivity calculations
+ 5 - initialize backward solver
+ 6 - initialize backward quadratures
+
+ 11 - reinitialize CVODES solver
+ 12 - reinitialize quadratures
+ 13 - reinitialize forward sensitivity calculations
+ 14 - reinitialize adjoint sensitivity calculations
+ 15 - reinitialize backward solver
+ 16 - reinitialize backward quadratures
+
+ 18 - toggle FSA off
+
+ 20 - solve problem
+ 21 - solve backward problem
+
+ 30 - get integrator stats
+ 31 - get backward integrator stats
+ 32 - extract data from cvode_mem
+
+ 33 - set one optional input at a time
+ 34 - set one optional input at a time for backward problems
+
+ 40 - finalize
+ */
+
+ mode = (int)mxGetScalar(prhs[0]);
+
+ mexUnlock();
+
+
+ if ( (mode != 1) && (cvmData == NULL) ) {
+ mexErrMsgTxt("CVODES - Illegal attempt to call before CVodeInit.");
+ }
+
+
+ switch(mode) {
+
+ /* Initialization functions */
+
+ case 1:
+ if (cvmData != NULL) {
+ CVM_Free(nlhs, plhs, nrhs-1, &prhs[1]);
+ cvmFinalCVODESdata();
+ }
+ cvmInitCVODESdata();
+ CVM_Initialization(0, nlhs, plhs, nrhs-1, &prhs[1]);
+ break;
+
+ case 2:
+ CVM_QuadInitialization(0, nlhs, plhs, nrhs-1, &prhs[1]);
+ break;
+
+ case 3:
+ CVM_SensInitialization(0, nlhs, plhs, nrhs-1, &prhs[1]);
+ break;
+
+ case 4:
+ CVM_AdjInitialization(0, nlhs, plhs, nrhs-1, &prhs[1]);
+ break;
+
+ case 5:
+ CVM_InitializationB(0, nlhs, plhs, nrhs-1, &prhs[1]);
+ break;
+
+ case 6:
+ CVM_QuadInitializationB(0, nlhs, plhs, nrhs-1, &prhs[1]);
+ break;
+
+ /* Re-initialization functions */
+
+ case 11:
+ CVM_Initialization(1, nlhs, plhs, nrhs-1, &prhs[1]);
+ break;
+
+ case 12:
+ CVM_QuadInitialization(1, nlhs, plhs, nrhs-1, &prhs[1]);
+ break;
+
+ case 13:
+ CVM_SensInitialization(1, nlhs, plhs, nrhs-1, &prhs[1]);
+ break;
+
+ case 14:
+ CVM_AdjInitialization(1, nlhs, plhs, nrhs-1, &prhs[1]);
+ break;
+
+ case 15:
+ CVM_InitializationB(1, nlhs, plhs, nrhs-1, &prhs[1]);
+ break;
+
+ case 16:
+ CVM_QuadInitializationB(1, nlhs, plhs, nrhs-1, &prhs[1]);
+ break;
+
+ /* Sensitivity toggle function */
+
+ case 18:
+ CVM_SensToggleOff(nlhs, plhs, nrhs-1, &prhs[1]);
+ break;
+
+ /* Solve functions */
+
+ case 20:
+ CVM_Solve(nlhs, plhs, nrhs-1, &prhs[1]);
+ break;
+
+ case 21:
+ CVM_SolveB(nlhs, plhs, nrhs-1, &prhs[1]);
+ break;
+
+ /* Optional output extraction functions */
+
+ case 30:
+ CVM_Stats(nlhs, plhs, nrhs-1, &prhs[1]);
+ break;
+
+ case 31:
+ CVM_StatsB(nlhs, plhs, nrhs-1, &prhs[1]);
+ break;
+
+ case 32:
+ CVM_Get(nlhs, plhs, nrhs-1, &prhs[1]);
+ break;
+
+ case 33:
+ CVM_Set(nlhs, plhs, nrhs-1, &prhs[1]);
+ break;
+
+ case 34:
+ CVM_SetB(nlhs, plhs, nrhs-1, &prhs[1]);
+ break;
+
+ /* Memory deallocation function */
+
+ case 40:
+ CVM_Free(nlhs, plhs, nrhs-1, &prhs[1]);
+ cvmFinalCVODESdata();
+ return;
+
+ }
+
+ /* Unless this was the CVodeFree call,
+ * make data persistent and lock the MEX file */
+ if (mode != 40) {
+ cvmPersistCVODESdata();
+ mexLock();
+ }
+
+ return;
+}
+
+/*
+ * ---------------------------------------------------------------------------------
+ * Private functions
+ * ---------------------------------------------------------------------------------
+ */
+
+static void cvmInitCVODESdata()
+{
+ /* Allocate space for global CVODES data structure */
+
+ cvmData = (cvmInterfaceData) mxMalloc(sizeof(struct cvmInterfaceData_));
+
+ /* Initialize global CVODES data */
+
+ cvmData->cvode_mem = NULL;
+
+ cvmData->fwdPb = NULL;
+ cvmData->bckPb = NULL;
+
+ cvmData->NbckPb = 0;
+
+ cvmData->Nd = 0;
+ cvmData->Nc = 0;
+ cvmData->asa = FALSE;
+
+ cvmData->errMsg = TRUE;
+
+ return;
+}
+
+
+static void cvmInitPbData(cvmPbData pb)
+{
+ mxArray *empty;
+
+ pb->n = 0;
+ pb->nq = 0;
+ pb->ng = 0;
+ pb->ns = 0;
+
+ pb->Y = NULL;
+ pb->YQ = NULL;
+ pb->YS = NULL;
+
+ pb->Quadr = FALSE;
+ pb->Fsa = FALSE;
+ pb->Mon = FALSE;
+
+ pb->LS = LS_DENSE;
+ pb->PM = PM_NONE;
+
+ empty = mxCreateDoubleMatrix(0,0,mxREAL);
+
+ pb->RHSfct = mxDuplicateArray(empty);
+ pb->Gfct = mxDuplicateArray(empty);
+ pb->QUADfct = mxDuplicateArray(empty);
+ pb->SRHSfct = mxDuplicateArray(empty);
+ pb->JACfct = mxDuplicateArray(empty);
+ pb->PSETfct = mxDuplicateArray(empty);
+ pb->PSOLfct = mxDuplicateArray(empty);
+ pb->GLOCfct = mxDuplicateArray(empty);
+ pb->GCOMfct = mxDuplicateArray(empty);
+
+ pb->MONfct = mxDuplicateArray(empty);
+ pb->MONdata = mxDuplicateArray(empty);
+
+ pb->mtlb_data = mxDuplicateArray(empty);
+
+ pb->fwd = cvmData->fwdPb;
+
+ pb->index = 0;
+ pb->next = NULL;
+
+ mxDestroyArray(empty);
+}
+
+
+static void cvmPersistCVODESdata()
+{
+ cvmPbData tmpPb;
+
+ /* Make global memory persistent */
+
+ if (cvmData->fwdPb != NULL) {
+ cvmPersistPbData(cvmData->fwdPb);
+ mexMakeMemoryPersistent(cvmData->fwdPb);
+ }
+
+ tmpPb = cvmData->bckPb;
+ while(tmpPb != NULL) {
+ cvmPersistPbData(tmpPb);
+ mexMakeMemoryPersistent(tmpPb);
+ tmpPb = tmpPb->next;
+ }
+
+ mexMakeMemoryPersistent(cvmData);
+
+ return;
+}
+
+
+static void cvmPersistPbData(cvmPbData pb)
+{
+ mexMakeArrayPersistent(pb->mtlb_data);
+
+ mexMakeArrayPersistent(pb->RHSfct);
+ mexMakeArrayPersistent(pb->Gfct);
+ mexMakeArrayPersistent(pb->QUADfct);
+ mexMakeArrayPersistent(pb->SRHSfct);
+ mexMakeArrayPersistent(pb->JACfct);
+ mexMakeArrayPersistent(pb->PSETfct);
+ mexMakeArrayPersistent(pb->PSOLfct);
+ mexMakeArrayPersistent(pb->GLOCfct);
+ mexMakeArrayPersistent(pb->GCOMfct);
+
+ mexMakeArrayPersistent(pb->MONfct);
+ mexMakeArrayPersistent(pb->MONdata);
+}
+
+static void cvmFinalCVODESdata()
+{
+ cvmPbData tmpPb;
+
+ if (cvmData == NULL) return;
+
+ if (cvmData->fwdPb != NULL) {
+ cvmFinalPbData(cvmData->fwdPb);
+ mxFree(cvmData->fwdPb);
+ cvmData->fwdPb = NULL;
+ }
+
+ while(cvmData->bckPb != NULL) {
+ tmpPb = cvmData->bckPb->next;
+ mxFree(cvmData->bckPb);
+ cvmData->bckPb = tmpPb;
+ }
+
+ mxFree(cvmData);
+ cvmData = NULL;
+
+ return;
+}
+
+
+static void cvmFinalPbData(cvmPbData pb)
+{
+ if (pb->Y != NULL) N_VDestroy(pb->Y);
+ if (pb->YQ != NULL) N_VDestroy(pb->YQ);
+ if (pb->YS != NULL) N_VDestroyVectorArray(pb->YS, pb->ns);
+
+ mxDestroyArray(pb->mtlb_data);
+
+ mxDestroyArray(pb->RHSfct);
+ mxDestroyArray(pb->Gfct);
+ mxDestroyArray(pb->QUADfct);
+ mxDestroyArray(pb->SRHSfct);
+ mxDestroyArray(pb->JACfct);
+ mxDestroyArray(pb->PSETfct);
+ mxDestroyArray(pb->PSOLfct);
+ mxDestroyArray(pb->GLOCfct);
+ mxDestroyArray(pb->GCOMfct);
+
+ mxDestroyArray(pb->MONfct);
+ mxDestroyArray(pb->MONdata);
+}
+
+/*
+ * ---------------------------------------------------------------------------------
+ * Error handler function.
+ *
+ * This function is both passed as the CVODES error handler and used throughout
+ * the Matlab interface.
+ *
+ * If called directly by one of the interface functions, error_code = -999 to
+ * indicate an error and err_code = +999 to indicate a warning. Otherwise,
+ * err_code is set by the calling CVODES function.
+ *
+ * NOTE: mexErrMsgTxt will end the execution of the MEX file. Therefore we do
+ * not have to intercept any of the CVODES error return flags.
+ * The only return flags we intercept are those from CVode() and CVodeB()
+ * which are passed back to the user (only positive values will make it).
+ * ---------------------------------------------------------------------------------
+ */
+
+void cvmErrHandler(int error_code,
+ const char *module, const char *function,
+ char *msg, void *eh_data)
+{
+ char err_msg[256];
+
+ if (!(cvmData->errMsg)) return;
+
+ if (error_code > 0) {
+ sprintf(err_msg,"Warning in ==> %s\n%s",function,msg);
+ mexWarnMsgTxt(err_msg);
+ } else if (error_code < 0) {
+ /*mexUnlock();
+ cvmFinalCVODESdata();*/
+ sprintf(err_msg,"Error using ==> %s\n%s",function,msg);
+ mexErrMsgTxt(err_msg);
+ }
+
+ return;
+}
+
+/*
+ * ---------------------------------------------------------------------------------
+ * Redability replacements
+ * ---------------------------------------------------------------------------------
+ */
+
+#define cvode_mem (cvmData->cvode_mem)
+
+#define asa (cvmData->asa)
+#define Nd (cvmData->Nd)
+#define Nc (cvmData->Nc)
+#define NbckPb (cvmData->NbckPb)
+
+#define fsa (fwdPb->Fsa)
+#define quadr (fwdPb->Quadr)
+#define mon (fwdPb->Mon)
+#define rootSet (fwdPb->RootSet)
+#define tstopSet (fwdPb->TstopSet)
+
+#define y (fwdPb->Y)
+#define yQ (fwdPb->YQ)
+#define yS (fwdPb->YS)
+#define N (fwdPb->n)
+#define Nq (fwdPb->nq)
+#define Ng (fwdPb->ng)
+#define Ns (fwdPb->ns)
+#define ls (fwdPb->LS)
+#define pm (fwdPb->PM)
+
+#define mtlb_data (fwdPb->mtlb_data)
+
+#define mtlb_RHSfct (fwdPb->RHSfct)
+#define mtlb_QUADfct (fwdPb->QUADfct)
+#define mtlb_JACfct (fwdPb->JACfct)
+#define mtlb_PSETfct (fwdPb->PSETfct)
+#define mtlb_PSOLfct (fwdPb->PSOLfct)
+#define mtlb_GLOCfct (fwdPb->GLOCfct)
+#define mtlb_GCOMfct (fwdPb->GCOMfct)
+#define mtlb_Gfct (fwdPb->Gfct)
+#define mtlb_SRHSfct (fwdPb->SRHSfct)
+
+#define mtlb_MONfct (fwdPb->MONfct)
+#define mtlb_MONdata (fwdPb->MONdata)
+
+
+
+#define indexB (bckPb->index)
+
+#define quadrB (bckPb->Quadr)
+#define monB (bckPb->Mon)
+
+#define yB (bckPb->Y)
+#define yQB (bckPb->YQ)
+#define NB (bckPb->n)
+#define NqB (bckPb->nq)
+#define lsB (bckPb->LS)
+#define pmB (bckPb->PM)
+
+#define mtlb_dataB (bckPb->mtlb_data)
+
+#define mtlb_RHSfctB (bckPb->RHSfct)
+#define mtlb_QUADfctB (bckPb->QUADfct)
+#define mtlb_JACfctB (bckPb->JACfct)
+#define mtlb_PSETfctB (bckPb->PSETfct)
+#define mtlb_PSOLfctB (bckPb->PSOLfct)
+#define mtlb_GLOCfctB (bckPb->GLOCfct)
+#define mtlb_GCOMfctB (bckPb->GCOMfct)
+
+#define mtlb_MONfctB (bckPb->MONfct)
+#define mtlb_MONdataB (bckPb->MONdata)
+
+
+
+/*
+ * ---------------------------------------------------------------------------------
+ * Exported procedures
+ * ---------------------------------------------------------------------------------
+ */
+
+/* CVM_Initialization
+ *
+ * action = 0 -> CVodeCreate + CVodeInit
+ * prhs contains:
+ * fct
+ * lmm
+ * iter
+ * t0
+ * y0
+ * options
+ * data
+ *
+ * action = 1 -> CVodeReInit
+ * prhs contains:
+ * t0
+ * y0
+ * options
+ *
+ */
+
+static int CVM_Initialization(int action, int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
+{
+ cvmPbData fwdPb;
+
+ const mxArray *options;
+
+ double t0, *y0;
+
+ int lmm, iter, maxord;
+
+ long int mxsteps;
+
+ int itol;
+ realtype reltol, Sabstol, *Vabstol;
+ N_Vector NV_abstol;
+
+ double hin, hmax, hmin;
+
+ double tstop;
+
+ booleantype sld;
+
+ booleantype errmsg;
+
+ booleantype rhs_s; /* ignored */
+
+ long int mupper, mlower;
+ int ptype, gstype, maxl;
+ long int mudq, mldq;
+ double dqrely;
+
+ char *bufval;
+ int buflen, status;
+
+ /*
+ * ------------------------------------
+ * Process inputs based on action
+ * ------------------------------------
+ */
+
+ switch (action) {
+
+ case 0: /* SOLVER INITIALIZATION */
+
+ /* Create and initialize a new problem */
+
+ fwdPb = (cvmPbData) mxMalloc(sizeof(struct cvmPbData_));
+ cvmInitPbData(fwdPb);
+
+ cvmData->fwdPb = fwdPb;
+
+ /* Initialize appropriate vector module */
+
+ InitVectors();
+
+ /* Extract user-provided RHS function */
+
+ mxDestroyArray(mtlb_RHSfct);
+ mtlb_RHSfct = mxDuplicateArray(prhs[0]);
+
+ /* Extract lmm */
+
+ buflen = mxGetM(prhs[1]) * mxGetN(prhs[1]) + 1;
+ bufval = mxCalloc(buflen, sizeof(char));
+ status = mxGetString(prhs[1], bufval, buflen);
+ if(status != 0) {
+ cvmErrHandler(-999, "CVODES", "CVodeInit",
+ "Cannot parse LMM input argument.", NULL);
+ goto error_return;
+ }
+ if(!strcmp(bufval,"Adams")) {
+ lmm = CV_ADAMS;
+ } else if(!strcmp(bufval,"BDF")) {
+ lmm = CV_BDF;
+ } else {
+ cvmErrHandler(-999, "CVODES", "CVodeInit",
+ "LMM has an illegal value.", NULL);
+ goto error_return;
+ }
+ mxFree(bufval);
+
+ /* Extract iter */
+
+ buflen = mxGetM(prhs[2]) * mxGetN(prhs[2]) + 1;
+ bufval = mxCalloc(buflen, sizeof(char));
+ status = mxGetString(prhs[2], bufval, buflen);
+ if(status != 0) {
+ cvmErrHandler(-999, "CVODES", "CVodeInit",
+ "Cannot parse NLS input argument.", NULL);
+ goto error_return;
+ }
+ if(!strcmp(bufval,"Functional")) {
+ iter = CV_FUNCTIONAL;
+ } else if(!strcmp(bufval,"Newton")) {
+ iter = CV_NEWTON;
+ } else {
+ cvmErrHandler(-999, "CVODES", "CVodeInit",
+ "NLS has an illegal value.", NULL);
+ goto error_return;
+ }
+ mxFree(bufval);
+
+ /* Extract initial time */
+
+ t0 = (double)mxGetScalar(prhs[3]);
+
+ /* Extract initial conditions */
+
+ y0 = mxGetPr(prhs[4]);
+ N = mxGetM(prhs[4]);
+
+ /* Create the solution N_Vector */
+
+ y = NewVector(N);
+
+ /* Load initial conditions */
+
+ PutData(y, y0, N);
+
+ /* Extract options structure */
+
+ options = prhs[5];
+
+ break;
+
+ case 1: /* SOLVER RE-INITIALIZATION */
+
+ fwdPb = cvmData->fwdPb;
+
+ /* If monitoring was enabled, finalize it now. */
+
+ if (mon) mxW_CVodeMonitor(2, 0.0, NULL, NULL, NULL, fwdPb);
+
+ /* Extract initial time */
+
+ t0 = (double)mxGetScalar(prhs[0]);
+
+ /* Extract initial conditions */
+
+ y0 = mxGetPr(prhs[1]);
+
+ if (mxGetM(prhs[1]) != N) {
+ cvmErrHandler(-999, "CVODES", "CVodeReInit",
+ "Size of y0 changed from CVodeInit call.", NULL);
+ goto error_return;
+ }
+
+ /* Load initial conditions */
+
+ PutData(y, y0, N);
+
+ /* Extract options structure */
+
+ options = prhs[2];
+
+ break;
+
+ }
+
+ /* Process the options structure */
+
+ status = get_IntgrOptions(options, fwdPb, TRUE, lmm,
+ &maxord, &sld, &errmsg, &mxsteps,
+ &itol, &reltol, &Sabstol, &Vabstol,
+ &hin, &hmax, &hmin, &tstop, &rhs_s);
+ if (status != 0) goto error_return;
+
+ /*
+ * ----------------------------------------
+ * Call appropriate CVODES functions
+ *
+ * If action = 0
+ * Create CVODES object and allocate memory
+ * Attach error handler function
+ * Redirect output
+ * If action = 1
+ * Reinitialize solver
+ * ----------------------------------------
+ */
+
+ switch (action) {
+
+ case 0:
+
+ /* Create CVODES object */
+ cvode_mem = CVodeCreate(lmm, iter);
+ if (cvode_mem == NULL) goto error_return;
+
+ /* Attach the global CVODES data as 'user-data' */
+ status = CVodeSetUserData(cvode_mem, fwdPb);
+ if (status != CV_SUCCESS) goto error_return;
+
+ /* Attach error handler function */
+ status = CVodeSetErrHandlerFn(cvode_mem, cvmErrHandler, NULL);
+ if (status != CV_SUCCESS) goto error_return;
+
+ /* Call CVodeInit */
+ status = CVodeInit(cvode_mem, mxW_CVodeRhs, t0, y);
+ if (status != CV_SUCCESS) goto error_return;
+
+ /* Redirect output */
+ status = CVodeSetErrFile(cvode_mem, stdout);
+ if (status != CV_SUCCESS) goto error_return;
+
+ break;
+
+ case 1:
+
+ /* Reinitialize solver */
+ status = CVodeReInit(cvode_mem, t0, y);
+ if (status != CV_SUCCESS) goto error_return;
+
+ break;
+
+ }
+
+ /*
+ * ----------------------------------------
+ * Set tolerances
+ * ----------------------------------------
+ */
+
+ switch (itol) {
+ case CV_SS:
+ status = CVodeSStolerances(cvode_mem, reltol, Sabstol);
+ if (status != CV_SUCCESS) goto error_return;
+ break;
+ case CV_SV:
+ NV_abstol = N_VClone(y);
+ PutData(NV_abstol, Vabstol, N);
+ status = CVodeSVtolerances(cvode_mem, reltol, NV_abstol);
+ if (status != CV_SUCCESS) goto error_return;
+ N_VDestroy(NV_abstol);
+ break;
+ }
+
+ /*
+ * --------------------------------
+ * Set various optional inputs
+ * --------------------------------
+ */
+
+ /* set maxorder (default is consistent with LMM) */
+ status = CVodeSetMaxOrd(cvode_mem, maxord);
+ if (status != CV_SUCCESS) goto error_return;
+
+ /* set initial step size (the default value of 0.0 is ignored by CVODES) */
+ status = CVodeSetInitStep(cvode_mem, hin);
+ if (status != CV_SUCCESS) goto error_return;
+
+ /* set max step (default is infinity) */
+ status = CVodeSetMaxStep(cvode_mem, hmax);
+ if (status != CV_SUCCESS) goto error_return;
+
+ /* set min step (default is 0) */
+ status = CVodeSetMinStep(cvode_mem, hmin);
+ if (status != CV_SUCCESS) goto error_return;
+
+ /* set number of max steps */
+ status = CVodeSetMaxNumSteps(cvode_mem, mxsteps);
+ if (status != CV_SUCCESS) goto error_return;
+
+ /* set tstop? */
+ if (tstopSet) {
+ status = CVodeSetStopTime(cvode_mem, tstop);
+ if (status != CV_SUCCESS) goto error_return;
+ }
+
+ /* set stability limit detection (default is FALSE) */
+ status = CVodeSetStabLimDet(cvode_mem, sld);
+ if (status != CV_SUCCESS) goto error_return;
+
+ /* Rootfinding? */
+ if ( !mxIsEmpty(mtlb_Gfct) && (Ng > 0) ) {
+ status = CVodeRootInit(cvode_mem, Ng, mxW_CVodeGfct);
+ if (status != CV_SUCCESS) goto error_return;
+ rootSet = TRUE;
+ } else {
+ rootSet = FALSE;
+ }
+
+ /*
+ * ----------------------------------------
+ * Need a linear solver?
+ * ----------------------------------------
+ */
+
+ if (iter == CV_NEWTON) {
+
+ status = get_LinSolvOptions(options, fwdPb, TRUE,
+ &mupper, &mlower,
+ &mudq, &mldq, &dqrely,
+ &ptype, &gstype, &maxl);
+ if (status != 0) goto error_return;
+
+ switch (ls) {
+
+ case LS_DENSE:
+
+ status = CVDense(cvode_mem, N);
+ if (status != CV_SUCCESS) goto error_return;
+ if (!mxIsEmpty(mtlb_JACfct)) {
+ status = CVDlsSetDenseJacFn(cvode_mem, mxW_CVodeDenseJac);
+ if (status != CV_SUCCESS) goto error_return;
+ }
+
+ break;
+
+ case LS_DIAG:
+
+ status = CVDiag(cvode_mem);
+ if (status != CV_SUCCESS) goto error_return;
+
+ break;
+
+ case LS_BAND:
+
+ status = CVBand(cvode_mem, N, mupper, mlower);
+ if (status != CV_SUCCESS) goto error_return;
+ if (!mxIsEmpty(mtlb_JACfct)) {
+ status = CVDlsSetBandJacFn(cvode_mem, mxW_CVodeBandJac);
+ if (status != CV_SUCCESS) goto error_return;
+ }
+
+ break;
+
+ case LS_SPGMR:
+
+ status = CVSpgmr(cvode_mem, ptype, maxl);
+ if (status != CV_SUCCESS) goto error_return;
+ status = CVSpilsSetGSType(cvode_mem, gstype);
+ if (status != CV_SUCCESS) goto error_return;
+
+ break;
+
+ case LS_SPBCG:
+
+ status = CVSpbcg(cvode_mem, ptype, maxl);
+ if (status != CV_SUCCESS) goto error_return;
+
+ break;
+
+ case LS_SPTFQMR:
+
+ status = CVSptfqmr(cvode_mem, ptype, maxl);
+ if (status != CV_SUCCESS) goto error_return;
+
+ break;
+
+ }
+
+
+ /* Jacobian * vector and preconditioner for SPILS linear solvers */
+
+ if ( (ls==LS_SPGMR) || (ls==LS_SPBCG) || (ls==LS_SPTFQMR) ) {
+
+ if (!mxIsEmpty(mtlb_JACfct)) {
+ status = CVSpilsSetJacTimesVecFn(cvode_mem, mxW_CVodeSpilsJac);
+ if (status != CV_SUCCESS) goto error_return;
+ }
+
+ switch (pm) {
+
+ case PM_NONE:
+
+ if (!mxIsEmpty(mtlb_PSOLfct)) {
+
+ if (!mxIsEmpty(mtlb_PSETfct)) status = CVSpilsSetPreconditioner(cvode_mem, mxW_CVodeSpilsPset, mxW_CVodeSpilsPsol);
+ else status = CVSpilsSetPreconditioner(cvode_mem, NULL, mxW_CVodeSpilsPsol);
+ if (status != CV_SUCCESS) goto error_return;
+
+ }
+
+ break;
+
+ case PM_BANDPRE:
+
+ status = CVBandPrecInit(cvode_mem, N, mupper, mlower);
+ if (status != CV_SUCCESS) goto error_return;
+
+ break;
+
+ case PM_BBDPRE:
+
+ if (!mxIsEmpty(mtlb_GCOMfct)) status = CVBBDPrecInit(cvode_mem, N, mudq, mldq, mupper, mlower, dqrely, mxW_CVodeBBDgloc, mxW_CVodeBBDgcom);
+ else status = CVBBDPrecInit(cvode_mem, N, mudq, mldq, mupper, mlower, dqrely, mxW_CVodeBBDgloc, NULL);
+ if (status != CV_SUCCESS) goto error_return;
+
+ break;
+ }
+
+ }
+
+ } else {
+
+ ls = LS_NONE;
+
+ }
+
+ /* Do we monitor? */
+
+ if (mon) mxW_CVodeMonitor(0, t0, NULL, NULL, NULL, fwdPb);
+
+ /* Set errMsg field in global data
+ * (all error messages from here on will respect this) */
+
+ cvmData->errMsg = errmsg;
+
+ /* Successful return */
+
+ status = 0;
+ plhs[0] = mxCreateDoubleScalar((double)status);
+ return(0);
+
+ /* Error return */
+
+ error_return:
+ status = -1;
+ plhs[0] = mxCreateDoubleScalar((double)status);
+ return(-1);
+
+}
+
+/* CVM_QuadInitialization
+ *
+ * action = 0 -> CVodeQuadInit
+ * prhs contains:
+ * fQ
+ * y0
+ * options
+ *
+ * action = 1 -> CVodeQuadReInit
+ * prhs contains:
+ * y0
+ * options
+ *
+ */
+
+static int CVM_QuadInitialization(int action, int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
+{
+ cvmPbData fwdPb;
+
+ const mxArray *options;
+
+ double *yQ0;
+
+ booleantype rhs_s; /* ignored */
+
+ booleantype errconQ;
+ int itolQ;
+ realtype reltolQ, SabstolQ, *VabstolQ;
+ N_Vector NV_abstolQ;
+
+ int status;
+
+ fwdPb = cvmData->fwdPb;
+
+ /*
+ * ------------------------------------
+ * Process inputs based on action
+ * ------------------------------------
+ */
+
+ switch (action) {
+
+ case 0: /* QUADRATURE INITIALIZATION */
+
+ /* Extract user-provided quadrature RHS function */
+
+ mxDestroyArray(mtlb_QUADfct);
+ mtlb_QUADfct = mxDuplicateArray(prhs[0]);
+
+ /* Extract quadrature initial conditions */
+
+ yQ0 = mxGetPr(prhs[1]);
+ Nq = mxGetM(prhs[1]);
+
+ /* Create the quadrature N_Vector */
+
+ yQ = NewVector(Nq);
+
+ /* Load quadrature initial conditions */
+
+ PutData(yQ, yQ0, Nq);
+
+ /* Extract quadrature options structure */
+
+ options = prhs[2];
+
+ break;
+
+ case 1: /* QUADRATURE RE-INITIALIZATION */
+
+ /* Extract quadrature initial conditions */
+
+ yQ0 = mxGetPr(prhs[0]);
+
+ if (mxGetM(prhs[0]) != Nq) {
+ cvmErrHandler(-999, "CVODES", "CVodeQuadReInit",
+ "Size of yQ0 changed from CVodeQuadInit call.", NULL);
+ goto error_return;
+ }
+
+ /* Load quadrature initial conditions */
+
+ PutData(yQ, yQ0, Nq);
+
+ /* Extract quadrature options structure */
+
+ options = prhs[1];
+
+ break;
+
+ }
+
+ /* Process the options structure */
+
+ status = get_QuadOptions(options, fwdPb, TRUE,
+ Nq, &rhs_s,
+ &errconQ,
+ &itolQ, &reltolQ, &SabstolQ, &VabstolQ);
+ if (status != 0) goto error_return;
+
+ /*
+ * ----------------------------------------
+ * Call appropriate CVODES functions
+ *
+ * If action = 0
+ * Initialize quadratures
+ * If action = 1
+ * Reinitialize quadratures
+ * ----------------------------------------
+ */
+
+ switch (action) {
+ case 0:
+ status = CVodeQuadInit(cvode_mem, mxW_CVodeQUADfct, yQ);
+ if (status != CV_SUCCESS) goto error_return;
+ break;
+ case 1:
+ status = CVodeQuadReInit(cvode_mem, yQ);
+ if (status != CV_SUCCESS) goto error_return;
+ break;
+ }
+
+ /*
+ * ----------------------------------------
+ * Set tolerances for quadrature variables
+ * ----------------------------------------
+ */
+
+ status = CVodeSetQuadErrCon(cvode_mem, errconQ);
+ if (status != CV_SUCCESS) goto error_return;
+
+ if (errconQ) {
+
+ switch (itolQ) {
+ case CV_SS:
+ status = CVodeQuadSStolerances(cvode_mem, reltolQ, SabstolQ);
+ if (status != CV_SUCCESS) goto error_return;
+ break;
+ case CV_SV:
+ NV_abstolQ = N_VClone(yQ);
+ PutData(NV_abstolQ, VabstolQ, Nq);
+ status = CVodeQuadSVtolerances(cvode_mem, reltolQ, NV_abstolQ);
+ if (status != CV_SUCCESS) goto error_return;
+ N_VDestroy(NV_abstolQ);
+ break;
+ }
+
+ }
+
+ /* Quadratures will be integrated */
+
+ quadr = TRUE;
+
+ /* Successful return */
+
+ status = 0;
+ plhs[0] = mxCreateDoubleScalar((double)status);
+ return(0);
+
+ /* Error return */
+
+ error_return:
+ status = -1;
+ plhs[0] = mxCreateDoubleScalar((double)status);
+ return(-1);
+
+}
+
+/* CVM_SensInitialization
+ *
+ * action = 0 -> CVodeSensInit
+ * prhs contains:
+ * Ns
+ * fS
+ * yS0
+ * options
+ * action = 1 -> CVodeSensReInit
+ * yS0
+ * options
+ *
+ */
+
+static int CVM_SensInitialization(int action, int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
+{
+ cvmPbData fwdPb;
+
+ const mxArray *options;
+
+ booleantype fS_DQ;
+ CVSensRhsFn rhsS;
+
+ double *yS0;
+
+ int ism;
+
+ mxArray *pfield;
+ char *pfield_name;
+
+ booleantype errconS;
+ int itolS;
+ realtype reltolS;
+ realtype *SabstolS, *VabstolS;
+ N_Vector *NV_abstolS;
+
+ int *plist, dqtype;
+ double *p, *pbar, rho;
+
+ int is, status;
+
+ p = NULL;
+ plist = NULL;
+ pbar = NULL;
+
+ fwdPb = cvmData->fwdPb;
+
+ /*
+ * ------------------------------------
+ * Process inputs based on action
+ * ------------------------------------
+ */
+
+ switch (action) {
+
+ case 0: /* FSA INITIALIZATION */
+
+ /* Extract number of sensitivities */
+
+ Ns = (int)mxGetScalar(prhs[0]);
+
+ /* Extract user-provided sensitivity RHS function */
+
+ if ( mxIsEmpty(prhs[1]) ) {
+ rhsS = NULL;
+ fS_DQ = TRUE;
+ } else {
+ mxDestroyArray(mtlb_SRHSfct);
+ mtlb_SRHSfct = mxDuplicateArray(prhs[1]);
+ rhsS = mxW_CVodeSensRhs;
+ fS_DQ = FALSE;
+ }
+
+ /* Extract sensitivity initial condition */
+
+ yS0 = mxGetPr(prhs[2]);
+
+ /* Create the sensitivity N_Vectors */
+
+ yS = N_VCloneVectorArray(Ns, y);
+
+ /* Load sensitivity initial conditions */
+
+ for (is=0;is<Ns;is++)
+ PutData(yS[is], &yS0[is*N], N);
+
+ /* Extract FSA options structure */
+
+ options = prhs[3];
+
+ break;
+
+ case 1: /* FSA RE-INITIALIZATION */
+
+ /* Extract sensitivity initial condition */
+
+ yS0 = mxGetPr(prhs[0]);
+
+ if ( (mxGetM(prhs[0]) != N) || (mxGetN(prhs[0]) != Ns) ) {
+ cvmErrHandler(-999, "CVODES", "CVodeSensReInit",
+ "Size of yS0 changed from CVodeSensInit call.", NULL);
+ goto error_return;
+ }
+
+ /* Load sensitivity initial conditions */
+
+ for (is=0;is<Ns;is++)
+ PutData(yS[is], &yS0[is*N], N);
+
+ /* Extract qFSA options structure */
+
+ options = prhs[1];
+
+ break;
+
+ }
+
+ /* Process the options structure */
+
+ status = get_FSAOptions(options, fwdPb,
+ &ism,
+ &pfield_name, &plist, &pbar,
+ &dqtype, &rho,
+ &errconS, &itolS, &reltolS, &SabstolS, &VabstolS);
+ if (status != 0) goto error_return;
+
+ /*
+ * ----------------------------------------
+ * Call appropriate CVODES functions
+ *
+ * If action = 0
+ * Check if required inputs are available
+ * Initialize FSA
+ * If action = 1
+ * Reinitialize FSA
+ * ----------------------------------------
+ */
+
+ switch (action) {
+
+ case 0:
+
+ /* Test required inputs */
+ if ( fS_DQ && (pfield_name == NULL) ) {
+ cvmErrHandler(-999, "CVODES", "CVodeSensInit/CVodeSensReInit",
+ "pfield required but was not provided.", NULL);
+ goto error_return;
+ }
+
+ status = CVodeSensInit(cvode_mem, Ns, ism, rhsS, yS);
+ if (status != CV_SUCCESS) goto error_return;
+
+ break;
+
+ case 1:
+
+ status = CVodeSensReInit(cvode_mem, ism, yS);
+ if (status != CV_SUCCESS) goto error_return;
+
+ break;
+
+ }
+
+ /*
+ * ----------------------------------------
+ * Set tolerances for sensitivity variables
+ * ----------------------------------------
+ */
+
+ switch (itolS) {
+ case CV_SS:
+ status = CVodeSensSStolerances(cvode_mem, reltolS, SabstolS);
+ if (status != CV_SUCCESS) goto error_return;
+ break;
+ case CV_SV:
+ NV_abstolS = N_VCloneVectorArray(Ns, y);
+ for (is=0;is<Ns;is++)
+ PutData(NV_abstolS[is], &VabstolS[is*N], N);
+ status = CVodeSensSVtolerances(cvode_mem, reltolS, NV_abstolS);
+ if (status != CV_SUCCESS) goto error_return;
+ N_VDestroyVectorArray(NV_abstolS, Ns);
+ break;
+ case CV_EE:
+ status = CVodeSensEEtolerances(cvode_mem);
+ if (status != CV_SUCCESS) goto error_return;
+ break;
+ }
+
+ /*
+ * --------------------------------
+ * Set various optional inputs
+ * --------------------------------
+ */
+
+ if (pfield_name != NULL) {
+ pfield = mxGetField(mtlb_data,0,pfield_name);
+ if (pfield == NULL) {
+ cvmErrHandler(-999, "CVODES", "CVodeSensInit/CVodeSensReInit",
+ "illegal pfield input.", NULL);
+ goto error_return;
+ }
+ p = mxGetPr(pfield);
+ }
+
+ status = CVodeSetSensParams(cvode_mem, p, pbar, plist);
+ if (status != CV_SUCCESS) goto error_return;
+
+ status = CVodeSetSensDQMethod(cvode_mem, dqtype, rho);
+ if (status != CV_SUCCESS) goto error_return;
+
+ status = CVodeSetSensErrCon(cvode_mem, errconS);
+ if (status != CV_SUCCESS) goto error_return;
+
+ fsa = TRUE;
+
+ /* Successful return */
+
+ status = 0;
+ plhs[0] = mxCreateDoubleScalar((double)status);
+ return(0);
+
+ /* Error return */
+
+ error_return:
+ status = -1;
+ plhs[0] = mxCreateDoubleScalar((double)status);
+ return(-1);
+
+}
+
+/*
+ * CVM_SensToggleOff
+ *
+ * deactivates FSA
+ */
+
+static int CVM_SensToggleOff(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
+{
+ cvmPbData fwdPb;
+ int status;
+
+ fwdPb = cvmData->fwdPb;
+
+ status = CVodeSensToggleOff(cvode_mem);
+ if (status != CV_SUCCESS) {
+ status = -1;
+ plhs[0] = mxCreateDoubleScalar((double)status);
+ return(-1);
+ }
+
+ fsa = FALSE;
+
+ status = 0;
+ plhs[0] = mxCreateDoubleScalar((double)status);
+ return(0);
+}
+
+
+/* CVM_AdjInitialization
+ *
+ * prhs contains:
+ * Nd - number of interpolatin data points (i.e. steps between check points)
+ * interp - type of interpolation
+ *
+ */
+
+static int CVM_AdjInitialization(int action, int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
+{
+ int interp;
+
+ int buflen, status;
+ char *bufval;
+
+ switch (action) {
+
+ case 0:
+
+ /* Number of steps */
+
+ Nd = (int)mxGetScalar(prhs[0]);
+
+ /* Interpolation method */
+
+ buflen = mxGetM(prhs[1]) * mxGetN(prhs[1]) + 1;
+ bufval = mxCalloc(buflen, sizeof(char));
+ status = mxGetString(prhs[1], bufval, buflen);
+ if(status != 0) {
+ cvmErrHandler(-999, "CVODES", "CVodeAdjInit",
+ "Could not parse InterpType.", NULL);
+ goto error_return;
+ }
+ if(!strcmp(bufval,"Hermite")) {
+ interp = CV_HERMITE;
+ } else if(!strcmp(bufval,"Polynomial")) {
+ interp = CV_POLYNOMIAL;
+ } else {
+ cvmErrHandler(-999, "CVODES", "CVodeAdjInit",
+ "Interp. type has an illegal value.", NULL);
+ goto error_return;
+ }
+
+ status = CVodeAdjInit(cvode_mem, Nd, interp);
+ if (status != CV_SUCCESS) goto error_return;
+
+ break;
+
+ case 1:
+
+ status = CVodeAdjReInit(cvode_mem);
+ if (status != CV_SUCCESS) goto error_return;
+
+ break;
+
+ }
+
+ asa = TRUE;
+
+ /* Successful return */
+
+ status = 0;
+ plhs[0] = mxCreateDoubleScalar((double)status);
+ return(0);
+
+ /* Error return */
+
+ error_return:
+ status = -1;
+ plhs[0] = mxCreateDoubleScalar((double)status);
+ return(-1);
+
+}
+
+
+/* CVM_InitializationB
+ *
+ * action = 0 -> CVodeCreateB + CVodeInitB
+ * prhs contains:
+ * fctB
+ * lmmB
+ * iterB
+ * tF
+ * yB0
+ * options
+ * plhs contains:
+ * indexB
+ *
+ * action = 1 -> CVodeReInitB
+ * prhs contains:
+ * indexB
+ * tF
+ * yB0
+ * options
+ *
+ */
+
+static int CVM_InitializationB(int action, int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
+{
+ cvmPbData bckPb;
+
+ const mxArray *options;
+
+ int idxB;
+
+ double tB0, *yB0;
+
+ int lmmB, iterB, maxordB;
+ long int mxstepsB;
+
+ int itolB;
+ realtype reltolB, SabstolB, *VabstolB;
+ N_Vector NV_abstolB;
+
+ double hinB, hmaxB, hminB;
+
+ double tstopB; /* ignored */
+ booleantype sldB; /* ignored */
+ booleantype errmsgB; /* ignored */
+
+ booleantype rhs_s;
+
+ long int mupperB, mlowerB;
+ int ptypeB, gstypeB, maxlB;
+ long int mudqB, mldqB;
+ double dqrelyB;
+
+ booleantype found_bck;
+
+ char *bufval;
+ int buflen;
+
+ int status;
+ int i_status;
+
+ /* Set output containing status */
+
+ i_status = (action == 0) ? 1 : 0;
+
+ /*
+ * -----------------------------
+ * Finalize Forward monitoring
+ * -----------------------------
+ */
+
+ if (cvmData->fwdPb->Mon) {
+ mxW_CVodeMonitor(2, 0.0, NULL, NULL, NULL, cvmData->fwdPb);
+ cvmData->fwdPb->Mon = FALSE;
+ }
+
+ /*
+ * ------------------------------------
+ * Process inputs based on action
+ * ------------------------------------
+ */
+
+ switch (action) {
+
+ case 0: /* BACKWARD SOLVER INITIALIZATION */
+
+ /* Create and initialize a new problem */
+
+ bckPb = (cvmPbData) mxMalloc(sizeof(struct cvmPbData_));
+ cvmInitPbData(bckPb);
+
+ bckPb->next = cvmData->bckPb;
+ cvmData->bckPb = bckPb;
+
+ /* Extract user-provided RHS function */
+
+ mxDestroyArray(mtlb_RHSfctB);
+ mtlb_RHSfctB = mxDuplicateArray(prhs[0]);
+
+ /* Extract lmmB */
+
+ buflen = mxGetM(prhs[1]) * mxGetN(prhs[1]) + 1;
+ bufval = mxCalloc(buflen, sizeof(char));
+ status = mxGetString(prhs[1], bufval, buflen);
+ if(status != 0) {
+ cvmErrHandler(-999, "CVODES", "CVodeInitB",
+ "Cannot parse LMM input argument.", NULL);
+ goto error_return;
+ }
+ if(!strcmp(bufval,"Adams")) {
+ lmmB = CV_ADAMS;
+ } else if(!strcmp(bufval,"BDF")) {
+ lmmB = CV_BDF;
+ } else {
+ cvmErrHandler(-999, "CVODES", "CVodeInitB",
+ "LMM has an illegal value.", NULL);
+ goto error_return;
+ }
+ mxFree(bufval);
+
+ /* Extract iterB */
+
+ buflen = mxGetM(prhs[2]) * mxGetN(prhs[2]) + 1;
+ bufval = mxCalloc(buflen, sizeof(char));
+ status = mxGetString(prhs[2], bufval, buflen);
+ if(status != 0) {
+ cvmErrHandler(-999, "CVODES", "CVodeInitB",
+ "Cannot parse NLS input argument.", NULL);
+ goto error_return;
+ }
+ if(!strcmp(bufval,"Functional")) {
+ iterB = CV_FUNCTIONAL;
+ } else if(!strcmp(bufval,"Newton")) {
+ iterB = CV_NEWTON;
+ } else {
+ cvmErrHandler(-999, "CVODES", "CVodeInitB",
+ "NLS has an illegal value.", NULL);
+ goto error_return;
+ }
+ mxFree(bufval);
+
+ /* Extract final time */
+
+ tB0 = (double)mxGetScalar(prhs[3]);
+
+ /* Extract final conditions */
+
+ yB0 = mxGetPr(prhs[4]);
+ NB = mxGetM(prhs[4]);
+
+ /* Create the solution N_Vector */
+
+ yB = NewVector(NB);
+
+ /* Load final conditions */
+
+ PutData(yB, yB0, NB);
+
+ /* Extract options structure */
+
+ options = prhs[5];
+
+ break;
+
+ case 1: /* BACKWARD SOLVER RE-INITIALIZATION */
+
+ /* Extract index of current backward problem */
+
+ idxB = (int)mxGetScalar(prhs[0]);
+
+ /* Find current backward problem */
+
+ found_bck = FALSE;
+ bckPb = cvmData->bckPb;
+ while (bckPb != NULL) {
+ if (indexB == idxB) {
+ found_bck = TRUE;
+ break;
+ }
+ bckPb = bckPb->next;
+ }
+
+ if (!found_bck) {
+ cvmErrHandler(-999, "CVODES", "CVodeReInitB",
+ "idxB has an illegal value.", NULL);
+ goto error_return;
+ }
+
+ /* If backward monitoring was enabled, finalize it now. */
+
+ if (monB) mxW_CVodeMonitorB(2, indexB, 0.0, NULL, NULL, bckPb);
+
+ /* Extract final time */
+
+ tB0 = (double)mxGetScalar(prhs[1]);
+
+ /* Extract final conditions */
+
+ yB0 = mxGetPr(prhs[2]);
+
+ if (mxGetM(prhs[2]) != NB) {
+ cvmErrHandler(-999, "CVODES", "CVodeReInitB",
+ "Size of yB0 changed from CVodeInitB call.", NULL);
+ goto error_return;
+ }
+
+ /* Load final conditions */
+
+ PutData(yB, yB0, NB);
+
+ /* Extract options structure */
+
+ options = prhs[3];
+
+ break;
+
+ }
+
+ /* Process the options structure */
+
+ status = get_IntgrOptions(options, bckPb, FALSE, lmmB,
+ &maxordB, &sldB, &errmsgB, &mxstepsB,
+ &itolB, &reltolB, &SabstolB, &VabstolB,
+ &hinB, &hmaxB, &hminB, &tstopB, &rhs_s);
+ if (status != 0) goto error_return;
+
+ /*
+ * ----------------------------------------
+ * Call appropriate CVODES functions
+ *
+ * If action = 0
+ * Create CVODES object and allocate memory
+ * Initialize and allocate memory
+ * If action = 1
+ * Reinitialize solver
+ * ----------------------------------------
+ */
+
+ switch (action) {
+
+ case 0:
+
+ status = CVodeCreateB(cvode_mem, lmmB, iterB, &idxB);
+ if (status != CV_SUCCESS) goto error_return;
+
+ status = CVodeSetUserDataB(cvode_mem, idxB, bckPb);
+ if (status != CV_SUCCESS) goto error_return;
+
+ if (rhs_s) {
+ status = CVodeInitBS(cvode_mem, idxB, mxW_CVodeRhsBS, tB0, yB);
+ } else {
+ status = CVodeInitB(cvode_mem, idxB, mxW_CVodeRhsB, tB0, yB);
+ }
+ if (status != CV_SUCCESS) goto error_return;
+
+ /* Load idxB in the 1st output (status is 2nd one for this action) */
+
+ plhs[0] = mxCreateDoubleScalar((double)idxB);
+
+ indexB = idxB;
+
+ NbckPb++;
+
+ break;
+
+ case 1:
+
+ status = CVodeReInitB(cvode_mem, idxB, tB0, yB);
+ if (status != CV_SUCCESS) goto error_return;
+
+ break;
+
+ }
+
+ /*
+ * ----------------------------------------
+ * Set tolerances
+ * ----------------------------------------
+ */
+
+ switch (itolB) {
+ case CV_SS:
+ status = CVodeSStolerancesB(cvode_mem, idxB, reltolB, SabstolB);
+ if (status != CV_SUCCESS) goto error_return;
+ break;
+ case CV_SV:
+ NV_abstolB = N_VClone(yB);
+ PutData(NV_abstolB, VabstolB, NB);
+ status = CVodeSVtolerancesB(cvode_mem, idxB, reltolB, NV_abstolB);
+ if (status != CV_SUCCESS) goto error_return;
+ N_VDestroy(NV_abstolB);
+ break;
+ }
+
+ /*
+ * --------------------------------
+ * Set various optional inputs
+ * --------------------------------
+ */
+
+ /* set maxorder (default is consistent with LMM) */
+ status = CVodeSetMaxOrdB(cvode_mem, idxB, maxordB);
+ if (status != CV_SUCCESS) goto error_return;
+
+ /* set initial step size (the default value of 0.0 is ignored by CVODES) */
+ status = CVodeSetInitStepB(cvode_mem, idxB, hinB);
+ if (status != CV_SUCCESS) goto error_return;
+
+ /* set max step (default is infinity) */
+ status = CVodeSetMaxStepB(cvode_mem, idxB, hmaxB);
+ if (status != CV_SUCCESS) goto error_return;
+
+ /* set min step (default is 0) */
+ status = CVodeSetMinStepB(cvode_mem, idxB, hminB);
+ if (status != CV_SUCCESS) goto error_return;
+
+ /* set number of max steps */
+ status = CVodeSetMaxNumStepsB(cvode_mem, idxB, mxstepsB);
+ if (status != CV_SUCCESS) goto error_return;
+
+ /*
+ * ----------------------------------------
+ * Need a linear solver?
+ * ----------------------------------------
+ */
+
+ if (iterB == CV_NEWTON) {
+
+ status = get_LinSolvOptions(options, bckPb, FALSE,
+ &mupperB, &mlowerB,
+ &mudqB, &mldqB, &dqrelyB,
+ &ptypeB, &gstypeB, &maxlB);
+ if (status != 0) goto error_return;
+
+ switch(lsB) {
+
+ case LS_DENSE:
+
+ status = CVDenseB(cvode_mem, idxB, NB);
+ if (status != CV_SUCCESS) goto error_return;
+ if (!mxIsEmpty(mtlb_JACfctB)) {
+ status = CVDlsSetDenseJacFnB(cvode_mem, idxB, mxW_CVodeDenseJacB);
+ if (status != CV_SUCCESS) goto error_return;
+ }
+
+ break;
+
+ case LS_DIAG:
+
+ status = CVDiagB(cvode_mem, idxB);
+ if (status != CV_SUCCESS) goto error_return;
+
+ break;
+
+ case LS_BAND:
+
+ status = CVBandB(cvode_mem, idxB, NB, mupperB, mlowerB);
+ if (status != CV_SUCCESS) goto error_return;
+ if (!mxIsEmpty(mtlb_JACfctB)) {
+ status = CVDlsSetBandJacFnB(cvode_mem, idxB, mxW_CVodeBandJacB);
+ if (status != CV_SUCCESS) goto error_return;
+ }
+
+ break;
+
+ case LS_SPGMR:
+
+ status = CVSpgmrB(cvode_mem, idxB, ptypeB, maxlB);
+ if (status != CV_SUCCESS) goto error_return;
+ status = CVSpilsSetGSTypeB(cvode_mem, idxB, gstypeB);
+ if (status != CV_SUCCESS) goto error_return;
+
+ break;
+
+ case LS_SPBCG:
+
+ status = CVSpbcgB(cvode_mem, idxB, ptypeB, maxlB);
+ if (status != CV_SUCCESS) goto error_return;
+
+ break;
+
+ case LS_SPTFQMR:
+
+ status = CVSptfqmrB(cvode_mem, idxB, ptypeB, maxlB);
+ if (status != CV_SUCCESS) goto error_return;
+
+ break;
+
+ }
+
+ /* Jacobian * vector and preconditioner for SPILS linear solvers */
+
+ if ( (lsB==LS_SPGMR) || (lsB==LS_SPBCG) || (lsB==LS_SPTFQMR) ) {
+
+ if (!mxIsEmpty(mtlb_JACfctB)) {
+ status = CVSpilsSetJacTimesVecFnB(cvode_mem, idxB, mxW_CVodeSpilsJacB);
+ if (status != CV_SUCCESS) goto error_return;
+ }
+
+ switch (pmB) {
+
+ case PM_NONE:
+
+ if (!mxIsEmpty(mtlb_PSOLfctB)) {
+ if (!mxIsEmpty(mtlb_PSETfctB)) status = CVSpilsSetPreconditionerB(cvode_mem, idxB, mxW_CVodeSpilsPsetB, mxW_CVodeSpilsPsolB);
+ else status = CVSpilsSetPreconditionerB(cvode_mem, idxB, NULL, mxW_CVodeSpilsPsolB);
+ }
+ if (status != CV_SUCCESS) goto error_return;
+
+ break;
+
+ case PM_BANDPRE:
+
+ status = CVBandPrecInitB(cvode_mem, idxB, NB, mupperB, mlowerB);
+ if (status != CV_SUCCESS) goto error_return;
+
+ break;
+
+ case PM_BBDPRE:
+
+ if (!mxIsEmpty(mtlb_GCOMfctB)) status = CVBBDPrecInitB(cvode_mem, idxB, NB, mudqB, mldqB, mupperB, mlowerB, dqrelyB, mxW_CVodeBBDglocB, mxW_CVodeBBDgcomB);
+ else status = CVBBDPrecInitB(cvode_mem, idxB, NB, mudqB, mldqB, mupperB, mlowerB, dqrelyB, mxW_CVodeBBDglocB, NULL);
+ if (status != CV_SUCCESS) goto error_return;
+
+ break;
+
+ }
+
+ }
+
+ } else {
+
+ lsB = LS_NONE;
+
+ }
+
+ /* Do we monitor? */
+
+ if (monB) mxW_CVodeMonitorB(0, idxB, tB0, NULL, NULL, bckPb);
+
+ /* Successful return */
+
+ status = 0;
+ plhs[i_status] = mxCreateDoubleScalar((double)status);
+ return(0);
+
+ /* Error return */
+
+ error_return:
+ status = -1;
+ plhs[i_status] = mxCreateDoubleScalar((double)status);
+ return(-1);
+
+}
+
+
+/* CVM_QuadInitializationB
+ *
+ * action = 0 -> CVodeQuadInitB
+ * prhs contains:
+ * idxB
+ * fQB
+ * yQB0
+ * options
+ *
+ * action = 1 -> CVodeQuadReInitB
+ * idxB
+ * yQB0
+ * options
+ *
+ */
+
+static int CVM_QuadInitializationB(int action, int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
+{
+ cvmPbData bckPb;
+
+ const mxArray *options;
+
+ int idxB;
+
+ double *yQB0;
+
+ booleantype rhs_s;
+
+ booleantype errconQB;
+ int itolQB;
+ realtype reltolQB, SabstolQB, *VabstolQB;
+ N_Vector NV_abstolQB;
+
+ booleantype found_bck;
+
+ int status;
+
+ /* Extract index of current backward problem */
+
+ idxB = (int)mxGetScalar(prhs[0]);
+
+ /* Find current backward problem */
+
+ found_bck = FALSE;
+ bckPb = cvmData->bckPb;
+ while (bckPb != NULL) {
+ if (indexB == idxB) {
+ found_bck = TRUE;
+ break;
+ }
+ bckPb = bckPb->next;
+ }
+
+ if (!found_bck) {
+ cvmErrHandler(-999, "CVODES", "CVodeQuadInitB/CVodeQuadReInitB",
+ "idxB has an illegal value.", NULL);
+ goto error_return;
+ }
+
+ /*
+ * ------------------------------------
+ * Process inputs based on action
+ * ------------------------------------
+ */
+
+ switch (action) {
+
+ case 0: /* BACKWARD QUADRATURE INITIALIZATION */
+
+ /* Extract user-provided quadrature RHS function */
+
+ mxDestroyArray(mtlb_QUADfctB);
+ mtlb_QUADfctB = mxDuplicateArray(prhs[1]);
+
+ /* Extract quadrature final conditions */
+
+ yQB0 = mxGetPr(prhs[2]);
+ NqB = mxGetM(prhs[2]);
+
+ /* Create the backward quadrature N_Vector */
+
+ yQB = NewVector(NqB);
+
+ /* Load quadrature final conditions */
+
+ PutData(yQB, yQB0, NqB);
+
+ /* Extract quadrature options structure */
+
+ options = prhs[3];
+
+ break;
+
+ case 1: /* BACKWARD QUADRATURE RE-INITIALIZATION */
+
+
+ /* Extract quadrature final conditions */
+
+ yQB0 = mxGetPr(prhs[1]);
+
+ if (mxGetM(prhs[1]) != NqB) cvmErrHandler(-999, "CVODES", "CVodeQuadReInitB",
+ "Size of yQB0 changed from CVodeQuadInitB call.", NULL);
+
+ /* Load quadrature final conditions */
+
+ PutData(yQB, yQB0, NqB);
+
+ /* Extract quadrature options structure */
+
+ options = prhs[2];
+
+ break;
+
+ }
+
+ /* Process the options structure */
+
+ status = get_QuadOptions(options, bckPb, FALSE,
+ NqB, &rhs_s,
+ &errconQB,
+ &itolQB, &reltolQB, &SabstolQB, &VabstolQB);
+ if (status != 0) goto error_return;
+
+ /*
+ * ----------------------------------------
+ * Call appropriate CVODES functions
+ *
+ * If action = 0
+ * Initialize backward quadratures
+ * If action = 1
+ * Reinitialize backward quadratures
+ * ----------------------------------------
+ */
+
+ switch (action) {
+ case 0:
+ if (rhs_s) status = CVodeQuadInitBS(cvode_mem, idxB, mxW_CVodeQUADfctBS, yQB);
+ else status = CVodeQuadInitB(cvode_mem, idxB, mxW_CVodeQUADfctB, yQB);
+ if (status != CV_SUCCESS) goto error_return;
+ break;
+ case 1:
+ status = CVodeQuadReInitB(cvode_mem, idxB, yQB);
+ if (status != CV_SUCCESS) goto error_return;
+ break;
+ }
+
+ /*
+ * ----------------------------------------
+ * Set tolerances for quadrature variables
+ * ----------------------------------------
+ */
+
+ status = CVodeSetQuadErrConB(cvode_mem, idxB, errconQB);
+ if (status != CV_SUCCESS) goto error_return;
+
+ if (errconQB) {
+
+ switch (itolQB) {
+ case CV_SS:
+ status = CVodeQuadSStolerancesB(cvode_mem, idxB, reltolQB, SabstolQB);
+ if (status != CV_SUCCESS) goto error_return;
+ break;
+ case CV_SV:
+ NV_abstolQB = N_VClone(yQB);
+ PutData(NV_abstolQB, VabstolQB, NqB);
+ status = CVodeQuadSVtolerancesB(cvode_mem, idxB, reltolQB, NV_abstolQB);
+ if (status != CV_SUCCESS) goto error_return;
+ N_VDestroy(NV_abstolQB);
+ break;
+ }
+
+ }
+
+ quadrB = TRUE;
+
+ /* Successful return */
+
+ status = 0;
+ plhs[0] = mxCreateDoubleScalar((double)status);
+ return(0);
+
+ /* Error return */
+
+ error_return:
+ status = -1;
+ plhs[0] = mxCreateDoubleScalar((double)status);
+ return(-1);
+
+}
+
+
+/*
+ * CVM_Solve - Main solution function
+ *
+ */
+
+static int CVM_Solve(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
+{
+ cvmPbData fwdPb;
+
+ int buflen;
+ char *bufval;
+
+ int nlhs_bad, dims[3];
+
+ int status, cv_status;
+ int itask, is, Ntout, itout, s_idx;
+ double *tout, tret, h;
+ double *tdata, *ydata, *yQdata, *ySdata;
+ long int nst;
+
+ fwdPb = cvmData->fwdPb;
+
+
+ /* Set index of output corresponding to FSA */
+
+ if (fsa) {
+ s_idx = quadr ? 4 : 3;
+ }
+
+
+ /*
+ * ----------------------------------------------------------------
+ * Verify if number of output arguments agrees with current options
+ * ----------------------------------------------------------------
+ */
+
+ nlhs_bad = 0;
+
+ if (nlhs < 3) nlhs_bad = -1;
+ if (nlhs > 5) nlhs_bad = 1;
+ if ( (nlhs == 3) && (quadr || fsa) ) nlhs_bad = -1;
+ if ( (nlhs == 4) && (quadr && fsa) ) nlhs_bad = -1;
+ if ( (nlhs == 5) && (!quadr || !fsa) ) nlhs_bad = 1;
+
+ if (nlhs_bad < 0) {
+ cvmErrHandler(-999, "CVODES", "CVode",
+ "Too few output arguments.", NULL);
+ goto error_return;
+ }
+
+ if (nlhs_bad > 0) {
+ cvmErrHandler(-999, "CVODES", "CVode",
+ "Too many output arguments.", NULL);
+ goto error_return;
+ }
+
+ /*
+ * ----------------------------------------------------------------
+ * Extract input arguments
+ * ----------------------------------------------------------------
+ */
+
+ /* Extract tout */
+
+ Ntout = mxGetM(prhs[0]) * mxGetN(prhs[0]);
+ tout = mxGetPr(prhs[0]);
+
+ /* If rootfinding or tstop are enabled, we do not allow multiple output times */
+
+ if (rootSet && (Ntout>1)) {
+ cvmErrHandler(-999, "CVODES", "CVode",
+ "More than one tout value prohibited with rootfinding enabled.", NULL);
+ goto error_return;
+ }
+
+ if (tstopSet && (Ntout>1)) {
+ cvmErrHandler(-999, "CVODES", "CVode",
+ "More than one tout value prohibited with tstop enabled.", NULL);
+ goto error_return;
+ }
+
+ /* Extract itask */
+
+ buflen = mxGetM(prhs[1]) * mxGetN(prhs[1]) + 1;
+ bufval = mxCalloc(buflen, sizeof(char));
+ status = mxGetString(prhs[1], bufval, buflen);
+ if(!strcmp(bufval,"Normal")) {
+ itask = CV_NORMAL;
+ } else if(!strcmp(bufval,"OneStep")) {
+ itask = CV_ONE_STEP;
+ } else {
+ cvmErrHandler(-999, "CVODES", "CVode",
+ "Illegal value for itask.", NULL);
+ goto error_return;
+ }
+
+ if (itask == CV_ONE_STEP) {
+
+ /* If itask==CV_ONE_STEP, we do not allow multiple output times and we do not monitor */
+
+ if (Ntout > 1) {
+ cvmErrHandler(-999, "CVODES", "CVode",
+ "More than one tout value prohibited in ONE_STEP mode.", NULL);
+ goto error_return;
+ }
+
+ if (mon) {
+ cvmErrHandler(+999, "CVODES", "CVode",
+ "Monitoring disabled in ONE_STEP mode.", NULL);
+ mon = FALSE;
+ }
+
+ } else {
+
+ /* Check if tout values are legal */
+
+ status = CVodeGetCurrentTime(cvode_mem, &tret);
+ if (status != CV_SUCCESS) goto error_return;
+ status = CVodeGetNumSteps(cvode_mem, &nst);
+ if (status != CV_SUCCESS) goto error_return;
+
+ /* h is used throughout this function as integration direction only */
+ if (nst == 0) {
+ h = tout[0] - tret;
+ } else {
+ status = CVodeGetLastStep(cvode_mem, &h);
+ if (status != CV_SUCCESS) goto error_return;
+ if ( (tout[0] - tret + h)*h < 0.0 ) {
+ cvmErrHandler(-999, "CVODES", "CVode",
+ "Illegal value of tout.", NULL);
+ goto error_return;
+ }
+ }
+
+ for (itout=1; itout<Ntout; itout++)
+ if ( (tout[itout] - tout[itout-1])*h < 0.0 ) {
+ cvmErrHandler(-999, "CVODES", "CVode",
+ "tout values are not monotonic.", NULL);
+ goto error_return;
+ }
+
+ }
+
+ /*
+ * ----------------------------------------------------------------
+ * Prepare the output arrays
+ * ----------------------------------------------------------------
+ */
+
+ /* Return time(s) */
+
+ plhs[1] = mxCreateDoubleMatrix(1,Ntout,mxREAL);
+ tdata = mxGetPr(plhs[1]);
+
+ /* Solution vector(s) */
+
+ plhs[2] = mxCreateDoubleMatrix(N,Ntout,mxREAL);
+ ydata = mxGetPr(plhs[2]);
+
+ /* Quadrature vector(s) */
+
+ if (quadr) {
+ plhs[3] = mxCreateDoubleMatrix(Nq,Ntout,mxREAL);
+ yQdata = mxGetPr(plhs[3]);
+ }
+
+ /* Sensitivity vectors */
+
+ if (fsa) {
+ dims[0] = N;
+ dims[1] = Ns;
+ dims[2] = Ntout;
+ plhs[s_idx] = mxCreateNumericArray(3, dims, mxDOUBLE_CLASS, mxREAL);
+ ySdata = mxGetPr(plhs[s_idx]);
+ }
+
+ /*
+ * ----------------------------------------------------------------
+ * Call the CVODES main solver function
+ * ----------------------------------------------------------------
+ */
+
+ if (!mon) {
+
+ /* No monitoring. itask can be either CV_ONE_STEP or CV_NORMAL */
+
+ for (itout=0; itout<Ntout; itout++) {
+
+ if (!asa) cv_status = CVode(cvode_mem, tout[itout], y, &tret, itask);
+ else cv_status = CVodeF(cvode_mem, tout[itout], y, &tret, itask, &Nc);
+ if (cv_status < 0) goto error_return;
+
+ tdata[itout] = tret;
+
+ GetData(y, &ydata[itout*N], N);
+
+ if (quadr) {
+ status = CVodeGetQuad(cvode_mem, &tret, yQ);
+ if (status != CV_SUCCESS) goto error_return;
+ GetData(yQ, &yQdata[itout*Nq], Nq);
+ }
+
+ if (fsa) {
+ status = CVodeGetSens(cvode_mem, &tret, yS);
+ if (status != CV_SUCCESS) goto error_return;
+ for (is=0; is<Ns; is++)
+ GetData(yS[is], &ySdata[itout*Ns*N+is*N], N);
+ }
+
+ }
+
+ } else {
+
+ /* Monitoring. itask = CV_NORMAL */
+
+ for (itout=0; itout<Ntout; itout++) {
+
+ /* In ONE_STEP mode, CVODE reads tout only at the first step.
+ * We must therefore check here whether we need to take additional steps,
+ * or simply return interpolated solution at tout. */
+
+ status = CVodeGetNumSteps(cvode_mem, &nst);
+ if (status != CV_SUCCESS) goto error_return;
+ status = CVodeGetCurrentTime(cvode_mem, &tret);
+ if (status != CV_SUCCESS) goto error_return;
+
+ if ( (nst>0) && ((tret - tout[itout])*h >= 0.0) ) {
+
+ /* No need to take an additional step */
+ cv_status = CV_SUCCESS;
+
+ } else {
+
+ /* Take additional steps */
+ while(1) {
+
+ if (!asa) cv_status = CVode(cvode_mem, tout[itout], y, &tret, CV_ONE_STEP);
+ else cv_status = CVodeF(cvode_mem, tout[itout], y, &tret, CV_ONE_STEP, &Nc);
+ if (cv_status < 0) goto error_return;
+
+ /* Call the monitoring function */
+ if (quadr) {
+ status = CVodeGetQuad(cvode_mem, &tret, yQ);
+ if (status != CV_SUCCESS) goto error_return;
+ }
+ if (fsa) {
+ status = CVodeGetSens(cvode_mem, &tret, yS);
+ if (status != CV_SUCCESS) goto error_return;
+ }
+ mxW_CVodeMonitor(1, tret, y, yQ, yS, fwdPb);
+
+ /* If a root was found or tstop was reached, break out of while loop */
+ if (cv_status == CV_TSTOP_RETURN || cv_status == CV_ROOT_RETURN) break;
+
+ /* If current tout was reached break out of while loop */
+ if ( (tret - tout[itout])*h >= 0.0 ) break;
+
+ }
+
+ }
+
+ /* On a tstop or root return, return solution at tret.
+ * Otherwise (cv_status=CV_SUCCESS), return solution at tout[itout]. */
+
+ if (cv_status == CV_TSTOP_RETURN || cv_status == CV_ROOT_RETURN) {
+
+ if (quadr) {
+ status = CVodeGetQuad(cvode_mem, &tret, yQ);
+ if (status != CV_SUCCESS) goto error_return;
+ }
+
+ if (fsa) {
+ status = CVodeGetSens(cvode_mem, &tret, yS);
+ if (status != CV_SUCCESS) goto error_return;
+ }
+
+ } else {
+
+ tret = tout[itout];
+
+ status = CVodeGetDky(cvode_mem, tret, 0, y);
+ if (status != CV_SUCCESS) goto error_return;
+
+ if (quadr) {
+ status = CVodeGetQuadDky(cvode_mem, tret, 0, yQ);
+ if (status != CV_SUCCESS) goto error_return;
+ }
+
+ if (fsa) {
+ status = CVodeGetSensDky(cvode_mem, tret, 0, yS);
+ if (status != CV_SUCCESS) goto error_return;
+ }
+
+ }
+
+ tdata[itout] = tret;
+
+ GetData(y, &ydata[itout*N], N);
+
+ if (quadr) GetData(yQ, &yQdata[itout*Nq], Nq);
+
+ if (fsa)
+ for (is=0; is<Ns; is++)
+ GetData(yS[is], &ySdata[itout*Ns*N+is*N], N);
+
+ }
+
+ }
+
+ /* CVODE return flag (only non-negative values make it here) */
+
+ plhs[0] = mxCreateDoubleScalar((double)cv_status);
+ return(0);
+
+ /* Error return */
+
+ error_return:
+ status = -1;
+ plhs[0] = mxCreateDoubleScalar((double)status);
+ plhs[1] = mxCreateDoubleMatrix(0,0,mxREAL);
+ plhs[2] = mxCreateDoubleMatrix(0,0,mxREAL);
+ if (quadr) {
+ plhs[3] = mxCreateDoubleMatrix(0,0,mxREAL);
+ }
+ if (fsa) {
+ s_idx = quadr ? 4 : 3;
+ plhs[s_idx] = mxCreateDoubleMatrix(0,0,mxREAL);
+ }
+ return(-1);
+
+}
+
+
+static int CVM_SolveB(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
+{
+ cvmPbData bckPb;
+
+ int buflen;
+ char *bufval;
+
+ int nlhs_bad;
+
+ int itaskB, NtoutB;
+ double *toutB;
+
+ double tret, h;
+
+ booleantype any_quadrB, any_monB;
+
+ int status, cv_status;
+
+ /*
+ * -------------------------------------------------------
+ * Check whether quadratures and/or monitoring are enabled
+ * for at least one backward problem
+ * -------------------------------------------------------
+ */
+
+ any_quadrB = FALSE;
+ any_monB = FALSE;
+ bckPb = cvmData->bckPb;
+ while(bckPb != NULL) {
+ if (quadrB) any_quadrB = TRUE;
+ if (monB) any_monB = TRUE;
+ bckPb = bckPb->next;
+ }
+
+ /*
+ * ----------------------------------------------------------------
+ * Verify if number of output arguments agrees with current options
+ * ----------------------------------------------------------------
+ */
+
+ nlhs_bad = 0;
+
+ if (nlhs < 3) nlhs_bad = -1;
+ if (nlhs > 4) nlhs_bad = 1;
+ if ( (nlhs == 3) && any_quadrB ) nlhs_bad = -1;
+
+ if (nlhs_bad < 0) {
+ cvmErrHandler(-999, "CVODES", "CVodeB",
+ "Too few output arguments.", NULL);
+ goto error_return;
+ }
+
+ if (nlhs_bad > 0) {
+ cvmErrHandler(-999, "CVODES", "CVodeB",
+ "Too many output arguments.", NULL);
+ goto error_return;
+ }
+
+ /*
+ * ----------------------------------------------------------------
+ * Extract input arguments
+ * ----------------------------------------------------------------
+ */
+
+ /* Extract tout */
+
+ NtoutB = mxGetM(prhs[0]) * mxGetN(prhs[0]);
+ toutB = mxGetPr(prhs[0]);
+
+ /* Check if first tout value is in the right direction */
+
+ status = CVodeGetLastStep(cvode_mem, &h);
+ if (status != CV_SUCCESS) goto error_return;
+ status = CVodeGetCurrentTime(cvode_mem, &tret);
+ if (status != CV_SUCCESS) goto error_return;
+
+ /* The stepsize of the forward problem is used to indicate the integration direction */
+ if ( (tret - toutB[0])*h < 0.0 ) {
+ cvmErrHandler(-999, "CVODES", "CVodeB",
+ "tout value in wrong direction.", NULL);
+ goto error_return;
+ }
+
+ /* Extract itaskB */
+
+ buflen = mxGetM(prhs[1]) * mxGetN(prhs[1]) + 1;
+ bufval = mxCalloc(buflen, sizeof(char));
+ status = mxGetString(prhs[1], bufval, buflen);
+ if(!strcmp(bufval,"Normal")) {
+ itaskB = CV_NORMAL;
+ } else if(!strcmp(bufval,"OneStep")) {
+ itaskB = CV_ONE_STEP;
+ } else {
+ cvmErrHandler(-999, "CVODES", "CVodeB",
+ "Illegal value for itask.", NULL);
+ goto error_return;
+ }
+
+ /* If itask == CV_ONE_STEP, then
+ * - we do not allow multiple output times
+ * - we disable monitoring
+ */
+
+ if ( itaskB == CV_ONE_STEP ) {
+
+ if (NtoutB > 1) {
+ cvmErrHandler(-999, "CVODES", "CVodeB",
+ "More than one tout value prohibited in ONE_STEP mode.", NULL);
+ goto error_return;
+ }
+
+ if (any_monB) {
+ cvmErrHandler(+999, "CVODES", "CVodeB",
+ "Monitoring disabled in itask=CV_ONE_STEP", NULL);
+ bckPb = cvmData->bckPb;
+ while(bckPb != NULL) {
+ monB = FALSE;
+ bckPb = bckPb->next;
+ }
+ any_monB = FALSE;
+ }
+
+ }
+
+ /* Call the appropriate function to do all the work.
+ * Note: if we made it here, we rely on the functions cvmSolveB_one and cvmSolveB_more
+ * to set the output arrays in plhs appropriately. */
+
+ if (NbckPb == 1) cv_status = cvmSolveB_one(plhs, NtoutB, toutB, itaskB);
+ else cv_status = cvmSolveB_more(plhs, NtoutB, toutB, itaskB, any_quadrB, any_monB);
+
+ if (cv_status < 0) return(-1);
+ else return(0);
+
+ /* Error return */
+
+ error_return:
+ status = -1;
+ plhs[0] = mxCreateDoubleScalar((double)status);
+ plhs[1] = mxCreateDoubleMatrix(0,0,mxREAL);
+ plhs[2] = mxCreateDoubleMatrix(0,0,mxREAL);
+ if (quadrB) {
+ plhs[3] = mxCreateDoubleMatrix(0,0,mxREAL);
+ }
+ return(-1);
+
+}
+
+
+
+static int cvmSolveB_one(mxArray *plhs[], int NtoutB, double *toutB, int itaskB)
+{
+ cvmPbData bckPb;
+
+ void *cvode_memB;
+
+ double tretB, hB;
+ double *tdata, *ydata, *yQdata;
+ int itout;
+ long int nstB;
+
+ int status, cv_status;
+
+ bckPb = cvmData->bckPb;
+
+ cvode_memB = CVodeGetAdjCVodeBmem(cvode_mem, indexB);
+
+ /* Check if tout values are legal */
+
+ CVodeGetCurrentTime(cvode_memB, &tretB);
+ CVodeGetNumSteps(cvode_memB, &nstB);
+
+ /* hB is used throughout this function as integration direction only */
+ if (nstB == 0) {
+ hB = toutB[0] - tretB;
+ } else {
+ CVodeGetLastStep(cvode_memB, &hB);
+ if ( (toutB[0] - tretB + hB)*hB < 0.0 ) {
+ cvmErrHandler(-999, "CVODES", "CVodeB",
+ "Illegal value of tout.", NULL);
+ goto error_return;
+ }
+ }
+
+ for (itout=1; itout<NtoutB; itout++) {
+ if ( (toutB[itout] - toutB[itout-1])*hB < 0.0 ) {
+ cvmErrHandler(-999, "CVODES", "CVodeB",
+ "tout values are not monotonic.", NULL);
+ goto error_return;
+ }
+ }
+
+ /*
+ * ----------------------------------------------------------------
+ * Prepare the output arrays
+ * ----------------------------------------------------------------
+ */
+
+ /* Return time(s) */
+
+ plhs[1] = mxCreateDoubleMatrix(1,NtoutB,mxREAL);
+ tdata = mxGetPr(plhs[1]);
+
+ /* Solution vector(s) */
+
+ plhs[2] = mxCreateDoubleMatrix(NB,NtoutB,mxREAL);
+ ydata = mxGetPr(plhs[2]);
+
+ /* Quadrature vector(s) */
+
+ if (quadrB) {
+ plhs[3] = mxCreateDoubleMatrix(NqB,NtoutB,mxREAL);
+ yQdata = mxGetPr(plhs[3]);
+ }
+
+ /*
+ * ----------------------------------------------------------------
+ * Call the CVodeB main solver function
+ * ----------------------------------------------------------------
+ */
+
+ if (!monB) {
+
+ /* No monitoring. itaskB can be either CV_ONE_STEP or CV_NORMAL */
+
+ for (itout=0; itout<NtoutB; itout++) {
+
+ cv_status = CVodeB(cvode_mem, toutB[itout], itaskB);
+ if (cv_status < 0) goto error_return;
+
+ status = CVodeGetB(cvode_mem, indexB, &tretB, yB);
+ if (status != CV_SUCCESS) goto error_return;
+
+ tdata[itout] = tretB;
+
+ GetData(yB, &ydata[itout*NB], NB);
+
+ if (quadrB) {
+ status = CVodeGetQuadB(cvode_mem, indexB, &tretB, yQB);
+ if (status != CV_SUCCESS) goto error_return;
+ GetData(yQB, &yQdata[itout*NqB], NqB);
+ }
+
+ }
+
+
+ } else {
+
+ /* Monitoring. itask = CV_NORMAL */
+
+ for (itout=0; itout<NtoutB; itout++) {
+
+ /* In ONE_STEP mode, CVODE reads tout only at the first step.
+ * We must therefore check here whether we need to take additional steps,
+ * or simply return interpolated solution at tout. */
+
+ status = CVodeGetNumSteps(cvode_memB, &nstB);
+ if (status != CV_SUCCESS) goto error_return;
+
+ status = CVodeGetCurrentTime(cvode_memB, &tretB);
+ if (status != CV_SUCCESS) goto error_return;
+
+ if ( (nstB>0) && ((tretB - toutB[itout])*hB >= 0.0) ) {
+
+ /* No need to take an additional step */
+ cv_status = CV_SUCCESS;
+
+ } else {
+
+ /* Take additional steps */
+ while(1) {
+
+ cv_status = CVodeB(cvode_mem, toutB[itout], CV_ONE_STEP);
+ if (cv_status < 0) goto error_return;
+
+ /* Call the monitoring function */
+
+ status = CVodeGetB(cvode_mem, indexB, &tretB, yB);
+ if (status != CV_SUCCESS) goto error_return;
+
+ if (quadrB) {
+ CVodeGetQuadB(cvode_mem, indexB, &tretB, yQB);
+ if (status != CV_SUCCESS) goto error_return;
+ }
+
+ mxW_CVodeMonitorB(1, indexB, tretB, yB, yQB, bckPb);
+
+ /* If current tout was reached break out of while loop */
+ if ( (tretB - toutB[itout])*hB >= 0.0 ) break;
+
+ }
+
+ }
+
+ tretB = toutB[itout];
+
+ tdata[itout] = tretB;
+
+ status = CVodeGetDky(cvode_memB, tretB, 0, yB);
+ if (status != CV_SUCCESS) goto error_return;
+
+ GetData(yB, &ydata[itout*NB], NB);
+
+ if (quadrB) {
+ status = CVodeGetQuadDky(cvode_memB, tretB, 0, yQB);
+ if (status != CV_SUCCESS) goto error_return;
+ GetData(yQB, &yQdata[itout*NqB], NqB);
+ }
+
+ }
+
+ }
+
+ /* CVodeB return flag (only non-negative values make it here) */
+
+ plhs[0] = mxCreateDoubleScalar((double)cv_status);
+ return(0);
+
+ error_return:
+ status = -1;
+ plhs[0] = mxCreateDoubleScalar((double)status);
+ plhs[1] = mxCreateDoubleMatrix(0,0,mxREAL);
+ plhs[2] = mxCreateDoubleMatrix(0,0,mxREAL);
+ if (quadrB) {
+ plhs[3] = mxCreateDoubleMatrix(0,0,mxREAL);
+ }
+ return(-1);
+
+}
+
+
+static int cvmSolveB_more(mxArray *plhs[], int NtoutB, double *toutB, int itaskB,
+ booleantype any_quadrB, booleantype any_monB)
+{
+ cvmPbData bckPb;
+ mxArray *cell;
+ void *cvode_memB;
+
+ double tretB, h, hB;
+ double **tdata, **ydata, **yQdata;
+ int itout;
+ long int nstB;
+
+ char err_msg[80];
+
+ int status, cv_status;
+
+ /* Check if tout values are legal */
+
+ CVodeGetLastStep(cvode_mem, &h);
+
+ bckPb = cvmData->bckPb;
+ while (bckPb != NULL) {
+
+ cvode_memB = CVodeGetAdjCVodeBmem(cvode_mem, indexB);
+
+ status = CVodeGetCurrentTime(cvode_memB, &tretB);
+ if (status != CV_SUCCESS) goto error_return;
+
+ status = CVodeGetNumSteps(cvode_memB, &nstB);
+ if (status != CV_SUCCESS) goto error_return;
+
+ if (nstB > 0) {
+ status = CVodeGetLastStep(cvode_memB, &hB);
+ if (status != CV_SUCCESS) goto error_return;
+ if ( (toutB[0] - tretB + hB)*hB < 0.0 ) {
+ sprintf(err_msg, "CVodeB:: illegal value of tout (pb. %d).",indexB+1);
+ cvmErrHandler(-999, "CVODES", "CVodeB", err_msg, NULL);
+ goto error_return;
+ }
+ }
+
+ for (itout=1; itout<NtoutB; itout++) {
+ if ( (toutB[itout] - toutB[itout-1]) * h > 0.0 ) {
+ sprintf(err_msg, "CVodeB:: tout values are not monotonic (pb. %d).", indexB+1);
+ cvmErrHandler(-999, "CVODES", "CVodeB", err_msg, NULL);
+ goto error_return;
+ }
+ }
+
+ bckPb = bckPb->next;
+
+ }
+
+ /*
+ * ----------------------------------------------------------------
+ * Prepare the output arrays
+ * ----------------------------------------------------------------
+ */
+
+ plhs[1] = mxCreateCellMatrix(NbckPb,1);
+ tdata = (double **) mxMalloc(NbckPb*sizeof(double *));
+
+ plhs[2] = mxCreateCellMatrix(NbckPb,1);
+ ydata = (double **) mxMalloc(NbckPb*sizeof(double *));
+
+ if (any_quadrB) {
+ plhs[3] = mxCreateCellMatrix(NbckPb,1);
+ yQdata = (double **) mxMalloc(NbckPb*sizeof(double *));
+ }
+
+
+ bckPb = cvmData->bckPb;
+ while (bckPb != NULL) {
+
+ /* Return time(s) */
+ cell = mxCreateDoubleMatrix(1,NtoutB,mxREAL);
+ tdata[indexB] = mxGetPr(cell);
+ mxSetCell(plhs[1], indexB, cell);
+
+ /* Solution vector(s) */
+ cell = mxCreateDoubleMatrix(NB,NtoutB,mxREAL);
+ ydata[indexB] = mxGetPr(cell);
+ mxSetCell(plhs[2], indexB, cell);
+
+ /* Quadrature vector(s) */
+ if (any_quadrB) {
+ if (quadrB) {
+ cell = mxCreateDoubleMatrix(NqB,NtoutB,mxREAL);
+ yQdata[indexB] = mxGetPr(cell);
+ } else {
+ cell = mxCreateDoubleMatrix(0,0,mxREAL);
+ }
+ mxSetCell(plhs[3], indexB, cell);
+ }
+
+ bckPb = bckPb->next;
+
+ }
+
+
+ /*
+ * ----------------------------------------------------------------
+ * Call the CVodeB main solver function
+ * ----------------------------------------------------------------
+ */
+
+ if (!any_monB) {
+
+ /* No monitoring. itaskB can be either CV_ONE_STEP or CV_NORMAL */
+
+ for (itout=0; itout<NtoutB; itout++) {
+
+ cv_status = CVodeB(cvode_mem, toutB[itout], itaskB);
+ if (cv_status < 0) goto error_return;
+
+ bckPb = cvmData->bckPb;
+ while (bckPb != NULL) {
+
+ status = CVodeGetB(cvode_mem, indexB, &tretB, yB);
+ if (status != CV_SUCCESS) goto error_return;
+
+ tdata[indexB][itout] = tretB;
+
+ GetData(yB, &ydata[indexB][itout*NB], NB);
+
+ if (quadrB) {
+ status = CVodeGetQuadB(cvode_mem, indexB, &tretB, yQB);
+ if (status != CV_SUCCESS) goto error_return;
+ GetData(yQB, &yQdata[indexB][itout*NqB], NqB);
+ }
+
+ bckPb = bckPb->next;
+
+ }
+
+ }
+
+
+ } else {
+
+ /* Monitoring for at least one backward problem. itask = CV_NORMAL */
+
+ cvmErrHandler(-999, "CVODES", "CVodeB",
+ "Monitoring currently prohibited with more than one backward problem defined .", NULL);
+ goto error_return;
+
+ }
+
+ /* CVODE return flag (only non-negative values make it here) */
+
+ plhs[0] = mxCreateDoubleScalar((double)cv_status);
+ return(0);
+
+ error_return:
+ status = -1;
+ plhs[0] = mxCreateDoubleScalar((double)status);
+ plhs[1] = mxCreateDoubleMatrix(0,0,mxREAL);
+ plhs[2] = mxCreateDoubleMatrix(0,0,mxREAL);
+ if (quadrB) {
+ plhs[3] = mxCreateDoubleMatrix(0,0,mxREAL);
+ }
+ return(-1);
+
+}
+
+
+static int CVM_Stats(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
+{
+ cvmPbData fwdPb;
+
+ const char *fnames_intgr[]={
+ "nst",
+ "nfe",
+ "nge",
+ "nsetups",
+ "netf",
+ "nni",
+ "ncfn",
+ "qlast",
+ "qcur",
+ "h0used",
+ "hlast",
+ "hcur",
+ "tcur",
+ "RootInfo",
+ "QuadInfo",
+ "LSInfo",
+ "FSAInfo"
+ };
+ const char *fnames_root[]={
+ "nge",
+ "roots"
+ };
+ const char *fnames_dense[]={
+ "name",
+ "njeD",
+ "nfeD"
+ };
+ const char *fnames_diag[]={
+ "name",
+ "nfeDI"
+ };
+ const char *fnames_band[]={
+ "name",
+ "njeB",
+ "nfeB"
+ };
+ const char *fnames_spils[]={
+ "name",
+ "nli",
+ "npe",
+ "nps",
+ "ncfl",
+ "njeSG",
+ "nfeSG"
+ };
+ const char *fnames_quad[]={
+ "nfQe",
+ "netfQ"
+ };
+ const char *fnames_sens[]={
+ "nfSe",
+ "nfeS",
+ "nsetupsS",
+ "netfS",
+ "nniS",
+ "ncfnS",
+ };
+
+ long int nst, nfe, nsetups, nni, ncfn, netf, nge;
+ int qlast, qcur;
+ double h0used, hlast, hcur, tcur;
+ int *rootsfound;
+
+ long int njeD, nfeD;
+ long int nfeDI;
+ long int njeB, nfeB;
+ long int nli, npe, nps, ncfl, njeSG, nfeSG;
+
+ long int nfQe, netfQ;
+
+ long int nfSe, nfeS, netfS, nsetupsS;
+ long int nniS, ncfnS;
+
+ int i, status;
+ mxArray *mxS_root, *mxS_ls, *mxS_quad, *mxS_fsa;
+ mxArray *mxS_rootsfound;
+ double *tmp;
+ int nfields;
+
+
+ if (cvmData == NULL) return(0);
+
+ fwdPb = cvmData->fwdPb;
+
+ status = CVodeGetIntegratorStats(cvode_mem, &nst, &nfe, &nsetups,
+ &netf, &qlast, &qcur, &h0used, &hlast, &hcur, &tcur);
+ if (status != CV_SUCCESS) goto error_return;
+
+ status = CVodeGetNonlinSolvStats(cvode_mem, &nni, &ncfn);
+ if (status != CV_SUCCESS) goto error_return;
+
+ nfields = sizeof(fnames_intgr)/sizeof(*fnames_intgr);
+ plhs[0] = mxCreateStructMatrix(1, 1, nfields, fnames_intgr);
+
+ mxSetField(plhs[0], 0, "nst", mxCreateDoubleScalar((double)nst));
+ mxSetField(plhs[0], 0, "nfe", mxCreateDoubleScalar((double)nfe));
+ mxSetField(plhs[0], 0, "nsetups", mxCreateDoubleScalar((double)nsetups));
+ mxSetField(plhs[0], 0, "netf", mxCreateDoubleScalar((double)netf));
+ mxSetField(plhs[0], 0, "nni", mxCreateDoubleScalar((double)nni));
+ mxSetField(plhs[0], 0, "ncfn", mxCreateDoubleScalar((double)ncfn));
+ mxSetField(plhs[0], 0, "qlast", mxCreateDoubleScalar((double)qlast));
+ mxSetField(plhs[0], 0, "qcur", mxCreateDoubleScalar((double)qcur));
+ mxSetField(plhs[0], 0, "h0used", mxCreateDoubleScalar(h0used));
+ mxSetField(plhs[0], 0, "hlast", mxCreateDoubleScalar(hlast));
+ mxSetField(plhs[0], 0, "hcur", mxCreateDoubleScalar(hcur));
+ mxSetField(plhs[0], 0, "tcur", mxCreateDoubleScalar(tcur));
+
+
+ /* Root Finding Statistics */
+
+ if (Ng > 0) {
+
+ status = CVodeGetNumGEvals(cvode_mem, &nge);
+ if (status != CV_SUCCESS) goto error_return;
+
+ nfields = sizeof(fnames_root)/sizeof(*fnames_root);
+ mxS_root = mxCreateStructMatrix(1, 1, nfields, fnames_root);
+
+ mxSetField(mxS_root, 0, "nge", mxCreateDoubleScalar((double)nge));
+
+ rootsfound = (int *) malloc(Ng*sizeof(int));
+ status = CVodeGetRootInfo(cvode_mem, rootsfound);
+ if (status != CV_SUCCESS) goto error_return;
+ mxS_rootsfound = mxCreateDoubleMatrix(Ng,1,mxREAL);
+ tmp = mxGetPr(mxS_rootsfound);
+ for (i=0;i<Ng;i++)
+ tmp[i] = (double)rootsfound[i];
+ mxSetField(mxS_root, 0, "roots", mxS_rootsfound);
+ free(rootsfound);
+
+ } else {
+
+ mxS_root = mxCreateDoubleMatrix(0,0,mxREAL);
+
+ }
+
+ mxSetField(plhs[0], 0, "RootInfo", mxS_root);
+
+ /* Quadrature Statistics */
+
+ if (quadr) {
+
+ status = CVodeGetQuadStats(cvode_mem, &nfQe, &netfQ);
+ if (status != CV_SUCCESS) goto error_return;
+
+ nfields = sizeof(fnames_quad)/sizeof(*fnames_quad);
+ mxS_quad = mxCreateStructMatrix(1, 1, nfields, fnames_quad);
+
+ mxSetField(mxS_quad, 0, "nfQe", mxCreateDoubleScalar((double)nfQe));
+ mxSetField(mxS_quad, 0, "netfQ", mxCreateDoubleScalar((double)netfQ));
+
+ } else {
+
+ mxS_quad = mxCreateDoubleMatrix(0,0,mxREAL);
+
+ }
+
+ mxSetField(plhs[0], 0, "QuadInfo", mxS_quad);
+
+ /* Linear Solver Statistics */
+
+ switch(ls){
+
+ case LS_NONE:
+
+ mxS_ls = mxCreateDoubleMatrix(0,0,mxREAL);
+ break;
+
+ case LS_DENSE:
+
+ status = CVDlsGetNumJacEvals(cvode_mem, &njeD);
+ if (status != CV_SUCCESS) goto error_return;
+ status = CVDlsGetNumRhsEvals(cvode_mem, &nfeD);
+ if (status != CV_SUCCESS) goto error_return;
+
+ nfields = sizeof(fnames_dense)/sizeof(*fnames_dense);
+ mxS_ls = mxCreateStructMatrix(1, 1, nfields, fnames_dense);
+
+ mxSetField(mxS_ls, 0, "name", mxCreateString("Dense"));
+ mxSetField(mxS_ls, 0, "njeD", mxCreateDoubleScalar((double)njeD));
+ mxSetField(mxS_ls, 0, "nfeD", mxCreateDoubleScalar((double)nfeD));
+
+ break;
+
+ case LS_DIAG:
+
+ status = CVDiagGetNumRhsEvals(cvode_mem, &nfeDI);
+ if (status != CV_SUCCESS) goto error_return;
+
+ nfields = sizeof(fnames_diag)/sizeof(*fnames_diag);
+ mxS_ls = mxCreateStructMatrix(1, 1, nfields, fnames_diag);
+
+ mxSetField(mxS_ls, 0, "name", mxCreateString("Diag"));
+ mxSetField(mxS_ls, 0, "nfeDI", mxCreateDoubleScalar((double)nfeDI));
+
+ break;
+
+ case LS_BAND:
+
+ status = CVDlsGetNumJacEvals(cvode_mem, &njeB);
+ if (status != CV_SUCCESS) goto error_return;
+ status = CVDlsGetNumRhsEvals(cvode_mem, &nfeB);
+ if (status != CV_SUCCESS) goto error_return;
+
+ nfields = sizeof(fnames_band)/sizeof(*fnames_band);
+ mxS_ls = mxCreateStructMatrix(1, 1, nfields, fnames_band);
+
+ mxSetField(mxS_ls, 0, "name", mxCreateString("Band"));
+ mxSetField(mxS_ls, 0, "njeB", mxCreateDoubleScalar((double)njeB));
+ mxSetField(mxS_ls, 0, "nfeB", mxCreateDoubleScalar((double)nfeB));
+
+ break;
+
+ case LS_SPGMR:
+ case LS_SPBCG:
+ case LS_SPTFQMR:
+
+ status = CVSpilsGetNumLinIters(cvode_mem, &nli);
+ if (status != CV_SUCCESS) goto error_return;
+ status = CVSpilsGetNumPrecEvals(cvode_mem, &npe);
+ if (status != CV_SUCCESS) goto error_return;
+ status = CVSpilsGetNumPrecSolves(cvode_mem, &nps);
+ if (status != CV_SUCCESS) goto error_return;
+ status = CVSpilsGetNumConvFails(cvode_mem, &ncfl);
+ if (status != CV_SUCCESS) goto error_return;
+ status = CVSpilsGetNumJtimesEvals(cvode_mem, &njeSG);
+ if (status != CV_SUCCESS) goto error_return;
+ status = CVSpilsGetNumRhsEvals(cvode_mem, &nfeSG);
+ if (status != CV_SUCCESS) goto error_return;
+
+ nfields = sizeof(fnames_spils)/sizeof(*fnames_spils);
+ mxS_ls = mxCreateStructMatrix(1, 1, nfields, fnames_spils);
+
+ if (ls == LS_SPGMR)
+ mxSetField(mxS_ls, 0, "name", mxCreateString("GMRES"));
+ else if (ls == LS_SPBCG)
+ mxSetField(mxS_ls, 0, "name", mxCreateString("BiCGStab"));
+ else
+ mxSetField(mxS_ls, 0, "name", mxCreateString("TFQMR"));
+
+ mxSetField(mxS_ls, 0, "nli", mxCreateDoubleScalar((double)nli));
+ mxSetField(mxS_ls, 0, "npe", mxCreateDoubleScalar((double)npe));
+ mxSetField(mxS_ls, 0, "nps", mxCreateDoubleScalar((double)nps));
+ mxSetField(mxS_ls, 0, "ncfl", mxCreateDoubleScalar((double)ncfl));
+ mxSetField(mxS_ls, 0, "njeSG", mxCreateDoubleScalar((double)njeSG));
+ mxSetField(mxS_ls, 0, "nfeSG", mxCreateDoubleScalar((double)nfeSG));
+
+ break;
+
+ }
+
+ mxSetField(plhs[0], 0, "LSInfo", mxS_ls);
+
+ /* Forward Sensitivity Statistics */
+
+ if (fsa) {
+
+ status = CVodeGetSensStats(cvode_mem, &nfSe, &nfeS, &netfS, &nsetupsS);
+ if (status != CV_SUCCESS) goto error_return;
+
+ status = CVodeGetSensNonlinSolvStats(cvode_mem, &nniS, &ncfnS);
+ if (status != CV_SUCCESS) goto error_return;
+
+ nfields = sizeof(fnames_sens)/sizeof(*fnames_sens);
+ mxS_fsa = mxCreateStructMatrix(1, 1, nfields, fnames_sens);
+
+ mxSetField(mxS_fsa, 0, "nfSe", mxCreateDoubleScalar((double)nfSe));
+ mxSetField(mxS_fsa, 0, "nfeS", mxCreateDoubleScalar((double)nfeS));
+ mxSetField(mxS_fsa, 0, "nsetupsS", mxCreateDoubleScalar((double)nsetupsS));
+ mxSetField(mxS_fsa, 0, "netfS", mxCreateDoubleScalar((double)netfS));
+ mxSetField(mxS_fsa, 0, "nniS", mxCreateDoubleScalar((double)nniS));
+ mxSetField(mxS_fsa, 0, "ncfnS", mxCreateDoubleScalar((double)ncfnS));
+
+ } else {
+
+ mxS_fsa = mxCreateDoubleMatrix(0,0,mxREAL);
+
+ }
+
+ mxSetField(plhs[0], 0, "FSAInfo", mxS_fsa);
+
+ /* Successful return */
+
+ status = 0;
+ plhs[1] = mxCreateDoubleScalar((double)status);
+ return(0);
+
+ /* Error return */
+
+ error_return:
+ status = -1;
+ plhs[1] = mxCreateDoubleScalar((double)status);
+ return(-1);
+
+}
+
+static int CVM_StatsB(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
+{
+ cvmPbData bckPb;
+ int idxB;
+
+ const char *fnames_intgr[]={
+ "nst",
+ "nfe",
+ "nge",
+ "nsetups",
+ "netf",
+ "nni",
+ "ncfn",
+ "qlast",
+ "qcur",
+ "h0used",
+ "hlast",
+ "hcur",
+ "tcur",
+ "QuadInfo",
+ "LSInfo",
+ };
+ const char *fnames_dense[]={
+ "name",
+ "njeD",
+ "nfeD"
+ };
+ const char *fnames_diag[]={
+ "name",
+ "nfeDI"
+ };
+ const char *fnames_band[]={
+ "name",
+ "njeB",
+ "nfeB"
+ };
+ const char *fnames_spils[]={
+ "name",
+ "nli",
+ "npe",
+ "nps",
+ "ncfl",
+ "njeSG",
+ "nfeSG"
+ };
+ const char *fnames_quad[]={
+ "nfQe",
+ "netfQ"
+ };
+
+ void *cvode_memB;
+
+ long int nst, nfe, nsetups, nni, ncfn, netf;
+ int qlast, qcur;
+ double h0used, hlast, hcur, tcur;
+
+ long int njeD, nfeD;
+ long int nfeDI;
+ long int njeB, nfeB;
+ long int nli, npe, nps, ncfl, njeSG, nfeSG;
+
+ long int nfQe, netfQ;
+
+ mxArray *mxS_ls, *mxS_quad;
+ int nfields;
+
+ booleantype found_bck;
+
+ int status;
+
+ /* Extract index of current backward problem */
+
+ idxB = (int)mxGetScalar(prhs[0]);
+
+ /* Find current backward problem */
+
+ found_bck = FALSE;
+ bckPb = cvmData->bckPb;
+ while (bckPb != NULL) {
+ if (indexB == idxB) {
+ found_bck = TRUE;
+ break;
+ }
+ bckPb = bckPb->next;
+ }
+
+ if (!found_bck) cvmErrHandler(-999, "CVODES", "CVodeGetStatsB",
+ "idxB has an illegal value.", NULL);
+
+ cvode_memB = CVodeGetAdjCVodeBmem(cvode_mem, indexB);
+
+ status = CVodeGetIntegratorStats(cvode_memB, &nst, &nfe, &nsetups,
+ &netf, &qlast, &qcur, &h0used, &hlast, &hcur, &tcur);
+ if (status != CV_SUCCESS) goto error_return;
+
+ status = CVodeGetNonlinSolvStats(cvode_memB, &nni, &ncfn);
+ if (status != CV_SUCCESS) goto error_return;
+
+ nfields = sizeof(fnames_intgr)/sizeof(*fnames_intgr);
+ plhs[0] = mxCreateStructMatrix(1, 1, nfields, fnames_intgr);
+
+ mxSetField(plhs[0], 0, "nst", mxCreateDoubleScalar((double)nst));
+ mxSetField(plhs[0], 0, "nfe", mxCreateDoubleScalar((double)nfe));
+ mxSetField(plhs[0], 0, "nsetups", mxCreateDoubleScalar((double)nsetups));
+ mxSetField(plhs[0], 0, "netf", mxCreateDoubleScalar((double)netf));
+ mxSetField(plhs[0], 0, "nni", mxCreateDoubleScalar((double)nni));
+ mxSetField(plhs[0], 0, "ncfn", mxCreateDoubleScalar((double)ncfn));
+ mxSetField(plhs[0], 0, "qlast", mxCreateDoubleScalar((double)qlast));
+ mxSetField(plhs[0], 0, "qcur", mxCreateDoubleScalar((double)qcur));
+ mxSetField(plhs[0], 0, "h0used", mxCreateDoubleScalar(h0used));
+ mxSetField(plhs[0], 0, "hlast", mxCreateDoubleScalar(hlast));
+ mxSetField(plhs[0], 0, "hcur", mxCreateDoubleScalar(hcur));
+ mxSetField(plhs[0], 0, "tcur", mxCreateDoubleScalar(tcur));
+
+
+ /* Quadrature Statistics */
+
+ if (quadrB) {
+
+ status = CVodeGetQuadStats(cvode_memB, &nfQe, &netfQ);
+ if (status != CV_SUCCESS) goto error_return;
+
+ nfields = sizeof(fnames_quad)/sizeof(*fnames_quad);
+ mxS_quad = mxCreateStructMatrix(1, 1, nfields, fnames_quad);
+
+ mxSetField(mxS_quad, 0, "nfQe", mxCreateDoubleScalar((double)nfQe));
+ mxSetField(mxS_quad, 0, "netfQ", mxCreateDoubleScalar((double)netfQ));
+
+ } else {
+
+ mxS_quad = mxCreateDoubleMatrix(0,0,mxREAL);
+
+ }
+
+ mxSetField(plhs[0], 0, "QuadInfo", mxS_quad);
+
+ /* Linear Solver Statistics */
+
+ switch(lsB){
+
+ case LS_NONE:
+
+ mxS_ls = mxCreateDoubleMatrix(0,0,mxREAL);
+ break;
+
+ case LS_DENSE:
+
+ status = CVDlsGetNumJacEvals(cvode_memB, &njeD);
+ if (status != CV_SUCCESS) goto error_return;
+ status = CVDlsGetNumRhsEvals(cvode_memB, &nfeD);
+ if (status != CV_SUCCESS) goto error_return;
+
+ nfields = sizeof(fnames_dense)/sizeof(*fnames_dense);
+ mxS_ls = mxCreateStructMatrix(1, 1, nfields, fnames_dense);
+
+ mxSetField(mxS_ls, 0, "name", mxCreateString("Dense"));
+ mxSetField(mxS_ls, 0, "njeD", mxCreateDoubleScalar((double)njeD));
+ mxSetField(mxS_ls, 0, "nfeD", mxCreateDoubleScalar((double)nfeD));
+
+ break;
+
+ case LS_DIAG:
+
+ status = CVDiagGetNumRhsEvals(cvode_memB, &nfeDI);
+ if (status != CV_SUCCESS) goto error_return;
+
+ nfields = sizeof(fnames_diag)/sizeof(*fnames_diag);
+ mxS_ls = mxCreateStructMatrix(1, 1, nfields, fnames_diag);
+
+ mxSetField(mxS_ls, 0, "name", mxCreateString("Diag"));
+ mxSetField(mxS_ls, 0, "nfeDI", mxCreateDoubleScalar((double)nfeDI));
+
+ break;
+
+ case LS_BAND:
+
+ status = CVDlsGetNumJacEvals(cvode_memB, &njeB);
+ if (status != CV_SUCCESS) goto error_return;
+ status = CVDlsGetNumRhsEvals(cvode_memB, &nfeB);
+ if (status != CV_SUCCESS) goto error_return;
+
+ nfields = sizeof(fnames_band)/sizeof(*fnames_band);
+ mxS_ls = mxCreateStructMatrix(1, 1, nfields, fnames_band);
+
+ mxSetField(mxS_ls, 0, "name", mxCreateString("Band"));
+ mxSetField(mxS_ls, 0, "njeB", mxCreateDoubleScalar((double)njeB));
+ mxSetField(mxS_ls, 0, "nfeB", mxCreateDoubleScalar((double)nfeB));
+
+ break;
+
+ case LS_SPGMR:
+ case LS_SPBCG:
+ case LS_SPTFQMR:
+
+ status = CVSpilsGetNumLinIters(cvode_memB, &nli);
+ if (status != CV_SUCCESS) goto error_return;
+ status = CVSpilsGetNumPrecEvals(cvode_memB, &npe);
+ if (status != CV_SUCCESS) goto error_return;
+ status = CVSpilsGetNumPrecSolves(cvode_memB, &nps);
+ if (status != CV_SUCCESS) goto error_return;
+ status = CVSpilsGetNumConvFails(cvode_memB, &ncfl);
+ if (status != CV_SUCCESS) goto error_return;
+ status = CVSpilsGetNumJtimesEvals(cvode_memB, &njeSG);
+ if (status != CV_SUCCESS) goto error_return;
+ status = CVSpilsGetNumRhsEvals(cvode_memB, &nfeSG);
+ if (status != CV_SUCCESS) goto error_return;
+
+ nfields = sizeof(fnames_spils)/sizeof(*fnames_spils);
+ mxS_ls = mxCreateStructMatrix(1, 1, nfields, fnames_spils);
+
+ if (lsB == LS_SPGMR)
+ mxSetField(mxS_ls, 0, "name", mxCreateString("GMRES"));
+ else if (lsB == LS_SPBCG)
+ mxSetField(mxS_ls, 0, "name", mxCreateString("BiCGStab"));
+ else
+ mxSetField(mxS_ls, 0, "name", mxCreateString("TFQMR"));
+
+ mxSetField(mxS_ls, 0, "nli", mxCreateDoubleScalar((double)nli));
+ mxSetField(mxS_ls, 0, "npe", mxCreateDoubleScalar((double)npe));
+ mxSetField(mxS_ls, 0, "nps", mxCreateDoubleScalar((double)nps));
+ mxSetField(mxS_ls, 0, "ncfl", mxCreateDoubleScalar((double)ncfl));
+ mxSetField(mxS_ls, 0, "njeSG", mxCreateDoubleScalar((double)njeSG));
+ mxSetField(mxS_ls, 0, "nfeSG", mxCreateDoubleScalar((double)nfeSG));
+
+ break;
+ }
+
+ mxSetField(plhs[0], 0, "LSInfo", mxS_ls);
+
+ /* Successful return */
+
+ status = 0;
+ plhs[1] = mxCreateDoubleScalar((double)status);
+ return(0);
+
+ /* Error return */
+
+ error_return:
+ status = -1;
+ plhs[1] = mxCreateDoubleScalar((double)status);
+ return(-1);
+
+}
+
+
+static int CVM_Set(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
+{
+ cvmPbData fwdPb;
+
+ const mxArray *options;
+ mxArray *opt;
+
+ double tstop;
+
+ int status;
+
+ fwdPb = cvmData->fwdPb;
+ options = prhs[0];
+
+ /* Return now if options was empty */
+
+ if (mxIsEmpty(options)) return(0);
+
+ /* User data */
+
+ opt = mxGetField(options,0,"UserData");
+ if ( !mxIsEmpty(opt) ) {
+ mxDestroyArray(mtlb_data);
+ mtlb_data = mxDuplicateArray(opt);
+ }
+
+ /* Stopping time */
+
+ opt = mxGetField(options,0,"StopTime");
+ if ( !mxIsEmpty(opt) ) {
+ tstop = (double)mxGetScalar(opt);
+ status = CVodeSetStopTime(cvode_mem, tstop);
+ if (status != CV_SUCCESS) goto error_return;
+ }
+
+ /* Successful return */
+
+ status = 0;
+ plhs[0] = mxCreateDoubleScalar((double)status);
+ return(0);
+
+ /* Error return */
+
+ error_return:
+ status = -1;
+ plhs[0] = mxCreateDoubleScalar((double)status);
+ return(-1);
+
+}
+
+static int CVM_SetB(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
+{
+ return(0);
+}
+
+static int CVM_Get(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
+{
+ cvmPbData fwdPb;
+
+ double t;
+ N_Vector ewt;
+ double *this, *next;
+ int key, k, i, nfields;
+
+ CVadjCheckPointRec *ckpnt;
+ const char *fnames_ckpnt[]={
+ "t0",
+ "t1",
+ "nstep",
+ "order",
+ "step"
+ };
+
+ int status;
+
+
+ fwdPb = cvmData->fwdPb;
+
+ key = (int) (*mxGetPr(prhs[0]));
+
+ switch (key) {
+ case 1: /* DerivSolution */
+
+ t = *mxGetPr(prhs[1]);
+ k = (int) (*mxGetPr(prhs[2]));
+
+ plhs[0] = mxCreateDoubleMatrix(N,1,mxREAL);
+ status = CVodeGetDky(cvode_mem, t, k, y);
+ if (status != CV_SUCCESS) goto error_return;
+ GetData(y, mxGetPr(plhs[0]), N);
+
+ break;
+
+ case 2: /* ErrorWeights */
+
+ ewt = N_VClone(y);
+
+ plhs[0] = mxCreateDoubleMatrix(N,1,mxREAL);
+ status = CVodeGetErrWeights(cvode_mem, ewt);
+ if (status != CV_SUCCESS) goto error_return;
+ GetData(ewt, mxGetPr(plhs[0]), N);
+
+ N_VDestroy(ewt);
+
+ break;
+
+ case 3: /* not used */
+
+ break;
+
+ case 4: /* CheckPointsInfo */
+
+ ckpnt = (CVadjCheckPointRec *) malloc ( (Nc+1)*sizeof(CVadjCheckPointRec));
+ status = CVodeGetAdjCheckPointsInfo(cvode_mem, ckpnt);
+ if (status != CV_SUCCESS) {
+ free(ckpnt);
+ goto error_return;
+ }
+ nfields = sizeof(fnames_ckpnt)/sizeof(*fnames_ckpnt);
+ plhs[0] = mxCreateStructMatrix(Nc+1, 1, nfields, fnames_ckpnt);
+ for (i=0; i<=Nc; i++) {
+ this = (double *)(ckpnt[Nc-i].my_addr);
+ next = (double *)(ckpnt[Nc-i].next_addr);
+ mxSetField(plhs[0], i, "t0", mxCreateDoubleScalar((double)(ckpnt[Nc-i].t0)));
+ mxSetField(plhs[0], i, "t1", mxCreateDoubleScalar((double)(ckpnt[Nc-i].t1)));
+ mxSetField(plhs[0], i, "nstep", mxCreateDoubleScalar((double)(ckpnt[Nc-i].nstep)));
+ mxSetField(plhs[0], i, "order", mxCreateDoubleScalar((double)(ckpnt[Nc-i].order)));
+ mxSetField(plhs[0], i, "step", mxCreateDoubleScalar((double)(ckpnt[Nc-i].step)));
+ }
+ free(ckpnt);
+ break;
+
+ }
+
+ /* Successful return */
+
+ status = 0;
+ plhs[1] = mxCreateDoubleScalar((double)status);
+ return(0);
+
+ /* Error return */
+
+ error_return:
+ status = -1;
+ plhs[1] = mxCreateDoubleScalar((double)status);
+ return(-1);
+
+}
+
+static int CVM_Free(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
+{
+ cvmPbData fwdPb, bckPb;
+
+ if (cvmData == NULL) return(0);
+
+ fwdPb = cvmData->fwdPb;
+ if (mon) mxW_CVodeMonitor(2, 0.0, NULL, NULL, NULL, fwdPb);
+
+ bckPb = cvmData->bckPb;
+ while (bckPb != NULL) {
+ if (monB) mxW_CVodeMonitorB(2, indexB, 0.0, NULL, NULL, bckPb);
+ bckPb = bckPb->next;
+ }
+
+ CVodeFree(&cvode_mem);
+
+ return(0);
+}
+
+
diff --git a/sundialsTB/cvodes/cvm/src/cvm.h b/sundialsTB/cvodes/cvm/src/cvm.h
new file mode 100644
index 0000000..d247edb
--- /dev/null
+++ b/sundialsTB/cvodes/cvm/src/cvm.h
@@ -0,0 +1,281 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.14 $
+ * $Date: 2012/03/07 21:44:21 $
+ * -----------------------------------------------------------------
+ * Programmer: 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 sundials-x.y.z/src/cvodes/LICENSE.
+ * -----------------------------------------------------------------
+ * Header file for the CVODES Matlab interface.
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _CVM_H
+#define _CVM_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <string.h>
+#include <stdlib.h>
+#include "mex.h"
+#include <cvodes/cvodes.h>
+#include <cvodes/cvodes_dense.h>
+#include <cvodes/cvodes_diag.h>
+#include <cvodes/cvodes_band.h>
+#include <cvodes/cvodes_spgmr.h>
+#include <cvodes/cvodes_spbcgs.h>
+#include <cvodes/cvodes_sptfqmr.h>
+#include <cvodes/cvodes_bandpre.h>
+#include <cvodes/cvodes_bbdpre.h>
+
+/*
+ * ---------------------------------------------------------------------------------
+ * Constants
+ * ---------------------------------------------------------------------------------
+ */
+
+/* Tolerance types */
+
+enum {CV_SS, CV_SV, CV_EE};
+
+/* Linear solver types */
+
+enum {LS_NONE, LS_DENSE, LS_DIAG, LS_BAND, LS_SPGMR, LS_SPBCG, LS_SPTFQMR};
+
+/* Preconditioner modules */
+
+enum {PM_NONE, PM_BANDPRE, PM_BBDPRE};
+
+/*
+ * ---------------------------------------------------------------------------------
+ * Types for global data structures
+ * ---------------------------------------------------------------------------------
+ */
+
+
+typedef struct cvmPbData_ {
+
+
+ long int n; /* problem dimension */
+ N_Vector Y; /* solution vector */
+
+ booleantype Quadr; /* integrate quadratures? */
+ long int nq; /* number of quadratures */
+ N_Vector YQ; /* quadratures vector */
+
+ booleantype Fsa; /* integrate sensitivities? */
+ int ns; /* number of sensitivities */
+ N_Vector *YS; /* sensitivity vectors */
+
+ booleantype RootSet; /* rootfinding active? */
+ int ng; /* number of root functions */
+
+ booleantype TstopSet; /* tstop active? */
+
+ int LS; /* linear solver type */
+ int PM; /* preconditioner module */
+
+ booleantype Mon; /* monitoring? */
+
+ /* Matlab functions and data associated with this problem */
+
+ mxArray *RHSfct;
+ mxArray *QUADfct;
+
+ mxArray *JACfct;
+
+ mxArray *PSETfct;
+ mxArray *PSOLfct;
+
+ mxArray *GLOCfct;
+ mxArray *GCOMfct;
+
+ mxArray *Gfct;
+
+ mxArray *SRHSfct;
+
+ mxArray *MONfct;
+ mxArray *MONdata;
+
+ /* Pointer to the global Matlab user data */
+
+ mxArray *mtlb_data;
+
+ /* Information for backward problems only */
+
+ struct cvmPbData_ *fwd;
+ int index; /* index of this problem */
+ struct cvmPbData_ *next; /* pointer to next problem in linked list */
+
+} *cvmPbData;
+
+
+typedef struct cvmInterfaceData_ {
+
+ void *cvode_mem; /* CVODES solver memory */
+
+ booleantype asa; /* Perform ASA? */
+ int Nd; /* number of data points */
+ int Nc; /* number of check points */
+
+ struct cvmPbData_ *fwdPb;
+ struct cvmPbData_ *bckPb;
+
+ int NbckPb; /* Number of backward problems in the linked list bckPb */
+
+ booleantype errMsg; /* post error/warning messages? */
+
+} *cvmInterfaceData;
+
+
+/*
+ * ---------------------------------------------------------------------------------
+ * Error handler function
+ * ---------------------------------------------------------------------------------
+ */
+
+void cvmErrHandler(int error_code,
+ const char *module, const char *function,
+ char *msg, void *eh_data);
+
+/*
+ * ---------------------------------------------------------------------------------
+ * Wrapper functions
+ * ---------------------------------------------------------------------------------
+ */
+
+int mxW_CVodeRhs(realtype t, N_Vector y, N_Vector yd, void *user_data);
+
+int mxW_CVodeGfct(realtype t, N_Vector y, double *g, void *user_data);
+
+int mxW_CVodeQUADfct(realtype t, N_Vector y, N_Vector yQd, void *user_data);
+
+
+int mxW_CVodeSensRhs1(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);
+int mxW_CVodeSensRhs(int Ns, realtype t,
+ N_Vector y, N_Vector ydot,
+ N_Vector *yS, N_Vector *ySdot,
+ void *user_data,
+ N_Vector tmp1, N_Vector tmp2);
+
+
+int mxW_CVodeDenseJac(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);
+int mxW_CVodeBandJac(long int N, long int mupper, long int mlower, realtype t,
+ N_Vector y, N_Vector fy,
+ DlsMat J, void *user_data,
+ N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
+int mxW_CVodeSpilsJac(N_Vector v, N_Vector Jv, realtype t,
+ N_Vector y, N_Vector fy,
+ void *user_data, N_Vector tmp);
+int mxW_CVodeSpilsPset(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);
+int mxW_CVodeSpilsPsol(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);
+
+
+int mxW_CVodeBBDgloc(long int Nlocal, realtype t, N_Vector y, N_Vector g, void *user_data);
+int mxW_CVodeBBDgcom(long int Nlocal, realtype t, N_Vector y, void *user_data);
+
+void mxW_CVodeMonitor(int call, double t,
+ N_Vector y, N_Vector yQ, N_Vector *yS,
+ cvmPbData fwdPb);
+
+
+int mxW_CVodeRhsB(realtype t, N_Vector y,
+ N_Vector yB, N_Vector yBdot, void *user_dataB);
+int mxW_CVodeRhsBS(realtype t, N_Vector y, N_Vector *yS,
+ N_Vector yB, N_Vector yBd, void *user_dataB);
+
+int mxW_CVodeQUADfctB(realtype t, N_Vector y,
+ N_Vector yB, N_Vector qBdot, void *user_dataB);
+int mxW_CVodeQUADfctBS(realtype t, N_Vector y, N_Vector *yS,
+ N_Vector yB, N_Vector yQBd, void *user_dataB);
+
+int mxW_CVodeDenseJacB(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);
+int mxW_CVodeBandJacB(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);
+int mxW_CVodeSpilsJacB(N_Vector vB, N_Vector JvB, realtype t,
+ N_Vector y, N_Vector yB, N_Vector fyB,
+ void *user_dataB, N_Vector tmpB);
+int mxW_CVodeSpilsPsetB(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);
+int mxW_CVodeSpilsPsolB(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);
+
+int mxW_CVodeBBDglocB(long int NlocalB, realtype t, N_Vector y,
+ N_Vector yB, N_Vector gB, void *user_dataB);
+
+int mxW_CVodeBBDgcomB(long int NlocalB, realtype t, N_Vector y,
+ N_Vector yB, void *user_dataB);
+
+
+void mxW_CVodeMonitorB(int call, int idxB, double tB,
+ N_Vector yB, N_Vector yQB,
+ cvmPbData bckPb);
+
+/*
+ * ---------------------------------------------------------------------------------
+ * Option handling functions
+ * ---------------------------------------------------------------------------------
+ */
+
+int get_IntgrOptions(const mxArray *options, cvmPbData thisPb, booleantype fwd, int lmm,
+ int *maxord, booleantype *sld, booleantype *errmsg,
+ long int *mxsteps,
+ int *itol, realtype *reltol, double *Sabstol, double **Vabstol,
+ double *hin, double *hmax, double *hmin,
+ double *tstop, booleantype *rhs_s);
+
+int get_LinSolvOptions(const mxArray *options, cvmPbData thisPb, booleantype fwd,
+ long int *mupper, long int *mlower,
+ long int *mudq, long int *mldq, double *dqrely,
+ int *ptype, int *gstype, int *maxl);
+
+int get_QuadOptions(const mxArray *options, cvmPbData thisPb, booleantype fwd,
+ long int Nq, booleantype *rhs_s,
+ booleantype *errconQ,
+ int *itolQ, double *reltolQ, double *SabstolQ, double **VabstolQ);
+
+int get_FSAOptions(const mxArray *options, cvmPbData thisPb,
+ int *ism,
+ char **pfield_name, int **plist, double **pbar,
+ int *dqtype, double *rho,
+ booleantype *errconS, int *itolS, double *reltolS,
+ double **SabstolS, double **VabstolS);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/sundialsTB/cvodes/cvm/src/cvmOpts.c b/sundialsTB/cvodes/cvm/src/cvmOpts.c
new file mode 100644
index 0000000..dd5be2e
--- /dev/null
+++ b/sundialsTB/cvodes/cvm/src/cvmOpts.c
@@ -0,0 +1,850 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.13 $
+ * $Date: 2012/03/07 21:44:21 $
+ * -----------------------------------------------------------------
+ * Programmer: 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 sundials-x.y.z/src/cvodes/LICENSE.
+ * -----------------------------------------------------------------
+ * Option parsing functions for the CVODES Matlab interface.
+ * -----------------------------------------------------------------
+ */
+
+#include <string.h>
+#include "cvm.h"
+
+/*
+ * ---------------------------------------------------------------------------------
+ * Redability replacements
+ * ---------------------------------------------------------------------------------
+ */
+
+#define N (thisPb->n)
+#define Ns (thisPb->ns)
+#define Ng (thisPb->ng)
+#define ls (thisPb->LS)
+#define pm (thisPb->PM)
+
+#define mtlb_data (thisPb->mtlb_data)
+
+#define mtlb_JACfct (thisPb->JACfct)
+#define mtlb_PSETfct (thisPb->PSETfct)
+#define mtlb_PSOLfct (thisPb->PSOLfct)
+#define mtlb_GLOCfct (thisPb->GLOCfct)
+#define mtlb_GCOMfct (thisPb->GCOMfct)
+#define mtlb_Gfct (thisPb->Gfct)
+
+#define mon (thisPb->Mon)
+#define tstopSet (thisPb->TstopSet)
+
+#define mtlb_MONfct (thisPb->MONfct)
+#define mtlb_MONdata (thisPb->MONdata)
+
+/*
+ * ---------------------------------------------------------------------------------
+ * Option handling functions
+ * ---------------------------------------------------------------------------------
+ */
+
+int get_IntgrOptions(const mxArray *options, cvmPbData thisPb, booleantype fwd, int lmm,
+ int *maxord, booleantype *sld, booleantype *errmsg,
+ long int *mxsteps,
+ int *itol, realtype *reltol, double *Sabstol, double **Vabstol,
+ double *hin, double *hmax, double *hmin, double *tstop,
+ booleantype *rhs_s)
+{
+ mxArray *opt;
+ int q;
+ long int i, m, n;
+ double *tmp;
+ char *fctName;
+ char *fwd_fctName = "CVodeInit/CVodeReInit";
+ char *bck_fctName = "CVodeInitB/CVodeReInitB";
+
+ if (fwd) fctName = fwd_fctName;
+ else fctName = bck_fctName;
+
+ /* Set default values */
+
+ *maxord = (lmm == CV_ADAMS) ? 12 : 5;
+
+ *sld = FALSE;
+
+ *mxsteps = 0;
+
+ *itol = CV_SS;
+ *reltol = 1.0e-3;
+ *Sabstol = 1.0e-6;
+ *Vabstol = NULL;
+
+ *hin = 0.0;
+ *hmax = 0.0;
+ *hmin = 0.0;
+
+ *rhs_s = FALSE;
+
+ Ng = 0;
+ tstopSet = FALSE;
+ mon = FALSE;
+
+ *errmsg = TRUE;
+
+
+ /* Return now if options was empty */
+
+ if (mxIsEmpty(options)) return(0);
+
+ /* User data */
+
+ opt = mxGetField(options,0,"UserData");
+ if ( !mxIsEmpty(opt) ) {
+ mxDestroyArray(mtlb_data);
+ mtlb_data = mxDuplicateArray(opt);
+ }
+
+ /* Tolerances */
+
+ opt = mxGetField(options,0,"RelTol");
+ if ( !mxIsEmpty(opt) ) {
+ *reltol = *mxGetPr(opt);
+ if (*reltol < 0.0 ) {
+ cvmErrHandler(-999, "CVODES", fctName, "RelTol is negative.", NULL);
+ return(-1);
+ }
+ }
+
+ opt = mxGetField(options,0,"AbsTol");
+ if ( !mxIsEmpty(opt) ) {
+ m = mxGetM(opt);
+ n = mxGetN(opt);
+ if ( (n != 1) && (m != 1) ) {
+ cvmErrHandler(-999, "CVODES", fctName, "AbsTol is not a scalar or a vector.", NULL);
+ return(-1);
+ }
+ if ( m > n ) n = m;
+ tmp = mxGetPr(opt);
+ if (n == 1) {
+ *itol = CV_SS;
+ *Sabstol = *tmp;
+ if (*Sabstol < 0.0) {
+ cvmErrHandler(-999, "CVODES", fctName, "AbsTol is negative.", NULL);
+ return(-1);
+ }
+ } else if (n == N) {
+ *itol = CV_SV;
+ *Vabstol = (double *) malloc(N*sizeof(double));
+ for(i=0;i<N;i++) {
+ (*Vabstol)[i] = tmp[i];
+ if (tmp[i] < 0.0) {
+ cvmErrHandler(-999, "CVODES", fctName, "AbsTol has a negative component.", NULL);
+ return(-1);
+ }
+ }
+ } else {
+ cvmErrHandler(-999, "CVODES", fctName, "AbsTol does not contain N elements.", NULL);
+ return(-1);
+ }
+ }
+
+ /* Maximum number of steps */
+
+ opt = mxGetField(options,0,"MaxNumSteps");
+ if ( !mxIsEmpty(opt) ) {
+ *mxsteps = (int)*mxGetPr(opt);
+ if (*mxsteps < 0) {
+ cvmErrHandler(-999, "CVODES", fctName, "MaxNumSteps is negative.", NULL);
+ return(-1);
+ }
+ }
+
+ /* Maximum order */
+
+ opt = mxGetField(options,0,"MaxOrder");
+ if ( !mxIsEmpty(opt) ) {
+ q = (int)*mxGetPr(opt);
+ if (q <= 0) {
+ cvmErrHandler(-999, "CVODES", fctName, "MaxOrder must be positive.", NULL);
+ return(-1);
+ }
+ if (q > *maxord) {
+ cvmErrHandler(-999, "CVODES", fctName, "MaxOrder is too large for the Method specified.", NULL);
+ return(-1);
+ }
+ *maxord = q;
+ }
+
+ /* Initial step size */
+
+ opt = mxGetField(options,0,"InitialStep");
+ if ( !mxIsEmpty(opt) ) {
+ *hin = *mxGetPr(opt);
+ }
+
+ /* Maximum step size */
+
+ opt = mxGetField(options,0,"MaxStep");
+ if ( !mxIsEmpty(opt) ) {
+ tmp = mxGetPr(opt);
+ if (*tmp < 0.0) {
+ cvmErrHandler(-999, "CVODES", fctName, "MaxStep is negative.", NULL);
+ return(-1);
+ }
+ if ( mxIsInf(*tmp) ) *hmax = 0.0;
+ else *hmax = *tmp;
+ }
+
+ /* Minimum step size */
+
+ opt = mxGetField(options,0,"MinStep");
+ if ( !mxIsEmpty(opt) ) {
+ *hmin = *mxGetPr(opt);
+ if (*hmin < 0.0) {
+ cvmErrHandler(-999, "CVODES", fctName, "MinStep is negative.", NULL);
+ return(-1);
+ }
+ }
+
+ /* Stability Limit Detection */
+
+ opt = mxGetField(options,0,"StabilityLimDet");
+ if ( !mxIsEmpty(opt) ) {
+ if (!mxIsLogical(opt)) {
+ cvmErrHandler(-999, "CVODES", fctName, "StabilityLimDet is not a logical scalar.", NULL);
+ return(-1);
+ }
+ if (mxIsLogicalScalarTrue(opt)) *sld = TRUE;
+ else *sld = FALSE;
+ }
+
+ /* Monitor? */
+
+ opt = mxGetField(options,0,"MonitorFn");
+ if ( !mxIsEmpty(opt) ) {
+ mon = TRUE;
+ mxDestroyArray(mtlb_MONfct);
+ mtlb_MONfct = mxDuplicateArray(opt);
+ opt = mxGetField(options,0,"MonitorData");
+ if ( !mxIsEmpty(opt) ) {
+ mxDestroyArray(mtlb_MONdata);
+ mtlb_MONdata = mxDuplicateArray(opt);
+ }
+ }
+
+ /* The remaining options are interpreted either for
+ * forward problems only or backward problems only */
+
+ if (fwd) { /* FORWARD PROBLEM ONLY */
+
+ /* Disable error/warning messages? */
+
+ opt = mxGetField(options,0,"ErrorMessages");
+ if ( !mxIsEmpty(opt) ) {
+ if (!mxIsLogical(opt)) {
+ cvmErrHandler(-999, "CVODES", fctName, "ErrorMessages is not a logical scalar.", NULL);
+ return(-1);
+ }
+ if (mxIsLogicalScalarTrue(opt)) *errmsg = TRUE;
+ else *errmsg = FALSE;
+ }
+
+ /* Stopping time */
+ opt = mxGetField(options,0,"StopTime");
+ if ( !mxIsEmpty(opt) ) {
+ *tstop = *mxGetPr(opt);
+ tstopSet = TRUE;
+ }
+
+ /* Number of root functions */
+ opt = mxGetField(options,0,"NumRoots");
+ if ( !mxIsEmpty(opt) ) {
+
+ Ng = (int)*mxGetPr(opt);
+ if (Ng < 0) {
+ cvmErrHandler(-999, "CVODES", fctName, "NumRoots is negative.", NULL);
+ return(-1);
+ }
+ if (Ng > 0) {
+ /* Roots function */
+ opt = mxGetField(options,0,"RootsFn");
+ if ( !mxIsEmpty(opt) ) {
+ mxDestroyArray(mtlb_Gfct);
+ mtlb_Gfct = mxDuplicateArray(opt);
+ } else {
+ cvmErrHandler(-999, "CVODES", fctName, "RootsFn required for NumRoots > 0", NULL);
+ return(-1);
+ }
+ }
+
+ }
+
+ } else { /* BACKWARD PROBLEM ONLY */
+
+ /* Dependency on forward sensitivities */
+
+ opt = mxGetField(options,0,"SensDependent");
+ if ( !mxIsEmpty(opt) ) {
+ if (!mxIsLogical(opt)) {
+ cvmErrHandler(-999, "CVODES", fctName, "SensDependent is not a logical scalar.", NULL);
+ return(-1);
+ }
+ if (mxIsLogicalScalarTrue(opt)) *rhs_s = TRUE;
+ else *rhs_s = FALSE;
+ }
+
+ }
+
+ /* We made it here without problems */
+
+ return(0);
+}
+
+
+int get_LinSolvOptions(const mxArray *options, cvmPbData thisPb, booleantype fwd,
+ long int *mupper, long int *mlower,
+ long int *mudq, long int *mldq, double *dqrely,
+ int *ptype, int *gstype, int *maxl)
+{
+ mxArray *opt;
+ char *bufval;
+ int buflen, status;
+ char *fctName;
+ char *fwd_fctName = "CVodeInit/CVodeReInit";
+ char *bck_fctName = "CVodeInitB/CVodeReInitB";
+
+ if (fwd) fctName = fwd_fctName;
+ else fctName = bck_fctName;
+
+ *mupper = 0;
+ *mlower = 0;
+
+ *mudq = 0;
+ *mldq = 0;
+ *dqrely = 0.0;
+
+ *ptype = PREC_NONE;
+ *gstype = MODIFIED_GS;
+ *maxl = 0;
+
+ /* Return now if options was empty */
+
+ if (mxIsEmpty(options)) return(0);
+
+ /* Linear solver type */
+
+ opt = mxGetField(options,0,"LinearSolver");
+ if ( !mxIsEmpty(opt) ) {
+ buflen = mxGetM(opt) * mxGetN(opt) + 1;
+ bufval = mxCalloc(buflen, sizeof(char));
+ status = mxGetString(opt, bufval, buflen);
+ if(status != 0) {
+ cvmErrHandler(-999, "CVODES", fctName, "Cannot parse LinearSolver.", NULL);
+ return(-1);
+ }
+ if(!strcmp(bufval,"Diag")) ls = LS_DIAG;
+ else if(!strcmp(bufval,"Band")) ls = LS_BAND;
+ else if(!strcmp(bufval,"GMRES")) ls = LS_SPGMR;
+ else if(!strcmp(bufval,"BiCGStab")) ls = LS_SPBCG;
+ else if(!strcmp(bufval,"TFQMR")) ls = LS_SPTFQMR;
+ else if(!strcmp(bufval,"Dense")) ls = LS_DENSE;
+ else {
+ cvmErrHandler(-999, "CVODES", fctName, "LinearSolver has an illegal value.", NULL);
+ return(-1);
+ }
+ }
+
+ /* Jacobian function */
+
+ opt = mxGetField(options,0,"JacobianFn");
+ if ( !mxIsEmpty(opt) ) {
+ mxDestroyArray(mtlb_JACfct);
+ mtlb_JACfct = mxDuplicateArray(opt);
+ }
+
+ /* Band linear solver */
+
+ if (ls==LS_BAND) {
+
+ opt = mxGetField(options,0,"UpperBwidth");
+ if ( !mxIsEmpty(opt) )
+ *mupper = (long int)*mxGetPr(opt);
+
+ opt = mxGetField(options,0,"LowerBwidth");
+ if ( !mxIsEmpty(opt) )
+ *mlower = (long int)*mxGetPr(opt);
+
+ }
+
+ /* SPGMR linear solver options */
+
+ if (ls==LS_SPGMR) {
+
+ /* Type of Gram-Schmidt procedure */
+
+ opt = mxGetField(options,0,"GramSchmidtType");
+ if ( !mxIsEmpty(opt) ) {
+ buflen = mxGetM(opt) * mxGetN(opt) + 1;
+ bufval = mxCalloc(buflen, sizeof(char));
+ status = mxGetString(opt, bufval, buflen);
+ if(status != 0) {
+ cvmErrHandler(-999, "CVODES", fctName, "Cannot parse GramSchmidtType.", NULL);
+ return(-1);
+ }
+ if(!strcmp(bufval,"Classical")) *gstype = CLASSICAL_GS;
+ else if(!strcmp(bufval,"Modified")) *gstype = MODIFIED_GS;
+ else {
+ cvmErrHandler(-999, "CVODES", fctName, "GramSchmidtType has an illegal value.", NULL);
+ return(-1);
+ }
+ }
+
+ }
+
+ /* SPILS linear solver options */
+
+ if ( (ls==LS_SPGMR) || (ls==LS_SPBCG) || (ls==LS_SPTFQMR) ) {
+
+ /* Max. dimension of Krylov subspace */
+
+ opt = mxGetField(options,0,"KrylovMaxDim");
+ if ( !mxIsEmpty(opt) ) {
+ *maxl = (int)*mxGetPr(opt);
+ if (*maxl < 0) {
+ cvmErrHandler(-999, "CVODES", fctName, "KrylovMaxDim is negative.", NULL);
+ return(-1);
+ }
+ }
+
+ /* Preconditioning type */
+
+ opt = mxGetField(options,0,"PrecType");
+ if ( !mxIsEmpty(opt) ) {
+ buflen = mxGetM(opt) * mxGetN(opt) + 1;
+ bufval = mxCalloc(buflen, sizeof(char));
+ status = mxGetString(opt, bufval, buflen);
+ if(status != 0) {
+ cvmErrHandler(-999, "CVODES", fctName, "Cannot parse PrecType.", NULL);
+ return(-1);
+ }
+ if(!strcmp(bufval,"Left")) *ptype = PREC_LEFT;
+ else if(!strcmp(bufval,"Right")) *ptype = PREC_RIGHT;
+ else if(!strcmp(bufval,"Both")) *ptype = PREC_BOTH;
+ else if(!strcmp(bufval,"None")) *ptype = PREC_NONE;
+ else {
+ cvmErrHandler(-999, "CVODES", fctName, "PrecType has an illegal value.", NULL);
+ return(-1);
+ }
+ }
+
+ /* User defined precoditioning */
+
+ opt = mxGetField(options,0,"PrecSetupFn");
+ if ( !mxIsEmpty(opt) ) {
+ mxDestroyArray(mtlb_PSETfct);
+ mtlb_PSETfct = mxDuplicateArray(opt);
+ }
+
+ opt = mxGetField(options,0,"PrecSolveFn");
+ if ( !mxIsEmpty(opt) ) {
+ mxDestroyArray(mtlb_PSOLfct);
+ mtlb_PSOLfct = mxDuplicateArray(opt);
+ }
+
+ /* Preconditioner module */
+
+ opt = mxGetField(options,0,"PrecModule");
+ if ( !mxIsEmpty(opt) ) {
+ buflen = mxGetM(opt) * mxGetN(opt) + 1;
+ bufval = mxCalloc(buflen, sizeof(char));
+ status = mxGetString(opt, bufval, buflen);
+ if(status != 0) {
+ cvmErrHandler(-999, "CVODES", fctName, "Cannot parse PrecModule.", NULL);
+ return(-1);
+ }
+ if(!strcmp(bufval,"BandPre")) pm = PM_BANDPRE;
+ else if(!strcmp(bufval,"BBDPre")) pm = PM_BBDPRE;
+ else if(!strcmp(bufval,"UserDefined")) pm = PM_NONE;
+ else {
+ cvmErrHandler(-999, "CVODES", fctName, "PrecModule has an illegal value.", NULL);
+ return(-1);
+ }
+ }
+
+ if (pm != PM_NONE) {
+
+ opt = mxGetField(options,0,"UpperBwidth");
+ if ( !mxIsEmpty(opt) )
+ *mupper = (long int)*mxGetPr(opt);
+
+ opt = mxGetField(options,0,"LowerBwidth");
+ if ( !mxIsEmpty(opt) )
+ *mlower = (long int)*mxGetPr(opt);
+
+ }
+
+ if (pm == PM_BBDPRE) {
+
+ opt = mxGetField(options,0,"UpperBwidthDQ");
+ if ( !mxIsEmpty(opt) )
+ *mudq = (long int)*mxGetPr(opt);
+
+ opt = mxGetField(options,0,"LowerBwidthDQ");
+ if ( !mxIsEmpty(opt) )
+ *mldq = (long int)*mxGetPr(opt);
+
+ opt = mxGetField(options,0,"GlocalFn");
+ if ( !mxIsEmpty(opt) ) {
+ mxDestroyArray(mtlb_GLOCfct);
+ mtlb_GLOCfct = mxDuplicateArray(opt);
+ } else {
+ cvmErrHandler(-999, "CVODES", fctName, "GlocalFn required for BBD preconditioner.", NULL);
+ return(-1);
+ }
+
+ opt = mxGetField(options,0,"GcommFn");
+ if ( !mxIsEmpty(opt) ) {
+ mxDestroyArray(mtlb_GCOMfct);
+ mtlb_GCOMfct = mxDuplicateArray(opt);
+ }
+
+ }
+
+ }
+
+
+ /* We made it here without problems */
+
+ return(0);
+
+}
+
+
+int get_QuadOptions(const mxArray *options, cvmPbData thisPb, booleantype fwd,
+ long int Nq, booleantype *rhs_s,
+ booleantype *errconQ,
+ int *itolQ, double *reltolQ, double *SabstolQ, double **VabstolQ)
+{
+ mxArray *opt;
+ long int i, m, n;
+ double *tmp;
+ char *fctName;
+ char *fwd_fctName = "CVodeQuadInit/CVodeQuadReInit";
+ char *bck_fctName = "CVodeQuadInitB/CVodeQuadReInitB";
+
+ if (fwd) fctName = fwd_fctName;
+ else fctName = bck_fctName;
+
+ *errconQ = FALSE;
+ *itolQ = CV_SS;
+ *reltolQ = 1.0e-4;
+ *SabstolQ = 1.0e-6;
+ *VabstolQ = NULL;
+
+ *rhs_s = FALSE;
+
+ /* Return now if options was empty */
+
+ if (mxIsEmpty(options)) return(0);
+
+ /* For backward problems only, check dependency on forward sensitivities */
+
+ if (!fwd) {
+
+ opt = mxGetField(options,0,"SensDependent");
+ if ( !mxIsEmpty(opt) ) {
+ if (!mxIsLogical(opt)) {
+ cvmErrHandler(-999, "CVODES", fctName, "SensDependent is not a logical scalar.", NULL);
+ return(-1);
+ }
+ if (mxIsLogicalScalarTrue(opt)) *rhs_s = TRUE;
+ else *rhs_s = FALSE;
+ }
+
+ }
+
+ /* Quadrature error control and tolerances */
+
+ opt = mxGetField(options,0,"ErrControl");
+
+ if ( mxIsEmpty(opt) ) return(0);
+
+ if (!mxIsLogical(opt)) {
+ cvmErrHandler(-999, "CVODES", fctName, "ErrControl is not a logical scalar.", NULL);
+ return(-1);
+ }
+
+ if (!mxIsLogicalScalarTrue(opt)) return(0);
+
+ /* the remining options are interpreted only if quadratures are included in error control */
+
+ *errconQ = TRUE;
+
+ opt = mxGetField(options,0,"RelTol");
+ if ( !mxIsEmpty(opt) ) {
+ *reltolQ = *mxGetPr(opt);
+ if (*reltolQ < 0.0) {
+ cvmErrHandler(-999, "CVODES", fctName, "RelTol is negative.", NULL);
+ return(-1);
+ }
+ }
+
+ opt = mxGetField(options,0,"AbsTol");
+ if ( !mxIsEmpty(opt) ) {
+
+ m = mxGetN(opt);
+ n = mxGetM(opt);
+ if ( (n != 1) && (m != 1) ) {
+ cvmErrHandler(-999, "CVODES", fctName, "AbsTol is not a scalar or a vector.", NULL);
+ return(-1);
+ }
+ if ( m > n ) n = m;
+ tmp = mxGetPr(opt);
+
+ if (n == 1) {
+ *itolQ = CV_SS;
+ *SabstolQ = *tmp;
+ if (*SabstolQ < 0.0) {
+ cvmErrHandler(-999, "CVODES", fctName, "AbsTol is negative.", NULL);
+ return(-1);
+ }
+ } else if (n == Nq) {
+ *itolQ = CV_SV;
+ *VabstolQ = (double *)malloc(Nq*sizeof(double));
+ for(i=0;i<Nq;i++) {
+ (*VabstolQ)[i] = tmp[i];
+ if (tmp[i] < 0.0) {
+ cvmErrHandler(-999, "CVODES", fctName, "AbsTol has a negative component.", NULL);
+ return(-1);
+ }
+ }
+ } else {
+ cvmErrHandler(-999, "CVODES", fctName, "AbsTol does not contain Nq elements.", NULL);
+ return(-1);
+ }
+
+ }
+
+ /* We made it here without problems */
+
+ return(0);
+}
+
+int get_FSAOptions(const mxArray *options, cvmPbData thisPb,
+ int *ism,
+ char **pfield_name, int **plist, double **pbar,
+ int *dqtype, double *rho,
+ booleantype *errconS, int *itolS, double *reltolS,
+ double **SabstolS, double **VabstolS)
+{
+ mxArray *opt;
+ char *bufval;
+ int i, is, m, n, buflen, status, this_plist;
+ double *tmp;
+
+ /* Set default values */
+
+ *ism = CV_STAGGERED;
+
+ *dqtype = CV_CENTERED;
+ *rho = 0.0;
+
+ *errconS = TRUE;
+
+ *itolS = CV_EE;
+ *SabstolS = NULL;
+ *VabstolS = NULL;
+
+ *pfield_name = NULL;
+ *plist = NULL;
+ *pbar = NULL;
+
+ /* Return now if options was empty */
+
+ if (mxIsEmpty(options)) return(0);
+
+ /* Sensitivity method */
+
+ opt = mxGetField(options,0,"method");
+ if ( !mxIsEmpty(opt) ) {
+
+ buflen = mxGetM(opt) * mxGetN(opt) + 1;
+ bufval = mxCalloc(buflen, sizeof(char));
+ status = mxGetString(opt, bufval, buflen);
+ if(status != 0) {
+ cvmErrHandler(-999, "CVODES", "CVodeSensInit/CVodeSensReInit", "Could not parse method.", NULL);
+ return(-1);
+ }
+ if(!strcmp(bufval,"Simultaneous")) *ism = CV_SIMULTANEOUS;
+ else if(!strcmp(bufval,"Staggered")) *ism = CV_STAGGERED;
+ else {
+ cvmErrHandler(-999, "CVODES", "CVodeSensInit/CVodeSensReInit", "method has an illegal value.", NULL);
+ return(-1);
+ }
+ }
+
+
+ /* Field name in data structure for params. */
+
+ opt = mxGetField(options,0,"ParamField");
+ if ( !mxIsEmpty(opt) ) {
+
+ buflen = mxGetM(opt) * mxGetN(opt) + 1;
+ bufval = mxCalloc(buflen, sizeof(char));
+ status = mxGetString(opt, bufval, buflen);
+ if(status != 0) {
+ cvmErrHandler(-999, "CVODES", "CVodeSensInit/CVodeSensReInit", "Could not parse ParamField.", NULL);
+ return(-1);
+ }
+ *pfield_name = mxCalloc(buflen, sizeof(char));
+ strcpy((*pfield_name), bufval);
+
+ }
+
+ /* PLIST */
+
+ opt = mxGetField(options,0,"ParamList");
+ if ( !mxIsEmpty(opt) ) {
+
+ tmp = mxGetPr(opt);
+ m = mxGetM(opt);
+ n = mxGetN(opt);
+ if ( (n != 1) && (m != 1) ) {
+ cvmErrHandler(-999, "CVODES", "CVodeSensInit/CVodeSensReInit", "ParamList is not a vector.", NULL);
+ return(-1);
+ }
+ if (m > n) n = m;
+ if ( n != Ns) {
+ cvmErrHandler(-999, "CVODES", "CVodeSensInit/CVodeSensReInit", "ParamList does not contain Ns elements.", NULL);
+ return(-1);
+ }
+ *plist = (int *) malloc(Ns*sizeof(int));
+ for (is=0;is<Ns;is++) {
+ this_plist = (int) tmp[is];
+ if (this_plist <= 0) {
+ cvmErrHandler(-999, "CVODES", "CVodeSensInit/CVodeSensReInit", "ParamList must contain only positive integers.", NULL);
+ return(-1);
+ }
+ (*plist)[is] = this_plist - 1;
+ }
+
+ }
+
+ /* PBAR */
+
+ opt = mxGetField(options,0,"ParamScales");
+ if ( !mxIsEmpty(opt) ) {
+
+ m = mxGetM(opt);
+ n = mxGetN(opt);
+ if ( (n != 1) && (m != 1) ) {
+ cvmErrHandler(-999, "CVODES", "CVodeSensInit/CVodeSensReInit", "ParamScales is not a vector.", NULL);
+ return(-1);
+ }
+ if ( m > n ) n = m;
+ if ( n != Ns) {
+ cvmErrHandler(-999, "CVODES", "CVodeSensInit/CVodeSensReInit", "ParamScales does not contain Ns elements.", NULL);
+ return(-1);
+ }
+ tmp = mxGetPr(opt);
+ *pbar = (double *) malloc(Ns*sizeof(double));
+ for(i=0;i<Ns;i++)
+ (*pbar)[i] = tmp[i];
+
+ }
+
+ /* DQ type */
+
+ opt = mxGetField(options,0,"DQtype");
+ if ( !mxIsEmpty(opt) ) {
+
+ buflen = mxGetM(opt) * mxGetN(opt) + 1;
+ bufval = mxCalloc(buflen, sizeof(char));
+ status = mxGetString(opt, bufval, buflen);
+ if(status != 0) {
+ cvmErrHandler(-999, "CVODES", "CVodeSensInit/CVodeSensReInit", "Cannot parse DQtype.", NULL);
+ return(-1);
+ }
+ if(!strcmp(bufval,"Centered")) *dqtype = CV_CENTERED;
+ else if(!strcmp(bufval,"Forward")) *dqtype = CV_FORWARD;
+ else {
+ cvmErrHandler(-999, "CVODES", "CVodeSensInit/CVodeSensReInit", "DQtype has an illegal value.", NULL);
+ return(-1);
+ }
+ }
+
+ /* DQ parameter */
+
+ opt = mxGetField(options,0,"DQparam");
+ if ( !mxIsEmpty(opt) )
+ *rho = *mxGetPr(opt);
+
+ /* Error control */
+
+ opt = mxGetField(options,0,"ErrControl");
+ if ( !mxIsEmpty(opt) ) {
+ if (!mxIsLogical(opt)) {
+ cvmErrHandler(-999, "CVODES", "CVodeSensInit/CVodeSensReInit", "ErrControl is not a logical scalar.", NULL);
+ return(-1);
+ }
+ if (mxIsLogicalScalarTrue(opt)) *errconS = TRUE;
+ else *errconS = FALSE;
+ }
+
+ /* Tolerances */
+
+ opt = mxGetField(options,0,"RelTol");
+ if ( !mxIsEmpty(opt) ) {
+
+ *reltolS = *mxGetPr(opt);
+ if (*reltolS < 0.0) {
+ cvmErrHandler(-999, "CVODES", "CVodeSensInit/CVodeSensReInit", "RelTol is negative.", NULL);
+ return(-1);
+ }
+ opt = mxGetField(options,0,"AbsTol");
+ if ( !mxIsEmpty(opt) ) {
+
+ m = mxGetM(opt);
+ n = mxGetN(opt);
+ if ( (m == 1) && (n == Ns) ) {
+ *itolS = CV_SS;
+ tmp = mxGetPr(opt);
+ *SabstolS = (double *) malloc(Ns*sizeof(double));
+ for (is=0; is<Ns; is++) {
+ (*SabstolS)[is] = tmp[is];
+ if ( tmp[is] < 0.0 ) {
+ cvmErrHandler(-999, "CVODES", "CVodeSensInit/CVodeSensReInit", "AbsTol has a negative component.", NULL);
+ return(-1);
+ }
+ }
+ } else if ( (m == N) && (n == Ns) ) {
+ *itolS = CV_SV;
+ tmp = mxGetPr(opt);
+ *VabstolS = (double *)malloc(Ns*N*sizeof(double));
+ for (i=0; i<Ns*N; i++) {
+ (*VabstolS)[i] = tmp[i];
+ if ( tmp[i] < 0.0 ) {
+ cvmErrHandler(-999, "CVODES", "CVodeSensInit/CVodeSensReInit", "AbsTol has a negative component.", NULL);
+ return(-1);
+ }
+ }
+ } else {
+ cvmErrHandler(-999, "CVODES", "CVodeSensInit/CVodeSensReInit", "AbsTol must be either a 1xNs vector or an NxNs matrix.", NULL);
+ return(-1);
+ }
+
+ } else {
+
+ *itolS = CV_EE;
+
+ }
+
+ }
+
+ /* We made it here without problems */
+
+ return(0);
+
+}
diff --git a/sundialsTB/cvodes/cvm/src/cvmWrap.c b/sundialsTB/cvodes/cvm/src/cvmWrap.c
new file mode 100644
index 0000000..179b466
--- /dev/null
+++ b/sundialsTB/cvodes/cvm/src/cvmWrap.c
@@ -0,0 +1,1225 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.12 $
+ * $Date: 2012/03/07 21:44:21 $
+ * -----------------------------------------------------------------
+ * Programmer: 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 sundials-x.y.z/src/cvodes/LICENSE.
+ * -----------------------------------------------------------------
+ * CVODES wrapper functions.
+ * -----------------------------------------------------------------
+ */
+
+#include "cvm.h"
+#include "nvm.h"
+
+static void UpdateUserData(mxArray *new_mtlb_data, cvmPbData pb);
+static void UpdateMonitorData(mxArray *new_mtlb_data, cvmPbData pb);
+
+/*
+ * ---------------------------------------------------------------------------------
+ * Redability replacements
+ * ---------------------------------------------------------------------------------
+ */
+
+#define fsa (fwdPb->Fsa)
+#define quadr (fwdPb->Quadr)
+#define N (fwdPb->n)
+#define Nq (fwdPb->nq)
+#define Ng (fwdPb->ng)
+#define Ns (fwdPb->ns)
+
+#define quadrB (bckPb->Quadr)
+#define NB (bckPb->n)
+#define NqB (bckPb->nq)
+
+/*
+ * ---------------------------------------------------------------------------------
+ * FORWARD PROBLEMS
+ * ---------------------------------------------------------------------------------
+ */
+
+int mxW_CVodeRhs(realtype t, N_Vector y, N_Vector yd, void *user_data)
+{
+ cvmPbData fwdPb;
+ mxArray *mx_in[4], *mx_out[3];
+ int ret;
+
+ /* Extract global interface data from user-data */
+ fwdPb = (cvmPbData) user_data;
+
+ /* Inputs to the Matlab function */
+ mx_in[0] = mxCreateDoubleScalar(t); /* current t */
+ mx_in[1] = mxCreateDoubleMatrix(N,1,mxREAL); /* current y */
+ mx_in[2] = fwdPb->RHSfct; /* matlab function handle */
+ mx_in[3] = fwdPb->mtlb_data; /* matlab user data */
+
+ /* Call matlab wrapper */
+ GetData(y, mxGetPr(mx_in[1]), N);
+
+ mexCallMATLAB(3,mx_out,4,mx_in,"cvm_rhs");
+
+ PutData(yd, mxGetPr(mx_out[0]), N);
+ ret = (int)*mxGetPr(mx_out[1]);
+
+ if (!mxIsEmpty(mx_out[2])) {
+ UpdateUserData(mx_out[2], fwdPb);
+ }
+
+ /* Free temporary space */
+ mxDestroyArray(mx_in[0]);
+ mxDestroyArray(mx_in[1]);
+ mxDestroyArray(mx_out[0]);
+ mxDestroyArray(mx_out[1]);
+ mxDestroyArray(mx_out[2]);
+
+ return(ret);
+}
+
+int mxW_CVodeQUADfct(realtype t, N_Vector y, N_Vector yQd, void *user_data)
+{
+ cvmPbData fwdPb;
+ mxArray *mx_in[4], *mx_out[3];
+ int ret;
+
+ /* Extract global interface data from user-data */
+ fwdPb = (cvmPbData) user_data;
+
+ /* Inputs to the Matlab function */
+ mx_in[0] = mxCreateDoubleScalar(t); /* current t */
+ mx_in[1] = mxCreateDoubleMatrix(N,1,mxREAL); /* current y */
+ mx_in[2] = fwdPb->QUADfct; /* matlab function handle */
+ mx_in[3] = fwdPb->mtlb_data; /* matlab user data */
+
+ /* Call matlab wrapper */
+ GetData(y, mxGetPr(mx_in[1]), N);
+
+ mexCallMATLAB(3,mx_out,4,mx_in,"cvm_rhsQ");
+
+ PutData(yQd, mxGetPr(mx_out[0]), Nq);
+ ret = (int)*mxGetPr(mx_out[1]);
+
+ if (!mxIsEmpty(mx_out[2])) {
+ UpdateUserData(mx_out[2], fwdPb);
+ }
+
+ /* Free temporary space */
+ mxDestroyArray(mx_in[0]);
+ mxDestroyArray(mx_in[1]);
+ mxDestroyArray(mx_out[0]);
+ mxDestroyArray(mx_out[1]);
+ mxDestroyArray(mx_out[2]);
+
+ return(ret);
+}
+
+int mxW_CVodeGfct(realtype t, N_Vector y, double *g, void *user_data)
+{
+ cvmPbData fwdPb;
+ double *gdata;
+ int i, ret;
+ mxArray *mx_in[4], *mx_out[3];
+
+ /* Extract global interface data from user-data */
+ fwdPb = (cvmPbData) user_data;
+
+ /* Inputs to the Matlab function */
+ mx_in[0] = mxCreateDoubleScalar(t); /* current t */
+ mx_in[1] = mxCreateDoubleMatrix(N,1,mxREAL); /* current y */
+ mx_in[2] = fwdPb->Gfct; /* matlab function handle */
+ mx_in[3] = fwdPb->mtlb_data; /* matlab user data */
+
+ /* Call matlab wrapper */
+ GetData(y, mxGetPr(mx_in[1]), N);
+
+ mexCallMATLAB(3,mx_out,4,mx_in,"cvm_root");
+
+ gdata = mxGetPr(mx_out[0]);
+ for (i=0;i<Ng;i++) g[i] = gdata[i];
+
+ ret = (int)*mxGetPr(mx_out[1]);
+
+ if (!mxIsEmpty(mx_out[2])) {
+ UpdateUserData(mx_out[2], fwdPb);
+ }
+
+ /* Free temporary space */
+ mxDestroyArray(mx_in[0]);
+ mxDestroyArray(mx_in[1]);
+ mxDestroyArray(mx_out[0]);
+ mxDestroyArray(mx_out[1]);
+ mxDestroyArray(mx_out[2]);
+
+ return(ret);
+}
+
+
+int mxW_CVodeDenseJac(long int Neq, realtype t,
+ N_Vector y, N_Vector fy,
+ DlsMat J, void *user_data,
+ N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
+{
+ cvmPbData fwdPb;
+ double *J_data;
+ long int i;
+ int ret;
+ mxArray *mx_in[5], *mx_out[3];
+
+ /* Extract global interface data from user-data */
+ fwdPb = (cvmPbData) user_data;
+
+ /* Inputs to the Matlab function */
+ mx_in[0] = mxCreateDoubleScalar(t); /* current t */
+ mx_in[1] = mxCreateDoubleMatrix(N,1,mxREAL); /* current y */
+ mx_in[2] = mxCreateDoubleMatrix(N,1,mxREAL); /* current fy */
+ mx_in[3] = fwdPb->JACfct; /* matlab function handle */
+ mx_in[4] = fwdPb->mtlb_data; /* matlab user data */
+
+ /* Call matlab wrapper */
+ GetData(y, mxGetPr(mx_in[1]), N);
+ GetData(fy, mxGetPr(mx_in[2]), N);
+
+ mexCallMATLAB(3,mx_out,5,mx_in,"cvm_djac");
+
+ /* Extract data */
+ J_data = mxGetPr(mx_out[0]);
+ for (i=0;i<N;i++)
+ memcpy(DENSE_COL(J,i), J_data + i*N, N*sizeof(double));
+
+ ret = (int)*mxGetPr(mx_out[1]);
+
+ if (!mxIsEmpty(mx_out[2])) {
+ UpdateUserData(mx_out[2], fwdPb);
+ }
+
+ /* Free temporary space */
+ mxDestroyArray(mx_in[0]);
+ mxDestroyArray(mx_in[1]);
+ mxDestroyArray(mx_in[2]);
+ mxDestroyArray(mx_out[0]);
+ mxDestroyArray(mx_out[1]);
+ mxDestroyArray(mx_out[2]);
+
+ return(ret);
+}
+
+int mxW_CVodeBandJac(long int Neq, long int mupper, long int mlower, realtype t,
+ N_Vector y, N_Vector fy,
+ DlsMat J, void *user_data,
+ N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
+{
+ cvmPbData fwdPb;
+ double *J_data;
+ long int eband, i;
+ int ret;
+ mxArray *mx_in[5], *mx_out[3];
+
+ /* Extract global interface data from user-data */
+ fwdPb = (cvmPbData) user_data;
+
+ /* Inputs to the Matlab function */
+ mx_in[0] = mxCreateDoubleScalar(t); /* current t */
+ mx_in[1] = mxCreateDoubleMatrix(N,1,mxREAL); /* current y */
+ mx_in[2] = mxCreateDoubleMatrix(N,1,mxREAL); /* current fy */
+ mx_in[3] = fwdPb->JACfct; /* matlab function handle */
+ mx_in[4] = fwdPb->mtlb_data; /* matlab user data */
+
+ /* Call matlab wrapper */
+ GetData(y, mxGetPr(mx_in[1]), N);
+ GetData(fy, mxGetPr(mx_in[2]), N);
+
+ mexCallMATLAB(3,mx_out,5,mx_in,"cvm_bjac");
+
+ /* Extract data */
+ eband = mupper + mlower + 1;
+ J_data = mxGetPr(mx_out[0]);
+ for (i=0;i<N;i++)
+ memcpy(BAND_COL(J,i) - mupper, J_data + i*eband, eband*sizeof(double));
+
+ ret = (int)*mxGetPr(mx_out[1]);
+
+ if (!mxIsEmpty(mx_out[2])) {
+ UpdateUserData(mx_out[2], fwdPb);
+ }
+
+ /* Free temporary space */
+ mxDestroyArray(mx_in[0]);
+ mxDestroyArray(mx_in[1]);
+ mxDestroyArray(mx_in[2]);
+ mxDestroyArray(mx_out[0]);
+ mxDestroyArray(mx_out[1]);
+ mxDestroyArray(mx_out[2]);
+
+ return(ret);
+}
+
+
+int mxW_CVodeSpilsJac(N_Vector v, N_Vector Jv, realtype t,
+ N_Vector y, N_Vector fy,
+ void *user_data, N_Vector tmp)
+{
+ cvmPbData fwdPb;
+ mxArray *mx_in[6], *mx_out[3];
+ int ret;
+
+ /* Extract global interface data from user-data */
+ fwdPb = (cvmPbData) user_data;
+
+ /* Inputs to the Matlab function */
+ mx_in[0] = mxCreateDoubleScalar(t); /* current t */
+ mx_in[1] = mxCreateDoubleMatrix(N,1,mxREAL); /* current y */
+ mx_in[2] = mxCreateDoubleMatrix(N,1,mxREAL); /* current fy */
+ mx_in[3] = mxCreateDoubleMatrix(N,1,mxREAL); /* vector v */
+ mx_in[4] = fwdPb->JACfct; /* matlab function handle */
+ mx_in[5] = fwdPb->mtlb_data; /* matlab user data */
+
+ /* Call matlab wrapper */
+ GetData(y, mxGetPr(mx_in[1]), N);
+ GetData(fy, mxGetPr(mx_in[2]), N);
+ GetData(v, mxGetPr(mx_in[3]), N);
+
+ mexCallMATLAB(3,mx_out,6,mx_in,"cvm_jtv");
+
+ PutData(Jv, mxGetPr(mx_out[0]), N);
+ ret = (int)*mxGetPr(mx_out[1]);
+
+ if (!mxIsEmpty(mx_out[2])) {
+ UpdateUserData(mx_out[2], fwdPb);
+ }
+
+ /* Free temporary space */
+ mxDestroyArray(mx_in[0]);
+ mxDestroyArray(mx_in[1]);
+ mxDestroyArray(mx_in[2]);
+ mxDestroyArray(mx_in[3]);
+ mxDestroyArray(mx_out[0]);
+ mxDestroyArray(mx_out[1]);
+ mxDestroyArray(mx_out[2]);
+
+ return(ret);
+}
+
+
+int mxW_CVodeSpilsPset(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)
+{
+ cvmPbData fwdPb;
+ mxArray *mx_in[7], *mx_out[3];
+ int ret;
+
+ /* Extract global interface data from user-data */
+ fwdPb = (cvmPbData) user_data;
+
+ /* Inputs to the Matlab function */
+ mx_in[0] = mxCreateDoubleScalar(t); /* current t */
+ mx_in[1] = mxCreateDoubleMatrix(N,1,mxREAL); /* current y */
+ mx_in[2] = mxCreateDoubleMatrix(N,1,mxREAL); /* current fy */
+ mx_in[3] = mxCreateLogicalScalar(jok); /* jok flag */
+ mx_in[4] = mxCreateDoubleScalar(gamma); /* gamma value */
+ mx_in[5] = fwdPb->PSETfct; /* matlab function handle */
+ mx_in[6] = fwdPb->mtlb_data; /* matlab user data */
+
+ /* Call matlab wrapper */
+ GetData(y, mxGetPr(mx_in[1]), N);
+ GetData(fy, mxGetPr(mx_in[2]), N);
+
+ mexCallMATLAB(3,mx_out,7,mx_in,"cvm_pset");
+
+ *jcurPtr = mxIsLogicalScalarTrue(mx_out[0]);
+ ret = (int)*mxGetPr(mx_out[1]);
+
+ if (!mxIsEmpty(mx_out[2])) {
+ UpdateUserData(mx_out[2], fwdPb);
+ }
+
+ /* Free temporary space */
+ mxDestroyArray(mx_in[0]);
+ mxDestroyArray(mx_in[1]);
+ mxDestroyArray(mx_in[2]);
+ mxDestroyArray(mx_in[3]);
+ mxDestroyArray(mx_in[4]);
+ mxDestroyArray(mx_out[0]);
+ mxDestroyArray(mx_out[1]);
+ mxDestroyArray(mx_out[2]);
+
+ return(ret);
+}
+
+
+int mxW_CVodeSpilsPsol(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)
+{
+ cvmPbData fwdPb;
+ mxArray *mx_in[6], *mx_out[3];
+ int ret;
+
+ /* Extract global interface data from user-data */
+ fwdPb = (cvmPbData) user_data;
+
+ /* Inputs to the Matlab function */
+ mx_in[0] = mxCreateDoubleScalar(t); /* current t */
+ mx_in[1] = mxCreateDoubleMatrix(N,1,mxREAL); /* current y */
+ mx_in[2] = mxCreateDoubleMatrix(N,1,mxREAL); /* current fy */
+ mx_in[3] = mxCreateDoubleMatrix(N,1,mxREAL); /* right hand side r */
+ mx_in[4] = fwdPb->PSOLfct; /* matlab function handle */
+ mx_in[5] = fwdPb->mtlb_data; /* matlab user data */
+
+ /* Call matlab wrapper */
+ GetData(y, mxGetPr(mx_in[1]), N);
+ GetData(fy, mxGetPr(mx_in[2]), N);
+ GetData(r, mxGetPr(mx_in[3]), N);
+
+ mexCallMATLAB(3,mx_out,6,mx_in,"cvm_psol");
+
+ PutData(z, mxGetPr(mx_out[0]), N);
+ ret = (int)*mxGetPr(mx_out[1]);
+
+ if (!mxIsEmpty(mx_out[2])) {
+ UpdateUserData(mx_out[2], fwdPb);
+ }
+
+ /* Free temporary space */
+ mxDestroyArray(mx_in[0]);
+ mxDestroyArray(mx_in[1]);
+ mxDestroyArray(mx_in[2]);
+ mxDestroyArray(mx_in[3]);
+ mxDestroyArray(mx_out[0]);
+ mxDestroyArray(mx_out[1]);
+ mxDestroyArray(mx_out[2]);
+
+ return(ret);
+}
+
+/*
+ * ----------------------------
+ * BBD PRECONDITONER FUNCTIONS
+ * ----------------------------
+ */
+
+int mxW_CVodeBBDgloc(long int Nlocal, realtype t, N_Vector y,
+ N_Vector g, void *user_data)
+{
+ cvmPbData fwdPb;
+ mxArray *mx_in[4], *mx_out[3];
+ int ret;
+
+ /* Extract global interface data from user-data */
+ fwdPb = (cvmPbData) user_data;
+
+ /* Inputs to the Matlab function */
+ mx_in[0] = mxCreateDoubleScalar(t); /* current t */
+ mx_in[1] = mxCreateDoubleMatrix(N,1,mxREAL); /* current y */
+ mx_in[2] = fwdPb->GLOCfct; /* matlab function handle */
+ mx_in[3] = fwdPb->mtlb_data; /* matlab user data */
+
+ /* Call matlab wrapper */
+ GetData(y, mxGetPr(mx_in[1]), N);
+
+ mexCallMATLAB(3,mx_out,4,mx_in,"cvm_gloc");
+
+ PutData(g, mxGetPr(mx_out[0]), N);
+ ret = (int)*mxGetPr(mx_out[1]);
+
+ if (!mxIsEmpty(mx_out[2])) {
+ UpdateUserData(mx_out[2], fwdPb);
+ }
+
+ /* Free temporary space */
+ mxDestroyArray(mx_in[0]);
+ mxDestroyArray(mx_in[1]);
+ mxDestroyArray(mx_out[0]);
+ mxDestroyArray(mx_out[1]);
+ mxDestroyArray(mx_out[2]);
+
+ return(ret);
+}
+
+int mxW_CVodeBBDgcom(long int Nlocal, realtype t, N_Vector y, void *user_data)
+{
+ cvmPbData fwdPb;
+ mxArray *mx_in[4], *mx_out[2];
+ int ret;
+
+ /* Extract global interface data from user-data */
+ fwdPb = (cvmPbData) user_data;
+
+ /* Inputs to the Matlab function */
+ mx_in[0] = mxCreateDoubleScalar(t); /* current t */
+ mx_in[1] = mxCreateDoubleMatrix(N,1,mxREAL); /* current y */
+ mx_in[2] = fwdPb->GCOMfct; /* matlab function handle */
+ mx_in[3] = fwdPb->mtlb_data; /* matlab user data */
+
+ /* Call matlab wrapper */
+ GetData(y, mxGetPr(mx_in[1]), N);
+
+ mexCallMATLAB(2,mx_out,4,mx_in,"cvm_gcom");
+
+ ret = (int)*mxGetPr(mx_out[0]);
+
+ if (!mxIsEmpty(mx_out[1])) {
+ UpdateUserData(mx_out[1], fwdPb);
+ }
+
+ /* Free temporary space */
+ mxDestroyArray(mx_in[0]);
+ mxDestroyArray(mx_in[1]);
+ mxDestroyArray(mx_out[0]);
+ mxDestroyArray(mx_out[1]);
+
+ return(ret);
+}
+
+/*
+ * ----------------------------
+ * FORWARD SENSITVITY FUNCTIONS
+ * ----------------------------
+ */
+
+int mxW_CVodeSensRhs(int Nsens, realtype t,
+ N_Vector y, N_Vector yd,
+ N_Vector *yS, N_Vector *ySd,
+ void *user_data,
+ N_Vector tmp1, N_Vector tmp2)
+{
+ cvmPbData fwdPb;
+ mxArray *mx_in[7], *mx_out[3];
+ int is, ret;
+ double *tmp;
+
+ /* Extract global interface data from user-data */
+ fwdPb = (cvmPbData) user_data;
+
+ /* Inputs to the Matlab function */
+ mx_in[0] = mxCreateDoubleScalar(t); /* current t */
+ mx_in[1] = mxCreateDoubleMatrix(N,1,mxREAL); /* current y */
+ mx_in[2] = mxCreateDoubleMatrix(N,1,mxREAL); /* current yd */
+ mx_in[3] = mxCreateDoubleScalar(Ns); /* number of sensitivities */
+ mx_in[4] = mxCreateDoubleMatrix(N*Ns,1,mxREAL); /* current yS */
+ mx_in[5] = fwdPb->SRHSfct; /* matlab function handle */
+ mx_in[6] = fwdPb->mtlb_data; /* matlab user data */
+
+ /* Call matlab wrapper */
+ GetData(y, mxGetPr(mx_in[1]), N);
+ GetData(yd, mxGetPr(mx_in[2]), N);
+ tmp = mxGetPr(mx_in[4]);
+ for (is=0; is<Ns; is++)
+ GetData(yS[is], &tmp[is*N], N);
+
+ mexCallMATLAB(3,mx_out,7,mx_in,"cvm_rhsS");
+
+ tmp = mxGetPr(mx_out[0]);
+
+ for(is=0;is<Ns;is++)
+ PutData(ySd[is], &tmp[is*N], N);
+
+ ret = (int)*mxGetPr(mx_out[1]);
+
+ if (!mxIsEmpty(mx_out[2])) {
+ UpdateUserData(mx_out[2], fwdPb);
+ }
+
+ /* Free temporary space */
+
+ mxDestroyArray(mx_in[0]);
+ mxDestroyArray(mx_in[1]);
+ mxDestroyArray(mx_in[2]);
+ mxDestroyArray(mx_in[3]);
+ mxDestroyArray(mx_in[4]);
+ mxDestroyArray(mx_out[0]);
+ mxDestroyArray(mx_out[1]);
+ mxDestroyArray(mx_out[2]);
+
+ return(ret);
+}
+
+
+/*
+ * ----------------------------
+ * ADJOINT SENSITVITY FUNCTIONS
+ * ----------------------------
+ */
+
+int mxW_CVodeRhsB(realtype t, N_Vector y, N_Vector yB, N_Vector yBd, void *user_dataB)
+{
+ cvmPbData fwdPb, bckPb;
+ mxArray *mx_in[6], *mx_out[3];
+ int ret;
+
+ /* Extract global interface data from user-data */
+ bckPb = (cvmPbData) user_dataB;
+ fwdPb = bckPb->fwd;
+
+ /* Inputs to the Matlab function */
+ mx_in[0] = mxCreateDoubleScalar(0.0); /* type=0: not dependent on yS */
+ mx_in[1] = mxCreateDoubleScalar(t); /* current t */
+ mx_in[2] = mxCreateDoubleMatrix(N,1,mxREAL); /* current y */
+ mx_in[3] = mxCreateDoubleMatrix(NB,1,mxREAL); /* current yB */
+ mx_in[4] = bckPb->RHSfct; /* matlab function handle */
+ mx_in[5] = bckPb->mtlb_data; /* matlab user data */
+
+ /* Call matlab wrapper */
+ GetData(y, mxGetPr(mx_in[2]), N);
+ GetData(yB, mxGetPr(mx_in[3]), NB);
+
+ mexCallMATLAB(3,mx_out,6,mx_in,"cvm_rhsB");
+
+ PutData(yBd, mxGetPr(mx_out[0]), NB);
+
+ ret = (int)*mxGetPr(mx_out[1]);
+
+ if (!mxIsEmpty(mx_out[2])) {
+ UpdateUserData(mx_out[2], bckPb);
+ }
+
+ /* Free temporary space */
+ mxDestroyArray(mx_in[0]);
+ mxDestroyArray(mx_in[1]);
+ mxDestroyArray(mx_in[2]);
+ mxDestroyArray(mx_in[3]);
+ mxDestroyArray(mx_out[0]);
+ mxDestroyArray(mx_out[1]);
+ mxDestroyArray(mx_out[2]);
+
+ return(ret);
+}
+
+
+int mxW_CVodeRhsBS(realtype t, N_Vector y, N_Vector *yS,
+ N_Vector yB, N_Vector yBd, void *user_dataB)
+{
+ cvmPbData fwdPb, bckPb;
+ mxArray *mx_in[8], *mx_out[3];
+ int is, ret;
+ double *tmp;
+
+ /* Extract global interface data from user-data */
+ bckPb = (cvmPbData) user_dataB;
+ fwdPb = bckPb->fwd;
+
+ /* Inputs to the Matlab function */
+ mx_in[0] = mxCreateDoubleScalar(1.0); /* type=1: dependent on yS */
+ mx_in[1] = mxCreateDoubleScalar(t); /* current t */
+ mx_in[2] = mxCreateDoubleMatrix(N,1,mxREAL); /* current y */
+ mx_in[3] = mxCreateDoubleScalar(Ns); /* number of sensitivities */
+ mx_in[4] = mxCreateDoubleMatrix(N*Ns,1,mxREAL); /* current yS */
+ mx_in[5] = mxCreateDoubleMatrix(NB,1,mxREAL); /* current yB */
+ mx_in[6] = bckPb->RHSfct; /* matlab function handle */
+ mx_in[7] = bckPb->mtlb_data; /* matlab user data */
+
+ /* Call matlab wrapper */
+ GetData(y, mxGetPr(mx_in[2]), N);
+
+ tmp = mxGetPr(mx_in[4]);
+ for (is=0; is<Ns; is++)
+ GetData(yS[is], &tmp[is*N], N);
+
+ GetData(yB, mxGetPr(mx_in[5]), NB);
+
+ mexCallMATLAB(3,mx_out,8,mx_in,"cvm_rhsB");
+
+ PutData(yBd, mxGetPr(mx_out[0]), NB);
+
+ ret = (int)*mxGetPr(mx_out[1]);
+
+ if (!mxIsEmpty(mx_out[2])) {
+ UpdateUserData(mx_out[2], bckPb);
+ }
+
+ /* Free temporary space */
+ mxDestroyArray(mx_in[0]);
+ mxDestroyArray(mx_in[1]);
+ mxDestroyArray(mx_in[2]);
+ mxDestroyArray(mx_in[3]);
+ mxDestroyArray(mx_in[4]);
+ mxDestroyArray(mx_in[5]);
+ mxDestroyArray(mx_out[0]);
+ mxDestroyArray(mx_out[1]);
+ mxDestroyArray(mx_out[2]);
+
+ return(ret);
+}
+
+
+
+int mxW_CVodeQUADfctB(realtype t, N_Vector y, N_Vector yB, N_Vector yQBd, void *user_dataB)
+{
+ cvmPbData fwdPb, bckPb;
+ mxArray *mx_in[6], *mx_out[3];
+ int ret;
+
+ /* Extract global interface data from user-data */
+ bckPb = (cvmPbData) user_dataB;
+ fwdPb = bckPb->fwd;
+
+ /* Inputs to the Matlab function */
+ mx_in[0] = mxCreateDoubleScalar(0.0); /* type=0: not dependent on yS */
+ mx_in[1] = mxCreateDoubleScalar(t); /* current t */
+ mx_in[2] = mxCreateDoubleMatrix(N,1,mxREAL); /* current y */
+ mx_in[3] = mxCreateDoubleMatrix(NB,1,mxREAL); /* current yB */
+ mx_in[4] = bckPb->QUADfct; /* matlab function handle */
+ mx_in[5] = bckPb->mtlb_data; /* matlab user data */
+
+ /* Call matlab wrapper */
+ GetData(y, mxGetPr(mx_in[2]), N);
+ GetData(yB, mxGetPr(mx_in[3]), NB);
+
+ mexCallMATLAB(3,mx_out,6,mx_in,"cvm_rhsQB");
+
+ PutData(yQBd, mxGetPr(mx_out[0]), NqB);
+
+ ret = (int)*mxGetPr(mx_out[1]);
+
+ if (!mxIsEmpty(mx_out[2])) {
+ UpdateUserData(mx_out[2], bckPb);
+ }
+
+ /* Free temporary space */
+ mxDestroyArray(mx_in[0]);
+ mxDestroyArray(mx_in[1]);
+ mxDestroyArray(mx_in[2]);
+ mxDestroyArray(mx_in[3]);
+ mxDestroyArray(mx_out[0]);
+ mxDestroyArray(mx_out[1]);
+ mxDestroyArray(mx_out[2]);
+
+ return(ret);
+}
+
+
+int mxW_CVodeQUADfctBS(realtype t, N_Vector y, N_Vector *yS,
+ N_Vector yB, N_Vector yQBd, void *user_dataB)
+{
+ cvmPbData fwdPb, bckPb;
+ mxArray *mx_in[8], *mx_out[3];
+ int is, ret;
+ double *tmp;
+
+ /* Extract global interface data from user-data */
+ bckPb = (cvmPbData) user_dataB;
+ fwdPb = bckPb->fwd;
+
+ /* Inputs to the Matlab function */
+ mx_in[0] = mxCreateDoubleScalar(1.0); /* type=1: dependent on yS */
+ mx_in[1] = mxCreateDoubleScalar(t); /* current t */
+ mx_in[2] = mxCreateDoubleMatrix(N,1,mxREAL); /* current y */
+ mx_in[3] = mxCreateDoubleScalar(Ns); /* number of sensitivities */
+ mx_in[4] = mxCreateDoubleMatrix(N*Ns,1,mxREAL); /* current yS */
+ mx_in[5] = mxCreateDoubleMatrix(NB,1,mxREAL); /* current yB */
+ mx_in[6] = bckPb->QUADfct; /* matlab function handle */
+ mx_in[7] = bckPb->mtlb_data; /* matlab user data */
+
+ /* Call matlab wrapper */
+
+ GetData(y, mxGetPr(mx_in[2]), N);
+
+ tmp = mxGetPr(mx_in[4]);
+ for (is=0; is<Ns; is++)
+ GetData(yS[is], &tmp[is*N], N);
+
+ GetData(yB, mxGetPr(mx_in[5]), NB);
+
+ mexCallMATLAB(3,mx_out,8,mx_in,"cvm_rhsQB");
+
+ PutData(yQBd, mxGetPr(mx_out[0]), NqB);
+
+ ret = (int)*mxGetPr(mx_out[1]);
+
+ if (!mxIsEmpty(mx_out[2])) {
+ UpdateUserData(mx_out[2], bckPb);
+ }
+
+ /* Free temporary space */
+ mxDestroyArray(mx_in[0]);
+ mxDestroyArray(mx_in[1]);
+ mxDestroyArray(mx_in[2]);
+ mxDestroyArray(mx_in[3]);
+ mxDestroyArray(mx_in[4]);
+ mxDestroyArray(mx_in[5]);
+ mxDestroyArray(mx_out[0]);
+ mxDestroyArray(mx_out[1]);
+ mxDestroyArray(mx_out[2]);
+
+ return(ret);
+}
+
+
+
+
+int mxW_CVodeDenseJacB(long int NeqB, 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)
+{
+ cvmPbData fwdPb, bckPb;
+ double *JB_data;
+ mxArray *mx_in[6], *mx_out[3];
+ int i, ret;
+
+ /* Extract global interface data from user-data */
+ bckPb = (cvmPbData) user_dataB;
+ fwdPb = bckPb->fwd;
+
+ /* Inputs to the Matlab function */
+ mx_in[0] = mxCreateDoubleScalar(t); /* current t */
+ mx_in[1] = mxCreateDoubleMatrix(N,1,mxREAL); /* current y */
+ mx_in[2] = mxCreateDoubleMatrix(NB,1,mxREAL); /* current yB */
+ mx_in[3] = mxCreateDoubleMatrix(NB,1,mxREAL); /* current fyB */
+ mx_in[4] = bckPb->JACfct; /* matlab function handle */
+ mx_in[5] = bckPb->mtlb_data; /* matlab user data */
+
+ /* Call matlab wrapper */
+ GetData(y, mxGetPr(mx_in[1]), N);
+ GetData(yB, mxGetPr(mx_in[2]), NB);
+ GetData(fyB, mxGetPr(mx_in[3]), NB);
+
+ mexCallMATLAB(3,mx_out,6,mx_in,"cvm_djacB");
+
+ JB_data = mxGetPr(mx_out[0]);
+ for (i=0;i<NB;i++)
+ memcpy(DENSE_COL(JB,i), JB_data + i*NB, NB*sizeof(double));
+
+ ret = (int)*mxGetPr(mx_out[1]);
+
+ if (!mxIsEmpty(mx_out[2])) {
+ UpdateUserData(mx_out[2], bckPb);
+ }
+
+ /* Free temporary space */
+ mxDestroyArray(mx_in[0]);
+ mxDestroyArray(mx_in[1]);
+ mxDestroyArray(mx_in[2]);
+ mxDestroyArray(mx_in[3]);
+ mxDestroyArray(mx_out[0]);
+ mxDestroyArray(mx_out[1]);
+ mxDestroyArray(mx_out[2]);
+
+ return(ret);
+}
+
+
+int mxW_CVodeBandJacB(long int NeqB, 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)
+{
+ cvmPbData fwdPb, bckPb;
+ double *JB_data;
+ mxArray *mx_in[6], *mx_out[3];
+ long int ebandB, i;
+ int ret;
+
+ /* Extract global interface data from user-data */
+ bckPb = (cvmPbData) user_dataB;
+ fwdPb = bckPb->fwd;
+
+ /* Inputs to the Matlab function */
+ mx_in[0] = mxCreateDoubleScalar(t); /* current t */
+ mx_in[1] = mxCreateDoubleMatrix(N,1,mxREAL); /* current y */
+ mx_in[2] = mxCreateDoubleMatrix(NB,1,mxREAL); /* current yB */
+ mx_in[3] = mxCreateDoubleMatrix(NB,1,mxREAL); /* current fyB */
+ mx_in[4] = bckPb->JACfct; /* matlab function handle */
+ mx_in[5] = bckPb->mtlb_data; /* matlab user data */
+
+ /* Call matlab wrapper */
+ GetData(y, mxGetPr(mx_in[1]), N);
+ GetData(yB, mxGetPr(mx_in[2]), NB);
+ GetData(fyB, mxGetPr(mx_in[3]), NB);
+
+ mexCallMATLAB(3,mx_out,6,mx_in,"cvm_bjacB");
+
+ ebandB = mupperB + mlowerB + 1;
+ JB_data = mxGetPr(mx_out[0]);
+ for (i=0;i<NB;i++)
+ memcpy(BAND_COL(JB,i) - mupperB, JB_data + i*ebandB, ebandB*sizeof(double));
+
+ ret = (int)*mxGetPr(mx_out[1]);
+
+ if (!mxIsEmpty(mx_out[2])) {
+ UpdateUserData(mx_out[2], bckPb);
+ }
+
+ /* Free temporary space */
+ mxDestroyArray(mx_in[0]);
+ mxDestroyArray(mx_in[1]);
+ mxDestroyArray(mx_in[2]);
+ mxDestroyArray(mx_in[3]);
+ mxDestroyArray(mx_out[0]);
+ mxDestroyArray(mx_out[1]);
+ mxDestroyArray(mx_out[2]);
+
+ return(ret);
+}
+
+
+int mxW_CVodeSpilsJacB(N_Vector vB, N_Vector JvB, realtype t,
+ N_Vector y, N_Vector yB, N_Vector fyB,
+ void *user_dataB, N_Vector tmpB)
+{
+ cvmPbData fwdPb, bckPb;
+ mxArray *mx_in[7], *mx_out[3];
+ int ret;
+
+ /* Extract global interface data from user-data */
+ bckPb = (cvmPbData) user_dataB;
+ fwdPb = bckPb->fwd;
+
+ /* Inputs to the Matlab function */
+ mx_in[0] = mxCreateDoubleScalar(t); /* current t */
+ mx_in[1] = mxCreateDoubleMatrix(N,1,mxREAL); /* current y */
+ mx_in[2] = mxCreateDoubleMatrix(NB,1,mxREAL); /* current yB */
+ mx_in[3] = mxCreateDoubleMatrix(NB,1,mxREAL); /* current fyB */
+ mx_in[4] = mxCreateDoubleMatrix(NB,1,mxREAL); /* vector vB */
+ mx_in[5] = bckPb->JACfct; /* matlab function handle */
+ mx_in[6] = bckPb->mtlb_data; /* matlab user data */
+
+ /* Call matlab wrapper */
+ GetData(y, mxGetPr(mx_in[1]), N);
+ GetData(yB, mxGetPr(mx_in[2]), NB);
+ GetData(fyB, mxGetPr(mx_in[3]), NB);
+ GetData(vB, mxGetPr(mx_in[4]), NB);
+
+ mexCallMATLAB(3,mx_out,7,mx_in,"cvm_jtvB");
+
+ PutData(JvB, mxGetPr(mx_out[0]), NB);
+ ret = (int)*mxGetPr(mx_out[1]);
+
+ if (!mxIsEmpty(mx_out[2])) {
+ UpdateUserData(mx_out[2], bckPb);
+ }
+
+ /* Free temporary space */
+ mxDestroyArray(mx_in[0]);
+ mxDestroyArray(mx_in[1]);
+ mxDestroyArray(mx_in[2]);
+ mxDestroyArray(mx_in[3]);
+ mxDestroyArray(mx_in[4]);
+ mxDestroyArray(mx_out[0]);
+ mxDestroyArray(mx_out[1]);
+ mxDestroyArray(mx_out[2]);
+
+ return(ret);
+
+}
+
+
+int mxW_CVodeSpilsPsetB(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)
+{
+ cvmPbData fwdPb, bckPb;
+ mxArray *mx_in[8], *mx_out[3];
+ int ret;
+
+ /* Extract global interface data from user-data */
+ bckPb = (cvmPbData) user_dataB;
+ fwdPb = bckPb->fwd;
+
+ /* Inputs to the Matlab function */
+ mx_in[0] = mxCreateDoubleScalar(t); /* current t */
+ mx_in[1] = mxCreateDoubleMatrix(N,1,mxREAL); /* current y */
+ mx_in[2] = mxCreateDoubleMatrix(NB,1,mxREAL); /* current yB */
+ mx_in[3] = mxCreateDoubleMatrix(NB,1,mxREAL); /* current fyB */
+ mx_in[4] = mxCreateLogicalScalar(jokB); /* jokB flag */
+ mx_in[5] = mxCreateDoubleScalar(gammaB); /* gammaB value */
+ mx_in[6] = bckPb->PSETfct; /* matlab function handle */
+ mx_in[7] = bckPb->mtlb_data; /* matlab user data */
+
+ /* Call matlab wrapper */
+ GetData(y, mxGetPr(mx_in[1]), N);
+ GetData(yB, mxGetPr(mx_in[2]), NB);
+ GetData(fyB, mxGetPr(mx_in[3]), NB);
+
+ mexCallMATLAB(3,mx_out,8,mx_in,"cvm_psetB");
+
+ *jcurPtrB = mxIsLogicalScalarTrue(mx_out[0]);
+ ret = (int)*mxGetPr(mx_out[1]);
+
+ if (!mxIsEmpty(mx_out[2])) {
+ UpdateUserData(mx_out[2], bckPb);
+ }
+
+ /* Free temporary space */
+ mxDestroyArray(mx_in[0]);
+ mxDestroyArray(mx_in[1]);
+ mxDestroyArray(mx_in[2]);
+ mxDestroyArray(mx_in[3]);
+ mxDestroyArray(mx_in[4]);
+ mxDestroyArray(mx_in[5]);
+ mxDestroyArray(mx_out[0]);
+ mxDestroyArray(mx_out[1]);
+ mxDestroyArray(mx_out[2]);
+
+ return(ret);
+
+}
+
+
+int mxW_CVodeSpilsPsolB(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)
+{
+ cvmPbData fwdPb, bckPb;
+ mxArray *mx_in[7], *mx_out[3];
+ int ret;
+
+ /* Extract global interface data from user-data */
+ bckPb = (cvmPbData) user_dataB;
+ fwdPb = bckPb->fwd;
+
+ /* Inputs to the Matlab function */
+ mx_in[0] = mxCreateDoubleScalar(t); /* current t */
+ mx_in[1] = mxCreateDoubleMatrix(N,1,mxREAL); /* current y */
+ mx_in[2] = mxCreateDoubleMatrix(NB,1,mxREAL); /* current yB */
+ mx_in[3] = mxCreateDoubleMatrix(NB,1,mxREAL); /* current fyB */
+ mx_in[4] = mxCreateDoubleMatrix(NB,1,mxREAL); /* right hand side rB */
+ mx_in[5] = bckPb->PSOLfct; /* matlab function handle */
+ mx_in[6] = bckPb->mtlb_data; /* matlab user data */
+
+ /* Call matlab wrapper */
+ GetData(y, mxGetPr(mx_in[1]), N);
+ GetData(yB, mxGetPr(mx_in[2]), NB);
+ GetData(fyB, mxGetPr(mx_in[3]), NB);
+ GetData(rB, mxGetPr(mx_in[4]), NB);
+
+ mexCallMATLAB(3,mx_out,7,mx_in,"cvm_psolB");
+
+ PutData(zB, mxGetPr(mx_out[0]), NB);
+ ret = (int)*mxGetPr(mx_out[1]);
+
+ if (!mxIsEmpty(mx_out[2])) {
+ UpdateUserData(mx_out[2], bckPb);
+ }
+
+ /* Free temporary space */
+ mxDestroyArray(mx_in[0]);
+ mxDestroyArray(mx_in[1]);
+ mxDestroyArray(mx_in[2]);
+ mxDestroyArray(mx_in[3]);
+ mxDestroyArray(mx_in[4]);
+ mxDestroyArray(mx_out[0]);
+ mxDestroyArray(mx_out[1]);
+ mxDestroyArray(mx_out[2]);
+
+ return(ret);
+
+}
+
+int mxW_CVodeBBDglocB(long int NlocalB, realtype t, N_Vector y,
+ N_Vector yB, N_Vector gB, void *user_dataB)
+{
+ cvmPbData fwdPb, bckPb;
+ mxArray *mx_in[5], *mx_out[3];
+ int ret;
+
+ /* Extract global interface data from user-data */
+ bckPb = (cvmPbData) user_dataB;
+ fwdPb = bckPb->fwd;
+
+ /* Inputs to the Matlab function */
+ mx_in[0] = mxCreateDoubleScalar(t); /* current t */
+ mx_in[1] = mxCreateDoubleMatrix(N,1,mxREAL); /* current y */
+ mx_in[2] = mxCreateDoubleMatrix(NB,1,mxREAL); /* current yB */
+ mx_in[3] = bckPb->GLOCfct; /* matlab function handle */
+ mx_in[4] = bckPb->mtlb_data; /* matlab user data */
+
+ /* Call matlab wrapper */
+ GetData(y, mxGetPr(mx_in[1]), N);
+ GetData(yB, mxGetPr(mx_in[2]), NB);
+
+ mexCallMATLAB(3,mx_out,5,mx_in,"cvm_glocB");
+
+ PutData(gB, mxGetPr(mx_out[0]), NB);
+
+ ret = (int)*mxGetPr(mx_out[1]);
+
+ if (!mxIsEmpty(mx_out[2])) {
+ UpdateUserData(mx_out[2], bckPb);
+ }
+
+ /* Free temporary space */
+ mxDestroyArray(mx_in[0]);
+ mxDestroyArray(mx_in[1]);
+ mxDestroyArray(mx_in[2]);
+ mxDestroyArray(mx_out[0]);
+ mxDestroyArray(mx_out[1]);
+ mxDestroyArray(mx_out[2]);
+
+ return(ret);
+}
+
+int mxW_CVodeBBDgcomB(long int NlocalB, realtype t, N_Vector y,
+ N_Vector yB, void *user_dataB)
+{
+ cvmPbData fwdPb, bckPb;
+ mxArray *mx_in[5], *mx_out[2];
+ int ret;
+
+ /* Extract global interface data from user-data */
+ bckPb = (cvmPbData) user_dataB;
+ fwdPb = bckPb->fwd;
+
+ /* Inputs to the Matlab function */
+ mx_in[0] = mxCreateDoubleScalar(t); /* current t */
+ mx_in[1] = mxCreateDoubleMatrix(N,1,mxREAL); /* current y */
+ mx_in[2] = mxCreateDoubleMatrix(NB,1,mxREAL); /* current yB */
+ mx_in[3] = bckPb->GCOMfct; /* matlab function handle */
+ mx_in[4] = bckPb->mtlb_data; /* matlab user data */
+
+ /* Call matlab wrapper */
+ GetData(y, mxGetPr(mx_in[1]), N);
+ GetData(yB, mxGetPr(mx_in[2]), NB);
+
+ mexCallMATLAB(2,mx_out,5,mx_in,"cvm_gcomB");
+
+ ret = (int)*mxGetPr(mx_out[0]);
+
+ if (!mxIsEmpty(mx_out[1])) {
+ UpdateUserData(mx_out[1], bckPb);
+ }
+
+ /* Free temporary space */
+ mxDestroyArray(mx_in[0]);
+ mxDestroyArray(mx_in[1]);
+ mxDestroyArray(mx_in[2]);
+ mxDestroyArray(mx_out[0]);
+ mxDestroyArray(mx_out[1]);
+
+ return(ret);
+}
+
+/*
+ * ---------------------------------------------------------------------------------
+ * Wrapper around matlab monitor function
+ * ---------------------------------------------------------------------------------
+ */
+
+void mxW_CVodeMonitor(int call, double t, N_Vector y, N_Vector yQ, N_Vector *yS,
+ cvmPbData fwdPb)
+{
+ mxArray *mx_in[8], *mx_out[1];
+ double *tmp;
+ int is;
+
+ mx_in[0] = mxCreateDoubleScalar(call); /* call type (0:first, 1:interm. 2:last) */
+ mx_in[1] = mxCreateDoubleScalar(t); /* current time */
+ mx_in[2] = mxCreateDoubleMatrix(N,1,mxREAL); /* current solution */
+ if (quadr)
+ mx_in[3] = mxCreateDoubleMatrix(Nq,1,mxREAL); /* current quadratures */
+ else
+ mx_in[3] = mxCreateDoubleMatrix(0,0,mxREAL);
+ mx_in[4] = mxCreateDoubleScalar(Ns); /* number of sensitivities */
+ if (fsa)
+ mx_in[5] = mxCreateDoubleMatrix(N*Ns,1,mxREAL); /* current sensitivities */
+ else
+ mx_in[5] = mxCreateDoubleMatrix(0,0,mxREAL);
+ mx_in[6] = fwdPb->MONfct; /* Matlab monitor function */
+ mx_in[7] = fwdPb->MONdata; /* data for monitor function */
+
+ if (call == 1) {
+
+ GetData(y, mxGetPr(mx_in[2]), N);
+
+ if (quadr)
+ GetData(yQ, mxGetPr(mx_in[3]), Nq);
+
+ if (fsa) {
+ tmp = mxGetPr(mx_in[5]);
+ for (is=0; is<Ns; is++)
+ GetData(yS[is], &tmp[is*N], N);
+ }
+
+ }
+
+ mexCallMATLAB(1,mx_out,8,mx_in,"cvm_monitor");
+
+ if (!mxIsEmpty(mx_out[0])) {
+ UpdateMonitorData(mx_out[0], fwdPb);
+ }
+
+ mxDestroyArray(mx_in[0]);
+ mxDestroyArray(mx_in[1]);
+ mxDestroyArray(mx_in[2]);
+ mxDestroyArray(mx_in[3]);
+ mxDestroyArray(mx_in[4]);
+ mxDestroyArray(mx_in[5]);
+ mxDestroyArray(mx_out[0]);
+}
+
+void mxW_CVodeMonitorB(int call, int idxB, double tB, N_Vector yB, N_Vector yQB,
+ cvmPbData bckPb)
+{
+ mxArray *mx_in[7], *mx_out[1];
+
+ mx_in[0] = mxCreateDoubleScalar(call); /* 0: first, 1: interm. 2: last */
+ mx_in[1] = mxCreateDoubleScalar(idxB); /* index of current problem */
+ mx_in[2] = mxCreateDoubleScalar(tB); /* current time */
+ mx_in[3] = mxCreateDoubleMatrix(NB,1,mxREAL); /* current solution */
+ if (quadrB)
+ mx_in[4] = mxCreateDoubleMatrix(NqB,1,mxREAL); /* current quadratures */
+ else
+ mx_in[4] = mxCreateDoubleMatrix(0,0,mxREAL);
+ mx_in[5] = bckPb->MONfct;
+ mx_in[6] = bckPb->MONdata;
+
+ if (call == 1) {
+
+ GetData(yB, mxGetPr(mx_in[3]), NB);
+
+ if (quadrB)
+ GetData(yQB, mxGetPr(mx_in[4]), NqB);
+ }
+
+ mexCallMATLAB(1,mx_out,7,mx_in,"cvm_monitorB");
+
+ if (!mxIsEmpty(mx_out[0])) {
+ UpdateMonitorData(mx_out[0], bckPb);
+ }
+
+ mxDestroyArray(mx_in[0]);
+ mxDestroyArray(mx_in[1]);
+ mxDestroyArray(mx_in[2]);
+ mxDestroyArray(mx_in[3]);
+ mxDestroyArray(mx_in[4]);
+ mxDestroyArray(mx_out[0]);
+}
+
+
+/*
+ * ---------------------------------------------------------------------------------
+ * Private functions to update the user data structures
+ * ---------------------------------------------------------------------------------
+ */
+
+static void UpdateUserData(mxArray *new_mtlb_data, cvmPbData pb)
+{
+ mexUnlock();
+ mxDestroyArray(pb->mtlb_data);
+ pb->mtlb_data = mxDuplicateArray(new_mtlb_data);
+ mexMakeArrayPersistent(pb->mtlb_data);
+ mexLock();
+}
+
+static void UpdateMonitorData(mxArray *new_mtlb_data, cvmPbData pb)
+{
+ mexUnlock();
+ mxDestroyArray(pb->MONdata);
+ pb->MONdata = mxDuplicateArray(new_mtlb_data);
+ mexMakeArrayPersistent(pb->MONdata);
+ mexLock();
+}
+
diff --git a/sundialsTB/cvodes/examples_par/mcvsAdvDiff_FSA_non_p.m b/sundialsTB/cvodes/examples_par/mcvsAdvDiff_FSA_non_p.m
new file mode 100644
index 0000000..d1fd9f4
--- /dev/null
+++ b/sundialsTB/cvodes/examples_par/mcvsAdvDiff_FSA_non_p.m
@@ -0,0 +1,206 @@
+function [] = mcvsAdvDiff_FSA_non_p(comm)
+%mcvsAdvDiff_FSA_non_p - CVODES forward sensitivity example
+% (parallel, Adams, Functional)
+% Semi-discrete form of the advection-diffusion equation in 1-D:
+% du/dt = q1 * d^2 u / dx^2 + q2 * du/dx
+% on the interval 0 <= x <= 2, and the time interval 0 <= t <= 5.
+% Homogeneous Dirichlet boundary conditions are posed, and the
+% initial condition is:
+% u(x,y,t=0) = x(2-x)exp(2x).
+% 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.
+%
+% Optionally, sensitivities with respect to q1 and q2 are also computed.
+%
+% This program solves the problem with the option for nonstiff
+% systems: ADAMS method and functional iteration.
+% It uses scalar relative and absolute tolerances.
+% Output is printed at t = .5, 1.0, ..., 5.
+%
+% See also: mpirun
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2005, The Regents of the University of California.
+% $Revision: 1.1 $Date: 2007/10/26 16:30:47 $
+
+sensi = true;
+
+xmax = 2.0;
+mx = 10;
+dx = xmax/(mx+1);
+neq = mx;
+
+[status npes] = MPI_Comm_size(comm);
+[status mype] = MPI_Comm_rank(comm);
+
+nperpe = floor(neq/npes);
+nrem = neq - npes*nperpe;
+
+if mype < nrem
+ nlocal = nperpe+1;
+ my_base = mype * nlocal;
+else
+ nlocal = nperpe;
+ my_base = mype * nperpe + nrem;
+end
+
+data.comm = comm;
+data.nlocal = nlocal;
+data.npes = npes;
+data.mype = mype;
+data.dx = dx;
+data.p = [1.0 ; 0.5];
+
+t0 = 0.0;
+for i = 1:nlocal
+ iglobal = my_base + i;
+ x = iglobal * dx;
+ u0(i,1) = x *(xmax-x)*exp(2.0*x);
+end
+
+rtol = 0.0;
+atol = 1.0e-5;
+
+options = CVodeSetOptions('Reltol',rtol,'AbsTol',atol);
+CVodeInit(@rhsfn,'Adams','Functional',t0,u0,options,data);
+
+
+if sensi
+
+ Ns = 2;
+ uS0 = zeros(nlocal,Ns);
+ pbar = data.p;
+ plist = [1;2];
+
+ FSAoptions = CVodeSensSetOptions('method','Simultaneous',...
+ 'ErrControl', 'on',...
+ 'ParamField', 'p',...
+ 'ParamList', plist,...
+ 'ParamScales', pbar);
+
+ CVodeSensInit(Ns, [], uS0, FSAoptions);
+
+end
+
+
+if mype == 0
+ fprintf('============================================================\n');
+ fprintf(' T Q H NST Max norm \n');
+ fprintf('============================================================\n');
+end
+
+nout = 10;
+dtout = 0.5;
+tout = dtout;
+for i = 1:nout
+ if sensi
+ [status,t,u,uS] = CVode(tout,'Normal');
+ PrintOutput(mype, comm, t, u, uS);
+ else
+ [status,t,u] = CVode(tout,'Normal');
+ PrintOutput(mype, comm, t, u, []);
+ end
+ tout = tout + dtout;
+end
+
+CVodeFree;
+
+%%
+%%-------------------------------------------------------------------
+%%
+
+function [ud, flag, new_data] = rhsfn(t, u, data)
+
+% Extract needed problem constants from data
+
+dx = data.dx;
+hordc = data.p(1) / dx^2;
+horac = data.p(2) / (2.0*dx);
+
+% Extract parameters for parallel computation
+
+comm = data.comm;
+npes = data.npes;
+mype = data.mype;
+
+nlocal = length(u);
+
+% Compute related parameters
+
+mype_m1 = mype-1;
+mype_p1 = mype+1;
+last_pe = npes-1;
+
+% Local copy of state
+
+y = [0.0 ; u ; 0.0];
+
+% Pass needed data to processes before and after current one
+
+if mype ~= 0
+ MPI_Send(u(1), mype_m1, 0, comm);
+end
+if mype ~= last_pe
+ MPI_Send(u(nlocal), mype_p1, 0, comm);
+end
+
+% Receive needed data from processes before and after current one
+
+buf = 0.0;
+
+if mype ~= 0
+ MPI_Recv(buf, mype_m1, 0, comm);
+ y(1) = buf;
+else
+ y(1) = 0.0; % zero BC
+end
+
+if mype ~= last_pe
+ MPI_Recv(buf, mype_p1, 0, comm);
+ y(nlocal+2) = buf;
+else
+ y(nlocal+2) = 0.0; % zero BC
+end
+
+for i = 2:nlocal+1
+ ui = y(i);
+ ul = y(i-1);
+ ur = y(i+1);
+
+ hdiff = hordc*(ul - 2.0*ui + ur);
+ hadv = horac * (ur-ul);
+
+ ud(i-1) = hdiff + hadv;
+
+end
+
+flag = 0;
+new_data = [];
+
+
+%%
+%%-------------------------------------------------------------------
+%%
+
+function [] = PrintOutput(mype, comm, t, u, uS)
+
+umax = N_VMaxNorm(u,comm);
+
+if ~isempty(uS)
+ smax1 = N_VMaxNorm(uS(:,1),comm);
+ smax2 = N_VMaxNorm(uS(:,2),comm);
+end
+
+if mype == 0
+ si = CVodeGetStats;
+ fprintf('%8.3e %2d %8.3e %5ld\n', t,si.qlast,si.hlast,si.nst);
+ fprintf(' Solution ');
+ fprintf('%12.4e \n', umax);
+ if ~isempty(uS)
+ fprintf(' Sensitivity 1 ');
+ fprintf('%12.4e \n', smax1);
+ fprintf(' Sensitivity 2 ');
+ fprintf('%12.4e \n', smax2);
+ end
+end
\ No newline at end of file
diff --git a/sundialsTB/cvodes/examples_par/mcvsAtmDisp_kry_bbd_p.m b/sundialsTB/cvodes/examples_par/mcvsAtmDisp_kry_bbd_p.m
new file mode 100644
index 0000000..02e50f8
--- /dev/null
+++ b/sundialsTB/cvodes/examples_par/mcvsAtmDisp_kry_bbd_p.m
@@ -0,0 +1,521 @@
+function [] = mcvsAtmDisp_kry_bbd_p(comm)
+%mcvsAtmDisp_kry_bbd_p - CVODES example problem
+% (parallel, BDF, Newton, GMRES, BBDP)
+% This example solves a 3D advection-diffusion PDE with a
+% distributed source to simulate atmospheric dispersion.
+%
+% This example uses the BBDP preconditioner module in CVODES.
+%
+% See also: mpirun
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2005, The Regents of the University of California.
+% $Revision: 1.1 $Date: 2007/10/26 16:30:47 $
+
+%---------------------------------
+% Domain definition
+% xmin - left boundary
+% xmax - right boundary
+% m - number of intervals
+% np - number of processes
+%---------------------------------
+
+xmin(1) = 0.0; xmax(1) = 20.0; m(1) = 20; np(1) = 2;
+xmin(2) = 0.0; xmax(2) = 20.0; m(2) = 40; np(2) = 2;
+xmin(3) = 0.0; xmax(3) = 20.0; m(3) = 20; np(3) = 1;
+
+%---------------------------------
+% Get MPI id and no. of processes
+%---------------------------------
+
+[status npes] = MPI_Comm_size(comm);
+[status myId] = MPI_Comm_rank(comm);
+
+if npes ~= prod(np)
+ error('Wrong number of processes');
+end
+
+%---------------------------------
+% Set-up problem data
+%---------------------------------
+
+data = SetData(comm, npes, myId, xmin, xmax, m, np);
+
+%--------------------------------
+% Problem dimensions
+%--------------------------------
+
+nlocal = prod(data.ml);
+neq = prod(data.m);
+
+fprintf('\nPVKX example problem\n\n');
+fprintf(' Processor %d/%d\n',myId,npes);
+fprintf(' Global problem size: %d\n',neq);
+fprintf(' Local problem size: %d\n\n',nlocal);
+
+
+%--------------------------------
+% Initial conditions
+%--------------------------------
+
+% Initial time
+t0 = 0.0;
+
+% Initial states (concentrations)
+y0 = zeros(nlocal,1);
+
+% TEST communication pattern
+fprintf('Local data structure\n');
+fprintf(' myId = %d\n',data.myId);
+fprintf(' xmin = %g %g %g\n',data.xmin);
+fprintf(' xmax = %g %g %g\n',data.xmax);
+fprintf(' dx = %g %g %g\n',data.dx);
+fprintf(' start = %3d %3d %3d\n',data.start);
+fprintf(' m = %3d %3d %3d\n',data.m);
+fprintf(' ml = %3d %3d %3d\n',data.ml);
+fprintf(' |yext| = %3d %3d %3d\n\n',size(data.yext));
+
+%--------------------------------
+% CVODES setup
+%--------------------------------
+
+% Tolerances
+options = CVodeSetOptions('RelTol',1.e-8,...
+ 'AbsTol',1.e-6);
+
+% Linear solver
+mldq = data.ml(1)+1;
+mudq = data.ml(1)+1;
+mlkeep = 2;
+mukeep = 2;
+
+options = CVodeSetOptions(options,...
+ 'LinearSolver','GMRES',...
+ 'PrecType','Left',...
+ 'PrecModule','BBDPre',...
+ 'GlocalFn', at pvkx_fl,...
+ 'LowerBwidthDQ',mldq,...
+ 'UpperBwidthDQ',mudq,...
+ 'LowerBwidth',mlkeep,...
+ 'UpperBwidth',mukeep);
+
+% Monitoring
+mondata = struct;
+if myId ==0
+ mondata.mode = 'text';
+else
+ mondata.post = false;
+end
+options = CVodeSetOptions(options,...
+ 'MonitorFn','CVodeMonitor',...
+ 'MonitorData',mondata);
+
+% Memory allocation and initialization
+CVodeInit(@rhsfn,'BDF','Newton',t0,y0,options,data);
+
+%--------------------------------
+% CVODES solution
+%--------------------------------
+
+tf = 0.01;
+
+[status,t,y] = CVode(tf,'Normal');
+
+if myId == 0
+ si = CVodeGetStats
+end
+
+
+CVodeFree;
+
+%
+% ===========================================================
+%
+
+function d = SetData(comm, npes, myId, xmin, xmax, m, np)
+
+%---------------------------------
+% MPI stuff
+%---------------------------------
+
+d.comm = comm;
+d.myId = myId;
+d.np = np;
+
+%---------------------------------
+% Domain boundaries
+%---------------------------------
+
+d.xmin = xmin;
+d.xmax = xmax;
+
+%--------------------------------------
+% Diffusion coefficient
+%--------------------------------------
+
+d.Dc = 1.0;
+
+%--------------------------------------
+% Velocity parameters: Poiseuille flow
+% across y direction, max. velocity=1
+% v(y) = Vc*(L-y)*(L+y)
+%--------------------------------------
+
+d.L = 0.5 * ( xmax(2) - xmin(2) );
+d.Vc = 1.0/d.L^2;
+
+
+%--------------------------------------
+% Grid spacing and differential volume
+% d.m -> number of internal points
+%--------------------------------------
+
+d.dx = (d.xmax - d.xmin) ./ m;
+d.m = m - [1 1 1];
+d.dOmega = prod(d.dx);
+
+%------------------------------------------------
+% Partitioning
+% d.left -> left neighbours
+% d.right -> right neighbours
+% d.start -> left border in global index space
+% d.ml -> length of subdomain
+%-----------------------------------------------
+
+npd = floor(d.m ./ np);
+
+% in x direction
+
+test = mod( myId , np(1) );
+
+d.left(1) = myId-1;
+d.right(1) = myId+1;
+d.start(1) = npd(1) * test + 1;
+d.ml(1) = npd(1);
+
+if test == 0
+ d.left(1) = myId;
+end
+
+if test == np(1)-1
+ d.right(1) = myId;
+ d.ml(1) = d.m(1) - d.start(1) + 1;
+end
+
+% in y direction
+
+test = mod( floor(myId/np(1)) , np(2) );
+
+d.left(2) = myId - np(1);
+d.right(2) = myId + np(1);
+d.start(2) = npd(2) * test + 1;
+d.ml(2) = npd(2);
+
+if test == 0
+ d.left(2) = myId;
+end
+
+if test == np(2)-1
+ d.right(2) = myId;
+ d.ml(2) = d.m(2) - d.start(2) + 1;
+end
+
+% in z direction
+
+test = mod( floor(myId/np(1)/np(2)) , np(3) );
+
+d.left(3) = myId - np(1)*np(2);
+d.right(3) = myId + np(1)*np(2);
+d.start(3) = npd(3) * test + 1;
+d.ml(3) = npd(3);
+
+if test == 0
+ d.left(3) = myId;
+end
+
+if test == np(3)-1
+ d.right(3) = myId;
+ d.ml(3) = d.m(3) - d.start(3) +1;
+end
+
+%--------------------------------------
+% Space for extended local solution
+% 3D matrix
+%--------------------------------------
+
+d.yext = zeros([d.ml(1)+2 d.ml(2)+2 d.ml(3)+2]);
+
+%--------------------------------------
+% Source parameters: Gaussians with
+% - A: amplitude
+% - S: sigma^2
+% - X: position
+%--------------------------------------
+
+d.A1 = 1.0;
+d.S1 = 1.7^2;
+d.X1 = 4.0; d.Y1 = 8.0; d.Z1 = 8.0;
+
+d.A2 = 0.8;
+d.S2 = 3.0^2;
+d.X2 = 16.0; d.Y2 = 12.0; d.Z2 = 12.0;
+
+d.GMIN = 1.0e-5;
+
+A1 = 1.0;
+S1 = 1.7^2;
+X1 = [ 4.0 8.0 8.0];
+
+A2 = 0.8;
+S2 = 3.0^2;
+X2 = [ 16.0 12.0 12.0];
+
+GMIN = 1.0e-5;
+
+
+
+d.s = zeros(d.ml);
+for i = 1:d.ml(1)
+ for j = 1:d.ml(2)
+ for k = 1:d.ml(3)
+ x = d.xmin + (d.start + [i-2 j-2 k-2] ) .* d.dx;
+ s = A1 * prod( exp( -(X1-x).^2 / S1 ) ) + ...
+ A2 * prod( exp( -(X2-x).^2 / S2 ) ) ;
+ if s < GMIN
+ s = 0.0;
+ end
+ d.s(i,j,k) = s;
+ end
+ end
+end
+
+% ===========================================================
+
+function [yd, flag, new_data] = rhsfn(t, y, data)
+
+% Do all inter-process communication
+% After this, data.yext contains all data needed for Finite Differences
+data = rhsfn_comm(y, data);
+
+% Compute right-hand side locally
+[yd, flag, new_data] = rhsfn_local(t, y, data);
+
+new_data = data;
+
+%=================================================================
+
+function [data] = rhsfn_comm(y, data)
+%rhsfn_comm loads the local extended 3D solution matrix, by:
+% a) using the local solution in the interior of the local grid
+% b) communicating with neighbouring processes to obtain solution
+% on the internal boundaries
+% c) setting 0-flux B.C. on the external boundaries.
+
+ml = data.ml;
+comm = data.comm;
+myId = data.myId;
+left = data.left;
+right = data.right;
+
+% Reshape local solution into a cube
+c = reshape(y,ml);
+
+% Load local solution into extended matrix
+data.yext(2:end-1,2:end-1,2:end-1) = c;
+
+% Internal boundaries: loop over each dimension and exchange data.
+% The processor with lower ID always sends first.
+% External boundaries: impose homogeneous Neumann B.C.
+
+for dim = 1:3
+
+ N = prod(ml)/ml(dim); % dimension of communication buffers
+
+% to the left
+
+ nbr = left(dim); % left neighbour
+
+ bufS = reshape( get_slice(c,dim,1), N, 1); % send buffer
+ bufR = zeros(N, 1); % receive buffer
+
+ if nbr == myId % external BC
+ data.yext = set_slice(data.yext,dim,1,bufS);
+ else % internal BC
+ if myId < nbr
+% fprintf(' left send/recv %d N = %d\n',nbr,N);
+ info = MPI_Send(bufS, nbr, 0, comm);
+ if info ~= 0
+ fprintf('Send to left: myId %d nbr %d info %d',myId,nbr,info);
+ MPI_Abort(comm, 0);
+ end
+ [info, stat] = MPI_Recv(bufR, nbr, 0, comm);
+ if info ~= 0
+ fprintf('Receive from left: myId %d nbr %d info %d',myId,nbr,info);
+ MPI_Abort(comm, 0);
+ end
+ else
+% fprintf(' left recv/send %d N = %d\n',nbr,N);
+ [info, stat] = MPI_Recv(bufR, nbr, 0, comm);
+ if info ~= 0
+ fprintf('Receive from left: myId %d nbr %d info %d',myId,nbr,info);
+ MPI_Abort(comm, 0);
+ end
+ info = MPI_Send(bufS, nbr, 0, comm);
+ if info ~= 0
+ fprintf('Send to left: myId %d nbr %d info %d',myId,nbr,info);
+ MPI_Abort(comm, 0);
+ end
+ end
+ data.yext = set_slice(data.yext,dim,1,bufR);
+ end
+
+% to the right
+
+ nbr = right(dim); % right neighbour
+
+ bufS = reshape( get_slice(c,dim,ml(dim)), N, 1); % send buffer
+ bufR = zeros(N, 1); % receive buffer
+
+ if nbr == myId % external BC
+ data.yext = set_slice(data.yext,dim,ml(dim)+2,bufS);
+ else % internal BC
+ if myId < nbr
+% fprintf(' right send/recv %d N = %d\n',nbr,N);
+ info = MPI_Send(bufS, nbr, 0, comm);
+ if info ~= 0
+ fprintf('Send to right: myId %d nbr %d info %d',myId,nbr,info);
+ MPI_Abort(comm, 0);
+ end
+ [info, stat] = MPI_Recv(bufR, nbr, 0, comm);
+ if info ~= 0
+ fprintf('Receive from right: myId %d nbr %d info %d',myId,nbr,info);
+ MPI_Abort(comm, 0);
+ end
+ else
+% fprintf(' right recv/send %d N = %d\n',nbr,N);
+ [info, stat] = MPI_Recv(bufR, nbr, 0, comm);
+ if info ~= 0
+ fprintf('Receive from right: myId %d nbr %d info %d',myId,nbr,info);
+ MPI_Abort(comm, 0);
+ end
+ info = MPI_Send(bufS, nbr, 0, comm);
+ if info ~= 0
+ fprintf('Send to right: myId %d nbr %d info %d',myId,nbr,info);
+ MPI_Abort(comm, 0);
+ end
+ end
+ data.yext = set_slice(data.yext,dim,ml(dim)+2,bufR);
+ end
+
+
+end
+
+function b = get_slice(a, dim, indx)
+%get_slice extracts from the 3D matrix A, the 2D matrix slice B at
+% index INDX in the dimension DIM
+
+switch dim
+ case 1
+ b = a(indx,:,:);
+ case 2
+ b = a(:,indx,:);
+ case 3
+ b = a(:,:,indx);
+end
+
+function a = set_slice(a, dim, indx, b)
+%set_slice loads the 2D matrix B at index INDX in the dimension DIM
+% into the 3D matrix A. A has 2 more components than B in each
+% dimension
+
+[nr, nc] = size(b); % number of rows and columns in B
+
+switch dim
+ case 1
+ nr = size(a,2)-2;
+ nc = size(a,3)-2;
+ a(indx,2:end-1,2:end-1) = reshape(b,nr,nc);
+ case 2
+ nr = size(a,1)-2;
+ nc = size(a,3)-2;
+ a(2:end-1,indx,2:end-1) = reshape(b,nr,nc);
+ case 3
+ nr = size(a,1)-2;
+ nc = size(a,2)-2;
+ a(2:end-1,2:end-1,indx) = reshape(b,nr,nc);
+end
+
+% ===========================================================
+
+function [yd, flag, new_data] = rhsfn_local(t, y, data)
+%rhsfn_local - local RHS computation
+
+xmin = data.xmin;
+ml = data.ml;
+start = data.start;
+dx = data.dx;
+Dc = data.Dc;
+yext = data.yext;
+
+for i = 2:ml(1)+1
+ for j = 2:ml(2)+1
+ for k = 2:ml(3)+1
+
+ x = xmin + (start + [i-2 j-2 k-2] ) .* dx;
+ v = velocity(x, data);
+ s = source(x,data);
+
+ [c, cl, cr] = stencil(yext,i,j,k);
+
+ adv = v .* (cr-cl) ./ (2.0*dx);
+ dif = Dc * (cr - 2.0*c + cl) / dx.^2;
+
+ yd(i-1,j-1,k-1) = s + sum(dif-adv);
+
+ end
+ end
+end
+
+yd = reshape(yd,prod(ml),1);
+
+flag = 0;
+new_data = [];
+
+
+function [c,cl,cr] = stencil(yext,i,j,k)
+
+c = yext(i,j,k) * ones(1,3);
+cl(1) = yext(i-1,j, k ); cr(1) = yext(i+1,j, k );
+cl(2) = yext(i, j-1,k ); cr(2) = yext(i, j+1,k );
+cl(3) = yext(i, j, k-1); cr(3) = yext(i, j, k+1);
+
+
+function v = velocity(x, data)
+
+L = data.L;
+Vc = data.Vc;
+xmin = data.xmin;
+
+y = x(2) - xmin(2) - L;
+
+v(1) = Vc * (L+y) * (L-y);
+v(2) = 0.0;
+v(3) = 0.0;
+
+
+function s = source(x, data)
+
+A1 = data.A1; A2 = data.A2;
+S1 = data.S1; S2 = data.S2;
+X1 = data.X1; X2 = data.X2;
+Y1 = data.Y1; Y2 = data.Y2;
+Z1 = data.Z1; Z2 = data.Z2;
+
+s1 = A1 * exp(-(X1-x(1))^2/S1) * exp(-(Y1-x(2))^2/S1) * exp(-(Z1-x(3))^2/S1);
+s2 = A2 * exp(-(X2-x(1))^2/S2) * exp(-(Y2-x(2))^2/S2) * exp(-(Z2-x(3))^2/S2);
+
+s = s1 + s2;
+
+if s < data.GMIN
+ s = 0.0;
+end
diff --git a/sundialsTB/cvodes/examples_par/mcvsDecoupl_non_p.m b/sundialsTB/cvodes/examples_par/mcvsDecoupl_non_p.m
new file mode 100644
index 0000000..63834be
--- /dev/null
+++ b/sundialsTB/cvodes/examples_par/mcvsDecoupl_non_p.m
@@ -0,0 +1,91 @@
+function [] = mcvsDecoupl_non_p(comm)
+%mcvsDecoupl_non_p - CVODES example problem
+% (parallel, Adams, Functional)
+% This is a simple test for the CVODES solver. It solves a
+% set of decoupled ODEs.
+%
+% See also: mpirun
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2005, The Regents of the University of California.
+% $Revision: 1.1 $Date: 2007/10/26 16:30:47 $
+
+[status npes] = MPI_Comm_size(comm);
+[status mype] = MPI_Comm_rank(comm);
+
+nlocal = 20;
+neq = npes * nlocal;
+
+alpha = 10.0/neq;
+
+data.alpha = alpha;
+data.comm = comm;
+data.nlocal = nlocal;
+data.mype = mype;
+
+t0 = 0.0;
+for i = 1:nlocal
+ y0(i,1) = 1.0;
+end
+
+rtol = 1.0e-5;
+atol = 1.0e-10;
+
+fprintf('\nPVNX example problem\n\n');
+fprintf(' Processor %d/%d\n',mype,npes);
+fprintf(' Global problem size: %d\n',neq);
+fprintf(' Local problem size: %d\n\n',nlocal);
+if mype == 0
+ fprintf(' alpha = %f\n',alpha);
+ fprintf(' rtol = %e atol = %e\n\n',rtol,atol);
+end
+
+options = CVodeSetOptions('Reltol',rtol,'AbsTol',atol);
+
+mondata = struct;
+
+if mype == 0
+ mondata.mode = 'both';
+ mondata.sol = true;
+else
+% mondata.post = false;
+ mondata.sol = true;
+ mondata.cntr = false;
+ mondata.stats = false;
+end
+options = CVodeSetOptions(options,...
+ 'MonitorFn','CVodeMonitor',...
+ 'MonitorData',mondata);
+
+CVodeInit(@rhsfn,'Adams','Functional',t0,y0,options,data);
+
+nout = 10;
+dtout = 0.1;
+tout = dtout;
+for i = 1:nout
+ [status,t,y] = CVode(tout,'Normal');
+ if mype == 0
+ si = CVodeGetStats;
+ fprintf('t = %f nst = %d nfe = %d\n',t,si.nst,si.nfe);
+ end
+ tout = tout + dtout;
+end
+
+CVodeFree;
+
+%
+%---------------------------------------------------------
+%
+
+function [yd, flag, new_data] = rhsfn(t, y, data)
+
+alpha = data.alpha;
+nlocal = data.nlocal;
+mype = data.mype;
+
+for i = 1:nlocal
+ yd(i) = -alpha * (mype*nlocal + i) * y(i);
+end
+
+flag = 0;
+new_data = [];
diff --git a/sundialsTB/cvodes/examples_ser/mcvsAdvDiff_bnd.m b/sundialsTB/cvodes/examples_ser/mcvsAdvDiff_bnd.m
new file mode 100644
index 0000000..923ba72
--- /dev/null
+++ b/sundialsTB/cvodes/examples_ser/mcvsAdvDiff_bnd.m
@@ -0,0 +1,243 @@
+function mcvsAdvDiff_bnd()
+%mcvsAdvDiff_bnd - CVODES example problem (serial, band)
+% The following is a simple example problem with a banded Jacobian,
+% with the program for its solution by 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
+% 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.
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2005, The Regents of the University of California.
+% $Revision: 1.1 $Date: 2007/10/26 16:30:47 $
+
+xmax = 2.0;
+ymax = 1.0;
+mx = 10;
+my = 5;
+
+rtol = 0.0;
+atol = 1.0e-5;
+
+t0 = 0.0;
+dtout = 0.1;
+nout = 6;
+
+dx = xmax/(mx+1);
+dy = ymax/(my+1);
+
+% Problem data structure
+data.xmax = xmax;
+data.ymax = ymax;
+data.mx = mx;
+data.my = my;
+data.dx = dx;
+data.dy = dy;
+data.hdcoef = 1.0/dx^2;
+data.hacoef = 0.5/(2.0*dx);
+data.vdcoef = 1.0/dy^2;
+
+% Options for integration
+options = CVodeSetOptions('UserData',data,...
+ 'RelTol',rtol,...
+ 'AbsTol',atol,...
+ 'LinearSolver','Band',...
+ 'JacobianFn', at bjacfn,...
+ 'UpperBwidth',my,...
+ 'LowerBwidth',my);
+
+mondata.grph = false;
+options = CVodeSetOptions(options,...
+ 'MonitorFn', at CVodeMonitor,...
+ 'MonitorData',mondata);
+
+% Initial conditions for states
+t = t0;
+u = zeros(mx*my,1);
+for j = 1:my
+ y = j * data.dy;
+ for i = 1:mx
+ x = i * data.dx;
+ u(j + (i-1)*my) = x*(xmax-x)*y*(ymax-y)*exp(5.0*x*y);
+ end
+end
+
+% Initialize integrator
+CVodeInit(@rhsfn, 'BDF', 'Newton', t, u, options);
+
+% Initialize quadratures (with default optional inputs)
+q = 0.0;
+CVodeQuadInit(@quadfn, q);
+
+
+ff=figure;
+hold on;
+box
+
+umax = norm(u,'inf');
+uavg = quadfn(t,u,data);
+fprintf('At t = %f max.norm(u) = %e\n',t, umax);
+
+for i = 1:nout
+
+ t_old = t;
+ uavg_old = uavg;
+
+ tout = t + dtout;
+ [status,t,u, q] = CVode(tout, 'Normal');
+
+ if status ~= 0
+ return
+ end
+
+ uavg = quadfn(t,u,data);
+ umax = norm(u,'inf');
+ fprintf('At t = %f max.norm(u) = %e\n',tout, umax);
+
+ figure(ff);
+ plot([t_old t],[uavg_old uavg]);
+ plot([t0 tout], [q q]/(tout-t0), 'r-');
+ plot([tout tout], [0 q]/(tout-t0), 'r-');
+
+end
+
+si= CVodeGetStats
+
+CVodeFree;
+
+return
+
+% ===========================================================================
+
+function [ud, flag, new_data] = rhsfn(t, u, data)
+% Right-hand side function
+
+mx = data.mx;
+my = data.my;
+hordc = data.hdcoef;
+horac = data.hacoef;
+verdc = data.vdcoef;
+
+for j = 1:my
+ for i = 1:mx
+ uij = u(j+(i-1)*my);
+ if j == 1
+ udn = 0.0;
+ else
+ udn = u(j-1+(i-1)*my);
+ end
+ if j == my
+ uup = 0.0;
+ else
+ uup = u(j+1+(i-1)*my);
+ end
+ if i == 1
+ ult = 0.0;
+ else
+ ult = u(j+(i-2)*my);
+ end
+ if i == mx
+ urt = 0.0;
+ else
+ urt = u(j+i*my);
+ end
+
+ hdiff = hordc * (ult - 2*uij + urt);
+ hadv = horac * (urt - ult);
+ vdiff = verdc * (uup - 2*uij + udn);
+ ud(j+(i-1)*my) = hdiff + hadv + vdiff;
+ end
+end
+
+flag = 0;
+new_data = [];
+
+return
+
+% ===========================================================================
+
+function [qd, flag, new_data] = quadfn(t, u, data)
+% Quadrature integrand function
+
+mx = data.mx;
+my = data.my;
+dx = data.dx;
+dy = data.dy;
+xmax = data.xmax;
+ymax = data.ymax;
+
+qd1 = 0.0;
+for j = 1:my
+ for i = 1:mx
+ uij = u(j+(i-1)*my);
+ if j == 1 | j == mx
+ del_y = dy/2;
+ else
+ del_y = dy;
+ end
+ if i == 1 | i == mx
+ del_x = dx/2;
+ else
+ del_x = dx;
+ end
+ qd1 = qd1 + uij * del_x*del_y;
+ end
+end
+
+qd1 = qd1 / (xmax*ymax);
+
+qd(1) = qd1;
+
+flag = 0;
+new_data = [];
+
+return
+
+% ===========================================================================
+
+function [J, flag, new_data] = bjacfn(t, y, fy, data)
+% Band Jacobian function
+
+mx = data.mx;
+my = data.my;
+hordc = data.hdcoef;
+horac = data.hacoef;
+verdc = data.vdcoef;
+
+mu = my;
+ml = my;
+mband = mu + 1 + ml;
+
+for i = 1:mx
+ for j = 1:my
+ k = j + (i-1)*my;
+ J(mu+1,k) = -2.0 * (verdc + hordc);
+ if i ~= 1
+ J(1,k) = hordc + horac;
+ end
+ if i ~= mx
+ J(mband,k) = hordc - horac;
+ end
+ if j ~= 1
+ J(mu,k) = verdc;
+ end
+ if j ~= my
+ J(mu+2,k) = verdc;
+ end
+ end
+end
+
+flag = 0;
+new_data = [];
diff --git a/sundialsTB/cvodes/examples_ser/mcvsDiscRHS_dns.m b/sundialsTB/cvodes/examples_ser/mcvsDiscRHS_dns.m
new file mode 100644
index 0000000..fc7bda9
--- /dev/null
+++ b/sundialsTB/cvodes/examples_ser/mcvsDiscRHS_dns.m
@@ -0,0 +1,150 @@
+function mcvsDiscRHS_dns()
+%mcvsDiscRHS_dns - CVODES example with RHS discontinuity
+% Trivial CVODES example to illustrate the proper
+% way to integrate over a discontinuity in the RHS:
+% y' = -y ; y(0) = 1 ; t = [0,1]
+% z' = -5*z ; z(1) = y(1) ; t = [1,2]
+% The problem is solved twice, first by explicitly treating the
+% discontinuity point and secondly by letting the integrator
+% deal with the discontinuity.
+
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2005, The Regents of the University of California.
+% $Revision: 1.1 $
+
+t0 = 0.0;
+t1 = 1.0;
+t2 = 2.0;
+
+y0 = 1.0;
+
+% ---------------------------------------------------------------
+% Discontinuity in RHS: Case 1 - let CVODES deal with it.
+% ---------------------------------------------------------------
+
+data.tdisc = t1;
+
+% Initialize solver
+options = CVodeSetOptions('UserData',data,...
+ 'RelTol',1.e-3,...
+ 'AbsTol',1.e-4,...
+ 'LinearSolver','Dense');
+CVodeInit(@rhsfn1, 'BDF', 'Newton', t0, y0, options);
+
+% Integrate over the point of discontinuity
+t = t0;
+i = 1;
+tt1(1) = t0; yy1(1) = y0;
+while t < t2
+ [status, t, y] = CVode(t2,'OneStep');
+ i = i+1;
+ tt1(i) = t;
+ yy1(i) = y;
+end
+
+% Free memory
+CVodeFree;
+
+% -------------------------------------------------------------
+% Discontinuity in RHS: Case 1 - explicit treatment
+% Note that, since we set tstop at the point of discontinuity,
+% we could simply use the exact same RHS function as before.
+% However, we chose to use a flag set in the user data (to also
+% illustrate the use of CVodeSet).
+% -------------------------------------------------------------
+
+% Initialize solver (data.flag = 1)
+
+data.flag = 1;
+
+options = CVodeSetOptions('UserData',data,...
+ 'RelTol',1.e-3,...
+ 'AbsTol',1.e-4,...
+ 'StopTime',t1,...
+ 'LinearSolver','Dense');
+CVodeInit(@rhsfn2, 'BDF', 'Newton', t0, y0, options);
+
+% Integrate to the point of discontinuity
+t = t0;
+i = 1;
+tt2(1) = t0; yy2(1) = y0;
+while t < t2
+ [status, t, y] = CVode(t2,'OneStep');
+ i = i+1;
+ tt2(i) = t;
+ yy2(i) = y;
+ if status == 1
+ % Once tstop is reached, flag a change in RHS
+ data.flag = 2;
+ CVodeSet('UserData',data);
+ end
+end
+
+% Free memory
+CVodeFree;
+
+
+% Plot the two solutions
+
+figure
+
+subplot(2,1,1)
+hold on
+plot(tt1,yy1);
+plot(tt2,yy2,'r');
+legend('Integrate over discontinuity','Stop at discontinuity');
+title('Discontinuity in RHS');
+xlabel('time');
+ylabel('y');
+box on
+
+subplot(2,1,2)
+hold on
+plot(tt1,yy1,'b',tt1,yy1,'b.');
+plot(tt2,yy2,'r',tt2,yy2,'r.');
+set(gca,'XLim',[0.99 1.01],'YLim',[0.36 0.37]);
+legend('Integrate over discontinuity','Stop at discontinuity');
+title('Zoom on discontinuity');
+xlabel('time');
+ylabel('y');
+grid on
+box on
+
+return
+
+% ===========================================================================
+
+function [yd, flag, new_data] = rhsfn1(t, y, data)
+% Right-hand side function for case 1
+
+
+if t <= data.tdisc
+ yd(1) = -y(1);
+else
+ yd(1) = -5*y(1);
+end
+
+flag = 0;
+new_data = [];
+
+return
+
+% ===========================================================================
+
+
+function [yd, flag, new_data] = rhsfn2(t, y, data)
+% Right-hand side function for case 2
+
+if data.flag == 1
+ yd(1) = -y(1);
+else
+ yd(1) = -5*y(1);
+end
+
+flag = 0;
+new_data = [];
+
+return
+
+
diff --git a/sundialsTB/cvodes/examples_ser/mcvsDiscSOL_dns.m b/sundialsTB/cvodes/examples_ser/mcvsDiscSOL_dns.m
new file mode 100644
index 0000000..194af5c
--- /dev/null
+++ b/sundialsTB/cvodes/examples_ser/mcvsDiscSOL_dns.m
@@ -0,0 +1,77 @@
+function mcvsDiscSOL_dns()
+%mcvsDiscSOL_dns - CVODES example with solution discontinuity
+% Trivial CVODES example to illustrate the use of
+% CVodeReInit to integrate over a discontinuity in
+% the solution:
+% y' = -y ; y(0) = 1 ; t = [0,1]
+% y' = -y ; y(1) = 1 ; t = [1,2]
+%
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2005, The Regents of the University of California.
+% $Revision: 1.1 $
+
+t0 = 0.0;
+t1 = 1.0;
+t2 = 2.0;
+
+% Initialize solver
+y = 1.0;
+options = CVodeSetOptions('RelTol',1.e-3,...
+ 'AbsTol',1.e-4,...
+ 'StopTime',t1,...
+ 'LinearSolver','Dense');
+CVodeInit(@rhsfn,'BDF','Newton',t0,y,options);
+
+% Integrate to the point of discontinuity
+t = t0;
+i = 1;
+tt(i) = t0; yy(i) = y;
+while t < t1
+ [status, t, y] = CVode(t1,'OneStep');
+ i = i+1;
+ tt(i) = t;
+ yy(i) = y;
+end
+
+% Add discontinuity and reinitialize solver
+y = 1.0;
+options = CVodeSetOptions(options,'StopTime',t2);
+CVodeReInit(t1,y,options);
+
+% Integrate from discontinuity to final time
+t = t1;
+i = i+1;
+tt(i) = t1; yy(i) = y;
+while t < t2
+ [status, t, y] = CVode(t2,'OneStep');
+ i = i+1;
+ tt(i) = t;
+ yy(i) = y;
+end
+
+% Plot solution
+figure
+plot(tt,yy)
+title('Discontinuity in solution');
+xlabel('time');
+ylabel('y');
+
+% Free memory
+CVodeFree;
+
+return
+
+% ===========================================================================
+
+function [yd, flag] = rhsfn(t, y)
+% Right-hand side function
+
+yd(1) = -y(1);
+flag = 0;
+
+return
+
+
+
+
diff --git a/sundialsTB/cvodes/examples_ser/mcvsDiurnal_kry.m b/sundialsTB/cvodes/examples_ser/mcvsDiurnal_kry.m
new file mode 100644
index 0000000..ab28620
--- /dev/null
+++ b/sundialsTB/cvodes/examples_ser/mcvsDiurnal_kry.m
@@ -0,0 +1,388 @@
+function [x,y,u0_2, u_2] = mcvsDiurnal_kry
+%mcvsDiurnal_kry - CVODES example problem (serial, Spgmr)
+% An ODE system is generated from the following 2-species diurnal
+% kinetics advection-diffusion PDE system in 2 space dimensions:
+%
+% dc(i)/dt = Kh*(d/dx)^2 c(i) + V*dc(i)/dx + (d/dy)(Kv(y)*dc(i)/dy)
+% + Ri(c1,c2,t) for i = 1,2, where
+% R1(c1,c2,t) = -q1*c1*c3 - q2*c1*c2 + 2*q3(t)*c3 + q4(t)*c2 ,
+% R2(c1,c2,t) = q1*c1*c3 - q2*c1*c2 - q4(t)*c2 ,
+% Kv(y) = Kv0*exp(y/5) ,
+% Kh, V, Kv0, q1, q2, and c3 are constants, and q3(t) and q4(t)
+% vary diurnally. The problem is posed on the square
+% 0 <= x <= 20, 30 <= y <= 50 (all in km),
+% with homogeneous Neumann boundary conditions, and for time t in
+% 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
+% method (i.e. using the CVSPGMR 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.
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2005, The Regents of the University of California.
+% $Revision: 1.1 $Date: 2007/10/26 16:30:47 $
+
+%------------------------
+% SET USER DATA STRUCTURE
+%------------------------
+
+ns = 2;
+
+mx = 50;
+my = 20;
+
+xmin = 0.0; xmax = 20.0; xmid = 10.0;
+ymin = 30.0; ymax = 50.0; ymid = 40.0;
+dx = (xmax-xmin)/(mx-1);
+dy = (ymax-ymin)/(my-1);
+
+kh = 4.0e-6;
+vel = 0.001;
+kv0 = 1.0e-8;
+halfday = 4.32e4;
+
+c1s = 1.0e6;
+c2s = 1.0e12;
+
+
+data.ns = ns;
+
+%% Problem constants
+
+data.mx = mx;
+data.xmin = xmin;
+data.xmax = xmax;
+data.xmid = xmid;
+data.dx = dx;
+
+data.my = my;
+data.ymin = ymin;
+data.ymax = ymax;
+data.ymid = ymid;
+data.dy = dy;
+
+data.q1 = 1.63e-16;
+data.q2 = 4.66e-16;
+data.c3 = 3.7e16;
+data.a3 = 22.62;
+data.a4 = 7.601;
+
+data.om = pi/halfday;
+data.hdco = kh/dx^2;
+data.haco = vel/(2*dx);
+data.vdco = kv0/dy^2;
+
+%% Workspace
+
+data.P = [];
+
+%------------------------
+% SET INITIAL PROFILE
+%------------------------
+
+t0 = 0.0;
+
+for jy = 1:my
+ y(jy) = ymin + (jy - 1) * dy;
+end
+for jx = 1:mx
+ x(jx) = xmin + (jx - 1) * dx;
+end
+
+for jy = 1:my
+ cy = (0.1 * (y(jy) - ymid))^2;
+ cy = 1.0 - cy + 0.5 * cy^2;
+ for jx = 1:mx
+ cx = (0.1 * (x(jx) - xmid))^2;
+ cx = 1.0 - cx + 0.5 * cx^2;
+ u0(1,jx,jy) = c1s * cx * cy;
+ u0(2,jx,jy) = c2s * cx * cy;
+ end
+end
+
+u0_2 = squeeze(u0(2,:,:));
+
+u0 = reshape(u0,2*mx*my,1);
+
+
+%------------------------
+% SET CVODES OPTIONS
+%------------------------
+
+% Tolerances
+rtol = 1.0e-5;
+atol = 1.0e-3;
+
+options = CVodeSetOptions('UserData',data,...
+ 'RelTol',rtol, 'AbsTol',atol,...
+ 'LinearSolver','GMRES',...
+ 'PrecType','Left',...
+ 'PrecSetupFn', at psetfn,...
+ 'PrecSolveFn', at psolfn);
+
+%mondata = struct;
+%options = CVodeSetOptions(options,'MonitorFn', at CVodeMonitor,'MonitorData',mondata);
+
+CVodeInit(@rhsfn, 'BDF', 'Newton', t0, u0, options);
+
+%------------------------
+% SOLVE PROBLEM
+%------------------------
+
+twohr = 7200.0;
+tout = twohr;
+nout = 12;
+
+for i = 1:nout
+ [status,t,u] = CVode(tout,'Normal');
+ si = CVodeGetStats;
+ u = reshape(u,2,mx,my);
+ fprintf('status = %d t = %.2e nst = %d q = %d h = %.2e\n',...
+ status, t, si.nst, si.qlast, si.hlast);
+ fprintf('c1 (bot.left/middle/top rt.) = %12.3e %12.3e %12.3e\n',...
+ u(1,1,1), u(1,5,5), u(1,10,10));
+ fprintf('c2 (bot.left/middle/top rt.) = %12.3e %12.3e %12.3e\n',...
+ u(2,1,1), u(2,5,5), u(2,10,10));
+ tout = tout + twohr;
+end
+
+u_2 = squeeze(u(2,:,:));
+
+si = CVodeGetStats
+
+%------------------------
+% FREE MEMORY
+%------------------------
+
+CVodeFree;
+
+%------------------------
+% PLOT RESULTS
+%------------------------
+
+figure;
+
+hsurf0 = surf(y,x,u0_2);
+
+set(hsurf0,'Edgecolor','flat','EdgeAlpha',0.6);
+set(hsurf0,'FaceAlpha',0);
+
+hold on
+
+hsurf = surf(y,x,u_2);
+set(hsurf,'FaceColor','interp', 'EdgeColor','none');
+
+title('Initial and final values for species 2');
+xlabel('y');
+ylabel('x');
+colorbar
+box on
+
+return
+
+% ===========================================================================
+
+function [ud, flag, new_data] = rhsfn(t, u, data)
+% Right-hand side function
+
+mx = data.mx;
+xmin = data.xmin;
+dx = data.dx;
+
+my = data.my;
+ymin = data.ymin;
+dy = data.dy;
+
+om = data.om;
+q1 = data.q1;
+q2 = data.q2;
+c3 = data.c3;
+a3 = data.a3;
+a4 = data.a4;
+hdco = data.hdco;
+haco = data.haco;
+vdco = data.vdco;
+
+s = sin(om*t);
+if s > 0.0
+ q3 = exp(-a3/s);
+ q4 = exp(-a4/s);
+else
+ q3 = 0.0;
+ q4 = 0.0;
+end
+
+u = reshape(u, 2,mx*my);
+
+for jy = 1:my
+ ydn = ymin + (jy - 1.5)*dy;
+ yup = ydn + dy;
+ cydn = vdco * exp(0.2*ydn);
+ cyup = vdco * exp(0.2*yup);
+ i = (jy-1)*mx;
+ idn = -mx;
+ if jy == 1
+ idn = mx;
+ end
+ iup = mx;
+ if jy == my
+ iup = -mx;
+ end
+ for jx = 1:mx
+ ii = i + jx;
+ c1 = u(1,ii);
+ c2 = u(2,ii);
+ % kinetic rate terms
+ qq1 = q1 * c1 * c3;
+ qq2 = q2 * c1 * c2;
+ qq3 = q3 * c3;
+ qq4 = q4 *c2;
+ rkin1 = -qq1 - qq2 + 2.0*qq3 + qq4;
+ rkin2 = qq1 - qq2 - qq4;
+ % vertical diffusion
+ c1dn = u(1,ii+idn);
+ c2dn = u(2,ii+idn);
+ c1up = u(1,ii+iup);
+ c2up = u(2,ii+iup);
+ vertd1 = cyup*(c1up - c1) - cydn*(c1 - c1dn);
+ vertd2 = cyup*(c2up - c2) - cydn*(c2 - c2dn);
+ % horizontal diffusion and advection
+ ileft = -1;
+ if jx == 1
+ ileft = 1;
+ end
+ iright = 1;
+ if jx == mx
+ iright = -1;
+ end
+ c1lt = u(1,ii+ileft);
+ c2lt = u(2,ii+ileft);
+ c1rt = u(1,ii+iright);
+ c2rt = u(2,ii+iright);
+ hord1 = hdco * (c1rt-2.0*c1+c1lt);
+ hord2 = hdco * (c2rt-2.0*c2+c2lt);
+ horad1 = haco * (c1rt-c1lt);
+ horad2 = haco * (c2rt-c2lt);
+ % load into ud
+ ud(1,ii) = vertd1 + hord1 + horad1 + rkin1;
+ ud(2,ii) = vertd2 + hord2 + horad2 + rkin2;
+ end
+
+end
+
+ud = reshape(ud,2*mx*my,1);
+
+flag = 0;
+new_data = [];
+
+new_data = data;
+
+return
+
+% ===========================================================================
+
+function [jcur, flag, data] = psetfn(t,u,fu,jok,gm,data)
+% Preconditioner setup function
+
+persistent Jbd
+
+mx = data.mx;
+my = data.my;
+
+if jok
+
+ % Copy Jbd to P
+
+ P = Jbd;
+ jcur = false;
+
+else
+
+ % Generate Jbd from scratch and copy to P
+
+ xmin = data.xmin;
+ dx = data.dx;
+
+ ymin = data.ymin;
+ dy = data.dy;
+
+ om = data.om;
+ q1 = data.q1;
+ q2 = data.q2;
+ c3 = data.c3;
+ a3 = data.a3;
+ a4 = data.a4;
+ hdco = data.hdco;
+ haco = data.haco;
+ vdco = data.vdco;
+
+ s = sin(om*t);
+ if s > 0.0
+ q4 = exp(-a4/s);
+ else
+ q4 = 0.0;
+ end
+
+ u = reshape(u,2,mx*my);
+
+ for jy = 1:my
+ ydn = ymin + (jy - 1.5)*dy;
+ yup = ydn + dy;
+ cydn = vdco * exp(0.2*ydn);
+ cyup = vdco * exp(0.2*yup);
+ diag = -(cydn + cyup + 2.0*hdco);
+ i = (jy-1)*mx;
+ for jx = 1:mx
+ ii = i + jx;
+ c1 = u(1,ii);
+ c2 = u(2,ii);
+ Jbd(1,1,ii) = (-q1*c3 - q2*c2) + diag;
+ Jbd(1,2,ii) = -q2*c1 + q4;
+ Jbd(2,1,ii) = q1*c3 - q2*c2;
+ Jbd(2,2,ii) = (-q2*c1 - q4) + diag;
+ end
+ end
+
+ P = Jbd;
+ jcur = true;
+
+end
+
+% Scale by -gamma and add identity
+P = - gm*P;
+for i = 1:mx*my
+ P(:,:,i) = eye(2) + P(:,:,i);
+end
+
+flag = 0;
+data.P = P;
+
+
+return
+
+% ===========================================================================
+
+function [z, flag, new_data] = psolfn(t,y,fy,r,data)
+% Preconditioner solve function
+
+P = data.P;
+
+mx = data.mx;
+my = data.my;
+
+r = reshape(r,2,mx*my);
+
+for i = 1:mx*my
+ z(:,i) = P(:,:,i)^(-1)*r(:,i);
+end
+
+z = reshape(z,2*mx*my,1);
+
+flag = 0;
+new_data = [];
+
+return
\ No newline at end of file
diff --git a/sundialsTB/cvodes/examples_ser/mcvsHessian_FSA_ASA.m b/sundialsTB/cvodes/examples_ser/mcvsHessian_FSA_ASA.m
new file mode 100644
index 0000000..a693d6b
--- /dev/null
+++ b/sundialsTB/cvodes/examples_ser/mcvsHessian_FSA_ASA.m
@@ -0,0 +1,349 @@
+function mcvsHessian_FSA_ASA
+%mcvsHessian_FSA_ASA - CVODES Hessian calculation example (FSA over ASA)
+% The following is a simple example illustrating the use
+% of simultaneous FSA and ASA computations in order to
+% evaluate the Hessian of a functional depending on the
+% ODE solution.
+%
+% The forward problem consists of the following 3 equations
+%
+% dy1/dt = - p1 * y1^2 - y3;
+% dy2/dt = - y2;
+% dy3/dt = - p2^2 * y2 * y3;
+%
+% depending on the parameters p1 = 1.0 and p2 = 2.0.
+%
+% The initial conditions are y1(0) = y2(0) = y390) = 1.0
+%
+% The functional considered is
+%
+% 2
+% /
+% G(p) = | 0.5 * ( y1^2 + y2^2 + y3^2 ) dt
+% /
+% 0
+%
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2005, The Regents of the University of California.
+% $Revision: 1.1 $Date: 2007/10/26 16:30:47 $
+
+
+
+Neq = 3;
+Np = 2;
+
+t0 = 0.0;
+tf = 2.0;
+
+% ----------------------------------------
+% User data structure
+% ----------------------------------------
+
+data.p = [1.0 2.0];
+
+% ----------------------------------------
+% Forward CVODES options
+% ----------------------------------------
+
+options = CVodeSetOptions('UserData',data,...
+ 'RelTol',1.e-8,...
+ 'AbsTol',1.0e-8,...
+ 'LinearSolver','Dense');
+
+optionsQ = CVodeQuadSetOptions('ErrControl',true,...
+ 'RelTol',1.e-8,'AbsTol',1.e-8);
+
+optionsS = CVodeSensSetOptions('method','Simultaneous',...
+ 'ErrControl', true,...
+ 'ParamScales', [1.0; 2.0]);
+
+y0 = ones(Neq,1);
+CVodeInit(@rhsfn, 'BDF', 'Newton', t0, y0, options);
+
+q0 = 0.0;
+CVodeQuadInit(@rhsQfn, q0, optionsQ);
+
+s0 = zeros(Neq,Np);
+CVodeSensInit(Np, @rhsSfn, s0, optionsS);
+
+% ----------------------------------------
+% Initialize ASA
+% ----------------------------------------
+
+CVodeAdjInit(100, 'Polynomial');
+
+% ----------------------------------------
+% Forward integration
+% ----------------------------------------
+
+fprintf('\nForward integration ');
+
+[status, tret, y, q, yS] = CVode(tf,'Normal');
+s = CVodeGetStats;
+
+fprintf('(%d steps)\n', s.nst);
+fprintf('G = %12.4e\n', q);
+
+% ----------------------------------------
+% Backward CVODES options
+% ----------------------------------------
+
+optionsB = CVodeSetOptions('UserData',data,...
+ 'RelTol',1.e-8,...
+ 'AbsTol',1.e-8,...
+ 'LinearSolver','Dense',...
+ 'SensDependent', true);
+
+optionsQB = CVodeQuadSetOptions('ErrControl',true,...
+ 'RelTol',1.e-8,'AbsTol',1.e-8,...
+ 'SensDependent', true);
+
+
+yB1 = zeros(2*Neq,1);
+idxB1 = CVodeInitB(@rhsB1fn, 'BDF', 'Newton', tf, yB1, optionsB);
+
+qB1 = zeros(2*Np,1);
+CVodeQuadInitB(idxB1, @rhsQB1fn, qB1, optionsQB);
+
+
+yB2 = zeros(2*Neq,1);
+idxB2 = CVodeInitB(@rhsB2fn, 'BDF', 'Newton', tf, yB2, optionsB);
+
+qB2 = zeros(2*Np,1);
+CVodeQuadInitB(idxB2, @rhsQB2fn, qB2, optionsQB);
+
+% ----------------------------------------
+% Backward integration
+% ----------------------------------------
+
+fprintf('\nBackward integration ');
+
+[status, tretB, yB, qB] = CVodeB(t0,'Normal');
+sB1 = CVodeGetStatsB(idxB1);
+sB2 = CVodeGetStatsB(idxB2);
+
+fprintf('(%d steps pb1) (%d steps pb2)\n',sB1.nst, sB2.nst);
+
+qB1 = -qB{idxB1};
+qB2 = -qB{idxB2};
+
+fprintf('Gradient\n');
+fprintf(' %12.4e %12.4e (from backward pb. 1)\n',qB1(1:2));
+fprintf(' %12.4e %12.4e (from backward pb. 2)\n',qB2(1:2));
+
+fprintf('Hessian\n');
+fprintf(' %12.4e %12.4e\n',qB1(3), qB2(3));
+fprintf(' %12.4e %12.4e\n',qB1(4), qB2(4));
+
+% ----------------------------------------
+% Free memory
+% ----------------------------------------
+
+CVodeFree;
+
+% ===========================================================================
+
+function [yd, flag, new_data] = rhsfn(t, y, data)
+% Right-hand side function
+
+p1 = data.p(1);
+p2 = data.p(2);
+
+yd(1) = - p1 * y(1)^2 - y(3);
+yd(2) = - y(2);
+yd(3) = - p2^2 * y(2) * y(3);
+
+flag = 0;
+new_data = [];
+
+return
+
+% ===========================================================================
+
+function [qd, flag, new_data] = rhsQfn(t, y, data)
+% Forward quadrature integrand function
+
+qd = 0.5 * ( y(1)^2 + y(2)^2 + y(3)^2 );
+
+flag = 0;
+new_data = [];
+
+return
+
+% ===========================================================================
+
+function [ySd, flag, new_data] = rhsSfn(t,y,yd,yS,data)
+% Sensitivity right-hand side function
+
+p1 = data.p(1);
+p2 = data.p(2);
+
+s = yS(:,1);
+
+fys1 = - 2.0*p1*y(1) * s(1) - s(3);
+fys2 = - s(2);
+fys3 = - p2*p2*y(3) * s(2) - p2*p2*y(2) * s(3);
+
+ySd(1,1) = fys1 - y(1)*y(1);
+ySd(2,1) = fys2;
+ySd(3,1) = fys3;
+
+s = yS(:,2);
+
+fys1 = - 2.0*p1*y(1) * s(1) - s(3);
+fys2 = - s(2);
+fys3 = - p2*p2*y(3) * s(2) - p2*p2*y(2) * s(3);
+
+ySd(1,2) = fys1;
+ySd(2,2) = fys2;
+ySd(3,2) = fys3 - 2.0*p2*y(2)*y(3);
+
+flag = 0;
+new_data = [];
+
+return
+
+% ===========================================================================
+
+function [yBd, flag, new_data] = rhsB1fn(t, y, yS, yB, data)
+% Backward problem right-hand side function for 1st Hessian column
+
+p1 = data.p(1);
+p2 = data.p(2);
+
+y1 = y(1);
+y2 = y(2);
+y3 = y(3);
+
+s1 = yS(1,1);
+s2 = yS(2,1);
+s3 = yS(3,1);
+
+l1 = yB(1);
+l2 = yB(2);
+l3 = yB(3);
+
+m1 = yB(4);
+m2 = yB(5);
+m3 = yB(6);
+
+yBd(1) = 2.0*p1*y1 * l1 - y1;
+yBd(2) = l2 + p2*p2*y3 * l3 - y2;
+yBd(3) = l1 + p2*p2*y2 * l3 - y3;
+
+yBd(4) = 2.0*p1*y1 * m1 + l1 * 2.0*(y1 + p1*s1) - s1;
+yBd(5) = m2 + p2*p2*y3 * m3 + l3 * p2*p2*s3 - s2;
+yBd(6) = m1 + p2*p2*y2 * m3 + l3 * p2*p2*s2 - s3;
+
+flag = 0;
+new_data = [];
+
+return
+
+% ===========================================================================
+
+function [yBd, flag, new_data] = rhsB2fn(t, y, yS, yB, data)
+% Backward problem right-hand side function 2nd Hessian column
+
+p1 = data.p(1);
+p2 = data.p(2);
+
+y1 = y(1);
+y2 = y(2);
+y3 = y(3);
+
+s1 = yS(1,2);
+s2 = yS(2,2);
+s3 = yS(3,2);
+
+l1 = yB(1);
+l2 = yB(2);
+l3 = yB(3);
+
+m1 = yB(4);
+m2 = yB(5);
+m3 = yB(6);
+
+yBd(1) = 2.0*p1*y1 * l1 - y1;
+yBd(2) = l2 + p2*p2*y3 * l3 - y2;
+yBd(3) = l1 + p2*p2*y2 * l3 - y3;
+
+yBd(4) = 2.0*p1*y1 * m1 + l1 * 2.0*p1*s1 - s1;
+yBd(5) = m2 + p2*p2*y3 * m3 + l3 * (2.0*p2*y3 + p2*p2*s3) - s2;
+yBd(6) = m1 + p2*p2*y2 * m3 + l3 * (2.0*p2*y3 + p2*p2*s2) - s3;
+
+flag = 0;
+new_data = [];
+
+return
+
+% ===========================================================================
+
+function [qBd, flag, new_data] = rhsQB1fn(t, y, yS, yB, data)
+% Backward problem quadrature integrand function for 1st Hessian column
+
+p1 = data.p(1);
+p2 = data.p(2);
+
+y1 = y(1);
+y2 = y(2);
+y3 = y(3);
+
+s1 = yS(1,1);
+s2 = yS(2,1);
+s3 = yS(3,1);
+
+l1 = yB(1);
+l2 = yB(2);
+l3 = yB(3);
+
+m1 = yB(4);
+m2 = yB(5);
+m3 = yB(6);
+
+qBd(1) = -y1*y1 * l1;
+qBd(2) = -2.0*p2*y2*y3 * l3;
+
+qBd(3) = -y1*y1 * m1 - l1 * 2.0*y1*s1;
+qBd(4) = -2.0*p2*y2*y3 * m3 - l3 * 2.0*(p2*y3*s2 + p2*y2*s3);
+
+flag = 0;
+new_data = [];
+
+return
+
+% ===========================================================================
+
+function [qBd, flag, new_data] = rhsQB2fn(t, y, yS, yB, data)
+% Backward problem quadrature integrand function for 2nd Hessian column
+
+p1 = data.p(1);
+p2 = data.p(2);
+
+y1 = y(1);
+y2 = y(2);
+y3 = y(3);
+
+s1 = yS(1,2);
+s2 = yS(2,2);
+s3 = yS(3,2);
+
+l1 = yB(1);
+l2 = yB(2);
+l3 = yB(3);
+
+m1 = yB(4);
+m2 = yB(5);
+m3 = yB(6);
+
+qBd(1) = -y1*y1 * l1;
+qBd(2) = -2.0*p2*y2*y3 * l3;
+
+qBd(3) = -y1*y1 * m1 - l1 * 2.0*y1*s1;
+qBd(4) = -2.0*p2*y2*y3 * m3 - l3 * 2.0*(p2*y3*s2 + p2*y2*s3 + y2*y3);
+
+flag = 0;
+new_data = [];
+
+return
\ No newline at end of file
diff --git a/sundialsTB/cvodes/examples_ser/mcvsOzone_FSA_dns.m b/sundialsTB/cvodes/examples_ser/mcvsOzone_FSA_dns.m
new file mode 100644
index 0000000..f9fd544
--- /dev/null
+++ b/sundialsTB/cvodes/examples_ser/mcvsOzone_FSA_dns.m
@@ -0,0 +1,143 @@
+function mcvsOzone_FSA_dns()
+%mcvsOzone_FSA_dns - CVODES example problem (serial, dense)
+% ozone depletion chemical mechanism (3 species)
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2007, The Regents of the University of California.
+% $Revision: 1.2 $Date: 2007/12/05 21:58:18 $
+
+
+% -------------------
+% User data structure
+% -------------------
+
+data.p = [1.63e-16 ; 4.66e-16 ; 5.00e-11 ; 2.50e-4];
+
+% ---------------------
+% CVODES initialization
+% ---------------------
+
+options = CVodeSetOptions('UserData',data,...
+ 'RelTol',1.e-4,...
+ 'AbsTol',1.e-8,...
+ 'LinearSolver','Dense');
+
+t0 = 0.0;
+y0 = [1.0e6 ; 1.0e12 ; 3.7e16];
+
+
+
+CVodeInit(@rhsfn, 'BDF', 'Newton', t0, y0, options);
+
+
+% ------------------
+% FSA initialization
+% ------------------
+
+Ns = 4;
+yS0 = zeros(3,Ns);
+
+FSAoptions = CVodeSensSetOptions('method','Simultaneous',...
+ 'ErrControl', true,...
+ 'ParamField', 'p',...
+ 'ParamScales', data.p);
+CVodeSensInit(Ns, [], yS0, FSAoptions);
+
+% ----------------
+% Problem solution
+% ----------------
+
+time(1,1) = t0;
+sol(1,:) = y0';
+
+t = t0;
+tf = 0.25;
+it = 1;
+while t<tf
+ it = it+1;
+ [status, t, y, yS] = CVode(tf,'OneStep');
+ time(it,1) = t;
+ sol(it,:) = y';
+end
+
+si = CVodeGetStats
+
+% -------------
+% Plot solution
+% -------------
+
+figure
+hold on
+plot(time, sol(:,1),'r');
+plot(time, sol(:,2),'g');
+plot(time, sol(:,3),'b');
+set(gca,'YScale','log');
+set(gca,'XLim',[t0 tf]);
+xlabel('time')
+
+grid on
+box on
+
+% -----------
+% Free memory
+% -----------
+CVodeFree;
+
+return
+
+% ===========================================================================
+
+function [yd, flag, new_data] = rhsfn(t, y, data)
+% Right-hand side function
+
+p = data.p;
+
+yd(1) = -p(1)*y(1)*y(2) - p(2)*y(1)*y(3) + 2*p(3)*y(2) + p(4)*y(3);
+yd(2) = -p(1)*y(1)*y(2) + 2*p(2)*y(1)*y(3) + p(4)*y(3);
+yd(3) = p(1)*y(1)*y(2) - p(2)*y(1)*y(3) - p(4)*y(3);
+
+flag = 0;
+new_data = [];
+
+return
+
+% ===========================================================================
+
+function [ySd, flag, new_data] = rhsSfn(t,y,yd,yS,data)
+% Sensitivity right-hand side function
+
+r1 = data.p(1);
+r2 = data.p(2);
+r3 = data.p(3);
+
+% r1
+
+yS1 = yS(:,1);
+yS1d = zeros(3,1);
+
+yS1d(1) = -r1*yS1(1) + r2*y(3)*yS1(2) + r2*y(2)*yS1(3);
+yS1d(3) = 2*r3*y(2)*yS1(2);
+yS1d(2) = -yS1d(1)-yS1d(3);
+
+yS1d(1) = yS1d(1) - y(1);
+yS1d(2) = yS1d(2) + y(1);
+
+% r2
+
+yS2 = yS(:,2);
+yS2d = zeros(3,1);
+
+yS2d(1) = -r1*yS2(1) + r2*y(3)*yS2(2) + r2*y(2)*yS2(3);
+yS2d(3) = 2*r3*y(2)*yS2(2);
+yS2d(2) = -yS2d(1)-yS2d(3);
+
+yS2d(1) = yS2d(1) + y(2)*y(3);
+yS2d(2) = yS2d(2) - y(2)*y(3);
+
+% Return values
+
+ySd = [yS1d yS2d];
+flag = 0;
+new_data = [];
+
+return
diff --git a/sundialsTB/cvodes/examples_ser/mcvsPleiades_non.m b/sundialsTB/cvodes/examples_ser/mcvsPleiades_non.m
new file mode 100644
index 0000000..ba138d7
--- /dev/null
+++ b/sundialsTB/cvodes/examples_ser/mcvsPleiades_non.m
@@ -0,0 +1,149 @@
+function mcvsPleiades_non()
+%mcvsPleiades_non - CVODES example problem (serial, nonstiff)
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2005, The Regents of the University of California.
+% $Revision: 1.1 $Date: 2007/10/26 16:30:48 $
+
+neq = 28;
+
+t0 = 0.0;
+tout = 3.0;
+
+y0 = zeros(neq,1);
+y0(1) = 3.0;
+y0(2) = 3.0;
+y0(3) = -1.0;
+y0(4) = -3.0;
+y0(5) = 2.0;
+y0(6) = -2.0;
+y0(7) = 2.0;
+y0(8) = 3.0;
+y0(9) = -3.0;
+y0(10) = 2.0;
+y0(13) = -4.0;
+y0(14) = 4.0;
+y0(20) = 1.75;
+y0(21) = -1.5;
+y0(25) = -1.25;
+y0(26) = 1.0;
+
+options = CVodeSetOptions('RelTol', 1.0e-7,...
+ 'AbsTol', 1.0e-7,...
+ 'StopTime',tout,...
+ 'MaxNumSteps',2000);
+
+CVodeInit(@rhsfn, 'Adams', 'Functional', t0, y0, options);
+
+% Loop in one-step mode
+t = t0;
+i = 0;
+while t < tout
+ i = i+1;
+ [status,t,y] = CVode(tout,'OneStep');
+ time(i) = t;
+ xx(:,i) = y(1:7);
+ yy(:,i) = y(8:14);
+end
+
+% Display solver statistics
+Stats = CVodeGetStats
+
+% Free solver memory
+CVodeFree;
+
+% Plot body trajectories
+colors = ['k','b','r','g','c','y','m'];
+figure;
+for i = 1:7
+ plot(xx(i,:),yy(i,:),colors(i));
+ hold on;
+end
+legend('Body 1','Body 2','Body 3','Body 4','Body 5','Body 6','Body 7');
+title('Body Trajectories');
+xlabel('x');
+ylabel('y');
+grid on;
+axis square;
+
+% ===========================================================================
+
+function [yd, flag, new_data] = rhsfn(t, y, data)
+% Right-hand side function
+
+for i = 1:7
+ sumx = 0.0;
+ sumy = 0.0;
+ for j = 1:7
+ mj = j;
+ rij = (y(i)-y(j))^2 + (y(i+7)-y(j+7))^2;
+ rij32 = rij^(3/2);
+ if j ~= i
+ sumx = sumx + mj*(y(j)-y(i))/rij32;
+ sumy = sumy + mj*(y(j+7)-y(i+7))/rij32;
+ end
+ end
+ yd(i+14) = sumx;
+ yd(i+21) = sumy;
+end
+for i = 1:14
+ yd(i) = y(i+14);
+end
+
+flag = 0;
+new_data = [];
+
+return
+
+% ===========================================================================
+
+function [J, flag, new_data] = djacfn(t, y, fy, data)
+% Dense Jacobian function
+
+neq = 28;
+
+J = zeros(neq,neq);
+for i = 1:14
+ J(i,14+i)=1.0;
+end
+for i = 2:7
+ mi=i;
+ for j = 1:i-1
+ mj = j;
+ rij = (y(i)-y(j))^2+(y(i+7)-y(j+7))^2;
+ rij32 = rij^(3/2);
+ rij52 = rij^(5/2);
+ fjh = (1.0-3.0*(y(j)-y(i))^2/rij)/rij32;
+ J(i+14,j) = mj*fjh;
+ J(j+14,i) = mi*fjh;
+ fjh = (1.0-3.0*(y(j+7)-y(i+7))^2/rij)/rij32;
+ J(i+21,j+7) = mj*fjh;
+ J(j+21,i+7) = mi*fjh;
+ fjh = -3.0*(y(j)-y(i))*(y(j+7)-y(i+7))/rij52;
+ J(i+14,j+7) = mj*fjh;
+ J(j+14,i+7) = mi*fjh;
+ J(i+21,j) = mj*fjh;
+ J(j+21,i) = mi*fjh;
+ end
+end
+for i = 1:7
+ sumxx = 0.0;
+ sumxy = 0.0;
+ sumyy = 0.0;
+ for j = 1:7
+ if j ~= i
+ sumxx = sumxx + J(i+14,j);
+ sumxy = sumxy + J(i+14,j+7);
+ sumyy = sumyy + J(i+21,j+7);
+ end
+ end
+ J(i+14,i) = -sumxx;
+ J(i+14,i+7) = -sumxy;
+ J(i+21,i) = -sumxy;
+ J(i+21,i+7) = -sumyy;
+end
+
+flag = 0;
+new_data = [];
+
+return
\ No newline at end of file
diff --git a/sundialsTB/cvodes/examples_ser/mcvsPollut_FSA_dns.m b/sundialsTB/cvodes/examples_ser/mcvsPollut_FSA_dns.m
new file mode 100644
index 0000000..25c46c7
--- /dev/null
+++ b/sundialsTB/cvodes/examples_ser/mcvsPollut_FSA_dns.m
@@ -0,0 +1,417 @@
+function mcvsPollut_FSA_dns()
+%mcvsPollut_FSA_dns - Air pollution model
+% J.G Verwer - Gauss-Seidel Iteration for Stiff ODEs from Chemical Kinetics
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2007, The Regents of the University of California.
+% $Revision: 1.2 $Date: 2007/12/05 21:58:18 $
+
+
+t0 = 0.0;
+tf = 1.0;
+
+
+Ny = 20;
+Np = 25;
+
+plist = [21;22;23;24;25];
+Ns = length(plist);
+
+% -------------------
+% User data structure
+% -------------------
+
+data.p = [0.35 ; 0.266e2 ; 0.123e5 ; 0.86e-3 ; 0.82e-3 ; ...
+ 0.15e5 ; 0.13e-3 ; 0.24e5 ; 0.165e5 ; 0.9e4 ; ...
+ 0.22e-1 ; 0.12e5 ; 0.188e1 ; 0.163e5 ; 0.48e7 ; ...
+ 0.35e-3 ; 0.175e-1 ; 0.1e9 ; 0.444e12 ; 0.124e4 ; ...
+ 0.21e1 ; 0.578e1 ; 0.474e-1 ; 0.178e4 ; 0.312e1];
+
+data.plist = plist;
+
+% ---------------------
+% CVODES initialization
+% ---------------------
+
+options = CVodeSetOptions('UserData',data,...
+ 'RelTol',1.e-5,...
+ 'AbsTol',1.e-8,...
+ 'LinearSolver','Dense');
+
+y0 = [0 ; 0.2 ; 0 ; 0.04 ; 0 ; ...
+ 0 ; 0.1 ; 0.3 ; 0.01 ; 0 ; ...
+ 0 ; 0 ; 0 ; 0 ; 0 ; ...
+ 0 ; 0.007 ; 0 ; 0 ; 0];
+
+
+CVodeInit(@rhsfn, 'BDF', 'Newton', t0, y0, options);
+
+
+% ------------------
+% FSA initialization
+% ------------------
+
+yS0 = zeros(Ny,Ns);
+
+FSAoptions = CVodeSensSetOptions('method','Simultaneous',...
+ 'ErrControl', true,...
+ 'ParamScales', data.p(plist));
+
+CVodeSensInit(Ns, @rhsSfn, yS0, FSAoptions);
+
+% ----------------
+% Problem solution
+% ----------------
+
+time(1,1) = t0;
+sol(1,:) = y0';
+sens(1,:,:) = yS0;
+
+t = t0;
+it = 1;
+while t<tf
+ it = it+1;
+ [status, t, y, yS] = CVode(tf,'OneStep');
+% [status, t, y] = CVode(tf,'OneStep');
+ time(it,1) = t;
+ sol(it,:) = y';
+ sens(it,:,:) = yS;
+end
+
+si = CVodeGetStats
+
+% -------------
+% Plot solution
+% -------------
+
+figure
+hold on
+for i = 1:Ny
+ plot(time, sol(:,i))
+end
+set(gca,'XLim',[t0 tf]);
+xlabel('time')
+grid on
+box on
+
+% -----------
+% Free memory
+% -----------
+
+CVodeFree;
+
+% ===========================================================================
+
+function [yd, flag, new_data] = rhsfn(t, y, data)
+% Right-hand side function
+
+p = data.p;
+
+p1 = p(1); p2 = p(2); p3 = p(3); p4 = p(4); p5 = p(5);
+p6 = p(6); p7 = p(7); p8 = p(8); p9 = p(9); p10 = p(10);
+p11 = p(11); p12 = p(12); p13 = p(13); p14 = p(14); p15 = p(15);
+p16 = p(16); p17 = p(17); p18 = p(18); p19 = p(19); p20 = p(20);
+p21 = p(21); p22 = p(22); p23 = p(23); p24 = p(24); p25 = p(25);
+
+y1 = y(1); y2 = y(2); y3 = y(3); y4 = y(4); y5 = y(5);
+y6 = y(6); y7 = y(7); y8 = y(8); y9 = y(9); y10 = y(10);
+y11 = y(11); y12 = y(12); y13 = y(13); y14 = y(14); y15 = y(15);
+y16 = y(16); y17 = y(17); y18 = y(18); y19 = y(19); y20 = y(20);
+
+
+r1 = p1*y1;
+r2 = p2*y2*y4;
+r3 = p3*y2*y5;
+r4 = p4*y7;
+r5 = p5*y7;
+
+r6 = p6*y6*y7;
+r7 = p7*y9;
+r8 = p8*y6*y9;
+r9 = p9*y2*y11;
+r10 = p10*y1*y11;
+
+r11 = p11*y13;
+r12 = p12*y2*y10;
+r13 = p13*y14;
+r14 = p14*y1*y6;
+r15 = p15*y3;
+
+r16 = p16*y4;
+r17 = p17*y4;
+r18 = p18*y16;
+r19 = p19*y16;
+r20 = p20*y6*y17;
+
+r21 = p21*y19;
+r22 = p22*y19;
+r23 = p23*y1*y4;
+r24 = p24*y1*y19;
+r25 = p25*y20;
+
+
+f1 = -r1-r10-r14-r23-r24+r2+r3+r9+r11+r12+r22+r25;
+f2 = -r2-r3-r9-r12+r1+r21;
+f3 = -r15+r1+r17+r19+r22;
+f4 = -r2-r16-r17-r23+r15;
+f5 = -r3+2*r4+r6+r7+r13+r20;
+
+f6 = -r6-r8-r14-r20+r3+2*r18;
+f7 = -r4-r5-r6+r13;
+f8 = r4+r5+r6+r7;
+f9 = -r7-r8;
+f10 = -r12+r7+r9;
+
+f11 = -r9-r10+r8+r11;
+f12 = r9;
+f13 = -r11+r10;
+f14 = -r13+r12;
+f15 = r14;
+
+f16 = -r18-r19+r16;
+f17 = -r20;
+f18 = r20;
+f19 = -r21-r22-r24+r23+r25;
+f20 = -r25+r24;
+
+yd = [f1 ; f2 ; f3 ; f4 ; f5 ; ...
+ f6 ; f7 ; f8 ; f9 ; f10 ; ...
+ f11 ; f12 ; f13 ; f14 ; f15 ; ...
+ f16 ; f17 ; f18 ; f19 ; f20];
+
+
+flag = 0;
+new_data = [];
+
+return
+
+% ===========================================================================
+
+function [ySd, flag, new_data] = rhsSfn(t,y,yd,yS,data)
+% Sensitivity right-hand side function
+
+J = Jmat(y,data);
+K = Kmat(y,data);
+
+pl = data.plist;
+
+ySd = J*yS + K(:,pl);
+
+flag = 0;
+new_data = [];
+
+return
+
+% ===========================================================================
+
+function [J, flag, new_data] = djacfn(t, y, fy, data)
+
+J = Jmat(y, data);
+
+flag = 0;
+new_data = [];
+
+return
+
+% ===========================================================================
+
+function J = Jmat(y, data)
+
+p = data.p;
+
+p1 = p(1); p2 = p(2); p3 = p(3); p4 = p(4); p5 = p(5);
+p6 = p(6); p7 = p(7); p8 = p(8); p9 = p(9); p10 = p(10);
+p11 = p(11); p12 = p(12); p13 = p(13); p14 = p(14); p15 = p(15);
+p16 = p(16); p17 = p(17); p18 = p(18); p19 = p(19); p20 = p(20);
+p21 = p(21); p22 = p(22); p23 = p(23); p24 = p(24); p25 = p(25);
+
+y1 = y(1); y2 = y(2); y3 = y(3); y4 = y(4); y5 = y(5);
+y6 = y(6); y7 = y(7); y8 = y(8); y9 = y(9); y10 = y(10);
+y11 = y(11); y12 = y(12); y13 = y(13); y14 = y(14); y15 = y(15);
+y16 = y(16); y17 = y(17); y18 = y(18); y19 = y(19); y20 = y(20);
+
+% Jacobian obtained symbolically :-)
+
+J = zeros(20, 20);
+
+J( 1, 1) = -p1-p10*y11-p14*y6-p23*y4-p24*y19;
+J( 1, 2) = p2*y4+p3*y5+p9*y11+p12*y10;
+J( 1, 4) = -p23*y1+p2*y2;
+J( 1, 5) = p3*y2;
+J( 1, 6) = -p14*y1;
+J( 1, 10) = p12*y2;
+J( 1, 11) = -p10*y1+p9*y2;
+J( 1, 13) = p11;
+J( 1, 19) = -p24*y1+p22;
+J( 1, 20) = p25;
+J( 2, 1) = p1;
+J( 2, 2) = -p2*y4-p3*y5-p9*y11-p12*y10;
+J( 2, 4) = -p2*y2;
+J( 2, 5) = -p3*y2;
+J( 2, 10) = -p12*y2;
+J( 2, 11) = -p9*y2;
+J( 2, 19) = p21;
+J( 3, 1) = p1;
+J( 3, 3) = -p15;
+J( 3, 4) = p17;
+J( 3, 16) = p19;
+J( 3, 19) = p22;
+J( 4, 1) = -p23*y4;
+J( 4, 2) = -p2*y4;
+J( 4, 3) = p15;
+J( 4, 4) = -p2*y2-p16-p17-p23*y1;
+J( 5, 2) = -p3*y5;
+J( 5, 5) = -p3*y2;
+J( 5, 6) = p6*y7+p20*y17;
+J( 5, 7) = 2*p4+p6*y6;
+J( 5, 9) = p7;
+J( 5, 14) = p13;
+J( 5, 17) = p20*y6;
+J( 6, 1) = -p14*y6;
+J( 6, 2) = p3*y5;
+J( 6, 5) = p3*y2;
+J( 6, 6) = -p6*y7-p8*y9-p14*y1-p20*y17;
+J( 6, 7) = -p6*y6;
+J( 6, 9) = -p8*y6;
+J( 6, 16) = 2*p18;
+J( 6, 17) = -p20*y6;
+J( 7, 6) = -p6*y7;
+J( 7, 7) = -p4-p5-p6*y6;
+J( 7, 14) = p13;
+J( 8, 6) = p6*y7;
+J( 8, 7) = p4+p5+p6*y6;
+J( 8, 9) = p7;
+J( 9, 6) = -p8*y9;
+J( 9, 9) = -p7-p8*y6;
+J(10, 2) = -p12*y10+p9*y11;
+J(10, 9) = p7;
+J(10, 10) = -p12*y2;
+J(10, 11) = p9*y2;
+J(11, 1) = -p10*y11;
+J(11, 2) = -p9*y11;
+J(11, 6) = p8*y9;
+J(11, 9) = p8*y6;
+J(11, 11) = -p9*y2-p10*y1;
+J(11, 13) = p11;
+J(12, 2) = p9*y11;
+J(12, 11) = p9*y2;
+J(13, 1) = p10*y11;
+J(13, 11) = p10*y1;
+J(13, 13) = -p11;
+J(14, 2) = p12*y10;
+J(14, 10) = p12*y2;
+J(14, 14) = -p13;
+J(15, 1) = p14*y6;
+J(15, 6) = p14*y1;
+J(16, 4) = p16;
+J(16, 16) = -p18-p19;
+J(17, 6) = -p20*y17;
+J(17, 17) = -p20*y6;
+J(18, 6) = p20*y17;
+J(18, 17) = p20*y6;
+J(19, 1) = -p24*y19+p23*y4;
+J(19, 4) = p23*y1;
+J(19, 19) = -p21-p22-p24*y1;
+J(19, 20) = p25;
+J(20, 1) = p24*y19;
+J(20, 19) = p24*y1;
+J(20, 20) = -p25;
+
+return
+
+% ===========================================================================
+
+function K = Kmat(y, data)
+
+p = data.p;
+
+p1 = p(1); p2 = p(2); p3 = p(3); p4 = p(4); p5 = p(5);
+p6 = p(6); p7 = p(7); p8 = p(8); p9 = p(9); p10 = p(10);
+p11 = p(11); p12 = p(12); p13 = p(13); p14 = p(14); p15 = p(15);
+p16 = p(16); p17 = p(17); p18 = p(18); p19 = p(19); p20 = p(20);
+p21 = p(21); p22 = p(22); p23 = p(23); p24 = p(24); p25 = p(25);
+
+y1 = y(1); y2 = y(2); y3 = y(3); y4 = y(4); y5 = y(5);
+y6 = y(6); y7 = y(7); y8 = y(8); y9 = y(9); y10 = y(10);
+y11 = y(11); y12 = y(12); y13 = y(13); y14 = y(14); y15 = y(15);
+y16 = y(16); y17 = y(17); y18 = y(18); y19 = y(19); y20 = y(20);
+
+K = zeros(20, 25);
+
+K( 1, 1) = -y1;
+K( 1, 2) = y2*y4;
+K( 1, 3) = y2*y5;
+K( 1, 9) = y2*y11;
+K( 1, 10) = -y1*y11;
+K( 1, 11) = y13;
+K( 1, 12) = y2*y10;
+K( 1, 14) = -y1*y6;
+K( 1, 22) = y19;
+K( 1, 23) = -y1*y4;
+K( 1, 24) = -y1*y19;
+K( 1, 25) = y20;
+K( 2, 1) = y1;
+K( 2, 2) = -y2*y4;
+K( 2, 3) = -y2*y5;
+K( 2, 9) = -y2*y11;
+K( 2, 12) = -y2*y10;
+K( 2, 21) = y19;
+K( 3, 1) = y1;
+K( 3, 15) = -y3;
+K( 3, 17) = y4;
+K( 3, 19) = y16;
+K( 3, 22) = y19;
+K( 4, 2) = -y2*y4;
+K( 4, 15) = y3;
+K( 4, 16) = -y4;
+K( 4, 17) = -y4;
+K( 4, 23) = -y1*y4;
+K( 5, 3) = -y2*y5;
+K( 5, 4) = 2*y7;
+K( 5, 6) = y6*y7;
+K( 5, 7) = y9;
+K( 5, 13) = y14;
+K( 5, 20) = y6*y17;
+K( 6, 3) = y2*y5;
+K( 6, 6) = -y6*y7;
+K( 6, 8) = -y6*y9;
+K( 6, 14) = -y1*y6;
+K( 6, 18) = 2*y16;
+K( 6, 20) = -y6*y17;
+K( 7, 4) = -y7;
+K( 7, 5) = -y7;
+K( 7, 6) = -y6*y7;
+K( 7, 13) = y14;
+K( 8, 4) = y7;
+K( 8, 5) = y7;
+K( 8, 6) = y6*y7;
+K( 8, 7) = y9;
+K( 9, 7) = -y9;
+K( 9, 8) = -y6*y9;
+K(10, 7) = y9;
+K(10, 9) = y2*y11;
+K(10, 12) = -y2*y10;
+K(11, 8) = y6*y9;
+K(11, 9) = -y2*y11;
+K(11, 10) = -y1*y11;
+K(11, 11) = y13;
+K(12, 9) = y2*y11;
+K(13, 10) = y1*y11;
+K(13, 11) = -y13;
+K(14, 12) = y2*y10;
+K(14, 13) = -y14;
+K(15, 14) = y1*y6;
+K(16, 16) = y4;
+K(16, 18) = -y16;
+K(16, 19) = -y16;
+K(17, 20) = -y6*y17;
+K(18, 20) = y6*y17;
+K(19, 21) = -y19;
+K(19, 22) = -y19;
+K(19, 23) = y1*y4;
+K(19, 24) = -y1*y19;
+K(19, 25) = y20;
+K(20, 24) = y1*y19;
+K(20, 25) = -y20;
+
+return
\ No newline at end of file
diff --git a/sundialsTB/cvodes/examples_ser/mcvsRoberts_ASAi_dns.m b/sundialsTB/cvodes/examples_ser/mcvsRoberts_ASAi_dns.m
new file mode 100644
index 0000000..ee6800b
--- /dev/null
+++ b/sundialsTB/cvodes/examples_ser/mcvsRoberts_ASAi_dns.m
@@ -0,0 +1,286 @@
+function mcvsRoberts_ASAi_dns()
+%mcvsRoberts_ASAi_dns - CVODES adjoint sensitivity example problem (serial, dense)
+% 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:
+% dy1/dt = -p1*y1 + p2*y2*y3
+% dy2/dt = p1*y1 - p2*y2*y3 - p3*(y2)^2
+% dy3/dt = p3*(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.
+%
+% This program solves the problem with the BDF method,
+% Newton iteration with the CVDENSE dense linear solver, and a
+% user-supplied Jacobian routine. It uses a scalar relative
+% tolerance and a vector absolute tolerance.
+%
+% The gradient with respect to the problem parameters p1, p2,
+% and p3 of the following quantity:
+% G = int_t0^t1 y3(t) dt
+% is computed using ASA.
+%
+% Writing the original ODE as:
+% dy/dt = f(y,p)
+% y(t0) = y0(p)
+% then the gradient with respect to the parameters p of
+% G(p) = int_t0^t1 g(y,p) dt
+% is obtained as:
+% dG/dp = int_t0^t1 (g_p + lambda^T f_p ) dt + lambda^T(t0)*y0_p
+% = -xi^T(t0) + lambda^T(t0)*y0_p
+% where lambda and xi are solutions of:
+% d(lambda)/dt = - (f_y)^T * lambda - (g_y)^T
+% lambda(t1) = 0
+% and
+% d(xi)/dt = (g_p)^T + (f_p)^T * lambda
+% xi(t1) = 0
+%
+% During the forward integration, CVODES also evaluates G as
+% G = q(t1)
+% where
+% dq/dt = g(t,y,p)
+% q(t0) = 0
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2005, The Regents of the University of California.
+% $Revision: 1.2 $Date: 2009/04/26 23:26:45 $
+
+
+% ----------------------------------------
+% User data structure
+% ----------------------------------------
+
+data.p = [0.04; 1.0e4; 3.0e7];
+
+% ----------------------------------------
+% Forward CVODES options
+% ----------------------------------------
+
+
+options = CVodeSetOptions('UserData',data,...
+ 'RelTol',1.e-6,...
+ 'AbsTol',[1.e-8; 1.e-14; 1.e-6],...
+ 'LinearSolver','Dense',...
+ 'JacobianFn', at djacfn);
+
+mondata = struct;
+mondata.sol = true;
+mondata.mode = 'both';
+options = CVodeSetOptions(options,...
+ 'MonitorFn', at CVodeMonitor,...
+ 'MonitorData',mondata);
+
+t0 = 0.0;
+y0 = [1.0;0.0;0.0];
+CVodeInit(@rhsfn, 'BDF', 'Newton', t0, y0, options);
+
+
+optionsQ = CVodeQuadSetOptions('ErrControl',true,...
+ 'RelTol',1.e-6,'AbsTol',1.e-6);
+
+q0 = 0.0;
+CVodeQuadInit(@quadfn, q0, optionsQ);
+
+% ----------------------------------------
+% Initialize ASA
+% ----------------------------------------
+
+CVodeAdjInit(150, 'Hermite');
+
+% ----------------------------------------
+% Forward integration
+% ----------------------------------------
+
+fprintf('Forward integration ');
+
+tout = 4.e7;
+[status,t,y,q] = CVode(tout,'Normal');
+s = CVodeGetStats;
+fprintf('(%d steps)\n',s.nst);
+fprintf('G = %12.4e\n',q);
+
+
+fprintf('\nCheck point info\n');
+
+ck = CVodeGet('CheckPointsInfo');
+fprintf([' t0 t1 nstep order step size\n']);
+for i = 1:length(ck)
+ fprintf('%8.3e %8.3e %4d %1d %10.5e\n',...
+ ck(i).t0, ck(i).t1, ck(i).nstep, ck(i).order, ck(i).step);
+end
+fprintf('\n');
+
+% ----------------------------------------
+% Backward CVODES options
+% ----------------------------------------
+
+optionsB = CVodeSetOptions('UserData',data,...
+ 'RelTol',1.e-6,...
+ 'AbsTol',1.e-8,...
+ 'LinearSolver','Dense',...
+ 'JacobianFn', at djacBfn);
+
+mondataB = struct;
+mondataB.mode = 'both';
+optionsB = CVodeSetOptions(optionsB,...
+ 'MonitorFn','CVodeMonitorB',...
+ 'MonitorData', mondataB);
+
+tB1 = 4.e7;
+yB1 = [0.0;0.0;0.0];
+idxB = CVodeInitB(@rhsBfn, 'BDF', 'Newton', tB1, yB1, optionsB);
+
+optionsQB = CVodeQuadSetOptions('ErrControl',true,...
+ 'RelTol',1.e-6,'AbsTol',1.e-3);
+
+qB1 = [0.0;0.0;0.0];
+CVodeQuadInitB(idxB, @quadBfn, qB1, optionsQB);
+
+% ----------------------------------------
+% Backward integration
+% ----------------------------------------
+
+fprintf('Backward integration ');
+
+[status,t,yB,qB] = CVodeB(t0,'Normal');
+sB=CVodeGetStatsB(idxB);
+fprintf('(%d steps)\n',sB.nst);
+
+fprintf('tB1: %12.4e\n',tB1);
+fprintf('dG/dp: %12.4e %12.4e %12.4e\n',...
+ -qB(1)+yB(1), -qB(2)+yB(2), -qB(3)+yB(3));
+fprintf('lambda(t0): %12.4e %12.4e %12.4e\n',...
+ yB(1),yB(2),yB(3));
+
+% ----------------------------------------
+% Free memory
+% ----------------------------------------
+
+CVodeFree;
+
+% ===========================================================================
+
+function [yd, flag, new_data] = rhsfn(t, y, data)
+% Right-hand side function
+
+r1 = data.p(1);
+r2 = data.p(2);
+r3 = data.p(3);
+
+yd(1) = -r1*y(1) + r2*y(2)*y(3);
+yd(3) = r3*y(2)*y(2);
+yd(2) = -yd(1) - yd(3);
+
+flag = 0;
+new_data = [];
+
+return
+
+% ===========================================================================
+
+function [qd, flag, new_data] = quadfn(t, y, data)
+% Forward quadrature integrand function
+
+qd = y(3);
+
+flag = 0;
+new_data = [];
+
+return
+
+% ===========================================================================
+
+function [J, flag, new_data] = djacfn(t, y, fy, data)
+% Dense Jacobian function
+
+r1 = data.p(1);
+r2 = data.p(2);
+r3 = data.p(3);
+
+J(1,1) = -r1;
+J(1,2) = r2*y(3);
+J(1,3) = r2*y(2);
+
+J(2,1) = r1;
+J(2,2) = -r2*y(3) - 2*r3*y(2);
+J(2,3) = -r2*y(2);
+
+J(3,2) = 2*r3*y(2);
+
+flag = 0;
+new_data = [];
+
+return
+
+% ===========================================================================
+
+function [yBd, flag, new_data] = rhsBfn(t, y, yB, data)
+% Backward problem right-hand side function
+
+r1 = data.p(1);
+r2 = data.p(2);
+r3 = data.p(3);
+
+y1 = y(1);
+y2 = y(2);
+y3 = y(3);
+
+l1 = yB(1);
+l2 = yB(2);
+l3 = yB(3);
+
+l21 = l2-l1;
+l32 = l3-l2;
+y23 = y2*y3;
+
+yBd(1) = - r1*l21;
+yBd(2) = r2*y3*l21 - 2.0*r3*y2*l32;
+yBd(3) = r2*y2*l21 - 1.0;
+
+flag = 0;
+new_data = [];
+
+return
+
+% ===========================================================================
+
+function [qBd, flag, new_data] = quadBfn(t, y, yB, data)
+% Backward problem quadrature integrand function
+
+r1 = data.p(1);
+r2 = data.p(2);
+r3 = data.p(3);
+
+y1 = y(1);
+y2 = y(2);
+y3 = y(3);
+
+l1 = yB(1);
+l2 = yB(2);
+l3 = yB(3);
+
+l21 = l2-l1;
+l32 = l3-l2;
+y23 = y2*y3;
+
+qBd(1) = y1*l21;
+qBd(2) = -y23*l21;
+qBd(3) = l32*y2^2;
+
+flag = 0;
+new_data = [];
+
+return
+
+% ===========================================================================
+
+function [JB, flag, new_data] = djacBfn(t, y, yB, fyB, data)
+% Backward problem Jacobian function
+
+J = djacfn(t,y,[],data);
+JB = -J';
+
+flag = 0;
+new_data = [];
+
+return
\ No newline at end of file
diff --git a/sundialsTB/cvodes/examples_ser/mcvsRoberts_FSA_dns.m b/sundialsTB/cvodes/examples_ser/mcvsRoberts_FSA_dns.m
new file mode 100644
index 0000000..7a589f4
--- /dev/null
+++ b/sundialsTB/cvodes/examples_ser/mcvsRoberts_FSA_dns.m
@@ -0,0 +1,197 @@
+function mcvsRoberts_FSA_dns()
+%mcvsRoberts_FSA_dns - CVODES forward sensitivity example (serial, dense)
+% 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:
+% 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 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
+% user-supplied Jacobian routine. It uses a scalar relative
+% tolerance and a vector absolute tolerance.
+%
+% Solution sensitivities with respect to the problem parameters
+% p1, p2, and p3 are computed using FSA. The sensitivity right-hand
+% side is given analytically through the user routine rhsSfn.
+% Tolerances for the sensitivity variables are estimated by
+% CVODES using the provided parameter scale information. The
+% sensitivity variables are included in the error test.
+%
+% Output is printed in decades from t = .4 to t = 4.e10.
+% Run statistics (optional outputs) are printed at the end.
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2005, The Regents of the University of California.
+% $Revision: 1.1 $Date: 2007/10/26 16:30:48 $
+
+% -------------------
+% User data structure
+% -------------------
+
+data.p = [0.04; 1.0e4; 3.0e7];
+
+% ---------------------
+% CVODES initialization
+% ---------------------
+
+options = CVodeSetOptions('UserData',data,...
+ 'RelTol',1.e-4,...
+ 'AbsTol',[1.e-8; 1.e-14; 1.e-6],...
+ 'JacobianFn', at djacfn);
+
+mondata = struct;
+mondata.mode = 'both';
+mondata.sol = true;
+mondata.sensi = true;
+options = CVodeSetOptions(options,'MonitorFn', at CVodeMonitor,'MonitorData',mondata);
+
+t0 = 0.0;
+y0 = [1.0;0.0;0.0];
+
+CVodeInit(@rhsfn, 'BDF', 'Newton', t0, y0, options);
+
+
+% ------------------
+% FSA initialization
+% ------------------
+
+Ns = 2;
+yS0 = zeros(3,Ns);
+
+% Case 1: user-provided sensitivity RHS
+
+FSAoptions = CVodeSensSetOptions('method','Simultaneous',...
+ 'ErrControl', true,...
+ 'ParamScales', [0.04; 1.0e4]);
+CVodeSensInit(Ns, @rhsSfn, yS0, FSAoptions);
+
+% Case 2: internal DQ approximation
+
+%FSAoptions = CVodeSensSetOptions('method','Simultaneous',...
+% 'ErrControl', true,...
+% 'ParamField', 'p',...
+% 'ParamList', [1 2],...
+% 'ParamScales', [0.04 1.0e4]);
+%CVodeSensInit(Ns, [], yS0, FSAoptions);
+
+% ----------------
+% Problem solution
+% ----------------
+
+t1 = 0.4;
+tmult = 10.0;
+nout = 12;
+
+iout = 0;
+tout = t1;
+while 1,
+ [status, t, y, yS] = CVode(tout,'Normal');
+ fprintf('t = %0.2e\n',t);
+ fprintf('solution = [ %14.6e %14.6e %14.6e ]\n', y(1), y(2), y(3));
+ fprintf('sensitivity 1 = [ %14.6e %14.6e %14.6e ]\n', yS(1,1), yS(2,1), yS(3,1));
+ fprintf('sensitivity 2 = [ %14.6e %14.6e %14.6e ]\n\n', yS(1,2), yS(2,2), yS(3,2));
+ if(status ==0)
+ iout = iout+1;
+ tout = tout*tmult;
+ end
+ if iout==nout
+ break;
+ end
+end
+
+si = CVodeGetStats
+
+% -----------
+% Free memory
+% -----------
+
+CVodeFree;
+
+% ===========================================================================
+
+function [yd, flag, new_data] = rhsfn(t, y, data)
+% Right-hand side function
+
+r1 = data.p(1);
+r2 = data.p(2);
+r3 = data.p(3);
+
+yd(1) = -r1*y(1) + r2*y(2)*y(3);
+yd(3) = r3*y(2)*y(2);
+yd(2) = -yd(1) - yd(3);
+
+flag = 0;
+new_data = [];
+
+return
+
+% ===========================================================================
+
+function [J, flag, new_data] = djacfn(t, y, fy, data)
+% Dense Jacobian function
+
+r1 = data.p(1);
+r2 = data.p(2);
+r3 = data.p(3);
+
+J(1,1) = -r1;
+J(1,2) = r2*y(3);
+J(1,3) = r2*y(2);
+
+J(2,1) = r1;
+J(2,2) = -r2*y(3) - 2*r3*y(2);
+J(2,3) = -r2*y(2);
+
+J(3,2) = 2*r3*y(2);
+
+flag = 0;
+new_data = [];
+
+return
+
+% ===========================================================================
+
+function [ySd, flag, new_data] = rhsSfn(t,y,yd,yS,data)
+% Sensitivity right-hand side function
+
+r1 = data.p(1);
+r2 = data.p(2);
+r3 = data.p(3);
+
+% r1
+
+yS1 = yS(:,1);
+yS1d = zeros(3,1);
+
+yS1d(1) = -r1*yS1(1) + r2*y(3)*yS1(2) + r2*y(2)*yS1(3);
+yS1d(3) = 2*r3*y(2)*yS1(2);
+yS1d(2) = -yS1d(1)-yS1d(3);
+
+yS1d(1) = yS1d(1) - y(1);
+yS1d(2) = yS1d(2) + y(1);
+
+% r2
+
+yS2 = yS(:,2);
+yS2d = zeros(3,1);
+
+yS2d(1) = -r1*yS2(1) + r2*y(3)*yS2(2) + r2*y(2)*yS2(3);
+yS2d(3) = 2*r3*y(2)*yS2(2);
+yS2d(2) = -yS2d(1)-yS2d(3);
+
+yS2d(1) = yS2d(1) + y(2)*y(3);
+yS2d(2) = yS2d(2) - y(2)*y(3);
+
+% Return values
+
+ySd = [yS1d yS2d];
+flag = 0;
+new_data = [];
+
+return
diff --git a/sundialsTB/cvodes/examples_ser/mcvsRoberts_dns.m b/sundialsTB/cvodes/examples_ser/mcvsRoberts_dns.m
new file mode 100644
index 0000000..15ca4bf
--- /dev/null
+++ b/sundialsTB/cvodes/examples_ser/mcvsRoberts_dns.m
@@ -0,0 +1,132 @@
+function mcvsRoberts_dns()
+%mcvsRoberts_dns - CVODES example problem (serial, dense)
+% 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:
+% 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 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
+% user-supplied Jacobian routine. It uses a scalar relative
+% tolerance and a vector absolute tolerance and also illustrates
+% the rootfinding capability in CVODES.
+%
+% Output is printed in decades from t = .4 to t = 4.e10.
+% Run statistics (optional outputs) are printed at the end.
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2005, The Regents of the University of California.
+% $Revision: 1.1 $Date: 2007/10/26 16:30:48 $
+
+data.p = [0.04; 1.0e4; 3.0e7];
+
+t0 = 0.0;
+y0 = [1.0;0.0;0.0];
+
+options = CVodeSetOptions('UserData', data,...
+ 'RelTol',1.e-8,...
+ 'AbsTol',[1.e-8; 1.e-14; 1.e-6],...
+ 'LinearSolver','Dense',...
+ 'JacobianFn', at djacfn,...
+ 'RootsFn', at rootfn, 'NumRoots',2);
+
+mondata.sol = true;
+mondata.mode = 'text';
+mondata.skip = 9;
+mondata.updt = 100;
+options = CVodeSetOptions(options,'MonitorFn', at CVodeMonitor,'MonitorData',mondata);
+
+CVodeInit(@rhsfn, 'BDF', 'Newton', t0, y0, options);
+
+t1 = 0.4;
+tmult = 10.0;
+nout = 12;
+
+iout = 0;
+tout = t1;
+while iout < nout
+
+ [status,t,y] = CVode(tout,'Normal');
+
+% Extract statistics
+ si = CVodeGetStats;
+
+% Print output
+ fprintf('t = %0.2e order = %1d step = %0.2e',t, si.qlast, si.hlast);
+ if(status == 2)
+ fprintf(' ... Root found %d %d\n',si.RootInfo.roots(1), si.RootInfo.roots(2));
+ else
+ fprintf('\n');
+ end
+ fprintf('solution = [ %14.6e %14.6e %14.6e ]\n\n', y(1), y(2), y(3));
+
+% Update output time
+ if(status == 0)
+ iout = iout+1;
+ tout = tout*tmult;
+ end
+
+end
+
+si = CVodeGetStats;
+
+CVodeFree;
+
+% ===========================================================================
+
+function [yd, flag, new_data] = rhsfn(t, y, data)
+% Right-hand side function
+
+r1 = data.p(1);
+r2 = data.p(2);
+r3 = data.p(3);
+
+yd(1) = -r1*y(1) + r2*y(2)*y(3);
+yd(3) = r3*y(2)*y(2);
+yd(2) = -yd(1) - yd(3);
+
+flag = 0;
+new_data = [];
+
+return
+
+% ===========================================================================
+
+function [J, flag, new_data] = djacfn(t, y, fy, data)
+% Dense Jacobian function
+
+r1 = data.p(1);
+r2 = data.p(2);
+r3 = data.p(3);
+
+J(1,1) = -r1;
+J(1,2) = r2*y(3);
+J(1,3) = r2*y(2);
+
+J(2,1) = r1;
+J(2,2) = -r2*y(3) - 2*r3*y(2);
+J(2,3) = -r2*y(2);
+
+J(3,2) = 2*r3*y(2);
+
+flag = 0;
+new_data = [];
+
+return
+
+% ===========================================================================
+
+function [g, flag, new_data] = rootfn(t,y,data)
+% Root finding function
+
+g(1) = y(1) - 0.0001;
+g(2) = y(3) - 0.01;
+
+flag = 0;
+new_data = [];
diff --git a/sundialsTB/cvodes/examples_ser/mcvsVanDPol_dns.m b/sundialsTB/cvodes/examples_ser/mcvsVanDPol_dns.m
new file mode 100644
index 0000000..ab77d71
--- /dev/null
+++ b/sundialsTB/cvodes/examples_ser/mcvsVanDPol_dns.m
@@ -0,0 +1,64 @@
+function mcvsVanDPol_dns()
+%mcvsVanDPol_dns - CVODES example problem (serial, dense)
+% van der Pol problem.
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2005, The Regents of the University of California.
+% $Revision: 1.2 $Date: 2007/12/05 21:58:18 $
+
+
+data.mu = 100.0;
+
+t0 = 0.0;
+tf = 300.0;
+y0 = [2.0;0.0];
+
+options = CVodeSetOptions('UserData',data,...
+ 'RelTol',1.e-8,...
+ 'AbsTol',1e-6,...
+ 'JacobianFn', at djacfn);
+
+mondata.mode = 'both';
+mondata.skip = 20;
+options = CVodeSetOptions(options,'MonitorFn', at CVodeMonitor,'MonitorData',mondata);
+
+CVodeInit(@rhsfn, 'BDF', 'Newton', t0, y0, options);
+
+ntout = 50;
+dt = (tf-t0)/ntout;
+tt = linspace(t0+dt,tf,ntout-1);
+
+[status,t,y] = CVode(tt,'Normal');
+
+CVodeFree;
+
+figure;
+plot(t,y(1,:),'r',t,y(1,:),'.');
+
+% ===========================================================================
+
+function [yd, flag, new_data] = rhsfn(t, y, data)
+% Right-hand side function
+
+mu = data.mu;
+
+yd = [ y(2)
+ mu*(1-y(1)^2)*y(2)-y(1) ];
+
+flag = 0;
+new_data = [];
+
+return
+
+% ===========================================================================
+
+function [J, flag, new_data] = djacfn(t, y, fy, data)
+% Dense Jacobian function (if using Newton)
+
+mu = data.mu;
+
+J = [ 0 1
+ -2*mu*y(1)*y(2)-1 mu*(1-y(1)^2) ];
+
+flag = 0;
+new_data = [];
\ No newline at end of file
diff --git a/sundialsTB/cvodes/function_types/CVBandJacFn.m b/sundialsTB/cvodes/function_types/CVBandJacFn.m
new file mode 100644
index 0000000..10233fb
--- /dev/null
+++ b/sundialsTB/cvodes/function_types/CVBandJacFn.m
@@ -0,0 +1,31 @@
+%CVBandJacFn - type for user provided banded Jacobian function.
+%
+% The function BJACFUN must be defined as
+% FUNCTION [J, FLAG] = BJACFUN(T, Y, FY)
+% and must return a matrix J corresponding to the banded Jacobian of f(t,y).
+% The input argument FY contains the current value of f(t,y).
+% If a user data structure DATA was specified in CVodeInit, then
+% BJACFUN must be defined as
+% FUNCTION [J, FLAG, NEW_DATA] = BJACFUN(T, Y, FY, DATA)
+% If the local modifications to the user data structure are needed in
+% other user-provided functions then, besides setting the matrix J,
+% the BJACFUN function must also set NEW_DATA. Otherwise, it should
+% set NEW_DATA=[] (do not set NEW_DATA = DATA as it would lead to
+% unnecessary copying).
+%
+% The function BJACFUN must set FLAG=0 if successful, FLAG<0 if an
+% unrecoverable failure occurred, or FLAG>0 if a recoverable error
+% occurred.
+%
+% See also CVodeSetOptions
+%
+% See the CVODES user guide for more informaiton on the structure of
+% a banded Jacobian.
+%
+% NOTE: BJACFUN is specified through the property JacobianFn to
+% CVodeSetOptions and is used only if the property LinearSolver
+% was set to 'Band'.
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2005, The Regents of the University of California.
+% $Revision: 1.2 $Date: 2011/06/01 20:44:05 $
diff --git a/sundialsTB/cvodes/function_types/CVBandJacFnB.m b/sundialsTB/cvodes/function_types/CVBandJacFnB.m
new file mode 100644
index 0000000..1ea8215
--- /dev/null
+++ b/sundialsTB/cvodes/function_types/CVBandJacFnB.m
@@ -0,0 +1,27 @@
+%CVBandJacFnB - type for user provided banded Jacobian function for backward problems.
+%
+% The function BJACFUNB must be defined either as
+% FUNCTION [JB, FLAG] = BJACFUNB(T, Y, YB, FYB)
+% or as
+% FUNCTION [JB, FLAG, NEW_DATA] = BJACFUNB(T, Y, YB, FYB, DATA)
+% depending on whether a user data structure DATA was specified in
+% CVodeInit. In either case, it must return the matrix JB, the
+% Jacobian of fB(t,y,yB), with respect to yB. The input argument
+% FYB contains the current value of f(t,y,yB).
+%
+% The function BJACFUNB must set FLAG=0 if successful, FLAG<0 if an
+% unrecoverable failure occurred, or FLAG>0 if a recoverable error
+% occurred.
+%
+% See also CVodeSetOptions
+%
+% See the CVODES user guide for more informaiton on the structure of
+% a banded Jacobian.
+%
+% NOTE: BJACFUNB is specified through the property JacobianFn to
+% CVodeSetOptions and is used only if the property LinearSolver
+% was set to 'Band'.
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2005, The Regents of the University of California.
+% $Revision: 1.2 $Date: 2011/06/01 20:44:05 $
diff --git a/sundialsTB/cvodes/function_types/CVDenseJacFn.m b/sundialsTB/cvodes/function_types/CVDenseJacFn.m
new file mode 100644
index 0000000..ee30758
--- /dev/null
+++ b/sundialsTB/cvodes/function_types/CVDenseJacFn.m
@@ -0,0 +1,27 @@
+%CVDenseJacFn - type for user provided dense Jacobian function.
+%
+% The function DJACFUN must be defined as
+% FUNCTION [J, FLAG] = DJACFUN(T, Y, FY)
+% and must return a matrix J corresponding to the Jacobian of f(t,y).
+% The input argument FY contains the current value of f(t,y).
+% If a user data structure DATA was specified in CVodeInit, then
+% DJACFUN must be defined as
+% FUNCTION [J, FLAG, NEW_DATA] = DJACFUN(T, Y, FY, DATA)
+% If the local modifications to the user data structure are needed in
+% other user-provided functions then, besides setting the matrix J,
+% the DJACFUN function must also set NEW_DATA. Otherwise, it should
+% set NEW_DATA=[] (do not set NEW_DATA = DATA as it would lead to
+% unnecessary copying).
+%
+% The function DJACFUN must set FLAG=0 if successful, FLAG<0 if an
+% unrecoverable failure occurred, or FLAG>0 if a recoverable error
+% occurred.
+% See also CVodeSetOptions
+%
+% NOTE: DJACFUN is specified through the property JacobianFn to
+% CVodeSetOptions and is used only if the property LinearSolver
+% was set to 'Dense'.
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2005, The Regents of the University of California.
+% $Revision: 1.2 $Date: 2011/06/01 20:44:05 $
diff --git a/sundialsTB/cvodes/function_types/CVDenseJacFnB.m b/sundialsTB/cvodes/function_types/CVDenseJacFnB.m
new file mode 100644
index 0000000..0c5d133
--- /dev/null
+++ b/sundialsTB/cvodes/function_types/CVDenseJacFnB.m
@@ -0,0 +1,24 @@
+%CVDenseJacFnB - type for user provided dense Jacobian function for backward problems.
+%
+% The function DJACFUNB must be defined either as
+% FUNCTION [JB, FLAG] = DJACFUNB(T, Y, YB, FYB)
+% or as
+% FUNCTION [JB, FLAG, NEW_DATA] = DJACFUNB(T, Y, YB, FYB, DATA)
+% depending on whether a user data structure DATA was specified in
+% CVodeInit. In either case, it must return the matrix JB, the
+% Jacobian of fB(t,y,yB), with respect to yB. The input argument
+% FYB contains the current value of f(t,y,yB).
+%
+% The function DJACFUNB must set FLAG=0 if successful, FLAG<0 if an
+% unrecoverable failure occurred, or FLAG>0 if a recoverable error
+% occurred.
+%
+% See also CVodeSetOptions
+%
+% NOTE: DJACFUNB is specified through the property JacobianFn to
+% CVodeSetOptions and is used only if the property LinearSolver
+% was set to 'Dense'.
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2005, The Regents of the University of California.
+% $Revision: 1.2 $Date: 2011/06/01 20:44:05 $
diff --git a/sundialsTB/cvodes/function_types/CVGcommFn.m b/sundialsTB/cvodes/function_types/CVGcommFn.m
new file mode 100644
index 0000000..4ddd3b3
--- /dev/null
+++ b/sundialsTB/cvodes/function_types/CVGcommFn.m
@@ -0,0 +1,34 @@
+%CVGcommFn - type for user provided communication function (BBDPre).
+%
+% The function GCOMFUN must be defined as
+% FUNCTION FLAG = GCOMFUN(T, Y)
+% and can be used to perform all interprocess communication necessary
+% to evaluate the approximate right-hand side function for the BBDPre
+% preconditioner module.
+% If a user data structure DATA was specified in CVodeInit, then
+% GCOMFUN must be defined as
+% FUNCTION [FLAG, NEW_DATA] = GCOMFUN(T, Y, DATA)
+% If the local modifications to the user data structure are needed
+% in other user-provided functions then the GCOMFUN function must also
+% set NEW_DATA. Otherwise, it should set NEW_DATA=[] (do not set
+% NEW_DATA = DATA as it would lead to unnecessary copying).
+%
+% The function GCOMFUN must set FLAG=0 if successful, FLAG<0 if an
+% unrecoverable failure occurred, or FLAG>0 if a recoverable error
+% occurred.
+%
+% See also CVGlocalFn, CVodeSetOptions
+%
+% NOTES:
+% GCOMFUN is specified through the GcommFn property in CVodeSetOptions
+% and is used only if the property PrecModule is set to 'BBDPre'.
+%
+% Each call to GCOMFUN is preceded by a call to the RHS function
+% ODEFUN with the same arguments T and Y. Thus GCOMFUN can omit
+% any communication done by ODEFUN if relevant to the evaluation
+% of G by GLOCFUN. If all necessary communication was done by ODEFUN,
+% GCOMFUN need not be provided.
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2005, The Regents of the University of California.
+% $Revision: 1.2 $Date: 2011/06/01 20:44:05 $
diff --git a/sundialsTB/cvodes/function_types/CVGcommFnB.m b/sundialsTB/cvodes/function_types/CVGcommFnB.m
new file mode 100644
index 0000000..78dd01e
--- /dev/null
+++ b/sundialsTB/cvodes/function_types/CVGcommFnB.m
@@ -0,0 +1,28 @@
+%CVGcommFn - type for user provided communication function (BBDPre) for backward problems.
+%
+% The function GCOMFUNB must be defined either as
+% FUNCTION FLAG = GCOMFUNB(T, Y, YB)
+% or as
+% FUNCTION [FLAG, NEW_DATA] = GCOMFUNB(T, Y, YB, DATA)
+% depending on whether a user data structure DATA was specified in
+% CVodeInit.
+%
+% The function GCOMFUNB must set FLAG=0 if successful, FLAG<0 if an
+% unrecoverable failure occurred, or FLAG>0 if a recoverable error
+% occurred.
+%
+% See also CVGlocalFnB, CVodeSetOptions
+%
+% NOTES:
+% GCOMFUNB is specified through the GcommFn property in CVodeSetOptions
+% and is used only if the property PrecModule is set to 'BBDPre'.
+%
+% Each call to GCOMFUNB is preceded by a call to the RHS function
+% ODEFUNB with the same arguments T, Y, and YB. Thus GCOMFUNB can
+% omit any communication done by ODEFUNB if relevant to the evaluation
+% of G by GLOCFUNB. If all necessary communication was done by ODEFUNB,
+% GCOMFUNB need not be provided.
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2005, The Regents of the University of California.
+% $Revision: 1.2 $Date: 2011/06/01 20:44:05 $
diff --git a/sundialsTB/cvodes/function_types/CVGlocalFn.m b/sundialsTB/cvodes/function_types/CVGlocalFn.m
new file mode 100644
index 0000000..26d9e4d
--- /dev/null
+++ b/sundialsTB/cvodes/function_types/CVGlocalFn.m
@@ -0,0 +1,28 @@
+%CVGlocalFn - type for user provided RHS approximation function (BBDPre).
+%
+% The function GLOCFUN must be defined as
+% FUNCTION [GLOC, FLAG] = GLOCFUN(T,Y)
+% and must return a vector GLOC corresponding to an approximation to f(t,y)
+% which will be used in the BBDPRE preconditioner module. The case where
+% G is mathematically identical to F is allowed.
+% If a user data structure DATA was specified in CVodeInit, then
+% GLOCFUN must be defined as
+% FUNCTION [GLOC, FLAG, NEW_DATA] = GLOCFUN(T,Y,DATA)
+% If the local modifications to the user data structure are needed
+% in other user-provided functions then, besides setting the vector G,
+% the GLOCFUN function must also set NEW_DATA. Otherwise, it should set
+% NEW_DATA=[] (do not set NEW_DATA = DATA as it would lead to
+% unnecessary copying).
+%
+% The function GLOCFUN must set FLAG=0 if successful, FLAG<0 if an
+% unrecoverable failure occurred, or FLAG>0 if a recoverable error
+% occurred.
+%
+% See also CVGcommFn, CVodeSetOptions
+%
+% NOTE: GLOCFUN is specified through the GlocalFn property in CVodeSetOptions
+% and is used only if the property PrecModule is set to 'BBDPre'.
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2005, The Regents of the University of California.
+% $Revision: 1.2 $Date: 2011/06/01 20:44:05 $
diff --git a/sundialsTB/cvodes/function_types/CVGlocalFnB.m b/sundialsTB/cvodes/function_types/CVGlocalFnB.m
new file mode 100644
index 0000000..c3a74ca
--- /dev/null
+++ b/sundialsTB/cvodes/function_types/CVGlocalFnB.m
@@ -0,0 +1,22 @@
+%CVGlocalFnB - type for user provided RHS approximation function (BBDPre) for backward problems.
+%
+% The function GLOCFUNB must be defined either as
+% FUNCTION [GLOCB, FLAG] = GLOCFUNB(T,Y,YB)
+% or as
+% FUNCTION [GLOCB, FLAG, NEW_DATA] = GLOCFUNB(T,Y,YB,DATA)
+% depending on whether a user data structure DATA was specified in
+% CVodeInit. In either case, it must return the vector GLOCB
+% corresponding to an approximation to fB(t,y,yB).
+%
+% The function GLOCFUNB must set FLAG=0 if successful, FLAG<0 if an
+% unrecoverable failure occurred, or FLAG>0 if a recoverable error
+% occurred.
+%
+% See also CVGcommFnB, CVodeSetOptions
+%
+% NOTE: GLOCFUNB is specified through the GlocalFn property in CVodeSetOptions
+% and is used only if the property PrecModule is set to 'BBDPre'.
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2005, The Regents of the University of California.
+% $Revision: 1.2 $Date: 2011/06/01 20:44:05 $
diff --git a/sundialsTB/cvodes/function_types/CVJacTimesVecFn.m b/sundialsTB/cvodes/function_types/CVJacTimesVecFn.m
new file mode 100644
index 0000000..94c9a1e
--- /dev/null
+++ b/sundialsTB/cvodes/function_types/CVJacTimesVecFn.m
@@ -0,0 +1,28 @@
+%CVJacTimesVecFn - type for user provided Jacobian times vector function.
+%
+% The function JTVFUN must be defined as
+% FUNCTION [JV, FLAG] = JTVFUN(T,Y,FY,V)
+% and must return a vector JV corresponding to the product of the
+% Jacobian of f(t,y) with the vector v.
+% The input argument FY contains the current value of f(t,y).
+% If a user data structure DATA was specified in CVodeInit, then
+% JTVFUN must be defined as
+% FUNCTION [JV, FLAG, NEW_DATA] = JTVFUN(T,Y,FY,V,DATA)
+% If the local modifications to the user data structure are needed in
+% other user-provided functions then, besides setting the vector JV,
+% the JTVFUN function must also set NEW_DATA. Otherwise, it should set
+% NEW_DATA=[] (do not set NEW_DATA = DATA as it would lead to
+% unnecessary copying).
+%
+% The function JTVFUN must set FLAG=0 if successful, or FLAG~=0 if
+% a failure occurred.
+%
+% See also CVodeSetOptions
+%
+% NOTE: JTVFUN is specified through the property JacobianFn to
+% CVodeSetOptions and is used only if the property LinearSolver
+% was set to 'GMRES', 'BiCGStab', or 'TFQMR'.
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2005, The Regents of the University of California.
+% $Revision: 1.2 $Date: 2011/06/01 20:44:05 $
diff --git a/sundialsTB/cvodes/function_types/CVJacTimesVecFnB.m b/sundialsTB/cvodes/function_types/CVJacTimesVecFnB.m
new file mode 100644
index 0000000..a1bd075
--- /dev/null
+++ b/sundialsTB/cvodes/function_types/CVJacTimesVecFnB.m
@@ -0,0 +1,23 @@
+%CVJacTimesVecFnB - type for user provided Jacobian times vector function for backward problems.
+%
+% The function JTVFUNB must be defined either as
+% FUNCTION [JVB, FLAG] = JTVFUNB(T,Y,YB,FYB,VB)
+% or as
+% FUNCTION [JVB, FLAG, NEW_DATA] = JTVFUNB(T,Y,YB,FYB,VB,DATA)
+% depending on whether a user data structure DATA was specified in
+% CVodeInit. In either case, it must return the vector JVB, the
+% product of the Jacobian of fB(t,y,yB) with respect to yB and a vector
+% vB. The input argument FYB contains the current value of f(t,y,yB).
+%
+% The function JTVFUNB must set FLAG=0 if successful, or FLAG~=0 if
+% a failure occurred.
+%
+% See also CVodeSetOptions
+%
+% NOTE: JTVFUNB is specified through the property JacobianFn to
+% CVodeSetOptions and is used only if the property LinearSolver
+% was set to 'GMRES', 'BiCGStab', or 'TFQMR'.
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2005, The Regents of the University of California.
+% $Revision: 1.2 $Date: 2011/06/01 20:44:05 $
diff --git a/sundialsTB/cvodes/function_types/CVMonitorFn.m b/sundialsTB/cvodes/function_types/CVMonitorFn.m
new file mode 100644
index 0000000..aaf9b30
--- /dev/null
+++ b/sundialsTB/cvodes/function_types/CVMonitorFn.m
@@ -0,0 +1,37 @@
+%CVMonitorFn - type for user provided monitoring function for forward problems.
+%
+% The function MONFUN must be defined as
+% FUNCTION [] = MONFUN(CALL, T, Y, YQ, YS)
+% It is called after every internal CVode step and can be used to
+% monitor the progress of the solver. MONFUN is called with CALL=0
+% from CVodeInit at which time it should initialize itself and it
+% is called with CALL=2 from CVodeFree. Otherwise, CALL=1.
+%
+% It receives as arguments the current time T, solution vector Y,
+% and, if they were computed, quadrature vector YQ, and forward
+% sensitivity matrix YS. If YQ and/or YS were not computed they
+% are empty here.
+%
+% If additional data is needed inside MONFUN, it must be defined
+% as
+% FUNCTION NEW_MONDATA = MONFUN(CALL, T, Y, YQ, YS, MONDATA)
+% If the local modifications to the user data structure need to be
+% saved (e.g. for future calls to MONFUN), then MONFUN must set
+% NEW_MONDATA. Otherwise, it should set NEW_MONDATA=[]
+% (do not set NEW_MONDATA = DATA as it would lead to unnecessary copying).
+%
+% A sample monitoring function, CVodeMonitor, is provided with CVODES.
+%
+% See also CVodeSetOptions, CVodeMonitor
+%
+% NOTES:
+%
+% MONFUN is specified through the MonitorFn property in CVodeSetOptions.
+% If this property is not set, or if it is empty, MONFUN is not used.
+% MONDATA is specified through the MonitorData property in CVodeSetOptions.
+%
+% See CVodeMonitor for an implementation example.
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2005, The Regents of the University of California.
+% $Revision: 1.1 $Date: 2007/05/11 18:51:33 $
diff --git a/sundialsTB/cvodes/function_types/CVMonitorFnB.m b/sundialsTB/cvodes/function_types/CVMonitorFnB.m
new file mode 100644
index 0000000..8606ec7
--- /dev/null
+++ b/sundialsTB/cvodes/function_types/CVMonitorFnB.m
@@ -0,0 +1,37 @@
+%CVMonitorFnB - type of user provided monitoring function for backward problems.
+%
+% The function MONFUNB must be defined as
+% FUNCTION [] = MONFUNB(CALL, IDXB, T, Y, YQ)
+% It is called after every internal CVodeB step and can be used to
+% monitor the progress of the solver. MONFUNB is called with CALL=0
+% from CVodeInitB at which time it should initialize itself and it
+% is called with CALL=2 from CVodeFree. Otherwise, CALL=1.
+%
+% It receives as arguments the index of the backward problem (as
+% returned by CVodeInitB), the current time T, solution vector Y,
+% and, if it was computed, the quadrature vector YQ. If quadratures
+% were not computed for this backward problem, YQ is empty here.
+%
+% If additional data is needed inside MONFUNB, it must be defined
+% as
+% FUNCTION NEW_MONDATA = MONFUNB(CALL, IDXB, T, Y, YQ, MONDATA)
+% If the local modifications to the user data structure need to be
+% saved (e.g. for future calls to MONFUNB), then MONFUNB must set
+% NEW_MONDATA. Otherwise, it should set NEW_MONDATA=[]
+% (do not set NEW_MONDATA = DATA as it would lead to unnecessary copying).
+%
+% A sample monitoring function, CVodeMonitorB, is provided with CVODES.
+%
+% See also CVodeSetOptions, CVodeMonitorB
+%
+% NOTES:
+%
+% MONFUNB is specified through the MonitorFn property in CVodeSetOptions.
+% If this property is not set, or if it is empty, MONFUNB is not used.
+% MONDATA is specified through the MonitorData property in CVodeSetOptions.
+%
+% See CVodeMonitorB for an implementation example.
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2005, The Regents of the University of California.
+% $Revision: 1.1 $Date: 2007/05/11 18:51:33 $
diff --git a/sundialsTB/cvodes/function_types/CVPrecSetupFn.m b/sundialsTB/cvodes/function_types/CVPrecSetupFn.m
new file mode 100644
index 0000000..d9b6677
--- /dev/null
+++ b/sundialsTB/cvodes/function_types/CVPrecSetupFn.m
@@ -0,0 +1,68 @@
+%CVPrecSetupFn - type for user provided preconditioner setup function.
+%
+% The user-supplied preconditioner setup function PSETFUN and
+% the user-supplied preconditioner solve function PSOLFUN
+% 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 PSETFUN
+% is to do any necessary setup operations.
+%
+% The user-supplied preconditioner setup function PSETFUN
+% is to evaluate and preprocess any Jacobian-related data
+% needed by the preconditioner solve function PSOLFUN.
+% 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 PSOLFUN, but instead will be called
+% only as often as necessary to achieve convergence within the
+% Newton iteration. If the PSOLFUN function needs no
+% preparation, the PSETFUN function need not be provided.
+%
+% For greater efficiency, the PSETFUN 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 JCUR accordingly.
+%
+% Each call to the PSETFUN function is preceded by a call to
+% ODEFUN with the same (t,y) arguments. Thus the PSETFUN
+% function can use any auxiliary data that is computed and
+% saved by the ODEFUN function and made accessible to PSETFUN.
+%
+% The function PSETFUN must be defined as
+% FUNCTION [JCUR, FLAG] = PSETFUN(T,Y,FY,JOK,GAMMA)
+% and must return a logical flag JCUR (true if Jacobian information
+% was recomputed and false if saved data was reused). If PSETFUN
+% was successful, it must return FLAG=0. For a recoverable error (in
+% which case the setup will be retried) it must set FLAG to a positive
+% integer value. If an unrecoverable error occurs, it must set FLAG
+% to a negative value, in which case the integration will be halted.
+% The input argument FY contains the current value of f(t,y).
+% If the input logical flag JOK is false, it means that
+% Jacobian-related data must be recomputed from scratch. If it is true,
+% it means that Jacobian data, if saved from the previous PSETFUN call
+% can be reused (with the current value of GAMMA).
+%
+% If a user data structure DATA was specified in CVodeInit, then
+% PSETFUN must be defined as
+% FUNCTION [JCUR, FLAG, NEW_DATA] = PSETFUN(T,Y,FY,JOK,GAMMA,DATA)
+% If the local modifications to the user data structure are needed in
+% other user-provided functions then, besides setting the flags JCUR
+% and FLAG, the PSETFUN function must also set NEW_DATA. Otherwise, it
+% should set NEW_DATA=[] (do not set NEW_DATA = DATA as it would lead
+% to unnecessary copying).
+%
+% See also CVPrecSolveFn, CVodeSetOptions
+%
+% NOTE: PSETFUN is specified through the property PrecSetupFn to
+% CVodeSetOptions and is used only if the property LinearSolver was
+% set to 'GMRES', 'BiCGStab', or 'TFQMR' and if the property PrecType
+% is not 'None'.
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2005, The Regents of the University of California.
+% $Revision: 1.2 $Date: 2011/06/01 20:44:05 $
diff --git a/sundialsTB/cvodes/function_types/CVPrecSetupFnB.m b/sundialsTB/cvodes/function_types/CVPrecSetupFnB.m
new file mode 100644
index 0000000..aaeaa8b
--- /dev/null
+++ b/sundialsTB/cvodes/function_types/CVPrecSetupFnB.m
@@ -0,0 +1,53 @@
+%CVPrecSetupFnB - type for user provided preconditioner setup function for backward problems.
+%
+% The user-supplied preconditioner setup function PSETFUN and
+% the user-supplied preconditioner solve function PSOLFUN
+% 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 PSETFUN
+% is to do any necessary setup operations.
+%
+% The user-supplied preconditioner setup function PSETFUN
+% is to evaluate and preprocess any Jacobian-related data
+% needed by the preconditioner solve function PSOLFUN.
+% 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 PSOLFUN, but instead will be called
+% only as often as necessary to achieve convergence within the
+% Newton iteration. If the PSOLFUN function needs no
+% preparation, the PSETFUN function need not be provided.
+%
+% For greater efficiency, the PSETFUN 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 JCUR accordingly.
+%
+% Each call to the PSETFUN function is preceded by a call to
+% ODEFUN with the same (t,y) arguments. Thus the PSETFUN
+% function can use any auxiliary data that is computed and
+% saved by the ODEFUN function and made accessible to PSETFUN.
+%
+%
+% The function PSETFUNB must be defined either as
+% FUNCTION [JCURB, FLAG] = PSETFUNB(T,Y,YB,FYB,JOK,GAMMAB)
+% or as
+% FUNCTION [JCURB, FLAG, NEW_DATA] = PSETFUNB(T,Y,YB,FYB,JOK,GAMMAB,DATA)
+% depending on whether a user data structure DATA was specified in
+% CVodeInit. In either case, it must return the flags JCURB and FLAG.
+%
+% See also CVPrecSolveFnB, CVodeSetOptions
+%
+% NOTE: PSETFUNB is specified through the property PrecSetupFn to
+% CVodeSetOptions and is used only if the property LinearSolver was
+% set to 'GMRES', 'BiCGStab', or 'TFQMR' and if the property PrecType
+% is not 'None'.
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2005, The Regents of the University of California.
+% $Revision: 1.3 $Date: 2012/03/20 21:08:32 $
diff --git a/sundialsTB/cvodes/function_types/CVPrecSolveFn.m b/sundialsTB/cvodes/function_types/CVPrecSolveFn.m
new file mode 100644
index 0000000..f2285df
--- /dev/null
+++ b/sundialsTB/cvodes/function_types/CVPrecSolveFn.m
@@ -0,0 +1,35 @@
+%CVPrecSolveFn - type for user provided preconditioner solve function.
+%
+% The user-supplied preconditioner solve function PSOLFN
+% 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.
+%
+% The function PSOLFUN must be defined as
+% FUNCTION [Z, FLAG] = PSOLFUN(T,Y,FY,R)
+% and must return a vector Z containing the solution of Pz=r.
+% If PSOLFUN was successful, it must return FLAG=0. For a recoverable
+% error (in which case the step will be retried) it must set FLAG to a
+% positive value. If an unrecoverable error occurs, it must set FLAG
+% to a negative value, in which case the integration will be halted.
+% The input argument FY contains the current value of f(t,y).
+%
+% If a user data structure DATA was specified in CVodeInit, then
+% PSOLFUN must be defined as
+% FUNCTION [Z, FLAG, NEW_DATA] = PSOLFUN(T,Y,FY,R,DATA)
+% If the local modifications to the user data structure are needed in
+% other user-provided functions then, besides setting the vector Z and
+% the flag FLAG, the PSOLFUN function must also set NEW_DATA. Otherwise,
+% it should set NEW_DATA=[] (do not set NEW_DATA = DATA as it would
+% lead to unnecessary copying).
+%
+% See also CVPrecSetupFn, CVodeSetOptions
+%
+% NOTE: PSOLFUN is specified through the property PrecSolveFn to
+% CVodeSetOptions and is used only if the property LinearSolver was
+% set to 'GMRES', 'BiCGStab', or 'TFQMR' and if the property PrecType
+% is not 'None'.
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2005, The Regents of the University of California.
+% $Revision: 1.2 $Date: 2011/06/01 20:44:05 $
diff --git a/sundialsTB/cvodes/function_types/CVPrecSolveFnB.m b/sundialsTB/cvodes/function_types/CVPrecSolveFnB.m
new file mode 100644
index 0000000..e10943c
--- /dev/null
+++ b/sundialsTB/cvodes/function_types/CVPrecSolveFnB.m
@@ -0,0 +1,25 @@
+%CVPrecSolveFnB - type for user provided preconditioner solve function for backward problems.
+%
+% The user-supplied preconditioner solve function PSOLFN
+% 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.
+%
+% The function PSOLFUNB must be defined either as
+% FUNCTION [ZB, FLAG] = PSOLFUNB(T,Y,YB,FYB,RB)
+% or as
+% FUNCTION [ZB, FLAG, NEW_DATA] = PSOLFUNB(T,Y,YB,FYB,RB,DATA)
+% depending on whether a user data structure DATA was specified in
+% CVodeInit. In either case, it must return the vector ZB and the
+% flag FLAG.
+%
+% See also CVPrecSetupFnB, CVodeSetOptions
+%
+% NOTE: PSOLFUNB is specified through the property PrecSolveFn to
+% CVodeSetOptions and is used only if the property LinearSolver was
+% set to 'GMRES', 'BiCGStab', or 'TFQMR' and if the property PrecType
+% is not 'None'.
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2005, The Regents of the University of California.
+% $Revision: 1.2 $Date: 2011/06/01 20:44:05 $
diff --git a/sundialsTB/cvodes/function_types/CVQuadRhsFn.m b/sundialsTB/cvodes/function_types/CVQuadRhsFn.m
new file mode 100644
index 0000000..cbe4071
--- /dev/null
+++ b/sundialsTB/cvodes/function_types/CVQuadRhsFn.m
@@ -0,0 +1,24 @@
+%CVQuadRhsFn - type for user provided quadrature RHS function.
+%
+% The function ODEQFUN must be defined as
+% FUNCTION [YQD, FLAG] = ODEQFUN(T,Y)
+% and must return a vector YQD corresponding to fQ(t,y), the integrand
+% for the integral to be evaluated.
+% If a user data structure DATA was specified in CVodeInit, then
+% ODEQFUN must be defined as
+% FUNCTION [YQD, FLAG, NEW_DATA] = ODEQFUN(T,Y,DATA)
+% If the local modifications to the user data structure are needed in
+% other user-provided functions then, besides setting the vector YQD,
+% the ODEQFUN function must also set NEW_DATA. Otherwise, it should set
+% NEW_DATA=[] (do not set NEW_DATA = DATA as it would lead to
+% unnecessary copying).
+%
+% The function ODEQFUN must set FLAG=0 if successful, FLAG<0 if an
+% unrecoverable failure occurred, or FLAG>0 if a recoverable error
+% occurred.
+%
+% See also CVodeQuadInit
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2005, The Regents of the University of California.
+% $Revision: 1.2 $Date: 2011/06/01 20:44:05 $
diff --git a/sundialsTB/cvodes/function_types/CVQuadRhsFnB.m b/sundialsTB/cvodes/function_types/CVQuadRhsFnB.m
new file mode 100644
index 0000000..46cab29
--- /dev/null
+++ b/sundialsTB/cvodes/function_types/CVQuadRhsFnB.m
@@ -0,0 +1,20 @@
+%CVQuadRhsFnB - type for user provided quadrature RHS function for backward problems
+%
+% The function ODEQFUNB must be defined either as
+% FUNCTION [YQBD, FLAG] = ODEQFUNB(T,Y,YB)
+% or as
+% FUNCTION [YQBD, FLAG, NEW_DATA] = ODEQFUNB(T,Y,YB,DATA)
+% depending on whether a user data structure DATA was specified in
+% CVodeInit. In either case, it must return the vector YQBD
+% corresponding to fQB(t,y,yB), the integrand for the integral to be
+% evaluated on the backward phase.
+%
+% The function ODEQFUNB must set FLAG=0 if successful, FLAG<0 if an
+% unrecoverable failure occurred, or FLAG>0 if a recoverable error
+% occurred.
+%
+% See also CVodeQuadInitB
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2005, The Regents of the University of California.
+% $Revision: 1.2 $Date: 2011/06/01 20:44:05 $
diff --git a/sundialsTB/cvodes/function_types/CVRhsFn.m b/sundialsTB/cvodes/function_types/CVRhsFn.m
new file mode 100644
index 0000000..a4e5c37
--- /dev/null
+++ b/sundialsTB/cvodes/function_types/CVRhsFn.m
@@ -0,0 +1,24 @@
+%CVRhsFn - type for user provided RHS function
+%
+% The function ODEFUN must be defined as
+% FUNCTION [YD, FLAG] = ODEFUN(T,Y)
+% and must return a vector YD corresponding to f(t,y).
+% If a user data structure DATA was specified in CVodeInit, then
+% ODEFUN must be defined as
+% FUNCTION [YD, FLAG, NEW_DATA] = ODEFUN(T,Y,DATA)
+% If the local modifications to the user data structure are needed
+% in other user-provided functions then, besides setting the vector YD,
+% the ODEFUN function must also set NEW_DATA. Otherwise, it should set
+% NEW_DATA=[] (do not set NEW_DATA = DATA as it would lead to
+% unnecessary copying).
+%
+% The function ODEFUN must set FLAG=0 if successful, FLAG<0 if an
+% unrecoverable failure occurred, or FLAG>0 if a recoverable error
+% occurred.
+%
+% See also CVodeInit
+%
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2005, The Regents of the University of California.
+% $Revision: 1.2 $Date: 2011/06/01 20:44:05 $
diff --git a/sundialsTB/cvodes/function_types/CVRhsFnB.m b/sundialsTB/cvodes/function_types/CVRhsFnB.m
new file mode 100644
index 0000000..bf3bd74
--- /dev/null
+++ b/sundialsTB/cvodes/function_types/CVRhsFnB.m
@@ -0,0 +1,20 @@
+%CVRhsFnB - type for user provided RHS function for backward problems.
+%
+% The function ODEFUNB must be defined either as
+% FUNCTION [YBD, FLAG] = ODEFUNB(T,Y,YB)
+% or as
+% FUNCTION [YBD, FLAG, NEW_DATA] = ODEFUNB(T,Y,YB,DATA)
+% depending on whether a user data structure DATA was specified in
+% CVodeInit. In either case, it must return the vector YBD
+% corresponding to fB(t,y,yB).
+%
+% The function ODEFUNB must set FLAG=0 if successful, FLAG<0 if an
+% unrecoverable failure occurred, or FLAG>0 if a recoverable error
+% occurred.
+%
+% See also CVodeInitB
+%
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2005, The Regents of the University of California.
+% $Revision: 1.2 $Date: 2011/06/01 20:44:05 $
diff --git a/sundialsTB/cvodes/function_types/CVRootFn.m b/sundialsTB/cvodes/function_types/CVRootFn.m
new file mode 100644
index 0000000..0dda7e6
--- /dev/null
+++ b/sundialsTB/cvodes/function_types/CVRootFn.m
@@ -0,0 +1,26 @@
+%CVRootFn - type for user provided root-finding function.
+%
+% The function ROOTFUN must be defined as
+% FUNCTION [G, FLAG] = ROOTFUN(T,Y)
+% and must return a vector G corresponding to g(t,y).
+% If a user data structure DATA was specified in CVodeInit, then
+% ROOTFUN must be defined as
+% FUNCTION [G, FLAG, NEW_DATA] = ROOTFUN(T,Y,DATA)
+% If the local modifications to the user data structure are needed in
+% other user-provided functions then, besides setting the vector G,
+% the ROOTFUN function must also set NEW_DATA. Otherwise, it should
+% set NEW_DATA=[] (do not set NEW_DATA = DATA as it would lead to
+% unnecessary copying).
+%
+% The function ROOTFUN must set FLAG=0 if successful, or FLAG~=0 if
+% a failure occurred.
+%
+% See also CVodeSetOptions
+%
+% NOTE: ROOTFUN is specified through the RootsFn property in
+% CVodeSetOptions and is used only if the property NumRoots is a
+% positive integer.
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2005, The Regents of the University of California.
+% $Revision: 1.2 $Date: 2011/06/01 20:44:05 $
diff --git a/sundialsTB/cvodes/function_types/CVSensRhsFn.m b/sundialsTB/cvodes/function_types/CVSensRhsFn.m
new file mode 100644
index 0000000..076801e
--- /dev/null
+++ b/sundialsTB/cvodes/function_types/CVSensRhsFn.m
@@ -0,0 +1,26 @@
+%CVSensRhsFn - type for user provided sensitivity RHS function.
+%
+% The function ODESFUN must be defined as
+% FUNCTION [YSD, FLAG] = ODESFUN(T,Y,YD,YS)
+% and must return a matrix YSD corresponding to fS(t,y,yS).
+% If a user data structure DATA was specified in CVodeInit, then
+% ODESFUN must be defined as
+% FUNCTION [YSD, FLAG, NEW_DATA] = ODESFUN(T,Y,YD,YS,DATA)
+% If the local modifications to the user data structure are needed in
+% other user-provided functions then, besides setting the matrix YSD,
+% the ODESFUN function must also set NEW_DATA. Otherwise, it should
+% set NEW_DATA=[] (do not set NEW_DATA = DATA as it would lead to
+% unnecessary copying).
+%
+% The function ODESFUN must set FLAG=0 if successful, FLAG<0 if an
+% unrecoverable failure occurred, or FLAG>0 if a recoverable error
+% occurred.
+%
+% See also CVodeSetFSAOptions
+%
+% NOTE: ODESFUN is specified through the property FSARhsFn to
+% CVodeSetFSAOptions.
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2005, The Regents of the University of California.
+% $Revision: 1.2 $Date: 2011/06/01 20:44:05 $
diff --git a/sundialsTB/idas/Contents.m b/sundialsTB/idas/Contents.m
new file mode 100644
index 0000000..2a7c375
--- /dev/null
+++ b/sundialsTB/idas/Contents.m
@@ -0,0 +1,113 @@
+% IDAS, a DAE integrator with sensitivity analysis capabilities
+%
+% The Matlab interface to the SUNDIALS solver IDAS provides access
+% to all functionality of the underlying solver, including IVP simulation
+% and sensitvity analysis (both forward and adjoint).
+%
+% The interface consists of several user-callable functions. In addition,
+% the user must provide several required and optional user-supplied
+% functions which define the problem to be solved. The user-callable
+% functions and the types of user-supplied functions are listed below.
+% For completness, some functions appear more than once.
+%
+% Functions for DAE integration
+%
+% IDASetOptions - create an options structure for IDAS.
+% IDASetQuadOptions - create an options structure for quadrature integration.
+% IDAInit - allocate and initialize memory for IDAS.
+% IDAQuadInit - allocate and initialize memory for quadrature integration.
+% IDAReInit - reinitialize memory for IDAS.
+% IDAQuadReInit - reinitialize memory for quadrature integration.
+% IDACalcIC - compute consistent initial conditions.
+% IDASolve - integrate the DAE problem.
+% IDAGetStats - return statistics for the IDAS solver.
+% IDAGet - extract data from IDAS memory.
+% IDAFree - deallocate memory for the IDAS solver.
+%
+% Functions for forward sensitivity analysis
+%
+% IDASetOptions - create an options structure for an DAE problem.
+% IDAQuadSetOptions - create an options structure for quadrature integration.
+% IDASensSetOptions - create an options structure for FSA.
+% IDAInit - allocate and initialize memory for IDAS.
+% IDAQuadInit - allocate and initialize memory for quadrature integration.
+% IDASensInit - allocate and initialize memory for FSA.
+% IDAReInit - reinitialize memory for IDAS.
+% IDAQuadReInit - reinitialize memory for quadrature integration.
+% IDASensReInit - reinitialize memory for FSA.
+% IDASensToggleOff - temporarily deactivates FSA.
+% IDASetIC - compute consistent initial conditions.
+% IDASolve - integrate the DAE problem.
+% IDAGetStats - return statistics for the IDAS solver.
+% IDAGet - extract data from IDAS memory.
+% IDAFree - deallocate memory for the IDAS solver.
+%
+% Functions for adjoint sensitivity analysis
+%
+% IDASetOptions - create an options structure for an DAE problem.
+% IDAQuadSetOptions - create an options structure for quadrature integration.
+% IDAInit - allocate and initialize memory for the forward problem.
+% IDAQuadInit - allocate and initialize memory for forward quadrature integration.
+% IDAQuadReInit - reinitialize memory for forward quadrature integration.
+% IDAReInit - reinitialize memory for the forward problem.
+% IDAAdjInit - allocate and initialize memory for ASA.
+% IDAInitB - allocate and initialize a backward problem.
+% IDAAdjReInit - reinitialize memory for ASA.
+% IDAReInitB - reinitialize a backward problem.
+% IDASetIC - compute consistent initial conditions.
+% IDASetICb - compute consistent final conditions for backward problem.
+% IDASolve - integrate the forward DAE problem.
+% IDASolveB - integrate the backward problems.
+% IDAGetStats - return statistics for the integration of the forward problem.
+% IDAGetStatsB - return statistics for the integration of a backward problem.
+% IDAGet - extract data from IDAS memory.
+% IDAFree - deallocate memory for the IDAS solver.
+%
+% User-supplied function types for forward problems
+%
+% IDAResFn - DAE residual function
+% IDARootFn - root-finding function
+% IDAQuadRhsFn - quadrature RHS function
+% IDASensResFn - sensitivity DAE residual function
+% IDADenseJacFn - dense Jacobian function
+% IDABandJacFn - banded Jacobian function
+% IDAJacTimesVecFn - Jacobian times vector function
+% IDAPrecSetupFn - preconditioner setup function
+% IDAPrecSolveFn - preconditioner solve function
+% IDAGlocalFn - RHS approximation function (BBDPre)
+% IDAGcomFn - communication function (BBDPre)
+% IDAMonitorFn - monitoring function
+%
+% User-supplied function types for backward problems
+%
+% IDAResFnB - backard DAE residual function
+% IDAQuadRhsFnB - quadrature RHS function
+% IDADenseJacFnB - dense Jacobian function
+% IDABandJacFnB - banded Jacobian function
+% IDAJacTimesVecFnB - Jacobian times vector function
+% IDAPrecSetupFnB - preconditioner setup function
+% IDAPrecSolveFnB - preconditioner solve function
+% IDAGlocalFnB - RHS approximation function (BBDPre)
+% IDAGcomFnB - communication function (BBDPre)
+% IDAMonitorFnB - monitoring function
+%
+% Serial examples provided with the toolbox
+%
+% midasRoberts_dns - chemical kinetics problem (index-1 DAE)
+% midasRoberts_ASAi_dns - ASA for the robertson problem
+% midasBruss_dns - 2D, 2-species, time dependent PDE (index-1 DAE)
+% midasBruss_ASA_dns - ASA for the brusselator example
+% midasHeat2D_bnd - 2D heat problem
+% midasPendI1_dns - simple pendulum example (index-1 DAE)
+% midasPendI2_dns - simple pendulum example (stabilized index-2 DAE)
+% midasSlCrank_dns - slider-crank example (stabilized index-2 DAE)
+% midasSlCrank_FSA_dns - FSA for the slider-crank example
+% midasReInit_dns - integration over solution discontinuities
+%
+% Parallel examples provided with the toolbox
+%
+% N/A
+% Use the mpirun function to run any of the parallel examples
+%
+% See also nvector, putils
+
diff --git a/sundialsTB/idas/IDAAdjInit.m b/sundialsTB/idas/IDAAdjInit.m
new file mode 100644
index 0000000..482069e
--- /dev/null
+++ b/sundialsTB/idas/IDAAdjInit.m
@@ -0,0 +1,23 @@
+function status = IDAAdjInit(steps, interp)
+%IDAAdjInit allocates and initializes memory for ASA with IDAS.
+%
+% Usage: IDAAdjInit(STEPS, INTEPR)
+%
+% STEPS specifies the (maximum) number of integration steps between two
+% consecutive check points.
+% INTERP Specifies the type of interpolation used for estimating the forward
+% solution during the backward integration phase. INTERP should be
+% 'Hermite', indicating cubic Hermite interpolation, or 'Polynomial',
+% indicating variable order polynomial interpolation.
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2005, The Regents of the University of California.
+% $Revision: 1.2 $Date: 2007/12/05 21:58:18 $
+
+mode = 4;
+
+if nargin ~= 2
+ error('Wrong number of input arguments');
+end
+
+status = idm(mode,steps,interp);
diff --git a/sundialsTB/idas/IDAAdjReInit.m b/sundialsTB/idas/IDAAdjReInit.m
new file mode 100644
index 0000000..294e417
--- /dev/null
+++ b/sundialsTB/idas/IDAAdjReInit.m
@@ -0,0 +1,13 @@
+function status = IDAAdjReInit()
+%IDAAdjReInit re-initializes memory for ASA with CVODES.
+%
+% Usage: IDAAdjReInit
+%
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2007, The Regents of the University of California.
+% $Revision: 1.2 $Date: 2007/12/05 21:58:18 $
+
+mode = 14;
+
+status = idm(mode);
diff --git a/sundialsTB/idas/IDACalcIC.m b/sundialsTB/idas/IDACalcIC.m
new file mode 100644
index 0000000..573a1c5
--- /dev/null
+++ b/sundialsTB/idas/IDACalcIC.m
@@ -0,0 +1,73 @@
+function [status, varargout] = IDACalcIC(tout,icmeth)
+%IDACalcIC computes consistent initial conditions
+%
+% Usage: STATUS = IDACalcIC ( TOUT, ICMETH )
+% [STATUS, YY0, YP0] = IDACalcIC ( TOUT, ICMETH )
+%
+% IDACalcIC corrects the guess for initial conditions passed
+% to IDAInit or IDAReInit so that the algebraic constraints
+% are satisfied.
+%
+% The argument TOUT is the first value of t at which a soluton will be
+% requested (from IDASolve). This is needed here to determine the
+% direction of integration and rough scale in the independent variable.
+%
+% If ICMETH is 'FindAlgebraic', then IDACalcIC attempts to compute
+% the algebraic components of y and differential components of y',
+% given the differential components of y.
+% This option requires that the vector id was set through IDASetOptions
+% specifying the differential and algebraic components.
+% If ICMETH is 'FindAll', then IDACalcIC attempts to compute all
+% components of y, given y'. In this case, id is not required.
+%
+% On return, STATUS is one of the following:
+% SUCCESS IDACalcIC was successful. The corrected
+% initial value vectors are in y0 and yp0.
+% IDA_MEM_NULL The argument ida_mem was NULL.
+% IDA_ILL_INPUT One of the input arguments was illegal.
+% See printed message.
+% IDA_LINIT_FAIL The linear solver's init routine failed.
+% IDA_BAD_EWT Some component of the error weight vector
+% is zero (illegal), either for the input
+% value of y0 or a corrected value.
+% IDA_RES_FAIL The user's residual routine returned
+% a non-recoverable error flag.
+% IDA_FIRST_RES_FAIL The user's residual routine returned
+% a recoverable error flag on the first call,
+% but IDACalcIC was unable to recover.
+% IDA_LSETUP_FAIL The linear solver's setup routine had a
+% non-recoverable error.
+% IDA_LSOLVE_FAIL The linear solver's solve routine had a
+% non-recoverable error.
+% IDA_NO_RECOVERY The user's residual routine, or the linear
+% solver's setup or solve routine had a
+% recoverable error, but IDACalcIC was
+% unable to recover.
+% IDA_CONSTR_FAIL IDACalcIC was unable to find a solution
+% satisfying the inequality constraints.
+% IDA_LINESEARCH_FAIL The Linesearch algorithm failed to find a
+% solution with a step larger than steptol
+% in weighted RMS norm.
+% IDA_CONV_FAIL IDACalcIC failed to get convergence of the
+% Newton iterations.
+%
+% If the output arguments YY0 and YP0 are present, they will
+% contain the consistent initial conditions.
+%
+% See also: IDASetOptions, IDAInit, IDAReInit
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2005, The Regents of the University of California.
+% $Revision: 1.3 $Date: 2007/08/21 17:38:42 $
+
+mode = 25;
+
+if nargout == 1
+ status = idm(mode, tout, icmeth);
+elseif nargout == 3
+ [status, yy, yp] = idm(mode, tout, icmeth);
+ varargout(1) = {yy};
+ varargout(2) = {yp};
+else
+ disp('IDACalcIC:: wrong number of output arguments');
+end
diff --git a/sundialsTB/idas/IDACalcICB.m b/sundialsTB/idas/IDACalcICB.m
new file mode 100644
index 0000000..ca26b4b
--- /dev/null
+++ b/sundialsTB/idas/IDACalcICB.m
@@ -0,0 +1,23 @@
+function [status, varargout] = IDACalcICB(tout,icmeth)
+%IDACalcICB computes consistent initial conditions for the backward phase.
+%
+% Usage: STATUS = IDACalcICB ( TOUTB, ICMETHB )
+% [STATUS, YY0B, YP0B] = IDACalcIC ( TOUTB, ICMETHB )
+%
+% See also: IDASetOptions, IDAInitB, IDAReInitB
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2005, The Regents of the University of California.
+% $Revision: 1.4 $Date: 2011/05/26 00:05:36 $
+
+mode = 26;
+
+if nargout == 1
+ status = idm(mode, tout, icmeth);
+elseif nargout == 3
+ [status, yy, yp] = idm(mode, tout, icmeth);
+ varargout(1) = {yy};
+ varargout(2) = {yp};
+else
+ disp('IDACalcICB:: wrong number of output arguments');
+end
diff --git a/sundialsTB/idas/IDAFree.m b/sundialsTB/idas/IDAFree.m
new file mode 100644
index 0000000..aee3cf4
--- /dev/null
+++ b/sundialsTB/idas/IDAFree.m
@@ -0,0 +1,11 @@
+function [] = IDAFree()
+%IDAFree deallocates memory for the IDAS solver.
+%
+% Usage: IDAFree
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2007, The Regents of the University of California.
+% $Revision: 1.3 $Date: 2007/08/21 17:38:42 $
+
+mode = 40;
+idm(mode);
diff --git a/sundialsTB/idas/IDAGet.m b/sundialsTB/idas/IDAGet.m
new file mode 100644
index 0000000..50cfd26
--- /dev/null
+++ b/sundialsTB/idas/IDAGet.m
@@ -0,0 +1,36 @@
+function [output, status] = IDAGet(key, varargin)
+%IDAGet extracts data from the IDAS solver memory.
+%
+% Usage: RET = IDAGet ( KEY [, P1 [, P2] ... ])
+%
+% IDAGet returns internal IDAS information based on KEY. For some values
+% of KEY, additional arguments may be required and/or more than one output is
+% returned.
+%
+% KEY is a string and should be one of:
+% o DerivSolution - Returns a vector containing the K-th order derivative
+% of the solution at time T. The time T and order K must be passed through
+% the input arguments P1 and P2, respectively:
+% DKY = IDAGet('DerivSolution', T, K)
+% o ErrorWeights - Returns a vector containing the current error weights.
+% EWT = IDAGet('ErrorWeights')
+% o CheckPointsInfo - Returns an array of structures with check point information.
+% CK = IDAGet('CheckPointInfo)
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2005, The Regents of the University of California.
+% $Revision: 1.4 $Date: 2007/12/05 21:58:18 $
+
+mode = 32;
+
+if strcmp(key, 'DerivSolution')
+ t = varargin{1};
+ k = varargin{2};
+ [output, status] = idm(mode,1,t,k);
+elseif strcmp(key, 'ErrorWeights')
+ [output, status] = idm(mode,2);
+elseif strcmp(key, 'CheckPointsInfo')
+ [output, status] = idm(mode,4);
+else
+ error('IDAGet:: Unrecognized key');
+end
\ No newline at end of file
diff --git a/sundialsTB/idas/IDAGetStats.m b/sundialsTB/idas/IDAGetStats.m
new file mode 100644
index 0000000..6892ba7
--- /dev/null
+++ b/sundialsTB/idas/IDAGetStats.m
@@ -0,0 +1,80 @@
+function [si, status] = IDAGetStats()
+%IDAGetStats returns run statistics for the IDAS solver.
+%
+% Usage: STATS = IDAGetStats
+%
+%Fields in the structure STATS
+%
+%o nst - number of integration steps
+%o nre - number of residual function evaluations
+%o nsetups - number of linear solver setup calls
+%o netf - number of error test failures
+%o nni - number of nonlinear solver iterations
+%o ncfn - number of convergence test failures
+%o qlast - last method order used
+%o qcur - current method order
+%o h0used - actual initial step size used
+%o hlast - last step size used
+%o hcur - current step size
+%o tcur - current time reached by the integrator
+%o RootInfo - strucutre with rootfinding information
+%o QuadInfo - structure with quadrature integration statistics
+%o LSInfo - structure with linear solver statistics
+%o FSAInfo - structure with forward sensitivity solver statistics
+%
+%If rootfinding was requested, the structure RootInfo has the following fields
+%
+%o nge - number of calls to the rootfinding function
+%o roots - array of integers (a value of 1 in the i-th component means that the
+% i-th rootfinding function has a root (upon a return with status=2 from
+% IDASolve).
+%
+%If quadratures were present, the structure QuadInfo has the following fields
+%
+%o nfQe - number of quadrature integrand function evaluations
+%o netfQ - number of error test failures for quadrature variables
+%
+%The structure LSinfo has different fields, depending on the linear solver used.
+%
+% Fields in LSinfo for the 'Dense' linear solver
+%
+%o name - 'Dense'
+%o njeD - number of Jacobian evaluations
+%o nreD - number of residual function evaluations for difference-quotient
+% Jacobian approximation
+%
+% Fields in LSinfo for the 'Band' linear solver
+%
+%o name - 'Band'
+%o njeB - number of Jacobian evaluations
+%o nreB - number of residual function evaluations for difference-quotient
+% Jacobian approximation
+%
+% Fields in LSinfo for the 'GMRES' and 'BiCGStab' linear solvers
+%
+%o name - 'GMRES' or 'BiCGStab'
+%o nli - number of linear solver iterations
+%o npe - number of preconditioner setups
+%o nps - number of preconditioner solve function calls
+%o ncfl - number of linear system convergence test failures
+%o njeSG - number of Jacobian-vector product evaluations
+%o nreSG - number of residual function evaluations for difference-quotient
+% Jacobian-vector product approximation
+%
+%If forward sensitivities were computed, the structure FSAInfo has the
+%following fields
+%
+%o nrSe - number of sensitivity residual evaluations
+%o nreS - number of residual evaluations for difference-quotient
+% sensitivity residual approximation
+%o nsetupsS - number of linear solver setups triggered by sensitivity variables
+%o netfS - number of error test failures for sensitivity variables
+%o nniS - number of nonlinear solver iterations for sensitivity variables
+%o ncfnS - number of convergence test failures due to sensitivity variables
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2005, The Regents of the University of California.
+% $Revision: 1.3 $Date: 2007/12/05 21:58:18 $
+
+mode = 30;
+[si, status] = idm(mode);
diff --git a/sundialsTB/idas/IDAGetStatsB.m b/sundialsTB/idas/IDAGetStatsB.m
new file mode 100644
index 0000000..4a9cc7c
--- /dev/null
+++ b/sundialsTB/idas/IDAGetStatsB.m
@@ -0,0 +1,66 @@
+function [si, status] = IDAGetStatsB(idxB)
+%IDAGetStatsB returns run statistics for the backward IDAS solver.
+%
+% Usage: STATS = IDAGetStatsB(IDXB)
+%
+% IDXB is the index of the backward problem, returned by IDAInitB.
+%
+%Fields in the structure STATS
+%
+%o nst - number of integration steps
+%o nre - number of residual function evaluations
+%o nsetups - number of linear solver setup calls
+%o netf - number of error test failures
+%o nni - number of nonlinear solver iterations
+%o ncfn - number of convergence test failures
+%o qlast - last method order used
+%o qcur - current method order
+%o h0used - actual initial step size used
+%o hlast - last step size used
+%o hcur - current step size
+%o tcur - current time reached by the integrator
+%o QuadInfo - structure with quadrature integration statistics
+%o LSInfo - structure with linear solver statistics
+%
+%The structure LSinfo has different fields, depending on the linear solver used.
+%
+%If quadratures were present, the structure QuadInfo has the following fields
+%
+%o nfQe - number of quadrature integrand function evaluations
+%o netfQ - number of error test failures for quadrature variables
+%
+% Fields in LSinfo for the 'Dense' linear solver
+%
+%o name - 'Dense'
+%o njeD - number of Jacobian evaluations
+%o nreD - number of residual function evaluations for difference-quotient
+% Jacobian approximation
+%
+% Fields in LSinfo for the 'Band' linear solver
+%
+%o name - 'Band'
+%o njeB - number of Jacobian evaluations
+%o nreB - number of residual function evaluations for difference-quotient
+% Jacobian approximation
+%
+% Fields in LSinfo for the 'GMRES' and 'BiCGStab' linear solvers
+%
+%o name - 'GMRES' or 'BiCGStab'
+%o nli - number of linear solver iterations
+%o npe - number of preconditioner setups
+%o nps - number of preconditioner solve function calls
+%o ncfl - number of linear system convergence test failures
+%o njeSG - number of Jacobian-vector product evaluations
+%o nreSG - number of residual function evaluations for difference-quotient
+% Jacobian-vector product approximation
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2005, The Regents of the University of California.
+% $Revision: 1.4 $Date: 2007/12/05 21:58:18 $
+
+mode = 31;
+
+if nargin ~= 1
+ error('Wrong number of input arguments');
+end
+[si, status] = idm(mode, idxB-1);
diff --git a/sundialsTB/idas/IDAInit.m b/sundialsTB/idas/IDAInit.m
new file mode 100644
index 0000000..b90b6a1
--- /dev/null
+++ b/sundialsTB/idas/IDAInit.m
@@ -0,0 +1,31 @@
+function status = IDAInit(fct,t0,yy0,yp0,options)
+%IDAInit allocates and initializes memory for IDAS.
+%
+% Usage: IDAInit ( DAEFUN, T0, YY0, YP0 [, OPTIONS ] )
+%
+% DAEFUN is a function defining the DAE residual: f(t,yy,yp).
+% This function must return a vector containing the current
+% value of the residual.
+% T0 is the initial value of t.
+% YY0 is the initial condition vector y(t0).
+% YP0 is the initial condition vector y'(t0).
+% OPTIONS is an (optional) set of integration options, created with
+% the IDASetOptions function.
+%
+% See also: IDASetOptions, IDAResFn
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2007, The Regents of the University of California.
+% $Revision: 1.3 $Date: 2011/05/26 00:05:36 $
+
+mode = 1;
+
+if nargin < 4
+ error('Too few input arguments');
+end
+
+if nargin < 5
+ options = [];
+end
+
+status = idm(mode, fct, t0, yy0, yp0, options);
diff --git a/sundialsTB/idas/IDAInitB.m b/sundialsTB/idas/IDAInitB.m
new file mode 100644
index 0000000..01d6373
--- /dev/null
+++ b/sundialsTB/idas/IDAInitB.m
@@ -0,0 +1,37 @@
+function [idxB, status] = IDAInitB(fctB, tB0, yyB0, ypB0, optionsB)
+%IDAInitB allocates and initializes backward memory for CVODES.
+%
+% Usage: IDXB = IDAInitB ( DAEFUNB, TB0, YYB0, YPB0 [, OPTIONSB] )
+%
+% DAEFUNB is a function defining the adjoint DAE: F(t,y,y',yB,yB')=0
+% This function must return a vector containing the current
+% value of the adjoint DAE residual.
+% TB0 is the final value of t.
+% YYB0 is the final condition vector yB(tB0).
+% YPB0 is the final condition vector yB'(tB0).
+% OPTIONSB is an (optional) set of integration options, created with
+% the IDASetOptions function.
+%
+% IDAInitB returns the index IDXB associated with this backward
+% problem. This index must be passed as an argument to any subsequent
+% functions related to this backward problem.
+%
+% See also: IDASetOptions, IDAResFnB
+%
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2007, The Regents of the University of California.
+% $Revision: 1.2 $Date: 2007/12/05 21:58:18 $
+
+mode = 5;
+
+if nargin < 4
+ error('Too few input arguments');
+end
+
+if nargin < 5
+ optionsB = [];
+end
+
+[idxB, status] = idm(mode, fctB, tB0, yyB0, ypB0, optionsB);
+idxB = idxB+1;
diff --git a/sundialsTB/idas/IDAMonitor.m b/sundialsTB/idas/IDAMonitor.m
new file mode 100644
index 0000000..d1908b1
--- /dev/null
+++ b/sundialsTB/idas/IDAMonitor.m
@@ -0,0 +1,796 @@
+function [new_data] = IDAMonitor(call, T, Y, YQ, YS, data)
+%IDAMonitor is the default IDAS monitoring function.
+% To use it, set the Monitor property in IDASetOptions to
+% 'IDAMonitor' or to @IDAMonitor and 'MonitorData' to mondata
+% (defined as a structure).
+%
+% With default settings, this function plots the evolution of the step
+% size, method order, and various counters.
+%
+% Various properties can be changed from their default values by passing
+% to IDASetOptions, through the property 'MonitorData', a structure
+% MONDATA with any of the following fields. If a field is not defined,
+% the corresponding default value is used.
+%
+% Fields in MONDATA structure:
+% o stats [ {true} | false ]
+% If true, report the evolution of the step size and method order.
+% o cntr [ {true} | false ]
+% If true, report the evolution of the following counters:
+% nst, nfe, nni, netf, ncfn (see IDAGetStats)
+% o mode [ {'graphical'} | 'text' | 'both' ]
+% In graphical mode, plot the evolutions of the above quantities.
+% In text mode, print a table.
+% o sol [ true | {false} ]
+% If true, plot solution components.
+% o sensi [ true | {false} ]
+% If true and if FSA is enabled, plot sensitivity components.
+% o select [ array of integers ]
+% To plot only particular solution components, specify their indeces in
+% the field select. If not defined, but sol=true, all components are plotted.
+% o updt [ integer | {50} ]
+% Update frequency. Data is posted in blocks of dimension n.
+% o skip [ integer | {0} ]
+% Number of integrations steps to skip in collecting data to post.
+% o post [ {true} | false ]
+% If false, disable all posting. This option is necessary to disable
+% monitoring on some processors when running in parallel.
+%
+% See also IDASetOptions, IDAMonitorFn
+%
+% NOTES:
+% 1. The argument mondata is REQUIRED. Even if only the default options
+% are desired, set mondata=struct; and pass it to IDASetOptions.
+% 2. The yQ argument is currently ignored.
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2007, The Regents of the University of California.
+% $Revision: 1.4 $Date: 2009/04/22 04:25:06 $
+
+if (nargin ~= 6)
+ error('Monitor data not defined.');
+end
+
+new_data = [];
+
+if call == 0
+
+% Initialize unspecified fields to default values.
+ data = initialize_data(data);
+
+% Open figure windows
+ if data.post
+
+ if data.grph
+ if data.stats | data.cntr
+ data.hfg = figure;
+ end
+% Number of subplots in figure hfg
+ if data.stats
+ data.npg = data.npg + 2;
+ end
+ if data.cntr
+ data.npg = data.npg + 1;
+ end
+ end
+
+ if data.text
+ if data.cntr | data.stats
+ data.hft = figure;
+ end
+ end
+
+ if data.sol | data.sensi
+ data.hfs = figure;
+ end
+
+ end
+
+% Initialize other private data
+ data.i = 0;
+ data.n = 1;
+ data.t = zeros(1,data.updt);
+ if data.stats
+ data.h = zeros(1,data.updt);
+ data.q = zeros(1,data.updt);
+ end
+ if data.cntr
+ data.nst = zeros(1,data.updt);
+ data.nfe = zeros(1,data.updt);
+ data.nni = zeros(1,data.updt);
+ data.netf = zeros(1,data.updt);
+ data.ncfn = zeros(1,data.updt);
+ end
+
+ data.first = true; % the next one will be the first call = 1
+ data.initialized = false; % the graphical windows were not initalized
+
+ new_data = data;
+
+ return;
+
+else
+
+% If this is the first call ~= 0,
+% use Y and YS for additional initializations
+
+ if data.first
+
+ if isempty(YS)
+ data.sensi = false;
+ end
+
+ if data.sol | data.sensi
+
+ if isempty(data.select)
+
+ data.N = length(Y);
+ data.select = [1:data.N];
+
+ else
+
+ data.N = length(data.select);
+
+ end
+
+ if data.sol
+ data.y = zeros(data.N,data.updt);
+ data.nps = data.nps + 1;
+ end
+
+ if data.sensi
+ data.Ns = size(YS,2);
+ data.ys = zeros(data.N, data.Ns, data.updt);
+ data.nps = data.nps + data.Ns;
+ end
+
+ end
+
+ data.first = false;
+
+ end
+
+% Extract variables from data
+
+ hfg = data.hfg;
+ hft = data.hft;
+ hfs = data.hfs;
+ npg = data.npg;
+ nps = data.nps;
+ i = data.i;
+ n = data.n;
+ t = data.t;
+ N = data.N;
+ Ns = data.Ns;
+ y = data.y;
+ ys = data.ys;
+ h = data.h;
+ q = data.q;
+ nst = data.nst;
+ nfe = data.nfe;
+ nni = data.nni;
+ netf = data.netf;
+ ncfn = data.ncfn;
+
+end
+
+
+% Load current statistics?
+
+if call == 1
+
+ if i ~= 0
+ i = i-1;
+ data.i = i;
+ new_data = data;
+ return;
+ end
+
+ si = IDAGetStats;
+
+ t(n) = si.tcur;
+
+ if data.stats
+ h(n) = si.hlast;
+ q(n) = si.qlast;
+ end
+
+ if data.cntr
+ nst(n) = si.nst;
+ nfe(n) = si.nfe;
+ nni(n) = si.nni;
+ netf(n) = si.netf;
+ ncfn(n) = si.ncfn;
+ end
+
+ if data.sol
+ for j = 1:N
+ y(j,n) = Y(data.select(j));
+ end
+ end
+
+ if data.sensi
+ for k = 1:Ns
+ for j = 1:N
+ ys(j,k,n) = YS(data.select(j),k);
+ end
+ end
+ end
+
+end
+
+% Is it time to post?
+
+if data.post & (n == data.updt | call==2)
+
+ if call == 2
+ n = n-1;
+ end
+
+ if ~data.initialized
+
+ if (data.stats | data.cntr) & data.grph
+ graphical_init(n, hfg, npg, data.stats, data.cntr, ...
+ t, h, q, nst, nfe, nni, netf, ncfn);
+ end
+
+ if (data.stats | data.cntr) & data.text
+ text_init(n, hft, data.stats, data.cntr, ...
+ t, h, q, nst, nfe, nni, netf, ncfn);
+ end
+
+ if data.sol | data.sensi
+ sol_init(n, hfs, nps, data.sol, data.sensi, ...
+ N, Ns, t, y, ys);
+ end
+
+ data.initialized = true;
+
+ else
+
+ if (data.stats | data.cntr) & data.grph
+ graphical_update(n, hfg, npg, data.stats, data.cntr, ...
+ t, h, q, nst, nfe, nni, netf, ncfn);
+ end
+
+ if (data.stats | data.cntr) & data.text
+ text_update(n, hft, data.stats, data.cntr, ...
+ t, h, q, nst, nfe, nni, netf, ncfn);
+ end
+
+ if data.sol
+ sol_update(n, hfs, nps, data.sol, data.sensi, N, Ns, t, y, ys);
+ end
+
+ end
+
+ if call == 2
+
+ if (data.stats | data.cntr) & data.grph
+ graphical_final(hfg, npg, data.cntr, data.stats);
+ end
+
+ if data.sol | data.sensi
+ sol_final(hfs, nps, data.sol, data.sensi, N, Ns);
+ end
+
+ return;
+
+ end
+
+ n = 1;
+
+else
+
+ n = n + 1;
+
+end
+
+
+% Save updated values in data
+
+data.i = data.skip;
+data.n = n;
+data.npg = npg;
+data.t = t;
+data.y = y;
+data.ys = ys;
+data.h = h;
+data.q = q;
+data.nst = nst;
+data.nfe = nfe;
+data.nni = nni;
+data.netf = netf;
+data.ncfn = ncfn;
+
+new_data = data;
+
+return;
+
+%-------------------------------------------------------------------------
+
+function data = initialize_data(data)
+
+if ~isfield(data,'mode')
+ data.mode = 'graphical';
+end
+if ~isfield(data,'updt')
+ data.updt = 50;
+end
+if ~isfield(data,'skip')
+ data.skip = 0;
+end
+if ~isfield(data,'stats')
+ data.stats = true;
+end
+if ~isfield(data,'cntr')
+ data.cntr = true;
+end
+if ~isfield(data,'sol')
+ data.sol = false;
+end
+if ~isfield(data,'sensi')
+ data.sensi = false;
+end
+if ~isfield(data,'select')
+ data.select = [];
+end
+if ~isfield(data,'post')
+ data.post = true;
+end
+
+data.grph = true;
+data.text = true;
+if strcmp(data.mode,'graphical')
+ data.text = false;
+end
+if strcmp(data.mode,'text')
+ data.grph = false;
+end
+
+if ~data.sol & ~data.sensi
+ data.select = [];
+end
+
+% Other initializations
+data.npg = 0;
+data.nps = 0;
+data.hfg = 0;
+data.hft = 0;
+data.hfs = 0;
+data.h = 0;
+data.q = 0;
+data.nst = 0;
+data.nfe = 0;
+data.nni = 0;
+data.netf = 0;
+data.ncfn = 0;
+data.N = 0;
+data.Ns = 0;
+data.y = 0;
+data.ys = 0;
+
+%-------------------------------------------------------------------------
+
+function [] = graphical_init(n, hfg, npg, stats, cntr, ...
+ t, h, q, nst, nfe, nni, netf, ncfn)
+
+fig_name = 'IDAS run statistics';
+
+% If this is a parallel job, look for the MPI rank in the global
+% workspace and append it to the figure name
+
+global sundials_MPI_rank
+
+if ~isempty(sundials_MPI_rank)
+ fig_name = sprintf('%s (PE %d)',fig_name,sundials_MPI_rank);
+end
+
+figure(hfg);
+set(hfg,'Name',fig_name);
+set(hfg,'color',[1 1 1]);
+pl = 0;
+
+% Time label and figure title
+
+tlab = '\rightarrow t \rightarrow';
+
+% Step size and order
+if stats
+ pl = pl+1;
+ subplot(npg,1,pl)
+ semilogy(t(1:n),abs(h(1:n)),'-');
+ hold on;
+ box on;
+ grid on;
+ xlabel(tlab);
+ ylabel('|Step size|');
+
+ pl = pl+1;
+ subplot(npg,1,pl)
+ plot(t(1:n),q(1:n),'-');
+ hold on;
+ box on;
+ grid on;
+ xlabel(tlab);
+ ylabel('Order');
+end
+
+% Counters
+if cntr
+ pl = pl+1;
+ subplot(npg,1,pl)
+ plot(t(1:n),nst(1:n),'k-');
+ hold on;
+ plot(t(1:n),nfe(1:n),'b-');
+ plot(t(1:n),nni(1:n),'r-');
+ plot(t(1:n),netf(1:n),'g-');
+ plot(t(1:n),ncfn(1:n),'c-');
+ box on;
+ grid on;
+ xlabel(tlab);
+ ylabel('Counters');
+end
+
+drawnow;
+
+%-------------------------------------------------------------------------
+
+function [] = graphical_update(n, hfg, npg, stats, cntr, ...
+ t, h, q, nst, nfe, nni, netf, ncfn)
+
+figure(hfg);
+pl = 0;
+
+% Step size and order
+if stats
+ pl = pl+1;
+ subplot(npg,1,pl)
+ hc = get(gca,'Children');
+ xd = [get(hc,'XData') t(1:n)];
+ yd = [get(hc,'YData') abs(h(1:n))];
+ set(hc, 'XData', xd, 'YData', yd);
+
+ pl = pl+1;
+ subplot(npg,1,pl)
+ hc = get(gca,'Children');
+ xd = [get(hc,'XData') t(1:n)];
+ yd = [get(hc,'YData') q(1:n)];
+ set(hc, 'XData', xd, 'YData', yd);
+end
+
+% Counters
+if cntr
+ pl = pl+1;
+ subplot(npg,1,pl)
+ hc = get(gca,'Children');
+% Attention: Children are loaded in reverse order!
+ xd = [get(hc(1),'XData') t(1:n)];
+ yd = [get(hc(1),'YData') ncfn(1:n)];
+ set(hc(1), 'XData', xd, 'YData', yd);
+ yd = [get(hc(2),'YData') netf(1:n)];
+ set(hc(2), 'XData', xd, 'YData', yd);
+ yd = [get(hc(3),'YData') nni(1:n)];
+ set(hc(3), 'XData', xd, 'YData', yd);
+ yd = [get(hc(4),'YData') nfe(1:n)];
+ set(hc(4), 'XData', xd, 'YData', yd);
+ yd = [get(hc(5),'YData') nst(1:n)];
+ set(hc(5), 'XData', xd, 'YData', yd);
+end
+
+drawnow;
+
+%-------------------------------------------------------------------------
+
+function [] = graphical_final(hfg,npg,stats,cntr)
+
+figure(hfg);
+pl = 0;
+
+if stats
+ pl = pl+1;
+ subplot(npg,1,pl)
+ hc = get(gca,'Children');
+ xd = get(hc,'XData');
+ set(gca,'XLim',sort([xd(1) xd(end)]));
+
+ pl = pl+1;
+ subplot(npg,1,pl)
+ ylim = get(gca,'YLim');
+ ylim(1) = ylim(1) - 1;
+ ylim(2) = ylim(2) + 1;
+ set(gca,'YLim',ylim);
+ set(gca,'XLim',sort([xd(1) xd(end)]));
+end
+
+if cntr
+ pl = pl+1;
+ subplot(npg,1,pl)
+ hc = get(gca,'Children');
+ xd = get(hc(1),'XData');
+ set(gca,'XLim',sort([xd(1) xd(end)]));
+ legend('nst','nfe','nni','netf','ncfn',2);
+end
+
+%-------------------------------------------------------------------------
+
+function [] = text_init(n,hft,stats,cntr,t,h,q,nst,nfe,nni,netf,ncfn)
+
+fig_name = 'IDAS run statistics';
+
+% If this is a parallel job, look for the MPI rank in the global
+% workspace and append it to the figure name
+
+global sundials_MPI_rank
+
+if ~isempty(sundials_MPI_rank)
+ fig_name = sprintf('%s (PE %d)',fig_name,sundials_MPI_rank);
+end
+
+figure(hft);
+set(hft,'Name',fig_name);
+set(hft,'color',[1 1 1]);
+set(hft,'MenuBar','none');
+set(hft,'Resize','off');
+
+% Create text box
+
+margins=[10 10 50 50]; % left, right, top, bottom
+pos=get(hft,'position');
+tbpos=[margins(1) margins(4) pos(3)-margins(1)-margins(2) ...
+ pos(4)-margins(3)-margins(4)];
+tbpos(tbpos<1)=1;
+
+htb=uicontrol(hft,'style','listbox','position',tbpos,'tag','textbox');
+set(htb,'BackgroundColor',[1 1 1]);
+set(htb,'SelectionHighlight','off');
+set(htb,'FontName','courier');
+
+% Create table head
+
+tpos = [tbpos(1) tbpos(2)+tbpos(4)+10 tbpos(3) 20];
+ht=uicontrol(hft,'style','text','position',tpos,'tag','text');
+set(ht,'BackgroundColor',[1 1 1]);
+set(ht,'HorizontalAlignment','left');
+set(ht,'FontName','courier');
+newline = ' time step order | nst nfe nni netf ncfn';
+set(ht,'String',newline);
+
+% Create OK button
+
+bsize=[60,28];
+badjustpos=[0,25];
+bpos=[pos(3)/2-bsize(1)/2+badjustpos(1) -bsize(2)/2+badjustpos(2)...
+ bsize(1) bsize(2)];
+bpos=round(bpos);
+bpos(bpos<1)=1;
+hb=uicontrol(hft,'style','pushbutton','position',bpos,...
+ 'string','Close','tag','okaybutton');
+set(hb,'callback','close');
+
+% Save handles
+
+handles=guihandles(hft);
+guidata(hft,handles);
+
+for i = 1:n
+ newline = '';
+ if stats
+ newline = sprintf('%10.3e %10.3e %1d |',t(i),h(i),q(i));
+ end
+ if cntr
+ newline = sprintf('%s %5d %5d %5d %5d %5d',...
+ newline,nst(i),nfe(i),nni(i),netf(i),ncfn(i));
+ end
+ string = get(handles.textbox,'String');
+ string{end+1}=newline;
+ set(handles.textbox,'String',string);
+end
+
+drawnow
+
+%-------------------------------------------------------------------------
+
+function [] = text_update(n,hft,stats,cntr,t,h,q,nst,nfe,nni,netf,ncfn)
+
+figure(hft);
+
+handles=guidata(hft);
+
+for i = 1:n
+ if stats
+ newline = sprintf('%10.3e %10.3e %1d |',t(i),h(i),q(i));
+ end
+ if cntr
+ newline = sprintf('%s %5d %5d %5d %5d %5d',...
+ newline,nst(i),nfe(i),nni(i),netf(i),ncfn(i));
+ end
+ string = get(handles.textbox,'String');
+ string{end+1}=newline;
+ set(handles.textbox,'String',string);
+end
+
+drawnow
+
+%-------------------------------------------------------------------------
+
+function [] = sol_init(n, hfs, nps, sol, sensi, N, Ns, t, y, ys)
+
+fig_name = 'IDAS solution';
+
+% If this is a parallel job, look for the MPI rank in the global
+% workspace and append it to the figure name
+
+global sundials_MPI_rank
+
+if ~isempty(sundials_MPI_rank)
+ fig_name = sprintf('%s (PE %d)',fig_name,sundials_MPI_rank);
+end
+
+
+figure(hfs);
+set(hfs,'Name',fig_name);
+set(hfs,'color',[1 1 1]);
+
+% Time label
+
+tlab = '\rightarrow t \rightarrow';
+
+% Get number of colors in colormap
+map = colormap;
+ncols = size(map,1);
+
+% Initialize current subplot counter
+pl = 0;
+
+if sol
+
+ pl = pl+1;
+ subplot(nps,1,pl);
+ hold on;
+
+ for i = 1:N
+ hp = plot(t(1:n),y(i,1:n),'-');
+ ic = 1+(i-1)*floor(ncols/N);
+ set(hp,'Color',map(ic,:));
+ end
+ box on;
+ grid on;
+ xlabel(tlab);
+ ylabel('y');
+ title('Solution');
+
+end
+
+if sensi
+
+ for is = 1:Ns
+
+ pl = pl+1;
+ subplot(nps,1,pl);
+ hold on;
+
+ ys_crt = ys(:,is,1:n);
+ for i = 1:N
+ hp = plot(t(1:n),ys_crt(i,1:n),'-');
+ ic = 1+(i-1)*floor(ncols/N);
+ set(hp,'Color',map(ic,:));
+ end
+ box on;
+ grid on;
+ xlabel(tlab);
+ str = sprintf('s_{%d}',is); ylabel(str);
+ str = sprintf('Sensitivity %d',is); title(str);
+
+ end
+
+end
+
+
+drawnow;
+
+%-------------------------------------------------------------------------
+
+function [] = sol_update(n, hfs, nps, sol, sensi, N, Ns, t, y, ys)
+
+figure(hfs);
+
+pl = 0;
+
+if sol
+
+ pl = pl+1;
+ subplot(nps,1,pl);
+
+ hc = get(gca,'Children');
+ xd = [get(hc(1),'XData') t(1:n)];
+% Attention: Children are loaded in reverse order!
+ for i = 1:N
+ yd = [get(hc(i),'YData') y(N-i+1,1:n)];
+ set(hc(i), 'XData', xd, 'YData', yd);
+ end
+
+end
+
+if sensi
+
+ for is = 1:Ns
+
+ pl = pl+1;
+ subplot(nps,1,pl);
+
+ ys_crt = ys(:,is,:);
+
+ hc = get(gca,'Children');
+ xd = [get(hc(1),'XData') t(1:n)];
+% Attention: Children are loaded in reverse order!
+ for i = 1:N
+ yd = [get(hc(i),'YData') ys_crt(N-i+1,1:n)];
+ set(hc(i), 'XData', xd, 'YData', yd);
+ end
+
+ end
+
+end
+
+
+drawnow;
+
+
+%-------------------------------------------------------------------------
+
+function [] = sol_final(hfs, nps, sol, sensi, N, Ns)
+
+figure(hfs);
+
+pl = 0;
+
+if sol
+
+ pl = pl +1;
+ subplot(nps,1,pl);
+
+ hc = get(gca,'Children');
+ xd = get(hc(1),'XData');
+ set(gca,'XLim',sort([xd(1) xd(end)]));
+
+ ylim = get(gca,'YLim');
+ addon = 0.1*abs(ylim(2)-ylim(1));
+ ylim(1) = ylim(1) + sign(ylim(1))*addon;
+ ylim(2) = ylim(2) + sign(ylim(2))*addon;
+ set(gca,'YLim',ylim);
+
+ for i = 1:N
+ cstring{i} = sprintf('y_{%d}',i);
+ end
+ legend(cstring);
+
+end
+
+if sensi
+
+ for is = 1:Ns
+
+ pl = pl+1;
+ subplot(nps,1,pl);
+
+ hc = get(gca,'Children');
+ xd = get(hc(1),'XData');
+ set(gca,'XLim',sort([xd(1) xd(end)]));
+
+ ylim = get(gca,'YLim');
+ addon = 0.1*abs(ylim(2)-ylim(1));
+ ylim(1) = ylim(1) + sign(ylim(1))*addon;
+ ylim(2) = ylim(2) + sign(ylim(2))*addon;
+ set(gca,'YLim',ylim);
+
+ for i = 1:N
+ cstring{i} = sprintf('s%d_{%d}',is,i);
+ end
+ legend(cstring);
+
+ end
+
+end
+
+drawnow
diff --git a/sundialsTB/idas/IDAMonitorB.m b/sundialsTB/idas/IDAMonitorB.m
new file mode 100644
index 0000000..776a540
--- /dev/null
+++ b/sundialsTB/idas/IDAMonitorB.m
@@ -0,0 +1,697 @@
+function [new_data] = IDAMonitorB(call, idxB, T, Y, YQ, data)
+%IDAMonitorB is the default IDAS monitoring function for backward problems.
+% To use it, set the Monitor property in IDASetOptions to
+% 'IDAMonitorB' or to @IDAMonitorB and 'MonitorData' to mondata
+% (defined as a structure).
+%
+% With default settings, this function plots the evolution of the step
+% size, method order, and various counters.
+%
+% Various properties can be changed from their default values by passing
+% to IDASetOptions, through the property 'MonitorData', a structure
+% MONDATA with any of the following fields. If a field is not defined,
+% the corresponding default value is used.
+%
+% Fields in MONDATA structure:
+% o stats [ {true} | false ]
+% If true, report the evolution of the step size and method order.
+% o cntr [ {true} | false ]
+% If true, report the evolution of the following counters:
+% nst, nfe, nni, netf, ncfn (see IDAGetStats)
+% o mode [ {'graphical'} | 'text' | 'both' ]
+% In graphical mode, plot the evolutions of the above quantities.
+% In text mode, print a table.
+% o sol [ true | {false} ]
+% If true, plot solution components.
+% o select [ array of integers ]
+% To plot only particular solution components, specify their indeces in
+% the field select. If not defined, but sol=true, all components are plotted.
+% o updt [ integer | {50} ]
+% Update frequency. Data is posted in blocks of dimension n.
+% o skip [ integer | {0} ]
+% Number of integrations steps to skip in collecting data to post.
+% o post [ {true} | false ]
+% If false, disable all posting. This option is necessary to disable
+% monitoring on some processors when running in parallel.
+%
+% See also IDASetOptions, IDAMonitorFnB
+%
+% NOTES:
+% 1. The argument mondata is REQUIRED. Even if only the default options
+% are desired, set mondata=struct; and pass it to IDASetOptions.
+% 2. The yQ argument is currently ignored.
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2007, The Regents of the University of California.
+% $Revision: 1.2 $Date: 2009/04/22 04:25:06 $
+
+
+if (nargin ~= 6)
+ error('Monitor data not defined.');
+end
+
+
+new_data = [];
+
+if call == 0
+
+% Initialize unspecified fields to default values.
+ data = initialize_data(data);
+
+% Open figure windows
+ if data.post
+
+ if data.grph
+ if data.stats | data.cntr
+ data.hfg = figure;
+ end
+% Number of subplots in figure hfg
+ if data.stats
+ data.npg = data.npg + 2;
+ end
+ if data.cntr
+ data.npg = data.npg + 1;
+ end
+ end
+
+ if data.text
+ if data.cntr | data.stats
+ data.hft = figure;
+ end
+ end
+
+ if data.sol
+ data.hfs = figure;
+ end
+
+ end
+
+% Initialize other private data
+ data.i = 0;
+ data.n = 1;
+ data.t = zeros(1,data.updt);
+ if data.stats
+ data.h = zeros(1,data.updt);
+ data.q = zeros(1,data.updt);
+ end
+ if data.cntr
+ data.nst = zeros(1,data.updt);
+ data.nfe = zeros(1,data.updt);
+ data.nni = zeros(1,data.updt);
+ data.netf = zeros(1,data.updt);
+ data.ncfn = zeros(1,data.updt);
+ end
+
+ data.first = true; % the next one will be the first call = 1
+ data.initialized = false; % the graphical windows were not initalized
+
+ new_data = data;
+
+ return;
+
+else
+
+% If this is the first call ~= 0,
+% use Y for additional initializations
+
+ if data.first
+
+ if data.sol
+
+ if isempty(data.select)
+
+ data.N = length(Y);
+ data.select = [1:data.N];
+
+ else
+
+ data.N = length(data.select);
+
+ end
+
+ if data.sol
+ data.y = zeros(data.N,data.updt);
+ data.nps = data.nps + 1;
+ end
+
+ end
+
+ data.first = false;
+
+ end
+
+% Extract variables from data
+
+ hfg = data.hfg;
+ hft = data.hft;
+ hfs = data.hfs;
+ npg = data.npg;
+ nps = data.nps;
+ i = data.i;
+ n = data.n;
+ t = data.t;
+ N = data.N;
+ y = data.y;
+ h = data.h;
+ q = data.q;
+ nst = data.nst;
+ nfe = data.nfe;
+ nni = data.nni;
+ netf = data.netf;
+ ncfn = data.ncfn;
+
+end
+
+
+% Load current statistics?
+
+if call == 1
+
+ if i ~= 0
+ i = i-1;
+ data.i = i;
+ new_data = data;
+ return;
+ end
+
+ si = IDAGetStatsB(idxB);
+
+ t(n) = si.tcur;
+
+ if data.stats
+ h(n) = si.hlast;
+ q(n) = si.qlast;
+ end
+
+ if data.cntr
+ nst(n) = si.nst;
+ nfe(n) = si.nfe;
+ nni(n) = si.nni;
+ netf(n) = si.netf;
+ ncfn(n) = si.ncfn;
+ end
+
+ if data.sol
+ for j = 1:N
+ y(j,n) = Y(data.select(j));
+ end
+ end
+
+end
+
+% Is it time to post?
+
+if data.post & (n == data.updt | call==2)
+
+ if call == 2
+ n = n-1;
+ end
+
+ if ~data.initialized
+
+ if (data.stats | data.cntr) & data.grph
+ graphical_init(n, hfg, npg, data.stats, data.cntr, ...
+ t, h, q, nst, nfe, nni, netf, ncfn);
+ end
+
+ if (data.stats | data.cntr) & data.text
+ text_init(n, hft, data.stats, data.cntr, ...
+ t, h, q, nst, nfe, nni, netf, ncfn);
+ end
+
+ if data.sol
+ sol_init(n, hfs, nps, data.sol, ...
+ N, t, y);
+ end
+
+ data.initialized = true;
+
+ else
+
+ if (data.stats | data.cntr) & data.grph
+ graphical_update(n, hfg, npg, data.stats, data.cntr, ...
+ t, h, q, nst, nfe, nni, netf, ncfn);
+ end
+
+ if (data.stats | data.cntr) & data.text
+ text_update(n, hft, data.stats, data.cntr, ...
+ t, h, q, nst, nfe, nni, netf, ncfn);
+ end
+
+ if data.sol
+ sol_update(n, hfs, nps, data.sol, N, t, y);
+ end
+
+ end
+
+ if call == 2
+
+ if (data.stats | data.cntr) & data.grph
+ graphical_final(hfg, npg, data.cntr, data.stats);
+ end
+
+ if data.sol
+ sol_final(hfs, nps, data.sol, N);
+ end
+
+ return;
+
+ end
+
+ n = 1;
+
+else
+
+ n = n + 1;
+
+end
+
+
+% Save updated values in data
+
+data.i = data.skip;
+data.n = n;
+data.npg = npg;
+data.t = t;
+data.y = y;
+data.h = h;
+data.q = q;
+data.nst = nst;
+data.nfe = nfe;
+data.nni = nni;
+data.netf = netf;
+data.ncfn = ncfn;
+
+new_data = data;
+
+return;
+
+%-------------------------------------------------------------------------
+
+function data = initialize_data(data)
+
+if ~isfield(data,'mode')
+ data.mode = 'graphical';
+end
+if ~isfield(data,'updt')
+ data.updt = 50;
+end
+if ~isfield(data,'skip')
+ data.skip = 0;
+end
+if ~isfield(data,'stats')
+ data.stats = true;
+end
+if ~isfield(data,'cntr')
+ data.cntr = true;
+end
+if ~isfield(data,'sol')
+ data.sol = false;
+end
+if ~isfield(data,'select')
+ data.select = [];
+end
+if ~isfield(data,'post')
+ data.post = true;
+end
+
+data.grph = true;
+data.text = true;
+if strcmp(data.mode,'graphical')
+ data.text = false;
+end
+if strcmp(data.mode,'text')
+ data.grph = false;
+end
+
+if ~data.sol
+ data.select = [];
+end
+
+% Other initializations
+data.npg = 0;
+data.nps = 0;
+data.hfg = 0;
+data.hft = 0;
+data.hfs = 0;
+data.h = 0;
+data.q = 0;
+data.nst = 0;
+data.nfe = 0;
+data.nni = 0;
+data.netf = 0;
+data.ncfn = 0;
+data.N = 0;
+data.y = 0;
+
+%-------------------------------------------------------------------------
+
+function [] = graphical_init(n, hfg, npg, stats, cntr, ...
+ t, h, q, nst, nfe, nni, netf, ncfn)
+
+fig_name = 'IDAS run statistics';
+
+% If this is a parallel job, look for the MPI rank in the global
+% workspace and append it to the figure name
+
+global sundials_MPI_rank
+
+if ~isempty(sundials_MPI_rank)
+ fig_name = sprintf('%s (PE %d)',fig_name,sundials_MPI_rank);
+end
+
+figure(hfg);
+set(hfg,'Name',fig_name);
+set(hfg,'color',[1 1 1]);
+pl = 0;
+
+% Time label and figure title
+
+tlab = '\leftarrow t \leftarrow';
+
+% Step size and order
+if stats
+ pl = pl+1;
+ subplot(npg,1,pl)
+ semilogy(t(1:n),abs(h(1:n)),'-');
+ hold on;
+ box on;
+ grid on;
+ xlabel(tlab);
+ ylabel('|Step size|');
+
+ pl = pl+1;
+ subplot(npg,1,pl)
+ plot(t(1:n),q(1:n),'-');
+ hold on;
+ box on;
+ grid on;
+ xlabel(tlab);
+ ylabel('Order');
+end
+
+% Counters
+if cntr
+ pl = pl+1;
+ subplot(npg,1,pl)
+ plot(t(1:n),nst(1:n),'k-');
+ hold on;
+ plot(t(1:n),nfe(1:n),'b-');
+ plot(t(1:n),nni(1:n),'r-');
+ plot(t(1:n),netf(1:n),'g-');
+ plot(t(1:n),ncfn(1:n),'c-');
+ box on;
+ grid on;
+ xlabel(tlab);
+ ylabel('Counters');
+end
+
+drawnow;
+
+%-------------------------------------------------------------------------
+
+function [] = graphical_update(n, hfg, npg, stats, cntr, ...
+ t, h, q, nst, nfe, nni, netf, ncfn)
+
+figure(hfg);
+pl = 0;
+
+% Step size and order
+if stats
+ pl = pl+1;
+ subplot(npg,1,pl)
+ hc = get(gca,'Children');
+ xd = [get(hc,'XData') t(1:n)];
+ yd = [get(hc,'YData') abs(h(1:n))];
+ set(hc, 'XData', xd, 'YData', yd);
+
+ pl = pl+1;
+ subplot(npg,1,pl)
+ hc = get(gca,'Children');
+ xd = [get(hc,'XData') t(1:n)];
+ yd = [get(hc,'YData') q(1:n)];
+ set(hc, 'XData', xd, 'YData', yd);
+end
+
+% Counters
+if cntr
+ pl = pl+1;
+ subplot(npg,1,pl)
+ hc = get(gca,'Children');
+% Attention: Children are loaded in reverse order!
+ xd = [get(hc(1),'XData') t(1:n)];
+ yd = [get(hc(1),'YData') ncfn(1:n)];
+ set(hc(1), 'XData', xd, 'YData', yd);
+ yd = [get(hc(2),'YData') netf(1:n)];
+ set(hc(2), 'XData', xd, 'YData', yd);
+ yd = [get(hc(3),'YData') nni(1:n)];
+ set(hc(3), 'XData', xd, 'YData', yd);
+ yd = [get(hc(4),'YData') nfe(1:n)];
+ set(hc(4), 'XData', xd, 'YData', yd);
+ yd = [get(hc(5),'YData') nst(1:n)];
+ set(hc(5), 'XData', xd, 'YData', yd);
+end
+
+drawnow;
+
+%-------------------------------------------------------------------------
+
+function [] = graphical_final(hfg,npg,stats,cntr)
+
+figure(hfg);
+pl = 0;
+
+if stats
+ pl = pl+1;
+ subplot(npg,1,pl)
+ hc = get(gca,'Children');
+ xd = get(hc,'XData');
+ set(gca,'XLim',sort([xd(1) xd(end)]));
+
+ pl = pl+1;
+ subplot(npg,1,pl)
+ ylim = get(gca,'YLim');
+ ylim(1) = ylim(1) - 1;
+ ylim(2) = ylim(2) + 1;
+ set(gca,'YLim',ylim);
+ set(gca,'XLim',sort([xd(1) xd(end)]));
+end
+
+if cntr
+ pl = pl+1;
+ subplot(npg,1,pl)
+ hc = get(gca,'Children');
+ xd = get(hc(1),'XData');
+ set(gca,'XLim',sort([xd(1) xd(end)]));
+ legend('nst','nfe','nni','netf','ncfn',2);
+end
+
+%-------------------------------------------------------------------------
+
+function [] = text_init(n,hft,stats,cntr,t,h,q,nst,nfe,nni,netf,ncfn)
+
+fig_name = 'IDAS run statistics';
+
+% If this is a parallel job, look for the MPI rank in the global
+% workspace and append it to the figure name
+
+global sundials_MPI_rank
+
+if ~isempty(sundials_MPI_rank)
+ fig_name = sprintf('%s (PE %d)',fig_name,sundials_MPI_rank);
+end
+
+figure(hft);
+set(hft,'Name',fig_name);
+set(hft,'color',[1 1 1]);
+set(hft,'MenuBar','none');
+set(hft,'Resize','off');
+
+% Create text box
+
+margins=[10 10 50 50]; % left, right, top, bottom
+pos=get(hft,'position');
+tbpos=[margins(1) margins(4) pos(3)-margins(1)-margins(2) ...
+ pos(4)-margins(3)-margins(4)];
+tbpos(tbpos<1)=1;
+
+htb=uicontrol(hft,'style','listbox','position',tbpos,'tag','textbox');
+set(htb,'BackgroundColor',[1 1 1]);
+set(htb,'SelectionHighlight','off');
+set(htb,'FontName','courier');
+
+% Create table head
+
+tpos = [tbpos(1) tbpos(2)+tbpos(4)+10 tbpos(3) 20];
+ht=uicontrol(hft,'style','text','position',tpos,'tag','text');
+set(ht,'BackgroundColor',[1 1 1]);
+set(ht,'HorizontalAlignment','left');
+set(ht,'FontName','courier');
+newline = ' time step order | nst nfe nni netf ncfn';
+set(ht,'String',newline);
+
+% Create OK button
+
+bsize=[60,28];
+badjustpos=[0,25];
+bpos=[pos(3)/2-bsize(1)/2+badjustpos(1) -bsize(2)/2+badjustpos(2)...
+ bsize(1) bsize(2)];
+bpos=round(bpos);
+bpos(bpos<1)=1;
+hb=uicontrol(hft,'style','pushbutton','position',bpos,...
+ 'string','Close','tag','okaybutton');
+set(hb,'callback','close');
+
+% Save handles
+
+handles=guihandles(hft);
+guidata(hft,handles);
+
+for i = 1:n
+ newline = '';
+ if stats
+ newline = sprintf('%10.3e %10.3e %1d |',t(i),h(i),q(i));
+ end
+ if cntr
+ newline = sprintf('%s %5d %5d %5d %5d %5d',...
+ newline,nst(i),nfe(i),nni(i),netf(i),ncfn(i));
+ end
+ string = get(handles.textbox,'String');
+ string{end+1}=newline;
+ set(handles.textbox,'String',string);
+end
+
+drawnow
+
+%-------------------------------------------------------------------------
+
+function [] = text_update(n,hft,stats,cntr,t,h,q,nst,nfe,nni,netf,ncfn)
+
+figure(hft);
+
+handles=guidata(hft);
+
+for i = 1:n
+ if stats
+ newline = sprintf('%10.3e %10.3e %1d |',t(i),h(i),q(i));
+ end
+ if cntr
+ newline = sprintf('%s %5d %5d %5d %5d %5d',...
+ newline,nst(i),nfe(i),nni(i),netf(i),ncfn(i));
+ end
+ string = get(handles.textbox,'String');
+ string{end+1}=newline;
+ set(handles.textbox,'String',string);
+end
+
+drawnow
+
+%-------------------------------------------------------------------------
+
+function [] = sol_init(n, hfs, nps, sol, N, t, y)
+
+fig_name = 'IDAS solution';
+
+% If this is a parallel job, look for the MPI rank in the global
+% workspace and append it to the figure name
+
+global sundials_MPI_rank
+
+if ~isempty(sundials_MPI_rank)
+ fig_name = sprintf('%s (PE %d)',fig_name,sundials_MPI_rank);
+end
+
+
+figure(hfs);
+set(hfs,'Name',fig_name);
+set(hfs,'color',[1 1 1]);
+
+% Time label
+
+tlab = '\leftarrow t \leftarrow';
+
+% Get number of colors in colormap
+map = colormap;
+ncols = size(map,1);
+
+% Initialize current subplot counter
+pl = 0;
+
+if sol
+
+ pl = pl+1;
+ subplot(nps,1,pl);
+ hold on;
+
+ for i = 1:N
+ hp = plot(t(1:n),y(i,1:n),'-');
+ ic = 1+(i-1)*floor(ncols/N);
+ set(hp,'Color',map(ic,:));
+ end
+ box on;
+ grid on;
+ xlabel(tlab);
+ ylabel('y');
+ title('Solution');
+
+end
+
+drawnow;
+
+%-------------------------------------------------------------------------
+
+function [] = sol_update(n, hfs, nps, sol, N, t, y)
+
+figure(hfs);
+
+pl = 0;
+
+if sol
+
+ pl = pl+1;
+ subplot(nps,1,pl);
+
+ hc = get(gca,'Children');
+ xd = [get(hc(1),'XData') t(1:n)];
+% Attention: Children are loaded in reverse order!
+ for i = 1:N
+ yd = [get(hc(i),'YData') y(N-i+1,1:n)];
+ set(hc(i), 'XData', xd, 'YData', yd);
+ end
+
+end
+
+drawnow;
+
+
+%-------------------------------------------------------------------------
+
+function [] = sol_final(hfs, nps, sol, N)
+
+figure(hfs);
+
+pl = 0;
+
+if sol
+
+ pl = pl +1;
+ subplot(nps,1,pl);
+
+ hc = get(gca,'Children');
+ xd = get(hc(1),'XData');
+ set(gca,'XLim',sort([xd(1) xd(end)]));
+
+ ylim = get(gca,'YLim');
+ addon = 0.1*abs(ylim(2)-ylim(1));
+ ylim(1) = ylim(1) + sign(ylim(1))*addon;
+ ylim(2) = ylim(2) + sign(ylim(2))*addon;
+ set(gca,'YLim',ylim);
+
+ for i = 1:N
+ cstring{i} = sprintf('y_{%d}',i);
+ end
+ legend(cstring);
+
+end
+
+drawnow
diff --git a/sundialsTB/idas/IDAMonitorB_octave.m b/sundialsTB/idas/IDAMonitorB_octave.m
new file mode 100644
index 0000000..b9e3207
--- /dev/null
+++ b/sundialsTB/idas/IDAMonitorB_octave.m
@@ -0,0 +1,545 @@
+function [new_data] = IDAMonitorB(call, idxB, T, Y, YQ, data)
+%IDAMonitorB is the default IDAS monitoring function for backward problems.
+% To use it, set the Monitor property in IDASetOptions to
+% 'IDAMonitorB' or to @IDAMonitorB and 'MonitorData' to mondata
+% (defined as a structure).
+%
+% With default settings, this function plots the evolution of the step
+% size, method order, and various counters.
+%
+% Various properties can be changed from their default values by passing
+% to IDASetOptions, through the property 'MonitorData', a structure
+% MONDATA with any of the following fields. If a field is not defined,
+% the corresponding default value is used.
+%
+% Fields in MONDATA structure:
+% o stats [ {true} | false ]
+% If true, report the evolution of the step size and method order.
+% o cntr [ {true} | false ]
+% If true, report the evolution of the following counters:
+% nst, nfe, nni, netf, ncfn (see IDAGetStats)
+% o sol [ true | {false} ]
+% If true, plot solution components.
+% o select [ array of integers ]
+% To plot only particular solution components, specify their indeces in
+% the field select. If not defined, but sol=true, all components are plotted.
+% o updt [ integer | {50} ]
+% Update frequency. Data is posted in blocks of dimension n.
+% o skip [ integer | {0} ]
+% Number of integrations steps to skip in collecting data to post.
+% o post [ {true} | false ]
+% If false, disable all posting. This option is necessary to disable
+% monitoring on some processors when running in parallel.
+%
+% See also IDASetOptions, IDAMonitorFnB
+%
+% NOTES:
+% 1. The argument mondata is REQUIRED. Even if only the default options
+% are desired, set mondata=struct; and pass it to IDASetOptions.
+% 2. The yQ argument is currently ignored.
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2007, The Regents of the University of California.
+% $Revision: 1.1 $Date: 2007/08/21 17:38:42 $
+
+
+if (nargin ~= 6)
+ error('Monitor data not defined.');
+end
+
+
+new_data = [];
+
+if call == 0
+
+% Initialize unspecified fields to default values.
+ data = initialize_data(data);
+
+% Open figure windows
+ if data.post
+
+ if data.stats | data.cntr
+ data.hfg = figure;
+ end
+% Number of subplots in figure hfg
+ if data.stats
+ data.npg = data.npg + 2;
+ end
+ if data.cntr
+ data.npg = data.npg + 1;
+ end
+
+ if data.sol
+ data.hfs = figure;
+ end
+
+ end
+
+% Initialize other private data
+ data.i = 0;
+ data.n = 1;
+ data.t = zeros(1,data.updt);
+ if data.stats
+ data.h = zeros(1,data.updt);
+ data.q = zeros(1,data.updt);
+ end
+ if data.cntr
+ data.nst = zeros(1,data.updt);
+ data.nfe = zeros(1,data.updt);
+ data.nni = zeros(1,data.updt);
+ data.netf = zeros(1,data.updt);
+ data.ncfn = zeros(1,data.updt);
+ end
+
+ data.first = true; % the next one will be the first call = 1
+ data.initialized = false; % the graphical windows were not initalized
+
+ new_data = data;
+
+ return;
+
+else
+
+% If this is the first call ~= 0,
+% use Y for additional initializations
+
+ if data.first
+
+ if data.sol
+
+ if isempty(data.select)
+
+ data.N = length(Y);
+ data.select = [1:data.N];
+
+ else
+
+ data.N = length(data.select);
+
+ end
+
+ if data.sol
+ data.y = zeros(data.N,data.updt);
+ data.nps = data.nps + 1;
+ end
+
+ end
+
+ data.first = false;
+
+ end
+
+% Extract variables from data
+
+ hfg = data.hfg;
+ hft = data.hft;
+ hfs = data.hfs;
+ npg = data.npg;
+ nps = data.nps;
+ i = data.i;
+ n = data.n;
+ t = data.t;
+ N = data.N;
+ y = data.y;
+ h = data.h;
+ q = data.q;
+ nst = data.nst;
+ nfe = data.nfe;
+ nni = data.nni;
+ netf = data.netf;
+ ncfn = data.ncfn;
+
+end
+
+
+% Load current statistics?
+
+if call == 1
+
+ if i ~= 0
+ i = i-1;
+ data.i = i;
+ new_data = data;
+ return;
+ end
+
+ si = IDAGetStatsB(idxB);
+
+ t(n) = si.tcur;
+
+ if data.stats
+ h(n) = si.hlast;
+ q(n) = si.qlast;
+ end
+
+ if data.cntr
+ nst(n) = si.nst;
+ nfe(n) = si.nfe;
+ nni(n) = si.nni;
+ netf(n) = si.netf;
+ ncfn(n) = si.ncfn;
+ end
+
+ if data.sol
+ for j = 1:N
+ y(j,n) = Y(data.select(j));
+ end
+ end
+
+end
+
+% Is it time to post?
+
+if data.post & (n == data.updt | call==2)
+
+ if call == 2
+ n = n-1;
+ end
+
+ if ~data.initialized
+
+ if (data.stats | data.cntr)
+ graphical_init(n, hfg, npg, data.stats, data.cntr, ...
+ t, h, q, nst, nfe, nni, netf, ncfn);
+ end
+
+ if data.sol
+ sol_init(n, hfs, nps, data.sol, ...
+ N, t, y);
+ end
+
+ data.initialized = true;
+
+ else
+
+ if (data.stats | data.cntr)
+ graphical_update(n, hfg, npg, data.stats, data.cntr, ...
+ t, h, q, nst, nfe, nni, netf, ncfn);
+ end
+
+ if data.sol
+ sol_update(n, hfs, nps, data.sol, N, t, y);
+ end
+
+ end
+
+ if call == 2
+
+ if (data.stats | data.cntr)
+ graphical_final(hfg, npg, data.cntr, data.stats);
+ end
+
+ if data.sol
+ sol_final(hfs, nps, data.sol, N);
+ end
+
+ return;
+
+ end
+
+ n = 1;
+
+else
+
+ n = n + 1;
+
+end
+
+
+% Save updated values in data
+
+data.i = data.skip;
+data.n = n;
+data.npg = npg;
+data.t = t;
+data.y = y;
+data.h = h;
+data.q = q;
+data.nst = nst;
+data.nfe = nfe;
+data.nni = nni;
+data.netf = netf;
+data.ncfn = ncfn;
+
+new_data = data;
+
+return;
+
+%-------------------------------------------------------------------------
+
+function data = initialize_data(data)
+
+if ~isfield(data,'updt')
+ data.updt = 50;
+end
+if ~isfield(data,'skip')
+ data.skip = 0;
+end
+if ~isfield(data,'stats')
+ data.stats = true;
+end
+if ~isfield(data,'cntr')
+ data.cntr = true;
+end
+if ~isfield(data,'sol')
+ data.sol = false;
+end
+if ~isfield(data,'select')
+ data.select = [];
+end
+if ~isfield(data,'post')
+ data.post = true;
+end
+
+if ~data.sol
+ data.select = [];
+end
+
+% Other initializations
+data.npg = 0;
+data.nps = 0;
+data.hfg = 0;
+data.hft = 0;
+data.hfs = 0;
+data.h = 0;
+data.q = 0;
+data.nst = 0;
+data.nfe = 0;
+data.nni = 0;
+data.netf = 0;
+data.ncfn = 0;
+data.N = 0;
+data.y = 0;
+
+%-------------------------------------------------------------------------
+
+function [] = graphical_init(n, hfg, npg, stats, cntr, ...
+ t, h, q, nst, nfe, nni, netf, ncfn)
+
+figure(hfg);
+pl = 0;
+
+% Time label and figure title
+
+tlab = '<- t <-';
+
+% Step size and order
+if stats
+ pl = pl+1;
+ subplot(npg,1,pl)
+ semilogy(t(1:n),abs(h(1:n)),'-');
+ hold on;
+ box on;
+ grid on;
+ xlabel(tlab);
+ ylabel('|Step size|');
+
+ pl = pl+1;
+ subplot(npg,1,pl)
+ plot(t(1:n),q(1:n),'-');
+ hold on;
+ box on;
+ grid on;
+ xlabel(tlab);
+ ylabel('Order');
+end
+
+% Counters
+if cntr
+ pl = pl+1;
+ subplot(npg,1,pl)
+ plot(t(1:n),nst(1:n),'k-');
+ hold on;
+ plot(t(1:n),nfe(1:n),'b-');
+ plot(t(1:n),nni(1:n),'r-');
+ plot(t(1:n),netf(1:n),'g-');
+ plot(t(1:n),ncfn(1:n),'c-');
+ box on;
+ grid on;
+ xlabel(tlab);
+ ylabel('Counters');
+end
+
+drawnow;
+
+%-------------------------------------------------------------------------
+
+function [] = graphical_update(n, hfg, npg, stats, cntr, ...
+ t, h, q, nst, nfe, nni, netf, ncfn)
+
+figure(hfg);
+pl = 0;
+
+% Step size and order
+if stats
+ pl = pl+1;
+ subplot(npg,1,pl)
+ hc = get(gca,'Children');
+ xd = [get(hc,'XData') ; t(1:n)'];
+ yd = [get(hc,'YData') ; abs(h(1:n)')];
+ set(hc, 'XData', xd, 'YData', yd);
+
+ pl = pl+1;
+ subplot(npg,1,pl)
+ hc = get(gca,'Children');
+ xd = [get(hc,'XData') ; t(1:n)'];
+ yd = [get(hc,'YData') ; q(1:n)'];
+ set(hc, 'XData', xd, 'YData', yd);
+end
+
+% Counters
+if cntr
+
+ pl = pl+1;
+
+ subplot(npg,1,pl)
+ hc = get(gca,'Children');
+
+ xd = [get(hc(1),'XData') ; t(1:n)'];
+
+ yd = [get(hc(5),'YData') ; ncfn(1:n)'];
+ set(hc(5), 'XData', xd, 'YData', yd);
+
+ yd = [get(hc(4),'YData') ; netf(1:n)'];
+ set(hc(4), 'XData', xd, 'YData', yd);
+
+ yd = [get(hc(3),'YData') ; nni(1:n)'];
+ set(hc(3), 'XData', xd, 'YData', yd);
+
+ yd = [get(hc(2),'YData') ; nfe(1:n)'];
+ set(hc(2), 'XData', xd, 'YData', yd);
+
+ yd = [get(hc(1),'YData') ; nst(1:n)'];
+ set(hc(1), 'XData', xd, 'YData', yd);
+
+end
+
+drawnow;
+
+%-------------------------------------------------------------------------
+
+function [] = graphical_final(hfg,npg,stats,cntr)
+
+figure(hfg);
+pl = 0;
+
+if stats
+ pl = pl+1;
+ subplot(npg,1,pl)
+ hc = get(gca,'Children');
+ xd = get(hc,'XData');
+ set(gca,'XLim',sort([xd(1) xd(end)]));
+
+ pl = pl+1;
+ subplot(npg,1,pl)
+ ylim = get(gca,'YLim');
+ ylim(1) = ylim(1) - 1;
+ ylim(2) = ylim(2) + 1;
+ set(gca,'YLim',ylim);
+ set(gca,'XLim',sort([xd(1) xd(end)]));
+end
+
+if cntr
+ pl = pl+1;
+ subplot(npg,1,pl)
+ hc = get(gca,'Children');
+ xd = get(hc(1),'XData');
+ set(gca,'XLim',sort([xd(1) xd(end)]));
+ legend('nst','nfe','nni','netf','ncfn',2);
+end
+
+%-------------------------------------------------------------------------
+
+function [] = sol_init(n, hfs, nps, sol, N, t, y)
+
+figure(hfs);
+
+% Time label
+
+tlab = '<- t <-';
+
+% Get number of colors in colormap
+map = colormap;
+ncols = size(map,1);
+
+% Initialize current subplot counter
+pl = 0;
+
+if sol
+
+ pl = pl+1;
+ subplot(nps,1,pl);
+ hold on;
+
+ for i = 1:N
+ hp = plot(t(1:n),y(i,1:n),'-');
+ ic = 1+(i-1)*floor(ncols/N);
+ set(hp,'Color',map(ic,:));
+ end
+ box on;
+ grid on;
+ xlabel(tlab);
+ ylabel('y');
+ title('Solution');
+
+end
+
+drawnow;
+
+%-------------------------------------------------------------------------
+
+function [] = sol_update(n, hfs, nps, sol, N, t, y)
+
+figure(hfs);
+
+pl = 0;
+
+if sol
+
+ pl = pl+1;
+ subplot(nps,1,pl);
+
+ hc = get(gca,'Children');
+ xd = [get(hc(1),'XData') ; t(1:n)'];
+
+ for i = 1:N
+ yd = [get(hc(i),'YData') ; y(i,1:n)'];
+ set(hc(i), 'XData', xd, 'YData', yd);
+ end
+
+end
+
+drawnow;
+
+
+%-------------------------------------------------------------------------
+
+function [] = sol_final(hfs, nps, sol, N)
+
+figure(hfs);
+
+pl = 0;
+
+if sol
+
+ pl = pl +1;
+ subplot(nps,1,pl);
+
+ hc = get(gca,'Children');
+ xd = get(hc(1),'XData');
+ set(gca,'XLim',sort([xd(1) xd(end)]));
+
+ ylim = get(gca,'YLim');
+ addon = 0.1*abs(ylim(2)-ylim(1));
+ ylim(1) = ylim(1) + sign(ylim(1))*addon;
+ ylim(2) = ylim(2) + sign(ylim(2))*addon;
+ set(gca,'YLim',ylim);
+
+ for i = 1:N
+ cstring{i} = sprintf('y_{%d}',i);
+ end
+ legend(cstring);
+
+end
+
+drawnow
diff --git a/sundialsTB/idas/IDAMonitor_octave.m b/sundialsTB/idas/IDAMonitor_octave.m
new file mode 100644
index 0000000..fc30315
--- /dev/null
+++ b/sundialsTB/idas/IDAMonitor_octave.m
@@ -0,0 +1,637 @@
+function [new_data] = IDAMonitor(call, T, Y, YQ, YS, data)
+%IDAMonitor is the default IDAS monitoring function.
+% To use it, set the Monitor property in IDASetOptions to
+% 'IDAMonitor' or to @IDAMonitor and 'MonitorData' to mondata
+% (defined as a structure).
+%
+% With default settings, this function plots the evolution of the step
+% size, method order, and various counters.
+%
+% Various properties can be changed from their default values by passing
+% to IDASetOptions, through the property 'MonitorData', a structure
+% MONDATA with any of the following fields. If a field is not defined,
+% the corresponding default value is used.
+%
+% Fields in MONDATA structure:
+% o stats [ {true} | false ]
+% If true, report the evolution of the step size and method order.
+% o cntr [ {true} | false ]
+% If true, report the evolution of the following counters:
+% nst, nfe, nni, netf, ncfn (see IDAGetStats)
+% o sol [ true | {false} ]
+% If true, plot solution components.
+% o sensi [ true | {false} ]
+% If true and if FSA is enabled, plot sensitivity components.
+% o select [ array of integers ]
+% To plot only particular solution components, specify their indeces in
+% the field select. If not defined, but sol=true, all components are plotted.
+% o updt [ integer | {50} ]
+% Update frequency. Data is posted in blocks of dimension n.
+% o skip [ integer | {0} ]
+% Number of integrations steps to skip in collecting data to post.
+% o post [ {true} | false ]
+% If false, disable all posting. This option is necessary to disable
+% monitoring on some processors when running in parallel.
+%
+% See also IDASetOptions, IDAMonitorFn
+%
+% NOTES:
+% 1. The argument mondata is REQUIRED. Even if only the default options
+% are desired, set mondata=struct; and pass it to IDASetOptions.
+% 2. The yQ argument is currently ignored.
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2007, The Regents of the University of California.
+% $Revision: 1.1 $Date: 2007/08/21 17:38:42 $
+
+% NOTES:
+% - Unlike Matlab, Octave loads children in the normal order
+% - Unlike Matlab, Octave stores 'XData' and 'YData' as column vectors
+
+if (nargin ~= 6)
+ error('Monitor data not defined.');
+end
+
+new_data = [];
+
+if call == 0
+
+% Initialize unspecified fields to default values.
+ data = initialize_data(data);
+
+% Open figure windows
+ if data.post
+
+ if data.stats | data.cntr
+ data.hfg = figure;
+ end
+% Number of subplots in figure hfg
+ if data.stats
+ data.npg = data.npg + 2;
+ end
+ if data.cntr
+ data.npg = data.npg + 1;
+ end
+
+ if data.sol | data.sensi
+ data.hfs = figure;
+ end
+
+ end
+
+% Initialize other private data
+ data.i = 0;
+ data.n = 1;
+ data.t = zeros(1,data.updt);
+ if data.stats
+ data.h = zeros(1,data.updt);
+ data.q = zeros(1,data.updt);
+ end
+ if data.cntr
+ data.nst = zeros(1,data.updt);
+ data.nfe = zeros(1,data.updt);
+ data.nni = zeros(1,data.updt);
+ data.netf = zeros(1,data.updt);
+ data.ncfn = zeros(1,data.updt);
+ end
+
+ data.first = true; % the next one will be the first call = 1
+ data.initialized = false; % the graphical windows were not initalized
+
+ new_data = data;
+
+ return;
+
+else
+
+% If this is the first call ~= 0,
+% use Y and YS for additional initializations
+
+ if data.first
+
+ if isempty(YS)
+ data.sensi = false;
+ end
+
+ if data.sol | data.sensi
+
+ if isempty(data.select)
+
+ data.N = length(Y);
+ data.select = [1:data.N];
+
+ else
+
+ data.N = length(data.select);
+
+ end
+
+ if data.sol
+ data.y = zeros(data.N,data.updt);
+ data.nps = data.nps + 1;
+ end
+
+ if data.sensi
+ data.Ns = size(YS,2);
+ data.ys = zeros(data.N, data.Ns, data.updt);
+ data.nps = data.nps + data.Ns;
+ end
+
+ end
+
+ data.first = false;
+
+ end
+
+% Extract variables from data
+
+ hfg = data.hfg;
+ hft = data.hft;
+ hfs = data.hfs;
+ npg = data.npg;
+ nps = data.nps;
+ i = data.i;
+ n = data.n;
+ t = data.t;
+ N = data.N;
+ Ns = data.Ns;
+ y = data.y;
+ ys = data.ys;
+ h = data.h;
+ q = data.q;
+ nst = data.nst;
+ nfe = data.nfe;
+ nni = data.nni;
+ netf = data.netf;
+ ncfn = data.ncfn;
+
+end
+
+
+% Load current statistics?
+
+if call == 1
+
+ if i ~= 0
+ i = i-1;
+ data.i = i;
+ new_data = data;
+ return;
+ end
+
+ si = IDAGetStats;
+
+ t(n) = si.tcur;
+
+ if data.stats
+ h(n) = si.hlast;
+ q(n) = si.qlast;
+ end
+
+ if data.cntr
+ nst(n) = si.nst;
+ nfe(n) = si.nfe;
+ nni(n) = si.nni;
+ netf(n) = si.netf;
+ ncfn(n) = si.ncfn;
+ end
+
+ if data.sol
+ for j = 1:N
+ y(j,n) = Y(data.select(j));
+ end
+ end
+
+ if data.sensi
+ for k = 1:Ns
+ for j = 1:N
+ ys(j,k,n) = YS(data.select(j),k);
+ end
+ end
+ end
+
+end
+
+% Is it time to post?
+
+if data.post & (n == data.updt | call==2)
+
+ if call == 2
+ n = n-1;
+ end
+
+ if ~data.initialized
+
+ if (data.stats | data.cntr)
+ graphical_init(n, hfg, npg, data.stats, data.cntr, ...
+ t, h, q, nst, nfe, nni, netf, ncfn);
+ end
+
+ if data.sol | data.sensi
+ sol_init(n, hfs, nps, data.sol, data.sensi, ...
+ N, Ns, t, y, ys);
+ end
+
+ data.initialized = true;
+
+ else
+
+ if (data.stats | data.cntr)
+ graphical_update(n, hfg, npg, data.stats, data.cntr, ...
+ t, h, q, nst, nfe, nni, netf, ncfn);
+ end
+
+ if data.sol
+ sol_update(n, hfs, nps, data.sol, data.sensi, N, Ns, t, y, ys);
+ end
+
+ end
+
+ if call == 2
+
+ if (data.stats | data.cntr)
+ graphical_final(hfg, npg, data.cntr, data.stats);
+ end
+
+ if data.sol | data.sensi
+ sol_final(hfs, nps, data.sol, data.sensi, N, Ns);
+ end
+
+ return;
+
+ end
+
+ n = 1;
+
+else
+
+ n = n + 1;
+
+end
+
+
+% Save updated values in data
+
+data.i = data.skip;
+data.n = n;
+data.npg = npg;
+data.t = t;
+data.y = y;
+data.ys = ys;
+data.h = h;
+data.q = q;
+data.nst = nst;
+data.nfe = nfe;
+data.nni = nni;
+data.netf = netf;
+data.ncfn = ncfn;
+
+new_data = data;
+
+return;
+
+%-------------------------------------------------------------------------
+
+function data = initialize_data(data)
+
+if ~isfield(data,'updt')
+ data.updt = 50;
+end
+if ~isfield(data,'skip')
+ data.skip = 0;
+end
+if ~isfield(data,'stats')
+ data.stats = true;
+end
+if ~isfield(data,'cntr')
+ data.cntr = true;
+end
+if ~isfield(data,'sol')
+ data.sol = false;
+end
+if ~isfield(data,'sensi')
+ data.sensi = false;
+end
+if ~isfield(data,'select')
+ data.select = [];
+end
+if ~isfield(data,'post')
+ data.post = true;
+end
+
+if ~data.sol & ~data.sensi
+ data.select = [];
+end
+
+% Other initializations
+data.npg = 0;
+data.nps = 0;
+data.hfg = 0;
+data.hft = 0;
+data.hfs = 0;
+data.h = 0;
+data.q = 0;
+data.nst = 0;
+data.nfe = 0;
+data.nni = 0;
+data.netf = 0;
+data.ncfn = 0;
+data.N = 0;
+data.Ns = 0;
+data.y = 0;
+data.ys = 0;
+
+%-------------------------------------------------------------------------
+
+function [] = graphical_init(n, hfg, npg, stats, cntr, ...
+ t, h, q, nst, nfe, nni, netf, ncfn)
+
+figure(hfg);
+pl = 0;
+
+% Time label and figure title
+
+tlab = '-> t ->';
+
+% Step size and order
+if stats
+ pl = pl+1;
+ subplot(npg,1,pl)
+ semilogy(t(1:n),abs(h(1:n)),'-');
+ hold on;
+ box on;
+ grid on;
+ xlabel(tlab);
+ ylabel('|Step size|');
+
+ pl = pl+1;
+ subplot(npg,1,pl)
+ plot(t(1:n),q(1:n),'-');
+ hold on;
+ box on;
+ grid on;
+ xlabel(tlab);
+ ylabel('Order');
+end
+
+% Counters
+if cntr
+ pl = pl+1;
+ subplot(npg,1,pl)
+ plot(t(1:n),nst(1:n),'k-');
+ hold on;
+ plot(t(1:n),nfe(1:n),'b-');
+ plot(t(1:n),nni(1:n),'r-');
+ plot(t(1:n),netf(1:n),'g-');
+ plot(t(1:n),ncfn(1:n),'c-');
+ box on;
+ grid on;
+ xlabel(tlab);
+ ylabel('Counters');
+end
+
+drawnow;
+
+%-------------------------------------------------------------------------
+
+function [] = graphical_update(n, hfg, npg, stats, cntr, ...
+ t, h, q, nst, nfe, nni, netf, ncfn)
+
+figure(hfg);
+pl = 0;
+
+% Step size and order
+if stats
+ pl = pl+1;
+ subplot(npg,1,pl)
+ hc = get(gca,'Children');
+ xd = [get(hc,'XData') ; t(1:n)'];
+ yd = [get(hc,'YData') ; abs(h(1:n)')];
+ set(hc, 'XData', xd, 'YData', yd);
+
+ pl = pl+1;
+ subplot(npg,1,pl)
+ hc = get(gca,'Children');
+ xd = [get(hc,'XData') ; t(1:n)'];
+ yd = [get(hc,'YData') ; q(1:n)'];
+ set(hc, 'XData', xd, 'YData', yd);
+end
+
+% Counters
+if cntr
+ pl = pl+1;
+ subplot(npg,1,pl)
+ hc = get(gca,'Children');
+ xd = [get(hc(1),'XData') ; t(1:n)'];
+ yd = [get(hc(1),'YData') ; ncfn(1:n)'];
+ set(hc(1), 'XData', xd, 'YData', yd);
+ yd = [get(hc(2),'YData') ; netf(1:n)'];
+ set(hc(2), 'XData', xd, 'YData', yd);
+ yd = [get(hc(3),'YData') ; nni(1:n)'];
+ set(hc(3), 'XData', xd, 'YData', yd);
+ yd = [get(hc(4),'YData') ; nfe(1:n)'];
+ set(hc(4), 'XData', xd, 'YData', yd);
+ yd = [get(hc(5),'YData') ; nst(1:n)'];
+ set(hc(5), 'XData', xd, 'YData', yd);
+end
+
+drawnow;
+
+%-------------------------------------------------------------------------
+
+function [] = graphical_final(hfg,npg,stats,cntr)
+
+figure(hfg);
+pl = 0;
+
+if stats
+ pl = pl+1;
+ subplot(npg,1,pl)
+ hc = get(gca,'Children');
+ xd = get(hc,'XData');
+ set(gca,'XLim',sort([xd(1) xd(end)]));
+
+ pl = pl+1;
+ subplot(npg,1,pl)
+ ylim = get(gca,'YLim');
+ ylim(1) = ylim(1) - 1;
+ ylim(2) = ylim(2) + 1;
+ set(gca,'YLim',ylim);
+ set(gca,'XLim',sort([xd(1) xd(end)]));
+end
+
+if cntr
+ pl = pl+1;
+ subplot(npg,1,pl)
+ hc = get(gca,'Children');
+ xd = get(hc(1),'XData');
+ set(gca,'XLim',sort([xd(1) xd(end)]));
+ legend('nst','nfe','nni','netf','ncfn',2);
+end
+
+%-------------------------------------------------------------------------
+
+function [] = sol_init(n, hfs, nps, sol, sensi, N, Ns, t, y, ys)
+
+figure(hfs);
+
+% Time label
+
+tlab = '-> t ->';
+
+% Get number of colors in colormap
+map = colormap;
+ncols = size(map,1);
+
+% Initialize current subplot counter
+pl = 0;
+
+if sol
+
+ pl = pl+1;
+ subplot(nps,1,pl);
+ hold on;
+
+ for i = 1:N
+ hp = plot(t(1:n),y(i,1:n),'-');
+ ic = 1+(i-1)*floor(ncols/N);
+ set(hp,'Color',map(ic,:));
+ end
+ box on;
+ grid on;
+ xlabel(tlab);
+ ylabel('y');
+ title('Solution');
+
+end
+
+if sensi
+
+ for is = 1:Ns
+
+ pl = pl+1;
+ subplot(nps,1,pl);
+ hold on;
+
+ ys_crt = ys(:,is,1:n);
+ for i = 1:N
+ hp = plot(t(1:n),ys_crt(i,1:n),'-');
+ ic = 1+(i-1)*floor(ncols/N);
+ set(hp,'Color',map(ic,:));
+ end
+ box on;
+ grid on;
+ xlabel(tlab);
+ str = sprintf('s_{%d}',is); ylabel(str);
+ str = sprintf('Sensitivity %d',is); title(str);
+
+ end
+
+end
+
+
+drawnow;
+
+%-------------------------------------------------------------------------
+
+function [] = sol_update(n, hfs, nps, sol, sensi, N, Ns, t, y, ys)
+
+figure(hfs);
+
+pl = 0;
+
+if sol
+
+ pl = pl+1;
+ subplot(nps,1,pl);
+
+ hc = get(gca,'Children');
+ xd = [get(hc(1),'XData') ; t(1:n)'];
+ for i = 1:N
+ yd = [get(hc(i),'YData') ; y(i,1:n)'];
+ set(hc(i), 'XData', xd, 'YData', yd);
+ end
+
+end
+
+if sensi
+
+ for is = 1:Ns
+
+ pl = pl+1;
+ subplot(nps,1,pl);
+
+ ys_crt = ys(:,is,:);
+
+ hc = get(gca,'Children');
+ xd = [get(hc(1),'XData') ; t(1:n)'];
+ for i = 1:N
+ yd = [get(hc(i),'YData') ; ys_crt(i,1:n)'];
+ set(hc(i), 'XData', xd, 'YData', yd);
+ end
+
+ end
+
+end
+
+
+drawnow;
+
+
+%-------------------------------------------------------------------------
+
+function [] = sol_final(hfs, nps, sol, sensi, N, Ns)
+
+figure(hfs);
+
+pl = 0;
+
+if sol
+
+ pl = pl +1;
+ subplot(nps,1,pl);
+
+ hc = get(gca,'Children');
+ xd = get(hc(1),'XData');
+ set(gca,'XLim',sort([xd(1) xd(end)]));
+
+ ylim = get(gca,'YLim');
+ addon = 0.1*abs(ylim(2)-ylim(1));
+ ylim(1) = ylim(1) + sign(ylim(1))*addon;
+ ylim(2) = ylim(2) + sign(ylim(2))*addon;
+ set(gca,'YLim',ylim);
+
+ for i = 1:N
+ cstring{i} = sprintf('y_{%d}',i);
+ end
+ legend(cstring);
+
+end
+
+if sensi
+
+ for is = 1:Ns
+
+ pl = pl+1;
+ subplot(nps,1,pl);
+
+ hc = get(gca,'Children');
+ xd = get(hc(1),'XData');
+ set(gca,'XLim',sort([xd(1) xd(end)]));
+
+ ylim = get(gca,'YLim');
+ addon = 0.1*abs(ylim(2)-ylim(1));
+ ylim(1) = ylim(1) + sign(ylim(1))*addon;
+ ylim(2) = ylim(2) + sign(ylim(2))*addon;
+ set(gca,'YLim',ylim);
+
+ for i = 1:N
+ cstring{i} = sprintf('s%d_{%d}',is,i);
+ end
+ legend(cstring);
+
+ end
+
+end
+
+drawnow
diff --git a/sundialsTB/idas/IDAQuadInit.m b/sundialsTB/idas/IDAQuadInit.m
new file mode 100644
index 0000000..921610b
--- /dev/null
+++ b/sundialsTB/idas/IDAQuadInit.m
@@ -0,0 +1,28 @@
+function status = IDAQuadInit(fctQ, yQ0, options)
+%IDAQuadInit allocates and initializes memory for quadrature integration.
+%
+% Usage: IDAQuadInit ( QFUN, YQ0 [, OPTIONS ] )
+%
+% QFUN is a function defining the righ-hand sides of the quadrature
+% ODEs yQ' = fQ(t,y).
+% YQ0 is the initial conditions vector yQ(t0).
+% OPTIONS is an (optional) set of QUAD options, created with
+% the IDASetQuadOptions function.
+%
+% See also: IDASetQuadOptions, IDAQuadRhsFn
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2007, The Regents of the University of California.
+% $Revision: 1.2 $Date: 2007/12/05 21:58:18 $
+
+mode = 2;
+
+if nargin < 2
+ error('Too few input arguments');
+end
+
+if nargin < 3
+ options = [];
+end
+
+status = idm(mode, fctQ, yQ0, options);
diff --git a/sundialsTB/idas/IDAQuadInitB.m b/sundialsTB/idas/IDAQuadInitB.m
new file mode 100644
index 0000000..83fbbbe
--- /dev/null
+++ b/sundialsTB/idas/IDAQuadInitB.m
@@ -0,0 +1,32 @@
+function status = IDAQuadInitB(idxB, fctQB, yQB0, optionsB)
+%IDAQuadInitB allocates and initializes memory for backward quadrature integration.
+%
+% Usage: IDAQuadInitB ( IDXB, QBFUN, YQB0 [, OPTIONS ] )
+%
+% IDXB is the index of the backward problem, returned by
+% IDAInitB.
+% QBFUN is a function defining the righ-hand sides of the
+% backward ODEs yQB' = fQB(t,y,yB).
+% YQB0 is the final conditions vector yQB(tB0).
+% OPTIONS is an (optional) set of QUAD options, created with
+% the IDASetQuadOptions function.
+%
+% See also: IDAInitB, IDASetQuadOptions, IDAQuadRhsFnB
+%
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2007, The Regents of the University of California.
+% $Revision: 1.2 $Date: 2007/12/05 21:58:18 $
+
+mode = 6;
+
+if nargin < 3
+ error('Too few input arguments');
+end
+
+if nargin < 4
+ optionsB = [];
+end
+
+idxB = idxB-1;
+status = idm(mode, idxB, fctQB, yQB0, optionsB);
diff --git a/sundialsTB/idas/IDAQuadReInit.m b/sundialsTB/idas/IDAQuadReInit.m
new file mode 100644
index 0000000..14f2c5f
--- /dev/null
+++ b/sundialsTB/idas/IDAQuadReInit.m
@@ -0,0 +1,28 @@
+function status = IDAQuadReInit(yQ0, options)
+%IDAQuadReInit reinitializes IDAS's quadrature-related memory
+% assuming it has already been allocated in prior calls to IDAInit
+% and IDAQuadInit.
+%
+% Usage: IDAQuadReInit ( YQ0 [, OPTIONS ] )
+%
+% YQ0 Initial conditions for quadrature variables yQ(t0).
+% OPTIONS is an (optional) set of QUAD options, created with
+% the IDASetQuadOptions function.
+%
+% See also: IDASetQuadOptions, IDAQuadInit
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2007, The Regents of the University of California.
+% $Revision: 1.2 $Date: 2007/12/05 21:58:18 $
+
+mode = 12;
+
+if nargin < 1
+ error('Too few input arguments');
+end
+
+if nargin < 2
+ options = [];
+end
+
+status = idm(mode, yQ0, options);
diff --git a/sundialsTB/idas/IDAQuadReInitB.m b/sundialsTB/idas/IDAQuadReInitB.m
new file mode 100644
index 0000000..b117e68
--- /dev/null
+++ b/sundialsTB/idas/IDAQuadReInitB.m
@@ -0,0 +1,30 @@
+function status = IDAQuadReInitB(idxB, yQB0, optionsB)
+%IDAQuadReInitB reinitializes memory for backward quadrature integration.
+%
+% Usage: IDAQuadReInitB ( IDXB, YS0 [, OPTIONS ] )
+%
+% IDXB is the index of the backward problem, returned by
+% IDAInitB.
+% YQB0 is the final conditions vector yQB(tB0).
+% OPTIONS is an (optional) set of QUAD options, created with
+% the IDASetQuadOptions function.
+%
+% See also: IDASetQuadOptions, IDAReInitB, IDAQuadInitB
+%
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2007, The Regents of the University of California.
+% $Revision: 1.2 $Date: 2007/12/05 21:58:18 $
+
+mode = 16;
+
+if nargin < 2
+ error('Too few input arguments');
+end
+
+if nargin < 3
+ optionsB = [];
+end
+
+idxB = idxB-1;
+status = idm(mode, idxB, yQB0, optionsB);
diff --git a/sundialsTB/idas/IDAQuadSetOptions.m b/sundialsTB/idas/IDAQuadSetOptions.m
new file mode 100644
index 0000000..0e180fb
--- /dev/null
+++ b/sundialsTB/idas/IDAQuadSetOptions.m
@@ -0,0 +1,63 @@
+function options = IDAQuadSetOptions(varargin)
+%IDAQuadSetOptions creates an options structure for IDAS.
+%
+% Usage: OPTIONS = IDAQuadSetOptions('NAME1',VALUE1,'NAME2',VALUE2,...)
+% OPTIONS = IDAQuadSetOptions(OLDOPTIONS,'NAME1',VALUE1,...)
+%
+% OPTIONS = IDAQuadSetOptions('NAME1',VALUE1,'NAME2',VALUE2,...) creates
+% an IDAS options structure OPTIONS in which the named properties have
+% the specified values. Any unspecified properties have default values.
+% It is sufficient to type only the leading characters that uniquely
+% identify the property. Case is ignored for property names.
+%
+% OPTIONS = IDAQuadSetOptions(OLDOPTIONS,'NAME1',VALUE1,...) alters an
+% existing options structure OLDOPTIONS.
+%
+% IDAQuadSetOptions with no input arguments displays all property names
+% and their possible values.
+%
+%IDAQuadSetOptions properties
+%(See also the IDAS User Guide)
+%
+%ErrControl - Error control strategy for quadrature variables [ on | {off} ]
+% Specifies whether quadrature variables are included in the error test.
+%RelTol - Relative tolerance for quadrature variables [ scalar {1e-4} ]
+% Specifies the relative tolerance for quadrature variables. This parameter is
+% used only if QuadErrCon=on.
+%AbsTol - Absolute tolerance for quadrature variables [ scalar or vector {1e-6} ]
+% Specifies the absolute tolerance for quadrature variables. This parameter is
+% used only if QuadErrCon=on.
+%
+%SensDependent - Backward problem depending on sensitivities [ {false} | true ]
+% Specifies whether the backward problem quadrature right-hand side depends
+% on forward sensitivites. If TRUE, the right-hand side function provided for
+% this backward problem must have the appropriate type (see IDAQuadRhsFnB).
+%
+% See also
+% IDAQuadInit, IDAQuadReInit.
+% IDAQuadInitB, IDAQuadReInitB
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2005, The Regents of the University of California.
+% $Revision: 1.1 $Date: 2007/08/21 17:38:42 $
+
+% If called without input and output arguments, print out the possible keywords
+
+if (nargin == 0) && (nargout == 0)
+ fprintf(' ErrControl: [ {false} | true ]\n');
+ fprintf(' RelTol: [ positive scalar {1e-4} ]\n');
+ fprintf(' AbsTol: [ positive scalar or vector {1e-6} ]\n');
+ fprintf('\n');
+ fprintf(' SensDependent: [ {false} | true ]\n');
+ fprintf('\n');
+ return;
+end
+
+KeyNames = {
+ 'ErrControl'
+ 'RelTol'
+ 'AbsTol'
+ 'SensDependent'
+ };
+
+options = idm_options(KeyNames,varargin{:});
diff --git a/sundialsTB/idas/IDAReInit.m b/sundialsTB/idas/IDAReInit.m
new file mode 100644
index 0000000..a405020
--- /dev/null
+++ b/sundialsTB/idas/IDAReInit.m
@@ -0,0 +1,33 @@
+function status = IDAReInit(t0,yy0,yp0,options)
+%IDAReInit reinitializes memory for IDAS.
+% where a prior call to IDAInit has been made with the same
+% problem size N. IDAReInit performs the same input checking
+% and initializations that IDAInit does, but it does no
+% memory allocation, assuming that the existing internal memory
+% is sufficient for the new problem.
+%
+% Usage: IDAReInit ( T0, YY0, YP0 [, OPTIONS ] )
+%
+% T0 is the initial value of t.
+% YY0 is the initial condition vector y(t0).
+% YP0 is the initial condition vector y'(t0).
+% OPTIONS is an (optional) set of integration options, created with
+% the IDASetOptions function.
+%
+% See also: IDASetOptions, IDAInit
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2007, The Regents of the University of California.
+% $Revision: 1.3 $Date: 2007/12/05 21:58:18 $
+
+mode = 11;
+
+if nargin < 3
+ error('Too few input arguments');
+end
+
+if nargin < 4
+ options = [];
+end
+
+status = idm(mode, t0, yy0, yp0, options);
diff --git a/sundialsTB/idas/IDAReInitB.m b/sundialsTB/idas/IDAReInitB.m
new file mode 100644
index 0000000..a940159
--- /dev/null
+++ b/sundialsTB/idas/IDAReInitB.m
@@ -0,0 +1,37 @@
+function status = IDAReInitB(idxB,tB0,yyB0,ypB0,optionsB)
+%IDAReInitB allocates and initializes backward memory for IDAS.
+% where a prior call to IDAInitB has been made with the same
+% problem size NB. IDAReInitB performs the same input checking
+% and initializations that IDAInitB does, but it does no
+% memory allocation, assuming that the existing internal memory
+% is sufficient for the new problem.
+%
+% Usage: IDAReInitB ( IDXB, TB0, YYB0, YPB0 [, OPTIONSB] )
+%
+% IDXB is the index of the backward problem, returned by
+% IDAInitB.
+% TB0 is the final value of t.
+% YYB0 is the final condition vector yB(tB0).
+% YPB0 is the final condition vector yB'(tB0).
+% OPTIONSB is an (optional) set of integration options, created with
+% the IDASetOptions function.
+%
+% See also: IDASetOptions, IDAInitB
+%
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2007, The Regents of the University of California.
+% $Revision: 1.3 $Date: 2007/12/05 21:58:18 $
+
+mode = 15;
+
+if nargin < 4
+ error('Too few input arguments');
+end
+
+if nargin < 5
+ optionsB = [];
+end
+
+idxB = idxB-1;
+status = idm(mode, idxB, tB0, yyB0, ypB0, optionsB);
diff --git a/sundialsTB/idas/IDASensInit.m b/sundialsTB/idas/IDASensInit.m
new file mode 100644
index 0000000..deff514
--- /dev/null
+++ b/sundialsTB/idas/IDASensInit.m
@@ -0,0 +1,32 @@
+function status = IDASensInit(Ns,fctS,yyS0,ypS0,options)
+%IDASensInit allocates and initializes memory for FSA with IDAS.
+%
+% Usage: IDASensInit ( NS, SFUN, YYS0, YPS0 [, OPTIONS ] )
+%
+% NS is the number of parameters with respect to which sensitivities
+% are desired
+% SFUN is a function defining the residual of the sensitivity DAEs
+% fS(t,y,yp,yS,ypS).
+% YYS0, YPS0 Initial conditions for sensitivity variables.
+% YYS0 and YPS0 must be matrices with N rows and Ns columns, where N is
+% the problem dimension and Ns the number of sensitivity systems.
+% OPTIONS is an (optional) set of FSA options, created with
+% the IDASetFSAOptions function.
+%
+% See also IDASensSetOptions, IDAInit, IDASensResFn
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2007, The Regents of the University of California.
+% $Revision: 1.2 $Date: 2007/12/05 21:58:19 $
+
+mode = 3;
+
+if nargin < 4
+ error('Too few input arguments');
+end
+
+if nargin < 5
+ options = [];
+end
+
+status = idm(mode, Ns, fctS, yyS0, ypS0, options);
diff --git a/sundialsTB/idas/IDASensReInit.m b/sundialsTB/idas/IDASensReInit.m
new file mode 100644
index 0000000..b978502
--- /dev/null
+++ b/sundialsTB/idas/IDASensReInit.m
@@ -0,0 +1,32 @@
+function status = IDASensReInit(yyS0,ypS0,options)
+%IDASensReInit reinitializes IDAS's FSA-related memory
+% assuming it has already been allocated in prior calls to IDAInit
+% and IDASensInit.
+% The number of sensitivities Ns is assumed to be unchanged since the
+% previous call to IDASensInit.
+%
+% Usage: IDASensReInit ( YYS0, YPS0 [, OPTIONS ] )
+%
+% YYS0, YPS0 Initial conditions for sensitivity variables.
+% YYS0 and YPS0 must be matrices with N rows and Ns columns, where N is
+% the problem dimension and Ns the number of sensitivity systems.
+% OPTIONS is an (optional) set of FSA options, created with
+% the IDASetFSAOptions function.
+%
+% See also: IDASensSetOptions, IDAReInit, IDASensInit
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2007, The Regents of the University of California.
+% $Revision: 1.3 $Date: 2007/12/05 21:58:19 $
+
+mode = 13;
+
+if nargin < 2
+ error('Too few input arguments');
+end
+
+if nargin < 3
+ options = [];
+end
+
+status = idm(mode, yyS0, ypS0, options);
diff --git a/sundialsTB/idas/IDASensSetOptions.m b/sundialsTB/idas/IDASensSetOptions.m
new file mode 100644
index 0000000..94dddfa
--- /dev/null
+++ b/sundialsTB/idas/IDASensSetOptions.m
@@ -0,0 +1,112 @@
+function options = IDASensSetOptions(varargin)
+%IDASensSetOptions creates an options structure for FSA with IDAS.
+%
+% Usage: OPTIONS = IDASensSetOptions('NAME1',VALUE1,'NAME2',VALUE2,...)
+% OPTIONS = IDASensSetOptions(OLDOPTIONS,'NAME1',VALUE1,...)
+%
+% OPTIONS = IDASensSetOptions('NAME1',VALUE1,'NAME2',VALUE2,...) creates
+% a IDAS options structure OPTIONS in which the named properties have
+% the specified values. Any unspecified properties have default values.
+% It is sufficient to type only the leading characters that uniquely
+% identify the property. Case is ignored for property names.
+%
+% OPTIONS = IDASensSetOptions(OLDOPTIONS,'NAME1',VALUE1,...) alters an
+% existing options structure OLDOPTIONS.
+%
+% IDASensSetOptions with no input arguments displays all property names
+% and their possible values.
+%
+%IDASensSetOptions properties
+%(See also the IDAS User Guide)
+%
+%method - FSA solution method [ 'Simultaneous' | {'Staggered'} ]
+% Specifies the FSA method for treating the nonlinear system solution for
+% sensitivity variables. In the simultaneous case, the nonlinear systems
+% for states and all sensitivities are solved simultaneously. In the
+% Staggered case, the nonlinear system for states is solved first and then
+% the nonlinear systems for all sensitivities are solved at the same time.
+%ParamField - Problem parameters [ string ]
+% Specifies the name of the field in the user data structure (specified through
+% the 'UserData' field with IDASetOptions) in which the nominal values of the problem
+% parameters are stored. This property is used only if IDAS will use difference
+% quotient approximations to the sensitivity residuals (see IDASensResFn).
+%ParamList - Parameters with respect to which FSA is performed [ integer vector ]
+% Specifies a list of Ns parameters with respect to which sensitivities are to
+% be computed. This property is used only if IDAS will use difference-quotient
+% approximations to the sensitivity residuals. Its length must be Ns,
+% consistent with the number of columns of yS0 (see IDASensInit).
+%ParamScales - Order of magnitude for problem parameters [ vector ]
+% Provides order of magnitude information for the parameters with respect to
+% which sensitivities are computed. This information is used if IDAS
+% approximates the sensitivity residuals or if IDAS estimates integration
+% tolerances for the sensitivity variables (see RelTol and AbsTol).
+%RelTol - Relative tolerance for sensitivity variables [ positive scalar ]
+% Specifies the scalar relative tolerance for the sensitivity variables.
+% See also AbsTol.
+%AbsTol - Absolute tolerance for sensitivity variables [ row-vector or matrix ]
+% Specifies the absolute tolerance for sensitivity variables. AbsTol must be
+% either a row vector of dimension Ns, in which case each of its components is
+% used as a scalar absolute tolerance for the coresponding sensitivity vector,
+% or a N x Ns matrix, in which case each of its columns is used as a vector
+% of absolute tolerances for the corresponding sensitivity vector.
+% By default, IDAS estimates the integration tolerances for sensitivity
+% variables, based on those for the states and on the order of magnitude
+% information for the problem parameters specified through ParamScales.
+%ErrControl - Error control strategy for sensitivity variables [ false | {true} ]
+% Specifies whether sensitivity variables are included in the error control test.
+% Note that sensitivity variables are always included in the nonlinear system
+% convergence test.
+%DQtype - Type of DQ approx. of the sensi. RHS [{Centered} | Forward ]
+% Specifies whether to use centered (second-order) or forward (first-order)
+% difference quotient approximations of the sensitivity eqation residuals.
+% This property is used only if a user-defined sensitivity residual function
+% was not provided.
+%DQparam - Cut-off parameter for the DQ approx. of the sensi. RES [ scalar | {0.0} ]
+% Specifies the value which controls the selection of the difference-quotient
+% scheme used in evaluating the sensitivity residuals (switch between
+% simultaneous or separate evaluations of the two components in the sensitivity
+% right-hand side). The default value 0.0 indicates the use of simultaenous approximation
+% exclusively (centered or forward, depending on the value of DQtype.
+% For DQparam >= 1, IDAS uses a simultaneous approximation if the estimated
+% DQ perturbations for states and parameters are within a factor of DQparam,
+% and separate approximations otherwise. Note that a value DQparam < 1
+% will inhibit switching! This property is used only if a user-defined sensitivity
+% residual function was not provided.
+%
+% See also
+% IDASensInit, IDASensReInit
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2007, The Regents of the University of California.
+% $Revision: 1.1 $Date: 2007/08/21 17:38:43 $
+
+% If called without input and output arguments, print out the possible keywords
+
+if (nargin == 0) & (nargout == 0)
+ fprintf(' method: [ Simultaneous | {Staggered} ]\n');
+ fprintf(' ParamField: [ string ]\n');
+ fprintf(' ParamList: [ integer vector ]\n');
+ fprintf(' ParamScales: [ vector ]\n');
+ fprintf(' RelTol: [ positive scalar ]\n');
+ fprintf(' AbsTol: [ row-vector or matrix ]\n');
+ fprintf(' ErrControl: [ false | {true} ]\n');
+ fprintf(' DQtype: [ {Centered} | {Forward} ]\n');
+ fprintf(' DQparam: [ scalar | {0.0} ]\n');
+ fprintf('\n');
+ return;
+end
+
+KeyNames = {
+ 'method'
+ 'ParamField'
+ 'ParamList'
+ 'ParamScales'
+ 'RelTol'
+ 'AbsTol'
+ 'ErrControl'
+ 'DQtype'
+ 'DQparam'
+ };
+
+options = idm_options(KeyNames,varargin{:});
+
diff --git a/sundialsTB/idas/IDASensToggleOff.m b/sundialsTB/idas/IDASensToggleOff.m
new file mode 100644
index 0000000..04ac508
--- /dev/null
+++ b/sundialsTB/idas/IDASensToggleOff.m
@@ -0,0 +1,16 @@
+function status = IDASensToggleOff()
+% IDASensToggleOff deactivates sensitivity calculations.
+% It does NOT deallocate sensitivity-related memory so that
+% sensitivity computations can be later toggled ON (through
+% IDASensReInit).
+%
+% Usage: IDASensToggleOff
+%
+% See also: IDASensInit, IDASensReInit
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2005, The Regents of the University of California.
+% $Revision: 1.3 $Date: 2007/12/05 21:58:19 $
+
+mode = 18;
+status = idm(mode);
diff --git a/sundialsTB/idas/IDASet.m b/sundialsTB/idas/IDASet.m
new file mode 100644
index 0000000..e525c61
--- /dev/null
+++ b/sundialsTB/idas/IDASet.m
@@ -0,0 +1,52 @@
+function status = IDASet(varargin)
+%IDASet changes optional input values during the integration.
+%
+% Usage: IDASet('NAME1',VALUE1,'NAME2',VALUE2,...)
+%
+% IDASet can be used to change some of the optional inputs during
+% the integration, i.e., without need for a solver reinitialization.
+% The property names accepted by IDASet are a subset of those valid
+% for IDASetOptions. Any unspecified properties are left unchanged.
+%
+% IDASet with no input arguments displays all property names.
+%
+%IDASet properties
+%(See also the IDAS User Guide)
+%
+%UserData - problem data passed unmodified to all user functions.
+% Set VALUE to be the new user data.
+%RelTol - Relative tolerance
+% Set VALUE to the new relative tolerance
+%AbsTol - absolute tolerance
+% Set VALUE to be either the new scalar absolute tolerance or
+% a vector of absolute tolerances, one for each solution component.
+%StopTime - Stopping time
+% Set VALUE to be a new value for the independent variable past which
+% the solution is not to proceed.
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2007, The Regents of the University of California.
+% $Revision: 1.2 $Date: 2007/12/05 21:58:19 $
+
+if (nargin == 0)
+ fprintf(' UserData\n');
+ fprintf('\n');
+ fprintf(' RelTol\n');
+ fprintf(' AbsTol\n');
+ fprintf(' StopTime\n');
+ fprintf('\n');
+ return;
+end
+
+KeyNames = {
+ 'UserData'
+ 'RelTol'
+ 'AbsTol'
+ 'StopTime'
+ };
+
+options = idm_options(KeyNames,varargin{:});
+
+mode = 33;
+
+status = idm(mode, options);
diff --git a/sundialsTB/idas/IDASetB.m b/sundialsTB/idas/IDASetB.m
new file mode 100644
index 0000000..98152e2
--- /dev/null
+++ b/sundialsTB/idas/IDASetB.m
@@ -0,0 +1,48 @@
+function status = IDASetB(idxB, varargin)
+%IDASetB changes optional input values during the integration.
+%
+% Usage: IDASetB( IDXB, 'NAME1',VALUE1,'NAME2',VALUE2,... )
+%
+% IDASetB can be used to change some of the optional inputs for
+% the backward problem identified by IDXB during the backward
+% integration, i.e., without need for a solver reinitialization.
+% The property names accepted by IDASet are a subset of those valid
+% for IDASetOptions. Any unspecified properties are left unchanged.
+%
+% IDASetB with no input arguments displays all property names.
+%
+%IDASetB properties
+%(See also the IDAS User Guide)
+%
+%UserData - problem data passed unmodified to all user functions.
+% Set VALUE to be the new user data.
+%RelTol - Relative tolerance
+% Set VALUE to the new relative tolerance
+%AbsTol - absolute tolerance
+% Set VALUE to be either the new scalar absolute tolerance or
+% a vector of absolute tolerances, one for each solution component.
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2007, The Regents of the University of California.
+% $Revision: 1.2 $Date: 2007/12/05 21:58:19 $
+
+if (nargin == 0)
+ fprintf(' UserData\n');
+ fprintf('\n');
+ fprintf(' RelTol\n');
+ fprintf(' AbsTol\n');
+ fprintf('\n');
+ return;
+end
+
+KeyNames = {
+ 'UserData'
+ 'RelTol'
+ 'AbsTol'
+ };
+
+options = idm_options(KeyNames,varargin{:});
+
+mode = 34;
+
+status = idm(mode, idxB, options);
diff --git a/sundialsTB/idas/IDASetOptions.m b/sundialsTB/idas/IDASetOptions.m
new file mode 100644
index 0000000..e1ba816
--- /dev/null
+++ b/sundialsTB/idas/IDASetOptions.m
@@ -0,0 +1,263 @@
+function options = IDASetOptions(varargin)
+%IDASetOptions creates an options structure for IDAS.
+%
+% Usage: OPTIONS = IDASetOptions('NAME1',VALUE1,'NAME2',VALUE2,...)
+% OPTIONS = IDASetOptions(OLDOPTIONS,'NAME1',VALUE1,...)
+%
+% OPTIONS = IDASetOptions('NAME1',VALUE1,'NAME2',VALUE2,...) creates
+% a IDAS options structure OPTIONS in which the named properties have
+% the specified values. Any unspecified properties have default values.
+% It is sufficient to type only the leading characters that uniquely
+% identify the property. Case is ignored for property names.
+%
+% OPTIONS = IDASetOptions(OLDOPTIONS,'NAME1',VALUE1,...) alters an
+% existing options structure OLDOPTIONS.
+%
+% IDASetOptions with no input arguments displays all property names
+% and their possible values.
+%
+%IDASetOptions properties
+%(See also the IDAS User Guide)
+%
+%UserData - User data passed unmodified to all functions [ empty ]
+% If UserData is not empty, all user provided functions will be
+% passed the problem data as their last input argument. For example,
+% the RES function must be defined as R = DAEFUN(T,YY,TP,DATA).
+%
+%RelTol - Relative tolerance [ positive scalar | {1e-4} ]
+% RelTol defaults to 1e-4 and is applied to all components of the solution
+% vector. See AbsTol.
+%AbsTol - Absolute tolerance [ positive scalar or vector | {1e-6} ]
+% The relative and absolute tolerances define a vector of error weights
+% with components
+% ewt(i) = 1/(RelTol*|y(i)| + AbsTol) if AbsTol is a scalar
+% ewt(i) = 1/(RelTol*|y(i)| + AbsTol(i)) if AbsTol is a vector
+% This vector is used in all error and convergence tests, which
+% use a weighted RMS norm on all error-like vectors v:
+% WRMSnorm(v) = sqrt( (1/N) sum(i=1..N) (v(i)*ewt(i))^2 ),
+% where N is the problem dimension.
+%MaxNumSteps - Maximum number of steps [positive integer | {500}]
+% IDASolve will return with an error after taking MaxNumSteps internal steps
+% in its attempt to reach the next output time.
+%InitialStep - Suggested initial stepsize [ positive scalar ]
+% By default, IDASolve estimates an initial stepsize h0 at the initial time
+% t0 as the solution of
+% WRMSnorm(h0^2 ydd / 2) = 1
+% where ydd is an estimated second derivative of y(t0).
+%MaxStep - Maximum stepsize [ positive scalar | {inf} ]
+% Defines an upper bound on the integration step size.
+%MaxOrder - Maximum method order [ 1-5 for BDF | {5} ]
+% Defines an upper bound on the linear multistep method order.
+%StopTime - Stopping time [ scalar ]
+% Defines a value for the independent variable past which the solution
+% is not to proceed.
+%RootsFn - Rootfinding function [ function ]
+% To detect events (roots of functions), set this property to the event
+% function. See IDARootFn.
+%NumRoots - Number of root functions [ integer | {0} ]
+% Set NumRoots to the number of functions for which roots are monitored.
+% If NumRoots is 0, rootfinding is disabled.
+%
+%SuppressAlgVars - Suppres algebraic vars. from error test [ on | {off} ]
+%VariableTypes - Alg./diff. variables [ vector ]
+%ConstraintTypes - Simple bound constraints [ vector ]
+%
+%LinearSolver - Linear solver type [{Dense}|Band|GMRES|BiCGStab|TFQMR]
+% Specifies the type of linear solver to be used for the Newton nonlinear
+% solver. Valid choices are: Dense (direct, dense Jacobian), Band (direct,
+% banded Jacobian), GMRES (iterative, scaled preconditioned GMRES),
+% BiCGStab (iterative, scaled preconditioned stabilized BiCG), TFQMR
+% (iterative, scaled transpose-free QMR).
+% The GMRES, BiCGStab, and TFQMR are matrix-free linear solvers.
+%JacobianFn - Jacobian function [ function ]
+% This propeerty is overloaded. Set this value to a function that returns
+% Jacobian information consistent with the linear solver used (see Linsolver).
+% If not specified, IDAS uses difference quotient approximations.
+% For the Dense linear solver, JacobianFn must be of type IDADenseJacFn and
+% must return a dense Jacobian matrix. For the Band linear solver, JacobianFn
+% must be of type IDABandJacFn and must return a banded Jacobian matrix.
+% For the iterative linear solvers, GMRES, BiCGStab, and TFQMR, JacobianFn must
+% be of type IDAJacTimesVecFn and must return a Jacobian-vector product.
+%KrylovMaxDim - Maximum number of Krylov subspace vectors [ integer | {5} ]
+% Specifies the maximum number of vectors in the Krylov subspace. This property
+% is used only if an iterative linear solver, GMRES, BiCGStab, or TFQMR is used
+% (see LinSolver).
+%GramSchmidtType - Gram-Schmidt orthogonalization [ Classical | {Modified} ]
+% Specifies the type of Gram-Schmidt orthogonalization (classical or modified).
+% This property is used only if the GMRES linear solver is used (see LinSolver).
+%PrecModule - Preconditioner module [ BBDPre | {UserDefined} ]
+% If PrecModule = 'UserDefined', then the user must provide at least a
+% preconditioner solve function (see PrecSolveFn)
+% IDAS provides one general-purpose preconditioner module, BBDPre, which can
+% be only used with parallel vectors. It 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,yp) approximating
+% f(t,y,yp) (see GlocalFn). The blocks are generated by a difference quotient
+% scheme on each processor independently. This scheme utilizes an assumed
+% banded structure with given half-bandwidths, mldq and mudq (specified through
+% LowerBwidthDQ and UpperBwidthDQ, respectively). However, the banded Jacobian
+% block kept by the scheme has half-bandwiths ml and mu (specified through
+% LowerBwidth and UpperBwidth), which may be smaller.
+%PrecSetupFn - Preconditioner setup function [ function ]
+% If PrecType is not 'None', PrecSetupFn specifies an optional function which,
+% together with PrecSolve, defines the preconditioner matrix, which must be an
+% aproximation to the Newton matrix. PrecSetupFn must be of type IDAPrecSetupFn.
+%PrecSolveFn - Preconditioner solve function [ function ]
+% If PrecType is not 'None', PrecSolveFn specifies a required function which
+% must solve a linear system Pz = r, for given r. PrecSolveFn must be of type
+% IDAPrecSolveFn.
+%GlocalFn - Local residual approximation function for BBDPre [ function ]
+% If PrecModule is BBDPre, GlocalFn specifies a required function that
+% evaluates a local approximation to the DAE residual. GlocalFn must
+% be of type IDAGlocFn.
+%GcommFn - Inter-process communication function for BBDPre [ function ]
+% If PrecModule is BBDPre, GcommFn specifies an optional function
+% to perform any inter-process communication required for the evaluation of
+% GlocalFn. GcommFn must be of type IDAGcommFn.
+%LowerBwidth - Jacobian/preconditioner lower bandwidth [ integer | {0} ]
+% This property is overloaded. If the Band linear solver is used (see LinSolver),
+% it specifies the lower half-bandwidth of the band Jacobian approximation.
+% If one of the three iterative linear solvers, GMRES, BiCGStab, or TFQMR is used
+% (see LinSolver) and if the BBDPre preconditioner module in IDAS is used
+% (see PrecModule), it specifies the lower half-bandwidth of the retained
+% banded approximation of the local Jacobian block.
+% LowerBwidth defaults to 0 (no sub-diagonals).
+%UpperBwidth - Jacobian/preconditioner upper bandwidth [ integer | {0} ]
+% This property is overloaded. If the Band linear solver is used (see LinSolver),
+% it specifies the upper half-bandwidth of the band Jacobian approximation.
+% If one of the three iterative linear solvers, GMRES, BiCGStab, or TFQMR is used
+% (see LinSolver) and if the BBDPre preconditioner module in IDAS is used
+% (see PrecModule), it specifies the upper half-bandwidth of the retained
+% banded approximation of the local Jacobian block.
+% UpperBwidth defaults to 0 (no super-diagonals).
+%LowerBwidthDQ - BBDPre preconditioner DQ lower bandwidth [ integer | {0} ]
+% Specifies the lower half-bandwidth used in the difference-quotient Jacobian
+% approximation for the BBDPre preconditioner (see PrecModule).
+%UpperBwidthDQ - BBDPre preconditioner DQ upper bandwidth [ integer | {0} ]
+% Specifies the upper half-bandwidth used in the difference-quotient Jacobian
+% approximation for the BBDPre preconditioner (see PrecModule).
+%
+%MonitorFn - User-provied monitoring function [ function ]
+% Specifies a function that is called after each successful integration step.
+% This function must have type IDAMonitorFn or IDAMonitorFnB, depending on
+% whether these options are for a forward or a backward problem, respectively.
+% Sample monitoring functions IDAMonitor and IDAMonitorB are provided
+% with IDAS.
+%MonitorData - User-provied data for the monitoring function [ struct ]
+% Specifies a data structure that is passed to the MonitorFn function every time
+% it is called.
+%
+%SensDependent - Backward problem depending on sensitivities [ {false} | true ]
+% Specifies whether the backward problem right-hand side depends on
+% forward sensitivites. If TRUE, the residual function provided for
+% this backward problem must have the appropriate type (see IDAResFnB).
+%
+%ErrorMessages - Post error/warning messages [ {true} | false ]
+% Note that any errors in IDAInit will result in a Matlab error, thus
+% stoping execution. Only subsequent calls to IDAS functions will respect
+% the value specified for 'ErrorMessages'.
+%
+%NOTES:
+%
+% The properties listed above that can only be used for forward problems
+% are: ConstraintTypes, StopTime, RootsFn, and NumRoots.
+%
+% The property SensDependent is relevant only for backward problems.
+%
+% See also
+% IDAInit, IDAReInit, IDAInitB, IDAReInitB
+% IDAResFn, IDARootFn
+% IDADenseJacFn, IDABandJacFn, IDAJacTimesVecFn
+% IDAPrecSetupFn, IDAPrecSolveFn
+% IDAGlocalFn, IDAGcommFn
+% IDAMonitorFn
+% IDAResFnB
+% IDADenseJacFnB, IDABandJacFnB, IDAJacTimesVecFnB
+% IDAPrecSetupFnB, IDAPrecSolveFnB
+% IDAGlocalFnB, IDAGcommFnB
+% IDAMonitorFnB
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2005, The Regents of the University of California.
+% $Revision: 1.5 $Date: 2007/12/05 21:58:19 $
+
+
+% If called without input and output arguments, print out the possible keywords
+
+if (nargin == 0) & (nargout == 0)
+ fprintf(' UserData: [ empty ]\n');
+ fprintf('\n');
+ fprintf(' RelTol: [ positive scalar | {1e-4} ]\n');
+ fprintf(' AbsTol: [ positive scalar or vector | {1e-6} ]\n');
+ fprintf(' MaxNumSteps: [ positive integer | {500} ]\n');
+ fprintf(' InitialStep: [ positive scalar ]\n');
+ fprintf(' MaxStep: [ positive scalar | {inf} ]\n');
+ fprintf(' MaxOrder: [ 1-12 for Adams, 1-5 for BDF | {5} ]\n');
+ fprintf(' StopTime: [ scalar ]\n');
+ fprintf(' RootsFn: [ function ]\n');
+ fprintf(' NumRoots: [ integer | {0} ]\n');
+ fprintf('\n');
+ fprintf(' SuppressAlgVars: [ on | {off} ]\n');
+ fprintf(' VariableTypes: [ vector ]\n');
+ fprintf(' ConstraintTypes: [ vector ]\n');
+ fprintf('\n');
+ fprintf(' LinearSolver: [ {Dense} | Band | GMRES | BiCGStab | TFQMR ]\n');
+ fprintf(' JacobianFn: [ function ]\n');
+ fprintf(' KrylovMaxDim: [ integer | {5} ]\n');
+ fprintf(' GramSchmidtType: [ Classical | {Modified} ]\n');
+ fprintf(' PrecModule: [ BBDPre | {UserDefined} ]\n');
+ fprintf(' PrecSetupFn: [ function ]\n');
+ fprintf(' PrecSolveFn: [ function ]\n');
+ fprintf(' GlocalFn: [ function ]\n');
+ fprintf(' GcommFn: [ function ]\n');
+ fprintf(' LowerBwidth: [ integer | {0} ]\n');
+ fprintf(' UpperBwidth: [ integer | {0} ]\n');
+ fprintf(' LowerBwidthDQ: [ integer | {0} ]\n');
+ fprintf(' UpperBwidthDQ: [ integer | {0} ]\n');
+ fprintf('\n');
+ fprintf(' MonitorFn: [ function ]\n');
+ fprintf(' MonitorData: [ struct ]\n');
+ fprintf('\n');
+ fprintf(' SensDependent: [ {false} | true ]\n');
+ fprintf('\n');
+ fprintf(' ErrorMessages: [ false | {true} ]\n');
+ fprintf('\n');
+ return;
+end
+
+KeyNames = {
+ 'UserData'
+ 'RelTol'
+ 'AbsTol'
+ 'MaxNumSteps'
+ 'InitialStep'
+ 'MaxStep'
+ 'MaxOrder'
+ 'StopTime'
+ 'RootsFn'
+ 'NumRoots'
+ 'VariableTypes'
+ 'ConstraintTypes'
+ 'SuppressAlgVars'
+ 'LinearSolver'
+ 'JacobianFn'
+ 'PrecModule'
+ 'PrecSetupFn'
+ 'PrecSolveFn'
+ 'KrylovMaxDim'
+ 'GramSchmidtType'
+ 'GlocalFn'
+ 'GcommFn'
+ 'LowerBwidth'
+ 'UpperBwidth'
+ 'LowerBwidthDQ'
+ 'UpperBwidthDQ'
+ 'MonitorFn'
+ 'MonitorData'
+ 'SensDependent'
+ 'ErrorMessages'
+ };
+
+options = idm_options(KeyNames,varargin{:});
\ No newline at end of file
diff --git a/sundialsTB/idas/IDASolve.m b/sundialsTB/idas/IDASolve.m
new file mode 100644
index 0000000..857d52b
--- /dev/null
+++ b/sundialsTB/idas/IDASolve.m
@@ -0,0 +1,56 @@
+function [varargout] = IDASolve(tout,itask)
+%IDASolve integrates the DAE.
+%
+% Usage: [STATUS, T, Y] = IDASolve ( TOUT, ITASK )
+% [STATUS, T, Y, YQ] = IDASolve (TOUT, ITASK )
+% [STATUS, T, Y, YS] = IDASolve ( TOUT, ITASK )
+% [STATUS, T, Y, YQ, YS] = IDASolve ( TOUT, ITASK )
+%
+% If ITASK is 'Normal', then the solver integrates from its current internal
+% T value to a point at or beyond TOUT, then interpolates to T = TOUT and returns
+% Y(TOUT). If ITASK is 'OneStep', then the solver takes one internal time step
+% and returns in Y the solution at the new internal time. In this case, TOUT
+% is used only during the first call to IDASolve to determine the direction of
+% integration and the rough scale of the problem. In either case, the time
+% reached by the solver is returned in T.
+%
+% If quadratures were computed (see IDAQuadInit), IDASolve will return their
+% values at T in the vector YQ.
+%
+% If sensitivity calculations were enabled (see IDASensInit), IDASolve will
+% return their values at T in the matrix YS. Each row in the matrix YS
+% represents the sensitivity vector with respect to one of the problem parameters.
+%
+% In ITASK =' Normal' mode, to obtain solutions at specific times T0,T1,...,TFINAL
+% (all increasing or all decreasing) use TOUT = [T0 T1 ... TFINAL]. In this case
+% the output arguments Y and YQ are matrices, each column representing the solution
+% vector at the corresponding time returned in the vector T. If computed, the
+% sensitivities are eturned in the 3-dimensional array YS, with YS(:,:,I) representing
+% the sensitivity vectors at the time T(I).
+%
+% On return, STATUS is one of the following:
+% 0: IDASolve succeeded and no roots were found.
+% 1: IDASolve succeded and returned at tstop.
+% 2: IDASolve succeeded, and found one or more roots.
+% -1: An error occurred (see printed message).
+%
+% See also IDASetOptions, IDAGetStats
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2007, The Regents of the University of California.
+% $Revision: 1.5 $Date: 2011/06/01 22:05:01 $
+
+
+mode = 20;
+
+if nargin ~= 2
+ error('Wrong number of input arguments');
+end
+
+if nargout < 3 || nargout > 5
+ error('Wrong number of output arguments');
+end
+
+varargout = cell (nargout, 1);
+
+[varargout{:}] = idm(mode,tout,itask);
diff --git a/sundialsTB/idas/IDASolveB.m b/sundialsTB/idas/IDASolveB.m
new file mode 100644
index 0000000..c9d6512
--- /dev/null
+++ b/sundialsTB/idas/IDASolveB.m
@@ -0,0 +1,50 @@
+function [varargout] = IDASolveB(tout,itask)
+%IDASolveB integrates the backward DAE.
+%
+% Usage: [STATUS, T, YB] = IDASolveB ( TOUT, ITASK )
+% [STATUS, T, YB, YQB] = IDASolveB ( TOUT, ITASK )
+%
+% If ITASK is 'Normal', then the solver integrates from its current internal
+% T value to a point at or beyond TOUT, then interpolates to T = TOUT and returns
+% YB(TOUT). If ITASK is 'OneStep', then the solver takes one internal time step
+% and returns in YB the solution at the new internal time. In this case, TOUT
+% is used only during the first call to IDASolveB to determine the direction of
+% integration and the rough scale of the problem. In either case, the time
+% reached by the solver is returned in T.
+%
+% If quadratures were computed (see IDAQuadInitB), IDASolveB will return their
+% values at T in the vector YQB.
+%
+% In ITASK =' Normal' mode, to obtain solutions at specific times T0,T1,...,TFINAL
+% (all increasing or all decreasing) use TOUT = [T0 T1 ... TFINAL]. In this case
+% the output arguments YB and YQB are matrices, each column representing the solution
+% vector at the corresponding time returned in the vector T.
+%
+% If more than one backward problem was defined, the return arguments are cell
+% arrays, with T{IDXB}, YB{IDXB}, and YQB{IDXB} corresponding to the backward
+% problem with index IDXB (as returned by IDAInitB).
+%
+% On return, STATUS is one of the following:
+% 0: IDASolveB succeeded.
+% 1: IDASolveB succeded and return at a tstop value (internally set).
+% -1: An error occurred (see printed message).
+%
+% See also IDASetOptions, IDAGetStatsB
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2007, The Regents of the University of California.
+% $Revision: 1.5 $Date: 2011/06/01 22:05:01 $
+
+mode = 21;
+
+if nargin ~= 2
+ error('Wrong number of input arguments');
+end
+
+if nargout < 3 || nargout > 4
+ error('Wrong number of output arguments');
+end
+
+varargout = cell (nargout, 1);
+[varargout{:}] = idm(mode,tout,itask);
+
diff --git a/sundialsTB/idas/examples_ser/midasBruss_ASA_dns.m b/sundialsTB/idas/examples_ser/midasBruss_ASA_dns.m
new file mode 100644
index 0000000..3ef330c
--- /dev/null
+++ b/sundialsTB/idas/examples_ser/midasBruss_ASA_dns.m
@@ -0,0 +1,446 @@
+function midasBruss_ASA_dns
+%midasBruss_ASA_dns - ASA example for the Brusselator problem
+% This example solves the forward and adjoint problems for
+% the 2D Brusselator example.
+%
+% See also: midasBruss_dns
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2007, The Regents of the University of California.
+% $Revision: 1.1 $Date: 2007/10/26 16:30:48 $
+
+%--------------
+% Problem data
+%--------------
+
+eps = 2.0e-3; % diffusion param
+A = 1.0;
+B = 3.4;
+
+% Spatial length 0 <= x,y, <= L
+L = 1.0;
+
+% grid size
+mx = 20;
+my = 20;
+dx = L/mx;
+dy = L/my;
+
+% coefficients in central FD
+hdif = eps/dx^2;
+vdif = eps/dy^2;
+
+% problem dimension
+nx = mx+1;
+ny = my+1;
+n = 2*nx*ny;
+
+x = linspace(0,L,nx);
+y = linspace(0,L,ny);
+
+% Load user data structure
+data.eps = eps;
+data.A = A;
+data.B = B;
+data.L = L;
+data.dx = dx;
+data.dy = dy;
+data.nx = nx;
+data.ny = ny;
+data.x = x;
+data.y = y;
+data.hdif = hdif;
+data.vdif = vdif;
+
+% ---------------------
+% Initialize integrator
+% ---------------------
+
+% Integration limits
+
+t0 = 0.0;
+tf = 1.0;
+
+% Initial conditions
+
+[u, v] = BRUSic(data);
+Y = UV2Y(u, v, data);
+Yp = zeros(n,1);
+
+% Specify algebraic variables
+
+u_id = ones(ny,nx);
+u_id(1,:) = 0;
+u_id(ny,:) = 0;
+u_id(:,1) = 0;
+u_id(:,nx) = 0;
+
+v_id = ones(ny,nx);
+v_id(1,:) = 0;
+v_id(ny,:) = 0;
+v_id(:,1) = 0;
+v_id(:,nx) = 0;
+
+id = UV2Y(u_id, v_id, data);
+
+% Optional inputs
+
+options = IDASetOptions('UserData',data,...
+ 'RelTol',1.e-5,...
+ 'AbsTol',1.e-5,...
+ 'VariableTypes',id,...
+ 'suppressAlgVars','on',...
+ 'MaxNumSteps', 1000,...
+ 'LinearSolver','Dense');
+
+% Initialize forward problem
+
+IDAInit(@BRUSres,t0,Y,Yp,options);
+
+% Compute consistent I.C.
+
+[status, Y, Yp] = IDACalcIC(tf, 'FindAlgebraic');
+
+% --------------
+% Initialize ASA
+% --------------
+
+IDAAdjInit(150, 'Hermite');
+
+% ---------------
+% Integrate to tf
+% ---------------
+
+[status, t, Y] = IDASolve(tf, 'Normal');
+
+[u,v] = Y2UV(Y, data);
+
+stats_fwd = IDAGetStats;
+
+plotSol(t,Y,data);
+
+% ---------------------------
+% Initialize backward problem
+% ---------------------------
+
+% Specify algebraic variables
+
+l_id = ones(ny,nx);
+l_id(1,:) = 0;
+l_id(ny,:) = 0;
+l_id(:,1) = 0;
+l_id(:,nx) = 0;
+
+m_id = ones(ny,nx);
+m_id(1,:) = 0;
+m_id(ny,:) = 0;
+m_id(:,1) = 0;
+m_id(:,nx) = 0;
+
+idB = UV2Y(l_id, m_id, data);
+
+% Final conditions
+
+l = ones(ny,nx);
+m = zeros(ny,nx);
+YB = UV2Y(l, m, data);
+
+lp = -2.0 * u .* v .* l + (B+1) * l;
+mp = - l .* (u.^2);
+YBp = UV2Y(lp, mp, data);
+
+% Optional inputs
+
+optionsB = IDASetOptions('UserData',data,...
+ 'RelTol',1.e-5,...
+ 'AbsTol',1.e-5,...
+ 'VariableTypes',id,...
+ 'suppressAlgVars','on',...
+ 'LinearSolver','Dense');
+
+% Initialize backward problem
+
+idxB = IDAInitB(@BRUSresB,tf,YB,YBp,optionsB);
+
+% --------------------------
+% Backward integration to t0
+% --------------------------
+
+[status, t, YB] = IDASolveB(t0,'Normal');
+
+plotSol(t,YB,data);
+
+% -----------
+% Free memory
+% -----------
+
+IDAFree;
+
+return
+
+
+
+
+
+
+% ====================================================================================
+% Initial conditions
+% ====================================================================================
+
+function [u0, v0] = BRUSic(data)
+
+dx = data.dx;
+dy = data.dy;
+nx = data.nx;
+ny = data.ny;
+L = data.L;
+x = data.x;
+y = data.y;
+
+n = 2*nx*ny;
+
+[x2D , y2D] = meshgrid(x,y);
+
+u0 = 1.0 - 0.5 * cos(pi*y2D/L);
+u0(1,:) = u0(2,:);
+u0(ny,:) = u0(ny-1,:);
+u0(:,1) = u0(:,2);
+u0(:,nx) = u0(:,nx-1);
+
+v0 = 3.5 - 2.5*cos(pi*x2D/L);
+v0(1,:) = v0(2,:);
+v0(ny,:) = v0(ny-1,:);
+v0(:,1) = v0(:,2);
+v0(:,nx) = v0(:,nx-1);
+
+return
+
+
+
+
+
+% ====================================================================================
+% Residual function
+% ====================================================================================
+
+function [res, flag, new_data] = BRUSres(t,Y,Yp,data)
+
+nx = data.nx;
+ny = data.ny;
+
+A = data.A;
+B = data.B;
+
+hdif = data.hdif;
+vdif = data.vdif;
+
+% Convert Y and Yp to (u,v) and (up, vp)
+
+[u,v] = Y2UV(Y,data);
+[up,vp] = Y2UV(Yp,data);
+
+% 2D residuals
+
+ru = zeros(ny,nx);
+rv = zeros(ny,nx);
+
+% Inside the domain
+
+for iy = 2:ny-1
+
+ for ix = 2:nx-1
+
+ uu = u(iy,ix);
+ vv = v(iy,ix);
+
+ ru(iy,ix) = up(iy,ix) ...
+ - hdif * ( u(iy,ix+1) - 2*uu + u(iy,ix-1) ) ...
+ - vdif * ( u(iy+1,ix) - 2*uu + u(iy-1,ix) ) ...
+ - A + (B+1)*uu - uu^2 * vv;
+
+ rv(iy,ix) = vp(iy,ix) ...
+ - hdif * ( v(iy,ix+1) - 2*vv + v(iy,ix-1) ) ...
+ - vdif * ( v(iy+1,ix) - 2*vv + v(iy-1,ix) ) ...
+ - B*uu + uu^2 * vv;
+
+ end
+
+end
+
+% Boundary conditions
+
+ru(1,:) = u(1,:) - u(2,:);
+ru(ny,:) = u(ny,:) - u(ny-1,:);
+ru(:,1) = u(:,1) - u(:,2);
+ru(:,nx) = u(:,nx) - u(:,nx-1);
+
+rv(1,:) = v(1,:) - v(2,:);
+rv(ny,:) = v(ny,:) - v(ny-1,:);
+rv(:,1) = v(:,1) - v(:,2);
+rv(:,nx) = v(:,nx) - v(:,nx-1);
+
+% Convert (ru,rv) to res
+
+res = UV2Y(ru,rv,data);
+
+% Return flag and pb. data
+
+flag = 0;
+new_data = [];
+
+
+
+
+% ====================================================================================
+% Backward residual function
+% ====================================================================================
+
+function [resB, flag, new_data] = BRUSresB(t, Y, Yp, YB, YBp, data)
+
+nx = data.nx;
+ny = data.ny;
+
+A = data.A;
+B = data.B;
+
+hdif = data.hdif;
+vdif = data.vdif;
+
+% Convert Y to (u,v)
+
+[u,v] = Y2UV(Y,data);
+
+% Convert YB and YBp to (l,m) and (lp,mp)
+
+[l,m] = Y2UV(YB,data);
+[lp,mp] = Y2UV(YBp,data);
+
+% 2D residuals
+
+rl = zeros(ny,nx);
+rm = zeros(ny,nx);
+
+% Inside the domain
+
+for iy = 2:ny-1
+
+ for ix = 2:nx-1
+
+ uu = u(iy,ix);
+ vv = v(iy,ix);
+
+ ll = l(iy,ix);
+ mm = m(iy,ix);
+
+ rl(iy,ix) = lp(iy,ix) ...
+ + hdif * ( l(iy,ix+1) - 2*ll + l(iy,ix-1) ) ...
+ + vdif * ( l(iy+1,ix) - 2*ll + l(iy-1,ix) ) ...
+ + 2*uu*vv*ll - (B+1)*ll + B*mm - 2*uu*vv*mm;
+
+ rm(iy,ix) = mp(iy,ix) ...
+ + hdif * ( m(iy,ix+1) - 2*mm + m(iy,ix-1) ) ...
+ + vdif * ( m(iy+1,ix) - 2*mm + m(iy-1,ix) ) ...
+ + ll * uu^2 - mm * uu^2;
+
+ end
+
+end
+
+% Boundary conditions
+
+rl(1,:) = l(1,:) - l(2,:);
+rl(ny,:) = l(ny,:) - l(ny-1,:);
+rl(:,1) = l(:,1) - l(:,2);
+rl(:,nx) = l(:,nx) - l(:,nx-1);
+
+rm(1,:) = m(1,:) - m(2,:);
+rm(ny,:) = m(ny,:) - m(ny-1,:);
+rm(:,1) = m(:,1) - m(:,2);
+rm(:,nx) = m(:,nx) - m(:,nx-1);
+
+% Convert (rl,rm) to resB
+
+resB = UV2Y(rl,rm,data);
+
+% Return flag and pb. data
+
+flag = 0;
+new_data = [];
+
+
+
+
+
+% ====================================================================================
+% 1D <-> 2D conversion functions
+% ====================================================================================
+
+function y = UV2Y(u, v, data)
+
+nx = data.nx;
+ny = data.ny;
+
+u1 = reshape(u, 1, nx*ny);
+v1 = reshape(v, 1, nx*ny);
+
+y = reshape([u1;v1], 2*nx*ny,1);
+
+return
+
+
+function [u,v] = Y2UV(y, data)
+
+nx = data.nx;
+ny = data.ny;
+
+y2 = reshape(y, 2, nx*ny);
+
+u = reshape(y2(1,:), ny, nx);
+v = reshape(y2(2,:), ny, nx);
+
+return
+
+
+
+
+% ====================================================================================
+% Plot (u,v)
+% ====================================================================================
+
+function plotSol(t,Y,data)
+
+x = data.x;
+y = data.y;
+
+[u,v] = Y2UV(Y, data);
+
+figure;
+set(gcf,'position',[600 600 650 300])
+
+subplot(1,2,1)
+surfc(x,y,u);
+shading interp
+%view(0,90)
+view(-15,35)
+axis tight
+box on
+grid off
+xlabel('x');
+ylabel('y');
+title(sprintf('u(x,y,%g)',t))
+%colorbar('horiz');
+
+subplot(1,2,2)
+surfc(x,y,v);
+shading interp
+%view(0,90)
+view(-15,35)
+axis tight
+box on
+grid off
+xlabel('x');
+ylabel('y');
+title(sprintf('v(x,y,%g)',t))
+%colorbar('horiz');
+
+return
diff --git a/sundialsTB/idas/examples_ser/midasBruss_dns.m b/sundialsTB/idas/examples_ser/midasBruss_dns.m
new file mode 100644
index 0000000..2148044
--- /dev/null
+++ b/sundialsTB/idas/examples_ser/midasBruss_dns.m
@@ -0,0 +1,301 @@
+function midasBruss_dns
+%midasBruss_dns Brusselator example
+% This example solves the 2D Brusselator example on an (mx)x(my)
+% grid of the square with side L, using the MOL with central
+% finite-differences for the semidiscretization in space.
+% Homogeneous BC on all sides are incorporated as algebraic
+% constraints.
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2007, The Regents of the University of California.
+% $Revision: 1.1 $Date: 2007/10/26 16:30:48 $
+
+%--------------
+% Problem data
+%--------------
+
+eps = 2.0e-3; % diffusion param
+A = 1.0;
+B = 3.4;
+
+% Spatial length 0 <= x,y, <= L
+L = 1.0;
+
+% grid size
+mx = 20;
+my = 20;
+dx = L/mx;
+dy = L/my;
+
+% coefficients in central FD
+hdif = eps/dx^2;
+vdif = eps/dy^2;
+
+% problem dimension
+nx = mx+1;
+ny = my+1;
+n = 2*nx*ny;
+
+x = linspace(0,L,nx);
+y = linspace(0,L,ny);
+
+data.eps = eps;
+data.A = A;
+data.B = B;
+data.L = L;
+data.dx = dx;
+data.dy = dy;
+data.nx = nx;
+data.ny = ny;
+data.x = x;
+data.y = y;
+data.hdif = hdif;
+data.vdif = vdif;
+
+%-------------------
+% Initial conditions
+%-------------------
+
+[u0, v0] = BRUSic(data);
+Y0 = UV2Y(u0, v0, data);
+Yp0 = zeros(n,1);
+
+% ---------------------
+% Initialize integrator
+% ---------------------
+
+% Integration limits
+
+t0 = 0.0;
+tf = 1.0;
+
+% Specify algebraic variables
+
+u_id = ones(ny,nx);
+u_id(1,:) = 0;
+u_id(ny,:) = 0;
+u_id(:,1) = 0;
+u_id(:,nx) = 0;
+
+v_id = ones(ny,nx);
+v_id(1,:) = 0;
+v_id(ny,:) = 0;
+v_id(:,1) = 0;
+v_id(:,nx) = 0;
+
+id = UV2Y(u_id, v_id, data);
+
+options = IDASetOptions('UserData',data,...
+ 'RelTol',1.e-5,...
+ 'AbsTol',1.e-5,...
+ 'VariableTypes',id,...
+ 'suppressAlgVars','on',...
+ 'MaxNumSteps', 1000,...
+ 'LinearSolver','Dense');
+
+% Initialize IDAS
+
+IDAInit(@BRUSres,t0,Y0,Yp0,options);
+
+% Compute consistent I.C.
+
+[status, Y0, Yp0] = IDACalcIC(tf, 'FindAlgebraic');
+
+% ---------------
+% Integrate to tf
+% ---------------
+
+plotSol(t0,Y0,data);
+
+[status, t, Y] = IDASolve(tf, 'Normal');
+
+plotSol(t,Y,data);
+
+% -----------
+% Free memory
+% -----------
+
+IDAFree;
+
+
+%%save foo.mat t Y data
+
+return
+
+
+% ====================================================================================
+% Initial conditions
+% ====================================================================================
+
+function [u0, v0] = BRUSic(data)
+
+dx = data.dx;
+dy = data.dy;
+nx = data.nx;
+ny = data.ny;
+L = data.L;
+x = data.x;
+y = data.y;
+
+n = 2*nx*ny;
+
+[x2D , y2D] = meshgrid(x,y);
+
+u0 = 1.0 - 0.5 * cos(pi*y2D/L);
+u0(1,:) = u0(2,:);
+u0(ny,:) = u0(ny-1,:);
+u0(:,1) = u0(:,2);
+u0(:,nx) = u0(:,nx-1);
+
+v0 = 3.5 - 2.5*cos(pi*x2D/L);
+v0(1,:) = v0(2,:);
+v0(ny,:) = v0(ny-1,:);
+v0(:,1) = v0(:,2);
+v0(:,nx) = v0(:,nx-1);
+
+return
+
+
+% ====================================================================================
+% 1D <-> 2D conversion functions
+% ====================================================================================
+
+function y = UV2Y(u, v, data)
+
+nx = data.nx;
+ny = data.ny;
+
+u1 = reshape(u, 1, nx*ny);
+v1 = reshape(v, 1, nx*ny);
+
+y = reshape([u1;v1], 2*nx*ny,1);
+
+return
+
+
+function [u,v] = Y2UV(y, data)
+
+nx = data.nx;
+ny = data.ny;
+
+y2 = reshape(y, 2, nx*ny);
+
+u = reshape(y2(1,:), ny, nx);
+v = reshape(y2(2,:), ny, nx);
+
+return
+
+% ====================================================================================
+% Residual function
+% ====================================================================================
+
+function [res, flag, new_data] = BRUSres(t,Y,Yp,data)
+
+dx = data.dx;
+dy = data.dy;
+nx = data.nx;
+ny = data.ny;
+
+eps = data.eps;
+A = data.A;
+B = data.B;
+L = data.L;
+
+hdif = data.hdif;
+vdif = data.vdif;
+
+% Convert Y and Yp to (u,v) and (up, vp)
+
+[u,v] = Y2UV(Y,data);
+[up,vp] = Y2UV(Yp,data);
+
+% 2D residuals
+
+ru = zeros(ny,nx);
+rv = zeros(ny,nx);
+
+% Inside the domain
+
+for iy = 2:ny-1
+
+ for ix = 2:nx-1
+
+ uu = u(iy,ix);
+ vv = v(iy,ix);
+
+ ru(iy,ix) = up(iy,ix) - ...
+ hdif * ( u(iy,ix+1) - 2*uu + u(iy,ix-1) ) - ...
+ vdif * ( u(iy+1,ix) - 2*uu + u(iy-1,ix) ) - ...
+ A + (B+1)*uu - uu^2 * vv;
+
+ rv(iy,ix) = vp(iy,ix) - ...
+ hdif * ( v(iy,ix+1) - 2*vv + v(iy,ix-1) ) - ...
+ vdif * ( v(iy+1,ix) - 2*vv + v(iy-1,ix) ) - ...
+ B*uu + uu^2 * vv;
+
+ end
+
+end
+
+% Boundary conditions
+
+ru(1,:) = u(1,:) - u(2,:);
+ru(ny,:) = u(ny,:) - u(ny-1,:);
+ru(:,1) = u(:,1) - u(:,2);
+ru(:,nx) = u(:,nx) - u(:,nx-1);
+
+rv(1,:) = v(1,:) - v(2,:);
+rv(ny,:) = v(ny,:) - v(ny-1,:);
+rv(:,1) = v(:,1) - v(:,2);
+rv(:,nx) = v(:,nx) - v(:,nx-1);
+
+% Convert (ru,rv) to res
+
+res = UV2Y(ru,rv,data);
+
+% Return flag and pb. data
+
+flag = 0;
+new_data = [];
+
+% ====================================================================================
+% Plot (u,v)
+% ====================================================================================
+
+function plotSol(t,Y,data)
+
+x = data.x;
+y = data.y;
+
+[u,v] = Y2UV(Y, data);
+
+figure;
+set(gcf,'position',[600 600 650 300])
+
+subplot(1,2,1)
+surfc(x,y,u);
+shading interp
+%view(0,90)
+view(-15,35)
+axis tight
+box on
+grid off
+xlabel('x');
+ylabel('y');
+title(sprintf('u(x,y,%g)',t))
+%colorbar('horiz');
+
+subplot(1,2,2)
+surfc(x,y,v);
+shading interp
+%view(0,90)
+view(-15,35)
+axis tight
+box on
+grid off
+xlabel('x');
+ylabel('y');
+title(sprintf('v(x,y,%g)',t))
+%colorbar('horiz');
+
+return
diff --git a/sundialsTB/idas/examples_ser/midasHeat2D_bnd.m b/sundialsTB/idas/examples_ser/midasHeat2D_bnd.m
new file mode 100644
index 0000000..369b325
--- /dev/null
+++ b/sundialsTB/idas/examples_ser/midasHeat2D_bnd.m
@@ -0,0 +1,175 @@
+function midasHeat2D_bnd
+%midasHeat2D_bnd: 2D heat equation, serial, banded.
+%
+% This example solves a discretized 2D heat equation problem.
+% This version uses the band solver IDABand, and IDACalcIC.
+%
+% The DAE system solved is a spatial discretization of the PDE
+% du/dt = d^2u/dx^2 + d^2u/dy^2
+% on the unit square. The boundary condition is u = 0 on all edges.
+% Initial conditions are given by u = 16 x (1 - x) y (1 - y).
+% The PDE is treated with central differences on a uniform M x M
+% grid. The values of u at the interior points satisfy ODEs, and
+% equations u = 0 at the boundaries are appended, to form a DAE
+% system of size N = M^2. Here M = 10.
+%
+% The system is solved with IDA using the banded linear system
+% solver, half-bandwidths equal to M, and default
+% difference-quotient 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.)
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2007, The Regents of the University of California.
+% $Revision: 1.1 $Date: 2007/10/26 16:30:48 $
+
+m = 20;
+N = m^2;
+data.m = m;
+data.N = N;
+data.dx = 1.0/(m-1);
+data.c = 1.0/data.dx^2;
+
+fp = figure;
+set(gcf,'position',[250 175 560 900]);
+
+[t0,yy0,yp0,id,cnstr] = ic(data);
+
+% Plot initial guess for IC
+
+figure(fp);
+subplot(2,1,1);
+hold on
+hs1 = surf(reshape(yy0,m,m));
+shading interp
+set(hs1,'FaceAlpha',0.35);
+box on
+view(-30,30)
+
+options = IDASetOptions('UserData',data,...
+ 'RelTol',0.0,...
+ 'AbsTol',1.0e-3,...
+ 'VariableTypes',id,...
+ 'ConstraintTypes',cnstr,...
+ 'LinearSolver','Band',...
+ 'LowerBwidth',m,...
+ 'UpperBwidth',m);
+
+IDAInit(@resfun,t0,yy0,yp0,options);
+
+tout = 0.01;
+[status, yy0_mod, yp0_mod] = IDACalcIC(tout, 'FindAlgebraic');
+
+% Plot corrected IC
+
+figure(fp);
+subplot(2,1,1);
+hs1 = surf(reshape(yy0_mod,m,m));
+set(hs1,'FaceColor','none');
+
+
+% Plot solution
+
+subplot(2,1,2);
+hold on
+hs1 = surf(reshape(yy0_mod,m,m));
+shading interp
+view(-30,30)
+zlim_yy = get(gca,'ZLim');
+box on
+
+fprintf('t = %.4f [Press any key]\n',t0);
+pause;
+
+nout = 5;
+tout = 0.01;
+
+for iout = 1:nout
+ [status,t,yy] = IDASolve(tout,'Normal');
+ tout = 2*tout;
+
+ figure(fp);
+ subplot(2,1,2);
+ set(hs1,'FaceAlpha',0.15);
+ hs1 = surf(reshape(yy,m,m));
+ shading interp
+ set(gca,'ZLim',zlim_yy);
+
+ fprintf('t = %.4f [Press any key]\n',t);
+ pause;
+
+end
+
+IDAFree;
+
+
+function [t,yy,yp,id,cnstr] = ic(data)
+
+m = data.m;
+N = data.N;
+dx = data.dx;
+
+id = ones(N,1);
+cnstr = ones(N,1);
+yy = zeros(N,1);
+yp = zeros(N,1);
+
+t = 0.0;
+
+% Initialize yy on all grid points. */
+for j=0:m-1
+ yfact = dx * j;
+ offset = m*j;
+ for i=0:m-1
+ xfact = dx * i;
+ loc = offset + i + 1;
+ yy(loc) = 16.0 * xfact * (1.0 - xfact) * yfact * (1.0 - yfact);
+ end
+end
+
+% The residual gives the negative of ODE RHS values at
+% interior points.
+yp = zeros(N,1);
+[yp,flag,new_data] = resfun(t,yy,yp,data);
+yp = -yp;
+
+% Finally, set values of yy, yp, and id at boundary points.
+for j=0:m-1
+ offset = m*j;
+ for i=0:m-1
+ loc = offset + i + 1;
+ if (j == 0 || j == m-1 || i == 0 || i == m-1 )
+ yy(loc) = 0.1;
+ yp(loc) = 0.0;
+ id(loc) = 0.0;
+ end
+ end
+end
+
+% ====================================================================
+
+function [rr,flag,new_data] = resfun(t,yy,yp,data)
+
+m = data.m;
+N = data.N;
+dx = data.dx;
+c = data.c;
+
+% Initialize resval to uu, to take care of boundary equations.
+rr = yy;
+
+% Loop over interior points; set rr = yp - (central difference).
+for j = 1:m-2
+ offset = m*j;
+ for i = 1:m-2
+ loc = offset + i + 1;
+ rr(loc) = yp(loc) - c * ...
+ (yy(loc-1) + yy(loc+1) + yy(loc-m) + yy(loc+m) - 4.0*yy(loc));
+ end
+end
+
+flag = 0;
+new_data = [];
\ No newline at end of file
diff --git a/sundialsTB/idas/examples_ser/midasPendI1_dns.m b/sundialsTB/idas/examples_ser/midasPendI1_dns.m
new file mode 100644
index 0000000..72dd96c
--- /dev/null
+++ b/sundialsTB/idas/examples_ser/midasPendI1_dns.m
@@ -0,0 +1,183 @@
+function midasPendI1_dns
+%midasPendI1_dns - Simple pendulum modeled as an index-1 DAE
+% The pendulum is modeled using the x and y positions with
+% the constraint x^2 + y^2 = L^2
+% The index-1 DAE formulation (in first-order form) includes
+% differential equations for the positions and velocities and
+% the acceleration-level constraint.
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2007, The Regents of the University of California.
+% $Revision: 1.2 $Date: 2007/12/05 21:58:19 $
+
+
+% x, y, vx, vy, lam
+neq = 5;
+
+t0 = 0.0;
+tf = 10.0;
+
+id = ones(neq,1);
+id(5) = 0;
+
+options = IDASetOptions('RelTol',1.e-6,...
+ 'AbsTol',1.e-6,...
+ 'VariableTypes',id,...
+ 'MaxNumSteps', 1000,...
+ 'LinearSolver','Dense',...
+ 'JacobianFn', at pend_J);
+%mondata.update = 100;
+%options = IDASetOptions(options,'MonitorFn', at IDAMonitor,'MonitorData',mondata);
+
+y0 = zeros(neq,1);
+y0(1) = 1.0;
+y0(5) = 0.1;
+yp0 = zeros(neq,1);
+fprintf('Estimated IC\n');
+disp([y0 yp0])
+
+IDAInit(@pend_f,t0,y0,yp0,options);
+
+[status, y0_mod, yp0_mod] = IDACalcIC(tf, 'FindAlgebraic');
+fprintf('Corrected IC\n');
+disp([y0_mod yp0_mod])
+
+it = 1;
+time(it) = t0;
+sol_y(it,:) = y0_mod';
+[pc(it) vc(it)] = pend_constr(t0,y0_mod);
+
+%t = t0;
+%t_start = clock;
+%while t < tf
+% [status,t,y] = IDASolve(tf,'OneStep');
+% it = it+1;
+% time(it) = t;
+% sol_y(it,:) = y';
+% % Compute position and velocity constraint violations
+% [pc(it) vc(it)] = pend_constr(t,y);
+%end
+%runtime = etime(clock,t_start);
+
+
+dt = 0.1;
+nt = ceil((tf-t0)/dt);
+
+t_start = clock;
+for it = 1:nt
+ tout = t0 + it*dt;
+ [status,t,y] = IDASolve(tout,'Normal');
+ time(it) = t;
+ sol_y(it,:) = y';
+% Compute position and velocity constraint violations
+ [pc(it) vc(it)] = pend_constr(t,y);
+end
+runtime = etime(clock,t_start);
+
+fprintf('Solver stats:\n');
+disp(IDAGetStats);
+fprintf('Run time: %f\n',runtime);
+
+
+figure;
+
+subplot(3,1,1)
+hold on
+plot(time,sol_y(:,1),'b');
+plot(time,sol_y(:,2),'r');
+box on
+set(gca,'XLim',[t0 tf])
+title('position');
+legend('x','y');
+
+subplot(3,1,2)
+hold on
+plot(time,sol_y(:,3),'b');
+plot(time,sol_y(:,4),'r');
+box on
+set(gca,'XLim',[t0 tf])
+title('velocity');
+legend('v_x', 'v_y');
+
+subplot(3,1,3)
+plot(time,sol_y(:,5));
+box on
+set(gca,'XLim',[t0 tf])
+title('Lagrange multiplier');
+
+figure
+
+plotyy(time, pc, time, vc);
+box on
+title('position and velocity constraint violations');
+
+figure
+
+subplot(2,1,1)
+plot(sol_y(:,1),sol_y(:,2));
+axis equal
+axis tight
+box on
+grid on
+xlabel('x');
+ylabel('y');
+title('trajectory');
+
+phi = atan2( sol_y(:,1) , sol_y(:,2) );
+phi_d = ( sol_y(:,1).*sol_y(:,4) - sol_y(:,2).*sol_y(:,3) ) ./ ( sol_y(:,1).^2 + sol_y(:,2).^2 ) ;
+subplot(2,1,2)
+plot3(time,phi, phi_d);
+xlabel('time');
+ylabel('\phi');
+zlabel('\phi^\prime');
+view(-30,15);
+set(gca,'XLim',[t0 tf])
+grid on
+box on
+title('phase plot');
+
+IDAFree;
+
+% ================================================================================
+
+function [res, flag, new_data] = pend_f(t,y,yp)
+% Residual function for a simple pendulum
+% mass = 1.0
+% length = 1.0
+% damping coeff. = 0.3
+% g = 9.81
+
+res = [
+ -yp(1) + y(3)
+ -yp(2) + y(4)
+ -yp(3) - 2*y(1)*y(5) - 0.3*y(3)
+ -yp(4) + 9.81 - 2*y(2)*y(5) - 0.3*y(4)
+ -2*y(5) + y(3)^2 - 0.3*y(1)*y(3) + y(4)^2 + y(2)*(9.81-0.3*y(4))
+ ];
+
+flag = 0;
+new_data = [];
+
+% ================================================================================
+
+function [J, flag, new_data] = pend_J(t,y,yp, rr, cj)
+
+J = [
+ -cj 0 1 0 0
+ 0 -cj 0 1 0
+ -2*y(5) 0 -cj-0.3 0 -2*y(1)
+ 0 -2*y(5) 0 -cj-0.3 -2*y(2)
+ -0.3*y(3) 9.81-0.3*y(4) 2*y(3)-0.3*y(1) 2*y(4)-0.3*y(2) -2
+ ];
+
+flag = 0;
+new_data = [];
+
+% ================================================================================
+
+function [pc, vc] = pend_constr(t,y)
+% Position and velocity constraints
+%
+
+pc = y(1)^2 + y(2)^2 - 1.0;
+vc = y(1)*y(3) + y(2)*y(4);
\ No newline at end of file
diff --git a/sundialsTB/idas/examples_ser/midasPendI2_dns.m b/sundialsTB/idas/examples_ser/midasPendI2_dns.m
new file mode 100644
index 0000000..437a07f
--- /dev/null
+++ b/sundialsTB/idas/examples_ser/midasPendI2_dns.m
@@ -0,0 +1,158 @@
+function midasPendI2_dns
+%midasPendI1_dns - Simple pendulum modeled as an index-2 DAE
+% The pendulum is modeled using the x and y positions with
+% the constraint x^2 + y^2 = L^2
+% The stabilized index-2 (GGL formulation) DAE (in first-order form)
+% includes differential equations for the positions and velocities
+% with additional Lagrange multipliers included in the position
+% differential equations) and the position and velocity constraints.
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2007, The Regents of the University of California.
+% $Revision: 1.2 $Date: 2007/12/05 21:58:19 $
+
+% x, y, vx, vy, lam, mu
+neq = 6;
+
+t0 = 0.0;
+tf = 10.0;
+
+id = ones(neq,1);
+id(5) = 0;
+id(6) = 0;
+
+options = IDASetOptions('RelTol',1.e-6,...
+ 'AbsTol',1.e-6,...
+ 'VariableTypes',id,...
+ 'suppressAlgVars','on',...
+ 'MaxNumSteps', 1000,...
+ 'LinearSolver','Dense');
+y0 = zeros(neq,1);
+yp0 = zeros(neq,1);
+y0(1) = 1.0;
+yp0(4) = 9.81;
+fprintf('Consistent IC:\n');
+disp([y0 yp0])
+
+IDAInit(@pendGGL_f,t0,y0,yp0,options);
+
+it = 1;
+time(it) = t0;
+sol_y(it,:) = y0';
+[res, dummy1, status] = pendGGL_f(t0, y0, yp0);
+pc(it) = res(5);
+vc(it) = res(6);
+
+t = t0;
+t_start = clock;
+while t < tf
+ [status,t,y] = IDASolve(tf,'OneStep');
+ it = it+1;
+ time(it) = t;
+ sol_y(it,:) = y';
+ yp=yp0;
+ % For verification purposes only, compute position and velocity constraint violations
+ % (use dummy yp = yp0)
+ [res, dummy1, status] = pendGGL_f(t, y, yp0);
+ pc(it) = res(5);
+ vc(it) = res(6);
+
+end
+runtime = etime(clock,t_start);
+
+fprintf('Solver stats:\n');
+disp(IDAGetStats);
+fprintf('Run time: %f\n',runtime);
+
+
+figure;
+
+subplot(3,1,1)
+hold on
+plot(time,sol_y(:,1),'b');
+plot(time,sol_y(:,2),'r');
+box on
+set(gca,'XLim',[t0 tf])
+title('position');
+legend('x','y');
+
+subplot(3,1,2)
+hold on
+plot(time,sol_y(:,3),'b');
+plot(time,sol_y(:,4),'r');
+box on
+set(gca,'XLim',[t0 tf])
+title('velocity');
+legend('v_x', 'v_y');
+
+subplot(3,1,3)
+hold on
+plot(time,sol_y(:,5),'b');
+plot(time,sol_y(:,6),'r');
+box on
+set(gca,'XLim',[t0 tf])
+title('Lagrange multipliers');
+legend('\lambda', '\mu');
+
+figure
+
+plotyy(time, pc, time, vc);
+box on
+title('position and velocity constraint violations');
+
+figure
+
+subplot(2,1,1)
+plot(sol_y(:,1),sol_y(:,2));
+axis equal
+axis tight
+box on
+grid on
+xlabel('x');
+ylabel('y');
+title('trajectory');
+
+phi = atan2( sol_y(:,1) , sol_y(:,2) );
+phi_d = ( sol_y(:,1).*sol_y(:,4) - sol_y(:,2).*sol_y(:,3) ) ./ ( sol_y(:,1).^2 + sol_y(:,2).^2 ) ;
+subplot(2,1,2)
+plot3(time,phi, phi_d);
+xlabel('time');
+ylabel('\phi');
+zlabel('\phi^\prime');
+view(-30,15);
+set(gca,'XLim',[t0 tf])
+grid on
+box on
+title('phase plot');
+
+IDAFree;
+
+
+
+function [res, flag, new_data] = pendGGL_f(t,yy,yp)
+
+g = 9.81;
+m = 1.0;
+b = 0.3;
+L = 1.0;
+
+x = yy(1); xd = yp(1);
+y = yy(2); yd = yp(2);
+vx = yy(3); vxd = yp(3);
+vy = yy(4); vyd = yp(4);
+
+lam = yy(5);
+mu = yy(6);
+
+res(1) = -xd + (vx+2*x*mu);
+res(2) = -yd + (vy+2*y*mu);
+res(3) = -vxd + (-b*vx+2*x*lam)/m;
+res(4) = -vyd + (m*g-b*vy+2*y*lam)/m;
+
+res(5) = x^2 + y^2 - L^2;
+res(6) = 2*x*vx + 2*y*vy;
+
+flag = 0;
+new_data = [];
+
+
diff --git a/sundialsTB/idas/examples_ser/midasReInit_dns.m b/sundialsTB/idas/examples_ser/midasReInit_dns.m
new file mode 100644
index 0000000..cf74f15
--- /dev/null
+++ b/sundialsTB/idas/examples_ser/midasReInit_dns.m
@@ -0,0 +1,108 @@
+function [] = midasReInit_dns()
+%midasReInit_dns - Illustration of the IDAS reinitialization function
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2007, The Regents of the University of California.
+% $Revision: 1.1 $Date: 2007/10/26 16:30:48 $
+
+
+fprintf('Example for integrating over a discontinuity in states\n');
+fprintf('using the IDAS re-initialization function\n\n');
+fprintf('Integrate over t = [ 0 1.0 ] the DAE:');
+fprintf(' y1'' + y1 - y2 = 0\n');
+fprintf(' y1 + y2 = 0\n');
+fprintf('with initial conditions:\n');
+fprintf(' y1(0) = 1.0\n');
+fprintf(' y2(0) = -1.0\n');
+fprintf('until y2(t*) = -0.5. At t*, perturb:\n');
+fprintf(' y1(t*) <- y1(t*) - 0.25\n');
+fprintf(' y2(t*) <- y2(t*) + 0.25\n');
+fprintf('and continue the integration to t = 1.0\n\n');
+
+t0 = 0.0;
+tout = 1.0;
+y0 = [1.0;-1.0];
+yp0 = [-2.0;0.0];
+
+% Set optional inputs
+options = IDASetOptions('RelTol',1.e-4,...
+ 'AbsTol',1.e-5,...
+ 'LinearSolver','Dense');
+options = IDASetOptions(options,'RootsFn', at my_rootfct, 'NumRoots',1);
+
+% Initialize solver
+IDAInit(@my_resfct,t0,y0,yp0,options);
+
+% Initialize arrays
+tt = [];
+yy1 = [];
+yy2 = [];
+
+% Integrate DAE until root is found
+t = t0;
+while t<tout
+ [status, t, y] = IDASolve(tout,'OneStep');
+ tt = [tt;t];
+ yy1 = [yy1;y(1)];
+ yy2 = [yy2;y(2)];
+ if status == 2
+ break;
+ end
+end
+
+
+fprintf('');
+
+% Get yp at current time
+yp = IDAGet('DerivSolution',t,0);
+
+% Add discontinuity in solution
+% (must be consistent with the algebraic constraint)
+t0 = t;
+y0 = [y(1)-0.25; y(2)+0.25];
+yp0 = [yp(1)+0.25; 0.0];
+
+% Reinitialize solver
+IDAReInit(t0,y0,yp0,options);
+
+% Integrate to final time
+t = t0;
+while t<tout
+ [status, t, y] = IDASolve(tout,'OneStep');
+ tt = [tt;t];
+ yy1 = [yy1;y(1)];
+ yy2 = [yy2;y(2)];
+end
+
+% Free memory
+IDAFree;
+
+% Plot solution
+hp1 = plot(tt,yy1);
+hold on
+hp2 = plot(tt,yy2,'r');
+set(gca,'XLim',[tt(1) tt(end)]);
+plot([t0 t0],get(gca,'YLim'),'k:');
+
+legend([hp1,hp2],'y_1','y_2');
+
+%
+% ========================================================
+%
+
+function [rr, flag] = my_resfct(t, y, yp)
+
+rr(1) = yp(1) + y(1) - y(2);
+rr(2) = y(1) + y(2);
+
+flag = 0;
+
+%
+% ========================================================
+%
+
+function [g, flag] = my_rootfct(t, y, yp)
+
+g(1) = y(2) + 0.5;
+
+flag = 0;
diff --git a/sundialsTB/idas/examples_ser/midasRoberts_ASAi_dns.m b/sundialsTB/idas/examples_ser/midasRoberts_ASAi_dns.m
new file mode 100644
index 0000000..a66707d
--- /dev/null
+++ b/sundialsTB/idas/examples_ser/midasRoberts_ASAi_dns.m
@@ -0,0 +1,209 @@
+function midasRoberts_ASAi_dns()
+%midasRoberts_ASAi_dns - IDAS ASA example problem (serial, dense)
+% The following is a simple example problem, with the coding
+% needed for its solution by IDAS. 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
+% 0 = y1 + y2 + y3 - 1
+% on the interval from t = 0.0 to t = 4.e7, with initial
+% conditions: y1 = 1.0, y2 = y3 = 0. The problem is stiff.
+% 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.
+%
+% The gradient with respect to the problem parameters p1, p2,
+% and p3 of the following quantity:
+% G = int_t0^t1 y3(t) dt
+% is computed using ASA.
+%
+% The gradient dG/dp is obtained as:
+% dG/dp = [ int_t0^tf y1*(l1-l2) dt ,
+% int_t0^tf -y2*y3*(l1-l2) dt ,
+% int_t0^tf y2^2*l2 dt ]
+%
+% where l = [l1, l2, l3] is solutions of:
+% dl1/dt = p1*l1 - p1*l2 + l3
+% dl2/dt = -p2*y3*l1 + (p2*y3+2*p3*y2)*l2 + l3
+% 0 = -p2*y2*l1 + p2*y2*l2 + l3 + 1
+% with final conditions
+% l1(tf) = l2(tf) = 0.0 and l3(tf) = -1.0
+%
+% All integrals (appearing in G and dG/dp) are computed using
+% the quadrature integration features in IDAS.
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2007, The Regents of the University of California.
+% $Revision: 1.1 $Date: 2007/10/26 16:30:48 $
+
+% Problem parameters
+% ------------------
+
+data.p = [0.04; 1.0e4; 3.0e7];
+
+% Initialize forward problem
+% --------------------------
+
+options = IDASetOptions('UserData', data,...
+ 'RelTol',1.e-4,...
+ 'AbsTol',[1.e-8; 1.e-14; 1.e-6],...
+ 'LinearSolver','Dense',...
+ 'JacobianFn', at djacfn);
+
+%mondata.sol = true;
+%mondata.updt = 100;
+%options = IDASetOptions(options,'MonitorFn', at IDAMonitor,'MonitorData',mondata);
+
+t0 = 0.0;
+y = [1.0;0.0;0.0];
+yp = [-0.04;0.04;0.0];
+IDAInit(@resfn,t0,y,yp,options);
+
+% Initialize forward quadrature (G)
+% ---------------------------------
+
+optionsQ = IDAQuadSetOptions('ErrControl',true,...
+ 'RelTol',1.e-4,'AbsTol',1.e-6);
+q = 0.0;
+IDAQuadInit(@quadfn, q, optionsQ);
+
+% Activate ASA
+% ------------
+
+IDAAdjInit(150, 'Hermite');
+
+% Forward integration
+% -------------------
+
+fprintf('Forward integration ');
+tf = 4.e7;
+[status, t, y, q] = IDASolve(tf,'Normal');
+si = IDAGetStats;
+fprintf('(%d steps)\n',si.nst);
+
+fprintf('G = %12.4e\n',q(1));
+
+% Initialize backward problem
+% ---------------------------
+
+optionsB = IDASetOptions('UserData',data,...
+ 'RelTol',1.e-6,...
+ 'AbsTol',1.e-3,...
+ 'LinearSolver','Dense');
+%mondataB = struct;
+%optionsB = IDASetOptions(optionsB,'MonitorFn', at IDAMonitorB,'MonitorData',mondataB);
+
+yB = [0.0 ; 0.0 ; -1.0];
+yBp = [ -1.0 ; -1.0 ; 0.0 ];
+idxB = IDAInitB(@resfnB,tf,yB,yBp,optionsB);
+
+% Initialize backward quadratures (dG/dp)
+% ---------------------------------------
+
+optionsQB = IDAQuadSetOptions('ErrControl',true,...
+ 'RelTol',1.e-6,'AbsTol',1.e-3);
+
+qB = [0.0;0.0;0.0];
+IDAQuadInitB(idxB, @quadfnB, qB, optionsQB);
+
+% Backward integration
+% --------------------
+
+fprintf('Backward integration ');
+[status, t, yB, qB] = IDASolveB(t0,'Normal');
+siB = IDAGetStatsB(idxB);
+fprintf('(%d steps)\n',siB.nst);
+
+fprintf('dG/dp: %12.4e %12.4e %12.4e\n',...
+ -qB(1),-qB(2),-qB(3));
+fprintf('lambda(t0): %12.4e %12.4e %12.4e\n',...
+ yB(1),yB(2),yB(3));
+
+% Free IDAS memory
+% ----------------
+
+IDAFree;
+
+return
+
+% ===========================================================================
+function [rr, flag, new_data] = resfn(t, y, yp, data)
+% DAE residual function
+
+r1 = data.p(1);
+r2 = data.p(2);
+r3 = data.p(3);
+
+rr(1) = -r1*y(1) + r2*y(2)*y(3) - yp(1);
+rr(2) = r1*y(1) - r2*y(2)*y(3) - r3*y(2)*y(2) - yp(2);
+rr(3) = y(1) + y(2) + y(3) - 1.0;
+
+flag = 0;
+new_data = [];
+
+% ===========================================================================
+function [J, flag, new_data] = djacfn(t, y, yp, rr, cj, data)
+% Dense Jacobian function
+
+r1 = data.p(1);
+r2 = data.p(2);
+r3 = data.p(3);
+
+J(1,1) = -r1 - cj;
+J(2,1) = r1;
+J(3,1) = 1.0;
+
+J(1,2) = r2*y(3);
+J(2,2) = -r2*y(3) - 2*r3*y(2) - cj;
+J(3,2) = 1.0;
+
+J(1,3) = r2*y(2);
+J(2,3) = -r2*y(2);
+J(3,3) = 1.0;
+
+flag = 0;
+new_data = [];
+
+% ===========================================================================
+function [qd, flag, new_data] = quadfn(t, y, yp, data)
+% Forward quadrature integrand function
+
+qd = y(3);
+
+flag = 0;
+new_data = [];
+
+return
+
+% ===========================================================================
+function [rrB, flag, new_data] = resfnB(t, y, yp, yB, yBp, data)
+% Adjoint residual function
+
+r1 = data.p(1);
+r2 = data.p(2);
+r3 = data.p(3);
+
+
+rrB(1) = yBp(1) - r1*(yB(1)-yB(2)) - yB(3);
+rrB(2) = yBp(2) + r2*y(3)*(yB(1)-yB(2)) - 2.0*r3*y(2)*yB(2) - yB(3);
+rrB(3) = -r2*y(2)*(yB(1)-yB(2)) + yB(3) + 1.0;
+
+flag = 0;
+new_data = [];
+
+return
+
+% ===========================================================================
+function [qBd, flag, new_data] = quadfnB(t, y, yp, yB, ypB, data)
+% Backward problem quadrature integrand function
+
+qBd(1) = y(1)*(yB(1)-yB(2));
+qBd(2) = -y(2)*y(3)*(yB(1)-yB(2));
+qBd(3) = y(2)^2*yB(2);
+
+flag = 0;
+new_data = [];
+
+return
+
diff --git a/sundialsTB/idas/examples_ser/midasRoberts_dns.m b/sundialsTB/idas/examples_ser/midasRoberts_dns.m
new file mode 100644
index 0000000..1e89cab
--- /dev/null
+++ b/sundialsTB/idas/examples_ser/midasRoberts_dns.m
@@ -0,0 +1,120 @@
+function midasRoberts_dns
+%midasRoberts_dns - IDAS example problem (serial, dense)
+% The following is a simple example problem, with the coding
+% needed for its solution by IDAS. 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
+% 1 = y1 + y2 + y3
+% 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 rootfinding
+% feature to find the points at which y1 = 1e-4 or at which
+% y3 = 0.01.
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2007, The Regents of the University of California.
+% $Revision: 1.1 $Date: 2007/10/26 16:30:48 $
+
+data.p = [0.04; 1.0e4; 3.0e7];
+
+t0 = 0.0;
+y0 = [1.0;0.0;0.0];
+yp0 = [-0.04;0.04;0.0];
+
+options = IDASetOptions('UserData', data,...
+ 'RelTol',1.e-4,...
+ 'AbsTol',[1.e-8; 1.e-14; 1.e-6],...
+ 'LinearSolver','Dense',...
+ 'JacobianFn', at djacfn);
+
+options = IDASetOptions(options,'RootsFn', at rootfn, 'NumRoots',2);
+
+%mondata.sol = true;
+mondata.updt = 100;
+options = IDASetOptions(options,'MonitorFn', at IDAMonitor,'MonitorData',mondata);
+
+IDAInit(@resfn,t0,y0,yp0,options);
+
+t1 = 0.4;
+tmult = 10.0;
+nout = 12;
+
+fprintf('-----------------------------------------------------------------------\n');
+fprintf(' t y1 y2 y3');
+fprintf(' | nst k h\n');
+fprintf('-----------------------------------------------------------------------\n');
+
+iout = 0;
+tout = t1;
+while iout < nout
+
+ [status,t,y] = IDASolve(tout,'Normal');
+
+% Extract statistics
+ si = IDAGetStats;
+
+% Print output
+ if(status == 2)
+ fprintf(' ... Root found %d %d\n',si.RootInfo.roots(1), si.RootInfo.roots(2));
+ end
+ fprintf('%10.4e %12.4e %12.4e %12.4e | %3d %1d %12.4e\n',...
+ t, y(1), y(2), y(3), si.nst, si.qlast, si.hlast);
+
+% Update output time
+ if(status == 0)
+ iout = iout+1;
+ tout = tout*tmult;
+ end
+
+end
+
+si = IDAGetStats;
+
+IDAFree;
+
+function [rr, flag, new_data] = resfn(t, y, yp, data)
+% DAE residual function
+
+r1 = data.p(1);
+r2 = data.p(2);
+r3 = data.p(3);
+
+rr(1) = -r1*y(1) + r2*y(2)*y(3) - yp(1);
+rr(2) = r1*y(1) - r2*y(2)*y(3) - r3*y(2)*y(2) - yp(2);
+rr(3) = y(1) + y(2) + y(3) - 1.0;
+
+flag = 0;
+new_data = [];
+
+function [J, flag, new_data] = djacfn(t, y, yp, rr, cj, data)
+% Dense Jacobian function
+
+r1 = data.p(1);
+r2 = data.p(2);
+r3 = data.p(3);
+
+J(1,1) = -r1 - cj;
+J(2,1) = r1;
+J(3,1) = 1.0;
+
+J(1,2) = r2*y(3);
+J(2,2) = -r2*y(3) - 2*r3*y(2) - cj;
+J(3,2) = 1.0;
+
+J(1,3) = r2*y(2);
+J(2,3) = -r2*y(2);
+J(3,3) = 1.0;
+
+flag = 0;
+new_data = [];
+
+function [g, flag, new_data] = rootfn(t,y,yp,data)
+% Root finding function
+
+g(1) = y(1) - 0.0001;
+g(2) = y(3) - 0.01;
+
+flag = 0;
+new_data = [];
diff --git a/sundialsTB/idas/examples_ser/midasSlCrank_FSA_dns.m b/sundialsTB/idas/examples_ser/midasSlCrank_FSA_dns.m
new file mode 100644
index 0000000..ad12bab
--- /dev/null
+++ b/sundialsTB/idas/examples_ser/midasSlCrank_FSA_dns.m
@@ -0,0 +1,238 @@
+function midasSlCrank_FSA_dns
+%midasSlCrank_FSA_dns - FSA for the slider-crank example
+%
+% Sensitivities w.r.t. k and c are computed
+%
+% See also: midasSlCrank_dns
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2007, The Regents of the University of California.
+% $Revision: 1.2 $Date: 2009/04/26 23:27:29 $
+
+
+% Problem data
+data.a = 0.5;
+data.J1 = 1.0;
+data.m2 = 1.0;
+data.J2 = 2.0;
+data.l0 = 1.0;
+data.F = 1.0;
+data.params(1) = 1.0; % spring constant
+data.params(2) = 1.0; % damper constant
+
+% Integration limits
+t0 = 0.0;
+tf = 10.0;
+
+% Specify algebraic variables
+id = ones(10,1);
+id(7:10) = 0.0;
+
+% Integration options
+options = IDASetOptions('UserData',data,...
+ 'RelTol',1.e-6,...
+ 'AbsTol',1.e-6,...
+ 'VariableTypes',id,...
+ 'suppressAlgVars','on',...
+ 'MaxNumSteps', 1000,...
+ 'LinearSolver','Dense');
+% Set consistent IC
+[yy0, yp0] = setIC(data);
+
+% Initialize IDAS
+IDAInit(@scRES,t0,yy0,yp0,options);
+
+% FSA options
+Ns = 2;
+options = IDASensSetOptions('method','Simultaneous',...
+ 'ErrControl',true,...
+ 'ParamField','params',...
+ 'ParamList',[1 2]);
+
+% Sensitivity IC
+yyS0 = zeros(10, Ns);
+ypS0 = zeros(10, Ns);
+
+% Initialize FSA
+IDASensInit(Ns, [], yyS0, ypS0, options);
+
+% Compute consistent IC
+
+% Store inital time and IC
+it = 1;
+time(it,1) = t0;
+solution(it,:) = yy0';
+sensitivity1(it,:) = yyS0(:,1)';
+sensitivity2(it,:) = yyS0(:,2)';
+
+% Call solver in ONE_STEP mode
+t = t0;
+while t < tf
+ [status,t,y,yS] = IDASolve(tf,'OneStep');
+ it = it+1;
+ time(it,1) = t;
+ solution(it,:) = y';
+ sensitivity1(it,:) = yS(:,1)';
+ sensitivity2(it,:) = yS(:,2)';
+end
+
+fprintf('Solver stats:\n');
+disp(IDAGetStats);
+
+IDAFree;
+
+% Plot slider position and its sensitivities
+figure;
+set(gcf,'position',[475 250 1000 400]);
+
+hold on
+X = [time ; flipud(time)];
+Y1 = [solution(:,2) ; flipud(solution(:,2)+sensitivity1(:,2))];
+Y2 = [solution(:,2) ; flipud(solution(:,2)+sensitivity2(:,2))];
+
+
+hp1 = patch(X,Y1,'r');
+hp2 = patch(X,Y2,'b');
+
+%set(hp1,'EdgeColor','none','FaceAlpha',0.5);
+%set(hp2,'EdgeColor','none','FaceAlpha',0.5);
+
+set(hp1,'EdgeColor','none');
+set(hp2,'EdgeColor','none');
+
+hp = plot(time,solution(:,2),'k');
+set(hp,'LineWidth',2);
+
+set(gca,'XLim',[t0 tf]);
+
+box on
+grid on
+
+
+% ====================================================================================
+% Consistent IC
+% ====================================================================================
+
+function [yy, yp] = setIC(data)
+
+a = data.a;
+J1 = data.J1;
+m2 = data.m2;
+J2 = data.J2;
+
+q = pi/2.0;
+p = -asin(a*sin(q));
+x = cos(p) + a*cos(q);
+
+yy = zeros(10,1);
+yp = zeros(10,1);
+
+yy(1) = q; % crank angle
+yy(2) = x; % slider position
+yy(3) = p; % conecting rod angle
+
+Q = force(yy, data);
+
+yp(4) = Q(1)/J1; % crank angular acceleration
+yp(5) = Q(2)/m2; % slider horizontal acceleration
+yp(6) = Q(3)/J2; % connecting rod angular acceleration
+
+return
+
+% ====================================================================================
+% Generalized force calculation
+% ====================================================================================
+
+function Q = force(yy, data)
+
+a = data.a;
+k = data.params(1);
+c = data.params(2);
+l0 = data.l0;
+F = data.F;
+
+q = yy(1); % crank angle
+x = yy(2); % slider position
+p = yy(3); % conecting rod angle
+
+qd = yy(4); % crank angular velocity
+xd = yy(5); % slider horizontal velocity
+pd = yy(6); % conecting rod angular velocity
+
+s1 = sin(q);
+c1 = cos(q);
+s2 = sin(p);
+c2 = cos(p);
+s21 = s2*c1 - c2*s1;
+c21 = c2*c1 + s2*s1;
+
+l2 = x^2 - x*(c2+a*c1) + (1.0 + a^2)/4.0 + a*c21/2.0;
+l = sqrt(l2);
+ld = 2.0*x*xd - xd*(c2+a*c1) + x*(s2*pd+a*s1*qd) - a*s21*(pd-qd)/2.0;
+ld = ld / (2.0*l);
+
+f = k*(l-l0) + c*ld;
+fl = f/l;
+
+Q(1) = - fl * a * (s21/2.0 + x*s1) / 2.0;
+Q(2) = fl * (c2/2.0 - x + a*c1/2.0) + F;
+Q(3) = - fl * (x*s2 - a*s21/2.0) / 2.0 - F*s2;
+
+return
+
+% ====================================================================================
+% Residual function
+% ====================================================================================
+
+function [res, flag, new_data] = scRES(t,yy,yp,data)
+
+a = data.a;
+J1 = data.J1;
+m2 = data.m2;
+J2 = data.J2;
+
+q = yy(1); % crank angle
+x = yy(2); % slider position
+p = yy(3); % conecting rod angle
+
+qd = yy(4); % crank angular velocity
+xd = yy(5); % slider horizontal velocity
+pd = yy(6); % conecting rod angular velocity
+
+lam1 = yy(7); % Lagrange multiplier (cnstr)
+lam2 = yy(8); % Lagrange multiplier (cnstr)
+
+mu1 = yy(9); % Lagrange multiplier (GGL)
+mu2 = yy(10); % Lagrange multiplier (GGL)
+
+s1 = sin(q);
+c1 = cos(q);
+s2 = sin(p);
+c2 = cos(p);
+
+% Generalized forces
+Q = force(yy, data);
+
+% Velocities (GGL modified)
+res(1) = yp(1) - qd + a*s1*mu1 - a*c1*mu2;
+res(2) = yp(2) - xd + mu1;
+res(3) = yp(3) - pd + s2*mu1 - c2*mu2;
+
+% Dynamical equations
+res(4) = J1*yp(4) - Q(1) + a*s1*lam1 - a*c1*lam2;
+res(5) = m2*yp(5) - Q(2) + lam1;
+res(6) = J2*yp(6) - Q(3) + s2*lam1 - c2*lam2;
+
+% Position constraints
+res(7) = x - c2 - a*c1;
+res(8) = -s2 - a*s1;
+
+% Velocity constraints
+res(9) = a*s1*qd + xd + s2*pd;
+res(10) = -a*c1*qd - c2*pd;
+
+flag = 0;
+new_data = [];
+
+return
+
diff --git a/sundialsTB/idas/examples_ser/midasSlCrank_dns.m b/sundialsTB/idas/examples_ser/midasSlCrank_dns.m
new file mode 100644
index 0000000..e1a5ee5
--- /dev/null
+++ b/sundialsTB/idas/examples_ser/midasSlCrank_dns.m
@@ -0,0 +1,481 @@
+function midasSlCrank_dns
+%midasSlCrank_dns Slider-crank example
+% The multibody system consists of two bodies (crank and
+% connecting rod) with a translational-spring-damper (TSDA)
+% and a constant force acting on the connecting rod.
+%
+% The system has a single degree of freedom. It is modeled with 3
+% generalized coordinates (crank angle, horizontal position of the
+% translational joint, and angle of the connecting rod) and
+% therefore has 2 constraints.
+%
+% Example 6.1.8, pp. 271 in
+% Ed. Haug - Intermediate Dynamics, Prentiss Hall, 1992
+%
+% For its solution with IDAS, the resulting index-3 DAE is reformulated
+% as a stabilized index-2 DAE (Gear-Gupta-Leimkhuler formulation) by
+% introducing 2 additional Lagrange multipliers and appending the
+% velocity constraints.
+%
+% | |
+% | /\ | /\
+% | / \ | / \
+% | a/2 / \ 1/2 | / \
+% | / \ | / \
+% | /--TSDA--\ | / \
+% | / \ | / \
+% | / a/2 \ 1/2 | / \---
+% |/ \ |/ \ q1 q3 / \ \
+% +----------------------------- +----------------------------
+% \ | \ |\
+% \ | -|-\
+% \ 1 | | \
+% \ |<----- q2 ----->| \
+% \ \
+% \ \
+% \ --> F \
+%
+% The local reference frame on the crank is positioned at the
+% revolute joint on the ground. The crank has length a, mass m1, and
+% intertia (with respect to the local frame) J1.
+% The local reference frame on the conncting rod is positioned at the
+% translational joint. The connecting rod has length 2, mass m2, and
+% inertia J2.
+% The TSDA has spring constant k, damping constant c, and free length l0.
+% A constant horizontal force F acts on the connecting rod.
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2007, The Regents of the University of California.
+% $Revision: 1.2 $Date: 2009/04/26 23:27:29 $
+
+% Problem data
+data.a = 0.5;
+data.J1 = 1.0;
+data.m2 = 1.0;
+data.J2 = 2.0;
+data.k = 1.0;
+data.c = 1.0;
+data.l0 = 1.0;
+data.F = 1.0;
+
+% Integration limits
+t0 = 0.0;
+tf = 10.0;
+
+% Specify algebraic variables
+id = ones(10,1);
+id(7:10) = 0.0;
+
+% Integration options
+options = IDASetOptions('UserData',data,...
+ 'RelTol',1.e-6,...
+ 'AbsTol',1.e-6,...
+ 'VariableTypes',id,...
+ 'suppressAlgVars','on',...
+ 'MaxNumSteps', 1000,...
+ 'LinearSolver','Dense');
+% Set consistent IC
+[yy0, yp0] = setIC(data);
+
+% Initialize IDAS
+IDAInit(@scRes,t0,yy0,yp0,options);
+
+% Store inital time and IC
+it = 1;
+time(it) = t0;
+pos(it,:) = yy0(1:3)';
+vel(it,:) = yy0(4:6)';
+acc(it,:) = yp0(4:6)';
+lam(it,:) = yy0(7:8)';
+
+% Compute constraint joint forces at initial time
+Fc(it,:) = joint_forces(yy0, yp0, data);
+
+% Call solver in ONE_STEP mode
+t = t0;
+while t < tf
+ [status,t,yy] = IDASolve(tf,'OneStep');
+ it = it+1;
+ time(it) = t;
+ pos(it,:) = yy(1:3)';
+ vel(it,:) = yy(4:6)';
+ lam(it,:) = yy(7:8)';
+ yp = IDAGet('DerivSolution',t,1);
+ acc(it,:) = yp(4:6)';
+ Fc(it,:) = joint_forces(yy, yp, data);
+end
+
+fprintf('Solver stats:\n');
+disp(IDAGetStats);
+
+% Plot solution
+figure;
+set(gcf,'position',[475 250 1000 800]);
+
+subplot(2,2,1)
+hold on
+plot(time,pos(:,1),'b');
+plot(time,pos(:,2),'r');
+plot(time,pos(:,3),'g');
+box on
+set(gca,'XLim',[t0 tf])
+title('position');
+legend('q','x','p');
+
+subplot(2,2,2)
+hold on
+plot(time,vel(:,1),'b');
+plot(time,vel(:,2),'r');
+plot(time,vel(:,3),'g');
+box on
+set(gca,'XLim',[t0 tf])
+title('velocity');
+legend('q''', 'x''', 'p''');
+
+subplot(2,2,3)
+hold on
+plot(time,acc(:,1),'b');
+plot(time,acc(:,2),'r');
+plot(time,acc(:,3),'g');
+box on
+set(gca,'XLim',[t0 tf])
+title('acceleration');
+legend('q''''', 'x''''', 'p''''');
+
+
+subplot(2,2,4)
+hold on
+plot(time,lam(:,1),'b');
+plot(time,lam(:,2),'r');
+box on
+set(gca,'XLim',[t0 tf])
+title('Lagrange multipliers (cnstr. forces)');
+legend('\lambda_1', '\lambda_2');
+
+
+% Plot joint forces
+figure;
+set(gcf,'position',[275 150 800 800]);
+
+plot(time,Fc);
+set(gca,'XLim',[t0 tf])
+title('joint forces');
+legend('vrt. force in rev. crank-ground',...
+ 'hrz. force in rev. crank-ground',...
+ 'vrt. force in rev. crank-rod',...
+ 'hrz. force in rev. crank-rod',...
+ 'vrt. force in transl.',...
+ 'torque in transl.');
+
+
+IDAFree;
+
+% ====================================================================================
+% Consistent IC
+% ====================================================================================
+
+function [yy, yp] = setIC(data)
+
+a = data.a;
+J1 = data.J1;
+m2 = data.m2;
+J2 = data.J2;
+
+q = pi/2.0;
+p = -asin(a*sin(q));
+x = cos(p) + a*cos(q);
+
+yy = zeros(10,1);
+yp = zeros(10,1);
+
+yy(1) = q; % crank angle
+yy(2) = x; % slider position
+yy(3) = p; % conecting rod angle
+
+Q = appl_forces(yy, data);
+g = gamma(yy,data);
+G = jac(yy,data);
+
+% Extended mass matrix in index-1 formulation
+
+MM = zeros(5,5);
+MM(1,1) = J1;
+MM(2,2) = m2;
+MM(3,3) = J2;
+MM(4:5,1:3) = G;
+MM(1:3,4:5) = G';
+
+% Right-hand side in index-1 formulation
+
+b = [Q;g];
+
+% Solution of MM*x = b
+
+acc = MM^(-1)*b;
+
+yp(4) = acc(1);
+yp(5) = acc(2);
+yp(6) = acc(3);
+%
+yy(7) = acc(4);
+yy(8) = acc(5);
+
+return
+
+% ====================================================================================
+% Constraint Jacobian
+% ====================================================================================
+
+function G = jac(yy,data)
+
+a = data.a;
+
+q = yy(1); % crank angle
+x = yy(2); % slider position
+p = yy(3); % conecting rod angle
+
+qd = yy(4); % crank angular velocity
+xd = yy(5); % slider horizontal velocity
+pd = yy(6); % conecting rod angular velocity
+
+s1 = sin(q);
+c1 = cos(q);
+s2 = sin(p);
+c2 = cos(p);
+
+G(1,1) = a*s1;
+G(1,2) = 1.0;
+G(1,3) = s2;
+
+G(2,1) = -a*c1;
+G(2,2) = 0.0;
+G(2,3) = -c2;
+
+return
+
+% ====================================================================================
+% Right-hand side of acceleration constraint
+% ====================================================================================
+
+function g = gamma(yy, data)
+
+a = data.a;
+
+q = yy(1); % crank angle
+x = yy(2); % slider position
+p = yy(3); % conecting rod angle
+
+qd = yy(4); % crank angular velocity
+xd = yy(5); % slider horizontal velocity
+pd = yy(6); % conecting rod angular velocity
+
+s1 = sin(q);
+c1 = cos(q);
+s2 = sin(p);
+c2 = cos(p);
+
+g(1,1) = - (a*qd^2*c1+pd^2*c2);
+g(2,1) = - (a*qd^2*s1 + pd^2*s2);
+
+return
+
+% ====================================================================================
+% Generalized applied forces calculation
+% ====================================================================================
+
+function Q = appl_forces(yy, data)
+
+a = data.a;
+k = data.k;
+c = data.c;
+l0 = data.l0;
+F = data.F;
+
+q = yy(1); % crank angle
+x = yy(2); % slider position
+p = yy(3); % conecting rod angle
+
+qd = yy(4); % crank angular velocity
+xd = yy(5); % slider horizontal velocity
+pd = yy(6); % conecting rod angular velocity
+
+s1 = sin(q);
+c1 = cos(q);
+s2 = sin(p);
+c2 = cos(p);
+s21 = s2*c1 - c2*s1;
+c21 = c2*c1 + s2*s1;
+
+l2 = x^2 - x*(c2+a*c1) + (1.0 + a^2)/4.0 + a*c21/2.0;
+l = sqrt(l2);
+ld = 2.0*x*xd - xd*(c2+a*c1) + x*(s2*pd+a*s1*qd) - a*s21*(pd-qd)/2.0;
+ld = ld / (2.0*l);
+
+f = k*(l-l0) + c*ld;
+fl = f/l;
+
+Q(1,1) = - fl * a * (s21/2.0 + x*s1) / 2.0;
+Q(2,1) = fl * (c2/2.0 - x + a*c1/2.0) + F;
+Q(3,1) = - fl * (x*s2 - a*s21/2.0) / 2.0 - F*s2;
+
+return
+
+% ====================================================================================
+% Residual function
+% ====================================================================================
+
+function [res, flag, new_data] = scRes(t,yy,yp,data)
+
+a = data.a;
+J1 = data.J1;
+m2 = data.m2;
+J2 = data.J2;
+
+q = yy(1); % crank angle
+x = yy(2); % slider position
+p = yy(3); % conecting rod angle
+
+qd = yy(4); % crank angular velocity
+xd = yy(5); % slider horizontal velocity
+pd = yy(6); % conecting rod angular velocity
+
+lam1 = yy(7); % Lagrange multiplier (cnstr)
+lam2 = yy(8); % Lagrange multiplier (cnstr)
+
+mu1 = yy(9); % Lagrange multiplier (GGL)
+mu2 = yy(10); % Lagrange multiplier (GGL)
+
+s1 = sin(q);
+c1 = cos(q);
+s2 = sin(p);
+c2 = cos(p);
+
+% Generalized forces
+Q = appl_forces(yy, data);
+
+% Velocities (GGL modified)
+res(1) = yp(1) - qd + a*s1*mu1 - a*c1*mu2;
+res(2) = yp(2) - xd + mu1;
+res(3) = yp(3) - pd + s2*mu1 - c2*mu2;
+
+% Dynamical equations
+res(4) = J1*yp(4) - Q(1) + a*s1*lam1 - a*c1*lam2;
+res(5) = m2*yp(5) - Q(2) + lam1;
+res(6) = J2*yp(6) - Q(3) + s2*lam1 - c2*lam2;
+
+% Position constraints
+res(7) = x - c2 - a*c1;
+res(8) = -s2 - a*s1;
+
+% Velocity constraints
+res(9) = a*s1*qd + xd + s2*pd;
+res(10) = -a*c1*qd - c2*pd;
+
+flag = 0;
+new_data = [];
+
+return
+
+% ====================================================================================
+% Joint constraint forces
+% ====================================================================================
+
+function Fc = joint_forces(yy, yp, data)
+% Compute joint reaction forces for given positins, velocities, and
+% accelerations. This is done by including the reaction forces and torques,
+% considering the free body diagrams for the crank and connecting rod, and
+% writing the dynamical equilibrium equations.
+%
+
+a = data.a;
+k = data.k;
+c = data.c;
+l0 = data.l0;
+F = data.F;
+
+J1 = data.J1;
+m2 = data.m2;
+J2 = data.J2;
+
+q = yy(1); % crank angle
+x = yy(2); % slider position
+p = yy(3); % conecting rod angle
+
+qd = yy(4); % crank angular velocity
+xd = yy(5); % slider horizontal velocity
+pd = yy(6); % conecting rod angular velocity
+
+qdd = yp(4); % crank angular acc.
+xdd = yp(5); % slider horizontal acc.
+pdd = yp(6); % connecting rod angular acc.
+
+s1 = sin(q);
+c1 = cos(q);
+s2 = sin(p);
+c2 = cos(p);
+s21 = s2*c1 - c2*s1;
+c21 = c2*c1 + s2*s1;
+
+l2 = x^2 - x*(c2+a*c1) + (1.0 + a^2)/4.0 + a*c21/2.0;
+l = sqrt(l2);
+ld = 2.0*x*xd - xd*(c2+a*c1) + x*(s2*pd+a*s1*qd) - a*s21*(pd-qd)/2.0;
+ld = ld / (2.0*l);
+
+f = k*(l-l0) + c*ld;
+fl = f/l;
+
+% TSDA forces acting on crank and connecting rod
+
+Q1A(1) = x-0.5*c2-a/2*c1;
+Q1A(2) = -0.5*(s2+a*s1);
+Q1A(3) = -0.5*(a*x*s1+s21);
+
+Q2A(1) = -Q1A(1);
+Q2A(2) = -Q1A(2);
+Q2A(3) = -0.5*(x*s2+a*s21);
+
+Q1A = fl*Q1A';
+Q2A = fl*Q2A';
+
+QA = [-Q1A;-Q2A];
+
+% Force F acting on connecting rod
+FA = [0;0;0;F;0;-F*s2];
+
+% Dynamic forces
+MA = [0;0;J1*qdd;m2*xdd;0;J2*pdd];
+
+% Dynamic equilibrium equations:
+% MA = QA+FA + FC
+% where the joint constraint forces are:
+% Fc(1) = vertical force in revolute join crank-ground
+% Fc(2) = horizontal force in revolute join crank-ground
+% Fc(3) = vertical force in revolute joint crank-connecting rod
+% Fc(4) = vertical force in revolute joint crank-connecting rod
+% Fc(5) = vertical force in translational joint
+% Fc(6) = reaction torque acting in translational joint
+% and therefore
+% FC = A * Fc
+% where
+% A = [
+% 0 1 0 1 0 0
+% 1 0 1 0 0 0
+% 0 0 a*c1 -1*s1 0 0
+% 0 0 0 -1 0 0
+% 0 0 -1 0 1 0
+% 0 0 -c2 -s2 0 1
+% ];
+
+b = MA-QA-FA;
+
+Fc(4) = -b(4);
+Fc(2) = b(1) - Fc(4);
+if abs(c1) > 0.1
+ Fc(3) = ( b(3) + a*s1*Fc(4) ) / (a*c1);
+end
+Fc(1) = b(2) - Fc(3);
+Fc(5) = b(5) + Fc(3);
+Fc(6) = b(6) + c2*Fc(3) + s2*Fc(4);
+
+return
+
diff --git a/sundialsTB/idas/function_types/IDABandJacFn.m b/sundialsTB/idas/function_types/IDABandJacFn.m
new file mode 100644
index 0000000..78472ae
--- /dev/null
+++ b/sundialsTB/idas/function_types/IDABandJacFn.m
@@ -0,0 +1,32 @@
+%IDABandJacFn - type for banded Jacobian function.
+%
+% The function BJACFUN must be defined as
+% FUNCTION [J, FLAG] = BJACFUN(T, YY, YP, RR, CJ)
+% and must return a matrix J corresponding to the banded Jacobian
+% (df/dyy + cj*df/dyp).
+% The input argument RR contains the current value of f(t,yy,yp).
+% If a user data structure DATA was specified in IDAInit, then
+% BJACFUN must be defined as
+% FUNCTION [J, FLAG, NEW_DATA] = BJACFUN(T, YY, YP, RR, CJ, DATA)
+% If the local modifications to the user data structure are needed in
+% other user-provided functions then, besides setting the matrix J,
+% the BJACFUN function must also set NEW_DATA. Otherwise, it should
+% set NEW_DATA=[] (do not set NEW_DATA = DATA as it would lead to
+% unnecessary copying).
+%
+% The function BJACFUN must set FLAG=0 if successful, FLAG<0 if an
+% unrecoverable failure occurred, or FLAG>0 if a recoverable error
+% occurred.
+%
+% See also IDASetOptions
+%
+% See the IDAS user guide for more information on the structure of
+% a banded Jacobian.
+%
+% NOTE: BJACFUN is specified through the property JacobianFn to
+% IDASetOptions and is used only if the property LinearSolver
+% was set to 'Band'.
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2007, The Regents of the University of California.
+% $Revision: 1.3 $Date: 2011/05/26 00:01:23 $
diff --git a/sundialsTB/idas/function_types/IDABandJacFnB.m b/sundialsTB/idas/function_types/IDABandJacFnB.m
new file mode 100644
index 0000000..68b49d9
--- /dev/null
+++ b/sundialsTB/idas/function_types/IDABandJacFnB.m
@@ -0,0 +1,27 @@
+%IDABandJacFnB - type for banded Jacobian function for backward problems.
+%
+% The function BJACFUNB must be defined either as
+% FUNCTION [JB, FLAG] = BJACFUNB(T, YY, YP, YYB, YPB, RRB, CJB)
+% or as
+% FUNCTION [JB,FLAG,NEW_DATA] = BJACFUNB(T,YY,YP,YYB,YPB,RRB,CJB)
+% depending on whether a user data structure DATA was specified in
+% IDAInit. In either case, it must return the matrix JB, the
+% Jacobian (dfB/dyyB + cjB*dfB/dypB)of fB(t,y,yB). The input argument
+% RRB contains the current value of f(t,yy,yp,yyB,ypB).
+%
+% The function BJACFUNB must set FLAG=0 if successful, FLAG<0 if an
+% unrecoverable failure occurred, or FLAG>0 if a recoverable error
+% occurred.
+%
+% See also IDASetOptions
+%
+% See the IDAS user guide for more information on the structure of
+% a banded Jacobian.
+%
+% NOTE: BJACFUNB is specified through the property JacobianFn to
+% IDASetOptions and is used only if the property LinearSolver
+% was set to 'Band'.
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2007, The Regents of the University of California.
+% $Revision: 1.2 $Date: 2011/05/26 00:01:23 $
diff --git a/sundialsTB/idas/function_types/IDADenseJacFn.m b/sundialsTB/idas/function_types/IDADenseJacFn.m
new file mode 100644
index 0000000..de580ff
--- /dev/null
+++ b/sundialsTB/idas/function_types/IDADenseJacFn.m
@@ -0,0 +1,29 @@
+%IDADenseJacFn - type for dense Jacobian function.
+%
+% The function DJACFUN must be defined as
+% FUNCTION [J, FLAG] = DJACFUN(T, YY, YP, RR, CJ)
+% and must return a matrix J corresponding to the Jacobian
+% (df/dyy + cj*df/dyp).
+% The input argument RR contains the current value of f(t,yy,yp).
+% If a user data structure DATA was specified in IDAInit, then
+% DJACFUN must be defined as
+% FUNCTION [J, FLAG, NEW_DATA] = DJACFUN(T, YY, YP, RR, CJ, DATA)
+% If the local modifications to the user data structure are needed in
+% other user-provided functions then, besides setting the matrix J,
+% the DJACFUN function must also set NEW_DATA. Otherwise, it should
+% set NEW_DATA=[] (do not set NEW_DATA = DATA as it would lead to
+% unnecessary copying).
+%
+% The function DJACFUN must set FLAG=0 if successful, FLAG<0 if an
+% unrecoverable failure occurred, or FLAG>0 if a recoverable error
+% occurred.
+%
+% See also IDASetOptions
+%
+% NOTE: DJACFUN is specified through the property JacobianFn to
+% IDASetOptions and is used only if the property LinearSolver
+% was set to 'Dense'.
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2007, The Regents of the University of California.
+% $Revision: 1.3 $Date: 2011/05/26 00:01:23 $
diff --git a/sundialsTB/idas/function_types/IDADenseJacFnB.m b/sundialsTB/idas/function_types/IDADenseJacFnB.m
new file mode 100644
index 0000000..94f9da0
--- /dev/null
+++ b/sundialsTB/idas/function_types/IDADenseJacFnB.m
@@ -0,0 +1,24 @@
+%IDADenseJacFnb - type for dense Jacobian function for backward problems.
+%
+% The function DJACFUNB must be defined either as
+% FUNCTION [JB, FLAG] = DJACFUNB(T, YY, YP, YYB, YPB, RRB, CJB)
+% or as
+% FUNCTION [JB,FLAG,NEW_DATA] = DJACFUNB(T,YY,YP,YYB,YPB,RRB,CJB,DATA)
+% depending on whether a user data structure DATA was specified in
+% IDAInit. In either case, it must return the matrix JB, the
+% Jacobian (dfB/dyyB + cjb*dfB/dypB). The input argument RRB contains
+% the current value of f(t,yy,yp,yyB,ypB).
+%
+% The function DJACFUNB must set FLAG=0 if successful, FLAG<0 if an
+% unrecoverable failure occurred, or FLAG>0 if a recoverable error
+% occurred.
+%
+% See also IDADenseJacFn, IDASetOptions
+%
+% NOTE: DJACFUNB is specified through the property JacobianFn to
+% IDASetOptions and is used only if the property LinearSolver was
+% set to 'Dense'.
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2007, The Regents of the University of California.
+% $Revision: 1.2 $Date: 2011/05/26 00:01:23 $
diff --git a/sundialsTB/idas/function_types/IDAGcommFn.m b/sundialsTB/idas/function_types/IDAGcommFn.m
new file mode 100644
index 0000000..b8e5a03
--- /dev/null
+++ b/sundialsTB/idas/function_types/IDAGcommFn.m
@@ -0,0 +1,34 @@
+%IDAGcommFn - type for communication function (BBDPre).
+%
+% The function GCOMFUN must be defined as
+% FUNCTION FLAG = GCOMFUN(T, YY, YP)
+% and can be used to perform all interprocess communication necessary
+% to evaluate the approximate residual function for the BBDPre
+% preconditioner module.
+% If a user data structure DATA was specified in IDAInit, then
+% GCOMFUN must be defined as
+% FUNCTION [FLAG, NEW_DATA] = GCOMFUN(T, YY, YP, DATA)
+% If the local modifications to the user data structure are needed
+% in other user-provided functions then the GCOMFUN function must also
+% set NEW_DATA. Otherwise, it should set NEW_DATA=[] (do not set
+% NEW_DATA = DATA as it would lead to unnecessary copying).
+%
+% The function GCOMFUN must set FLAG=0 if successful, FLAG<0 if an
+% unrecoverable failure occurred, or FLAG>0 if a recoverable error
+% occurred.
+%
+% See also IDAGlocalFn, IDASetOptions
+%
+% NOTES:
+% GCOMFUN is specified through the GcommFn property in IDASetOptions
+% and is used only if the property PrecModule is set to 'BBDPre'.
+%
+% Each call to GCOMFUN is preceded by a call to the residual function
+% DAEFUN with the same arguments T, YY, and YP.
+% Thus GCOMFUN can omit any communication done by DAEFUN if relevant
+% to the evaluation of G by GLOCFUN. If all necessary communication
+% was done by DAEFUN, GCOMFUN need not be provided.
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2007, The Regents of the University of California.
+% $Revision: 1.3 $Date: 2011/05/26 00:01:23 $
diff --git a/sundialsTB/idas/function_types/IDAGcommFnB.m b/sundialsTB/idas/function_types/IDAGcommFnB.m
new file mode 100644
index 0000000..6e91e3e
--- /dev/null
+++ b/sundialsTB/idas/function_types/IDAGcommFnB.m
@@ -0,0 +1,28 @@
+%IDAGcommFnB - type for communication function (BBDPre) for backward problems.
+%
+% The function GCOMFUNB must be defined either as
+% FUNCTION FLAG = GCOMFUNB(T, YY, YP, YYB, YPB)
+% or as
+% FUNCTION [FLAG, NEW_DATA] = GCOMFUNB(T, YY, YP, YYB, YPB, DATA)
+% depending on whether a user data structure DATA was specified in
+% IDAInit.
+%
+% The function GCOMFUNB must set FLAG=0 if successful, FLAG<0 if an
+% unrecoverable failure occurred, or FLAG>0 if a recoverable error
+% occurred.
+%
+% See also IDAGlocalFnB, IDAGcommFn, IDASetOptions
+%
+% NOTES:
+% GCOMFUNB is specified through the GcommFn property in IDASetOptions
+% and is used only if the property PrecModule is set to 'BBDPre'.
+%
+% Each call to GCOMFUNB is preceded by a call to the residual function
+% DAEFUN with the same arguments T, YY, YP and YYB and YPB.
+% Thus GCOMFUNB can omit any communication done by DAEFUNB if relevant
+% to the evaluation of G by GLOCFUNB. If all necessary communication
+% was done by DAEFUNB, GCOMFUNB need not be provided.
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2007, The Regents of the University of California.
+% $Revision: 1.2 $Date: 2011/05/26 00:01:23 $
diff --git a/sundialsTB/idas/function_types/IDAGlocalFn.m b/sundialsTB/idas/function_types/IDAGlocalFn.m
new file mode 100644
index 0000000..e511490
--- /dev/null
+++ b/sundialsTB/idas/function_types/IDAGlocalFn.m
@@ -0,0 +1,29 @@
+%IDAGlocalFn - type for RES approximation function (BBDPre).
+%
+% The function GLOCFUN must be defined as
+% FUNCTION [GLOC, FLAG] = GLOCFUN(T,YY,YP)
+% and must return a vector GLOC corresponding to an approximation to f(t,yy,yp)
+% which will be used in the BBDPRE preconditioner module. The case where
+% G is mathematically identical to F is allowed.
+% If a user data structure DATA was specified in IDAInit, then
+% GLOCFUN must be defined as
+% FUNCTION [GLOC, FLAG, NEW_DATA] = GLOCFUN(T,YY,YP,DATA)
+% If the local modifications to the user data structure are needed
+% in other user-provided functions then, besides setting the vector G,
+% the GLOCFUN function must also set NEW_DATA. Otherwise, it should set
+% NEW_DATA=[] (do not set NEW_DATA = DATA as it would lead to
+% unnecessary copying).
+%
+% The function GLOCFUN must set FLAG=0 if successful, FLAG<0 if an
+% unrecoverable failure occurred, or FLAG>0 if a recoverable error
+% occurred.
+%
+% See also IDAGcommFn, IDASetOptions
+%
+% NOTE: GLOCFUN and GLOCFUNB are specified through the GlocalFn property
+% in IDASetOptions and are used only if the property PrecModule
+% is set to 'BBDPre'.
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2007, The Regents of the University of California.
+% $Revision: 1.3 $Date: 2011/05/26 00:01:23 $
diff --git a/sundialsTB/idas/function_types/IDAGlocalFnB.m b/sundialsTB/idas/function_types/IDAGlocalFnB.m
new file mode 100644
index 0000000..c078b2a
--- /dev/null
+++ b/sundialsTB/idas/function_types/IDAGlocalFnB.m
@@ -0,0 +1,23 @@
+%IDAGlocalFnB - type for RES approximation function (BBDPre) for backward problems.
+%
+% The function GLOCFUNB must be defined either as
+% FUNCTION [GLOCB, FLAG] = GLOCFUNB(T,YY,YP,YYB,YPB)
+% or as
+% FUNCTION [GLOCB, FLAG, NEW_DATA] = GLOCFUNB(T,YY,YP,YYB,YPB,DATA)
+% depending on whether a user data structure DATA was specified in
+% IDAInit. In either case, it must return the vector GLOCB
+% corresponding to an approximation to fB(t,yy,yp,yyB,ypB).
+%
+% The function GLOCFUNB must set FLAG=0 if successful, FLAG<0 if an
+% unrecoverable failure occurred, or FLAG>0 if a recoverable error
+% occurred.
+%
+% See also IDAGcommFnB, IDAGlocalFn, IDASetOptions
+%
+% NOTE: GLOCFUN and GLOCFUNB are specified through the GlocalFn property
+% in IDASetOptions and are used only if the property PrecModule
+% is set to 'BBDPre'.
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2007, The Regents of the University of California.
+% $Revision: 1.2 $Date: 2011/05/26 00:01:23 $
diff --git a/sundialsTB/idas/function_types/IDAJacTimesVecFn.m b/sundialsTB/idas/function_types/IDAJacTimesVecFn.m
new file mode 100644
index 0000000..da5267c
--- /dev/null
+++ b/sundialsTB/idas/function_types/IDAJacTimesVecFn.m
@@ -0,0 +1,28 @@
+%IDAJacTimesVecFn - type for Jacobian times vector function.
+%
+% The function JTVFUN must be defined as
+% FUNCTION [JV, FLAG] = JTVFUN(T,YY,YP,RR,V,CJ)
+% and must return a vector JV corresponding to the product of the
+% Jacobian ( df/dyy + cj * df/dyp ) with the vector v.
+% The input argument RR contains the current value of f(t,yy,yp).
+% If a user data structure DATA was specified in IDAInit, then
+% JTVFUN must be defined as
+% FUNCTION [JV, FLAG, NEW_DATA] = JTVFUN(T,YY,YP,RR,V,CJ,DATA)
+% If the local modifications to the user data structure are needed in
+% other user-provided functions then, besides setting the vector JV,
+% the JTVFUN function must also set NEW_DATA. Otherwise, it should set
+% NEW_DATA=[] (do not set NEW_DATA = DATA as it would lead to
+% unnecessary copying).
+%
+% The function JTVFUN must set FLAG=0 if successful, or FLAG~=0 if
+% a failure occurred.
+%
+% See also IDASetOptions
+%
+% NOTE: JTVFUN is specified through the property JacobianFn to
+% IDASetOptions and is used only if the property LinearSolver
+% was set to 'GMRES', 'BiCGStab', or 'TFQMR'.
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2007, The Regents of the University of California.
+% $Revision: 1.3 $Date: 2011/05/26 00:01:23 $
diff --git a/sundialsTB/idas/function_types/IDAJacTimesVecFnB.m b/sundialsTB/idas/function_types/IDAJacTimesVecFnB.m
new file mode 100644
index 0000000..6406e50
--- /dev/null
+++ b/sundialsTB/idas/function_types/IDAJacTimesVecFnB.m
@@ -0,0 +1,23 @@
+%IDAJacTimesVecFn - type for Jacobian times vector function for backward problems.
+%
+% The function JTVFUNB must be defined either as
+% FUNCTION [JVB,FLAG] = JTVFUNB(T,YY,YP,YYB,YPB,RRB,VB,CJB)
+% or as
+% FUNCTION [JVB,FLAG,NEW_DATA] = JTVFUNB(T,YY,YP,YYB,YPB,RRB,VB,CJB,DATA)
+% depending on whether a user data structure DATA was specified in
+% IDAInit. In either case, it must return the vector JVB, the
+% product of the Jacobian (dfB/dyyB + cj * dfB/dypB) and a vector
+% vB. The input argument RRB contains the current value of f(t,yy,yp,yyB,ypB).
+%
+% The function JTVFUNB must set FLAG=0 if successful, or FLAG~=0 if
+% a failure occurred.
+%
+% See also IDASetOptions
+%
+% NOTE: JTVFUNB is specified through the property JacobianFn to IDASetOptions
+% and is used only if the property LinearSolver was set to 'GMRES', 'BiCGStab',
+% or 'TFQMR'.
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2007, The Regents of the University of California.
+% $Revision: 1.2 $Date: 2011/05/26 00:01:23 $
diff --git a/sundialsTB/idas/function_types/IDAMonitorFn.m b/sundialsTB/idas/function_types/IDAMonitorFn.m
new file mode 100644
index 0000000..5ffaa6a
--- /dev/null
+++ b/sundialsTB/idas/function_types/IDAMonitorFn.m
@@ -0,0 +1,67 @@
+%IDAMonitorFn - type for monitoring function.
+%
+% The function MONFUN must be defined as
+% FUNCTION [] = MONFUN(CALL, T, YY, YP, YQ, YYS, YPS)
+%
+% To enable monitoring using a given monitor function MONFUN,
+% use IDASetOptions to set the property 'MonitorFn" to 'MONFUN'
+% (or to @MONFUN).
+%
+% MONFUN is called with the following input arguments:
+%
+% o CALL indicates the phase during the integration process at which
+% MONFUN is called:
+% CALL=1 : MONFUN was called at the initial time; this can be either
+% after IDAInit or after IDAReInit.
+% (typically, MONFUN should perform its own initialization)
+% CALL=2 : MONFUN was called right before a solver reinitializtion.
+% (typically, MONFUN should decide whether to initialize
+% itself or else to continue monitoring)
+% CALL=3 : MONFUN was called during solver finalization.
+% (typically, MONFUN should finalize monitoring)
+% CALL=0 : MONFUN was called after the solver took a successful
+% internal step.
+% (typically, MONFUN should collect and/or display data)
+%
+% o T is the current integration time
+%
+% o YY and YP are vectors containing the solution and solution
+% derivative at time T
+%
+% o YQ is a vector containing the quadrature variables at time T
+%
+% o YYS and YPS are matrices containing the forward sensitivities
+% and their derivatives, respectively, at time T.
+%
+% If additional data is needed inside a MONFUN function, then it must
+% be defined as
+% FUNCTION NEW_MONDATA = MONFUN(CALL, T, YY, YP, YQ, YYS, YPS, MONDATA)
+%
+% In this case, the MONFUN function is passed the additional argument
+% MONDATA, the same as that specified through the property 'MonitorData'
+% in IDASetOptions. If the local modifications to the monitor data structure
+% need to be saved (e.g. for future calls to MONFUN), then MONFUN must set
+% NEW_MONDATA. Otherwise, it should set NEW_MONDATA=[] (do not set
+% NEW_MONDATA = DATA as it would lead to unnecessary copying).
+%
+% NOTES:
+%
+% 1. MONFUN is specified through the MonitorFn property in IDASetOptions.
+% If this property is not set, or if it is empty, MONFUN is not used.
+% MONDATA is specified through the MonitorData property in IDASetOptions.
+%
+% 2. If quadrature integration is not enabled, YQ is empty. Similarly, if
+% forward sensitivity analysis is not enabled, YYS and YPS are empty.
+%
+% 3. When CALL = 2 or 3, all arguments YY, YP, YQ, YYS, and YPS are empty.
+% Moreover, when CALL = 3, T = 0.0
+%
+% 4. If MONFUN is used on the backward integration phase, YYS and YPS are
+% always empty.
+%
+% See also IDASetOptions, IDAMonitor
+%
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2007, The Regents of the University of California.
+% $Revision: 1.3 $Date: 2011/05/26 00:01:23 $
diff --git a/sundialsTB/idas/function_types/IDAMonitorFnB.m b/sundialsTB/idas/function_types/IDAMonitorFnB.m
new file mode 100644
index 0000000..a740c2f
--- /dev/null
+++ b/sundialsTB/idas/function_types/IDAMonitorFnB.m
@@ -0,0 +1,37 @@
+%IDAMonitorFnB - type of monitoring function for backward problems.
+%
+% The function MONFUNB must be defined as
+% FUNCTION [] = MONFUNB(CALL, IDXB, T, Y, YQ)
+% It is called after every internal IDASolveB step and can be used to
+% monitor the progress of the solver. MONFUNB is called with CALL=0
+% from IDAInitB at which time it should initialize itself and it
+% is called with CALL=2 from IDAFree. Otherwise, CALL=1.
+%
+% It receives as arguments the index of the backward problem (as
+% returned by IDAInitB), the current time T, solution vector Y,
+% and, if it was computed, the quadrature vector YQ. If quadratures
+% were not computed for this backward problem, YQ is empty here.
+%
+% If additional data is needed inside MONFUNB, it must be defined
+% as
+% FUNCTION NEW_MONDATA = MONFUNB(CALL, IDXB, T, Y, YQ, MONDATA)
+% If the local modifications to the user data structure need to be
+% saved (e.g. for future calls to MONFUNB), then MONFUNB must set
+% NEW_MONDATA. Otherwise, it should set NEW_MONDATA=[]
+% (do not set NEW_MONDATA = DATA as it would lead to unnecessary copying).
+%
+% A sample monitoring function, IDAMonitorB, is provided with CVODES.
+%
+% See also IDASetOptions, IDAMonitorB
+%
+% NOTES:
+%
+% MONFUNB is specified through the MonitorFn property in IDASetOptions.
+% If this property is not set, or if it is empty, MONFUNB is not used.
+% MONDATA is specified through the MonitorData property in IDASetOptions.
+%
+% See IDAMonitorB for an implementation example.
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2007, The Regents of the University of California.
+% $Revision: 1.1 $Date: 2007/08/21 17:38:44 $
diff --git a/sundialsTB/idas/function_types/IDAPrecSetupFn.m b/sundialsTB/idas/function_types/IDAPrecSetupFn.m
new file mode 100644
index 0000000..6835c2b
--- /dev/null
+++ b/sundialsTB/idas/function_types/IDAPrecSetupFn.m
@@ -0,0 +1,53 @@
+%IDAPrecSetupFn - type for preconditioner setup function.
+%
+% The user-supplied preconditioner setup function PSETFUN and
+% the user-supplied preconditioner solve function PSOLFUN
+% together must define a preconditoner matrix P which is an
+% approximation to the Newton matrix M = J_yy - cj*J_yp.
+% Here J_yy = df/dyy, J_yp = df/dyp, and cj is a scalar proportional
+% to the integration step size h. The solution of systems P z = r,
+% is to be carried out by the PrecSolve function, and PSETFUN
+% is to do any necessary setup operations.
+%
+% The user-supplied preconditioner setup function PSETFUN
+% is to evaluate and preprocess any Jacobian-related data
+% needed by the preconditioner solve function PSOLFUN.
+% 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 PSOLFUN, but instead will be called
+% only as often as necessary to achieve convergence within the
+% Newton iteration. If the PSOLFUN function needs no
+% preparation, the PSETFUN function need not be provided.
+%
+% Each call to the PSETFUN function is preceded by a call to
+% DAEFUN with the same (t,yy,yp) arguments. Thus the PSETFUN
+% function can use any auxiliary data that is computed and
+% saved by the DAEFUN function and made accessible to PSETFUN.
+%
+% The function PSETFUN must be defined as
+% FUNCTION FLAG = PSETFUN(T,YY,YP,RR,CJ)
+% If successful, it must return FLAG=0. For a recoverable error (in
+% which case the setup will be retried) it must set FLAG to a positive
+% integer value. If an unrecoverable error occurs, it must set FLAG
+% to a negative value, in which case the integration will be halted.
+% The input argument RR contains the current value of f(t,yy,yp).
+%
+% If a user data structure DATA was specified in IDASetUserData, then
+% PSETFUN must be defined as
+% FUNCTION [FLAG,NEW_DATA] = PSETFUN(T,YY,YP,RR,CJ,DATA)
+% If the local modifications to the user data structure are needed in
+% other user-provided functions then, besides setting the flag
+% FLAG, the PSETFUN function must also set NEW_DATA. Otherwise, it
+% should set NEW_DATA=[] (do not set NEW_DATA = DATA as it would lead
+% to unnecessary copying).
+%
+% See also IDAPrecSolveFn, IDASetOptions
+%
+% NOTE: PSETFUN and PSETFUNB are specified through the property
+% PrecSetupFn to IDASetOptions and are used only if the property
+% LinearSolver was set to 'GMRES', 'BiCGStab', or 'TFQMR'.
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2007, The Regents of the University of California.
+% $Revision: 1.3 $Date: 2011/05/18 23:55:40 $
diff --git a/sundialsTB/idas/function_types/IDAPrecSetupFnB.m b/sundialsTB/idas/function_types/IDAPrecSetupFnB.m
new file mode 100644
index 0000000..5638589
--- /dev/null
+++ b/sundialsTB/idas/function_types/IDAPrecSetupFnB.m
@@ -0,0 +1,18 @@
+%IDAPrecSetupFnB - type for preconditioner setup function for backward problems.
+%
+% The function PSETFUNB must be defined either as
+% FUNCTION FLAG = PSETFUNB(T,YY,YP,YYB,YPB,RRB,CJB)
+% or as
+% FUNCTION [FLAG,NEW_DATA] = PSETFUNB(T,YY,YP,YYB,YPB,RRB,CJB,DATA)
+% depending on whether a user data structure DATA was specified in
+% IDASetUserData.
+%
+% See also IDAPrecSolveFnB, IDAPrecSetupFn, IDASetOptions
+%
+% NOTE: PSETFUN and PSETFUNB are specified through the property
+% PrecSetupFn to IDASetOptions and are used only if the property
+% LinearSolver was set to 'GMRES', 'BiCGStab', or 'TFQMR'.
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2007, The Regents of the University of California.
+% $Revision: 1.2 $Date: 2011/05/26 00:01:23 $
diff --git a/sundialsTB/idas/function_types/IDAPrecSolveFn.m b/sundialsTB/idas/function_types/IDAPrecSolveFn.m
new file mode 100644
index 0000000..5e2a05e
--- /dev/null
+++ b/sundialsTB/idas/function_types/IDAPrecSolveFn.m
@@ -0,0 +1,33 @@
+%IDAPrecSolveFn - type for preconditioner solve function.
+%
+% The user-supplied preconditioner solve function PSOLFUN
+% is to solve a linear system P z = r, where P is the
+% preconditioner matrix.
+%
+% The function PSOLFUN must be defined as
+% FUNCTION [Z, FLAG] = PSOLFUN(T,YY,YP,RR,R)
+% and must return a vector Z containing the solution of Pz=r.
+% If PSOLFUN was successful, it must return FLAG=0. For a recoverable
+% error (in which case the step will be retried) it must set FLAG to a
+% positive value. If an unrecoverable error occurs, it must set FLAG
+% to a negative value, in which case the integration will be halted.
+% The input argument RR contains the current value of f(t,yy,yp).
+%
+% If a user data structure DATA was specified in IDAInit, then
+% PSOLFUN must be defined as
+% FUNCTION [Z, FLAG, NEW_DATA] = PSOLFUN(T,YY,YP,RR,R,DATA)
+% If the local modifications to the user data structure are needed in
+% other user-provided functions then, besides setting the vector Z and
+% the flag FLAG, the PSOLFUN function must also set NEW_DATA. Otherwise,
+% it should set NEW_DATA=[] (do not set NEW_DATA = DATA as it would
+% lead to unnecessary copying).
+%
+% See also IDAPrecSetupFn, IDASetOptions
+%
+% NOTE: PSOLFUN and PSOLFUNB are specified through the property
+% PrecSolveFn to IDASetOptions and are used only if the property
+% LinearSolver was set to 'GMRES', 'BiCGStab', or 'TFQMR'.
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2007, The Regents of the University of California.
+% $Revision: 1.3 $Date: 2011/05/26 00:01:23 $
diff --git a/sundialsTB/idas/function_types/IDAPrecSolveFnB.m b/sundialsTB/idas/function_types/IDAPrecSolveFnB.m
new file mode 100644
index 0000000..2457bb6
--- /dev/null
+++ b/sundialsTB/idas/function_types/IDAPrecSolveFnB.m
@@ -0,0 +1,23 @@
+%IDAPrecSolveFnB - type for preconditioner solve function.
+%
+% The user-supplied preconditioner solve function PSOLFUNB
+% is to solve a linear system P z = r, where P is the
+% preconditioner matrix.
+%
+% The function PSOLFUNB must be defined either as
+% FUNCTION [ZB,FLAG] = PSOLFUNB(T,YY,YP,YYB,YPB,RRB,RB)
+% or as
+% FUNCTION [ZB,FLAG,NEW_DATA] = PSOLFUNB(T,YY,YP,YYB,YPB,RRB,RB,DATA)
+% depending on whether a user data structure DATA was specified in
+% IDAInit. In either case, it must return the vector ZB and the
+% flag FLAG.
+%
+% See also IDAPrecSetupFnB, IDAPrecSolveFn, IDASetOptions
+%
+% NOTE: PSOLFUN and PSOLFUNB are specified through the property
+% PrecSolveFn to IDASetOptions and are used only if the property
+% LinearSolver was set to 'GMRES', 'BiCGStab', or 'TFQMR'.
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2007, The Regents of the University of California.
+% $Revision: 1.2 $Date: 2011/05/26 00:01:23 $
diff --git a/sundialsTB/idas/function_types/IDAQuadRhsFn.m b/sundialsTB/idas/function_types/IDAQuadRhsFn.m
new file mode 100644
index 0000000..3a65318
--- /dev/null
+++ b/sundialsTB/idas/function_types/IDAQuadRhsFn.m
@@ -0,0 +1,24 @@
+%IDAQuadRhsFn - type for user provided quadrature RHS function.
+%
+% The function QFUN must be defined as
+% FUNCTION [YQD, FLAG] = QFUN(T, YY, YP)
+% and must return a vector YQD corresponding to fQ(t,yy,yp), the
+% integrand for the integral to be evaluated.
+% If a user data structure DATA was specified in IDAInit, then
+% QFUN must be defined as
+% FUNCTION [YQD, FLAG, NEW_DATA] = QFUN(T, YY, YP, DATA)
+% If the local modifications to the user data structure are needed in
+% other user-provided functions then, besides setting the vector YQD,
+% the QFUN function must also set NEW_DATA. Otherwise, it should set
+% NEW_DATA=[] (do not set NEW_DATA = DATA as it would lead to
+% unnecessary copying).
+%
+% The function QFUN must set FLAG=0 if successful, FLAG<0 if an
+% unrecoverable failure occurred, or FLAG>0 if a recoverable error
+% occurred.
+%
+% See also IDAQuadInit
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2005, The Regents of the University of California.
+% $Revision: 1.3 $Date: 2011/05/26 00:01:23 $
diff --git a/sundialsTB/idas/function_types/IDAQuadRhsFnB.m b/sundialsTB/idas/function_types/IDAQuadRhsFnB.m
new file mode 100644
index 0000000..11500e6
--- /dev/null
+++ b/sundialsTB/idas/function_types/IDAQuadRhsFnB.m
@@ -0,0 +1,20 @@
+%IDAQuadRhsFnB - type for quadrature RHS function for backward problems
+%
+% The function QFUNB must be defined either as
+% FUNCTION [YQBD, FLAG] = QFUNB(T, YY, YP, YYB, YPB)
+% or as
+% FUNCTION [YQBD, FLAG, NEW_DATA] = QFUNB(T, YY, YP, YYB, YPB, DATA)
+% depending on whether a user data structure DATA was specified in
+% IDAInit. In either case, it must return the vector YQBD
+% corresponding to fQB(t,yy,yp,yyB,ypB), the integrand for the integral to be
+% evaluated on the backward phase.
+%
+% The function QFUNB must set FLAG=0 if successful, FLAG<0 if an
+% unrecoverable failure occurred, or FLAG>0 if a recoverable error
+% occurred.
+%
+% See also IDAQuadInitB
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2007, The Regents of the University of California.
+% $Revision: 1.2 $Date: 2011/05/26 00:01:23 $
diff --git a/sundialsTB/idas/function_types/IDAResFn.m b/sundialsTB/idas/function_types/IDAResFn.m
new file mode 100644
index 0000000..a1a705c
--- /dev/null
+++ b/sundialsTB/idas/function_types/IDAResFn.m
@@ -0,0 +1,23 @@
+%IDAResFn - type for residual function
+%
+% The function DAEFUN must be defined as
+% FUNCTION [R, FLAG] = DAEFUN(T, YY, YP)
+% and must return a vector R corresponding to f(t,yy,yp).
+% If a user data structure DATA was specified in IDAInit, then
+% DAEFUN must be defined as
+% FUNCTION [R, FLAG, NEW_DATA] = DAEFUN(T, YY, YP, DATA)
+% If the local modifications to the user data structure are needed
+% in other user-provided functions then, besides setting the vector YD,
+% the DAEFUN function must also set NEW_DATA. Otherwise, it should set
+% NEW_DATA=[] (do not set NEW_DATA = DATA as it would lead to
+% unnecessary copying).
+%
+% The function DAEFUN must set FLAG=0 if successful, FLAG<0 if an
+% unrecoverable failure occurred, or FLAG>0 if a recoverable error
+% occurred.
+%
+% See also IDAInit
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2007, The Regents of the University of California.
+% $Revision: 1.3 $Date: 2011/05/26 00:01:23 $
diff --git a/sundialsTB/idas/function_types/IDAResFnB.m b/sundialsTB/idas/function_types/IDAResFnB.m
new file mode 100644
index 0000000..62cdb46
--- /dev/null
+++ b/sundialsTB/idas/function_types/IDAResFnB.m
@@ -0,0 +1,19 @@
+%IDAResFnb - type for residual function for backward problems
+%
+% The function DAEFUNB must be defined either as
+% FUNCTION [RB, FLAG] = DAEFUNB(T, YY, YP, YYB, YPB)
+% or as
+% FUNCTION [RB, FLAG, NEW_DATA] = DAEFUNB(T, YY, YP, YYB, YPB, DATA)
+% depending on whether a user data structure DATA was specified in
+% IDAInit. In either case, it must return the vector RB
+% corresponding to fB(t,yy,yp,yyB,ypB).
+%
+% The function DAEFUNB must set FLAG=0 if successful, FLAG<0 if an
+% unrecoverable failure occurred, or FLAG>0 if a recoverable error
+% occurred.
+%
+% See also IDAInitB, IDARhsFn
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2007, The Regents of the University of California.
+% $Revision: 1.2 $Date: 2011/05/26 00:01:23 $
diff --git a/sundialsTB/idas/function_types/IDARootFn.m b/sundialsTB/idas/function_types/IDARootFn.m
new file mode 100644
index 0000000..35ed80f
--- /dev/null
+++ b/sundialsTB/idas/function_types/IDARootFn.m
@@ -0,0 +1,26 @@
+%IDARootFn - type for user provided root-finding function.
+%
+% The function ROOTFUN must be defined as
+% FUNCTION [G, FLAG] = ROOTFUN(T,YY,YP)
+% and must return a vector G corresponding to g(t,yy,yp).
+% If a user data structure DATA was specified in IDAInit, then
+% ROOTFUN must be defined as
+% FUNCTION [G, FLAG, NEW_DATA] = ROOTFUN(T,YY,YP,DATA)
+% If the local modifications to the user data structure are needed in
+% other user-provided functions then, besides setting the vector G,
+% the ROOTFUN function must also set NEW_DATA. Otherwise, it should
+% set NEW_DATA=[] (do not set NEW_DATA = DATA as it would lead to
+% unnecessary copying).
+%
+% The function ROOTFUN must set FLAG=0 if successful, or FLAG~=0 if
+% a failure occurred.
+%
+% See also IDASetOptions
+%
+% NOTE: ROOTFUN is specified through the RootsFn property in
+% IDASetOptions and is used only if the property NumRoots is a
+% positive integer.
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2005, The Regents of the University of California.
+% $Revision: 1.2 $Date: 2011/05/26 00:01:23 $
diff --git a/sundialsTB/idas/function_types/IDASensResFn.m b/sundialsTB/idas/function_types/IDASensResFn.m
new file mode 100644
index 0000000..1e964ec
--- /dev/null
+++ b/sundialsTB/idas/function_types/IDASensResFn.m
@@ -0,0 +1,26 @@
+%IDASensRhsFn - type for user provided sensitivity RHS function.
+%
+% The function DAESFUN must be defined as
+% FUNCTION [RS, FLAG] = DAESFUN(T,YY,YP,YYS,YPS)
+% and must return a matrix RS corresponding to fS(t,yy,yp,yyS,ypS).
+% If a user data structure DATA was specified in IDAInit, then
+% DAESFUN must be defined as
+% FUNCTION [RS, FLAG, NEW_DATA] = DAESFUN(T,YY,YP,YYS,YPS,DATA)
+% If the local modifications to the user data structure are needed in
+% other user-provided functions then, besides setting the matrix YSD,
+% the ODESFUN function must also set NEW_DATA. Otherwise, it should
+% set NEW_DATA=[] (do not set NEW_DATA = DATA as it would lead to
+% unnecessary copying).
+%
+% The function DAESFUN must set FLAG=0 if successful, FLAG<0 if an
+% unrecoverable failure occurred, or FLAG>0 if a recoverable error
+% occurred.
+%
+% See also IDASetFSAOptions
+%
+% NOTE: DAESFUN is specified through the property FSAResFn to
+% IDASetFSAOptions.
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2005, The Regents of the University of California.
+% $Revision: 1.2 $Date: 2011/05/26 00:01:23 $
diff --git a/sundialsTB/idas/idm/Contents.m b/sundialsTB/idas/idm/Contents.m
new file mode 100644
index 0000000..ab363f3
--- /dev/null
+++ b/sundialsTB/idas/idm/Contents.m
@@ -0,0 +1,3 @@
+% MEX binding of IDAS functions
+%
+%-- Radu Serban @ LLNL -- August 2007
diff --git a/sundialsTB/idas/idm/idm_bjac.m b/sundialsTB/idas/idm/idm_bjac.m
new file mode 100644
index 0000000..3427c36
--- /dev/null
+++ b/sundialsTB/idas/idm/idm_bjac.m
@@ -0,0 +1,13 @@
+function [J, flag, new_data] = idm_bjac(t, yy, yp, rr, cj, fct, data)
+
+%
+% Wrapper around the actual user-provided Matlab function
+%
+
+if isempty(data)
+ [J, flag] = feval(fct,t,yy,yp,rr,cj);
+ new_data = [];
+else
+ [J, flag, new_data] = feval(fct,t,yy,yp,rr,cj,data);
+end
+
diff --git a/sundialsTB/idas/idm/idm_bjacB.m b/sundialsTB/idas/idm/idm_bjacB.m
new file mode 100644
index 0000000..452206d
--- /dev/null
+++ b/sundialsTB/idas/idm/idm_bjacB.m
@@ -0,0 +1,13 @@
+function [J, flag, new_data] = idm_bjacB(t, yy, yp, rr, cj, fct, data)
+
+%
+% Wrapper around the actual user-provided Matlab function
+%
+
+if isempty(data)
+ [J, flag] = feval(fct,t,yy,yp,rr,cj);
+ new_data = [];
+else
+ [J, flag, new_data] = feval(fct,t,yy,yp,rr,cj,data);
+end
+
diff --git a/sundialsTB/idas/idm/idm_djac.m b/sundialsTB/idas/idm/idm_djac.m
new file mode 100644
index 0000000..a68fa16
--- /dev/null
+++ b/sundialsTB/idas/idm/idm_djac.m
@@ -0,0 +1,13 @@
+function [J, flag, new_data] = idm_djac(t, yy, yp, rr, cj, fct, data)
+
+%
+% Wrapper around the actual user-provided Matlab function
+%
+
+if isempty(data)
+ [J, flag] = feval(fct,t,yy,yp,rr,cj);
+ new_data = [];
+else
+ [J, flag, new_data] = feval(fct,t,yy,yp,rr,cj,data);
+end
+
diff --git a/sundialsTB/idas/idm/idm_djacB.m b/sundialsTB/idas/idm/idm_djacB.m
new file mode 100644
index 0000000..87528af
--- /dev/null
+++ b/sundialsTB/idas/idm/idm_djacB.m
@@ -0,0 +1,12 @@
+function [JB, flag, new_data] = idm_djacB(t, yy, yp, yyB, ypB, rrB, cjB, fct, data)
+
+%
+% Wrapper around the actual user-provided Matlab function
+%
+
+if isempty(data)
+ [JB, flag] = feval(fct,t,yy,yp,yyB,ypB,rrB,cjB);
+ new_data = [];
+else
+ [JB, flag, new_data] = feval(fct,t,yy,yp,yyB,ypB,rrB,cjB,data);
+end
diff --git a/sundialsTB/idas/idm/idm_gcom.m b/sundialsTB/idas/idm/idm_gcom.m
new file mode 100644
index 0000000..0a2e1e5
--- /dev/null
+++ b/sundialsTB/idas/idm/idm_gcom.m
@@ -0,0 +1,12 @@
+function [flag, new_data] = idm_gcom(t, yy, yp, fct, data)
+
+%
+% Wrapper around the actual user-provided Matlab function
+%
+
+if isempty(data)
+ flag = feval(fct,t,yy,yp);
+ new_data = [];
+else
+ [flag, new_data] = feval(fct,t,yy,yp,data);
+end
diff --git a/sundialsTB/idas/idm/idm_gcomB.m b/sundialsTB/idas/idm/idm_gcomB.m
new file mode 100644
index 0000000..06ce22a
--- /dev/null
+++ b/sundialsTB/idas/idm/idm_gcomB.m
@@ -0,0 +1,12 @@
+function [flag, new_data] = idm_gcomB(t, yy, yp, yyB, ypB, fct, data)
+
+%
+% Wrapper around the actual user-provided Matlab function
+%
+
+if isempty(data)
+ flag = feval(fct,t,yy,yp,yyB,ypB);
+ new_data = [];
+else
+ [flag, new_data] = feval(fct,t,yy,yp,yyB,ypB,data);
+end
diff --git a/sundialsTB/idas/idm/idm_gloc.m b/sundialsTB/idas/idm/idm_gloc.m
new file mode 100644
index 0000000..1879b00
--- /dev/null
+++ b/sundialsTB/idas/idm/idm_gloc.m
@@ -0,0 +1,13 @@
+function [res, flag, new_data] = idm_gloc(t, yy, yp, fct, data)
+
+%
+% Wrapper around the actual user-provided Matlab function
+%
+
+if isempty(data)
+ [res, flag] = feval(fct,t,yy,yp);
+ new_data = [];
+else
+ [res, flag, new_data] = feval(fct,t,yy,yp,data);
+end
+
diff --git a/sundialsTB/idas/idm/idm_glocB.m b/sundialsTB/idas/idm/idm_glocB.m
new file mode 100644
index 0000000..b32e34a
--- /dev/null
+++ b/sundialsTB/idas/idm/idm_glocB.m
@@ -0,0 +1,13 @@
+function [resB, flag, new_data] = idm_glocB(t, yy, yp, yyB, ypB, fct, data)
+
+%
+% Wrapper around the actual user-provided Matlab function
+%
+
+if isempty(data)
+ [resB, flag] = feval(fct,t,yy,yp,yyB,ypB);
+ new_data = [];
+else
+ [resB, flag, new_data] = feval(fct,t,yy,yp,yyB,ypB,data);
+end
+
diff --git a/sundialsTB/idas/idm/idm_jtv.m b/sundialsTB/idas/idm/idm_jtv.m
new file mode 100644
index 0000000..ebbadd1
--- /dev/null
+++ b/sundialsTB/idas/idm/idm_jtv.m
@@ -0,0 +1,12 @@
+function [Jv, flag, new_data] = idm_jtv(t, yy, yp, rr, v, cj, fct, data)
+
+%
+% Wrapper around the actual user-provided Matlab function
+%
+
+if isempty(data)
+ [Jv, flag] = feval(fct,t,yy,yp,rr,v,cj);
+ new_data = [];
+else
+ [Jv, flag, new_data] = feval(fct,t,yy,yp,rr,v,cj,data);
+end
diff --git a/sundialsTB/idas/idm/idm_jtvB.m b/sundialsTB/idas/idm/idm_jtvB.m
new file mode 100644
index 0000000..2d91c84
--- /dev/null
+++ b/sundialsTB/idas/idm/idm_jtvB.m
@@ -0,0 +1,12 @@
+function [JvB, flag, new_data] = idm_jtvB(t, yy, yp, yyB, ypB, rrB, vB, cjB, fct, data)
+
+%
+% Wrapper around the actual user-provided Matlab function
+%
+
+if isempty(data)
+ [JvB, flag] = feval(fct,t,yy,yp,yyB,ypB,rrB,vB,cjB);
+ new_data = [];
+else
+ [JvB, flag, new_data] = feval(fct,t,yy,yp,yyB,ypB,rrB,vB,cjB,data);
+end
diff --git a/sundialsTB/idas/idm/idm_monitor.m b/sundialsTB/idas/idm/idm_monitor.m
new file mode 100644
index 0000000..909b151
--- /dev/null
+++ b/sundialsTB/idas/idm/idm_monitor.m
@@ -0,0 +1,16 @@
+function new_mondata = idm_monitor(call, t, yy, yQ, Ns, yyS, fct, mondata)
+
+%
+% Wrapper around the actual user-provided Matlab function
+%
+
+N = length(yy);
+yyS = reshape(yyS, N, Ns);
+
+if isempty(mondata)
+ feval(fct, call, t, yy, yQ, yyS);
+ new_mondata = [];
+else
+ new_mondata = feval(fct, call, t, yy, yQ, yyS, mondata);
+end
+
diff --git a/sundialsTB/idas/idm/idm_monitorB.m b/sundialsTB/idas/idm/idm_monitorB.m
new file mode 100644
index 0000000..77019f5
--- /dev/null
+++ b/sundialsTB/idas/idm/idm_monitorB.m
@@ -0,0 +1,15 @@
+function [new_mondata] = idm_monitorB(call, idxB, t, y, yQ, fct, mondata)
+
+%
+% Wrapper around the actual user-provided Matlab function
+%
+
+N = length(y);
+
+idxB = idxB+1;
+if isempty(mondata)
+ feval(fct, call, idxB, t, y, yQ);
+ new_mondata = [];
+else
+ new_mondata = feval(fct, call, idxB, t, y, yQ, mondata);
+end
diff --git a/sundialsTB/idas/idm/idm_options.m b/sundialsTB/idas/idm/idm_options.m
new file mode 100644
index 0000000..f0da21c
--- /dev/null
+++ b/sundialsTB/idas/idm/idm_options.m
@@ -0,0 +1,66 @@
+function options = idm_options(KeyNames, varargin)
+
+m = length(KeyNames);
+
+% Initialize the output options structure
+
+options = [];
+for i = 1:m
+ options.(KeyNames{i}) = [];
+end
+
+% If the first argument is an options structure, read its non-empty fields
+% and update options. Store in j the start of key-value pairs.
+
+arg = varargin{1};
+
+if isa(arg,'struct')
+ for i = 1:m
+ if isfield(arg,KeyNames{i})
+ options.(KeyNames{i}) = arg.(KeyNames{i});
+ end
+ end
+ j = 2;
+else
+ j = 1;
+end
+
+% The remaining input arguments must be key-value pairs
+
+if rem(nargin-j,2) ~= 0
+ error('Arguments must be key-value pairs.');
+end
+
+% Process each key-value pair
+
+np = (nargin-j)/2;
+
+keynames = lower(KeyNames);
+
+for i = 1:np
+
+ % Get the key
+ key = varargin{j};
+
+ % key must be a string
+ if ~isstr(key)
+ error(sprintf('Argument %d is not a string property name.', j));
+ end
+
+ % Get the index in keynames that exactly matches the current key
+ % (modulo the case)
+ ik = strmatch(lower(key), keynames, 'exact');
+ if isempty(ik)
+ error(sprintf('Unrecognized property "%s"', key));
+ end
+
+ % Get the value
+ val = varargin{j+1};
+
+ % Set the proper field in options
+ options.(KeyNames{ik}) = val;
+
+ % move to next pair
+ j = j+2;
+
+end
diff --git a/sundialsTB/idas/idm/idm_pset.m b/sundialsTB/idas/idm/idm_pset.m
new file mode 100644
index 0000000..f071900
--- /dev/null
+++ b/sundialsTB/idas/idm/idm_pset.m
@@ -0,0 +1,12 @@
+function [flag, new_data] = idm_pset(t, yy, yp, rr, cj, fct, data)
+
+%
+% Wrapper around the actual user-provided Matlab function
+%
+
+if isempty(data)
+ flag = feval(fct,t,yy,yp,rr,cj);
+ new_data = [];
+else
+ [flag, new_data] = feval(fct,t,yy,yp,rr,cj,data);
+end
diff --git a/sundialsTB/idas/idm/idm_psetB.m b/sundialsTB/idas/idm/idm_psetB.m
new file mode 100644
index 0000000..9afe7b9
--- /dev/null
+++ b/sundialsTB/idas/idm/idm_psetB.m
@@ -0,0 +1,13 @@
+function [flag, new_data] = idm_psetB(t, yy, yp, yyB, ypB, rrB, cjB, fct, data)
+
+%
+% Wrapper around the actual user-provided Matlab function
+%
+
+if isempty(data)
+ flag = feval(fct,t,yy,yp,yyB,ypB,rrB,cjB);
+ new_data = [];
+else
+ [flag, new_data] = feval(fct,t,yy,yp,yyB,ypB,rrB,cjBy,data);
+end
+
diff --git a/sundialsTB/idas/idm/idm_psol.m b/sundialsTB/idas/idm/idm_psol.m
new file mode 100644
index 0000000..9c67f34
--- /dev/null
+++ b/sundialsTB/idas/idm/idm_psol.m
@@ -0,0 +1,13 @@
+function [z, flag, new_data] = idm_psol(t, yy, yp, rr, r, cj, fct, data)
+
+%
+% Wrapper around the actual user-provided Matlab function
+%
+
+if isempty(data)
+ [z, flag] = feval(fct,t,yy,yp,rr,r,cj);
+ new_data = [];
+else
+ [z, flag, new_data] = feval(fct,t,yy,yp,rr,r,cj,data);
+end
+
diff --git a/sundialsTB/idas/idm/idm_psolB.m b/sundialsTB/idas/idm/idm_psolB.m
new file mode 100644
index 0000000..40feaeb
--- /dev/null
+++ b/sundialsTB/idas/idm/idm_psolB.m
@@ -0,0 +1,13 @@
+function [zB, flag, new_data] = idm_psolB(t, yy, yp, yyB, ypB, rrB, rB, cjB, fct, data)
+
+%
+% Wrapper around the actual user-provided Matlab function
+%
+
+if isempty(data)
+ [zB, flag] = feval(fct,t,yy,yp,yyB,ypB,rrB,rB,cjB);
+ new_data = [];
+else
+ [zB, flag, new_data] = feval(fct,t,yy,yp,yyB,ypB,rrB,rB,cjB,data);
+end
+
diff --git a/sundialsTB/idas/idm/idm_res.m b/sundialsTB/idas/idm/idm_res.m
new file mode 100644
index 0000000..1224e38
--- /dev/null
+++ b/sundialsTB/idas/idm/idm_res.m
@@ -0,0 +1,12 @@
+function [res, flag, new_data] = idm_res(t, yy, yp, fct, data)
+
+%
+% Wrapper around the actual user-provided Matlab function
+%
+
+if isempty(data)
+ [res, flag] = feval(fct,t,yy,yp);
+ new_data = [];
+else
+ [res, flag, new_data] = feval(fct,t,yy,yp,data);
+end
diff --git a/sundialsTB/idas/idm/idm_resB.m b/sundialsTB/idas/idm/idm_resB.m
new file mode 100644
index 0000000..b4e8b32
--- /dev/null
+++ b/sundialsTB/idas/idm/idm_resB.m
@@ -0,0 +1,54 @@
+function [resB, flag, new_data] = idm_resB(type, varargin)
+
+%
+% Wrapper around the actual user-provided Matlab function
+%
+
+switch type
+
+ case 0
+
+ % Not dependent on yS
+
+ t = varargin{1};
+ yy = varargin{2};
+ yp = varargin{3};
+ yyB = varargin{4};
+ ypB = varargin{5};
+ fct = varargin{6};
+ data = varargin{7};
+
+ if isempty(data)
+ [resB, flag] = feval(fct,t,yy,yp,yyB,ypB);
+ new_data = [];
+ else
+ [resB, flag, new_data] = feval(fct,t,yy,yp,yyB,ypB,data);
+ end
+
+ case 1
+
+ % Dependent on yS
+
+ t = varargin{1};
+ yy = varargin{2};
+ yp = varargin{3};
+ Ns = varargin{4};
+ yyS = varargin{5};
+ ypS = varargin{6};
+ yyB = varargin{7};
+ ypB = varargin{8};
+ fct = varargin{9};
+ data = varargin{10};
+
+ N = length(yy);
+ yyS = reshape(yyS,N,Ns);
+ ypS = reshape(ypS,N,Ns);
+
+ if isempty(data)
+ [resB, flag] = feval(fct,t,yy,yp,yyS,ypS,yyB,ypB);
+ new_data = [];
+ else
+ [resB, flag, new_data] = feval(fct,t,yy,yp,yyS,ypS,yyB,ypB,data);
+ end
+
+end
diff --git a/sundialsTB/idas/idm/idm_resS.m b/sundialsTB/idas/idm/idm_resS.m
new file mode 100644
index 0000000..7dcef47
--- /dev/null
+++ b/sundialsTB/idas/idm/idm_resS.m
@@ -0,0 +1,18 @@
+function [rrS, flag, new_data] = idm_resS(t, yy, yp, rr, Ns, yyS, ypS, fct, data)
+
+%
+% Wrapper around the actual user-provided Matlab function
+%
+
+N = length(yy);
+yyS = reshape(yyS, N, Ns);
+ypS = reshape(ypS, N, Ns);
+
+if isempty(data)
+ [rrS, flag] = feval(fct,t,yy,yp,rr,yyS,ypS);
+ new_data = [];
+else
+ [rrS, flag, new_data] = feval(fct,t,yy,yp,rr,yyS,ypS,data);
+end
+
+rrS = reshape(rrS, N*Ns, 1);
\ No newline at end of file
diff --git a/sundialsTB/idas/idm/idm_rhsQ.m b/sundialsTB/idas/idm/idm_rhsQ.m
new file mode 100644
index 0000000..aeb35e2
--- /dev/null
+++ b/sundialsTB/idas/idm/idm_rhsQ.m
@@ -0,0 +1,12 @@
+function [qd, flag, new_data] = idm_rhsQ(t, yy, yp, fct, data)
+
+%
+% Wrapper around the actual user-provided Matlab function
+%
+
+if isempty(data)
+ [qd, flag] = feval(fct,t,yy,yp);
+ new_data =[];
+else
+ [qd, flag, new_data] = feval(fct,t,yy,yp,data);
+end
diff --git a/sundialsTB/idas/idm/idm_rhsQB.m b/sundialsTB/idas/idm/idm_rhsQB.m
new file mode 100644
index 0000000..cf191af
--- /dev/null
+++ b/sundialsTB/idas/idm/idm_rhsQB.m
@@ -0,0 +1,55 @@
+function [qBd, flag, new_data] = idm_rhsQB(type, varargin)
+
+%
+% Wrapper around the actual user-provided Matlab function
+%
+
+switch type
+
+ case 0
+
+ % Not dependent on yS
+
+ t = varargin{1};
+ yy = varargin{2};
+ yp = varargin{3};
+ yyB = varargin{4};
+ ypB = varargin{5};
+ fct = varargin{6};
+ data = varargin{7};
+
+ if isempty(data)
+ [qBd, flag] = feval(fct,t,yy,yp,yyB,ypB);
+ new_data = [];
+ else
+ [qBd, flag, new_data] = feval(fct,t,yy,yp,yyB,ypB,data);
+ end
+
+ case 1
+
+ % Dependent on yS
+
+ t = varargin{1};
+ yy = varargin{2};
+ yp = varargin{3};
+ Ns = varargin{4};
+ yyS = varargin{5};
+ ypS = varargin{6};
+ yyB = varargin{7};
+ ypB = varargin{8};
+ fct = varargin{9};
+ data = varargin{10};
+
+ N = length(y);
+ yyS = reshape(yS,N,Ns);
+ ypS = reshape(yS,N,Ns);
+
+ if isempty(data)
+ [qBd, flag] = feval(fct,t,yy,yp,yyS,ypS,yyB,ypB);
+ new_data = [];
+ else
+ [qBd, flag, new_data] = feval(fct,t,yy,yp,yyS,ypS,yyB,ypB,data);
+ end
+
+
+end
\ No newline at end of file
diff --git a/sundialsTB/idas/idm/idm_root.m b/sundialsTB/idas/idm/idm_root.m
new file mode 100644
index 0000000..5ebf404
--- /dev/null
+++ b/sundialsTB/idas/idm/idm_root.m
@@ -0,0 +1,13 @@
+function [g, flag, new_data] = idm_root(t, yy, yp, fct, data)
+
+%
+% Wrapper around the actual user-provided Matlab function
+%
+
+if isempty(data)
+ [g, flag] = feval(fct,t,yy,yp);
+ new_data = [];
+else
+ [g, flag, new_data] = feval(fct,t,yy,yp,data);
+end
+
diff --git a/sundialsTB/idas/idm/src/idm.c b/sundialsTB/idas/idm/src/idm.c
new file mode 100644
index 0000000..5ca7faf
--- /dev/null
+++ b/sundialsTB/idas/idm/src/idm.c
@@ -0,0 +1,3513 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.21 $
+ * $Date: 2012/03/07 21:49:18 $
+ * -----------------------------------------------------------------
+ * Programmer: 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 sundials-x.y.z/src/idas/LICENSE.
+ * -----------------------------------------------------------------
+ * MEX implementation for IDAS Matlab interface.
+ * -----------------------------------------------------------------
+ */
+
+
+/*
+ * TO DO
+ *
+ * - implement idmSolveB_more
+ * - implement IDM_CalcICB
+ */
+
+
+
+#include <string.h>
+#include <stdlib.h>
+#include "idm.h"
+#include "nvm.h"
+
+/*
+ * ---------------------------------------------------------------------------------
+ * Global interface data variable
+ * ---------------------------------------------------------------------------------
+ */
+
+idmInterfaceData idmData = NULL;
+
+/*
+ * ---------------------------------------------------------------------------------
+ * Static function prototypes
+ * ---------------------------------------------------------------------------------
+ */
+
+static void idmInitIDASdata();
+static void idmPersistIDASdata();
+static void idmFinalIDASdata();
+
+static void idmInitPbData(idmPbData pb);
+static void idmPersistPbData(idmPbData pb);
+static void idmFinalPbData(idmPbData pb);
+
+
+static int IDM_Initialization(int action, int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]);
+static int IDM_QuadInitialization(int action, int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]);
+static int IDM_SensInitialization(int action, int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]);
+static int IDM_AdjInitialization(int action, int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]);
+
+static int IDM_InitializationB(int action, int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]);
+static int IDM_QuadInitializationB(int action, int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]);
+
+static int IDM_SensToggleOff(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]);
+
+static int IDM_CalcIC(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]);
+static int IDM_CalcICB(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]);
+
+static int IDM_Solve(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]);
+static int IDM_SolveB(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]);
+
+static int idmSolveB_one(mxArray *plhs[], int NtoutB, double *toutB, int itaskB);
+static int idmSolveB_more(mxArray *plhs[], int NtoutB, double *toutB, int itaskB,
+ booleantype any_quadrB, booleantype any_monB);
+
+static int IDM_Stats(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]);
+static int IDM_StatsB(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]);
+
+static int IDM_Set(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]);
+static int IDM_SetB(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]);
+
+static int IDM_Get(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]);
+
+static int IDM_Free(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]);
+
+/*
+ * ---------------------------------------------------------------------------------
+ * Main entry point
+ * ---------------------------------------------------------------------------------
+ */
+
+void mexFunction(int nlhs, mxArray *plhs[],
+ int nrhs, const mxArray *prhs[])
+{
+ int mode;
+ /*
+ Modes:
+
+ 1 - initialize IDAS solver
+ 2 - initialize quadratures
+ 3 - initialize forward sensitivity calculations
+ 4 - initialize adjoint sensitivity calculations
+ 5 - initialize backward solver
+ 6 - initialize backward quadratures
+
+ 11 - reinitialize IDAS solver
+ 12 - reinitialize quadratures
+ 13 - reinitialize forward sensitivity calculations
+ 14 - reinitialize adjoint sensitivity calculations
+ 15 - reinitialize backward solver
+ 16 - reinitialize backward quadratures
+
+ 18 - toggle FSA off
+
+ 20 - solve problem
+ 21 - solve backward problem TODO
+
+ 25 - calculate consistent IC
+ 26 - calculate backward consistent IC TODO
+
+ 30 - get integrator stats
+ 31 - get backward integrator stats
+ 32 - extract data from ida_mem
+
+ 33 - set one optional input at a time
+ 34 - set one optional input at a time for backward problems
+
+ 40 - finalize
+ */
+
+ mode = (int)mxGetScalar(prhs[0]);
+
+ mexUnlock();
+
+ if ( (mode != 1) && (idmData == NULL) ) {
+ mexErrMsgTxt("IDAS - Illegal attempt to call before IDAInit.");
+ }
+
+
+ switch(mode) {
+
+ /* Initialization functions */
+
+ case 1:
+ if (idmData != NULL) {
+ IDM_Free(nlhs, plhs, nrhs-1, &prhs[1]);
+ idmFinalIDASdata();
+ }
+ idmInitIDASdata();
+ IDM_Initialization(0, nlhs, plhs, nrhs-1, &prhs[1]);
+ break;
+
+ case 2:
+ IDM_QuadInitialization(0, nlhs, plhs, nrhs-1, &prhs[1]);
+ break;
+
+ case 3:
+ IDM_SensInitialization(0, nlhs, plhs, nrhs-1, &prhs[1]);
+ break;
+
+ case 4:
+ IDM_AdjInitialization(0, nlhs, plhs, nrhs-1, &prhs[1]);
+ break;
+
+ case 5:
+ IDM_InitializationB(0, nlhs, plhs, nrhs-1, &prhs[1]);
+ break;
+
+ case 6:
+ IDM_QuadInitializationB(0, nlhs, plhs, nrhs-1, &prhs[1]);
+ break;
+
+ /* Re-initialization functions */
+
+ case 11:
+ IDM_Initialization(1, nlhs, plhs, nrhs-1, &prhs[1]);
+ break;
+
+ case 12:
+ IDM_QuadInitialization(1, nlhs, plhs, nrhs-1, &prhs[1]);
+ break;
+
+ case 13:
+ IDM_SensInitialization(1, nlhs, plhs, nrhs-1, &prhs[1]);
+ break;
+
+ case 14:
+ IDM_AdjInitialization(1, nlhs, plhs, nrhs-1, &prhs[1]);
+ break;
+
+ case 15:
+ IDM_InitializationB(1, nlhs, plhs, nrhs-1, &prhs[1]);
+ break;
+
+ case 16:
+ IDM_QuadInitializationB(1, nlhs, plhs, nrhs-1, &prhs[1]);
+ break;
+
+ /* Sensitivity toggle function */
+
+ case 18:
+ IDM_SensToggleOff(nlhs, plhs, nrhs-1, &prhs[1]);
+ break;
+
+ /* Solve functions */
+
+ case 20:
+ IDM_Solve(nlhs, plhs, nrhs-1, &prhs[1]);
+ break;
+
+ case 21:
+ IDM_SolveB(nlhs, plhs, nrhs-1, &prhs[1]);
+ break;
+
+ /* Consistent IC calculation functions */
+
+ case 25:
+ IDM_CalcIC(nlhs, plhs, nrhs-1, &prhs[1]);
+ break;
+
+ case 26:
+ IDM_CalcICB(nlhs, plhs, nrhs-1, &prhs[1]);
+ break;
+
+ /* Optional output extraction functions */
+
+ case 30:
+ IDM_Stats(nlhs, plhs, nrhs-1, &prhs[1]);
+ break;
+
+ case 31:
+ IDM_StatsB(nlhs, plhs, nrhs-1, &prhs[1]);
+ break;
+
+ case 32:
+ IDM_Get(nlhs, plhs, nrhs-1, &prhs[1]);
+ break;
+
+ case 33:
+ IDM_Set(nlhs, plhs, nrhs-1, &prhs[1]);
+ break;
+
+ case 34:
+ IDM_SetB(nlhs, plhs, nrhs-1, &prhs[1]);
+ break;
+
+ /* Memory deallocation function */
+
+ case 40:
+ IDM_Free(nlhs, plhs, nrhs-1, &prhs[1]);
+ idmFinalIDASdata();
+ return;
+
+ }
+
+ /* Unless this was the IDAFree call,
+ * make data persistent and lock the MEX file */
+ if (mode != 40) {
+ idmPersistIDASdata();
+ mexLock();
+ }
+
+ return;
+}
+
+
+/*
+ * ---------------------------------------------------------------------------------
+ * Private functions
+ * ---------------------------------------------------------------------------------
+ */
+
+
+static void idmInitIDASdata()
+{
+ /* Allocate space for global IDAS data structure */
+
+ idmData = (idmInterfaceData) mxMalloc(sizeof(struct idmInterfaceData_));
+
+ /* Initialize global IDAS data */
+
+ idmData->ida_mem = NULL;
+
+ idmData->fwdPb = NULL;
+ idmData->bckPb = NULL;
+
+ idmData->NbckPb = 0;
+
+ idmData->Nd = 0;
+ idmData->Nc = 0;
+ idmData->asa = FALSE;
+
+ idmData->errMsg = TRUE;
+
+ return;
+}
+
+
+static void idmInitPbData(idmPbData pb)
+{
+ mxArray *empty;
+
+ pb->n = 0;
+ pb->nq = 0;
+ pb->ng = 0;
+ pb->ns = 0;
+
+ pb->YY = NULL;
+ pb->YP = NULL;
+
+ pb->YQ = NULL;
+
+ pb->YYS = NULL;
+ pb->YPS = NULL;
+
+ pb->Quadr = FALSE;
+ pb->Fsa = FALSE;
+ pb->Mon = FALSE;
+
+ pb->LS = LS_DENSE;
+ pb->PM = PM_NONE;
+
+ empty = mxCreateDoubleMatrix(0,0,mxREAL);
+
+ pb->RESfct = mxDuplicateArray(empty);
+ pb->Gfct = mxDuplicateArray(empty);
+ pb->QUADfct = mxDuplicateArray(empty);
+ pb->SRESfct = mxDuplicateArray(empty);
+ pb->JACfct = mxDuplicateArray(empty);
+ pb->PSETfct = mxDuplicateArray(empty);
+ pb->PSOLfct = mxDuplicateArray(empty);
+ pb->GLOCfct = mxDuplicateArray(empty);
+ pb->GCOMfct = mxDuplicateArray(empty);
+
+ pb->MONfct = mxDuplicateArray(empty);
+ pb->MONdata = mxDuplicateArray(empty);
+
+ pb->mtlb_data = mxDuplicateArray(empty);
+
+ pb->fwd = idmData->fwdPb;
+
+ pb->index = 0;
+ pb->next = NULL;
+
+ mxDestroyArray(empty);
+}
+
+
+static void idmPersistIDASdata()
+{
+ idmPbData tmpPb;
+
+ /* Make global memory persistent */
+
+ if (idmData->fwdPb != NULL) {
+ idmPersistPbData(idmData->fwdPb);
+ mexMakeMemoryPersistent(idmData->fwdPb);
+ }
+
+ tmpPb = idmData->bckPb;
+ while(tmpPb != NULL) {
+ idmPersistPbData(tmpPb);
+ mexMakeMemoryPersistent(tmpPb);
+ tmpPb = tmpPb->next;
+ }
+
+ mexMakeMemoryPersistent(idmData);
+
+ return;
+}
+
+
+static void idmPersistPbData(idmPbData pb)
+{
+ mexMakeArrayPersistent(pb->mtlb_data);
+
+ mexMakeArrayPersistent(pb->RESfct);
+ mexMakeArrayPersistent(pb->Gfct);
+ mexMakeArrayPersistent(pb->QUADfct);
+ mexMakeArrayPersistent(pb->SRESfct);
+ mexMakeArrayPersistent(pb->JACfct);
+ mexMakeArrayPersistent(pb->PSETfct);
+ mexMakeArrayPersistent(pb->PSOLfct);
+ mexMakeArrayPersistent(pb->GLOCfct);
+ mexMakeArrayPersistent(pb->GCOMfct);
+
+ mexMakeArrayPersistent(pb->MONfct);
+ mexMakeArrayPersistent(pb->MONdata);
+}
+
+static void idmFinalIDASdata()
+{
+ idmPbData tmpPb;
+
+ if (idmData == NULL) return;
+
+ if (idmData->fwdPb != NULL) {
+ idmFinalPbData(idmData->fwdPb);
+ mxFree(idmData->fwdPb);
+ idmData->fwdPb = NULL;
+ }
+
+ while(idmData->bckPb != NULL) {
+ tmpPb = idmData->bckPb->next;
+ mxFree(idmData->bckPb);
+ idmData->bckPb = tmpPb;
+ }
+
+ mxFree(idmData);
+ idmData = NULL;
+
+ return;
+}
+
+
+static void idmFinalPbData(idmPbData pb)
+{
+
+ if (pb->YY != NULL) N_VDestroy(pb->YY);
+ if (pb->YP != NULL) N_VDestroy(pb->YP);
+
+ if (pb->YQ != NULL) N_VDestroy(pb->YQ);
+
+ if (pb->YYS != NULL) N_VDestroyVectorArray(pb->YYS, pb->ns);
+ if (pb->YPS != NULL) N_VDestroyVectorArray(pb->YPS, pb->ns);
+
+ mxDestroyArray(pb->mtlb_data);
+
+ mxDestroyArray(pb->RESfct);
+ mxDestroyArray(pb->Gfct);
+ mxDestroyArray(pb->QUADfct);
+ mxDestroyArray(pb->SRESfct);
+ mxDestroyArray(pb->JACfct);
+ mxDestroyArray(pb->PSETfct);
+ mxDestroyArray(pb->PSOLfct);
+ mxDestroyArray(pb->GLOCfct);
+ mxDestroyArray(pb->GCOMfct);
+
+ mxDestroyArray(pb->MONfct);
+ mxDestroyArray(pb->MONdata);
+
+}
+
+/*
+ * ---------------------------------------------------------------------------------
+ * Error handler function.
+ *
+ * This function is both passed as the IDAS error handler and used throughout
+ * the Matlab interface.
+ *
+ * If called directly by one of the interface functions, error_code = -999 to
+ * indicate an error and err_code = +999 to indicate a warning. Otherwise,
+ * err_code is set by the calling IDAS function.
+ *
+ * NOTE: mexErrMsgTxt will end the execution of the MEX file. Therefore we do
+ * not have to intercept any of the IDAS error return flags.
+ * The only return flags we intercept are those from IDASolve() and IDASolveB()
+ * which are passed back to the user (only positive values will make it).
+ * ---------------------------------------------------------------------------------
+ */
+
+void idmErrHandler(int error_code,
+ const char *module, const char *function,
+ char *msg, void *f_data)
+{
+ char err_msg[256];
+
+ if (!(idmData->errMsg)) return;
+
+ if (error_code > 0) {
+ sprintf(err_msg,"Warning in ==> %s\n%s",function,msg);
+ mexWarnMsgTxt(err_msg);
+ } else if (error_code < 0) {
+ sprintf(err_msg,"Error using ==> %s\n%s",function,msg);
+ mexErrMsgTxt(err_msg);
+ }
+
+ return;
+}
+
+
+/*
+ * ---------------------------------------------------------------------------------
+ * Redability replacements
+ * ---------------------------------------------------------------------------------
+ */
+
+#define ida_mem (idmData->ida_mem)
+
+#define asa (idmData->asa)
+#define Nd (idmData->Nd)
+#define Nc (idmData->Nc)
+#define NbckPb (idmData->NbckPb)
+
+#define fsa (fwdPb->Fsa)
+#define quadr (fwdPb->Quadr)
+#define mon (fwdPb->Mon)
+#define rootSet (fwdPb->RootSet)
+#define tstopSet (fwdPb->TstopSet)
+
+#define yy (fwdPb->YY)
+#define yp (fwdPb->YP)
+#define yQ (fwdPb->YQ)
+#define yyS (fwdPb->YYS)
+#define ypS (fwdPb->YPS)
+#define N (fwdPb->n)
+#define Nq (fwdPb->nq)
+#define Ng (fwdPb->ng)
+#define Ns (fwdPb->ns)
+#define ls (fwdPb->LS)
+#define pm (fwdPb->PM)
+
+#define mtlb_data (fwdPb->mtlb_data)
+
+#define mtlb_RESfct (fwdPb->RESfct)
+#define mtlb_QUADfct (fwdPb->QUADfct)
+#define mtlb_JACfct (fwdPb->JACfct)
+#define mtlb_PSETfct (fwdPb->PSETfct)
+#define mtlb_PSOLfct (fwdPb->PSOLfct)
+#define mtlb_GLOCfct (fwdPb->GLOCfct)
+#define mtlb_GCOMfct (fwdPb->GCOMfct)
+#define mtlb_Gfct (fwdPb->Gfct)
+#define mtlb_SRESfct (fwdPb->SRESfct)
+
+#define mtlb_MONfct (fwdPb->MONfct)
+#define mtlb_MONdata (fwdPb->MONdata)
+
+
+#define indexB (bckPb->index)
+
+#define quadrB (bckPb->Quadr)
+#define monB (bckPb->Mon)
+
+#define yyB (bckPb->YY)
+#define ypB (bckPb->YP)
+#define yQB (bckPb->YQ)
+#define NB (bckPb->n)
+#define NqB (bckPb->nq)
+#define lsB (bckPb->LS)
+#define pmB (bckPb->PM)
+
+#define mtlb_dataB (bckPb->mtlb_data)
+
+#define mtlb_RESfctB (bckPb->RESfct)
+#define mtlb_QUADfctB (bckPb->QUADfct)
+#define mtlb_JACfctB (bckPb->JACfct)
+#define mtlb_PSETfctB (bckPb->PSETfct)
+#define mtlb_PSOLfctB (bckPb->PSOLfct)
+#define mtlb_GLOCfctB (bckPb->GLOCfct)
+#define mtlb_GCOMfctB (bckPb->GCOMfct)
+
+#define mtlb_MONfctB (bckPb->MONfct)
+#define mtlb_MONdataB (bckPb->MONdata)
+
+
+/*
+ * ---------------------------------------------------------------------------------
+ * Exported procedures
+ * ---------------------------------------------------------------------------------
+ */
+
+/* IDM_Initialization
+ *
+ * action = 0 -> IDACreate + IDAInit
+ * action = 1 -> IDAReInit
+ *
+ * prhs contains:
+ * res
+ * t0
+ * yy0
+ * yp0
+ * options
+ * data
+ *
+ * plhs contains:
+ * status
+ *
+ */
+
+static int IDM_Initialization(int action, int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
+{
+ idmPbData fwdPb;
+
+ const mxArray *options;
+
+ double t0, *yy0, *yp0;
+
+ int maxord;
+ long int mxsteps;
+
+ int itol;
+ realtype reltol, Sabstol, *Vabstol;
+ N_Vector NV_abstol;
+
+ double hin, hmax;
+ double tstop;
+
+ booleantype suppress;
+
+ long int mupper, mlower;
+ int gstype, maxl;
+ long int mudq, mldq;
+ double dqrely;
+
+ double *id, *cnstr;
+ N_Vector NV_id, NV_cnstr;
+
+ booleantype errmsg;
+
+ booleantype res_s; /* ignored */
+
+ int status;
+
+ /*
+ * ------------------------------------
+ * Process inputs based on action
+ * ------------------------------------
+ */
+
+ switch (action) {
+
+ case 0: /* SOLVER INITIALIZATION */
+
+ /* Create and initialize a new problem */
+
+ fwdPb = (idmPbData) mxMalloc(sizeof(struct idmPbData_));
+ idmInitPbData(fwdPb);
+
+ idmData->fwdPb = fwdPb;
+
+ /* Initialize appropriate vector module */
+
+ InitVectors();
+
+ /* Extract user-provided RES function */
+
+ mxDestroyArray(mtlb_RESfct);
+ mtlb_RESfct = mxDuplicateArray(prhs[0]);
+
+ /* Extract initial time */
+
+ t0 = (double)mxGetScalar(prhs[1]);
+
+ /* Extract initial conditions */
+
+ yy0 = mxGetPr(prhs[2]);
+ yp0 = mxGetPr(prhs[3]);
+ N = mxGetM(prhs[2]);
+
+ /* Create the solution N_Vectors */
+
+ yy = NewVector(N);
+ yp = NewVector(N);
+
+ /* Load initial conditions */
+
+ PutData(yy, yy0, N);
+ PutData(yp, yp0, N);
+
+ /* Extract options structure */
+
+ options = prhs[4];
+
+ break;
+
+ case 1: /* SOLVER RE-INITIALIZATION */
+
+ fwdPb = idmData->fwdPb;
+
+ /* If monitoring was enabled, finalize it now. */
+
+ if (mon) mxW_IDAMonitor(2, 0.0, NULL, NULL, NULL, fwdPb);
+
+ /* Extract initial time */
+
+ t0 = (double)mxGetScalar(prhs[0]);
+
+ /* Extract initial conditions */
+
+ yy0 = mxGetPr(prhs[1]);
+
+ if (mxGetM(prhs[1]) != N) {
+ idmErrHandler(-999, "IDAS", "IDAReInit",
+ "Size of yy0 changed from IDAInit call.", NULL);
+ goto error_return;
+ }
+
+ yp0 = mxGetPr(prhs[2]);
+
+ if (mxGetM(prhs[2]) != N) {
+ idmErrHandler(-999, "IDAS", "IDAReInit",
+ "Size of yp0 changed from IDAInit call.", NULL);
+ goto error_return;
+ }
+
+ /* Load initial conditions */
+
+ PutData(yy, yy0, N);
+ PutData(yp, yp0, N);
+
+ /* Extract options structure */
+
+ options = prhs[3];
+
+ break;
+
+ }
+
+ /* Process the options structure */
+
+ status = get_IntgrOptions(options, fwdPb, TRUE,
+ &maxord, &mxsteps,
+ &itol, &reltol, &Sabstol, &Vabstol,
+ &hin, &hmax, &tstop,
+ &suppress, &errmsg,
+ &id, &cnstr,
+ &res_s);
+ if (status != 0) goto error_return;
+
+ /*
+ * ----------------------------------------
+ * Call appropriate IDAS functions
+ *
+ * If action = 0
+ * Create IDAS object and allocate memory
+ * Attach error handler function
+ * Redirect output
+ * If action = 1
+ * Reinitialize solver
+ * ----------------------------------------
+ */
+
+ switch (action) {
+
+ case 0:
+
+ /* Create IDAS object */
+ ida_mem = IDACreate();
+ if (ida_mem == NULL) goto error_return;
+
+ /* Attach the global IDAS data as 'user-data' */
+ status = IDASetUserData(ida_mem, fwdPb);
+ if (status != IDA_SUCCESS) goto error_return;
+
+ /* Attach error handler function */
+ status = IDASetErrHandlerFn(ida_mem, idmErrHandler, fwdPb);
+ if (status != IDA_SUCCESS) goto error_return;
+
+ /* Call IDAInit */
+ status = IDAInit(ida_mem, mxW_IDARes, t0, yy, yp);
+ if (status != IDA_SUCCESS) goto error_return;
+
+ /* Redirect output */
+ status = IDASetErrFile(ida_mem, stdout);
+ if (status != IDA_SUCCESS) goto error_return;
+
+ break;
+
+ case 1:
+
+ /* Reinitialize solver */
+ status = IDAReInit(ida_mem, t0, yy, yp);
+ if (status != IDA_SUCCESS) goto error_return;
+
+ break;
+
+ }
+
+ /*
+ * ----------------------------------------
+ * Set tolerances
+ * ----------------------------------------
+ */
+
+ switch (itol) {
+ case IDA_SS:
+ status = IDASStolerances(ida_mem, reltol, Sabstol);
+ if (status != IDA_SUCCESS) goto error_return;
+ break;
+ case IDA_SV:
+ NV_abstol = N_VClone(yy);
+ PutData(NV_abstol, Vabstol, N);
+ status = IDASVtolerances(ida_mem, reltol, NV_abstol);
+ if (status != IDA_SUCCESS) goto error_return;
+ N_VDestroy(NV_abstol);
+ break;
+ }
+
+
+ /*
+ * --------------------------------
+ * Set various optional inputs
+ * --------------------------------
+ */
+
+ /* set maxorder (default is 5) */
+ status = IDASetMaxOrd(ida_mem, maxord);
+ if (status != IDA_SUCCESS) goto error_return;
+
+ /* set initial step size (the default value of 0.0 is ignored by IDAS) */
+ status = IDASetInitStep(ida_mem, hin);
+ if (status != IDA_SUCCESS) goto error_return;
+
+ /* set max step (default is infinity) */
+ status = IDASetMaxStep(ida_mem, hmax);
+ if (status != IDA_SUCCESS) goto error_return;
+
+ /* set number of max steps */
+ status = IDASetMaxNumSteps(ida_mem, mxsteps);
+ if (status != IDA_SUCCESS) goto error_return;
+
+ /* set suppressAlg */
+ status = IDASetSuppressAlg(ida_mem, suppress);
+ if (status != IDA_SUCCESS) goto error_return;
+
+ /* set tstop? */
+ if (tstopSet) {
+ status = IDASetStopTime(ida_mem, tstop);
+ if (status != IDA_SUCCESS) goto error_return;
+ }
+
+ /* Rootfinding? */
+ if ( !mxIsEmpty(mtlb_Gfct) && (Ng > 0) ) {
+ status = IDARootInit(ida_mem, Ng, mxW_IDAGfct);
+ if (status != IDA_SUCCESS) goto error_return;
+ rootSet = TRUE;
+ } else {
+ rootSet = FALSE;
+ }
+
+ /* ID vector specified? */
+ if (id != NULL) {
+ NV_id = N_VClone(yy);
+ PutData(NV_id, id, N);
+ status = IDASetId(ida_mem, NV_id);
+ if (status != IDA_SUCCESS) goto error_return;
+ N_VDestroy(NV_id);
+ }
+
+ /* Constraint vector specified? */
+ if (cnstr != NULL) {
+ NV_cnstr = N_VClone(yy);
+ PutData(NV_cnstr, cnstr, N);
+ status = IDASetConstraints(ida_mem, NV_cnstr);
+ if (status != IDA_SUCCESS) goto error_return;
+ N_VDestroy(NV_cnstr);
+ }
+
+
+ /*
+ * ----------------------------------------
+ * Linear solver
+ * ----------------------------------------
+ */
+
+ status = get_LinSolvOptions(options, fwdPb, TRUE,
+ &mupper, &mlower,
+ &mudq, &mldq, &dqrely,
+ &gstype, &maxl);
+ if (status != 0) goto error_return;
+
+ switch (ls) {
+
+ case LS_DENSE:
+
+ status = IDADense(ida_mem, N);
+ if (status != IDA_SUCCESS) goto error_return;
+ if (!mxIsEmpty(mtlb_JACfct)) {
+ status = IDADlsSetDenseJacFn(ida_mem, mxW_IDADenseJac);
+ if (status != IDA_SUCCESS) goto error_return;
+ }
+
+ break;
+
+ case LS_BAND:
+
+ status = IDABand(ida_mem, N, mupper, mlower);
+ if (status != IDA_SUCCESS) goto error_return;
+ if (!mxIsEmpty(mtlb_JACfct)) {
+ status = IDADlsSetBandJacFn(ida_mem, mxW_IDABandJac);
+ if (status != IDA_SUCCESS) goto error_return;
+ }
+
+ break;
+
+ case LS_SPGMR:
+
+ status = IDASpgmr(ida_mem, maxl);
+ if (status != IDA_SUCCESS) goto error_return;
+ status = IDASpilsSetGSType(ida_mem, gstype);
+ if (status != IDA_SUCCESS) goto error_return;
+
+ break;
+
+ case LS_SPBCG:
+
+ status = IDASpbcg(ida_mem, maxl);
+ if (status != IDA_SUCCESS) goto error_return;
+
+ break;
+
+ case LS_SPTFQMR:
+
+ status = IDASptfqmr(ida_mem, maxl);
+ if (status != IDA_SUCCESS) goto error_return;
+
+ break;
+
+ }
+
+ /* Jacobian * vector and preconditioner for SPILS linear solvers */
+
+ if ( (ls==LS_SPGMR) || (ls==LS_SPBCG) || (ls==LS_SPTFQMR) ) {
+
+ if (!mxIsEmpty(mtlb_JACfct)) {
+ status = IDASpilsSetJacTimesVecFn(ida_mem, mxW_IDASpilsJac);
+ if (status != IDA_SUCCESS) goto error_return;
+ }
+
+ switch (pm) {
+
+ case PM_NONE:
+
+ if (!mxIsEmpty(mtlb_PSOLfct)) {
+ if (!mxIsEmpty(mtlb_PSETfct)) status = IDASpilsSetPreconditioner(ida_mem, mxW_IDASpilsPset, mxW_IDASpilsPsol);
+ else status = IDASpilsSetPreconditioner(ida_mem, NULL, mxW_IDASpilsPsol);
+ }
+ if (status != IDA_SUCCESS) goto error_return;
+
+ break;
+
+ case PM_BBDPRE:
+
+ if (!mxIsEmpty(mtlb_GCOMfct)) status = IDABBDPrecInit(ida_mem, N, mudq, mldq, mupper, mlower, dqrely, mxW_IDABBDgloc, mxW_IDABBDgcom);
+ else status = IDABBDPrecInit(ida_mem, N, mudq, mldq, mupper, mlower, dqrely, mxW_IDABBDgloc, NULL);
+ if (status != IDA_SUCCESS) goto error_return;
+
+ break;
+
+ }
+
+ }
+
+ /* Do we monitor? */
+
+ if (mon) mxW_IDAMonitor(0, t0, NULL, NULL, NULL, fwdPb);
+
+ /* Set errMsg field in global data
+ * (all error messages from here on will respect this) */
+
+ idmData->errMsg = errmsg;
+
+ /* Successful return */
+
+ status = 0;
+ plhs[0] = mxCreateDoubleScalar((double)status);
+ return(0);
+
+ /* Error return */
+
+ error_return:
+ status = -1;
+ plhs[0] = mxCreateDoubleScalar((double)status);
+ return(-1);
+
+}
+
+/* IDM_QuadInitialization
+ *
+ * action = 0 -> IDAQuadInit
+ * prhs contains:
+ * fQ
+ * y0
+ * options
+ *
+ * action = 1 -> IDAQuadReInit
+ * prhs contains:
+ * y0
+ * options
+ *
+ */
+
+static int IDM_QuadInitialization(int action, int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
+{
+ idmPbData fwdPb;
+
+ const mxArray *options;
+
+ double *yQ0;
+
+ booleantype rhs_s; /* ignored */
+
+ booleantype errconQ;
+ int itolQ;
+ realtype reltolQ, SabstolQ, *VabstolQ;
+ N_Vector NV_abstolQ;
+
+ int status;
+
+ fwdPb = idmData->fwdPb;
+
+ /*
+ * ------------------------------------
+ * Process inputs based on action
+ * ------------------------------------
+ */
+
+ switch (action) {
+
+ case 0: /* QUADRATURE INITIALIZATION */
+
+ /* Extract user-provided quadrature RHS function */
+
+ mxDestroyArray(mtlb_QUADfct);
+ mtlb_QUADfct = mxDuplicateArray(prhs[0]);
+
+ /* Extract quadrature initial conditions */
+
+ yQ0 = mxGetPr(prhs[1]);
+ Nq = mxGetM(prhs[1]);
+
+ /* Create the quadrature N_Vector */
+
+ yQ = NewVector(Nq);
+
+ /* Load quadrature initial conditions */
+
+ PutData(yQ, yQ0, Nq);
+
+ /* Extract quadrature options structure */
+
+ options = prhs[2];
+
+ break;
+
+ case 1: /* QUADRATURE RE-INITIALIZATION */
+
+ /* Extract quadrature initial conditions */
+
+ yQ0 = mxGetPr(prhs[0]);
+
+ if (mxGetM(prhs[0]) != Nq) {
+ idmErrHandler(-999, "IDAS", "IDAQuadReInit",
+ "Size of yQ0 changed from IDAQuadInit call.", NULL);
+ goto error_return;
+ }
+
+ /* Load quadrature initial conditions */
+
+ PutData(yQ, yQ0, Nq);
+
+ /* Extract quadrature options structure */
+
+ options = prhs[1];
+
+ break;
+
+ }
+
+ /* Process the options structure */
+
+ status = get_QuadOptions(options, fwdPb, TRUE,
+ Nq, &rhs_s,
+ &errconQ,
+ &itolQ, &reltolQ, &SabstolQ, &VabstolQ);
+ if (status != 0) goto error_return;
+
+ /*
+ * ----------------------------------------
+ * Call appropriate IDAS functions
+ *
+ * If action = 0
+ * Initialize quadratures
+ * If action = 1
+ * Reinitialize quadratures
+ * ----------------------------------------
+ */
+
+ switch (action) {
+ case 0:
+ status = IDAQuadInit(ida_mem, mxW_IDAQuadFct, yQ);
+ if (status != IDA_SUCCESS) goto error_return;
+ break;
+ case 1:
+ status = IDAQuadReInit(ida_mem, yQ);
+ if (status != IDA_SUCCESS) goto error_return;
+ break;
+ }
+
+ /*
+ * ----------------------------------------
+ * Set tolerances for quadrature variables
+ * ----------------------------------------
+ */
+
+ status = IDASetQuadErrCon(ida_mem, errconQ);
+ if (status != IDA_SUCCESS) goto error_return;
+
+ if (errconQ) {
+
+ switch (itolQ) {
+ case IDA_SS:
+ status = IDAQuadSStolerances(ida_mem, reltolQ, SabstolQ);
+ if (status != IDA_SUCCESS) goto error_return;
+ break;
+ case IDA_SV:
+ NV_abstolQ = N_VClone(yQ);
+ PutData(NV_abstolQ, VabstolQ, Nq);
+ status = IDAQuadSVtolerances(ida_mem, reltolQ, NV_abstolQ);
+ if (status != IDA_SUCCESS) goto error_return;
+ N_VDestroy(NV_abstolQ);
+ break;
+ }
+
+ }
+
+ /* Quadratures will be integrated */
+
+ quadr = TRUE;
+
+ /* Successful return */
+
+ status = 0;
+ plhs[0] = mxCreateDoubleScalar((double)status);
+ return(0);
+
+ /* Error return */
+
+ error_return:
+ status = -1;
+ plhs[0] = mxCreateDoubleScalar((double)status);
+ return(-1);
+
+}
+
+
+/* IDM_SensInitialization
+ * action = 0 -> IDASensInit
+ * action = 1 -> IDASensReInit
+ *
+ * prhs contains:
+ * Ns
+ * sensi_meth
+ * yS0
+ * options
+ *
+ * plhs contains:
+ * status
+ *
+ */
+
+static int IDM_SensInitialization(int action, int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
+{
+ idmPbData fwdPb;
+
+ const mxArray *options;
+
+ booleantype fS_DQ;
+ IDASensResFn resS;
+
+ double *yyS0, *ypS0;
+
+ int ism;
+
+ mxArray *pfield;
+ char *pfield_name;
+
+ booleantype errconS;
+ int itolS;
+ realtype reltolS;
+ realtype *SabstolS, *VabstolS;
+ N_Vector *NV_abstolS;
+
+ int *plist, dqtype;
+ double *p, *pbar, rho;
+
+ int is, status;
+
+ p = NULL;
+ plist = NULL;
+ pbar = NULL;
+
+ fwdPb = idmData->fwdPb;
+
+ /*
+ * ------------------------------------
+ * Process inputs based on action
+ * ------------------------------------
+ */
+
+ switch (action) {
+
+ case 0: /* FSA INITIALIZATION */
+
+ /* Extract number of sensitivities */
+
+ Ns = (int)mxGetScalar(prhs[0]);
+
+ /* Extract user-provided sensitivity residual function */
+
+ if ( mxIsEmpty(prhs[1]) ) {
+ resS = NULL;
+ fS_DQ = TRUE;
+ } else {
+ mxDestroyArray(mtlb_SRESfct);
+ mtlb_SRESfct = mxDuplicateArray(prhs[1]);
+ resS = mxW_IDASensRes;
+ fS_DQ = FALSE;
+ }
+
+ /* Extract sensitivity initial conditions */
+
+ yyS0 = mxGetPr(prhs[2]);
+ ypS0 = mxGetPr(prhs[3]);
+
+ /* Create the sensitivity N_Vectors */
+
+ yyS = N_VCloneVectorArray(Ns, yy);
+ ypS = N_VCloneVectorArray(Ns, yy);
+
+ /* Load sensitivity initial conditions */
+
+ for (is=0;is<Ns;is++) {
+ PutData(yyS[is], &yyS0[is*N], N);
+ PutData(ypS[is], &ypS0[is*N], N);
+ }
+
+ /* Extract FSA options structure */
+
+ options = prhs[4];
+
+ break;
+
+ case 1: /* FSA RE-INITIALIZATION */
+
+ /* Extract sensitivity initial condition */
+
+ yyS0 = mxGetPr(prhs[0]);
+ ypS0 = mxGetPr(prhs[1]);
+
+ if ( (mxGetM(prhs[0]) != N) || (mxGetN(prhs[0]) != Ns) ) {
+ idmErrHandler(-999, "IDAS", "IDASensReInit",
+ "Size of yyS0 changed from IDASensInit call.", NULL);
+ goto error_return;
+ }
+
+ if ( (mxGetM(prhs[1]) != N) || (mxGetN(prhs[1]) != Ns) ) {
+ idmErrHandler(-999, "IDAS", "IDASensReInit",
+ "Size of ypS0 changed from IDASensInit call.", NULL);
+ goto error_return;
+ }
+
+ /* Load sensitivity initial conditions */
+
+ for (is=0;is<Ns;is++) {
+ PutData(yyS[is], &yyS0[is*N], N);
+ PutData(ypS[is], &ypS0[is*N], N);
+ }
+
+ /* Extract qFSA options structure */
+
+ options = prhs[2];
+
+ break;
+
+ }
+
+ /* Process the options structure */
+
+ status = get_FSAOptions(options, fwdPb,
+ &ism,
+ &pfield_name, &plist, &pbar,
+ &dqtype, &rho,
+ &errconS, &itolS, &reltolS, &SabstolS, &VabstolS);
+ if (status != 0) goto error_return;
+
+ /*
+ * ----------------------------------------
+ * Call appropriate IDAS functions
+ *
+ * If action = 0
+ * Check if required inputs are available
+ * Initialize FSA
+ * If action = 1
+ * Reinitialize FSA
+ * ----------------------------------------
+ */
+
+ switch (action) {
+
+ case 0:
+
+ if (fS_DQ) {
+
+ if (pfield_name == NULL) {
+ idmErrHandler(-999, "IDAS", "IDASensInit/IDASensReInit",
+ "pfield required but was not provided.", NULL);
+ goto error_return;
+ }
+
+ pfield = mxGetField(mtlb_data,0,pfield_name);
+
+ if (pfield == NULL) {
+ idmErrHandler(-999, "IDAS", "IDASensInit/IDASensReInit",
+ "illegal pfield input.", NULL);
+ goto error_return;
+ }
+
+ p = mxGetPr(pfield);
+
+ }
+
+ status = IDASensInit(ida_mem, Ns, ism, resS, yyS, ypS);
+ if (status != IDA_SUCCESS) goto error_return;
+
+ break;
+
+ case 1:
+
+ status = IDASensReInit(ida_mem, ism, yyS, ypS);
+ if (status != IDA_SUCCESS) goto error_return;
+
+ break;
+
+ }
+
+ /*
+ * ----------------------------------------
+ * Set tolerances for sensitivity variables
+ * ----------------------------------------
+ */
+
+ switch (itolS) {
+ case IDA_SS:
+ status = IDASensSStolerances(ida_mem, reltolS, SabstolS);
+ if (status != IDA_SUCCESS) goto error_return;
+ break;
+ case IDA_SV:
+ NV_abstolS = N_VCloneVectorArray(Ns, yy);
+ for (is=0;is<Ns;is++)
+ PutData(NV_abstolS[is], &VabstolS[is*N], N);
+ status = IDASensSVtolerances(ida_mem, reltolS, NV_abstolS);
+ if (status != IDA_SUCCESS) goto error_return;
+ N_VDestroyVectorArray(NV_abstolS, Ns);
+ break;
+ case IDA_EE:
+ status = IDASensEEtolerances(ida_mem);
+ if (status != IDA_SUCCESS) goto error_return;
+ break;
+ }
+
+ /*
+ * --------------------------------
+ * Set various optional inputs
+ * --------------------------------
+ */
+
+ status = IDASetSensParams(ida_mem, p, pbar, plist);
+ if (status != IDA_SUCCESS) goto error_return;
+
+ status = IDASetSensDQMethod(ida_mem, dqtype, rho);
+ if (status != IDA_SUCCESS) goto error_return;
+
+ status = IDASetSensErrCon(ida_mem, errconS);
+ if (status != IDA_SUCCESS) goto error_return;
+
+ fsa = TRUE;
+
+ /* Successful return */
+
+ status = 0;
+ plhs[0] = mxCreateDoubleScalar((double)status);
+ return(0);
+
+ /* Error return */
+
+ error_return:
+ status = -1;
+ plhs[0] = mxCreateDoubleScalar((double)status);
+ return(-1);
+
+}
+
+/*
+ * IDM_SensToggleOff
+ *
+ * deactivates FSA
+ */
+
+static int IDM_SensToggleOff(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
+{
+ idmPbData fwdPb;
+ int status;
+
+ fwdPb = idmData->fwdPb;
+
+ status = IDASensToggleOff(ida_mem);
+ if (status != IDA_SUCCESS) {
+ status = -1;
+ plhs[0] = mxCreateDoubleScalar((double)status);
+ return(-1);
+ }
+
+ fsa = FALSE;
+
+ status = 0;
+ plhs[0] = mxCreateDoubleScalar((double)status);
+ return(0);
+}
+
+
+/* IDM_AdjInitialization
+ *
+ * prhs contains:
+ *
+ * plhs contains:
+ * status
+ */
+
+static int IDM_AdjInitialization(int action, int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
+{
+ int interp;
+
+ int buflen, status;
+ char *bufval;
+
+ switch (action) {
+
+ case 0:
+
+ /* Number of steps */
+
+ Nd = (int)mxGetScalar(prhs[0]);
+
+ /* Interpolation method */
+
+ buflen = mxGetM(prhs[1]) * mxGetN(prhs[1]) + 1;
+ bufval = mxCalloc(buflen, sizeof(char));
+ status = mxGetString(prhs[1], bufval, buflen);
+ if(status != 0) {
+ idmErrHandler(-999, "IDAS", "IDAAdjInit",
+ "Could not parse InterpType.", NULL);
+ goto error_return;
+ }
+
+ if(!strcmp(bufval,"Hermite")) {
+ interp = IDA_HERMITE;
+ } else if(!strcmp(bufval,"Polynomial")) {
+ interp = IDA_POLYNOMIAL;
+ } else {
+ idmErrHandler(-999, "IDAS", "IDAAdjInit",
+ "Interp. type has an illegal value.", NULL);
+ goto error_return;
+ }
+
+ status = IDAAdjInit(ida_mem, Nd, interp);
+ if (status != IDA_SUCCESS) goto error_return;
+
+ break;
+
+ case 1:
+
+ status = IDAAdjReInit(ida_mem);
+ if (status != IDA_SUCCESS) goto error_return;
+
+ break;
+
+ }
+
+ asa = TRUE;
+
+ /* Successful return */
+
+ status = 0;
+ plhs[0] = mxCreateDoubleScalar((double)status);
+ return(0);
+
+ /* Error return */
+
+ error_return:
+ status = -1;
+ plhs[0] = mxCreateDoubleScalar((double)status);
+ return(-1);
+
+}
+
+
+/* IDM_InitializationB
+ *
+ * action = 0 -> IDACreateB + IDAInitB
+ * action = 1 -> IDAReInitB
+ *
+ * prhs contains:
+ * resB
+ * tF
+ * yyB0
+ * ypB0
+ * options
+ * data
+ *
+ * plhs contains:
+ * status
+ *
+ */
+static int IDM_InitializationB(int action, int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
+{
+ idmPbData bckPb;
+
+ const mxArray *options;
+
+ int idxB;
+
+ double tB0, *yyB0, *ypB0;
+
+ int maxordB;
+ long int mxstepsB;
+
+ int itolB;
+ realtype reltolB, SabstolB, *VabstolB;
+ N_Vector NV_abstolB;
+
+ double hinB, hmaxB;
+ double tstopB; /* ignored */
+ booleantype errmsgB; /* ignored */
+
+ booleantype suppressB;
+
+ long int mupperB, mlowerB;
+ int gstypeB, maxlB;
+ long int mudqB, mldqB;
+ double dqrelyB;
+
+ double *idB, *cnstrB;
+ N_Vector NV_idB;
+
+ booleantype res_s;
+
+ booleantype found_bck;
+
+ int status;
+ int i_status;
+
+
+ /* Set output containing status */
+
+ i_status = (action == 0) ? 1 : 0;
+
+ /*
+ * -----------------------------
+ * Finalize Forward monitoring
+ * -----------------------------
+ */
+
+ if (idmData->fwdPb->Mon) {
+ mxW_IDAMonitor(2, 0.0, NULL, NULL, NULL, idmData->fwdPb);
+ idmData->fwdPb->Mon = FALSE;
+ }
+
+ /*
+ * ------------------------------------
+ * Process inputs based on action
+ * ------------------------------------
+ */
+
+ switch (action) {
+
+ case 0: /* BACKWARD SOLVER INITIALIZATION */
+
+ /* Create and initialize a new problem */
+
+ bckPb = (idmPbData) mxMalloc(sizeof(struct idmPbData_));
+ idmInitPbData(bckPb);
+
+ bckPb->next = idmData->bckPb;
+ idmData->bckPb = bckPb;
+
+ /* Extract user-provided RHS function */
+
+ mxDestroyArray(mtlb_RESfctB);
+ mtlb_RESfctB = mxDuplicateArray(prhs[0]);
+
+ /* Extract final time */
+
+ tB0 = (double)mxGetScalar(prhs[1]);
+
+ /* Extract final conditions */
+
+ yyB0 = mxGetPr(prhs[2]);
+ ypB0 = mxGetPr(prhs[3]);
+ NB = mxGetM(prhs[2]);
+
+ /* Create the solution N_Vectors */
+
+ yyB = NewVector(NB);
+ ypB = NewVector(NB);
+
+ /* Load final conditions */
+
+ PutData(yyB, yyB0, NB);
+ PutData(ypB, ypB0, NB);
+
+ /* Extract options structure */
+
+ options = prhs[4];
+
+ break;
+
+ case 1: /* BACKWARD SOLVER RE-INITIALIZATION */
+
+ /* Extract index of current backward problem */
+
+ idxB = (int)mxGetScalar(prhs[0]);
+
+ /* Find current backward problem */
+
+ found_bck = FALSE;
+ bckPb = idmData->bckPb;
+ while (bckPb != NULL) {
+ if (indexB == idxB) {
+ found_bck = TRUE;
+ break;
+ }
+ bckPb = bckPb->next;
+ }
+
+ if (!found_bck) {
+ idmErrHandler(-999, "IDAS", "IDAReInitB",
+ "idxB has an illegal value.", NULL);
+ goto error_return;
+ }
+
+ /* If backward monitoring was enabled, finalize it now. */
+
+ if (monB) mxW_IDAMonitorB(2, indexB, 0.0, NULL, NULL, bckPb);
+
+ /* Extract final time */
+
+ tB0 = (double)mxGetScalar(prhs[1]);
+
+ /* Extract final conditions */
+
+ yyB0 = mxGetPr(prhs[2]);
+
+ if (mxGetM(prhs[2]) != NB) {
+ idmErrHandler(-999, "IDAS", "IDAReInitB",
+ "Size of yyB0 changed from IDAInitB call.", NULL);
+ goto error_return;
+ }
+
+ yyB0 = mxGetPr(prhs[3]);
+
+ if (mxGetM(prhs[3]) != NB) {
+ idmErrHandler(-999, "IDAS", "IDAReInitB",
+ "Size of ypB0 changed from IDAInitB call.", NULL);
+ goto error_return;
+ }
+
+ /* Load final conditions */
+
+ PutData(yyB, yyB0, NB);
+ PutData(ypB, ypB0, NB);
+
+ /* Extract options structure */
+
+ options = prhs[4];
+
+ break;
+
+ }
+
+ /* Process the options structure */
+
+ status = get_IntgrOptions(options, bckPb, FALSE,
+ &maxordB, &mxstepsB,
+ &itolB, &reltolB, &SabstolB, &VabstolB,
+ &hinB, &hmaxB, &tstopB,
+ &suppressB, &errmsgB,
+ &idB, &cnstrB,
+ &res_s);
+ if (status != 0) goto error_return;
+
+ /*
+ * ----------------------------------------
+ * Call appropriate IDAS functions
+ *
+ * If action = 0
+ * Create IDAS object and allocate memory
+ * Initialize and allocate memory
+ * If action = 1
+ * Reinitialize solver
+ * ----------------------------------------
+ */
+
+ switch (action) {
+
+ case 0:
+
+ status = IDACreateB(ida_mem, &idxB);
+ if (status != IDA_SUCCESS) goto error_return;
+ status = IDASetUserDataB(ida_mem, idxB, bckPb);
+ if (status != IDA_SUCCESS) goto error_return;
+
+ if (res_s) status = IDAInitBS(ida_mem, idxB, mxW_IDAResBS, tB0, yyB, ypB);
+ else status = IDAInitB(ida_mem, idxB, mxW_IDAResB, tB0, yyB, ypB);
+ if (status != IDA_SUCCESS) goto error_return;
+
+ /* Return idxB */
+
+ plhs[0] = mxCreateDoubleScalar((double)idxB);
+
+ indexB = idxB;
+
+ NbckPb++;
+
+ break;
+
+ case 1:
+
+ status = IDAReInitB(ida_mem, idxB, tB0, yyB, ypB);
+ if (status != IDA_SUCCESS) goto error_return;
+
+ break;
+
+ }
+
+ /*
+ * ----------------------------------------
+ * Set tolerances
+ * ----------------------------------------
+ */
+
+ switch (itolB) {
+ case IDA_SS:
+ status = IDASStolerancesB(ida_mem, idxB, reltolB, SabstolB);
+ if (status != IDA_SUCCESS) goto error_return;
+ break;
+ case IDA_SV:
+ NV_abstolB = N_VClone(yyB);
+ PutData(NV_abstolB, VabstolB, NB);
+ status = IDASVtolerancesB(ida_mem, idxB, reltolB, NV_abstolB);
+ if (status != IDA_SUCCESS) goto error_return;
+ N_VDestroy(NV_abstolB);
+ break;
+ }
+
+ /*
+ * --------------------------------
+ * Set various optional inputs
+ * --------------------------------
+ */
+
+ /* set maxorder (default is consistent with LMM) */
+ status = IDASetMaxOrdB(ida_mem, idxB, maxordB);
+ if (status != IDA_SUCCESS) goto error_return;
+
+ /* set initial step size (the default value of 0.0 is ignored by IDAS) */
+ status = IDASetInitStepB(ida_mem, idxB, hinB);
+ if (status != IDA_SUCCESS) goto error_return;
+
+ /* set max step (default is infinity) */
+ status = IDASetMaxStepB(ida_mem, idxB, hmaxB);
+ if (status != IDA_SUCCESS) goto error_return;
+
+ /* set number of max steps */
+ status = IDASetMaxNumStepsB(ida_mem, idxB, mxstepsB);
+ if (status != IDA_SUCCESS) goto error_return;
+
+ /* set suppressAlg */
+ status = IDASetSuppressAlgB(ida_mem, idxB, suppressB);
+ if (status != IDA_SUCCESS) goto error_return;
+
+ /* ID vector specified? */
+ if (idB != NULL) {
+ NV_idB = N_VClone(yyB);
+ PutData(NV_idB, idB, NB);
+ status = IDASetIdB(ida_mem, idxB, NV_idB);
+ if (status != IDA_SUCCESS) goto error_return;
+ N_VDestroy(NV_idB);
+ }
+
+ /*
+ * ----------------------------------------
+ * Linear solver
+ * ----------------------------------------
+ */
+
+ status = get_LinSolvOptions(options, bckPb, FALSE,
+ &mupperB, &mlowerB,
+ &mudqB, &mldqB, &dqrelyB,
+ &gstypeB, &maxlB);
+ if (status != 0) goto error_return;
+
+ switch(lsB) {
+
+ case LS_DENSE:
+
+ status = IDADenseB(ida_mem, idxB, NB);
+ if (status != IDA_SUCCESS) goto error_return;
+ if (!mxIsEmpty(mtlb_JACfctB)) {
+ status = IDADlsSetDenseJacFnB(ida_mem, idxB, mxW_IDADenseJacB);
+ if (status != IDA_SUCCESS) goto error_return;
+ }
+
+ break;
+
+ case LS_BAND:
+
+ status = IDABandB(ida_mem, idxB, NB, mupperB, mlowerB);
+ if (status != IDA_SUCCESS) goto error_return;
+ if (!mxIsEmpty(mtlb_JACfctB)) {
+ status = IDADlsSetBandJacFnB(ida_mem, idxB, mxW_IDABandJacB);
+ if (status != IDA_SUCCESS) goto error_return;
+ }
+
+ break;
+
+ case LS_SPGMR:
+
+ status = IDASpgmrB(ida_mem, idxB, maxlB);
+ if (status != IDA_SUCCESS) goto error_return;
+ status = IDASpilsSetGSTypeB(ida_mem, idxB, gstypeB);
+ if (status != IDA_SUCCESS) goto error_return;
+
+ break;
+
+ case LS_SPBCG:
+
+ status = IDASpbcgB(ida_mem, idxB, maxlB);
+ if (status != IDA_SUCCESS) goto error_return;
+
+ break;
+
+ case LS_SPTFQMR:
+
+ status = IDASptfqmrB(ida_mem, idxB, maxlB);
+ if (status != IDA_SUCCESS) goto error_return;
+
+ break;
+
+ }
+
+ /* Jacobian * vector and preconditioner for SPILS linear solvers */
+
+ if ( (lsB==LS_SPGMR) || (lsB==LS_SPBCG) || (lsB==LS_SPTFQMR) ) {
+
+ if (!mxIsEmpty(mtlb_JACfctB)) {
+ status =IDASpilsSetJacTimesVecFnB(ida_mem, idxB, mxW_IDASpilsJacB);
+ if (status != IDA_SUCCESS) goto error_return;
+ }
+
+ switch (pmB) {
+
+ case PM_NONE:
+
+ if (!mxIsEmpty(mtlb_PSOLfctB)) {
+ if (!mxIsEmpty(mtlb_PSETfctB)) status = IDASpilsSetPreconditionerB(ida_mem, idxB, mxW_IDASpilsPsetB, mxW_IDASpilsPsolB);
+ else status =IDASpilsSetPreconditionerB(ida_mem, idxB, NULL, mxW_IDASpilsPsolB);
+ }
+ if (status != IDA_SUCCESS) goto error_return;
+
+ break;
+
+ case PM_BBDPRE:
+
+ if (!mxIsEmpty(mtlb_GCOMfctB)) status = IDABBDPrecInitB(ida_mem, idxB, NB, mudqB, mldqB, mupperB, mlowerB, dqrelyB, mxW_IDABBDglocB, mxW_IDABBDgcomB);
+ else status = IDABBDPrecInitB(ida_mem, idxB, NB, mudqB, mldqB, mupperB, mlowerB, dqrelyB, mxW_IDABBDglocB, NULL);
+ if (status != IDA_SUCCESS) goto error_return;
+
+ break;
+
+ }
+
+ }
+
+ /* Do we monitor? */
+
+ if (monB) mxW_IDAMonitorB(0, idxB, tB0, NULL, NULL, bckPb);
+
+ /* Successful return */
+
+ status = 0;
+ plhs[i_status] = mxCreateDoubleScalar((double)status);
+ return(0);
+
+ /* Error return */
+
+ error_return:
+ status = -1;
+ plhs[i_status] = mxCreateDoubleScalar((double)status);
+ return(-1);
+
+}
+
+/* IDM_QuadInitializationB
+ *
+ * action = 0 -> IDAQuadInitB
+ * prhs contains:
+ * idxB
+ * fQB
+ * yQB0
+ * options
+ *
+ * action = 1 -> IDAQuadReInitB
+ * idxB
+ * yQB0
+ * options
+ *
+ */
+
+static int IDM_QuadInitializationB(int action, int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
+{
+ idmPbData bckPb;
+
+ const mxArray *options;
+
+ int idxB;
+
+ double *yQB0;
+
+ booleantype rhs_s;
+
+ booleantype errconQB;
+ int itolQB;
+ realtype reltolQB, SabstolQB, *VabstolQB;
+ N_Vector NV_abstolQB;
+
+ booleantype found_bck;
+
+ int status;
+
+ /* Extract index of current backward problem */
+
+ idxB = (int)mxGetScalar(prhs[0]);
+
+ /* Find current backward problem */
+
+ found_bck = FALSE;
+ bckPb = idmData->bckPb;
+ while (bckPb != NULL) {
+ if (indexB == idxB) {
+ found_bck = TRUE;
+ break;
+ }
+ bckPb = bckPb->next;
+ }
+
+ if (!found_bck) {
+ idmErrHandler(-999, "IDAS", "IDAQuadInitB/IDAQuadReInitB",
+ "idxB has an illegal value.", NULL);
+ goto error_return;
+ }
+
+ /*
+ * ------------------------------------
+ * Process inputs based on action
+ * ------------------------------------
+ */
+
+ switch (action) {
+
+ case 0: /* BACKWARD QUADRATURE INITIALIZATION */
+
+ /* Extract user-provided quadrature RHS function */
+
+ mxDestroyArray(mtlb_QUADfctB);
+ mtlb_QUADfctB = mxDuplicateArray(prhs[1]);
+
+ /* Extract quadrature final conditions */
+
+ yQB0 = mxGetPr(prhs[2]);
+ NqB = mxGetM(prhs[2]);
+
+ /* Create the backward quadrature N_Vector */
+
+ yQB = NewVector(NqB);
+
+ /* Load quadrature final conditions */
+
+ PutData(yQB, yQB0, NqB);
+
+ /* Extract quadrature options structure */
+
+ options = prhs[3];
+
+ break;
+
+ case 1: /* BACKWARD QUADRATURE RE-INITIALIZATION */
+
+
+ /* Extract quadrature final conditions */
+
+ yQB0 = mxGetPr(prhs[1]);
+
+ if (mxGetM(prhs[1]) != NqB) {
+ idmErrHandler(-999, "IDAS", "IDAQuadReInitB",
+ "Size of yQB0 changed from IDAQuadInitB call.", NULL);
+ goto error_return;
+ }
+
+ /* Load quadrature final conditions */
+
+ PutData(yQB, yQB0, NqB);
+
+ /* Extract quadrature options structure */
+
+ options = prhs[2];
+
+ break;
+
+ }
+
+ /* Process the options structure */
+
+ status = get_QuadOptions(options, bckPb, FALSE,
+ NqB, &rhs_s,
+ &errconQB,
+ &itolQB, &reltolQB, &SabstolQB, &VabstolQB);
+ if (status != 0) goto error_return;
+
+ /*
+ * ----------------------------------------
+ * Call appropriate IDAS functions
+ *
+ * If action = 0
+ * Initialize backward quadratures
+ * If action = 1
+ * Reinitialize backward quadratures
+ * ----------------------------------------
+ */
+
+ switch (action) {
+ case 0:
+ if (rhs_s) status = IDAQuadInitBS(ida_mem, idxB, mxW_IDAQuadFctBS, yQB);
+ else status = IDAQuadInitB(ida_mem, idxB, mxW_IDAQuadFctB, yQB);
+ if (status != IDA_SUCCESS) goto error_return;
+ break;
+ case 1:
+ status = IDAQuadReInitB(ida_mem, idxB, yQB);
+ if (status != IDA_SUCCESS) goto error_return;
+ break;
+ }
+
+ /*
+ * ----------------------------------------
+ * Set tolerances for quadrature variables
+ * ----------------------------------------
+ */
+
+ status = IDASetQuadErrConB(ida_mem, idxB, errconQB);
+ if (status != IDA_SUCCESS) goto error_return;
+
+ if (errconQB) {
+
+ switch (itolQB) {
+ case IDA_SS:
+ status = IDAQuadSStolerancesB(ida_mem, idxB, reltolQB, SabstolQB);
+ if (status != IDA_SUCCESS) goto error_return;
+ break;
+ case IDA_SV:
+ NV_abstolQB = N_VClone(yQB);
+ PutData(NV_abstolQB, VabstolQB, NqB);
+ status = IDAQuadSVtolerancesB(ida_mem, idxB, reltolQB, NV_abstolQB);
+ if (status != IDA_SUCCESS) goto error_return;
+ N_VDestroy(NV_abstolQB);
+ break;
+ }
+
+ }
+
+ quadrB = TRUE;
+
+ /* Successful return */
+
+ status = 0;
+ plhs[0] = mxCreateDoubleScalar((double)status);
+ return(0);
+
+ /* Error return */
+
+ error_return:
+ status = -1;
+ plhs[0] = mxCreateDoubleScalar((double)status);
+ return(-1);
+
+}
+
+static int IDM_CalcIC(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
+{
+ idmPbData fwdPb;
+
+ double tout;
+ int buflen, icopt;
+ char *bufval;
+
+ int status;
+
+ fwdPb = idmData->fwdPb;
+
+ /* Extract tout */
+ tout = (double) mxGetScalar(prhs[0]);
+
+ /* Extract icopt */
+ icopt = -1;
+ buflen = mxGetM(prhs[1]) * mxGetN(prhs[1]) + 1;
+ bufval = mxCalloc(buflen, sizeof(char));
+ status = mxGetString(prhs[1], bufval, buflen);
+ if(!strcmp(bufval,"FindAlgebraic")) {
+ icopt = IDA_YA_YDP_INIT;
+ } else if(!strcmp(bufval,"FindAll")) {
+ icopt = IDA_Y_INIT;
+ } else {
+ idmErrHandler(-999, "IDAS", "IDACalcIC",
+ "icopt has an illegal value.", NULL);
+ goto error_return;
+ }
+
+ /* Call IDACalcIC */
+ status = IDACalcIC(ida_mem, icopt, tout);
+ if (status < 0) goto error_return;
+
+ /* IDACalcIC return flag */
+ plhs[0] = mxCreateDoubleScalar((double)status);
+
+ if (nlhs == 1) return(0);
+
+ /* Extract and return corrected IC */
+ status = IDAGetConsistentIC(ida_mem, yy, yp);
+ if (status != IDA_SUCCESS) goto error_return;
+ plhs[1] = mxCreateDoubleMatrix(N,1,mxREAL);
+ GetData(yy, mxGetPr(plhs[1]), N);
+ plhs[2] = mxCreateDoubleMatrix(N,1,mxREAL);
+ GetData(yp, mxGetPr(plhs[2]), N);
+
+ /* Successful return */
+
+ status = 0;
+ plhs[0] = mxCreateDoubleScalar((double)status);
+ return(0);
+
+ /* Error return */
+
+ error_return:
+ status = -1;
+ plhs[0] = mxCreateDoubleScalar((double)status);
+ if (nlhs > 1) {
+ plhs[1] = mxCreateDoubleScalar((double)status);
+ plhs[2] = mxCreateDoubleScalar((double)status);
+ }
+ return(-1);
+
+}
+
+static int IDM_CalcICB(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
+{
+ return(0);
+}
+
+static int IDM_Solve(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
+{
+ idmPbData fwdPb;
+
+ int buflen;
+ char *bufval;
+
+ int nlhs_needed, dims[3];
+
+ int itask, is, Ntout, itout, s_idx;
+ double *tout, tret, h;
+ double *tdata, *yydata, *yQdata, *yySdata;
+ long int nst;
+
+ int status, ida_status;
+
+
+ fwdPb = idmData->fwdPb;
+
+ /* Set index of output corresponding to FSA */
+
+ if (fsa) {
+ s_idx = quadr ? 4 : 3;
+ }
+
+ /*
+ * ----------------------------------------------------------------
+ * Verify if number of output arguments agrees with current options
+ * ----------------------------------------------------------------
+ */
+
+ nlhs_needed = 3;
+
+ if (quadr) nlhs_needed++;
+ if (fsa) nlhs_needed++;
+
+ if (nlhs < nlhs_needed) {
+ idmErrHandler(-999, "IDAS", "IDASolve",
+ "Too few output arguments.", NULL);
+ goto error_return;
+ }
+
+ if (nlhs > nlhs_needed) {
+ idmErrHandler(-999, "IDAS", "IDASolve",
+ "Too many output arguments.", NULL);
+ goto error_return;
+ }
+
+ /*
+ * ----------------------------------------------------------------
+ * Extract input arguments
+ * ----------------------------------------------------------------
+ */
+
+ /* Extract tout */
+
+ Ntout = mxGetM(prhs[0]) * mxGetN(prhs[0]);
+ tout = mxGetPr(prhs[0]);
+
+ /* If rootfinding or tstop are enabled, we do not allow multiple output times */
+
+ if (rootSet && (Ntout>1)) {
+ idmErrHandler(-999, "IDAS", "IDASolve",
+ "More than one tout value prohibited with rootfinding enabled.", NULL);
+ goto error_return;
+ }
+
+ if (tstopSet && (Ntout>1)) {
+ idmErrHandler(-999, "IDAS", "IDASolve",
+ "More than one tout value prohibited with tstop enabled.", NULL);
+ goto error_return;
+ }
+
+ /* Extract itask */
+
+ buflen = mxGetM(prhs[1]) * mxGetN(prhs[1]) + 1;
+ bufval = mxCalloc(buflen, sizeof(char));
+ status = mxGetString(prhs[1], bufval, buflen);
+ if(!strcmp(bufval,"Normal")) {
+ itask = IDA_NORMAL;
+ } else if(!strcmp(bufval,"OneStep")) {
+ itask = IDA_ONE_STEP;
+ } else {
+ idmErrHandler(-999, "IDAS", "IDASolve",
+ "Illegal value for itask.", NULL);
+ goto error_return;
+ }
+
+
+ if (itask == IDA_ONE_STEP) {
+
+ /* If itask==IDA_ONE_STEP, we do not allow multiple output times and we do not monitor */
+
+ if (Ntout>1) {
+ idmErrHandler(-999, "IDAS", "IDASolve",
+ "More than one tout value prohibited in ONE_STEP mode.", NULL);
+ goto error_return;
+ }
+
+ if (mon) {
+ idmErrHandler(+999, "IDAS", "IDASolve",
+ "Monitoring disabled in ONE_STEP mode.", NULL);
+ mon = FALSE;
+ }
+
+ } else {
+
+ /* Check if tout values are legal */
+
+ status = IDAGetCurrentTime(ida_mem, &tret);
+ if (status != IDA_SUCCESS) goto error_return;
+ status = IDAGetNumSteps(ida_mem, &nst);
+ if (status != IDA_SUCCESS) goto error_return;
+
+ /* h is used throughout this function as integration direction only */
+ if (nst == 0) {
+ h = tout[0] - tret;
+ } else {
+ IDAGetLastStep(ida_mem, &h);
+ if ( (tout[0] - tret + h)*h < 0.0 ) {
+ idmErrHandler(-999, "IDAS", "IDASolve",
+ "Illegal value of tout.", NULL);
+ goto error_return;
+ }
+ }
+
+ for (itout=1; itout<Ntout; itout++)
+ if ( (tout[itout] - tout[itout-1])*h < 0.0 ) {
+ idmErrHandler(-999, "IDAS", "IDASolve",
+ "tout values are not monotonic.", NULL);
+ goto error_return;
+ }
+
+ }
+
+
+ /*
+ * ----------------------------------------------------------------
+ * Prepare the output arrays
+ * ----------------------------------------------------------------
+ */
+
+ /* Return time(s) */
+
+ plhs[1] = mxCreateDoubleMatrix(1,Ntout,mxREAL);
+ tdata = mxGetPr(plhs[1]);
+
+ /* Solution vector(s) */
+
+ plhs[2] = mxCreateDoubleMatrix(N,Ntout,mxREAL);
+ yydata = mxGetPr(plhs[2]);
+
+ /* Quadrature vector(s) */
+
+ if (quadr) {
+ plhs[3] = mxCreateDoubleMatrix(Nq,Ntout,mxREAL);
+ yQdata = mxGetPr(plhs[3]);
+ }
+
+ /* Sensitivity vectors */
+
+ if (fsa) {
+ dims[0] = N;
+ dims[1] = Ns;
+ dims[2] = Ntout;
+ plhs[s_idx] = mxCreateNumericArray(3, dims, mxDOUBLE_CLASS, mxREAL);
+ yySdata = mxGetPr(plhs[s_idx]);
+ }
+
+ /*
+ * ----------------------------------------------------------------
+ * Call the IDAS main solver function
+ * ----------------------------------------------------------------
+ */
+
+ if (!mon) {
+
+ /* No monitoring. itask can be either IDA_ONE_STEP or IDA_NORMAL */
+
+ for (itout=0; itout<Ntout; itout++) {
+
+ if (!asa) ida_status = IDASolve(ida_mem, tout[itout], &tret, yy, yp, itask);
+ else ida_status = IDASolveF(ida_mem, tout[itout], &tret, yy, yp, itask, &Nc);
+ if (ida_status < 0) goto error_return;
+
+ tdata[itout] = tret;
+
+ GetData(yy, &yydata[itout*N], N);
+
+ if (quadr) {
+ status = IDAGetQuad(ida_mem, &tret, yQ);
+ if (status != IDA_SUCCESS) goto error_return;
+ GetData(yQ, &yQdata[itout*Nq], Nq);
+ }
+
+ if (fsa) {
+ status = IDAGetSens(ida_mem, &tret, yyS);
+ if (status != IDA_SUCCESS) goto error_return;
+ for (is=0; is<Ns; is++)
+ GetData(yyS[is], &yySdata[itout*Ns*N+is*N], N);
+ }
+
+ }
+
+ } else {
+
+ /* Monitoring. itask = IDA_NORMAL */
+
+ for (itout=0; itout<Ntout; itout++) {
+
+ /* In ONE_STEP mode, IDAS reads tout only at the first step.
+ * We must therefore check here whether we need to take additional steps,
+ * or simply return interpolated solution at tout. */
+
+ status = IDAGetNumSteps(ida_mem, &nst);
+ if (status != IDA_SUCCESS) goto error_return;
+ status = IDAGetCurrentTime(ida_mem, &tret);
+ if (status != IDA_SUCCESS) goto error_return;
+
+ if ( (nst>0) && ((tret - tout[itout])*h >= 0.0) ) {
+
+ /* No need to take an additional step */
+ ida_status = IDA_SUCCESS;
+
+ } else {
+
+ /* Take additional steps */
+ while(1) {
+
+ if (!asa) ida_status = IDASolve(ida_mem, tout[itout], &tret, yy, yp, IDA_ONE_STEP);
+ else ida_status = IDASolveF(ida_mem, tout[itout], &tret, yy, yp, IDA_ONE_STEP, &Nc);
+ if (ida_status < 0) goto error_return;
+
+ /* Call the monitoring function */
+
+ if (quadr) {
+ status = IDAGetQuad(ida_mem, &tret, yQ);
+ if (status != IDA_SUCCESS) goto error_return;
+ }
+
+ if (fsa) {
+ status = IDAGetSens(ida_mem, &tret, yyS);
+ if (status != IDA_SUCCESS) goto error_return;
+ }
+
+ mxW_IDAMonitor(1, tret, yy, yQ, yyS, fwdPb);
+
+ /* If a root was found or tstop was reached, break out of while loop */
+ if (ida_status == IDA_TSTOP_RETURN || ida_status == IDA_ROOT_RETURN) break;
+
+ /* If current tout was reached break out of while loop */
+ if ( (tret - tout[itout])*h >= 0.0 ) break;
+
+ }
+
+ }
+
+ /* On a tstop or root return, return solution at tret.
+ * Otherwise (ida_status=IDA_SUCCESS), return solution at tout[itout]. */
+
+ if (ida_status == IDA_TSTOP_RETURN || ida_status == IDA_ROOT_RETURN) {
+
+ if (quadr) {
+ status = IDAGetQuad(ida_mem, &tret, yQ);
+ if (status != IDA_SUCCESS) goto error_return;
+ }
+
+ if (fsa) {
+ status = IDAGetSens(ida_mem, &tret, yyS);
+ if (status != IDA_SUCCESS) goto error_return;
+ }
+
+ } else {
+
+ tret = tout[itout];
+
+ status = IDAGetDky(ida_mem, tret, 0, yy);
+ if (status != IDA_SUCCESS) goto error_return;
+
+ if (quadr) {
+ status = IDAGetQuadDky(ida_mem, tret, 0, yQ);
+ if (status != IDA_SUCCESS) goto error_return;
+ }
+
+ if (fsa) {
+ status = IDAGetSensDky(ida_mem, tret, 0, yyS);
+ if (status != IDA_SUCCESS) goto error_return;
+ }
+
+ }
+
+ tdata[itout] = tret;
+
+ GetData(yy, &yydata[itout*N], N);
+
+ if (quadr) {
+ GetData(yQ, &yQdata[itout*Nq], Nq);
+ }
+
+ if (fsa) {
+ for (is=0; is<Ns; is++) {
+ GetData(yyS[is], &yySdata[itout*Ns*N+is*N], N);
+ }
+ }
+
+ }
+
+ }
+
+ /* IDASolve return flag (only non-negative values make it here) */
+
+ plhs[0] = mxCreateDoubleScalar((double)ida_status);
+ return(0);
+
+ /* Error return */
+
+ error_return:
+ status = -1;
+ plhs[0] = mxCreateDoubleScalar((double)status);
+ plhs[1] = mxCreateDoubleMatrix(0,0,mxREAL);
+ plhs[2] = mxCreateDoubleMatrix(0,0,mxREAL);
+ if (quadr) {
+ plhs[3] = mxCreateDoubleMatrix(0,0,mxREAL);
+ }
+ if (fsa) {
+ s_idx = quadr ? 4 : 3;
+ plhs[s_idx] = mxCreateDoubleMatrix(0,0,mxREAL);
+ }
+ return(-1);
+
+}
+
+
+static int IDM_SolveB(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
+{
+ idmPbData bckPb;
+
+ int buflen;
+ char *bufval;
+
+ int nlhs_bad;
+
+ int itaskB, NtoutB;
+ double *toutB;
+
+ double tret, h;
+
+ booleantype any_quadrB, any_monB;
+
+ int status, ida_status;
+
+ /*
+ * -------------------------------------------------------
+ * Check whether quadratures and/or monitoring are enabled
+ * for at least one backward problem
+ * -------------------------------------------------------
+ */
+
+ any_quadrB = FALSE;
+ any_monB = FALSE;
+ bckPb = idmData->bckPb;
+ while(bckPb != NULL) {
+ if (quadrB) any_quadrB = TRUE;
+ if (monB) any_monB = TRUE;
+ bckPb = bckPb->next;
+ }
+
+ /*
+ * ----------------------------------------------------------------
+ * Verify if number of output arguments agrees with current options
+ * ----------------------------------------------------------------
+ */
+
+ nlhs_bad = 0;
+
+ if (nlhs < 3) nlhs_bad = -1;
+ if (nlhs > 4) nlhs_bad = 1;
+ if ( (nlhs == 3) && any_quadrB ) nlhs_bad = -1;
+
+ if (nlhs_bad < 0) {
+ idmErrHandler(-999, "IDAS", "IDASolveB",
+ "Too few output arguments.", NULL);
+ goto error_return;
+ }
+
+ if (nlhs_bad > 0) {
+ idmErrHandler(-999, "IDAS", "IDASolveB",
+ "Too many output arguments.", NULL);
+ goto error_return;
+ }
+
+ /*
+ * ----------------------------------------------------------------
+ * Extract input arguments
+ * ----------------------------------------------------------------
+ */
+
+ /* Extract tout */
+
+ NtoutB = mxGetM(prhs[0]) * mxGetN(prhs[0]);
+ toutB = mxGetPr(prhs[0]);
+
+ /* Check if first tout value is in the right direction */
+
+ status = IDAGetLastStep(ida_mem, &h);
+ if (status != IDA_SUCCESS) goto error_return;
+ status = IDAGetCurrentTime(ida_mem, &tret);
+ if (status != IDA_SUCCESS) goto error_return;
+
+ /* The stepsize of the forward problem is used to indicate the integration direction */
+ if ( (tret - toutB[0])*h < 0.0 ) {
+ idmErrHandler(-999, "IDAS", "IDASolveB",
+ "tout value in wrong direction.", NULL);
+ goto error_return;
+ }
+
+ /* Extract itaskB */
+
+ buflen = mxGetM(prhs[1]) * mxGetN(prhs[1]) + 1;
+ bufval = mxCalloc(buflen, sizeof(char));
+ status = mxGetString(prhs[1], bufval, buflen);
+ if(!strcmp(bufval,"Normal")) {
+ itaskB = IDA_NORMAL;
+ } else if(!strcmp(bufval,"OneStep")) {
+ itaskB = IDA_ONE_STEP;
+ } else {
+ idmErrHandler(-999, "IDAS", "IDASolveB",
+ "Illegal value for itask.", NULL);
+ goto error_return;
+ }
+
+ /* If itask == IDA_ONE_STEP, then
+ * - we do not allow multiple output times
+ * - we disable monitoring
+ */
+
+ if ( itaskB == IDA_ONE_STEP ) {
+
+ if (NtoutB > 1) {
+ idmErrHandler(-999, "IDAS", "IDASolveB",
+ "More than one tout value prohibited in ONE_STEP mode.", NULL);
+ goto error_return;
+ }
+
+ if (any_monB) {
+ idmErrHandler(+999, "IDAS", "IDASolveB",
+ "Monitoring disabled in itask=ONE_STEP", NULL);
+ bckPb = idmData->bckPb;
+ while(bckPb != NULL) {
+ monB = FALSE;
+ bckPb = bckPb->next;
+ }
+ any_monB = FALSE;
+ }
+
+ }
+
+ /* Call the appropriate function to do all the work.
+ * Note: if we made it here, we rely on the functions idmSolveB_one and idmSolveB_more
+ * to set the output arrays in plhs appropriately. */
+
+ if (NbckPb == 1) ida_status = idmSolveB_one(plhs, NtoutB, toutB, itaskB);
+ else ida_status = idmSolveB_more(plhs, NtoutB, toutB, itaskB, any_quadrB, any_monB);
+
+ if (ida_status < 0) return(-1);
+ else return(0);
+
+ /* Error return */
+
+ error_return:
+ status = -1;
+ plhs[0] = mxCreateDoubleScalar((double)status);
+ plhs[1] = mxCreateDoubleMatrix(0,0,mxREAL);
+ plhs[2] = mxCreateDoubleMatrix(0,0,mxREAL);
+ if (quadrB) {
+ plhs[3] = mxCreateDoubleMatrix(0,0,mxREAL);
+ }
+ return(-1);
+
+}
+
+static int idmSolveB_one(mxArray *plhs[], int NtoutB, double *toutB, int itaskB)
+{
+ idmPbData bckPb;
+
+ void *ida_memB;
+
+ double tretB, hB;
+ double *tdata, *ydata, *yQdata;
+ int itout;
+ long int nstB;
+
+ int status, ida_status;
+
+ bckPb = idmData->bckPb;
+
+ ida_memB = IDAGetAdjIDABmem(ida_mem, indexB);
+
+ /* Check if tout values are legal */
+
+ status = IDAGetCurrentTime(ida_memB, &tretB);
+ if (status != IDA_SUCCESS) goto error_return;
+ status = IDAGetNumSteps(ida_memB, &nstB);
+ if (status != IDA_SUCCESS) goto error_return;
+
+ /* hB is used throughout this function as integration direction only */
+ if (nstB == 0) {
+ hB = toutB[0] - tretB;
+ } else {
+ status = IDAGetLastStep(ida_memB, &hB);
+ if (status != IDA_SUCCESS) goto error_return;
+ if ( (toutB[0] - tretB + hB)*hB < 0.0 ) {
+ idmErrHandler(-999, "IDAS", "IDASolveB",
+ "Illegal value of tout.", NULL);
+ goto error_return;
+ }
+ }
+
+ for (itout=1; itout<NtoutB; itout++) {
+ if ( (toutB[itout] - toutB[itout-1])*hB < 0.0 ) {
+ idmErrHandler(-999, "IDAS", "IDASolveB",
+ "tout values are not monotonic.", NULL);
+ goto error_return;
+ }
+ }
+
+ /*
+ * ----------------------------------------------------------------
+ * Prepare the output arrays
+ * ----------------------------------------------------------------
+ */
+
+ /* Return time(s) */
+
+ plhs[1] = mxCreateDoubleMatrix(1,NtoutB,mxREAL);
+ tdata = mxGetPr(plhs[1]);
+
+ /* Solution vector(s) */
+
+ plhs[2] = mxCreateDoubleMatrix(NB,NtoutB,mxREAL);
+ ydata = mxGetPr(plhs[2]);
+
+ /* Quadrature vector(s) */
+
+ if (quadrB) {
+ plhs[3] = mxCreateDoubleMatrix(NqB,NtoutB,mxREAL);
+ yQdata = mxGetPr(plhs[3]);
+ }
+
+ /*
+ * ----------------------------------------------------------------
+ * Call the IDASolveB main solver function
+ * ----------------------------------------------------------------
+ */
+
+ if (!monB) {
+
+ /* No monitoring. itaskB can be either IDA_ONE_STEP or IDA_NORMAL */
+
+ for (itout=0; itout<NtoutB; itout++) {
+
+ ida_status = IDASolveB(ida_mem, toutB[itout], itaskB);
+ if (ida_status < 0) goto error_return;
+
+ status = IDAGetB(ida_mem, indexB, &tretB, yyB, ypB);
+ if (status != IDA_SUCCESS) goto error_return;
+
+ tdata[itout] = tretB;
+
+ GetData(yyB, &ydata[itout*NB], NB);
+
+ if (quadrB) {
+ status = IDAGetQuadB(ida_mem, indexB, &tretB, yQB);
+
+ if (status != IDA_SUCCESS) goto error_return;
+ GetData(yQB, &yQdata[itout*NqB], NqB);
+ }
+
+ }
+
+
+ } else {
+
+ /* Monitoring. itask = IDA_NORMAL */
+
+ for (itout=0; itout<NtoutB; itout++) {
+
+ /* In ONE_STEP mode, IDAS reads tout only at the first step.
+ * We must therefore check here whether we need to take additional steps,
+ * or simply return interpolated solution at tout. */
+
+ status = IDAGetNumSteps(ida_memB, &nstB);
+ if (status != IDA_SUCCESS) goto error_return;
+ status = IDAGetCurrentTime(ida_memB, &tretB);
+ if (status != IDA_SUCCESS) goto error_return;
+
+ if ( (nstB>0) && ((tretB - toutB[itout])*hB >= 0.0) ) {
+
+ /* No need to take an additional step */
+ ida_status = IDA_SUCCESS;
+
+ } else {
+
+ /* Take additional steps */
+ while(1) {
+
+ ida_status = IDASolveB(ida_mem, toutB[itout], IDA_ONE_STEP);
+ if (ida_status < 0) goto error_return;
+
+ /* Call the monitoring function */
+ status = IDAGetB(ida_mem, indexB, &tretB, yyB, ypB);
+ if (status != IDA_SUCCESS) goto error_return;
+ if (quadrB) {
+ status = IDAGetQuadB(ida_mem, indexB, &tretB, yQB);
+ if (status != IDA_SUCCESS) goto error_return;
+ }
+ mxW_IDAMonitorB(1, indexB, tretB, yyB, yQB, bckPb);
+
+ /* If current tout was reached break out of while loop */
+ if ( (tretB - toutB[itout])*hB >= 0.0 ) break;
+
+ }
+
+ }
+
+ tretB = toutB[itout];
+
+ tdata[itout] = tretB;
+
+ status = IDAGetDky(ida_memB, tretB, 0, yyB);
+ if (status != IDA_SUCCESS) goto error_return;
+
+ GetData(yyB, &ydata[itout*NB], NB);
+
+ if (quadrB) {
+ status = IDAGetQuadDky(ida_memB, tretB, 0, yQB);
+ if (status != IDA_SUCCESS) goto error_return;
+ GetData(yQB, &yQdata[itout*NqB], NqB);
+ }
+
+ }
+
+ }
+
+ /* IDASolve return flag (only non-negative values make it here) */
+
+ plhs[0] = mxCreateDoubleScalar((double)ida_status);
+ return(0);
+
+ error_return:
+ status = -1;
+ plhs[0] = mxCreateDoubleScalar((double)status);
+ plhs[1] = mxCreateDoubleMatrix(0,0,mxREAL);
+ plhs[2] = mxCreateDoubleMatrix(0,0,mxREAL);
+ if (quadrB) {
+ plhs[3] = mxCreateDoubleMatrix(0,0,mxREAL);
+ }
+ return(-1);
+
+}
+
+
+static int idmSolveB_more(mxArray *plhs[], int NtoutB, double *toutB, int itaskB,
+ booleantype any_quadrB, booleantype any_monB)
+{
+ idmPbData bckPb;
+ mxArray *cell;
+ int status, ida_status;
+
+ idmErrHandler(-999, "IDAS", "IDASolveB",
+ "Integration of multiple backward problems is not yet implemented.", NULL);
+ goto error_return;
+
+ plhs[0] = mxCreateDoubleScalar((double)ida_status);
+ return(0);
+
+ error_return:
+ status = -1;
+ plhs[0] = mxCreateDoubleScalar((double)status);
+ /*
+ plhs[1] = mxCreateDoubleMatrix(0,0,mxREAL);
+ plhs[2] = mxCreateDoubleMatrix(0,0,mxREAL);
+ if (quadrB) {
+ plhs[3] = mxCreateDoubleMatrix(0,0,mxREAL);
+ }
+ */
+ return(-1);
+
+}
+
+
+static int IDM_Stats(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
+{
+ idmPbData fwdPb;
+
+ const char *fnames_intgr[]={
+ "nst",
+ "nfe",
+ "nge",
+ "nsetups",
+ "netf",
+ "nni",
+ "ncfn",
+ "qlast",
+ "qcur",
+ "h0used",
+ "hlast",
+ "hcur",
+ "tcur",
+ "RootInfo",
+ "QuadInfo",
+ "LSInfo",
+ "FSAInfo"
+ };
+ const char *fnames_root[]={
+ "nge",
+ "roots"
+ };
+ const char *fnames_dense[]={
+ "name",
+ "njeD",
+ "nfeD"
+ };
+ const char *fnames_band[]={
+ "name",
+ "njeB",
+ "nfeB"
+ };
+ const char *fnames_spils[]={
+ "name",
+ "nli",
+ "npe",
+ "nps",
+ "ncfl",
+ "njeSG",
+ "nfeSG"
+ };
+ const char *fnames_quad[]={
+ "nfQe",
+ "netfQ"
+ };
+ const char *fnames_sens[]={
+ "nrSe",
+ "nfeS",
+ "nsetupsS",
+ "netfS",
+ "nniS",
+ "ncfnS",
+ };
+
+ long int nst, nfe, nsetups, nni, ncfn, netf, nge;
+ int qlast, qcur;
+ double h0used, hlast, hcur, tcur;
+ int *rootsfound;
+
+ long int njeD, nfeD;
+ long int njeB, nfeB;
+ long int nli, npe, nps, ncfl, njeSG, nfeSG;
+
+ long int nfQe, netfQ;
+
+ long int nrSe, nfeS, netfS, nsetupsS;
+ long int nniS, ncfnS;
+
+ int i, status;
+ mxArray *mxS_root, *mxS_ls, *mxS_quad, *mxS_fsa;
+ mxArray *mxS_rootsfound;
+ double *tmp;
+ int nfields;
+
+ if (idmData == NULL) return(0);
+
+ fwdPb = idmData->fwdPb;
+
+ status = IDAGetIntegratorStats(ida_mem, &nst, &nfe, &nsetups,
+ &netf, &qlast, &qcur, &h0used, &hlast, &hcur, &tcur);
+ if (status != IDA_SUCCESS) goto error_return;
+
+ status = IDAGetNonlinSolvStats(ida_mem, &nni, &ncfn);
+ if (status != IDA_SUCCESS) goto error_return;
+
+ nfields = sizeof(fnames_intgr)/sizeof(*fnames_intgr);
+ plhs[0] = mxCreateStructMatrix(1, 1, nfields, fnames_intgr);
+
+ mxSetField(plhs[0], 0, "nst", mxCreateDoubleScalar((double)nst));
+ mxSetField(plhs[0], 0, "nfe", mxCreateDoubleScalar((double)nfe));
+ mxSetField(plhs[0], 0, "nsetups", mxCreateDoubleScalar((double)nsetups));
+ mxSetField(plhs[0], 0, "netf", mxCreateDoubleScalar((double)netf));
+ mxSetField(plhs[0], 0, "nni", mxCreateDoubleScalar((double)nni));
+ mxSetField(plhs[0], 0, "ncfn", mxCreateDoubleScalar((double)ncfn));
+ mxSetField(plhs[0], 0, "qlast", mxCreateDoubleScalar((double)qlast));
+ mxSetField(plhs[0], 0, "qcur", mxCreateDoubleScalar((double)qcur));
+ mxSetField(plhs[0], 0, "h0used", mxCreateDoubleScalar(h0used));
+ mxSetField(plhs[0], 0, "hlast", mxCreateDoubleScalar(hlast));
+ mxSetField(plhs[0], 0, "hcur", mxCreateDoubleScalar(hcur));
+ mxSetField(plhs[0], 0, "tcur", mxCreateDoubleScalar(tcur));
+
+
+ /* Root Finding Statistics */
+
+ if (Ng > 0) {
+
+ status = IDAGetNumGEvals(ida_mem, &nge);
+ if (status != IDA_SUCCESS) goto error_return;
+
+ nfields = sizeof(fnames_root)/sizeof(*fnames_root);
+ mxS_root = mxCreateStructMatrix(1, 1, nfields, fnames_root);
+
+ mxSetField(mxS_root, 0, "nge", mxCreateDoubleScalar((double)nge));
+
+ rootsfound = (int *) malloc(Ng*sizeof(int));
+ status = IDAGetRootInfo(ida_mem, rootsfound);
+ if (status != IDA_SUCCESS) goto error_return;
+ mxS_rootsfound = mxCreateDoubleMatrix(Ng,1,mxREAL);
+ tmp = mxGetPr(mxS_rootsfound);
+ for (i=0;i<Ng;i++)
+ tmp[i] = (double)rootsfound[i];
+ mxSetField(mxS_root, 0, "roots", mxS_rootsfound);
+ free(rootsfound);
+
+ } else {
+
+ mxS_root = mxCreateDoubleMatrix(0,0,mxREAL);
+
+ }
+
+ mxSetField(plhs[0], 0, "RootInfo", mxS_root);
+
+ /* Quadrature Statistics */
+
+ if (quadr) {
+
+ status = IDAGetQuadStats(ida_mem, &nfQe, &netfQ);
+ if (status != IDA_SUCCESS) goto error_return;
+
+ nfields = sizeof(fnames_quad)/sizeof(*fnames_quad);
+ mxS_quad = mxCreateStructMatrix(1, 1, nfields, fnames_quad);
+
+ mxSetField(mxS_quad, 0, "nfQe", mxCreateDoubleScalar((double)nfQe));
+ mxSetField(mxS_quad, 0, "netfQ", mxCreateDoubleScalar((double)netfQ));
+
+ } else {
+
+ mxS_quad = mxCreateDoubleMatrix(0,0,mxREAL);
+
+ }
+
+ mxSetField(plhs[0], 0, "QuadInfo", mxS_quad);
+
+ /* Linear Solver Statistics */
+
+ switch(ls){
+
+ case LS_DENSE:
+
+ status = IDADlsGetNumJacEvals(ida_mem, &njeD);
+ if (status != IDA_SUCCESS) goto error_return;
+ status = IDADlsGetNumResEvals(ida_mem, &nfeD);
+ if (status != IDA_SUCCESS) goto error_return;
+
+ nfields = sizeof(fnames_dense)/sizeof(*fnames_dense);
+ mxS_ls = mxCreateStructMatrix(1, 1, nfields, fnames_dense);
+
+ mxSetField(mxS_ls, 0, "name", mxCreateString("Dense"));
+ mxSetField(mxS_ls, 0, "njeD", mxCreateDoubleScalar((double)njeD));
+ mxSetField(mxS_ls, 0, "nfeD", mxCreateDoubleScalar((double)nfeD));
+
+ break;
+
+ case LS_BAND:
+
+ status = IDADlsGetNumJacEvals(ida_mem, &njeB);
+ if (status != IDA_SUCCESS) goto error_return;
+ status = IDADlsGetNumResEvals(ida_mem, &nfeB);
+ if (status != IDA_SUCCESS) goto error_return;
+
+ nfields = sizeof(fnames_band)/sizeof(*fnames_band);
+ mxS_ls = mxCreateStructMatrix(1, 1, nfields, fnames_band);
+
+ mxSetField(mxS_ls, 0, "name", mxCreateString("Band"));
+ mxSetField(mxS_ls, 0, "njeB", mxCreateDoubleScalar((double)njeB));
+ mxSetField(mxS_ls, 0, "nfeB", mxCreateDoubleScalar((double)nfeB));
+
+ break;
+
+ case LS_SPGMR:
+ case LS_SPBCG:
+ case LS_SPTFQMR:
+
+ status = IDASpilsGetNumLinIters(ida_mem, &nli);
+ if (status != IDA_SUCCESS) goto error_return;
+ status = IDASpilsGetNumPrecEvals(ida_mem, &npe);
+ if (status != IDA_SUCCESS) goto error_return;
+ status = IDASpilsGetNumPrecSolves(ida_mem, &nps);
+ if (status != IDA_SUCCESS) goto error_return;
+ status = IDASpilsGetNumConvFails(ida_mem, &ncfl);
+ if (status != IDA_SUCCESS) goto error_return;
+ status = IDASpilsGetNumJtimesEvals(ida_mem, &njeSG);
+ if (status != IDA_SUCCESS) goto error_return;
+ status = IDASpilsGetNumResEvals(ida_mem, &nfeSG);
+ if (status != IDA_SUCCESS) goto error_return;
+
+ nfields = sizeof(fnames_spils)/sizeof(*fnames_spils);
+ mxS_ls = mxCreateStructMatrix(1, 1, nfields, fnames_spils);
+
+ if (ls == LS_SPGMR)
+ mxSetField(mxS_ls, 0, "name", mxCreateString("GMRES"));
+ else if (ls == LS_SPBCG)
+ mxSetField(mxS_ls, 0, "name", mxCreateString("BiCGStab"));
+ else
+ mxSetField(mxS_ls, 0, "name", mxCreateString("TFQMR"));
+
+ mxSetField(mxS_ls, 0, "nli", mxCreateDoubleScalar((double)nli));
+ mxSetField(mxS_ls, 0, "npe", mxCreateDoubleScalar((double)npe));
+ mxSetField(mxS_ls, 0, "nps", mxCreateDoubleScalar((double)nps));
+ mxSetField(mxS_ls, 0, "ncfl", mxCreateDoubleScalar((double)ncfl));
+ mxSetField(mxS_ls, 0, "njeSG", mxCreateDoubleScalar((double)njeSG));
+ mxSetField(mxS_ls, 0, "nfeSG", mxCreateDoubleScalar((double)nfeSG));
+
+ break;
+
+ }
+
+ mxSetField(plhs[0], 0, "LSInfo", mxS_ls);
+
+ /* Forward Sensitivity Statistics */
+
+ if (fsa) {
+
+ status = IDAGetSensStats(ida_mem, &nrSe, &nfeS, &netfS, &nsetupsS);
+ if (status != IDA_SUCCESS) goto error_return;
+
+ status = IDAGetSensNonlinSolvStats(ida_mem, &nniS, &ncfnS);
+ if (status != IDA_SUCCESS) goto error_return;
+
+ nfields = sizeof(fnames_sens)/sizeof(*fnames_sens);
+ mxS_fsa = mxCreateStructMatrix(1, 1, nfields, fnames_sens);
+
+ mxSetField(mxS_fsa, 0, "nrSe", mxCreateDoubleScalar((double)nrSe));
+ mxSetField(mxS_fsa, 0, "nfeS", mxCreateDoubleScalar((double)nfeS));
+ mxSetField(mxS_fsa, 0, "nsetupsS", mxCreateDoubleScalar((double)nsetupsS));
+ mxSetField(mxS_fsa, 0, "netfS", mxCreateDoubleScalar((double)netfS));
+ mxSetField(mxS_fsa, 0, "nniS", mxCreateDoubleScalar((double)nniS));
+ mxSetField(mxS_fsa, 0, "ncfnS", mxCreateDoubleScalar((double)ncfnS));
+
+ } else {
+
+ mxS_fsa = mxCreateDoubleMatrix(0,0,mxREAL);
+
+ }
+
+ mxSetField(plhs[0], 0, "FSAInfo", mxS_fsa);
+
+ /* Successful return */
+
+ status = 0;
+ plhs[1] = mxCreateDoubleScalar((double)status);
+ return(0);
+
+ /* Error return */
+
+ error_return:
+ status = -1;
+ plhs[1] = mxCreateDoubleScalar((double)status);
+ return(-1);
+
+}
+
+static int IDM_StatsB(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
+{
+ idmPbData bckPb;
+ int idxB;
+
+ const char *fnames_intgr[]={
+ "nst",
+ "nfe",
+ "nge",
+ "nsetups",
+ "netf",
+ "nni",
+ "ncfn",
+ "qlast",
+ "qcur",
+ "h0used",
+ "hlast",
+ "hcur",
+ "tcur",
+ "QuadInfo",
+ "LSInfo",
+ };
+ const char *fnames_dense[]={
+ "name",
+ "njeD",
+ "nfeD"
+ };
+ const char *fnames_band[]={
+ "name",
+ "njeB",
+ "nfeB"
+ };
+ const char *fnames_spils[]={
+ "name",
+ "nli",
+ "npe",
+ "nps",
+ "ncfl",
+ "njeSG",
+ "nfeSG"
+ };
+ const char *fnames_quad[]={
+ "nfQe",
+ "netfQ"
+ };
+
+ void *ida_memB;
+
+ long int nst, nfe, nsetups, nni, ncfn, netf;
+ int qlast, qcur;
+ double h0used, hlast, hcur, tcur;
+
+ long int njeD, nfeD;
+ long int njeB, nfeB;
+ long int nli, npe, nps, ncfl, njeSG, nfeSG;
+
+ long int nfQe, netfQ;
+
+ int status;
+ mxArray *mxS_ls, *mxS_quad;
+ int nfields;
+
+ booleantype found_bck;
+
+
+ /* Extract index of current backward problem */
+
+ idxB = (int)mxGetScalar(prhs[0]);
+
+ /* Find current backward problem */
+
+ found_bck = FALSE;
+ bckPb = idmData->bckPb;
+ while (bckPb != NULL) {
+ if (indexB == idxB) {
+ found_bck = TRUE;
+ break;
+ }
+ bckPb = bckPb->next;
+ }
+
+ if (!found_bck) idmErrHandler(-999, "IDAS", "IDAGetStatsB",
+ "idxB has an illegal value.", NULL);
+
+ ida_memB = IDAGetAdjIDABmem(ida_mem, indexB);
+
+ status = IDAGetIntegratorStats(ida_memB, &nst, &nfe, &nsetups,
+ &netf, &qlast, &qcur, &h0used, &hlast, &hcur, &tcur);
+ if (status != IDA_SUCCESS) goto error_return;
+
+ status = IDAGetNonlinSolvStats(ida_memB, &nni, &ncfn);
+ if (status != IDA_SUCCESS) goto error_return;
+
+ nfields = sizeof(fnames_intgr)/sizeof(*fnames_intgr);
+ plhs[0] = mxCreateStructMatrix(1, 1, nfields, fnames_intgr);
+
+ mxSetField(plhs[0], 0, "nst", mxCreateDoubleScalar((double)nst));
+ mxSetField(plhs[0], 0, "nfe", mxCreateDoubleScalar((double)nfe));
+ mxSetField(plhs[0], 0, "nsetups", mxCreateDoubleScalar((double)nsetups));
+ mxSetField(plhs[0], 0, "netf", mxCreateDoubleScalar((double)netf));
+ mxSetField(plhs[0], 0, "nni", mxCreateDoubleScalar((double)nni));
+ mxSetField(plhs[0], 0, "ncfn", mxCreateDoubleScalar((double)ncfn));
+ mxSetField(plhs[0], 0, "qlast", mxCreateDoubleScalar((double)qlast));
+ mxSetField(plhs[0], 0, "qcur", mxCreateDoubleScalar((double)qcur));
+ mxSetField(plhs[0], 0, "h0used", mxCreateDoubleScalar(h0used));
+ mxSetField(plhs[0], 0, "hlast", mxCreateDoubleScalar(hlast));
+ mxSetField(plhs[0], 0, "hcur", mxCreateDoubleScalar(hcur));
+ mxSetField(plhs[0], 0, "tcur", mxCreateDoubleScalar(tcur));
+
+
+ /* Quadrature Statistics */
+
+ if (quadrB) {
+
+ status = IDAGetQuadStats(ida_memB, &nfQe, &netfQ);
+ if (status != IDA_SUCCESS) goto error_return;
+
+ nfields = sizeof(fnames_quad)/sizeof(*fnames_quad);
+ mxS_quad = mxCreateStructMatrix(1, 1, nfields, fnames_quad);
+
+ mxSetField(mxS_quad, 0, "nfQe", mxCreateDoubleScalar((double)nfQe));
+ mxSetField(mxS_quad, 0, "netfQ", mxCreateDoubleScalar((double)netfQ));
+
+ } else {
+
+ mxS_quad = mxCreateDoubleMatrix(0,0,mxREAL);
+
+ }
+
+ mxSetField(plhs[0], 0, "QuadInfo", mxS_quad);
+
+ /* Linear Solver Statistics */
+
+ switch(lsB){
+
+ case LS_DENSE:
+
+ status = IDADlsGetNumJacEvals(ida_memB, &njeD);
+ if (status != IDA_SUCCESS) goto error_return;
+ status = IDADlsGetNumResEvals(ida_memB, &nfeD);
+ if (status != IDA_SUCCESS) goto error_return;
+
+ nfields = sizeof(fnames_dense)/sizeof(*fnames_dense);
+ mxS_ls = mxCreateStructMatrix(1, 1, nfields, fnames_dense);
+
+ mxSetField(mxS_ls, 0, "name", mxCreateString("Dense"));
+ mxSetField(mxS_ls, 0, "njeD", mxCreateDoubleScalar((double)njeD));
+ mxSetField(mxS_ls, 0, "nfeD", mxCreateDoubleScalar((double)nfeD));
+
+ break;
+
+ case LS_BAND:
+
+ status = IDADlsGetNumJacEvals(ida_memB, &njeB);
+ if (status != IDA_SUCCESS) goto error_return;
+ status = IDADlsGetNumResEvals(ida_memB, &nfeB);
+ if (status != IDA_SUCCESS) goto error_return;
+
+ nfields = sizeof(fnames_band)/sizeof(*fnames_band);
+ mxS_ls = mxCreateStructMatrix(1, 1, nfields, fnames_band);
+
+ mxSetField(mxS_ls, 0, "name", mxCreateString("Band"));
+ mxSetField(mxS_ls, 0, "njeB", mxCreateDoubleScalar((double)njeB));
+ mxSetField(mxS_ls, 0, "nfeB", mxCreateDoubleScalar((double)nfeB));
+
+ break;
+
+ case LS_SPGMR:
+ case LS_SPBCG:
+ case LS_SPTFQMR:
+
+ status = IDASpilsGetNumLinIters(ida_memB, &nli);
+ if (status != IDA_SUCCESS) goto error_return;
+ status = IDASpilsGetNumPrecEvals(ida_memB, &npe);
+ if (status != IDA_SUCCESS) goto error_return;
+ status = IDASpilsGetNumPrecSolves(ida_memB, &nps);
+ if (status != IDA_SUCCESS) goto error_return;
+ status = IDASpilsGetNumConvFails(ida_memB, &ncfl);
+ if (status != IDA_SUCCESS) goto error_return;
+ status = IDASpilsGetNumJtimesEvals(ida_memB, &njeSG);
+ if (status != IDA_SUCCESS) goto error_return;
+ status = IDASpilsGetNumResEvals(ida_memB, &nfeSG);
+ if (status != IDA_SUCCESS) goto error_return;
+
+ nfields = sizeof(fnames_spils)/sizeof(*fnames_spils);
+ mxS_ls = mxCreateStructMatrix(1, 1, nfields, fnames_spils);
+
+ if (lsB == LS_SPGMR)
+ mxSetField(mxS_ls, 0, "name", mxCreateString("GMRES"));
+ else if (lsB == LS_SPBCG)
+ mxSetField(mxS_ls, 0, "name", mxCreateString("BiCGStab"));
+ else
+ mxSetField(mxS_ls, 0, "name", mxCreateString("TFQMR"));
+
+ mxSetField(mxS_ls, 0, "nli", mxCreateDoubleScalar((double)nli));
+ mxSetField(mxS_ls, 0, "npe", mxCreateDoubleScalar((double)npe));
+ mxSetField(mxS_ls, 0, "nps", mxCreateDoubleScalar((double)nps));
+ mxSetField(mxS_ls, 0, "ncfl", mxCreateDoubleScalar((double)ncfl));
+ mxSetField(mxS_ls, 0, "njeSG", mxCreateDoubleScalar((double)njeSG));
+ mxSetField(mxS_ls, 0, "nfeSG", mxCreateDoubleScalar((double)nfeSG));
+
+ break;
+ }
+
+ mxSetField(plhs[0], 0, "LSInfo", mxS_ls);
+
+ /* Successful return */
+
+ status = 0;
+ plhs[1] = mxCreateDoubleScalar((double)status);
+ return(0);
+
+ /* Error return */
+
+ error_return:
+ status = -1;
+ plhs[1] = mxCreateDoubleScalar((double)status);
+ return(-1);
+
+}
+
+static int IDM_Set(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
+{
+ idmPbData fwdPb;
+
+ const mxArray *options;
+ mxArray *opt;
+
+ double tstop;
+
+ int status;
+
+ fwdPb = idmData->fwdPb;
+ options = prhs[0];
+
+ /* Return now if options was empty */
+
+ if (mxIsEmpty(options)) return(0);
+
+ /* User data */
+
+ opt = mxGetField(options,0,"UserData");
+ if ( !mxIsEmpty(opt) ) {
+ mxDestroyArray(mtlb_data);
+ mtlb_data = mxDuplicateArray(opt);
+ }
+
+ /* Stopping time */
+
+ opt = mxGetField(options,0,"StopTime");
+ if ( !mxIsEmpty(opt) ) {
+ tstop = (double)mxGetScalar(opt);
+ status = IDASetStopTime(ida_mem, tstop);
+ if (status != IDA_SUCCESS) goto error_return;
+ }
+
+ /* Successful return */
+
+ status = 0;
+ plhs[0] = mxCreateDoubleScalar((double)status);
+ return(0);
+
+ /* Error return */
+
+ error_return:
+ status = -1;
+ plhs[0] = mxCreateDoubleScalar((double)status);
+ return(-1);
+
+}
+
+static int IDM_SetB(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
+{
+ return(0);
+}
+
+static int IDM_Get(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
+{
+ idmPbData fwdPb;
+
+ double t;
+ N_Vector ewt;
+ double *this, *next;
+ int key, k, i, nfields;
+
+ IDAadjCheckPointRec *ckpnt;
+ const char *fnames_ckpnt[]={
+ "t0",
+ "t1",
+ "nstep",
+ "order",
+ "step"
+ };
+
+ int status;
+
+ fwdPb = idmData->fwdPb;
+
+ key = (int) (*mxGetPr(prhs[0]));
+
+ switch (key) {
+
+ case 1: /* DerivSolution */
+
+ t = *mxGetPr(prhs[1]);
+ k = (int) (*mxGetPr(prhs[2]));
+
+ plhs[0] = mxCreateDoubleMatrix(N,1,mxREAL);
+ status = IDAGetDky(ida_mem, t, k, yy);
+ if (status != IDA_SUCCESS) goto error_return;
+ GetData(yy, mxGetPr(plhs[0]), N);
+
+ break;
+
+ case 2: /* ErrorWeights */
+
+ ewt = N_VClone(yy);
+
+ plhs[0] = mxCreateDoubleMatrix(N,1,mxREAL);
+ status = IDAGetErrWeights(ida_mem, ewt);
+ if (status != IDA_SUCCESS) goto error_return;
+ GetData(ewt, mxGetPr(plhs[0]), N);
+
+ N_VDestroy(ewt);
+
+ break;
+
+ case 3: /* not used */
+
+ break;
+
+ case 4: /* CheckPointsInfo */
+
+ ckpnt = (IDAadjCheckPointRec *) malloc ( (Nc+1)*sizeof(IDAadjCheckPointRec));
+ status = IDAGetAdjCheckPointsInfo(ida_mem, ckpnt);
+ if (status != IDA_SUCCESS) {
+ free(ckpnt);
+ goto error_return;
+ }
+ nfields = sizeof(fnames_ckpnt)/sizeof(*fnames_ckpnt);
+ plhs[0] = mxCreateStructMatrix(Nc+1, 1, nfields, fnames_ckpnt);
+ for (i=0; i<=Nc; i++) {
+ this = (double *)(ckpnt[Nc-i].my_addr);
+ next = (double *)(ckpnt[Nc-i].next_addr);
+ mxSetField(plhs[0], i, "t0", mxCreateDoubleScalar((double)(ckpnt[Nc-i].t0)));
+ mxSetField(plhs[0], i, "t1", mxCreateDoubleScalar((double)(ckpnt[Nc-i].t1)));
+ mxSetField(plhs[0], i, "nstep", mxCreateDoubleScalar((double)(ckpnt[Nc-i].nstep)));
+ mxSetField(plhs[0], i, "order", mxCreateDoubleScalar((double)(ckpnt[Nc-i].order)));
+ mxSetField(plhs[0], i, "step", mxCreateDoubleScalar((double)(ckpnt[Nc-i].step)));
+ }
+ free(ckpnt);
+ break;
+
+ }
+
+ /* Successful return */
+
+ status = 0;
+ plhs[1] = mxCreateDoubleScalar((double)status);
+ return(0);
+
+ /* Error return */
+
+ error_return:
+ status = -1;
+ plhs[1] = mxCreateDoubleScalar((double)status);
+ return(-1);
+}
+
+static int IDM_Free(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
+{
+ idmPbData fwdPb, bckPb;
+
+ if (idmData == NULL) return(0);
+
+ fwdPb = idmData->fwdPb;
+ if (mon) mxW_IDAMonitor(2, 0.0, NULL, NULL, NULL, fwdPb);
+
+ bckPb = idmData->bckPb;
+ while (bckPb != NULL) {
+ if (monB) mxW_IDAMonitorB(2, indexB, 0.0, NULL, NULL, bckPb);
+ bckPb = bckPb->next;
+ }
+
+ IDAFree(&ida_mem);
+
+ return(0);
+}
+
diff --git a/sundialsTB/idas/idm/src/idm.h b/sundialsTB/idas/idm/src/idm.h
new file mode 100644
index 0000000..81933fc
--- /dev/null
+++ b/sundialsTB/idas/idm/src/idm.h
@@ -0,0 +1,319 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.10 $
+ * $Date: 2012/03/07 21:49:18 $
+ * -----------------------------------------------------------------
+ * Programmer: 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 sundials-x.y.z/src/idas/LICENSE.
+ * -----------------------------------------------------------------
+ * Header file for the IDAS Matlab interface.
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _IDM_H
+#define _IDM_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <string.h>
+#include <stdlib.h>
+#include "mex.h"
+#include <idas/idas.h>
+#include <idas/idas_dense.h>
+#include <idas/idas_band.h>
+#include <idas/idas_spgmr.h>
+#include <idas/idas_spbcgs.h>
+#include <idas/idas_sptfqmr.h>
+#include <idas/idas_bbdpre.h>
+
+/*
+ * ---------------------------------------------------------------------------------
+ * Constants
+ * ---------------------------------------------------------------------------------
+ */
+
+/* Tolerance types */
+
+enum {IDA_SS, IDA_SV, IDA_EE};
+
+/* Linear solver types */
+
+enum {LS_DENSE, LS_BAND, LS_SPGMR, LS_SPBCG, LS_SPTFQMR};
+
+/* Preconditioner modules */
+
+enum {PM_NONE, PM_BBDPRE};
+
+/*
+ * ---------------------------------------------------------------------------------
+ * Types for global data structures
+ * ---------------------------------------------------------------------------------
+ */
+
+
+typedef struct idmPbData_ {
+
+
+ long int n; /* problem dimension */
+ N_Vector YY; /* solution vector */
+ N_Vector YP; /* derivative of solution vector */
+
+ booleantype Quadr; /* integrate quadratures? */
+ long int nq; /* number of quadratures */
+ N_Vector YQ; /* quadratures vector */
+
+ booleantype Fsa; /* integrate sensitivities? */
+ int ns; /* number of sensitivities */
+ N_Vector *YYS; /* sensitivity vectors */
+ N_Vector *YPS; /* derivatives of sensitivity vectors */
+
+ booleantype RootSet; /* rootfinding active? */
+ int ng; /* number of root functions */
+
+ booleantype TstopSet; /* tstop active? */
+
+ int LS; /* linear solver type */
+ int PM; /* preconditioner module */
+
+ booleantype Mon; /* monitoring? */
+
+ /* Matlab functions and data associated with this problem */
+
+ mxArray *RESfct;
+ mxArray *QUADfct;
+
+ mxArray *JACfct;
+
+ mxArray *PSETfct;
+ mxArray *PSOLfct;
+
+ mxArray *GLOCfct;
+ mxArray *GCOMfct;
+
+ mxArray *Gfct;
+
+ mxArray *SRESfct;
+
+ mxArray *MONfct;
+ mxArray *MONdata;
+
+ /* Pointer to the global Matlab user data */
+
+ mxArray *mtlb_data;
+
+ /* Information for backward problems only */
+
+ struct idmPbData_ *fwd;
+ int index; /* index of this problem */
+ struct idmPbData_ *next; /* pointer to next problem in linked list */
+
+} *idmPbData;
+
+
+typedef struct idmInterfaceData_ {
+
+ void *ida_mem; /* IDAS solver memory */
+
+ booleantype asa; /* Perform ASA? */
+ int Nd; /* number of data points */
+ int Nc; /* number of check points */
+
+ struct idmPbData_ *fwdPb;
+ struct idmPbData_ *bckPb;
+
+ int NbckPb; /* Number of backward problems in the linked list bckPb */
+
+ booleantype errMsg; /* post error/warning messages? */
+
+} *idmInterfaceData;
+
+
+
+/*
+ * ---------------------------------------------------------------------------------
+ * Error handler function
+ * ---------------------------------------------------------------------------------
+ */
+
+void idmErrHandler(int error_code,
+ const char *module, const char *function,
+ char *msg, void *eh_data);
+
+
+/*
+ * ---------------------------------------------------------------------------------
+ * Wrapper functions
+ * ---------------------------------------------------------------------------------
+ */
+
+int mxW_IDARes(realtype tt, N_Vector yy, N_Vector yp,
+ N_Vector rr, void *user_data);
+
+int mxW_IDAGfct(realtype t, N_Vector y, N_Vector yp,
+ realtype *gout, void *user_data);
+
+int mxW_IDAQuadFct(realtype tres, N_Vector yy, N_Vector yp,
+ N_Vector ypQ,
+ void *user_data);
+
+int mxW_IDASensRes(int Nsens, realtype tres,
+ N_Vector yy, N_Vector yp, N_Vector resval,
+ N_Vector *yyS, N_Vector *ypS, N_Vector *resvalS,
+ void *user_data,
+ N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
+
+int mxW_IDADenseJac(long int Neq,
+ realtype tt, realtype c_j,
+ N_Vector yy, N_Vector yp, N_Vector rr,
+ DlsMat Jac, void *user_data,
+ N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
+
+int mxW_IDABandJac(long int Neq, long int mupper, long int mlower,
+ realtype tt, realtype c_j,
+ N_Vector yy, N_Vector yp, N_Vector rr,
+ DlsMat Jac, void *user_data,
+ N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
+
+int mxW_IDASpilsJac(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);
+int mxW_IDASpilsPset(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 mxW_IDASpilsPsol(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);
+
+int mxW_IDABBDgloc(long int Nlocal, realtype tt,
+ N_Vector yy, N_Vector yp, N_Vector gval,
+ void *user_data);
+int mxW_IDABBDgcom(long int Nlocal, realtype tt,
+ N_Vector yy, N_Vector yp,
+ void *user_data);
+
+void mxW_IDAMonitor(int call, double t,
+ N_Vector yy,
+ N_Vector yQ,
+ N_Vector *yyS,
+ idmPbData fwdPb);
+
+int mxW_IDAResB(realtype tt,
+ N_Vector yy, N_Vector yp,
+ N_Vector yyB, N_Vector ypB, N_Vector rrB,
+ void *user_dataB);
+int mxW_IDAResBS(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);
+
+int mxW_IDAQuadFctB(realtype tt,
+ N_Vector yy, N_Vector yp,
+ N_Vector yyB, N_Vector ypB,
+ N_Vector ypQB,
+ void *user_dataB);
+int mxW_IDAQuadFctBS(realtype t,
+ N_Vector yy, N_Vector yp,
+ N_Vector *yyS, N_Vector *ypS,
+ N_Vector yyB, N_Vector ypB,
+ N_Vector ypQB,
+ void *user_dataB);
+
+int mxW_IDADenseJacB(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);
+
+int mxW_IDABandJacB(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);
+
+int mxW_IDASpilsJacB(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);
+int mxW_IDASpilsPsetB(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);
+int mxW_IDASpilsPsolB(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);
+
+int mxW_IDABBDglocB(long int NlocalB, realtype tt,
+ N_Vector yy, N_Vector yp,
+ N_Vector yyB, N_Vector ypB, N_Vector gvalB,
+ void *user_dataB);
+int mxW_IDABBDgcomB(long int NlocalB, realtype tt,
+ N_Vector yy, N_Vector yp,
+ N_Vector yyB, N_Vector ypB,
+ void *user_dataB);
+
+void mxW_IDAMonitorB(int call, int idxB, double tB,
+ N_Vector yyB,
+ N_Vector yQB,
+ idmPbData bckPb);
+
+/*
+ * ---------------------------------------------------------------------------------
+ * Option handling functions
+ * ---------------------------------------------------------------------------------
+ */
+
+int get_IntgrOptions(const mxArray *options, idmPbData thisPb, booleantype fwd,
+ int *maxord,
+ long int *mxsteps,
+ int *itol, realtype *reltol, double *Sabstol, double **Vabstol,
+ double *hin, double *hmax,
+ double *tstop,
+ booleantype *suppress,
+ booleantype *errmsg,
+ double **id, double **cnstr,
+ booleantype *res_s);
+
+int get_LinSolvOptions(const mxArray *options, idmPbData thisPb, booleantype fwd,
+ long int *mupper, long int *mlower,
+ long int *mudq, long int *mldq, double *dqrely,
+ int *gstype, int *maxl);
+
+int get_QuadOptions(const mxArray *options, idmPbData thisPb, booleantype fwd,
+ long int Nq, booleantype *rhs_s,
+ booleantype *errconQ,
+ int *itolQ, double *reltolQ, double *SabstolQ, double **VabstolQ);
+
+int get_FSAOptions(const mxArray *options, idmPbData thisPb,
+ int *ism,
+ char **pfield_name, int **plist, double **pbar,
+ int *dqtype, double *rho,
+ booleantype *errconS, int *itolS, double *reltolS,
+ double **SabstolS, double **VabstolS);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/sundialsTB/idas/idm/src/idmOpts.c b/sundialsTB/idas/idm/src/idmOpts.c
new file mode 100644
index 0000000..2378a23
--- /dev/null
+++ b/sundialsTB/idas/idm/src/idmOpts.c
@@ -0,0 +1,875 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.11 $
+ * $Date: 2012/03/07 21:49:18 $
+ * -----------------------------------------------------------------
+ * Programmer: 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 sundials-x.y.z/src/idas/LICENSE.
+ * -----------------------------------------------------------------
+ * Option parsing functions for the IDAS Matlab interface.
+ * -----------------------------------------------------------------
+ */
+
+#include <string.h>
+#include "idm.h"
+
+/*
+ * ---------------------------------------------------------------------------------
+ * Redability replacements
+ * ---------------------------------------------------------------------------------
+ */
+
+#define N (thisPb->n)
+#define Ns (thisPb->ns)
+#define Ng (thisPb->ng)
+#define ls (thisPb->LS)
+#define pm (thisPb->PM)
+
+#define mtlb_data (thisPb->mtlb_data)
+
+#define mtlb_JACfct (thisPb->JACfct)
+#define mtlb_PSETfct (thisPb->PSETfct)
+#define mtlb_PSOLfct (thisPb->PSOLfct)
+#define mtlb_GLOCfct (thisPb->GLOCfct)
+#define mtlb_GCOMfct (thisPb->GCOMfct)
+#define mtlb_Gfct (thisPb->Gfct)
+
+#define mon (thisPb->Mon)
+#define tstopSet (thisPb->TstopSet)
+
+#define mtlb_MONfct (thisPb->MONfct)
+#define mtlb_MONdata (thisPb->MONdata)
+
+
+/*
+ * ---------------------------------------------------------------------------------
+ * Option handling functions
+ * ---------------------------------------------------------------------------------
+ */
+
+int get_IntgrOptions(const mxArray *options, idmPbData thisPb, booleantype fwd,
+ int *maxord,
+ long int *mxsteps,
+ int *itol, realtype *reltol, double *Sabstol, double **Vabstol,
+ double *hin, double *hmax,
+ double *tstop,
+ booleantype *suppress,
+ booleantype *errmsg,
+ double **id, double **cnstr,
+ booleantype *res_s)
+{
+ mxArray *opt;
+ char *bufval;
+ int buflen, status, q;
+ long int i, m, n;
+ double *tmp;
+ char *fctName;
+ char *fwd_fctName = "IDAInit/IDAReInit";
+ char *bck_fctName = "IDAInitB/IDAReInitB";
+
+ if (fwd) fctName = fwd_fctName;
+ else fctName = bck_fctName;
+
+ /* Set default values */
+
+ *maxord = 5;
+
+ *mxsteps = 0;
+
+ *itol = IDA_SS;
+ *reltol = 1.0e-3;
+ *Sabstol = 1.0e-6;
+ *Vabstol = NULL;
+
+ *hin = 0.0;
+ *hmax = 0.0;
+
+ *res_s = FALSE;
+
+ *suppress = FALSE;
+
+ *id = NULL;
+ *cnstr = NULL;
+
+ Ng = 0;
+ tstopSet = FALSE;
+ mon = FALSE;
+
+ *errmsg = TRUE;
+
+ /* Return now if options was empty */
+
+ if (mxIsEmpty(options)) return(0);
+
+ /* User data */
+
+ opt = mxGetField(options,0,"UserData");
+ if ( !mxIsEmpty(opt) ) {
+ mxDestroyArray(mtlb_data);
+ mtlb_data = mxDuplicateArray(opt);
+ }
+
+ /* Tolerances */
+
+ opt = mxGetField(options,0,"RelTol");
+ if ( !mxIsEmpty(opt) ) {
+ *reltol = *mxGetPr(opt);
+ if (*reltol < 0.0 ) {
+ idmErrHandler(-999, "IDAS", fctName, "RelTol is negative.", NULL);
+ return(-1);
+ }
+ }
+
+ opt = mxGetField(options,0,"AbsTol");
+ if ( !mxIsEmpty(opt) ) {
+ m = mxGetM(opt);
+ n = mxGetN(opt);
+ if ( (n != 1) && (m != 1) ) {
+ idmErrHandler(-999, "IDAS", fctName, "AbsTol is not a scalar or a vector.", NULL);
+ return(-1);
+ }
+ if ( m > n ) n = m;
+ tmp = mxGetPr(opt);
+ if (n == 1) {
+ *itol = IDA_SS;
+ *Sabstol = *tmp;
+ if (*Sabstol < 0.0) {
+ idmErrHandler(-999, "IDAS", fctName, "AbsTol is negative.", NULL);
+ return(-1);
+ }
+ } else if (n == N) {
+ *itol = IDA_SV;
+ *Vabstol = (double *) malloc(N*sizeof(double));
+ for(i=0;i<N;i++) {
+ (*Vabstol)[i] = tmp[i];
+ if (tmp[i] < 0.0) {
+ idmErrHandler(-999, "IDAS", fctName, "AbsTol has a negative component.", NULL);
+ return(-1);
+ }
+ }
+ } else {
+ idmErrHandler(-999, "IDAS", fctName, "AbsTol does not contain N elements.", NULL);
+ return(-1);
+ }
+ }
+
+ /* Maximum number of steps */
+
+ opt = mxGetField(options,0,"MaxNumSteps");
+ if ( !mxIsEmpty(opt) ) {
+ *mxsteps = (int)*mxGetPr(opt);
+ if (*mxsteps < 0) {
+ idmErrHandler(-999, "IDAS", fctName, "MaxNumSteps is negative.", NULL);
+ return(-1);
+ }
+ }
+
+ /* Maximum order */
+
+ opt = mxGetField(options,0,"MaxOrder");
+ if ( !mxIsEmpty(opt) ) {
+ q = (int)*mxGetPr(opt);
+ if (q <= 0) {
+ idmErrHandler(-999, "IDAS", fctName, "MaxOrder must be positive.", NULL);
+ return(-1);
+ }
+ if (q > *maxord) {
+ idmErrHandler(-999, "IDAS", fctName, "MaxOrder is too large for BDF.", NULL);
+ return(-1);
+ }
+ *maxord = q;
+ }
+
+ /* Initial step size */
+
+ opt = mxGetField(options,0,"InitialStep");
+ if ( !mxIsEmpty(opt) ) {
+ *hin = *mxGetPr(opt);
+ }
+
+ /* Maximum step size */
+
+ opt = mxGetField(options,0,"MaxStep");
+ if ( !mxIsEmpty(opt) ) {
+ tmp = mxGetPr(opt);
+ if (*tmp < 0.0) {
+ idmErrHandler(-999, "IDAS", fctName, "MaxStep is negative.", NULL);
+ return(-1);
+ }
+ if ( mxIsInf(*tmp) )
+ *hmax = 0.0;
+ else
+ *hmax = *tmp;
+ }
+
+ /* ID vector */
+
+ opt = mxGetField(options,0,"VariableTypes");
+ if ( !mxIsEmpty(opt) ) {
+ m = mxGetM(opt);
+ n = mxGetN(opt);
+ if ( (n != 1) && (m != 1) ) {
+ idmErrHandler(-999, "IDAS", fctName, "VariableTypes is not a vector.", NULL);
+ return(-1);
+ }
+ if ( m > n ) n = m;
+ if (n == N) {
+ tmp = mxGetPr(opt);
+ *id = (double *)malloc(N*sizeof(double));
+ for(i=0;i<N;i++)
+ (*id)[i] = tmp[i];
+ } else {
+ idmErrHandler(-999, "IDAS", fctName, "VariableTypes has wrong dimension." , NULL);
+ return(-1);
+ }
+ }
+
+ /* Suppress algebraic variables? */
+
+ opt = mxGetField(options,0,"SuppressAlgVars");
+ if ( !mxIsEmpty(opt) ) {
+ buflen = mxGetM(opt) * mxGetN(opt) + 1;
+ bufval = mxCalloc(buflen, sizeof(char));
+ status = mxGetString(opt, bufval, buflen);
+ if(status != 0) {
+ idmErrHandler(-999, "IDAS", fctName, "Canot parse SuppressAlgVars.", NULL);
+ return(-1);
+ }
+ if(!strcmp(bufval,"on")) {
+ *suppress = TRUE;
+ } else if(!strcmp(bufval,"off")) {
+ *suppress = FALSE;
+ } else {
+ idmErrHandler(-999, "IDAS", fctName, "SuppressAlgVars has an illegal value.", NULL);
+ return(-1);
+ }
+ }
+
+ /* Monitor? */
+
+ opt = mxGetField(options,0,"MonitorFn");
+ if ( !mxIsEmpty(opt) ) {
+ mon = TRUE;
+ mxDestroyArray(mtlb_MONfct);
+ mtlb_MONfct = mxDuplicateArray(opt);
+ opt = mxGetField(options,0,"MonitorData");
+ if ( !mxIsEmpty(opt) ) {
+ mxDestroyArray(mtlb_MONdata);
+ mtlb_MONdata = mxDuplicateArray(opt);
+ }
+ }
+
+ /* The remaining options are interpreted either for
+ * forward problems only or backward problems only */
+
+ if (fwd) { /* FORWARD PROBLEM ONLY */
+
+
+ /* Disable error/warning messages? */
+ opt = mxGetField(options,0,"ErrorMessages");
+ if ( !mxIsEmpty(opt) ) {
+ if (!mxIsLogical(opt)) {
+ idmErrHandler(-999, "IDAS", fctName, "ErrorMessages is not a logical scalar.", NULL);
+ return(-1);
+ }
+ if (mxIsLogicalScalarTrue(opt)) *errmsg = TRUE;
+ else *errmsg = FALSE;
+ }
+
+
+ /* Stopping time */
+ opt = mxGetField(options,0,"StopTime");
+ if ( !mxIsEmpty(opt) ) {
+ *tstop = *mxGetPr(opt);
+ tstopSet = TRUE;
+ }
+
+ /* Number of root functions */
+ opt = mxGetField(options,0,"NumRoots");
+ if ( !mxIsEmpty(opt) ) {
+
+ Ng = (int)*mxGetPr(opt);
+ if (Ng < 0) {
+ idmErrHandler(-999, "IDAS", fctName, "NumRoots is negative.", NULL);
+ return(-1);
+ }
+ if (Ng > 0) {
+ /* Roots function */
+ opt = mxGetField(options,0,"RootsFn");
+ if ( !mxIsEmpty(opt) ) {
+ mxDestroyArray(mtlb_Gfct);
+ mtlb_Gfct = mxDuplicateArray(opt);
+ } else {
+ idmErrHandler(-999, "IDAS", fctName, "RootsFn required for NumRoots > 0", NULL);
+ return(-1);
+ }
+ }
+
+ }
+
+ /* Constraints vector */
+ opt = mxGetField(options,0,"ConstraintTypes");
+ if ( !mxIsEmpty(opt) ) {
+ m = mxGetM(opt);
+ n = mxGetN(opt);
+ if ( (n != 1) && (m != 1) ) {
+ idmErrHandler(-999, "IDAS", fctName, "ConstraintTypes is not a vector.", NULL);
+ return(-1);
+ }
+ if ( m > n ) n = m;
+ if (n == N) {
+ tmp = mxGetPr(opt);
+ *cnstr = (double *)malloc(N*sizeof(double));
+ for(i=0;i<N;i++)
+ (*cnstr)[i] = tmp[i];
+ } else {
+ idmErrHandler(-999, "IDAS", fctName, "ConstraintTypes has wrong dimension.", NULL);
+ return(-1);
+ }
+ }
+
+ } else { /* BACKWARD PROBLEM ONLY */
+
+ /* Dependency on forward sensitivities */
+
+ opt = mxGetField(options,0,"SensDependent");
+ if ( !mxIsEmpty(opt) ) {
+ if (!mxIsLogical(opt)) {
+ idmErrHandler(-999, "IDAS", fctName, "SensDependent is not a logical scalar.", NULL);
+ return(-1);
+ }
+ if (mxIsLogicalScalarTrue(opt)) *res_s = TRUE;
+ else *res_s = FALSE;
+ }
+
+ }
+
+ /* We made it here without problems */
+
+ return(0);
+}
+
+
+int get_LinSolvOptions(const mxArray *options, idmPbData thisPb, booleantype fwd,
+ long int *mupper, long int *mlower,
+ long int *mudq, long int *mldq, double *dqrely,
+ int *gstype, int *maxl)
+{
+ mxArray *opt;
+ char *bufval;
+ int buflen, status;
+ char *fctName;
+ char *fwd_fctName = "IDAInit/IDAReInit";
+ char *bck_fctName = "IDAInitB/IDAReInitB";
+
+ if (fwd) fctName = fwd_fctName;
+ else fctName = bck_fctName;
+
+ *mupper = 0;
+ *mlower = 0;
+
+ *mudq = 0;
+ *mldq = 0;
+ *dqrely = 0.0;
+
+ *gstype = MODIFIED_GS;
+ *maxl = 0;
+
+ /* Return now if options was empty */
+
+ if (mxIsEmpty(options)) return(0);
+
+ /* Linear solver type */
+
+ opt = mxGetField(options,0,"LinearSolver");
+ if ( !mxIsEmpty(opt) ) {
+ buflen = mxGetM(opt) * mxGetN(opt) + 1;
+ bufval = mxCalloc(buflen, sizeof(char));
+ status = mxGetString(opt, bufval, buflen);
+ if(status != 0) {
+ idmErrHandler(-999, "IDAS", fctName,
+ "Cannot parse LinearSolver.", NULL);
+ return(-1);
+ }
+ if(!strcmp(bufval,"Band")) ls = LS_BAND;
+ else if(!strcmp(bufval,"GMRES")) ls = LS_SPGMR;
+ else if(!strcmp(bufval,"BiCGStab")) ls = LS_SPBCG;
+ else if(!strcmp(bufval,"TFQMR")) ls = LS_SPTFQMR;
+ else if(!strcmp(bufval,"Dense")) ls = LS_DENSE;
+ else {
+ idmErrHandler(-999, "IDAS", fctName, "LinearSolver has an illegal value.", NULL);
+ return(-1);
+ }
+ }
+
+ /* Jacobian function */
+
+ opt = mxGetField(options,0,"JacobianFn");
+ if ( !mxIsEmpty(opt) ) {
+ mxDestroyArray(mtlb_JACfct);
+ mtlb_JACfct = mxDuplicateArray(opt);
+ }
+
+ /* Band linear solver */
+
+ if (ls==LS_BAND) {
+
+ opt = mxGetField(options,0,"UpperBwidth");
+ if ( !mxIsEmpty(opt) )
+ *mupper = (long int)*mxGetPr(opt);
+
+ opt = mxGetField(options,0,"LowerBwidth");
+ if ( !mxIsEmpty(opt) )
+ *mlower = (long int)*mxGetPr(opt);
+
+ }
+
+ /* SPGMR linear solver options */
+
+ if (ls==LS_SPGMR) {
+
+ /* Type of Gram-Schmidt procedure */
+
+ opt = mxGetField(options,0,"GramSchmidtType");
+ if ( !mxIsEmpty(opt) ) {
+ buflen = mxGetM(opt) * mxGetN(opt) + 1;
+ bufval = mxCalloc(buflen, sizeof(char));
+ status = mxGetString(opt, bufval, buflen);
+ if(status != 0) {
+ idmErrHandler(-999, "IDAS", fctName, "Cannot parse GramSchmidtType.", NULL);
+ return(-1);
+ }
+ if(!strcmp(bufval,"Classical")) *gstype = CLASSICAL_GS;
+ else if(!strcmp(bufval,"Modified")) *gstype = MODIFIED_GS;
+ else {
+ idmErrHandler(-999, "IDAS", fctName, "GramSchmidtType has an illegal value.", NULL);
+ return(-1);
+ }
+ }
+
+ }
+
+ /* SPILS linear solver options */
+
+ if ( (ls==LS_SPGMR) || (ls==LS_SPBCG) || (ls==LS_SPTFQMR) ) {
+
+ /* Max. dimension of Krylov subspace */
+
+ opt = mxGetField(options,0,"KrylovMaxDim");
+ if ( !mxIsEmpty(opt) ) {
+ *maxl = (int)*mxGetPr(opt);
+ if (*maxl < 0) {
+ idmErrHandler(-999, "IDAS", fctName, "KrylovMaxDim is negative.", NULL);
+ return(-1);
+ }
+ }
+
+ /* User defined precoditioning */
+
+ opt = mxGetField(options,0,"PrecSetupFn");
+ if ( !mxIsEmpty(opt) ) {
+ mxDestroyArray(mtlb_PSETfct);
+ mtlb_PSETfct = mxDuplicateArray(opt);
+ }
+
+ opt = mxGetField(options,0,"PrecSolveFn");
+ if ( !mxIsEmpty(opt) ) {
+ mxDestroyArray(mtlb_PSOLfct);
+ mtlb_PSOLfct = mxDuplicateArray(opt);
+ }
+
+ /* Preconditioner module */
+
+ opt = mxGetField(options,0,"PrecModule");
+ if ( !mxIsEmpty(opt) ) {
+ buflen = mxGetM(opt) * mxGetN(opt) + 1;
+ bufval = mxCalloc(buflen, sizeof(char));
+ status = mxGetString(opt, bufval, buflen);
+ if(status != 0) {
+ idmErrHandler(-999, "IDAS", fctName, "Cannot parse PrecModule.", NULL);
+ return(-1);
+ }
+ if(!strcmp(bufval,"BBDPre")) pm = PM_BBDPRE;
+ else if(!strcmp(bufval,"UserDefined")) pm = PM_NONE;
+ else {
+ idmErrHandler(-999, "IDAS", fctName, "PrecModule has an illegal value.", NULL);
+ return(-1);
+ }
+ }
+
+ if (pm == PM_BBDPRE) {
+
+ opt = mxGetField(options,0,"UpperBwidth");
+ if ( !mxIsEmpty(opt) )
+ *mupper = (long int)*mxGetPr(opt);
+
+ opt = mxGetField(options,0,"LowerBwidth");
+ if ( !mxIsEmpty(opt) )
+ *mlower = (long int)*mxGetPr(opt);
+
+ opt = mxGetField(options,0,"UpperBwidthDQ");
+ if ( !mxIsEmpty(opt) )
+ *mudq = (long int)*mxGetPr(opt);
+
+ opt = mxGetField(options,0,"LowerBwidthDQ");
+ if ( !mxIsEmpty(opt) )
+ *mldq = (long int)*mxGetPr(opt);
+
+ opt = mxGetField(options,0,"GlocalFn");
+ if ( !mxIsEmpty(opt) ) {
+ mxDestroyArray(mtlb_GLOCfct);
+ mtlb_GLOCfct = mxDuplicateArray(opt);
+ } else {
+ idmErrHandler(-999, "IDAS", fctName, "GlocalFn required for BBD preconditioner.", NULL);
+ return(-1);
+ }
+
+ opt = mxGetField(options,0,"GcommFn");
+ if ( !mxIsEmpty(opt) ) {
+ mxDestroyArray(mtlb_GCOMfct);
+ mtlb_GCOMfct = mxDuplicateArray(opt);
+ }
+
+ }
+
+ }
+
+
+ /* We made it here without problems */
+
+ return(0);
+
+}
+
+
+int get_QuadOptions(const mxArray *options, idmPbData thisPb, booleantype fwd,
+ long int Nq, booleantype *rhs_s,
+ booleantype *errconQ,
+ int *itolQ, double *reltolQ, double *SabstolQ, double **VabstolQ)
+{
+ mxArray *opt;
+ long int i, m, n;
+ double *tmp;
+ char *fctName;
+ char *fwd_fctName = "IDAQuadInit/IDAQuadReInit";
+ char *bck_fctName = "IDAQuadInitB/IDAQuadReInitB";
+
+ if (fwd) fctName = fwd_fctName;
+ else fctName = bck_fctName;
+
+ *errconQ = FALSE;
+ *itolQ = IDA_SS;
+ *reltolQ = 1.0e-4;
+ *SabstolQ = 1.0e-6;
+ *VabstolQ = NULL;
+
+ *rhs_s = FALSE;
+
+ /* Return now if options was empty */
+
+ if (mxIsEmpty(options)) return(0);
+
+ /* For backward problems only, check dependency on forward sensitivities */
+
+ if (!fwd) {
+
+ opt = mxGetField(options,0,"SensDependent");
+ if ( !mxIsEmpty(opt) ) {
+ if (!mxIsLogical(opt)) {
+ idmErrHandler(-999, "IDAS", fctName, "SensDependent is not a logical scalar.", NULL);
+ return(-1);
+ }
+ if (mxIsLogicalScalarTrue(opt)) *rhs_s = TRUE;
+ else *rhs_s = FALSE;
+ }
+
+ }
+
+ /* Quadrature error control and tolerances */
+
+ opt = mxGetField(options,0,"ErrControl");
+ if ( mxIsEmpty(opt) ) return(0);
+
+ if (!mxIsLogical(opt)) {
+ idmErrHandler(-999, "IDAS", fctName, "ErrControl is not a logical scalar.", NULL);
+ return(-1);
+ }
+
+ if (!mxIsLogicalScalarTrue(opt)) return(0);
+
+ *errconQ = TRUE;
+
+ opt = mxGetField(options,0,"RelTol");
+ if ( !mxIsEmpty(opt) ) {
+ *reltolQ = *mxGetPr(opt);
+ if (*reltolQ < 0.0) {
+ idmErrHandler(-999, "IDAS", fctName, "RelTol is negative.", NULL);
+ return(-1);
+ }
+ }
+
+ opt = mxGetField(options,0,"AbsTol");
+ if ( !mxIsEmpty(opt) ) {
+
+ m = mxGetN(opt);
+ n = mxGetM(opt);
+ if ( (n != 1) && (m != 1) ) {
+ idmErrHandler(-999, "IDAS", fctName, "AbsTol is not a scalar or a vector.", NULL);
+ return(-1);
+ }
+ if ( m > n ) n = m;
+ tmp = mxGetPr(opt);
+
+ if (n == 1) {
+ *itolQ = IDA_SS;
+ *SabstolQ = *tmp;
+ if (*SabstolQ < 0.0) {
+ idmErrHandler(-999, "IDAS", fctName, "AbsTol is negative.", NULL);
+ return(-1);
+ }
+ } else if (n == Nq) {
+ *itolQ = IDA_SV;
+ *VabstolQ = (double *)malloc(Nq*sizeof(double));
+ for(i=0;i<Nq;i++) {
+ (*VabstolQ)[i] = tmp[i];
+ if (tmp[i] < 0.0) {
+ idmErrHandler(-999, "IDAS", fctName, "AbsTol has a negative component.", NULL);
+ return(-1);
+ }
+ }
+ } else {
+ idmErrHandler(-999, "IDAS", fctName, "AbsTol does not contain Nq elements.", NULL);
+ return(-1);
+ }
+
+ }
+
+ /* We made it here without problems */
+
+ return(0);
+}
+
+int get_FSAOptions(const mxArray *options, idmPbData thisPb,
+ int *ism,
+ char **pfield_name, int **plist, double **pbar,
+ int *dqtype, double *rho,
+ booleantype *errconS, int *itolS, double *reltolS,
+ double **SabstolS, double **VabstolS)
+{
+ mxArray *opt;
+ char *bufval;
+ int i, is, m, n, buflen, status, this_plist;
+ double *tmp;
+
+ /* Set default values */
+
+ *ism = IDA_STAGGERED;
+
+ *dqtype = IDA_CENTERED;
+ *rho = 0.0;
+
+ *errconS = TRUE;
+
+ *itolS = IDA_EE;
+ *SabstolS = NULL;
+ *VabstolS = NULL;
+
+ *pfield_name = NULL;
+ *plist = NULL;
+ *pbar = NULL;
+
+ /* Return now if options was empty */
+
+ if (mxIsEmpty(options)) return(0);
+
+ /* Sensitivity method */
+
+ opt = mxGetField(options,0,"method");
+ if ( !mxIsEmpty(opt) ) {
+
+ buflen = mxGetM(opt) * mxGetN(opt) + 1;
+ bufval = mxCalloc(buflen, sizeof(char));
+ status = mxGetString(opt, bufval, buflen);
+ if(status != 0) {
+ idmErrHandler(-999, "IDAS", "IDASensInit/IDASensReInit", "Could not parse method.", NULL);
+ return(-1);
+ }
+ if(!strcmp(bufval,"Simultaneous")) *ism = IDA_SIMULTANEOUS;
+ else if(!strcmp(bufval,"Staggered")) *ism = IDA_STAGGERED;
+ else {
+ idmErrHandler(-999, "IDAS", "IDASensInit/IDASensReInit", "Method has an illegal value.", NULL);
+ return(-1);
+ }
+
+ }
+
+ /* Field name in data structure for params. */
+
+ opt = mxGetField(options,0,"ParamField");
+ if ( !mxIsEmpty(opt) ) {
+
+ buflen = mxGetM(opt) * mxGetN(opt) + 1;
+ bufval = mxCalloc(buflen, sizeof(char));
+ status = mxGetString(opt, bufval, buflen);
+ if(status != 0) {
+ idmErrHandler(-999, "IDAS", "IDASensInit/IDASensReInit", "Could not parse ParamField.", NULL);
+ return(-1);
+ }
+ *pfield_name = mxCalloc(buflen, sizeof(char));
+ strcpy((*pfield_name), bufval);
+
+ }
+
+ /* PLIST */
+
+ opt = mxGetField(options,0,"ParamList");
+ if ( !mxIsEmpty(opt) ) {
+
+ tmp = mxGetPr(opt);
+ m = mxGetM(opt);
+ n = mxGetN(opt);
+ if ( (n != 1) && (m != 1) ) {
+ idmErrHandler(-999, "IDAS", "IDASensInit/IDASensReInit", "ParamList is not a vector.", NULL);
+ return(-1);
+ }
+ if (m > n) n = m;
+ if ( n != Ns) {
+ idmErrHandler(-999, "IDAS", "IDASensInit/IDASensReInit", "ParamList does not contain Ns elements.", NULL);
+ return(-1);
+ }
+ *plist = (int *) malloc(Ns*sizeof(int));
+ for (is=0;is<Ns;is++) {
+ this_plist = (int) tmp[is];
+ if (this_plist <= 0) {
+ idmErrHandler(-999, "IDAS", "IDASensInit/IDASensReInit", "ParamList must contain only positive integers.", NULL);
+ return(-1);
+ }
+ (*plist)[is] = this_plist - 1;
+ }
+
+ }
+
+ /* PBAR */
+
+ opt = mxGetField(options,0,"ParamScales");
+ if ( !mxIsEmpty(opt) ) {
+
+ m = mxGetM(opt);
+ n = mxGetN(opt);
+ if ( (n != 1) && (m != 1) ) {
+ idmErrHandler(-999, "IDAS", "IDASensInit/IDASensReInit", "ParamScales is not a vector.", NULL);
+ return(-1);
+ }
+ if ( m > n ) n = m;
+ if ( n != Ns) {
+ idmErrHandler(-999, "IDAS", "IDASensInit/IDASensReInit", "ParamScales does not contain Ns elements.", NULL);
+ return(-1);
+ }
+ tmp = mxGetPr(opt);
+ *pbar = (double *) malloc(Ns*sizeof(double));
+ for(i=0;i<Ns;i++)
+ (*pbar)[i] = tmp[i];
+
+ }
+
+ /* DQ type */
+
+ opt = mxGetField(options,0,"DQtype");
+ if ( !mxIsEmpty(opt) ) {
+
+ buflen = mxGetM(opt) * mxGetN(opt) + 1;
+ bufval = mxCalloc(buflen, sizeof(char));
+ status = mxGetString(opt, bufval, buflen);
+ if(status != 0) {
+ idmErrHandler(-999, "IDAS", "IDASensInit/IDASensReInit", "Cannot parse DQtype.", NULL);
+ return(-1);
+ }
+
+ if(!strcmp(bufval,"Centered")) *dqtype = IDA_CENTERED;
+ else if(!strcmp(bufval,"Forward")) *dqtype = IDA_FORWARD;
+ else {
+ idmErrHandler(-999, "IDAS", "IDASensInit/IDASensReInit", "DQtype has an illegal value.", NULL);
+ return(-1);
+ }
+
+ }
+
+ /* DQ parameter */
+
+ opt = mxGetField(options,0,"DQparam");
+ if ( !mxIsEmpty(opt) )
+ *rho = *mxGetPr(opt);
+
+ /* Error control */
+
+ opt = mxGetField(options,0,"ErrControl");
+ if ( !mxIsEmpty(opt) ) {
+ if (!mxIsLogical(opt)) {
+ idmErrHandler(-999, "IDAS", "IDASensInit/IDASensReInit", "ErrControl is not a logical scalar.", NULL);
+ return(-1);
+ }
+ if (mxIsLogicalScalarTrue(opt)) *errconS = TRUE;
+ else *errconS = FALSE;
+ }
+
+ /* Tolerances */
+
+ opt = mxGetField(options,0,"RelTol");
+ if ( !mxIsEmpty(opt) ) {
+
+ *reltolS = *mxGetPr(opt);
+ if (*reltolS < 0.0) {
+ idmErrHandler(-999, "IDAS", "IDASensInit/IDASensReInit", "RelTol is negative.", NULL);
+ return(-1);
+ }
+
+ opt = mxGetField(options,0,"AbsTol");
+ if ( !mxIsEmpty(opt) ) {
+
+ m = mxGetM(opt);
+ n = mxGetN(opt);
+ if ( (m == 1) && (n == Ns) ) {
+ *itolS = IDA_SS;
+ tmp = mxGetPr(opt);
+ *SabstolS = (double *) malloc(Ns*sizeof(double));
+ for (is=0; is<Ns; is++) {
+ (*SabstolS)[is] = tmp[is];
+ if ( tmp[is] < 0.0 ) {
+ idmErrHandler(-999, "IDAS", "IDASensInit/IDASensReInit", "AbsTol has a negative component.", NULL);
+ return(-1);
+ }
+ }
+ } else if ( (m == N) && (n == Ns) ) {
+ *itolS = IDA_SV;
+ tmp = mxGetPr(opt);
+ *VabstolS = (double *)malloc(Ns*N*sizeof(double));
+ for (i=0; i<Ns*N; i++) {
+ (*VabstolS)[i] = tmp[i];
+ if ( tmp[i] < 0.0 ) {
+ idmErrHandler(-999, "IDAS", "IDASensInit/IDASensReInit", "AbsTol has a negative component.", NULL);
+ return(-1);
+ }
+ }
+ } else {
+ idmErrHandler(-999, "IDAS", "IDASensInit/IDASensReInit", "AbsTol must be either a 1xNs vector or an NxNs matrix.", NULL);
+ return(-1);
+ }
+
+ } else {
+
+ *itolS = IDA_EE;
+
+ }
+
+ }
+
+ /* We made it here without problems */
+
+ return(0);
+
+}
+
diff --git a/sundialsTB/idas/idm/src/idmWrap.c b/sundialsTB/idas/idm/src/idmWrap.c
new file mode 100644
index 0000000..3c1dc8b
--- /dev/null
+++ b/sundialsTB/idas/idm/src/idmWrap.c
@@ -0,0 +1,1378 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.10 $
+ * $Date: 2012/03/07 21:49:18 $
+ * -----------------------------------------------------------------
+ * Programmer: 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 sundials-x.y.z/src/ida/LICENSE.
+ * -----------------------------------------------------------------
+ * IDA wrapper functions.
+ * -----------------------------------------------------------------
+ */
+
+#include "idm.h"
+#include "nvm.h"
+
+static void UpdateUserData(mxArray *new_mtlb_data, idmPbData pb);
+static void UpdateMonitorData(mxArray *new_mtlb_data, idmPbData pb);
+
+/*
+ * ---------------------------------------------------------------------------------
+ * Redability replacements
+ * ---------------------------------------------------------------------------------
+ */
+
+#define fsa (fwdPb->Fsa)
+#define quadr (fwdPb->Quadr)
+#define N (fwdPb->n)
+#define Nq (fwdPb->nq)
+#define Ng (fwdPb->ng)
+#define Ns (fwdPb->ns)
+
+#define quadrB (bckPb->Quadr)
+#define NB (bckPb->n)
+#define NqB (bckPb->nq)
+
+/*
+ * ---------------------------------------------------------------------------------
+ * Wrapper functions
+ * ---------------------------------------------------------------------------------
+ */
+
+int mxW_IDARes(realtype tt, N_Vector yy, N_Vector yp,
+ N_Vector rr, void *user_data)
+{
+ idmPbData fwdPb;
+ mxArray *mx_in[5], *mx_out[3];
+ int ret;
+
+ /* Extract global interface data from user-data */
+ fwdPb = (idmPbData) user_data;
+
+ /* Inputs to the Matlab function */
+ mx_in[0] = mxCreateDoubleScalar(tt); /* current t */
+ mx_in[1] = mxCreateDoubleMatrix(N,1,mxREAL); /* current yy */
+ mx_in[2] = mxCreateDoubleMatrix(N,1,mxREAL); /* current yp */
+ mx_in[3] = fwdPb->RESfct; /* matlab function handle */
+ mx_in[4] = fwdPb->mtlb_data; /* matlab user data */
+
+ /* Call matlab wrapper */
+ GetData(yy, mxGetPr(mx_in[1]), N);
+ GetData(yp, mxGetPr(mx_in[2]), N);
+
+ mexCallMATLAB(3,mx_out,5,mx_in,"idm_res");
+
+ PutData(rr, mxGetPr(mx_out[0]), N);
+ ret = (int)*mxGetPr(mx_out[1]);
+
+ if (!mxIsEmpty(mx_out[2])) {
+ UpdateUserData(mx_out[2], fwdPb);
+ }
+
+ /* Free temporary space */
+ mxDestroyArray(mx_in[0]);
+ mxDestroyArray(mx_in[1]);
+ mxDestroyArray(mx_in[2]);
+ mxDestroyArray(mx_out[0]);
+ mxDestroyArray(mx_out[1]);
+ mxDestroyArray(mx_out[2]);
+
+ return(ret);
+}
+
+int mxW_IDAQuadFct(realtype tres, N_Vector yy, N_Vector yp, N_Vector ypQ,
+ void *user_data)
+{
+ idmPbData fwdPb;
+ mxArray *mx_in[5], *mx_out[3];
+ int ret;
+
+ /* Extract global interface data from user-data */
+ fwdPb = (idmPbData) user_data;
+
+ /* Inputs to the Matlab function */
+ mx_in[0] = mxCreateDoubleScalar(tres); /* current t */
+ mx_in[1] = mxCreateDoubleMatrix(N,1,mxREAL); /* current yy */
+ mx_in[2] = mxCreateDoubleMatrix(N,1,mxREAL); /* current yp */
+ mx_in[3] = fwdPb->QUADfct; /* matlab function handle */
+ mx_in[4] = fwdPb->mtlb_data; /* matlab user data */
+
+ /* Call matlab wrapper */
+ GetData(yy, mxGetPr(mx_in[1]), N);
+ GetData(yp, mxGetPr(mx_in[2]), N);
+
+ mexCallMATLAB(3,mx_out,5,mx_in,"idm_rhsQ");
+
+ PutData(ypQ, mxGetPr(mx_out[0]), Nq);
+ ret = (int)*mxGetPr(mx_out[1]);
+
+ if (!mxIsEmpty(mx_out[2])) {
+ UpdateUserData(mx_out[2], fwdPb);
+ }
+
+ /* Free temporary space */
+ mxDestroyArray(mx_in[0]);
+ mxDestroyArray(mx_in[1]);
+ mxDestroyArray(mx_in[2]);
+ mxDestroyArray(mx_out[0]);
+ mxDestroyArray(mx_out[1]);
+ mxDestroyArray(mx_out[2]);
+
+ return(ret);
+}
+
+int mxW_IDAGfct(realtype t, N_Vector yy, N_Vector yp,
+ realtype *gout, void *user_data)
+{
+ idmPbData fwdPb;
+ double *gdata;
+ int i, ret;
+ mxArray *mx_in[5], *mx_out[3];
+
+ /* Extract global interface data from user-data */
+ fwdPb = (idmPbData) user_data;
+
+ /* Inputs to the Matlab function */
+ mx_in[0] = mxCreateDoubleScalar(t); /* current t */
+ mx_in[1] = mxCreateDoubleMatrix(N,1,mxREAL); /* current yy */
+ mx_in[2] = mxCreateDoubleMatrix(N,1,mxREAL); /* current yp */
+ mx_in[3] = fwdPb->Gfct; /* matlab function handle */
+ mx_in[4] = fwdPb->mtlb_data; /* matlab user data */
+
+ /* Call matlab wrapper */
+ GetData(yy, mxGetPr(mx_in[1]), N);
+ GetData(yp, mxGetPr(mx_in[2]), N);
+
+ mexCallMATLAB(3,mx_out,5,mx_in,"idm_root");
+
+ gdata = mxGetPr(mx_out[0]);
+ for (i=0;i<Ng;i++) gout[i] = gdata[i];
+
+ ret = (int)*mxGetPr(mx_out[1]);
+
+ if (!mxIsEmpty(mx_out[2])) {
+ UpdateUserData(mx_out[2], fwdPb);
+ }
+
+ /* Free temporary space */
+ mxDestroyArray(mx_in[0]);
+ mxDestroyArray(mx_in[1]);
+ mxDestroyArray(mx_in[2]);
+ mxDestroyArray(mx_out[0]);
+ mxDestroyArray(mx_out[1]);
+ mxDestroyArray(mx_out[2]);
+
+ return(ret);
+}
+
+int mxW_IDADenseJac(long int Neq, realtype tt, realtype c_j,
+ N_Vector yy, N_Vector yp, N_Vector rr,
+ DlsMat Jac, void *user_data,
+ N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
+{
+ idmPbData fwdPb;
+ double *J_data;
+ int i, ret;
+ mxArray *mx_in[7], *mx_out[3];
+
+ /* Extract global interface data from user-data */
+ fwdPb = (idmPbData) user_data;
+
+ /* Inputs to the Matlab function */
+ mx_in[0] = mxCreateDoubleScalar(tt); /* current t */
+ mx_in[1] = mxCreateDoubleMatrix(N,1,mxREAL); /* current yy */
+ mx_in[2] = mxCreateDoubleMatrix(N,1,mxREAL); /* current yp */
+ mx_in[3] = mxCreateDoubleMatrix(N,1,mxREAL); /* current rr */
+ mx_in[4] = mxCreateDoubleScalar(c_j); /* current c_j */
+ mx_in[5] = fwdPb->JACfct; /* matlab function handle */
+ mx_in[6] = fwdPb->mtlb_data; /* matlab user data */
+
+ /* Call matlab wrapper */
+ GetData(yy, mxGetPr(mx_in[1]), N);
+ GetData(yp, mxGetPr(mx_in[2]), N);
+ GetData(rr, mxGetPr(mx_in[3]), N);
+
+ mexCallMATLAB(3,mx_out,7,mx_in,"idm_djac");
+
+ /* Extract data */
+ J_data = mxGetPr(mx_out[0]);
+ for (i=0;i<N;i++)
+ memcpy(DENSE_COL(Jac,i), J_data + i*N, N*sizeof(double));
+
+ ret = (int)*mxGetPr(mx_out[1]);
+
+ if (!mxIsEmpty(mx_out[2])) {
+ UpdateUserData(mx_out[2], fwdPb);
+ }
+
+ /* Free temporary space */
+ mxDestroyArray(mx_in[0]);
+ mxDestroyArray(mx_in[1]);
+ mxDestroyArray(mx_in[2]);
+ mxDestroyArray(mx_in[3]);
+ mxDestroyArray(mx_in[4]);
+ mxDestroyArray(mx_out[0]);
+ mxDestroyArray(mx_out[1]);
+ mxDestroyArray(mx_out[2]);
+
+ return(ret);
+}
+
+int mxW_IDABandJac(long int Neq, long int mupper, long int mlower,
+ realtype tt, realtype c_j,
+ N_Vector yy, N_Vector yp, N_Vector rr,
+ DlsMat Jac, void *user_data,
+ N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
+{
+ idmPbData fwdPb;
+ double *J_data;
+ long int eband, i;
+ int ret;
+ mxArray *mx_in[7], *mx_out[3];
+
+ /* Extract global interface data from user-data */
+ fwdPb = (idmPbData) user_data;
+
+ /* Inputs to the Matlab function */
+ mx_in[0] = mxCreateDoubleScalar(tt); /* current t */
+ mx_in[1] = mxCreateDoubleMatrix(N,1,mxREAL); /* current yy */
+ mx_in[2] = mxCreateDoubleMatrix(N,1,mxREAL); /* current yp */
+ mx_in[3] = mxCreateDoubleMatrix(N,1,mxREAL); /* current rr */
+ mx_in[4] = mxCreateDoubleScalar(c_j); /* current c_j */
+ mx_in[5] = fwdPb->JACfct; /* matlab function handle */
+ mx_in[6] = fwdPb->mtlb_data; /* matlab user data */
+
+ /* Call matlab wrapper */
+ GetData(yy, mxGetPr(mx_in[1]), N);
+ GetData(yp, mxGetPr(mx_in[2]), N);
+ GetData(rr, mxGetPr(mx_in[3]), N);
+
+ mexCallMATLAB(3,mx_out,7,mx_in,"idm_bjac");
+
+ /* Extract data */
+ eband = mupper + mlower + 1;
+ J_data = mxGetPr(mx_out[0]);
+ for (i=0;i<N;i++)
+ memcpy(BAND_COL(Jac,i) - mupper, J_data + i*eband, eband*sizeof(double));
+
+ ret = (int)*mxGetPr(mx_out[1]);
+
+ if (!mxIsEmpty(mx_out[2])) {
+ UpdateUserData(mx_out[2], fwdPb);
+ }
+
+ /* Free temporary space */
+ mxDestroyArray(mx_in[0]);
+ mxDestroyArray(mx_in[1]);
+ mxDestroyArray(mx_in[2]);
+ mxDestroyArray(mx_in[3]);
+ mxDestroyArray(mx_in[4]);
+ mxDestroyArray(mx_out[0]);
+ mxDestroyArray(mx_out[1]);
+ mxDestroyArray(mx_out[2]);
+
+ return(ret);
+}
+
+int mxW_IDASpilsJac(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)
+{
+ idmPbData fwdPb;
+ mxArray *mx_in[8], *mx_out[3];
+ int ret;
+
+ /* Extract global interface data from user-data */
+ fwdPb = (idmPbData) user_data;
+
+ /* Inputs to the Matlab function */
+ mx_in[0] = mxCreateDoubleScalar(tt); /* current t */
+ mx_in[1] = mxCreateDoubleMatrix(N,1,mxREAL); /* current yy */
+ mx_in[2] = mxCreateDoubleMatrix(N,1,mxREAL); /* current yp */
+ mx_in[3] = mxCreateDoubleMatrix(N,1,mxREAL); /* current rr */
+ mx_in[4] = mxCreateDoubleMatrix(N,1,mxREAL); /* vector v */
+ mx_in[5] = mxCreateDoubleScalar(c_j); /* current c_j */
+ mx_in[6] = fwdPb->JACfct; /* matlab function handle */
+ mx_in[7] = fwdPb->mtlb_data; /* matlab user data */
+
+ /* Call matlab wrapper */
+ GetData(yy, mxGetPr(mx_in[1]), N);
+ GetData(yp, mxGetPr(mx_in[2]), N);
+ GetData(rr, mxGetPr(mx_in[3]), N);
+ GetData(v, mxGetPr(mx_in[4]), N);
+
+ mexCallMATLAB(3,mx_out,8,mx_in,"idm_jtv");
+
+ PutData(Jv, mxGetPr(mx_out[0]), N);
+ ret = (int)*mxGetPr(mx_out[1]);
+
+ if (!mxIsEmpty(mx_out[2])) {
+ UpdateUserData(mx_out[2], fwdPb);
+ }
+
+ /* Free temporary space */
+ mxDestroyArray(mx_in[0]);
+ mxDestroyArray(mx_in[1]);
+ mxDestroyArray(mx_in[2]);
+ mxDestroyArray(mx_in[3]);
+ mxDestroyArray(mx_in[4]);
+ mxDestroyArray(mx_in[5]);
+ mxDestroyArray(mx_out[0]);
+ mxDestroyArray(mx_out[1]);
+ mxDestroyArray(mx_out[2]);
+
+ return(ret);
+}
+
+int mxW_IDASpilsPset(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)
+{
+ idmPbData fwdPb;
+ mxArray *mx_in[7], *mx_out[2];
+ int ret;
+
+ /* Extract global interface data from user-data */
+ fwdPb = (idmPbData) user_data;
+
+ /* Inputs to the Matlab function */
+ mx_in[0] = mxCreateDoubleScalar(tt); /* current t */
+ mx_in[1] = mxCreateDoubleMatrix(N,1,mxREAL); /* current yy */
+ mx_in[2] = mxCreateDoubleMatrix(N,1,mxREAL); /* current yp */
+ mx_in[3] = mxCreateDoubleMatrix(N,1,mxREAL); /* current rr */
+ mx_in[4] = mxCreateLogicalScalar(c_j); /* current c_j */
+ mx_in[5] = fwdPb->PSETfct; /* matlab function handle */
+ mx_in[6] = fwdPb->mtlb_data; /* matlab user data */
+
+ /* Call matlab wrapper */
+ GetData(yy, mxGetPr(mx_in[1]), N);
+ GetData(yp, mxGetPr(mx_in[2]), N);
+ GetData(rr, mxGetPr(mx_in[3]), N);
+
+ mexCallMATLAB(2,mx_out,7,mx_in,"idm_pset");
+
+ ret = (int)*mxGetPr(mx_out[0]);
+
+ if (!mxIsEmpty(mx_out[1])) {
+ UpdateUserData(mx_out[1], fwdPb);
+ }
+
+ /* Free temporary space */
+ mxDestroyArray(mx_in[0]);
+ mxDestroyArray(mx_in[1]);
+ mxDestroyArray(mx_in[2]);
+ mxDestroyArray(mx_in[3]);
+ mxDestroyArray(mx_in[4]);
+ mxDestroyArray(mx_out[0]);
+ mxDestroyArray(mx_out[1]);
+
+ return(ret);
+}
+
+int mxW_IDASpilsPsol(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)
+{
+ idmPbData fwdPb;
+ mxArray *mx_in[8], *mx_out[3];
+ int ret;
+
+ /* Extract global interface data from user-data */
+ fwdPb = (idmPbData) user_data;
+
+ /* Inputs to the Matlab function */
+ mx_in[0] = mxCreateDoubleScalar(tt); /* current t */
+ mx_in[1] = mxCreateDoubleMatrix(N,1,mxREAL); /* current yy */
+ mx_in[2] = mxCreateDoubleMatrix(N,1,mxREAL); /* current yp */
+ mx_in[3] = mxCreateDoubleMatrix(N,1,mxREAL); /* current rr */
+ mx_in[4] = mxCreateDoubleMatrix(N,1,mxREAL); /* right hand side r */
+ mx_in[5] = mxCreateDoubleScalar(c_j); /* current c_j */
+ mx_in[6] = fwdPb->PSOLfct; /* matlab function handle */
+ mx_in[7] = fwdPb->mtlb_data; /* matlab user data */
+
+ /* Call matlab wrapper */
+ GetData(yy, mxGetPr(mx_in[1]), N);
+ GetData(yp, mxGetPr(mx_in[2]), N);
+ GetData(rr, mxGetPr(mx_in[3]), N);
+ GetData(rvec, mxGetPr(mx_in[4]), N);
+
+ mexCallMATLAB(3,mx_out,8,mx_in,"idm_psol");
+
+ PutData(zvec, mxGetPr(mx_out[0]), N);
+ ret = (int)*mxGetPr(mx_out[1]);
+
+ if (!mxIsEmpty(mx_out[2])) {
+ UpdateUserData(mx_out[2], fwdPb);
+ }
+
+ /* Free temporary space */
+ mxDestroyArray(mx_in[0]);
+ mxDestroyArray(mx_in[1]);
+ mxDestroyArray(mx_in[2]);
+ mxDestroyArray(mx_in[3]);
+ mxDestroyArray(mx_in[4]);
+ mxDestroyArray(mx_in[5]);
+ mxDestroyArray(mx_out[0]);
+ mxDestroyArray(mx_out[1]);
+ mxDestroyArray(mx_out[2]);
+
+ return(ret);
+}
+
+/*
+ * ----------------------------
+ * BBD PRECONDITONER FUNCTIONS
+ * ----------------------------
+ */
+
+int mxW_IDABBDgloc(long int Nlocal, realtype tt,
+ N_Vector yy, N_Vector yp, N_Vector gval,
+ void *user_data)
+{
+ idmPbData fwdPb;
+ mxArray *mx_in[5], *mx_out[3];
+ int ret;
+
+ /* Extract global interface data from user-data */
+ fwdPb = (idmPbData) user_data;
+
+ /* Inputs to the Matlab function */
+ mx_in[0] = mxCreateDoubleScalar(tt); /* current t */
+ mx_in[1] = mxCreateDoubleMatrix(N,1,mxREAL); /* current yy */
+ mx_in[2] = mxCreateDoubleMatrix(N,1,mxREAL); /* current yp */
+ mx_in[3] = fwdPb->GLOCfct; /* matlab function handle */
+ mx_in[4] = fwdPb->mtlb_data; /* matlab user data */
+
+ /* Call matlab wrapper */
+ GetData(yy, mxGetPr(mx_in[1]), N);
+ GetData(yp, mxGetPr(mx_in[2]), N);
+
+ mexCallMATLAB(3,mx_out,5,mx_in,"idm_gloc");
+
+ PutData(gval, mxGetPr(mx_out[0]), N);
+ ret = (int)*mxGetPr(mx_out[1]);
+
+ if (!mxIsEmpty(mx_out[2])) {
+ UpdateUserData(mx_out[2], fwdPb);
+ }
+
+ /* Free temporary space */
+ mxDestroyArray(mx_in[0]);
+ mxDestroyArray(mx_in[1]);
+ mxDestroyArray(mx_in[2]);
+ mxDestroyArray(mx_out[0]);
+ mxDestroyArray(mx_out[1]);
+ mxDestroyArray(mx_out[2]);
+
+ return(ret);
+}
+
+int mxW_IDABBDgcom(long int Nlocal, realtype tt,
+ N_Vector yy, N_Vector yp,
+ void *user_data)
+{
+ idmPbData fwdPb;
+ mxArray *mx_in[5], *mx_out[2];
+ int ret;
+
+ /* Extract global interface data from user-data */
+ fwdPb = (idmPbData) user_data;
+
+ /* Inputs to the Matlab function */
+ mx_in[0] = mxCreateDoubleScalar(tt); /* current t */
+ mx_in[1] = mxCreateDoubleMatrix(N,1,mxREAL); /* current yy */
+ mx_in[2] = mxCreateDoubleMatrix(N,1,mxREAL); /* current yp */
+ mx_in[3] = fwdPb->GCOMfct; /* matlab function handle */
+ mx_in[4] = fwdPb->mtlb_data; /* matlab user data */
+
+ /* Call matlab wrapper */
+ GetData(yy, mxGetPr(mx_in[1]), N);
+ GetData(yp, mxGetPr(mx_in[2]), N);
+
+ mexCallMATLAB(2,mx_out,5,mx_in,"idm_gcom");
+
+ ret = (int)*mxGetPr(mx_out[0]);
+
+ if (!mxIsEmpty(mx_out[1])) {
+ UpdateUserData(mx_out[1], fwdPb);
+ }
+
+ /* Free temporary space */
+ mxDestroyArray(mx_in[0]);
+ mxDestroyArray(mx_in[1]);
+ mxDestroyArray(mx_in[2]);
+ mxDestroyArray(mx_out[0]);
+ mxDestroyArray(mx_out[1]);
+
+ return(ret);
+}
+
+/*
+ * ----------------------------
+ * FORWARD SENSITVITY FUNCTIONS
+ * ----------------------------
+ */
+
+int mxW_IDASensRes(int Nsens, realtype tres,
+ N_Vector yy, N_Vector yp, N_Vector rr,
+ N_Vector *yyS, N_Vector *ypS, N_Vector *rrS,
+ void *user_data,
+ N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
+{
+ idmPbData fwdPb;
+ mxArray *mx_in[9], *mx_out[3];
+ int is, ret;
+ double *tmp_yyS, *tmp_ypS, *tmp_rrS;
+
+ /* Extract global interface data from user-data */
+ fwdPb = (idmPbData) user_data;
+
+ /* Inputs to the Matlab function */
+ mx_in[0] = mxCreateDoubleScalar(tres); /* current t */
+ mx_in[1] = mxCreateDoubleMatrix(N,1,mxREAL); /* current yy */
+ mx_in[2] = mxCreateDoubleMatrix(N,1,mxREAL); /* current yp */
+ mx_in[3] = mxCreateDoubleMatrix(N,1,mxREAL); /* current rr */
+ mx_in[4] = mxCreateDoubleScalar(Ns); /* number of sensitivities */
+ mx_in[5] = mxCreateDoubleMatrix(N*Ns,1,mxREAL); /* current yyS */
+ mx_in[6] = mxCreateDoubleMatrix(N*Ns,1,mxREAL); /* current ypS */
+ mx_in[7] = fwdPb->SRESfct; /* matlab function handle */
+ mx_in[8] = fwdPb->mtlb_data; /* matlab user data */
+
+ /* Call matlab wrapper */
+
+ GetData(yy, mxGetPr(mx_in[1]), N);
+ GetData(yp, mxGetPr(mx_in[2]), N);
+ GetData(rr, mxGetPr(mx_in[3]), N);
+
+ tmp_yyS = mxGetPr(mx_in[5]);
+ tmp_ypS = mxGetPr(mx_in[6]);
+ for (is=0; is<Ns; is++) {
+ GetData(yyS[is], &tmp_yyS[is*N], N);
+ GetData(ypS[is], &tmp_ypS[is*N], N);
+ }
+
+ mexCallMATLAB(3,mx_out,9,mx_in,"idm_resS");
+
+ tmp_rrS = mxGetPr(mx_out[0]);
+
+ for(is=0;is<Ns;is++)
+ PutData(rrS[is], &tmp_rrS[is*N], N);
+
+ ret = (int)*mxGetPr(mx_out[1]);
+
+ if (!mxIsEmpty(mx_out[2])) {
+ UpdateUserData(mx_out[2], fwdPb);
+ }
+
+ /* Free temporary space */
+
+ mxDestroyArray(mx_in[0]);
+ mxDestroyArray(mx_in[1]);
+ mxDestroyArray(mx_in[2]);
+ mxDestroyArray(mx_in[3]);
+ mxDestroyArray(mx_in[4]);
+ mxDestroyArray(mx_in[5]);
+ mxDestroyArray(mx_in[6]);
+ mxDestroyArray(mx_out[0]);
+ mxDestroyArray(mx_out[1]);
+ mxDestroyArray(mx_out[2]);
+
+ return(ret);
+}
+
+
+/*
+ * ----------------------------
+ * ADJOINT SENSITVITY FUNCTIONS
+ * ----------------------------
+ */
+
+int mxW_IDAResB(realtype tt,
+ N_Vector yy, N_Vector yp,
+ N_Vector yyB, N_Vector ypB, N_Vector rrB,
+ void *user_dataB)
+{
+ idmPbData fwdPb, bckPb;
+ mxArray *mx_in[8], *mx_out[3];
+ int ret;
+
+ /* Extract global interface data from user-data */
+ bckPb = (idmPbData) user_dataB;
+ fwdPb = bckPb->fwd;
+
+ /* Inputs to the Matlab function */
+ mx_in[0] = mxCreateDoubleScalar(0.0); /* type=0: not dependent on yS */
+ mx_in[1] = mxCreateDoubleScalar(tt); /* current t */
+ mx_in[2] = mxCreateDoubleMatrix(N,1,mxREAL); /* current yy */
+ mx_in[3] = mxCreateDoubleMatrix(N,1,mxREAL); /* current yp */
+ mx_in[4] = mxCreateDoubleMatrix(NB,1,mxREAL); /* current yyB */
+ mx_in[5] = mxCreateDoubleMatrix(NB,1,mxREAL); /* current ypB */
+ mx_in[6] = bckPb->RESfct; /* matlab function handle */
+ mx_in[7] = bckPb->mtlb_data; /* matlab user data */
+
+ /* Call matlab wrapper */
+ GetData(yy, mxGetPr(mx_in[2]), N);
+ GetData(yp, mxGetPr(mx_in[3]), N);
+ GetData(yyB, mxGetPr(mx_in[4]), NB);
+ GetData(ypB, mxGetPr(mx_in[5]), NB);
+
+ mexCallMATLAB(3,mx_out,8,mx_in,"idm_resB");
+
+ PutData(rrB, mxGetPr(mx_out[0]), NB);
+
+ ret = (int)*mxGetPr(mx_out[1]);
+
+ if (!mxIsEmpty(mx_out[2])) {
+ UpdateUserData(mx_out[2], bckPb);
+ }
+
+ /* Free temporary space */
+ mxDestroyArray(mx_in[0]);
+ mxDestroyArray(mx_in[1]);
+ mxDestroyArray(mx_in[2]);
+ mxDestroyArray(mx_in[3]);
+ mxDestroyArray(mx_in[4]);
+ mxDestroyArray(mx_in[5]);
+ mxDestroyArray(mx_out[0]);
+ mxDestroyArray(mx_out[1]);
+ mxDestroyArray(mx_out[2]);
+
+ return(ret);
+}
+
+int mxW_IDAResBS(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)
+{
+ idmPbData fwdPb, bckPb;
+ mxArray *mx_in[11], *mx_out[3];
+ double *tmp_yyS, *tmp_ypS;
+ int is, ret;
+
+ /* Extract global interface data from user-data */
+ bckPb = (idmPbData) user_dataB;
+ fwdPb = bckPb->fwd;
+
+ /* Inputs to the Matlab function */
+ mx_in[0] = mxCreateDoubleScalar(1.0); /* type=1: dependent on yS */
+ mx_in[1] = mxCreateDoubleScalar(tt); /* current t */
+ mx_in[2] = mxCreateDoubleMatrix(N,1,mxREAL); /* current yy */
+ mx_in[3] = mxCreateDoubleMatrix(N,1,mxREAL); /* current yp */
+ mx_in[4] = mxCreateDoubleScalar(Ns); /* number of sensitivities */
+ mx_in[5] = mxCreateDoubleMatrix(N*Ns,1,mxREAL); /* current yyS */
+ mx_in[6] = mxCreateDoubleMatrix(N*Ns,1,mxREAL); /* current ypS */
+ mx_in[7] = mxCreateDoubleMatrix(NB,1,mxREAL); /* current yyB */
+ mx_in[8] = mxCreateDoubleMatrix(NB,1,mxREAL); /* current ypB */
+ mx_in[9] = bckPb->RESfct; /* matlab function handle */
+ mx_in[10] = bckPb->mtlb_data; /* matlab user data */
+
+ /* Call matlab wrapper */
+
+ GetData(yy, mxGetPr(mx_in[2]), N);
+ GetData(yp, mxGetPr(mx_in[3]), N);
+
+ tmp_yyS = mxGetPr(mx_in[5]);
+ tmp_ypS = mxGetPr(mx_in[6]);
+ for (is=0; is<Ns; is++) {
+ GetData(yyS[is], &tmp_yyS[is*N], N);
+ GetData(ypS[is], &tmp_ypS[is*N], N);
+ }
+
+ GetData(yyB, mxGetPr(mx_in[7]), NB);
+ GetData(ypB, mxGetPr(mx_in[8]), NB);
+
+ mexCallMATLAB(3,mx_out,11,mx_in,"idm_resB");
+
+ PutData(rrB, mxGetPr(mx_out[0]), NB);
+
+ ret = (int)*mxGetPr(mx_out[1]);
+
+ if (!mxIsEmpty(mx_out[2])) {
+ UpdateUserData(mx_out[2], bckPb);
+ }
+
+ /* Free temporary space */
+ mxDestroyArray(mx_in[0]);
+ mxDestroyArray(mx_in[1]);
+ mxDestroyArray(mx_in[2]);
+ mxDestroyArray(mx_in[3]);
+ mxDestroyArray(mx_in[4]);
+ mxDestroyArray(mx_in[5]);
+ mxDestroyArray(mx_in[6]);
+ mxDestroyArray(mx_in[7]);
+ mxDestroyArray(mx_in[8]);
+ mxDestroyArray(mx_out[0]);
+ mxDestroyArray(mx_out[1]);
+ mxDestroyArray(mx_out[2]);
+
+ return(ret);
+}
+
+int mxW_IDAQuadFctB(realtype tt,
+ N_Vector yy, N_Vector yp,
+ N_Vector yyB, N_Vector ypB,
+ N_Vector ypQB, void *user_dataB)
+{
+ idmPbData fwdPb, bckPb;
+ mxArray *mx_in[8], *mx_out[3];
+ int ret;
+
+ /* Extract global interface data from user-data */
+ bckPb = (idmPbData) user_dataB;
+ fwdPb = bckPb->fwd;
+
+ /* Inputs to the Matlab function */
+ mx_in[0] = mxCreateDoubleScalar(0.0); /* type=0: not dependent on yS */
+ mx_in[1] = mxCreateDoubleScalar(tt); /* current t */
+ mx_in[2] = mxCreateDoubleMatrix(N,1,mxREAL); /* current yy */
+ mx_in[3] = mxCreateDoubleMatrix(N,1,mxREAL); /* current yp */
+ mx_in[4] = mxCreateDoubleMatrix(NB,1,mxREAL); /* current yyB */
+ mx_in[5] = mxCreateDoubleMatrix(NB,1,mxREAL); /* current ypB */
+ mx_in[6] = bckPb->QUADfct; /* matlab function handle */
+ mx_in[7] = bckPb->mtlb_data; /* matlab user data */
+
+ /* Call matlab wrapper */
+ GetData(yy, mxGetPr(mx_in[2]), N);
+ GetData(yp, mxGetPr(mx_in[3]), N);
+ GetData(yyB, mxGetPr(mx_in[4]), NB);
+ GetData(ypB, mxGetPr(mx_in[5]), NB);
+
+ mexCallMATLAB(3,mx_out,8,mx_in,"idm_rhsQB");
+
+ PutData(ypQB, mxGetPr(mx_out[0]), NqB);
+
+ ret = (int)*mxGetPr(mx_out[1]);
+
+ if (!mxIsEmpty(mx_out[2])) {
+ UpdateUserData(mx_out[2], bckPb);
+ }
+
+ /* Free temporary space */
+ mxDestroyArray(mx_in[0]);
+ mxDestroyArray(mx_in[1]);
+ mxDestroyArray(mx_in[2]);
+ mxDestroyArray(mx_in[3]);
+ mxDestroyArray(mx_in[4]);
+ mxDestroyArray(mx_in[5]);
+ mxDestroyArray(mx_out[0]);
+ mxDestroyArray(mx_out[1]);
+ mxDestroyArray(mx_out[2]);
+
+ return(ret);
+}
+
+int mxW_IDAQuadFctBS(realtype tt,
+ N_Vector yy, N_Vector yp,
+ N_Vector *yyS, N_Vector *ypS,
+ N_Vector yyB, N_Vector ypB,
+ N_Vector ypQB, void *user_dataB)
+{
+ idmPbData fwdPb, bckPb;
+ mxArray *mx_in[11], *mx_out[3];
+ double *tmp_yyS, *tmp_ypS;
+ int is, ret;
+
+ /* Extract global interface data from user-data */
+ bckPb = (idmPbData) user_dataB;
+ fwdPb = bckPb->fwd;
+
+ /* Inputs to the Matlab function */
+ mx_in[0] = mxCreateDoubleScalar(1.0); /* type=1: dependent on yS */
+ mx_in[1] = mxCreateDoubleScalar(tt); /* current t */
+ mx_in[2] = mxCreateDoubleMatrix(N,1,mxREAL); /* current yy */
+ mx_in[3] = mxCreateDoubleMatrix(N,1,mxREAL); /* current yp */
+ mx_in[4] = mxCreateDoubleScalar(Ns); /* number of sensitivities */
+ mx_in[5] = mxCreateDoubleMatrix(N*Ns,1,mxREAL); /* current yyS */
+ mx_in[6] = mxCreateDoubleMatrix(N*Ns,1,mxREAL); /* current ypS */
+ mx_in[7] = mxCreateDoubleMatrix(NB,1,mxREAL); /* current yyB */
+ mx_in[8] = mxCreateDoubleMatrix(NB,1,mxREAL); /* current ypB */
+ mx_in[9] = bckPb->QUADfct; /* matlab function handle */
+ mx_in[10] = bckPb->mtlb_data; /* matlab user data */
+
+ /* Call matlab wrapper */
+
+ GetData(yy, mxGetPr(mx_in[2]), N);
+ GetData(yp, mxGetPr(mx_in[3]), N);
+
+ tmp_yyS = mxGetPr(mx_in[5]);
+ tmp_ypS = mxGetPr(mx_in[6]);
+ for (is=0; is<Ns; is++) {
+ GetData(yyS[is], &tmp_yyS[is*N], N);
+ GetData(ypS[is], &tmp_ypS[is*N], N);
+ }
+
+ GetData(yyB, mxGetPr(mx_in[7]), NB);
+ GetData(ypB, mxGetPr(mx_in[8]), NB);
+
+ mexCallMATLAB(3,mx_out,11,mx_in,"idm_rhsQB");
+
+ PutData(ypQB, mxGetPr(mx_out[0]), NqB);
+
+ ret = (int)*mxGetPr(mx_out[1]);
+
+ if (!mxIsEmpty(mx_out[2])) {
+ UpdateUserData(mx_out[2], bckPb);
+ }
+
+ /* Free temporary space */
+ mxDestroyArray(mx_in[0]);
+ mxDestroyArray(mx_in[1]);
+ mxDestroyArray(mx_in[2]);
+ mxDestroyArray(mx_in[3]);
+ mxDestroyArray(mx_in[4]);
+ mxDestroyArray(mx_in[5]);
+ mxDestroyArray(mx_in[6]);
+ mxDestroyArray(mx_in[7]);
+ mxDestroyArray(mx_in[8]);
+ mxDestroyArray(mx_out[0]);
+ mxDestroyArray(mx_out[1]);
+ mxDestroyArray(mx_out[2]);
+
+ return(ret);
+}
+
+int mxW_IDADenseJacB(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)
+{
+ idmPbData fwdPb, bckPb;
+ double *JB_data;
+ mxArray *mx_in[9], *mx_out[3];
+ int i, ret;
+
+ /* Extract global interface data from user-data */
+ bckPb = (idmPbData) user_dataB;
+ fwdPb = bckPb->fwd;
+
+ /* Inputs to the Matlab function */
+ mx_in[0] = mxCreateDoubleScalar(tt); /* current t */
+ mx_in[1] = mxCreateDoubleMatrix(N,1,mxREAL); /* current yy */
+ mx_in[2] = mxCreateDoubleMatrix(N,1,mxREAL); /* current yp */
+ mx_in[3] = mxCreateDoubleMatrix(NB,1,mxREAL); /* current yyB */
+ mx_in[4] = mxCreateDoubleMatrix(NB,1,mxREAL); /* current ypB */
+ mx_in[5] = mxCreateDoubleMatrix(NB,1,mxREAL); /* current rrB */
+ mx_in[6] = mxCreateDoubleScalar(c_jB); /* current c_jB */
+ mx_in[7] = bckPb->JACfct; /* matlab function handle */
+ mx_in[8] = bckPb->mtlb_data; /* matlab user data */
+
+ /* Call matlab wrapper */
+ GetData(yy, mxGetPr(mx_in[1]), N);
+ GetData(yp, mxGetPr(mx_in[2]), N);
+ GetData(yyB, mxGetPr(mx_in[3]), NB);
+ GetData(ypB, mxGetPr(mx_in[4]), NB);
+ GetData(rrB, mxGetPr(mx_in[5]), NB);
+
+ mexCallMATLAB(3,mx_out,9,mx_in,"idm_djacB");
+
+ JB_data = mxGetPr(mx_out[0]);
+ for (i=0;i<NB;i++)
+ memcpy(DENSE_COL(JacB,i), JB_data + i*NB, NB*sizeof(double));
+
+ ret = (int)*mxGetPr(mx_out[1]);
+
+ if (!mxIsEmpty(mx_out[2])) {
+ UpdateUserData(mx_out[2], bckPb);
+ }
+
+ /* Free temporary space */
+ mxDestroyArray(mx_in[0]);
+ mxDestroyArray(mx_in[1]);
+ mxDestroyArray(mx_in[2]);
+ mxDestroyArray(mx_in[3]);
+ mxDestroyArray(mx_in[4]);
+ mxDestroyArray(mx_in[5]);
+ mxDestroyArray(mx_in[6]);
+ mxDestroyArray(mx_out[0]);
+ mxDestroyArray(mx_out[1]);
+ mxDestroyArray(mx_out[2]);
+
+ return(ret);
+}
+
+int mxW_IDABandJacB(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)
+{
+ idmPbData fwdPb, bckPb;
+ double *JB_data;
+ mxArray *mx_in[9], *mx_out[3];
+ long int ebandB, i;
+ int ret;
+
+ /* Extract global interface data from user-data */
+ bckPb = (idmPbData) user_dataB;
+ fwdPb = bckPb->fwd;
+
+ /* Inputs to the Matlab function */
+ mx_in[0] = mxCreateDoubleScalar(tt); /* current t */
+ mx_in[1] = mxCreateDoubleMatrix(N,1,mxREAL); /* current yy */
+ mx_in[2] = mxCreateDoubleMatrix(N,1,mxREAL); /* current yp */
+ mx_in[3] = mxCreateDoubleMatrix(NB,1,mxREAL); /* current yyB */
+ mx_in[4] = mxCreateDoubleMatrix(NB,1,mxREAL); /* current ypB */
+ mx_in[5] = mxCreateDoubleMatrix(NB,1,mxREAL); /* current rrB */
+ mx_in[6] = mxCreateDoubleScalar(c_jB); /* current c_jB */
+ mx_in[7] = bckPb->JACfct; /* matlab function handle */
+ mx_in[8] = bckPb->mtlb_data; /* matlab user data */
+
+ /* Call matlab wrapper */
+ GetData(yy, mxGetPr(mx_in[1]), N);
+ GetData(yp, mxGetPr(mx_in[2]), N);
+ GetData(yyB, mxGetPr(mx_in[3]), NB);
+ GetData(ypB, mxGetPr(mx_in[4]), NB);
+ GetData(rrB, mxGetPr(mx_in[5]), NB);
+
+ mexCallMATLAB(3,mx_out,9,mx_in,"idm_bjacB");
+
+ ebandB = mupperB + mlowerB + 1;
+ JB_data = mxGetPr(mx_out[0]);
+ for (i=0;i<NB;i++)
+ memcpy(BAND_COL(JacB,i) - mupperB, JB_data + i*ebandB, ebandB*sizeof(double));
+
+ ret = (int)*mxGetPr(mx_out[1]);
+
+ if (!mxIsEmpty(mx_out[2])) {
+ UpdateUserData(mx_out[2], bckPb);
+ }
+
+ /* Free temporary space */
+ mxDestroyArray(mx_in[0]);
+ mxDestroyArray(mx_in[1]);
+ mxDestroyArray(mx_in[2]);
+ mxDestroyArray(mx_in[3]);
+ mxDestroyArray(mx_in[4]);
+ mxDestroyArray(mx_in[5]);
+ mxDestroyArray(mx_in[6]);
+ mxDestroyArray(mx_out[0]);
+ mxDestroyArray(mx_out[1]);
+ mxDestroyArray(mx_out[2]);
+
+ return(ret);
+}
+
+int mxW_IDASpilsJacB(realtype tt,
+ 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)
+{
+ idmPbData fwdPb, bckPb;
+ mxArray *mx_in[10], *mx_out[3];
+ int ret;
+
+ /* Extract global interface data from user-data */
+ bckPb = (idmPbData) user_dataB;
+ fwdPb = bckPb->fwd;
+
+ /* Inputs to the Matlab function */
+ mx_in[0] = mxCreateDoubleScalar(tt); /* current t */
+ mx_in[1] = mxCreateDoubleMatrix(N,1,mxREAL); /* current yy */
+ mx_in[2] = mxCreateDoubleMatrix(N,1,mxREAL); /* current yp */
+ mx_in[3] = mxCreateDoubleMatrix(NB,1,mxREAL); /* current yyB */
+ mx_in[4] = mxCreateDoubleMatrix(NB,1,mxREAL); /* current ypB */
+ mx_in[5] = mxCreateDoubleMatrix(NB,1,mxREAL); /* current rrB */
+ mx_in[6] = mxCreateDoubleMatrix(NB,1,mxREAL); /* vector vB */
+ mx_in[7] = mxCreateDoubleScalar(c_jB); /* current c_jB */
+ mx_in[8] = bckPb->JACfct; /* matlab function handle */
+ mx_in[9] = bckPb->mtlb_data; /* matlab user data */
+
+ /* Call matlab wrapper */
+ GetData(yy, mxGetPr(mx_in[1]), N);
+ GetData(yp, mxGetPr(mx_in[2]), N);
+ GetData(yyB, mxGetPr(mx_in[3]), NB);
+ GetData(ypB, mxGetPr(mx_in[4]), NB);
+ GetData(rrB, mxGetPr(mx_in[5]), NB);
+ GetData(vB, mxGetPr(mx_in[6]), NB);
+
+ mexCallMATLAB(3,mx_out,10,mx_in,"idm_jtvB");
+
+ PutData(JvB, mxGetPr(mx_out[0]), NB);
+ ret = (int)*mxGetPr(mx_out[1]);
+
+ if (!mxIsEmpty(mx_out[2])) {
+ UpdateUserData(mx_out[2], bckPb);
+ }
+
+ /* Free temporary space */
+ mxDestroyArray(mx_in[0]);
+ mxDestroyArray(mx_in[1]);
+ mxDestroyArray(mx_in[2]);
+ mxDestroyArray(mx_in[3]);
+ mxDestroyArray(mx_in[4]);
+ mxDestroyArray(mx_in[5]);
+ mxDestroyArray(mx_in[6]);
+ mxDestroyArray(mx_in[7]);
+ mxDestroyArray(mx_out[0]);
+ mxDestroyArray(mx_out[1]);
+ mxDestroyArray(mx_out[2]);
+
+ return(ret);
+
+}
+
+int mxW_IDASpilsPsetB(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)
+{
+ idmPbData fwdPb, bckPb;
+ mxArray *mx_in[9], *mx_out[2];
+ int ret;
+
+ /* Extract global interface data from user-data */
+ bckPb = (idmPbData) user_dataB;
+ fwdPb = bckPb->fwd;
+
+ /* Inputs to the Matlab function */
+ mx_in[0] = mxCreateDoubleScalar(tt); /* current t */
+ mx_in[1] = mxCreateDoubleMatrix(N,1,mxREAL); /* current yy */
+ mx_in[2] = mxCreateDoubleMatrix(N,1,mxREAL); /* current yp */
+ mx_in[3] = mxCreateDoubleMatrix(NB,1,mxREAL); /* current yyB */
+ mx_in[4] = mxCreateDoubleMatrix(NB,1,mxREAL); /* current ypB */
+ mx_in[5] = mxCreateDoubleMatrix(NB,1,mxREAL); /* current rrB */
+ mx_in[6] = mxCreateDoubleScalar(c_jB); /* current c_jB */
+ mx_in[7] = bckPb->PSETfct; /* matlab function handle */
+ mx_in[8] = bckPb->mtlb_data; /* matlab user data */
+
+ /* Call matlab wrapper */
+ GetData(yy, mxGetPr(mx_in[1]), N);
+ GetData(yp, mxGetPr(mx_in[2]), N);
+ GetData(yyB, mxGetPr(mx_in[3]), NB);
+ GetData(ypB, mxGetPr(mx_in[4]), NB);
+ GetData(rrB, mxGetPr(mx_in[5]), NB);
+
+ mexCallMATLAB(2,mx_out,9,mx_in,"idm_psetB");
+
+ ret = (int)*mxGetPr(mx_out[0]);
+
+ if (!mxIsEmpty(mx_out[1])) {
+ UpdateUserData(mx_out[1], bckPb);
+ }
+
+ /* Free temporary space */
+ mxDestroyArray(mx_in[0]);
+ mxDestroyArray(mx_in[1]);
+ mxDestroyArray(mx_in[2]);
+ mxDestroyArray(mx_in[3]);
+ mxDestroyArray(mx_in[4]);
+ mxDestroyArray(mx_in[5]);
+ mxDestroyArray(mx_in[6]);
+ mxDestroyArray(mx_out[0]);
+ mxDestroyArray(mx_out[1]);
+
+ return(ret);
+
+}
+
+int mxW_IDASpilsPsolB(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)
+{
+ idmPbData fwdPb, bckPb;
+ mxArray *mx_in[10], *mx_out[3];
+ int ret;
+
+ /* Extract global interface data from user-data */
+ bckPb = (idmPbData) user_dataB;
+ fwdPb = bckPb->fwd;
+
+ /* Inputs to the Matlab function */
+ mx_in[0] = mxCreateDoubleScalar(tt); /* current t */
+ mx_in[1] = mxCreateDoubleMatrix(N,1,mxREAL); /* current yy */
+ mx_in[2] = mxCreateDoubleMatrix(N,1,mxREAL); /* current yp */
+ mx_in[3] = mxCreateDoubleMatrix(NB,1,mxREAL); /* current yyB */
+ mx_in[4] = mxCreateDoubleMatrix(NB,1,mxREAL); /* current ypB */
+ mx_in[5] = mxCreateDoubleMatrix(NB,1,mxREAL); /* current rrB */
+ mx_in[6] = mxCreateDoubleMatrix(NB,1,mxREAL); /* right hand side rB */
+ mx_in[7] = mxCreateDoubleScalar(c_jB); /* current c_jB */
+ mx_in[8] = bckPb->PSOLfct; /* matlab function handle */
+ mx_in[9] = bckPb->mtlb_data; /* matlab user data */
+
+ /* Call matlab wrapper */
+ GetData(yy, mxGetPr(mx_in[1]), N);
+ GetData(yp, mxGetPr(mx_in[2]), N);
+ GetData(yyB, mxGetPr(mx_in[3]), NB);
+ GetData(ypB, mxGetPr(mx_in[4]), NB);
+ GetData(rrB, mxGetPr(mx_in[5]), NB);
+ GetData(rvecB, mxGetPr(mx_in[6]), NB);
+
+ mexCallMATLAB(3,mx_out,10,mx_in,"idm_psolB");
+
+ PutData(zvecB, mxGetPr(mx_out[0]), NB);
+ ret = (int)*mxGetPr(mx_out[1]);
+
+ if (!mxIsEmpty(mx_out[2])) {
+ UpdateUserData(mx_out[2], bckPb);
+ }
+
+ /* Free temporary space */
+ mxDestroyArray(mx_in[0]);
+ mxDestroyArray(mx_in[1]);
+ mxDestroyArray(mx_in[2]);
+ mxDestroyArray(mx_in[3]);
+ mxDestroyArray(mx_in[4]);
+ mxDestroyArray(mx_in[5]);
+ mxDestroyArray(mx_in[6]);
+ mxDestroyArray(mx_in[7]);
+ mxDestroyArray(mx_out[0]);
+ mxDestroyArray(mx_out[1]);
+ mxDestroyArray(mx_out[2]);
+
+ return(ret);
+
+}
+
+int mxW_IDABBDglocB(long int NlocalB, realtype tt,
+ N_Vector yy, N_Vector yp,
+ N_Vector yyB, N_Vector ypB, N_Vector gvalB,
+ void *user_dataB)
+{
+ idmPbData fwdPb, bckPb;
+ mxArray *mx_in[7], *mx_out[3];
+ int ret;
+
+ /* Extract global interface data from user-data */
+ bckPb = (idmPbData) user_dataB;
+ fwdPb = bckPb->fwd;
+
+ /* Inputs to the Matlab function */
+ mx_in[0] = mxCreateDoubleScalar(tt); /* current t */
+ mx_in[1] = mxCreateDoubleMatrix(N,1,mxREAL); /* current yy */
+ mx_in[2] = mxCreateDoubleMatrix(N,1,mxREAL); /* current yp */
+ mx_in[3] = mxCreateDoubleMatrix(NB,1,mxREAL); /* current yyB */
+ mx_in[4] = mxCreateDoubleMatrix(NB,1,mxREAL); /* current ypB */
+ mx_in[5] = bckPb->GLOCfct; /* matlab function handle */
+ mx_in[6] = bckPb->mtlb_data; /* matlab user data */
+
+ /* Call matlab wrapper */
+ GetData(yy, mxGetPr(mx_in[1]), N);
+ GetData(yp, mxGetPr(mx_in[2]), N);
+ GetData(yyB, mxGetPr(mx_in[3]), NB);
+ GetData(ypB, mxGetPr(mx_in[4]), NB);
+
+ mexCallMATLAB(3,mx_out,7,mx_in,"idm_glocB");
+
+ PutData(gvalB, mxGetPr(mx_out[0]), NB);
+
+ ret = (int)*mxGetPr(mx_out[1]);
+
+ if (!mxIsEmpty(mx_out[2])) {
+ UpdateUserData(mx_out[2], bckPb);
+ }
+
+ /* Free temporary space */
+ mxDestroyArray(mx_in[0]);
+ mxDestroyArray(mx_in[1]);
+ mxDestroyArray(mx_in[2]);
+ mxDestroyArray(mx_in[3]);
+ mxDestroyArray(mx_in[4]);
+ mxDestroyArray(mx_out[0]);
+ mxDestroyArray(mx_out[1]);
+ mxDestroyArray(mx_out[2]);
+
+ return(ret);
+}
+
+int mxW_IDABBDgcomB(long int NlocalB, realtype tt,
+ N_Vector yy, N_Vector yp,
+ N_Vector yyB, N_Vector ypB,
+ void *user_dataB)
+{
+ idmPbData fwdPb, bckPb;
+ mxArray *mx_in[7], *mx_out[2];
+ int ret;
+
+ /* Extract global interface data from user-data */
+ bckPb = (idmPbData) user_dataB;
+ fwdPb = bckPb->fwd;
+
+ /* Inputs to the Matlab function */
+ mx_in[0] = mxCreateDoubleScalar(tt); /* current t */
+ mx_in[1] = mxCreateDoubleMatrix(N,1,mxREAL); /* current yy */
+ mx_in[2] = mxCreateDoubleMatrix(N,1,mxREAL); /* current yp */
+ mx_in[3] = mxCreateDoubleMatrix(NB,1,mxREAL); /* current yyB */
+ mx_in[4] = mxCreateDoubleMatrix(NB,1,mxREAL); /* current ypB */
+ mx_in[5] = bckPb->GCOMfct; /* matlab function handle */
+ mx_in[6] = bckPb->mtlb_data; /* matlab user data */
+
+ /* Call matlab wrapper */
+ GetData(yy, mxGetPr(mx_in[1]), N);
+ GetData(yp, mxGetPr(mx_in[2]), N);
+ GetData(yyB, mxGetPr(mx_in[3]), NB);
+ GetData(ypB, mxGetPr(mx_in[4]), NB);
+
+ mexCallMATLAB(2,mx_out,7,mx_in,"idm_gcomB");
+
+ ret = (int)*mxGetPr(mx_out[0]);
+
+ if (!mxIsEmpty(mx_out[1])) {
+ UpdateUserData(mx_out[1], bckPb);
+ }
+
+ /* Free temporary space */
+ mxDestroyArray(mx_in[0]);
+ mxDestroyArray(mx_in[1]);
+ mxDestroyArray(mx_in[2]);
+ mxDestroyArray(mx_in[3]);
+ mxDestroyArray(mx_in[4]);
+ mxDestroyArray(mx_out[0]);
+ mxDestroyArray(mx_out[1]);
+
+ return(ret);
+}
+
+/*
+ * ---------------------------------------------------------------------------------
+ * Wrapper around matlab monitor function
+ * ---------------------------------------------------------------------------------
+ */
+
+void mxW_IDAMonitor(int call, double t,
+ N_Vector yy,
+ N_Vector yQ,
+ N_Vector *yyS,
+ idmPbData fwdPb)
+{
+ mxArray *mx_in[8], *mx_out[1];
+ double *tmp_yyS;
+ int is;
+
+ mx_in[0] = mxCreateDoubleScalar(call); /* call type (0:first, 1:interm. 2:last) */
+ mx_in[1] = mxCreateDoubleScalar(t); /* current time */
+ mx_in[2] = mxCreateDoubleMatrix(N,1,mxREAL); /* current yy */
+ if (quadr) {
+ mx_in[3] = mxCreateDoubleMatrix(Nq,1,mxREAL); /* current quadratures */
+ } else {
+ mx_in[3] = mxCreateDoubleMatrix(0,0,mxREAL);
+ }
+ mx_in[4] = mxCreateDoubleScalar(Ns); /* number of sensitivities */
+ if (fsa) {
+ mx_in[5] = mxCreateDoubleMatrix(N*Ns,1,mxREAL); /* current yyS */
+ } else {
+ mx_in[5] = mxCreateDoubleMatrix(0,0,mxREAL);
+ }
+ mx_in[6] = fwdPb->MONfct; /* Matlab monitor function */
+ mx_in[7] = fwdPb->MONdata; /* data for monitor function */
+
+ if (call == 1) {
+
+ GetData(yy, mxGetPr(mx_in[2]), N);
+
+ if (quadr) {
+ GetData(yQ, mxGetPr(mx_in[3]), Nq);
+ }
+
+ if (fsa) {
+ tmp_yyS = mxGetPr(mx_in[5]);
+ for (is=0; is<Ns; is++) {
+ GetData(yyS[is], &tmp_yyS[is*N], N);
+ }
+ }
+
+ }
+
+ mexCallMATLAB(1,mx_out,8,mx_in,"idm_monitor");
+
+ if (!mxIsEmpty(mx_out[0])) {
+ UpdateMonitorData(mx_out[0], fwdPb);
+ }
+
+ mxDestroyArray(mx_in[0]);
+ mxDestroyArray(mx_in[1]);
+ mxDestroyArray(mx_in[2]);
+ mxDestroyArray(mx_in[3]);
+ mxDestroyArray(mx_in[4]);
+ mxDestroyArray(mx_in[5]);
+ mxDestroyArray(mx_out[0]);
+}
+
+void mxW_IDAMonitorB(int call, int idxB, double tB,
+ N_Vector yyB,
+ N_Vector yQB,
+ idmPbData bckPb)
+{
+ mxArray *mx_in[7], *mx_out[1];
+
+ mx_in[0] = mxCreateDoubleScalar(call); /* 0: first, 1: interm. 2: last */
+ mx_in[1] = mxCreateDoubleScalar(idxB); /* index of current problem */
+ mx_in[2] = mxCreateDoubleScalar(tB); /* current time */
+ mx_in[3] = mxCreateDoubleMatrix(NB,1,mxREAL); /* current yyB */
+ if (quadrB) {
+ mx_in[4] = mxCreateDoubleMatrix(NqB,1,mxREAL); /* current quadratures */
+ } else {
+ mx_in[4] = mxCreateDoubleMatrix(0,0,mxREAL);
+ }
+ mx_in[5] = bckPb->MONfct;
+ mx_in[6] = bckPb->MONdata;
+
+ if (call == 1) {
+
+ GetData(yyB, mxGetPr(mx_in[3]), NB);
+
+ if (quadrB)
+ GetData(yQB, mxGetPr(mx_in[4]), NqB);
+ }
+
+ mexCallMATLAB(1,mx_out,7,mx_in,"idm_monitorB");
+
+ if (!mxIsEmpty(mx_out[0])) {
+ UpdateMonitorData(mx_out[0], bckPb);
+ }
+
+ mxDestroyArray(mx_in[0]);
+ mxDestroyArray(mx_in[1]);
+ mxDestroyArray(mx_in[2]);
+ mxDestroyArray(mx_in[3]);
+ mxDestroyArray(mx_in[4]);
+ mxDestroyArray(mx_out[0]);
+}
+
+
+/*
+ * ---------------------------------------------------------------------------------
+ * Private functions to update the user data structures
+ * ---------------------------------------------------------------------------------
+ */
+
+static void UpdateUserData(mxArray *new_mtlb_data, idmPbData pb)
+{
+ mexUnlock();
+ mxDestroyArray(pb->mtlb_data);
+ pb->mtlb_data = mxDuplicateArray(new_mtlb_data);
+ mexMakeArrayPersistent(pb->mtlb_data);
+ mexLock();
+}
+
+static void UpdateMonitorData(mxArray *new_mtlb_data, idmPbData pb)
+{
+ mexUnlock();
+ mxDestroyArray(pb->MONdata);
+ pb->MONdata = mxDuplicateArray(new_mtlb_data);
+ mexMakeArrayPersistent(pb->MONdata);
+ mexLock();
+}
+
+
diff --git a/sundialsTB/install_STB.m b/sundialsTB/install_STB.m
new file mode 100644
index 0000000..c93be4b
--- /dev/null
+++ b/sundialsTB/install_STB.m
@@ -0,0 +1,1025 @@
+function [] = install_STB
+%
+% INSTALL_STB Interactive compilation and installtion of sundialsTB
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2007, The Regents of the University of California.
+% $Revision: 1.23 $Date: 2009/04/22 03:34:01 $
+
+% MEX compiler command
+% --------------------
+
+mexcompiler = 'mex -v';
+
+% Location of sundialsTB and top of sundials source tree
+% ------------------------------------------------------
+
+stb = pwd;
+cd('..');
+sun = pwd;
+cd(stb);
+
+% Test mex
+% --------
+
+mex_ok = check_mex(mexcompiler);
+
+if ~mex_ok
+ return
+end
+
+% Should we enable parallel support?
+% ----------------------------------
+
+par = true;
+if isempty(getenv('LAMHOME'))
+ par = false;
+end
+if isempty(getenv('MPITB_ROOT'))
+ par = false;
+end
+q = fullfile(sun,'src','nvec_par');
+if ~exist(q, 'dir')
+ par = false;
+end
+
+% Figure out what modules exist and which ones will be built
+% ----------------------------------------------------------
+
+fprintf('\n\nSelect modules to be built\n');
+
+q = fullfile(sun,'src','cvodes');
+if exist(q, 'dir')
+ answ = input(' Compile CVODES interface? (y/n) ','s');
+ if answ == 'y'
+ cvm_ok = true;
+ else
+ cvm_ok = false;
+ end
+end
+
+if exist(q, 'dir')
+ answ = input(' Compile IDAS interface? (y/n) ','s');
+ if answ == 'y'
+ idm_ok = true;
+ else
+ idm_ok = false;
+ end
+end
+
+q = fullfile(sun,'src','kinsol');
+if exist(q, 'dir')
+ answ = input(' Compile KINSOL interface? (y/n) ','s');
+ if answ == 'y'
+ kim_ok = true;
+ else
+ kim_ok = false;
+ end
+end
+
+if ~cvm_ok && ~idm_ok && ~kim_ok
+ fprintf('\nOK. All done.\n');
+ return
+end
+
+% Create sundials_config.h
+% ------------------------
+
+mkdir('sundials');
+fi = fopen(fullfile('sundials','sundials_config.h'),'w');
+fprintf(fi,'#define SUNDIALS_PACKAGE_VERSION "2.4.0"\n');
+fprintf(fi,'#define SUNDIALS_DOUBLE_PRECISION 1\n');
+fprintf(fi,'#define SUNDIALS_USE_GENERIC_MATH 1\n');
+fprintf(fi,'#define SUNDIALS_EXPORT\n');
+fclose(fi);
+
+% Compile MEX file for the selected modules
+% -----------------------------------------
+
+if cvm_ok
+ compile_CVM(mexcompiler,stb,sun,par);
+end
+
+if idm_ok
+ compile_IDM(mexcompiler,stb,sun,par);
+end
+
+if kim_ok
+ compile_KIM(mexcompiler,stb,sun,par);
+end
+
+% Remove sundials_config.h
+% ------------------------
+
+rmdir('sundials','s');
+
+% Install sundialsTB
+% ------------------
+
+fprintf('\n\nMEX files were successfully created.\n');
+answ = input(' Install toolbox? (y/n) ','s');
+if answ ~= 'y'
+ fprintf('\n\nOK. All done.\n');
+ return
+end
+
+while true
+ fprintf('\n\nSpecify the location where you wish to install the toolbox.\n');
+ fprintf('The toolbox will be installed in a subdirectory "sundialsTB".\n');
+ fprintf('Enter return to cancel the installation.\n');
+ where = input(' Installation directory: ','s');
+ if isempty(where)
+ go = 0;
+ break;
+ end
+ if exist(where,'dir')
+ go = 1;
+ break
+ end
+ fprintf('\n%s does not exist!\n', where);
+end
+
+if ~go
+ fprintf('\n\nOK. All done.\n');
+ return
+end
+
+stbi = fullfile(where,'sundialsTB');
+
+go = 1;
+if exist(stbi,'dir')
+ fprintf('\n\nDirectory %s exists!\n',stbi);
+ answ = input(' Replace? (y/n) ','s');
+ if answ == 'y'
+ rmdir(stbi,'s');
+ go = 1;
+ else
+ go = 0;
+ end
+end
+
+if ~go
+ fprintf('\n\nOK. All done.\n');
+ return
+end
+
+mkdir(where,'sundialsTB');
+mkdir(fullfile(where,'sundialsTB'),'nvector');
+if par
+ mkdir(fullfile(where,'sundialsTB'),'putils');
+end
+
+instSTB(stb, where, par);
+
+if cvm_ok
+ mkdir(fullfile(where,'sundialsTB'),'cvodes');
+ mkdir(fullfile(where,'sundialsTB','cvodes'),'cvm');
+ mkdir(fullfile(where,'sundialsTB','cvodes'),'function_types');
+ mkdir(fullfile(where,'sundialsTB','cvodes'),'examples_ser');
+ if par
+ mkdir(fullfile(where,'sundialsTB','cvodes'),'examples_par');
+ end
+ instCVM(stb, where, par);
+end
+
+if idm_ok
+ mkdir(fullfile(where,'sundialsTB'),'idas');
+ mkdir(fullfile(where,'sundialsTB','idas'),'idm');
+ mkdir(fullfile(where,'sundialsTB','idas'),'function_types');
+ mkdir(fullfile(where,'sundialsTB','idas'),'examples_ser');
+ if par
+ mkdir(fullfile(where,'sundialsTB','idas'),'examples_par');
+ end
+ instIDM(stb, where, par);
+end
+
+if kim_ok
+ mkdir(fullfile(where,'sundialsTB'),'kinsol');
+ mkdir(fullfile(where,'sundialsTB','kinsol'),'kim');
+ mkdir(fullfile(where,'sundialsTB','kinsol'),'function_types');
+ mkdir(fullfile(where,'sundialsTB','kinsol'),'examples_ser');
+ if par
+ mkdir(fullfile(where,'sundialsTB','kinsol'),'examples_par');
+ end
+ instKIM(stb, where, par);
+end
+
+fprintf('\n\nThe sundialsTB toolbox was installed in %s\n',stbi);
+fprintf('\nA startup file, "startup_STB.m" was created in %s.\n',stbi);
+fprintf('Use it as your Matlab startup file, or, if you already have a startup.m file,\n');
+fprintf('add a call to %s\n',fullfile(stbi,'startup_STB.m'));
+fprintf('\nEnjoy!\n\n');
+
+%---------------------------------------------------------------------------------
+% Check if mex works and if the user accepts the current mexopts
+%---------------------------------------------------------------------------------
+
+function mex_ok = check_mex(mexcompiler)
+
+% Create a dummy file
+fid = fopen('foo.c', 'w');
+fprintf(fid,'#include "mex.h"\n');
+fprintf(fid,'void mexFunction(int nlhs,mxArray *plhs[],int nrhs,const mxArray *prhs[])\n');
+fprintf(fid,'{return;}\n');
+fclose(fid);
+
+% Run mexcompiler on foo.c
+mex_cmd = sprintf('%s foo.c', mexcompiler);
+eval(mex_cmd);
+
+% Remove dummy source file and resulting mex file
+delete('foo.c')
+delete(sprintf('foo.%s', mexext))
+
+fprintf('\n\nMEX files will be compiled and built using the above options\n');
+answ = input(' Proceed? (y/n) ','s');
+if answ == 'y'
+ mex_ok = true;
+else
+ fprintf('\n\nOK. All done.\n');
+ mex_ok = false;
+end
+
+return
+
+%---------------------------------------------------------------------------------
+% compilation of cvm MEX file
+%---------------------------------------------------------------------------------
+
+function [] = compile_CVM(mexcompiler,stb,sun,par)
+
+cvm_sources = {
+ fullfile(stb,'cvodes','cvm','src','cvm.c')
+ fullfile(stb,'cvodes','cvm','src','cvmWrap.c')
+ fullfile(stb,'cvodes','cvm','src','cvmOpts.c')
+ };
+if par
+ nvm_sources = {
+ fullfile(stb,'nvector','src','nvm_parallel.c')
+ fullfile(stb,'nvector','src','nvm_ops.c')
+ };
+else
+ nvm_sources = {
+ fullfile(stb,'nvector','src','nvm_serial.c')
+ fullfile(stb,'nvector','src','nvm_ops.c')
+ };
+end
+sources = '';
+for i=1:length(cvm_sources)
+ sources = sprintf('%s "%s"',sources,cvm_sources{i});
+end
+for i=1:length(nvm_sources)
+ sources = sprintf('%s "%s"',sources,nvm_sources{i});
+end
+
+cvm_incdir = fullfile(stb,'cvodes','cvm','src'); % for cvm.h
+nvm_incdir = fullfile(stb,'nvector','src'); % for nvm.h
+includes = sprintf('-I"%s" -I"%s" -I"%s"',stb,cvm_incdir,nvm_incdir);
+
+libraries = '';
+
+% Add CVODES sources and header files
+
+cvs_sources = {
+ fullfile(sun,'src','cvodes','cvodes_band.c')
+ fullfile(sun,'src','cvodes','cvodes_bandpre.c')
+ fullfile(sun,'src','cvodes','cvodes_bbdpre.c')
+ fullfile(sun,'src','cvodes','cvodes_direct.c')
+ fullfile(sun,'src','cvodes','cvodes_dense.c')
+ fullfile(sun,'src','cvodes','cvodes_diag.c')
+ fullfile(sun,'src','cvodes','cvodea.c')
+ fullfile(sun,'src','cvodes','cvodes.c')
+ fullfile(sun,'src','cvodes','cvodes_io.c')
+ fullfile(sun,'src','cvodes','cvodea_io.c')
+ fullfile(sun,'src','cvodes','cvodes_spils.c')
+ fullfile(sun,'src','cvodes','cvodes_spbcgs.c')
+ fullfile(sun,'src','cvodes','cvodes_spgmr.c')
+ fullfile(sun,'src','cvodes','cvodes_sptfqmr.c')
+ };
+shr_sources = {
+ fullfile(sun,'src','sundials','sundials_band.c')
+ fullfile(sun,'src','sundials','sundials_dense.c')
+ fullfile(sun,'src','sundials','sundials_iterative.c')
+ fullfile(sun,'src','sundials','sundials_nvector.c')
+ fullfile(sun,'src','sundials','sundials_direct.c')
+ fullfile(sun,'src','sundials','sundials_spbcgs.c')
+ fullfile(sun,'src','sundials','sundials_spgmr.c')
+ fullfile(sun,'src','sundials','sundials_sptfqmr.c')
+ fullfile(sun,'src','sundials','sundials_math.c')
+ };
+for i=1:length(cvs_sources)
+ sources = sprintf('%s "%s"',sources,cvs_sources{i});
+end
+for i=1:length(shr_sources)
+ sources = sprintf('%s "%s"',sources,shr_sources{i});
+end
+
+sun_incdir = fullfile(sun,'include'); % for SUNDIALS exported headers
+cvs_srcdir = fullfile(sun,'src','cvodes'); % for cvodes_impl.h
+includes = sprintf('%s -I"%s" -I"%s"',includes,sun_incdir,cvs_srcdir);
+
+% Add NVEC_SER sources and header files
+
+nvs_sources = fullfile(sun,'src','nvec_ser','nvector_serial.c');
+sources = sprintf('%s "%s"',sources, nvs_sources);
+
+if par
+
+ % Add NVEC_PAR sources and header files
+
+ nvp_sources = fullfile(sun,'src','nvec_par','nvector_parallel.c');
+ sources = sprintf('%s "%s"',sources, nvp_sources);
+
+% Add LAM headers and libraries
+
+ lam = getenv('LAMHOME');
+ lam_incdir = fullfile(lam, 'include');
+ lam_libdir = fullfile(lam, 'lib');
+ includes = sprintf('%s -I"%s"',includes,lam_incdir);
+ libraries = sprintf('%s -L"%s" -lmpi -llam -lutil',libraries,lam_libdir);
+
+end
+
+% Create MEX file
+
+cvm_dir = fullfile(stb,'cvodes','cvm');
+cd(cvm_dir)
+mex_cmd = sprintf('%s %s %s %s', mexcompiler, includes, sources, libraries);
+disp(mex_cmd);
+eval(mex_cmd);
+
+% Move back to sundialsTB
+
+cd(stb)
+
+%---------------------------------------------------------------------------------
+% compilation of idm MEX file
+%---------------------------------------------------------------------------------
+
+function [] = compile_IDM(mexcompiler,stb,sun,par)
+
+idm_sources = {
+ fullfile(stb,'idas','idm','src','idm.c')
+ fullfile(stb,'idas','idm','src','idmWrap.c')
+ fullfile(stb,'idas','idm','src','idmOpts.c')
+ };
+if par
+ nvm_sources = {
+ fullfile(stb,'nvector','src','nvm_parallel.c')
+ fullfile(stb,'nvector','src','nvm_ops.c')
+ };
+else
+ nvm_sources = {
+ fullfile(stb,'nvector','src','nvm_serial.c')
+ fullfile(stb,'nvector','src','nvm_ops.c')
+ };
+end
+sources = '';
+for i=1:length(idm_sources)
+ sources = sprintf('%s "%s"',sources,idm_sources{i});
+end
+for i=1:length(nvm_sources)
+ sources = sprintf('%s "%s"',sources,nvm_sources{i});
+end
+
+idm_incdir = fullfile(stb,'idas','idm','src'); % for idm.h
+nvm_incdir = fullfile(stb,'nvector','src'); % for nvm.h
+includes = sprintf('-I"%s" -I"%s" -I"%s"',stb,idm_incdir,nvm_incdir);
+
+libraries = '';
+
+% Add IDAS sources and header files
+
+ids_sources = {
+ fullfile(sun,'src','idas','idas_band.c')
+ fullfile(sun,'src','idas','idas_bbdpre.c')
+ fullfile(sun,'src','idas','idas_dense.c')
+ fullfile(sun,'src','idas','idas_direct.c')
+ fullfile(sun,'src','idas','idaa.c')
+ fullfile(sun,'src','idas','idas.c')
+ fullfile(sun,'src','idas','idas_ic.c')
+ fullfile(sun,'src','idas','idas_io.c')
+ fullfile(sun,'src','idas','idaa_io.c')
+ fullfile(sun,'src','idas','idas_spils.c')
+ fullfile(sun,'src','idas','idas_spbcgs.c')
+ fullfile(sun,'src','idas','idas_spgmr.c')
+ fullfile(sun,'src','idas','idas_sptfqmr.c')
+ };
+shr_sources = {
+ fullfile(sun,'src','sundials','sundials_band.c')
+ fullfile(sun,'src','sundials','sundials_dense.c')
+ fullfile(sun,'src','sundials','sundials_iterative.c')
+ fullfile(sun,'src','sundials','sundials_nvector.c')
+ fullfile(sun,'src','sundials','sundials_direct.c')
+ fullfile(sun,'src','sundials','sundials_spbcgs.c')
+ fullfile(sun,'src','sundials','sundials_spgmr.c')
+ fullfile(sun,'src','sundials','sundials_sptfqmr.c')
+ fullfile(sun,'src','sundials','sundials_math.c')
+ };
+for i=1:length(ids_sources)
+ sources = sprintf('%s "%s"',sources,ids_sources{i});
+end
+for i=1:length(shr_sources)
+ sources = sprintf('%s "%s"',sources,shr_sources{i});
+end
+
+sun_incdir = fullfile(sun,'include'); % for SUNDIALS exported headers
+ids_srcdir = fullfile(sun,'src','idas'); % for idas_impl.h
+includes = sprintf('%s -I"%s" -I"%s"',includes,sun_incdir,ids_srcdir);
+
+% Add NVEC_SER sources and header files
+
+nvs_sources = fullfile(sun,'src','nvec_ser','nvector_serial.c');
+sources = sprintf('%s "%s"',sources, nvs_sources);
+
+if par
+
+ % Add NVEC_PAR sources and header files
+
+ nvp_sources = fullfile(sun,'src','nvec_par','nvector_parallel.c');
+ sources = sprintf('%s "%s"',sources, nvp_sources);
+
+% Add LAM headers and libraries
+
+ lam = getenv('LAMHOME');
+ lam_incdir = fullfile(lam, 'include');
+ lam_libdir = fullfile(lam, 'lib');
+ includes = sprintf('%s -I"%s"',includes,lam_incdir);
+ libraries = sprintf('%s -L"%s" -lmpi -llam -lutil',libraries,lam_libdir);
+
+end
+
+% Create MEX file
+
+idm_dir = fullfile(stb,'idas','idm');
+cd(idm_dir)
+mex_cmd = sprintf('%s %s %s %s', mexcompiler, includes, sources, libraries);
+disp(mex_cmd);
+eval(mex_cmd);
+
+% Move back to sundialsTB
+
+cd(stb)
+
+
+%---------------------------------------------------------------------------------
+% compilation of KINSOL MEX file
+%---------------------------------------------------------------------------------
+
+function [] = compile_KIM(mexcompiler,stb,sun,par)
+
+kim_sources = {
+ fullfile(stb,'kinsol','kim','src','kim.c')
+ fullfile(stb,'kinsol','kim','src','kimWrap.c')
+ fullfile(stb,'kinsol','kim','src','kimOpts.c')
+ };
+if par
+ nvm_sources = {
+ fullfile(stb,'nvector','src','nvm_parallel.c')
+ fullfile(stb,'nvector','src','nvm_ops.c')
+ };
+else
+ nvm_sources = {
+ fullfile(stb,'nvector','src','nvm_serial.c')
+ fullfile(stb,'nvector','src','nvm_ops.c')
+ };
+end
+sources = '';
+for i=1:length(kim_sources)
+ sources = sprintf('%s "%s"',sources,kim_sources{i});
+end
+for i=1:length(nvm_sources)
+ sources = sprintf('%s "%s"',sources,nvm_sources{i});
+end
+
+kim_incdir = fullfile(stb,'kinsol','kim','src'); % for kim.h
+nvm_incdir = fullfile(stb,'nvector','src'); % for nvm.h
+includes = sprintf('-I"%s" -I"%s" -I"%s"',stb,kim_incdir,nvm_incdir);
+
+libraries = '';
+
+% Add KINSOL sources and header files
+
+kin_sources = {
+ fullfile(sun,'src','kinsol','kinsol_band.c')
+ fullfile(sun,'src','kinsol','kinsol_bbdpre.c')
+ fullfile(sun,'src','kinsol','kinsol_dense.c')
+ fullfile(sun,'src','kinsol','kinsol_direct.c')
+ fullfile(sun,'src','kinsol','kinsol.c')
+ fullfile(sun,'src','kinsol','kinsol_io.c')
+ fullfile(sun,'src','kinsol','kinsol_spils.c')
+ fullfile(sun,'src','kinsol','kinsol_spbcgs.c')
+ fullfile(sun,'src','kinsol','kinsol_spgmr.c')
+ fullfile(sun,'src','kinsol','kinsol_sptfqmr.c')
+ };
+shr_sources = {
+ fullfile(sun,'src','sundials','sundials_band.c')
+ fullfile(sun,'src','sundials','sundials_dense.c')
+ fullfile(sun,'src','sundials','sundials_iterative.c')
+ fullfile(sun,'src','sundials','sundials_nvector.c')
+ fullfile(sun,'src','sundials','sundials_direct.c')
+ fullfile(sun,'src','sundials','sundials_spbcgs.c')
+ fullfile(sun,'src','sundials','sundials_spgmr.c')
+ fullfile(sun,'src','sundials','sundials_sptfqmr.c')
+ fullfile(sun,'src','sundials','sundials_math.c')
+ };
+
+for i=1:length(kin_sources)
+ sources = sprintf('%s "%s"',sources,kin_sources{i});
+end
+for i=1:length(shr_sources)
+ sources = sprintf('%s "%s"',sources,shr_sources{i});
+end
+
+sun_incdir = fullfile(sun,'include'); % for SUNDIALS exported headers
+kin_srcdir = fullfile(sun,'src','kinsol'); % for kinsol_impl.h
+includes = sprintf('%s -I"%s" -I"%s"',includes,sun_incdir,kin_srcdir);
+
+% Add NVEC_SER sources and header files
+
+nvs_sources = fullfile(sun,'src','nvec_ser','nvector_serial.c');
+sources = sprintf('%s "%s"',sources, nvs_sources);
+
+if par
+
+ % Add NVEC_PAR sources and header files
+
+ nvp_sources = fullfile(sun,'src','nvec_par','nvector_parallel.c');
+ sources = sprintf('%s "%s"',sources, nvp_sources);
+
+% Add LAM headers and libraries
+
+ lam = getenv('LAMHOME');
+ lam_incdir = fullfile(lam, 'include');
+ lam_libdir = fullfile(lam, 'lib');
+ includes = sprintf('%s -I"%s"',includes,lam_incdir);
+ libraries = sprintf('%s -L"%s" -lmpi -llam -lutil',libraries,lam_libdir);
+
+end
+
+% Create MEX file
+
+kim_dir = fullfile(stb, 'kinsol', 'kim');
+cd(kim_dir)
+mex_cmd = sprintf('%s %s %s %s', mexcompiler, includes, sources, libraries);
+disp(mex_cmd);
+eval(mex_cmd);
+
+% Move back to sundialsTB
+
+cd(stb)
+
+%---------------------------------------------------------------------------------
+% Installation of common sundialsTB files
+%---------------------------------------------------------------------------------
+
+function [] = instSTB(stb, where, par)
+
+stbi = fullfile(where,'sundialsTB');
+
+% Create startup_STB.m (use the template startup_STB.in)
+
+in_file = fullfile(stb,'startup_STB.in');
+fi = fopen(in_file,'r');
+out_file = fullfile(stbi,'startup_STB.m');
+fo = fopen(out_file,'w');
+while(~feof(fi))
+ l = fgets(fi);
+ i = strfind(l,'@STB_PATH@');
+ if ~isempty(i)
+ l = sprintf(' stb_path = ''%s'';\n',where);
+ end
+ fprintf(fo,'%s',l);
+end
+fclose(fo);
+fclose(fi);
+
+top_files = {
+ 'LICENSE'
+ 'Contents.m'
+ };
+
+nvm_files = {
+ fullfile('nvector','Contents.m')
+ fullfile('nvector','N_VDotProd.m')
+ fullfile('nvector','N_VL1Norm.m')
+ fullfile('nvector','N_VMax.m')
+ fullfile('nvector','N_VMaxNorm.m')
+ fullfile('nvector','N_VMin.m')
+ fullfile('nvector','N_VWL2Norm.m')
+ fullfile('nvector','N_VWrmsNorm.m')
+ };
+
+put_files = {
+ fullfile('putils','Contents.m')
+ fullfile('putils','mpistart.m')
+ fullfile('putils','mpirun.m')
+ fullfile('putils','mpiruns.m')
+ };
+
+stb_files = [top_files ; nvm_files];
+if par
+ stb_files = [stb_files; put_files];
+end
+
+fprintf('\n\n');
+for i=1:length(stb_files)
+ src = fullfile(stb,stb_files{i});
+ dest = fullfile(stbi,stb_files{i});
+ fprintf('Install %s\n',dest);
+ [success,msg,msgid] = copyfile(src,dest);
+ if ~success
+ disp(msg);
+ break;
+ end
+end
+
+%---------------------------------------------------------------------------------
+% Installation of CVODES files
+%---------------------------------------------------------------------------------
+
+function [] = instCVM(stb, where, par)
+
+stbi = fullfile(where,'sundialsTB');
+
+% Copy files to installation directory
+
+cvmmex = ['cvm.' mexext];
+
+cvm_files = {
+ fullfile('cvodes','Contents.m')
+%
+ fullfile('cvodes','CVodeSetOptions.m')
+ fullfile('cvodes','CVodeQuadSetOptions.m')
+ fullfile('cvodes','CVodeSensSetOptions.m')
+ fullfile('cvodes','CVodeInit.m')
+ fullfile('cvodes','CVodeReInit.m')
+ fullfile('cvodes','CVodeQuadInit.m')
+ fullfile('cvodes','CVodeQuadReInit.m')
+ fullfile('cvodes','CVodeSensInit.m')
+ fullfile('cvodes','CVodeSensReInit.m')
+ fullfile('cvodes','CVode.m')
+ fullfile('cvodes','CVodeGet.m')
+ fullfile('cvodes','CVodeSet.m')
+ fullfile('cvodes','CVodeGetStats.m')
+%
+ fullfile('cvodes','CVodeAdjInit.m')
+ fullfile('cvodes','CVodeAdjReInit.m')
+%
+ fullfile('cvodes','CVodeInitB.m')
+ fullfile('cvodes','CVodeReInitB.m')
+ fullfile('cvodes','CVodeQuadInitB.m')
+ fullfile('cvodes','CVodeQuadReInitB.m')
+ fullfile('cvodes','CVodeSensToggleOff.m')
+ fullfile('cvodes','CVodeB.m')
+ fullfile('cvodes','CVodeSetB.m')
+ fullfile('cvodes','CVodeGetStatsB.m')
+%
+ fullfile('cvodes','CVodeFree.m')
+%
+ fullfile('cvodes','cvm','Contents.m')
+ fullfile('cvodes','cvm','cvm_options.m')
+%
+ fullfile('cvodes','cvm','cvm_rhs.m')
+ fullfile('cvodes','cvm','cvm_rhsQ.m')
+ fullfile('cvodes','cvm','cvm_rhsS.m')
+ fullfile('cvodes','cvm','cvm_root.m')
+ fullfile('cvodes','cvm','cvm_bjac.m')
+ fullfile('cvodes','cvm','cvm_djac.m')
+ fullfile('cvodes','cvm','cvm_jtv.m')
+ fullfile('cvodes','cvm','cvm_pset.m')
+ fullfile('cvodes','cvm','cvm_psol.m')
+ fullfile('cvodes','cvm','cvm_gcom.m')
+ fullfile('cvodes','cvm','cvm_gloc.m')
+ fullfile('cvodes','cvm','cvm_monitor.m')
+%
+ fullfile('cvodes','cvm','cvm_rhsB.m')
+ fullfile('cvodes','cvm','cvm_rhsQB.m')
+ fullfile('cvodes','cvm','cvm_bjacB.m')
+ fullfile('cvodes','cvm','cvm_djacB.m')
+ fullfile('cvodes','cvm','cvm_jtvB.m')
+ fullfile('cvodes','cvm','cvm_psetB.m')
+ fullfile('cvodes','cvm','cvm_psolB.m')
+ fullfile('cvodes','cvm','cvm_gcomB.m')
+ fullfile('cvodes','cvm','cvm_glocB.m')
+ fullfile('cvodes','cvm','cvm_monitorB.m')
+%
+ fullfile('cvodes','cvm',cvmmex)
+ };
+
+cvm_ftypes = {
+ fullfile('cvodes','function_types','CVRhsFn.m')
+ fullfile('cvodes','function_types','CVQuadRhsFn.m')
+ fullfile('cvodes','function_types','CVSensRhsFn.m')
+ fullfile('cvodes','function_types','CVRootFn.m')
+ fullfile('cvodes','function_types','CVBandJacFn.m')
+ fullfile('cvodes','function_types','CVDenseJacFn.m')
+ fullfile('cvodes','function_types','CVJacTimesVecFn.m')
+ fullfile('cvodes','function_types','CVPrecSetupFn.m')
+ fullfile('cvodes','function_types','CVPrecSolveFn.m')
+ fullfile('cvodes','function_types','CVGcommFn.m')
+ fullfile('cvodes','function_types','CVGlocalFn.m')
+ fullfile('cvodes','function_types','CVMonitorFn.m')
+%
+ fullfile('cvodes','function_types','CVRhsFnB.m')
+ fullfile('cvodes','function_types','CVQuadRhsFnB.m')
+ fullfile('cvodes','function_types','CVBandJacFnB.m')
+ fullfile('cvodes','function_types','CVDenseJacFnB.m')
+ fullfile('cvodes','function_types','CVJacTimesVecFnB.m')
+ fullfile('cvodes','function_types','CVPrecSetupFnB.m')
+ fullfile('cvodes','function_types','CVPrecSolveFnB.m')
+ fullfile('cvodes','function_types','CVGcommFnB.m')
+ fullfile('cvodes','function_types','CVGlocalFnB.m')
+ fullfile('cvodes','function_types','CVMonitorFnB.m')
+ };
+
+cvm_exs = {
+ fullfile('cvodes','examples_ser','mcvsAdvDiff_bnd.m')
+ fullfile('cvodes','examples_ser','mcvsDiscRHS_dns.m')
+ fullfile('cvodes','examples_ser','mcvsDiscSOL_dns.m')
+ fullfile('cvodes','examples_ser','mcvsDiurnal_kry.m')
+ fullfile('cvodes','examples_ser','mcvsHessian_FSA_ASA.m')
+ fullfile('cvodes','examples_ser','mcvsOzone_FSA_dns.m')
+ fullfile('cvodes','examples_ser','mcvsPleiades_non.m')
+ fullfile('cvodes','examples_ser','mcvsPollut_FSA_dns.m')
+ fullfile('cvodes','examples_ser','mcvsRoberts_ASAi_dns.m')
+ fullfile('cvodes','examples_ser','mcvsRoberts_dns.m')
+ fullfile('cvodes','examples_ser','mcvsRoberts_FSA_dns.m')
+ fullfile('cvodes','examples_ser','mcvsVanDPol_dns.m')
+ };
+
+cvm_exp = {
+ fullfile('cvodes','examples_par','mcvsAdvDiff_FSA_non_p.m')
+ fullfile('cvodes','examples_par','mcvsAtmDisp_kry_bbd_p.m')
+ fullfile('cvodes','examples_par','mcvsDecoupl_non_p.m')
+ };
+
+stb_files = [cvm_files ; cvm_ftypes ; cvm_exs];
+if par
+ stb_files = [stb_files ; cvm_exp];
+end
+
+fprintf('\n\n');
+for i=1:length(stb_files)
+ src = fullfile(stb,stb_files{i});
+ dest = fullfile(stbi,stb_files{i});
+ fprintf('Install %s\n',dest);
+ [success,msg,msgid] = copyfile(src,dest);
+ if ~success
+ disp(msg);
+ break;
+ end
+end
+
+if (exist ('OCTAVE_VERSION'))
+ cvmon = fullfile('cvodes','CVodeMonitor_octave.m');
+ cvmonB = fullfile('cvodes','CVodeMonitorB_octave.m');
+else
+ cvmon = fullfile('cvodes','CVodeMonitor.m');
+ cvmonB = fullfile('cvodes','CVodeMonitorB.m');
+end
+
+src = fullfile(stb,cvmon);
+dest = fullfile(stbi,'cvodes','CVodeMonitor.m');
+fprintf('Install %s\n',dest);
+[success,msg,msgid] = copyfile(src,dest);
+if ~success
+ disp(msg);
+end
+
+src = fullfile(stb,cvmonB);
+dest = fullfile(stbi,'cvodes','CVodeMonitorB.m');
+fprintf('Install %s\n',dest);
+[success,msg,msgid] = copyfile(src,dest);
+if ~success
+ disp(msg);
+end
+
+%---------------------------------------------------------------------------------
+% Installation of IDAS files
+%---------------------------------------------------------------------------------
+
+function [] = instIDM(stb, where, par)
+
+stbi = fullfile(where,'sundialsTB');
+
+% Copy files to installation directory
+
+idmmex = ['idm.' mexext];
+
+idm_files = {
+ fullfile('idas','Contents.m')
+%
+ fullfile('idas','IDASetOptions.m')
+ fullfile('idas','IDAQuadSetOptions.m')
+ fullfile('idas','IDASensSetOptions.m')
+ fullfile('idas','IDAInit.m')
+ fullfile('idas','IDAReInit.m')
+ fullfile('idas','IDAQuadInit.m')
+ fullfile('idas','IDAQuadReInit.m')
+ fullfile('idas','IDASensInit.m')
+ fullfile('idas','IDASensReInit.m')
+ fullfile('idas','IDASensToggleOff.m')
+ fullfile('idas','IDAAdjReInit.m')
+ fullfile('idas','IDACalcIC.m')
+ fullfile('idas','IDASolve.m')
+ fullfile('idas','IDASet.m')
+ fullfile('idas','IDAGet.m')
+ fullfile('idas','IDAGetStats.m')
+%
+ fullfile('idas','IDAAdjInit.m')
+%
+ fullfile('idas','IDAInitB.m')
+ fullfile('idas','IDAReInitB.m')
+ fullfile('idas','IDAQuadInitB.m')
+ fullfile('idas','IDAQuadReInitB.m')
+ fullfile('idas','IDACalcICB.m')
+ fullfile('idas','IDASolveB.m')
+ fullfile('idas','IDASetB.m')
+ fullfile('idas','IDAGetStatsB.m')
+%
+ fullfile('idas','IDAFree.m')
+%
+ fullfile('idas','idm','Contents.m')
+ fullfile('idas','idm','idm_options.m')
+%
+ fullfile('idas','idm','idm_res.m')
+ fullfile('idas','idm','idm_rhsQ.m')
+ fullfile('idas','idm','idm_bjac.m')
+ fullfile('idas','idm','idm_djac.m')
+ fullfile('idas','idm','idm_gcom.m')
+ fullfile('idas','idm','idm_gloc.m')
+ fullfile('idas','idm','idm_jtv.m')
+ fullfile('idas','idm','idm_pset.m')
+ fullfile('idas','idm','idm_psol.m')
+ fullfile('idas','idm','idm_root.m')
+ fullfile('idas','idm','idm_resS.m')
+ fullfile('idas','idm','idm_monitor.m')
+%
+ fullfile('idas','idm','idm_resB.m')
+ fullfile('idas','idm','idm_rhsQB.m')
+ fullfile('idas','idm','idm_bjacB.m')
+ fullfile('idas','idm','idm_djacB.m')
+ fullfile('idas','idm','idm_jtvB.m')
+ fullfile('idas','idm','idm_psetB.m')
+ fullfile('idas','idm','idm_psolB.m')
+ fullfile('idas','idm','idm_gcomB.m')
+ fullfile('idas','idm','idm_glocB.m')
+ fullfile('idas','idm','idm_monitorB.m')
+%
+ fullfile('idas','idm',idmmex)
+ };
+
+idm_ftypes = {
+ fullfile('idas','function_types','IDABandJacFn.m')
+ fullfile('idas','function_types','IDABandJacFnB.m')
+ fullfile('idas','function_types','IDADenseJacFn.m')
+ fullfile('idas','function_types','IDADenseJacFnB.m')
+ fullfile('idas','function_types','IDAGcommFn.m')
+ fullfile('idas','function_types','IDAGcommFnB.m')
+ fullfile('idas','function_types','IDAGlocalFn.m')
+ fullfile('idas','function_types','IDAGlocalFnB.m')
+ fullfile('idas','function_types','IDAJacTimesVecFn.m')
+ fullfile('idas','function_types','IDAJacTimesVecFnB.m')
+ fullfile('idas','function_types','IDAMonitorFn.m')
+ fullfile('idas','function_types','IDAMonitorFnB.m')
+ fullfile('idas','function_types','IDAPrecSetupFn.m')
+ fullfile('idas','function_types','IDAPrecSetupFnB.m')
+ fullfile('idas','function_types','IDAPrecSolveFn.m')
+ fullfile('idas','function_types','IDAPrecSolveFnB.m')
+ fullfile('idas','function_types','IDAQuadRhsFn.m')
+ fullfile('idas','function_types','IDAQuadRhsFnB.m')
+ fullfile('idas','function_types','IDAResFn.m')
+ fullfile('idas','function_types','IDAResFnB.m')
+ fullfile('idas','function_types','IDARootFn.m')
+ fullfile('idas','function_types','IDASensResFn.m')
+ };
+
+idm_exs = {
+ fullfile('idas','examples_ser','midasBruss_ASA_dns.m')
+ fullfile('idas','examples_ser','midasBruss_dns.m')
+ fullfile('idas','examples_ser','midasHeat2D_bnd.m')
+ fullfile('idas','examples_ser','midasPendI1_dns.m')
+ fullfile('idas','examples_ser','midasPendI2_dns.m')
+ fullfile('idas','examples_ser','midasReInit_dns.m')
+ fullfile('idas','examples_ser','midasRoberts_ASAi_dns.m')
+ fullfile('idas','examples_ser','midasRoberts_dns.m')
+ fullfile('idas','examples_ser','midasSlCrank_dns.m')
+ fullfile('idas','examples_ser','midasSlCrank_FSA_dns.m')
+ };
+
+stb_files = [idm_files ; idm_ftypes ; idm_exs];
+%if par
+% stb_files = [stb_files ; idm_exp];
+%end
+
+fprintf('\n\n');
+for i=1:length(stb_files)
+ src = fullfile(stb,stb_files{i});
+ dest = fullfile(stbi,stb_files{i});
+ fprintf('Install %s\n',dest);
+ [success,msg,msgid] = copyfile(src,dest);
+ if ~success
+ disp(msg);
+ break;
+ end
+end
+
+if (exist ('OCTAVE_VERSION'))
+ idamon = fullfile('idas','IDAMonitor_octave.m');
+ idamonB = fullfile('idas','IDAMonitorB_octave.m');
+else
+ idamon = fullfile('idas','IDAMonitor.m');
+ idamonB = fullfile('idas','IDAMonitorB.m');
+end
+
+src = fullfile(stb,idamon);
+dest = fullfile(stbi,'idas','IDAMonitor.m');
+fprintf('Install %s\n',dest);
+[success,msg,msgid] = copyfile(src,dest);
+if ~success
+ disp(msg);
+end
+
+src = fullfile(stb,idamonB);
+dest = fullfile(stbi,'idas','IDAMonitorB.m');
+fprintf('Install %s\n',dest);
+[success,msg,msgid] = copyfile(src,dest);
+if ~success
+ disp(msg);
+end
+
+
+
+%---------------------------------------------------------------------------------
+% Installation of KINSOL files
+%---------------------------------------------------------------------------------
+
+function [] = instKIM(stb, where, par)
+
+stbi = fullfile(where,'sundialsTB');
+
+% Copy files to installation directory
+
+kimmex = ['kim.' mexext];
+
+kim_files = {
+ fullfile('kinsol','Contents.m')
+ fullfile('kinsol','KINFree.m')
+ fullfile('kinsol','KINGetStats.m')
+ fullfile('kinsol','KINInit.m')
+ fullfile('kinsol','KINSetOptions.m')
+ fullfile('kinsol','KINSol.m')
+ fullfile('kinsol','kim','Contents.m')
+ fullfile('kinsol','kim','kim_bjac.m')
+ fullfile('kinsol','kim','kim_djac.m')
+ fullfile('kinsol','kim','kim_gcom.m')
+ fullfile('kinsol','kim','kim_gloc.m')
+ fullfile('kinsol','kim','kim_info.m')
+ fullfile('kinsol','kim','kim_jtv.m')
+ fullfile('kinsol','kim','kim_pset.m')
+ fullfile('kinsol','kim','kim_psol.m')
+ fullfile('kinsol','kim','kim_sys.m')
+ fullfile('kinsol','kim',kimmex)
+ };
+
+kim_ftypes = {
+ fullfile('kinsol','function_types','KINSysFn.m')
+ fullfile('kinsol','function_types','KINBandJacFn.m')
+ fullfile('kinsol','function_types','KINDenseJacFn.m')
+ fullfile('kinsol','function_types','KINJacTimesVecFn.m')
+ fullfile('kinsol','function_types','KINPrecSetupFn.m')
+ fullfile('kinsol','function_types','KINPrecSolveFn.m')
+ fullfile('kinsol','function_types','KINGcommFn.m')
+ fullfile('kinsol','function_types','KINGlocalFn.m')
+ };
+
+kim_exs = {
+ fullfile('kinsol','examples_ser','mkinDiagon_kry.m')
+ fullfile('kinsol','examples_ser','mkinTest_dns.m')
+ fullfile('kinsol','examples_ser','mkinFerTron_dns.m')
+ fullfile('kinsol','examples_ser','mkinRoboKin_dns.m')
+ };
+
+kim_exp = {
+ fullfile('kinsol','examples_par','mkinDiagon_kry_p.m')
+ };
+
+stb_files = [kim_files ; kim_ftypes ; kim_exs];
+if par
+ stb_files = [stb_files ; kim_exp];
+end
+
+fprintf('\n\n');
+for i=1:length(stb_files)
+ src = fullfile(stb,stb_files{i});
+ dest = fullfile(stbi,stb_files{i});
+ fprintf('Install %s\n',dest);
+ [success,msg,msgid] = copyfile(src,dest);
+ if ~success
+ disp(msg);
+ break;
+ end
+end
+
+
diff --git a/sundialsTB/kinsol/Contents.m b/sundialsTB/kinsol/Contents.m
new file mode 100644
index 0000000..1620ffd
--- /dev/null
+++ b/sundialsTB/kinsol/Contents.m
@@ -0,0 +1,28 @@
+% KINSOL, nonlinear system solver
+%
+% Functions
+% KINSetOptions - creates an options structure for KINSOL.
+% KINInit - allocates and initializes memory for KINSOL.
+% KINSol - solves the nonlinear problem.
+% KINGetStats - returns statistics for the KINSOL solver
+% KINFree - deallocates memory for the KINSOL solver.
+%
+% User-supplied function types
+% KINSysFn - system function
+% KINDenseJacFn - dense Jacobian function
+% KINJacTimesVecFn - Jacobian times vector function
+% KINPrecSetupFn - preconditioner setup function
+% KINPrecSolveFn - preconditioner solve function
+% KINGlocalFn - RHS approximation function (BBDPre)
+% KINGcomFn - communication function (BBDPre)
+%
+% Serial examples
+% mkinDiagon_kry - simple serial diagonal example
+% mkinTest_dns - simple 2 dimensional example
+% mkinRoboKin - robot kinematics problem
+%
+% Parallel examples
+% mkinDiagon_kry_p - simple parallel diagonal example
+% Use the mpirun function to run any of the parallel examples
+%
+% See also nvector, putils
diff --git a/sundialsTB/kinsol/KINFree.m b/sundialsTB/kinsol/KINFree.m
new file mode 100644
index 0000000..b6780bd
--- /dev/null
+++ b/sundialsTB/kinsol/KINFree.m
@@ -0,0 +1,11 @@
+function KINFree()
+%KINFree deallocates memory for the KINSOL solver.
+%
+% Usage: KINFree
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2005, The Regents of the University of California.
+% $Revision: 1.2 $Date: 2007/12/05 21:58:19 $
+
+mode = 6;
+kim(mode);
diff --git a/sundialsTB/kinsol/KINGetStats.m b/sundialsTB/kinsol/KINGetStats.m
new file mode 100644
index 0000000..ffa548c
--- /dev/null
+++ b/sundialsTB/kinsol/KINGetStats.m
@@ -0,0 +1,44 @@
+function [si, status] = KINGetStats()
+%KINGetStats returns statistics for the main KINSOL solver and the linear
+%solver used.
+%
+% Usage: STATS = KINGetStats
+%
+%Fields in the structure STATS
+%
+%o nfe - total number evaluations of the nonlinear system function SYSFUN
+%o nni - total number of nonlinear iterations
+%o nbcf - total number of beta-condition failures
+%o nbops - total number of backtrack operations (step length adjustments)
+% performed by the line search algorithm
+%o fnorm - scaled norm of the nonlinear system function f(y) evaluated at the
+% current iterate: ||fscale*f(y)||_L2
+%o step - scaled norm (or length) of the step used during the previous
+% iteration: ||uscale*p||_L2
+%o LSInfo - structure with linear solver statistics
+%
+%The structure LSinfo has different fields, depending on the linear solver used.
+%
+% Fields in LSinfo for the 'Dense' linear solver
+%
+%o name - 'Dense'
+%o njeD - number of Jacobian evaluations
+%o nfeD - number of right-hand side function evaluations for difference-quotient
+% Jacobian approximation
+%
+% Fields in LSinfo for the 'GMRES' or 'BiCGStab' linear solver
+%
+%o name - 'GMRES' or 'BiCGStab'
+%o nli - number of linear solver iterations
+%o npe - number of preconditioner setups
+%o nps - number of preconditioner solve function calls
+%o ncfl - number of linear system convergence test failures
+%
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2005, The Regents of the University of California.
+% $Revision: 1.2 $Date: 2007/12/05 21:58:19 $
+
+
+mode = 3;
+[si, status] = kim(mode);
diff --git a/sundialsTB/kinsol/KINInit.m b/sundialsTB/kinsol/KINInit.m
new file mode 100644
index 0000000..3fa9ded
--- /dev/null
+++ b/sundialsTB/kinsol/KINInit.m
@@ -0,0 +1,29 @@
+function status = KINInit(fct, n, options)
+%KINInit allocates and initializes memory for KINSOL.
+%
+% Usage: KINInit ( SYSFUN, N [, OPTIONS ] );
+%
+% SYSFUN is a function defining the nonlinear problem f(y) = 0.
+% This function must return a column vector FY containing the
+% current value of the residual
+% N is the (local) problem dimension.
+% OPTIONS is an (optional) set of integration options, created with
+% the KINSetOptions function.
+%
+% See also: KINSetOptions, KINSysFn
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2005, The Regents of the University of California.
+% $Revision: 1.1 $Date: 2007/12/05 21:58:19 $
+
+mode = 1;
+
+if nargin < 2
+ error('Too few input arguments');
+end
+
+if nargin < 3
+ options = [];
+end
+
+status = kim(mode, fct, n, options);
diff --git a/sundialsTB/kinsol/KINSetOptions.m b/sundialsTB/kinsol/KINSetOptions.m
new file mode 100644
index 0000000..29be3e2
--- /dev/null
+++ b/sundialsTB/kinsol/KINSetOptions.m
@@ -0,0 +1,336 @@
+function options = KINSetOptions(varargin)
+%KINSetOptions creates an options structure for KINSOL.
+%
+% Usage:
+%
+% options = KINSetOptions('NAME1',VALUE1,'NAME2',VALUE2,...) creates a KINSOL
+% options structure options in which the named properties have the
+% specified values. Any unspecified properties have default values. It is
+% sufficient to type only the leading characters that uniquely identify the
+% property. Case is ignored for property names.
+%
+% options = KINSetOptions(oldoptions,'NAME1',VALUE1,...) alters an existing
+% options structure oldoptions.
+%
+% options = KINSetOptions(oldoptions,newoptions) combines an existing options
+% structure oldoptions with a new options structure newoptions. Any new
+% properties overwrite corresponding old properties.
+%
+% KINSetOptions with no input arguments displays all property names and their
+% possible values.
+%
+%KINSetOptions properties
+%(See also the KINSOL User Guide)
+%
+%UserData - User data passed unmodified to all functions [ empty ]
+% If UserData is not empty, all user provided functions will be
+% passed the problem data as their last input argument. For example,
+% the SYS function must be defined as FY = SYSFUN(Y,DATA).
+%
+%MaxNumIter - maximum number of nonlinear iterations [ scalar | {200} ]
+% Specifies the maximum number of iterations that the nonlinar solver is allowed
+% to take.
+%FuncRelErr - relative residual error [ scalar | {eps} ]
+% Specifies the realative error in computing f(y) when used in difference
+% quotient approximation of matrix-vector product J(y)*v.
+%FuncNormTol - residual stopping criteria [ scalar | {eps^(1/3)} ]
+% Specifies the stopping tolerance on ||fscale*ABS(f(y))||_L-infinity
+%ScaledStepTol - step size stopping criteria [ scalar | {eps^(2/3)} ]
+% Specifies the stopping tolerance on the maximum scaled step length:
+% || y_(k+1) - y_k ||
+% || ------------------ ||_L-infinity
+% || |y_(k+1)| + yscale ||
+%MaxNewtonStep - maximum Newton step size [ scalar | {0.0} ]
+% Specifies the maximum allowable value of the scaled length of the Newton step.
+%InitialSetup - initial call to linear solver setup [ false | {true} ]
+% Specifies whether or not KINSol makes an initial call to the linear solver
+% setup function.
+%MaxNumSetups - [ scalar | {10} ]
+% Specifies the maximum number of nonlinear iterations between calls to the
+% linear solver setup function (i.e. Jacobian/preconditioner evaluation)
+%MaxNumSubSetups - [ scalar | {5} ]
+% Specifies the maximum number of nonlinear iterations between checks by the
+% nonlinear residual monitoring algorithm (specifies length of subintervals).
+% NOTE: MaxNumSetups should be a multiple of MaxNumSubSetups.
+%MaxNumBetaFails - maximum number of beta-condition failures [ scalar | {10} ]
+% Specifies the maximum number of beta-condiiton failures in the line search
+% algorithm.
+%EtaForm - Inexact Newton method [ Constant | Type2 | {Type1} ]
+% Specifies the method for computing the eta coefficient used in the calculation
+% of the linear solver convergence tolerance (used only if strategy='InexactNEwton'
+% in the call to KINSol):
+% lintol = (eta + eps)*||fscale*f(y)||_L2
+% which is the used to check if the following inequality is satisfied:
+% ||fscale*(f(y)+J(y)*p)||_L2 <= lintol
+% Valid choices are:
+% | ||f(y_(k+1))||_L2 - ||f(y_k)+J(y_k)*p_k||_L2 |
+% EtaForm='Type1' eta = ------------------------------------------------
+% ||f(y_k)||_L2
+%
+% [ ||f(y_(k+1))||_L2 ]^alpha
+% EtaForm='Type2' eta = gamma * [ ----------------- ]
+% [ ||f(y_k)||_L2 ]
+% EtaForm='Constant'
+%Eta - constant value for eta [ scalar | {0.1} ]
+% Specifies the constant value for eta in the case EtaForm='Constant'.
+%EtaAlpha - alpha parameter for eta [ scalar | {2.0} ]
+% Specifies the parameter alpha in the case EtaForm='Type2'
+%EtaGamma - gamma parameter for eta [ scalar | {0.9} ]
+% Specifies the parameter gamma in the case EtaForm='Type2'
+%MinBoundEps - lower bound on eps [ false | {true} ]
+% Specifies whether or not the value of eps is bounded below by 0.01*FuncNormtol.
+%Constraints - solution constraints [ vector ]
+% Specifies additional constraints on the solution components.
+% Constraints(i) = 0 : no constrain on y(i)
+% Constraints(i) = 1 : y(i) >= 0
+% Constraints(i) = -1 : y(i) <= 0
+% Constraints(i) = 2 : y(i) > 0
+% Constraints(i) = -2 : y(i) < 0
+% If Constraints is not specified, no constraints are applied to y.
+%
+%LinearSolver - Type of linear solver [ {Dense} | Band | GMRES | BiCGStab | TFQMR ]
+% Specifies the type of linear solver to be used for the Newton nonlinear solver.
+% Valid choices are: Dense (direct, dense Jacobian), GMRES (iterative, scaled
+% preconditioned GMRES), BiCGStab (iterative, scaled preconditioned stabilized
+% BiCG), TFQMR (iterative, scaled preconditioned transpose-free QMR).
+% The GMRES, BiCGStab, and TFQMR are matrix-free linear solvers.
+%JacobianFn - Jacobian function [ function ]
+% This propeerty is overloaded. Set this value to a function that returns
+% Jacobian information consistent with the linear solver used (see Linsolver).
+% If not specified, KINSOL uses difference quotient approximations.
+% For the Dense linear solver, JacobianFn must be of type KINDenseJacFn and must
+% return a dense Jacobian matrix. For the iterative linear solvers, GMRES,
+% BiCGStab, or TFQMR, JacobianFn must be of type KINJactimesVecFn and must return
+% a Jacobian-vector product.
+%KrylovMaxDim - Maximum number of Krylov subspace vectors [ scalar | {10} ]
+% Specifies the maximum number of vectors in the Krylov subspace. This property
+% is used only if an iterative linear solver, GMRES, BiCGStab, or TFQMR is used
+% (see LinSolver).
+%MaxNumRestarts - Maximum number of GMRES restarts [ scalar | {0} ]
+% Specifies the maximum number of times the GMRES (see LinearSolver) solver
+% can be restarted.
+%PrecModule - Built-in preconditioner module [ BBDPre | {UserDefined} ]
+% If the PrecModule = 'UserDefined', then the user must provide at least a
+% preconditioner solve function (see PrecSolveFn)
+% KINSOL provides a built-in preconditioner module, BBDPre which can only be used
+% with parallel vectors. It provide a preconditioner matrix that is block-diagonal
+% with banded blocks. The blocking corresponds to the distribution of the variable
+% vector 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(y) (see GlocalFn). The blocks are generated by a difference
+% quotient scheme on each processor independently. This scheme utilizes an assumed
+% banded structure with given half-bandwidths, mldq and mudq (specified through
+% LowerBwidthDQ and UpperBwidthDQ, respectively). However, the banded Jacobian
+% block kept by the scheme has half-bandwiths ml and mu (specified through
+% LowerBwidth and UpperBwidth), which may be smaller.
+%PrecSetupFn - Preconditioner setup function [ function ]
+% PrecSetupFn specifies an optional function which, together with PrecSolve,
+% defines a right preconditioner matrix which is an aproximation
+% to the Newton matrix. PrecSetupFn must be of type KINPrecSetupFn.
+%PrecSolveFn - Preconditioner solve function [ function ]
+% PrecSolveFn specifies an optional function which must solve a linear system
+% Pz = r, for given r. If PrecSolveFn is not defined, the no preconditioning will
+% be used. PrecSolveFn must be of type KINPrecSolveFn.
+%GlocalFn - Local right-hand side approximation funciton for BBDPre [ function ]
+% If PrecModule is BBDPre, GlocalFn specifies a required function that
+% evaluates a local approximation to the system function. GlocalFn must
+% be of type KINGlocalFn.
+%GcommFn - Inter-process communication function for BBDPre [ function ]
+% If PrecModule is BBDPre, GcommFn specifies an optional function
+% to perform any inter-process communication required for the evaluation of
+% GlocalFn. GcommFn must be of type KINGcommFn.
+%LowerBwidth - Jacobian/preconditioner lower bandwidth [ scalar | {0} ]
+% This property is overloaded. If the Band linear solver is used (see LinSolver),
+% it specifies the lower half-bandwidth of the band Jacobian approximation.
+% If one of the three iterative linear solvers, GMRES, BiCGStab, or TFQMR is used
+% (see LinSolver) and if the BBDPre preconditioner module in KINSOL is used
+% (see PrecModule), it specifies the lower half-bandwidth of the retained
+% banded approximation of the local Jacobian block.
+% LowerBwidth defaults to 0 (no sub-diagonals).
+%UpperBwidth - Jacobian/preconditioner upper bandwidth [ scalar | {0} ]
+% This property is overloaded. If the Band linear solver is used (see LinSolver),
+% it specifies the upper half-bandwidth of the band Jacobian approximation.
+% If one of the three iterative linear solvers, GMRES, BiCGStab, or TFQMR is used
+% (see LinSolver) and if the BBDPre preconditioner module in KINSOL is used
+% (see PrecModule), it specifies the upper half-bandwidth of the retained
+% banded approximation of the local Jacobian block.
+% UpperBwidth defaults to 0 (no super-diagonals).
+%LowerBwidthDQ - BBDPre preconditioner DQ lower bandwidth [ scalar | {0} ]
+% Specifies the lower half-bandwidth used in the difference-quotient Jacobian
+% approximation for the BBDPre preconditioner (see PrecModule).
+%UpperBwidthDQ - BBDPre preconditioner DQ upper bandwidth [ scalar | {0} ]
+% Specifies the upper half-bandwidth used in the difference-quotient Jacobian
+% approximation for the BBDPre preconditioner (see PrecModule).
+%
+%Verbose - verbose output [ true | {false} ]
+% Specifies whether or not KINSOL should output additional information
+%ErrorMessages - Post error/warning messages [ false | {true} ]
+% Note that any errors in KINInit will result in a Matlab error, thus
+% stoping execution. Only subsequent calls to KINSOL functions will respect
+% the value specified for 'ErrorMessages'.
+%
+% See also
+% KINDenseJacFn, KINJacTimesVecFn
+% KINPrecSetupFn, KINPrecSolveFn
+% KINGlocalFn, KINGcommFn
+%
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2005, The Regents of the University of California.
+% $Revision: 1.5 $Date: 2011/06/01 21:11:01 $
+
+% Based on Matlab's ODESET function
+
+% Print out possible values of properties.
+if (nargin == 0) & (nargout == 0)
+ fprintf(' UserData: [ empty ]\n');
+ fprintf('\n');
+ fprintf(' MaxNumIter: [ scalar | {200} ]\n');
+ fprintf(' FuncRelErr: [ scalar | {eps} ]\n');
+ fprintf(' FuncNormTol: [ scalar | {eps^(1/3)} ]\n');
+ fprintf(' ScaledStepTol: [ scalar | {eps^(2/3)} ]\n');
+ fprintf(' MaxNewtonStep: [ scalar | {0.0} ]\n');
+ fprintf(' InitialSetup: [ false | {true} ]\n');
+ fprintf(' MaxNumSetups: [ scalar | {10} ]\n');
+ fprintf(' MaxNumSubSetups: [ scalar | {5} ]\n');
+ fprintf(' MaxNumBetaFails: [ scalar | {10} ]\n');
+ fprintf(' EtaForm: [ Constant | Type2 | {Type1} ]\n');
+ fprintf(' Eta: [ scalar | {0.1} ]\n');
+ fprintf(' EtaAlpha: [ scalar | {2.0} ]\n');
+ fprintf(' EtaGamma: [ scalar | {0.9} ]\n');
+ fprintf(' MinBoundEps: [ false | {true} ]\n');
+ fprintf(' Constraints: [ array of scalar ]\n');
+ fprintf('\n');
+ fprintf(' LinearSolver: [ {Dense} | Band | GMRES | BiCGStab | TFQMR ]\n');
+ fprintf(' JacobianFn: [ function ]\n');
+ fprintf(' KrylovMaxDim: [ scalar | {10} ]');
+ fprintf(' MaxNumRestarts: [ Classical | {Modified} ]\n');
+ fprintf(' PrecModule: [ BBDPre | {UserDefined} ]\n');
+ fprintf(' PrecSetupFn: [ function ]\n');
+ fprintf(' PrecSolveFn: [ function ]\n');
+ fprintf(' GlocalFn: [ function ]\n');
+ fprintf(' GcommFn: [ function ]\n');
+ fprintf(' LowerBwidth: [ scalar | {0} ]\n');
+ fprintf(' UpperBwidth: [ scalar | {0} ]\n');
+ fprintf(' LowerBwidthDQ: [ scalar | {0} ]\n');
+ fprintf(' UpperBwidthDQ: [ scalar | {0} ]\n');
+ fprintf('\n');
+ fprintf(' Verbose: [ true | {false} ]\n');
+ fprintf(' ErrorMessages: [ false | {true} ]\n');
+ fprintf('\n');
+ return;
+end
+
+KeyNames = {
+ 'UserData'
+ 'MaxNumIter'
+ 'MaxNumSetups'
+ 'MaxNumSubSetups'
+ 'MaxNumBetaFails'
+ 'EtaForm'
+ 'Eta'
+ 'EtaAlpha'
+ 'EtaGamma'
+ 'MaxNewtonStep'
+ 'FuncRelErr'
+ 'FuncNormTol'
+ 'ScaledStepTol'
+ 'InitialSetup'
+ 'MinBoundEps'
+ 'Constraints'
+ 'LinearSolver'
+ 'JacobianFn'
+ 'PrecType'
+ 'PrecModule'
+ 'PrecSetupFn'
+ 'PrecSolveFn'
+ 'GlocalFn'
+ 'GcommFn'
+ 'KrylovMaxDim'
+ 'MaxNumRestarts'
+ 'LowerBwidthDQ'
+ 'UpperBwidthDQ'
+ 'LowerBwidth'
+ 'UpperBwidth'
+ 'Verbose'
+ 'ErrorMessages'
+ };
+
+
+options = cvm_options(KeyNames,varargin{:});
+
+return;
+
+
+%
+% Actual option processing
+% ------------------------
+
+function options = kim_options(KeyNames, varargin)
+
+m = length(KeyNames);
+
+% Initialize the output options structure
+
+options = [];
+for i = 1:m
+ options.(KeyNames{i}) = [];
+end
+
+% If the first argument is an options structure, read its non-empty fields
+% and update options. Store in j the start of key-value pairs.
+
+arg = varargin{1};
+
+if isa(arg,'struct')
+ for i = 1:m
+ if isfield(arg,KeyNames{i})
+ options.(KeyNames{i}) = arg.(KeyNames{i});
+ end
+ end
+ j = 2;
+else
+ j = 1;
+end
+
+% The remaining input arguments must be key-value pairs
+
+if rem(nargin-j,2) ~= 0
+ error('Arguments must be key-value pairs.');
+end
+
+% Process each key-value pair
+
+np = (nargin-j)/2;
+
+keynames = lower(KeyNames);
+
+for i = 1:np
+
+ % Get the key
+ key = varargin{j};
+
+ % key must be a string
+ if ~isstr(key)
+ error(sprintf('Argument %d is not a string property name.', j));
+ end
+
+ % Get the index in keynames that exactly matches the current key
+ % (modulo the case)
+ ik = strmatch(lower(key), keynames, 'exact');
+ if isempty(ik)
+ error(sprintf('Unrecognized property "%s"', key));
+ end
+
+ % Get the value
+ val = varargin{j+1};
+
+ % Set the proper field in options
+ options.(KeyNames{ik}) = val;
+
+ % move to next pair
+ j = j+2;
+
+end
+
+return;
diff --git a/sundialsTB/kinsol/KINSol.m b/sundialsTB/kinsol/KINSol.m
new file mode 100644
index 0000000..750a893
--- /dev/null
+++ b/sundialsTB/kinsol/KINSol.m
@@ -0,0 +1,47 @@
+function [status, y] = KINSol(y0, strategy, yscale, fscale)
+%KINSol solves the nonlinear problem.
+%
+% Usage: [STATUS, Y] = KINSol(Y0, STRATEGY, YSCALE, FSCALE)
+%
+% KINSol manages the computational process of computing an approximate
+% solution of the nonlinear system. If the initial guess (initial value
+% assigned to vector Y0) doesn't violate any user-defined constraints,
+% then KINSol attempts to solve the system f(y)=0. If an iterative linear
+% solver was specified (see KINSetOptions), KINSol uses a nonlinear Krylov
+% subspace projection method. The Newton-Krylov iterations are stopped
+% if either of the following conditions is satisfied:
+%
+% ||f(y)||_L-infinity <= 0.01*fnormtol
+%
+% ||y[i+1] - y[i]||_L-infinity <= scsteptol
+%
+% However, if the current iterate satisfies the second stopping
+% criterion, it doesn't necessarily mean an approximate solution
+% has been found since the algorithm may have stalled, or the
+% user-specified step tolerance may be too large.
+%
+% STRATEGY specifies the global strategy applied to the Newton step if it is
+% unsatisfactory. Valid choices are 'None' or 'LineSearch'.
+% YSCALE is a vector containing diagonal elements of scaling matrix for vector
+% Y chosen so that the components of YSCALE*Y (as a matrix multiplication) all
+% have about the same magnitude when Y is close to a root of f(y)
+% FSCALE is a vector containing diagonal elements of scaling matrix for f(y)
+% chosen so that the components of FSCALE*f(Y) (as a matrix multiplication)
+% all have roughly the same magnitude when u is not too near a root of f(y)
+%
+% On return, status is one of the following:
+% 0: KINSol succeeded
+% 1: The initial y0 already satisfies the stopping criterion given above
+% 2: Stopping tolerance on scaled step length satisfied
+% -1: An error occurred (see printed error message)
+%
+% See also KINSetOptions, KINGetstats
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2005, The Regents of the University of California.
+% $Revision: 1.2 $Date: 2007/12/05 21:58:19 $
+
+mode = 2;
+
+[status, y] = kim(mode, y0, strategy, yscale, fscale);
+
diff --git a/sundialsTB/kinsol/examples_par/mkinDiagon_kry_p.m b/sundialsTB/kinsol/examples_par/mkinDiagon_kry_p.m
new file mode 100644
index 0000000..ed6a739
--- /dev/null
+++ b/sundialsTB/kinsol/examples_par/mkinDiagon_kry_p.m
@@ -0,0 +1,128 @@
+function [] = mkinDiagon_kry_p(comm)
+%mkinDiagon_kry_p - KINSOL example problem (parallel, GMRES)
+% Simple diagonal test, using user-supplied preconditioner setup and
+% solve routines.
+%
+% This example does a basic test of the solver by solving the system:
+% f(y) = 0 for
+% f(y) = y(i)^2 - i^2
+%
+% No scaling is done.
+% An approximate diagonal preconditioner is used.
+%
+% See also: mpirun
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2005, The Regents of the University of California.
+% $Revision: 1.2 $Date: 2007/12/05 21:58:19 $
+
+[status npes] = MPI_Comm_size(comm);
+[status mype] = MPI_Comm_rank(comm);
+
+% Problem size
+
+nlocal = 32;
+neq = npes * nlocal;
+
+% Problem options
+
+fnormtol = 1.0e-5;
+scsteptol = 1.0e-4;
+maxl = 10;
+maxlrst = 2;
+msbset = 5;
+
+% User data structure
+
+data.mype = mype; % MPI id
+data.nlocal = nlocal; % local problem size
+data.P = []; % workspace for preconditioner
+
+
+options = KINSetOptions('UserData', data,...
+ 'FuncNormTol', fnormtol,...
+ 'ScaledStepTol',scsteptol,...
+ 'LinearSolver','GMRES',....
+ 'KrylovMaxDim', maxl,...
+ 'MaxNumRestarts', maxlrst,...
+ 'MaxNumSetups', msbset,...
+ 'PrecSetupFn', at psetfn,...
+ 'PrecSolveFn', at psolfn);
+
+if mype==0
+ options = KINSetOptions(options,'Verbose',true);
+end
+
+KINInit(@sysfn, nlocal, options);
+
+% Initial guess and scale vector
+
+y0 = 2.0 * ([1:nlocal] + mype*nlocal);
+scale = ones(nlocal,1);
+
+% Solve problem using Inexact Newton
+
+strategy = 'None';
+[status, y] = KINSol(y0, strategy, scale, scale);
+
+% Print solution
+
+if status < 0
+ fprintf('KINSOL failed. status = %d\n',status);
+else
+ for i = 1:4:nlocal
+ fprintf('%4d | %6.2f %6.2f %6.2f %6.2f\n',...
+ i, y(i), y(i+1), y(i+2), y(i+3));
+ end
+end
+
+fprintf('DONE\n');
+
+
+% Free memory
+
+KINFree;
+
+% =======================================================
+
+function [fy, flag, new_data] = sysfn(y, data)
+
+nlocal = data.nlocal;
+mype = data.mype;
+baseadd = mype * nlocal;
+
+for i = 1:nlocal
+ fy(i) = y(i)^2 - (i+baseadd)^2;
+end
+
+new_data = []; % data was not modified
+flag = 0; % success
+
+% =======================================================
+
+function [flag, new_data] = psetfn(y,yscale,fy,fscale,data)
+
+nlocal = data.nlocal;
+
+for i = 1:nlocal
+ P(i) = 0.5 / (y(i)+5.0);
+end
+
+new_data = data;
+new_data.P = P;
+
+flag = 0;
+
+% =======================================================
+
+function [x, flag, new_data] = psolfn(y,yscale,fy,fscale,v,data)
+
+nlocal = data.nlocal;
+P = data.P;
+
+for i=1:nlocal
+ x(i) = v(i) * P(i);
+end
+
+new_data = [];
+flag = 0;
diff --git a/sundialsTB/kinsol/examples_ser/mkinDiagon_kry.m b/sundialsTB/kinsol/examples_ser/mkinDiagon_kry.m
new file mode 100644
index 0000000..061c18c
--- /dev/null
+++ b/sundialsTB/kinsol/examples_ser/mkinDiagon_kry.m
@@ -0,0 +1,104 @@
+function mkinDiagon_kry
+%mkinDiagon_kry - KINSOL example problem (serial, GMRES)
+% Simple diagonal test, using user-supplied preconditioner setup and
+% solve routines.
+%
+% This example does a basic test of the solver by solving the system:
+% f(y) = 0 for
+% f(y) = y(i)^2 - i^2
+%
+% No scaling is done.
+% An approximate diagonal preconditioner is used.
+%
+% See also: kindiag_sys kindag_pset kindiag_psol
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2005, The Regents of the University of California.
+% $Revision: 1.2 $Date: 2007/12/05 21:58:19 $
+
+neq = 128;
+
+strategy = 'None';
+
+fnormtol = 1.0e-5;
+scsteptol = 1.0e-4;
+maxl = 10;
+maxrs = 2;
+msbset = 5;
+
+data.P = [];
+
+options = KINSetOptions('UserData', data,...
+ 'Verbose',true,...
+ 'FuncNormTol', fnormtol,...
+ 'ScaledStepTol',scsteptol,...
+ 'LinearSolver','GMRES',....
+ 'KrylovMaxDim', maxl,...
+ 'MaxNumRestarts', maxrs,...
+ 'MaxNumSetups', msbset,...
+ 'PrecSetupFn', at psetfn,...
+ 'PrecSolveFn', at psolfn);
+KINInit(@sysfn, neq, options);
+
+y0 = 2.0*[1:neq]';
+scale = ones(neq,1);
+
+[status, y] = KINSol(y0, strategy, scale, scale);
+
+if status < 0
+ fprintf('KINSOL failed. status = %d\n',status);
+else
+ for i = 1:4:neq
+ fprintf('%4d | %6.2f %6.2f %6.2f %6.2f\n',...
+ i, y(i), y(i+1), y(i+2), y(i+3));
+ end
+end
+
+stats = KINGetStats;
+ls_stats = stats.LSInfo;
+
+stats
+ls_stats
+
+KINFree;
+
+
+% ============================================================
+
+function [fy, flag, new_data] = sysfn(y, data)
+
+neq = length(y);
+for i = 1:neq
+ fy(i) = y(i)^2 - i^2;
+end
+
+new_data = []; % data was not modified
+flag = 0; % success
+
+% ============================================================
+
+function [flag, new_data] = psetfn(y,yscale,fy,fscale,data)
+
+neq = length(y);
+
+for i = 1:neq
+ P(i) = 0.5 / (y(i)+5.0);
+end
+
+new_data.P = P; % updated P in data structure
+flag = 0; % success
+
+% ============================================================
+
+function [x, flag, new_data] = psolfn(y,yscale,fy,fscale,v,data)
+
+P = data.P;
+
+neq = length(y);
+
+for i=1:neq
+ x(i) = v(i) * P(i);
+end
+
+new_data = []; % data was not modified
+flag = 0; % success
diff --git a/sundialsTB/kinsol/examples_ser/mkinFerTron_dns.m b/sundialsTB/kinsol/examples_ser/mkinFerTron_dns.m
new file mode 100644
index 0000000..d7762c2
--- /dev/null
+++ b/sundialsTB/kinsol/examples_ser/mkinFerTron_dns.m
@@ -0,0 +1,182 @@
+function mkinFerTron_dns
+% mkinFerTron_dns - Ferraris-Tronconi test problem
+%
+% Source: "Handbook of Test Problems in Local and Global Optimization",
+% 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
+% 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.
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2007, The Regents of the University of California.
+% $Revision: 1.1 $Date: 2007/12/05 21:58:19 $
+
+
+% Initializations
+% ---------------
+
+% User data
+lb = [0.25 ; 1.5];
+ub = [1.0 ; 2*pi];
+data.lb = lb;
+data.ub = ub;
+
+% Number of problem variables
+nvar = 2;
+
+% Number of equations = number of problem vars. + number of bound variables
+neq = nvar + 2*nvar;
+
+% Function tolerance
+ftol = 1.0e-5;
+
+% Step tolerance
+stol = 1.0e-5;
+
+% Constraints
+constraints = [ 0 0 1 -1 1 -1];
+
+% Modified/exact Newton
+% msbset = 0 -> modified Newton
+% msbset = 1 -> exact Newton
+msbset = 0;
+
+% Initialize solver
+options = KINSetOptions('UserData', data, ...
+ 'FuncNormTol', ftol, ...
+ 'ScaledStepTol', stol, ...
+ 'Constraints', constraints, ...
+ 'MaxNumSetups', msbset, ...
+ 'LinearSolver', 'Dense');
+KINInit(@sysfn, neq, options);
+
+% Initial guess
+% -------------
+%
+% There are two known solutions for this problem
+%
+% the following initial guess should take us to (0.29945; 2.83693)
+x1 = lb(1);
+x2 = lb(2);
+u1 = [ x1 ; x2 ; x1-lb(1) ; x1-ub(1) ; x2-lb(2) ; x2-ub(2) ];
+% while this one should take us to (0.5; 3.1415926)
+x1 = 0.5*(lb(1)+ub(1));
+x2 = 0.5*(lb(2)+ub(2));
+u2 = [ x1 ; x2 ; x1-lb(1) ; x1-ub(1) ; x2-lb(2) ; x2-ub(2) ];
+
+% No Y and F scaling
+yscale = ones(neq,1);
+fscale = ones(neq,1);
+
+% No globalization
+strategy = 'None';
+
+
+fprintf('\nFerraris and Tronconi test problem\n');
+fprintf('Tolerance parameters:\n');
+fprintf(' fnormtol = %10.6g\n scsteptol = %10.6g\n', ftol, stol);
+if msbset == 1
+ fprintf('Exact Newton');
+else
+ fprintf('Modified Newton');
+end
+if strcmp(strategy,'None')
+ fprintf('\n');
+else
+ fprintf(' with line search\n');
+end
+
+% Solve problem starting from the 1st initial guess
+% -------------------------------------------------
+
+fprintf('\n------------------------------------------\n');
+fprintf('\nInitial guess on lower bounds\n');
+fprintf(' [x1,x2] = %8.6g %8.6g', u1(1), u1(2));
+
+[status, u1] = KINSol(u1, strategy, yscale, fscale);
+stats = KINGetStats;
+
+fprintf('\nsolution\n');
+fprintf(' [x1,x2] = %8.6g %8.6g', u1(1), u1(2));
+fprintf('\nSolver statistics:\n');
+fprintf(' nni = %5d nfe = %5d \n', stats.nni, stats.nfe);
+fprintf(' nje = %5d nfeD = %5d \n', stats.LSInfo.njeD, stats.LSInfo.nfeD);
+
+% Solve problem starting from the 2nd initial guess
+% -------------------------------------------------
+
+fprintf('\n------------------------------------------\n');
+fprintf('\nInitial guess in middle of feasible region\n');
+fprintf(' [x1,x2] = %8.6g %8.6g', u2(1), u2(2));
+
+[status, u2] = KINSol(u2, strategy, yscale, fscale);
+stats = KINGetStats;
+
+fprintf('\nsolution\n');
+fprintf(' [x1,x2] = %8.6g %8.6g', u2(1), u2(2));
+fprintf('\nSolver statistics:\n');
+fprintf(' nni = %5d nfe = %5d \n', stats.nni, stats.nfe);
+fprintf(' nje = %5d nfeD = %5d \n', stats.LSInfo.njeD, stats.LSInfo.nfeD);
+
+% Free memory
+% --------------------------------------
+
+KINFree;
+
+return
+
+
+% System function
+% ---------------
+
+function [fu, flag, new_data] = sysfn(u, data)
+
+lb = data.lb;
+ub = data.ub;
+
+x1 = u(1);
+x2 = u(2);
+l1 = u(3);
+L1 = u(4);
+l2 = u(5);
+L2 = u(6);
+
+e = exp(1);
+
+fu(1) = 0.5 * sin(x1*x2) - 0.25 * x2 / pi - 0.5 * x1;
+fu(2) = (1.0 - 0.25/pi)*(exp(2.0*x1)-e) + e*x2/pi - 2.0*e*x1;
+fu(3) = l1 - x1 + lb(1);
+fu(4) = L1 - x1 + ub(1);
+fu(5) = l2 - x2 + lb(2);
+fu(6) = L2 - x2 + ub(2);
+
+
+flag = 0;
+new_data = [];
+return
diff --git a/sundialsTB/kinsol/examples_ser/mkinRoboKin_dns.m b/sundialsTB/kinsol/examples_ser/mkinRoboKin_dns.m
new file mode 100644
index 0000000..a9a6f1f
--- /dev/null
+++ b/sundialsTB/kinsol/examples_ser/mkinRoboKin_dns.m
@@ -0,0 +1,248 @@
+function mkinRoboKin_dns
+% mkinRoboKin_dns - nonlinear system from robot kinematics.
+%
+% Source: "Handbook of Test Problems in Local and Global Optimization",
+% C.A. Floudas, P.M. Pardalos et al.
+% Kluwer Academic Publishers, 1999.
+% Test problem 6 from Section 14.1, Chapter 14
+%
+% The nonlinear system is solved by KINSOL using the DENSE linear solver.
+%
+% Constraints are imposed to make all components of the solution be
+% within [-1,1]. This is achieved by introducing additional "bound variables",
+% l_i = x_i + 1 and u-i = 1 - x_i, i = 1,...,nvar
+% and using the Constraints option to KINSOL to enforce l_i >=0 and u_i >= 0.
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2007, The Regents of the University of California.
+% $Revision: 1.1 $Date: 2007/12/05 21:58:19 $
+
+
+fprintf('\nRobot Kinematics Example\n');
+fprintf('8 variables; -1 <= x_i <= 1\n');
+fprintf('KINSOL problem size: 8 + 2*8 = 24 \n\n');
+
+% Number of problem variables
+nvar = 8;
+
+% Number of equations = number of problem vars. + number of bound variables
+neq = nvar + 2*nvar;
+
+% Function tolerance
+ftol = 1.0e-5;
+
+% Step tolerance
+stol = 1.0e-5;
+
+% Constraints (all bound variables non-negative)
+constraints = [ zeros(nvar,1); ones(nvar,1) ; ones(nvar,1) ];
+
+% Force exact Newton
+msbset = 1;
+
+% Initialize solver
+options = KINSetOptions('FuncNormTol', ftol, ...
+ 'ScaledStepTol', stol, ...
+ 'Constraints', constraints, ...
+ 'MaxNumSetups', msbset, ...
+ 'LinearSolver', 'Dense', ...
+ 'JacobianFn', @sysjac);
+KINInit(@sysfn, neq, options);
+
+% Initial guess
+y = ones(neq,1);
+y(1:nvar) = 1.0/sqrt(2);
+
+fprintf('Initial guess:\n');
+PrintOutput(y);
+
+% Call KINSol to solve the problem
+yscale = ones(neq,1);
+fscale = ones(neq,1);
+strategy = 'LineSearch';
+[status, y] = KINSol(y, strategy, yscale, fscale);
+
+fprintf('\nComputed solution:\n');
+PrintOutput(y);
+
+% Print final statistics and free memory
+stats = KINGetStats;
+ls_stats = stats.LSInfo;
+fprintf('\nSolver statistics:');
+stats
+ls_stats
+
+KINFree;
+
+return;
+
+% System function
+% ---------------
+
+function [fy, flag] = sysfn(y)
+
+% Extract problem variables and bound variables
+
+x1 = y(1); l1 = y( 9); u1 = y(17);
+x2 = y(2); l2 = y(10); u2 = y(18);
+x3 = y(3); l3 = y(11); u3 = y(19);
+x4 = y(4); l4 = y(12); u4 = y(20);
+x5 = y(5); l5 = y(13); u5 = y(21);
+x6 = y(6); l6 = y(14); u6 = y(22);
+x7 = y(7); l7 = y(15); u7 = y(23);
+x8 = y(8); l8 = y(16); u8 = y(24);
+
+% Nonlinear equations
+
+eq1 = - 0.1238*x1 + x7 - 0.001637*x2 - 0.9338*x4 + 0.004731*x1*x3 - 0.3578*x2*x3 - 0.3571;
+eq2 = 0.2638*x1 - x7 - 0.07745*x2 - 0.6734*x4 + 0.2238*x1*x3 + 0.7623*x2*x3 - 0.6022;
+eq3 = 0.3578*x1 + 0.004731*x2 + x6*x8;
+eq4 = - 0.7623*x1 + 0.2238*x2 + 0.3461;
+eq5 = x1*x1 + x2*x2 - 1;
+eq6 = x3*x3 + x4*x4 - 1;
+eq7 = x5*x5 + x6*x6 - 1;
+eq8 = x7*x7 + x8*x8 - 1;
+
+% Lower bounds ( l_i = 1 + x_i >= 0)
+
+lb1 = l1 - 1.0 - x1;
+lb2 = l2 - 1.0 - x2;
+lb3 = l3 - 1.0 - x3;
+lb4 = l4 - 1.0 - x4;
+lb5 = l5 - 1.0 - x5;
+lb6 = l6 - 1.0 - x6;
+lb7 = l7 - 1.0 - x7;
+lb8 = l8 - 1.0 - x8;
+
+% Upper bounds ( u_i = 1 - x_i >= 0)
+
+ub1 = u1 - 1.0 + x1;
+ub2 = u2 - 1.0 + x2;
+ub3 = u3 - 1.0 + x3;
+ub4 = u4 - 1.0 + x4;
+ub5 = u5 - 1.0 + x5;
+ub6 = u6 - 1.0 + x6;
+ub7 = u7 - 1.0 + x7;
+ub8 = u8 - 1.0 + x8;
+
+% Load residuals for the problem equations
+% and the equations encoding the constraints
+
+fy(1) = eq1; fy( 9) = lb1; fy(17) = ub1;
+fy(2) = eq2; fy(10) = lb2; fy(18) = ub2;
+fy(3) = eq3; fy(11) = lb3; fy(19) = ub3;
+fy(4) = eq4; fy(12) = lb4; fy(20) = ub4;
+fy(5) = eq5; fy(13) = lb5; fy(21) = ub5;
+fy(6) = eq6; fy(14) = lb6; fy(22) = ub6;
+fy(7) = eq7; fy(15) = lb7; fy(23) = ub7;
+fy(8) = eq8; fy(16) = lb8; fy(24) = ub8;
+
+flag = 0;
+
+return;
+
+
+% System Jacobian
+% ---------------
+
+function [J, flag] = sysjac(y, fy)
+
+% Extract problem variables
+
+x1 = y(1);
+x2 = y(2);
+x3 = y(3);
+x4 = y(4);
+x5 = y(5);
+x6 = y(6);
+x7 = y(7);
+x8 = y(8);
+
+% Nonlinear equations
+
+% - 0.1238*x1 + x7 - 0.001637*x2 - 0.9338*x4 + 0.004731*x1*x3 - 0.3578*x2*x3 - 0.3571
+
+J(1,1) = - 0.1238 + 0.004731*x3;
+J(1,2) = - 0.001637 - 0.3578*x3;
+J(1,3) = 0.004731*x1 - 0.3578*x2;
+J(1,4) = - 0.9338;
+J(1,7) = 1.0;
+
+% 0.2638*x1 - x7 - 0.07745*x2 - 0.6734*x4 + 0.2238*x1*x3 + 0.7623*x2*x3 - 0.6022
+
+J(2,1) = 0.2638 + 0.2238*x3;
+J(2,2) = - 0.07745 + 0.7623*x3;
+J(2,3) = 0.2238*x1 + 0.7623*x2;
+J(2,4) = - 0.6734;
+J(2,7) = -1.0;
+
+% 0.3578*x1 + 0.004731*x2 + x6*x8
+
+J(3,1) = 0.3578;
+J(3,2) = 0.004731;
+J(3,6) = x8;
+J(3,8) = x6;
+
+% - 0.7623*x1 + 0.2238*x2 + 0.3461
+
+J(4,1) = - 0.7623;
+J(4,2) = 0.2238;
+
+% x1*x1 + x2*x2 - 1
+
+J(5,1) = 2.0*x1;
+J(5,2) = 2.0*x2;
+
+% x3*x3 + x4*x4 - 1
+
+J(6,3) = 2.0*x3;
+J(6,4) = 2.0*x4;
+
+% x5*x5 + x6*x6 - 1
+
+J(7,5) = 2.0*x5;
+J(7,6) = 2.0*x6;
+
+% x7*x7 + x8*x8 - 1
+
+J(8,7) = 2.0*x7;
+J(8,8) = 2.0*x8;
+
+% Lower bounds ( l_i = 1 + x_i >= 0)
+% l_i - 1.0 - x_i
+
+for i=1:8
+ J(8+i,i) = -1.0;
+ J(8+i,8+i) = 1.0;
+end
+
+% Upper bounds ( u_i = 1 - x_i >= 0)
+% u_i - 1.0 + x_i
+
+for i=1:8
+ J(16+i,i) = 1.0;
+ J(16+i,16+i) = 1.0;
+end
+
+flag = 0;
+
+return
+
+
+
+% Print solution
+% --------------
+
+function PrintOutput(y)
+
+nvar = 8;
+
+fprintf(' l=x+1 x u=1-x\n');
+fprintf(' ----------------------------------\n');
+
+for i = 1:nvar
+ fprintf(' %10.6g %10.6g %10.6g\n', y(i+nvar), y(i), y(i+2*nvar));
+end
+
+return
+
diff --git a/sundialsTB/kinsol/examples_ser/mkinTest_dns.m b/sundialsTB/kinsol/examples_ser/mkinTest_dns.m
new file mode 100644
index 0000000..3113aab
--- /dev/null
+++ b/sundialsTB/kinsol/examples_ser/mkinTest_dns.m
@@ -0,0 +1,59 @@
+function mkinTest_dns
+%mkinTest_dns - KINSOL example problem (serial, dense)
+% Simple test problem for the Dense linear solver in KINSOL
+% This example solves the system
+% y(1)^2 + y(2)^2 = 1
+% y(2) = y(1)^2
+%
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2005, The Regents of the University of California.
+% $Revision: 1.2 $Date: 2007/12/05 21:58:19 $
+
+% Initialize problem
+neq = 2;
+fnormtol = 1.0e-5;
+scsteptol = 1.0e-4;
+msbset = 1; % force exact Newton
+options = KINSetOptions('FuncNormTol', fnormtol,...
+ 'ScaledStepTol',scsteptol,...
+ 'LinearSolver','Dense',....
+ 'MaxNumSetups', msbset);
+KINInit(@sysfn, neq, options);
+
+% Solve problem
+y0 = ones(neq,1);
+scale = ones(neq,1);
+strategy = 'LineSearch';
+[status, y] = KINSol(y0, strategy, scale, scale);
+
+% Evaluate system function at solution
+[fy, flag] = sysfn(y);
+
+% Print results
+fprintf('Solution: %10.4e %10.4e\n', y(1), y(2));
+fprintf('Residual: %10.4e %10.4e\n', fy(1), fy(2));
+
+slv_stats = KINGetStats;
+ls_stats = slv_stats.LSInfo;
+slv_stats
+ls_stats
+
+
+% Free memory
+KINFree;
+
+return
+
+% ===================================================================
+
+function [fy, flag] = sysfn(y)
+
+fy(1) = y(1)^2 + y(2)^2 - 1.0;
+fy(2) = y(2) - y(1)^2;
+
+flag = 0;
+
+return
+
+
diff --git a/sundialsTB/kinsol/function_types/KINBandJacFn.m b/sundialsTB/kinsol/function_types/KINBandJacFn.m
new file mode 100644
index 0000000..0bd4e54
--- /dev/null
+++ b/sundialsTB/kinsol/function_types/KINBandJacFn.m
@@ -0,0 +1,27 @@
+%KINBandJacFn - type for user provided banded Jacobian function.
+%
+% The function BJACFUN must be defined as
+% FUNCTION [J, FLAG] = BJACFUN(Y, FY)
+% and must return a matrix J corresponding to the banded Jacobian of f(y).
+% The input argument FY contains the current value of f(y).
+% If a user data structure DATA was specified in KINInit, then
+% BJACFUN must be defined as
+% FUNCTION [J, FLAG, NEW_DATA] = BJACFUN(Y, FY, DATA)
+% If the local modifications to the user data structure are needed in
+% other user-provided functions then, besides setting the matrix J and
+% the flag FLAG, the BJACFUN function must also set NEW_DATA. Otherwise,
+% it should set NEW_DATA=[] (do not set NEW_DATA = DATA as it would lead
+% to unnecessary copying).
+%
+% The function BJACFUN must set FLAG=0 if successful, FLAG<0 if an
+% unrecoverable failure occurred, or FLAG>0 if a recoverable error
+% occurred.
+%
+% See also KINSetOptions
+%
+% NOTE: BJACFUN is specified through the property JacobianFn to KINSetOptions
+% and is used only if the property LinearSolver was set to 'Band'.
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2005, The Regents of the University of California.
+% $Revision: 1.2 $Date: 2011/06/01 21:01:10 $
diff --git a/sundialsTB/kinsol/function_types/KINDenseJacFn.m b/sundialsTB/kinsol/function_types/KINDenseJacFn.m
new file mode 100644
index 0000000..74fbb41
--- /dev/null
+++ b/sundialsTB/kinsol/function_types/KINDenseJacFn.m
@@ -0,0 +1,27 @@
+%KINDenseJacFn - type for user provided dense Jacobian function.
+%
+% The function DJACFUN must be defined as
+% FUNCTION [J, FLAG] = DJACFUN(Y,FY)
+% and must return a matrix J corresponding to the Jacobian of f(y).
+% The input argument FY contains the current value of f(y).
+% If a user data structure DATA was specified in KINInit, then
+% DJACFUN must be defined as
+% FUNCTION [J, FLAG, NEW_DATA] = DJACFUN(Y,FY,DATA)
+% If the local modifications to the user data structure are needed in
+% other user-provided functions then, besides setting the matrix J and
+% the flag FLAG, the DJACFUN function must also set NEW_DATA. Otherwise,
+% it should set NEW_DATA=[] (do not set NEW_DATA = DATA as it would lead
+% to unnecessary copying).
+%
+% The function DJACFUN must set FLAG=0 if successful, FLAG<0 if an
+% unrecoverable failure occurred, or FLAG>0 if a recoverable error
+% occurred.
+%
+% See also KINSetOptions
+%
+% NOTE: DJACFUN is specified through the property JacobianFn to KINSetOptions
+% and is used only if the property LinearSolver was set to 'Dense'.
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2005, The Regents of the University of California.
+% $Revision: 1.2 $Date: 2011/06/01 21:01:10 $
diff --git a/sundialsTB/kinsol/function_types/KINGcommFn.m b/sundialsTB/kinsol/function_types/KINGcommFn.m
new file mode 100644
index 0000000..72ef194
--- /dev/null
+++ b/sundialsTB/kinsol/function_types/KINGcommFn.m
@@ -0,0 +1,33 @@
+%KINGcommFn - type for user provided communication function (BBDPre).
+%
+% The function GCOMFUN must be defined as
+% FUNCTION FLAG = GCOMFUN(Y)
+% and can be used to perform all interprocess communication necessary
+% to evaluate the approximate right-hand side function for the BBDPre
+% preconditioner module.
+% If a user data structure DATA was specified in KINInit, then
+% GCOMFUN must be defined as
+% FUNCTION [FLAG, NEW_DATA] = GCOMFUN(Y, DATA)
+% If the local modifications to the user data structure are needed
+% in other user-provided functions then the GCOMFUN function must also
+% set NEW_DATA. Otherwise, it should set NEW_DATA=[] (do not set
+% NEW_DATA = DATA as it would lead to unnecessary copying).
+%
+% The function GCOMFUN must set FLAG=0 if successful, FLAG<0 if an
+% unrecoverable failure occurred, or FLAG>0 if a recoverable error
+% occurred.
+%
+% See also KINGlocalFn, KINSetOptions
+%
+% NOTES:
+% GCOMFUN is specified through the GcommFn property in KINSetOptions
+% and is used only if the property PrecModule is set to 'BBDPre'.
+%
+% Each call to GCOMFUN is preceded by a call to the system function
+% SYSFUN with the same argument Y. Thus GCOMFUN can omit any communication
+% done by SYSFUN if relevant to the evaluation of G by GLOCFUN. If all
+% necessary communication was done by SYSFUN, GCOMFUN need not be provided.
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2005, The Regents of the University of California.
+% $Revision: 1.2 $Date: 2011/06/01 21:01:10 $
diff --git a/sundialsTB/kinsol/function_types/KINGlocalFn.m b/sundialsTB/kinsol/function_types/KINGlocalFn.m
new file mode 100644
index 0000000..4df5763
--- /dev/null
+++ b/sundialsTB/kinsol/function_types/KINGlocalFn.m
@@ -0,0 +1,28 @@
+%KINGlocalFn - type for user provided RHS approximation function (BBDPre).
+%
+% The function GLOCFUN must be defined as
+% FUNCTION [G, FLAG] = GLOCFUN(Y)
+% and must return a vector G corresponding to an approximation to f(y)
+% which will be used in the BBDPRE preconditioner module. The case where
+% G is mathematically identical to F is allowed.
+% If a user data structure DATA was specified in KINInit, then
+% GLOCFUN must be defined as
+% FUNCTION [G, FLAG, NEW_DATA] = GLOCFUN(Y, DATA)
+% If the local modifications to the user data structure are needed
+% in other user-provided functions then, besides setting the vector G,
+% the GLOCFUN function must also set NEW_DATA. Otherwise, it should set
+% NEW_DATA=[] (do not set NEW_DATA = DATA as it would lead to
+% unnecessary copying).
+%
+% The function GLOCFUN must set FLAG=0 if successful, FLAG<0 if an
+% unrecoverable failure occurred, or FLAG>0 if a recoverable error
+% occurred.
+%
+% See also KINGcommFn, KINSetOptions
+%
+% NOTE: GLOCFUN is specified through the GlocalFn property in KINSetOptions
+% and is used only if the property PrecModule is set to 'BBDPre'.
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2005, The Regents of the University of California.
+% $Revision: 1.2 $Date: 2011/06/01 21:01:10 $
diff --git a/sundialsTB/kinsol/function_types/KINJacTimesVecFn.m b/sundialsTB/kinsol/function_types/KINJacTimesVecFn.m
new file mode 100644
index 0000000..d1dab21
--- /dev/null
+++ b/sundialsTB/kinsol/function_types/KINJacTimesVecFn.m
@@ -0,0 +1,29 @@
+%KINJacTimesVecFn - type for user provided Jacobian times vector function.
+%
+% The function JTVFUN must be defined as
+% FUNCTION [JV, NEW_Y, FLAG] = JTVFUN(Y, V, NEW_Y)
+% and must return a vector JV corresponding to the product of the
+% Jacobian of f(y) with the vector v. On input, NEW_Y indicates if
+% the iterate has been updated in the interim. JV must be update
+% or reevaluated, if appropriate, unless NEW_Y=false. This flag must
+% be reset by the user.
+% If a user data structure DATA was specified in KINInit, then
+% JTVFUN must be defined as
+% FUNCTION [JV, NEW_Y, FLAG, NEW_DATA] = JTVFUN(Y, V, NEW_Y, DATA)
+% If the local modifications to the user data structure are needed in
+% other user-provided functions then, besides setting the vector JV, and
+% flags NEW_Y and FLAG, the JTVFUN function must also set NEW_DATA. Otherwise,
+% it should set NEW_DATA=[] (do not set NEW_DATA = DATA as it would lead to
+% unnecessary copying).
+%
+% If successful, FLAG should be set to 0. If an error occurs, FLAG should
+% be set to a nonzero value.
+%
+% See also KINSetOptions
+%
+% NOTE: JTVFUN is specified through the property JacobianFn to KINSetOptions
+% and is used only if the property LinearSolver was set to 'GMRES' or 'BiCGStab'.
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2005, The Regents of the University of California.
+% $Revision: 1.2 $Date: 2011/06/01 21:01:10 $
diff --git a/sundialsTB/kinsol/function_types/KINPrecSetupFn.m b/sundialsTB/kinsol/function_types/KINPrecSetupFn.m
new file mode 100644
index 0000000..26cc520
--- /dev/null
+++ b/sundialsTB/kinsol/function_types/KINPrecSetupFn.m
@@ -0,0 +1,48 @@
+%KINPrecSetupFn - type for user provided preconditioner setup function.
+%
+% The user-supplied preconditioner setup subroutine should compute
+% the right-preconditioner matrix P used to form the scaled preconditioned
+% linear system:
+%
+% (Df*J(y)*(P^-1)*(Dy^-1)) * (Dy*P*x) = Df*(-F(y))
+%
+% where Dy and Df denote the diagonal scaling matrices whose diagonal elements
+% are stored in the vectors YSCALE and FSCALE, respectively.
+%
+% 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 PRECSOLVE function requires no preparation, then a
+% preconditioner setup function need not be given.
+%
+% The function PSETFUN must be defined as
+% FUNCTION FLAG = PSETFUN(Y, YSCALE, FY, FSCALE)
+% The input argument FY contains the current value of f(y), while YSCALE
+% and FSCALE are the scaling vectors for solution and system function,
+% respectively (as passed to KINSol)
+%
+% If a user data structure DATA was specified in KINInit, then
+% PSETFUN must be defined as
+% FUNCTION [FLAG, NEW_DATA] = PSETFUN(Y, YSCALE, FY, FSCALE, DATA)
+% If the local modifications to the user data structure are needed in
+% other user-provided functions then, besides setting the flag FLAG,
+% the PSETFUN function must also set NEW_DATA. Otherwise, it should
+% set NEW_DATA=[] (do not set NEW_DATA = DATA as it would lead
+% to unnecessary copying).
+%
+% If successful, PSETFUN must return FLAG=0. For a recoverable error (in
+% which case the setup will be retried) it must set FLAG to a positive
+% integer value. If an unrecoverable error occurs, it must set FLAG
+% to a negative value, in which case the solver will halt.
+%
+% See also KINPrecSolveFn, KINSetOptions, KINSol
+%
+% NOTE: PSETFUN is specified through the property PrecSetupFn to KINSetOptions
+% and is used only if the property LinearSolver was set to 'GMRES' or 'BiCGStab'.
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2005, The Regents of the University of California.
+% $Revision: 1.2 $Date: 2011/06/01 21:01:10 $
diff --git a/sundialsTB/kinsol/function_types/KINPrecSolveFn.m b/sundialsTB/kinsol/function_types/KINPrecSolveFn.m
new file mode 100644
index 0000000..accdf97
--- /dev/null
+++ b/sundialsTB/kinsol/function_types/KINPrecSolveFn.m
@@ -0,0 +1,35 @@
+%KINPrecSolveFn - type for user provided preconditioner solve function.
+%
+% The user-supplied preconditioner solve function PSOLFN
+% is to solve a linear system P z = r in which the matrix P is
+% the preconditioner matrix (possibly set implicitely by PSETFUN)
+%
+% The function PSOLFUN must be defined as
+% FUNCTION [Z, FLAG] = PSOLFUN(Y, YSCALE, FY, FSCALE, R)
+% and must return a vector Z containing the solution of Pz=r.
+% The input argument FY contains the current value of f(y), while YSCALE
+% and FSCALE are the scaling vectors for solution and system function,
+% respectively (as passed to KINSol)
+%
+% If a user data structure DATA was specified in KINInit, then
+% PSOLFUN must be defined as
+% FUNCTION [Z, FLAG, NEW_DATA] = PSOLFUN(Y,YSCALE,FY,FSCALE,R,DATA)
+% If the local modifications to the user data structure are needed in
+% other user-provided functions then, besides setting the vector Z and
+% the flag FLAG, the PSOLFUN function must also set NEW_DATA. Otherwise,
+% it should set NEW_DATA=[] (do not set NEW_DATA = DATA as it would
+% lead to unnecessary copying).
+%
+% If successful, PSOLFUN must return FLAG=0. For a recoverable error it
+% must set FLAG to a positive value (in which case the solver will attempt
+% to correct). If an unrecoverable error occurs, it must set FLAG
+% to a negative value, in which case the solver will halt.
+%
+% See also KINPrecSetupFn, KINSetOptions
+%
+% NOTE: PSOLFUN is specified through the property PrecSolveFn to KINSetOptions
+% and is used only if the property LinearSolver was set to 'GMRES' or 'BiCGStab'.
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2005, The Regents of the University of California.
+% $Revision: 1.2 $Date: 2011/06/01 21:01:10 $
diff --git a/sundialsTB/kinsol/function_types/KINSysFn.m b/sundialsTB/kinsol/function_types/KINSysFn.m
new file mode 100644
index 0000000..d9788c5
--- /dev/null
+++ b/sundialsTB/kinsol/function_types/KINSysFn.m
@@ -0,0 +1,25 @@
+%KINSysFn - type for user provided system function
+%
+% The function SYSFUN must be defined as
+% FUNCTION [FY, FLAG] = SYSFUN(Y)
+% and must return a vector FY corresponding to f(y).
+% If a user data structure DATA was specified in KINInit, then
+% SYSFUN must be defined as
+% FUNCTION [FY, FLAG, NEW_DATA] = SYSFUN(Y,DATA)
+% If the local modifications to the user data structure are needed
+% in other user-provided functions then, besides setting the vector FY,
+% the SYSFUN function must also set NEW_DATA. Otherwise, it should set
+% NEW_DATA=[] (do not set NEW_DATA = DATA as it would lead to
+% unnecessary copying).
+%
+% The function SYSFUN must set FLAG=0 if successful, FLAG<0 if an
+% unrecoverable failure occurred, or FLAG>0 if a recoverable error
+% occurred.
+%
+% See also KINInit
+%
+% NOTE: SYSFUN is specified through the KINInit function.
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2005, The Regents of the University of California.
+% $Revision: 1.2 $Date: 2011/06/01 21:01:10 $
diff --git a/sundialsTB/kinsol/kim/Contents.m b/sundialsTB/kinsol/kim/Contents.m
new file mode 100644
index 0000000..18a1adb
--- /dev/null
+++ b/sundialsTB/kinsol/kim/Contents.m
@@ -0,0 +1,3 @@
+% MEX binding of KINSOL functions
+%
+%-- Radu Serban @ LLNL -- April 2005
diff --git a/sundialsTB/kinsol/kim/kim_bjac.m b/sundialsTB/kinsol/kim/kim_bjac.m
new file mode 100644
index 0000000..a4a0bb0
--- /dev/null
+++ b/sundialsTB/kinsol/kim/kim_bjac.m
@@ -0,0 +1,12 @@
+function [ret, flag, new_data] = kim_bjac(y, fy, fct, data)
+
+%
+% Wrapper around the actual user-provided Matlab function
+%
+
+if isempty(data)
+ [ret, flag] = feval(fct,y,fy);
+ new_data = [];
+else
+ [ret, flag, new_data] = feval(fct,y,fy,data);
+end
diff --git a/sundialsTB/kinsol/kim/kim_djac.m b/sundialsTB/kinsol/kim/kim_djac.m
new file mode 100644
index 0000000..077e267
--- /dev/null
+++ b/sundialsTB/kinsol/kim/kim_djac.m
@@ -0,0 +1,12 @@
+function [ret, flag, new_data] = kim_djac(y, fy, fct, data)
+
+%
+% Wrapper around the actual user-provided Matlab function
+%
+
+if isempty(data)
+ [ret, flag] = feval(fct,y,fy);
+ new_data = [];
+else
+ [ret, flag, new_data] = feval(fct,y,fy,data);
+end
diff --git a/sundialsTB/kinsol/kim/kim_gcom.m b/sundialsTB/kinsol/kim/kim_gcom.m
new file mode 100644
index 0000000..aea86a5
--- /dev/null
+++ b/sundialsTB/kinsol/kim/kim_gcom.m
@@ -0,0 +1,13 @@
+function [flag, new_data] = kim_gcom(y, f, data)
+
+%
+% Wrapper around the actual user-provided Matlab function
+%
+
+if isempty(data)
+ flag = feval(fct,y);
+ new_data = [];
+else
+ [flag, new_data] = feval(fct,y,data);
+end
+
diff --git a/sundialsTB/kinsol/kim/kim_gloc.m b/sundialsTB/kinsol/kim/kim_gloc.m
new file mode 100644
index 0000000..06f59b2
--- /dev/null
+++ b/sundialsTB/kinsol/kim/kim_gloc.m
@@ -0,0 +1,12 @@
+function [gval, flag, new_data] = kim_gloc(y, fct, data)
+
+%
+% Wrapper around the actual user-provided Matlab function
+%
+
+if isempty(data)
+ [gval, flag] = feval(fct,y);
+ new_data = [];
+else
+ [gval, flag, new_data] = feval(fct,y,data);
+end
diff --git a/sundialsTB/kinsol/kim/kim_info.m b/sundialsTB/kinsol/kim/kim_info.m
new file mode 100644
index 0000000..91d61a2
--- /dev/null
+++ b/sundialsTB/kinsol/kim/kim_info.m
@@ -0,0 +1,81 @@
+function varargout = kim_info(action, fin, message);
+
+switch action
+
+ case 0 % initialize
+
+ % Create figure
+
+ f = figure;
+
+ set(f,'resizefcn','kim_info(2,0,0)');
+ set(f,'name','KINSOL info','numbertitle','off');
+ set(f,'menubar','none','tag','figure');
+
+ % Create text box
+
+ tbpos=getTBPos(f);
+ h=uicontrol(f,'style','listbox','position',tbpos,'tag','textbox');
+ set(h,'BackgroundColor',[1 1 1]);
+ set(h,'SelectionHighlight','off');
+
+ % Create OK button
+
+ bpos=getOKPos(f);
+ h=uicontrol(f,'style','pushbutton','position',bpos,'string','Close','tag','okaybutton');
+ set(h,'callback','kim_info(3,0,0)');
+
+ % Save handles
+
+ handles=guihandles(f);
+ guidata(f,handles);
+
+ varargout{1} = f;
+
+ case 1 % append text
+
+ f = fin;
+ new_str = message;
+
+ handles=guidata(f);
+ string = get(handles.textbox,'String');
+ string{end+1}=new_str;
+ set(handles.textbox,'String',string);
+
+ case 2 % resize
+
+ handles=guidata(gcbo);
+ tbpos=getTBPos(handles.figure);
+ bpos=getOKPos(handles.figure);
+ set(handles.okaybutton,'position',bpos);
+ set(handles.textbox,'position',tbpos);
+
+ case 3 % close
+
+ handles=guidata(gcbo);
+ close(handles.figure);
+
+end
+
+%------------------------------------
+function tbpos=getTBPos(f)
+
+margins=[10 10 10 50]; % left, right, top, bottom
+pos=get(f,'position');
+tbpos=[margins(1) margins(4) pos(3)-margins(1)-margins(2) ...
+ pos(4)-margins(3)-margins(4)];
+tbpos(tbpos<1)=1;
+
+
+%------------------------------------
+function tbpos=getOKPos(f)
+
+bsize=[60,30];
+badjustpos=[0,25];
+
+pos=get(f,'position');
+
+tbpos=[pos(3)/2-bsize(1)/2+badjustpos(1) -bsize(2)/2+badjustpos(2)...
+ bsize(1) bsize(2)];
+tbpos=round(tbpos);
+tbpos(tbpos<1)=1;
diff --git a/sundialsTB/kinsol/kim/kim_jtv.m b/sundialsTB/kinsol/kim/kim_jtv.m
new file mode 100644
index 0000000..20513dd
--- /dev/null
+++ b/sundialsTB/kinsol/kim/kim_jtv.m
@@ -0,0 +1,12 @@
+function [ret, new_y, flag, new_data] = kim_jtv(y, v, new_y, fct, data)
+
+%
+% Wrapper around the actual user-provided Matlab function
+%
+
+if isempty(data)
+ [ret, new_y, flag] = feval(fct,y,v,new_y);
+ new_data = [];
+else
+ [ret, new_y, flag, new_data] = feval(fct,y,v,new_y,data);
+end
diff --git a/sundialsTB/kinsol/kim/kim_pset.m b/sundialsTB/kinsol/kim/kim_pset.m
new file mode 100644
index 0000000..61aca0b
--- /dev/null
+++ b/sundialsTB/kinsol/kim/kim_pset.m
@@ -0,0 +1,12 @@
+function [flag, new_data] = kim_pset(y, yscale, fy, fscale, fct, data)
+
+%
+% Wrapper around the actual user-provided Matlab function
+%
+
+if isempty(data)
+ flag = feval(fct,y,yscale,fy,fscale);
+ new_data =[];
+else
+ [flag, new_data] = feval(fct,y,yscale,fy,fscale,data);
+end
diff --git a/sundialsTB/kinsol/kim/kim_psol.m b/sundialsTB/kinsol/kim/kim_psol.m
new file mode 100644
index 0000000..17c3258
--- /dev/null
+++ b/sundialsTB/kinsol/kim/kim_psol.m
@@ -0,0 +1,11 @@
+function [ret, flag, new_data] = kim_psol(y, yscale, fy, fscale, v, fct, data)
+
+%
+% Wrapper around the actual user-provided Matlab function
+%
+if isempty(data)
+ [ret, flag] = feval(fct,y,yscale,fy,fscale,v);
+ new_data = [];
+else
+ [ret, flag, new_data] = feval(fct,y,yscale,fy,fscale,v,data);
+end
diff --git a/sundialsTB/kinsol/kim/kim_sys.m b/sundialsTB/kinsol/kim/kim_sys.m
new file mode 100644
index 0000000..4cd2825
--- /dev/null
+++ b/sundialsTB/kinsol/kim/kim_sys.m
@@ -0,0 +1,13 @@
+function [ret, flag, new_data] = kim_sys(y, fct, data)
+
+%
+% Wrapper around the actual user-provided Matlab function
+%
+
+if isempty(data)
+ [ret, flag] = feval(fct,y);
+ new_data = [];
+else
+ [ret, flag, new_data] = feval(fct,y,data);
+end
+
diff --git a/sundialsTB/kinsol/kim/src/kim.c b/sundialsTB/kinsol/kim/src/kim.c
new file mode 100644
index 0000000..9b1dc32
--- /dev/null
+++ b/sundialsTB/kinsol/kim/src/kim.c
@@ -0,0 +1,811 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.8 $
+ * $Date: 2012/03/07 21:50:32 $
+ * -----------------------------------------------------------------
+ * Programmer: 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 sundials-x.y.z/src/cvodes/LICENSE.
+ * -----------------------------------------------------------------
+ * MEX implementation for KINSOL Matlab interface.
+ * -----------------------------------------------------------------
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include "kim.h"
+#include "nvm.h"
+
+/*
+ * ---------------------------------------------------------------------------------
+ * Global interface data variable
+ * ---------------------------------------------------------------------------------
+ */
+
+kimInterfaceData kimData = NULL;
+
+/*
+ * ---------------------------------------------------------------------------------
+ * Static function prototypes
+ * ---------------------------------------------------------------------------------
+ */
+
+static void kimInitKINSOLdata();
+static void kimPersistKINSOLdata();
+static void kimFinalKINSOLdata();
+
+static int KIM_Initialization(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]);
+static int KIM_Solve(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]);
+static int KIM_Stats(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]);
+static int KIM_Get(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]);
+static int KIM_Set(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]);
+static int KIM_Free(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]);
+
+/*
+ * ---------------------------------------------------------------------------------
+ * Main entry point
+ * ---------------------------------------------------------------------------------
+ */
+
+void mexFunction(int nlhs, mxArray *plhs[],
+ int nrhs, const mxArray *prhs[] )
+{
+ int mode;
+ /*
+ Modes:
+
+ 1 - initialize KINSOL solver
+ 2 - solve problem
+ 3 - get solver stats
+ 4 - extract data from kin_mem
+ 5 - set one optional input at a time
+ 6 - finalize
+ */
+
+ mode = (int)mxGetScalar(prhs[0]);
+
+ mexUnlock();
+
+ if ( (mode != 1) && (kimData == NULL) ) {
+ mexErrMsgTxt("KINSOL - Illegal attempt to call before KINInit.");
+ }
+
+
+ switch(mode) {
+
+ case 1:
+ if (kimData != NULL) {
+ KIM_Free(nlhs, plhs, nrhs-1, &prhs[1]);
+ kimFinalKINSOLdata();
+ }
+ kimInitKINSOLdata();
+ KIM_Initialization(nlhs, plhs, nrhs-1, &prhs[1]);
+ break;
+
+ case 2:
+ KIM_Solve(nlhs, plhs, nrhs-1, &prhs[1]);
+ break;
+
+ case 3:
+ KIM_Stats(nlhs, plhs, nrhs-1, &prhs[1]);
+ break;
+
+ case 4:
+ KIM_Get(nlhs, plhs, nrhs-1, &prhs[1]);
+ break;
+
+ case 5:
+ KIM_Set(nlhs, plhs, nrhs-1, &prhs[1]);
+ break;
+
+ case 6:
+ KIM_Free(nlhs, plhs, nrhs-1, &prhs[1]);
+ kimFinalKINSOLdata();
+ break;
+
+ }
+
+ /* Unless this was the KINFree call,
+ * make data persistent and lock the MEX file */
+ if (mode != 6) {
+ kimPersistKINSOLdata();
+ mexLock();
+ }
+
+ return;
+}
+
+/*
+ * ---------------------------------------------------------------------------------
+ * Private functions to deal with the global data
+ * ---------------------------------------------------------------------------------
+ */
+
+static void kimInitKINSOLdata()
+{
+ mxArray *empty;
+
+ /* Allocate space for global KINSOL data structure */
+
+ kimData = (kimInterfaceData) mxMalloc(sizeof(struct kimInterfaceData_));
+
+ /* Initialize global KINSOL data */
+
+ kimData->kin_mem = NULL;
+
+ kimData->n = 0;
+
+ kimData->Y = NULL;
+
+ kimData->LS = LS_DENSE;
+ kimData->PM = PM_NONE;
+
+ kimData->errMsg = TRUE;
+
+ /* Initialize Matlab mex arrays to empty */
+
+ empty = mxCreateDoubleMatrix(0,0,mxREAL);
+
+ kimData->SYSfct = mxDuplicateArray(empty);
+ kimData->JACfct = mxDuplicateArray(empty);
+ kimData->PSETfct = mxDuplicateArray(empty);
+ kimData->PSOLfct = mxDuplicateArray(empty);
+ kimData->GLOCfct = mxDuplicateArray(empty);
+ kimData->GCOMfct = mxDuplicateArray(empty);
+
+ kimData->mtlb_data = mxDuplicateArray(empty);
+
+ mxDestroyArray(empty);
+
+ return;
+}
+
+static void kimPersistKINSOLdata()
+{
+ /* Make global memory persistent */
+
+ mexMakeArrayPersistent(kimData->mtlb_data);
+
+ mexMakeArrayPersistent(kimData->SYSfct);
+ mexMakeArrayPersistent(kimData->JACfct);
+ mexMakeArrayPersistent(kimData->PSETfct);
+ mexMakeArrayPersistent(kimData->PSOLfct);
+ mexMakeArrayPersistent(kimData->GLOCfct);
+ mexMakeArrayPersistent(kimData->GCOMfct);
+
+ mexMakeMemoryPersistent(kimData);
+
+ return;
+}
+
+static void kimFinalKINSOLdata()
+{
+ if (kimData == NULL) return;
+
+ if (kimData->Y != NULL) N_VDestroy(kimData->Y);
+
+ mxDestroyArray(kimData->mtlb_data);
+
+ mxDestroyArray(kimData->SYSfct);
+ mxDestroyArray(kimData->JACfct);
+ mxDestroyArray(kimData->PSETfct);
+ mxDestroyArray(kimData->PSOLfct);
+ mxDestroyArray(kimData->GLOCfct);
+ mxDestroyArray(kimData->GCOMfct);
+
+ mxFree(kimData);
+ kimData = NULL;
+
+ return;
+}
+
+/*
+ * ---------------------------------------------------------------------------------
+ * Error handler function.
+ *
+ * This function is both passed as the KINSOL error handler and used throughout
+ * the Matlab interface.
+ *
+ * If called directly by one of the interface functions, error_code = -999 to
+ * indicate an error and err_code = +999 to indicate a warning. Otherwise,
+ * err_code is set by the calling KINSOL function.
+ *
+ * NOTE: mexErrMsgTxt will end the execution of the MEX file. Therefore we do
+ * not have to intercept any of the KINSOL error return flags.
+ * The only return flags we intercept are those from CVode() and CVodeB()
+ * which are passed back to the user (only positive values will make it).
+ * ---------------------------------------------------------------------------------
+ */
+
+void kimErrHandler(int error_code,
+ const char *module, const char *function,
+ char *msg, void *eh_data)
+{
+ char err_msg[256];
+
+ if (!(kimData->errMsg)) return;
+
+ if (error_code > 0) {
+ sprintf(err_msg,"Warning in ==> %s\n%s",function,msg);
+ mexWarnMsgTxt(err_msg);
+ } else if (error_code < 0) {
+ /*mexUnlock();
+ kimFinalKINSOLdata();*/
+ sprintf(err_msg,"Error using ==> %s\n%s",function,msg);
+ mexErrMsgTxt(err_msg);
+ }
+
+ return;
+}
+
+/*
+ * ---------------------------------------------------------------------------------
+ * Info handler function
+ *
+ * This function is passed as the KINSOL info handler if verbose output was
+ * requested. It is a wrapper around the Matlab m-file kim_info.m which posts
+ * all info messages to a separate Matlab figure.
+ * ---------------------------------------------------------------------------------
+ */
+
+void kimInfoHandler(const char *module, const char *function,
+ char *msg, void *ih_data)
+{
+ char my_msg[400];
+ mxArray *mx_in[3];
+
+ sprintf(my_msg,"[%s] %s\n %s\n",module,function,msg);
+
+ /* action=1 -> append */
+ mx_in[0] = mxCreateDoubleScalar(1);
+ mx_in[1] = mxCreateDoubleScalar((double)kimData->fig_handle);
+ mx_in[2] = mxCreateString(my_msg);
+
+ mexCallMATLAB(0,NULL,3,mx_in,"kim_info");
+
+}
+
+/*
+ * ---------------------------------------------------------------------------------
+ * Redability replacements
+ * ---------------------------------------------------------------------------------
+ */
+
+#define kin_mem (kimData->kin_mem)
+
+#define y (kimData->Y)
+#define N (kimData->n)
+#define ls (kimData->LS)
+#define pm (kimData->PM)
+
+#define mtlb_data (kimData->mtlb_data)
+
+#define mtlb_SYSfct (kimData->SYSfct)
+#define mtlb_JACfct (kimData->JACfct)
+#define mtlb_PSETfct (kimData->PSETfct)
+#define mtlb_PSOLfct (kimData->PSOLfct)
+#define mtlb_GLOCfct (kimData->GLOCfct)
+#define mtlb_GCOMfct (kimData->GCOMfct)
+
+/*
+ * ---------------------------------------------------------------------------------
+ * Interface procedures
+ * ---------------------------------------------------------------------------------
+ */
+
+static int KIM_Initialization(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
+{
+ const mxArray *options;
+ mxArray *mx_in[3], *mx_out[2];
+
+ int status;
+
+ int mxiter, msbset, msbsetsub, etachoice, mxnbcf;
+ double eta, egamma, ealpha, mxnewtstep, relfunc, fnormtol, scsteptol;
+ booleantype verbose, errmsg, noInitSetup, noMinEps;
+
+ double *constraints;
+ N_Vector NVconstraints;
+
+ int ptype;
+ long int mudq, mldq, mupper, mlower;
+ int maxl, maxrs;
+ double dqrely;
+
+ /*
+ * ------------------------------------
+ * Initialize appropriate vector module
+ * ------------------------------------
+ */
+
+ InitVectors();
+
+ /*
+ * ----------------------------
+ * Extract stuff from arguments
+ * ----------------------------
+ */
+
+ /* Matlab user-provided function */
+
+ mxDestroyArray(mtlb_SYSfct);
+ mtlb_SYSfct = mxDuplicateArray(prhs[0]);
+
+ /* Problem dimension */
+
+ N = (long int) mxGetScalar(prhs[1]);
+
+ /* Solver Options (may be empty) */
+
+ options = prhs[2];
+
+ /* Create the solution N_Vector */
+
+ y = NewVector(N);
+
+ /*
+ * -----------------------------
+ * Process the options structure
+ * -----------------------------
+ */
+
+ status = get_SolverOptions(options,
+ &verbose, &errmsg,
+ &mxiter, &msbset, &msbsetsub, &etachoice, &mxnbcf,
+ &eta, &egamma, &ealpha, &mxnewtstep,
+ &relfunc, &fnormtol, &scsteptol,
+ &constraints,
+ &noInitSetup, &noMinEps);
+ if (status != 0) goto error_return;
+
+ /*
+ * ------------------------------------------------------
+ * Create KINSOL object, allocate memory, and set options
+ * ------------------------------------------------------
+ */
+
+ kin_mem = KINCreate();
+ if (kin_mem == NULL) goto error_return;
+
+ /* Attach the global KINSOL data as 'user_data' */
+ status = KINSetUserData(kin_mem, kimData);
+ if (status != KIN_SUCCESS) goto error_return;
+
+ /* Attach error handler function */
+ status = KINSetErrHandlerFn(kin_mem, kimErrHandler, NULL);
+ if (status != KIN_SUCCESS) goto error_return;
+
+ /* If verbose was set to TRUE */
+ if (verbose) {
+ /* Set print level to its highest value */
+ status = KINSetPrintLevel(kin_mem,3);
+ if (status != KIN_SUCCESS) goto error_return;
+ /* Attach info handler function */
+ status = KINSetInfoHandlerFn(kin_mem, kimInfoHandler, NULL);
+ if (status != KIN_SUCCESS) goto error_return;
+ /* Initialize the output window and store the figure handle */
+ mx_in[0] = mxCreateDoubleScalar(0); /* action=0, initialize */
+ mx_in[1] = mxCreateDoubleScalar(0); /* ignored */
+ mx_in[2] = mxCreateDoubleScalar(0); /* ignored */
+ mexCallMATLAB(1,mx_out,3,mx_in,"kim_info");
+ kimData->fig_handle = (int)*mxGetPr(mx_out[0]);
+ }
+
+ /* Call KINInit */
+ status = KINInit(kin_mem, mxW_KINSys, y);
+ if (status != KIN_SUCCESS) goto error_return;
+
+ /* Redirect output */
+ status = KINSetErrFile(kin_mem, stdout);
+ if (status != KIN_SUCCESS) goto error_return;
+
+ /* Optional inputs */
+ status = KINSetNumMaxIters(kin_mem, mxiter);
+ if (status != KIN_SUCCESS) goto error_return;
+ status = KINSetNoInitSetup(kin_mem, noInitSetup);
+ if (status != KIN_SUCCESS) goto error_return;
+ status = KINSetNoMinEps(kin_mem, noMinEps);
+ if (status != KIN_SUCCESS) goto error_return;
+ status = KINSetMaxSetupCalls(kin_mem, msbset);
+ if (status != KIN_SUCCESS) goto error_return;
+ status = KINSetMaxSubSetupCalls(kin_mem, msbsetsub);
+ if (status != KIN_SUCCESS) goto error_return;
+ status = KINSetMaxBetaFails(kin_mem, mxnbcf);
+ if (status != KIN_SUCCESS) goto error_return;
+ status = KINSetEtaForm(kin_mem, etachoice);
+ if (status != KIN_SUCCESS) goto error_return;
+ status = KINSetEtaConstValue(kin_mem, eta);
+ if (status != KIN_SUCCESS) goto error_return;
+ status = KINSetEtaParams(kin_mem, egamma, ealpha);
+ if (status != KIN_SUCCESS) goto error_return;
+ status = KINSetMaxNewtonStep(kin_mem, mxnewtstep);
+ if (status != KIN_SUCCESS) goto error_return;
+ status = KINSetRelErrFunc(kin_mem, relfunc);
+ if (status != KIN_SUCCESS) goto error_return;
+ status = KINSetFuncNormTol(kin_mem, fnormtol);
+ if (status != KIN_SUCCESS) goto error_return;
+ status = KINSetScaledStepTol(kin_mem, scsteptol);
+ if (status != KIN_SUCCESS) goto error_return;
+
+ /* Constraints */
+ if (constraints != NULL) {
+ NVconstraints = N_VCloneEmpty(y);
+ N_VSetArrayPointer(constraints, NVconstraints);
+ status = KINSetConstraints(kin_mem, NVconstraints);
+ if (status != KIN_SUCCESS) goto error_return;
+ N_VDestroy(NVconstraints);
+ }
+
+ /*
+ * --------------------
+ * Attach linear solver
+ * --------------------
+ */
+
+ status = get_LinSolvOptions(options,
+ &mupper, &mlower,
+ &mudq, &mldq, &dqrely,
+ &ptype, &maxrs, &maxl);
+ if (status != 0) goto error_return;
+
+ switch (ls) {
+
+ case LS_NONE:
+
+ kimErrHandler(-999, "KINSOL", "KINInit",
+ "No linear solver was specified.", NULL);
+ goto error_return;
+
+ case LS_DENSE:
+
+ status = KINDense(kin_mem, N);
+ if (status != KIN_SUCCESS) goto error_return;
+ if (!mxIsEmpty(mtlb_JACfct)) {
+ status = KINDlsSetDenseJacFn(kin_mem, mxW_KINDenseJac);
+ if (status != KIN_SUCCESS) goto error_return;
+ }
+
+ break;
+
+ case LS_BAND:
+
+ status = KINBand(kin_mem, N, mupper, mlower);
+ if (status != KIN_SUCCESS) goto error_return;
+ if (!mxIsEmpty(mtlb_JACfct)) {
+ status = KINDlsSetBandJacFn(kin_mem, mxW_KINBandJac);
+ if (status != KIN_SUCCESS) goto error_return;
+ }
+
+ break;
+
+ case LS_SPGMR:
+
+ status = KINSpgmr(kin_mem, maxl);
+ if (status != KIN_SUCCESS) goto error_return;
+ status = KINSpilsSetMaxRestarts(kin_mem, maxrs);
+ if (status != KIN_SUCCESS) goto error_return;
+
+ break;
+
+ case LS_SPBCG:
+
+ status = KINSpbcg(kin_mem, maxl);
+ if (status != KIN_SUCCESS) goto error_return;
+
+ break;
+
+ case LS_SPTFQMR:
+
+ status = KINSptfqmr(kin_mem, maxl);
+ if (status != KIN_SUCCESS) goto error_return;
+
+ break;
+
+ }
+
+ /* Jacobian * vector and preconditioner for SPILS linear solvers */
+
+ if ( (ls==LS_SPGMR) || (ls==LS_SPBCG) || (ls==LS_SPTFQMR) ) {
+
+ if (!mxIsEmpty(mtlb_JACfct)) {
+ status = KINSpilsSetJacTimesVecFn(kin_mem, mxW_KINSpilsJac);
+ if (status != KIN_SUCCESS) goto error_return;
+ }
+
+ switch (pm) {
+
+ case PM_NONE:
+
+ if (!mxIsEmpty(mtlb_PSOLfct)) {
+
+ if (!mxIsEmpty(mtlb_PSETfct)) status = KINSpilsSetPreconditioner(kin_mem, mxW_KINSpilsPset, mxW_KINSpilsPsol);
+ else status = KINSpilsSetPreconditioner(kin_mem, NULL, mxW_KINSpilsPsol);
+ if (status != KIN_SUCCESS) goto error_return;
+
+ }
+
+ break;
+
+ case PM_BBDPRE:
+
+ if (!mxIsEmpty(mtlb_GCOMfct)) status = KINBBDPrecInit(kin_mem, N, mudq, mldq, mupper, mlower, dqrely, mxW_KINGloc, mxW_KINGcom);
+ else status = KINBBDPrecInit(kin_mem, N, mudq, mldq, mupper, mlower, dqrely, mxW_KINGloc, NULL);
+ if (status != KIN_SUCCESS) goto error_return;
+
+ break;
+
+ }
+
+
+ }
+
+ /* Set errMsg field in global data
+ * (all error messages from here on will respect this) */
+
+ kimData->errMsg = errmsg;
+
+ /* Successfull return */
+
+ status = 0;
+ plhs[0] = mxCreateDoubleScalar((double)status);
+ return(0);
+
+ /* Error return */
+
+ error_return:
+ status = -1;
+ plhs[0] = mxCreateDoubleScalar((double)status);
+ return(-1);
+
+}
+
+static int KIM_Solve(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
+{
+ double *y0, *ys, *fs;
+ N_Vector yscale = NULL, fscale = NULL;
+ int buflen, status, strategy;
+ char *bufval;
+
+ /*
+ * ----------------------------------------------------------------
+ * Extract input arguments
+ * ----------------------------------------------------------------
+ */
+
+ /* Exract y0 and load initial guess in y */
+
+ y0 = mxGetPr(prhs[0]);
+ PutData(y, y0, N);
+
+ /* Extract strategy */
+
+ buflen = mxGetM(prhs[1]) * mxGetN(prhs[1]) + 1;
+ bufval = mxCalloc(buflen, sizeof(char));
+ status = mxGetString(prhs[1], bufval, buflen);
+ if(!strcmp(bufval,"None")) {
+ strategy = KIN_NONE;
+ } else if(!strcmp(bufval,"LineSearch")) {
+ strategy = KIN_LINESEARCH;
+ } else {
+ kimErrHandler(-999, "KINSOL", "KINSol",
+ "Illegal value for strategy.", NULL);
+ goto error_return;
+ }
+
+ /* Extract yscale */
+
+ ys = mxGetPr(prhs[2]);
+ yscale = N_VCloneEmpty(y);
+ N_VSetArrayPointer(ys, yscale);
+
+ /* Extract fscale */
+
+ fs = mxGetPr(prhs[3]);
+ fscale = N_VCloneEmpty(y);
+ N_VSetArrayPointer(fs, fscale);
+
+ /*
+ * -------------------------
+ * Call main solver function
+ * -------------------------
+ */
+
+ status = KINSol(kin_mem, y, strategy, yscale, fscale);
+ if (status < 0) goto error_return;
+
+ /* Extract solution vector */
+ plhs[1] = mxCreateDoubleMatrix(N,1,mxREAL);
+ GetData(y, mxGetPr(plhs[1]), N);
+
+ /* Free temporary vectors */
+ N_VDestroy(yscale);
+ N_VDestroy(fscale);
+
+ /* KINSOL return flag (only non-negative values make it here) */
+ plhs[0] = mxCreateDoubleScalar((double)status);
+ return(0);
+
+ error_return:
+ status = -1;
+ plhs[0] = mxCreateDoubleScalar((double)status);
+ plhs[1] = mxCreateDoubleMatrix(0,0,mxREAL);
+ if (yscale != NULL) N_VDestroy(yscale);
+ if (fscale != NULL) N_VDestroy(fscale);
+ return(-1);
+
+}
+
+static int KIM_Stats(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
+{
+ const char *fnames_solver[]={
+ "nfe",
+ "nni",
+ "nbcf",
+ "nbops",
+ "fnorm",
+ "step",
+ "LSInfo",
+ };
+ const char *fnames_dense[]={
+ "name",
+ "njeD",
+ "nfeD"
+ };
+ const char *fnames_band[]={
+ "name",
+ "njeD",
+ "nfeD"
+ };
+ const char *fnames_spils[]={
+ "name",
+ "nli",
+ "npe",
+ "nps",
+ "ncfl",
+ };
+
+ long int nfe, nni, nbcf, nbops;
+ double fnorm, step;
+
+ long int njeD, nfeD;
+ long int nli, npe, nps, ncfl;
+
+ mxArray *mx_ls;
+ int nfields;
+
+ int status;
+
+
+ if (kimData == NULL) return;
+
+ status = KINGetNumNonlinSolvIters(kin_mem, &nni);
+ if (status != KIN_SUCCESS) goto error_return;
+ status = KINGetNumFuncEvals(kin_mem, &nfe);
+ if (status != KIN_SUCCESS) goto error_return;
+ status = KINGetNumBetaCondFails(kin_mem, &nbcf);
+ if (status != KIN_SUCCESS) goto error_return;
+ status = KINGetNumBacktrackOps(kin_mem, &nbops);
+ if (status != KIN_SUCCESS) goto error_return;
+
+ status = KINGetFuncNorm(kin_mem, &fnorm);
+ if (status != KIN_SUCCESS) goto error_return;
+ status = KINGetStepLength(kin_mem, &step);
+ if (status != KIN_SUCCESS) goto error_return;
+
+ nfields = sizeof(fnames_solver)/sizeof(*fnames_solver);
+ plhs[0] = mxCreateStructMatrix(1, 1, nfields, fnames_solver);
+
+ mxSetField(plhs[0], 0, "nfe", mxCreateDoubleScalar((double)nfe));
+ mxSetField(plhs[0], 0, "nni", mxCreateDoubleScalar((double)nni));
+ mxSetField(plhs[0], 0, "nbcf", mxCreateDoubleScalar((double)nbcf));
+ mxSetField(plhs[0], 0, "nbops", mxCreateDoubleScalar((double)nbops));
+ mxSetField(plhs[0], 0, "fnorm", mxCreateDoubleScalar(fnorm));
+ mxSetField(plhs[0], 0, "step", mxCreateDoubleScalar(step));
+
+ /* Linear Solver Statistics */
+
+ switch(ls){
+
+ case LS_DENSE:
+
+ status = KINDlsGetNumJacEvals(kin_mem, &njeD);
+ if (status != KIN_SUCCESS) goto error_return;
+ status = KINDlsGetNumFuncEvals(kin_mem, &nfeD);
+ if (status != KIN_SUCCESS) goto error_return;
+
+ nfields = sizeof(fnames_dense)/sizeof(*fnames_dense);
+ mx_ls = mxCreateStructMatrix(1, 1, nfields, fnames_dense);
+
+ mxSetField(mx_ls, 0, "name", mxCreateString("Dense"));
+ mxSetField(mx_ls, 0, "njeD", mxCreateDoubleScalar((double)njeD));
+ mxSetField(mx_ls, 0, "nfeD", mxCreateDoubleScalar((double)nfeD));
+
+ break;
+
+ case LS_BAND:
+
+ status = KINDlsGetNumJacEvals(kin_mem, &njeD);
+ if (status != KIN_SUCCESS) goto error_return;
+ status = KINDlsGetNumFuncEvals(kin_mem, &nfeD);
+ if (status != KIN_SUCCESS) goto error_return;
+
+ nfields = sizeof(fnames_band)/sizeof(*fnames_band);
+ mx_ls = mxCreateStructMatrix(1, 1, nfields, fnames_band);
+
+ mxSetField(mx_ls, 0, "name", mxCreateString("Band"));
+ mxSetField(mx_ls, 0, "njeD", mxCreateDoubleScalar((double)njeD));
+ mxSetField(mx_ls, 0, "nfeD", mxCreateDoubleScalar((double)nfeD));
+
+ break;
+
+ case LS_SPGMR:
+ case LS_SPBCG:
+ case LS_SPTFQMR:
+
+ status = KINSpilsGetNumLinIters(kin_mem, &nli);
+ if (status != KIN_SUCCESS) goto error_return;
+ status = KINSpilsGetNumPrecEvals(kin_mem, &npe);
+ if (status != KIN_SUCCESS) goto error_return;
+ status = KINSpilsGetNumPrecSolves(kin_mem, &nps);
+ if (status != KIN_SUCCESS) goto error_return;
+ status = KINSpilsGetNumConvFails(kin_mem, &ncfl);
+ if (status != KIN_SUCCESS) goto error_return;
+
+ nfields = sizeof(fnames_spils)/sizeof(*fnames_spils);
+ mx_ls = mxCreateStructMatrix(1, 1, nfields, fnames_spils);
+
+ if (ls == LS_SPGMR)
+ mxSetField(mx_ls, 0, "name", mxCreateString("GMRES"));
+ else if (ls == LS_SPBCG)
+ mxSetField(mx_ls, 0, "name", mxCreateString("BiCGStab"));
+ else
+ mxSetField(mx_ls, 0, "name", mxCreateString("TFQMR"));
+
+ mxSetField(mx_ls, 0, "nli", mxCreateDoubleScalar((double)nli));
+ mxSetField(mx_ls, 0, "npe", mxCreateDoubleScalar((double)npe));
+ mxSetField(mx_ls, 0, "nps", mxCreateDoubleScalar((double)nps));
+ mxSetField(mx_ls, 0, "ncfl", mxCreateDoubleScalar((double)ncfl));
+
+ break;
+
+ }
+
+ mxSetField(plhs[0], 0, "LSInfo", mx_ls);
+
+ /* Successfull return */
+
+ status = 0;
+ plhs[1] = mxCreateDoubleScalar((double)status);
+ return(0);
+
+ /* Error return */
+
+ error_return:
+ status = -1;
+ plhs[1] = mxCreateDoubleScalar((double)status);
+ return(-1);
+
+}
+
+
+static int KIM_Set(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
+{
+ return(0);
+}
+
+static int KIM_Get(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
+{
+ return(0);
+}
+
+static int KIM_Free(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
+{
+ if (kimData == NULL) return(0);
+
+ KINFree(&kin_mem);
+
+ return;
+}
diff --git a/sundialsTB/kinsol/kim/src/kim.h b/sundialsTB/kinsol/kim/src/kim.h
new file mode 100644
index 0000000..9facbde
--- /dev/null
+++ b/sundialsTB/kinsol/kim/src/kim.h
@@ -0,0 +1,166 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.5 $
+ * $Date: 2012/03/07 21:50:32 $
+ * -----------------------------------------------------------------
+ * Programmer: 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 sundials-x.y.z/src/kinsol/LICENSE.
+ * -----------------------------------------------------------------
+ * Header file for the KINSOL Matlab interface.
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _KIM_H
+#define _KIM_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <string.h>
+#include <stdlib.h>
+#include "mex.h"
+#include <kinsol/kinsol.h>
+#include <kinsol/kinsol_dense.h>
+#include <kinsol/kinsol_band.h>
+#include <kinsol/kinsol_spgmr.h>
+#include <kinsol/kinsol_spbcgs.h>
+#include <kinsol/kinsol_sptfqmr.h>
+#include <kinsol/kinsol_bbdpre.h>
+
+/*
+ * ---------------------------------------------------------------------------------
+ * Constants
+ * ---------------------------------------------------------------------------------
+ */
+
+
+/* Linear solver types */
+
+enum {LS_NONE, LS_DENSE, LS_BAND, LS_SPGMR, LS_SPBCG, LS_SPTFQMR};
+
+/* Preconditioner modules */
+
+enum {PM_NONE, PM_BBDPRE};
+
+/*
+ * ---------------------------------------------------------------------------------
+ * Types for global data structures
+ * ---------------------------------------------------------------------------------
+ */
+
+typedef struct kimInterfaceData_ {
+
+ void *kin_mem; /* KINSOL solver memory */
+
+ long int n; /* problem dimension */
+
+ N_Vector Y; /* solution vector */
+
+ int LS; /* linear solver type */
+ int PM; /* preconditioner module */
+
+ booleantype errMsg; /* post error/warning messages? */
+
+ int fig_handle; /* figure for posting info */
+
+ /* Matlab functions and data associated with this problem */
+
+ mxArray *SYSfct;
+
+ mxArray *JACfct;
+
+ mxArray *PSETfct;
+ mxArray *PSOLfct;
+
+ mxArray *GLOCfct;
+ mxArray *GCOMfct;
+
+ mxArray *mtlb_data;
+
+} *kimInterfaceData;
+
+/*
+ * ---------------------------------------------------------------------------------
+ * Error and info handler functions
+ * ---------------------------------------------------------------------------------
+ */
+
+void kimErrHandler(int error_code,
+ const char *module, const char *function,
+ char *msg, void *eh_data);
+
+void kimInfoHandler(const char *module, const char *function,
+ char *msg, void *ih_data);
+
+/*
+ * ---------------------------------------------------------------------------------
+ * Wrapper functions
+ * ---------------------------------------------------------------------------------
+ */
+
+
+int mxW_KINSys(N_Vector y, N_Vector fy, void *user_data );
+
+/* Dense direct linear solver */
+
+int mxW_KINDenseJac(long int N,
+ N_Vector y, N_Vector fy,
+ DlsMat J, void *user_data,
+ N_Vector tmp1, N_Vector tmp2);
+
+/* Band direct linear solver */
+
+int mxW_KINBandJac(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);
+
+/* Scaled Preconditioned Iterative Linear Solver (SPGMR or SPBCG) */
+
+int mxW_KINSpilsJac(N_Vector v, N_Vector Jv,
+ N_Vector y, booleantype *new_y,
+ void *user_data);
+int mxW_KINSpilsPset(N_Vector y, N_Vector yscale,
+ N_Vector fy, N_Vector fscale,
+ void *user_data, N_Vector vtemp1,
+ N_Vector vtemp2);
+int mxW_KINSpilsPsol(N_Vector y, N_Vector yscale,
+ N_Vector fy, N_Vector fscale,
+ N_Vector v, void *user_data,
+ N_Vector vtemp);
+
+/* BBD Preconditioner */
+
+int mxW_KINGloc(long int Nlocal, N_Vector y, N_Vector gval, void *user_data);
+int mxW_KINGcom(long int Nlocal, N_Vector y, void *user_data);
+
+/*
+ * ---------------------------------------------------------------------------------
+ * Option handling functions
+ * ---------------------------------------------------------------------------------
+ */
+
+int get_SolverOptions(const mxArray *options,
+ booleantype *verbose, booleantype *errmsg,
+ int *mxiter, int *msbset, int *msbsetsub,
+ int *etachoice, int *mxnbcf,
+ double *eta, double *egamma, double *ealpha, double *mxnewtstep,
+ double *relfunc, double *fnormtol, double *scsteptol,
+ double **constraints,
+ booleantype *noInitSetup, booleantype *noMinEps);
+
+int get_LinSolvOptions(const mxArray *options,
+ long int *mupper, long int *mlower,
+ long int *mudq, long int *mldq, double *dqrely,
+ int *ptype, int *maxrs, int *maxl);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/sundialsTB/kinsol/kim/src/kimOpts.c b/sundialsTB/kinsol/kim/src/kimOpts.c
new file mode 100644
index 0000000..421d26d
--- /dev/null
+++ b/sundialsTB/kinsol/kim/src/kimOpts.c
@@ -0,0 +1,431 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.6 $
+ * $Date: 2012/03/07 21:50:32 $
+ * -----------------------------------------------------------------
+ * Programmer: 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 sundials-x.y.z/src/kinsol/LICENSE.
+ * -----------------------------------------------------------------
+ * Option parsing functions for the KINSOL Matlab interface.
+ * -----------------------------------------------------------------
+ */
+
+#include <string.h>
+#include "kim.h"
+
+/*
+ * ---------------------------------------------------------------------------------
+ * Global interface data variable (defined in kim.c)
+ * ---------------------------------------------------------------------------------
+ */
+
+extern kimInterfaceData kimData;
+
+/*
+ * ---------------------------------------------------------------------------------
+ * Redability replacements
+ * ---------------------------------------------------------------------------------
+ */
+
+#define N (kimData->n)
+#define ls (kimData->LS)
+#define pm (kimData->PM)
+
+#define mtlb_data (kimData->mtlb_data)
+
+#define mtlb_JACfct (kimData->JACfct)
+#define mtlb_PSETfct (kimData->PSETfct)
+#define mtlb_PSOLfct (kimData->PSOLfct)
+#define mtlb_GLOCfct (kimData->GLOCfct)
+#define mtlb_GCOMfct (kimData->GCOMfct)
+
+/*
+ * ---------------------------------------------------------------------------------
+ * Option handling functions
+ * ---------------------------------------------------------------------------------
+ */
+
+int get_SolverOptions(const mxArray *options,
+ booleantype *verbose, booleantype *errmsg,
+ int *mxiter, int *msbset, int *msbsetsub,
+ int *etachoice, int *mxnbcf,
+ double *eta, double *egamma, double *ealpha, double *mxnewtstep,
+ double *relfunc, double *fnormtol, double *scsteptol,
+ double **constraints,
+ booleantype *noInitSetup, booleantype *noMinEps)
+{
+ mxArray *opt;
+ char *bufval;
+ int buflen, status;
+ long int i, m, n;
+ double *tmp;
+
+ /* Set default values (pass 0 values. KINSOL does the rest) */
+
+ *mxiter = 0;
+ *msbset = 0;
+ *msbsetsub = 0;
+ *mxnbcf = 0;
+ *etachoice = KIN_ETACHOICE1;
+
+ *eta = 0.0;
+ *egamma = 0.0;
+ *ealpha = 0.0;
+ *mxnewtstep = 0.0;
+ *relfunc = 0.0;
+ *fnormtol = 0.0;
+ *scsteptol = 0.0;
+
+ *noInitSetup = FALSE;
+ *noMinEps = FALSE;
+
+ *constraints = NULL;
+
+ *verbose = FALSE;
+ *errmsg = TRUE;
+
+ /* Return now if options was empty */
+
+ if (mxIsEmpty(options)) return(0);
+
+ /* User data */
+
+ opt = mxGetField(options,0,"UserData");
+ if ( !mxIsEmpty(opt) ) {
+ mxDestroyArray(mtlb_data);
+ mtlb_data = mxDuplicateArray(opt);
+ }
+
+ /* Integer values */
+
+ opt = mxGetField(options,0,"MaxNumIter");
+ if ( !mxIsEmpty(opt) )
+ *mxiter = (int)*mxGetPr(opt);
+
+ opt = mxGetField(options,0,"MaxNumSetups");
+ if ( !mxIsEmpty(opt) )
+ *msbset = (int)*mxGetPr(opt);
+
+ opt = mxGetField(options,0,"MaxNumSubSetups");
+ if ( !mxIsEmpty(opt) )
+ *msbsetsub = (int)*mxGetPr(opt);
+
+ opt = mxGetField(options,0,"MaxNumBetaFails");
+ if ( !mxIsEmpty(opt) )
+ *mxnbcf = (int)*mxGetPr(opt);
+
+ opt = mxGetField(options,0,"EtaForm");
+ if ( !mxIsEmpty(opt) ) {
+ buflen = mxGetM(opt) * mxGetN(opt) + 1;
+ bufval = mxCalloc(buflen, sizeof(char));
+ status = mxGetString(opt, bufval, buflen);
+ if(status != 0) {
+ kimErrHandler(-999, "KINSOL", "KINInit", "Cannot parse EtaForm.", NULL);
+ return(-1);
+ }
+ if(!strcmp(bufval,"Type1")) *etachoice = KIN_ETACHOICE1;
+ else if(!strcmp(bufval,"Type2")) *etachoice = KIN_ETACHOICE2;
+ else if(!strcmp(bufval,"Constant")) *etachoice = KIN_ETACONSTANT;
+ else {
+ kimErrHandler(-999, "KINSOL", "KINInit", "EtaForm has an illegal value.", NULL);
+ return(-1);
+ }
+ }
+
+ /* Real values */
+
+ opt = mxGetField(options,0,"Eta");
+ if ( !mxIsEmpty(opt) )
+ *eta = (double)*mxGetPr(opt);
+
+ opt = mxGetField(options,0,"EtaAlpha");
+ if ( !mxIsEmpty(opt) )
+ *ealpha = (double)*mxGetPr(opt);
+
+ opt = mxGetField(options,0,"EtaGamma");
+ if ( !mxIsEmpty(opt) )
+ *egamma = (double)*mxGetPr(opt);
+
+ opt = mxGetField(options,0,"MaxNewtonStep");
+ if ( !mxIsEmpty(opt) )
+ *mxnewtstep = (double)*mxGetPr(opt);
+
+ opt = mxGetField(options,0,"FuncRelErr");
+ if ( !mxIsEmpty(opt) )
+ *relfunc = (double)*mxGetPr(opt);
+
+ opt = mxGetField(options,0,"FuncNormTol");
+ if ( !mxIsEmpty(opt) )
+ *fnormtol = (double)*mxGetPr(opt);
+
+ opt = mxGetField(options,0,"ScaledStepTol");
+ if ( !mxIsEmpty(opt) )
+ *scsteptol = (double)*mxGetPr(opt);
+
+ /* Boolean values */
+
+ opt = mxGetField(options,0,"ErrorMessages");
+ if ( !mxIsEmpty(opt) ) {
+ if (!mxIsLogical(opt)) {
+ kimErrHandler(-999, "KINSOL", "KINInit", "ErrorMessages is not a logical scalar.", NULL);
+ return(-1);
+ }
+ if (mxIsLogicalScalarTrue(opt)) *errmsg = TRUE;
+ else *errmsg = FALSE;
+ }
+
+ opt = mxGetField(options,0,"Verbose");
+ if ( !mxIsEmpty(opt) ) {
+ if (!mxIsLogical(opt)) {
+ kimErrHandler(-999, "KINSOL", "KINInit", "Verbose is not a logical scalar.", NULL);
+ return(-1);
+ }
+ if (mxIsLogicalScalarTrue(opt)) *verbose = TRUE;
+ else *verbose = FALSE;
+ }
+
+ opt = mxGetField(options,0,"InitialSetup");
+ if ( !mxIsEmpty(opt) ) {
+ if (!mxIsLogical(opt)) {
+ kimErrHandler(-999, "KINSOL", "KINInit", "InitialSetup is not a logical scalar.", NULL);
+ return(-1);
+ }
+ if (mxIsLogicalScalarTrue(opt)) *noInitSetup = FALSE;
+ else *noInitSetup = TRUE;
+ }
+
+
+ opt = mxGetField(options,0,"MinBoundEps");
+ if ( !mxIsEmpty(opt) ) {
+ if (!mxIsLogical(opt)) {
+ kimErrHandler(-999, "KINSOL", "KINInit", "MinBoundEps is not a logical scalar.", NULL);
+ return(-1);
+ }
+ if (mxIsLogicalScalarTrue(opt)) *noMinEps = FALSE;
+ else *noMinEps = TRUE;
+ }
+
+ /* Constraints */
+
+ opt = mxGetField(options,0,"Constraints");
+ if ( !mxIsEmpty(opt) ) {
+ m = mxGetM(opt);
+ n = mxGetN(opt);
+ if ( (n != 1) && (m != 1) ) {
+ kimErrHandler(-999, "KINSOL", "KINInit", "constraints is not a vector.", NULL);
+ return(-1);
+ }
+ if ( m > n ) n = m;
+ if ( n != N ) {
+ kimErrHandler(-999, "KINSOL", "KINInit", "constraints has wrong number of components.", NULL);
+ return(-1);
+ }
+ tmp = mxGetPr(opt);
+ *constraints = (double *) malloc(N*sizeof(double));
+ for (i=0;i<N;i++) (*constraints)[i] = tmp[i];
+ }
+
+ /* We made it here without problems */
+
+ return(0);
+}
+
+
+int get_LinSolvOptions(const mxArray *options,
+ long int *mupper, long int *mlower,
+ long int *mudq, long int *mldq, double *dqrely,
+ int *ptype, int *maxrs, int *maxl)
+{
+ mxArray *opt;
+ char *bufval;
+ int buflen, status;
+
+ *mupper = 0;
+ *mlower = 0;
+
+ *mudq = 0;
+ *mldq = 0;
+ *dqrely = 0.0;
+
+ *ptype = PREC_NONE;
+
+ *maxl = 0;
+ *maxrs = 0;
+
+ ls = LS_DENSE;
+ pm = PM_NONE;
+
+ /* Return now if options was empty */
+
+ if (mxIsEmpty(options)) return(0);
+
+ /* Linear solver type */
+
+ opt = mxGetField(options,0,"LinearSolver");
+ if ( !mxIsEmpty(opt) ) {
+ buflen = mxGetM(opt) * mxGetN(opt) + 1;
+ bufval = mxCalloc(buflen, sizeof(char));
+ status = mxGetString(opt, bufval, buflen);
+ if(status != 0) {
+ kimErrHandler(-999, "KINSOL", "KINInit", "Cannot parse LinearSolver.", NULL);
+ return(-1);
+ }
+ if(!strcmp(bufval,"Band")) ls = LS_BAND;
+ else if(!strcmp(bufval,"GMRES")) ls = LS_SPGMR;
+ else if(!strcmp(bufval,"BiCGStab")) ls = LS_SPBCG;
+ else if(!strcmp(bufval,"TFQMR")) ls = LS_SPTFQMR;
+ else if(!strcmp(bufval,"Dense")) ls = LS_DENSE;
+ else {
+ kimErrHandler(-999, "KINSOL", "KINInit", "LinearSolver has an illegal value.", NULL);
+ return(-1);
+ }
+ }
+
+ /* Jacobian function */
+
+ opt = mxGetField(options,0,"JacobianFn");
+ if ( !mxIsEmpty(opt) ) {
+ mxDestroyArray(mtlb_JACfct);
+ mtlb_JACfct = mxDuplicateArray(opt);
+ }
+
+ /* Band linear solver */
+
+ if (ls==LS_BAND) {
+
+ opt = mxGetField(options,0,"UpperBwidth");
+ if ( !mxIsEmpty(opt) )
+ *mupper = (long int)*mxGetPr(opt);
+
+ opt = mxGetField(options,0,"LowerBwidth");
+ if ( !mxIsEmpty(opt) )
+ *mlower = (long int)*mxGetPr(opt);
+
+ }
+
+ /* SPGMR linear solver options */
+
+ if (ls==LS_SPGMR) {
+
+ opt = mxGetField(options,0,"MaxNumRestarts");
+ if ( !mxIsEmpty(opt) )
+ *maxrs = (int)*mxGetPr(opt);
+
+ }
+
+ /* SPILS linear solver options */
+
+ if ( (ls==LS_SPGMR) || (ls==LS_SPBCG) || (ls==LS_SPTFQMR) ) {
+
+ /* Max. dimension of Krylov subspace */
+
+ opt = mxGetField(options,0,"KrylovMaxDim");
+ if ( !mxIsEmpty(opt) ) {
+ *maxl = (int)*mxGetPr(opt);
+ if (*maxl < 0) {
+ kimErrHandler(-999, "KINSOL", "KINInit", "KrylovMaxDim is negative.", NULL);
+ return(-1);
+ }
+ }
+
+ /* Preconditioning type */
+
+ opt = mxGetField(options,0,"PrecType");
+ if ( !mxIsEmpty(opt) ) {
+ buflen = mxGetM(opt) * mxGetN(opt) + 1;
+ bufval = mxCalloc(buflen, sizeof(char));
+ status = mxGetString(opt, bufval, buflen);
+ if(status != 0) {
+ kimErrHandler(-999, "KINSOL", "KINInit", "Cannot parse PrecType.", NULL);
+ return(-1);
+ }
+ if(!strcmp(bufval,"Right")) *ptype = PREC_RIGHT;
+ else if(!strcmp(bufval,"None")) *ptype = PREC_NONE;
+ else {
+ kimErrHandler(-999, "KINSOL", "KINInit", "PrecType has an illegal value.", NULL);
+ return(-1);
+ }
+ }
+
+ /* User defined precoditioning */
+
+ opt = mxGetField(options,0,"PrecSetupFn");
+ if ( !mxIsEmpty(opt) ) {
+ mxDestroyArray(mtlb_PSETfct);
+ mtlb_PSETfct = mxDuplicateArray(opt);
+ }
+
+ opt = mxGetField(options,0,"PrecSolveFn");
+ if ( !mxIsEmpty(opt) ) {
+ mxDestroyArray(mtlb_PSOLfct);
+ mtlb_PSOLfct = mxDuplicateArray(opt);
+ }
+
+ /* Preconditioner module */
+
+ opt = mxGetField(options,0,"PrecModule");
+ if ( !mxIsEmpty(opt) ) {
+ buflen = mxGetM(opt) * mxGetN(opt) + 1;
+ bufval = mxCalloc(buflen, sizeof(char));
+ status = mxGetString(opt, bufval, buflen);
+ if(status != 0) {
+ kimErrHandler(-999, "KINSOL", "KINInit", "Cannot parse PrecModule.", NULL);
+ return(-1);
+ }
+ if(!strcmp(bufval,"BBDPre")) pm = PM_BBDPRE;
+ else if(!strcmp(bufval,"UserDefined")) pm = PM_NONE;
+ else {
+ kimErrHandler(-999, "KINSOL", "KINInit", "PrecModule has an illegal value.", NULL);
+ return(-1);
+ }
+ }
+
+
+ if (pm == PM_BBDPRE) {
+
+ opt = mxGetField(options,0,"UpperBwidth");
+ if ( !mxIsEmpty(opt) )
+ *mupper = (long int)*mxGetPr(opt);
+
+ opt = mxGetField(options,0,"LowerBwidth");
+ if ( !mxIsEmpty(opt) )
+ *mlower = (long int)*mxGetPr(opt);
+
+ opt = mxGetField(options,0,"UpperBwidthDQ");
+ if ( !mxIsEmpty(opt) )
+ *mudq = (long int)*mxGetPr(opt);
+
+ opt = mxGetField(options,0,"LowerBwidthDQ");
+ if ( !mxIsEmpty(opt) )
+ *mldq = (long int)*mxGetPr(opt);
+
+ opt = mxGetField(options,0,"GlocalFn");
+ if ( !mxIsEmpty(opt) ) {
+ mxDestroyArray(mtlb_GLOCfct);
+ mtlb_GLOCfct = mxDuplicateArray(opt);
+ }
+ else {
+ kimErrHandler(-999, "KINSOL", "KINInit", "GlocalFn required for BBD preconditioner.", NULL);
+ return(-1);
+ }
+
+ opt = mxGetField(options,0,"GcommFn");
+ if ( !mxIsEmpty(opt) ) {
+ mxDestroyArray(mtlb_GCOMfct);
+ mtlb_GCOMfct = mxDuplicateArray(opt);
+ }
+
+ }
+
+ }
+
+ /* We made it here without problems */
+
+ return(0);
+
+}
+
diff --git a/sundialsTB/kinsol/kim/src/kimWrap.c b/sundialsTB/kinsol/kim/src/kimWrap.c
new file mode 100644
index 0000000..51d8984
--- /dev/null
+++ b/sundialsTB/kinsol/kim/src/kimWrap.c
@@ -0,0 +1,388 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.6 $
+ * $Date: 2012/03/07 21:50:32 $
+ * -----------------------------------------------------------------
+ * Programmer: 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 sundials-x.y.z/src/kinsol/LICENSE.
+ * -----------------------------------------------------------------
+ * KINSOL wrapper functions.
+ * -----------------------------------------------------------------
+ */
+
+#include "kim.h"
+#include "nvm.h"
+
+static void UpdateUserData(mxArray *new_mtlb_data, kimInterfaceData kimData);
+
+/*
+ * ---------------------------------------------------------------------------------
+ * Redability replacements
+ * ---------------------------------------------------------------------------------
+ */
+
+#define N (kimData->n)
+#define ls (kimData->LS)
+#define pm (kimData->PM)
+
+/*
+ * ---------------------------------------------------------------------------------
+ * Wrapper functions
+ * ---------------------------------------------------------------------------------
+ */
+
+int mxW_KINSys(N_Vector y, N_Vector fy, void *user_data )
+{
+ kimInterfaceData kimData;
+ mxArray *mx_in[3], *mx_out[3];
+ int ret;
+
+ /* Extract global interface data from user-data */
+ kimData = (kimInterfaceData) user_data;
+
+ /* Inputs to the Matlab function */
+ mx_in[0] = mxCreateDoubleMatrix(N,1,mxREAL); /* current y */
+ mx_in[1] = kimData->SYSfct; /* matlab function handle */
+ mx_in[2] = kimData->mtlb_data; /* matlab user data */
+
+ /* Call matlab wrapper */
+
+ GetData(y, mxGetPr(mx_in[0]), N);
+
+ mexCallMATLAB(3,mx_out,3,mx_in,"kim_sys");
+
+ PutData(fy, mxGetPr(mx_out[0]), N);
+ ret = (int)*mxGetPr(mx_out[1]);
+ if (!mxIsEmpty(mx_out[2])) {
+ UpdateUserData(mx_out[2], kimData);
+ }
+
+ /* Free temporary space */
+ mxDestroyArray(mx_in[0]);
+ mxDestroyArray(mx_out[0]);
+ mxDestroyArray(mx_out[1]);
+ mxDestroyArray(mx_out[2]);
+
+ return(ret);
+}
+
+int mxW_KINDenseJac(long int Neq,
+ N_Vector y, N_Vector fy,
+ DlsMat J, void *user_data,
+ N_Vector tmp1, N_Vector tmp2)
+{
+ kimInterfaceData kimData;
+ double *J_data;
+ mxArray *mx_in[4], *mx_out[3];
+ int i, ret;
+
+ /* Extract global interface data from user-data */
+ kimData = (kimInterfaceData) user_data;
+
+ /* Inputs to the Matlab function */
+ mx_in[0] = mxCreateDoubleMatrix(N,1,mxREAL); /* current y */
+ mx_in[1] = mxCreateDoubleMatrix(N,1,mxREAL); /* current fy */
+ mx_in[2] = kimData->JACfct; /* matlab function handle */
+ mx_in[3] = kimData->mtlb_data; /* matlab user data */
+
+ /* Call matlab wrapper */
+
+ GetData(y, mxGetPr(mx_in[0]), N);
+ GetData(fy, mxGetPr(mx_in[1]), N);
+
+ mexCallMATLAB(3,mx_out,4,mx_in,"kim_djac");
+
+ J_data = mxGetPr(mx_out[0]);
+ for (i=0;i<N;i++) memcpy(DENSE_COL(J,i), J_data + i*N, N*sizeof(double));
+ ret = (int)*mxGetPr(mx_out[1]);
+
+ if (!mxIsEmpty(mx_out[2])) {
+ UpdateUserData(mx_out[2], kimData);
+ }
+
+ /* Free temporary space */
+ mxDestroyArray(mx_in[0]);
+ mxDestroyArray(mx_in[1]);
+ mxDestroyArray(mx_out[0]);
+ mxDestroyArray(mx_out[1]);
+ mxDestroyArray(mx_out[2]);
+
+ return(ret);
+}
+
+
+int mxW_KINBandJac(long int Neq, long int mupper, long int mlower,
+ N_Vector y, N_Vector fy,
+ DlsMat J, void *user_data,
+ N_Vector tmp1, N_Vector tmp2)
+{
+ kimInterfaceData kimData;
+ double *J_data;
+ mxArray *mx_in[4], *mx_out[3];
+ long int eband, i;
+ int ret;
+
+ /* Extract global interface data from user-data */
+ kimData = (kimInterfaceData) user_data;
+
+ /* Inputs to the Matlab function */
+ mx_in[0] = mxCreateDoubleMatrix(N,1,mxREAL); /* current y */
+ mx_in[1] = mxCreateDoubleMatrix(N,1,mxREAL); /* current fy */
+ mx_in[2] = kimData->JACfct; /* matlab function handle */
+ mx_in[3] = kimData->mtlb_data; /* matlab user data */
+
+ /* Call matlab wrapper */
+
+ GetData(y, mxGetPr(mx_in[0]), N);
+ GetData(fy, mxGetPr(mx_in[1]), N);
+
+ mexCallMATLAB(3,mx_out,4,mx_in,"kim_bjac");
+
+ eband = mupper + mlower + 1;
+ J_data = mxGetPr(mx_out[0]);
+ for (i=0;i<N;i++) memcpy(BAND_COL(J,i) - mupper, J_data + i*eband, eband*sizeof(double));
+ ret = (int)*mxGetPr(mx_out[1]);
+
+ if (!mxIsEmpty(mx_out[2])) {
+ UpdateUserData(mx_out[2], kimData);
+ }
+
+ /* Free temporary space */
+ mxDestroyArray(mx_in[0]);
+ mxDestroyArray(mx_in[1]);
+ mxDestroyArray(mx_out[0]);
+ mxDestroyArray(mx_out[1]);
+ mxDestroyArray(mx_out[2]);
+
+ return(ret);
+}
+
+int mxW_KINSpilsJac(N_Vector v, N_Vector Jv,
+ N_Vector y, booleantype *new_y,
+ void *user_data)
+{
+ kimInterfaceData kimData;
+ mxArray *mx_in[5], *mx_out[4];
+ int ret;
+
+ /* Extract global interface data from user-data */
+ kimData = (kimInterfaceData) user_data;
+
+ /* Inputs to the Matlab function */
+ mx_in[0] = mxCreateDoubleMatrix(N,1,mxREAL); /* current y */
+ mx_in[1] = mxCreateDoubleMatrix(N,1,mxREAL); /* vector v */
+ mx_in[2] = mxCreateLogicalScalar(*new_y); /* */
+ mx_in[3] = kimData->JACfct; /* matlab function handle */
+ mx_in[4] = kimData->mtlb_data; /* matlab user data */
+
+ /* Call matlab wrapper */
+
+ GetData(y, mxGetPr(mx_in[0]), N);
+ GetData(v, mxGetPr(mx_in[1]), N);
+
+ mexCallMATLAB(4,mx_out,5,mx_in,"kim_jtv");
+
+ PutData(Jv, mxGetPr(mx_out[0]), N);
+ *new_y = mxIsLogicalScalarTrue(mx_out[1]);
+ ret = (int)*mxGetPr(mx_out[2]);
+
+ if (!mxIsEmpty(mx_out[3])) {
+ UpdateUserData(mx_out[3], kimData);
+ }
+
+ /* Free temporary space */
+ mxDestroyArray(mx_in[0]);
+ mxDestroyArray(mx_in[1]);
+ mxDestroyArray(mx_in[2]);
+ mxDestroyArray(mx_out[0]);
+ mxDestroyArray(mx_out[1]);
+ mxDestroyArray(mx_out[2]);
+ mxDestroyArray(mx_out[3]);
+
+ return(ret);
+}
+
+int mxW_KINSpilsPset(N_Vector y, N_Vector yscale,
+ N_Vector fy, N_Vector fscale,
+ void *user_data, N_Vector vtemp1,
+ N_Vector vtemp2)
+{
+ kimInterfaceData kimData;
+ mxArray *mx_in[6], *mx_out[2];
+ int ret;
+
+ /* Extract global interface data from user-data */
+ kimData = (kimInterfaceData) user_data;
+
+ /* Inputs to the Matlab function */
+ mx_in[0] = mxCreateDoubleMatrix(N,1,mxREAL); /* current y */
+ mx_in[1] = mxCreateDoubleMatrix(N,1,mxREAL); /* current yscale */
+ mx_in[2] = mxCreateDoubleMatrix(N,1,mxREAL); /* current fy */
+ mx_in[3] = mxCreateDoubleMatrix(N,1,mxREAL); /* current fscale */
+ mx_in[4] = kimData->PSETfct; /* matlab function handle */
+ mx_in[5] = kimData->mtlb_data; /* matlab user data */
+
+ /* Call matlab wrapper */
+
+ GetData(y, mxGetPr(mx_in[0]), N);
+ GetData(yscale, mxGetPr(mx_in[1]), N);
+ GetData(fy, mxGetPr(mx_in[2]), N);
+ GetData(fscale, mxGetPr(mx_in[3]), N);
+
+ mexCallMATLAB(2,mx_out,6,mx_in,"kim_pset");
+
+ ret = (int)*mxGetPr(mx_out[0]);
+
+ if (!mxIsEmpty(mx_out[1])) {
+ UpdateUserData(mx_out[1], kimData);
+ }
+
+ /* Free temporary space */
+ mxDestroyArray(mx_in[0]);
+ mxDestroyArray(mx_in[1]);
+ mxDestroyArray(mx_in[2]);
+ mxDestroyArray(mx_in[3]);
+ mxDestroyArray(mx_out[0]);
+ mxDestroyArray(mx_out[1]);
+
+ return(ret);
+}
+
+int mxW_KINSpilsPsol(N_Vector y, N_Vector yscale,
+ N_Vector fy, N_Vector fscale,
+ N_Vector v, void *user_data,
+ N_Vector vtemp)
+{
+ kimInterfaceData kimData;
+ mxArray *mx_in[7], *mx_out[3];
+ int ret;
+
+ /* Extract global interface data from user-data */
+ kimData = (kimInterfaceData) user_data;
+
+ /* Inputs to the Matlab function */
+ mx_in[0] = mxCreateDoubleMatrix(N,1,mxREAL); /* current y */
+ mx_in[1] = mxCreateDoubleMatrix(N,1,mxREAL); /* current yscale */
+ mx_in[2] = mxCreateDoubleMatrix(N,1,mxREAL); /* current fy */
+ mx_in[3] = mxCreateDoubleMatrix(N,1,mxREAL); /* current fscale */
+ mx_in[4] = mxCreateDoubleMatrix(N,1,mxREAL); /* right hand side */
+ mx_in[5] = kimData->PSOLfct; /* matlab function handle */
+ mx_in[6] = kimData->mtlb_data; /* matlab user data */
+
+ /* Call matlab wrapper */
+
+ GetData(y, mxGetPr(mx_in[0]), N);
+ GetData(yscale, mxGetPr(mx_in[1]), N);
+ GetData(fy, mxGetPr(mx_in[2]), N);
+ GetData(fscale, mxGetPr(mx_in[3]), N);
+ GetData(v, mxGetPr(mx_in[4]), N);
+
+ mexCallMATLAB(3,mx_out,7,mx_in,"kim_psol");
+
+ PutData(v, mxGetPr(mx_out[0]), N);
+ ret = (int)*mxGetPr(mx_out[1]);
+
+ if (!mxIsEmpty(mx_out[2])) {
+ UpdateUserData(mx_out[2], kimData);
+ }
+
+ /* Free temporary space */
+ mxDestroyArray(mx_in[0]);
+ mxDestroyArray(mx_in[1]);
+ mxDestroyArray(mx_in[2]);
+ mxDestroyArray(mx_in[3]);
+ mxDestroyArray(mx_in[4]);
+ mxDestroyArray(mx_out[0]);
+ mxDestroyArray(mx_out[1]);
+ mxDestroyArray(mx_out[2]);
+
+ return(ret);
+}
+
+int mxW_KINGloc(long int Nlocal, N_Vector y, N_Vector gval, void *user_data)
+{
+ kimInterfaceData kimData;
+ mxArray *mx_in[3], *mx_out[3];
+ int ret;
+
+ /* Extract global interface data from user-data */
+ kimData = (kimInterfaceData) user_data;
+
+ /* Inputs to the Matlab function */
+ mx_in[0] = mxCreateDoubleMatrix(N,1,mxREAL); /* current y */
+ mx_in[1] = kimData->GLOCfct; /* matlab function handle */
+ mx_in[2] = kimData->mtlb_data; /* matlab user data */
+
+ /* Call matlab wrapper */
+
+ GetData(y, mxGetPr(mx_in[0]), N);
+ mexCallMATLAB(3,mx_out,3,mx_in,"kim_gloc");
+
+ PutData(gval, mxGetPr(mx_out[0]), N);
+
+ ret = (int)*mxGetPr(mx_out[1]);
+
+ if (!mxIsEmpty(mx_out[2])) {
+ UpdateUserData(mx_out[2], kimData);
+ }
+
+ /* Free temporary space */
+ mxDestroyArray(mx_in[0]);
+ mxDestroyArray(mx_out[0]);
+ mxDestroyArray(mx_out[1]);
+ mxDestroyArray(mx_out[2]);
+
+ return(ret);
+}
+
+int mxW_KINGcom(long int Nlocal, N_Vector y, void *user_data)
+{
+ kimInterfaceData kimData;
+ mxArray *mx_in[5], *mx_out[2];
+ int ret;
+
+ /* Extract global interface data from user-data */
+ kimData = (kimInterfaceData) user_data;
+
+ /* Inputs to the Matlab function */
+ mx_in[0] = mxCreateDoubleMatrix(N,1,mxREAL); /* current y */
+ mx_in[1] = kimData->GCOMfct; /* matlab function handle */
+ mx_in[2] = kimData->mtlb_data; /* matlab user data */
+
+ /* Call matlab wrapper */
+
+ GetData(y, mxGetPr(mx_in[0]), N);
+ mexCallMATLAB(2,mx_out,3,mx_in,"kim_gcom");
+
+ ret = (int)*mxGetPr(mx_out[0]);
+
+ if (!mxIsEmpty(mx_out[1])) {
+ UpdateUserData(mx_out[1], kimData);
+ }
+
+ /* Free temporary space */
+ mxDestroyArray(mx_in[0]);
+ mxDestroyArray(mx_out[0]);
+ mxDestroyArray(mx_out[1]);
+
+ return(ret);
+}
+
+/*
+ * ---------------------------------------------------------------------------------
+ * Private function to update the user data structure
+ * ---------------------------------------------------------------------------------
+ */
+
+static void UpdateUserData(mxArray *new_mtlb_data, kimInterfaceData kimData)
+{
+ mexUnlock();
+ mxDestroyArray(kimData->mtlb_data);
+ kimData->mtlb_data = mxDuplicateArray(new_mtlb_data);
+ mexMakeArrayPersistent(kimData->mtlb_data);
+ mexLock();
+}
diff --git a/sundialsTB/nvector/Contents.m b/sundialsTB/nvector/Contents.m
new file mode 100644
index 0000000..3abbcc1
--- /dev/null
+++ b/sundialsTB/nvector/Contents.m
@@ -0,0 +1,17 @@
+% SUNDIALS NVECTOR operations
+%
+% Functions:
+%
+% N_VMax - returns the largest element of x
+% N_VMaxNorm - returns the maximum norm of x
+% N_VMin - returns the smallest element of x
+% N_VDotProd - returns the dot product of two vectors
+% N_VWrmsNorm - returns the weighted root mean square norm of x
+% N_VWL2Norm - returns the weighted Euclidean L2 norm of x
+% N_VL1Norm - returns the L1 norm of x
+%
+% NOTE For serial vectors, all of the above operations default to
+% the corresponding MATLAB functions. For parallel vectors, they
+% can be used either on the local portion of the distributed vector
+% or on the global vector (in which case they will trigger an MPI
+% allreduce operation).
diff --git a/sundialsTB/nvector/N_VDotProd.m b/sundialsTB/nvector/N_VDotProd.m
new file mode 100644
index 0000000..79d6ccc
--- /dev/null
+++ b/sundialsTB/nvector/N_VDotProd.m
@@ -0,0 +1,26 @@
+function ret = N_VDotProd(x,y,comm)
+%N_VDotProd returns the dot product of two vectors
+%
+% Usage: RET = N_VDotProd ( X, Y [, COMM] )
+%
+%If COMM is not present, N_VDotProd returns the dot product of the
+%local portions of X and Y. Otherwise, it returns the global dot
+%product.
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2005, The Regents of the University of California.
+% $Revision: 1.1 $Date: 2006/01/06 19:00:10 $
+
+
+if nargin == 2
+
+ ret = dot(x,y);
+
+else
+
+ ldot = dot(x,y);
+ gdot = 0.0;
+ MPI_Allreduce(ldot,gdot,'SUM',comm);
+ ret = gdot;
+
+end
\ No newline at end of file
diff --git a/sundialsTB/nvector/N_VL1Norm.m b/sundialsTB/nvector/N_VL1Norm.m
new file mode 100644
index 0000000..a34109d
--- /dev/null
+++ b/sundialsTB/nvector/N_VL1Norm.m
@@ -0,0 +1,25 @@
+function ret = N_VL1Norm(x,comm)
+%N_VL1Norm returns the L1 norm of x
+%
+% Usage: RET = N_VL1Norm ( X [, COMM] )
+%
+%If COMM is not present, N_VL1Norm returns the L1 norm of
+%the local portion of X. Otherwise, it returns the global
+%L1 norm..
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2005, The Regents of the University of California.
+% $Revision: 1.1 $Date: 2006/01/06 19:00:10 $
+
+if nargin == 1
+
+ ret = norm(x,1);
+
+else
+
+ lnrm = norm(x,1);
+ gnrm = 0.0;
+ MPI_Allreduce(lnrm,gnrm,'MAX',comm);
+ ret = gnrm;
+
+end
\ No newline at end of file
diff --git a/sundialsTB/nvector/N_VMax.m b/sundialsTB/nvector/N_VMax.m
new file mode 100644
index 0000000..4fc4625
--- /dev/null
+++ b/sundialsTB/nvector/N_VMax.m
@@ -0,0 +1,25 @@
+function ret = N_VMax(x,comm)
+%N_VMax returns the largest element of x
+%
+% Usage: RET = N_VMax ( X [, COMM] )
+%
+%If COMM is not present, N_VMax returns the maximum value of
+%the local portion of X. Otherwise, it returns the global
+%maximum value.
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2005, The Regents of the University of California.
+% $Revision: 1.1 $Date: 2006/01/06 19:00:10 $
+
+if nargin == 1
+
+ ret = max(x);
+
+else
+
+ lmax = max(x);
+ gmax = 0.0;
+ MPI_Allreduce(lmax,gmax,'MAX',comm);
+ ret = gmax;
+
+end
\ No newline at end of file
diff --git a/sundialsTB/nvector/N_VMaxNorm.m b/sundialsTB/nvector/N_VMaxNorm.m
new file mode 100644
index 0000000..30e01aa
--- /dev/null
+++ b/sundialsTB/nvector/N_VMaxNorm.m
@@ -0,0 +1,25 @@
+function ret = N_VMaxNorm(x, comm)
+%N_VMaxNorm returns the L-infinity norm of x
+%
+% Usage: RET = N_VMaxNorm ( X [, COMM] )
+%
+%If COMM is not present, N_VMaxNorm returns the L-infinity norm
+%of the local portion of X. Otherwise, it returns the global
+%L-infinity norm..
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2005, The Regents of the University of California.
+% $Revision: 1.1 $Date: 2006/01/06 19:00:10 $
+
+if nargin == 1
+
+ ret = norm(x,'inf');
+
+else
+
+ lnrm = norm(x,'inf');
+ gnrm = 0.0;
+ MPI_Allreduce(lnrm,gnrm,'MAX',comm);
+ ret = gnrm;
+
+end
\ No newline at end of file
diff --git a/sundialsTB/nvector/N_VMin.m b/sundialsTB/nvector/N_VMin.m
new file mode 100644
index 0000000..3485a8b
--- /dev/null
+++ b/sundialsTB/nvector/N_VMin.m
@@ -0,0 +1,24 @@
+function ret = N_VMin(x,comm)
+%N_VMin returns the smallest element of x
+% Usage: RET = N_VMin ( X [, COMM] )
+%
+%If COMM is not present, N_VMin returns the minimum value of
+%the local portion of X. Otherwise, it returns the global
+%minimum value.
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2005, The Regents of the University of California.
+% $Revision: 1.1 $Date: 2006/01/06 19:00:10 $
+
+if nargin == 1
+
+ ret = min(x);
+
+else
+
+ lmin = min(x);
+ gmin = 0.0;
+ MPI_Allreduce(lmin,gmin,'MIN',comm);
+ ret = gmin;
+
+end
\ No newline at end of file
diff --git a/sundialsTB/nvector/N_VWL2Norm.m b/sundialsTB/nvector/N_VWL2Norm.m
new file mode 100644
index 0000000..33ae963
--- /dev/null
+++ b/sundialsTB/nvector/N_VWL2Norm.m
@@ -0,0 +1,29 @@
+function ret = N_VWL2Norm(x,w,comm)
+%N_VWL2Norm returns the weighted Euclidean L2 norm of x
+% with weight vector w:
+% sqrt [(sum (i = 0 to N-1) {(x[i]*w[i])^2})]
+%
+% Usage: RET = N_VWL2Norm ( X, W [, COMM] )
+%
+%If COMM is not present, N_VWL2Norm returns the weighted L2
+%norm of the local portion of X. Otherwise, it returns the
+%global weighted L2 norm..
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2005, The Regents of the University of California.
+% $Revision: 1.1 $Date: 2006/01/06 19:00:10 $
+
+if nargin == 2
+
+ ret = dot(x.^2,w.^2);
+ ret = sqrt(ret);
+
+else
+
+ lnrm = dot(x.^2,w.^2);
+ gnrm = 0.0;
+ MPI_Allreduce(lnrm,gnrm,'SUM',comm);
+
+ ret = sqrt(gnrm);
+
+end
\ No newline at end of file
diff --git a/sundialsTB/nvector/N_VWrmsNorm.m b/sundialsTB/nvector/N_VWrmsNorm.m
new file mode 100644
index 0000000..b965bf2
--- /dev/null
+++ b/sundialsTB/nvector/N_VWrmsNorm.m
@@ -0,0 +1,34 @@
+function ret = N_VWrmsNorm(x,w,comm)
+%N_VWrmsNorm returns the weighted root mean square norm of x
+%with weight vector w:
+% sqrt [(sum (i = 0 to N-1) {(x[i]*w[i])^2})/N]
+%
+% Usage: RET = N_VWrmsNorm ( X, W [, COMM] )
+%
+%If COMM is not present, N_VWrmsNorm returns the WRMS norm
+%of the local portion of X. Otherwise, it returns the global
+%WRMS norm..
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2005, The Regents of the University of California.
+% $Revision: 1.1 $Date: 2006/01/06 19:00:11 $
+
+if nargin == 2
+
+ ret = dot(x.^2,w.^2);
+ ret = sqrt(ret/length(x));
+
+else
+
+ lnrm = dot(x.^2,w.^2);
+ gnrm = 0.0;
+ MPI_Allreduce(lnrm,gnrm,'SUM',comm);
+
+ ln = length(x);
+ gn = 0;
+ MPI_Allreduce(ln,gn,'SUM',comm);
+
+ ret = sqrt(gnrm/gn);
+
+end
+
diff --git a/sundialsTB/nvector/src/nvm.h b/sundialsTB/nvector/src/nvm.h
new file mode 100644
index 0000000..065c808
--- /dev/null
+++ b/sundialsTB/nvector/src/nvm.h
@@ -0,0 +1,43 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.3 $
+ * $Date: 2012/03/07 21:41:19 $
+ * -----------------------------------------------------------------
+ * Programmer: 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.
+ * -----------------------------------------------------------------
+ * Header file for the MNVECTOR Matlab interface.
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _NVM_H
+#define _NVM_H
+
+#ifdef __cplusplus /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#include <sundials/sundials_nvector.h>
+#include "mex.h"
+
+ /*
+ * ------------------
+ * Vector functions
+ * ------------------
+ */
+
+ void InitVectors();
+ N_Vector NewVector(long int n);
+
+ void PutData(N_Vector v, double *data, long int n);
+ void GetData(N_Vector v, double *data, long int n);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/sundialsTB/nvector/src/nvm_ops.c b/sundialsTB/nvector/src/nvm_ops.c
new file mode 100644
index 0000000..9a303cd
--- /dev/null
+++ b/sundialsTB/nvector/src/nvm_ops.c
@@ -0,0 +1,43 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.3 $
+ * $Date: 2012/03/07 21:41:19 $
+ * -----------------------------------------------------------------
+ * Programmer: 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.
+ * -----------------------------------------------------------------
+ * Vector constructors for the SUNDIALS Matlab interfaces.
+ * -----------------------------------------------------------------
+ */
+
+#include <stdlib.h>
+#include "nvm.h"
+
+void PutData(N_Vector v, double *data, long int n)
+{
+ double *vdata;
+ long int i;
+
+ vdata = N_VGetArrayPointer(v);
+
+ for(i=0;i<n;i++) vdata[i] = data[i];
+
+ return;
+}
+
+
+void GetData(N_Vector v, double *data, long int n)
+{
+ double *vdata;
+ long int i;
+
+ vdata = N_VGetArrayPointer(v);
+
+ for(i=0;i<n;i++) data[i] = vdata[i];
+
+ return;
+}
diff --git a/sundialsTB/nvector/src/nvm_parallel.c b/sundialsTB/nvector/src/nvm_parallel.c
new file mode 100644
index 0000000..2d9ed5b
--- /dev/null
+++ b/sundialsTB/nvector/src/nvm_parallel.c
@@ -0,0 +1,79 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.3 $
+ * $Date: 2012/03/07 21:41:19 $
+ * -----------------------------------------------------------------
+ * Programmer: 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.
+ * -----------------------------------------------------------------
+ * Vector constructors for the SUNDIALS Matlab interfaces.
+ * -----------------------------------------------------------------
+ */
+
+#include <stdlib.h>
+#include <mpi.h>
+#include "nvm.h"
+#include <nvector/nvector_serial.h>
+#include <nvector/nvector_parallel.h>
+
+int sundials_VecType;
+MPI_Comm sundials_comm;
+
+void InitVectors()
+{
+ const mxArray *mx_comm;
+ char *str;
+
+ /* Check if the Matlab global variable sundials_MPI_comm exists
+ (mpirun and mpiruns set it) */
+
+ mx_comm = mexGetVariable("global", "sundials_MPI_comm");
+
+ if (mx_comm == NULL) {
+
+ /* If it does not exist, set vector type to 1 (serial) */
+
+ sundials_VecType = 1;
+
+ } else {
+
+ /* If it does exist, set vector type to 2 (parallel) and
+ set the MPI communicator */
+
+ sundials_VecType = 2;
+
+ str = mxArrayToString(mx_comm);
+ if (!strcmp(str,"NULL" )) sundials_comm = MPI_COMM_NULL ;
+ else if (!strcmp(str,"WORLD" )) sundials_comm = MPI_COMM_WORLD ;
+ else if (!strcmp(str,"SELF" )) sundials_comm = MPI_COMM_SELF ;
+ else sundials_comm = *(MPI_Comm*)mxGetData(mx_comm);
+
+ }
+
+}
+
+N_Vector NewVector(long int n)
+{
+ N_Vector v;
+ long int nlocal, nglobal;
+
+ if (sundials_VecType == 1) {
+
+ v = N_VNew_Serial((long int)n);
+
+ } else {
+
+ nlocal = n;
+ MPI_Allreduce(&nlocal, &nglobal, 1, MPI_INT, MPI_SUM, sundials_comm);
+ v = N_VNew_Parallel(sundials_comm, nlocal, nglobal);
+
+ }
+
+ return(v);
+}
+
+
diff --git a/sundialsTB/nvector/src/nvm_serial.c b/sundialsTB/nvector/src/nvm_serial.c
new file mode 100644
index 0000000..c58ef66
--- /dev/null
+++ b/sundialsTB/nvector/src/nvm_serial.c
@@ -0,0 +1,29 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision: 1.3 $
+ * $Date: 2012/03/07 21:41:19 $
+ * -----------------------------------------------------------------
+ * Programmer: 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.
+ * -----------------------------------------------------------------
+ * Vector constructors for the SUNDIALS Matlab interfaces.
+ * -----------------------------------------------------------------
+ */
+
+#include <stdlib.h>
+#include "nvm.h"
+#include <nvector/nvector_serial.h>
+
+void InitVectors()
+{}
+
+N_Vector NewVector(long int n)
+{
+ N_Vector v;
+ v = N_VNew_Serial(n);
+ return(v);
+}
diff --git a/sundialsTB/putils/Contents.m b/sundialsTB/putils/Contents.m
new file mode 100644
index 0000000..2ca90c5
--- /dev/null
+++ b/sundialsTB/putils/Contents.m
@@ -0,0 +1,9 @@
+% Parallel utilities for the Matlab SUNDIALS interfaces
+%
+% Functions:
+%
+% mpirun - runs parallel examples
+% mpiruns - runs the parallel example on a child MATLAB process
+% mpistart - lamboot and MPI_Init master (if required)
+
+
diff --git a/sundialsTB/putils/mpirun.m b/sundialsTB/putils/mpirun.m
new file mode 100644
index 0000000..2578982
--- /dev/null
+++ b/sundialsTB/putils/mpirun.m
@@ -0,0 +1,67 @@
+function [] = mpirun(fct,npe,dbg)
+%MPIRUN runs parallel examples.
+%
+% Usage: MPIRUN ( FCT , NPE [, DBG] )
+%
+% FCT - function to be executed on all MATLAB processes.
+% NPE - number of processes to be used (including the master).
+% DBG - flag for debugging [ true | {false} ]
+% If true, spawn MATLAB child processes with a visible xterm.
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2005, The Regents of the University of California.
+% $Revision: 1.2 $Date: 2006/03/07 01:20:01 $
+
+ih = isa(fct,'function_handle');
+is = isa(fct,'char');
+if ih
+ sh = functions(fct);
+ fct_str = sh.function;
+elseif is
+ fct_str = fct;
+else
+ error('mpirun:: Unrecognized function');
+end
+
+if exist(fct_str) ~= 2
+ err_msg = sprintf('mpirun:: Function %s not in search path.',fct_str);
+ error(err_msg);
+end
+
+nslaves = npe-1;
+mpistart(nslaves);
+
+debug = false;
+if (nargin > 2) & dbg
+ debug = true;
+end
+
+cmd_slaves = sprintf('mpiruns(''%s'')',fct_str);
+
+if debug
+ cmd = 'xterm';
+ args = {'-sb','-sl','5000','-e','matlab','-nosplash','-nojvm','-r',cmd_slaves};
+else
+ cmd = 'matlab';
+ args = {'-nosplash','-nojvm','-r',cmd_slaves};
+end
+
+[info children errs] = MPI_Comm_spawn(cmd,args,nslaves,'NULL',0,'SELF');
+
+[info NEWORLD] = MPI_Intercomm_merge(children,0);
+
+% Put the MPI communicator in the global workspace
+global sundials_MPI_comm;
+sundials_MPI_comm = NEWORLD;
+
+% Get rank of current process and put it in the global workspace
+[status mype] = MPI_Comm_rank(NEWORLD);
+global sundials_MPI_rank;
+sundials_MPI_rank = mype;
+
+% Call the user main program
+feval(fct,NEWORLD);
+
+% Clear the global MPI communicator variable
+clear sundials_MPI_comm
+
diff --git a/sundialsTB/putils/mpiruns.m b/sundialsTB/putils/mpiruns.m
new file mode 100644
index 0000000..321128b
--- /dev/null
+++ b/sundialsTB/putils/mpiruns.m
@@ -0,0 +1,50 @@
+function [] = mpiruns(fct)
+%MPIRUNS runs the parallel example on a child MATLAB process.
+%
+% Usage: MPIRUNS ( FCT )
+%
+% This function should not be called directly. It is called
+% by mpirun on the spawned child processes.
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2005, The Regents of the University of California.
+% $Revision: 1.2 $Date: 2006/03/07 01:20:01 $
+
+clc;
+
+[dummy hostname]=system('hostname');
+fprintf('mpiruns :: child MATLAB process on %s\n',hostname);
+
+MPI_Init;
+
+MPI_Errhandler_set('WORLD','RETURN');
+
+[info parent] = MPI_Comm_get_parent;
+
+fprintf('mpiruns :: waiting to merge MPI intercommunicators ... ');
+[info NEWORLD] = MPI_Intercomm_merge(parent,1);
+fprintf('OK!\n\n');
+
+MPI_Errhandler_set(NEWORLD,'RETURN');
+
+% Put the MPI communicator in the global workspace
+global sundials_MPI_comm;
+sundials_MPI_comm = NEWORLD;
+
+% Get rank of current process and put it in the global workspace
+[status mype] = MPI_Comm_rank(NEWORLD);
+global sundials_MPI_rank;
+sundials_MPI_rank = mype;
+
+fprintf('mpiruns :: MPI rank: %d\n\n',mype);
+
+fprintf('----------------------------------------------------------------\n\n');
+
+% Call the user main program
+feval(fct,NEWORLD);
+
+% Clear the global MPI communicator variable
+clear sundials_MPI_comm
+
+% Finalize MPI on this slave
+MPI_Finalize;
\ No newline at end of file
diff --git a/sundialsTB/putils/mpistart.m b/sundialsTB/putils/mpistart.m
new file mode 100644
index 0000000..61b09ae
--- /dev/null
+++ b/sundialsTB/putils/mpistart.m
@@ -0,0 +1,324 @@
+function mpistart(nslaves, rpi, hosts)
+%MPISTART invokes lamboot (if required) and MPI_Init (if required).
+%
+% Usage: MPISTART [ ( NSLAVES [, RPI [, HOSTS] ] ) ]
+%
+% MPISTART boots LAM and initializes MPI to match a given number of slave
+% hosts (and rpi) from a given list of hosts. All three args optional.
+%
+% If they are not defined, HOSTS are taken from a builtin HOSTS list
+% (edit HOSTS at the beginning of this file to match your cluster)
+% or from the bhost file if defined through LAMBHOST (in this order).
+%
+% If not defined, RPI is taken from the builtin variable RPI (edit it
+% to suit your needs) or from the LAM_MPI_SSI_rpi environment variable
+% (in this order).
+
+% Heavily based on the LAM_Init function in MPITB.
+
+%------------------------------
+% ARGCHECK
+%------------------------------
+
+% List of hosts
+
+if nargin>2
+
+% Hosts passed as an argument...
+
+ if ~iscell(hosts)
+ error('MPISTART: 3rd arg is not a cell');
+ end
+ for i=1:length(hosts)
+ if ~ischar(hosts{i})
+ error('MPISTART: 3rd arg is not cell-of-strings');
+ end
+ end
+
+else
+
+% Get hosts from file specified in env. var. LAMBHOST
+
+ bfile = getenv('LAMBHOST');
+ if isempty(bfile)
+ error('MPISTART: cannot find list of hosts');
+ end
+ hosts = readHosts(bfile);
+
+end
+
+% RPI
+
+if nargin>1
+
+% RPI passed as an argument
+
+ if ~ischar(rpi)
+ error('MPISTART: 2nd arg is not a string')
+ end
+% Get full rpi name, if single letter used
+ rpi = rpi_str(rpi);
+ if isempty(rpi)
+ error('MPISTART: 2nd arg is not a known RPI')
+ end
+
+else
+
+% Get RPI from env. var. LAM_MPI_SSI_rpi
+
+ RPI = getenv('LAM_MPI_SSI_rpi');
+ if isempty(RPI)
+% If LAM_MPI_SSI_rpi not defined, use RPI='tcp'
+ RPI = 'tcp';
+ end
+ rpi = rpi_str(RPI);
+
+end
+
+% Number of slaves
+
+if nargin>0
+ if ~isreal(nslaves) || fix(nslaves)~=nslaves || nslaves>=length(hosts)
+ error('MPISTART: 1st arg is not a valid #slaves')
+ end
+else
+ nslaves = length(hosts)-1;
+end
+
+%------------------------------
+% LAMHALT %
+%-------------------------------------------------------------
+% reasons to lamhalt:
+% - not enough nodes (nslv+1) % NHL < NSLAVES+1
+% - localhost not in list % weird - just lamboot (NHL=0)
+% - localhost not last in list % weird - just lamboot (NHL=0)
+%-------------------------------------------------------------
+
+% Lam Nodes Output
+[stat, LNO] = system('lamnodes');
+if ~stat % already lambooted
+
+ emptyflag = false;
+ if isempty(LNO)
+ % this shouldn't happen
+ emptyflag=true;
+ % it's MATLAB's fault I think
+ fprintf('pushing stubborn MATLAB "system" call (lamnodes): ');
+ end
+
+ while isempty(LNO) || stat
+ fprintf('.');
+ [stat, LNO] = system('lamnodes');
+ end
+ if emptyflag
+ fprintf('\n');
+ end
+
+ LF = char(10);
+ LNO = split(LNO,LF); % split lines in rows at \n
+
+ [stat, NHL] = system('lamnodes|wc -l'); % Number of Hosts in Lamnodes
+
+ emptyflag = false; % again,
+ if isempty(NHL) % this shouldn't happen
+ emptyflag=true; % it's MATLAB's fault I think
+ fprintf('pushing stubborn MATLAB "system" call (lamnodes|wc): ');
+ end
+ while isempty(NHL) || stat
+ fprintf('.');
+ [stat, NHL] = system('lamnodes|wc -l');
+ end
+ if emptyflag
+ fprintf('\n');
+ end
+
+ NHL = str2num(NHL);
+ if NHL ~= size(LNO,1) || ~ NHL>0 % Oh my, logic error
+ NHL= 0; % pretend there are no nodes
+ disp('MPISTART: internal logic error: lamboot')
+ end % to force lamboot w/o lamhalt
+ if isempty(findstr(LNO(end,:),'this_node')) % master computer last in list
+ disp('MPISTART: local host is not last in nodelist, hope that''s right')
+ beforeflag=0;
+ for i=1:size(LNO,1)
+ if ~isempty(findstr(LNO(i,:),'this_node'))
+ beforeflag=1;
+ break; % well, not 1st but it's there
+ end
+ end % we already warned the user
+ if ~beforeflag % Oh my, incredible, not there
+ NHL= 0; % pretend there are no nodes
+ disp('MPISTART: local host not in LAM? lamboot')
+ end
+ end % to force lamboot w/o lamhalt
+
+ if NHL > 0 % accurately account multiprocessors
+ NCL = 0; % number of CPUs in lamnodes
+ for i=1:size(LNO,1) % add the 2nd ":"-separated
+ fields=split(LNO(i,:),':'); % field, ie, #CPUs
+ NCL = NCL + str2num(fields(2,:));
+ end
+ if NCL<NHL % Oh my, logic error
+ NHL= 0; % pretend there are no nodes
+ disp('MPISTART: internal logic error: lamboot')
+ else
+ % update count
+ NHL=NCL;
+ end % can't get count from MPI,
+ end % since might be not _Init'ed
+
+ if NHL < nslaves+1 % we have to lamboot
+
+ % but avoid getting caught
+ [infI flgI]=MPI_Initialized; % Init?
+ [infF flgF]=MPI_Finalized; % Finalize?
+ if infI || infF
+ error('MPISTART: error calling _Initialized/_Finalized?')
+ end
+ if flgI && ~flgF % avoid hangup due to
+ MPI_Finalize; % inminent lamhalt
+ clear MPI_* % force MPI_Init in Mast/Ping
+ disp('MPISTART: MPI already used- clearing before lamboot')
+ end % by pretending "not _Init"
+ if NHL > 0 % avoid lamhalt in weird cases
+ disp('MPISTART: halting LAM')
+ system('lamhalt'); % won't get caught on this
+ end
+ end
+end
+
+%------------------------------
+% LAMBOOT
+%-------------------------------------------------------------
+% reasons to lamboot: %
+% - not lambooted yet % stat~=0
+% - lamhalted above (or weird) % NHL < NSLAVES+1 (0 _is_ <)
+%-------------------------------------------------------------
+
+if stat || NHL<nslaves+1
+
+ HNAMS=hosts{end};
+ for i=nslaves:-1:1
+ HNAMS=strvcat(hosts{i},HNAMS);
+ end
+ HNAMS = HNAMS'; % transpose for "for"
+
+ fid=fopen('bhost','wt');
+ for h = HNAMS
+ fprintf(fid,'%s\n',h'); % write slaves' hostnames
+ end
+ fclose(fid);
+ disp ('MPISTART: booting LAM')
+
+ stat = system('lamboot -s -v bhost');
+
+ if stat % again, this shouldn't happen
+ fprintf('pushing stubborn MATLAB "system" call (lamboot): ');
+ while stat
+ fprintf('.'); stat = system('lamboot -s -v bhost');
+ end
+ fprintf('\n');
+ end
+
+ system('rm -f bhost'); % don't need bhost anymore
+end % won't wipe on exit/could lamhalt
+
+%------------------------------
+% RPI CHECK
+%------------------------------
+
+[infI flgI] = MPI_Initialized; % Init?
+[infF flgF] = MPI_Finalized; % Finalize?
+
+if infI || infF
+ error('MPISTART: error calling _Initialized/_Finalized?')
+end
+
+if flgI && ~flgF % Perfect, ready to start
+else % something we could fix?
+ if flgI || flgF % MPI used, will break
+ clear MPI_* % unless we clear MPITB
+ disp('MPISTART: MPI already used- clearing') % must start over
+ end
+
+ MPI_Init;
+end
+
+%------------------------------
+% NSLAVES CHECK
+%------------------------------
+
+[info attr flag] = MPI_Attr_get(MPI_COMM_WORLD,MPI_UNIVERSE_SIZE);
+if info | ~flag
+ error('MPISTART: attribute MPI_UNIVERSE_SIZE does not exist?')
+end
+if attr<2
+ error('MPISTART: required 2 computers in LAM')
+end
+
+%====================================================================
+
+function hosts = readHosts(bfile)
+
+hosts = [];
+
+fid = fopen(bfile);
+if fid == -1
+ fprintf('Cannot open bhost file %s\n',bfile);
+ return;
+end
+
+i = 0;
+while ~feof(fid)
+% get a line
+ l = fgetl(fid);
+% Discard comments
+ ic = min(strfind(l,'#'));
+ if ~isempty(ic), l = l(1:ic-1); end
+% Test if there is anything left :-)
+ if isempty(l), continue; end
+% Got a new host
+ i = i + 1;
+% Stop at first blank or tab=char(9)
+ indx = find((l==' ') | (l==char(9)));
+ if isempty(indx)
+ hosts{i} = l;
+ else
+ hosts{i} = l(1:min(indx));
+ end
+end
+
+fclose(fid);
+
+
+%====================================================================
+
+function rpi = rpi_str(c)
+%RPI_STR Full LAM SSI RPI string given initial letter(s)
+%
+% rpi = rpi_str (c)
+%
+% c initial char(s) of rpi name: t,l,u,s
+% rpi full rpi name, one of: tcp, lamd, usysv, sysv
+% Use '' if c doesn't match to any supported rpi
+%
+
+flag = nargin~=1 || isempty(c) || ~ischar(c);
+if flag
+ return
+end
+
+c=lower(c(1));
+rpis={'tcp','lamd','usysv','sysv','none'}; % 'none' is sentinel
+
+for i=1:length(rpis)
+ if rpis{i}(1)==c
+ break
+ end
+end
+
+if i<length(rpis)
+ rpi=rpis{i}; % normal cases
+else
+ rpi=''; % no way, unknown rpi
+end
diff --git a/sundialsTB/startup_STB.in b/sundialsTB/startup_STB.in
new file mode 100644
index 0000000..d839508
--- /dev/null
+++ b/sundialsTB/startup_STB.in
@@ -0,0 +1,65 @@
+function [] = startup_STB(stb)
+% STARTUP_STB path/environment setup script for sundialsTB
+
+% Radu Serban <radu at llnl.gov>
+% Copyright (c) 2007, The Regents of the University of California.
+% $Revision: 1.7 $Date: 2007/12/05 21:58:17 $
+
+% If called without any argument, use the path specified which was
+% harcoded when startup_STB.m was created.
+
+if nargin == 0
+ stb_path = '@STB_PATH@';
+ stb = fullfile(stb_path,'sundialsTB');
+end
+
+
+if ~exist(stb, 'dir')
+ warning('SUNDIALS Toolbox not found');
+ return
+end
+
+% Add top-level directory to path
+
+addpath(stb);
+
+% Add sundialsTB components to path
+
+q = fullfile(stb,'cvodes');
+if exist(q, 'dir')
+ addpath(q);
+ q = fullfile(stb,'cvodes','cvm');
+ addpath(q);
+ q = fullfile(stb,'cvodes','function_types');
+ addpath(q);
+end
+
+q = fullfile(stb,'idas');
+if exist(q, 'dir')
+ addpath(q);
+ q = fullfile(stb,'idas','idm');
+ addpath(q);
+ q = fullfile(stb,'idas','function_types');
+ addpath(q);
+end
+
+q = fullfile(stb,'kinsol');
+if exist(q, 'dir')
+ addpath(q);
+ q = fullfile(stb,'kinsol','kim');
+ addpath(q);
+ q = fullfile(stb,'kinsol','function_types');
+ addpath(q);
+end
+
+q = fullfile(stb,'nvector');
+if exist(q, 'dir')
+ addpath(q);
+end
+
+q = fullfile(stb,'putils');
+if exist(q, 'dir')
+ addpath(q);
+end
+
+
--
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