From 5b1a4a60bb1576c6dbfa15273c57f290035b829a Mon Sep 17 00:00:00 2001 From: Ray Speth Date: Tue, 18 Oct 2016 14:54:30 -0400 Subject: [PATCH] [Thermo] Fix silent failures in HP/UV/SV/SP convergence In cases where the specified state was non-physical (i.e. corresponded to a negative temperature), the iteration would exit when the temperature reached a small enough value. Computing the error in temperature relative to the current temperature avoids this problem. Fixes #264 --- interfaces/cython/cantera/test/test_thermo.py | 16 ++++++++++++++++ src/thermo/ThermoPhase.cpp | 8 ++++---- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/interfaces/cython/cantera/test/test_thermo.py b/interfaces/cython/cantera/test/test_thermo.py index 2fd0f7a681..ef4a66e2fa 100644 --- a/interfaces/cython/cantera/test/test_thermo.py +++ b/interfaces/cython/cantera/test/test_thermo.py @@ -646,6 +646,12 @@ def test_setSV_lowT(self): self.assertNear(self.gas.v, 3 * v1) self.assertTrue(self.gas.T < self.gas.min_temp) + def test_setSV_low_invalid(self): + self.gas.TPX = 450, 1e5, 'H2:1.0, O2:0.4, AR:3' + self.gas.SV = 4600, None + with self.assertRaises(ct.CanteraError): + self.gas.SV = -1000, None + def test_setSV_highT(self): """ Set state in terms of (s,v) when the end temperature is above the @@ -675,6 +681,16 @@ def test_setHP_lowT(self): self.assertNear(self.gas.P, p1) self.assertTrue(self.gas.T < self.gas.min_temp) + def test_setHP_low_invalid(self): + """ + Set state in terms of (h,p) when the enthalpy would imply a negative + temperature + """ + + self.gas.TPX = 300, 101325, 'H2:1.0' + with self.assertRaises(ct.CanteraError): + self.gas.HP = -4e6, 101325 + def test_setHP_highT(self): """ Set state in terms of (s,v) when the end temperature is above the diff --git a/src/thermo/ThermoPhase.cpp b/src/thermo/ThermoPhase.cpp index 8eb070efee..610ab79c51 100644 --- a/src/thermo/ThermoPhase.cpp +++ b/src/thermo/ThermoPhase.cpp @@ -409,9 +409,9 @@ void ThermoPhase::setState_HPorUV(doublereal Htarget, doublereal p, // Convergence in H double Herr = Htarget - Hnew; double acpd = std::max(fabs(cpd), 1.0E-5); - double denom = std::max(fabs(Htarget), acpd * dTtol); + double denom = std::max(fabs(Htarget), acpd * Tnew); double HConvErr = fabs((Herr)/denom); - if (HConvErr < 0.00001 *dTtol || fabs(dt) < dTtol) { + if (HConvErr < 0.00001 * dTtol || fabs(dt/Tnew) < 0.00001 * dTtol) { return; } } @@ -595,9 +595,9 @@ void ThermoPhase::setState_SPorSV(doublereal Starget, doublereal p, // Convergence in S double Serr = Starget - Snew; double acpd = std::max(fabs(cpd), 1.0E-5); - double denom = std::max(fabs(Starget), acpd * dTtol); + double denom = std::max(fabs(Starget), acpd * Tnew); double SConvErr = fabs((Serr * Tnew)/denom); - if (SConvErr < 0.00001 *dTtol || fabs(dt) < dTtol) { + if (SConvErr < 0.00001 * dTtol || fabs(dt/Tnew) < 0.00001 * dTtol) { return; } }