36 DebyeHuckel::DebyeHuckel() :
38 m_formDH(DHFORM_DILUTE_LIMIT),
40 m_IionicMolality(0.0),
41 m_maxIionicStrength(30.0),
42 m_useHelgesonFixedForm(false),
43 m_IionicMolalityStoich(0.0),
44 m_form_A_Debye(A_DEBYE_CONST),
68 m_formDH(DHFORM_DILUTE_LIMIT),
70 m_IionicMolality(0.0),
71 m_maxIionicStrength(30.0),
72 m_useHelgesonFixedForm(false),
73 m_IionicMolalityStoich(0.0),
74 m_form_A_Debye(A_DEBYE_CONST),
90 m_formDH(DHFORM_DILUTE_LIMIT),
92 m_IionicMolality(0.0),
93 m_maxIionicStrength(3.0),
94 m_useHelgesonFixedForm(false),
95 m_IionicMolalityStoich(0.0),
96 m_form_A_Debye(A_DEBYE_CONST),
100 m_densWaterSS(1000.),
118 m_formDH(DHFORM_DILUTE_LIMIT),
120 m_IionicMolality(0.0),
121 m_maxIionicStrength(30.0),
122 m_useHelgesonFixedForm(false),
123 m_IionicMolalityStoich(0.0),
124 m_form_A_Debye(A_DEBYE_CONST),
126 m_B_Debye(3.28640E9),
128 m_densWaterSS(1000.),
166 throw CanteraError(
"DebyHuckel::operator=()",
"Dynamic cast to waterPDSS failed");
268 double uu = hh - pres * molarV;
308 err(
"not implemented");
385 double* vbar = &
m_pp[0];
389 doublereal vtotal = 0.0;
390 for (
size_t i = 0; i <
m_kk; i++) {
391 vtotal += vbar[i] * x[i];
410 throw CanteraError(
"DebyeHuckel::isothermalCompressibility",
428 throw CanteraError(
"DebyeHuckel::thermalExpansionCoeff",
454 "Density is not an independent variable");
472 "molarDensity/density is not an independent variable");
508 for (
size_t k = 0; k <
m_kk; k++) {
533 return 1.0 / mvSolvent;
543 return log(c_solvent);
570 for (
int i = 0; i < sizeUA; i++) {
575 uA[1] = -int(
nDim());
608 for (
size_t k = 0; k <
m_kk; k++) {
636 for (
size_t k = 0; k <
m_kk; k++) {
637 acMolality[k] = exp(acMolality[k]);
662 const double xxSmall = 1.0E-150;
677 for (
size_t k = 0; k <
m_kk; k++) {
683 xx =
std::max(xmolSolvent, xxSmall);
712 for (
size_t k = 0; k <
m_kk; k++) {
729 for (
size_t k = 0; k <
m_kk; k++) {
776 for (
size_t k = 0; k <
m_kk; k++) {
789 for (
size_t k = 0; k <
m_kk; k++) {
807 for (
size_t k = 0; k <
m_kk; k++) {
842 for (
size_t k = 0; k <
m_kk; k++) {
864 for (
size_t k = 0; k <
m_kk; k++) {
885 for (
size_t k = 0; k <
m_kk; k++) {
930 if (inputFile.size() == 0) {
932 "input file is null");
935 ifstream fin(path.c_str());
937 throw CanteraError(
"DebyeHuckel::initThermo",
"could not open "
938 +path+
" for reading.");
950 "ERROR: Can not find phase named " +
951 id +
" in file named " + inputFile);
953 fxml_phase->
copy(&phaseNode_XML);
964 const char* cc = estString.c_str();
966 const char* ccl = lc.c_str();
967 if (!strcmp(ccl,
"solvent")) {
969 }
else if (!strcmp(ccl,
"chargedspecies")) {
970 return cEST_chargedSpecies;
971 }
else if (!strcmp(ccl,
"weakacidassociated")) {
972 return cEST_weakAcidAssociated;
973 }
else if (!strcmp(ccl,
"strongacidassociated")) {
974 return cEST_strongAcidAssociated;
975 }
else if (!strcmp(ccl,
"polarneutral")) {
976 return cEST_polarNeutral;
977 }
else if (!strcmp(ccl,
"nonpolarneutral")) {
978 return cEST_nonpolarNeutral;
981 if ((retn = sscanf(cc,
"%d", &rval)) != 1) {
1014 if (
id.
size() > 0) {
1015 std::string idp = phaseNode.
id();
1018 "phasenode and Id are incompatible");
1025 if (!phaseNode.
hasChild(
"thermo")) {
1027 "no thermo XML node");
1034 if (thermoNode.
hasChild(
"standardConc")) {
1037 std::string formString = scNode.
attrib(
"model");
1038 if (formString !=
"") {
1039 if (formString ==
"unity") {
1041 printf(
"exit standardConc = unity not done\n");
1043 }
else if (formString ==
"molar_volume") {
1045 printf(
"exit standardConc = molar_volume not done\n");
1047 }
else if (formString ==
"solvent_volume") {
1051 "Unknown standardConc model: " + formString);
1059 std::string solventName =
"";
1060 if (thermoNode.
hasChild(
"solvent")) {
1062 vector<std::string> nameSolventa;
1064 int nsp =
static_cast<int>(nameSolventa.size());
1067 "badly formed solvent XML node");
1069 solventName = nameSolventa[0];
1076 if (thermoNode.
hasChild(
"activityCoefficients")) {
1077 XML_Node& scNode = thermoNode.
child(
"activityCoefficients");
1079 std::string formString = scNode.
attrib(
"model");
1080 if (formString !=
"") {
1081 if (formString ==
"Dilute_limit") {
1083 }
else if (formString ==
"Bdot_with_variable_a") {
1085 }
else if (formString ==
"Bdot_with_common_a") {
1087 }
else if (formString ==
"Beta_ij") {
1089 }
else if (formString ==
"Pitzer_with_Beta_ij") {
1093 "Unknown standardConc model: " + formString);
1112 "importPhase failed ");
1141 if (!phaseNode.
hasChild(
"thermo")) {
1143 "no thermo XML node");
1150 if (thermoNode.
hasChild(
"standardConc")) {
1153 std::string formString = scNode.
attrib(
"model");
1154 if (formString !=
"") {
1155 if (formString ==
"unity") {
1157 printf(
"exit standardConc = unity not done\n");
1159 }
else if (formString ==
"molar_volume") {
1161 printf(
"exit standardConc = molar_volume not done\n");
1163 }
else if (formString ==
"solvent_volume") {
1167 "Unknown standardConc model: " + formString);
1181 std::string solventName =
"";
1182 if (thermoNode.
hasChild(
"solvent")) {
1184 vector<std::string> nameSolventa;
1186 int nsp =
static_cast<int>(nameSolventa.size());
1189 "badly formed solvent XML node");
1191 solventName = nameSolventa[0];
1193 for (
size_t k = 0; k <
m_kk; k++) {
1195 if (solventName == sname) {
1201 cout <<
"DebyeHuckel::initThermoXML: Solvent Name not found"
1204 "Solvent name not found");
1208 "Solvent " + solventName +
1209 " should be first species");
1216 if (thermoNode.
hasChild(
"activityCoefficients")) {
1217 XML_Node& scNode = thermoNode.
child(
"activityCoefficients");
1219 std::string formString = scNode.
attrib(
"model");
1220 if (formString !=
"") {
1221 if (formString ==
"Dilute_limit") {
1223 }
else if (formString ==
"Bdot_with_variable_a") {
1225 }
else if (formString ==
"Bdot_with_common_a") {
1227 }
else if (formString ==
"Beta_ij") {
1229 }
else if (formString ==
"Pitzer_with_Beta_ij") {
1233 "Unknown standardConc model: " + formString);
1261 for (
size_t k = 0; k <
m_kk; k++) {
1265 "Species Data Base " + sss[k] +
" not found");
1270 "Species " + sss[k] +
1271 " standardState XML block not found");
1273 std::string modelStringa = ss->
attrib(
"model");
1274 if (modelStringa ==
"") {
1276 "Species " + sss[k] +
1277 " standardState XML block model attribute not found");
1279 std::string modelString =
lowercase(modelStringa);
1282 if (modelString ==
"wateriapws" || modelString ==
"real_water" ||
1283 modelString ==
"waterpdss") {
1290 "Dynamic cast to PDSS_Water failed");
1301 #ifdef DEBUG_MODE_NOT
1302 cout <<
"Solvent species " << sss[k] <<
" has volume " <<
1305 }
else if (modelString ==
"constant_incompressible") {
1307 #ifdef DEBUG_MODE_NOT
1308 cout <<
"species " << sss[k] <<
" has volume " <<
1313 "Solvent SS Model \"" + modelStringa +
1317 if (modelString !=
"constant_incompressible") {
1319 "Solute SS Model \"" + modelStringa +
1323 #ifdef DEBUG_MODE_NOT
1324 cout <<
"species " << sss[k] <<
" has volume " <<
1336 if (thermoNode.
hasChild(
"activityCoefficients")) {
1337 XML_Node& acNode = thermoNode.
child(
"activityCoefficients");
1338 acNodePtr = &acNode;
1344 string modelStringa = ss->
attrib(
"model");
1345 string modelString =
lowercase(modelStringa);
1346 if (modelString !=
"") {
1347 if (modelString ==
"water") {
1351 "A_Debye Model \"" + modelStringa +
1356 #ifdef DEBUG_HKM_NOT
1357 cout <<
"A_Debye = " <<
m_A_Debye << endl;
1378 #ifdef DEBUG_HKM_NOT
1379 cout <<
"B_Debye = " <<
m_B_Debye << endl;
1389 m_formDH == DHFORM_PITZER_BETAIJ) {
1391 "B_dot entry in the wrong DH form");
1393 double bdot_common =
getFloat(acNode,
"B_dot");
1394 #ifdef DEBUG_HKM_NOT
1395 cout <<
"B_dot = " << bdot_common << endl;
1400 for (
size_t k = 0; k <
m_kk; k++) {
1402 if (fabs(z_k) > 0.0001) {
1413 if (acNode.
hasChild(
"maxIonicStrength")) {
1415 #ifdef DEBUG_HKM_NOT
1416 cout <<
"m_maxIionicStrength = "
1424 if (acNode.
hasChild(
"UseHelgesonFixedForm")) {
1433 if (acNode.
hasChild(
"ionicRadius")) {
1436 std::string Aunits =
"";
1437 double Afactor = 1.0;
1439 std::string Aunits = irNode.
attrib(
"units");
1440 Afactor =
toSI(Aunits);
1444 std::string ads = irNode.
attrib(
"default");
1446 for (
size_t k = 0; k <
m_kk; k++) {
1469 map<string, string> m;
1478 map<std::string,std::string>::const_iterator _b = m.begin();
1479 for (; _b != m.end(); ++_b) {
1492 if (acNode.
hasChild(
"DHBetaMatrix")) {
1494 m_formDH == DHFORM_PITZER_BETAIJ) {
1500 "DHBetaMatrix found for wrong type");
1512 for (
size_t k = 0; k <
m_kk; k++) {
1520 std::vector<const XML_Node*> xspecies=
speciesData();
1521 std::string kname, jname;
1522 size_t jj = xspecies.size();
1523 for (
size_t k = 0; k <
m_kk; k++) {
1526 for (
size_t j = 0; j < jj; j++) {
1529 if (jname == kname) {
1535 const XML_Node& sp = *xspecies[jmap];
1537 double val =
getFloat(sp,
"stoichIsMods");
1547 if (acNodePtr->
hasChild(
"stoichIsMods")) {
1550 map<std::string, std::string> msIs;
1552 map<std::string,std::string>::const_iterator _b = msIs.begin();
1553 for (; _b != msIs.end(); ++_b) {
1555 double val =
fpValue(_b->second);
1569 for (
size_t k = 0; k <
m_kk; k++) {
1588 std::vector<const XML_Node*> xspecies=
speciesData();
1591 for (
size_t k = 0; k <
m_kk; k++) {
1593 spPtr = xspecies[k];
1595 if (spPtr->
hasChild(
"electrolyteSpeciesType")) {
1596 std::string est =
getChildValue(*spPtr,
"electrolyteSpeciesType");
1599 "Bad electrolyte type: " + est);
1608 if (acNodePtr->
hasChild(
"electrolyteSpeciesType")) {
1609 XML_Node& ESTNode = acNodePtr->
child(
"electrolyteSpeciesType");
1610 map<std::string, std::string> msEST;
1612 map<std::string,std::string>::const_iterator _b = msEST.begin();
1613 for (; _b != msEST.end(); ++_b) {
1615 std::string est = _b->second;
1618 "Bad electrolyte type: " + est);
1694 if (tempArg != -1.0) {
1698 if (presArg != -1.0) {
1711 printf(
"shouldn't be here\n");
1730 if (tempArg != -1.0) {
1734 if (presArg != -1.0) {
1746 printf(
"shouldn't be here\n");
1765 if (tempArg != -1.0) {
1769 if (presArg != -1.0) {
1781 printf(
"shouldn't be here\n");
1800 if (tempArg != -1.0) {
1804 if (presArg != -1.0) {
1816 printf(
"shouldn't be here\n");
1842 doublereal DebyeHuckel::err(std::string msg)
const
1845 "Unfinished func called: " + msg);
1877 m_formDH == DHFORM_PITZER_BETAIJ) {
1891 double I2 = IionicMolality * IionicMolality;
1892 double l10actCoeff =
1896 return pow(10.0 , l10actCoeff);
1910 const double a0 = 1.454;
1911 const double b0 = 0.02236;
1912 const double c0 = 9.380E-3;
1913 const double d0 = -5.362E-4;
1918 double Is2 = Is * Is;
1919 double bhat = 1.0 + a0 * sqrt(Is);
1920 double func = bhat - 2.0 * log(bhat) - 1.0/bhat;
1921 double v1 =
m_A_Debye / (a0 * a0 * a0 * Is) * func;
1922 double oc = 1.0 - v1 + b0 * Is / 2.0 + 2.0 * c0 * Is2 / 3.0
1923 + 3.0 * d0 * Is2 * Is / 4.0;
1945 for (
size_t k = 0; k <
m_kk; k++) {
1972 double z_k, zs_k1, zs_k2;
1985 for (
size_t k = 0; k <
m_kk; k++) {
1999 for (
size_t k = 0; k <
m_kk; k++) {
2005 zs_k2 = z_k - zs_k1;
2032 xmolSolvent =
std::max(8.689E-3, xmolSolvent);
2035 double ac_nonPolar = 1.0;
2039 double lnActivitySolvent = 0.0;
2042 double y, yp1, sigma;
2044 case DHFORM_DILUTE_LIMIT:
2045 for (
size_t k = 0; k <
m_kk; k++) {
2050 (xmolSolvent - 1.0)/xmolSolvent +
2055 case DHFORM_BDOT_AK:
2057 for (
size_t k = 0; k <
m_kk; k++) {
2059 if (est == cEST_nonpolarNeutral) {
2064 - z_k * z_k * numTmp / (1.0 + denomTmp *
m_Aionic[k])
2069 lnActivitySolvent = (xmolSolvent - 1.0)/xmolSolvent;
2073 if (denomTmp > 0.0) {
2074 for (
size_t k = 0; k <
m_kk; k++) {
2078 sigma = 3.0 / (y * y * y) * (yp1 - 1.0/yp1 - 2.0*log(yp1));
2084 lnActivitySolvent += coeff * tmp;
2086 for (
size_t k = 0; k <
m_kk; k++) {
2092 lnActivitySolvent -=
2104 case DHFORM_BDOT_ACOMMON:
2106 for (
size_t k = 0; k <
m_kk; k++) {
2109 - z_k * z_k * numTmp / (1.0 + denomTmp)
2112 if (denomTmp > 0.0) {
2115 sigma = 3.0 / (y * y * y) * (yp1 - 1.0/yp1 - 2.0*log(yp1));
2120 (xmolSolvent - 1.0)/xmolSolvent +
2124 for (
size_t k = 0; k <
m_kk; k++) {
2130 lnActivitySolvent -=
2139 (xmolSolvent - 1.0)/xmolSolvent;
2141 for (
size_t k = 0; k <
m_kk; k++) {
2145 - z_k * z_k * numTmp / (1.0 + denomTmp);
2146 for (
size_t j = 0; j <
m_kk; j++) {
2148 #ifdef DEBUG_HKM_NOT
2150 printf(
"b: k = %d, j = %d, betakj = %g\n",
2158 if (denomTmp > 0.0) {
2161 sigma = 3.0 / (y * y * y) * (yp1 - 1.0/yp1 -2.0*log(yp1));
2166 (xmolSolvent - 1.0)/xmolSolvent +
2170 for (
size_t k = 0; k <
m_kk; k++) {
2171 for (
size_t j = 0; j <
m_kk; j++) {
2179 case DHFORM_PITZER_BETAIJ:
2181 denomTmp *= m_Aionic[0];
2183 tmpLn = log(1.0 + denomTmp);
2184 for (
size_t k = 0; k <
m_kk; k++) {
2188 - z_k * z_k * numTmp / 3.0 / (1.0 + denomTmp);
2192 for (
size_t j = 0; j <
m_kk; j++) {
2198 sigma = 1.0 / (1.0 + denomTmp);
2200 (xmolSolvent - 1.0)/xmolSolvent +
2204 for (
size_t k = 0; k <
m_kk; k++) {
2205 for (
size_t j = 0; j <
m_kk; j++) {
2225 lnActivitySolvent - log(xmolSolvent);
2242 double z_k, coeff, tmp, y, yp1, sigma, tmpLn;
2246 for (
size_t k = 0; k <
m_kk; k++) {
2256 xmolSolvent =
std::max(8.689E-3, xmolSolvent);
2260 double numdAdTTmp = dAdT * sqrtI;
2262 double d_lnActivitySolvent_dT = 0;
2265 case DHFORM_DILUTE_LIMIT:
2266 for (
size_t k = 1; k <
m_kk; k++) {
2270 d_lnActivitySolvent_dT = 2.0 / 3.0 * dAdT *
m_Mnaught *
2275 case DHFORM_BDOT_AK:
2276 for (
size_t k = 0; k <
m_kk; k++) {
2279 - z_k * z_k * numdAdTTmp / (1.0 + denomTmp *
m_Aionic[k]);
2284 coeff = 2.0 / 3.0 * dAdT *
m_Mnaught * sqrtI;
2286 if (denomTmp > 0.0) {
2287 for (
size_t k = 0; k <
m_kk; k++) {
2290 sigma = 3.0 / (y * y * y) * (yp1 - 1.0/yp1 - 2.0*log(yp1));
2298 case DHFORM_BDOT_ACOMMON:
2300 for (
size_t k = 0; k <
m_kk; k++) {
2303 - z_k * z_k * numdAdTTmp / (1.0 + denomTmp);
2305 if (denomTmp > 0.0) {
2308 sigma = 3.0 / (y * y * y) * (yp1 - 1.0/yp1 - 2.0*log(yp1));
2319 for (
size_t k = 0; k <
m_kk; k++) {
2323 - z_k * z_k * numdAdTTmp / (1.0 + denomTmp);
2326 if (denomTmp > 0.0) {
2329 sigma = 3.0 / (y * y * y) * (yp1 - 1.0/yp1 - 2.0*log(yp1));
2338 case DHFORM_PITZER_BETAIJ:
2340 tmpLn = log(1.0 + denomTmp);
2341 for (
size_t k = 0; k <
m_kk; k++) {
2345 - z_k * z_k * numdAdTTmp / (1.0 + denomTmp)
2346 - 2.0 * z_k * z_k * dAdT * tmpLn
2352 sigma = 1.0 / (1.0 + denomTmp);
2382 double z_k, coeff, tmp, y, yp1, sigma, tmpLn;
2385 if (d2AdT2 == 0.0 && dAdT == 0.0) {
2386 for (
size_t k = 0; k <
m_kk; k++) {
2397 xmolSolvent =
std::max(8.689E-3, xmolSolvent);
2401 double numd2AdT2Tmp = d2AdT2 * sqrtI;
2405 case DHFORM_DILUTE_LIMIT:
2406 for (
size_t k = 0; k <
m_kk; k++) {
2412 case DHFORM_BDOT_AK:
2413 for (
size_t k = 0; k <
m_kk; k++) {
2416 - z_k * z_k * numd2AdT2Tmp / (1.0 + denomTmp *
m_Aionic[k]);
2421 coeff = 2.0 / 3.0 * d2AdT2 *
m_Mnaught * sqrtI;
2423 if (denomTmp > 0.0) {
2424 for (
size_t k = 0; k <
m_kk; k++) {
2427 sigma = 3.0 / (y * y * y) * (yp1 - 1.0/yp1 - 2.0*log(yp1));
2435 case DHFORM_BDOT_ACOMMON:
2437 for (
size_t k = 0; k <
m_kk; k++) {
2440 - z_k * z_k * numd2AdT2Tmp / (1.0 + denomTmp);
2442 if (denomTmp > 0.0) {
2445 sigma = 3.0 / (y * y * y) * (yp1 - 1.0/yp1 - 2.0*log(yp1));
2456 for (
size_t k = 0; k <
m_kk; k++) {
2460 - z_k * z_k * numd2AdT2Tmp / (1.0 + denomTmp);
2463 if (denomTmp > 0.0) {
2466 sigma = 3.0 / (y * y * y) * (yp1 - 1.0/yp1 -2.0*log(yp1));
2475 case DHFORM_PITZER_BETAIJ:
2477 tmpLn = log(1.0 + denomTmp);
2478 for (
size_t k = 0; k <
m_kk; k++) {
2482 - z_k * z_k * numd2AdT2Tmp / (1.0 + denomTmp)
2483 - 2.0 * z_k * z_k * d2AdT2 * tmpLn
2489 sigma = 1.0 / (1.0 + denomTmp);
2517 double z_k, coeff, tmp, y, yp1, sigma, tmpLn;
2521 for (
size_t k = 0; k <
m_kk; k++) {
2531 xmolSolvent =
std::max(8.689E-3, xmolSolvent);
2535 double numdAdPTmp = dAdP * sqrtI;
2539 case DHFORM_DILUTE_LIMIT:
2540 for (
size_t k = 0; k <
m_kk; k++) {
2546 case DHFORM_BDOT_AK:
2547 for (
size_t k = 0; k <
m_kk; k++) {
2549 if (est == cEST_nonpolarNeutral) {
2554 - z_k * z_k * numdAdPTmp / (1.0 + denomTmp *
m_Aionic[k]);
2560 coeff = 2.0 / 3.0 * dAdP *
m_Mnaught * sqrtI;
2562 if (denomTmp > 0.0) {
2563 for (
size_t k = 0; k <
m_kk; k++) {
2566 sigma = 3.0 / (y * y * y) * (yp1 - 1.0/yp1 - 2.0*log(yp1));
2574 case DHFORM_BDOT_ACOMMON:
2576 for (
size_t k = 0; k <
m_kk; k++) {
2579 - z_k * z_k * numdAdPTmp / (1.0 + denomTmp);
2581 if (denomTmp > 0.0) {
2584 sigma = 3.0 / (y * y * y) * (yp1 - 1.0/yp1 - 2.0*log(yp1));
2595 for (
size_t k = 0; k <
m_kk; k++) {
2599 - z_k * z_k * numdAdPTmp / (1.0 + denomTmp);
2602 if (denomTmp > 0.0) {
2605 sigma = 3.0 / (y * y * y) * (yp1 - 1.0/yp1 - 2.0*log(yp1));
2614 case DHFORM_PITZER_BETAIJ:
2616 tmpLn = log(1.0 + denomTmp);
2617 for (
size_t k = 0; k <
m_kk; k++) {
2621 - z_k * z_k * numdAdPTmp / (1.0 + denomTmp)
2622 - 2.0 * z_k * z_k * dAdP * tmpLn
2628 sigma = 1.0 / (1.0 + denomTmp);