00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "HMWSoln.h"
00020 #include "ThermoFactory.h"
00021 #include "WaterProps.h"
00022 #include "PDSS_Water.h"
00023 #include <cstring>
00024 #include <cstdlib>
00025
00026 using namespace std;
00027
00028 namespace Cantera {
00029
00030
00031
00032
00033
00034
00035
00036 int HMWSoln::interp_est(std::string estString) {
00037 const char *cc = estString.c_str();
00038 string lcs = lowercase(estString);
00039 const char *ccl = lcs.c_str();
00040 if (!strcmp(ccl, "solvent")) {
00041 return cEST_solvent;
00042 } else if (!strcmp(ccl, "chargedspecies")) {
00043 return cEST_chargedSpecies;
00044 } else if (!strcmp(ccl, "weakacidassociated")) {
00045 return cEST_weakAcidAssociated;
00046 } else if (!strcmp(ccl, "strongacidassociated")) {
00047 return cEST_strongAcidAssociated;
00048 } else if (!strcmp(ccl, "polarneutral")) {
00049 return cEST_polarNeutral;
00050 } else if (!strcmp(ccl, "nonpolarneutral")) {
00051 return cEST_nonpolarNeutral;
00052 }
00053 int retn, rval;
00054 if ((retn = sscanf(cc, "%d", &rval)) != 1) {
00055 return -1;
00056 }
00057 return rval;
00058 }
00059
00060
00061
00062
00063
00064
00065
00066
00067 void HMWSoln::readXMLBinarySalt(XML_Node &BinSalt) {
00068 string xname = BinSalt.name();
00069 if (xname != "binarySaltParameters") {
00070 throw CanteraError("HMWSoln::readXMLBinarySalt",
00071 "Incorrect name for processing this routine: " + xname);
00072 }
00073 double *charge = DATA_PTR(m_speciesCharge);
00074 string stemp;
00075 int nParamsFound, i;
00076 vector_fp vParams;
00077 string iName = BinSalt.attrib("cation");
00078 if (iName == "") {
00079 throw CanteraError("HMWSoln::readXMLBinarySalt", "no cation attrib");
00080 }
00081 string jName = BinSalt.attrib("anion");
00082 if (jName == "") {
00083 throw CanteraError("HMWSoln::readXMLBinarySalt", "no anion attrib");
00084 }
00085
00086
00087
00088
00089 int iSpecies = speciesIndex(iName);
00090 if (iSpecies < 0) {
00091 return;
00092 }
00093 string ispName = speciesName(iSpecies);
00094 if (charge[iSpecies] <= 0) {
00095 throw CanteraError("HMWSoln::readXMLBinarySalt", "cation charge problem");
00096 }
00097 int jSpecies = speciesIndex(jName);
00098 if (jSpecies < 0) {
00099 return;
00100 }
00101 string jspName = speciesName(jSpecies);
00102 if (charge[jSpecies] >= 0) {
00103 throw CanteraError("HMWSoln::readXMLBinarySalt", "anion charge problem");
00104 }
00105
00106 int n = iSpecies * m_kk + jSpecies;
00107 int counter = m_CounterIJ[n];
00108 int num = BinSalt.nChildren();
00109 for (int iChild = 0; iChild < num; iChild++) {
00110 XML_Node &xmlChild = BinSalt.child(iChild);
00111 stemp = xmlChild.name();
00112 string nodeName = lowercase(stemp);
00113
00114
00115
00116 if (nodeName == "beta0") {
00117
00118
00119
00120 getFloatArray(xmlChild, vParams, false, "", "beta0");
00121 nParamsFound = vParams.size();
00122 if (m_formPitzerTemp == PITZER_TEMP_CONSTANT) {
00123 if (nParamsFound != 1) {
00124 throw CanteraError("HMWSoln::readXMLBinarySalt::beta0 for " + ispName
00125 + "::" + jspName,
00126 "wrong number of params found");
00127 }
00128 m_Beta0MX_ij[counter] = vParams[0];
00129 m_Beta0MX_ij_coeff(0,counter) = m_Beta0MX_ij[counter];
00130 } else if (m_formPitzerTemp == PITZER_TEMP_LINEAR) {
00131 if (nParamsFound != 2) {
00132 throw CanteraError("HMWSoln::readXMLBinarySalt::beta0 for " + ispName
00133 + "::" + jspName,
00134 "wrong number of params found");
00135 }
00136 m_Beta0MX_ij_coeff(0,counter) = vParams[0];
00137 m_Beta0MX_ij_coeff(1,counter) = vParams[1];
00138 m_Beta0MX_ij[counter] = vParams[0];
00139 } else if (m_formPitzerTemp == PITZER_TEMP_COMPLEX1) {
00140 if (nParamsFound != 5) {
00141 throw CanteraError("HMWSoln::readXMLBinarySalt::beta0 for " + ispName
00142 + "::" + jspName,
00143 "wrong number of params found");
00144 }
00145 for (i = 0; i < nParamsFound; i++) {
00146 m_Beta0MX_ij_coeff(i, counter) = vParams[i];
00147 }
00148 m_Beta0MX_ij[counter] = vParams[0];
00149 }
00150 }
00151 if (nodeName == "beta1") {
00152
00153
00154
00155
00156 getFloatArray(xmlChild, vParams, false, "", "beta1");
00157 nParamsFound = vParams.size();
00158 if (m_formPitzerTemp == PITZER_TEMP_CONSTANT) {
00159 if (nParamsFound != 1) {
00160 throw CanteraError("HMWSoln::readXMLBinarySalt::beta1 for " + ispName
00161 + "::" + jspName,
00162 "wrong number of params found");
00163 }
00164 m_Beta1MX_ij[counter] = vParams[0];
00165 m_Beta1MX_ij_coeff(0,counter) = m_Beta1MX_ij[counter];
00166 } else if (m_formPitzerTemp == PITZER_TEMP_LINEAR) {
00167 if (nParamsFound != 2) {
00168 throw CanteraError("HMWSoln::readXMLBinarySalt::beta1 for " + ispName
00169 + "::" + jspName,
00170 "wrong number of params found");
00171 }
00172 m_Beta1MX_ij_coeff(0,counter) = vParams[0];
00173 m_Beta1MX_ij_coeff(1,counter) = vParams[1];
00174 m_Beta1MX_ij[counter] = vParams[0];
00175 } else if (m_formPitzerTemp == PITZER_TEMP_COMPLEX1) {
00176 if (nParamsFound != 5) {
00177 throw CanteraError("HMWSoln::readXMLBinarySalt::beta1 for " + ispName
00178 + "::" + jspName,
00179 "wrong number of params found");
00180 }
00181 for (i = 0; i < nParamsFound; i++) {
00182 m_Beta1MX_ij_coeff(i, counter) = vParams[i];
00183 }
00184 m_Beta1MX_ij[counter] = vParams[0];
00185 }
00186 }
00187 if (nodeName == "beta2") {
00188 getFloatArray(xmlChild, vParams, false, "", "beta2");
00189 nParamsFound = vParams.size();
00190 if (m_formPitzerTemp == PITZER_TEMP_CONSTANT) {
00191 if (nParamsFound != 1) {
00192 throw CanteraError("HMWSoln::readXMLBinarySalt::beta2 for " + ispName
00193 + "::" + jspName,
00194 "wrong number of params found");
00195 }
00196 m_Beta2MX_ij[counter] = vParams[0];
00197 m_Beta2MX_ij_coeff(0,counter) = m_Beta2MX_ij[counter];
00198 } else if (m_formPitzerTemp == PITZER_TEMP_LINEAR) {
00199 if (nParamsFound != 2) {
00200 throw CanteraError("HMWSoln::readXMLBinarySalt::beta2 for " + ispName
00201 + "::" + jspName,
00202 "wrong number of params found");
00203 }
00204 m_Beta2MX_ij_coeff(0,counter) = vParams[0];
00205 m_Beta2MX_ij_coeff(1,counter) = vParams[1];
00206 m_Beta2MX_ij[counter] = vParams[0];
00207 } else if (m_formPitzerTemp == PITZER_TEMP_COMPLEX1) {
00208 if (nParamsFound != 5) {
00209 throw CanteraError("HMWSoln::readXMLBinarySalt::beta2 for " + ispName
00210 + "::" + jspName,
00211 "wrong number of params found");
00212 }
00213 for (i = 0; i < nParamsFound; i++) {
00214 m_Beta2MX_ij_coeff(i, counter) = vParams[i];
00215 }
00216 m_Beta2MX_ij[counter] = vParams[0];
00217 }
00218
00219 }
00220 if (nodeName == "cphi") {
00221
00222
00223
00224 getFloatArray(xmlChild, vParams, false, "", "Cphi");
00225 nParamsFound = vParams.size();
00226 if (m_formPitzerTemp == PITZER_TEMP_CONSTANT) {
00227 if (nParamsFound != 1) {
00228 throw CanteraError("HMWSoln::readXMLBinarySalt::Cphi for " + ispName
00229 + "::" + jspName,
00230 "wrong number of params found");
00231 }
00232 m_CphiMX_ij[counter] = vParams[0];
00233 m_CphiMX_ij_coeff(0,counter) = m_CphiMX_ij[counter];
00234 } else if (m_formPitzerTemp == PITZER_TEMP_LINEAR) {
00235 if (nParamsFound != 2) {
00236 throw CanteraError("HMWSoln::readXMLBinarySalt::Cphi for " + ispName
00237 + "::" + jspName,
00238 "wrong number of params found");
00239 }
00240 m_CphiMX_ij_coeff(0,counter) = vParams[0];
00241 m_CphiMX_ij_coeff(1,counter) = vParams[1];
00242 m_CphiMX_ij[counter] = vParams[0];
00243 } else if (m_formPitzerTemp == PITZER_TEMP_COMPLEX1) {
00244 if (nParamsFound != 5) {
00245 throw CanteraError("HMWSoln::readXMLBinarySalt::Cphi for " + ispName
00246 + "::" + jspName,
00247 "wrong number of params found");
00248 }
00249 for (i = 0; i < nParamsFound; i++) {
00250 m_CphiMX_ij_coeff(i, counter) = vParams[i];
00251 }
00252 m_CphiMX_ij[counter] = vParams[0];
00253 }
00254 }
00255
00256 if (nodeName == "alpha1") {
00257 stemp = xmlChild.value();
00258 m_Alpha1MX_ij[counter] = atofCheck(stemp.c_str());
00259 }
00260
00261 if (nodeName == "alpha2") {
00262 stemp = xmlChild.value();
00263 m_Alpha2MX_ij[counter] = atofCheck(stemp.c_str());
00264 }
00265 }
00266 }
00267
00268
00269
00270
00271
00272
00273 void HMWSoln::readXMLThetaAnion(XML_Node &BinSalt) {
00274 string xname = BinSalt.name();
00275 vector_fp vParams;
00276 int nParamsFound = 0;
00277 if (xname != "thetaAnion") {
00278 throw CanteraError("HMWSoln::readXMLThetaAnion",
00279 "Incorrect name for processing this routine: " + xname);
00280 }
00281 double *charge = DATA_PTR(m_speciesCharge);
00282 string stemp;
00283 string ispName = BinSalt.attrib("anion1");
00284 if (ispName == "") {
00285 throw CanteraError("HMWSoln::readXMLThetaAnion", "no anion1 attrib");
00286 }
00287 string jspName = BinSalt.attrib("anion2");
00288 if (jspName == "") {
00289 throw CanteraError("HMWSoln::readXMLThetaAnion", "no anion2 attrib");
00290 }
00291
00292
00293
00294
00295 int iSpecies = speciesIndex(ispName);
00296 if (iSpecies < 0) {
00297 return;
00298 }
00299 if (charge[iSpecies] >= 0) {
00300 throw CanteraError("HMWSoln::readXMLThetaAnion", "anion1 charge problem");
00301 }
00302 int jSpecies = speciesIndex(jspName);
00303 if (jSpecies < 0) {
00304 return;
00305 }
00306 if (charge[jSpecies] >= 0) {
00307 throw CanteraError("HMWSoln::readXMLThetaAnion", "anion2 charge problem");
00308 }
00309
00310 int n = iSpecies * m_kk + jSpecies;
00311 int counter = m_CounterIJ[n];
00312 int num = BinSalt.nChildren();
00313 for (int i = 0; i < num; i++) {
00314 XML_Node &xmlChild = BinSalt.child(i);
00315 stemp = xmlChild.name();
00316 string nodeName = lowercase(stemp);
00317 if (nodeName == "theta") {
00318 getFloatArray(xmlChild, vParams, false, "", stemp);
00319 nParamsFound = vParams.size();
00320 if (m_formPitzerTemp == PITZER_TEMP_CONSTANT) {
00321 if (nParamsFound != 1) {
00322 throw CanteraError("HMWSoln::readXMLThetaAnion::Theta for " + ispName
00323 + "::" + jspName,
00324 "wrong number of params found");
00325 }
00326 m_Theta_ij_coeff(0,counter) = vParams[0];
00327 m_Theta_ij[counter] = vParams[0];
00328 } else if (m_formPitzerTemp == PITZER_TEMP_LINEAR) {
00329 if (nParamsFound != 2) {
00330 throw CanteraError("HMWSoln::readXMLThetaAnion::Theta for " + ispName
00331 + "::" + jspName,
00332 "wrong number of params found");
00333 }
00334 m_Theta_ij_coeff(0,counter) = vParams[0];
00335 m_Theta_ij_coeff(1,counter) = vParams[1];
00336 m_Theta_ij[counter] = vParams[0];
00337 } else if (m_formPitzerTemp == PITZER_TEMP_COMPLEX1) {
00338 if (nParamsFound == 1) {
00339 vParams.resize(5, 0.0);
00340 nParamsFound = 5;
00341 } else if (nParamsFound != 5) {
00342 throw CanteraError("HMWSoln::readXMLThetaAnion::Theta for " + ispName
00343 + "::" + jspName,
00344 "wrong number of params found");
00345 }
00346 for (i = 0; i < nParamsFound; i++) {
00347 m_Theta_ij_coeff(i, counter) = vParams[i];
00348 }
00349 m_Theta_ij[counter] = vParams[0];
00350 }
00351 }
00352 }
00353 }
00354
00355
00356
00357
00358
00359
00360 void HMWSoln::readXMLThetaCation(XML_Node &BinSalt) {
00361 string xname = BinSalt.name();
00362 vector_fp vParams;
00363 int nParamsFound = 0;
00364 if (xname != "thetaCation") {
00365 throw CanteraError("HMWSoln::readXMLThetaCation",
00366 "Incorrect name for processing this routine: " + xname);
00367 }
00368 double *charge = DATA_PTR(m_speciesCharge);
00369 string stemp;
00370 string ispName = BinSalt.attrib("cation1");
00371 if (ispName == "") {
00372 throw CanteraError("HMWSoln::readXMLThetaCation", "no cation1 attrib");
00373 }
00374 string jspName = BinSalt.attrib("cation2");
00375 if (jspName == "") {
00376 throw CanteraError("HMWSoln::readXMLThetaCation", "no cation2 attrib");
00377 }
00378
00379
00380
00381
00382 int iSpecies = speciesIndex(ispName);
00383 if (iSpecies < 0) {
00384 return;
00385 }
00386 if (charge[iSpecies] <= 0) {
00387 throw CanteraError("HMWSoln::readXMLThetaCation", "cation1 charge problem");
00388 }
00389 int jSpecies = speciesIndex(jspName);
00390 if (jSpecies < 0) {
00391 return;
00392 }
00393 if (charge[jSpecies] <= 0) {
00394 throw CanteraError("HMWSoln::readXMLThetaCation", "cation2 charge problem");
00395 }
00396
00397 int n = iSpecies * m_kk + jSpecies;
00398 int counter = m_CounterIJ[n];
00399 int num = BinSalt.nChildren();
00400 for (int i = 0; i < num; i++) {
00401 XML_Node &xmlChild = BinSalt.child(i);
00402 stemp = xmlChild.name();
00403 string nodeName = lowercase(stemp);
00404 if (nodeName == "theta") {
00405 getFloatArray(xmlChild, vParams, false, "", stemp);
00406 nParamsFound = vParams.size();
00407 if (m_formPitzerTemp == PITZER_TEMP_CONSTANT) {
00408 if (nParamsFound != 1) {
00409 throw CanteraError("HMWSoln::readXMLThetaCation::Theta for " + ispName
00410 + "::" + jspName,
00411 "wrong number of params found");
00412 }
00413 m_Theta_ij_coeff(0,counter) = vParams[0];
00414 m_Theta_ij[counter] = vParams[0];
00415 } else if (m_formPitzerTemp == PITZER_TEMP_LINEAR) {
00416 if (nParamsFound != 2) {
00417 throw CanteraError("HMWSoln::readXMLThetaCation::Theta for " + ispName
00418 + "::" + jspName,
00419 "wrong number of params found");
00420 }
00421 m_Theta_ij_coeff(0,counter) = vParams[0];
00422 m_Theta_ij_coeff(1,counter) = vParams[1];
00423 m_Theta_ij[counter] = vParams[0];
00424 } else if (m_formPitzerTemp == PITZER_TEMP_COMPLEX1) {
00425 if (nParamsFound == 1) {
00426 vParams.resize(5, 0.0);
00427 nParamsFound = 5;
00428 } else if (nParamsFound != 5) {
00429 throw CanteraError("HMWSoln::readXMLThetaCation::Theta for " + ispName
00430 + "::" + jspName,
00431 "wrong number of params found");
00432 }
00433 for (i = 0; i < nParamsFound; i++) {
00434 m_Theta_ij_coeff(i, counter) = vParams[i];
00435 }
00436 m_Theta_ij[counter] = vParams[0];
00437 }
00438 }
00439 }
00440 }
00441
00442
00443
00444
00445
00446
00447 void HMWSoln::readXMLPsiCommonCation(XML_Node &BinSalt) {
00448 string xname = BinSalt.name();
00449 if (xname != "psiCommonCation") {
00450 throw CanteraError("HMWSoln::readXMLPsiCommonCation",
00451 "Incorrect name for processing this routine: " + xname);
00452 }
00453 double *charge = DATA_PTR(m_speciesCharge);
00454 string stemp;
00455 vector_fp vParams;
00456 int nParamsFound = 0;
00457 string kName = BinSalt.attrib("cation");
00458 if (kName == "") {
00459 throw CanteraError("HMWSoln::readXMLPsiCommonCation", "no cation attrib");
00460 }
00461 string iName = BinSalt.attrib("anion1");
00462 if (iName == "") {
00463 throw CanteraError("HMWSoln::readXMLPsiCommonCation", "no anion1 attrib");
00464 }
00465 string jName = BinSalt.attrib("anion2");
00466 if (jName == "") {
00467 throw CanteraError("HMWSoln::readXMLPsiCommonCation", "no anion2 attrib");
00468 }
00469
00470
00471
00472
00473 int kSpecies = speciesIndex(kName);
00474 if (kSpecies < 0) {
00475 return;
00476 }
00477 if (charge[kSpecies] <= 0) {
00478 throw CanteraError("HMWSoln::readXMLPsiCommonCation",
00479 "cation charge problem");
00480 }
00481 int iSpecies = speciesIndex(iName);
00482 if (iSpecies < 0) {
00483 return;
00484 }
00485 if (charge[iSpecies] >= 0) {
00486 throw CanteraError("HMWSoln::readXMLPsiCommonCation",
00487 "anion1 charge problem");
00488 }
00489 int jSpecies = speciesIndex(jName);
00490 if (jSpecies < 0) {
00491 return;
00492 }
00493 if (charge[jSpecies] >= 0) {
00494 throw CanteraError("HMWSoln::readXMLPsiCommonCation",
00495 "anion2 charge problem");
00496 }
00497
00498 int n = iSpecies * m_kk + jSpecies;
00499 int counter = m_CounterIJ[n];
00500 int num = BinSalt.nChildren();
00501 for (int i = 0; i < num; i++) {
00502 XML_Node &xmlChild = BinSalt.child(i);
00503 stemp = xmlChild.name();
00504 string nodeName = lowercase(stemp);
00505 if (nodeName == "theta") {
00506 stemp = xmlChild.value();
00507 double old = m_Theta_ij[counter];
00508 m_Theta_ij[counter] = atofCheck(stemp.c_str());
00509 if (old != 0.0) {
00510 if (old != m_Theta_ij[counter]) {
00511 throw CanteraError("HMWSoln::readXMLPsiCommonCation",
00512 "conflicting values");
00513 }
00514 }
00515 }
00516 if (nodeName == "psi") {
00517 getFloatArray(xmlChild, vParams, false, "", stemp);
00518 nParamsFound = vParams.size();
00519 n = iSpecies * m_kk *m_kk + jSpecies * m_kk + kSpecies ;
00520
00521 if (m_formPitzerTemp == PITZER_TEMP_CONSTANT) {
00522 if (nParamsFound != 1) {
00523 throw CanteraError("HMWSoln::readXMLPsiCommonCation::Psi for "
00524 + kName + "::" + iName + "::" + jName,
00525 "wrong number of params found");
00526 }
00527 m_Psi_ijk_coeff(0,n) = vParams[0];
00528 m_Psi_ijk[n] = vParams[0];
00529 } else if (m_formPitzerTemp == PITZER_TEMP_LINEAR) {
00530 if (nParamsFound != 2) {
00531 throw CanteraError("HMWSoln::readXMLPsiCation::Psi for "
00532 + kName + "::" + iName + "::" + jName,
00533 "wrong number of params found");
00534 }
00535 m_Psi_ijk_coeff(0,n) = vParams[0];
00536 m_Psi_ijk_coeff(1,n) = vParams[1];
00537 m_Psi_ijk[n] = vParams[0];
00538 } else if (m_formPitzerTemp == PITZER_TEMP_COMPLEX1) {
00539 if (nParamsFound == 1) {
00540 vParams.resize(5, 0.0);
00541 nParamsFound = 5;
00542 } else if (nParamsFound != 5) {
00543 throw CanteraError("HMWSoln::readXMLPsiCation::Psi for "
00544 + kName + "::" + iName + "::" + jName,
00545 "wrong number of params found");
00546 }
00547 for (i = 0; i < nParamsFound; i++) {
00548 m_Psi_ijk_coeff(i, n) = vParams[i];
00549 }
00550 m_Psi_ijk[n] = vParams[0];
00551 }
00552
00553
00554
00555 n = iSpecies * m_kk *m_kk + kSpecies * m_kk + jSpecies ;
00556 for (i = 0; i < nParamsFound; i++) {
00557 m_Psi_ijk_coeff(i, n) = vParams[i];
00558 }
00559 m_Psi_ijk[n] = vParams[0];
00560
00561 n = jSpecies * m_kk *m_kk + iSpecies * m_kk + kSpecies ;
00562 for (i = 0; i < nParamsFound; i++) {
00563 m_Psi_ijk_coeff(i, n) = vParams[i];
00564 }
00565 m_Psi_ijk[n] = vParams[0];
00566
00567 n = jSpecies * m_kk *m_kk + kSpecies * m_kk + iSpecies ;
00568 for (i = 0; i < nParamsFound; i++) {
00569 m_Psi_ijk_coeff(i, n) = vParams[i];
00570 }
00571 m_Psi_ijk[n] = vParams[0];
00572
00573 n = kSpecies * m_kk *m_kk + jSpecies * m_kk + iSpecies ;
00574 for (i = 0; i < nParamsFound; i++) {
00575 m_Psi_ijk_coeff(i, n) = vParams[i];
00576 }
00577 m_Psi_ijk[n] = vParams[0];
00578
00579 n = kSpecies * m_kk *m_kk + iSpecies * m_kk + jSpecies ;
00580 for (i = 0; i < nParamsFound; i++) {
00581 m_Psi_ijk_coeff(i, n) = vParams[i];
00582 }
00583 m_Psi_ijk[n] = vParams[0];
00584 }
00585 }
00586 }
00587
00588
00589
00590
00591
00592
00593 void HMWSoln::readXMLPsiCommonAnion(XML_Node &BinSalt) {
00594 string xname = BinSalt.name();
00595 if (xname != "psiCommonAnion") {
00596 throw CanteraError("HMWSoln::readXMLPsiCommonAnion",
00597 "Incorrect name for processing this routine: " + xname);
00598 }
00599 double *charge = DATA_PTR(m_speciesCharge);
00600 string stemp;
00601 vector_fp vParams;
00602 int nParamsFound = 0;
00603 string kName = BinSalt.attrib("anion");
00604 if (kName == "") {
00605 throw CanteraError("HMWSoln::readXMLPsiCommonAnion", "no anion attrib");
00606 }
00607 string iName = BinSalt.attrib("cation1");
00608 if (iName == "") {
00609 throw CanteraError("HMWSoln::readXMLPsiCommonAnion", "no cation1 attrib");
00610 }
00611 string jName = BinSalt.attrib("cation2");
00612 if (jName == "") {
00613 throw CanteraError("HMWSoln::readXMLPsiCommonAnion", "no cation2 attrib");
00614 }
00615
00616
00617
00618
00619 int kSpecies = speciesIndex(kName);
00620 if (kSpecies < 0) {
00621 return;
00622 }
00623 if (charge[kSpecies] >= 0) {
00624 throw CanteraError("HMWSoln::readXMLPsiCommonAnion", "anion charge problem");
00625 }
00626 int iSpecies = speciesIndex(iName);
00627 if (iSpecies < 0) {
00628 return;
00629 }
00630 if (charge[iSpecies] <= 0) {
00631 throw CanteraError("HMWSoln::readXMLPsiCommonAnion",
00632 "cation1 charge problem");
00633 }
00634 int jSpecies = speciesIndex(jName);
00635 if (jSpecies < 0) {
00636 return;
00637 }
00638 if (charge[jSpecies] <= 0) {
00639 throw CanteraError("HMWSoln::readXMLPsiCommonAnion",
00640 "cation2 charge problem");
00641 }
00642
00643 int n = iSpecies * m_kk + jSpecies;
00644 int counter = m_CounterIJ[n];
00645 int num = BinSalt.nChildren();
00646 for (int i = 0; i < num; i++) {
00647 XML_Node &xmlChild = BinSalt.child(i);
00648 stemp = xmlChild.name();
00649 string nodeName = lowercase(stemp);
00650 if (nodeName == "theta") {
00651 stemp = xmlChild.value();
00652 double old = m_Theta_ij[counter];
00653 m_Theta_ij[counter] = atofCheck(stemp.c_str());
00654 if (old != 0.0) {
00655 if (old != m_Theta_ij[counter]) {
00656 throw CanteraError("HMWSoln::readXMLPsiCommonAnion",
00657 "conflicting values");
00658 }
00659 }
00660 }
00661 if (nodeName == "psi") {
00662
00663 getFloatArray(xmlChild, vParams, false, "", stemp);
00664 nParamsFound = vParams.size();
00665 n = iSpecies * m_kk *m_kk + jSpecies * m_kk + kSpecies ;
00666
00667 if (m_formPitzerTemp == PITZER_TEMP_CONSTANT) {
00668 if (nParamsFound != 1) {
00669 throw CanteraError("HMWSoln::readXMLPsiCommonAnion::Psi for "
00670 + kName + "::" + iName + "::" + jName,
00671 "wrong number of params found");
00672 }
00673 m_Psi_ijk_coeff(0,n) = vParams[0];
00674 m_Psi_ijk[n] = vParams[0];
00675 } else if (m_formPitzerTemp == PITZER_TEMP_LINEAR) {
00676 if (nParamsFound != 2) {
00677 throw CanteraError("HMWSoln::readXMLPsiAnion::Psi for "
00678 + kName + "::" + iName + "::" + jName,
00679 "wrong number of params found");
00680 }
00681 m_Psi_ijk_coeff(0,n) = vParams[0];
00682 m_Psi_ijk_coeff(1,n) = vParams[1];
00683 m_Psi_ijk[n] = vParams[0];
00684 } else if (m_formPitzerTemp == PITZER_TEMP_COMPLEX1) {
00685 if (nParamsFound == 1) {
00686 vParams.resize(5, 0.0);
00687 nParamsFound = 5;
00688 } else if (nParamsFound != 5) {
00689 throw CanteraError("HMWSoln::readXMLPsiAnion::Psi for "
00690 + kName + "::" + iName + "::" + jName,
00691 "wrong number of params found");
00692 }
00693 for (i = 0; i < nParamsFound; i++) {
00694 m_Psi_ijk_coeff(i, n) = vParams[i];
00695 }
00696 m_Psi_ijk[n] = vParams[0];
00697 }
00698
00699
00700
00701 n = iSpecies * m_kk *m_kk + kSpecies * m_kk + jSpecies ;
00702 for (i = 0; i < nParamsFound; i++) {
00703 m_Psi_ijk_coeff(i, n) = vParams[i];
00704 }
00705 m_Psi_ijk[n] = vParams[0];
00706
00707 n = jSpecies * m_kk *m_kk + iSpecies * m_kk + kSpecies ;
00708 for (i = 0; i < nParamsFound; i++) {
00709 m_Psi_ijk_coeff(i, n) = vParams[i];
00710 }
00711 m_Psi_ijk[n] = vParams[0];
00712
00713 n = jSpecies * m_kk *m_kk + kSpecies * m_kk + iSpecies ;
00714 for (i = 0; i < nParamsFound; i++) {
00715 m_Psi_ijk_coeff(i, n) = vParams[i];
00716 }
00717 m_Psi_ijk[n] = vParams[0];
00718
00719 n = kSpecies * m_kk *m_kk + jSpecies * m_kk + iSpecies ;
00720 for (i = 0; i < nParamsFound; i++) {
00721 m_Psi_ijk_coeff(i, n) = vParams[i];
00722 }
00723 m_Psi_ijk[n] = vParams[0];
00724
00725 n = kSpecies * m_kk *m_kk + iSpecies * m_kk + jSpecies ;
00726 for (i = 0; i < nParamsFound; i++) {
00727 m_Psi_ijk_coeff(i, n) = vParams[i];
00728 }
00729 m_Psi_ijk[n] = vParams[0];
00730
00731 }
00732 }
00733 }
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743 void HMWSoln::readXMLLambdaNeutral(XML_Node &BinSalt) {
00744 string xname = BinSalt.name();
00745 vector_fp vParams;
00746 int nParamsFound;
00747 if (xname != "lambdaNeutral") {
00748 throw CanteraError("HMWSoln::readXMLLanbdaNeutral",
00749 "Incorrect name for processing this routine: " + xname);
00750 }
00751 double *charge = DATA_PTR(m_speciesCharge);
00752 string stemp;
00753 string iName = BinSalt.attrib("species1");
00754 if (iName == "") {
00755 throw CanteraError("HMWSoln::readXMLLambdaNeutral", "no species1 attrib");
00756 }
00757 string jName = BinSalt.attrib("species2");
00758 if (jName == "") {
00759 throw CanteraError("HMWSoln::readXMLLambdaNeutral", "no species2 attrib");
00760 }
00761
00762
00763
00764
00765 int iSpecies = speciesIndex(iName);
00766 if (iSpecies < 0) {
00767 return;
00768 }
00769 if (charge[iSpecies] != 0) {
00770 throw CanteraError("HMWSoln::readXMLLambdaNeutral",
00771 "neutral charge problem");
00772 }
00773 int jSpecies = speciesIndex(jName);
00774 if (jSpecies < 0) {
00775 return;
00776 }
00777
00778 int num = BinSalt.nChildren();
00779 for (int i = 0; i < num; i++) {
00780 XML_Node &xmlChild = BinSalt.child(i);
00781 stemp = xmlChild.name();
00782 string nodeName = lowercase(stemp);
00783 if (nodeName == "lambda") {
00784 int nCount = iSpecies*m_kk + jSpecies;
00785 getFloatArray(xmlChild, vParams, false, "", stemp);
00786 nParamsFound = vParams.size();
00787 if (m_formPitzerTemp == PITZER_TEMP_CONSTANT) {
00788 if (nParamsFound != 1) {
00789 throw CanteraError("HMWSoln::readXMLLambdaNeutral::Lambda for " + iName
00790 + "::" + jName,
00791 "wrong number of params found");
00792 }
00793 m_Lambda_nj_coeff(0,nCount) = vParams[0];
00794 m_Lambda_nj(iSpecies,jSpecies) = vParams[0];
00795
00796 } else if (m_formPitzerTemp == PITZER_TEMP_LINEAR) {
00797 if (nParamsFound != 2) {
00798 throw CanteraError("HMWSoln::readXMLLambdaNeutral::Lambda for " + iName
00799 + "::" + jName,
00800 "wrong number of params found");
00801 }
00802 m_Lambda_nj_coeff(0,nCount) = vParams[0];
00803 m_Lambda_nj_coeff(1,nCount) = vParams[1];
00804 m_Lambda_nj(iSpecies, jSpecies) = vParams[0];
00805
00806 } else if (m_formPitzerTemp == PITZER_TEMP_COMPLEX1) {
00807 if (nParamsFound == 1) {
00808 vParams.resize(5, 0.0);
00809 nParamsFound = 5;
00810 } else if (nParamsFound != 5) {
00811 throw CanteraError("HMWSoln::readXMLLambdaNeutral::Lambda for " + iName
00812 + "::" + jName,
00813 "wrong number of params found");
00814 }
00815 for (i = 0; i < nParamsFound; i++) {
00816 m_Lambda_nj_coeff(i,nCount) = vParams[i];
00817 }
00818 m_Lambda_nj(iSpecies, jSpecies) = vParams[0];
00819 }
00820 }
00821 }
00822 }
00823
00824
00825
00826
00827
00828
00829 void HMWSoln::readXMLMunnnNeutral(XML_Node &BinSalt) {
00830 string xname = BinSalt.name();
00831 vector_fp vParams;
00832 int nParamsFound;
00833 if (xname != "MunnnNeutral") {
00834 throw CanteraError("HMWSoln::readXMLMunnnNeutral",
00835 "Incorrect name for processing this routine: " + xname);
00836 }
00837 double *charge = DATA_PTR(m_speciesCharge);
00838 string stemp;
00839 string iName = BinSalt.attrib("species1");
00840 if (iName == "") {
00841 throw CanteraError("HMWSoln::readXMLMunnnNeutral", "no species1 attrib");
00842 }
00843
00844
00845
00846
00847
00848 int iSpecies = speciesIndex(iName);
00849 if (iSpecies < 0) {
00850 return;
00851 }
00852 if (charge[iSpecies] != 0) {
00853 throw CanteraError("HMWSoln::readXMLMunnnNeutral",
00854 "neutral charge problem");
00855 }
00856
00857
00858 int num = BinSalt.nChildren();
00859 for (int i = 0; i < num; i++) {
00860 XML_Node &xmlChild = BinSalt.child(i);
00861 stemp = xmlChild.name();
00862 string nodeName = lowercase(stemp);
00863 if (nodeName == "munnn") {
00864 getFloatArray(xmlChild, vParams, false, "", "Munnn");
00865 nParamsFound = vParams.size();
00866 if (m_formPitzerTemp == PITZER_TEMP_CONSTANT) {
00867 if (nParamsFound != 1) {
00868 throw CanteraError("HMWSoln::readXMLMunnnNeutral::Munnn for " + iName,
00869 "wrong number of params found");
00870 }
00871 m_Mu_nnn_coeff(0,iSpecies) = vParams[0];
00872 m_Mu_nnn[iSpecies] = vParams[0];
00873
00874 } else if (m_formPitzerTemp == PITZER_TEMP_LINEAR) {
00875 if (nParamsFound != 2) {
00876 throw CanteraError("HMWSoln::readXMLMunnnNeutral::Munnn for " + iName,
00877 "wrong number of params found");
00878 }
00879 m_Mu_nnn_coeff(0, iSpecies) = vParams[0];
00880 m_Mu_nnn_coeff(1, iSpecies) = vParams[1];
00881 m_Mu_nnn[iSpecies] = vParams[0];
00882
00883 } else if (m_formPitzerTemp == PITZER_TEMP_COMPLEX1) {
00884 if (nParamsFound == 1) {
00885 vParams.resize(5, 0.0);
00886 nParamsFound = 5;
00887 } else if (nParamsFound != 5) {
00888 throw CanteraError("HMWSoln::readXMLMunnnNeutral::Munnn for " + iName,
00889 "wrong number of params found");
00890 }
00891 for (i = 0; i < nParamsFound; i++) {
00892 m_Mu_nnn_coeff(i, iSpecies) = vParams[i];
00893 }
00894 m_Mu_nnn[iSpecies] = vParams[0];
00895 }
00896 }
00897 }
00898 }
00899
00900
00901
00902
00903
00904
00905 void HMWSoln::readXMLZetaCation(const XML_Node &BinSalt) {
00906 string xname = BinSalt.name();
00907 if (xname != "zetaCation") {
00908 throw CanteraError("HMWSoln::readXMLZetaCation",
00909 "Incorrect name for processing this routine: " + xname);
00910 }
00911 double *charge = DATA_PTR(m_speciesCharge);
00912 string stemp;
00913 vector_fp vParams;
00914 int nParamsFound = 0;
00915
00916 string iName = BinSalt.attrib("neutral");
00917 if (iName == "") {
00918 throw CanteraError("HMWSoln::readXMLZetaCation", "no neutral attrib");
00919 }
00920
00921 string jName = BinSalt.attrib("cation1");
00922 if (jName == "") {
00923 throw CanteraError("HMWSoln::readXMLZetaCation", "no cation1 attrib");
00924 }
00925
00926 string kName = BinSalt.attrib("anion1");
00927 if (kName == "") {
00928 throw CanteraError("HMWSoln::readXMLZetaCation", "no anion1 attrib");
00929 }
00930
00931
00932
00933
00934 int iSpecies = speciesIndex(iName);
00935 if (iSpecies < 0) {
00936 return;
00937 }
00938 if (charge[iSpecies] != 0.0) {
00939 throw CanteraError("HMWSoln::readXMLZetaCation", "neutral charge problem");
00940 }
00941
00942 int jSpecies = speciesIndex(jName);
00943 if (jSpecies < 0) {
00944 return;
00945 }
00946 if (charge[jSpecies] <= 0.0) {
00947 throw CanteraError("HMWSoln::readXLZetaCation", "cation1 charge problem");
00948 }
00949
00950 int kSpecies = speciesIndex(kName);
00951 if (kSpecies < 0) {
00952 return;
00953 }
00954 if (charge[kSpecies] >= 0.0) {
00955 throw CanteraError("HMWSoln::readXMLZetaCation", "anion1 charge problem");
00956 }
00957
00958 int num = BinSalt.nChildren();
00959 for (int i = 0; i < num; i++) {
00960 XML_Node &xmlChild = BinSalt.child(i);
00961 stemp = xmlChild.name();
00962 string nodeName = lowercase(stemp);
00963 if (nodeName == "zeta") {
00964 getFloatArray(xmlChild, vParams, false, "", "zeta");
00965 nParamsFound = vParams.size();
00966 int n = iSpecies * m_kk *m_kk + jSpecies * m_kk + kSpecies ;
00967
00968 if (m_formPitzerTemp == PITZER_TEMP_CONSTANT) {
00969 if (nParamsFound != 1) {
00970 throw CanteraError("HMWSoln::readXMLZetaCation::Zeta for "
00971 + iName + "::" + jName + "::" + kName,
00972 "wrong number of params found");
00973 }
00974 m_Psi_ijk_coeff(0,n) = vParams[0];
00975 m_Psi_ijk[n] = vParams[0];
00976 } else if (m_formPitzerTemp == PITZER_TEMP_LINEAR) {
00977 if (nParamsFound != 2) {
00978 throw CanteraError("HMWSoln::readXMLZetaCation::Zeta for "
00979 + iName + "::" + jName + "::" + kName,
00980 "wrong number of params found");
00981 }
00982 m_Psi_ijk_coeff(0,n) = vParams[0];
00983 m_Psi_ijk_coeff(1,n) = vParams[1];
00984 m_Psi_ijk[n] = vParams[0];
00985 } else if (m_formPitzerTemp == PITZER_TEMP_COMPLEX1) {
00986 if (nParamsFound == 1) {
00987 vParams.resize(5, 0.0);
00988 nParamsFound = 5;
00989 } else if (nParamsFound != 5) {
00990 throw CanteraError("HMWSoln::readXMLZetaCation::Zeta for "
00991 + iName + "::" + jName + "::" + kName,
00992 "wrong number of params found");
00993 }
00994 for (i = 0; i < nParamsFound; i++) {
00995 m_Psi_ijk_coeff(i, n) = vParams[i];
00996 }
00997 m_Psi_ijk[n] = vParams[0];
00998 }
00999
01000
01001 }
01002 }
01003 }
01004
01005
01006
01007
01008
01009
01010 void HMWSoln::readXMLCroppingCoefficients(const XML_Node &acNode) {
01011
01012 if (acNode.hasChild("croppingCoefficients")) {
01013 XML_Node &cropNode = acNode.child("croppingCoefficients");
01014 if (cropNode.hasChild("ln_gamma_k_min")) {
01015 XML_Node &gkminNode = cropNode.child("ln_gamma_k_min");
01016 getOptionalFloat(gkminNode, "pureSolventValue", CROP_ln_gamma_k_min);
01017 }
01018 if (cropNode.hasChild("ln_gamma_k_max")) {
01019 XML_Node &gkmaxNode = cropNode.child("ln_gamma_k_max");
01020 getOptionalFloat(gkmaxNode, "pureSolventValue", CROP_ln_gamma_k_max);
01021 }
01022
01023 if (cropNode.hasChild("ln_gamma_o_min")) {
01024 XML_Node &gominNode = cropNode.child("ln_gamma_o_min");
01025 getOptionalFloat(gominNode, "pureSolventValue", CROP_ln_gamma_o_min);
01026 }
01027
01028 if (cropNode.hasChild("ln_gamma_o_max")) {
01029 XML_Node &gomaxNode = cropNode.child("ln_gamma_o_max");
01030 getOptionalFloat(gomaxNode, "pureSolventValue", CROP_ln_gamma_o_max);
01031 }
01032 }
01033 }
01034
01035
01036
01037
01038
01039
01040
01041 void HMWSoln::initThermo() {
01042 MolalityVPSSTP::initThermo();
01043 initLengths();
01044 }
01045
01046
01047
01048
01049
01050
01051
01052
01053
01054
01055
01056
01057
01058
01059
01060 void HMWSoln::constructPhaseFile(std::string inputFile, std::string id) {
01061
01062 if (inputFile.size() == 0) {
01063 throw CanteraError("HMWSoln:constructPhaseFile",
01064 "input file is null");
01065 }
01066 string path = findInputFile(inputFile);
01067 std::ifstream fin(path.c_str());
01068 if (!fin) {
01069 throw CanteraError("HMWSoln:constructPhaseFile","could not open "
01070 +path+" for reading.");
01071 }
01072
01073
01074
01075
01076 XML_Node &phaseNode_XML = xml();
01077 XML_Node *fxml = new XML_Node();
01078 fxml->build(fin);
01079 XML_Node *fxml_phase = findXMLPhase(fxml, id);
01080 if (!fxml_phase) {
01081 throw CanteraError("HMWSoln:constructPhaseFile",
01082 "ERROR: Can not find phase named " +
01083 id + " in file named " + inputFile);
01084 }
01085 fxml_phase->copy(&phaseNode_XML);
01086 constructPhaseXML(*fxml_phase, id);
01087 delete fxml;
01088 }
01089
01090
01091
01092
01093
01094
01095
01096
01097
01098
01099
01100
01101
01102
01103
01104
01105
01106
01107
01108
01109
01110
01111
01112
01113
01114
01115
01116
01117 void HMWSoln::constructPhaseXML(XML_Node& phaseNode, std::string id) {
01118 string stemp;
01119 if (id.size() > 0) {
01120 string idp = phaseNode.id();
01121 if (idp != id) {
01122 throw CanteraError("HMWSoln::constructPhaseXML",
01123 "phasenode and Id are incompatible");
01124 }
01125 }
01126
01127
01128
01129
01130 if (!phaseNode.hasChild("thermo")) {
01131 throw CanteraError("HMWSoln::constructPhaseXML",
01132 "no thermo XML node");
01133 }
01134 XML_Node& thermoNode = phaseNode.child("thermo");
01135
01136
01137
01138
01139 if (thermoNode.hasChild("standardConc")) {
01140 XML_Node& scNode = thermoNode.child("standardConc");
01141 m_formGC = 2;
01142 stemp = scNode.attrib("model");
01143 string formString = lowercase(stemp);
01144 if (formString != "") {
01145 if (formString == "unity") {
01146 m_formGC = 0;
01147 printf("exit standardConc = unity not done\n");
01148 exit(EXIT_FAILURE);
01149 } else if (formString == "molar_volume") {
01150 m_formGC = 1;
01151 printf("exit standardConc = molar_volume not done\n");
01152 exit(EXIT_FAILURE);
01153 } else if (formString == "solvent_volume") {
01154 m_formGC = 2;
01155 } else {
01156 throw CanteraError("HMWSoln::constructPhaseXML",
01157 "Unknown standardConc model: " + formString);
01158 }
01159 }
01160 }
01161
01162
01163
01164
01165 string solventName = "";
01166 if (thermoNode.hasChild("solvent")) {
01167 XML_Node& scNode = thermoNode.child("solvent");
01168 vector<string> nameSolventa;
01169 getStringArray(scNode, nameSolventa);
01170 int nsp = static_cast<int>(nameSolventa.size());
01171 if (nsp != 1) {
01172 throw CanteraError("HMWSoln::constructPhaseXML",
01173 "badly formed solvent XML node");
01174 }
01175 solventName = nameSolventa[0];
01176 }
01177
01178
01179
01180
01181
01182 if (thermoNode.hasChild("activityCoefficients")) {
01183 XML_Node& scNode = thermoNode.child("activityCoefficients");
01184 m_formPitzer = m_formPitzer;
01185 stemp = scNode.attrib("model");
01186 string formString = lowercase(stemp);
01187 if (formString != "") {
01188 if (formString == "pitzer" || formString == "default") {
01189 m_formPitzer = PITZERFORM_BASE;
01190 } else if (formString == "base") {
01191 m_formPitzer = PITZERFORM_BASE;
01192 } else {
01193 throw CanteraError("HMWSoln::constructPhaseXML",
01194 "Unknown Pitzer ActivityCoeff model: "
01195 + formString);
01196 }
01197 }
01198
01199
01200
01201
01202
01203 stemp = scNode.attrib("TempModel");
01204 formString = lowercase(stemp);
01205 if (formString != "") {
01206 if (formString == "constant" || formString == "default") {
01207 m_formPitzerTemp = PITZER_TEMP_CONSTANT;
01208 } else if (formString == "linear") {
01209 m_formPitzerTemp = PITZER_TEMP_LINEAR;
01210 } else if (formString == "complex" || formString == "complex1") {
01211 m_formPitzerTemp = PITZER_TEMP_COMPLEX1;
01212 } else {
01213 throw CanteraError("HMWSoln::constructPhaseXML",
01214 "Unknown Pitzer ActivityCoeff Temp model: "
01215 + formString);
01216 }
01217 }
01218
01219
01220
01221
01222
01223
01224 stemp = scNode.attrib("TempReference");
01225 formString = lowercase(stemp);
01226 if (formString != "") {
01227 m_TempPitzerRef = atofCheck(formString.c_str());
01228 } else {
01229 m_TempPitzerRef = 273.15 + 25;
01230 }
01231
01232 }
01233
01234
01235
01236
01237
01238
01239 bool m_ok = importPhase(phaseNode, this);
01240 if (!m_ok) {
01241 throw CanteraError("HMWSoln::constructPhaseXML","importPhase failed ");
01242 }
01243
01244 }
01245
01246
01247
01248
01249
01250
01251
01252
01253
01254
01255
01256
01257
01258
01259
01260
01261
01262
01263
01264 void HMWSoln::
01265 initThermoXML(XML_Node& phaseNode, std::string id) {
01266 int k;
01267 string stemp;
01268
01269
01270
01271 if (!phaseNode.hasChild("thermo")) {
01272 throw CanteraError("HMWSoln::initThermoXML",
01273 "no thermo XML node");
01274 }
01275 XML_Node& thermoNode = phaseNode.child("thermo");
01276
01277
01278
01279
01280
01281 string solventName = "";
01282 if (thermoNode.hasChild("solvent")) {
01283 XML_Node& scNode = thermoNode.child("solvent");
01284 vector<string> nameSolventa;
01285 getStringArray(scNode, nameSolventa);
01286 int nsp = static_cast<int>(nameSolventa.size());
01287 if (nsp != 1) {
01288 throw CanteraError("HMWSoln::initThermoXML",
01289 "badly formed solvent XML node");
01290 }
01291 solventName = nameSolventa[0];
01292 }
01293
01294
01295
01296
01297
01298 initLengths();
01299
01300
01301
01302
01303 for (k = 0; k < m_kk; k++) {
01304 string sname = speciesName(k);
01305 if (solventName == sname) {
01306 setSolvent(k);
01307 if (k != 0) {
01308 throw CanteraError("HMWSoln::initThermoXML",
01309 "Solvent must be species 0 atm");
01310 }
01311 m_indexSolvent = k;
01312 break;
01313 }
01314 }
01315 if (m_indexSolvent == -1) {
01316 std::cout << "HMWSoln::initThermo: Solvent Name not found"
01317 << std::endl;
01318 throw CanteraError("HMWSoln::initThermoXML",
01319 "Solvent name not found");
01320 }
01321 if (m_indexSolvent != 0) {
01322 throw CanteraError("HMWSoln::initThermoXML",
01323 "Solvent " + solventName +
01324 " should be first species");
01325 }
01326
01327
01328
01329
01330
01331
01332 XML_Node& speciesList = phaseNode.child("speciesArray");
01333 XML_Node* speciesDB =
01334 get_XML_NameID("speciesData", speciesList["datasrc"],
01335 &phaseNode.root());
01336 const vector<string>&sss = speciesNames();
01337
01338 for (k = 0; k < m_kk; k++) {
01339 XML_Node* s = speciesDB->findByAttr("name", sss[k]);
01340 if (!s) {
01341 throw CanteraError("HMWSoln::initThermoXML",
01342 "Species Data Base " + sss[k] + " not found");
01343 }
01344 XML_Node *ss = s->findByName("standardState");
01345 if (!ss) {
01346 throw CanteraError("HMWSoln::initThermoXML",
01347 "Species " + sss[k] +
01348 " standardState XML block not found");
01349 }
01350 string modelStringa = ss->attrib("model");
01351 if (modelStringa == "") {
01352 throw CanteraError("HMWSoln::initThermoXML",
01353 "Species " + sss[k] +
01354 " standardState XML block model attribute not found");
01355 }
01356 string modelString = lowercase(modelStringa);
01357 if (k == 0) {
01358 if (modelString == "wateriapws" || modelString == "real_water" ||
01359 modelString == "waterpdss") {
01360
01361
01362
01363
01364 m_waterSS = dynamic_cast<PDSS_Water *>(providePDSS(0)) ;
01365 if (!m_waterSS) {
01366 throw CanteraError("HMWSoln::initThermoXML",
01367 "Dynamic cast to PDSS_Water failed");
01368 }
01369
01370
01371
01372
01373
01374 m_waterSS->setState_TP(300., OneAtm);
01375 double dens = m_waterSS->density();
01376 double mw = m_waterSS->molecularWeight();
01377 m_speciesSize[0] = mw / dens;
01378 #ifdef DEBUG_HKM_NOT
01379 cout << "Solvent species " << sss[k] << " has volume " <<
01380 m_speciesSize[k] << endl;
01381 #endif
01382 } else {
01383
01384
01385
01386 m_waterSS = providePDSS(0);
01387 m_waterSS->setState_TP(300., OneAtm);
01388 double dens = m_waterSS->density();
01389 double mw = m_waterSS->molecularWeight();
01390 m_speciesSize[0] = mw / dens;
01391 }
01392 } else {
01393 if (modelString != "constant_incompressible" && modelString != "hkft") {
01394 throw CanteraError("HMWSoln::initThermoXML",
01395 "Solute SS Model \"" + modelStringa +
01396 "\" is not known");
01397 }
01398 if (modelString == "constant_incompressible" ) {
01399 m_speciesSize[k] = getFloat(*ss, "molarVolume", "toSI");
01400 #ifdef DEBUG_HKM_NOT
01401 cout << "species " << sss[k] << " has volume " <<
01402 m_speciesSize[k] << endl;
01403 #endif
01404 }
01405
01406 }
01407 }
01408
01409
01410
01411
01412
01413 m_waterProps = new WaterProps(dynamic_cast<PDSS_Water*>(m_waterSS));
01414
01415
01416
01417
01418
01419
01420
01421
01422 for (k = 0; k < m_kk; k++) {
01423 m_speciesCharge_Stoich[k] = m_speciesCharge[k];
01424 }
01425
01426
01427
01428
01429
01430 XML_Node *acNodePtr = 0;
01431 if (thermoNode.hasChild("activityCoefficients")) {
01432 XML_Node& acNode = thermoNode.child("activityCoefficients");
01433 acNodePtr = &acNode;
01434
01435
01436
01437 if (acNode.hasChild("A_Debye")) {
01438 XML_Node &ADebye = acNode.child("A_Debye");
01439 m_form_A_Debye = A_DEBYE_CONST;
01440 stemp = "model";
01441 if (ADebye.hasAttrib(stemp)) {
01442 string atemp = ADebye.attrib(stemp);
01443 stemp = lowercase(atemp);
01444 if (stemp == "water") {
01445 m_form_A_Debye = A_DEBYE_WATER;
01446 }
01447 }
01448 if (m_form_A_Debye == A_DEBYE_CONST) {
01449 m_A_Debye = getFloat(acNode, "A_Debye");
01450 }
01451 #ifdef DEBUG_HKM_NOT
01452 cout << "A_Debye = " << m_A_Debye << endl;
01453 #endif
01454 }
01455
01456
01457
01458
01459 if (acNode.hasChild("maxIonicStrength")) {
01460 m_maxIionicStrength = getFloat(acNode, "maxIonicStrength");
01461 #ifdef DEBUG_HKM_NOT
01462 cout << "m_maxIionicStrength = "
01463 <<m_maxIionicStrength << endl;
01464 #endif
01465 }
01466
01467
01468
01469
01470
01471 if (acNode.hasChild("ionicRadius")) {
01472 XML_Node& irNode = acNode.child("ionicRadius");
01473
01474 string Aunits = "";
01475 double Afactor = 1.0;
01476 if (irNode.hasAttrib("units")) {
01477 string Aunits = irNode.attrib("units");
01478 Afactor = toSI(Aunits);
01479 }
01480
01481 if (irNode.hasAttrib("default")) {
01482 string ads = irNode.attrib("default");
01483 double ad = fpValue(ads);
01484 for (int k = 0; k < m_kk; k++) {
01485 m_Aionic[k] = ad * Afactor;
01486 }
01487 }
01488
01489 }
01490
01491
01492
01493
01494
01495
01496 std::vector<const XML_Node *> xspecies = speciesData();
01497
01498 string kname, jname;
01499 int jj = xspecies.size();
01500 for (k = 0; k < m_kk; k++) {
01501 int jmap = -1;
01502 kname = speciesName(k);
01503 for (int j = 0; j < jj; j++) {
01504 const XML_Node& sp = *xspecies[j];
01505 jname = sp["name"];
01506 if (jname == kname) {
01507 jmap = j;
01508 break;
01509 }
01510 }
01511 if (jmap > -1) {
01512 const XML_Node& sp = *xspecies[jmap];
01513 getOptionalFloat(sp, "stoichIsMods", m_speciesCharge_Stoich[k]);
01514
01515
01516
01517
01518 }
01519 }
01520
01521
01522
01523
01524 if (acNodePtr) {
01525 if (acNodePtr->hasChild("stoichIsMods")) {
01526 XML_Node& sIsNode = acNodePtr->child("stoichIsMods");
01527
01528 map<string, string> msIs;
01529 getMap(sIsNode, msIs);
01530 map<string,string>::const_iterator _b = msIs.begin();
01531 for (; _b != msIs.end(); ++_b) {
01532 int kk = speciesIndex(_b->first);
01533 if (kk < 0) {
01534
01535
01536
01537
01538 } else {
01539 double val = fpValue(_b->second);
01540 m_speciesCharge_Stoich[kk] = val;
01541 }
01542 }
01543 }
01544 }
01545
01546
01547
01548
01549
01550
01551 if (acNodePtr) {
01552 int n = acNodePtr->nChildren();
01553 for (int i = 0; i < n; i++) {
01554 XML_Node &xmlACChild = acNodePtr->child(i);
01555 stemp = xmlACChild.name();
01556 string nodeName = lowercase(stemp);
01557
01558
01559
01560
01561
01562 if (nodeName == "binarysaltparameters") {
01563 readXMLBinarySalt(xmlACChild);
01564 } else if (nodeName == "thetaanion") {
01565 readXMLThetaAnion(xmlACChild);
01566 } else if (nodeName == "thetacation") {
01567 readXMLThetaCation(xmlACChild);
01568 } else if (nodeName == "psicommonanion") {
01569 readXMLPsiCommonAnion(xmlACChild);
01570 } else if (nodeName == "psicommoncation") {
01571 readXMLPsiCommonCation(xmlACChild);
01572 } else if (nodeName == "lambdaneutral") {
01573 readXMLLambdaNeutral(xmlACChild);
01574 } else if (nodeName == "zetacation") {
01575 readXMLZetaCation(xmlACChild);
01576 }
01577 }
01578 }
01579
01580
01581 readXMLCroppingCoefficients(acNode);
01582
01583 }
01584
01585
01586
01587
01588
01589
01590
01591
01592 for (k = 0; k < m_kk; k++) {
01593 if (fabs(m_speciesCharge[k]) > 0.0001) {
01594 m_electrolyteSpeciesType[k] = cEST_chargedSpecies;
01595 if (fabs(m_speciesCharge_Stoich[k] - m_speciesCharge[k])
01596 > 0.0001) {
01597 m_electrolyteSpeciesType[k] = cEST_weakAcidAssociated;
01598 }
01599 } else if (fabs(m_speciesCharge_Stoich[k]) > 0.0001) {
01600 m_electrolyteSpeciesType[k] = cEST_weakAcidAssociated;
01601 } else {
01602 m_electrolyteSpeciesType[k] = cEST_nonpolarNeutral;
01603 }
01604 }
01605 m_electrolyteSpeciesType[m_indexSolvent] = cEST_solvent;
01606
01607
01608
01609
01610
01611 std::vector<const XML_Node *> xspecies = speciesData();
01612 const XML_Node *spPtr = 0;
01613 string kname;
01614 for (k = 0; k < m_kk; k++) {
01615 kname = speciesName(k);
01616 spPtr = xspecies[k];
01617 if (!spPtr) {
01618 if (spPtr->hasChild("electrolyteSpeciesType")) {
01619 string est = getChildValue(*spPtr, "electrolyteSpeciesType");
01620 if ((m_electrolyteSpeciesType[k] = interp_est(est)) == -1) {
01621 throw CanteraError("HMWSoln::initThermoXML",
01622 "Bad electrolyte type: " + est);
01623 }
01624 }
01625 }
01626 }
01627
01628
01629
01630 if (acNodePtr) {
01631 if (acNodePtr->hasChild("electrolyteSpeciesType")) {
01632 XML_Node& ESTNode = acNodePtr->child("electrolyteSpeciesType");
01633 map<string, string> msEST;
01634 getMap(ESTNode, msEST);
01635 map<string,string>::const_iterator _b = msEST.begin();
01636 for (; _b != msEST.end(); ++_b) {
01637 int kk = speciesIndex(_b->first);
01638 if (kk < 0) {
01639 } else {
01640 string est = _b->second;
01641 if ((m_electrolyteSpeciesType[kk] = interp_est(est)) == -1) {
01642 throw CanteraError("HMWSoln::initThermoXML",
01643 "Bad electrolyte type: " + est);
01644 }
01645 }
01646 }
01647 }
01648 }
01649
01650 IMS_typeCutoff_ = 2;
01651 if (IMS_typeCutoff_ == 2) {
01652 calcIMSCutoffParams_();
01653 }
01654 calcMCCutoffParams_();
01655 setMoleFSolventMin(1.0E-5);
01656
01657 MolalityVPSSTP::initThermoXML(phaseNode, id);
01658
01659
01660
01661
01662
01663
01664
01665
01666 }
01667
01668
01669 void HMWSoln::calcIMSCutoffParams_() {
01670 IMS_afCut_ = 1.0 / (std::exp(1.0) * IMS_gamma_k_min_);
01671 IMS_efCut_ = 0.0;
01672 bool converged = false;
01673 double oldV = 0.0;
01674 int its;
01675 for (its = 0; its < 100 && !converged; its++) {
01676 oldV = IMS_efCut_;
01677 IMS_afCut_ = 1.0 / (std::exp(1.0) * IMS_gamma_k_min_) -IMS_efCut_;
01678 IMS_bfCut_ = IMS_afCut_ / IMS_cCut_ + IMS_slopefCut_ - 1.0;
01679 IMS_dfCut_ = ((- IMS_afCut_/IMS_cCut_ + IMS_bfCut_ - IMS_bfCut_*IMS_X_o_cutoff_/IMS_cCut_)
01680 /
01681 (IMS_X_o_cutoff_*IMS_X_o_cutoff_/IMS_cCut_ - 2.0 * IMS_X_o_cutoff_));
01682 double tmp = IMS_afCut_ + IMS_X_o_cutoff_*( IMS_bfCut_ + IMS_dfCut_ *IMS_X_o_cutoff_);
01683 double eterm = std::exp(-IMS_X_o_cutoff_/IMS_cCut_);
01684 IMS_efCut_ = - eterm * (tmp);
01685 if (fabs(IMS_efCut_ - oldV) < 1.0E-14) {
01686 converged = true;
01687 }
01688 }
01689 if (!converged) {
01690 throw CanteraError("HMWSoln::calcIMSCutoffParams_()",
01691 " failed to converge on the f polynomial");
01692 }
01693 converged = false;
01694 double f_0 = IMS_afCut_ + IMS_efCut_;
01695 double f_prime_0 = 1.0 - IMS_afCut_ / IMS_cCut_ + IMS_bfCut_;
01696 IMS_egCut_ = 0.0;
01697 for (its = 0; its < 100 && !converged; its++) {
01698 oldV = IMS_egCut_;
01699 double lng_0 = -log(IMS_gamma_o_min_) - f_prime_0 / f_0;
01700 IMS_agCut_ = exp(lng_0) - IMS_egCut_;
01701 IMS_bgCut_ = IMS_agCut_ / IMS_cCut_ + IMS_slopegCut_ - 1.0;
01702 IMS_dgCut_ = ((- IMS_agCut_/IMS_cCut_ + IMS_bgCut_ - IMS_bgCut_*IMS_X_o_cutoff_/IMS_cCut_)
01703 /
01704 (IMS_X_o_cutoff_*IMS_X_o_cutoff_/IMS_cCut_ - 2.0 * IMS_X_o_cutoff_));
01705 double tmp = IMS_agCut_ + IMS_X_o_cutoff_*( IMS_bgCut_ + IMS_dgCut_ *IMS_X_o_cutoff_);
01706 double eterm = std::exp(-IMS_X_o_cutoff_/IMS_cCut_);
01707 IMS_egCut_ = - eterm * (tmp);
01708 if (fabs(IMS_egCut_ - oldV) < 1.0E-14) {
01709 converged = true;
01710 }
01711 }
01712 if (!converged) {
01713 throw CanteraError("HMWSoln::calcIMSCutoffParams_()",
01714 " failed to converge on the g polynomial");
01715 }
01716 }
01717
01718
01719 void HMWSoln::calcMCCutoffParams_() {
01720 MC_X_o_min_ = 0.35;
01721 MC_X_o_cutoff_ = 0.6;
01722 MC_slopepCut_ = 0.02;
01723 MC_cpCut_ = 0.25;
01724
01725
01726 MC_apCut_ = MC_X_o_min_;
01727 MC_epCut_ = 0.0;
01728 bool converged = false;
01729 double oldV = 0.0;
01730 int its;
01731 double damp = 0.5;
01732 for (its = 0; its < 500 && !converged; its++) {
01733 oldV = MC_epCut_;
01734 MC_apCut_ = damp *(MC_X_o_min_ - MC_epCut_) + (1-damp) * MC_apCut_;
01735 double MC_bpCutNew = MC_apCut_ / MC_cpCut_ + MC_slopepCut_ - 1.0;
01736 MC_bpCut_ = damp * MC_bpCutNew + (1-damp) * MC_bpCut_;
01737 double MC_dpCutNew = ((- MC_apCut_/MC_cpCut_ + MC_bpCut_ - MC_bpCut_ * MC_X_o_cutoff_/MC_cpCut_)
01738 /
01739 (MC_X_o_cutoff_ * MC_X_o_cutoff_/MC_cpCut_ - 2.0 * MC_X_o_cutoff_));
01740 MC_dpCut_ = damp * MC_dpCutNew + (1-damp) * MC_dpCut_;
01741 double tmp = MC_apCut_ + MC_X_o_cutoff_*( MC_bpCut_ + MC_dpCut_ * MC_X_o_cutoff_);
01742 double eterm = std::exp(- MC_X_o_cutoff_ / MC_cpCut_);
01743 MC_epCut_ = - eterm * (tmp);
01744 double diff = MC_epCut_ - oldV;
01745 if (fabs(diff) < 1.0E-14) {
01746 converged = true;
01747 }
01748 }
01749 if (!converged) {
01750 throw CanteraError("HMWSoln::calcMCCutoffParams_()",
01751 " failed to converge on the p polynomial");
01752 }
01753 }
01754
01755 }