00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #ifdef WIN32
00015 #pragma warning(disable:4786)
00016 #endif
00017
00018
00019 #include "SpeciesThermoFactory.h"
00020 using namespace std;
00021
00022 #include "SpeciesThermo.h"
00023 #include "NasaThermo.h"
00024 #include "ShomateThermo.h"
00025 #include "SimpleThermo.h"
00026 #include "GeneralSpeciesThermo.h"
00027 #include "Mu0Poly.h"
00028 #include "Nasa9PolyMultiTempRegion.h"
00029 #include "Nasa9Poly1.h"
00030
00031 #ifdef WITH_ADSORBATE
00032 #include "AdsorbateThermo.h"
00033 #endif
00034
00035 #include "SpeciesThermoMgr.h"
00036 #include "speciesThermoTypes.h"
00037 #include "VPSSMgr.h"
00038 #include "VPStandardStateTP.h"
00039
00040 #include "xml.h"
00041 #include "ctml.h"
00042
00043 #include <cmath>
00044
00045 using namespace ctml;
00046
00047
00048 namespace Cantera {
00049
00050 SpeciesThermoFactory* SpeciesThermoFactory::s_factory = 0;
00051
00052 #if defined(THREAD_SAFE_CANTERA)
00053 boost::mutex SpeciesThermoFactory::species_thermo_mutex ;
00054 #endif
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068 static void getSpeciesThermoTypes(std::vector<XML_Node *> & spDataNodeList,
00069 int& has_nasa, int& has_shomate, int& has_simple,
00070 int &has_other) {
00071 size_t ns = spDataNodeList.size();
00072 for (size_t n = 0; n < ns; n++) {
00073 XML_Node* spNode = spDataNodeList[n];
00074 if (spNode->hasChild("standardState")) {
00075 const XML_Node& ss = spNode->child("standardState");
00076 string mname = ss["model"];
00077 if (mname == "water" || mname == "waterIAPWS") {
00078 has_other = 1;
00079 continue;
00080 }
00081 }
00082 if (spNode->hasChild("thermo")) {
00083 const XML_Node& th = spNode->child("thermo");
00084 if (th.hasChild("NASA")) {
00085 has_nasa = 1;
00086 } else if (th.hasChild("Shomate")) {
00087 has_shomate = 1;
00088 } else if (th.hasChild("MinEQ3")) {
00089 has_shomate = 1;
00090 } else if (th.hasChild("const_cp")) {
00091 has_simple = 1;
00092 } else if (th.hasChild("poly")) {
00093 if (th.child("poly")["order"] == "1") has_simple = 1;
00094 else throw CanteraError("newSpeciesThermo",
00095 "poly with order > 1 not yet supported");
00096 }
00097 else if (th.hasChild("Mu0")) {
00098 has_other = 1;
00099 } else if (th.hasChild("NASA9")) {
00100 has_other = 1;
00101 } else if (th.hasChild("NASA9MULTITEMP")) {
00102 has_other = 1;
00103 } else if (th.hasChild("adsorbate")) {
00104 has_other = 1;
00105 } else {
00106 has_other = 1;
00107
00108
00109 }
00110 } else {
00111 throw CanteraError("getSpeciesThermoTypes:",
00112 spNode->attrib("name") + " is missing the thermo XML node");
00113 }
00114 }
00115 }
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126 SpeciesThermoFactory* SpeciesThermoFactory::factory() {
00127 #if defined(THREAD_SAFE_CANTERA)
00128 boost::mutex::scoped_lock lock(species_thermo_mutex);
00129 #endif
00130 if (!s_factory) s_factory = new SpeciesThermoFactory;
00131 return s_factory;
00132 }
00133
00134
00135
00136
00137
00138
00139
00140 void SpeciesThermoFactory::deleteFactory() {
00141 #if defined(THREAD_SAFE_CANTERA)
00142 boost::mutex::scoped_lock lock(species_thermo_mutex);
00143 #endif
00144 if (s_factory) {
00145 delete s_factory;
00146 s_factory = 0;
00147 }
00148 }
00149
00150
00151
00152
00153
00154
00155
00156
00157 SpeciesThermoFactory::~SpeciesThermoFactory() {
00158 }
00159
00160
00161
00162
00163
00164 SpeciesThermo* SpeciesThermoFactory::newSpeciesThermo(std::vector<XML_Node*> & spDataNodeList) const {
00165 int inasa = 0, ishomate = 0, isimple = 0, iother = 0;
00166 try {
00167 getSpeciesThermoTypes(spDataNodeList, inasa, ishomate, isimple, iother);
00168 } catch (UnknownSpeciesThermoModel) {
00169 iother = 1;
00170 popError();
00171 }
00172 if (iother) {
00173
00174 return new GeneralSpeciesThermo();
00175 }
00176 return newSpeciesThermo(NASA*inasa
00177 + SHOMATE*ishomate + SIMPLE*isimple);
00178 }
00179
00180
00181
00182
00183
00184 SpeciesThermo* SpeciesThermoFactory::
00185 newSpeciesThermoOpt(std::vector<XML_Node*> & spDataNodeList) const {
00186 int inasa = 0, ishomate = 0, isimple = 0, iother = 0;
00187 try {
00188 getSpeciesThermoTypes(spDataNodeList, inasa, ishomate, isimple, iother);
00189 } catch (UnknownSpeciesThermoModel) {
00190 iother = 1;
00191 popError();
00192 }
00193
00194 if (iother) {
00195 return new GeneralSpeciesThermo();
00196 }
00197 return newSpeciesThermo(NASA*inasa
00198 + SHOMATE*ishomate + SIMPLE*isimple);
00199 }
00200
00201 SpeciesThermo* SpeciesThermoFactory::newSpeciesThermo(int type) const {
00202 switch (type) {
00203 case NASA:
00204 return new NasaThermo;
00205 case SHOMATE:
00206 return new ShomateThermo;
00207 case SIMPLE:
00208 return new SimpleThermo;
00209 case NASA + SHOMATE:
00210 return new SpeciesThermoDuo<NasaThermo, ShomateThermo>;
00211 case NASA + SIMPLE:
00212 return new SpeciesThermoDuo<NasaThermo, SimpleThermo>;
00213 case SHOMATE + SIMPLE:
00214 return new SpeciesThermoDuo<ShomateThermo, SimpleThermo>;
00215 default:
00216 throw UnknownSpeciesThermo("SpeciesThermoFactory::newSpeciesThermo",
00217 type);
00218 return 0;
00219 }
00220 }
00221
00222 SpeciesThermo* SpeciesThermoFactory::newSpeciesThermoManager(std::string &stype) const {
00223 std::string ltype = lowercase(stype);
00224 if (ltype == "nasa") {
00225 return new NasaThermo;
00226 } else if (ltype == "shomate") {
00227 return new ShomateThermo;
00228 } else if (ltype == "simple" || ltype == "constant_cp") {
00229 return new SimpleThermo;
00230 } else if (ltype == "nasa_shomate_duo") {
00231 return new SpeciesThermoDuo<NasaThermo, ShomateThermo>;
00232 } else if (ltype == "nasa_simple_duo") {
00233 return new SpeciesThermoDuo<NasaThermo, SimpleThermo>;
00234 } else if (ltype == "shomate_simple_duo") {
00235 return new SpeciesThermoDuo<ShomateThermo, SimpleThermo>;
00236 } else if (ltype == "general") {
00237 return new GeneralSpeciesThermo();
00238 } else if (ltype == "") {
00239 return (SpeciesThermo*) 0;
00240 } else {
00241 throw UnknownSpeciesThermo("SpeciesThermoFactory::newSpeciesThermoManager",
00242 stype);
00243 }
00244 return (SpeciesThermo*) 0;
00245 }
00246
00247
00248
00249
00250
00251 void NasaThermo::checkContinuity(std::string name, double tmid, const doublereal* clow,
00252 doublereal* chigh) {
00253
00254 doublereal cplow = poly4(tmid, clow);
00255 doublereal cphigh = poly4(tmid, chigh);
00256 doublereal delta = cplow - cphigh;
00257 if (fabs(delta/(fabs(cplow)+1.0E-4)) > 0.001) {
00258 writelog("\n\n**** WARNING ****\nFor species "+name+
00259 ", discontinuity in cp/R detected at Tmid = "
00260 +fp2str(tmid)+"\n");
00261 writelog("\tValue computed using low-temperature polynomial: "
00262 +fp2str(cplow)+".\n");
00263 writelog("\tValue computed using high-temperature polynomial: "
00264 +fp2str(cphigh)+".\n");
00265 }
00266
00267
00268 doublereal hrtlow = enthalpy_RT(tmid, clow);
00269 doublereal hrthigh = enthalpy_RT(tmid, chigh);
00270 delta = hrtlow - hrthigh;
00271 if (fabs(delta/(fabs(hrtlow)+cplow*tmid)) > 0.001) {
00272 writelog("\n\n**** WARNING ****\nFor species "+name+
00273 ", discontinuity in h/RT detected at Tmid = "
00274 +fp2str(tmid)+"\n");
00275 writelog("\tValue computed using low-temperature polynomial: "
00276 +fp2str(hrtlow)+".\n");
00277 writelog("\tValue computed using high-temperature polynomial: "
00278 +fp2str(hrthigh)+".\n");
00279 }
00280
00281
00282 doublereal srlow = entropy_R(tmid, clow);
00283 doublereal srhigh = entropy_R(tmid, chigh);
00284 delta = srlow - srhigh;
00285 if (fabs(delta/(fabs(srlow)+cplow)) > 0.001) {
00286 writelog("\n\n**** WARNING ****\nFor species "+name+
00287 ", discontinuity in s/R detected at Tmid = "
00288 +fp2str(tmid)+"\n");
00289 writelog("\tValue computed using low-temperature polynomial: "
00290 +fp2str(srlow)+".\n");
00291 writelog("\tValue computed using high-temperature polynomial: "
00292 +fp2str(srhigh)+".\n");
00293 }
00294 }
00295
00296
00297
00298
00299
00300
00301
00302
00303 static void installNasaThermoFromXML(std::string speciesName,
00304 SpeciesThermo& sp, int k,
00305 const XML_Node* f0ptr, const XML_Node* f1ptr) {
00306 doublereal tmin0, tmax0, tmin1, tmax1, tmin, tmid, tmax;
00307
00308 const XML_Node& f0 = *f0ptr;
00309
00310
00311 bool dualRange = false;
00312
00313
00314
00315 if (f1ptr) {dualRange = true;}
00316
00317 tmin0 = fpValue(f0["Tmin"]);
00318 tmax0 = fpValue(f0["Tmax"]);
00319
00320 doublereal p0 = OneAtm;
00321 if (f0.hasAttrib("P0")) {
00322 p0 = fpValue(f0["P0"]);
00323 }
00324 if (f0.hasAttrib("Pref")) {
00325 p0 = fpValue(f0["Pref"]);
00326 }
00327 p0 = OneAtm;
00328
00329 tmin1 = tmax0;
00330 tmax1 = tmin1 + 0.0001;
00331 if (dualRange) {
00332 tmin1 = fpValue((*f1ptr)["Tmin"]);
00333 tmax1 = fpValue((*f1ptr)["Tmax"]);
00334 }
00335
00336 vector_fp c0, c1;
00337 if (fabs(tmax0 - tmin1) < 0.01) {
00338
00339 tmin = tmin0;
00340 tmid = tmax0;
00341 tmax = tmax1;
00342 getFloatArray(f0.child("floatArray"), c0, false);
00343 if (dualRange)
00344 getFloatArray(f1ptr->child("floatArray"), c1, false);
00345 else {
00346
00347 c1.resize(7,0.0);
00348 copy(c0.begin(), c0.end(), c1.begin());
00349 }
00350 }
00351 else if (fabs(tmax1 - tmin0) < 0.01) {
00352
00353 tmin = tmin1;
00354 tmid = tmax1;
00355 tmax = tmax0;
00356 getFloatArray(f1ptr->child("floatArray"), c0, false);
00357 getFloatArray(f0.child("floatArray"), c1, false);
00358 }
00359 else {
00360 throw CanteraError("installNasaThermo",
00361 "non-continuous temperature ranges.");
00362 }
00363
00364
00365
00366 array_fp c(15);
00367 c[0] = tmid;
00368
00369 c[1] = c0[5];
00370 c[2] = c0[6];
00371 copy(c0.begin(), c0.begin()+5, c.begin() + 3);
00372 c[8] = c1[5];
00373 c[9] = c1[6];
00374 copy(c1.begin(), c1.begin()+5, c.begin() + 10);
00375 sp.install(speciesName, k, NASA, &c[0], tmin, tmax, p0);
00376 }
00377
00378 #ifdef INCL_NASA96
00379
00380
00381
00382
00383
00384 static void installNasa96ThermoFromXML(std::string speciesName,
00385 SpeciesThermo& sp, int k,
00386 const XML_Node* f0ptr, const XML_Node* f1ptr) {
00387 doublereal tmin0, tmax0, tmin1, tmax1, tmin, tmid, tmax;
00388
00389 const XML_Node& f0 = *f0ptr;
00390 bool dualRange = false;
00391 if (f1ptr) {dualRange = true;}
00392 tmin0 = fpValue(f0["Tmin"]);
00393 tmax0 = fpValue(f0["Tmax"]);
00394 tmin1 = tmax0;
00395 tmax1 = tmin1 + 0.0001;
00396 if (dualRange) {
00397 tmin1 = fpValue((*f1ptr)["Tmin"]);
00398 tmax1 = fpValue((*f1ptr)["Tmax"]);
00399 }
00400
00401
00402 doublereal p0 = OneAtm;
00403 if (f0.hasAttrib("P0")) {
00404 p0 = fpValue(f0["P0"]);
00405 }
00406 if (f0.hasAttrib("Pref")) {
00407 p0 = fpValue(f0["Pref"]);
00408 }
00409
00410 vector_fp c0, c1;
00411 if (fabs(tmax0 - tmin1) < 0.01) {
00412 tmin = tmin0;
00413 tmid = tmax0;
00414 tmax = tmax1;
00415 getFloatArray(f0.child("floatArray"), c0, false);
00416 if (dualRange)
00417 getFloatArray(f1ptr->child("floatArray"), c1, false);
00418 else {
00419 c1.resize(7,0.0);
00420 copy(c0.begin(), c0.end(), c1.begin());
00421 }
00422 }
00423 else if (fabs(tmax1 - tmin0) < 0.01) {
00424 tmin = tmin1;
00425 tmid = tmax1;
00426 tmax = tmax0;
00427 getFloatArray(f1ptr->child("floatArray"), c0, false);
00428 getFloatArray(f0.child("floatArray"), c1, false);
00429 }
00430 else {
00431 throw CanteraError("installNasaThermo",
00432 "non-continuous temperature ranges.");
00433 }
00434 array_fp c(15);
00435 c[0] = tmid;
00436 c[1] = c0[5];
00437 c[2] = c0[6];
00438 copy(c0.begin(), c0.begin()+5, c.begin() + 3);
00439 c[8] = c1[5];
00440 c[9] = c1[6];
00441 copy(c1.begin(), c1.begin()+5, c.begin() + 10);
00442 sp.install(speciesName, k, NASA, &c[0], tmin, tmax, p0);
00443 }
00444
00445 #endif
00446
00447 static doublereal LookupGe(const std::string& elemName, ThermoPhase *th_ptr) {
00448 #ifdef OLDWAY
00449 int num = sizeof(geDataTable) / sizeof(struct GeData);
00450 string s3 = elemName.substr(0,3);
00451 for (int i = 0; i < num; i++) {
00452
00453 if (s3 == geDataTable[i].name) {
00454 return (geDataTable[i].GeValue);
00455 }
00456 }
00457 throw CanteraError("LookupGe", "element " + s + " not found");
00458 return -1.0;
00459 #else
00460 int iE = th_ptr->elementIndex(elemName);
00461 if (iE < 0) {
00462 throw CanteraError("PDSS_HKFT::LookupGe", "element " + elemName + " not found");
00463 }
00464 doublereal geValue = th_ptr->entropyElement298(iE);
00465 if (geValue == ENTROPY298_UNKNOWN) {
00466 throw CanteraError("PDSS_HKFT::LookupGe",
00467 "element " + elemName + " doesn not have a supplied entropy298");
00468 }
00469 geValue *= (-298.15);
00470 return geValue;
00471 #endif
00472 }
00473
00474 static doublereal convertDGFormation(int k, ThermoPhase *th_ptr) {
00475
00476
00477
00478 int ne = th_ptr->nElements();
00479 doublereal na;
00480 doublereal ge;
00481 string ename;
00482
00483 doublereal totalSum = 0.0;
00484 for (int m = 0; m < ne; m++) {
00485 na = th_ptr->nAtoms(k, m);
00486 if (na > 0.0) {
00487 ename = th_ptr->elementName(m);
00488 ge = LookupGe(ename, th_ptr);
00489 totalSum += na * ge;
00490 }
00491 }
00492 return totalSum;
00493 }
00494
00495
00496
00497 static void installMinEQ3asShomateThermoFromXML(std::string speciesName,
00498 ThermoPhase *th_ptr,
00499 SpeciesThermo& sp, int k,
00500 const XML_Node* MinEQ3node) {
00501
00502 array_fp coef(15), c0(7, 0.0);
00503 std::string astring = (*MinEQ3node)["Tmin"];
00504 doublereal tmin0 = strSItoDbl(astring);
00505 astring = (*MinEQ3node)["Tmax"];
00506 doublereal tmax0 = strSItoDbl(astring);
00507 astring = (*MinEQ3node)["Pref"];
00508 doublereal p0 = strSItoDbl(astring);
00509
00510 doublereal deltaG_formation_pr_tr =
00511 getFloatDefaultUnits(*MinEQ3node, "DG0_f_Pr_Tr", "cal/gmol", "actEnergy");
00512 doublereal deltaH_formation_pr_tr =
00513 getFloatDefaultUnits(*MinEQ3node, "DH0_f_Pr_Tr", "cal/gmol", "actEnergy");
00514 doublereal Entrop_pr_tr = getFloatDefaultUnits(*MinEQ3node, "S0_Pr_Tr", "cal/gmol/K");
00515 doublereal a = getFloatDefaultUnits(*MinEQ3node, "a", "cal/gmol/K");
00516 doublereal b = getFloatDefaultUnits(*MinEQ3node, "b", "cal/gmol/K2");
00517 doublereal c = getFloatDefaultUnits(*MinEQ3node, "c", "cal-K/gmol");
00518 doublereal dg = deltaG_formation_pr_tr * 4.184 * 1.0E3;
00519 doublereal fac = convertDGFormation(k, th_ptr);
00520 doublereal Mu0_tr_pr = fac + dg;
00521 doublereal e = Entrop_pr_tr * 1.0E3 * 4.184;
00522 doublereal Hcalc = Mu0_tr_pr + 298.15 * e;
00523 doublereal DHjmol = deltaH_formation_pr_tr * 1.0E3 * 4.184;
00524
00525
00526
00527 if (fabs(Hcalc -DHjmol) > 10.* 1.0E6 * 4.184) {
00528 throw CanteraError("installMinEQ3asShomateThermoFromXML()",
00529 "DHjmol is not consistent with G and S" +
00530 fp2str(Hcalc) + " vs " + fp2str(DHjmol));
00531 }
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543 double As = a * 4.184;
00544 double Bs = b * 4.184 * 1000.;
00545 double Cs = 0.0;
00546 double Ds = 0.0;
00547 double Es = c * 4.184 / (1.0E6);
00548
00549 double t = 298.15 / 1000.;
00550 double H298smFs = As * t + Bs * t * t / 2.0 - Es / t;
00551
00552 double HcalcS = Hcalc / 1.0E6;
00553 double Fs = HcalcS - H298smFs;
00554
00555 double S298smGs = As * log(t) + Bs * t - Es/(2.0*t*t);
00556 double ScalcS = e / 1.0E3;
00557 double Gs = ScalcS - S298smGs;
00558
00559 c0[0] = As;
00560 c0[1] = Bs;
00561 c0[2] = Cs;
00562 c0[3] = Ds;
00563 c0[4] = Es;
00564 c0[5] = Fs;
00565 c0[6] = Gs;
00566
00567 coef[0] = tmax0 - 0.001;
00568 copy(c0.begin(), c0.begin()+7, coef.begin() + 1);
00569 copy(c0.begin(), c0.begin()+7, coef.begin() + 8);
00570 sp.install(speciesName, k, SHOMATE, &coef[0], tmin0, tmax0, p0);
00571 }
00572
00573
00574
00575
00576
00577
00578 static void installShomateThermoFromXML(std::string speciesName,
00579 SpeciesThermo& sp, int k,
00580 const XML_Node* f0ptr, const XML_Node* f1ptr) {
00581 doublereal tmin0, tmax0, tmin1, tmax1, tmin, tmid, tmax;
00582
00583 const XML_Node& f0 = *f0ptr;
00584 bool dualRange = false;
00585 if (f1ptr) {dualRange = true;}
00586 tmin0 = fpValue(f0["Tmin"]);
00587 tmax0 = fpValue(f0["Tmax"]);
00588 tmin1 = tmax0;
00589 tmax1 = tmin1 + 0.0001;
00590 if (dualRange) {
00591 tmin1 = fpValue((*f1ptr)["Tmin"]);
00592 tmax1 = fpValue((*f1ptr)["Tmax"]);
00593 }
00594
00595 vector_fp c0, c1;
00596 if (fabs(tmax0 - tmin1) < 0.01) {
00597 tmin = tmin0;
00598 tmid = tmax0;
00599 tmax = tmax1;
00600 getFloatArray(f0.child("floatArray"), c0, false);
00601 if (dualRange)
00602 getFloatArray(f1ptr->child("floatArray"), c1, false);
00603 else {
00604 c1.resize(7,0.0);
00605 copy(c0.begin(), c0.begin()+7, c1.begin());
00606 }
00607 }
00608 else if (fabs(tmax1 - tmin0) < 0.01) {
00609 tmin = tmin1;
00610 tmid = tmax1;
00611 tmax = tmax0;
00612 getFloatArray(f1ptr->child("floatArray"), c0, false);
00613 getFloatArray(f0.child("floatArray"), c1, false);
00614 }
00615 else {
00616 throw CanteraError("installShomateThermoFromXML",
00617 "non-continuous temperature ranges.");
00618 }
00619 array_fp c(15);
00620 c[0] = tmid;
00621 doublereal p0 = OneAtm;
00622 copy(c0.begin(), c0.begin()+7, c.begin() + 1);
00623 copy(c1.begin(), c1.begin()+7, c.begin() + 8);
00624 sp.install(speciesName, k, SHOMATE, &c[0], tmin, tmax, p0);
00625 }
00626
00627
00628
00629
00630
00631
00632
00633 static void installSimpleThermoFromXML(std::string speciesName,
00634 SpeciesThermo& sp, int k,
00635 const XML_Node& f) {
00636 doublereal tmin, tmax;
00637 tmin = fpValue(f["Tmin"]);
00638 tmax = fpValue(f["Tmax"]);
00639 if (tmax == 0.0) tmax = 1.0e30;
00640
00641 vector_fp c(4);
00642 c[0] = getFloat(f, "t0", "toSI");
00643 c[1] = getFloat(f, "h0", "toSI");
00644 c[2] = getFloat(f, "s0", "toSI");
00645 c[3] = getFloat(f, "cp0", "toSI");
00646 doublereal p0 = OneAtm;
00647 sp.install(speciesName, k, SIMPLE, &c[0], tmin, tmax, p0);
00648 }
00649
00650
00651
00652
00653
00654
00655
00656 static void installNasa9ThermoFromXML(std::string speciesName,
00657 SpeciesThermo& sp, int k,
00658 const std::vector<XML_Node*>& tp)
00659 {
00660 const XML_Node * fptr = tp[0];
00661 int nRegTmp = tp.size();
00662 int nRegions = 0;
00663 vector_fp cPoly;
00664 Nasa9Poly1 *np_ptr = 0;
00665 std::vector<Nasa9Poly1 *> regionPtrs;
00666 doublereal tmin, tmax, pref = OneAtm;
00667
00668 for (int i = 0; i < nRegTmp; i++) {
00669 fptr = tp[i];
00670 if (fptr) {
00671 if (fptr->name() == "NASA9") {
00672 if (fptr->hasChild("floatArray")) {
00673
00674 tmin = fpValue((*fptr)["Tmin"]);
00675 tmax = fpValue((*fptr)["Tmax"]);
00676 if ((*fptr).hasAttrib("P0")) {
00677 pref = fpValue((*fptr)["P0"]);
00678 }
00679 if ((*fptr).hasAttrib("Pref")) {
00680 pref = fpValue((*fptr)["Pref"]);
00681 }
00682
00683 getFloatArray(fptr->child("floatArray"), cPoly, false);
00684 if (cPoly.size() != 9) {
00685 throw CanteraError("installNasa9ThermoFromXML",
00686 "Expected 9 coeff polynomial");
00687 }
00688 np_ptr = new Nasa9Poly1(k, tmin, tmax, pref,
00689 DATA_PTR(cPoly));
00690 regionPtrs.push_back(np_ptr);
00691 nRegions++;
00692 }
00693 }
00694 }
00695 }
00696 if (nRegions == 0) {
00697 throw UnknownSpeciesThermoModel("installThermoForSpecies",
00698 speciesName, " " );
00699 } else if (nRegions == 1) {
00700 sp.install_STIT(np_ptr);
00701 } else {
00702 Nasa9PolyMultiTempRegion* npMulti_ptr = new Nasa9PolyMultiTempRegion(regionPtrs);
00703 sp.install_STIT(npMulti_ptr);
00704 }
00705 }
00706
00707
00708
00709
00710
00711
00712
00713
00714 #ifdef WITH_ADSORBATE
00715 static void installAdsorbateThermoFromXML(std::string speciesName,
00716 SpeciesThermo& sp, int k,
00717 const XML_Node& f) {
00718 vector_fp freqs;
00719 doublereal tmin, tmax, pref = OneAtm;
00720 int nfreq = 0;
00721 tmin = fpValue(f["Tmin"]);
00722 tmax = fpValue(f["Tmax"]);
00723 if (f.hasAttrib("P0")) {
00724 pref = fpValue(f["P0"]);
00725 }
00726 if (f.hasAttrib("Pref")) {
00727 pref = fpValue(f["Pref"]);
00728 }
00729 if (tmax == 0.0) tmax = 1.0e30;
00730
00731 if (f.hasChild("floatArray")) {
00732 getFloatArray(f.child("floatArray"), freqs, false);
00733 nfreq = freqs.size();
00734 }
00735 for (int n = 0; n < nfreq; n++) {
00736 freqs[n] *= 3.0e10;
00737 }
00738 vector_fp coeffs(nfreq + 2);
00739 coeffs[0] = nfreq;
00740 coeffs[1] = getFloat(f, "binding_energy", "toSI");
00741 copy(freqs.begin(), freqs.end(), coeffs.begin() + 2);
00742
00743
00744 (&sp)->install(speciesName, k, ADSORBATE, &coeffs[0], tmin, tmax, pref);
00745 }
00746 #endif
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761 void SpeciesThermoFactory::
00762 installThermoForSpecies(int k, const XML_Node& speciesNode, ThermoPhase *th_ptr,
00763 SpeciesThermo& spthermo,
00764 const XML_Node *phaseNode_ptr) const {
00765
00766
00767
00768
00769 if (!(speciesNode.hasChild("thermo"))) {
00770 throw UnknownSpeciesThermoModel("installThermoForSpecies",
00771 speciesNode["name"], "<nonexistent>");
00772 }
00773 const XML_Node& thermo = speciesNode.child("thermo");
00774 const std::vector<XML_Node*>& tp = thermo.children();
00775 int nc = static_cast<int>(tp.size());
00776 string mname = thermo["model"];
00777
00778 if (mname == "MineralEQ3") {
00779 const XML_Node* f = tp[0];
00780 if (f->name() != "MinEQ3") {
00781 throw CanteraError("SpeciesThermoFactory::installThermoForSpecies",
00782 "confused: expedted MinEQ3");
00783 }
00784 installMinEQ3asShomateThermoFromXML(speciesNode["name"], th_ptr, spthermo, k, f);
00785 } else {
00786 if (nc == 1) {
00787 const XML_Node* f = tp[0];
00788 if (f->name() == "Shomate") {
00789 installShomateThermoFromXML(speciesNode["name"], spthermo, k, f, 0);
00790 }
00791 else if (f->name() == "const_cp") {
00792 installSimpleThermoFromXML(speciesNode["name"], spthermo, k, *f);
00793 }
00794 else if (f->name() == "NASA") {
00795 installNasaThermoFromXML(speciesNode["name"], spthermo, k, f, 0);
00796 }
00797 else if (f->name() == "Mu0") {
00798 installMu0ThermoFromXML(speciesNode["name"], spthermo, k, f);
00799 }
00800 else if (f->name() == "NASA9") {
00801 installNasa9ThermoFromXML(speciesNode["name"], spthermo, k, tp);
00802 }
00803
00804
00805
00806 #ifdef WITH_ADSORBATE
00807 else if (f->name() == "adsorbate") {
00808 installAdsorbateThermoFromXML(speciesNode["name"], spthermo, k, *f);
00809 }
00810 #endif
00811 else {
00812 throw UnknownSpeciesThermoModel("installThermoForSpecies",
00813 speciesNode["name"], f->name());
00814 }
00815 }
00816 else if (nc == 2) {
00817 const XML_Node* f0 = tp[0];
00818 const XML_Node* f1 = tp[1];
00819 if (f0->name() == "NASA" && f1->name() == "NASA") {
00820 installNasaThermoFromXML(speciesNode["name"], spthermo, k, f0, f1);
00821 }
00822 else if (f0->name() == "Shomate" && f1->name() == "Shomate") {
00823 installShomateThermoFromXML(speciesNode["name"], spthermo, k, f0, f1);
00824 }
00825 else if (f0->name() == "NASA9" && f1->name() == "NASA9") {
00826 installNasa9ThermoFromXML(speciesNode["name"], spthermo, k, tp);
00827 } else {
00828 throw UnknownSpeciesThermoModel("installThermoForSpecies", speciesNode["name"],
00829 f0->name() + " and " + f1->name());
00830 }
00831 }
00832 else if (nc >= 2) {
00833 const XML_Node* f0 = tp[0];
00834 if (f0->name() == "NASA9") {
00835 installNasa9ThermoFromXML(speciesNode["name"], spthermo, k, tp);
00836 } else {
00837 throw UnknownSpeciesThermoModel("installThermoForSpecies", speciesNode["name"],
00838 "multiple");
00839 }
00840 } else {
00841 throw UnknownSpeciesThermoModel("installThermoForSpecies", speciesNode["name"],
00842 "multiple");
00843 }
00844 }
00845 }
00846
00847
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865
00866
00867 void SpeciesThermoFactory::
00868 installVPThermoForSpecies(int k, const XML_Node& speciesNode,
00869 VPStandardStateTP *vp_ptr,
00870 VPSSMgr *vpssmgr_ptr,
00871 SpeciesThermo *spthermo_ptr,
00872 const XML_Node *phaseNode_ptr) const {
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882 vp_ptr->createInstallPDSS(k, speciesNode, phaseNode_ptr);
00883 }
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899 SpeciesThermo* newSpeciesThermoMgr(int type, SpeciesThermoFactory* f) {
00900 if (f == 0) {
00901 f = SpeciesThermoFactory::factory();
00902 }
00903 SpeciesThermo* sptherm = f->newSpeciesThermo(type);
00904 return sptherm;
00905 }
00906
00907
00908
00909
00910
00911
00912
00913
00914
00915
00916
00917
00918
00919
00920
00921 SpeciesThermo* newSpeciesThermoMgr(std::string &stype,
00922 SpeciesThermoFactory* f) {
00923 if (f == 0) {
00924 f = SpeciesThermoFactory::factory();
00925 }
00926 SpeciesThermo* sptherm = f->newSpeciesThermoManager(stype);
00927 return sptherm;
00928 }
00929
00930
00931
00932
00933
00934
00935
00936
00937
00938
00939
00940
00941
00942
00943
00944
00945
00946 SpeciesThermo* newSpeciesThermoMgr(std::vector<XML_Node*> spData_nodes,
00947 SpeciesThermoFactory* f, bool opt) {
00948 if (f == 0) {
00949 f = SpeciesThermoFactory::factory();
00950 }
00951 SpeciesThermo* sptherm;
00952 if (opt) {
00953 sptherm = f->newSpeciesThermoOpt(spData_nodes);
00954 } else {
00955 sptherm = f->newSpeciesThermo(spData_nodes);
00956 }
00957 return sptherm;
00958 }
00959
00960 }