MineralEQ3.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "ct_defs.h"
00021 #include "mix_defs.h"
00022 #include "MineralEQ3.h"
00023 #include "SpeciesThermo.h"
00024
00025 #include "ThermoFactory.h"
00026 #include "MineralEQ3.h"
00027
00028 #include <string>
00029
00030 using namespace std;
00031
00032 namespace Cantera {
00033
00034
00035
00036
00037
00038
00039
00040
00041 MineralEQ3::MineralEQ3():
00042 StoichSubstanceSSTP ()
00043 {
00044 }
00045
00046
00047
00048
00049
00050
00051
00052
00053 MineralEQ3::MineralEQ3(std::string infile, std::string id) :
00054 StoichSubstanceSSTP()
00055 {
00056 XML_Node* root = get_XML_File(infile);
00057 if (id == "-") id = "";
00058 XML_Node* xphase = get_XML_NameID("phase", std::string("#")+id, root);
00059 if (!xphase) {
00060 throw CanteraError("MineralEQ3::MineralEQ3",
00061 "Couldn't find phase name in file:" + id);
00062 }
00063
00064 const XML_Node& th = xphase->child("thermo");
00065 std::string model = th["model"];
00066 if (model != "StoichSubstance" && model != "MineralEQ3") {
00067 throw CanteraError("MineralEQ3::MineralEQ3",
00068 "thermo model attribute must be StoichSubstance");
00069 }
00070 importPhase(*xphase, this);
00071 }
00072
00073
00074
00075
00076
00077
00078 MineralEQ3::MineralEQ3(XML_Node& xmlphase, std::string id) :
00079 StoichSubstanceSSTP()
00080 {
00081 if (id != "") {
00082 std::string idxml = xmlphase["id"];
00083 if (id != idxml) {
00084 throw CanteraError("MineralEQ3::MineralEQ3",
00085 "id's don't match");
00086 }
00087 }
00088 const XML_Node& th = xmlphase.child("thermo");
00089 std::string model = th["model"];
00090 if (model != "StoichSubstance" && model != "MineralEQ3") {
00091 throw CanteraError("MineralEQ3::MineralEQ3",
00092 "thermo model attribute must be StoichSubstance");
00093 }
00094 importPhase(xmlphase, this);
00095 }
00096
00097
00098
00099
00100
00101 MineralEQ3::MineralEQ3(const MineralEQ3 &right) :
00102 StoichSubstanceSSTP()
00103 {
00104 *this = operator=(right);
00105 }
00106
00107
00108
00109
00110
00111 MineralEQ3 &
00112 MineralEQ3::operator=(const MineralEQ3 & right) {
00113 if (&right == this) {
00114 return *this;
00115 }
00116 StoichSubstanceSSTP::operator=(right);
00117 m_Mu0_pr_tr = right.m_Mu0_pr_tr;
00118 m_Entrop_pr_tr = right.m_Entrop_pr_tr;
00119 m_deltaG_formation_pr_tr = right.m_deltaG_formation_pr_tr;
00120 m_deltaH_formation_pr_tr = right.m_deltaH_formation_pr_tr;
00121 m_V0_pr_tr = right.m_V0_pr_tr;
00122 m_a = right.m_a;
00123 m_b = right.m_b;
00124 m_c = right.m_c;
00125
00126 return *this;
00127 }
00128
00129
00130
00131
00132
00133 MineralEQ3::~MineralEQ3()
00134 {
00135 }
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145 ThermoPhase *MineralEQ3::duplMyselfAsThermoPhase() const {
00146 MineralEQ3 *stp = new MineralEQ3(*this);
00147 return (ThermoPhase *) stp;
00148 }
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159 int MineralEQ3::eosType() const {
00160 return cStoichSubstance;
00161 }
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177 doublereal MineralEQ3::pressure() const {
00178 return m_press;
00179 }
00180
00181
00182
00183
00184
00185
00186
00187
00188 void MineralEQ3::setPressure(doublereal p) {
00189 m_press = p;
00190 }
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202 doublereal MineralEQ3::isothermalCompressibility() const {
00203 return 0.0;
00204 }
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217 doublereal MineralEQ3::thermalExpansionCoeff() const {
00218 return 0.0;
00219 }
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230 void MineralEQ3::
00231 getActivityConcentrations(doublereal* c) const {
00232 c[0] = 1.0;
00233 }
00234
00235
00236
00237
00238
00239
00240 doublereal MineralEQ3::standardConcentration(int k) const {
00241 return 1.0;
00242 }
00243
00244
00245
00246
00247
00248 doublereal MineralEQ3::logStandardConc(int k) const {
00249 return 0.0;
00250 }
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270 void MineralEQ3::
00271 getUnitsStandardConc(doublereal *uA, int k, int sizeUA) const {
00272 for (int i = 0; i < 6; i++) {
00273 uA[i] = 0;
00274 }
00275 }
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297 void MineralEQ3::
00298 getStandardChemPotentials(doublereal* mu0) const {
00299 getGibbs_RT(mu0);
00300 mu0[0] *= GasConstant * temperature();
00301 }
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313 void MineralEQ3::getEnthalpy_RT(doublereal* hrt) const {
00314 getEnthalpy_RT_ref(hrt);
00315 doublereal RT = GasConstant * temperature();
00316 doublereal presCorrect = (m_press - m_p0) / molarDensity();
00317 hrt[0] += presCorrect / RT;
00318 }
00319
00320
00321
00322
00323
00324
00325 void MineralEQ3::getEntropy_R(doublereal* sr) const {
00326 getEntropy_R_ref(sr);
00327 }
00328
00329
00330
00331
00332
00333
00334 void MineralEQ3::getGibbs_RT(doublereal* grt) const {
00335 getEnthalpy_RT(grt);
00336 grt[0] -= m_s0_R[0];
00337 }
00338
00339
00340
00341
00342
00343 void MineralEQ3::getCp_R(doublereal* cpr) const {
00344 _updateThermo();
00345 cpr[0] = m_cp0_R[0];
00346 }
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357 void MineralEQ3::getIntEnergy_RT(doublereal* urt) const {
00358 _updateThermo();
00359 doublereal RT = GasConstant * temperature();
00360 doublereal PV = m_p0 / molarDensity();
00361 urt[0] = m_h0_RT[0] - PV / RT;
00362 }
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380 void MineralEQ3::getIntEnergy_RT_ref(doublereal* urt) const {
00381 _updateThermo();
00382 doublereal RT = GasConstant * temperature();
00383 doublereal PV = m_p0 / molarDensity();
00384 urt[0] = m_h0_RT[0] - PV / RT;
00385 }
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410 void MineralEQ3::initThermo() {
00411
00412
00413
00414
00415 StoichSubstanceSSTP::initThermo();
00416 }
00417
00418
00419
00420
00421
00422
00423
00424
00425 void MineralEQ3::setParameters(int n, doublereal * const c) {
00426 doublereal rho = c[0];
00427 setDensity(rho);
00428 }
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438 void MineralEQ3::getParameters(int &n, doublereal * const c) const {
00439 doublereal rho = density();
00440 n = 1;
00441 c[0] = rho;
00442 }
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463 void MineralEQ3::initThermoXML(XML_Node& phaseNode, std::string id) {
00464
00465
00466
00467 if (!phaseNode.hasChild("thermo")) {
00468 throw CanteraError("HMWSoln::initThermoXML",
00469 "no thermo XML node");
00470 }
00471
00472 std::vector<const XML_Node *> xspecies = speciesData();
00473 const XML_Node *xsp = xspecies[0];
00474
00475 XML_Node *aStandardState = 0;
00476 if (xsp->hasChild("standardState")) {
00477 aStandardState = &xsp->child("standardState");
00478 } else {
00479 throw CanteraError("MineralEQ3::initThermoXML",
00480 "no standard state mode");
00481 }
00482 doublereal volVal = 0.0;
00483 string smodel = (*aStandardState)["model"];
00484 if (smodel != "constantVolume") {
00485 throw CanteraError("MineralEQ3::initThermoXML",
00486 "wrong standard state mode");
00487 }
00488 if (aStandardState->hasChild("V0_Pr_Tr")) {
00489 XML_Node& aV = aStandardState->child("V0_Pr_Tr");
00490 string Aunits = "";
00491 double Afactor = toSI("cm3/gmol");
00492 if (aV.hasAttrib("units")) {
00493 Aunits = aV.attrib("units");
00494 Afactor = toSI(Aunits);
00495 }
00496 volVal = getFloat(*aStandardState, "V0_Pr_Tr");
00497 m_V0_pr_tr= volVal;
00498 volVal *= Afactor;
00499 m_speciesSize[0] = volVal;
00500 } else {
00501 throw CanteraError("MineralEQ3::initThermoXML",
00502 "wrong standard state mode");
00503 }
00504 doublereal rho = molecularWeight(0) / volVal;
00505 setDensity(rho);
00506
00507 const XML_Node &sThermo = xsp->child("thermo");
00508 const XML_Node &MinEQ3node = sThermo.child("MinEQ3");
00509
00510
00511 m_deltaG_formation_pr_tr =
00512 getFloatDefaultUnits(MinEQ3node, "DG0_f_Pr_Tr", "cal/gmol", "actEnergy");
00513 m_deltaH_formation_pr_tr =
00514 getFloatDefaultUnits(MinEQ3node, "DH0_f_Pr_Tr", "cal/gmol", "actEnergy");
00515 m_Entrop_pr_tr = getFloatDefaultUnits(MinEQ3node, "S0_Pr_Tr", "cal/gmol/K");
00516 m_a = getFloatDefaultUnits(MinEQ3node, "a", "cal/gmol/K");
00517 m_b = getFloatDefaultUnits(MinEQ3node, "b", "cal/gmol/K2");
00518 m_c = getFloatDefaultUnits(MinEQ3node, "c", "cal-K/gmol");
00519
00520
00521 convertDGFormation();
00522
00523 }
00524
00525
00526 void MineralEQ3::setParametersFromXML(const XML_Node& eosdata) {
00527 std::string model = eosdata["model"];
00528 if (model != "MineralEQ3") {
00529 throw CanteraError("MineralEQ3::MineralEQ3",
00530 "thermo model attribute must be MineralEQ3");
00531 }
00532 }
00533
00534 doublereal MineralEQ3::LookupGe(const std::string& elemName) {
00535 #ifdef OLDWAY
00536 int num = sizeof(geDataTable) / sizeof(struct GeData);
00537 string s3 = elemName.substr(0,3);
00538 for (int i = 0; i < num; i++) {
00539
00540 if (s3 == geDataTable[i].name) {
00541 return (geDataTable[i].GeValue);
00542 }
00543 }
00544 throw CanteraError("LookupGe", "element " + s + " not found");
00545 return -1.0;
00546 #else
00547 int iE = elementIndex(elemName);
00548 if (iE < 0) {
00549 throw CanteraError("PDSS_HKFT::LookupGe", "element " + elemName + " not found");
00550 }
00551 doublereal geValue = entropyElement298(iE);
00552 if (geValue == ENTROPY298_UNKNOWN) {
00553 throw CanteraError("PDSS_HKFT::LookupGe",
00554 "element " + elemName + " doesn not have a supplied entropy298");
00555 }
00556 geValue *= (-298.15);
00557 return geValue;
00558 #endif
00559 }
00560
00561 void MineralEQ3::convertDGFormation() {
00562
00563
00564
00565 int ne = nElements();
00566 doublereal na;
00567 doublereal ge;
00568 string ename;
00569
00570 doublereal totalSum = 0.0;
00571 for (int m = 0; m < ne; m++) {
00572 na = nAtoms(0, m);
00573 if (na > 0.0) {
00574 ename = elementName(m);
00575 ge = LookupGe(ename);
00576 totalSum += na * ge;
00577 }
00578 }
00579
00580
00581
00582
00583
00584
00585
00586 doublereal dg = m_deltaG_formation_pr_tr * 4.184 * 1.0E3;
00587
00588 m_Mu0_pr_tr = dg + totalSum;
00589 }
00590
00591 }
00592
00593