Bug fixes for liquid electrolyte thermo capability.

thermo XML node now takes a couple of extra XML nodes that can specify
explicitly which standardStateManager and which variblePressureStandardState
manager to use.

These are :
  <standardStateManager model="provide_specific_model_here">


and
  <variablePressureStandardStateManager model="provide_specific_model_here">

Previously, these were being determined implicitly by querying the
input deck. However, it seems a no brainer to put the capability for
putting explicit instructions in.
This commit is contained in:
Harry Moffat 2008-09-23 15:57:52 +00:00
parent 4dcb746101
commit c884917c95
15 changed files with 260 additions and 161 deletions

View file

@ -32,6 +32,8 @@ namespace Cantera {
m_temp(-1.0),
m_pres(-1.0),
m_p0(-1.0),
m_minTemp(-1.0),
m_maxTemp(10000.0),
m_tp(0),
m_vpssmgr_ptr(0),
m_mw(0.0),
@ -55,6 +57,8 @@ namespace Cantera {
m_temp(-1.0),
m_pres(-1.0),
m_p0(-1.0),
m_minTemp(-1.0),
m_maxTemp(10000.0),
m_tp(tp),
m_vpssmgr_ptr(0),
m_mw(0.0),
@ -87,6 +91,8 @@ namespace Cantera {
m_temp(-1.0),
m_pres(-1.0),
m_p0(-1.0),
m_minTemp(-1.0),
m_maxTemp(10000.0),
m_tp(0),
m_vpssmgr_ptr(0),
m_mw(b.m_mw),
@ -121,6 +127,8 @@ namespace Cantera {
m_temp = b.m_temp;
m_pres = b.m_pres;
m_p0 = b.m_p0;
m_minTemp = b.m_minTemp;
m_maxTemp = b.m_maxTemp;
m_tp = b.m_tp;
m_vpssmgr_ptr = b.m_vpssmgr_ptr;
m_mw = b.m_mw;
@ -158,10 +166,12 @@ namespace Cantera {
void PDSS::initThermoXML(const XML_Node& phaseNode, std::string& id) {
AssertThrow(m_tp != 0, "PDSS::initThermoXML()");
m_vpssmgr_ptr = m_tp->provideVPSSMgr();
}
void PDSS::initThermo() {
AssertThrow(m_tp != 0, "PDSS::initThermo()");
m_vpssmgr_ptr = m_tp->provideVPSSMgr();
initPtrs();
}
@ -361,7 +371,6 @@ namespace Cantera {
return(cp_mole() - GasConstant * tmp);
}
/**
* Calculate the pressure (Pascals), given the temperature and density
* Temperature: kelvin

View file

@ -279,6 +279,17 @@ namespace Cantera {
return m_p0;
}
//! return the minimum temperature
doublereal minTemp() const {
return m_minTemp;
}
//! return the minimum temperature
doublereal maxTemp() const {
return m_maxTemp;
}
//! Return the molar gibbs free energy divided by RT at reference pressure
/*!
* Returns the species reference state gibbs free energy divided by RT at the
@ -486,6 +497,12 @@ namespace Cantera {
//! reference state pressure of the species.
doublereal m_p0;
//! minimum temperature
doublereal m_minTemp;
//! maximum temperature
doublereal m_maxTemp;
//! Thermophase which this species belongs to.
/*!
* Note, in some

View file

@ -155,7 +155,7 @@ namespace Cantera {
// Ok we may change this evaluation method in the future.
double GG = gibbs_mole();
double SS = entropy_mole();
double h = GG - m_temp * SS;
double h = GG + m_temp * SS;
return h;
}
@ -483,8 +483,8 @@ namespace Cantera {
const XML_Node& speciesNode,
const XML_Node& phaseNode, bool spInstalled) {
PDSS::initThermo();
SpeciesThermo &sp = m_tp->speciesThermo();
m_p0 = sp.refPressure(m_spindex);
// m_p0 = OneAtm;
if (!spInstalled) {
throw CanteraError("PDSS_HKFT::constructPDSSXML", "spInstalled false not handled");
@ -507,6 +507,23 @@ namespace Cantera {
"no Thermo::HKFT Node for species " + speciesNode.name());
}
// go get the attributes
m_p0 = OneAtm;
std::string p0string = (*hh)["Pref"];
if (p0string != "") {
m_p0 = strSItoDbl(p0string);
}
std::string minTstring = (*hh)["Tmin"];
if (minTstring != "") {
m_minTemp = atofCheck(minTstring.c_str());
}
std::string maxTstring = (*hh)["Tmax"];
if (maxTstring != "") {
m_maxTemp = atofCheck(maxTstring.c_str());
}
if (hh->hasChild("DG0_f_Pr_Tr")) {
double val = getFloat(*hh, "DG0_f_Pr_Tr");
m_deltaG_formation_tr_pr = val;

View file

@ -28,9 +28,8 @@ namespace Cantera {
PDSS_Water::PDSS_Water() :
PDSS(),
m_sub(0),
m_temp(0.0),
m_dens(1000.0),
m_iState(-3000),
m_iState(WATER_LIQUID),
EW_Offset(0.0),
SW_Offset(0.0),
m_verbose(0),
@ -40,14 +39,15 @@ namespace Cantera {
m_sub = new WaterPropsIAPWS();
m_spthermo = 0;
constructSet();
m_minTemp = 200.;
m_maxTemp = 10000.;
}
PDSS_Water::PDSS_Water(VPStandardStateTP *tp, int spindex) :
PDSS(tp, spindex),
m_sub(0),
m_temp(0.0),
m_dens(1000.0),
m_iState(-3000),
m_iState(WATER_LIQUID),
EW_Offset(0.0),
SW_Offset(0.0),
m_verbose(0),
@ -57,6 +57,8 @@ namespace Cantera {
m_sub = new WaterPropsIAPWS();
m_spthermo = 0;
constructSet();
m_minTemp = 200.;
m_maxTemp = 10000.;
}
@ -64,9 +66,8 @@ namespace Cantera {
std::string inputFile, std::string id) :
PDSS(tp, spindex),
m_sub(0),
m_temp(0.0),
m_dens(1000.0),
m_iState(-3000),
m_iState(WATER_LIQUID),
EW_Offset(0.0),
SW_Offset(0.0),
m_verbose(0),
@ -76,6 +77,8 @@ namespace Cantera {
m_sub = new WaterPropsIAPWS();
constructPDSSFile(tp, spindex, inputFile, id);
m_spthermo = 0;
m_minTemp = 200.;
m_maxTemp = 10000.;
}
PDSS_Water::PDSS_Water(VPStandardStateTP *tp, int spindex,
@ -83,9 +86,8 @@ namespace Cantera {
const XML_Node& phaseRoot, bool spInstalled) :
PDSS(tp, spindex),
m_sub(0),
m_temp(0.0),
m_dens(1000.0),
m_iState(-3000),
m_iState(WATER_LIQUID),
EW_Offset(0.0),
SW_Offset(0.0),
m_verbose(0),
@ -97,6 +99,8 @@ namespace Cantera {
constructPDSSXML(tp, spindex, phaseRoot, id) ;
initThermo();
m_spthermo = 0;
m_minTemp = 200.;
m_maxTemp = 10000.;
}
@ -104,9 +108,8 @@ namespace Cantera {
PDSS_Water::PDSS_Water(const PDSS_Water &b) :
PDSS(),
m_sub(0),
m_temp(0.0),
m_dens(1000.0),
m_iState(-3000),
m_iState(WATER_LIQUID),
EW_Offset(b.EW_Offset),
SW_Offset(b.SW_Offset),
m_verbose(b.m_verbose),
@ -131,7 +134,6 @@ namespace Cantera {
PDSS::operator=(b);
m_sub->operator=(*(b.m_sub));
m_temp = b.m_temp;
m_dens = b.m_dens;
m_iState = b.m_iState;
EW_Offset = b.EW_Offset;
@ -375,9 +377,7 @@ namespace Cantera {
if (T > m_sub->Tcrit()) {
waterState = WATER_SUPERCRIT;
}
if (p < 1.0) {
waterState = WATER_GAS;
}
#ifdef DEBUG_HKM
//printf("waterPDSS: set pres = %g t = %g, waterState = %d\n",
@ -393,8 +393,14 @@ namespace Cantera {
m_dens = dd;
m_pres = p;
// We are only putting the phase check here because of speed considerations.
m_iState = m_sub->phaseState(true);
if (! m_allowGasPhase) {
if (m_iState != WATER_SUPERCRIT && m_iState != WATER_LIQUID && m_iState != WATER_UNSTABLELIQUID) {
throw CanteraError("PDSS_Water::setPressure",
"Water State isn't liquid or crit");
}
}
}
// Return the volumetric thermal expansion coefficient. Units: 1/K.
@ -467,13 +473,10 @@ namespace Cantera {
// saturation pressure
doublereal PDSS_Water::satPressure(doublereal t){
doublereal pp = m_sub->psat(t);
doublereal dens = m_dens;
doublereal pp = m_sub->psat(t, WATER_LIQUID);
m_dens = m_sub->density();
m_temp = t;
m_dens = dens;
return pp;
}
}

View file

@ -486,11 +486,6 @@ namespace Cantera {
*/
mutable WaterPropsIAPWS *m_sub;
/**
* state of the system (temperature and density);
*/
doublereal m_temp;
//! State of the system - density
/*!
* Density is the independent variable here, but it's hidden behind the
@ -525,6 +520,7 @@ namespace Cantera {
//! Verbose flag - used?
bool m_verbose;
public:
/**
* Since this phase represents a liquid phase, it's an error to
* return a gas-phase answer. However, if the below is true, then
@ -537,6 +533,3 @@ namespace Cantera {
}
#endif

View file

@ -155,10 +155,7 @@ namespace Cantera {
+ SHOMATE*ishomate + SIMPLE*isimple);
}
SpeciesThermo* SpeciesThermoFactory::newSpeciesThermo(int type) {
switch (type) {
case NASA:
return new NasaThermo;
@ -173,12 +170,36 @@ namespace Cantera {
case SHOMATE + SIMPLE:
return new SpeciesThermoDuo<ShomateThermo, SimpleThermo>;
default:
throw UnknownSpeciesThermo(
"SpeciesThermoFactory::newSpeciesThermo",type);
throw UnknownSpeciesThermo("SpeciesThermoFactory::newSpeciesThermo",
type);
return 0;
}
}
SpeciesThermo* SpeciesThermoFactory::newSpeciesThermoManager(std::string &stype) {
std::string ltype = lowercase(stype);
if (ltype == "nasa") {
return new NasaThermo;
} else if (ltype == "shomate") {
return new ShomateThermo;
} else if (ltype == "simple" || ltype == "constant_cp") {
return new SimpleThermo;
} else if (ltype == "nasa_shomate_duo") {
return new SpeciesThermoDuo<NasaThermo, ShomateThermo>;
} else if (ltype == "nasa_simple_duo") {
return new SpeciesThermoDuo<NasaThermo, SimpleThermo>;
} else if (ltype == "shomate_simple_duo") {
return new SpeciesThermoDuo<ShomateThermo, SimpleThermo>;
} else if (ltype == "general") {
return new GeneralSpeciesThermo();
} else if (ltype == "") {
return (SpeciesThermo*) 0;
} else {
throw UnknownSpeciesThermo("SpeciesThermoFactory::newSpeciesThermoManager",
stype);
}
return (SpeciesThermo*) 0;
}
/*
* Check the continuity of properties at the midpoint
@ -186,7 +207,6 @@ namespace Cantera {
*/
void NasaThermo::checkContinuity(std::string name, double tmid, const doublereal* clow,
doublereal* chigh) {
// heat capacity
doublereal cplow = poly4(tmid, clow);
doublereal cphigh = poly4(tmid, chigh);

View file

@ -130,6 +130,16 @@ namespace Cantera {
*/
SpeciesThermo* newSpeciesThermo(int type);
//! Create a new species thermo property manager given a string
/*!
* Create a new species thermo property manager, given a
* string.
*
* @param stype String name for the species thermo type
*/
SpeciesThermo* newSpeciesThermoManager(std::string &stype);
//! Create a new species property manager.
/*!
* This routine will look through species nodes. It will discover what
@ -257,6 +267,29 @@ namespace Cantera {
return sptherm;
}
//! Create a new species thermo manager instance, by specifying
//!the type and (optionally) a pointer to the factory to use to create it.
/*!
* This utility program is a basic factory operation for spawning a
* new species reference-state thermo mananger
*
* These functions allows for using a different factory class that
* derives from SpeciesThermoFactory. However, no applications of this
* have been done yet.
*
* @param type Species thermo type.
* @param f Pointer to a SpeciesThermoFactory. optional parameter.
* Defautls to NULL.
*/
inline SpeciesThermo* newSpeciesThermoMgr(std::string &stype,
SpeciesThermoFactory* f=0) {
if (f == 0) {
f = SpeciesThermoFactory::factory();
}
SpeciesThermo* sptherm = f->newSpeciesThermoManager(stype);
return sptherm;
}
//! Function to return SpeciesThermo manager
/*!
* This utility program will look through species nodes. It will discover what

View file

@ -72,15 +72,13 @@ namespace Cantera {
//! Returns the minimum temperature that the thermo
//! parameterization is valid
doublereal STITbyPDSS::minTemp() const {
// This concept needs to be put into PDSS
return 0.0;
return m_PDSS_ptr->minTemp();
}
//! Returns the maximum temperature that the thermo
//! parameterization is valid
doublereal STITbyPDSS::maxTemp() const {
// This concept needs to be put into PDSS
return 0.0;
return m_PDSS_ptr->maxTemp();
}
//! Returns the reference pressure (Pa)

View file

@ -133,6 +133,10 @@ namespace Cantera {
UnknownSpeciesThermo(std::string proc, int type) :
CanteraError(proc, "Specified species parameterization type (" + int2str(type)
+ ") does not match any known type.") {}
UnknownSpeciesThermo(std::string proc, std::string stype) :
CanteraError(proc, "Specified species parameterization type (" + stype
+ ") does not match any known type.") {}
//! destructor
virtual ~UnknownSpeciesThermo() {}
};

View file

@ -377,14 +377,14 @@ namespace Cantera {
SpeciesThermo* spth = 0;
VPSSMgr* vp_spth = 0;
if (ssConvention == cSS_CONVENTION_TEMPERATURE) {
// Create a new species thermo manager. Function
// 'newSpeciesThermoMgr' looks at the species in the database
// to see what thermodynamic property parameterizations are
// used, and selects a class that can handle the
// parameterizations found.
// Create a new species thermo manager. Function
// 'newSpeciesThermoMgr' looks at the species in the database
// to see what thermodynamic property parameterizations are
// used, and selects a class that can handle the
// parameterizations found.
spth = newSpeciesThermoMgr(dbases);
// install it in the phase object
// install it in the phase object
th->setSpeciesThermo(spth);
// SpeciesThermo& spthermo = th->speciesThermo();
} else {

View file

@ -43,7 +43,7 @@ namespace Cantera {
m_plast(-1.0),
m_p0(-1.0),
m_minTemp(-1.0),
m_maxTemp(-1.0),
m_maxTemp(1.0E8),
m_useTmpRefStateStorage(false),
m_useTmpStandardStateStorage(false)
{
@ -67,7 +67,7 @@ namespace Cantera {
m_plast(-1.0),
m_p0(-1.0),
m_minTemp(-1.0),
m_maxTemp(-1.0),
m_maxTemp(1.0E8),
m_useTmpRefStateStorage(false),
m_useTmpStandardStateStorage(false)
{
@ -399,9 +399,7 @@ namespace Cantera {
PDSS * VPSSMgr::createInstallPDSS(int k, const XML_Node& s,
const XML_Node *phaseNode_ptr) {
// VPSSMgr_enumType tt = reportVPSSMgrType();
//string ttt = "createInstallPDSS: " + int2str(int(tt));
err( "createInstallPDSS: ");
err("VPSSMgr::createInstallPDSS");
return (PDSS *) 0;
}

View file

@ -150,18 +150,19 @@ namespace Cantera {
VPSSMgr_enumType
VPSSMgrFactory::VPSSMgr_StringConversion(std::string ssModel) const {
std::string lssModel = lowercase(ssModel);
VPSSMgr_enumType type;
if (ssModel == "IdealGas") {
if (lssModel == "idealgas") {
type = cVPSSMGR_IDEALGAS;
} else if (ssModel == "ConstVol") {
} else if (lssModel == "constvol") {
type = cVPSSMGR_CONSTVOL;
} else if (ssModel == "PureFuild") {
} else if (lssModel == "purefuild") {
type = cVPSSMGR_PUREFLUID;
} else if (ssModel == "Water_ConstVol") {
} else if (lssModel == "water_constvol") {
type = cVPSSMGR_WATER_CONSTVOL;
} else if (ssModel == "Water_HKFT") {
} else if (lssModel == "water_hkft") {
type = cVPSSMGR_WATER_HKFT;
} else if (ssModel == "General") {
} else if (lssModel == "general") {
type = cVPSSMGR_GENERAL;
} else {
type = cVPSSMGR_UNDEF;
@ -169,108 +170,65 @@ namespace Cantera {
return type;
}
// Stub out of new capabilities.
// Chose the variable pressure standard state manager
// and the reference standard state manager
VPSSMgr*
VPSSMgrFactory::newVPSSMgr(VPStandardStateTP *vp_ptr,
XML_Node* phaseNode_ptr,
XML_Node* spData_node) {
std::string ssModel="";
VPSSMgr *vpss = 0;
// First look for any explicit instructions within the XML Data
if (phaseNode_ptr) {
if (phaseNode_ptr->hasChild("thermo")) {
const XML_Node& thermoNode = phaseNode_ptr->child("thermo");
if (thermoNode.hasChild("standardState")) {
const XML_Node& ssNode = thermoNode.child("standardState");
ssModel = ssNode["model"];
}
}
}
// first get the reference state handler
SpeciesThermo *spth = newSpeciesThermoMgr(spData_node);
vp_ptr->setSpeciesThermo(spth);
if (ssModel != "") {
VPSSMgr_enumType type = VPSSMgr_StringConversion(ssModel);
vpss = newVPSSMgr(type, vp_ptr);
return vpss;
}
// If it comes back as general, then there may be some unknown
// parameterizations to the SpeciesThermo factory routine.
bool haveSomeUnknowns = true;
GeneralSpeciesThermo *ttmp = dynamic_cast<GeneralSpeciesThermo *>(spth);
if (ttmp == 0) {
haveSomeUnknowns = false;
}
if (vp_ptr->eosType() == cVPSS_IdealGas) {
vpss = new VPSSMgr_IdealGas(vp_ptr, spth);
}
if (vp_ptr->eosType() == cVPSS_ConstVol) {
vpss = new VPSSMgr_ConstVol(vp_ptr, spth);
}
int inasa = 0, ishomate = 0, isimple = 0, iwater = 0, itpx = 0, iother = 0;
int ihptx = 0;
try {
getVPSSMgrTypes(spData_node, inasa, ishomate, isimple, iwater,
itpx, ihptx, iother);
} catch (UnknownSpeciesThermoModel) {
iother = 1;
popError();
}
if (iwater == 1) {
if (ihptx == 0) {
vpss = new VPSSMgr_Water_ConstVol(vp_ptr, spth);
} else {
vpss = new VPSSMgr_Water_HKFT(vp_ptr, spth);
}
}
// The default here is to fall back to use the completely
// general representation.
if (vpss == 0) {
vpss = new VPSSMgr_General(vp_ptr, spth);
}
return vpss;
std::vector<XML_Node*> spData_nodes;
spData_nodes.push_back(spData_node);
VPSSMgr *vv = newVPSSMgr(vp_ptr, phaseNode_ptr, spData_nodes);
return vv;
}
// Chose the variable pressure standard state manager
// and the reference standard state manager
VPSSMgr*
VPSSMgrFactory::newVPSSMgr(VPStandardStateTP *vp_ptr,
XML_Node* phaseNode_ptr,
std::vector<XML_Node*> spData_nodes) {
std::string ssModel="";
std::string ssManager="";
std::string vpssManager="";
VPSSMgr *vpss = 0;
// First look for any explicit instructions within the XML Data
// First look for any explicit instructions within the XML Database
// for the standard state manager and the variable pressure
// standard state manager
if (phaseNode_ptr) {
if (phaseNode_ptr->hasChild("thermo")) {
const XML_Node& thermoNode = phaseNode_ptr->child("thermo");
if (thermoNode.hasChild("standardState")) {
const XML_Node& ssNode = thermoNode.child("standardState");
ssModel = ssNode["model"];
if (thermoNode.hasChild("standardStateManager")) {
const XML_Node& ssNode = thermoNode.child("standardStateManager");
ssManager = ssNode["model"];
}
if (thermoNode.hasChild("variablePressureStandardStateManager")) {
const XML_Node& vpssNode = thermoNode.child("variablePressureStandardStateManager");
vpssManager = vpssNode["model"];
}
}
}
// first get the reference state handler
SpeciesThermo *spth = newSpeciesThermoMgr(spData_nodes);
// first get the reference state handler. If we have explicit instructions,
// use them to spawn the object.
SpeciesThermo *spth = 0;
if (ssManager != "") {
spth = newSpeciesThermoMgr(ssManager);
} else {
spth = newSpeciesThermoMgr(spData_nodes);
}
vp_ptr->setSpeciesThermo(spth);
if (ssModel != "") {
VPSSMgr_enumType type = VPSSMgr_StringConversion(ssModel);
// Next, if we have specific directions, use them to get the VPSSSMgr object
// and return immediately
if (vpssManager != "") {
VPSSMgr_enumType type = VPSSMgr_StringConversion(vpssManager);
vpss = newVPSSMgr(type, vp_ptr);
return vpss;
}
// If it comes back as general, then there may be some unknown
// parameterizations to the SpeciesThermo factory routine.
bool haveSomeUnknowns = true;
@ -278,14 +236,16 @@ namespace Cantera {
if (ttmp == 0) {
haveSomeUnknowns = false;
}
if (vp_ptr->eosType() == cIdealSolnGasVPSS) {
// Handle special cases based on the VPStandardState types
if (vp_ptr->eosType() == cVPSS_IdealGas) {
vpss = new VPSSMgr_IdealGas(vp_ptr, spth);
return vpss;
} else if (vp_ptr->eosType() == cVPSS_ConstVol) {
vpss = new VPSSMgr_ConstVol(vp_ptr, spth);
return vpss;
}
if (vp_ptr->eosType() == cIdealSolnGasVPSS_iscv) {
vpss = new VPSSMgr_ConstVol(vp_ptr, spth);
}
int n = static_cast<int>(spData_nodes.size());
int inasa = 0, ishomate = 0, isimple = 0, iwater = 0, itpx = 0, iother = 0;

View file

@ -31,6 +31,7 @@
#include "PDSS_Water.h"
#include "PDSS_ConstVol.h"
#include "PDSS_HKFT.h"
#include "GeneralSpeciesThermo.h"
using namespace std;
@ -75,20 +76,20 @@ namespace Cantera {
}
void VPSSMgr_General::_updateRefStateThermo() const
{
for (int k = 0; k < m_kk; k++) {
PDSS *kPDSS = m_PDSS_ptrs[k];
kPDSS->setState_TP(m_tlast, m_plast);
m_h0_RT[k] = kPDSS->enthalpy_RT_ref();
m_s0_R[k] = kPDSS->entropy_R_ref();
m_g0_RT[k] = m_h0_RT[k] - m_s0_R[k];
m_cp0_R[k] = kPDSS->cp_R_ref();
m_V0[k] = kPDSS->molarVolume_ref();
if (m_useTmpRefStateStorage) {
for (int k = 0; k < m_kk; k++) {
PDSS *kPDSS = m_PDSS_ptrs[k];
kPDSS->setState_TP(m_tlast, m_plast);
m_h0_RT[k] = kPDSS->enthalpy_RT_ref();
m_s0_R[k] = kPDSS->entropy_R_ref();
m_g0_RT[k] = m_h0_RT[k] - m_s0_R[k];
m_cp0_R[k] = kPDSS->cp_R_ref();
m_V0[k] = kPDSS->molarVolume_ref();
}
}
}
void VPSSMgr_General::_updateStandardStateThermo()
{
@ -120,7 +121,9 @@ namespace Cantera {
const XML_Node *phaseNode_ptr, bool &doST) {
PDSS *kPDSS = 0;
doST = true;
GeneralSpeciesThermo *genSpthermo = dynamic_cast<GeneralSpeciesThermo *>(m_spthermo);
const XML_Node * const ss = speciesNode.findByName("standardState");
if (!ss) {
VPSSMgr::installSTSpecies(k, speciesNode, phaseNode_ptr);
@ -131,12 +134,23 @@ namespace Cantera {
if (model == "constant_incompressible") {
VPSSMgr::installSTSpecies(k, speciesNode, phaseNode_ptr);
kPDSS = new PDSS_ConstVol(m_vptp_ptr, k, speciesNode, *phaseNode_ptr, true);
} else if (model == "waterIAPWS" || model == "waterPDSS") {
doST = false;
kPDSS = new PDSS_Water();
} else if (model == "waterIAPWS" || model == "waterPDSS") {
// VPSSMgr::installSTSpecies(k, speciesNode, phaseNode_ptr);
kPDSS = new PDSS_Water(m_vptp_ptr, 0);
if (!genSpthermo) {
throw CanteraError("VPSSMgr_General::returnPDSS_ptr",
"failed dynamic cast");
}
genSpthermo->installPDSShandler(k, kPDSS, this);
m_useTmpRefStateStorage = false;
} else if (model == "HKFT") {
doST = false;
kPDSS = new PDSS_HKFT(m_vptp_ptr, k, speciesNode, *phaseNode_ptr, true);
if (!genSpthermo) {
throw CanteraError("VPSSMgr_General::returnPDSS_ptr",
"failed dynamic cast");
}
genSpthermo->installPDSShandler(k, kPDSS, this);
} else {
throw CanteraError("VPSSMgr_General::returnPDSS_ptr",
"unknown");
@ -153,8 +167,26 @@ namespace Cantera {
if ((int) m_PDSS_ptrs.size() < k+1) {
m_PDSS_ptrs.resize(k+1, 0);
}
m_PDSS_ptrs[k] = kPDSS;
if ((k+1) >= m_kk) {
m_kk = k+1;
}
doublereal minTemp = kPDSS->minTemp();
if (minTemp > m_minTemp) {
m_minTemp = minTemp;
}
doublereal maxTemp = kPDSS->maxTemp();
if (maxTemp < m_maxTemp) {
m_maxTemp = maxTemp;
}
doublereal p0 = kPDSS->refPressure();
if (k == 0) {
m_p0 = p0;
}
return kPDSS;
}

View file

@ -406,9 +406,15 @@ corr1(doublereal temperature, doublereal pressure, doublereal &densLiq,
* p : Pascals : Newtons/m**2
*/
static int method = 1;
doublereal WaterPropsIAPWS::psat(doublereal temperature) {
doublereal WaterPropsIAPWS::psat(doublereal temperature, int waterState) {
doublereal densLiq = -1.0, densGas = -1.0, delGRT = 0.0;
doublereal dp, pcorr;
if (temperature >= T_c) {
densGas = density(temperature, P_c, WATER_SUPERCRIT);
setState_TR(temperature, densGas);
return P_c;
}
doublereal p = psat_est(temperature);
bool conv = false;
for (int i = 0; i < 30; i++) {
@ -432,6 +438,15 @@ doublereal WaterPropsIAPWS::psat(doublereal temperature) {
}
}
}
// Put the fluid in the desired end condition
if (waterState == WATER_LIQUID) {
setState_TR(temperature, densLiq);
} else if (waterState == WATER_GAS) {
setState_TR(temperature, densGas);
} else {
throw Cantera::CanteraError("WaterPropsIAPWS::psat",
"unknown water state input: " + Cantera::int2str(waterState));
}
return p;
}

View file

@ -332,7 +332,7 @@ public:
* Returns the saturation pressure
* units = Pascal
*/
doublereal psat(doublereal temperature);
doublereal psat(doublereal temperature, int waterState = WATER_LIQUID);
//! Return the value of the density at the water spinodal point
//! for the current temperature.