cantera/include/cantera/thermo/WaterPropsIAPWS.h
Ray Speth 002c158761 Cleanup include statements
Move includes from header to implementation files where possible, and remove
unnecessary includes.
2014-08-28 16:54:13 +00:00

468 lines
17 KiB
C++

/**
* @file WaterPropsIAPWS.h
* Headers for a class for calculating the equation of state of water
* from the IAPWS 1995 Formulation based on the steam tables thermodynamic
* basis (See class \link Cantera::WaterPropsIAPWS WaterPropsIAPWS\endlink).
*/
/*
* Copyright (2005) Sandia Corporation. Under the terms of
* Contract DE-AC04-94AL85000 with Sandia Corporation, the
* U.S. Government retains certain rights in this software.
*/
#ifndef WATERPROPSIAPWS_H
#define WATERPROPSIAPWS_H
#include "WaterPropsIAPWSphi.h"
namespace Cantera
{
/**
* @name Names for the phase regions
*
* These constants are defined and used in the interface
* to describe the location of where we are in (T,rho) space.
*
* WATER_UNSTABLELIQUID indicates that we are in the unstable region, inside the
* spinodal curve where dpdrho < 0.0 amonst other properties. The difference
* between WATER_UNSTABLELIQUID and WATER_UNSTABLEGAS is that
* for WATER_UNSTABLELIQUID d2pdrho2 > 0 and dpdrho < 0.0
* for WATER_UNSTABLEGAS d2pdrho2 < 0 and dpdrho < 0.0
*/
//@{
#define WATER_GAS 0
#define WATER_LIQUID 1
#define WATER_SUPERCRIT 2
#define WATER_UNSTABLELIQUID 3
#define WATER_UNSTABLEGAS 4
//@}
//! Class for calculating the equation of state of water.
/*!
* The reference is W. Wagner, A. Prub, "The IAPWS Formulation 1995 for the
* Thermodynamic Properties of Ordinary Water Substance for General and
* Scientific Use," J. Phys. Chem. Ref. Dat, 31, 387, 2002.
*
* This class provides a very complicated polynomial for the specific
* Helmholtz free energy of water, as a function of temperature and density.
*
* \f[
* \frac{M\hat{f}(\rho,T)}{R T} = \phi(\delta, \tau) =
* \phi^o(\delta, \tau) + \phi^r(\delta, \tau)
* \f]
*
* where
*
* \f[
* \delta = \rho / \rho_c \quad \mathrm{and} \quad \tau = T_c / T
* \f]
*
* The following constants are assumed
*
* \f[
* T_c = 647.096\mathrm{\;K}
* \f]
* \f[
* \rho_c = 322 \mathrm{\;kg\,m^{-3}}
* \f]
* \f[
* R/M = 0.46151805 \mathrm{\;kJ\,kg^{-1}\,K^{-1}}
* \f]
*
* The free energy is a unique single-valued function of the temperature and
* density over its entire range.
*
* Note, the base thermodynamic state for this class is the one used in the
* steam tables, i.e., the liquid at the triple point for water has the
* following properties:
*
* - u(273.16, rho) = 0.0
* - s(273.16, rho) = 0.0
* - psat(273.16) = 611.655 Pascal
* - rho(273.16, psat) = 999.793 kg m-3
*
* Therefore, to use this class within %Cantera, offsets to u() and s() must
* be used to put the water class onto the same basis as other thermodynamic
* quantities. For example, in the WaterSSTP class, these offsets are
* calculated in the following way. The thermodynamic base state for water is
* set to the NIST basis here by specifying constants EW_Offset and SW_Offset.
* These offsets are calculated on the fly so that the following properties
* hold:
*
* - Delta_Hfo_idealGas(298.15, 1bar) = -241.826 kJ/gmol
* - So_idealGas(298.15, 1bar) = 188.835 J/gmolK
*
* The offsets are calculated by actually computing the above quantities and
* then calculating the correction factor.
*
* This class provides an interface to the WaterPropsIAPWSphi class, which
* actually calculates the \f$ \phi^o(\delta, \tau) \f$ and the
* \f$ \phi^r(\delta, \tau) \f$ polynomials in dimensionless form.
*
* All thermodynamic results from this class are returned in dimensional form.
* This is because the gas constant (and molecular weight) used within this
* class is allowed to be potentially different than that used elsewhere in
* %Cantera. Therefore, everything has to be in dimensional units. Note,
* however, the thermodynamic basis is set to that used in the steam tables.
* (u = s = 0 for liquid water at the triple point).
*
* This class is not a %ThermoPhase. However, it does maintain an internal
* state of the object that is dependent on temperature and density. The
* internal state is characterized by an internally stored \f$ \tau\f$ and a
* \f$ \delta \f$ value, and an iState value, which indicates whether the
* point is a liquid, a gas, or a supercritical fluid. Along with that the
* \f$ \tau\f$ and a \f$ \delta \f$ values are polynomials of \f$ \tau\f$ and
* a \f$ \delta \f$ that are kept by the WaterPropsIAPWSphi class. Therefore,
* whenever \f$ \tau\f$ or \f$ \delta \f$ is changed, the function setState()
* must be called in order for the internal state to be kept up to date.
*
* The class is pretty straightforward. However, one function deserves
* mention. The density() function calculates the density that is consistent
* with a particular value of the temperature and pressure. It may therefore
* be multivalued or potentially there may be no answer from this function. It
* therefore takes a phase guess and a density guess as optional parameters.
* If no guesses are supplied to density(), a gas phase guess is assumed. This
* may or may not be what is wanted. Therefore, density() should usually at
* least be supplied with a phase guess so that it may manufacture an
* appropriate density guess. density() manufactures the initial density
* guess, nondimensionalizes everything, and then calls
* WaterPropsIAPWSphi::dfind(), which does the iterative calculation to find
* the density condition that matches the desired input pressure.
*
* The phase guess defines are located in the .h file. they are
*
* - WATER_GAS
* - WATER_LIQUID
* - WATER_SUPERCRIT
*
* There are only three functions which actually change the value of the
* internal state of this object after it's been instantiated
*
* - setState_TR(temperature, rho)
* - density(temperature, pressure, phase, rhoguess)
* - psat(temperature, waterState);
*
* The setState_TR() is the main function that sets the temperature and rho
* value. The density() function serves as a setState_TP() function, in that
* it sets internal state to a temperature and pressure. However, note that
* this is potentially multivalued. Therefore, we need to supply in addition a
* phase guess and a rho guess to the input temperature and pressure. The
* psat() function sets the internal state to the saturated liquid or
* saturated gas state, depending on the waterState parameter.
*
* Because the underlying object WaterPropsIAPWSphi is privately held, you can
* be sure that the underlying state of this object doesn't change except due
* to the three function calls listed above.
*
* @ingroup thermoprops
*/
class WaterPropsIAPWS
{
public:
//! Base constructor
WaterPropsIAPWS();
//! Copy constructor
WaterPropsIAPWS(const WaterPropsIAPWS& right);
//! assignment constructor
WaterPropsIAPWS& operator=(const WaterPropsIAPWS& right);
//! destructor
~WaterPropsIAPWS();
//! Set the internal state of the object wrt temperature and density
/*!
* @param temperature temperature (kelvin)
* @param rho density (kg m-3)
*/
void setState_TR(doublereal temperature, doublereal rho);
//! Calculate the Helmholtz free energy in mks units of J kmol-1 K-1,
//! using the last temperature and density
doublereal helmholtzFE() const;
//! Calculate the Gibbs free energy in mks units of J kmol-1 K-1.
//! using the last temperature and density
doublereal Gibbs() const;
//! Calculate the enthalpy in mks units of J kmol-1
//! using the last temperature and density
doublereal enthalpy() const;
//! Calculate the internal energy in mks units of J kmol-1
doublereal intEnergy() const;
//! Calculate the entropy in mks units of J kmol-1 K-1
doublereal entropy() const;
//! Calculate the constant volume heat capacity in mks units of J kmol-1 K-1
//! at the last temperature and density
doublereal cv() const;
//! Calculate the constant pressure heat capacity in mks units of J kmol-1 K-1
//! at the last temperature and density
doublereal cp() const;
//! Calculate the molar volume (kmol m-3)
//! at the last temperature and density
doublereal molarVolume() const;
//! Calculates the pressure (Pascals), given the current value of the
//! temperature and density.
/*!
* The density is an independent variable in the underlying equation of state
*
* @return
* returns the pressure (Pascal)
*/
doublereal pressure() const;
//! Calculates the density given the temperature and the pressure,
//! and a guess at the density. Sets the internal state.
/*!
* Note, below T_c, this is a multivalued function.
*
* The density() function calculates the density that is consistent with
* a particular value of the temperature and pressure. It may therefore be
* multivalued or potentially there may be no answer from this function.
* It therefore takes a phase guess and a density guess as optional
* parameters. If no guesses are supplied to density(), a gas phase guess
* is assumed. This may or may not be what is wanted. Therefore, density()
* should usually at least be supplied with a phase guess so that it may
* manufacture an appropriate density guess. density() manufactures the
* initial density guess, nondimensionalizes everything, and then calls
* WaterPropsIAPWSphi::dfind(), which does the iterative calculation to
* find the density condition that matches the desired input pressure.
*
* @param temperature: Kelvin
* @param pressure : Pressure in Pascals (Newton/m**2)
* @param phase : guessed phase of water
* : -1: no guessed phase
* @param rhoguess : guessed density of the water
* : -1.0 no guessed density
* @return
* Returns the density. If an error is encountered in the calculation
* the value of -1.0 is returned.
*/
doublereal density(doublereal temperature, doublereal pressure,
int phase = -1, doublereal rhoguess = -1.0);
//! Calculates the density given the temperature and the pressure,
//! and a guess at the density, while not changing the internal state
/*!
* Note, below T_c, this is a multivalued function.
*
* The density() function calculates the density that is consistent with a
* particular value of the temperature and pressure. It may therefore be
* multivalued or potentially there may be no answer from this function.
* It therefore takes a phase guess and a density guess as optional
* parameters. If no guesses are supplied to density(), a gas phase guess
* is assumed. This may or may not be what is wanted. Therefore, density()
* should usually at least be supplied with a phase guess so that it may
* manufacture an appropriate density guess. density() manufactures the
* initial density guess, nondimensionalizes everything, and then calls
* WaterPropsIAPWSphi::dfind(), which does the iterative calculation to
* find the density condition that matches the desired input pressure.
*
* @param pressure : Pressure in Pascals (Newton/m**2)
* @param phase : guessed phase of water
* : -1: no guessed phase
* @param rhoguess : guessed density of the water
* : -1.0 no guessed density
* @return
* Returns the density. If an error is encountered in the calculation
* the value of -1.0 is returned.
*/
doublereal density_const(doublereal pressure, int phase = -1, doublereal rhoguess = -1.0) const;
//! Returns the density (kg m-3)
/*!
* The density is an independent variable in the underlying equation of state
*
* @return Returns the density (kg m-3)
*/
doublereal density() const;
//! Returns the temperature (Kelvin)
/*!
* @return Returns the internally stored temperature
*/
doublereal temperature() const;
//! Returns the coefficient of thermal expansion.
/*!
* alpha = d (ln V) / dT at constant P.
*
* @return
* Returns the coefficient of thermal expansion
*/
doublereal coeffThermExp() const;
//! Returns the isochoric pressure derivative wrt temperature
/*!
* beta = M / (rho * Rgas) (d (pressure) / dT) at constant rho
*
* Note for ideal gases this is equal to one.
*
* beta = delta (phi0_d() + phiR_d())
* - tau delta (phi0_dt() + phiR_dt())
*/
doublereal coeffPresExp() const;
//! Returns the coefficient of isothermal compressibility for the
//! state of the object
/*!
* kappa = - d (ln V) / dP at constant T.
*
* units - 1/Pascal
*
* @return
* returns the isothermal compressibility
*/
doublereal isothermalCompressibility() const;
//! Returns the value of dp / drho at constant T for the
//! state of the object
/*!
* units - Joules / kg
*
* @return
* returns dpdrho
*/
doublereal dpdrho() const;
//! This function returns an estimated value for the saturation pressure.
/*!
* It does this via a polynomial fit of the vapor pressure curve.
* units = (Pascals)
*
* @param temperature Input temperature (Kelvin)
*
* @return
* Returns the estimated saturation pressure
*/
doublereal psat_est(doublereal temperature) const;
//! This function returns the saturation pressure given the temperature as
//! an input parameter, and sets the internal state to the saturated
//! conditions.
/*!
* Note this function will return the saturation pressure, given the
* temperature. It will then set the state of the system to the
* saturation condition. The input parameter waterState is used to either
* specify the liquid state or the gas state at the desired temperature
* and saturated pressure.
*
* If the input temperature, T, is above T_c, this routine will set the
* internal state to T and the pressure to P_c. Then, return P_c.
*
* @param temperature input temperature (kelvin)
* @param waterState integer specifying the water state
*
* @return Returns the saturation pressure. units = Pascal
*/
doublereal psat(doublereal temperature, int waterState = WATER_LIQUID);
//! Return the value of the density at the water spinodal point (on the liquid side)
//! for the current temperature.
/*!
* @return returns the density with units of kg m-3
*/
doublereal densSpinodalWater() const;
//! Return the value of the density at the water spinodal point (on the gas side)
//! for the current temperature.
/*!
* @return returns the density with units of kg m-3
*/
doublereal densSpinodalSteam() const;
//! Returns the Phase State flag for the current state of the object
/*!
* @param checkState If true, this function does a complete check to see
* where in parameters space we are
*
* There are three values:
* - WATER_GAS below the critical temperature but below the critical density
* - WATER_LIQUID below the critical temperature but above the critical density
* - WATER_SUPERCRIT above the critical temperature
*/
int phaseState(bool checkState = false) const ;
//! Returns the critical temperature of water (Kelvin)
/*!
* This is hard coded to the value 647.096 Kelvin
*/
doublereal Tcrit() const {
return 647.096;
}
//! Returns the critical pressure of water (22.064E6 Pa)
/*!
* This is hard coded to the value of 22.064E6 pascals
*/
doublereal Pcrit() const {
return 22.064E6;
}
//! Return the critical density of water (kg m-3)
/*!
* This is equal to 322 kg m-3.
*/
doublereal Rhocrit() const {
return 322.;
}
private:
//! Calculate the dimensionless temp and rho and store internally.
/*!
* @param temperature input temperature (kelvin)
* @param rho density in kg m-3
*/
void calcDim(doublereal temperature, doublereal rho);
//! Utility routine in the calculation of the saturation pressure
/*!
* Calculate the Gibbs free energy in mks units of J kmol-1 K-1.
*
* @param temperature temperature (kelvin)
* @param pressure pressure (Pascal)
* @param densLiq Output density of liquid
* @param densGas output Density of gas
* @param delGRT output delGRT
*/
void corr(doublereal temperature, doublereal pressure, doublereal& densLiq,
doublereal& densGas, doublereal& delGRT);
//! Utility routine in the calculation of the saturation pressure
/*!
* @param temperature temperature (kelvin)
* @param pressure pressure (Pascal)
* @param densLiq Output density of liquid
* @param densGas output Density of gas
* @param pcorr output corrected pressure
*/
void corr1(doublereal temperature, doublereal pressure, doublereal& densLiq,
doublereal& densGas, doublereal& pcorr);
//! pointer to the underlying object that does the calculations.
WaterPropsIAPWSphi* m_phi;
//! Dimensionless temperature
/*!
* tau = T_C / T
*/
doublereal tau;
//! Dimensionless density
/*!
* delta = rho / rho_c
*/
mutable doublereal delta;
//! Current state of the system
mutable int iState;
};
}
#endif