00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "xml.h"
00016 #include "WaterSSTP.h"
00017 #include "WaterPropsIAPWS.h"
00018
00019 #include "WaterProps.h"
00020 #include "ThermoFactory.h"
00021 #include <cmath>
00022
00023 using namespace std;
00024
00025 namespace Cantera {
00026
00027
00028
00029
00030 WaterSSTP::WaterSSTP() :
00031 SingleSpeciesTP(),
00032 m_sub(0),
00033 m_waterProps(0),
00034 m_mw(0.0),
00035 EW_Offset(0.0),
00036 SW_Offset(0.0),
00037 m_ready(false),
00038 m_allowGasPhase(false)
00039 {
00040
00041 }
00042
00043
00044 WaterSSTP::WaterSSTP(std::string inputFile, std::string id) :
00045 SingleSpeciesTP(),
00046 m_sub(0),
00047 m_waterProps(0),
00048 m_mw(0.0),
00049 EW_Offset(0.0),
00050 SW_Offset(0.0),
00051 m_ready(false),
00052 m_allowGasPhase(false)
00053 {
00054 constructPhaseFile(inputFile, id);
00055 }
00056
00057
00058 WaterSSTP::WaterSSTP(XML_Node& phaseRoot, std::string id) :
00059 SingleSpeciesTP(),
00060 m_sub(0),
00061 m_waterProps(0),
00062 m_mw(0.0),
00063 EW_Offset(0.0),
00064 SW_Offset(0.0),
00065 m_ready(false),
00066 m_allowGasPhase(false)
00067 {
00068 constructPhaseXML(phaseRoot, id) ;
00069 }
00070
00071
00072
00073 WaterSSTP::WaterSSTP(const WaterSSTP &b) :
00074 SingleSpeciesTP(b),
00075 m_sub(0),
00076 m_waterProps(0),
00077 m_mw(b.m_mw),
00078 EW_Offset(b.EW_Offset),
00079 SW_Offset(b.SW_Offset),
00080 m_ready(false),
00081 m_allowGasPhase(b.m_allowGasPhase)
00082 {
00083 m_sub = new WaterPropsIAPWS(*(b.m_sub));
00084 m_waterProps = new WaterProps(m_sub);
00085
00086
00087
00088
00089
00090 *this = b;
00091 }
00092
00093
00094
00095
00096 WaterSSTP& WaterSSTP::operator=(const WaterSSTP&b) {
00097 if (&b == this) return *this;
00098 m_sub->operator=(*(b.m_sub));
00099
00100 if (!m_waterProps) {
00101 m_waterProps = new WaterProps(m_sub);
00102 }
00103 m_waterProps->operator=(*(b.m_waterProps));
00104
00105
00106 m_mw = b.m_mw;
00107 m_ready = b.m_ready;
00108 m_allowGasPhase = b.m_allowGasPhase;
00109 return *this;
00110 }
00111
00112
00113 ThermoPhase *WaterSSTP::duplMyselfAsThermoPhase() const {
00114 WaterSSTP* wtp = new WaterSSTP(*this);
00115 return (ThermoPhase *) wtp;
00116 }
00117
00118 WaterSSTP::~WaterSSTP() {
00119 delete m_sub;
00120 delete m_waterProps;
00121 }
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134 void WaterSSTP::constructPhaseXML(XML_Node& phaseNode, std::string id) {
00135
00136
00137
00138
00139
00140
00141 bool m_ok = importPhase(phaseNode, this);
00142 if (!m_ok) {
00143 throw CanteraError("initThermo","importPhase failed ");
00144 }
00145
00146 }
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162 void WaterSSTP::constructPhaseFile(std::string inputFile, std::string id) {
00163
00164 if (inputFile.size() == 0) {
00165 throw CanteraError("WaterTp::initThermo",
00166 "input file is null");
00167 }
00168 std::string path = findInputFile(inputFile);
00169 std::ifstream fin(path.c_str());
00170 if (!fin) {
00171 throw CanteraError("WaterSSTP::initThermo","could not open "
00172 +path+" for reading.");
00173 }
00174
00175
00176
00177
00178 XML_Node &phaseNode_XML = xml();
00179 XML_Node *fxml = new XML_Node();
00180 fxml->build(fin);
00181 XML_Node *fxml_phase = findXMLPhase(fxml, id);
00182 if (!fxml_phase) {
00183 throw CanteraError("WaterSSTP::initThermo",
00184 "ERROR: Can not find phase named " +
00185 id + " in file named " + inputFile);
00186 }
00187 fxml_phase->copy(&phaseNode_XML);
00188 constructPhaseXML(*fxml_phase, id);
00189 delete fxml;
00190 }
00191
00192
00193
00194 void WaterSSTP::initThermo() {
00195 SingleSpeciesTP::initThermo();
00196 }
00197
00198 void WaterSSTP::
00199 initThermoXML(XML_Node& phaseNode, std::string id) {
00200
00201
00202
00203
00204 initThermo();
00205 if (m_sub) delete m_sub;
00206 m_sub = new WaterPropsIAPWS();
00207 if (m_sub == 0) {
00208 throw CanteraError("WaterSSTP::initThermo",
00209 "could not create new substance object.");
00210 }
00211
00212
00213
00214
00215
00216
00217
00218
00219 int nH = elementIndex("H");
00220 if (nH < 0) {
00221 throw CanteraError("WaterSSTP::initThermo",
00222 "H not an element");
00223 }
00224 double mw_H = atomicWeight(nH);
00225 int nO = elementIndex("O");
00226 if (nO < 0) {
00227 throw CanteraError("WaterSSTP::initThermo",
00228 "O not an element");
00229 }
00230 double mw_O = atomicWeight(nO);
00231 m_mw = 2.0 * mw_H + mw_O;
00232 m_weight[0] = m_mw;
00233 setMolecularWeight(0,m_mw);
00234 double one = 1.0;
00235 setMoleFractions(&one);
00236
00237
00238
00239
00240 doublereal T = 298.15;
00241 State::setDensity(7.0E-8);
00242 State::setTemperature(T);
00243
00244 doublereal presLow = 1.0E-2;
00245 doublereal oneBar = 1.0E5;
00246 doublereal dd = m_sub->density(T, presLow, WATER_GAS, 7.0E-8);
00247 setDensity(dd);
00248 setTemperature(T);
00249 SW_Offset = 0.0;
00250 doublereal s = entropy_mole();
00251 s -= GasConstant * log(oneBar/presLow);
00252 if (s != 188.835E3) {
00253 SW_Offset = 188.835E3 - s;
00254 }
00255 s = entropy_mole();
00256 s -= GasConstant * log(oneBar/presLow);
00257
00258
00259 doublereal h = enthalpy_mole();
00260 if (h != -241.826E6) {
00261 EW_Offset = -241.826E6 - h;
00262 }
00263 h = enthalpy_mole();
00264
00265
00266
00267
00268
00269
00270
00271
00272 setTemperature(298.15);
00273 double rho0 = m_sub->density(298.15, OneAtm, WATER_LIQUID);
00274 setDensity(rho0);
00275
00276 m_waterProps = new WaterProps(m_sub);
00277
00278
00279
00280
00281
00282 if (m_spthermo) {
00283 delete m_spthermo;
00284 m_spthermo = 0;
00285 }
00286
00287
00288
00289
00290 m_ready = true;
00291 }
00292
00293 void WaterSSTP::
00294 setParametersFromXML(const XML_Node& eosdata) {
00295 eosdata._require("model","PureLiquidWater");
00296 }
00297
00298
00299
00300
00301 void WaterSSTP::getEnthalpy_RT(doublereal* hrt) const {
00302 double T = temperature();
00303 doublereal h = m_sub->enthalpy();
00304 *hrt = (h + EW_Offset)/(GasConstant*T);
00305 }
00306
00307
00308
00309
00310
00311 void WaterSSTP::getIntEnergy_RT(doublereal *ubar) const {
00312 doublereal u = m_sub->intEnergy();
00313 *ubar = (u + EW_Offset)/GasConstant;
00314 }
00315
00316
00317
00318
00319 void WaterSSTP::getEntropy_R(doublereal* sr) const {
00320 doublereal s = m_sub->entropy();
00321 sr[0] = (s + SW_Offset) / GasConstant;
00322 }
00323
00324
00325
00326
00327
00328 void WaterSSTP::getGibbs_RT(doublereal *grt) const {
00329 double T = temperature();
00330 doublereal g = m_sub->Gibbs();
00331 *grt = (g + EW_Offset - SW_Offset*T) / (GasConstant * T);
00332 if (!m_ready) {
00333 throw CanteraError("waterSSTP::", "Phase not ready");
00334 }
00335 }
00336
00337
00338
00339
00340
00341 void WaterSSTP::getStandardChemPotentials(doublereal *gss) const {
00342 double T = temperature();
00343 doublereal g = m_sub->Gibbs();
00344 *gss = (g + EW_Offset - SW_Offset*T);
00345 if (!m_ready) {
00346 throw CanteraError("waterSSTP::", "Phase not ready");
00347 }
00348 }
00349
00350 void WaterSSTP::getCp_R(doublereal* cpr) const {
00351 doublereal cp = m_sub->cp();
00352 cpr[0] = cp / GasConstant;
00353 }
00354
00355
00356
00357
00358
00359 doublereal WaterSSTP::cv_mole() const {
00360 doublereal cv = m_sub->cv();
00361 return cv;
00362 }
00363
00364
00365
00366
00367 void WaterSSTP::getEnthalpy_RT_ref(doublereal *hrt) const {
00368 doublereal p = pressure();
00369 double T = temperature();
00370 double dens = density();
00371 int waterState = WATER_GAS;
00372 double rc = m_sub->Rhocrit();
00373 if (dens > rc) {
00374 waterState = WATER_LIQUID;
00375 }
00376 doublereal dd = m_sub->density(T, OneAtm, waterState, dens);
00377 if (dd <= 0.0) {
00378 throw CanteraError("setPressure", "error");
00379 }
00380 doublereal h = m_sub->enthalpy();
00381 *hrt = (h + EW_Offset) / (GasConstant * T);
00382 dd = m_sub->density(T, p, waterState, dens);
00383 }
00384
00385 void WaterSSTP::getGibbs_RT_ref(doublereal *grt) const {
00386 doublereal p = pressure();
00387 double T = temperature();
00388 double dens = density();
00389 int waterState = WATER_GAS;
00390 double rc = m_sub->Rhocrit();
00391 if (dens > rc) {
00392 waterState = WATER_LIQUID;
00393 }
00394 doublereal dd = m_sub->density(T, OneAtm, waterState, dens);
00395 if (dd <= 0.0) {
00396 throw CanteraError("setPressure", "error");
00397 }
00398 m_sub->setState_TR(T, dd);
00399 doublereal g = m_sub->Gibbs();
00400 *grt = (g + EW_Offset - SW_Offset*T)/ (GasConstant * T);
00401 dd = m_sub->density(T, p, waterState, dens);
00402
00403 }
00404
00405 void WaterSSTP::getGibbs_ref(doublereal *g) const {
00406 getGibbs_RT_ref(g);
00407 doublereal rt = _RT();
00408 for (int k = 0; k < m_kk; k++) {
00409 g[k] *= rt;
00410 }
00411 }
00412
00413 void WaterSSTP::getEntropy_R_ref(doublereal *sr) const {
00414 doublereal p = pressure();
00415 double T = temperature();
00416 double dens = density();
00417 int waterState = WATER_GAS;
00418 double rc = m_sub->Rhocrit();
00419 if (dens > rc) {
00420 waterState = WATER_LIQUID;
00421 }
00422 doublereal dd = m_sub->density(T, OneAtm, waterState, dens);
00423
00424 if (dd <= 0.0) {
00425 throw CanteraError("setPressure", "error");
00426 }
00427 m_sub->setState_TR(T, dd);
00428
00429 doublereal s = m_sub->entropy();
00430 *sr = (s + SW_Offset)/ (GasConstant);
00431 dd = m_sub->density(T, p, waterState, dens);
00432
00433 }
00434
00435 void WaterSSTP::getCp_R_ref(doublereal *cpr) const {
00436 doublereal p = pressure();
00437 double T = temperature();
00438 double dens = density();
00439 int waterState = WATER_GAS;
00440 double rc = m_sub->Rhocrit();
00441 if (dens > rc) {
00442 waterState = WATER_LIQUID;
00443 }
00444 doublereal dd = m_sub->density(T, OneAtm, waterState, dens);
00445 m_sub->setState_TR(T, dd);
00446 if (dd <= 0.0) {
00447 throw CanteraError("setPressure", "error");
00448 }
00449 doublereal cp = m_sub->cp();
00450 *cpr = cp / (GasConstant);
00451 dd = m_sub->density(T, p, waterState, dens);
00452 }
00453
00454 void WaterSSTP::getStandardVolumes_ref(doublereal *vol) const {
00455 doublereal p = pressure();
00456 double T = temperature();
00457 double dens = density();
00458 int waterState = WATER_GAS;
00459 double rc = m_sub->Rhocrit();
00460 if (dens > rc) {
00461 waterState = WATER_LIQUID;
00462 }
00463 doublereal dd = m_sub->density(T, OneAtm, waterState, dens);
00464 if (dd <= 0.0) {
00465 throw CanteraError("setPressure", "error");
00466 }
00467 *vol = meanMolecularWeight() /dd;
00468 dd = m_sub->density(T, p, waterState, dens);
00469 }
00470
00471
00472
00473
00474
00475
00476 doublereal WaterSSTP::pressure() const {
00477 doublereal p = m_sub->pressure();
00478 return p;
00479 }
00480
00481 void WaterSSTP::
00482 setPressure(doublereal p) {
00483 double T = temperature();
00484 double dens = density();
00485 int waterState = WATER_GAS;
00486 double rc = m_sub->Rhocrit();
00487 if (dens > rc) {
00488 waterState = WATER_LIQUID;
00489 }
00490 doublereal dd = m_sub->density(T, p, waterState, dens);
00491 if (dd <= 0.0) {
00492 throw CanteraError("setPressure", "error");
00493 }
00494 setDensity(dd);
00495 }
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508 doublereal WaterSSTP::isothermalCompressibility() const {
00509 doublereal val = m_sub->isothermalCompressibility();
00510 return val;
00511 }
00512
00513
00514
00515
00516
00517
00518
00519
00520 doublereal WaterSSTP::thermalExpansionCoeff() const {
00521 doublereal val = m_sub->coeffThermExp();
00522 return val;
00523 }
00524
00525 doublereal WaterSSTP::dthermalExpansionCoeffdT() const {
00526 doublereal pres = pressure();
00527 doublereal dens_save = density();
00528 double T = temperature();
00529 double tt = T - 0.04;
00530 doublereal dd = m_sub->density(tt, pres, WATER_LIQUID, dens_save);
00531 if (dd < 0.0) {
00532 throw CanteraError("WaterSSTP::dthermalExpansionCoeffdT",
00533 "Unable to solve for the density at T = " + fp2str(tt) + ", P = " + fp2str(pres));
00534 }
00535 doublereal vald = m_sub->coeffThermExp();
00536 m_sub->setState_TR(T, dens_save);
00537 doublereal val2 = m_sub->coeffThermExp();
00538 doublereal val = (val2 - vald) / 0.04;
00539 return val;
00540 }
00541
00542
00543
00544 doublereal WaterSSTP::critTemperature() const { return m_sub->Tcrit(); }
00545
00546
00547 doublereal WaterSSTP::critPressure() const { return m_sub->Pcrit(); }
00548
00549
00550 doublereal WaterSSTP::critDensity() const { return m_sub->Rhocrit(); }
00551
00552
00553 void WaterSSTP::setTemperature(const doublereal temp) {
00554 State::setTemperature(temp);
00555 doublereal dd = density();
00556 m_sub->setState_TR(temp, dd);
00557 }
00558
00559 void WaterSSTP::setDensity(const doublereal dens) {
00560 State::setDensity(dens);
00561 doublereal temp = temperature();
00562 m_sub->setState_TR(temp, dens);
00563 }
00564
00565
00566 doublereal WaterSSTP::satPressure(doublereal t) const {
00567 doublereal tsave = temperature();
00568 doublereal dsave = density();
00569 doublereal pp = m_sub->psat(t);
00570 m_sub->setState_TR(tsave, dsave);
00571 return pp;
00572 }
00573
00574
00575 doublereal WaterSSTP::vaporFraction() const {
00576 if (temperature() >= m_sub->Tcrit()) {
00577 double dens = density();
00578 if (dens >= m_sub->Rhocrit()) {
00579 return 0.0;
00580 }
00581 return 1.0;
00582 }
00583
00584
00585
00586 return 0.0;
00587 }
00588
00589
00590 }