Changed the WaterTP class to WaterSSTP, which now inherits from SingleSpeciesTP,
as it should Fixed an error in pressure calculation within WaterSSTP. Added more function calls to the test problem for WaterSSTP.
This commit is contained in:
parent
581de52fbe
commit
6545937948
21 changed files with 928 additions and 499 deletions
|
|
@ -115,7 +115,7 @@ namespace Cantera {
|
|||
* - IdealGasPDSS in thermo/IdealGasPDSS.h
|
||||
* - MolalityVPSSTP in thermo/MolalityVPSSTP.h
|
||||
* - HMWSoln in thermo/HMWSoln.h
|
||||
* - WaterTP in thermo/WaterTP.h
|
||||
* - WaterSSTP in thermo/WaterSSTP.h
|
||||
* .
|
||||
*
|
||||
* @see newPhase(std::string file, std::string id) Description for how to
|
||||
|
|
|
|||
|
|
@ -850,7 +850,7 @@ namespace Cantera {
|
|||
copy(_s.begin(), _s.end(), sr);
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* Returns the vector of nondimensional
|
||||
* internal Energies of the standard state at the current temperature
|
||||
* of the solution and current pressure for each species.
|
||||
|
|
@ -870,7 +870,7 @@ namespace Cantera {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* Get the nondimensional heat capacity at constant pressure
|
||||
* function for the species
|
||||
* standard states at the current T and P of the solution.
|
||||
|
|
@ -891,7 +891,7 @@ namespace Cantera {
|
|||
copy(_cpr.begin(), _cpr.end(), cpr);
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* Get the molar volumes of each species in their standard
|
||||
* states at the current
|
||||
* <I>T</I> and <I>P</I> of the solution.
|
||||
|
|
@ -907,7 +907,7 @@ namespace Cantera {
|
|||
* Thermodynamic Values for the Species Reference States
|
||||
*********************************************************************/
|
||||
|
||||
/**
|
||||
/*
|
||||
* Returns the vector of non-dimensional Enthalpy function
|
||||
* of the reference state at the current temperature
|
||||
* of the solution and the reference pressure for the species.
|
||||
|
|
|
|||
|
|
@ -667,10 +667,10 @@ namespace Cantera {
|
|||
getPureGibbs(mu0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the array of nondimensional Enthalpy functions for the
|
||||
* standard state species
|
||||
* at the current <I>T</I> and <I>P</I> of the solution.
|
||||
|
||||
//! Get the array of nondimensional Enthalpy functions for the standard state species
|
||||
//! at the current <I>T</I> and <I>P</I> of the solution.
|
||||
/*!
|
||||
* We assume an incompressible constant partial molar
|
||||
* volume here:
|
||||
* \f[
|
||||
|
|
@ -686,10 +686,10 @@ namespace Cantera {
|
|||
*/
|
||||
void getEnthalpy_RT(doublereal* hrt) const;
|
||||
|
||||
/**
|
||||
* Get the nondimensional Entropies for the species
|
||||
* standard states at the current T and P of the solution.
|
||||
*
|
||||
|
||||
//! Get the nondimensional Entropies for the species
|
||||
//! standard states at the current T and P of the solution.
|
||||
/*!
|
||||
* Note, this is equal to the reference state entropies
|
||||
* due to the zero volume expansivity:
|
||||
* i.e., (dS/dP)_T = (dV/dT)_P = 0.0
|
||||
|
|
@ -699,6 +699,7 @@ namespace Cantera {
|
|||
* standard state entropy for species k.
|
||||
*/
|
||||
void getEntropy_R(doublereal* sr) const;
|
||||
|
||||
/**
|
||||
* Get the nondimensional gibbs function for the species
|
||||
* standard states at the current T and P of the solution.
|
||||
|
|
@ -733,10 +734,11 @@ namespace Cantera {
|
|||
*/
|
||||
virtual void getPureGibbs(doublereal* gpure) const;
|
||||
|
||||
/**
|
||||
* Returns the vector of nondimensional
|
||||
* internal Energies of the standard state at the current
|
||||
* temperature and pressure of the solution for each species.
|
||||
|
||||
//! Returns the vector of nondimensional
|
||||
//! internal Energies of the standard state at the current
|
||||
//! temperature and pressure of the solution for each species.
|
||||
/*!
|
||||
*
|
||||
* @param urt Output vector of standard state nondimensional internal energies.
|
||||
* Length: m_kk.
|
||||
|
|
|
|||
|
|
@ -34,16 +34,16 @@ ELECTRO_OBJ = SingleSpeciesTP.o StoichSubstanceSSTP.o \
|
|||
MolalityVPSSTP.o VPStandardStateTP.o \
|
||||
IdealSolidSolnPhase.o IdealMolalSoln.o \
|
||||
WaterPropsIAPWSphi.o WaterPropsIAPWS.o WaterProps.o \
|
||||
PDSS.o WaterPDSS.o WaterTP.o \
|
||||
PDSS.o WaterPDSS.o \
|
||||
HMWSoln.o HMWSoln_input.o DebyeHuckel.o \
|
||||
IdealGasPDSS.o
|
||||
IdealGasPDSS.o WaterSSTP.o
|
||||
|
||||
ELECTRO_H = SingleSpeciesTP.h StoichSubstanceSSTP.h \
|
||||
MolalityVPSSTP.h VPStandardStateTP.h \
|
||||
IdealSolidSolnPhase.h IdealMolalSoln.h \
|
||||
WaterPropsIAPWSphi.h WaterPropsIAPWS.h WaterProps.h \
|
||||
PDSS.h WaterPDSS.h WaterTP.h HMWSoln.h electrolytes.h \
|
||||
DebyeHuckel.h IdealGasPDSS.o
|
||||
PDSS.h WaterPDSS.h HMWSoln.h electrolytes.h \
|
||||
DebyeHuckel.h IdealGasPDSS.h WaterSSTP.h
|
||||
endif
|
||||
ifeq ($(do_issp),1)
|
||||
ISSP_OBJ = IdealSolidSolnPhase.o
|
||||
|
|
|
|||
|
|
@ -144,7 +144,7 @@ namespace Cantera {
|
|||
return cpbar;
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* cv_mole():
|
||||
*
|
||||
* Molar heat capacity at constant volume of the mixture.
|
||||
|
|
@ -246,6 +246,14 @@ namespace Cantera {
|
|||
sbar[0] *= GasConstant;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the species partial molar Heat Capacities. Units: J/kmol K.
|
||||
*/
|
||||
void SingleSpeciesTP::getPartialMolarCp(doublereal* cpbar) const {
|
||||
getCp_R(cpbar);
|
||||
cpbar[0] *= GasConstant;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the species partial molar volumes. Units: m^3/kmol.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -304,6 +304,17 @@ namespace Cantera {
|
|||
*/
|
||||
void getPartialMolarEntropies(doublereal* sbar) const;
|
||||
|
||||
//! Get the species partial molar heat capacties. Units: J/kmol/K.
|
||||
/*!
|
||||
* This function is resolved here by calling the standard state
|
||||
* thermo function.
|
||||
*
|
||||
* @param cpbar Output vector of species partial molar heat capacities
|
||||
* Length = 1. units are J/kmol/K.
|
||||
*/
|
||||
void getPartialMolarCp(doublereal* cpbar) const;
|
||||
|
||||
|
||||
//! Get the species partial molar volumes. Units: m^3/kmol.
|
||||
/*!
|
||||
* This function is resolved here by calling the density function.
|
||||
|
|
|
|||
|
|
@ -103,22 +103,22 @@ double WaterPropsIAPWS::helmholtzFE() const{
|
|||
*/
|
||||
double WaterPropsIAPWS::pressure(double temperature, double rho) {
|
||||
calcDim(temperature, rho);
|
||||
double retn = pressure_rhoRT();
|
||||
return (retn * rho * Rgas * temperature);
|
||||
double retn = pressureM_rhoRT();
|
||||
return (retn * rho * Rgas * temperature/M_water);
|
||||
}
|
||||
double WaterPropsIAPWS::pressure() const{
|
||||
double retn = pressure_rhoRT();
|
||||
double retn = pressureM_rhoRT();
|
||||
double rho = delta * Rho_c;
|
||||
double temperature = T_c / tau;
|
||||
return (retn * rho * Rgas * temperature);
|
||||
return (retn * rho * Rgas * temperature/M_water);
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculates the pressure in dimensionless form
|
||||
* p/(rhoRT) at the currently stored tau and delta values
|
||||
* pM/(rhoRT) at the currently stored tau and delta values
|
||||
*/
|
||||
double WaterPropsIAPWS::pressure_rhoRT() const {
|
||||
double retn = m_phi->pressure_rhoRT(tau, delta);
|
||||
double WaterPropsIAPWS::pressureM_rhoRT() const {
|
||||
double retn = m_phi->pressureM_rhoRT(tau, delta);
|
||||
return retn;
|
||||
}
|
||||
|
||||
|
|
@ -284,7 +284,7 @@ double WaterPropsIAPWS::coeffThermExp(double temperature, double pressure) {
|
|||
return retn;
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* Returns the coefficient of isothermal compressibility
|
||||
* of temperature and pressure.
|
||||
* kappa = - d (ln V) / dP at constant T.
|
||||
|
|
@ -404,8 +404,7 @@ corr1(double temperature, double pressure, double &densLiq,
|
|||
* p : Pascals : Newtons/m**2
|
||||
*/
|
||||
static int method = 1;
|
||||
double WaterPropsIAPWS::
|
||||
psat(double temperature) {
|
||||
double WaterPropsIAPWS::psat(double temperature) {
|
||||
double densLiq = -1.0, densGas = -1.0, delGRT = 0.0;
|
||||
double dp, pcorr;
|
||||
double p = psat_est(temperature);
|
||||
|
|
|
|||
|
|
@ -323,7 +323,7 @@ private:
|
|||
double cp_R() const;
|
||||
|
||||
//! Return the current dimensionless pressure
|
||||
double pressure_rhoRT() const;
|
||||
double pressureM_rhoRT() const;
|
||||
|
||||
protected:
|
||||
|
||||
|
|
|
|||
|
|
@ -631,7 +631,7 @@ double WaterPropsIAPWSphi::phi_d(double tau, double delta) {
|
|||
*
|
||||
* note: this is done so much, we have a seperate routine.
|
||||
*/
|
||||
double WaterPropsIAPWSphi::pressure_rhoRT(double tau, double delta) {
|
||||
double WaterPropsIAPWSphi::pressureM_rhoRT(double tau, double delta) {
|
||||
tdpolycalc(tau, delta);
|
||||
double res = phiR_d();
|
||||
double retn = 1.0 + delta * res;
|
||||
|
|
|
|||
|
|
@ -84,14 +84,14 @@ public:
|
|||
//! Calculate the dimensionless pressure at tau and delta;
|
||||
/*!
|
||||
*
|
||||
* p/(rhoRT) = delta * phi_d() = 1.0 + delta phiR_d()
|
||||
* pM/(rhoRT) = delta * phi_d() = 1.0 + delta phiR_d()
|
||||
*
|
||||
* @param tau Dimensionless temperature = T_c/T
|
||||
* @param delta Dimensionless density = delta = rho / Rho_c
|
||||
*
|
||||
* note: this is done so much, we have a seperate routine.
|
||||
*/
|
||||
double pressure_rhoRT(double tau, double delta);
|
||||
double pressureM_rhoRT(double tau, double delta);
|
||||
|
||||
/**
|
||||
* This program computes the reduced density, given the reduced pressure
|
||||
|
|
|
|||
530
Cantera/src/thermo/WaterSSTP.cpp
Normal file
530
Cantera/src/thermo/WaterSSTP.cpp
Normal file
|
|
@ -0,0 +1,530 @@
|
|||
/**
|
||||
* @file WaterTP.cpp
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* Copywrite (2006) Sandia Corporation. Under the terms of
|
||||
* Contract DE-AC04-94AL85000 with Sandia Corporation, the
|
||||
* U.S. Government retains certain rights in this software.
|
||||
*/
|
||||
/*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include "xml.h"
|
||||
#include "WaterSSTP.h"
|
||||
#include "WaterPropsIAPWS.h"
|
||||
#include "importCTML.h"
|
||||
|
||||
namespace Cantera {
|
||||
/**
|
||||
* Basic list of constructors and duplicators
|
||||
*/
|
||||
|
||||
WaterSSTP::WaterSSTP() :
|
||||
SingleSpeciesTP(),
|
||||
m_sub(0),
|
||||
m_subflag(0),
|
||||
m_mw(0.0),
|
||||
EW_Offset(0.0),
|
||||
SW_Offset(0.0),
|
||||
m_verbose(0),
|
||||
m_allowGasPhase(false)
|
||||
{
|
||||
constructPhase();
|
||||
}
|
||||
|
||||
|
||||
WaterSSTP::WaterSSTP(std::string inputFile, std::string id) :
|
||||
SingleSpeciesTP(),
|
||||
m_sub(0),
|
||||
m_subflag(0),
|
||||
m_mw(0.0),
|
||||
EW_Offset(0.0),
|
||||
SW_Offset(0.0),
|
||||
m_verbose(0),
|
||||
m_allowGasPhase(false)
|
||||
{
|
||||
constructPhaseFile(inputFile, id);
|
||||
}
|
||||
|
||||
|
||||
WaterSSTP::WaterSSTP(XML_Node& phaseRoot, std::string id) :
|
||||
SingleSpeciesTP(),
|
||||
m_sub(0),
|
||||
m_subflag(0),
|
||||
m_mw(0.0),
|
||||
EW_Offset(0.0),
|
||||
SW_Offset(0.0),
|
||||
m_verbose(0),
|
||||
m_allowGasPhase(false)
|
||||
{
|
||||
constructPhaseXML(phaseRoot, id) ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
WaterSSTP::WaterSSTP(const WaterSSTP &b) :
|
||||
SingleSpeciesTP(b),
|
||||
m_sub(0),
|
||||
m_subflag(b.m_subflag),
|
||||
m_mw(b.m_mw),
|
||||
EW_Offset(b.EW_Offset),
|
||||
SW_Offset(b.SW_Offset),
|
||||
m_verbose(b.m_verbose),
|
||||
m_allowGasPhase(b.m_allowGasPhase)
|
||||
{
|
||||
m_sub = new WaterPropsIAPWS(*(b.m_sub));
|
||||
/*
|
||||
* Use the assignment operator to do the brunt
|
||||
* of the work for the copy construtor.
|
||||
*/
|
||||
*this = b;
|
||||
}
|
||||
|
||||
/*
|
||||
* Assignment operator
|
||||
*/
|
||||
WaterSSTP& WaterSSTP::operator=(const WaterSSTP&b) {
|
||||
if (&b == this) return *this;
|
||||
m_sub->operator=(*(b.m_sub));
|
||||
m_subflag = b.m_subflag;
|
||||
m_mw = b.m_mw;
|
||||
m_verbose = b.m_verbose;
|
||||
m_allowGasPhase = b.m_allowGasPhase;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
ThermoPhase *WaterSSTP::duplMyselfAsThermoPhase() {
|
||||
WaterSSTP* wtp = new WaterSSTP(*this);
|
||||
return (ThermoPhase *) wtp;
|
||||
}
|
||||
|
||||
WaterSSTP::~WaterSSTP() {
|
||||
delete m_sub;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void WaterSSTP::constructPhase() {
|
||||
throw CanteraError("constructPhaseXML", "unimplemented");
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @param infile XML file containing the description of the
|
||||
* phase
|
||||
*
|
||||
* @param id Optional parameter identifying the name of the
|
||||
* phase. If none is given, the first XML
|
||||
* phase element will be used.
|
||||
*/
|
||||
void WaterSSTP::constructPhaseXML(XML_Node& phaseNode, std::string id) {
|
||||
|
||||
/*
|
||||
* Call the Cantera importPhase() function. This will import
|
||||
* all of the species into the phase. This will also handle
|
||||
* all of the solvent and solute standard states.
|
||||
*/
|
||||
bool m_ok = importPhase(phaseNode, this);
|
||||
if (!m_ok) {
|
||||
throw CanteraError("initThermo","importPhase failed ");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* constructPhaseFile
|
||||
*
|
||||
*
|
||||
* This routine is a precursor to constructPhaseXML(XML_Node*)
|
||||
* routine, which does most of the work.
|
||||
*
|
||||
* @param inputFile XML file containing the description of the
|
||||
* phase
|
||||
*
|
||||
* @param id Optional parameter identifying the name of the
|
||||
* phase. If none is given, the first XML
|
||||
* phase element will be used.
|
||||
*/
|
||||
void WaterSSTP::constructPhaseFile(std::string inputFile, std::string id) {
|
||||
|
||||
if (inputFile.size() == 0) {
|
||||
throw CanteraError("WaterTp::initThermo",
|
||||
"input file is null");
|
||||
}
|
||||
std::string path = findInputFile(inputFile);
|
||||
std::ifstream fin(path.c_str());
|
||||
if (!fin) {
|
||||
throw CanteraError("WaterSSTP::initThermo","could not open "
|
||||
+path+" for reading.");
|
||||
}
|
||||
/*
|
||||
* The phase object automatically constructs an XML object.
|
||||
* Use this object to store information.
|
||||
*/
|
||||
XML_Node &phaseNode_XML = xml();
|
||||
XML_Node *fxml = new XML_Node();
|
||||
fxml->build(fin);
|
||||
XML_Node *fxml_phase = findXMLPhase(fxml, id);
|
||||
if (!fxml_phase) {
|
||||
throw CanteraError("WaterSSTP::initThermo",
|
||||
"ERROR: Can not find phase named " +
|
||||
id + " in file named " + inputFile);
|
||||
}
|
||||
fxml_phase->copy(&phaseNode_XML);
|
||||
constructPhaseXML(*fxml_phase, id);
|
||||
delete fxml;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void WaterSSTP::initThermo() {
|
||||
}
|
||||
|
||||
void WaterSSTP::
|
||||
initThermoXML(XML_Node& phaseNode, std::string id) {
|
||||
if (m_sub) delete m_sub;
|
||||
m_sub = new WaterPropsIAPWS();
|
||||
if (m_sub == 0) {
|
||||
throw CanteraError("WaterSSTP::initThermo",
|
||||
"could not create new substance object.");
|
||||
}
|
||||
/*
|
||||
* Calculate the molecular weight. Note while there may
|
||||
* be a very good calculated weight in the steam table
|
||||
* class, using this weight may lead to codes exhibiting
|
||||
* mass loss issues. We need to grab the elemental
|
||||
* atomic weights used in the Element class and calculate
|
||||
* a consistent H2O molecular weight based on that.
|
||||
*/
|
||||
int nH = elementIndex("H");
|
||||
if (nH < 0) {
|
||||
throw CanteraError("WaterSSTP::initThermo",
|
||||
"H not an element");
|
||||
}
|
||||
double mw_H = atomicWeight(nH);
|
||||
int nO = elementIndex("O");
|
||||
if (nO < 0) {
|
||||
throw CanteraError("WaterSSTP::initThermo",
|
||||
"O not an element");
|
||||
}
|
||||
double mw_O = atomicWeight(nO);
|
||||
m_mw = 2.0 * mw_H + mw_O;
|
||||
m_weight[0] = m_mw;
|
||||
setMolecularWeight(0,m_mw);
|
||||
double one = 1.0;
|
||||
setMoleFractions(&one);
|
||||
|
||||
/*
|
||||
* Set the baseline
|
||||
*/
|
||||
doublereal T = 298.15;
|
||||
|
||||
doublereal presLow = 1.0E-2;
|
||||
doublereal oneBar = 1.0E5;
|
||||
doublereal dens = density();
|
||||
doublereal dd = m_sub->density(T, presLow, WATER_GAS, dens);
|
||||
setTemperature(T);
|
||||
setDensity(dd);
|
||||
SW_Offset = 0.0;
|
||||
doublereal s = entropy_mole();
|
||||
s -= GasConstant * log(oneBar/presLow);
|
||||
if (s != 188.835E3) {
|
||||
SW_Offset = 188.835E3 - s;
|
||||
}
|
||||
s = entropy_mole();
|
||||
s -= GasConstant * log(oneBar/presLow);
|
||||
printf("s = %g\n", s);
|
||||
|
||||
doublereal h = enthalpy_mole();
|
||||
if (h != -241.826E6) {
|
||||
EW_Offset = -241.826E6 - h;
|
||||
}
|
||||
h = enthalpy_mole();
|
||||
|
||||
printf("h = %g\n", h);
|
||||
|
||||
|
||||
/*
|
||||
* Set the initial state of the system to 298.15 K and
|
||||
* 1 bar.
|
||||
*/
|
||||
setTemperature(298.15);
|
||||
double rho0 = m_sub->density(298.15, OneAtm, WATER_LIQUID);
|
||||
setDensity(rho0);
|
||||
|
||||
/*
|
||||
* We have to do something with the thermo function here.
|
||||
*/
|
||||
if (m_spthermo) {
|
||||
delete m_spthermo;
|
||||
m_spthermo = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void WaterSSTP::
|
||||
setParametersFromXML(const XML_Node& eosdata) {
|
||||
eosdata._require("model","PureFluid");
|
||||
m_subflag = atoi(eosdata["fluid_type"].c_str());
|
||||
if (m_subflag < 0)
|
||||
throw CanteraError("WaterSSTP::setParametersFromXML",
|
||||
"missing or negative substance flag");
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the molar dimensionless enthalpy
|
||||
*/
|
||||
void WaterSSTP::getEnthalpy_RT(doublereal* hrt) const {
|
||||
double T = temperature();
|
||||
double dens = density();
|
||||
doublereal h = m_sub->enthalpy(T, dens);
|
||||
*hrt = (h + EW_Offset)/(GasConstant*T);
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate the internal energy in mks units of
|
||||
* J kmol-1
|
||||
*/
|
||||
void WaterSSTP::getIntEnergy_RT(doublereal *ubar) const {
|
||||
double T = temperature();
|
||||
double dens = density();
|
||||
doublereal u = m_sub->intEnergy(T, dens);
|
||||
*ubar = (u + EW_Offset)/GasConstant;
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate the dimensionless entropy
|
||||
*/
|
||||
void WaterSSTP::getEntropy_R(doublereal* sr) const {
|
||||
double T = temperature();
|
||||
double dens = density();
|
||||
doublereal s = m_sub->entropy(T, dens);
|
||||
sr[0] = (s + SW_Offset) / GasConstant;
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate the Gibbs free energy in mks units of
|
||||
* J kmol-1 K-1.
|
||||
*/
|
||||
void WaterSSTP::getGibbs_RT(doublereal *grt) const {
|
||||
double T = temperature();
|
||||
double dens = density();
|
||||
doublereal g = m_sub->Gibbs(T, dens);
|
||||
*grt = (g + EW_Offset - SW_Offset*T) / (GasConstant * T);
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate the Gibbs free energy in mks units of
|
||||
* J kmol-1 K-1.
|
||||
*/
|
||||
void WaterSSTP::getStandardChemPotentials(doublereal *gss) const {
|
||||
double T = temperature();
|
||||
double dens = density();
|
||||
doublereal g = m_sub->Gibbs(T, dens);
|
||||
*gss = (g + EW_Offset - SW_Offset*T);
|
||||
}
|
||||
|
||||
void WaterSSTP::getCp_R(doublereal* cpr) const {
|
||||
double T = temperature();
|
||||
double dens = density();
|
||||
doublereal cp = m_sub->cp(T, dens);
|
||||
cpr[0] = cp / GasConstant;
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate the constant volume heat capacity
|
||||
* in mks units of J kmol-1 K-1
|
||||
*/
|
||||
doublereal WaterSSTP::
|
||||
cv_mole() const {
|
||||
double T = temperature();
|
||||
double dens = density();
|
||||
doublereal cv = m_sub->cv(T, dens);
|
||||
return cv;
|
||||
}
|
||||
|
||||
// @name Thermodynamic Values for the Species Reference State
|
||||
|
||||
|
||||
void WaterSSTP::getEnthalpy_RT_ref(doublereal *hrt) const {
|
||||
doublereal p = pressure();
|
||||
double T = temperature();
|
||||
double dens = density();
|
||||
int waterState = WATER_GAS;
|
||||
double rc = m_sub->Rhocrit();
|
||||
if (dens > rc) {
|
||||
waterState = WATER_LIQUID;
|
||||
}
|
||||
doublereal dd = m_sub->density(T, OneAtm, waterState, dens);
|
||||
if (dd <= 0.0) {
|
||||
throw CanteraError("setPressure", "error");
|
||||
}
|
||||
doublereal h = m_sub->enthalpy(T, dd);
|
||||
*hrt = (h + EW_Offset) / (GasConstant * T);
|
||||
dd = m_sub->density(T, p, waterState, dens);
|
||||
}
|
||||
|
||||
void WaterSSTP::getGibbs_RT_ref(doublereal *grt) const {
|
||||
doublereal p = pressure();
|
||||
double T = temperature();
|
||||
double dens = density();
|
||||
int waterState = WATER_GAS;
|
||||
double rc = m_sub->Rhocrit();
|
||||
if (dens > rc) {
|
||||
waterState = WATER_LIQUID;
|
||||
}
|
||||
doublereal dd = m_sub->density(T, OneAtm, waterState, dens);
|
||||
if (dd <= 0.0) {
|
||||
throw CanteraError("setPressure", "error");
|
||||
}
|
||||
m_sub->setState(T, dd);
|
||||
doublereal g = m_sub->Gibbs(T, dd);
|
||||
*grt = (g + EW_Offset - SW_Offset*T)/ (GasConstant * T);
|
||||
dd = m_sub->density(T, p, waterState, dens);
|
||||
|
||||
}
|
||||
|
||||
void WaterSSTP::getGibbs_ref(doublereal *g) const {
|
||||
getGibbs_RT_ref(g);
|
||||
doublereal rt = _RT();
|
||||
for (int k = 0; k < m_kk; k++) {
|
||||
g[k] *= rt;
|
||||
}
|
||||
}
|
||||
|
||||
void WaterSSTP::getEntropy_R_ref(doublereal *sr) const {
|
||||
doublereal p = pressure();
|
||||
double T = temperature();
|
||||
double dens = density();
|
||||
int waterState = WATER_GAS;
|
||||
double rc = m_sub->Rhocrit();
|
||||
if (dens > rc) {
|
||||
waterState = WATER_LIQUID;
|
||||
}
|
||||
doublereal dd = m_sub->density(T, OneAtm, waterState, dens);
|
||||
|
||||
if (dd <= 0.0) {
|
||||
throw CanteraError("setPressure", "error");
|
||||
}
|
||||
m_sub->setState(T, dd);
|
||||
|
||||
doublereal s = m_sub->entropy(T, dd);
|
||||
*sr = (s + SW_Offset)/ (GasConstant);
|
||||
dd = m_sub->density(T, p, waterState, dens);
|
||||
|
||||
}
|
||||
|
||||
void WaterSSTP::getCp_R_ref(doublereal *cpr) const {
|
||||
doublereal p = pressure();
|
||||
double T = temperature();
|
||||
double dens = density();
|
||||
int waterState = WATER_GAS;
|
||||
double rc = m_sub->Rhocrit();
|
||||
if (dens > rc) {
|
||||
waterState = WATER_LIQUID;
|
||||
}
|
||||
doublereal dd = m_sub->density(T, OneAtm, waterState, dens);
|
||||
m_sub->setState(T, dd);
|
||||
if (dd <= 0.0) {
|
||||
throw CanteraError("setPressure", "error");
|
||||
}
|
||||
doublereal cp = m_sub->cp(T, dd);
|
||||
*cpr = cp / (GasConstant);
|
||||
dd = m_sub->density(T, p, waterState, dens);
|
||||
}
|
||||
|
||||
void WaterSSTP::getStandardVolumes_ref(doublereal *vol) const {
|
||||
doublereal p = pressure();
|
||||
double T = temperature();
|
||||
double dens = density();
|
||||
int waterState = WATER_GAS;
|
||||
double rc = m_sub->Rhocrit();
|
||||
if (dens > rc) {
|
||||
waterState = WATER_LIQUID;
|
||||
}
|
||||
doublereal dd = m_sub->density(T, OneAtm, waterState, dens);
|
||||
if (dd <= 0.0) {
|
||||
throw CanteraError("setPressure", "error");
|
||||
}
|
||||
*vol = meanMolecularWeight() /dd;
|
||||
dd = m_sub->density(T, p, waterState, dens);
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate the pressure (Pascals), given the temperature and density
|
||||
* Temperature: kelvin
|
||||
* rho: density in kg m-3
|
||||
*/
|
||||
doublereal WaterSSTP::
|
||||
pressure() const {
|
||||
double T = temperature();
|
||||
double dens = density();
|
||||
doublereal p = m_sub->pressure(T, dens);
|
||||
return p;
|
||||
}
|
||||
|
||||
void WaterSSTP::
|
||||
setPressure(doublereal p) {
|
||||
double T = temperature();
|
||||
double dens = density();
|
||||
int waterState = WATER_GAS;
|
||||
double rc = m_sub->Rhocrit();
|
||||
if (dens > rc) {
|
||||
waterState = WATER_LIQUID;
|
||||
}
|
||||
doublereal dd = m_sub->density(T, p, waterState, dens);
|
||||
if (dd <= 0.0) {
|
||||
throw CanteraError("setPressure", "error");
|
||||
}
|
||||
setDensity(dd);
|
||||
}
|
||||
|
||||
|
||||
// critical temperature
|
||||
doublereal WaterSSTP::critTemperature() const { return m_sub->Tcrit(); }
|
||||
|
||||
// critical pressure
|
||||
doublereal WaterSSTP::critPressure() const { return m_sub->Pcrit(); }
|
||||
|
||||
// critical density
|
||||
doublereal WaterSSTP::critDensity() const { return m_sub->Rhocrit(); }
|
||||
|
||||
|
||||
|
||||
void WaterSSTP::setTemperature(double temp) {
|
||||
State::setTemperature(temp);
|
||||
doublereal dd = density();
|
||||
m_sub->setState(temp, dd);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// saturation pressure
|
||||
doublereal WaterSSTP::satPressure(doublereal t){
|
||||
doublereal pp = m_sub->psat(t);
|
||||
double dens = density();
|
||||
setTemperature(t);
|
||||
setDensity(dens);
|
||||
return pp;
|
||||
}
|
||||
|
||||
// Return the fraction of vapor at the current conditions
|
||||
doublereal WaterSSTP::vaporFraction() const {
|
||||
if (temperature() >= m_sub->Tcrit()) {
|
||||
double dens = density();
|
||||
if (dens >= m_sub->Rhocrit()) {
|
||||
return 0.0;
|
||||
}
|
||||
return 1.0;
|
||||
}
|
||||
/*
|
||||
* If below tcrit we always return 0 from this class
|
||||
*/
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -1,7 +1,6 @@
|
|||
/**
|
||||
* @file WaterTP.h
|
||||
*
|
||||
* Declares a ThermoPhase class consisting of
|
||||
* @file WaterSSTP.h
|
||||
* Declares a %ThermoPhase class consisting of
|
||||
* pure water.
|
||||
*/
|
||||
/*
|
||||
|
|
@ -13,10 +12,10 @@
|
|||
* $Id$
|
||||
*/
|
||||
|
||||
#ifndef CT_WATERTP_H
|
||||
#define CT_WATERTP_H
|
||||
#ifndef CT_WATERSSTP_H
|
||||
#define CT_WATERSSTP_H
|
||||
|
||||
#include "ThermoPhase.h"
|
||||
#include "SingleSpeciesTP.h"
|
||||
|
||||
class WaterPropsIAPWS;
|
||||
|
||||
|
|
@ -52,41 +51,38 @@ namespace Cantera {
|
|||
* They assume u_liq(TP) = 0.0, s_liq(TP) = 0.0, where TP is the
|
||||
* triple point conditions.
|
||||
*
|
||||
* @todo
|
||||
* I should have made this inherit from SingleSpeciesTP!
|
||||
*
|
||||
* @ingroup thermoprops
|
||||
*
|
||||
*/
|
||||
class WaterTP : public ThermoPhase {
|
||||
class WaterSSTP : public SingleSpeciesTP {
|
||||
|
||||
public:
|
||||
|
||||
//! Base constructor
|
||||
WaterTP();
|
||||
WaterSSTP();
|
||||
|
||||
//! Copy constructor
|
||||
WaterTP(const WaterTP &);
|
||||
WaterSSTP(const WaterSSTP &);
|
||||
|
||||
//! Assignment operator
|
||||
WaterTP& operator=(const WaterTP&);
|
||||
WaterSSTP& operator=(const WaterSSTP&);
|
||||
|
||||
//! Full constructor for a water phase
|
||||
/*!
|
||||
* @param inputFile String name of the input file
|
||||
* @param id string id of the phase name
|
||||
*/
|
||||
WaterTP(std::string inputFile, std::string id = "");
|
||||
WaterSSTP(std::string inputFile, std::string id = "");
|
||||
|
||||
//! Full constructor for a water phase
|
||||
/*!
|
||||
* @param phaseRef XML node referencing the water phase.
|
||||
* @param id string id of the phase name
|
||||
*/
|
||||
WaterTP(XML_Node& phaseRef, std::string id = "");
|
||||
WaterSSTP(XML_Node& phaseRef, std::string id = "");
|
||||
|
||||
//! Destructor
|
||||
virtual ~WaterTP();
|
||||
virtual ~WaterSSTP();
|
||||
|
||||
//! Duplicator from a ThermoPhase object
|
||||
ThermoPhase *duplMyselfAsThermoPhase();
|
||||
|
|
@ -103,11 +99,7 @@ namespace Cantera {
|
|||
* @name Molar Thermodynamic Properties of the Solution --------------
|
||||
* @{
|
||||
*/
|
||||
virtual doublereal enthalpy_mole() const;
|
||||
virtual doublereal intEnergy_mole() const;
|
||||
virtual doublereal entropy_mole() const;
|
||||
virtual doublereal gibbs_mole() const;
|
||||
virtual doublereal cp_mole() const;
|
||||
|
||||
virtual doublereal cv_mole() const;
|
||||
|
||||
//@}
|
||||
|
|
@ -134,19 +126,158 @@ namespace Cantera {
|
|||
//@{
|
||||
|
||||
|
||||
//! get the chemical potential of the water
|
||||
/*!
|
||||
* @param mu vector of chemical potentials.
|
||||
*/
|
||||
virtual void getChemPotentials(doublereal* mu) const {
|
||||
mu[0] = gibbs_mole();
|
||||
}
|
||||
|
||||
//@}
|
||||
/// @name Properties of the Standard State of the Species
|
||||
// in the Solution --
|
||||
//@{
|
||||
|
||||
|
||||
//!Get the gibbs function for the species
|
||||
//! standard states at the current T and P of the solution.
|
||||
/*!
|
||||
* @param grt Vector of length m_kk, which on return sr[k]
|
||||
* will contain the
|
||||
* standard state gibbs function for species k.
|
||||
*/
|
||||
virtual void getStandardChemPotentials(doublereal* gss) const;
|
||||
|
||||
//!Get the nondimensional gibbs function for the species
|
||||
//! standard states at the current T and P of the solution.
|
||||
/*!
|
||||
* @param grt Vector of length m_kk, which on return sr[k]
|
||||
* will contain the nondimensional
|
||||
* standard state gibbs function for species k.
|
||||
*/
|
||||
virtual void getGibbs_RT(doublereal* grt) const;
|
||||
|
||||
//! Get the array of nondimensional Enthalpy functions for the standard state species
|
||||
//! at the current <I>T</I> and <I>P</I> of the solution.
|
||||
/*!
|
||||
*
|
||||
* @param hrt Vector of length m_kk, which on return hrt[k]
|
||||
* will contain the nondimensional
|
||||
* standard state enthalpy of species k.
|
||||
*/
|
||||
void getEnthalpy_RT(doublereal* hrt) const;
|
||||
|
||||
|
||||
//! Get the nondimensional Entropies for the species
|
||||
//! standard states at the current T and P of the solution.
|
||||
/*!
|
||||
* @param sr Vector of length m_kk, which on return sr[k]
|
||||
* will contain the nondimensional
|
||||
* standard state entropy for species k.
|
||||
*/
|
||||
void getEntropy_R(doublereal* sr) const;
|
||||
|
||||
//! Get the nondimensional heat capacity at constant pressure
|
||||
//! function for the species standard states at the current T and P of the solution.
|
||||
/*!
|
||||
*
|
||||
* @param cpr Vector of length m_kk, which on return cpr[k]
|
||||
* will contain the nondimensional
|
||||
* constant pressure heat capacity for species k.
|
||||
*/
|
||||
virtual void getCp_R(doublereal* cpr) const;
|
||||
|
||||
//! Returns the vector of nondimensional
|
||||
//! internal Energies of the standard state at the current
|
||||
//! temperature and pressure of the solution for each species.
|
||||
/*!
|
||||
*
|
||||
* @param urt Output vector of standard state nondimensional internal energies.
|
||||
* Length: m_kk.
|
||||
*/
|
||||
virtual void getIntEnergy_RT(doublereal *urt) const;
|
||||
|
||||
//@}
|
||||
//! @name Thermodynamic Values for the Species Reference State
|
||||
/*!
|
||||
* All functions in this group need to be overrided, because
|
||||
* the m_spthermo SpeciesThermo function is not adequate for
|
||||
* the real equation of state.
|
||||
*
|
||||
*/
|
||||
//@{
|
||||
|
||||
|
||||
|
||||
//! Returns the vector of nondimensional
|
||||
//! enthalpies of the reference state at the current temperature
|
||||
//! of the solution and the reference pressure for the species.
|
||||
/*!
|
||||
* @param hrt Output vector containing the nondimensional reference state enthalpies
|
||||
* Length: m_kk.
|
||||
*/
|
||||
virtual void getEnthalpy_RT_ref(doublereal *hrt) const;
|
||||
|
||||
/*!
|
||||
* Returns the vector of nondimensional
|
||||
* enthalpies of the reference state at the current temperature
|
||||
* of the solution and the reference pressure for the species.
|
||||
*
|
||||
* This function is resolved in this class. It is assumed that the m_spthermo species thermo
|
||||
* pointer is populated and yields the reference state.
|
||||
*
|
||||
* @param grt Output vector containing the nondimensional reference state
|
||||
* Gibbs Free energies. Length: m_kk.
|
||||
*/
|
||||
virtual void getGibbs_RT_ref(doublereal *grt) const;
|
||||
|
||||
|
||||
/*!
|
||||
* Returns the vector of the
|
||||
* gibbs function of the reference state at the current temperature
|
||||
* of the solution and the reference pressure for the species.
|
||||
* units = J/kmol
|
||||
*
|
||||
* This function is resolved in this class. It is assumed that the m_spthermo
|
||||
* species thermo
|
||||
* pointer is populated and yields the reference state.
|
||||
*
|
||||
* @param g Output vector containing the reference state
|
||||
* Gibbs Free energies. Length: m_kk. Units: J/kmol.
|
||||
*/
|
||||
virtual void getGibbs_ref(doublereal *g) const;
|
||||
|
||||
/*!
|
||||
* Returns the vector of nondimensional
|
||||
* entropies of the reference state at the current temperature
|
||||
* of the solution and the reference pressure for each species.
|
||||
*
|
||||
* This function is resolved in this class. It is assumed that the m_spthermo species thermo
|
||||
* pointer is populated and yields the reference state.
|
||||
*
|
||||
* @param er Output vector containing the nondimensional reference state
|
||||
* entropies. Length: m_kk.
|
||||
*/
|
||||
virtual void getEntropy_R_ref(doublereal *er) const;
|
||||
|
||||
/*!
|
||||
* Returns the vector of nondimensional
|
||||
* constant pressure heat capacities of the reference state
|
||||
* at the current temperature of the solution
|
||||
* and reference pressure for each species.
|
||||
*
|
||||
* This function is resolved in this class. It is assumed that the m_spthermo
|
||||
* species thermo
|
||||
* pointer is populated and yields the reference state.
|
||||
*
|
||||
* @param cprt Output vector of nondimensional reference state
|
||||
* heat capacities at constant pressure for the species.
|
||||
* Length: m_kk
|
||||
*/
|
||||
virtual void getCp_R_ref(doublereal *cprt) const;
|
||||
|
||||
//! Get the molar volumes of the species reference states at the current
|
||||
//! <I>T</I> and <I>P_ref</I> of the solution.
|
||||
/*!
|
||||
* units = m^3 / kmol
|
||||
*
|
||||
* @param vol Output vector containing the standard state volumes.
|
||||
* Length: m_kk.
|
||||
*/
|
||||
virtual void getStandardVolumes_ref(doublereal *vol) const;
|
||||
|
||||
/// critical temperature
|
||||
virtual doublereal critTemperature() const;
|
||||
|
|
@ -282,6 +413,14 @@ namespace Cantera {
|
|||
void check(doublereal v = 0.0) const;
|
||||
void reportTPXError() const;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @internal
|
||||
* This internal routine must be overwritten because
|
||||
* it is not applicable.
|
||||
*/
|
||||
void _updateThermo() const;
|
||||
|
||||
private:
|
||||
mutable WaterPropsIAPWS *m_sub;
|
||||
int m_subflag;
|
||||
|
|
@ -1,422 +0,0 @@
|
|||
/**
|
||||
* @file WaterTP.cpp
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* Copywrite (2006) Sandia Corporation. Under the terms of
|
||||
* Contract DE-AC04-94AL85000 with Sandia Corporation, the
|
||||
* U.S. Government retains certain rights in this software.
|
||||
*/
|
||||
/*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include "xml.h"
|
||||
#include "WaterTP.h"
|
||||
#include "WaterPropsIAPWS.h"
|
||||
#include "importCTML.h"
|
||||
|
||||
namespace Cantera {
|
||||
/**
|
||||
* Basic list of constructors and duplicators
|
||||
*/
|
||||
|
||||
WaterTP::WaterTP() :
|
||||
ThermoPhase(),
|
||||
m_sub(0),
|
||||
m_subflag(0),
|
||||
m_mw(0.0),
|
||||
EW_Offset(0.0),
|
||||
SW_Offset(0.0),
|
||||
m_verbose(0),
|
||||
m_allowGasPhase(false)
|
||||
{
|
||||
constructPhase();
|
||||
}
|
||||
|
||||
|
||||
WaterTP::WaterTP(std::string inputFile, std::string id) :
|
||||
ThermoPhase(),
|
||||
m_sub(0),
|
||||
m_subflag(0),
|
||||
m_mw(0.0),
|
||||
EW_Offset(0.0),
|
||||
SW_Offset(0.0),
|
||||
m_verbose(0),
|
||||
m_allowGasPhase(false)
|
||||
{
|
||||
constructPhaseFile(inputFile, id);
|
||||
}
|
||||
|
||||
|
||||
WaterTP::WaterTP(XML_Node& phaseRoot, std::string id) :
|
||||
ThermoPhase(),
|
||||
m_sub(0),
|
||||
m_subflag(0),
|
||||
m_mw(0.0),
|
||||
EW_Offset(0.0),
|
||||
SW_Offset(0.0),
|
||||
m_verbose(0),
|
||||
m_allowGasPhase(false)
|
||||
{
|
||||
constructPhaseXML(phaseRoot, id) ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
WaterTP::WaterTP(const WaterTP &b) :
|
||||
ThermoPhase(b),
|
||||
m_sub(0),
|
||||
m_subflag(b.m_subflag),
|
||||
m_mw(b.m_mw),
|
||||
EW_Offset(b.EW_Offset),
|
||||
SW_Offset(b.SW_Offset),
|
||||
m_verbose(b.m_verbose),
|
||||
m_allowGasPhase(b.m_allowGasPhase)
|
||||
{
|
||||
m_sub = new WaterPropsIAPWS(*(b.m_sub));
|
||||
/*
|
||||
* Use the assignment operator to do the brunt
|
||||
* of the work for the copy construtor.
|
||||
*/
|
||||
*this = b;
|
||||
}
|
||||
|
||||
/*
|
||||
* Assignment operator
|
||||
*/
|
||||
WaterTP& WaterTP::operator=(const WaterTP&b) {
|
||||
if (&b == this) return *this;
|
||||
m_sub->operator=(*(b.m_sub));
|
||||
m_subflag = b.m_subflag;
|
||||
m_mw = b.m_mw;
|
||||
m_verbose = b.m_verbose;
|
||||
m_allowGasPhase = b.m_allowGasPhase;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
ThermoPhase *WaterTP::duplMyselfAsThermoPhase() {
|
||||
WaterTP* wtp = new WaterTP(*this);
|
||||
return (ThermoPhase *) wtp;
|
||||
}
|
||||
|
||||
WaterTP::~WaterTP() {
|
||||
delete m_sub;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void WaterTP::constructPhase() {
|
||||
throw CanteraError("constructPhaseXML", "unimplemented");
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @param infile XML file containing the description of the
|
||||
* phase
|
||||
*
|
||||
* @param id Optional parameter identifying the name of the
|
||||
* phase. If none is given, the first XML
|
||||
* phase element will be used.
|
||||
*/
|
||||
void WaterTP::constructPhaseXML(XML_Node& phaseNode, std::string id) {
|
||||
|
||||
/*
|
||||
* Call the Cantera importPhase() function. This will import
|
||||
* all of the species into the phase. This will also handle
|
||||
* all of the solvent and solute standard states.
|
||||
*/
|
||||
bool m_ok = importPhase(phaseNode, this);
|
||||
if (!m_ok) {
|
||||
throw CanteraError("initThermo","importPhase failed ");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* initThermo():
|
||||
*
|
||||
*
|
||||
* This routine is a precursor to constructPhaseXML(XML_Node*)
|
||||
* routine, which does most of the work.
|
||||
*
|
||||
* @param inputFile XML file containing the description of the
|
||||
* phase
|
||||
*
|
||||
* @param id Optional parameter identifying the name of the
|
||||
* phase. If none is given, the first XML
|
||||
* phase element will be used.
|
||||
*/
|
||||
void WaterTP::constructPhaseFile(std::string inputFile, std::string id) {
|
||||
|
||||
if (inputFile.size() == 0) {
|
||||
throw CanteraError("WaterTp::initThermo",
|
||||
"input file is null");
|
||||
}
|
||||
std::string path = findInputFile(inputFile);
|
||||
std::ifstream fin(path.c_str());
|
||||
if (!fin) {
|
||||
throw CanteraError("WaterTP::initThermo","could not open "
|
||||
+path+" for reading.");
|
||||
}
|
||||
/*
|
||||
* The phase object automatically constructs an XML object.
|
||||
* Use this object to store information.
|
||||
*/
|
||||
XML_Node &phaseNode_XML = xml();
|
||||
XML_Node *fxml = new XML_Node();
|
||||
fxml->build(fin);
|
||||
XML_Node *fxml_phase = findXMLPhase(fxml, id);
|
||||
if (!fxml_phase) {
|
||||
throw CanteraError("WaterTP::initThermo",
|
||||
"ERROR: Can not find phase named " +
|
||||
id + " in file named " + inputFile);
|
||||
}
|
||||
fxml_phase->copy(&phaseNode_XML);
|
||||
constructPhaseXML(*fxml_phase, id);
|
||||
delete fxml;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void WaterTP::initThermo() {
|
||||
}
|
||||
|
||||
void WaterTP::
|
||||
initThermoXML(XML_Node& phaseNode, std::string id) {
|
||||
if (m_sub) delete m_sub;
|
||||
m_sub = new WaterPropsIAPWS();
|
||||
if (m_sub == 0) {
|
||||
throw CanteraError("WaterTP::initThermo",
|
||||
"could not create new substance object.");
|
||||
}
|
||||
/*
|
||||
* Calculate the molecular weight. Note while there may
|
||||
* be a very good calculated weight in the steam table
|
||||
* class, using this weight may lead to codes exhibiting
|
||||
* mass loss issues. We need to grab the elemental
|
||||
* atomic weights used in the Element class and calculate
|
||||
* a consistent H2O molecular weight based on that.
|
||||
*/
|
||||
int nH = elementIndex("H");
|
||||
if (nH < 0) {
|
||||
throw CanteraError("WaterTP::initThermo",
|
||||
"H not an element");
|
||||
}
|
||||
double mw_H = atomicWeight(nH);
|
||||
int nO = elementIndex("O");
|
||||
if (nO < 0) {
|
||||
throw CanteraError("WaterTP::initThermo",
|
||||
"O not an element");
|
||||
}
|
||||
double mw_O = atomicWeight(nO);
|
||||
m_mw = 2.0 * mw_H + mw_O;
|
||||
m_weight[0] = m_mw;
|
||||
setMolecularWeight(0,m_mw);
|
||||
double one = 1.0;
|
||||
setMoleFractions(&one);
|
||||
|
||||
/*
|
||||
* Set the baseline
|
||||
*/
|
||||
doublereal T = 298.15;
|
||||
|
||||
doublereal presLow = 1.0E-2;
|
||||
doublereal oneBar = 1.0E5;
|
||||
doublereal dens = density();
|
||||
doublereal dd = m_sub->density(T, presLow, WATER_GAS, dens);
|
||||
setTemperature(T);
|
||||
setDensity(dd);
|
||||
SW_Offset = 0.0;
|
||||
doublereal s = entropy_mole();
|
||||
s -= GasConstant * log(oneBar/presLow);
|
||||
if (s != 188.835E3) {
|
||||
SW_Offset = 188.835E3 - s;
|
||||
}
|
||||
s = entropy_mole();
|
||||
s -= GasConstant * log(oneBar/presLow);
|
||||
printf("s = %g\n", s);
|
||||
|
||||
doublereal h = enthalpy_mole();
|
||||
if (h != -241.826E6) {
|
||||
EW_Offset = -241.826E6 - h;
|
||||
}
|
||||
h = enthalpy_mole();
|
||||
|
||||
printf("h = %g\n", h);
|
||||
|
||||
|
||||
/*
|
||||
* Set the initial state of the system to 298.15 K and
|
||||
* 1 bar.
|
||||
*/
|
||||
setTemperature(298.15);
|
||||
double rho0 = m_sub->density(298.15, OneAtm, WATER_LIQUID);
|
||||
setDensity(rho0);
|
||||
|
||||
/*
|
||||
* We have to do something with the thermo function here.
|
||||
*/
|
||||
if (m_spthermo) {
|
||||
delete m_spthermo;
|
||||
m_spthermo = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void WaterTP::
|
||||
setParametersFromXML(const XML_Node& eosdata) {
|
||||
eosdata._require("model","PureFluid");
|
||||
m_subflag = atoi(eosdata["fluid_type"].c_str());
|
||||
if (m_subflag < 0)
|
||||
throw CanteraError("WaterTP::setParametersFromXML",
|
||||
"missing or negative substance flag");
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the molar enthalpy in units of J kmol-1
|
||||
*/
|
||||
doublereal WaterTP::
|
||||
enthalpy_mole() const {
|
||||
double T = temperature();
|
||||
double dens = density();
|
||||
doublereal h = m_sub->enthalpy(T, dens);
|
||||
return (h + EW_Offset);
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate the internal energy in mks units of
|
||||
* J kmol-1
|
||||
*/
|
||||
doublereal WaterTP::
|
||||
intEnergy_mole() const {
|
||||
double T = temperature();
|
||||
double dens = density();
|
||||
doublereal u = m_sub->intEnergy(T, dens);
|
||||
return (u + EW_Offset);
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate the entropy in mks units of
|
||||
* J kmol-1 K-1
|
||||
*/
|
||||
doublereal WaterTP::
|
||||
entropy_mole() const {
|
||||
double T = temperature();
|
||||
double dens = density();
|
||||
doublereal s = m_sub->entropy(T, dens);
|
||||
return (s + SW_Offset);
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate the Gibbs free energy in mks units of
|
||||
* J kmol-1 K-1.
|
||||
*/
|
||||
doublereal WaterTP::
|
||||
gibbs_mole() const {
|
||||
double T = temperature();
|
||||
double dens = density();
|
||||
doublereal g = m_sub->Gibbs(T, dens);
|
||||
return (g + EW_Offset - SW_Offset*T);
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate the constant pressure heat capacity
|
||||
* in mks units of J kmol-1 K-1
|
||||
*/
|
||||
doublereal WaterTP::
|
||||
cp_mole() const {
|
||||
double T = temperature();
|
||||
double dens = density();
|
||||
doublereal cp = m_sub->cp(T, dens);
|
||||
return cp;
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate the constant volume heat capacity
|
||||
* in mks units of J kmol-1 K-1
|
||||
*/
|
||||
doublereal WaterTP::
|
||||
cv_mole() const {
|
||||
double T = temperature();
|
||||
double dens = density();
|
||||
doublereal cv = m_sub->cv(T, dens);
|
||||
return cv;
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate the pressure (Pascals), given the temperature and density
|
||||
* Temperature: kelvin
|
||||
* rho: density in kg m-3
|
||||
*/
|
||||
doublereal WaterTP::
|
||||
pressure() const {
|
||||
double T = temperature();
|
||||
double dens = density();
|
||||
doublereal p = m_sub->pressure(T, dens);
|
||||
return p;
|
||||
}
|
||||
|
||||
void WaterTP::
|
||||
setPressure(doublereal p) {
|
||||
double T = temperature();
|
||||
double dens = density();
|
||||
int waterState = WATER_GAS;
|
||||
double rc = m_sub->Rhocrit();
|
||||
if (dens > rc) {
|
||||
waterState = WATER_LIQUID;
|
||||
}
|
||||
doublereal dd = m_sub->density(T, p, waterState, dens);
|
||||
if (dd <= 0.0) {
|
||||
throw CanteraError("setPressure", "error");
|
||||
}
|
||||
setDensity(dd);
|
||||
}
|
||||
|
||||
|
||||
// critical temperature
|
||||
doublereal WaterTP::critTemperature() const { return m_sub->Tcrit(); }
|
||||
|
||||
// critical pressure
|
||||
doublereal WaterTP::critPressure() const { return m_sub->Pcrit(); }
|
||||
|
||||
// critical density
|
||||
doublereal WaterTP::critDensity() const { return m_sub->Rhocrit(); }
|
||||
|
||||
|
||||
|
||||
void WaterTP::setTemperature(double temp) {
|
||||
State::setTemperature(temp);
|
||||
doublereal dd = density();
|
||||
m_sub->setState(temp, dd);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// saturation pressure
|
||||
doublereal WaterTP::satPressure(doublereal t){
|
||||
doublereal pp = m_sub->psat(t);
|
||||
double dens = density();
|
||||
setTemperature(t);
|
||||
setDensity(dens);
|
||||
return pp;
|
||||
}
|
||||
|
||||
// Return the fraction of vapor at the current conditions
|
||||
doublereal WaterTP::vaporFraction() const {
|
||||
if (temperature() >= m_sub->Tcrit()) {
|
||||
double dens = density();
|
||||
if (dens >= m_sub->Rhocrit()) {
|
||||
return 0.0;
|
||||
}
|
||||
return 1.0;
|
||||
}
|
||||
/*
|
||||
* If below tcrit we always return 0 from this class
|
||||
*/
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -1,3 +1,2 @@
|
|||
#define IEEE_8087
|
||||
#define Arith_Kind_ASL 1
|
||||
#define Double_Align
|
||||
#define IEEE_8087
|
||||
#define Arith_Kind_ASL 1
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
pres = 182080
|
||||
pres = 10107
|
||||
psat(273.16) = 611.655
|
||||
dens (liquid) = 999.793 kg m-3
|
||||
intEng (liquid) ~= 0.0 J/kmol (less than fabs(5.0E-7))
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
temp_success="1"
|
||||
/bin/rm -f output.txt outputa.txt
|
||||
|
||||
testName=testPress
|
||||
testName=testIAPWSPress
|
||||
#################################################################
|
||||
#
|
||||
#################################################################
|
||||
|
|
|
|||
|
|
@ -8,4 +8,4 @@ csvCode.txt
|
|||
diff_test.out
|
||||
test.diff
|
||||
test.out
|
||||
testWaterTP
|
||||
testWaterSSTP
|
||||
|
|
|
|||
|
|
@ -11,11 +11,11 @@
|
|||
.SUFFIXES : .d
|
||||
|
||||
# the name of the executable program to be created
|
||||
PROG_NAME = testWaterTP
|
||||
PROG_NAME = testWaterSSTP
|
||||
|
||||
# the object files to be linked together. List those generated from Fortran
|
||||
# and from C/C++ separately
|
||||
OBJS = testWaterTP.o
|
||||
OBJS = testWaterSSTP.o
|
||||
|
||||
# Location of the current build. Will assume that tests are run
|
||||
# in the source directory tree location
|
||||
|
|
|
|||
|
|
@ -38,6 +38,46 @@ Liquid Densities:
|
|||
400 2.46261 2.45769 937.486 0.0192166
|
||||
500 26.4447 26.392 831.318 0.0216707
|
||||
|
||||
Liquid 1bar or psat State: Partial Molar Quantities
|
||||
T press psat Cpbar Sbar -(G0-H298)/T H0-H298 Volume
|
||||
(K) (bar) (bar) (J/molK) (J/molK) (J/molK) (kJ/mol) m3/kmol
|
||||
273.19 1 0.00612989 76.0121 63.3157 70.2194 -1.88603 0.0180181
|
||||
298.15 1 0.0316993 75.3276 69.9224 69.9224 0 0.0180686
|
||||
300 1 0.0353681 75.3153 70.3884 69.9239 0.139344 0.0180775
|
||||
373.15 1.01621 1.01418 75.9465 86.857 71.6855 5.66125 0.0187982
|
||||
400 2.46261 2.45769 76.6642 92.1544 72.8766 7.71115 0.0192166
|
||||
500 26.4447 26.392 84.0126 109.805 78.4402 15.6825 0.0216707
|
||||
|
||||
Liquid 1bar or psat State: Standard State Quantities
|
||||
T press psat Cpbar Sbar -(G0-H298)/T H0-H298 Volume
|
||||
(K) (bar) (bar) (J/molK) (J/molK) (J/molK) (kJ/mol) m3/kmol
|
||||
273.19 1 0.00612989 76.0121 63.3157 70.2194 -1.88603 0.0180181
|
||||
298.15 1 0.0316993 75.3276 69.9224 69.9224 0 0.0180686
|
||||
300 1 0.0353681 75.3153 70.3884 69.9239 0.139344 0.0180775
|
||||
373.15 1.01621 1.01418 75.9465 86.857 71.6855 5.66125 0.0187982
|
||||
400 2.46261 2.45769 76.6642 92.1544 72.8766 7.71115 0.0192166
|
||||
500 26.4447 26.392 84.0126 109.805 78.4402 15.6825 0.0216707
|
||||
|
||||
Liquid 1bar or psat State: Reference State Quantities (Always 1 atm no matter what system pressure is)
|
||||
T press psat Cpbar Sbar -(G0-H298)/T H0-H298 Volume
|
||||
(K) (bar) (bar) (J/molK) (J/molK) (J/molK) (kJ/mol) m3/kmol
|
||||
273.19 1 0.00612989 76.0119 63.3157 70.2193 -1.886 0.0180181
|
||||
298.15 1 0.0316993 75.3275 69.9224 69.9224 2.21044e-05 0.0180686
|
||||
300 1 0.0353681 75.3153 70.3883 69.9238 0.139366 0.0180775
|
||||
373.15 1.01621 1.01418 75.9465 86.857 71.6855 5.66125 0.0187982
|
||||
400 2.46261 2.45769 76.6712 92.1569 72.8835 7.70936 0.0192181
|
||||
500 26.4447 26.392 84.4316 109.897 78.5506 15.6732 0.021734
|
||||
|
||||
Liquid 1 atm: Standard State Quantities - Should agree with table above
|
||||
T press psat Cpbar Sbar -(G0-H298)/T H0-H298 Volume
|
||||
(K) (bar) (bar) (J/molK) (J/molK) (J/molK) (kJ/mol) m3/kmol
|
||||
273.19 1.01325 0.00612989 76.0119 63.3157 70.2193 -1.886 0.0180181
|
||||
298.15 1.01325 0.0316993 75.3275 69.9224 69.9224 2.21044e-05 0.0180686
|
||||
300 1.01325 0.0353681 75.3153 70.3883 69.9238 0.139366 0.0180775
|
||||
373.15 1.01325 1.01418 75.9465 86.857 71.6855 5.66125 0.0187982
|
||||
400 1.01325 2.45769 76.6712 92.1569 72.8835 7.70936 0.0192181
|
||||
500 1.01325 26.392 84.4316 109.897 78.5506 15.6732 0.021734
|
||||
|
||||
|
||||
Table of increasing Enthalpy at 1 atm
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ testName=testWaterTP
|
|||
CANTERA_DATA=${CANTERA_DATA:=../../../data/inputs}; export CANTERA_DATA
|
||||
|
||||
CANTERA_BIN=${CANTERA_BIN:=../../../bin}
|
||||
./testWaterTP > output.txt
|
||||
./testWaterSSTP > output.txt
|
||||
retnStat=$?
|
||||
if [ $retnStat != "0" ]
|
||||
then
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
*/
|
||||
#include "stdio.h"
|
||||
#include "math.h"
|
||||
#include "WaterTP.h"
|
||||
#include "WaterSSTP.h"
|
||||
#include <new>
|
||||
using namespace std;
|
||||
using namespace Cantera;
|
||||
|
|
@ -22,7 +22,7 @@ int main () {
|
|||
|
||||
double pres;
|
||||
try {
|
||||
WaterTP *w = new WaterTP("waterTPphase.xml","");
|
||||
WaterSSTP *w = new WaterSSTP("waterTPphase.xml","");
|
||||
|
||||
|
||||
/*
|
||||
|
|
@ -34,6 +34,7 @@ int main () {
|
|||
double presLow = 1.0E-2;
|
||||
temp = 298.15;
|
||||
double oneBar = 1.0E5;
|
||||
double vol;
|
||||
|
||||
printf("Comparisons to NIST: (see http://webbook.nist.gov):\n\n");
|
||||
|
||||
|
|
@ -55,7 +56,7 @@ int main () {
|
|||
T[3] = 1000.;
|
||||
|
||||
double Cp0, delh0, delg0, g;
|
||||
|
||||
double Cp0_ss;
|
||||
printf("\nIdeal Gas Standard State:\n");
|
||||
printf (" T Cp0 S0 "
|
||||
" -(G0-H298)/T H0-H298\n");
|
||||
|
|
@ -69,6 +70,14 @@ int main () {
|
|||
g = w->gibbs_mole();
|
||||
delg0 = (g - h298)/temp + GasConstant * log(oneBar/presLow);
|
||||
Cp0 = w->cp_mole();
|
||||
{
|
||||
w->getCp_R(&Cp0_ss);
|
||||
Cp0_ss *= GasConstant;
|
||||
if (fabs(Cp0_ss - Cp0) > 1.0E-5) {
|
||||
printf("Inconsistency!\n");
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
s = w->entropy_mole();
|
||||
s -= GasConstant * log(oneBar/presLow);
|
||||
printf("%10g %10g %13g %13g %13g\n", temp, Cp0*1.0E-3, s*1.0E-3,
|
||||
|
|
@ -142,6 +151,120 @@ int main () {
|
|||
|
||||
}
|
||||
|
||||
|
||||
printf("\nLiquid 1bar or psat State: Partial Molar Quantities\n");
|
||||
printf (" T press psat Cpbar Sbar "
|
||||
" -(G0-H298)/T H0-H298 Volume\n");
|
||||
printf (" (K) (bar) (bar) (J/molK) (J/molK)"
|
||||
" (J/molK) (kJ/mol) m3/kmol\n");
|
||||
|
||||
for (int i = 0; i < 6; i++) {
|
||||
temp = T[i];
|
||||
double psat = w->satPressure(temp);
|
||||
double press = oneBar;
|
||||
if (psat > press) {
|
||||
press = psat*1.002;
|
||||
}
|
||||
w->setState_TP(temp, press);
|
||||
w->getPartialMolarEnthalpies(&h);
|
||||
delh0 = tvalue(h - h298l, 1.0E-6);
|
||||
w->getChemPotentials(&g);
|
||||
delg0 = (g - h298l)/temp;
|
||||
w->getPartialMolarCp(&Cp0);
|
||||
w->getPartialMolarEntropies(&s);
|
||||
w->getPartialMolarVolumes(&vol);
|
||||
printf("%10g %10g %12g %13g %13g %13g %13g %13g\n", temp, press*1.0E-5,
|
||||
psat*1.0E-5,
|
||||
Cp0*1.0E-3, s*1.0E-3,
|
||||
-delg0*1.0E-3, delh0*1.0E-6, vol);
|
||||
}
|
||||
|
||||
printf("\nLiquid 1bar or psat State: Standard State Quantities\n");
|
||||
printf (" T press psat Cpbar Sbar "
|
||||
" -(G0-H298)/T H0-H298 Volume\n");
|
||||
printf (" (K) (bar) (bar) (J/molK) (J/molK)"
|
||||
" (J/molK) (kJ/mol) m3/kmol\n");
|
||||
|
||||
for (int i = 0; i < 6; i++) {
|
||||
temp = T[i];
|
||||
double psat = w->satPressure(temp);
|
||||
double press = oneBar;
|
||||
if (psat > press) {
|
||||
press = psat*1.002;
|
||||
}
|
||||
w->setState_TP(temp, press);
|
||||
w->getEnthalpy_RT(&h);
|
||||
h *= temp * GasConstant;
|
||||
delh0 = tvalue(h - h298l, 1.0E-6);
|
||||
w->getStandardChemPotentials(&g);
|
||||
delg0 = (g - h298l)/temp;
|
||||
w->getCp_R(&Cp0);
|
||||
Cp0 *= GasConstant;
|
||||
w->getEntropy_R(&s);
|
||||
s *= GasConstant;
|
||||
w->getStandardVolumes(&vol);
|
||||
printf("%10g %10g %12g %13g %13g %13g %13g %13g\n", temp, press*1.0E-5,
|
||||
psat*1.0E-5,
|
||||
Cp0*1.0E-3, s*1.0E-3,
|
||||
-delg0*1.0E-3, delh0*1.0E-6, vol);
|
||||
}
|
||||
|
||||
printf("\nLiquid 1bar or psat State: Reference State Quantities (Always 1 atm no matter what system pressure is)\n");
|
||||
printf (" T press psat Cpbar Sbar "
|
||||
" -(G0-H298)/T H0-H298 Volume\n");
|
||||
printf (" (K) (bar) (bar) (J/molK) (J/molK)"
|
||||
" (J/molK) (kJ/mol) m3/kmol\n");
|
||||
|
||||
for (int i = 0; i < 6; i++) {
|
||||
temp = T[i];
|
||||
double psat = w->satPressure(temp);
|
||||
double press = oneBar;
|
||||
if (psat > press) {
|
||||
press = psat*1.002;
|
||||
}
|
||||
w->setState_TP(temp, press);
|
||||
w->getEnthalpy_RT_ref(&h);
|
||||
h *= temp * GasConstant;
|
||||
delh0 = tvalue(h - h298l, 1.0E-6);
|
||||
w->getGibbs_ref(&g);
|
||||
delg0 = (g - h298l)/temp;
|
||||
w->getCp_R_ref(&Cp0);
|
||||
Cp0 *= GasConstant;
|
||||
w->getEntropy_R_ref(&s);
|
||||
s *= GasConstant;
|
||||
w->getStandardVolumes_ref(&vol);
|
||||
printf("%10g %10g %12g %13g %13g %13g %13g %13g\n", temp, press*1.0E-5,
|
||||
psat*1.0E-5,
|
||||
Cp0*1.0E-3, s*1.0E-3,
|
||||
-delg0*1.0E-3, delh0*1.0E-6, vol);
|
||||
}
|
||||
|
||||
printf("\nLiquid 1 atm: Standard State Quantities - Should agree with table above\n");
|
||||
printf (" T press psat Cpbar Sbar "
|
||||
" -(G0-H298)/T H0-H298 Volume\n");
|
||||
printf (" (K) (bar) (bar) (J/molK) (J/molK)"
|
||||
" (J/molK) (kJ/mol) m3/kmol\n");
|
||||
|
||||
for (int i = 0; i < 6; i++) {
|
||||
temp = T[i];
|
||||
double psat = w->satPressure(temp);
|
||||
double press = OneAtm;
|
||||
w->setState_TP(temp, press);
|
||||
w->getEnthalpy_RT(&h);
|
||||
h *= temp * GasConstant;
|
||||
delh0 = tvalue(h - h298l, 1.0E-6);
|
||||
w->getStandardChemPotentials(&g);
|
||||
delg0 = (g - h298l)/temp;
|
||||
w->getCp_R(&Cp0);
|
||||
Cp0 *= GasConstant;
|
||||
w->getEntropy_R(&s);
|
||||
s *= GasConstant;
|
||||
w->getStandardVolumes(&vol);
|
||||
printf("%10g %10g %12g %13g %13g %13g %13g %13g\n", temp, press*1.0E-5,
|
||||
psat*1.0E-5,
|
||||
Cp0*1.0E-3, s*1.0E-3,
|
||||
-delg0*1.0E-3, delh0*1.0E-6, vol);
|
||||
}
|
||||
printf("\n\nTable of increasing Enthalpy at 1 atm\n\n");
|
||||
double dens;
|
||||
printf(" Enthalpy, Temperature, x_Vapor, Density, Entropy_mass, Gibbs_mass\n");
|
||||
Loading…
Add table
Reference in a new issue