[Thermo] Add method for setting the state using an AnyMap
Analogous to ThermoPhase::setStateFromXML, but more flexible
This commit is contained in:
parent
3251a3533e
commit
c8b737035d
7 changed files with 195 additions and 0 deletions
|
|
@ -500,6 +500,12 @@ public:
|
|||
*/
|
||||
void setState_TPM(doublereal t, doublereal p, const std::string& m);
|
||||
|
||||
//! @copydoc ThermoPhase::setState
|
||||
/*!
|
||||
* Additionally uses the keys `molalities` or `M` to set the molalities.
|
||||
*/
|
||||
virtual void setState(const AnyMap& state);
|
||||
|
||||
virtual void getdlnActCoeffdlnN(const size_t ld, doublereal* const dlnActCoeffdlnN) {
|
||||
getdlnActCoeffdlnN_numderiv(ld, dlnActCoeffdlnN);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -394,6 +394,12 @@ public:
|
|||
*/
|
||||
void getCoverages(doublereal* theta) const;
|
||||
|
||||
//! @copydoc ThermoPhase::setState
|
||||
/*!
|
||||
* Additionally uses the key `coverages` to set the fractional coverages.
|
||||
*/
|
||||
virtual void setState(const AnyMap& state);
|
||||
|
||||
protected:
|
||||
//! Surface site density (kmol m-2)
|
||||
doublereal m_n0;
|
||||
|
|
|
|||
|
|
@ -1140,6 +1140,31 @@ public:
|
|||
*/
|
||||
virtual void setState_RPY(doublereal rho, doublereal p, const std::string& y);
|
||||
|
||||
//! Set the state using an AnyMap containing any combination of properties
|
||||
//! supported by the thermodynamic model
|
||||
/*!
|
||||
* Accepted keys are:
|
||||
* * `X` (mole fractions)
|
||||
* * `Y` (mass fractions)
|
||||
* * `T` or `temperature`
|
||||
* * `P` or `pressure` [Pa]
|
||||
* * `H` or `enthalpy` [J/kg]
|
||||
* * `U` or `internal-energy` [J/kg]
|
||||
* * `S` or `entropy` [J/kg/K]
|
||||
* * `V` or `specific-volume` [m^3/kg]
|
||||
* * `D` or `density` [kg/m^3]
|
||||
*
|
||||
* Composition can be specified as either an AnyMap of species names to
|
||||
* values or as a composition string. All other values can be given as
|
||||
* floating point values in Cantera's default units, or as strings with the
|
||||
* units specified, which will be converted using the Units class.
|
||||
*
|
||||
* If no thermodynamic property pair is given, or only one of temperature or
|
||||
* pressure is given, then 298.15 K and 101325 Pa will be used as necessary
|
||||
* to fully set the state.
|
||||
*/
|
||||
virtual void setState(const AnyMap& state);
|
||||
|
||||
//@}
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -271,6 +271,23 @@ void MolalityVPSSTP::setState_TPM(doublereal t, doublereal p, const std::string&
|
|||
setState_TP(t, p);
|
||||
}
|
||||
|
||||
void MolalityVPSSTP::setState(const AnyMap& state) {
|
||||
AnyValue molalities;
|
||||
if (state.hasKey("molalities")) {
|
||||
molalities = state["molalities"];
|
||||
} else if (state.hasKey("M")) {
|
||||
molalities = state["M"];
|
||||
}
|
||||
|
||||
if (molalities.is<string>()) {
|
||||
setMolalitiesByName(molalities.asString());
|
||||
} else if (molalities.is<AnyMap>()) {
|
||||
setMolalitiesByName(molalities.asMap<double>());
|
||||
}
|
||||
|
||||
VPStandardStateTP::setState(state);
|
||||
}
|
||||
|
||||
void MolalityVPSSTP::initThermo()
|
||||
{
|
||||
VPStandardStateTP::initThermo();
|
||||
|
|
|
|||
|
|
@ -289,6 +289,17 @@ void SurfPhase::setCoveragesByName(const compositionMap& cov)
|
|||
setCoverages(cv.data());
|
||||
}
|
||||
|
||||
void SurfPhase::setState(const AnyMap& state) {
|
||||
if (state.hasKey("coverages")) {
|
||||
if (state["coverages"].is<string>()) {
|
||||
setCoveragesByName(state["coverages"].asString());
|
||||
} else {
|
||||
setCoveragesByName(state["coverages"].asMap<double>());
|
||||
}
|
||||
}
|
||||
ThermoPhase::setState(state);
|
||||
}
|
||||
|
||||
void SurfPhase::_updateThermo(bool force) const
|
||||
{
|
||||
doublereal tnow = temperature();
|
||||
|
|
|
|||
|
|
@ -191,6 +191,102 @@ void ThermoPhase::setState_UV(double u, double v, double rtol)
|
|||
setState_HPorUV(u, v, rtol, true);
|
||||
}
|
||||
|
||||
void ThermoPhase::setState(const AnyMap& input_state)
|
||||
{
|
||||
AnyMap state = input_state;
|
||||
|
||||
// Remap allowable synonyms
|
||||
if (state.hasKey("mass-fractions")) {
|
||||
state["Y"] = state["mass-fractions"];
|
||||
state.erase("mass-fractions");
|
||||
}
|
||||
if (state.hasKey("mole-fractions")) {
|
||||
state["X"] = state["mole-fractions"];
|
||||
state.erase("mole-fractions");
|
||||
}
|
||||
if (state.hasKey("temperature")) {
|
||||
state["T"] = state["temperature"];
|
||||
}
|
||||
if (state.hasKey("pressure")) {
|
||||
state["P"] = state["pressure"];
|
||||
}
|
||||
if (state.hasKey("enthalpy")) {
|
||||
state["H"] = state["enthalpy"];
|
||||
}
|
||||
if (state.hasKey("int-energy")) {
|
||||
state["U"] = state["int-energy"];
|
||||
}
|
||||
if (state.hasKey("internal-energy")) {
|
||||
state["U"] = state["internal-energy"];
|
||||
}
|
||||
if (state.hasKey("specific-volume")) {
|
||||
state["V"] = state["specific-volume"];
|
||||
}
|
||||
if (state.hasKey("entropy")) {
|
||||
state["S"] = state["entropy"];
|
||||
}
|
||||
if (state.hasKey("density")) {
|
||||
state["D"] = state["density"];
|
||||
}
|
||||
|
||||
// Set composition
|
||||
if (state.hasKey("X")) {
|
||||
if (state["X"].is<string>()) {
|
||||
setMoleFractionsByName(state["X"].asString());
|
||||
} else {
|
||||
setMoleFractionsByName(state["X"].asMap<double>());
|
||||
}
|
||||
state.erase("X");
|
||||
} else if (state.hasKey("Y")) {
|
||||
if (state["Y"].is<string>()) {
|
||||
setMassFractionsByName(state["Y"].asString());
|
||||
} else {
|
||||
setMassFractionsByName(state["Y"].asMap<double>());
|
||||
}
|
||||
state.erase("Y");
|
||||
}
|
||||
// set thermodynamic state using whichever property pair is found
|
||||
if (state.size() == 0) {
|
||||
setState_TP(298.15, OneAtm);
|
||||
} else if (state.hasKey("T") && state.hasKey("P")) {
|
||||
setState_TP(state.convert("T", "K"), state.convert("P", "Pa"));
|
||||
} else if (state.hasKey("T") && state.hasKey("D")) {
|
||||
setState_TR(state.convert("T", "K"), state.convert("D", "kg/m^3"));
|
||||
} else if (state.hasKey("T") && state.hasKey("V")) {
|
||||
setState_TV(state.convert("T", "K"), state.convert("V", "m^3/kg"));
|
||||
} else if (state.hasKey("H") && state.hasKey("P")) {
|
||||
setState_HP(state.convert("H", "J/kg"), state.convert("P", "Pa"));
|
||||
} else if (state.hasKey("U") && state.hasKey("V")) {
|
||||
setState_UV(state.convert("U", "J/kg"), state.convert("V", "m^3/kg"));
|
||||
} else if (state.hasKey("S") && state.hasKey("P")) {
|
||||
setState_SP(state.convert("S", "J/kg/K"), state.convert("P", "Pa"));
|
||||
} else if (state.hasKey("S") && state.hasKey("V")) {
|
||||
setState_SV(state.convert("S", "J/kg/K"), state.convert("V", "m^3/kg"));
|
||||
} else if (state.hasKey("S") && state.hasKey("T")) {
|
||||
setState_ST(state.convert("S", "J/kg/K"), state.convert("T", "K"));
|
||||
} else if (state.hasKey("P") && state.hasKey("V")) {
|
||||
setState_PV(state.convert("P", "Pa"), state.convert("V", "m^3/kg"));
|
||||
} else if (state.hasKey("U") && state.hasKey("P")) {
|
||||
setState_UP(state.convert("U", "J/kg"), state.convert("P", "Pa"));
|
||||
} else if (state.hasKey("V") && state.hasKey("H")) {
|
||||
setState_VH(state.convert("V", "m^3/kg"), state.convert("H", "J/kg"));
|
||||
} else if (state.hasKey("T") && state.hasKey("H")) {
|
||||
setState_TH(state.convert("T", "K"), state.convert("H", "J/kg"));
|
||||
} else if (state.hasKey("S") && state.hasKey("H")) {
|
||||
setState_SH(state.convert("S", "J/kg/K"), state.convert("H", "J/kg"));
|
||||
} else if (state.hasKey("D") && state.hasKey("P")) {
|
||||
setState_RP(state.convert("D", "kg/m^3"), state.convert("P", "Pa"));
|
||||
} else if (state.hasKey("T")) {
|
||||
setState_TP(state.convert("T", "K"), OneAtm);
|
||||
} else if (state.hasKey("P")) {
|
||||
setState_TP(298.15, state.convert("P", "Pa"));
|
||||
} else {
|
||||
throw CanteraError("ThermoPhase::setState",
|
||||
"'state' did not specify a recognized set of properties.\n"
|
||||
"Keys provided were: {}", input_state.keys_str());
|
||||
}
|
||||
}
|
||||
|
||||
void ThermoPhase::setState_conditional_TP(doublereal t, doublereal p, bool set_p)
|
||||
{
|
||||
setTemperature(t);
|
||||
|
|
|
|||
|
|
@ -75,4 +75,38 @@ TEST_F(TestThermoMethods, setState_nan)
|
|||
EXPECT_THROW(thermo->setState_TR(555, nan), CanteraError);
|
||||
}
|
||||
|
||||
TEST_F(TestThermoMethods, setState_AnyMap)
|
||||
{
|
||||
AnyMap state;
|
||||
state["temperature"] = 321;
|
||||
state["Y"] = "AR: 4, O2: 1.0";
|
||||
state["P"] = "5 bar";
|
||||
thermo->setState(state);
|
||||
EXPECT_DOUBLE_EQ(thermo->temperature(), 321);
|
||||
EXPECT_DOUBLE_EQ(thermo->pressure(), 5e5);
|
||||
EXPECT_DOUBLE_EQ(thermo->massFraction("O2"), 0.2);
|
||||
|
||||
AnyMap state2;
|
||||
state2["P"] = OneAtm;
|
||||
state2["enthalpy"] = 0;
|
||||
state2["X"]["O2"] = 0.9;
|
||||
state2["X"]["AR"] = 0.1;
|
||||
thermo->setState(state2);
|
||||
EXPECT_DOUBLE_EQ(thermo->pressure(), OneAtm);
|
||||
EXPECT_NEAR(thermo->temperature(), 298.15, 1e-6);
|
||||
EXPECT_DOUBLE_EQ(thermo->moleFraction("AR"), 0.1);
|
||||
|
||||
AnyMap state3;
|
||||
state3["density"] = 10;
|
||||
state3["V"] = 0.1;
|
||||
state3["mole-fractions"] = "O2: 1.0";
|
||||
EXPECT_THROW(thermo->setState(state3), CanteraError);
|
||||
|
||||
AnyMap state4;
|
||||
state4["mole-fractions"] = "O2: 1.0";
|
||||
thermo->setState(state4);
|
||||
EXPECT_DOUBLE_EQ(thermo->pressure(), OneAtm);
|
||||
EXPECT_NEAR(thermo->temperature(), 298.15, 1e-6);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue