WaterProps.cpp

Go to the documentation of this file.
00001 /**
00002  *  @file WaterProps.cpp
00003  */
00004 /*
00005  * Copywrite (2006) Sandia Corporation. Under the terms of
00006  * Contract DE-AC04-94AL85000 with Sandia Corporation, the
00007  * U.S. Government retains certain rights in this software.
00008  */
00009 /*
00010  * $Id: WaterProps.cpp 387 2010-01-17 18:17:55Z hkmoffa $
00011  */
00012 
00013 //@{
00014 #ifndef MAX
00015 #define MAX(x,y)    (( (x) > (y) ) ? (x) : (y))
00016 #endif
00017 //@}
00018 
00019 #include "WaterProps.h"
00020 #include "ctml.h"
00021 #include "PDSS_Water.h"
00022 #include "WaterPropsIAPWS.h"
00023 
00024 #include <cmath>
00025 
00026 namespace Cantera {
00027 
00028 
00029   /*
00030    * default constructor -> object owns its own water evaluator
00031    */
00032   WaterProps::WaterProps():
00033     m_waterIAPWS(0),
00034     m_own_sub(false)
00035   {
00036     m_waterIAPWS = new WaterPropsIAPWS();
00037     m_own_sub = true;
00038   }
00039 
00040   /*
00041    * constructor -> object in slave mode, It doesn't own its
00042    *      own water evaluator.
00043    */
00044   WaterProps::WaterProps(PDSS_Water *wptr)  :
00045     m_waterIAPWS(0),
00046     m_own_sub(false)
00047   {
00048     if (wptr) {
00049       m_waterIAPWS = wptr->getWater();
00050       m_own_sub = false;
00051     } else {
00052       m_waterIAPWS = new WaterPropsIAPWS();
00053       m_own_sub = true;
00054     }
00055   }
00056 
00057   WaterProps::WaterProps(WaterPropsIAPWS *waterIAPWS)  :
00058     m_waterIAPWS(0),
00059     m_own_sub(false)
00060   {
00061     if (waterIAPWS) {
00062       m_waterIAPWS = waterIAPWS;
00063       m_own_sub = false;
00064     } else {
00065       m_waterIAPWS = new WaterPropsIAPWS();
00066       m_own_sub = true;
00067     }
00068   }
00069 
00070   /**
00071    * Copy constructor
00072    */
00073   WaterProps::WaterProps(const WaterProps &b)  :
00074     m_waterIAPWS(0),
00075     m_own_sub(false)
00076   {
00077     *this = b;
00078   }
00079 
00080   /**
00081    * Destructor
00082    */
00083   WaterProps::~WaterProps() {
00084     if (m_own_sub) {
00085       delete m_waterIAPWS;
00086     }
00087   }
00088 
00089   /**
00090    * Assignment operator
00091    */
00092   WaterProps& WaterProps::operator=(const WaterProps&b) {
00093     if (&b == this) return *this;
00094    
00095     if (m_own_sub) {
00096       if (m_waterIAPWS) {
00097         delete m_waterIAPWS;
00098         m_waterIAPWS = 0;
00099       }
00100     }
00101     if (b.m_own_sub) {
00102       m_waterIAPWS = new WaterPropsIAPWS();
00103       m_own_sub = true;
00104     } else {
00105       m_waterIAPWS = b.m_waterIAPWS;
00106       m_own_sub = false;
00107     }
00108 
00109     return *this;
00110   }
00111   
00112   // Simple calculation of water density at atmospheric pressure.
00113   // Valid up to boiling point.
00114   /*
00115    * This formulation has no dependence on the pressure and shouldn't
00116    * be used where accuracy is needed.
00117    *
00118    * @param T temperature in kelvin
00119    * @param P Pressure in pascal
00120    * @param ifunc changes what's returned
00121    *
00122    * @return value returned depends on ifunc value:
00123    * ifunc = 0 Returns the density in kg/m^3
00124    * ifunc = 1 returns the derivative of the density wrt T.
00125    * ifunc = 2 returns the 2nd derivative of the density wrt T 
00126    * ifunc = 3 returns the derivative of the density wrt P.
00127    *
00128    * Verification:
00129    *   Agrees with the CRC values (6-10) for up to 4 sig digits.
00130    *
00131    * units = returns density in kg m-3.
00132    */
00133   doublereal WaterProps::density_T(doublereal T, doublereal P, int ifunc) {
00134     doublereal Tc = T - 273.15;
00135     const doublereal U1 = 288.9414;
00136     const doublereal U2 = 508929.2;
00137     const doublereal U3 = 68.12963;
00138     const doublereal U4 = -3.9863;
00139     
00140     doublereal tmp1 = Tc + U1;
00141     doublereal tmp4 = Tc + U4;
00142     doublereal t4t4 = tmp4 * tmp4;
00143     doublereal tmp3 = Tc + U3;
00144     doublereal rho = 1000. * (1.0 - tmp1*t4t4/(U2 * tmp3));
00145 
00146     /*
00147      * Impose an ideal gas lower bound on rho. We need this
00148      * to ensure positivity of rho, even though it is
00149      * grossly unrepresentative.
00150      */
00151     doublereal rhomin = P / (GasConstant * T);
00152     if (rho < rhomin) {
00153       rho = rhomin;
00154       if (ifunc == 1) {
00155         doublereal drhodT = - rhomin / T;
00156         return drhodT;
00157       } else if (ifunc == 3) {
00158         doublereal drhodP = rhomin / P;
00159         return drhodP;
00160       } else if (ifunc == 2) {
00161         doublereal d2rhodT2 = 2.0 * rhomin / (T * T);
00162         return d2rhodT2;
00163       }
00164     }
00165     
00166     if (ifunc == 1) {
00167       doublereal drhodT = 1000./U2 * (
00168                                   - tmp4 * tmp4 / (tmp3)
00169                                   - tmp1 * 2 * tmp4 / (tmp3)
00170                                   + tmp1 * t4t4 / (tmp3*tmp3)
00171                                   );
00172       return drhodT;
00173     } else if (ifunc == 3) {
00174       return 0.0;
00175     } else if (ifunc == 2) {
00176       doublereal t3t3 = tmp3 * tmp3;
00177       doublereal d2rhodT2 =  1000./U2 * 
00178         ((-4.0*tmp4-2.0*tmp1)/tmp3 +
00179          (2.0*t4t4 + 4.0*tmp1*tmp4)/t3t3 
00180          - 2.0*tmp1 * t4t4/(t3t3*tmp3));
00181       return d2rhodT2;
00182     }
00183         
00184     return rho;
00185   }
00186 
00187   //  Bradley-Pitzer equation for the dielectric constant 
00188   //  of water as a function of temperature and pressure.
00189   /*!
00190    *  Returns the dimensionless relative dielectric constant
00191    *  and its derivatives.
00192    * 
00193    *  ifunc = 0 value
00194    *  ifunc = 1 Temperature deriviative
00195    *  ifunc = 2 second temperature derivative
00196    *  ifunc = 3 return pressure first derivative
00197    *
00198    * Range of validity 0 to 350C, 0 to 1 kbar pressure
00199    *
00200    * @param T temperature (kelvin)
00201    * @param P_pascal pressure in pascal
00202    * @param ifunc changes what's returned from the function
00203    *
00204    * @return Depends on the value of ifunc:
00205    * ifunc = 0 return value
00206    * ifunc = 1 return temperature derivative
00207    * ifunc = 2 return second temperature derivative
00208    * ifunc = 3 return pressure first derivative
00209    *
00210    *  Validation:
00211    *   Numerical experiments indicate that this function agrees with
00212    *   the Archer and Wang data in the CRC p. 6-10 to all 4 significant
00213    *   digits shown (0 to 100C).
00214    * 
00215    *   value at 25C, relEps = 78.38
00216    * 
00217    */
00218   doublereal WaterProps::relEpsilon(doublereal T, doublereal P_pascal, 
00219                                 int ifunc) {
00220     const doublereal U1 = 3.4279E2;
00221     const doublereal U2 = -5.0866E-3;
00222     const doublereal U3 = 9.4690E-7;
00223     const doublereal U4 = -2.0525;
00224     const doublereal U5 = 3.1159E3;
00225     const doublereal U6 = -1.8289E2;
00226     const doublereal U7 = -8.0325E3;
00227     const doublereal U8 = 4.2142E6;
00228     const doublereal U9 = 2.1417;
00229     doublereal T2 = T * T;
00230 
00231     doublereal eps1000 = U1 * exp(U2 * T + U3 * T2);
00232     doublereal C = U4 + U5/(U6 + T);
00233     doublereal B = U7 + U8/T + U9 * T;
00234 
00235     doublereal Pbar = P_pascal * 1.0E-5;
00236     doublereal tmpBpar = B + Pbar;
00237     doublereal tmpB1000 = B + 1000.0;
00238     doublereal ltmp =  log(tmpBpar/tmpB1000);
00239     doublereal epsRel = eps1000 + C * ltmp;
00240 
00241     if (ifunc == 1 || ifunc == 2) {
00242       doublereal tmpC = U6 + T;
00243       doublereal dCdT = - U5/(tmpC * tmpC);
00244 
00245       doublereal dBdT = - U8/(T * T) + U9;
00246 
00247       doublereal deps1000dT = eps1000 * (U2 + 2.0 * U3 * T);
00248 
00249       doublereal dltmpdT = (dBdT/tmpBpar - dBdT/tmpB1000);
00250       if (ifunc == 1) {
00251         doublereal depsReldT = deps1000dT + dCdT * ltmp + C * dltmpdT;
00252         return depsReldT;
00253       }
00254       doublereal T3     = T2 * T;
00255       doublereal d2CdT2 = - 2.0 * dCdT / tmpC;
00256       doublereal d2BdT2 =   2.0 * U8 / (T3);
00257 
00258       doublereal d2ltmpdT2 = (d2BdT2*(1.0/tmpBpar - 1.0/tmpB1000) +
00259                           dBdT*dBdT*(1.0/(tmpB1000*tmpB1000) - 1.0/(tmpBpar*tmpBpar)));
00260 
00261       doublereal d2eps1000dT2 =  (deps1000dT * (U2 + 2.0 * U3 * T) + eps1000  * (2.0 * U3));
00262 
00263       if (ifunc == 2) {
00264         doublereal d2epsReldT2 = (d2eps1000dT2 + d2CdT2 * ltmp + 2.0 * dCdT * dltmpdT
00265                               + C * d2ltmpdT2);
00266         return d2epsReldT2;
00267       }
00268     }
00269     if (ifunc == 3) {
00270       doublereal dltmpdP   = 1.0E-5 / tmpBpar; 
00271       doublereal depsReldP = C * dltmpdP;
00272       return depsReldP;
00273     }
00274 
00275     return epsRel;
00276   }
00277 
00278   /*
00279    * ADebye calculates the value of A_Debye as a function
00280    * of temperature and pressure according to relations
00281    * that take into account the temperature and pressure
00282    * dependence of the water density and dieletric constant.
00283    *
00284    * A_Debye -> this expression appears on the top of the
00285    *            ln actCoeff term in the general Debye-Huckel
00286    *            expression
00287    *            It depends on temperature. And, therefore,
00288    *            most be recalculated whenever T or P changes.
00289    *            
00290    *            A_Debye = (1/(8 Pi)) sqrt(2 Na dw / 1000) 
00291    *                          (e e/(epsilon R T))^3/2
00292    *
00293    *            Units = sqrt(kg/gmol) ~ sqrt(1/I)
00294    *
00295    *            Nominal value = 1.172576 sqrt(kg/gmol)
00296    *                  based on:
00297    *                    epsilon/epsilon_0 = 78.54
00298    *                           (water at 25C)
00299    *                    epsilon_0 = 8.854187817E-12 C2 N-1 m-2
00300    *                    e = 1.60217653E-19 C
00301    *                    F = 9.6485309E7 C kmol-1
00302    *                    R = 8.314472E3 kg m2 s-2 kmol-1 K-1
00303    *                    T = 298.15 K
00304    *                    B_Debye = 3.28640E9 sqrt(kg/gmol)/m
00305    *                    Na = 6.0221415E26
00306    *
00307    * ifunc = 0 return value
00308    * ifunc = 1 return temperature derivative
00309    * ifunc = 2 return temperature second derivative
00310    * ifunc = 3 return pressure first derivative
00311    *
00312    *  Verification:
00313    *    With the epsRelWater value from the BP relation,
00314    *    and the water density from the WaterDens function,
00315    *    The A_Debye computed with this function agrees with
00316    *    the Pitzer table p. 99 to 4 significant digits at 25C.
00317    *    and 20C. (Aphi = ADebye/3)
00318    * 
00319    * (statically defined within the object)
00320    */
00321   doublereal WaterProps::ADebye(doublereal T, doublereal P_input, int ifunc) {
00322     const doublereal e =  1.60217653E-19;
00323     const doublereal epsilon0 =  8.854187817E-12;
00324     const doublereal R = 8.314472E3;
00325     doublereal psat = satPressure(T);
00326     doublereal P;
00327     if (psat > P_input) {
00328       //printf("ADebye WARNING: p_input < psat: %g %g\n",
00329       // P_input, psat);
00330       P = psat;
00331     } else {
00332       P = P_input;
00333     }
00334     doublereal epsRelWater = relEpsilon(T, P, 0);
00335     //printf("releps calc = %g, compare to 78.38\n", epsRelWater);
00336     //doublereal B_Debye = 3.28640E9;
00337     const doublereal Na = 6.0221415E26;
00338 
00339     doublereal epsilon = epsilon0 * epsRelWater;
00340     doublereal dw = density_IAPWS(T, P);
00341     doublereal tmp = sqrt( 2.0 * Na * dw / 1000.);
00342     doublereal tmp2 = e * e * Na / (epsilon * R * T);
00343     doublereal tmp3 = tmp2 * sqrt(tmp2);
00344     doublereal A_Debye = tmp * tmp3 / (8.0 * Pi);
00345 
00346 
00347     /*
00348      *  dAdT = - 3/2 Ad/T + 1/2 Ad/dw d(dw)/dT - 3/2 Ad/eps d(eps)/dT
00349      *
00350      *  dAdT = - 3/2 Ad/T - 1/2 Ad/Vw d(Vw)/dT - 3/2 Ad/eps d(eps)/dT
00351      */
00352     if (ifunc == 1 || ifunc == 2) {
00353       doublereal dAdT = - 1.5 * A_Debye / T;
00354 
00355       doublereal depsRelWaterdT = relEpsilon(T, P, 1);
00356       dAdT -= A_Debye * (1.5 * depsRelWaterdT / epsRelWater);
00357 
00358       //int methodD = 1;
00359       //doublereal ddwdT = density_T_new(T, P, 1);
00360       // doublereal contrib1 = A_Debye * (0.5 * ddwdT / dw);
00361          
00362       /*
00363        * calculate d(lnV)/dT _constantP, i.e., the cte
00364        */
00365       doublereal cte = coeffThermalExp_IAPWS(T, P);
00366       doublereal contrib2 =  - A_Debye * (0.5 * cte);
00367 
00368       //dAdT += A_Debye * (0.5 * ddwdT / dw);
00369       dAdT += contrib2;
00370 
00371 #ifdef DEBUG_HKM
00372       //printf("dAdT = %g, contrib1 = %g, contrib2 = %g\n", 
00373       //         dAdT, contrib1, contrib2);
00374 #endif
00375  
00376       if (ifunc == 1) {
00377         return dAdT;
00378       }
00379 
00380       if (ifunc == 2) {
00381         /*
00382          * Get the second derivative of the dielectric constant wrt T
00383          * -> we will take each of the terms in dAdT and differentiate
00384          *    it again.
00385          */
00386         doublereal d2AdT2 = 1.5 / T * (A_Debye/T - dAdT);
00387 
00388         doublereal d2epsRelWaterdT2 = relEpsilon(T, P, 2);
00389 
00390         //doublereal dT = -0.01;
00391         //doublereal TT = T + dT;
00392         //doublereal depsRelWaterdTdel = relEpsilon(TT, P, 1);
00393         //doublereal d2alt = (depsRelWaterdTdel- depsRelWaterdT ) / dT;
00394         //printf("diff %g %g\n",d2epsRelWaterdT2, d2alt); 
00395         // HKM -> checks out, i.e., they are the same.
00396 
00397         d2AdT2 += 1.5 * (- dAdT * depsRelWaterdT / epsRelWater 
00398                          - A_Debye / epsRelWater * 
00399                          (d2epsRelWaterdT2 - depsRelWaterdT * depsRelWaterdT / epsRelWater));
00400             
00401         doublereal deltaT = -0.1;
00402         doublereal Tdel = T + deltaT;
00403         doublereal cte_del =  coeffThermalExp_IAPWS(Tdel, P);
00404         doublereal dctedT = (cte_del - cte) / Tdel;
00405             
00406            
00407         //doublereal d2dwdT2 = density_T_new(T, P, 2);
00408 
00409         doublereal contrib3 = 0.5 * ( -(dAdT * cte) -(A_Debye * dctedT));
00410         d2AdT2 += contrib3;
00411 
00412         return d2AdT2;
00413       }
00414     }
00415     /*
00416      *  A_Debye = (1/(8 Pi)) sqrt(2 Na dw / 1000) 
00417      *                          (e e/(epsilon R T))^3/2
00418      *
00419      *  dAdP =  + 1/2 Ad/dw d(dw)/dP - 3/2 Ad/eps d(eps)/dP
00420      *
00421      *  dAdP =  - 1/2 Ad/Vw d(Vw)/dP - 3/2 Ad/eps d(eps)/dP
00422      *
00423      *  dAdP =  + 1/2 Ad * kappa  - 3/2 Ad/eps d(eps)/dP
00424      *
00425      *  where kappa = - 1/Vw d(Vw)/dP_T (isothermal compressibility)
00426      */
00427     if (ifunc == 3) {
00428           
00429       doublereal dAdP = 0.0;
00430           
00431       doublereal depsRelWaterdP = relEpsilon(T, P, 3);
00432       dAdP -=  A_Debye * (1.5 * depsRelWaterdP / epsRelWater);
00433           
00434       doublereal kappa = isothermalCompressibility_IAPWS(T,P);
00435 
00436       //doublereal ddwdP = density_T_new(T, P, 3);
00437       dAdP += A_Debye * (0.5 * kappa);
00438 
00439       return dAdP;
00440     }
00441 
00442     return A_Debye;
00443   }
00444 
00445   doublereal WaterProps::satPressure(doublereal T) {
00446     doublereal pres = m_waterIAPWS->psat(T);
00447     return pres;
00448   }
00449  
00450   // Returns the density of water
00451   /*
00452    * This function sets the internal temperature and pressure
00453    * of the underlying object at the same time.
00454    *
00455    * @param T Temperature (kelvin)
00456    * @param P pressure (pascal)
00457    */
00458   doublereal WaterProps::density_IAPWS(doublereal temp, doublereal press) {
00459     doublereal dens = m_waterIAPWS->density(temp, press, WATER_LIQUID);
00460     return dens;
00461   }
00462 
00463   // Returns the density of water
00464   /*
00465    *  This function uses the internal state of the
00466    *  underlying water object
00467    */
00468   doublereal WaterProps::density_IAPWS() const {
00469     doublereal dens = m_waterIAPWS->density();
00470     return dens;
00471   }
00472 
00473   doublereal WaterProps::coeffThermalExp_IAPWS(doublereal temp, doublereal press) {
00474     doublereal dens = m_waterIAPWS->density(temp, press, WATER_LIQUID);
00475     if (dens < 0.0) {
00476       throw CanteraError("WaterProps::coeffThermalExp_IAPWS", 
00477                          "Unable to solve for density at T = " + fp2str(temp) + " and P = " + fp2str(press));
00478     }
00479     doublereal cte = m_waterIAPWS->coeffThermExp();
00480     return cte;
00481   }
00482 
00483   doublereal WaterProps::isothermalCompressibility_IAPWS(doublereal temp, doublereal press) {
00484     doublereal dens = m_waterIAPWS->density(temp, press, WATER_LIQUID);
00485     if (dens < 0.0) {
00486       throw CanteraError("WaterProps::isothermalCompressibility_IAPWS", 
00487                          "Unable to solve for density at T = " + fp2str(temp) + " and P = " + fp2str(press));
00488     }
00489     doublereal kappa = m_waterIAPWS->isothermalCompressibility();
00490     return kappa;
00491   }
00492 
00493 
00494 
00495 
00496 
00497   // Parameters for the viscosityWater() function
00498 
00499   //@{
00500   const doublereal H[4] = {1.,
00501                        0.978197,
00502                        0.579829,
00503                        -0.202354};
00504   //! parameter
00505   const doublereal Hij[6][7] =
00506     {
00507       { 0.5132047, 0.2151778, -0.2818107,  0.1778064, -0.04176610,          0.,           0.},
00508       { 0.3205656, 0.7317883, -1.070786 ,  0.4605040,          0., -0.01578386,           0.},
00509       { 0.,        1.241044 , -1.263184 ,  0.2340379,          0.,          0.,           0.},
00510       { 0.,        1.476783 ,         0., -0.4924179,   0.1600435,          0., -0.003629481},
00511       {-0.7782567,      0.0 ,         0.,  0.       ,          0.,          0.,           0.},
00512       { 0.1885447,      0.0 ,         0.,  0.       ,          0.,          0.,           0.},
00513     };
00514   const doublereal TStar = 647.27;       // Kelvin
00515   const doublereal rhoStar = 317.763;    // kg / m3
00516   const doublereal presStar = 22.115E6;  // Pa
00517   const doublereal muStar = 55.071E-6;   //Pa s
00518   //@}
00519 
00520   // Returns the viscosity of water at the current conditions
00521   // (kg/m/s)
00522   /*
00523    *  This function calculates the value of the viscosity of pure
00524    *  water at the current T and P.
00525    *
00526    *  The formulas used are from the paper
00527    *
00528    *     J. V. Sengers, J. T. R. Watson, "Improved International
00529    *     Formulations for the Viscosity and Thermal Conductivity of
00530    *     Water Substance", J. Phys. Chem. Ref. Data, 15, 1291 (1986).
00531    *
00532    *  The formulation is accurate for all temperatures and pressures,
00533    *  for steam and for water, even near the critical point.
00534    *  Pressures above 500 MPa and temperature above 900 C are suspect.
00535    */
00536   doublereal WaterProps::viscosityWater() const {
00537 
00538     doublereal temp = m_waterIAPWS->temperature();
00539     doublereal dens = m_waterIAPWS->density();
00540 
00541     //WaterPropsIAPWS *waterP = new WaterPropsIAPWS();
00542     //m_waterIAPWS->setState_TR(temp, dens);
00543     //doublereal pressure = m_waterIAPWS->pressure();
00544     //printf("pressure = %g\n", pressure);
00545     //dens = 18.02 * pressure / (GasConstant * temp);
00546     //printf ("mod dens = %g\n", dens);
00547 
00548     doublereal rhobar = dens/rhoStar;
00549     doublereal tbar = temp / TStar;
00550     // doublereal pbar = pressure / presStar;  
00551 
00552     doublereal tbar2 = tbar * tbar;
00553     doublereal tbar3 = tbar2 * tbar;
00554 
00555     doublereal mu0bar = std::sqrt(tbar) / (H[0] + H[1]/tbar + H[2]/tbar2 + H[3]/tbar3);
00556 
00557     //printf("mu0bar = %g\n", mu0bar);
00558     //printf("mu0 = %g\n", mu0bar * muStar);
00559  
00560     doublereal tfac1 = 1.0 / tbar - 1.0;
00561     doublereal tfac2 = tfac1 * tfac1;
00562     doublereal tfac3 = tfac2 * tfac1;
00563     doublereal tfac4 = tfac3 * tfac1;
00564     doublereal tfac5 = tfac4 * tfac1;
00565 
00566     doublereal rfac1 = rhobar - 1.0;
00567     doublereal rfac2 = rfac1 * rfac1;
00568     doublereal rfac3 = rfac2 * rfac1;
00569     doublereal rfac4 = rfac3 * rfac1;
00570     doublereal rfac5 = rfac4 * rfac1;
00571     doublereal rfac6 = rfac5 * rfac1;
00572 
00573     doublereal sum = (Hij[0][0]       + Hij[1][0]*tfac1       + Hij[4][0]*tfac4       + Hij[5][0]*tfac5 +
00574                   Hij[0][1]*rfac1 + Hij[1][1]*tfac1*rfac1 + Hij[2][1]*tfac2*rfac1 + Hij[3][1]*tfac3*rfac1 +
00575                   Hij[0][2]*rfac2 + Hij[1][2]*tfac1*rfac2 + Hij[2][2]*tfac2*rfac2 +
00576                   Hij[0][3]*rfac3 + Hij[1][3]*tfac1*rfac3 + Hij[2][3]*tfac2*rfac3 + Hij[3][3]*tfac3*rfac3 +
00577                   Hij[0][4]*rfac4 + Hij[3][4]*tfac3*rfac4 + 
00578                   Hij[1][5]*tfac1*rfac5 + Hij[3][6]*tfac3*rfac6 
00579                   );
00580     doublereal mu1bar = std::exp(rhobar * sum);
00581 
00582     // Apply the near-critical point corrections if necessary
00583     doublereal mu2bar = 1.0;
00584     if ((tbar >= 0.9970) && tbar <= 1.0082) {
00585       if ((rhobar >= 0.755) && (rhobar <= 1.290)) {
00586         doublereal drhodp =  1.0 / m_waterIAPWS->dpdrho();
00587         drhodp *= presStar / rhoStar;
00588         doublereal xsi = rhobar * drhodp;
00589         if (xsi >= 21.93) {
00590           mu2bar = 0.922 * std::pow(xsi, 0.0263);
00591         }
00592       }
00593     }
00594 
00595     doublereal mubar = mu0bar * mu1bar * mu2bar;
00596 
00597     return mubar * muStar;
00598   }
00599 
00600   //! Returns the thermal conductivity of water at the current conditions
00601   //! (W/m/K)
00602   /*!
00603    *  This function calculates the value of the thermal conductivity of
00604    *  water at the current T and P.
00605    *
00606    *  The formulas used are from the paper
00607    *     J. V. Sengers, J. T. R. Watson, "Improved International
00608    *     Formulations for the Viscosity and Thermal Conductivity of
00609    *     Water Substance", J. Phys. Chem. Ref. Data, 15, 1291 (1986).
00610    *
00611    *  The formulation is accurate for all temperatures and pressures,
00612    *  for steam and for water, even near the critical point.
00613    *  Pressures above 500 MPa and temperature above 900 C are suspect.
00614    */
00615   doublereal WaterProps::thermalConductivityWater() const {
00616     static const doublereal Tstar = 647.27;
00617     static const doublereal rhostar = 317.763;
00618     static const doublereal lambdastar = 0.4945;
00619     static const doublereal presstar = 22.115E6;
00620     static const doublereal L[4] = 
00621       {
00622         1.0000,
00623         6.978267,
00624         2.599096,
00625         -0.998254
00626       };
00627     static const doublereal Lji[6][5] = 
00628       {
00629         { 1.3293046,    1.7018363,   5.2246158,   8.7127675, -1.8525999},
00630         {-0.40452437,  -2.2156845, -10.124111,   -9.5000611,  0.93404690},
00631         { 0.24409490,   1.6511057,   4.9874687,   4.3786606,  0.0},
00632         { 0.018660751, -0.76736002, -0.27297694, -0.91783782, 0.0},
00633         {-0.12961068,   0.37283344, -0.43083393,  0.0,        0.0},
00634         { 0.044809953, -0.11203160,  0.13333849,  0.0,        0.0},
00635       };
00636 
00637     doublereal temp = m_waterIAPWS->temperature();
00638     doublereal dens = m_waterIAPWS->density();
00639 
00640     doublereal rhobar = dens/rhostar;
00641     doublereal tbar = temp / Tstar;
00642     doublereal tbar2 = tbar * tbar;
00643     doublereal tbar3 = tbar2 * tbar;
00644     doublereal lambda0bar = sqrt(tbar) / (L[0] + L[1]/tbar + L[2]/tbar2 + L[3]/tbar3);
00645 
00646     //doublereal lambdagas = lambda0bar * lambdastar * 1.0E3;
00647 
00648     doublereal tfac1 = 1.0 / tbar - 1.0;
00649     doublereal tfac2 = tfac1 * tfac1;
00650     doublereal tfac3 = tfac2 * tfac1;
00651     doublereal tfac4 = tfac3 * tfac1;
00652 
00653     doublereal rfac1 = rhobar - 1.0;
00654     doublereal rfac2 = rfac1 * rfac1;
00655     doublereal rfac3 = rfac2 * rfac1;
00656     doublereal rfac4 = rfac3 * rfac1;
00657     doublereal rfac5 = rfac4 * rfac1;
00658 
00659     doublereal sum = (Lji[0][0]       + Lji[0][1]*tfac1        + Lji[0][2]*tfac2       + Lji[0][3]*tfac3       + Lji[0][4]*tfac4       + 
00660                   Lji[1][0]*rfac1 + Lji[1][1]*tfac1*rfac1  + Lji[1][2]*tfac2*rfac1 + Lji[1][3]*tfac3*rfac1 + Lji[1][4]*tfac4*rfac1 +
00661                   Lji[2][0]*rfac2 + Lji[2][1]*tfac1*rfac2  + Lji[2][2]*tfac2*rfac2 + Lji[2][3]*tfac3*rfac2 +
00662                   Lji[3][0]*rfac3 + Lji[3][1]*tfac1*rfac3  + Lji[3][2]*tfac2*rfac3 + Lji[3][3]*tfac3*rfac3 +
00663                   Lji[4][0]*rfac4 + Lji[4][1]*tfac1*rfac4  + Lji[4][2]*tfac2*rfac4 +
00664                   Lji[5][0]*rfac5 + Lji[5][1]*tfac1*rfac5  + Lji[5][2]*tfac2*rfac5 
00665                   );
00666     doublereal  lambda1bar = exp(rhobar * sum);
00667 
00668     doublereal mu0bar = std::sqrt(tbar) / (H[0] + H[1]/tbar + H[2]/tbar2 + H[3]/tbar3);
00669 
00670     doublereal tfac5 = tfac4 * tfac1;    
00671     doublereal rfac6 = rfac5 * rfac1;
00672 
00673     sum = (Hij[0][0]       + Hij[1][0]*tfac1       + Hij[4][0]*tfac4       + Hij[5][0]*tfac5 +
00674            Hij[0][1]*rfac1 + Hij[1][1]*tfac1*rfac1 + Hij[2][1]*tfac2*rfac1 + Hij[3][1]*tfac3*rfac1 +
00675            Hij[0][2]*rfac2 + Hij[1][2]*tfac1*rfac2 + Hij[2][2]*tfac2*rfac2 +
00676            Hij[0][3]*rfac3 + Hij[1][3]*tfac1*rfac3 + Hij[2][3]*tfac2*rfac3 + Hij[3][3]*tfac3*rfac3 +
00677            Hij[0][4]*rfac4 + Hij[3][4]*tfac3*rfac4 + 
00678            Hij[1][5]*tfac1*rfac5 + Hij[3][6]*tfac3*rfac6 
00679            );
00680     doublereal mu1bar = std::exp(rhobar * sum);
00681 
00682     doublereal t2r2 = tbar * tbar / (rhobar * rhobar);
00683     doublereal drhodp =  1.0 / m_waterIAPWS->dpdrho();
00684     drhodp *= presStar / rhoStar;
00685     doublereal xsi = rhobar * drhodp;
00686     doublereal xsipow = std::pow(xsi, 0.4678);
00687     doublereal rho1 = rhobar - 1.;
00688     doublereal rho2 = rho1 * rho1;
00689     doublereal rho4 = rho2 * rho2;
00690     doublereal temp2 = (tbar - 1.0) * (tbar - 1.0);
00691 
00692     /*
00693      *     beta = M / (rho * Rgas) (d (pressure) / dT) at constant rho
00694      *
00695      *  Note for ideal gases this is equal to one.
00696      *
00697      *    beta = delta (phi0_d() + phiR_d())
00698      *            - tau delta (phi0_dt() + phiR_dt())
00699      */
00700     doublereal beta = m_waterIAPWS->coeffPresExp();
00701 
00702     doublereal dpdT_const_rho = beta * GasConstant * dens / 18.015268;
00703     dpdT_const_rho *= Tstar /  presstar;
00704 
00705     doublereal  lambda2bar = 0.0013848 / (mu0bar * mu1bar) * t2r2 * dpdT_const_rho * dpdT_const_rho *
00706       xsipow * sqrt(rhobar) * exp(-18.66*temp2 - rho4);
00707 
00708     doublereal lambda = ( lambda0bar * lambda1bar + lambda2bar) * lambdastar;
00709     return lambda;
00710   }
00711 
00712 
00713 }
Generated by  doxygen 1.6.3