From 0886de8650873d4db8808ed30902fe67030acc30 Mon Sep 17 00:00:00 2001 From: Ray Speth Date: Thu, 28 Aug 2014 16:55:41 +0000 Subject: [PATCH] Include CVodes error text in resulting CanteraErrors Failures in 'integrate' and 'advance' now include the error text provided by CVodes directly, rather than just the numerical error code. This is especially helpful in cases where the direct output from CVodes to stderr is lost (e.g. when running from the Matlab GUI). --- include/cantera/numerics/CVodesIntegrator.h | 4 ++++ src/numerics/CVodesIntegrator.cpp | 20 ++++++++++++++------ 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/include/cantera/numerics/CVodesIntegrator.h b/include/cantera/numerics/CVodesIntegrator.h index 97a5dd3ad..d36c06af0 100644 --- a/include/cantera/numerics/CVodesIntegrator.h +++ b/include/cantera/numerics/CVodesIntegrator.h @@ -80,6 +80,9 @@ public: //! responsible for integrator failures or unexpected small timesteps. virtual std::string getErrorInfo(int N); + //! Error message information provide by CVodes + std::string m_error_message; + protected: //! Applies user-specified options to the underlying CVODES solver. Called //! during integrator initialization or reinitialization. @@ -113,6 +116,7 @@ private: //! Indicates whether the sensitivities stored in m_yS have been updated //! for at the current integrator time. bool m_sens_ok; + }; } // namespace diff --git a/src/numerics/CVodesIntegrator.cpp b/src/numerics/CVodesIntegrator.cpp index 74ff7fc54..e024e14f4 100644 --- a/src/numerics/CVodesIntegrator.cpp +++ b/src/numerics/CVodesIntegrator.cpp @@ -43,8 +43,6 @@ public: vector_fp m_pars; FuncEval* m_func; }; -} - extern "C" { @@ -79,10 +77,19 @@ extern "C" { } return 0; // successful evaluation } + + //! Function called by CVodes when an error is encountered instead of + //! writing to stdout. Here, save the error message provided by CVodes so + //! that it can be included in the subsequently raised CanteraError. + static void cvodes_err(int error_code, const char* module, + const char* function, char* msg, void* eh_data) + { + CVodesIntegrator* integrator = (CVodesIntegrator*) eh_data; + integrator->m_error_message = msg; + integrator->m_error_message += "\n"; + } } -namespace Cantera -{ CVodesIntegrator::CVodesIntegrator() : m_neq(0), m_cvode_mem(0), @@ -299,6 +306,7 @@ void CVodesIntegrator::initialize(double t0, FuncEval& func) throw CVodesErr("CVodeInit failed."); } } + CVodeSetErrHandlerFn(m_cvode_mem, &cvodes_err, this); if (m_itol == CV_SV) { flag = CVodeSVtolerances(m_cvode_mem, m_reltol, m_abstol); @@ -394,7 +402,7 @@ void CVodesIntegrator::integrate(double tout) { int flag = CVode(m_cvode_mem, tout, m_y, &m_time, CV_NORMAL); if (flag != CV_SUCCESS) { - throw CVodesErr(" CVodes error encountered. Error code: " + int2str(flag) + + throw CVodesErr("CVodes error encountered. Error code: " + int2str(flag) + "\n" + m_error_message + "\nComponents with largest weighted error estimates:\n" + getErrorInfo(10)); } m_sens_ok = false; @@ -404,7 +412,7 @@ double CVodesIntegrator::step(double tout) { int flag = CVode(m_cvode_mem, tout, m_y, &m_time, CV_ONE_STEP); if (flag != CV_SUCCESS) { - throw CVodesErr(" CVodes error encountered. Error code: " + int2str(flag) + + throw CVodesErr("CVodes error encountered. Error code: " + int2str(flag) + "\n" + m_error_message + "\nComponents with largest weighted error estimates:\n" + getErrorInfo(10)); }