From 38dfea4f876c18b4ae66e2a1bfc7ebdcabbc1582 Mon Sep 17 00:00:00 2001 From: Ray Speth Date: Fri, 15 Feb 2013 19:47:47 +0000 Subject: [PATCH] [Kinetics] Fixed crashes when reaction mechanism contains no reactions Make sure several arrays are never of length zero so that taking &v[0] is always well-defined. Partial cherry-pick of r2138 from trunk. --- src/kinetics/AqueousKinetics.cpp | 10 ++++++++++ src/kinetics/GasKinetics.cpp | 10 ++++++++++ src/kinetics/InterfaceKinetics.cpp | 30 ++++++++++++++++++++++-------- src/kinetics/importKinetics.cpp | 1 + 4 files changed, 43 insertions(+), 8 deletions(-) diff --git a/src/kinetics/AqueousKinetics.cpp b/src/kinetics/AqueousKinetics.cpp index babf76b5e..d4b85e19c 100644 --- a/src/kinetics/AqueousKinetics.cpp +++ b/src/kinetics/AqueousKinetics.cpp @@ -594,6 +594,16 @@ void AqueousKinetics::finalize() { if (!m_finalized) { m_finalized = true; + + // Guarantee that these arrays can be converted to double* even in the + // special case where there are no reactions defined. + if (!m_ii) { + m_perturb.resize(1, 1.0); + m_ropf.resize(1, 0.0); + m_ropr.resize(1, 0.0); + m_ropnet.resize(1, 0.0); + m_rkcn.resize(1, 0.0); + } } } diff --git a/src/kinetics/GasKinetics.cpp b/src/kinetics/GasKinetics.cpp index d0d04a2d3..dad04fddb 100644 --- a/src/kinetics/GasKinetics.cpp +++ b/src/kinetics/GasKinetics.cpp @@ -838,6 +838,16 @@ void GasKinetics::finalize() concm_3b_values.resize(m_3b_concm.workSize()); concm_falloff_values.resize(m_falloff_concm.workSize()); m_finalized = true; + + // Guarantee that these arrays can be converted to double* even in the + // special case where there are no reactions defined. + if (!m_ii) { + m_perturb.resize(1, 1.0); + m_ropf.resize(1, 0.0); + m_ropr.resize(1, 0.0); + m_ropnet.resize(1, 0.0); + m_rkcn.resize(1, 0.0); + } } } //==================================================================================================================== diff --git a/src/kinetics/InterfaceKinetics.cpp b/src/kinetics/InterfaceKinetics.cpp index 1dc78404a..a84593418 100644 --- a/src/kinetics/InterfaceKinetics.cpp +++ b/src/kinetics/InterfaceKinetics.cpp @@ -403,10 +403,10 @@ void InterfaceKinetics::updateKc() void InterfaceKinetics::checkPartialEquil() { vector_fp dmu(nTotalSpecies(), 0.0); - vector_fp rmu(nReactions(), 0.0); - vector_fp frop(nReactions(), 0.0); - vector_fp rrop(nReactions(), 0.0); - vector_fp netrop(nReactions(), 0.0); + vector_fp frop(std::max(nReactions(), 1), 0.0); + vector_fp rrop(std::max(nReactions(), 1), 0.0); + vector_fp netrop(std::max(nReactions(), 1), 0.0); + vector_fp rmu(std::max(nReactions(), 1), 0.0); if (m_nrev > 0) { doublereal rt = GasConstant*thermo(0).temperature(); cout << "T = " << thermo(0).temperature() << " " << rt << endl; @@ -1332,7 +1332,8 @@ void InterfaceKinetics::init() void InterfaceKinetics::finalize() { Kinetics::finalize(); - m_rwork.resize(nReactions()); + size_t safe_reaction_size = std::max(nReactions(), 1); + m_rwork.resize(safe_reaction_size); size_t ks = reactionPhaseIndex(); if (ks == npos) throw CanteraError("InterfaceKinetics::finalize", "no surface phase is present."); @@ -1343,13 +1344,19 @@ void InterfaceKinetics::finalize() +int2str(m_surf->nDim())); m_StandardConc.resize(m_kk, 0.0); - m_deltaG0.resize(m_ii, 0.0); - m_ProdStanConcReac.resize(m_ii, 0.0); + m_deltaG0.resize(safe_reaction_size, 0.0); + m_ProdStanConcReac.resize(safe_reaction_size, 0.0); if (m_thermo.size() != m_phaseExists.size()) { throw CanteraError("InterfaceKinetics::finalize", "internal error"); } + // Guarantee that these arrays can be converted to double* even in the + // special case where there are no reactions defined. + if (!m_ii) { + m_perturb.resize(1, 1.0); + } + m_finalized = true; } @@ -1485,7 +1492,7 @@ void InterfaceKinetics::setPhaseStability(const int iphase, const int isStable) //================================================================================================ void EdgeKinetics::finalize() { - m_rwork.resize(nReactions()); + m_rwork.resize(std::max(nReactions(), 1)); size_t ks = reactionPhaseIndex(); if (ks == npos) throw CanteraError("EdgeKinetics::finalize", "no edge phase is present."); @@ -1494,6 +1501,13 @@ void EdgeKinetics::finalize() throw CanteraError("EdgeKinetics::finalize", "expected interface dimension = 1, but got dimension = " +int2str(m_surf->nDim())); + + // Guarantee that these arrays can be converted to double* even in the + // special case where there are no reactions defined. + if (!m_ii) { + m_perturb.resize(1, 1.0); + } + m_finalized = true; } //================================================================================================ diff --git a/src/kinetics/importKinetics.cpp b/src/kinetics/importKinetics.cpp index cf750c223..c73a13350 100644 --- a/src/kinetics/importKinetics.cpp +++ b/src/kinetics/importKinetics.cpp @@ -902,6 +902,7 @@ bool installReactionArrays(const XML_Node& p, Kinetics& kin, p.getChildren("reactionArray",rarrays); int na = static_cast(rarrays.size()); if (na == 0) { + kin.finalize(); return false; } for (int n = 0; n < na; n++) {