00001 /** 00002 * @file WaterPropsIAPWS.h 00003 * Headers for a class for calculating the equation of state of water 00004 * from the IAPWS 1995 Formulation based on the steam tables thermodynamic 00005 * basis (See class \link Cantera::WaterPropsIAPWS WaterPropsIAPWS\endlink). 00006 */ 00007 /* 00008 * Copywrite (2005) Sandia Corporation. Under the terms of 00009 * Contract DE-AC04-94AL85000 with Sandia Corporation, the 00010 * U.S. Government retains certain rights in this software. 00011 */ 00012 /* 00013 * $Id: WaterPropsIAPWS.h 279 2009-12-05 19:08:43Z hkmoffa $ 00014 */ 00015 00016 #ifndef WATERPROPSIAPWS_H 00017 #define WATERPROPSIAPWS_H 00018 00019 #include "WaterPropsIAPWSphi.h" 00020 #include "config.h" 00021 00022 namespace Cantera { 00023 /** 00024 * @name Names for the phase regions 00025 * 00026 * These constants are defined and used in the interface 00027 * to describe the location of where we are in (T,rho) space. 00028 * 00029 * WATER_UNSTABLELIQUID indicates that we are in the unstable region, inside the 00030 * spinodal curve where dpdrho < 0.0 amonst other properties. The difference 00031 * between WATER_UNSTABLELIQUID and WATER_UNSTABLEGAS is that 00032 * for WATER_UNSTABLELIQUID d2pdrho2 > 0 and dpdrho < 0.0 00033 * for WATER_UNSTABLEGAS d2pdrho2 < 0 and dpdrho < 0.0 00034 */ 00035 //@{ 00036 #define WATER_GAS 0 00037 #define WATER_LIQUID 1 00038 #define WATER_SUPERCRIT 2 00039 #define WATER_UNSTABLELIQUID 3 00040 #define WATER_UNSTABLEGAS 4 00041 //@} 00042 00043 //! Class for calculating the equation of state of water. 00044 /*! 00045 * 00046 * The reference is W. Wagner, A. Prub, "The IAPWS Formulation 1995 for the Themodynamic 00047 * Properties of Ordinary Water Substance for General and Scientific Use," 00048 * J. Phys. Chem. Ref. Dat, 31, 387, 2002. 00049 * 00050 * This class provides a very complicated polynomial for the specific helmholtz free 00051 * energy of water, as a function of temperature and density. 00052 * 00053 * \f[ 00054 * \frac{M\hat{f}(\rho,T)}{R T} = \phi(\delta, \tau) = 00055 * \phi^o(\delta, \tau) + \phi^r(\delta, \tau) 00056 * \f] 00057 * 00058 * where 00059 * 00060 * \f[ 00061 * \delta = \rho / \rho_c \mbox{\qquad and \qquad} \tau = T_c / T 00062 * \f] 00063 * 00064 * The following constants are assumed 00065 * 00066 * \f[ 00067 * T_c = 647.096\mbox{\ K} 00068 * \f] 00069 * \f[ 00070 * \rho_c = 322 \mbox{\ kg\ m$^{-3}$} 00071 * \f] 00072 * \f[ 00073 * R/M = 0.46151805 \mbox{\ kJ\ kg$^{-1}$\ K$^{-1}$} 00074 * \f] 00075 * 00076 * The free energy is a unique single-valued function of the temperature and density 00077 * over its entire range. 00078 * 00079 * Note, the base thermodynamic state for this class is the one 00080 * used in the steam tables, i.e., the liquid at the triple point 00081 * for water has the following properties: 00082 * 00083 * - u(273.16, rho) = 0.0 00084 * - s(273.16, rho) = 0.0 00085 * - psat(273.16) = 611.655 Pascal 00086 * - rho(273.16, psat) = 999.793 kg m-3 00087 * 00088 * Therefore, to use this class within %Cantera, offsets to u() and s() must be used 00089 * to put the water class onto the same basis as other thermodynamic quantities. 00090 * For example, in the WaterSSTP class, these offsets are calculated in the following way. 00091 * The thermodynamic base state for water is set to the NIST basis here 00092 * by specifying constants EW_Offset and SW_Offset. These offsets are 00093 * calculated on the fly so that the following properties hold: 00094 * 00095 * - Delta_Hfo_idealGas(298.15, 1bar) = -241.826 kJ/gmol 00096 * - So_idealGas(298.15, 1bar) = 188.835 J/gmolK 00097 * 00098 * The offsets are calculated by actually computing the above quantities and then 00099 * calculating the correction factor. 00100 * 00101 * This class provides an interface to the #WaterPropsIAPWSphi class, which actually 00102 * calculates the \f$ \phi^o(\delta, \tau) \f$ and the \f$ \phi^r(\delta, \tau) \f$ 00103 * polynomials in dimensionless form. 00104 * 00105 * All thermodynamic results from this class are returned in dimensional form. This 00106 * is because the gas constant (and molecular weight) used within this class is allowed to be potentially 00107 * different than that used elsewhere in %Cantera. Therefore, everything has to be 00108 * in dimensional units. Note, however, the thermodynamic basis is set to that used 00109 * in the steam tables. (u = s = 0 for liquid water at the triple point). 00110 * 00111 * This class is not a %ThermoPhase. However, it does maintain an internal state of 00112 * the object that is dependent on temperature and density. The internal state 00113 * is characterized by an internally storred \f$ \tau\f$ and a \f$ \delta \f$ value, 00114 * and an iState value, which indicates whether the point is a liquid, a gas, 00115 * or a supercritical fluid. 00116 * Along with that the \f$ \tau\f$ and a \f$ \delta \f$ values are polynomials of 00117 * \f$ \tau\f$ and a \f$ \delta \f$ that are kept by the #WaterPropsIAPWSphi class. 00118 * Therefore, whenever \f$ \tau\f$ or \f$ \delta \f$ is changed, the function setState() 00119 * must be called in order for the internal state to be kept up to date. 00120 * 00121 * The class is pretty straightfoward. However, one function deserves mention. 00122 * the #density() function calculates the density that is consistent with 00123 * a particular value of the temperature and pressure. It may therefore be 00124 * multivalued or potentially there may be no answer from this function. It therefore 00125 * takes a phase guess and a density guess as optional parameters. If no guesses are 00126 * supplied to density(), a gas phase guess is assumed. This may or may not be what 00127 * is wanted. Therefore, density() should usually at leat be supplied with a phase 00128 * guess so that it may manufacture an appropriate density guess. 00129 * #density() manufactures the initial density guess, nondimensionalizes everything, 00130 * and then calls #WaterPropsIAPWSphi::dfind(), which does the iterative calculation 00131 * to find the density condition that matches the desired input pressure. 00132 * 00133 * The phase guess defines are located in the .h file. they are 00134 * 00135 * - WATER_GAS 00136 * - WATER_LIQUID 00137 * - WATER_SUPERCRIT 00138 * 00139 * There are only three functions which actually change the value of the internal 00140 * state of this object after it's been instantiated 00141 00142 * - setState_TR(temperature, rho) 00143 * - density(temperature, pressure, phase, rhoguess) 00144 * - psat(temperature, waterState); 00145 * 00146 * The setState_TR() is the main function that sets the temperature and rho value. 00147 * The density() function serves as a setState_TP() function, in that it sets 00148 * internal state to a temperature and pressure. However, note that this is potentially 00149 * multivalued. Therefore, we need to supply in addition a phase guess and a rho guess 00150 * to the input temperature and pressure. 00151 * The psat() function sets the internal state to the saturated liquid or saturated gas 00152 * state, dependeing on the waterState parameter. 00153 * 00154 * Because the underlying object WaterPropsIAPWSphi is privately held, you can be 00155 * sure that the underlying state of this object doesn't change except due to the 00156 * three function calls listed above. 00157 * 00158 * @ingroup thermoprops 00159 * 00160 */ 00161 class WaterPropsIAPWS { 00162 public: 00163 00164 //! Base constructor 00165 WaterPropsIAPWS(); 00166 00167 //! Copy constructor 00168 /*! 00169 * @param right Object to be copied 00170 */ 00171 WaterPropsIAPWS(const WaterPropsIAPWS &right); 00172 00173 //! assignment constructor 00174 /*! 00175 * @param right Object to be copied 00176 */ 00177 WaterPropsIAPWS & operator=(const WaterPropsIAPWS &right); 00178 00179 //! destructor 00180 ~WaterPropsIAPWS(); 00181 00182 //! Set the internal state of the object wrt temperature and density 00183 /*! 00184 * @param temperature temperature (kelvin) 00185 * @param rho density (kg m-3) 00186 */ 00187 void setState_TR(doublereal temperature, doublereal rho); 00188 00189 //! Calculate the Helmholtz free energy in mks units of J kmol-1 K-1, 00190 //! using the last temperature and density 00191 doublereal helmholtzFE() const; 00192 00193 //! Calculate the Gibbs free energy in mks units of J kmol-1 K-1. 00194 //! using the last temperature and density 00195 doublereal Gibbs() const; 00196 00197 //! Calculate the enthalpy in mks units of J kmol-1 00198 //! using the last temperature and density 00199 doublereal enthalpy() const; 00200 00201 //! Calculate the internal energy in mks units of J kmol-1 00202 doublereal intEnergy() const; 00203 00204 //! Calculate the entropy in mks units of J kmol-1 K-1 00205 doublereal entropy() const; 00206 00207 //! Calculate the constant volume heat capacity in mks units of J kmol-1 K-1 00208 //! at the last temperature and density 00209 doublereal cv() const; 00210 00211 //! Calculate the constant pressure heat capacity in mks units of J kmol-1 K-1 00212 //! at the last temperature and density 00213 doublereal cp() const; 00214 00215 //! Calculate the molar volume (kmol m-3) 00216 //! at the last temperature and density 00217 doublereal molarVolume() const; 00218 00219 //! Calculates the pressure (Pascals), given the current value of the 00220 //! temperature and density. 00221 /*! 00222 * The density is an independent variable in the underlying equation of state 00223 * 00224 * @return 00225 * returns the pressure (Pascal) 00226 */ 00227 doublereal pressure() const; 00228 00229 //! Calculates the density given the temperature and the pressure, 00230 //! and a guess at the density. Sets the internal state. 00231 /*! 00232 * Note, below T_c, this is a multivalued function. 00233 * 00234 * The #density() function calculates the density that is consistent with 00235 * a particular value of the temperature and pressure. It may therefore be 00236 * multivalued or potentially there may be no answer from this function. It therefore 00237 * takes a phase guess and a density guess as optional parameters. If no guesses are 00238 * supplied to density(), a gas phase guess is assumed. This may or may not be what 00239 * is wanted. Therefore, density() should usually at leat be supplied with a phase 00240 * guess so that it may manufacture an appropriate density guess. 00241 * #density() manufactures the initial density guess, nondimensionalizes everything, 00242 * and then calls #WaterPropsIAPWSphi::dfind(), which does the iterative calculation 00243 * to find the density condition that matches the desired input pressure. 00244 * 00245 * @param temperature: Kelvin 00246 * @param pressure : Pressure in Pascals (Newton/m**2) 00247 * @param phase : guessed phase of water 00248 * : -1: no guessed phase 00249 * @param rhoguess : guessed density of the water 00250 * : -1.0 no guessed density 00251 * @return 00252 * Returns the density. If an error is encountered in the calculation 00253 * the value of -1.0 is returned. 00254 */ 00255 doublereal density(doublereal temperature, doublereal pressure, 00256 int phase = -1, doublereal rhoguess = -1.0); 00257 00258 //! Calculates the density given the temperature and the pressure, 00259 //! and a guess at the density, while not changing the internal state 00260 /*! 00261 * Note, below T_c, this is a multivalued function. 00262 * 00263 * The #density() function calculates the density that is consistent with 00264 * a particular value of the temperature and pressure. It may therefore be 00265 * multivalued or potentially there may be no answer from this function. It therefore 00266 * takes a phase guess and a density guess as optional parameters. If no guesses are 00267 00268 * supplied to density(), a gas phase guess is assumed. This may or may not be what 00269 * is wanted. Therefore, density() should usually at leat be supplied with a phase 00270 * guess so that it may manufacture an appropriate density guess. 00271 * #density() manufactures the initial density guess, nondimensionalizes everything, 00272 * and then calls #WaterPropsIAPWSphi::dfind(), which does the iterative calculation 00273 * to find the density condition that matches the desired input pressure. 00274 * 00275 * @param pressure : Pressure in Pascals (Newton/m**2) 00276 * @param phase : guessed phase of water 00277 * : -1: no guessed phase 00278 * @param rhoguess : guessed density of the water 00279 * : -1.0 no guessed density 00280 * @return 00281 * Returns the density. If an error is encountered in the calculation 00282 * the value of -1.0 is returned. 00283 */ 00284 doublereal density_const(doublereal pressure, int phase = -1, doublereal rhoguess = -1.0) const; 00285 00286 //! Returns the density (kg m-3) 00287 /*! 00288 * The density is an independent variable in the underlying equation of state 00289 * 00290 * @return Returns the density (kg m-3) 00291 */ 00292 doublereal density() const; 00293 00294 //! Returns the temperature (Kelvin) 00295 /*! 00296 * @return Returns the internally storred temperature 00297 */ 00298 doublereal temperature() const; 00299 00300 //! Returns the coefficient of thermal expansion. 00301 /*! 00302 * alpha = d (ln V) / dT at constant P. 00303 * 00304 * @return 00305 * Returns the coefficient of thermal expansion 00306 */ 00307 doublereal coeffThermExp() const; 00308 00309 //! Returns the isochoric pressure derivative wrt temperature 00310 /*! 00311 * 00312 * beta = M / (rho * Rgas) (d (pressure) / dT) at constant rho 00313 * 00314 * Note for ideal gases this is equal to one. 00315 * 00316 * beta = delta (phi0_d() + phiR_d()) 00317 * - tau delta (phi0_dt() + phiR_dt()) 00318 */ 00319 doublereal coeffPresExp() const; 00320 00321 //! Returns the coefficient of isothermal compressibility for the 00322 //! state of the object 00323 /*! 00324 * kappa = - d (ln V) / dP at constant T. 00325 * 00326 * units - 1/Pascal 00327 * 00328 * @return 00329 * returns the isothermal compressibility 00330 */ 00331 doublereal isothermalCompressibility() const; 00332 00333 //! Returns the value of dp / drho at constant T for the 00334 //! state of the object 00335 /*! 00336 * units - Joules / kg 00337 * 00338 * @return 00339 * returns dpdrho 00340 */ 00341 doublereal dpdrho() const; 00342 00343 //! This function returns an estimated value for the saturation pressure. 00344 /*! 00345 * It does this via a polynomial fit of the vapor pressure curve. 00346 * units = (Pascals) 00347 * 00348 * @param temperature Input temperature (Kelvin) 00349 * 00350 * @return 00351 * Returns the estimated saturation pressure 00352 */ 00353 doublereal psat_est(doublereal temperature) const; 00354 00355 //! This function returns the saturation pressure given the 00356 //! temperature as an input parameter, and sets the internal state to the saturated 00357 //! conditions. 00358 /*! 00359 * Note this function will return the saturation pressure, given the temperature. 00360 * It will then set the state of the system to the saturation condition. The input 00361 * parameter waterState is used to either specify the liquid state or the 00362 * gas state at the desired temperatue and saturated pressure. 00363 * 00364 * If the input temperature, T, is above T_c, this routine will set the internal 00365 * state to T and the pressure to P_c. Then, return P_c. 00366 * 00367 * @param temperature input temperature (kelvin) 00368 * @param waterState integer specifying the water state 00369 * 00370 * @return Returns the saturation pressure 00371 * units = Pascal 00372 */ 00373 doublereal psat(doublereal temperature, int waterState = WATER_LIQUID); 00374 00375 //! Return the value of the density at the water spinodal point (on the liquid side) 00376 //! for the current temperature. 00377 /*! 00378 * @return returns the density with units of kg m-3 00379 */ 00380 doublereal densSpinodalWater() const; 00381 00382 //! Return the value of the density at the water spinodal point (on the gas side) 00383 //! for the current temperature. 00384 /*! 00385 * @return returns the density with units of kg m-3 00386 */ 00387 doublereal densSpinodalSteam() const; 00388 00389 //! Returns the Phase State flag for the current state of the object 00390 /*! 00391 * @param checkState If true, this function does a complete check to see where 00392 * in paramters space we are 00393 * 00394 * There are three values: 00395 * WATER_GAS below the critical temperature but below the critical density 00396 * WATER_LIQUID below the critical temperature but above the critical density 00397 * WATER_SUPERCRIT above the critical temperature 00398 */ 00399 int phaseState(bool checkState = false) const ; 00400 00401 //! Returns the critical temperature of water (Kelvin) 00402 /*! 00403 * This is hard coded to the value 647.096 Kelvin 00404 */ 00405 doublereal Tcrit() const { return 647.096;} 00406 00407 //! Returns the critical pressure of water (22.064E6 Pa) 00408 /*! 00409 * This is hard coded to the value of 22.064E6 pascals 00410 */ 00411 doublereal Pcrit() const { return 22.064E6;} 00412 00413 //! Return the critical density of water (kg m-3) 00414 /*! 00415 * This is equal to 322 kg m-3. 00416 */ 00417 doublereal Rhocrit() const { return 322.;} 00418 00419 private: 00420 //! Calculate the dimensionless temp and rho and store internally. 00421 /*! 00422 * Private routine 00423 * 00424 * @param temperature input temperature (kelvin) 00425 * @param rho density in kg m-3 00426 */ 00427 void calcDim(doublereal temperature, doublereal rho); 00428 00429 //! Utility routine in the calculation of the saturation pressure 00430 /*! 00431 * Private routine 00432 * 00433 * @param temperature temperature (kelvin) 00434 * @param pressure pressure (Pascal) 00435 * @param densLiq Output density of liquid 00436 * @param densGas output Density of gas 00437 * @param delGRT output delGRT 00438 */ 00439 void corr(doublereal temperature, doublereal pressure, doublereal &densLiq, 00440 doublereal &densGas, doublereal &delGRT); 00441 00442 //! Utility routine in the calculation of the saturation pressure 00443 /*! 00444 * Private routine 00445 * 00446 * @param temperature temperature (kelvin) 00447 * @param pressure pressure (Pascal) 00448 * @param densLiq Output density of liquid 00449 * @param densGas output Density of gas 00450 * @param pcorr output corrected pressure 00451 */ 00452 void corr1(doublereal temperature, doublereal pressure, doublereal &densLiq, 00453 doublereal &densGas, doublereal &pcorr); 00454 00455 private: 00456 00457 //! pointer to the underlying object that does the calculations. 00458 WaterPropsIAPWSphi *m_phi; 00459 00460 //! Dimensionless temperature 00461 /*! 00462 * tau = T_C / T 00463 */ 00464 doublereal tau; 00465 00466 //! Dimensionless density 00467 /*! 00468 * delta = rho / rho_c 00469 */ 00470 mutable doublereal delta; 00471 00472 //! Current state of the system 00473 mutable int iState; 00474 }; 00475 00476 } 00477 #endif