00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "xml.h"
00012 #include "PureFluidPhase.h"
00013
00014 #ifdef WITH_PURE_FLUIDS
00015
00016 #include "../../../ext/tpx/Sub.h"
00017 #include "../../../ext/tpx/utils.h"
00018
00019 #include <cstdlib>
00020
00021 namespace Cantera {
00022
00023
00024 PureFluidPhase::PureFluidPhase() :
00025 ThermoPhase(),
00026 m_sub(0),
00027 m_subflag(0),
00028 m_mw(-1.0),
00029 m_verbose(false)
00030 {
00031 }
00032
00033
00034 PureFluidPhase::PureFluidPhase(const PureFluidPhase& right) :
00035 ThermoPhase(),
00036 m_sub(0),
00037 m_subflag(0),
00038 m_mw(-1.0),
00039 m_verbose(false)
00040 {
00041 *this = right;
00042 }
00043
00044
00045
00046
00047
00048 PureFluidPhase& PureFluidPhase::operator=(const PureFluidPhase& right) {
00049 if (&right != this) {
00050 ThermoPhase::operator=(right);
00051 if (m_sub) {
00052 delete m_sub;
00053 }
00054 m_subflag = right.m_subflag;
00055 m_sub = tpx::GetSub(m_subflag);
00056 m_mw = right.m_mw;
00057 m_verbose = right.m_verbose;
00058 }
00059 return *this;
00060 }
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070 ThermoPhase *PureFluidPhase::duplMyselfAsThermoPhase() const {
00071 PureFluidPhase *igp = new PureFluidPhase(*this);
00072 return (ThermoPhase *) igp;
00073 }
00074
00075
00076
00077
00078 PureFluidPhase::~PureFluidPhase() {
00079 delete m_sub;
00080 }
00081
00082 void PureFluidPhase::
00083 initThermo() {
00084 if (m_sub) delete m_sub;
00085 m_sub = tpx::GetSub(m_subflag);
00086 if (m_sub == 0) {
00087 throw CanteraError("PureFluidPhase::initThermo",
00088 "could not create new substance object.");
00089 }
00090 m_mw = m_sub->MolWt();
00091 m_weight[0] = m_mw;
00092 setMolecularWeight(0,m_mw);
00093 double one = 1.0;
00094 setMoleFractions(&one);
00095 double cp0_R, h0_RT, s0_R, T0, p;
00096 T0 = 298.15;
00097 if (T0 < m_sub->Tcrit()) {
00098 m_sub->Set(tpx::TX, T0, 1.0);
00099 p = 0.01*m_sub->P();
00100 }
00101 else {
00102 p = 0.001*m_sub->Pcrit();
00103 }
00104 m_sub->Set(tpx::TP, T0, p);
00105
00106 m_spthermo->update_one(0, T0, &cp0_R, &h0_RT, &s0_R);
00107 double s_R = s0_R - log(p/refPressure());
00108 m_sub->setStdState(h0_RT*GasConstant*298.15/m_mw,
00109 s_R*GasConstant/m_mw, T0, p);
00110 if (m_verbose) {
00111 writelog("PureFluidPhase::initThermo: initialized phase "
00112 +id()+"\n");
00113 }
00114 }
00115
00116 void PureFluidPhase::
00117 setParametersFromXML(const XML_Node& eosdata) {
00118 eosdata._require("model","PureFluid");
00119 m_subflag = atoi(eosdata["fluid_type"].c_str());
00120 if (m_subflag < 0)
00121 throw CanteraError("PureFluidPhase::setParametersFromXML",
00122 "missing or negative substance flag");
00123 }
00124
00125 doublereal PureFluidPhase::
00126 enthalpy_mole() const {
00127 setTPXState();
00128 doublereal h = m_sub->h() * m_mw;
00129 check(h);
00130 return h;
00131 }
00132
00133 doublereal PureFluidPhase::
00134 intEnergy_mole() const {
00135 setTPXState();
00136 doublereal u = m_sub->u() * m_mw;
00137 check(u);
00138 return u;
00139 }
00140
00141 doublereal PureFluidPhase::
00142 entropy_mole() const {
00143 setTPXState();
00144 doublereal s = m_sub->s() * m_mw;
00145 check(s);
00146 return s;
00147 }
00148
00149 doublereal PureFluidPhase::
00150 gibbs_mole() const {
00151 setTPXState();
00152 doublereal g = m_sub->g() * m_mw;
00153 check(g);
00154 return g;
00155 }
00156
00157 doublereal PureFluidPhase::
00158 cp_mole() const {
00159 setTPXState();
00160 doublereal cp = m_sub->cp() * m_mw;
00161 check(cp);
00162 return cp;
00163 }
00164
00165 doublereal PureFluidPhase::
00166 cv_mole() const {
00167 setTPXState();
00168 doublereal cv = m_sub->cv() * m_mw;
00169 check(cv);
00170 return cv;
00171 }
00172
00173 doublereal PureFluidPhase::
00174 pressure() const {
00175 setTPXState();
00176 doublereal p = m_sub->P();
00177 check(p);
00178 return p;
00179 }
00180
00181 void PureFluidPhase::
00182 setPressure(doublereal p) {
00183 Set(tpx::TP, temperature(), p);
00184 setDensity(1.0/m_sub->v());
00185 check();
00186 }
00187
00188 void PureFluidPhase::Set(int n, double x, double y) const {
00189 try {
00190 m_sub->Set(n, x, y);
00191 }
00192 catch(tpx::TPX_Error) {
00193 reportTPXError();
00194 }
00195 }
00196
00197 void PureFluidPhase::setTPXState() const {
00198 Set(tpx::TV, temperature(), 1.0/density());
00199 }
00200
00201 void PureFluidPhase::check(doublereal v) const {
00202 if (m_sub->Error() || v == tpx::Undef) {
00203 throw CanteraError("PureFluidPhase",string(tpx::errorMsg(
00204 m_sub->Error())));
00205 }
00206 }
00207
00208 void PureFluidPhase::reportTPXError() const {
00209 string msg = tpx::TPX_Error::ErrorMessage;
00210 string proc = "tpx::"+tpx::TPX_Error::ErrorProcedure;
00211 throw CanteraError(proc,msg);
00212 }
00213
00214
00215 doublereal PureFluidPhase::isothermalCompressibility() const {
00216 return m_sub->isothermalCompressibility();
00217 }
00218
00219 doublereal PureFluidPhase::thermalExpansionCoeff() const {
00220 return m_sub->thermalExpansionCoeff();
00221 }
00222
00223 tpx::Substance& PureFluidPhase::TPX_Substance() { return *m_sub; }
00224
00225
00226 doublereal PureFluidPhase::critTemperature() const { return m_sub->Tcrit(); }
00227
00228
00229 doublereal PureFluidPhase::critPressure() const { return m_sub->Pcrit(); }
00230
00231
00232 doublereal PureFluidPhase::critDensity() const { return 1.0/m_sub->Vcrit(); }
00233
00234
00235
00236 doublereal PureFluidPhase::satTemperature(doublereal p) const {
00237 try {
00238 doublereal ts = m_sub->Tsat(p);
00239 return ts;
00240 }
00241 catch(tpx::TPX_Error) {
00242 reportTPXError();
00243 return -1.0;
00244 }
00245 }
00246
00247 void PureFluidPhase::setState_HP(doublereal h, doublereal p,
00248 doublereal tol) {
00249 Set(tpx::HP, h, p);
00250 setState_TR(m_sub->Temp(), 1.0/m_sub->v());
00251 check();
00252 }
00253
00254 void PureFluidPhase::setState_UV(doublereal u, doublereal v,
00255 doublereal tol) {
00256 Set(tpx::UV, u, v);
00257 setState_TR(m_sub->Temp(), 1.0/m_sub->v());
00258 check();
00259 }
00260
00261 void PureFluidPhase::setState_SV(doublereal s, doublereal v,
00262 doublereal tol) {
00263 Set(tpx::SV, s, v);
00264 setState_TR(m_sub->Temp(), 1.0/m_sub->v());
00265 check();
00266 }
00267
00268 void PureFluidPhase::setState_SP(doublereal s, doublereal p,
00269 doublereal tol) {
00270 Set(tpx::SP, s, p);
00271 setState_TR(m_sub->Temp(), 1.0/m_sub->v());
00272 check();
00273 }
00274
00275
00276 doublereal PureFluidPhase::satPressure(doublereal t) const {
00277 doublereal vsv = m_sub->v();
00278 try {
00279 Set(tpx::TV,t,vsv);
00280 doublereal ps = m_sub->Ps();
00281 return ps;
00282 }
00283 catch(tpx::TPX_Error) {
00284 reportTPXError();
00285 return -1.0;
00286 }
00287 }
00288
00289 doublereal PureFluidPhase::vaporFraction() const {
00290 setTPXState();
00291 doublereal x = m_sub->x();
00292 check(x);
00293 return x;
00294 }
00295
00296 void PureFluidPhase::setState_Tsat(doublereal t, doublereal x) {
00297 setTemperature(t);
00298 setTPXState();
00299 Set(tpx::TX, t, x);
00300 setDensity(1.0/m_sub->v());
00301 check();
00302 }
00303
00304 void PureFluidPhase::setState_Psat(doublereal p, doublereal x) {
00305 setTPXState();
00306 Set(tpx::PX, p, x);
00307 setTemperature(m_sub->Temp());
00308 setDensity(1.0/m_sub->v());
00309 check();
00310 }
00311
00312
00313
00314
00315
00316 std::string PureFluidPhase::report(bool show_thermo) const {
00317
00318
00319 char p[800];
00320 string s = "";
00321 try {
00322 if (name() != "") {
00323 sprintf(p, " \n %s:\n", name().c_str());
00324 s += p;
00325 }
00326 sprintf(p, " \n temperature %12.6g K\n", temperature());
00327 s += p;
00328 sprintf(p, " pressure %12.6g Pa\n", pressure());
00329 s += p;
00330 sprintf(p, " density %12.6g kg/m^3\n", density());
00331 s += p;
00332 sprintf(p, " mean mol. weight %12.6g amu\n", meanMolecularWeight());
00333 s += p;
00334
00335 if (eosType() == cPureFluid) {
00336 double xx = ((PureFluidPhase *) (this))->vaporFraction();
00337 sprintf(p, " vapor fraction %12.6g \n",
00338 xx);
00339 s += p;
00340 }
00341
00342 doublereal phi = electricPotential();
00343 if (phi != 0.0) {
00344 sprintf(p, " potential %12.6g V\n", phi);
00345 s += p;
00346 }
00347 if (show_thermo) {
00348 sprintf(p, " \n");
00349 s += p;
00350 sprintf(p, " 1 kg 1 kmol\n");
00351 s += p;
00352 sprintf(p, " ----------- ------------\n");
00353 s += p;
00354 sprintf(p, " enthalpy %12.6g %12.4g J\n",
00355 enthalpy_mass(), enthalpy_mole());
00356 s += p;
00357 sprintf(p, " internal energy %12.6g %12.4g J\n",
00358 intEnergy_mass(), intEnergy_mole());
00359 s += p;
00360 sprintf(p, " entropy %12.6g %12.4g J/K\n",
00361 entropy_mass(), entropy_mole());
00362 s += p;
00363 sprintf(p, " Gibbs function %12.6g %12.4g J\n",
00364 gibbs_mass(), gibbs_mole());
00365 s += p;
00366 sprintf(p, " heat capacity c_p %12.6g %12.4g J/K\n",
00367 cp_mass(), cp_mole());
00368 s += p;
00369 try {
00370 sprintf(p, " heat capacity c_v %12.6g %12.4g J/K\n",
00371 cv_mass(), cv_mole());
00372 s += p;
00373 }
00374 catch(CanteraError) {
00375 sprintf(p, " heat capacity c_v <not implemented> \n");
00376 s += p;
00377 }
00378 }
00379
00380 int kk = nSpecies();
00381 array_fp x(kk);
00382 array_fp y(kk);
00383 array_fp mu(kk);
00384 getMoleFractions(&x[0]);
00385 getMassFractions(&y[0]);
00386 getChemPotentials(&mu[0]);
00387 doublereal rt = GasConstant * temperature();
00388 int k;
00389
00390
00391 if (show_thermo) {
00392 sprintf(p, " \n X "
00393 " Y Chem. Pot. / RT \n");
00394 s += p;
00395 sprintf(p, " ------------- "
00396 "------------ ------------\n");
00397 s += p;
00398 for (k = 0; k < kk; k++) {
00399 if (x[k] > SmallNumber) {
00400 sprintf(p, "%18s %12.6g %12.6g %12.6g\n",
00401 speciesName(k).c_str(), x[k], y[k], mu[k]/rt);
00402 }
00403 else {
00404 sprintf(p, "%18s %12.6g %12.6g \n",
00405 speciesName(k).c_str(), x[k], y[k]);
00406 }
00407 s += p;
00408 }
00409 }
00410 else {
00411 sprintf(p, " \n X"
00412 "Y\n");
00413 s += p;
00414 sprintf(p, " -------------"
00415 " ------------\n");
00416 s += p;
00417 for (k = 0; k < kk; k++) {
00418 sprintf(p, "%18s %12.6g %12.6g\n",
00419 speciesName(k).c_str(), x[k], y[k]);
00420 s += p;
00421 }
00422 }
00423 }
00424
00425 catch (CanteraError) {
00426 ;
00427 }
00428 return s;
00429 }
00430
00431
00432 }
00433
00434 #endif // WITH_PURE_FLUIDS