mirror of
https://github.com/Cantera/cantera.git
synced 2026-07-31 08:38:28 -05:00
[Thermo] Revert to previous state after error setting thermo state
This prevents ThermoPhase objects from ending up in broken states where they can't be set to a new state because of a partially-applied invalid state, for example caused by an out-of-range temperature.
This commit is contained in:
@@ -397,8 +397,15 @@ void Phase::setMassFractionsByName(const string& y)
|
||||
|
||||
void Phase::setState_TD(double t, double rho)
|
||||
{
|
||||
setTemperature(t);
|
||||
setDensity(rho);
|
||||
vector<double> state(partialStateSize());
|
||||
savePartialState(state.size(), state.data());
|
||||
try {
|
||||
setTemperature(t);
|
||||
setDensity(rho);
|
||||
} catch (std::exception&) {
|
||||
restorePartialState(state.size(), state.data());
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
double Phase::molecularWeight(size_t k) const
|
||||
|
||||
@@ -120,26 +120,40 @@ void ThermoPhase::setState_TPY(double t, double p, const string& y)
|
||||
|
||||
void ThermoPhase::setState_TP(double t, double p)
|
||||
{
|
||||
double tsave = temperature();
|
||||
double dsave = density();
|
||||
vector<double> state(partialStateSize());
|
||||
savePartialState(state.size(), state.data());
|
||||
try {
|
||||
setTemperature(t);
|
||||
setPressure(p);
|
||||
} catch (CanteraError&) {
|
||||
setState_TD(tsave, dsave);
|
||||
} catch (std::exception&) {
|
||||
restorePartialState(state.size(), state.data());
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
void ThermoPhase::setState_HP(double Htarget, double p, double rtol)
|
||||
{
|
||||
setState_HPorUV(Htarget, p, rtol, false);
|
||||
vector<double> state(partialStateSize());
|
||||
savePartialState(state.size(), state.data());
|
||||
try {
|
||||
setState_HPorUV(Htarget, p, rtol, false);
|
||||
} catch (std::exception&) {
|
||||
restorePartialState(state.size(), state.data());
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
void ThermoPhase::setState_UV(double u, double v, double rtol)
|
||||
{
|
||||
assertCompressible("setState_UV");
|
||||
setState_HPorUV(u, v, rtol, true);
|
||||
vector<double> state(partialStateSize());
|
||||
savePartialState(state.size(), state.data());
|
||||
try {
|
||||
setState_HPorUV(u, v, rtol, true);
|
||||
} catch (std::exception&) {
|
||||
restorePartialState(state.size(), state.data());
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
void ThermoPhase::setState(const AnyMap& input_state)
|
||||
@@ -452,13 +466,27 @@ void ThermoPhase::setState_HPorUV(double Htarget, double p,
|
||||
|
||||
void ThermoPhase::setState_SP(double Starget, double p, double rtol)
|
||||
{
|
||||
setState_SPorSV(Starget, p, rtol, false);
|
||||
vector<double> state(partialStateSize());
|
||||
savePartialState(state.size(), state.data());
|
||||
try {
|
||||
setState_SPorSV(Starget, p, rtol, false);
|
||||
} catch (std::exception&) {
|
||||
restorePartialState(state.size(), state.data());
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
void ThermoPhase::setState_SV(double Starget, double v, double rtol)
|
||||
{
|
||||
assertCompressible("setState_SV");
|
||||
setState_SPorSV(Starget, v, rtol, true);
|
||||
vector<double> state(partialStateSize());
|
||||
savePartialState(state.size(), state.data());
|
||||
try {
|
||||
setState_SPorSV(Starget, v, rtol, true);
|
||||
} catch (std::exception&) {
|
||||
restorePartialState(state.size(), state.data());
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
void ThermoPhase::setState_SPorSV(double Starget, double p,
|
||||
|
||||
@@ -302,4 +302,61 @@ TEST_F(EquilRatio_MixFrac_Test, EquilRatio_MixFrac_StoichMix_Mass)
|
||||
test_stoich_mixture(ThermoBasis::mass, 0.050011556441079318, 18.995378491732041);
|
||||
}
|
||||
|
||||
struct SetStateRecovery : public testing::Test
|
||||
{
|
||||
SetStateRecovery() {
|
||||
auto soln = newSolution("debye-huckel-all.yaml", "debye-huckel-B-dot-ak-IAPWS");
|
||||
thermo = soln->thermo();
|
||||
T1 = thermo->temperature();
|
||||
P1 = thermo->pressure();
|
||||
h1 = thermo->enthalpy_mass();
|
||||
cp1 = thermo->cp_mass();
|
||||
s1 = thermo->entropy_mass();
|
||||
}
|
||||
|
||||
shared_ptr<ThermoPhase> thermo;
|
||||
double T1, P1, h1, cp1, s1;
|
||||
};
|
||||
|
||||
TEST_F(SetStateRecovery, HP)
|
||||
{
|
||||
double h2 = h1 + cp1 * (600 - T1); // Water state is invalid at 600 K
|
||||
EXPECT_THROW(thermo->setState_HP(h2, P1), CanteraError);
|
||||
EXPECT_DOUBLE_EQ(thermo->temperature(), T1);
|
||||
EXPECT_DOUBLE_EQ(thermo->pressure(), P1);
|
||||
double h3 = h1 + cp1 * (350 - T1);
|
||||
thermo->setState_HP(h3, P1);
|
||||
EXPECT_NEAR(thermo->temperature(), 350, 1.0);
|
||||
}
|
||||
|
||||
TEST_F(SetStateRecovery, SP)
|
||||
{
|
||||
double T3 = T1 + 0.5 * (600 - T1);
|
||||
thermo->setState_TP(T3, P1);
|
||||
double s3 = thermo->entropy_mass();
|
||||
double s2 = s1 + 2.0 * (s3 - s1);
|
||||
thermo->setState_TP(T1, P1);
|
||||
EXPECT_THROW(thermo->setState_SP(s2, P1), CanteraError);
|
||||
EXPECT_DOUBLE_EQ(thermo->temperature(), T1);
|
||||
EXPECT_DOUBLE_EQ(thermo->pressure(), P1);
|
||||
thermo->setState_SP(s3, P1);
|
||||
EXPECT_NEAR(thermo->temperature(), T3, 1e-2);
|
||||
}
|
||||
|
||||
TEST_F(SetStateRecovery, TD)
|
||||
{
|
||||
EXPECT_THROW(thermo->setState_TD(400, -1), CanteraError);
|
||||
EXPECT_DOUBLE_EQ(thermo->temperature(), T1);
|
||||
EXPECT_DOUBLE_EQ(thermo->pressure(), P1);
|
||||
thermo->setState_TP(500, 2 * P1);
|
||||
}
|
||||
|
||||
TEST_F(SetStateRecovery, TP)
|
||||
{
|
||||
EXPECT_THROW(thermo->setState_TP(400, -1), CanteraError);
|
||||
EXPECT_DOUBLE_EQ(thermo->temperature(), T1);
|
||||
EXPECT_DOUBLE_EQ(thermo->pressure(), P1);
|
||||
thermo->setState_TP(500, 2 * P1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user