From 195a1004737ac399960411a0d022c561019052b6 Mon Sep 17 00:00:00 2001 From: Ray Speth Date: Sat, 2 Dec 2017 16:06:19 -0500 Subject: [PATCH 1/2] [Thermo] Use min/max temperatures from equation of state The values in the liquidvapor.cti should be ignored, since this thermo data is not actually applicable -- it is just used to set the reference state. --- include/cantera/thermo/PureFluidPhase.h | 3 +++ interfaces/cython/cantera/test/test_purefluid.py | 5 +++++ src/thermo/PureFluidPhase.cpp | 10 ++++++++++ 3 files changed, 18 insertions(+) diff --git a/include/cantera/thermo/PureFluidPhase.h b/include/cantera/thermo/PureFluidPhase.h index 7328085ddb..6ea1f83b36 100644 --- a/include/cantera/thermo/PureFluidPhase.h +++ b/include/cantera/thermo/PureFluidPhase.h @@ -43,6 +43,9 @@ class PureFluidPhase : public ThermoPhase m_tpx_name = name; } + virtual double minTemp(size_t k=npos) const; + virtual double maxTemp(size_t k=npos) const; + virtual doublereal enthalpy_mole() const; virtual doublereal intEnergy_mole() const; virtual doublereal entropy_mole() const; diff --git a/interfaces/cython/cantera/test/test_purefluid.py b/interfaces/cython/cantera/test/test_purefluid.py index 122dcbb815..37ed15715f 100644 --- a/interfaces/cython/cantera/test/test_purefluid.py +++ b/interfaces/cython/cantera/test/test_purefluid.py @@ -17,6 +17,11 @@ def test_critical_properties(self): self.assertNear(self.water.critical_temperature, 647.286) self.assertNear(self.water.critical_density, 317.0) + def test_temperature_limits(self): + co2 = ct.CarbonDioxide() + self.assertNear(co2.min_temp, 216.54) + self.assertNear(co2.max_temp, 1500.0) + def test_set_state(self): self.water.PX = 101325, 0.5 self.assertNear(self.water.P, 101325) diff --git a/src/thermo/PureFluidPhase.cpp b/src/thermo/PureFluidPhase.cpp index ddb736f5c1..51783e71b9 100644 --- a/src/thermo/PureFluidPhase.cpp +++ b/src/thermo/PureFluidPhase.cpp @@ -73,6 +73,16 @@ void PureFluidPhase::setParametersFromXML(const XML_Node& eosdata) } } +double PureFluidPhase::minTemp(size_t k) const +{ + return m_sub->Tmin(); +} + +double PureFluidPhase::maxTemp(size_t k) const +{ + return m_sub->Tmax(); +} + doublereal PureFluidPhase::enthalpy_mole() const { setTPXState(); From 8087a323a1535533ecb053c1906f169bd9f66ba2 Mon Sep 17 00:00:00 2001 From: Ray Speth Date: Sat, 2 Dec 2017 16:49:34 -0500 Subject: [PATCH 2/2] [Reactor] Fix using pure substances near temperature limits Fixes #475 --- .../cython/cantera/test/test_reactor.py | 26 +++++++++++++++++++ src/zeroD/Reactor.cpp | 17 ++++++++---- 2 files changed, 38 insertions(+), 5 deletions(-) diff --git a/interfaces/cython/cantera/test/test_reactor.py b/interfaces/cython/cantera/test/test_reactor.py index fe840dd111..2091805590 100644 --- a/interfaces/cython/cantera/test/test_reactor.py +++ b/interfaces/cython/cantera/test/test_reactor.py @@ -1468,6 +1468,32 @@ def test_Reactor(self): self.assertEqual(states.X[-1], 1) self.assertNear(states.X[30], 0.54806, 1e-4) + def test_Reactor_2(self): + phase = ct.PureFluid('liquidvapor.xml', 'carbondioxide') + air = ct.Solution('air.xml') + + phase.TP = 218, 5e6 + r1 = ct.Reactor(phase) + r1.volume = 0.1 + + air.TP = 500, 5e6 + r2 = ct.Reactor(air) + r2.volume = 10.0 + + w1 = ct.Wall(r1, r2, U=10000, A=1) + w1.expansion_rate_coeff = 1e-3 + net = ct.ReactorNet([r1,r2]) + + states = ct.SolutionArray(phase, extra='t') + for t in np.arange(0.0, 60.0, 1): + net.advance(t) + states.append(TD=r1.thermo.TD, t=net.time) + + self.assertEqual(states.X[0], 0) + self.assertEqual(states.X[-1], 1) + self.assertNear(states.X[20], 0.644865, 1e-4) + + def test_ConstPressureReactor(self): phase = ct.Nitrogen() air = ct.Solution('air.xml') diff --git a/src/zeroD/Reactor.cpp b/src/zeroD/Reactor.cpp index 82c87b4a04..abb1301b45 100644 --- a/src/zeroD/Reactor.cpp +++ b/src/zeroD/Reactor.cpp @@ -144,13 +144,20 @@ void Reactor::updateState(doublereal* y) TT = bmt::bracket_and_solve_root( u_err, T, 1.2, true, bmt::eps_tolerance(48), maxiter); } catch (std::exception& err) { - // Set m_thermo back to a reasonable state if root finding fails - m_thermo->setState_TR(T, m_mass / m_vol); - throw CanteraError("Reactor::updateState", err.what()); + // Try full-range bisection if bracketing fails (e.g. near + // temperature limits for the phase's equation of state) + try { + TT = bmt::bisect(u_err, m_thermo->minTemp(), m_thermo->maxTemp(), + bmt::eps_tolerance(48), maxiter); + } catch (std::exception& err2) { + // Set m_thermo back to a reasonable state if root finding fails + m_thermo->setState_TR(T, m_mass / m_vol); + throw CanteraError("Reactor::updateState", + "{}\nat U = {}, rho = {}", err2.what(), U, m_mass / m_vol); + } } if (fabs(TT.first - TT.second) > 1e-7*TT.first) { - throw CanteraError("Reactor::updateState", - "bracket_and_solve_root failed"); + throw CanteraError("Reactor::updateState", "root finding failed"); } m_thermo->setState_TR(TT.second, m_mass / m_vol); } else {