00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #ifdef WIN32
00018 #pragma warning(disable:4786)
00019 #pragma warning(disable:4503)
00020 #endif
00021
00022 #include "SurfPhase.h"
00023 #include "EdgePhase.h"
00024 #include "ThermoFactory.h"
00025
00026 using namespace std;
00027
00028
00029
00030
00031
00032
00033
00034 namespace Cantera {
00035
00036 SurfPhase::SurfPhase(doublereal n0):
00037 ThermoPhase(),
00038 m_n0(n0),
00039 m_logn0(0.0),
00040 m_tmin(0.0),
00041 m_tmax(0.0),
00042 m_press(OneAtm),
00043 m_tlast(0.0)
00044 {
00045 if (n0 > 0.0) m_logn0 = log(n0);
00046 setNDim(2);
00047 }
00048
00049 SurfPhase::SurfPhase(std::string infile, std::string id) :
00050 ThermoPhase(),
00051 m_n0(0.0),
00052 m_logn0(0.0),
00053 m_tmin(0.0),
00054 m_tmax(0.0),
00055 m_press(OneAtm),
00056 m_tlast(0.0)
00057 {
00058 XML_Node* root = get_XML_File(infile);
00059 if (id == "-") id = "";
00060 XML_Node* xphase = get_XML_NameID("phase", std::string("#")+id, root);
00061 if (!xphase) {
00062 throw CanteraError("SurfPhase::SurfPhase",
00063 "Couldn't find phase name in file:" + id);
00064 }
00065
00066 const XML_Node& th = xphase->child("thermo");
00067 string model = th["model"];
00068 if (model != "Surface" && model != "Edge") {
00069 throw CanteraError("SurfPhase::SurfPhase",
00070 "thermo model attribute must be Surface or Edge");
00071 }
00072 importPhase(*xphase, this);
00073 }
00074
00075
00076 SurfPhase::SurfPhase(XML_Node& xmlphase) :
00077 ThermoPhase(),
00078 m_n0(0.0),
00079 m_logn0(0.0),
00080 m_tmin(0.0),
00081 m_tmax(0.0),
00082 m_press(OneAtm),
00083 m_tlast(0.0)
00084 {
00085 const XML_Node& th = xmlphase.child("thermo");
00086 string model = th["model"];
00087 if (model != "Surface" && model != "Edge") {
00088 throw CanteraError("SurfPhase::SurfPhase",
00089 "thermo model attribute must be Surface or Edge");
00090 }
00091 importPhase(xmlphase, this);
00092 }
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103 SurfPhase::SurfPhase(const SurfPhase &right) :
00104 m_n0(right.m_n0),
00105 m_logn0(right.m_logn0),
00106 m_tmin(right.m_tmin),
00107 m_tmax(right.m_tmax),
00108 m_press(right.m_press),
00109 m_tlast(right.m_tlast)
00110 {
00111 *this = operator=(right);
00112 }
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122 SurfPhase& SurfPhase::
00123 operator=(const SurfPhase &right) {
00124 if (&right != this) {
00125 ThermoPhase::operator=(right);
00126 m_n0 = right.m_n0;
00127 m_logn0 = right.m_logn0;
00128 m_tmin = right.m_tmin;
00129 m_tmax = right.m_tmax;
00130 m_press = right.m_press;
00131 m_tlast = right.m_tlast;
00132 m_h0 = right.m_h0;
00133 m_s0 = right.m_s0;
00134 m_cp0 = right.m_cp0;
00135 m_mu0 = right.m_mu0;
00136 m_work = right.m_work;
00137 m_pe = right.m_pe;
00138 m_logsize = right.m_logsize;
00139 }
00140 return *this;
00141 }
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151 ThermoPhase *SurfPhase::duplMyselfAsThermoPhase() const {
00152 SurfPhase *igp = new SurfPhase(*this);
00153 return (ThermoPhase *) igp;
00154 }
00155
00156 doublereal SurfPhase::
00157 enthalpy_mole() const {
00158 if (m_n0 <= 0.0) return 0.0;
00159 _updateThermo();
00160 return mean_X(DATA_PTR(m_h0));
00161 }
00162
00163 SurfPhase::~SurfPhase() {
00164 }
00165
00166
00167
00168
00169
00170
00171 doublereal SurfPhase::
00172 intEnergy_mole() const { return enthalpy_mole(); }
00173
00174
00175
00176
00177
00178 void SurfPhase::getPartialMolarEnthalpies(doublereal* hbar) const {
00179 getEnthalpy_RT(hbar);
00180 doublereal rt = GasConstant * temperature();
00181 for (int k = 0; k < m_kk; k++) {
00182 hbar[k] *= rt;
00183 }
00184 }
00185
00186
00187
00188
00189
00190
00191
00192 void SurfPhase::getPartialMolarEntropies(doublereal* sbar) const {
00193 getEntropy_R(sbar);
00194 for (int k = 0; k < m_kk; k++) {
00195 sbar[k] *= GasConstant;
00196 }
00197 }
00198
00199
00200
00201
00202
00203
00204
00205 void SurfPhase::getPartialMolarCp(doublereal* cpbar) const {
00206 getCp_R(cpbar);
00207 for (int k = 0; k < m_kk; k++) {
00208 cpbar[k] *= GasConstant;
00209 }
00210 }
00211
00212 void SurfPhase::getPartialMolarVolumes(doublereal* vbar) const {
00213 getStandardVolumes(vbar);
00214 }
00215
00216 void SurfPhase::getStandardChemPotentials(doublereal* mu0) const {
00217 _updateThermo();
00218 copy(m_mu0.begin(), m_mu0.end(), mu0);
00219 }
00220
00221 void SurfPhase::getChemPotentials(doublereal* mu) const {
00222 _updateThermo();
00223 copy(m_mu0.begin(), m_mu0.end(), mu);
00224 int k;
00225 getActivityConcentrations(DATA_PTR(m_work));
00226 for (k = 0; k < m_kk; k++) {
00227 mu[k] += GasConstant * temperature() *
00228 (log(m_work[k]) - logStandardConc(k));
00229 }
00230 }
00231
00232 void SurfPhase::getActivityConcentrations(doublereal* c) const {
00233 getConcentrations(c);
00234 }
00235
00236 doublereal SurfPhase::standardConcentration(int k) const {
00237 return m_n0/size(k);
00238 }
00239
00240 doublereal SurfPhase::logStandardConc(int k) const {
00241 return m_logn0 - m_logsize[k];
00242 }
00243
00244
00245 void SurfPhase::setParameters(int n, doublereal* const c) {
00246 if (n != 1) {
00247 throw CanteraError("SurfPhase::setParameters",
00248 "Bad value for number of parameter");
00249 }
00250 m_n0 = c[0];
00251 if (m_n0 <= 0.0) {
00252 throw CanteraError("SurfPhase::setParameters",
00253 "Bad value for parameter");
00254 }
00255 m_logn0 = log(m_n0);
00256 }
00257
00258 void SurfPhase::getGibbs_RT(doublereal* grt) const {
00259 _updateThermo();
00260 double rrt = 1.0/(GasConstant*temperature());
00261 scale(m_mu0.begin(), m_mu0.end(), grt, rrt);
00262 }
00263
00264 void SurfPhase::
00265 getEnthalpy_RT(doublereal* hrt) const {
00266 _updateThermo();
00267 double rrt = 1.0/(GasConstant*temperature());
00268 scale(m_h0.begin(), m_h0.end(), hrt, rrt);
00269 }
00270
00271 void SurfPhase::getEntropy_R(doublereal* sr) const {
00272 _updateThermo();
00273 double rr = 1.0/GasConstant;
00274 scale(m_s0.begin(), m_s0.end(), sr, rr);
00275 }
00276
00277 void SurfPhase::getCp_R(doublereal* cpr) const {
00278 _updateThermo();
00279 double rr = 1.0/GasConstant;
00280 scale(m_cp0.begin(), m_cp0.end(), cpr, rr);
00281 }
00282
00283 void SurfPhase::getStandardVolumes(doublereal* vol) const {
00284 _updateThermo();
00285 for (int k = 0; k < m_kk; k++) {
00286 vol[k] = 1.0/standardConcentration(k);
00287 }
00288 }
00289
00290 void SurfPhase::getGibbs_RT_ref(doublereal* grt) const {
00291 getGibbs_RT(grt);
00292 }
00293
00294 void SurfPhase::getEnthalpy_RT_ref(doublereal* hrt) const {
00295 getEnthalpy_RT(hrt);
00296 }
00297
00298 void SurfPhase::getEntropy_R_ref(doublereal* sr) const {
00299 getEntropy_R(sr);
00300 }
00301
00302 void SurfPhase::getCp_R_ref(doublereal* cprt) const {
00303 getCp_R(cprt);
00304 }
00305
00306 void SurfPhase::initThermo() {
00307 if (m_kk <= 0) {
00308 throw CanteraError("SurfPhase::initThermo",
00309 "Number of species is less than or equal to zero");
00310 }
00311 m_h0.resize(m_kk);
00312 m_s0.resize(m_kk);
00313 m_cp0.resize(m_kk);
00314 m_mu0.resize(m_kk);
00315 m_work.resize(m_kk);
00316 m_pe.resize(m_kk, 0.0);
00317 vector_fp cov(m_kk, 0.0);
00318 cov[0] = 1.0;
00319 setCoverages(DATA_PTR(cov));
00320 m_logsize.resize(m_kk);
00321 for (int k = 0; k < m_kk; k++)
00322 m_logsize[k] = log(size(k));
00323 }
00324
00325 void SurfPhase::setPotentialEnergy(int k, doublereal pe) {
00326 m_pe[k] = pe;
00327 _updateThermo(true);
00328 }
00329
00330 void SurfPhase::setSiteDensity(doublereal n0) {
00331 doublereal x = n0;
00332 setParameters(1, &x);
00333 }
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353 void SurfPhase::
00354 setCoverages(const doublereal* theta) {
00355 double sum = 0.0;
00356 int k;
00357 for (k = 0; k < m_kk; k++) {
00358 sum += theta[k];
00359 }
00360 if (sum <= 0.0) {
00361 for (k = 0; k < m_kk; k++) {
00362 cout << "theta(" << k << ") = " << theta[k] << endl;
00363 }
00364 throw CanteraError("SurfPhase::setCoverages",
00365 "Sum of Coverage fractions is zero or negative");
00366 }
00367 for (k = 0; k < m_kk; k++) {
00368 m_work[k] = m_n0*theta[k]/(sum*size(k));
00369 }
00370
00371
00372
00373
00374 setConcentrations(DATA_PTR(m_work));
00375 }
00376
00377 void SurfPhase::
00378 setCoveragesNoNorm(const doublereal* theta) {
00379 for (int k = 0; k < m_kk; k++) {
00380 m_work[k] = m_n0*theta[k]/(size(k));
00381 }
00382
00383
00384
00385
00386 setConcentrations(DATA_PTR(m_work));
00387 }
00388
00389 void SurfPhase::
00390 getCoverages(doublereal* theta) const {
00391 getConcentrations(theta);
00392 for (int k = 0; k < m_kk; k++) {
00393 theta[k] *= size(k)/m_n0;
00394 }
00395 }
00396
00397 void SurfPhase::
00398 setCoveragesByName(std::string cov) {
00399 int kk = nSpecies();
00400 int k;
00401 compositionMap cc;
00402 for (k = 0; k < kk; k++) {
00403 cc[speciesName(k)] = -1.0;
00404 }
00405 parseCompString(cov, cc);
00406 doublereal c;
00407 vector_fp cv(kk, 0.0);
00408 bool ifound = false;
00409 for (k = 0; k < kk; k++) {
00410 c = cc[speciesName(k)];
00411 if (c > 0.0) {
00412 ifound = true;
00413 cv[k] = c;
00414 }
00415 }
00416 if (!ifound) {
00417 throw CanteraError("SurfPhase::setCoveragesByName",
00418 "Input coverages are all zero or negative");
00419 }
00420 setCoverages(DATA_PTR(cv));
00421 }
00422
00423
00424 void SurfPhase::
00425 _updateThermo(bool force) const {
00426 doublereal tnow = temperature();
00427 if (m_tlast != tnow || force) {
00428 m_spthermo->update(tnow, DATA_PTR(m_cp0), DATA_PTR(m_h0),
00429 DATA_PTR(m_s0));
00430 m_tlast = tnow;
00431 doublereal rt = GasConstant * tnow;
00432 int k;
00433 for (k = 0; k < m_kk; k++) {
00434 m_h0[k] *= rt;
00435 m_s0[k] *= GasConstant;
00436 m_cp0[k] *= GasConstant;
00437 m_mu0[k] = m_h0[k] - tnow*m_s0[k];
00438 }
00439 m_tlast = tnow;
00440 }
00441 }
00442
00443 void SurfPhase::
00444 setParametersFromXML(const XML_Node& eosdata) {
00445 eosdata._require("model","Surface");
00446 doublereal n = getFloat(eosdata, "site_density", "toSI");
00447 if (n <= 0.0)
00448 throw CanteraError("SurfPhase::setParametersFromXML",
00449 "missing or negative site density");
00450 m_n0 = n;
00451 m_logn0 = log(m_n0);
00452 }
00453
00454
00455 void SurfPhase::setStateFromXML(const XML_Node& state) {
00456
00457 double t;
00458 if (getOptionalFloat(state, "temperature", t, "temperature")) {
00459 setTemperature(t);
00460 }
00461
00462 if (state.hasChild("coverages")) {
00463 string comp = getChildValue(state,"coverages");
00464 setCoveragesByName(comp);
00465 }
00466 }
00467
00468
00469 EdgePhase::EdgePhase(doublereal n0) : SurfPhase(n0) {
00470 setNDim(1);
00471 }
00472
00473
00474
00475
00476
00477 EdgePhase::EdgePhase(const EdgePhase & right) :
00478 SurfPhase(right.m_n0)
00479 {
00480 setNDim(1);
00481 *this = operator=(right);
00482 }
00483
00484
00485
00486
00487
00488 EdgePhase& EdgePhase::operator=(const EdgePhase & right) {
00489 if (&right != this) {
00490 SurfPhase::operator=(right);
00491 setNDim(1);
00492 }
00493 return *this;
00494 }
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504 ThermoPhase *EdgePhase::duplMyselfAsThermoPhase() const {
00505 EdgePhase *igp = new EdgePhase(*this);
00506 return (ThermoPhase *) igp;
00507 }
00508
00509 void EdgePhase::
00510 setParametersFromXML(const XML_Node& eosdata) {
00511 eosdata._require("model","Edge");
00512 doublereal n = getFloat(eosdata, "site_density", "toSI");
00513 if (n <= 0.0)
00514 throw CanteraError("EdgePhase::setParametersFromXML",
00515 "missing or negative site density");
00516 m_n0 = n;
00517 m_logn0 = log(m_n0);
00518 }
00519
00520
00521 }