00001 #ifndef FLASHESSENTIAL_H
00002 #define FLASHESSENTIAL_H
00003
00004
00005 #include <cmath>
00006
00007
00008 #include "newtonraphson.h"
00009 #include <assert.h>
00010 namespace Flash
00011 {
00012
00013
00014
00015
00016
00017 enum PhysicalState { LIQUID, GAS, SUPERCRITICAL };
00018
00019
00020
00021
00022
00023
00024
00025 const double TcH2O = 647.30;
00026 const double PcH2O = 221.20;
00027
00028
00029 const double TcCO2 = 304.20;
00030 const double PcCO2 = 73.83;
00031
00032
00033 const double TcH2S = 373.50;
00034 const double PcH2S = 89.63;
00035
00036
00037
00038
00039
00040
00041 const double R = 83.14472;
00042
00043
00044
00045
00046
00047
00048
00049 inline double aCO2(double T) { return 7.54E7 - 4.13E4 * T; };
00050 const double bCO2 = 27.80;
00051 const double bH2O = 18.18;
00052 const double aH2OCO2 = 7.89E7;
00053
00054
00055 const double a1H2S = 5.2386075E-2;
00056 const double a2H2S = -2.7463906E-1;
00057 const double a3H2S = -9.6760173E-2;
00058 const double a4H2S = 1.3618104E-2;
00059 const double a5H2S = -8.8681753E-2;
00060 const double a6H2S = 4.1176908E-2;
00061 const double a7H2S = 3.6354018E-4;
00062 const double a8H2S = 2.2719194E-3;
00063 const double a9H2S = -7.6962514E-4;
00064 const double a10H2S = -2.1948579E-5;
00065 const double a11H2S = -1.1707631E-4;
00066 const double a12H2S = 4.0756926E-5;
00067 const double a13H2S = 5.7582260E-2;
00068 const double a14H2S = 1.00;
00069 const double a15H2S = 0.06;
00070
00071
00072 inline double koH2O(double T)
00073 {
00074 T = T - 273.15;
00075 return std::pow(10.0, -2.209 + 3.097E-2 * T - 1.098E-4 * T*T + 2.048E-7 * T*T*T);
00076 }
00077
00078 inline double koCO2(double T, PhysicalState stateCO2)
00079 {
00080 T = T - 273.15;
00081 return (stateCO2 == GAS || stateCO2 == SUPERCRITICAL) ?
00082 std::pow(10.0, 1.189 + 1.304E-2 * T - 5.446E-5 * T*T) :
00083 std::pow(10.0, 1.169 + 1.368E-2 * T - 5.380E-5 * T*T);
00084 }
00085
00086
00087 const double Po = 1.0;
00088
00089
00090 const double vH2O = 18.1;
00091 inline double vCO2(PhysicalState stateCO2) { return (stateCO2 == GAS || stateCO2 == SUPERCRITICAL) ? 32.6 : 32.0; }
00092
00093
00094 inline double lambdaCO2(double T, double P)
00095 {
00096 return -0.411370585 + 6.07632013E-4 * T + 97.5347708/T - 0.0237622469 * P/T + 0.0170656236 * P/(630.0 - T) + 1.41335834E-5 * T * std::log(P);
00097 }
00098
00099 inline double zetaCO2(double T, double P)
00100 {
00101 return 3.36389723E-4 - 1.98298980E-5 * T + 2.12220830E-3 * P/T - 5.24873303E-3 * P/(630.0 - T);
00102 }
00103
00104
00105 inline double uRTH2S(double T, double P)
00106 {
00107 return 42.564957 - 8.6260377E-2 * T - 6084.3775/T + 6.8714437E-5 * (T*T) - 102.76849/(680 - T) + 8.4482895E-4 * P - 1.0590768 * P/(680 - T) + 3.5665902E-3 * (P*P)/T;
00108 }
00109
00110 inline double lambdaH2S(double T, double P)
00111 {
00112 return 8.5004999E-2 + 3.5330378E-5 * T - 1.5882605/T + 1.1894926E-5 * P;
00113 }
00114
00115 const double zetaH2S = -1.0832589E-2;
00116
00117
00118
00119
00120
00121
00122
00123 inline double ComputeSaturatedMolalityNaCl(double T, double P) { return std::exp( 2.86623 - 571.361/T + 77128/(T*T) + 4.0479E-4 * P - 7.445E-7 * (P*P) + 6.209E-10 * (P*P*P) ); }
00124
00125
00126
00127
00128
00129
00130
00131 inline double ComputeSaturatedPressureH2O(double T)
00132 {
00133 double x = 1.0 - T/TcH2O;
00134 return PcH2O * std::exp(1.0/(1 - x) * (-7.76451 * x + 1.45838 * std::pow(x, 1.5) - 2.77580 * std::pow(x, 3) - 1.23303 * std::pow(x, 6)));
00135 }
00136
00137
00138 inline double ComputeSaturatedPressureCO2(double T)
00139 {
00140 double x = 1.0 - T/TcCO2;
00141 return PcCO2 * std::exp(1.0/(1 - x) * (-6.95626 * x + 1.19695 * std::pow(x, 1.5) - 3.12614 * std::pow(x, 3) + 2.99448 * std::pow(x, 6)));
00142 }
00143
00144
00145 struct SaturatedPressureH2SEquation
00146 {
00147 double T;
00148 double operator()(double Psat) { return 36.067 - 3132.31/T - 3.985 * std::log(T) + 653.0 * Psat/(T*T) - std::log(Psat); }
00149 };
00150
00151
00152 inline double ComputeSaturatedPressureH2S(double T)
00153 {
00154
00155 double Psat0 = 20.0;
00156
00157 static SaturatedPressureH2SEquation equation;
00158
00159 equation.T = T;
00160
00161 return NewtonRaphson(equation, Psat0);
00162 }
00163
00164
00165
00166
00167
00168
00169
00170 inline PhysicalState DeterminePhysicalStateCO2(double T, double P)
00171 {
00172 return (T < TcCO2) ? ( (P > ComputeSaturatedPressureCO2(T)) ? LIQUID : GAS ) : ( (P > PcCO2) ? SUPERCRITICAL : GAS );
00173 }
00174
00175
00176 inline PhysicalState DeterminePhysicalStateH2S(double T, double P)
00177 {
00178 return (T < TcH2S) ? ( (P > ComputeSaturatedPressureH2S(T)) ? LIQUID : GAS ) : ( (P > PcH2S) ? SUPERCRITICAL : GAS );
00179 }
00180
00181
00182
00183
00184
00185
00186
00187 struct VolumeCO2Equation
00188 {
00189 double T, P;
00190 double operator()(double V) { return V*V*V - (R*T/P)*(V*V) - (R*T*bCO2/P - aCO2(T)/(P*std::sqrt(T)) + bCO2*bCO2)*(V) - aCO2(T)*bCO2/(P*std::sqrt(T)); }
00191 };
00192
00193
00194 struct VolumeCO2DerivativeEquation
00195 {
00196 double T, P;
00197 double operator()(double V) { return 3*V*V - 2*(R*T/P)*V - (R*T*bCO2/P - aCO2(T)/(P*sqrtf(T)) + bCO2*bCO2); }
00198 };
00199
00200
00201 inline double ComputeVolumeCO2(double T, double P, PhysicalState stateCO2)
00202 {
00203
00204 double V0 = (stateCO2 == GAS || stateCO2 == SUPERCRITICAL) ? (R * T/P) : 59.22;
00205
00206
00207 static VolumeCO2Equation equation;
00208
00209 static VolumeCO2DerivativeEquation derivative;
00210
00211 equation.T = T; derivative.T = T;
00212 equation.P = P; derivative.P = P;
00213
00214
00215 return NewtonRaphson(equation, derivative, V0);
00216 }
00217
00218
00219 inline double ComputeVolumeCO2(double T, double P)
00220 {
00221 PhysicalState stateCO2=DeterminePhysicalStateCO2(T,P);
00222
00223
00224 double V0 = (stateCO2 == GAS || stateCO2 == SUPERCRITICAL) ? (R * T/P) : 59.22;
00225
00226
00227 static VolumeCO2Equation equation;
00228
00229 static VolumeCO2DerivativeEquation derivative;
00230
00231 equation.T = T; derivative.T = T;
00232 equation.P = P; derivative.P = P;
00233
00234 double result=NewtonRaphson(equation, derivative, V0);
00235 assert(result>=0.0);
00236 return result;
00237 }
00238
00239
00240 struct VolumeH2SEquation
00241 {
00242 double T, P;
00243 double operator()(double V)
00244 {
00245 static double Tr1;
00246 static double Tr2;
00247 static double Tr3;
00248 static double Vr1;
00249 static double Vr2;
00250 static double Vr4;
00251 static double Vr5;
00252
00253 Tr1 = TcH2S/T;
00254 Tr2 = Tr1 * Tr1;
00255 Tr3 = Tr2 * Tr1;
00256 Vr1 = (R * TcH2S)/(V * PcH2S);
00257 Vr2 = Vr1 * Vr1;
00258 Vr4 = Vr2 * Vr2;
00259 Vr5 = Vr4 * Vr1;
00260
00261 return 1.0 +
00262 Vr1 * (a1H2S + a2H2S * Tr2 + a3H2S * Tr3) +
00263 Vr2 * (a4H2S + a5H2S * Tr2 + a6H2S * Tr3) +
00264 Vr4 * (a7H2S + a8H2S * Tr2 + a9H2S * Tr3) +
00265 Vr5 * (a10H2S + a11H2S * Tr2 + a12H2S * Tr3) +
00266 a13H2S * Tr3 * Vr2 * (a14H2S + a15H2S * Vr2) *
00267 std::exp(-a15H2S * Vr2) - (P*V)/(R*T);
00268 }
00269 };
00270
00271
00272 struct VolumeH2SDerivativeEquation
00273 {
00274 double T, P;
00275 double operator()(double V)
00276 {
00277 double Tr1 = TcH2S/T;
00278 double Tr2 = Tr1 * Tr1;
00279 double Tr3 = Tr2 * Tr1;
00280 double Vr1 = (R * TcH2S)/(V * PcH2S);
00281 double Vr2 = Vr1 * Vr1;
00282 double Vr3 = Vr2 * Vr1;
00283 double Vr4 = Vr2 * Vr2;
00284 double Vr5 = Vr4 * Vr1;
00285 double Vr6 = Vr5 * Vr1;
00286
00287 return - (Vr2 * (a1H2S + a2H2S * Tr2 + a3H2S * Tr3) +
00288 2.0 * Vr3 * (a4H2S + a5H2S * Tr2 + a6H2S * Tr3) +
00289 4.0 * Vr5 * (a7H2S + a8H2S * Tr2 + a9H2S * Tr3) +
00290 5.0 * Vr6 * (a10H2S + a11H2S * Tr2 + a12H2S * Tr3) +
00291 4.0 * a13H2S * a15H2S * Tr3 * Vr6 * (a14H2S + 2.0 * a15H2S * Vr2) *
00292 expf(-a15H2S * Vr2)) * PcH2S/(R*TcH2S) - P/(R*T);
00293 }
00294 };
00295
00296
00297 const double toleranceVolumeH2SEquation = 1.0E-2;
00298
00299
00300 inline double ComputeVolumeH2S(double T, double P, PhysicalState stateH2S)
00301 {
00302
00303 double V0 = (stateH2S == GAS || stateH2S == SUPERCRITICAL) ? (R * T/P) : 44.60;
00304
00305 static VolumeH2SEquation equation;
00306
00307 static VolumeH2SDerivativeEquation derivative;
00308
00309 equation.T = T; derivative.T = T;
00310 equation.P = P; derivative.P = P;
00311
00312 return NewtonRaphson(equation, derivative, V0, toleranceVolumeH2SEquation);
00313 }
00314
00315
00316
00317
00318
00319
00320
00321 inline double ComputeFugacityH2O(double volumeCO2, double T, double P)
00322 {
00323
00324 double a1 = std::log(volumeCO2/(volumeCO2 - bCO2));
00325 double a2 = std::log(1 + bCO2/volumeCO2);
00326 double a3 = bCO2/(volumeCO2 + bCO2);
00327 double a4 = std::log((P * volumeCO2)/(R * T));
00328 double a5 = R * std::pow(T, 1.5);
00329
00330 return std::exp(a1 + bH2O/(volumeCO2 - bCO2) - 2 * aH2OCO2/bCO2 * a2/a5 + (aCO2(T) * bH2O)/(bCO2 * bCO2) * (a2 - a3)/a5 - a4);
00331 }
00332
00333
00334 inline double ComputeFugacityCO2(double volumeCO2, double T, double P)
00335 {
00336
00337 double a1 = std::log(volumeCO2/(volumeCO2 - bCO2));
00338 double a2 = std::log(1 + bCO2/volumeCO2);
00339 double a3 = bCO2/(volumeCO2 + bCO2);
00340 double a4 = std::log((P * volumeCO2)/(R * T));
00341 double a5 = R * std::pow(T, 1.5);
00342
00343 return std::exp(a1 + bCO2/(volumeCO2 - bCO2) - 2 * aCO2(T)/bCO2 * a2/a5 + aCO2(T)/bCO2 * (a2 - a3)/a5 - a4);
00344 }
00345
00346
00347 inline double ComputeFugacityH2S(double volumeH2S, double T, double P)
00348 {
00349
00350 static double Z;
00351 static double Tr1;
00352 static double Tr2;
00353 static double Tr3;
00354 static double Vr1;
00355 static double Vr2;
00356 static double Vr4;
00357 static double Vr5;
00358
00359 Z = (P * volumeH2S)/(R * T);
00360 Tr1 = TcH2S/T;
00361 Tr2 = Tr1 * Tr1;
00362 Tr3 = Tr2 * Tr1;
00363 Vr1 = (R * TcH2S)/(volumeH2S * PcH2S);
00364 Vr2 = Vr1 * Vr1;
00365 Vr4 = Vr2 * Vr2;
00366 Vr5 = Vr4 * Vr1;
00367
00368 return std::exp(Z - 1.0 - std::log(Z) +
00369 Vr1 * (a1H2S + a2H2S * Tr2 + a3H2S * Tr3) +
00370 Vr2 * (a4H2S + a5H2S * Tr2 + a6H2S * Tr3) * 0.50 +
00371 Vr4 * (a7H2S + a8H2S * Tr2 + a9H2S * Tr3) * 0.25 +
00372 Vr5 * (a10H2S + a11H2S * Tr2 + a12H2S * Tr3) * 0.20 +
00373 a13H2S/a15H2S * Tr3 * 0.50 *
00374 (a14H2S + 1.0 - (a14H2S + 1.0 + a15H2S * Vr2) *
00375 std::exp(-a15H2S * Vr2)));
00376 }
00377 }
00378
00379 #endif