From 5efea129599cfdb7a4d7f580c145db95dde15b9c Mon Sep 17 00:00:00 2001 From: Ray Speth Date: Sun, 19 Feb 2017 16:32:28 -0500 Subject: [PATCH] [Thermo] Allow instantiation of IdealSolnGasVPSS without XML This is also the first test of PDSS_IdealGas that doesn't use XML --- include/cantera/thermo/IdealSolnGasVPSS.h | 16 +++++- src/thermo/IdealSolnGasVPSS.cpp | 62 ++++++++++++++--------- test/thermo/phaseConstructors.cpp | 28 ++++++++++ 3 files changed, 80 insertions(+), 26 deletions(-) diff --git a/include/cantera/thermo/IdealSolnGasVPSS.h b/include/cantera/thermo/IdealSolnGasVPSS.h index 1e377809e..e9336464e 100644 --- a/include/cantera/thermo/IdealSolnGasVPSS.h +++ b/include/cantera/thermo/IdealSolnGasVPSS.h @@ -45,6 +45,19 @@ public: return "IdealSolnGas"; } + //! Set this phase to represent an ideal gas + void setGasMode() { m_idealGas = true; } + + //! Set this phase to represent an ideal liquid or solid solution + void setSolnMode() { m_idealGas = false; } + + //! Set the standard concentration model + /* + * Does not apply to the ideal gas case. Must be one of 'unity', + * 'molar_volume', or 'solvent_volume'. + */ + void setStandardConcentrationModel(const std::string& model); + //! @} //! @name Molar Thermodynamic Properties //! @{ @@ -134,6 +147,7 @@ public: virtual bool addSpecies(shared_ptr spec); virtual void setParametersFromXML(const XML_Node& thermoNode); + virtual void initThermo(); virtual void setToEquilState(const doublereal* lambda_RT); virtual void initThermoXML(XML_Node& phaseNode, const std::string& id); @@ -149,7 +163,7 @@ protected: //! form of the generalized concentrations /*! - * - 0 unity + * - 0 unity (default) * - 1 1/V_k * - 2 1/V_0 */ diff --git a/src/thermo/IdealSolnGasVPSS.cpp b/src/thermo/IdealSolnGasVPSS.cpp index 8884ff351..be3167bb0 100644 --- a/src/thermo/IdealSolnGasVPSS.cpp +++ b/src/thermo/IdealSolnGasVPSS.cpp @@ -22,7 +22,7 @@ namespace Cantera { IdealSolnGasVPSS::IdealSolnGasVPSS() : - m_idealGas(0), + m_idealGas(-1), m_formGC(0) { } @@ -43,6 +43,25 @@ IdealSolnGasVPSS::IdealSolnGasVPSS(const std::string& infile, std::string id_) : importPhase(*xphase, this); } +void IdealSolnGasVPSS::setStandardConcentrationModel(const std::string& model) +{ + if (m_idealGas) { + throw CanteraError("IdealSolnGasVPSS::setStandardConcentrationModel", + "Standard concentration model not applicable for ideal gas"); + } + + if (ba::iequals(model, "unity")) { + m_formGC = 0; + } else if (ba::iequals(model, "molar_volume")) { + m_formGC = 1; + } else if (ba::iequals(model, "solvent_volume")) { + m_formGC = 2; + } else { + throw CanteraError("IdealSolnGasVPSS::setStandardConcentrationModel", + "Unknown standard concentration model '{}'", model); + } +} + // ------------Molar Thermodynamic Properties ------------------------- doublereal IdealSolnGasVPSS::enthalpy_mole() const @@ -234,15 +253,24 @@ bool IdealSolnGasVPSS::addSpecies(shared_ptr spec) return added; } +void IdealSolnGasVPSS::initThermo() +{ + VPStandardStateTP::initThermo(); + if (m_idealGas == -1) { + throw CanteraError("IdealSolnGasVPSS::initThermo", + "solution / gas mode not set"); + } +} + void IdealSolnGasVPSS::initThermoXML(XML_Node& phaseNode, const std::string& id_) { if (phaseNode.hasChild("thermo")) { XML_Node& thermoNode = phaseNode.child("thermo"); std::string model = thermoNode["model"]; if (model == "IdealGasVPSS") { - m_idealGas = 1; + setGasMode(); } else if (model == "IdealSolnVPSS") { - m_idealGas = 0; + setSolnMode(); } else { throw CanteraError("IdealSolnGasVPSS::initThermoXML", "Unknown thermo model : " + model); @@ -255,27 +283,11 @@ void IdealSolnGasVPSS::initThermoXML(XML_Node& phaseNode, const std::string& id_ // // if (phaseNode.hasChild("standardConc")) { - if (m_idealGas) { - throw CanteraError("IdealSolnGasVPSS::initThermoXML", - "standardConc node for ideal gas"); - } XML_Node& scNode = phaseNode.child("standardConc"); - string formString = scNode.attrib("model"); - if (ba::iequals(formString, "unity")) { - m_formGC = 0; - } else if (ba::iequals(formString, "molar_volume")) { - m_formGC = 1; - } else if (ba::iequals(formString, "solvent_volume")) { - m_formGC = 2; - } else { - throw CanteraError("initThermoXML", - "Unknown standardConc model: " + formString); - } - } else { - if (!m_idealGas) { - throw CanteraError("initThermoXML", - "Unspecified standardConc model"); - } + setStandardConcentrationModel(scNode.attrib("model")); + } else if (!m_idealGas) { + throw CanteraError("IdealSolnGasVPSS::initThermoXML", + "Unspecified standardConc model"); } VPStandardStateTP::initThermoXML(phaseNode, id_); @@ -286,9 +298,9 @@ void IdealSolnGasVPSS::setParametersFromXML(const XML_Node& thermoNode) VPStandardStateTP::setParametersFromXML(thermoNode); std::string model = thermoNode["model"]; if (model == "IdealGasVPSS") { - m_idealGas = 1; + setGasMode(); } else if (model == "IdealSolnVPSS") { - m_idealGas = 0; + setSolnMode(); } else { throw CanteraError("IdealSolnGasVPSS::initThermoXML", "Unknown thermo model : " + model); diff --git a/test/thermo/phaseConstructors.cpp b/test/thermo/phaseConstructors.cpp index 4a50a2e9f..701633480 100644 --- a/test/thermo/phaseConstructors.cpp +++ b/test/thermo/phaseConstructors.cpp @@ -1,10 +1,12 @@ #include "gtest/gtest.h" #include "cantera/thermo/ThermoFactory.h" +#include "cantera/thermo/PDSSFactory.h" #include "cantera/thermo/FixedChemPotSSTP.h" #include "cantera/thermo/PureFluidPhase.h" #include "cantera/thermo/WaterSSTP.h" #include "cantera/thermo/RedlichKwongMFTP.h" #include "cantera/thermo/IonsFromNeutralVPSSTP.h" +#include "cantera/thermo/IdealSolnGasVPSS.h" #include "cantera/thermo/NasaPoly2.h" #include "cantera/thermo/ShomatePoly.h" #include "cantera/thermo/IdealGasPhase.h" @@ -224,6 +226,32 @@ TEST_F(ConstructFromScratch, RedlichKwongMFTP) EXPECT_NEAR(p.enthalpy_mole(), -404848642.3797, 1e-3); } +TEST_F(ConstructFromScratch, IdealSolnGasVPSS_gas) +{ + IdealSolnGasVPSS p; + p.addUndefinedElements(); + p.addSpecies(sH2O); + p.addSpecies(sH2); + p.addSpecies(sO2); + std::unique_ptr pH2O(newPDSS("ideal-gas")); + std::unique_ptr pH2(newPDSS("ideal-gas")); + std::unique_ptr pO2(newPDSS("ideal-gas")); + p.installPDSS(0, std::move(pH2O)); + p.installPDSS(1, std::move(pH2)); + p.installPDSS(2, std::move(pO2)); + + p.setGasMode(); + EXPECT_THROW(p.setStandardConcentrationModel("unity"), CanteraError); + p.initThermo(); + + p.setState_TPX(400, 5*OneAtm, "H2:0.01, O2:0.99"); + p.equilibrate("HP"); + + EXPECT_NEAR(p.temperature(), 479.929, 1e-3); // based on h2o2.cti + EXPECT_NEAR(p.moleFraction("H2O"), 0.01, 1e-4); + EXPECT_NEAR(p.moleFraction("H2"), 0.0, 1e-4); +} + TEST(PureFluidFromScratch, CarbonDioxide) { PureFluidPhase p;