00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #ifdef WIN32
00019 #pragma warning(disable:4786)
00020 #pragma warning(disable:4503)
00021 #endif
00022
00023 #include "ThermoPhase.h"
00024
00025
00026 #ifndef MAX
00027 #define MAX(x,y) (( (x) > (y) ) ? (x) : (y))
00028 #endif
00029
00030
00031 using namespace std;
00032
00033 namespace Cantera {
00034
00035
00036
00037
00038 ThermoPhase::ThermoPhase() :
00039 Phase(),
00040 m_spthermo(0), m_speciesData(0),
00041 m_index(-1),
00042 m_phi(0.0),
00043 m_hasElementPotentials(false),
00044 m_chargeNeutralityNecessary(false),
00045 m_ssConvention(cSS_CONVENTION_TEMPERATURE)
00046 {
00047 }
00048
00049 ThermoPhase::~ThermoPhase()
00050 {
00051 for (int k = 0; k < m_kk; k++) {
00052 if (!m_speciesData[k]) {
00053 delete m_speciesData[k];
00054 }
00055 }
00056 delete m_spthermo;
00057 }
00058
00059
00060
00061
00062
00063
00064
00065 ThermoPhase::ThermoPhase(const ThermoPhase &right) :
00066 Phase(),
00067 m_spthermo(0),
00068 m_speciesData(0),
00069 m_index(-1),
00070 m_phi(0.0),
00071 m_hasElementPotentials(false),
00072 m_chargeNeutralityNecessary(false),
00073 m_ssConvention(cSS_CONVENTION_TEMPERATURE)
00074 {
00075
00076
00077
00078 *this = operator=(right);
00079 }
00080
00081
00082
00083
00084
00085
00086
00087 ThermoPhase& ThermoPhase::
00088 operator=(const ThermoPhase &right) {
00089
00090
00091
00092 if (this == &right) return *this;
00093
00094
00095
00096
00097 for (int k = 0; k < m_kk; k++) {
00098 if (!m_speciesData[k]) {
00099 delete m_speciesData[k];
00100 }
00101 }
00102 if (m_spthermo) {
00103 delete m_spthermo;
00104 }
00105
00106
00107
00108
00109 (void)Phase::operator=(right);
00110
00111
00112
00113
00114
00115 m_spthermo = (right.m_spthermo)->duplMyselfAsSpeciesThermo();
00116
00117
00118
00119
00120 m_speciesData.resize(m_kk);
00121 for (int k = 0; k < m_kk; k++) {
00122 m_speciesData[k] = new XML_Node(*(right.m_speciesData[k]));
00123 }
00124
00125 m_index = right.m_index;
00126 m_phi = right.m_phi;
00127 m_lambdaRRT = right.m_lambdaRRT;
00128 m_hasElementPotentials = right.m_hasElementPotentials;
00129 m_chargeNeutralityNecessary = right.m_chargeNeutralityNecessary;
00130 m_ssConvention = right.m_ssConvention;
00131 return *this;
00132 }
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145 ThermoPhase *ThermoPhase::duplMyselfAsThermoPhase() const {
00146 ThermoPhase* tp = new ThermoPhase(*this);
00147 return tp;
00148 }
00149
00150 int ThermoPhase::activityConvention() const {
00151 return cAC_CONVENTION_MOLAR;
00152 }
00153
00154 int ThermoPhase::standardStateConvention() const {
00155 return m_ssConvention;
00156 }
00157
00158 doublereal ThermoPhase::logStandardConc(int k) const {
00159 return log(standardConcentration(k));
00160 }
00161
00162 void ThermoPhase::getActivities(doublereal* a) const {
00163 getActivityConcentrations(a);
00164 int nsp = nSpecies();
00165 int k;
00166 for (k = 0; k < nsp; k++) a[k] /= standardConcentration(k);
00167 }
00168
00169 void ThermoPhase::getLNActivityCoefficients(doublereal *const lnac) const {
00170 getActivityCoefficients(lnac);
00171 for (int k = 0; k < m_kk; k++) {
00172 lnac[k] = std::log(lnac[k]);
00173 }
00174 }
00175
00176 void ThermoPhase::setState_TPX(doublereal t, doublereal p,
00177 const doublereal* x) {
00178 setMoleFractions(x); setTemperature(t); setPressure(p);
00179 }
00180
00181 void ThermoPhase::setState_TPX(doublereal t, doublereal p,
00182 compositionMap& x) {
00183 setMoleFractionsByName(x); setTemperature(t); setPressure(p);
00184 }
00185
00186 void ThermoPhase::setState_TPX(doublereal t, doublereal p,
00187 const std::string& x) {
00188 compositionMap xx;
00189 int kk = nSpecies();
00190 for (int k = 0; k < kk; k++) xx[speciesName(k)] = -1.0;
00191 try {
00192 parseCompString(x, xx);
00193 }
00194 catch (CanteraError) {
00195 throw CanteraError("setState_TPX",
00196 "Unknown species in composition map: "+ x);
00197 }
00198 setMoleFractionsByName(xx); setTemperature(t); setPressure(p);
00199 }
00200
00201 void ThermoPhase::setState_TPY(doublereal t, doublereal p,
00202 const doublereal* y) {
00203 setMassFractions(y); setTemperature(t); setPressure(p);
00204 }
00205
00206 void ThermoPhase::setState_TPY(doublereal t, doublereal p,
00207 compositionMap& y) {
00208 setMassFractionsByName(y); setTemperature(t); setPressure(p);
00209 }
00210
00211 void ThermoPhase::setState_TPY(doublereal t, doublereal p,
00212 const std::string& y) {
00213 compositionMap yy;
00214 int kk = nSpecies();
00215 for (int k = 0; k < kk; k++) yy[speciesName(k)] = -1.0;
00216 try {
00217 parseCompString(y, yy);
00218 }
00219 catch (CanteraError) {
00220 throw CanteraError("setState_TPY",
00221 "Unknown species in composition map: "+ y);
00222 }
00223 setMassFractionsByName(yy); setTemperature(t); setPressure(p);
00224 }
00225
00226 void ThermoPhase::setState_TP(doublereal t, doublereal p) {
00227 setTemperature(t); setPressure(p);
00228 }
00229
00230 void ThermoPhase::setState_PX(doublereal p, doublereal* x) {
00231 setMoleFractions(x); setPressure(p);
00232 }
00233
00234 void ThermoPhase::setState_PY(doublereal p, doublereal* y) {
00235 setMassFractions(y); setPressure(p);
00236 }
00237
00238 void ThermoPhase::setState_HP(doublereal Htarget, doublereal p,
00239 doublereal dTtol) {
00240 setState_HPorUV(Htarget, p, dTtol, false);
00241 }
00242
00243 void ThermoPhase::setState_UV(doublereal u, doublereal v,
00244 doublereal dTtol) {
00245 setState_HPorUV(u, v, dTtol, true);
00246 }
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258 void ThermoPhase::setState_HPorUV(doublereal Htarget, doublereal p,
00259 doublereal dTtol, bool doUV) {
00260 doublereal dt;
00261 doublereal Hmax = 0.0, Hmin = 0.0;;
00262 doublereal v = 0.0;
00263
00264
00265 if (doUV) {
00266 v = p;
00267 if (v < 1.0E-300) {
00268 throw CanteraError("setState_HPorUV (UV)",
00269 "Input specific volume is too small or negative. v = " + fp2str(v));
00270 }
00271 setDensity(1.0/v);
00272 } else {
00273 if (p < 1.0E-300) {
00274 throw CanteraError("setState_HPorUV (HP)",
00275 "Input pressure is too small or negative. p = " + fp2str(p));
00276 }
00277 setPressure(p);
00278 }
00279 double Tmax = maxTemp() + 0.1;
00280 double Tmin = minTemp() - 0.1;
00281
00282
00283
00284 double Tnew = temperature();
00285 double Tinit = Tnew;
00286 if (Tnew > Tmax) {
00287 Tnew = Tmax - 1.0;
00288 if (doUV) {
00289 setTemperature(Tnew);
00290 } else {
00291 setState_TP(Tnew, p);
00292 }
00293 }
00294 if (Tnew < Tmin) {
00295 Tnew = Tmin + 1.0;
00296 if (doUV) {
00297 setTemperature(Tnew);
00298 } else {
00299 setState_TP(Tnew, p);
00300 }
00301 }
00302
00303 double Hnew = 0.0;
00304 double Cpnew = 0.0;
00305 if (doUV) {
00306 Hnew = intEnergy_mass();
00307 Cpnew = cv_mass();
00308 } else {
00309 Hnew = enthalpy_mass();
00310 Cpnew = cp_mass();
00311 }
00312 double Htop = Hnew;
00313 double Ttop = Tnew;
00314 double Hbot = Hnew;
00315 double Tbot = Tnew;
00316 double Told = Tnew;
00317 double Hold = Hnew;
00318
00319 bool ignoreBounds = false;
00320
00321
00322
00323 bool unstablePhase = false;
00324
00325
00326 double Tunstable = -1.0;
00327 bool unstablePhaseNew = false;
00328
00329
00330
00331 for (int n = 0; n < 500; n++) {
00332 Told = Tnew;
00333 Hold = Hnew;
00334 double cpd = Cpnew;
00335 if (cpd < 0.0) {
00336 unstablePhase = true;
00337 Tunstable = Tnew;
00338 }
00339 dt = (Htarget - Hold)/cpd;
00340
00341
00342 if (dt > 100.0) dt = 100.0;
00343 else if (dt < -100.0) dt = -100.0;
00344
00345
00346 Tnew = Told + dt;
00347
00348
00349
00350
00351 if (dt > 0.0) {
00352 if (!unstablePhase) {
00353 if (Htop > Htarget) {
00354 if (Tnew > (0.75 * Ttop + 0.25 * Told)) {
00355 dt = 0.75 * (Ttop - Told);
00356 Tnew = Told + dt;
00357 }
00358 }
00359 } else {
00360 if (Hbot < Htarget) {
00361 if (Tnew < (0.75 * Tbot + 0.25 * Told)) {
00362 dt = 0.75 * (Tbot - Told);
00363 Tnew = Told + dt;
00364 }
00365 }
00366 }
00367 } else {
00368 if (!unstablePhase) {
00369 if (Hbot < Htarget) {
00370 if (Tnew < (0.75 * Tbot + 0.25 * Told)) {
00371 dt = 0.75 * (Tbot - Told);
00372 Tnew = Told + dt;
00373 }
00374 }
00375 } else {
00376 if (Htop > Htarget) {
00377 if (Tnew > (0.75 * Ttop + 0.25 * Told)) {
00378 dt = 0.75 * (Ttop - Told);
00379 Tnew = Told + dt;
00380 }
00381 }
00382 }
00383 }
00384
00385 if (Tnew > Tmax) {
00386 if (!ignoreBounds) {
00387 if (doUV) {
00388 setTemperature(Tmax);
00389 Hmax = intEnergy_mass();
00390 } else {
00391 setState_TP(Tmax, p);
00392 Hmax = enthalpy_mass();
00393 }
00394 if (Hmax >= Htarget) {
00395 if (Htop < Htarget) {
00396 Ttop = Tmax;
00397 Htop = Hmax;
00398 }
00399 } else {
00400 Tnew = Tmax + 1.0;
00401 ignoreBounds = true;
00402 }
00403 }
00404 }
00405 if (Tnew < Tmin) {
00406 if (!ignoreBounds) {
00407 if (doUV) {
00408 setTemperature(Tmin);
00409 Hmin = intEnergy_mass();
00410 } else {
00411 setState_TP(Tmin, p);
00412 Hmin = enthalpy_mass();
00413 }
00414 if (Hmin <= Htarget) {
00415 if (Hbot > Htarget) {
00416 Tbot = Tmin;
00417 Hbot = Hmin;
00418 }
00419 } else {
00420 Tnew = Tmin - 1.0;
00421 ignoreBounds = true;
00422 }
00423 }
00424 }
00425
00426
00427
00428
00429 for (int its = 0; its < 10; its++) {
00430 Tnew = Told + dt;
00431 if (doUV) {
00432 setTemperature(Tnew);
00433 Hnew = intEnergy_mass();
00434 Cpnew = cv_mass();
00435 } else {
00436 setState_TP(Tnew, p);
00437 Hnew = enthalpy_mass();
00438 Cpnew = cp_mass();
00439 }
00440 if (Cpnew < 0.0) {
00441 unstablePhaseNew = true;
00442 Tunstable = Tnew;
00443 } else {
00444 unstablePhaseNew = false;
00445 break;
00446 }
00447 if (unstablePhase == false) {
00448 if (unstablePhaseNew == true) {
00449 dt *= 0.25;
00450 }
00451 }
00452 }
00453
00454 if (Hnew == Htarget) {
00455 return;
00456 } else if (Hnew > Htarget) {
00457 if ((Htop < Htarget) || (Hnew < Htop)) {
00458 Htop = Hnew;
00459 Ttop = Tnew;
00460 }
00461 } else if (Hnew < Htarget) {
00462 if ((Hbot > Htarget) || (Hnew > Hbot)) {
00463 Hbot = Hnew;
00464 Tbot = Tnew;
00465 }
00466 }
00467
00468 double Herr = Htarget - Hnew;
00469 double acpd = MAX(fabs(cpd), 1.0E-5);
00470 double denom = MAX(fabs(Htarget), acpd * dTtol);
00471 double HConvErr = fabs((Herr)/denom);
00472 if (HConvErr < 0.00001 *dTtol) {
00473 return;
00474 }
00475 if (fabs(dt) < dTtol) {
00476 return;
00477 }
00478
00479 }
00480
00481
00482
00483
00484
00485 string ErrString = "No convergence in 500 iterations\n";
00486 if (doUV) {
00487 ErrString += "\tTarget Internal Energy = " + fp2str(Htarget) + "\n";
00488 ErrString += "\tCurrent Specific Volume = " + fp2str(v) + "\n";
00489 ErrString += "\tStarting Temperature = " + fp2str(Tinit) + "\n";
00490 ErrString += "\tCurrent Temperature = " + fp2str(Tnew) + "\n";
00491 ErrString += "\tCurrent Internal Energy = " + fp2str(Hnew) + "\n";
00492 ErrString += "\tCurrent Delta T = " + fp2str(dt) + "\n";
00493 } else {
00494 ErrString += "\tTarget Enthalpy = " + fp2str(Htarget) + "\n";
00495 ErrString += "\tCurrent Pressure = " + fp2str(p) + "\n";
00496 ErrString += "\tStarting Temperature = " + fp2str(Tinit) + "\n";
00497 ErrString += "\tCurrent Temperature = " + fp2str(Tnew) + "\n";
00498 ErrString += "\tCurrent Enthalpy = " + fp2str(Hnew) + "\n";
00499 ErrString += "\tCurrent Delta T = " + fp2str(dt) + "\n";
00500 }
00501 if (unstablePhase) {
00502 ErrString += "\t - The phase became unstable (Cp < 0) T_unstable_last = "
00503 + fp2str(Tunstable) + "\n";
00504 }
00505 if (doUV) {
00506 throw CanteraError("setState_HPorUV (UV)", ErrString);
00507 } else {
00508 throw CanteraError("setState_HPorUV (HP)", ErrString);
00509 }
00510 }
00511
00512 void ThermoPhase::setState_SP(doublereal Starget, doublereal p,
00513 doublereal dTtol) {
00514 setState_SPorSV(Starget, p, dTtol, false);
00515 }
00516
00517 void ThermoPhase::setState_SV(doublereal Starget, doublereal v,
00518 doublereal dTtol) {
00519 setState_SPorSV(Starget, v, dTtol, true);
00520 }
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532 void ThermoPhase::setState_SPorSV(doublereal Starget, doublereal p,
00533 doublereal dTtol, bool doSV) {
00534 doublereal v = 0.0;
00535 doublereal dt;
00536 if (doSV) {
00537 v = p;
00538 if (v < 1.0E-300) {
00539 throw CanteraError("setState_SPorSV (SV)",
00540 "Input specific volume is too small or negative. v = " + fp2str(v));
00541 }
00542 setDensity(1.0/v);
00543 } else {
00544 if (p < 1.0E-300) {
00545 throw CanteraError("setState_SPorSV (SP)",
00546 "Input pressure is too small or negative. p = " + fp2str(p));
00547 }
00548 setPressure(p);
00549 }
00550 double Tmax = maxTemp() + 0.1;
00551 double Tmin = minTemp() - 0.1;
00552
00553
00554
00555 double Tnew = temperature();
00556 double Tinit = Tnew;
00557 if (Tnew > Tmax) {
00558 Tnew = Tmax - 1.0;
00559 if (doSV) {
00560 setTemperature(Tnew);
00561 } else {
00562 setState_TP(Tnew, p);
00563 }
00564 }
00565 if (Tnew < Tmin) {
00566 Tnew = Tmin + 1.0;
00567 if (doSV) {
00568 setTemperature(Tnew);
00569 } else {
00570 setState_TP(Tnew, p);
00571 }
00572 }
00573
00574 double Snew = entropy_mass();
00575 double Cpnew = 0.0;
00576 if (doSV) {
00577 Cpnew = cv_mass();
00578 } else {
00579 Cpnew = cp_mass();
00580 }
00581
00582 double Stop = Snew;
00583 double Ttop = Tnew;
00584 double Sbot = Snew;
00585 double Tbot = Tnew;
00586 double Told = Tnew;
00587 double Sold = Snew;
00588
00589 bool ignoreBounds = false;
00590
00591
00592
00593 bool unstablePhase = false;
00594 double Tunstable = -1.0;
00595 bool unstablePhaseNew = false;
00596
00597
00598
00599 for (int n = 0; n < 500; n++) {
00600 Told = Tnew;
00601 Sold = Snew;
00602 double cpd = Cpnew;
00603 if (cpd < 0.0) {
00604 unstablePhase = true;
00605 Tunstable = Tnew;
00606 }
00607 dt = (Starget - Sold)*Told/cpd;
00608
00609
00610 if (dt > 100.0) dt = 100.0;
00611 else if (dt < -100.0) dt = -100.0;
00612 Tnew = Told + dt;
00613
00614 if (dt > 0.0) {
00615 if (!unstablePhase) {
00616 if (Stop > Starget) {
00617 if (Tnew > Ttop) {
00618 dt = 0.75 * (Ttop - Told);
00619 Tnew = Told + dt;
00620 }
00621 }
00622 } else {
00623 if (Sbot < Starget) {
00624 if (Tnew < Tbot) {
00625 dt = 0.75 * (Tbot - Told);
00626 Tnew = Told + dt;
00627 }
00628 }
00629 }
00630 } else {
00631 if (!unstablePhase) {
00632 if (Sbot < Starget) {
00633 if (Tnew < Tbot) {
00634 dt = 0.75 * (Tbot - Told);
00635 Tnew = Told + dt;
00636 }
00637 }
00638 } else {
00639 if (Stop > Starget) {
00640 if (Tnew > Ttop) {
00641 dt = 0.75 * (Ttop - Told);
00642 Tnew = Told + dt;
00643 }
00644 }
00645 }
00646 }
00647
00648 if (Tnew > Tmax) {
00649 if (!ignoreBounds) {
00650 if (doSV) {
00651 setTemperature(Tmax);
00652 } else {
00653 setState_TP(Tmax, p);
00654 }
00655 double Smax = entropy_mass();
00656 if (Smax >= Starget) {
00657 if (Stop < Starget) {
00658 Ttop = Tmax;
00659 Stop = Smax;
00660 }
00661 } else {
00662 Tnew = Tmax + 1.0;
00663 ignoreBounds = true;
00664 }
00665 }
00666 }
00667 if (Tnew < Tmin) {
00668 if (!ignoreBounds) {
00669 if (doSV) {
00670 setTemperature(Tmin);
00671 } else {
00672 setState_TP(Tmin, p);
00673 }
00674 double Smin = enthalpy_mass();
00675 if (Smin <= Starget) {
00676 if (Sbot > Starget) {
00677 Sbot = Tmin;
00678 Sbot = Smin;
00679 }
00680 } else {
00681 Tnew = Tmin - 1.0;
00682 ignoreBounds = true;
00683 }
00684 }
00685 }
00686
00687
00688
00689
00690 for (int its = 0; its < 10; its++) {
00691 Tnew = Told + dt;
00692 if (doSV) {
00693 setTemperature(Tnew);
00694 Cpnew = cv_mass();
00695 } else {
00696 setState_TP(Tnew, p);
00697 Cpnew = cp_mass();
00698 }
00699 Snew = entropy_mass();
00700 if (Cpnew < 0.0) {
00701 unstablePhaseNew = true;
00702 Tunstable = Tnew;
00703 } else {
00704 unstablePhaseNew = false;
00705 break;
00706 }
00707 if (unstablePhase == false) {
00708 if (unstablePhaseNew == true) {
00709 dt *= 0.25;
00710 }
00711 }
00712 }
00713
00714 if (Snew == Starget) {
00715 return;
00716 } else if (Snew > Starget) {
00717 if ((Stop < Starget) || (Snew < Stop)) {
00718 Stop = Snew;
00719 Ttop = Tnew;
00720 }
00721 } else if (Snew < Starget) {
00722 if ((Sbot > Starget) || (Snew > Sbot)) {
00723 Sbot = Snew;
00724 Tbot = Tnew;
00725 }
00726 }
00727
00728 double Serr = Starget - Snew;
00729 double acpd = MAX(fabs(cpd), 1.0E-5);
00730 double denom = MAX(fabs(Starget), acpd * dTtol);
00731 double SConvErr = fabs((Serr * Tnew)/denom);
00732 if (SConvErr < 0.00001 *dTtol) {
00733 return;
00734 }
00735 if (fabs(dt) < dTtol) {
00736 return;
00737 }
00738 }
00739
00740
00741
00742
00743
00744 string ErrString = "No convergence in 500 iterations\n";
00745 if (doSV) {
00746 ErrString += "\tTarget Entropy = " + fp2str(Starget) + "\n";
00747 ErrString += "\tCurrent Specific Volume = " + fp2str(v) + "\n";
00748 ErrString += "\tStarting Temperature = " + fp2str(Tinit) + "\n";
00749 ErrString += "\tCurrent Temperature = " + fp2str(Tnew) + "\n";
00750 ErrString += "\tCurrent Entropy = " + fp2str(Snew) + "\n";
00751 ErrString += "\tCurrent Delta T = " + fp2str(dt) + "\n";
00752 } else {
00753 ErrString += "\tTarget Entropy = " + fp2str(Starget) + "\n";
00754 ErrString += "\tCurrent Pressure = " + fp2str(p) + "\n";
00755 ErrString += "\tStarting Temperature = " + fp2str(Tinit) + "\n";
00756 ErrString += "\tCurrent Temperature = " + fp2str(Tnew) + "\n";
00757 ErrString += "\tCurrent Entropy = " + fp2str(Snew) + "\n";
00758 ErrString += "\tCurrent Delta T = " + fp2str(dt) + "\n";
00759 }
00760 if (unstablePhase) {
00761 ErrString += "\t - The phase became unstable (Cp < 0) T_unstable_last = "
00762 + fp2str(Tunstable) + "\n";
00763 }
00764 if (doSV) {
00765 throw CanteraError("setState_SPorSV (SV)", ErrString);
00766 } else {
00767 throw CanteraError("setState_SPorSV (SP)", ErrString);
00768 }
00769 }
00770
00771 doublereal ThermoPhase::err(std::string msg) const {
00772 throw CanteraError("ThermoPhase","Base class method "
00773 +msg+" called. Equation of state type: "+int2str(eosType()));
00774 return 0.0;
00775 }
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804 void ThermoPhase::getUnitsStandardConc(double *uA, int k, int sizeUA) const {
00805 for (int i = 0; i < sizeUA; i++) {
00806 if (i == 0) uA[0] = 1.0;
00807 if (i == 1) uA[1] = -nDim();
00808 if (i == 2) uA[2] = 0.0;
00809 if (i == 3) uA[3] = 0.0;
00810 if (i == 4) uA[4] = 0.0;
00811 if (i == 5) uA[5] = 0.0;
00812 }
00813 }
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830 void ThermoPhase::initThermoFile(std::string inputFile, std::string id) {
00831
00832 if (inputFile.size() == 0) {
00833 throw CanteraError("ThermoPhase::initThermoFile",
00834 "input file is null");
00835 }
00836 string path = findInputFile(inputFile);
00837 ifstream fin(path.c_str());
00838 if (!fin) {
00839 throw CanteraError("initThermoFile","could not open "
00840 +path+" for reading.");
00841 }
00842
00843
00844
00845
00846 XML_Node &phaseNode_XML = xml();
00847 XML_Node *fxml = new XML_Node();
00848 fxml->build(fin);
00849 XML_Node *fxml_phase = findXMLPhase(fxml, id);
00850 if (!fxml_phase) {
00851 throw CanteraError("ThermoPhase::initThermo",
00852 "ERROR: Can not find phase named " +
00853 id + " in file named " + inputFile);
00854 }
00855 fxml_phase->copy(&phaseNode_XML);
00856 initThermoXML(*fxml_phase, id);
00857 delete fxml;
00858 }
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879 void ThermoPhase::initThermoXML(XML_Node& phaseNode, std::string id) {
00880
00881
00882
00883
00884 if (phaseNode.hasChild("state")) {
00885 XML_Node& stateNode = phaseNode.child("state");
00886 setStateFromXML(stateNode);
00887 }
00888 setReferenceComposition(0);
00889 }
00890
00891 void ThermoPhase::setReferenceComposition(const doublereal *const x) {
00892 xMol_Ref.resize(m_kk);
00893 if (x) {
00894 for (int k = 0; k < m_kk; k++) {
00895 xMol_Ref[k] = x[k];
00896 }
00897 } else {
00898 getMoleFractions(DATA_PTR(xMol_Ref));
00899 }
00900 double sum = -1.0;
00901 for (int k = 0; k < m_kk; k++) {
00902 sum += xMol_Ref[k];
00903 }
00904 if (fabs(sum) > 1.0E-11) {
00905 throw CanteraError("ThermoPhase::setReferenceComposition",
00906 "input mole fractions don't sum to 1.0");
00907 }
00908
00909 }
00910
00911 void ThermoPhase::getReferenceComposition( doublereal *const x) const {
00912 for (int k = 0; k < m_kk; k++) {
00913 x[k] = xMol_Ref[k];
00914 }
00915 }
00916
00917
00918
00919
00920
00921
00922
00923
00924
00925
00926
00927
00928
00929
00930
00931
00932 void ThermoPhase::initThermo() {
00933
00934 if (m_kk <= 0) {
00935 throw CanteraError("ThermoPhase::initThermo()",
00936 "Number of species is less than or equal to zero");
00937 }
00938 xMol_Ref.resize(m_kk, 0.0);
00939 }
00940
00941 void ThermoPhase::saveSpeciesData(const int k, const XML_Node* const data) {
00942 if ((int) m_speciesData.size() < (k + 1)) {
00943 m_speciesData.resize(k+1, 0);
00944 }
00945 m_speciesData[k] = new XML_Node(*data);
00946 }
00947
00948
00949
00950 const std::vector<const XML_Node *> & ThermoPhase::speciesData() const {
00951 if ((int) m_speciesData.size() != m_kk) {
00952 throw CanteraError("ThermoPhase::speciesData",
00953 "m_speciesData is the wrong size");
00954 }
00955 return m_speciesData;
00956 }
00957
00958
00959
00960
00961 void ThermoPhase::setStateFromXML(const XML_Node& state) {
00962 string comp = getChildValue(state,"moleFractions");
00963 if (comp != "")
00964 setMoleFractionsByName(comp);
00965 else {
00966 comp = getChildValue(state,"massFractions");
00967 if (comp != "")
00968 setMassFractionsByName(comp);
00969 }
00970 if (state.hasChild("temperature")) {
00971 double t = getFloat(state, "temperature", "temperature");
00972 setTemperature(t);
00973 }
00974 if (state.hasChild("pressure")) {
00975 double p = getFloat(state, "pressure", "pressure");
00976 setPressure(p);
00977 }
00978 if (state.hasChild("density")) {
00979 double rho = getFloat(state, "density", "density");
00980 setDensity(rho);
00981 }
00982 }
00983
00984
00985
00986
00987
00988
00989
00990
00991
00992
00993 void ThermoPhase::setElementPotentials(const vector_fp& lambda) {
00994 doublereal rrt = 1.0/(GasConstant* temperature());
00995 int mm = nElements();
00996 if (lambda.size() < (size_t) mm) {
00997 throw CanteraError("setElementPotentials", "lambda too small");
00998 }
00999 if (!m_hasElementPotentials) {
01000 m_lambdaRRT.resize(mm);
01001 }
01002 for (int m = 0; m < mm; m++) {
01003 m_lambdaRRT[m] = lambda[m] * rrt;
01004 }
01005 m_hasElementPotentials = true;
01006 }
01007
01008
01009
01010
01011
01012
01013
01014
01015 bool ThermoPhase::getElementPotentials(doublereal* lambda) const {
01016 doublereal rt = GasConstant* temperature();
01017 int mm = nElements();
01018 if (m_hasElementPotentials) {
01019 for (int m = 0; m < mm; m++) {
01020 lambda[m] = m_lambdaRRT[m] * rt;
01021 }
01022 }
01023 return (m_hasElementPotentials);
01024 }
01025
01026
01027
01028
01029 std::string ThermoPhase::report(bool show_thermo) const {
01030 char p[800];
01031 string s = "";
01032 try {
01033 if (name() != "") {
01034 sprintf(p, " \n %s:\n", name().c_str());
01035 s += p;
01036 }
01037 sprintf(p, " \n temperature %12.6g K\n", temperature());
01038 s += p;
01039 sprintf(p, " pressure %12.6g Pa\n", pressure());
01040 s += p;
01041 sprintf(p, " density %12.6g kg/m^3\n", density());
01042 s += p;
01043 sprintf(p, " mean mol. weight %12.6g amu\n", meanMolecularWeight());
01044 s += p;
01045
01046 doublereal phi = electricPotential();
01047 if (phi != 0.0) {
01048 sprintf(p, " potential %12.6g V\n", phi);
01049 s += p;
01050 }
01051 if (show_thermo) {
01052 sprintf(p, " \n");
01053 s += p;
01054 sprintf(p, " 1 kg 1 kmol\n");
01055 s += p;
01056 sprintf(p, " ----------- ------------\n");
01057 s += p;
01058 sprintf(p, " enthalpy %12.6g %12.4g J\n",
01059 enthalpy_mass(), enthalpy_mole());
01060 s += p;
01061 sprintf(p, " internal energy %12.6g %12.4g J\n",
01062 intEnergy_mass(), intEnergy_mole());
01063 s += p;
01064 sprintf(p, " entropy %12.6g %12.4g J/K\n",
01065 entropy_mass(), entropy_mole());
01066 s += p;
01067 sprintf(p, " Gibbs function %12.6g %12.4g J\n",
01068 gibbs_mass(), gibbs_mole());
01069 s += p;
01070 sprintf(p, " heat capacity c_p %12.6g %12.4g J/K\n",
01071 cp_mass(), cp_mole());
01072 s += p;
01073 try {
01074 sprintf(p, " heat capacity c_v %12.6g %12.4g J/K\n",
01075 cv_mass(), cv_mole());
01076 s += p;
01077 }
01078 catch(CanteraError) {
01079 sprintf(p, " heat capacity c_v <not implemented> \n");
01080 s += p;
01081 }
01082 }
01083
01084 int kk = nSpecies();
01085 array_fp x(kk);
01086 array_fp y(kk);
01087 array_fp mu(kk);
01088 getMoleFractions(&x[0]);
01089 getMassFractions(&y[0]);
01090 getChemPotentials(&mu[0]);
01091 doublereal rt = GasConstant * temperature();
01092 int k;
01093
01094
01095 if (show_thermo) {
01096 sprintf(p, " \n X "
01097 " Y Chem. Pot. / RT \n");
01098 s += p;
01099 sprintf(p, " ------------- "
01100 "------------ ------------\n");
01101 s += p;
01102 for (k = 0; k < kk; k++) {
01103 if (x[k] > SmallNumber) {
01104 sprintf(p, "%18s %12.6g %12.6g %12.6g\n",
01105 speciesName(k).c_str(), x[k], y[k], mu[k]/rt);
01106 }
01107 else {
01108 sprintf(p, "%18s %12.6g %12.6g \n",
01109 speciesName(k).c_str(), x[k], y[k]);
01110 }
01111 s += p;
01112 }
01113 }
01114 else {
01115 sprintf(p, " \n X"
01116 "Y\n");
01117 s += p;
01118 sprintf(p, " -------------"
01119 " ------------\n");
01120 s += p;
01121 for (k = 0; k < kk; k++) {
01122 sprintf(p, "%18s %12.6g %12.6g\n",
01123 speciesName(k).c_str(), x[k], y[k]);
01124 s += p;
01125 }
01126 }
01127 }
01128
01129 catch (CanteraError) {
01130 ;
01131 }
01132 return s;
01133 }
01134
01135
01136 }