31 m_formPitzerTemp(PITZER_TEMP_CONSTANT),
32 m_IionicMolality(0.0),
33 m_maxIionicStrength(100.0),
34 m_TempPitzerRef(298.15),
35 m_form_A_Debye(A_DEBYE_CONST),
38 m_molalitiesAreCropped(false),
56 CROP_ln_gamma_o_min(-6.0),
57 CROP_ln_gamma_o_max(3.0),
58 CROP_ln_gamma_k_min(-5.0),
59 CROP_ln_gamma_k_max(15.0),
69 m_formPitzerTemp(PITZER_TEMP_CONSTANT),
70 m_IionicMolality(0.0),
71 m_maxIionicStrength(100.0),
72 m_TempPitzerRef(298.15),
73 m_form_A_Debye(A_DEBYE_CONST),
76 m_molalitiesAreCropped(false),
94 CROP_ln_gamma_o_min(-6.0),
95 CROP_ln_gamma_o_max(3.0),
96 CROP_ln_gamma_k_min(-5.0),
97 CROP_ln_gamma_k_max(15.0),
104 m_formPitzerTemp(PITZER_TEMP_CONSTANT),
105 m_IionicMolality(0.0),
106 m_maxIionicStrength(100.0),
107 m_TempPitzerRef(298.15),
108 m_form_A_Debye(A_DEBYE_CONST),
111 m_molalitiesAreCropped(false),
112 IMS_X_o_cutoff_(0.2),
129 CROP_ln_gamma_o_min(-6.0),
130 CROP_ln_gamma_o_max(3.0),
131 CROP_ln_gamma_k_min(-5.0),
132 CROP_ln_gamma_k_max(15.0),
151 for (
size_t k = 0; k <
m_kk; k++) {
163 size_t kcation =
npos;
164 double xcation = 0.0;
165 size_t kanion =
npos;
166 for (
size_t k = 0; k <
m_kk; k++) {
172 }
else if (
charge(k) < 0.0) {
173 if (
m_tmpV[k] > xcation) {
179 if (kcation ==
npos || kanion ==
npos) {
182 double xuse = xcation;
184 if (xanion < xcation) {
186 if (
charge(kcation) != 1.0) {
190 if (
charge(kanion) != 1.0) {
194 xuse = xuse / factor;
223 return cp - beta * beta * tt * molarV / kappa_t;
246 "Overloaded function to be removed after Cantera 2.5. "
247 "Error will be thrown by Phase::setDensity instead");
249 if (rho != dens_old) {
251 "Density is not an independent variable");
258 "Overloaded function to be removed after Cantera 2.5. "
259 "Error will be thrown by Phase::setMolarDensity instead");
261 "Density is not an independent variable");
273 for (
size_t k = 1; k <
m_kk; k++) {
282 double mvSolvent =
m_tmpV[0];
286 return 1.0 / mvSolvent;
295 s_update_lnMolalityActCoeff();
298 for (
size_t k = 1; k <
m_kk; k++) {
309 s_update_lnMolalityActCoeff();
311 for (
size_t k = 0; k <
m_kk; k++) {
312 acMolality[k] = exp(acMolality[k]);
328 s_update_lnMolalityActCoeff();
330 for (
size_t k = 1; k <
m_kk; k++) {
344 for (
size_t k = 0; k <
m_kk; k++) {
350 s_update_lnMolalityActCoeff();
352 for (
size_t k = 0; k <
m_kk; k++) {
364 for (
size_t k = 0; k <
m_kk; k++) {
370 s_update_lnMolalityActCoeff();
375 for (
size_t k = 1; k <
m_kk; k++) {
387 for (
size_t k = 0; k <
m_kk; k++) {
398 s_update_lnMolalityActCoeff();
400 for (
size_t k = 0; k <
m_kk; k++) {
408 for (
size_t k = 0; k <
m_kk; k++) {
414 s_update_lnMolalityActCoeff();
417 for (
size_t k = 0; k <
m_kk; k++) {
435 static void check_nParams(
const std::string& method,
size_t nParams,
436 size_t m_formPitzerTemp)
438 if (m_formPitzerTemp == PITZER_TEMP_CONSTANT && nParams != 1) {
439 throw CanteraError(method,
"'constant' temperature model requires one"
440 " coefficient for each of parameter, but {} were given", nParams);
441 }
else if (m_formPitzerTemp == PITZER_TEMP_LINEAR && nParams != 2) {
442 throw CanteraError(method,
"'linear' temperature model requires two"
443 " coefficients for each parameter, but {} were given", nParams);
445 if (m_formPitzerTemp == PITZER_TEMP_COMPLEX1 && nParams != 5) {
446 throw CanteraError(method,
"'complex' temperature model requires five"
447 " coefficients for each parameter, but {} were given", nParams);
451 void HMWSoln::setBinarySalt(
const std::string& sp1,
const std::string& sp2,
452 size_t nParams,
double* beta0,
double* beta1,
double* beta2,
453 double* Cphi,
double alpha1,
double alpha2)
458 throw CanteraError(
"HMWSoln::setBinarySalt",
"Species '{}' not found", sp1);
459 }
else if (k2 ==
npos) {
460 throw CanteraError(
"HMWSoln::setBinarySalt",
"Species '{}' not found", sp2);
465 throw CanteraError(
"HMWSoln::setBinarySalt",
"Species '{}' and '{}' "
466 "do not have opposite charges ({}, {})", sp1, sp2,
476 for (
size_t n = 0; n < nParams; n++) {
482 m_Alpha1MX_ij[c] = alpha1;
486 void HMWSoln::setTheta(
const std::string& sp1,
const std::string& sp2,
487 size_t nParams,
double* theta)
492 throw CanteraError(
"HMWSoln::setTheta",
"Species '{}' not found", sp1);
493 }
else if (k2 ==
npos) {
494 throw CanteraError(
"HMWSoln::setTheta",
"Species '{}' not found", sp2);
497 throw CanteraError(
"HMWSoln::setTheta",
"Species '{}' and '{}' "
498 "should both have the same (non-zero) charge ({}, {})", sp1, sp2,
504 for (
size_t n = 0; n < nParams; n++) {
509 void HMWSoln::setPsi(
const std::string& sp1,
const std::string& sp2,
510 const std::string& sp3,
size_t nParams,
double* psi)
516 throw CanteraError(
"HMWSoln::setPsi",
"Species '{}' not found", sp1);
517 }
else if (k2 ==
npos) {
518 throw CanteraError(
"HMWSoln::setPsi",
"Species '{}' not found", sp2);
519 }
else if (k3 ==
npos) {
520 throw CanteraError(
"HMWSoln::setPsi",
"Species '{}' not found", sp3);
525 throw CanteraError(
"HMWSoln::setPsi",
"All species must be ions and"
526 " must include at least one cation and one anion, but given species"
527 " (charges) were: {} ({}), {} ({}), and {} ({}).",
538 for (
size_t n = 0; n < nParams; n++) {
545 void HMWSoln::setLambda(
const std::string& sp1,
const std::string& sp2,
546 size_t nParams,
double* lambda)
551 throw CanteraError(
"HMWSoln::setLambda",
"Species '{}' not found", sp1);
552 }
else if (k2 ==
npos) {
553 throw CanteraError(
"HMWSoln::setLambda",
"Species '{}' not found", sp2);
557 throw CanteraError(
"HMWSoln::setLambda",
"Expected at least one neutral"
558 " species, but given species (charges) were: {} ({}) and {} ({}).",
565 size_t c = k1*
m_kk + k2;
566 for (
size_t n = 0; n < nParams; n++) {
572 void HMWSoln::setMunnn(
const std::string& sp,
size_t nParams,
double* munnn)
576 throw CanteraError(
"HMWSoln::setMunnn",
"Species '{}' not found", sp);
580 throw CanteraError(
"HMWSoln::setMunnn",
"Expected a neutral species,"
581 " got {} ({}).", sp,
charge(k));
584 for (
size_t n = 0; n < nParams; n++) {
590 void HMWSoln::setZeta(
const std::string& sp1,
const std::string& sp2,
591 const std::string& sp3,
size_t nParams,
double* psi)
597 throw CanteraError(
"HMWSoln::setZeta",
"Species '{}' not found", sp1);
598 }
else if (k2 ==
npos) {
599 throw CanteraError(
"HMWSoln::setZeta",
"Species '{}' not found", sp2);
600 }
else if (k3 ==
npos) {
601 throw CanteraError(
"HMWSoln::setZeta",
"Species '{}' not found", sp3);
606 throw CanteraError(
"HMWSoln::setZeta",
"Requires one neutral species, "
607 "one cation, and one anion, but given species (charges) were: "
608 "{} ({}), {} ({}), and {} ({}).",
615 }
else if (
charge(k3) == 0) {
627 for (
size_t n = 0; n < nParams; n++) {
633 void HMWSoln::setPitzerTempModel(
const std::string& model)
642 throw CanteraError(
"HMWSoln::setPitzerTempModel",
643 "Unknown Pitzer ActivityCoeff Temp model: {}", model);
657 void HMWSoln::setCroppingCoefficients(
double ln_gamma_k_min,
658 double ln_gamma_k_max,
double ln_gamma_o_min,
double ln_gamma_o_max)
660 CROP_ln_gamma_k_min = ln_gamma_k_min;
661 CROP_ln_gamma_k_max = ln_gamma_k_max;
662 CROP_ln_gamma_o_min = ln_gamma_o_min;
663 CROP_ln_gamma_o_max = ln_gamma_o_max;
666 vector_fp getSizedVector(
const AnyMap& item,
const std::string& key,
size_t nCoeffs)
669 if (item[key].is<double>()) {
672 v.push_back(item[key].asDouble());
674 v = item[key].asVector<
double>(1, nCoeffs);
676 if (v.size() == 1 && nCoeffs == 5) {
689 setPitzerTempModel(actData[
"temperature-model"].asString());
697 if (actData.hasKey(
"A_Debye")) {
698 if (actData[
"A_Debye"] ==
"variable") {
701 setA_Debye(actData.convert(
"A_Debye",
"kg^0.5/gmol^0.5"));
704 if (actData.hasKey(
"max-ionic-strength")) {
705 setMaxIonicStrength(actData[
"max-ionic-strength"].asDouble());
707 if (actData.hasKey(
"interactions")) {
708 for (
auto& item : actData[
"interactions"].asVector<AnyMap>()) {
709 auto&
species = item[
"species"].asVector<
string>(1, 3);
714 if (nsp == 2 && q0 * q1 < 0) {
716 vector_fp beta0 = getSizedVector(item,
"beta0", nCoeffs);
717 vector_fp beta1 = getSizedVector(item,
"beta1", nCoeffs);
718 vector_fp beta2 = getSizedVector(item,
"beta2", nCoeffs);
719 vector_fp Cphi = getSizedVector(item,
"Cphi", nCoeffs);
720 if (beta0.size() != beta1.size() || beta0.size() != beta2.size()
721 || beta0.size() != Cphi.size()) {
723 "Inconsistent binary salt array sizes ({}, {}, {}, {})",
724 beta0.size(), beta1.size(), beta2.size(), Cphi.size());
726 double alpha1 = item[
"alpha1"].asDouble();
727 double alpha2 = item.getDouble(
"alpha2", 0.0);
729 beta0.data(), beta1.data(), beta2.data(), Cphi.data(),
731 }
else if (nsp == 2 && q0 * q1 > 0) {
733 vector_fp theta = getSizedVector(item,
"theta", nCoeffs);
735 }
else if (nsp == 2 && q0 * q1 == 0) {
737 vector_fp lambda = getSizedVector(item,
"lambda", nCoeffs);
739 }
else if (nsp == 3 && q0 * q1 * q2 != 0) {
741 vector_fp psi = getSizedVector(item,
"psi", nCoeffs);
743 psi.size(), psi.data());
744 }
else if (nsp == 3 && q0 * q1 * q2 == 0) {
746 vector_fp zeta = getSizedVector(item,
"zeta", nCoeffs);
748 zeta.size(), zeta.data());
749 }
else if (nsp == 1) {
751 vector_fp mu = getSizedVector(item,
"mu", nCoeffs);
752 setMunnn(
species[0], mu.size(), mu.data());
756 if (actData.hasKey(
"cropping-coefficients")) {
757 auto& crop = actData[
"cropping-coefficients"].as<
AnyMap>();
758 setCroppingCoefficients(
759 crop.getDouble(
"ln_gamma_k_min", -5.0),
760 crop.getDouble(
"ln_gamma_k_max", 15.0),
761 crop.getDouble(
"ln_gamma_o_min", -6.0),
762 crop.getDouble(
"ln_gamma_o_max", 3.0));
768 for (
int i = 0; i < 17; i++) {
790 for (
size_t k = 0; k <
m_kk; k++) {
792 if (fabs(mf[k] *
charge(k)) > MaxC) {
799 if (fabs(sum) > 1.0E-30) {
801 if (mf[kHp] > sum * 1.1) {
815 if (mf[kOHm] > -sum * 1.1) {
827 if (notDone && kMaxC !=
npos) {
828 if (mf[kMaxC] > (1.1 * sum /
charge(kMaxC))) {
829 mf[kMaxC] -= sum /
charge(kMaxC);
830 mf[0] += sum /
charge(kMaxC);
851 if (id_.size() > 0) {
852 string idp = phaseNode.
id();
855 "phasenode and Id are incompatible");
860 if (!phaseNode.
hasChild(
"thermo")) {
862 "no thermo XML node");
868 if (thermoNode.
hasChild(
"activityCoefficients")) {
873 string formString = scNode.
attrib(
"TempModel");
874 if (formString !=
"") {
875 setPitzerTempModel(formString);
881 formString = scNode.
attrib(
"TempReference");
882 if (formString !=
"") {
893 if (thermoNode.
hasChild(
"activityCoefficients")) {
907 if (acNode.
hasChild(
"maxIonicStrength")) {
908 setMaxIonicStrength(
getFloat(acNode,
"maxIonicStrength"));
911 for (
const auto& xmlACChild : acNode.
children()) {
912 string nodeName = xmlACChild->name();
935 if (acNode.
hasChild(
"croppingCoefficients")) {
937 setCroppingCoefficients(
938 getFloat(cropNode.
child(
"ln_gamma_k_min"),
"pureSolventValue"),
939 getFloat(cropNode.
child(
"ln_gamma_k_max"),
"pureSolventValue"),
940 getFloat(cropNode.
child(
"ln_gamma_o_min"),
"pureSolventValue"),
941 getFloat(cropNode.
child(
"ln_gamma_o_max"),
"pureSolventValue"));
952 if (tempArg != -1.0) {
956 if (presArg != -1.0) {
975 throw CanteraError(
"HMWSoln::A_Debye_TP",
"shouldn't be here");
983 if (tempArg != -1.0) {
987 if (presArg != -1.0) {
999 throw CanteraError(
"HMWSoln::dA_DebyedT_TP",
"shouldn't be here");
1007 if (tempArg != -1.0) {
1011 if (presArg != -1.0) {
1024 dAdP = cached.
value;
1027 cached.
value = dAdP;
1031 throw CanteraError(
"HMWSoln::dA_DebyedP_TP",
"shouldn't be here");
1039 double dAphidT = dAdT /3.0;
1041 if (tempArg != -1.0) {
1050 double dAphidP = dAdP /3.0;
1052 if (tempArg != -1.0) {
1061 if (tempArg != -1.0) {
1066 double d2Aphi = d2 / 3.0;
1067 return 2.0 * A_L / T + 4.0 *
GasConstant * T * T *d2Aphi;
1073 if (tempArg != -1.0) {
1077 if (presArg != -1.0) {
1089 throw CanteraError(
"HMWSoln::d2A_DebyedT2_TP",
"shouldn't be here");
1103 size_t maxCounterIJlen = 1 + (
m_kk-1) * (
m_kk-2) / 2;
1106 int TCoeffLength = 1;
1137 m_Alpha1MX_ij.resize(maxCounterIJlen, 2.0);
1178 m_BMX_IJ.resize(maxCounterIJlen, 0.0);
1190 m_Phi_IJ.resize(maxCounterIJlen, 0.0);
1199 m_CMX_IJ.resize(maxCounterIJlen, 0.0);
1211 void HMWSoln::s_update_lnMolalityActCoeff()
const
1239 double lnActCoeffMolal0 = - log(xx) + (xx - 1.0)/xx;
1240 double lnxs = log(xx);
1242 for (
size_t k = 1; k <
m_kk; k++) {
1277 doublereal Imax = 0.0;
1280 for (
size_t k = 0; k <
m_kk; k++) {
1286 if (cropMethod == 0) {
1293 for (
size_t i = 1; i < (
m_kk - 1); i++) {
1294 double charge_i =
charge(i);
1295 double abs_charge_i = fabs(charge_i);
1296 if (charge_i == 0.0) {
1299 for (
size_t j = (i+1); j <
m_kk; j++) {
1300 double charge_j =
charge(j);
1301 double abs_charge_j = fabs(charge_j);
1304 if (charge_i * charge_j < 0) {
1309 if (Imax > Iac_max) {
1313 if (Imax > Iac_max) {
1318 if (Imax > Iac_max) {
1322 if (Imax > Iac_max) {
1332 for (
int times = 0; times< 10; times++) {
1333 double anion_charge = 0.0;
1334 double cation_charge = 0.0;
1335 size_t anion_contrib_max_i =
npos;
1336 double anion_contrib_max = -1.0;
1337 size_t cation_contrib_max_i =
npos;
1338 double cation_contrib_max = -1.0;
1339 for (
size_t i = 0; i <
m_kk; i++) {
1340 double charge_i =
charge(i);
1341 if (charge_i < 0.0) {
1343 anion_charge += anion_contrib;
1344 if (anion_contrib > anion_contrib_max) {
1345 anion_contrib_max = anion_contrib;
1346 anion_contrib_max_i = i;
1348 }
else if (charge_i > 0.0) {
1350 cation_charge += cation_contrib;
1351 if (cation_contrib > cation_contrib_max) {
1352 cation_contrib_max = cation_contrib;
1353 cation_contrib_max_i = i;
1357 double total_charge = cation_charge - anion_charge;
1358 if (total_charge > 1.0E-8) {
1359 double desiredCrop = total_charge/
charge(cation_contrib_max_i);
1361 if (desiredCrop < maxCrop) {
1367 }
else if (total_charge < -1.0E-8) {
1368 double desiredCrop = total_charge/
charge(anion_contrib_max_i);
1370 if (desiredCrop < maxCrop) {
1382 if (cropMethod == 1) {
1385 double xmolSolvent = molF[0];
1391 double poly = MC_apCut_ + MC_bpCut_ * xmolSolvent + MC_dpCut_* xmolSolvent * xmolSolvent;
1392 double p = xmolSolvent + MC_epCut_ + exp(- xmolSolvent/ MC_cpCut_) * poly;
1394 for (
size_t k = 0; k <
m_kk; k++) {
1402 for (
size_t k = 0; k <
m_kk; k++) {
1407 for (
size_t k = 0; k <
m_kk; k++) {
1420 for (
size_t i = 0; i <
m_kk; i++) {
1422 size_t nc =
m_kk * i;
1426 for (
size_t i = 1; i < (
m_kk - 1); i++) {
1427 size_t n =
m_kk * i + i;
1429 for (
size_t j = (i+1); j <
m_kk; j++) {
1431 size_t nc =
m_kk * i + j;
1441 if (BinSalt.
name() !=
"binarySaltParameters") {
1443 "Incorrect name for processing this routine: " + BinSalt.
name());
1446 string iName = BinSalt.
attrib(
"cation");
1448 throw CanteraError(
"HMWSoln::readXMLBinarySalt",
"no cation attrib");
1450 string jName = BinSalt.
attrib(
"anion");
1452 throw CanteraError(
"HMWSoln::readXMLBinarySalt",
"no anion attrib");
1466 if (beta0.size() != beta1.size() || beta0.size() != beta2.size() ||
1467 beta0.size() != Cphi.size()) {
1468 throw CanteraError(
"HMWSoln::readXMLBinarySalt",
"Inconsistent"
1469 " array sizes ({}, {}, {}, {})", beta0.size(), beta1.size(),
1470 beta2.size(), Cphi.size());
1473 beta0.resize(5, 0.0);
1474 beta1.resize(5, 0.0);
1475 beta2.resize(5, 0.0);
1476 Cphi.resize(5, 0.0);
1478 double alpha1 =
getFloat(BinSalt,
"Alpha1");
1479 double alpha2 = 0.0;
1481 setBinarySalt(iName, jName, beta0.size(), beta0.data(), beta1.data(),
1482 beta2.data(), Cphi.data(), alpha1, alpha2);
1487 string ispName, jspName;
1488 if (node.
name() ==
"thetaAnion") {
1489 ispName = node.
attrib(
"anion1");
1490 if (ispName ==
"") {
1491 throw CanteraError(
"HMWSoln::readXMLTheta",
"no anion1 attrib");
1493 jspName = node.
attrib(
"anion2");
1494 if (jspName ==
"") {
1495 throw CanteraError(
"HMWSoln::readXMLTheta",
"no anion2 attrib");
1497 }
else if (node.
name() ==
"thetaCation") {
1498 ispName = node.
attrib(
"cation1");
1499 if (ispName ==
"") {
1500 throw CanteraError(
"HMWSoln::readXMLTheta",
"no cation1 attrib");
1502 jspName = node.
attrib(
"cation2");
1503 if (jspName ==
"") {
1504 throw CanteraError(
"HMWSoln::readXMLTheta",
"no cation2 attrib");
1508 "Incorrect name for processing this routine: " + node.
name());
1520 theta.resize(5, 0.0);
1522 setTheta(ispName, jspName, theta.size(), theta.data());
1527 string iName, jName, kName;
1528 if (node.
name() ==
"psiCommonCation") {
1529 kName = node.
attrib(
"cation");
1531 throw CanteraError(
"HMWSoln::readXMLPsi",
"no cation attrib");
1533 iName = node.
attrib(
"anion1");
1535 throw CanteraError(
"HMWSoln::readXMLPsi",
"no anion1 attrib");
1537 jName = node.
attrib(
"anion2");
1539 throw CanteraError(
"HMWSoln::readXMLPsi",
"no anion2 attrib");
1541 }
else if (node.
name() ==
"psiCommonAnion") {
1542 kName = node.
attrib(
"anion");
1544 throw CanteraError(
"HMWSoln::readXMLPsi",
"no anion attrib");
1546 iName = node.
attrib(
"cation1");
1548 throw CanteraError(
"HMWSoln::readXMLPsi",
"no cation1 attrib");
1550 jName = node.
attrib(
"cation2");
1552 throw CanteraError(
"HMWSoln::readXMLPsi",
"no cation2 attrib");
1556 "Incorrect name for processing this routine: " + node.
name());
1571 setPsi(iName, jName, kName, psi.size(), psi.data());
1577 if (node.
name() !=
"lambdaNeutral") {
1579 "Incorrect name for processing this routine: " + node.
name());
1581 string iName = node.
attrib(
"species1");
1583 throw CanteraError(
"HMWSoln::readXMLLambdaNeutral",
"no species1 attrib");
1585 string jName = node.
attrib(
"species2");
1587 throw CanteraError(
"HMWSoln::readXMLLambdaNeutral",
"no species2 attrib");
1599 lambda.resize(5, 0.0);
1601 setLambda(iName, jName, lambda.size(), lambda.data());
1606 if (node.
name() !=
"MunnnNeutral") {
1608 "Incorrect name for processing this routine: " + node.
name());
1610 string iName = node.
attrib(
"species1");
1612 throw CanteraError(
"HMWSoln::readXMLMunnnNeutral",
"no species1 attrib");
1624 munnn.resize(5, 0.0);
1626 setMunnn(iName, munnn.size(), munnn.data());
1631 if (node.
name() !=
"zetaCation") {
1633 "Incorrect name for processing this routine: " + node.
name());
1636 string iName = node.
attrib(
"neutral");
1638 throw CanteraError(
"HMWSoln::readXMLZetaCation",
"no neutral attrib");
1640 string jName = node.
attrib(
"cation1");
1642 throw CanteraError(
"HMWSoln::readXMLZetaCation",
"no cation1 attrib");
1644 string kName = node.
attrib(
"anion1");
1646 throw CanteraError(
"HMWSoln::readXMLZetaCation",
"no anion1 attrib");
1659 zeta.resize(5, 0.0);
1661 setZeta(iName, jName, kName, zeta.size(), zeta.data());
1666 double IMS_gamma_o_min_ = 1.0E-5;
1667 double IMS_gamma_k_min_ = 10.0;
1668 double IMS_slopefCut_ = 0.6;
1670 IMS_afCut_ = 1.0 / (std::exp(1.0) * IMS_gamma_k_min_);
1672 bool converged =
false;
1674 for (
int its = 0; its < 100 && !converged; its++) {
1676 IMS_afCut_ = 1.0 / (std::exp(1.0) * IMS_gamma_k_min_) -IMS_efCut_;
1677 IMS_bfCut_ = IMS_afCut_ /
IMS_cCut_ + IMS_slopefCut_ - 1.0;
1683 IMS_efCut_ = - eterm * tmp;
1684 if (fabs(IMS_efCut_ - oldV) < 1.0E-14) {
1690 " failed to converge on the f polynomial");
1693 double f_0 = IMS_afCut_ + IMS_efCut_;
1694 double f_prime_0 = 1.0 - IMS_afCut_ /
IMS_cCut_ + IMS_bfCut_;
1696 for (
int its = 0; its < 100 && !converged; its++) {
1698 double lng_0 = -log(IMS_gamma_o_min_) - f_prime_0 / f_0;
1699 IMS_agCut_ = exp(lng_0) - IMS_egCut_;
1706 IMS_egCut_ = - eterm * tmp;
1707 if (fabs(IMS_egCut_ - oldV) < 1.0E-14) {
1713 " failed to converge on the g polynomial");
1719 double MC_X_o_min_ = 0.35;
1721 double MC_slopepCut_ = 0.02;
1725 MC_apCut_ = MC_X_o_min_;
1727 bool converged =
false;
1730 for (
int its = 0; its < 500 && !converged; its++) {
1732 MC_apCut_ = damp *(MC_X_o_min_ - MC_epCut_) + (1-damp) * MC_apCut_;
1733 double MC_bpCutNew = MC_apCut_ / MC_cpCut_ + MC_slopepCut_ - 1.0;
1734 MC_bpCut_ = damp * MC_bpCutNew + (1-damp) * MC_bpCut_;
1735 double MC_dpCutNew = ((- MC_apCut_/MC_cpCut_ + MC_bpCut_ - MC_bpCut_ *
MC_X_o_cutoff_/MC_cpCut_)
1738 MC_dpCut_ = damp * MC_dpCutNew + (1-damp) * MC_dpCut_;
1741 MC_epCut_ = - eterm * tmp;
1742 double diff = MC_epCut_ - oldV;
1743 if (fabs(diff) < 1.0E-14) {
1749 " failed to converge on the p polynomial");
1756 const double twoT = 2.0 * T;
1757 const double invT = 1.0 / T;
1758 const double invT2 = invT * invT;
1759 const double twoinvT3 = 2.0 * invT * invT2;
1760 double tinv = 0.0, tln = 0.0, tlin = 0.0, tquad = 0.0;
1770 for (
size_t i = 1; i < (
m_kk - 1); i++) {
1771 for (
size_t j = (i+1); j <
m_kk; j++) {
1773 size_t n =
m_kk*i + j;
1783 case PITZER_TEMP_CONSTANT:
1785 case PITZER_TEMP_LINEAR:
1788 + beta0MX_coeff[1]*tlin;
1792 + beta1MX_coeff[1]*tlin;
1796 + beta2MX_coeff[1]*tlin;
1800 + CphiMX_coeff[1]*tlin;
1803 m_Theta_ij[counterIJ] = Theta_coeff[0] + Theta_coeff[1]*tlin;
1808 case PITZER_TEMP_COMPLEX1:
1810 + beta0MX_coeff[1]*tlin
1811 + beta0MX_coeff[2]*tquad
1812 + beta0MX_coeff[3]*tinv
1813 + beta0MX_coeff[4]*tln;
1815 + beta1MX_coeff[1]*tlin
1816 + beta1MX_coeff[2]*tquad
1817 + beta1MX_coeff[3]*tinv
1818 + beta1MX_coeff[4]*tln;
1820 + beta2MX_coeff[1]*tlin
1821 + beta2MX_coeff[2]*tquad
1822 + beta2MX_coeff[3]*tinv
1823 + beta2MX_coeff[4]*tln;
1825 + CphiMX_coeff[1]*tlin
1826 + CphiMX_coeff[2]*tquad
1827 + CphiMX_coeff[3]*tinv
1828 + CphiMX_coeff[4]*tln;
1830 + Theta_coeff[1]*tlin
1831 + Theta_coeff[2]*tquad
1832 + Theta_coeff[3]*tinv
1833 + Theta_coeff[4]*tln;
1835 + beta0MX_coeff[2]*twoT
1836 - beta0MX_coeff[3]*invT2
1837 + beta0MX_coeff[4]*invT;
1839 + beta1MX_coeff[2]*twoT
1840 - beta1MX_coeff[3]*invT2
1841 + beta1MX_coeff[4]*invT;
1843 + beta2MX_coeff[2]*twoT
1844 - beta2MX_coeff[3]*invT2
1845 + beta2MX_coeff[4]*invT;
1847 + CphiMX_coeff[2]*twoT
1848 - CphiMX_coeff[3]*invT2
1849 + CphiMX_coeff[4]*invT;
1851 + Theta_coeff[2]*twoT
1852 - Theta_coeff[3]*invT2
1853 + Theta_coeff[4]*invT;
1857 + beta0MX_coeff[2]*2.0
1858 + beta0MX_coeff[3]*twoinvT3
1859 - beta0MX_coeff[4]*invT2;
1861 + beta1MX_coeff[2]*2.0
1862 + beta1MX_coeff[3]*twoinvT3
1863 - beta1MX_coeff[4]*invT2;
1865 + beta2MX_coeff[2]*2.0
1866 + beta2MX_coeff[3]*twoinvT3
1867 - beta2MX_coeff[4]*invT2;
1869 + CphiMX_coeff[2]*2.0
1870 + CphiMX_coeff[3]*twoinvT3
1871 - CphiMX_coeff[4]*invT2;
1873 + Theta_coeff[2]*2.0
1874 + Theta_coeff[3]*twoinvT3
1875 - Theta_coeff[4]*invT2;
1885 for (
size_t i = 1; i <
m_kk; i++) {
1887 for (
size_t j = 1; j <
m_kk; j++) {
1888 size_t n = i *
m_kk + j;
1891 case PITZER_TEMP_CONSTANT:
1894 case PITZER_TEMP_LINEAR:
1895 m_Lambda_nj(i,j) = Lambda_coeff[0] + Lambda_coeff[1]*tlin;
1899 case PITZER_TEMP_COMPLEX1:
1901 + Lambda_coeff[1]*tlin
1902 + Lambda_coeff[2]*tquad
1903 + Lambda_coeff[3]*tinv
1904 + Lambda_coeff[4]*tln;
1907 + Lambda_coeff[2]*twoT
1908 - Lambda_coeff[3]*invT2
1909 + Lambda_coeff[4]*invT;
1913 + Lambda_coeff[3]*twoinvT3
1914 - Lambda_coeff[4]*invT2;
1920 case PITZER_TEMP_CONSTANT:
1923 case PITZER_TEMP_LINEAR:
1924 m_Mu_nnn[i] = Mu_coeff[0] + Mu_coeff[1]*tlin;
1928 case PITZER_TEMP_COMPLEX1:
1940 + Mu_coeff[3]*twoinvT3
1941 - Mu_coeff[4]*invT2;
1949 case PITZER_TEMP_CONSTANT:
1950 for (
size_t i = 1; i <
m_kk; i++) {
1951 for (
size_t j = 1; j <
m_kk; j++) {
1952 for (
size_t k = 1; k <
m_kk; k++) {
1960 case PITZER_TEMP_LINEAR:
1961 for (
size_t i = 1; i <
m_kk; i++) {
1962 for (
size_t j = 1; j <
m_kk; j++) {
1963 for (
size_t k = 1; k <
m_kk; k++) {
1966 m_Psi_ijk[n] = Psi_coeff[0] + Psi_coeff[1]*tlin;
1973 case PITZER_TEMP_COMPLEX1:
1974 for (
size_t i = 1; i <
m_kk; i++) {
1975 for (
size_t j = 1; j <
m_kk; j++) {
1976 for (
size_t k = 1; k <
m_kk; k++) {
1981 + Psi_coeff[2]*tquad
1986 - Psi_coeff[3]*invT2
1987 + Psi_coeff[4]*invT;
1990 + Psi_coeff[3]*twoinvT3
1991 - Psi_coeff[4]*invT2;
2009 double etheta[5][5], etheta_prime[5][5], sqrtIs;
2016 double molarcharge = 0.0;
2020 double molalitysumUncropped = 0.0;
2026 for (
size_t n = 1; n <
m_kk; n++) {
2030 molarcharge += fabs(
charge(n)) * molality[n];
2045 for (
int z1 = 1; z1 <=4; z1++) {
2046 for (
int z2 =1; z2 <=4; z2++) {
2047 calc_thetas(z1, z2, ðeta[z1][z2], ðeta_prime[z1][z2]);
2054 for (
size_t i = 1; i < (
m_kk - 1); i++) {
2055 for (
size_t j = (i+1); j <
m_kk; j++) {
2057 size_t n =
m_kk*i + j;
2063 double x1 = sqrtIs * m_Alpha1MX_ij[counterIJ];
2064 if (x1 > 1.0E-100) {
2065 m_gfunc_IJ[counterIJ] = 2.0*(1.0-(1.0 + x1) * exp(-x1)) / (x1 * x1);
2067 (1.0-(1.0 + x1 + 0.5 * x1 * x1) * exp(-x1)) / (x1 * x1);
2075 if (x2 > 1.0E-100) {
2076 m_g2func_IJ[counterIJ] = 2.0*(1.0-(1.0 + x2) * exp(-x2)) / (x2 * x2);
2078 (1.0-(1.0 + x2 + 0.5 * x2 * x2) * exp(-x2)) / (x2 * x2);
2093 for (
size_t i = 1; i <
m_kk - 1; i++) {
2094 for (
size_t j = i+1; j <
m_kk; j++) {
2096 size_t n =
m_kk*i + j;
2106 if (Is > 1.0E-150) {
2123 for (
size_t i = 1; i <
m_kk-1; i++) {
2124 for (
size_t j = i+1; j <
m_kk; j++) {
2126 size_t n =
m_kk*i + j;
2142 for (
size_t i = 1; i <
m_kk-1; i++) {
2143 for (
size_t j = i+1; j <
m_kk; j++) {
2145 size_t n =
m_kk*i + j;
2151 int z1 = (int) fabs(
charge(i));
2152 int z2 = (int) fabs(
charge(j));
2167 double F = -Aphi * (sqrt(Is) / (1.0 + 1.2*sqrt(Is))
2168 + (2.0/1.2) * log(1.0+1.2*(sqrtIs)));
2169 for (
size_t i = 1; i <
m_kk-1; i++) {
2170 for (
size_t j = i+1; j <
m_kk; j++) {
2172 size_t n =
m_kk*i + j;
2189 for (
size_t i = 1; i <
m_kk; i++) {
2202 for (
size_t j = 1; j <
m_kk; j++) {
2204 size_t n =
m_kk*i + j;
2209 sum1 += molality[j] *
2215 for (
size_t k = j+1; k <
m_kk; k++) {
2219 sum3 += molality[j]*molality[k]*
m_Psi_ijk[n];
2228 sum2 += molality[j]*(2.0*
m_Phi_IJ[counterIJ]);
2230 for (
size_t k = 1; k <
m_kk; k++) {
2234 sum2 += molality[j]*molality[k]*
m_Psi_ijk[n];
2239 sum4 += (fabs(
charge(i))*
2240 molality[j]*molality[k]*
m_CMX_IJ[counterIJ2]);
2250 for (
size_t k = 1; k <
m_kk; k++) {
2257 sum5 += molality[j]*molality[k]*zeta;
2281 for (
size_t j = 1; j <
m_kk; j++) {
2283 size_t n =
m_kk*i + j;
2288 sum1 += molality[j]*
2291 for (
size_t k = j+1; k <
m_kk; k++) {
2295 sum3 += molality[j]*molality[k]*
m_Psi_ijk[n];
2305 sum2 += molality[j]*(2.0*
m_Phi_IJ[counterIJ]);
2307 for (
size_t k = 1; k <
m_kk; k++) {
2311 sum2 += molality[j]*molality[k]*
m_Psi_ijk[n];
2316 molality[j]*molality[k]*
m_CMX_IJ[counterIJ2];
2325 for (
size_t k = 1; k <
m_kk; k++) {
2333 sum5 += molality[j]*molality[k]*zeta;
2349 for (
size_t j = 1; j <
m_kk; j++) {
2353 for (
size_t k = 1; k <
m_kk; k++) {
2356 sum3 += molality[j]*molality[k]*
m_Psi_ijk[n];
2361 double sum2 = 3.0 * molality[i]* molality[i] *
m_Mu_nnn[i];
2383 double term1 = -Aphi * pow(Is,1.5) / (1.0 + 1.2 * sqrt(Is));
2385 for (
size_t j = 1; j <
m_kk; j++) {
2388 for (
size_t k = 1; k <
m_kk; k++) {
2391 size_t n =
m_kk*j + k;
2394 sum1 += molality[j]*molality[k]*
2399 for (
size_t k = j+1; k <
m_kk; k++) {
2400 if (j == (
m_kk-1)) {
2402 throw CanteraError(
"HMWSoln::s_updatePitzer_lnMolalityActCoeff",
2403 "logic error 1 in Step 9 of hmw_act");
2408 size_t n =
m_kk*j + k;
2410 sum2 += molality[j]*molality[k]*
m_PhiPhi_IJ[counterIJ];
2411 for (
size_t m = 1; m <
m_kk; m++) {
2415 sum2 += molality[j]*molality[k]*molality[m]*
m_Psi_ijk[n];
2424 for (
size_t k = j+1; k <
m_kk; k++) {
2427 throw CanteraError(
"HMWSoln::s_updatePitzer_lnMolalityActCoeff",
2428 "logic error 2 in Step 9 of hmw_act");
2433 size_t n =
m_kk*j + k;
2435 sum3 += molality[j]*molality[k]*
m_PhiPhi_IJ[counterIJ];
2436 for (
size_t m = 1; m <
m_kk; m++) {
2439 sum3 += molality[j]*molality[k]*molality[m]*
m_Psi_ijk[n];
2448 for (
size_t k = 1; k <
m_kk; k++) {
2458 }
else if (k == j) {
2459 sum6 += 0.5 * molality[j]*molality[k]*
m_Lambda_nj(j,k);
2464 for (
size_t m = 1; m <
m_kk; m++) {
2470 sum7 += molality[izeta]*molality[jzeta]*molality[k]*zeta;
2476 sum7 += molality[j]*molality[j]*molality[j]*
m_Mu_nnn[j];
2479 double sum_m_phi_minus_1 = 2.0 *
2480 (term1 + sum1 + sum2 + sum3 + sum4 + sum5 + sum6 + sum7);
2483 double osmotic_coef;
2484 if (molalitysumUncropped > 1.0E-150) {
2485 osmotic_coef = 1.0 + (sum_m_phi_minus_1 / molalitysumUncropped);
2489 double lnwateract = -(
m_weightSolvent/1000.0) * molalitysumUncropped * osmotic_coef;
2516 for (
size_t k = 1; k <
m_kk; k++) {
2540 double etheta[5][5], etheta_prime[5][5], sqrtIs;
2547 double molarcharge = 0.0;
2551 double molalitysum = 0.0;
2557 for (
size_t n = 1; n <
m_kk; n++) {
2561 molarcharge += fabs(
charge(n)) * molality[n];
2562 molalitysum += molality[n];
2576 for (
int z1 = 1; z1 <=4; z1++) {
2577 for (
int z2 =1; z2 <=4; z2++) {
2578 calc_thetas(z1, z2, ðeta[z1][z2], ðeta_prime[z1][z2]);
2585 for (
size_t i = 1; i < (
m_kk - 1); i++) {
2586 for (
size_t j = (i+1); j <
m_kk; j++) {
2588 size_t n =
m_kk*i + j;
2594 double x1 = sqrtIs * m_Alpha1MX_ij[counterIJ];
2595 if (x1 > 1.0E-100) {
2596 m_gfunc_IJ[counterIJ] = 2.0*(1.0-(1.0 + x1) * exp(-x1)) / (x1 * x1);
2598 (1.0-(1.0 + x1 + 0.5 * x1 *x1) * exp(-x1)) / (x1 * x1);
2606 if (x2 > 1.0E-100) {
2607 m_g2func_IJ[counterIJ] = 2.0*(1.0-(1.0 + x2) * exp(-x2)) / (x2 * x2);
2609 (1.0-(1.0 + x2 + 0.5 * x2 * x2) * exp(-x2)) / (x2 * x2);
2625 for (
size_t i = 1; i <
m_kk - 1; i++) {
2626 for (
size_t j = i+1; j <
m_kk; j++) {
2628 size_t n =
m_kk*i + j;
2637 if (Is > 1.0E-150) {
2653 for (
size_t i = 1; i <
m_kk-1; i++) {
2654 for (
size_t j = i+1; j <
m_kk; j++) {
2656 size_t n =
m_kk*i + j;
2671 for (
size_t i = 1; i <
m_kk-1; i++) {
2672 for (
size_t j = i+1; j <
m_kk; j++) {
2674 size_t n =
m_kk*i + j;
2693 double dAphidT = dA_DebyedT /3.0;
2694 double dFdT = -dAphidT * (sqrt(Is) / (1.0 + 1.2*sqrt(Is))
2695 + (2.0/1.2) * log(1.0+1.2*(sqrtIs)));
2696 for (
size_t i = 1; i <
m_kk-1; i++) {
2697 for (
size_t j = i+1; j <
m_kk; j++) {
2699 size_t n =
m_kk*i + j;
2716 for (
size_t i = 1; i <
m_kk; i++) {
2726 for (
size_t j = 1; j <
m_kk; j++) {
2728 size_t n =
m_kk*i + j;
2733 sum1 += molality[j]*
2739 for (
size_t k = j+1; k <
m_kk; k++) {
2752 sum2 += molality[j]*(2.0*
m_Phi_IJ_L[counterIJ]);
2754 for (
size_t k = 1; k <
m_kk; k++) {
2764 molality[j]*molality[k]*
m_CMX_IJ_L[counterIJ2];
2775 for (
size_t k = 1; k <
m_kk; k++) {
2781 if (zeta_L != 0.0) {
2782 sum5 += molality[j]*molality[k]*zeta_L;
2791 zsqdFdT + sum1 + sum2 + sum3 + sum4 + sum5;
2804 for (
size_t j = 1; j <
m_kk; j++) {
2806 size_t n =
m_kk*i + j;
2811 sum1 += molality[j]*
2814 for (
size_t k = j+1; k <
m_kk; k++) {
2828 sum2 += molality[j]*(2.0*
m_Phi_IJ_L[counterIJ]);
2830 for (
size_t k = 1; k <
m_kk; k++) {
2838 sum4 += fabs(
charge(i)) *
2839 molality[j]*molality[k]*
m_CMX_IJ_L[counterIJ2];
2847 for (
size_t k = 1; k <
m_kk; k++) {
2854 if (zeta_L != 0.0) {
2855 sum5 += molality[j]*molality[k]*zeta_L;
2862 zsqdFdT + sum1 + sum2 + sum3 + sum4 + sum5;
2872 for (
size_t j = 1; j <
m_kk; j++) {
2876 for (
size_t k = 1; k <
m_kk; k++) {
2884 double sum2 = 3.0 * molality[i] * molality[i] *
m_Mu_nnn_L[i];
2904 double term1 = -dAphidT * Is * sqrt(Is) / (1.0 + 1.2 * sqrt(Is));
2906 for (
size_t j = 1; j <
m_kk; j++) {
2909 for (
size_t k = 1; k <
m_kk; k++) {
2912 size_t n =
m_kk*j + k;
2914 sum1 += molality[j]*molality[k]*
2919 for (
size_t k = j+1; k <
m_kk; k++) {
2920 if (j == (
m_kk-1)) {
2922 throw CanteraError(
"HMWSoln::s_updatePitzer_dlnMolalityActCoeff_dT",
2923 "logic error 1 in Step 9 of hmw_act");
2928 size_t n =
m_kk*j + k;
2931 for (
size_t m = 1; m <
m_kk; m++) {
2935 sum2 += molality[j]*molality[k]*molality[m]*
m_Psi_ijk_L[n];
2944 for (
size_t k = j+1; k <
m_kk; k++) {
2947 throw CanteraError(
"HMWSoln::s_updatePitzer_dlnMolalityActCoeff_dT",
2948 "logic error 2 in Step 9 of hmw_act");
2953 size_t n =
m_kk*j + k;
2956 for (
size_t m = 1; m <
m_kk; m++) {
2959 sum3 += molality[j]*molality[k]*molality[m]*
m_Psi_ijk_L[n];
2968 for (
size_t k = 1; k <
m_kk; k++) {
2978 }
else if (k == j) {
2984 for (
size_t m = 1; m <
m_kk; m++) {
2989 if (zeta_L != 0.0) {
2990 sum7 += molality[izeta]*molality[jzeta]*molality[k]*zeta_L;
2996 sum7 += molality[j]*molality[j]*molality[j]*
m_Mu_nnn_L[j];
2999 double sum_m_phi_minus_1 = 2.0 *
3000 (term1 + sum1 + sum2 + sum3 + sum4 + sum5 + sum6 + sum7);
3003 double d_osmotic_coef_dT;
3004 if (molalitysum > 1.0E-150) {
3005 d_osmotic_coef_dT = 0.0 + (sum_m_phi_minus_1 / molalitysum);
3007 d_osmotic_coef_dT = 0.0;
3010 double d_lnwateract_dT = -(
m_weightSolvent/1000.0) * molalitysum * d_osmotic_coef_dT;
3035 for (
size_t k = 1; k <
m_kk; k++) {
3054 double etheta[5][5], etheta_prime[5][5], sqrtIs;
3061 double molarcharge = 0.0;
3065 double molalitysum = 0.0;
3071 for (
size_t n = 1; n <
m_kk; n++) {
3075 molarcharge += fabs(
charge(n)) * molality[n];
3076 molalitysum += molality[n];
3090 for (
int z1 = 1; z1 <=4; z1++) {
3091 for (
int z2 =1; z2 <=4; z2++) {
3092 calc_thetas(z1, z2, ðeta[z1][z2], ðeta_prime[z1][z2]);
3099 for (
size_t i = 1; i < (
m_kk - 1); i++) {
3100 for (
size_t j = (i+1); j <
m_kk; j++) {
3102 size_t n =
m_kk*i + j;
3108 double x1 = sqrtIs * m_Alpha1MX_ij[counterIJ];
3109 if (x1 > 1.0E-100) {
3110 m_gfunc_IJ[counterIJ] = 2.0*(1.0-(1.0 + x1) * exp(-x1)) / (x1 *x1);
3112 (1.0-(1.0 + x1 + 0.5*x1 * x1) * exp(-x1)) / (x1 * x1);
3120 if (x2 > 1.0E-100) {
3121 m_g2func_IJ[counterIJ] = 2.0*(1.0-(1.0 + x2) * exp(-x2)) / (x2 * x2);
3123 (1.0-(1.0 + x2 + 0.5 * x2 * x2) * exp(-x2)) / (x2 * x2);
3139 for (
size_t i = 1; i <
m_kk - 1; i++) {
3140 for (
size_t j = i+1; j <
m_kk; j++) {
3142 size_t n =
m_kk*i + j;
3151 if (Is > 1.0E-150) {
3167 for (
size_t i = 1; i <
m_kk-1; i++) {
3168 for (
size_t j = i+1; j <
m_kk; j++) {
3170 size_t n =
m_kk*i + j;
3185 for (
size_t i = 1; i <
m_kk-1; i++) {
3186 for (
size_t j = i+1; j <
m_kk; j++) {
3188 size_t n =
m_kk*i + j;
3207 double d2FdT2 = -d2AphidT2 * (sqrt(Is) / (1.0 + 1.2*sqrt(Is))
3208 + (2.0/1.2) * log(1.0+1.2*(sqrtIs)));
3209 for (
size_t i = 1; i <
m_kk-1; i++) {
3210 for (
size_t j = i+1; j <
m_kk; j++) {
3212 size_t n =
m_kk*i + j;
3224 d2FdT2 += molality[i]*molality[j] *
m_Phiprime_IJ[counterIJ];
3229 for (
size_t i = 1; i <
m_kk; i++) {
3239 for (
size_t j = 1; j <
m_kk; j++) {
3241 size_t n =
m_kk*i + j;
3246 sum1 += molality[j]*
3252 for (
size_t k = j+1; k <
m_kk; k++) {
3267 for (
size_t k = 1; k <
m_kk; k++) {
3276 sum4 += fabs(
charge(i)) *
3286 for (
size_t k = 1; k <
m_kk; k++) {
3292 if (zeta_LL != 0.0) {
3293 sum5 += molality[j]*molality[k]*zeta_LL;
3302 zsqd2FdT2 + sum1 + sum2 + sum3 + sum4 + sum5;
3314 for (
size_t j = 1; j <
m_kk; j++) {
3316 size_t n =
m_kk*i + j;
3321 sum1 += molality[j]*
3324 for (
size_t k = j+1; k <
m_kk; k++) {
3340 for (
size_t k = 1; k <
m_kk; k++) {
3348 sum4 += fabs(
charge(i)) *
3358 for (
size_t k = 1; k <
m_kk; k++) {
3365 if (zeta_LL != 0.0) {
3366 sum5 += molality[j]*molality[k]*zeta_LL;
3373 zsqd2FdT2 + sum1 + sum2 + sum3 + sum4 + sum5;
3382 for (
size_t j = 1; j <
m_kk; j++) {
3386 for (
size_t k = 1; k <
m_kk; k++) {
3394 double sum2 = 3.0 * molality[i] * molality[i] *
m_Mu_nnn_LL[i];
3413 double term1 = -d2AphidT2 * Is * sqrt(Is) / (1.0 + 1.2 * sqrt(Is));
3415 for (
size_t j = 1; j <
m_kk; j++) {
3418 for (
size_t k = 1; k <
m_kk; k++) {
3421 size_t n =
m_kk*j + k;
3424 sum1 += molality[j]*molality[k] *
3429 for (
size_t k = j+1; k <
m_kk; k++) {
3430 if (j == (
m_kk-1)) {
3432 throw CanteraError(
"HMWSoln::s_updatePitzer_d2lnMolalityActCoeff_dT2",
3433 "logic error 1 in Step 9 of hmw_act");
3438 size_t n =
m_kk*j + k;
3441 for (
size_t m = 1; m <
m_kk; m++) {
3445 sum2 += molality[j]*molality[k]*molality[m]*
m_Psi_ijk_LL[n];
3454 for (
size_t k = j+1; k <
m_kk; k++) {
3457 throw CanteraError(
"HMWSoln::s_updatePitzer_d2lnMolalityActCoeff_dT2",
3458 "logic error 2 in Step 9 of hmw_act");
3463 size_t n =
m_kk*j + k;
3467 for (
size_t m = 1; m <
m_kk; m++) {
3470 sum3 += molality[j]*molality[k]*molality[m]*
m_Psi_ijk_LL[n];
3479 for (
size_t k = 1; k <
m_kk; k++) {
3489 }
else if (k == j) {
3495 for (
size_t m = 1; m <
m_kk; m++) {
3500 if (zeta_LL != 0.0) {
3501 sum7 += molality[izeta]*molality[jzeta]*molality[k]*zeta_LL;
3508 sum7 += molality[j] * molality[j] * molality[j] *
m_Mu_nnn_LL[j];
3511 double sum_m_phi_minus_1 = 2.0 *
3512 (term1 + sum1 + sum2 + sum3 + sum4 + sum5 + sum6 + sum7);
3515 double d2_osmotic_coef_dT2;
3516 if (molalitysum > 1.0E-150) {
3517 d2_osmotic_coef_dT2 = 0.0 + (sum_m_phi_minus_1 / molalitysum);
3519 d2_osmotic_coef_dT2 = 0.0;
3521 double d2_lnwateract_dT2 = -(
m_weightSolvent/1000.0) * molalitysum * d2_osmotic_coef_dT2;
3543 for (
size_t k = 1; k <
m_kk; k++) {
3561 double etheta[5][5], etheta_prime[5][5], sqrtIs;
3568 double molarcharge = 0.0;
3572 double molalitysum = 0.0;
3580 for (
size_t n = 1; n <
m_kk; n++) {
3584 molarcharge += fabs(
charge(n)) * molality[n];
3585 molalitysum += molality[n];
3599 for (
int z1 = 1; z1 <=4; z1++) {
3600 for (
int z2 =1; z2 <=4; z2++) {
3601 calc_thetas(z1, z2, ðeta[z1][z2], ðeta_prime[z1][z2]);
3608 for (
size_t i = 1; i < (
m_kk - 1); i++) {
3609 for (
size_t j = (i+1); j <
m_kk; j++) {
3611 size_t n =
m_kk*i + j;
3617 double x1 = sqrtIs * m_Alpha1MX_ij[counterIJ];
3618 if (x1 > 1.0E-100) {
3619 m_gfunc_IJ[counterIJ] = 2.0*(1.0-(1.0 + x1) * exp(-x1)) / (x1 * x1);
3621 (1.0-(1.0 + x1 + 0.5 * x1 * x1) * exp(-x1)) / (x1 * x1);
3629 if (x2 > 1.0E-100) {
3630 m_g2func_IJ[counterIJ] = 2.0*(1.0-(1.0 + x2) * exp(-x2)) / (x2 * x2);
3632 (1.0-(1.0 + x2 + 0.5 * x2 * x2) * exp(-x2)) / (x2 * x2);
3648 for (
size_t i = 1; i <
m_kk - 1; i++) {
3649 for (
size_t j = i+1; j <
m_kk; j++) {
3651 size_t n =
m_kk*i + j;
3660 if (Is > 1.0E-150) {
3676 for (
size_t i = 1; i <
m_kk-1; i++) {
3677 for (
size_t j = i+1; j <
m_kk; j++) {
3679 size_t n =
m_kk*i + j;
3694 for (
size_t i = 1; i <
m_kk-1; i++) {
3695 for (
size_t j = i+1; j <
m_kk; j++) {
3697 size_t n =
m_kk*i + j;
3716 double dAphidP = dA_DebyedP /3.0;
3717 double dFdP = -dAphidP * (sqrt(Is) / (1.0 + 1.2*sqrt(Is))
3718 + (2.0/1.2) * log(1.0+1.2*(sqrtIs)));
3719 for (
size_t i = 1; i <
m_kk-1; i++) {
3720 for (
size_t j = i+1; j <
m_kk; j++) {
3722 size_t n =
m_kk*i + j;
3739 for (
size_t i = 1; i <
m_kk; i++) {
3749 for (
size_t j = 1; j <
m_kk; j++) {
3751 size_t n =
m_kk*i + j;
3756 sum1 += molality[j]*
3762 for (
size_t k = j+1; k <
m_kk; k++) {
3775 sum2 += molality[j]*(2.0*
m_Phi_IJ_P[counterIJ]);
3777 for (
size_t k = 1; k <
m_kk; k++) {
3786 sum4 += fabs(
charge(i)) *
3787 molality[j]*molality[k]*
m_CMX_IJ_P[counterIJ2];
3796 for (
size_t k = 1; k <
m_kk; k++) {
3802 if (zeta_P != 0.0) {
3803 sum5 += molality[j]*molality[k]*zeta_P;
3813 zsqdFdP + sum1 + sum2 + sum3 + sum4 + sum5;
3825 for (
size_t j = 1; j <
m_kk; j++) {
3827 size_t n =
m_kk*i + j;
3832 sum1 += molality[j] *
3835 for (
size_t k = j+1; k <
m_kk; k++) {
3849 sum2 += molality[j]*(2.0*
m_Phi_IJ_P[counterIJ]);
3851 for (
size_t k = 1; k <
m_kk; k++) {
3860 molality[j]*molality[k]*
m_CMX_IJ_P[counterIJ2];
3869 for (
size_t k = 1; k <
m_kk; k++) {
3876 if (zeta_P != 0.0) {
3877 sum5 += molality[j]*molality[k]*zeta_P;
3884 zsqdFdP + sum1 + sum2 + sum3 + sum4 + sum5;
3891 for (
size_t j = 1; j <
m_kk; j++) {
3895 for (
size_t k = 1; k <
m_kk; k++) {
3903 double sum2 = 3.0 * molality[i] * molality[i] *
m_Mu_nnn_P[i];
3922 double term1 = -dAphidP * Is * sqrt(Is) / (1.0 + 1.2 * sqrt(Is));
3924 for (
size_t j = 1; j <
m_kk; j++) {
3927 for (
size_t k = 1; k <
m_kk; k++) {
3930 size_t n =
m_kk*j + k;
3932 sum1 += molality[j]*molality[k]*
3937 for (
size_t k = j+1; k <
m_kk; k++) {
3938 if (j == (
m_kk-1)) {
3940 throw CanteraError(
"HMWSoln::s_updatePitzer_dlnMolalityActCoeff_dP",
3941 "logic error 1 in Step 9 of hmw_act");
3946 size_t n =
m_kk*j + k;
3949 for (
size_t m = 1; m <
m_kk; m++) {
3953 sum2 += molality[j]*molality[k]*molality[m]*
m_Psi_ijk_P[n];
3962 for (
size_t k = j+1; k <
m_kk; k++) {
3965 throw CanteraError(
"HMWSoln::s_updatePitzer_dlnMolalityActCoeff_dP",
3966 "logic error 2 in Step 9 of hmw_act");
3971 size_t n =
m_kk*j + k;
3975 for (
size_t m = 1; m <
m_kk; m++) {
3978 sum3 += molality[j]*molality[k]*molality[m]*
m_Psi_ijk_P[n];
3987 for (
size_t k = 1; k <
m_kk; k++) {
3997 }
else if (k == j) {
4003 for (
size_t m = 1; m <
m_kk; m++) {
4008 if (zeta_P != 0.0) {
4009 sum7 += molality[izeta]*molality[jzeta]*molality[k]*zeta_P;
4016 sum7 += molality[j] * molality[j] * molality[j] *
m_Mu_nnn_P[j];
4019 double sum_m_phi_minus_1 = 2.0 *
4020 (term1 + sum1 + sum2 + sum3 + sum4 + sum5 + sum6 + sum7);
4024 double d_osmotic_coef_dP;
4025 if (molalitysum > 1.0E-150) {
4026 d_osmotic_coef_dP = 0.0 + (sum_m_phi_minus_1 / molalitysum);
4028 d_osmotic_coef_dP = 0.0;
4030 double d_lnwateract_dP = -(
m_weightSolvent/1000.0) * molalitysum * d_osmotic_coef_dP;
4043 if( m_last_is == is ) {
4050 double c1 = 4.581, c2 = 0.7237, c3 = 0.0120, c4 = 0.528;
4051 double aphi = 0.392;
4052 if (is < 1.0E-150) {
4053 for (
int i = 0; i < 17; i++) {
4062 for (
int i=1; i<=4; i++) {
4063 for (
int j=i; j<=4; j++) {
4067 double zprod = (double)ij;
4070 double x = 6.0* zprod * aphi * sqrt(is);
4072 double jfunc = x / (4.0 + c1*pow(x,-c2)*exp(-c3*pow(x,c4)));
4074 double t = c3 * c4 * pow(x,c4);
4075 double dj = c1* pow(x,(-c2-1.0)) * (c2+t) * exp(-c3*pow(x,c4));
4076 double jprime = (jfunc/x)*(1.0 + jfunc*dj);
4078 elambda[ij] = zprod*jfunc / (4.0*is);
4079 elambda1[ij] = (3.0*zprod*zprod*aphi*jprime/(4.0*sqrt(is))
4086 double* etheta,
double* etheta_prime)
const
4093 "we shouldn't be here");
4095 "called with one species being neutral");
4101 *etheta_prime = 0.0;
4104 double f1 = (double)i / (2.0 * j);
4105 double f2 = (double)j / (2.0 * i);
4120 for (
size_t k = 1; k <
m_kk; k++) {
4127 double eterm = std::exp(-xoverc);
4129 double fptmp = IMS_bfCut_ - IMS_afCut_ /
IMS_cCut_ - IMS_bfCut_*xoverc
4130 + 2.0*IMS_dfCut_*xmolSolvent - IMS_dfCut_*xmolSolvent*xoverc;
4131 double f_prime = 1.0 + eterm*fptmp;
4132 double f = xmolSolvent + IMS_efCut_
4133 + eterm * (IMS_afCut_ + xmolSolvent * (IMS_bfCut_ + IMS_dfCut_*xmolSolvent));
4135 double gptmp = IMS_bgCut_ - IMS_agCut_ /
IMS_cCut_ - IMS_bgCut_*xoverc
4136 + 2.0*IMS_dgCut_*xmolSolvent - IMS_dgCut_*xmolSolvent*xoverc;
4137 double g_prime = 1.0 + eterm*gptmp;
4138 double g = xmolSolvent + IMS_egCut_
4139 + eterm * (IMS_agCut_ + xmolSolvent * (IMS_bgCut_ + IMS_dgCut_*xmolSolvent));
4141 double tmp = (xmolSolvent / g * g_prime + (1.0 - xmolSolvent) / f * f_prime);
4142 double lngammak = -1.0 - log(f) + tmp * xmolSolvent;
4143 double lngammao =-log(g) - tmp * (1.0-xmolSolvent);
4145 tmp = log(xx) + lngammak;
4146 for (
size_t k = 1; k <
m_kk; k++) {
4163 writelog(
"Index Name MoleF MolalityCropped Charge\n");
4164 for (
size_t k = 0; k <
m_kk; k++) {
4165 writelogf(
"%2d %-16s %14.7le %14.7le %5.1f \n",
4169 writelog(
"\n Species Species beta0MX "
4170 "beta1MX beta2MX CphiMX alphaMX thetaij\n");
4171 for (
size_t i = 1; i <
m_kk - 1; i++) {
4172 for (
size_t j = i+1; j <
m_kk; j++) {
4173 size_t n = i *
m_kk + j;
4175 writelogf(
" %-16s %-16s %9.5f %9.5f %9.5f %9.5f %9.5f %9.5f \n",
4183 writelog(
"\n Species Species Species psi \n");
4184 for (
size_t i = 1; i <
m_kk; i++) {
4185 for (
size_t j = 1; j <
m_kk; j++) {
4186 for (
size_t k = 1; k <
m_kk; k++) {
4189 writelogf(
" %-16s %-16s %-16s %9.5f \n",
4206 doublereal afac = -1.0 *(lnGammaClMs2 - lnGammaCLMs1);
4207 for (
size_t k = 0; k <
m_kk; k++) {
4208 acMolality[k] *= exp(
charge(k) * afac);
4221 doublereal afac = -1.0 *(lnGammaClMs2 - lnGammaCLMs1);
4222 for (
size_t k = 0; k <
m_kk; k++) {
4236 doublereal afac = -1.0 *(dlnGammaClM_dT_s2 - dlnGammaCLM_dT_s1);
4237 for (
size_t k = 0; k <
m_kk; k++) {
4251 doublereal afac = -1.0 *(d2lnGammaClM_dT2_s2 - d2lnGammaCLM_dT2_s1);
4252 for (
size_t k = 0; k <
m_kk; k++) {
4266 doublereal afac = -1.0 *(dlnGammaClM_dP_s2 - dlnGammaCLM_dP_s1);
4267 for (
size_t k = 0; k <
m_kk; k++) {
4276 doublereal lnGammaClMs2 = - A * sqrtIs /(1.0 + 1.5 * sqrtIs);
4277 return lnGammaClMs2;
4284 return - dAdT * sqrtIs /(1.0 + 1.5 * sqrtIs);
4291 return - d2AdT2 * sqrtIs /(1.0 + 1.5 * sqrtIs);
4298 return - dAdP * sqrtIs /(1.0 + 1.5 * sqrtIs);
Headers for the HMWSoln ThermoPhase object, which models concentrated electrolyte solutions (see Ther...
Implementation of a pressure dependent standard state virtual function for a Pure Water Phase (see Sp...
Headers for the factory class that can create known ThermoPhase objects (see Thermodynamic Properties...
A map of string keys to values whose type can vary at runtime.
bool hasKey(const std::string &key) const
Returns true if the map contains an item named key.
void resize(size_t n, size_t m, doublereal v=0.0)
Resize the array, and fill the new entries with 'v'.
doublereal * ptrColumn(size_t j)
Return a pointer to the top of column j, columns are contiguous in memory.
Base class for exceptions thrown by Cantera classes.
vector_fp m_CMX_IJ_P
Derivative of m_CMX_IJ wrt P. Vector index is counterIJ.
void calcIMSCutoffParams_()
Precalculate the IMS Cutoff parameters for typeCutoff = 2.
Array2D m_Theta_ij_coeff
Array of coefficients for Theta_ij[i][j] in the Pitzer/HMW formulation.
vector_fp m_BphiMX_IJ_P
Derivative of BphiMX_IJ wrt P. Vector index is counterIJ.
doublereal MC_X_o_cutoff_
value of the solvent mole fraction that centers the cutoff polynomials for the cutoff =1 process;
virtual void applyphScale(doublereal *acMolality) const
Apply the current phScale to a set of activity Coefficients or activities.
Array2D m_Beta0MX_ij_coeff
Array of coefficients for Beta0, a variable in Pitzer's papers.
vector_fp m_PhiPhi_IJ
Intermediate variable called PhiPhi in Pitzer's paper.
vector_fp m_Theta_ij_L
Derivative of Theta_ij[i][j] wrt T. Vector index is counterIJ.
vector_fp m_BMX_IJ_L
Derivative of BMX_IJ wrt T. Vector index is counterIJ.
vector_fp m_BMX_IJ_P
Derivative of BMX_IJ wrt P. Vector index is counterIJ.
double m_A_Debye
A_Debye: this expression appears on the top of the ln actCoeff term in the general Debye-Huckel expre...
void readXMLLambdaNeutral(XML_Node &BinSalt)
Process an XML node called "lambdaNeutral".
virtual double d2A_DebyedT2_TP(double temperature=-1.0, double pressure=-1.0) const
Value of the 2nd derivative of the Debye Huckel constant with respect to temperature as a function of...
vector_fp m_Phi_IJ_LL
Derivative of m_Phi_IJ wrt TT. Vector index is counterIJ.
vector_fp m_Beta0MX_ij_P
Derivative of Beta0_ij[i][j] wrt P. Vector index is counterIJ.
Array2D m_Lambda_nj_P
Derivative of Lambda_nj[i][j] wrt P.
void s_updateScaling_pHScaling_dT() const
Apply the current phScale to a set of derivatives of the activity Coefficients wrt temperature.
double m_IionicMolality
Current value of the ionic strength on the molality scale Associated Salts, if present in the mechani...
vector_fp m_PhiPhi_IJ_L
Derivative of m_PhiPhi_IJ wrt T. Vector index is counterIJ.
void calcMCCutoffParams_()
Calculate molality cut-off parameters.
vector_fp m_dlnActCoeffMolaldT_Scaled
Derivative of the Logarithm of the activity coefficients on the molality scale wrt T.
Array2D m_Beta2MX_ij_coeff
Array of coefficients for Beta2, a variable in Pitzer's papers.
vector_fp m_BphiMX_IJ_LL
Derivative of BphiMX_IJ wrt TT. Vector index is counterIJ.
void s_update_d2lnMolalityActCoeff_dT2() const
This function calculates the temperature second derivative of the natural logarithm of the molality a...
doublereal IMS_cCut_
Parameter in the polyExp cutoff treatment having to do with rate of exp decay.
doublereal IMS_slopegCut_
Parameter in the polyExp cutoff treatment.
int m_form_A_Debye
Form of the constant outside the Debye-Huckel term called A.
void getUnscaledMolalityActivityCoefficients(doublereal *acMolality) const
Get the array of unscaled non-dimensional molality based activity coefficients at the current solutio...
vector_int CROP_speciesCropped_
This is a boolean-type vector indicating whether a species's activity coefficient is in the cropped r...
vector_fp m_Psi_ijk_L
Derivative of Psi_ijk[n] wrt T.
virtual doublereal cp_mole() const
Molar heat capacity at constant pressure. Units: J/kmol/K.
vector_fp m_Phiprime_IJ
Intermediate variable called Phiprime in Pitzer's paper.
doublereal s_NBS_CLM_dlnMolalityActCoeff_dP() const
Calculate the pressure derivative of the Chlorine activity coefficient.
virtual void getPartialMolarEnthalpies(doublereal *hbar) const
Returns an array of partial molar enthalpies for the species in the mixture.
virtual void getPartialMolarEntropies(doublereal *sbar) const
Returns an array of partial molar entropies of the species in the solution.
vector_fp m_Beta1MX_ij
Array of 2D data used in the Pitzer/HMW formulation.
vector_fp m_lnActCoeffMolal_Unscaled
Logarithm of the activity coefficients on the molality scale.
Array2D m_Lambda_nj_L
Derivative of Lambda_nj[i][j] wrt T. see m_Lambda_ij.
virtual void initThermoXML(XML_Node &phaseNode, const std::string &id)
Initialize the phase parameters from an XML file.
vector_fp m_BprimeMX_IJ_P
Derivative of BprimeMX wrt P. Vector index is counterIJ.
virtual doublereal enthalpy_mole() const
Molar enthalpy. Units: J/kmol.
vector_fp m_h2func_IJ
hfunc2, was called gprime in Pitzer's paper.
vector_fp m_Alpha2MX_ij
Array of 2D data used in the Pitzer/HMW formulation.
doublereal IMS_X_o_cutoff_
value of the solute mole fraction that centers the cutoff polynomials for the cutoff =1 process;
vector_fp m_Psi_ijk_P
Derivative of Psi_ijk[n] wrt P.
virtual void getPartialMolarVolumes(doublereal *vbar) const
Return an array of partial molar volumes for the species in the mixture.
vector_fp m_dlnActCoeffMolaldT_Unscaled
Derivative of the Logarithm of the activity coefficients on the molality scale wrt T.
doublereal s_NBS_CLM_dlnMolalityActCoeff_dT() const
Calculate the temperature derivative of the Chlorine activity coefficient on the NBS scale.
vector_fp m_PhiPhi_IJ_LL
Derivative of m_PhiPhi_IJ wrt TT. Vector index is counterIJ.
vector_fp m_CMX_IJ_L
Derivative of m_CMX_IJ wrt T. Vector index is counterIJ.
void s_updateScaling_pHScaling_dP() const
Apply the current phScale to a set of derivatives of the activity Coefficients wrt pressure.
void printCoeffs() const
Print out all of the input Pitzer coefficients.
virtual doublereal cv_mole() const
Molar heat capacity at constant volume. Units: J/kmol/K.
virtual void getActivityConcentrations(doublereal *c) const
This method returns an array of generalized activity concentrations.
vector_fp m_BphiMX_IJ
Intermediate variable called BphiMX in Pitzer's paper.
void s_update_dlnMolalityActCoeff_dT() const
This function calculates the temperature derivative of the natural logarithm of the molality activity...
vector_fp m_CphiMX_ij
Array of 2D data used in the Pitzer/HMW formulation.
vector_fp m_CphiMX_ij_L
Derivative of Cphi_ij[i][j] wrt T. Vector index is counterIJ.
double ADebye_V(double temperature=-1.0, double pressure=-1.0) const
Return Pitzer's definition of A_V.
vector_fp m_Beta0MX_ij_L
Derivative of Beta0_ij[i][j] wrt T. Vector index is counterIJ.
virtual void getPartialMolarCp(doublereal *cpbar) const
Return an array of partial molar heat capacities for the species in the mixture.
vector_fp m_Phi_IJ_P
Derivative of m_Phi_IJ wrt P. Vector index is counterIJ.
void counterIJ_setup() const
Set up a counter variable for keeping track of symmetric binary interactions amongst the solute speci...
vector_fp m_hfunc_IJ
hfunc, was called gprime in Pitzer's paper.
vector_fp m_Theta_ij_P
Derivative of Theta_ij[i][j] wrt P. Vector index is counterIJ.
vector_fp m_Beta1MX_ij_LL
Derivative of Beta1_ij[i][j] wrt TT. Vector index is counterIJ.
vector_fp m_Mu_nnn
Mu coefficient for the self-ternary neutral coefficient.
vector_fp m_d2lnActCoeffMolaldT2_Scaled
Derivative of the Logarithm of the activity coefficients on the molality scale wrt TT.
Array2D m_Psi_ijk_coeff
Array of coefficients for Psi_ijk[n] in the Pitzer/HMW formulation.
virtual void setMolarDensity(const doublereal conc)
Set the internally stored molar density (kmol/m^3) for the phase.
HMWSoln()
Default Constructor.
void readXMLZetaCation(const XML_Node &BinSalt)
Process an XML node called "zetaCation".
vector_fp m_CphiMX_ij_LL
Derivative of Cphi_ij[i][j] wrt TT. Vector index is counterIJ.
vector_fp m_Beta2MX_ij_L
Derivative of Beta2_ij[i][j] wrt T. Vector index is counterIJ.
void readXMLPsi(XML_Node &BinSalt)
Process an XML node called "psiCommonAnion" or "psiCommonCation".
void setA_Debye(double A)
Set the A_Debye parameter.
int m_formPitzerTemp
This is the form of the temperature dependence of Pitzer parameterization used in the model.
virtual void setDensity(const doublereal rho)
Set the internally stored density (kg/m^3) of the phase.
virtual doublereal entropy_mole() const
Molar entropy. Units: J/kmol/K.
vector_fp m_Mu_nnn_LL
Mu coefficient 2nd temperature derivative for the self-ternary neutral coefficient.
vector_fp m_BMX_IJ_LL
Derivative of BMX_IJ wrt TT. Vector index is counterIJ.
void s_updatePitzer_CoeffWRTemp(int doDerivs=2) const
Calculates the Pitzer coefficients' dependence on the temperature.
vector_fp m_molalitiesCropped
Cropped and modified values of the molalities used in activity coefficient calculations.
vector_fp m_Psi_ijk_LL
Derivative of Psi_ijk[n] wrt TT.
doublereal s_NBS_CLM_d2lnMolalityActCoeff_dT2() const
Calculate the second temperature derivative of the Chlorine activity coefficient on the NBS scale.
virtual void initThermo()
void s_updatePitzer_dlnMolalityActCoeff_dP() const
Calculates the Pressure derivative of the natural logarithm of the molality activity coefficients.
vector_fp m_Beta2MX_ij_P
Derivative of Beta2_ij[i][j] wrt P. Vector index is counterIJ.
Array2D m_Lambda_nj
Lambda coefficient for the ij interaction.
vector_fp m_Phi_IJ
Intermediate variable called Phi in Pitzer's paper.
vector_fp m_Beta2MX_ij
Array of 2D data used in the Pitzer/HMW formulation.
vector_fp m_BprimeMX_IJ_L
Derivative of BprimeMX wrt T. Vector index is counterIJ.
vector_fp m_PhiPhi_IJ_P
Derivative of m_PhiPhi_IJ wrt P. Vector index is counterIJ.
void calc_thetas(int z1, int z2, double *etheta, double *etheta_prime) const
Calculate etheta and etheta_prime.
vector_fp m_Beta2MX_ij_LL
Derivative of Beta2_ij[i][j] wrt TT. Vector index is counterIJ.
vector_fp m_d2lnActCoeffMolaldT2_Unscaled
Derivative of the Logarithm of the activity coefficients on the molality scale wrt TT.
Array2D m_Mu_nnn_coeff
Array of coefficients form_Mu_nnn term.
double ADebye_L(double temperature=-1.0, double pressure=-1.0) const
Return Pitzer's definition of A_L.
vector_fp m_Mu_nnn_P
Mu coefficient pressure derivative for the self-ternary neutral coefficient.
vector_fp m_CMX_IJ
Intermediate variable called CMX in Pitzer's paper.
PDSS * m_waterSS
Water standard state calculator.
void calc_lambdas(double is) const
Calculate the lambda interactions.
double elambda1[17]
This is elambda1, MEC.
virtual doublereal relative_molal_enthalpy() const
Excess molar enthalpy of the solution from the mixing process on a molality basis.
vector_fp m_Phi_IJ_L
Derivative of m_Phi_IJ wrt T. Vector index is counterIJ.
vector_fp m_Theta_ij_LL
Derivative of Theta_ij[i][j] wrt TT. Vector index is counterIJ.
double m_maxIionicStrength
Maximum value of the ionic strength allowed in the calculation of the activity coefficients.
vector_fp m_BphiMX_IJ_L
Derivative of BphiMX_IJ wrt T. Vector index is counterIJ.
virtual doublereal gibbs_mole() const
Molar Gibbs function. Units: J/kmol.
vector_fp m_dlnActCoeffMolaldP_Unscaled
Derivative of the Logarithm of the activity coefficients on the molality scale wrt P.
vector_fp m_BprimeMX_IJ_LL
Derivative of BprimeMX wrt TT. Vector index is counterIJ.
vector_fp IMS_lnActCoeffMolal_
Logarithm of the molal activity coefficients.
void s_updatePitzer_dlnMolalityActCoeff_dT() const
Calculates the temperature derivative of the natural logarithm of the molality activity coefficients.
void s_updatePitzer_lnMolalityActCoeff() const
Calculate the Pitzer portion of the activity coefficients.
vector_fp m_CMX_IJ_LL
Derivative of m_CMX_IJ wrt TT. Vector index is counterIJ.
vector_fp m_gamma_tmp
Intermediate storage of the activity coefficient itself.
vector_fp m_Psi_ijk
Array of 3D data used in the Pitzer/HMW formulation.
void readXMLMunnnNeutral(XML_Node &BinSalt)
Process an XML node called "MunnnNeutral".
virtual double dA_DebyedT_TP(double temperature=-1.0, double pressure=-1.0) const
Value of the derivative of the Debye Huckel constant with respect to temperature as a function of tem...
virtual doublereal relative_enthalpy() const
Excess molar enthalpy of the solution from the mixing process.
vector_fp m_Beta1MX_ij_P
Derivative of Beta1_ij[i][j] wrt P. Vector index is counterIJ.
vector_fp m_Mu_nnn_L
Mu coefficient temperature derivative for the self-ternary neutral coefficient.
Array2D m_Lambda_nj_LL
Derivative of Lambda_nj[i][j] wrt TT.
void s_updatePitzer_d2lnMolalityActCoeff_dT2() const
This function calculates the temperature second derivative of the natural logarithm of the molality a...
void readXMLTheta(XML_Node &BinSalt)
Process an XML node called "thetaAnion" or "thetaCation".
Array2D m_Lambda_nj_coeff
Array of coefficients for Lambda_nj[i][j] in the Pitzer/HMW formulation.
vector_fp m_Theta_ij
Array of 2D data for Theta_ij[i][j] in the Pitzer/HMW formulation.
void initLengths()
Initialize all of the species-dependent lengths in the object.
vector_fp m_Beta0MX_ij
Array of 2D data used in the Pitzer/HMW formulation.
vector_fp m_BMX_IJ
Intermediate variable called BMX in Pitzer's paper.
vector_fp m_Beta0MX_ij_LL
Derivative of Beta0_ij[i][j] wrt TT. Vector index is counterIJ.
vector_fp m_gfunc_IJ
Various temporary arrays used in the calculation of the Pitzer activity coefficients.
void s_update_dlnMolalityActCoeff_dP() const
This function calculates the pressure derivative of the natural logarithm of the molality activity co...
double m_TempPitzerRef
Reference Temperature for the Pitzer formulations.
virtual void getChemPotentials(doublereal *mu) const
Get the species chemical potentials. Units: J/kmol.
vector_fp m_Beta1MX_ij_L
Derivative of Beta1_ij[i][j] wrt T. Vector index is counterIJ.
void readXMLBinarySalt(XML_Node &BinSalt)
Process an XML node called "binarySaltParameters".
virtual doublereal satPressure(doublereal T)
Get the saturation pressure for a given temperature.
double elambda[17]
This is elambda, MEC.
std::unique_ptr< WaterProps > m_waterProps
Pointer to the water property calculator.
vector_fp m_BprimeMX_IJ
Intermediate variable called BprimeMX in Pitzer's paper.
void s_updateIMS_lnMolalityActCoeff() const
This function will be called to update the internally stored natural logarithm of the molality activi...
void calcMolalitiesCropped() const
Calculate the cropped molalities.
virtual void getActivities(doublereal *ac) const
Get the array of non-dimensional activities at the current solution temperature, pressure,...
vector_fp m_CphiMX_ij_P
Derivative of Cphi_ij[i][j] wrt P. Vector index is counterIJ.
vector_fp m_tmpV
vector of size m_kk, used as a temporary holding area.
double ADebye_J(double temperature=-1.0, double pressure=-1.0) const
Return Pitzer's definition of A_J.
void s_updateScaling_pHScaling_dT2() const
Apply the current phScale to a set of 2nd derivatives of the activity Coefficients wrt temperature.
Array2D m_Beta1MX_ij_coeff
Array of coefficients for Beta1, a variable in Pitzer's papers.
doublereal s_NBS_CLM_lnMolalityActCoeff() const
Calculate the Chlorine activity coefficient on the NBS scale.
void s_updateScaling_pHScaling() const
Apply the current phScale to a set of activity Coefficients.
Array2D m_CphiMX_ij_coeff
Array of coefficients for CphiMX, a parameter in the activity coefficient formulation.
vector_fp m_g2func_IJ
This is the value of g2(x2) in Pitzer's papers. Vector index is counterIJ.
virtual double A_Debye_TP(double temperature=-1.0, double pressure=-1.0) const
Value of the Debye Huckel constant as a function of temperature and pressure.
virtual double dA_DebyedP_TP(double temperature=-1.0, double pressure=-1.0) const
Value of the derivative of the Debye Huckel constant with respect to pressure, as a function of tempe...
void calcDensity()
Calculate the density of the mixture using the partial molar volumes and mole fractions as input.
vector_fp m_dlnActCoeffMolaldP_Scaled
Derivative of the Logarithm of the activity coefficients on the molality scale wrt P.
vector_int m_CounterIJ
a counter variable for keeping track of symmetric binary interactions amongst the solute species.
vector_fp m_lnActCoeffMolal_Scaled
Logarithm of the activity coefficients on the molality scale.
bool m_molalitiesAreCropped
Boolean indicating whether the molalities are cropped or are modified.
virtual doublereal standardConcentration(size_t k=0) const
Return the standard concentration for the kth species.
size_t m_indexCLM
Index of the phScale species.
void setMoleFSolventMin(doublereal xmolSolventMIN)
Sets the minimum mole fraction in the molality formulation.
virtual void initThermo()
doublereal m_xmolSolventMIN
int m_pHScalingType
Scaling to be used for output of single-ion species activity coefficients.
doublereal m_Mnaught
This is the multiplication factor that goes inside log expressions involving the molalities of specie...
void calcMolalities() const
Calculates the molality of all species and stores the result internally.
vector_fp m_molalities
Current value of the molalities of the species in the phase.
doublereal m_weightSolvent
Molecular weight of the Solvent.
Class for the liquid water pressure dependent standard state.
virtual void setState_TP(doublereal temp, doublereal pres)
Set the internal temperature and pressure.
virtual doublereal satPressure(doublereal T)
saturation pressure
void assignDensity(const double density_)
Set the internally stored constant density (kg/m^3) of the phase.
virtual void setMoleFractions(const double *const x)
Set the mole fractions to the specified values.
doublereal mean_X(const doublereal *const Q) const
Evaluate the mole-fraction-weighted mean of an array Q.
ValueCache m_cache
Cached for saved calculations within each ThermoPhase.
doublereal charge(size_t k) const
Dimensionless electrical charge of a single molecule of species k The charge is normalized by the the...
size_t m_kk
Number of species in the phase.
std::string speciesName(size_t k) const
Name of the species with index k.
doublereal meanMolecularWeight() const
The mean molecular weight. Units: (kg/kmol)
void getMoleFractions(double *const x) const
Get the species mole fraction vector.
double moleFraction(size_t k) const
Return the mole fraction of a single species.
virtual double density() const
Density (kg/m^3).
int stateMFNumber() const
Return the State Mole Fraction Number.
doublereal temperature() const
Temperature (K).
size_t speciesIndex(const std::string &name) const
Returns the index of a species named 'name' within the Phase object.
double molarVolume() const
Molar volume (m^3/kmol).
shared_ptr< Species > species(const std::string &name) const
Return the Species object for the named species.
doublereal RT() const
Return the Gas Constant multiplied by the current temperature.
virtual doublereal isothermalCompressibility() const
Returns the isothermal compressibility. Units: 1/Pa.
virtual void initThermoFile(const std::string &inputFile, const std::string &id)
virtual void initThermoXML(XML_Node &phaseNode, const std::string &id)
Import and initialize a ThermoPhase object using an XML tree.
virtual doublereal thermalExpansionCoeff() const
Return the volumetric thermal expansion coefficient. Units: 1/K.
AnyMap m_input
Data supplied via setParameters.
virtual void getStandardVolumes(doublereal *vol) const
Get the molar volumes of the species standard states at the current T and P of the solution.
virtual void getCp_R(doublereal *cpr) const
Get the nondimensional Heat Capacities at constant pressure for the species standard states at the cu...
virtual void getEntropy_R(doublereal *sr) const
Get the array of nondimensional Entropy functions for the standard state species at the current T and...
virtual doublereal pressure() const
Returns the current pressure of the phase.
virtual void getStandardChemPotentials(doublereal *mu) const
Get the array of chemical potentials at unit activity for the species at their standard states at the...
virtual void updateStandardStateThermo() const
Updates the standard state thermodynamic functions at the current T and P of the solution.
virtual void getEnthalpy_RT(doublereal *hrt) const
Get the nondimensional Enthalpy functions for the species at their standard states at the current T a...
CachedScalar getScalar(int id)
Get a reference to a CachedValue object representing a scalar (doublereal) with the given id.
int getId()
Get a unique id for a cached value.
The WaterProps class is used to house several approximation routines for properties of water.
Class XML_Node is a tree-based representation of the contents of an XML file.
std::string attrib(const std::string &attr) const
Function returns the value of an attribute.
std::string name() const
Returns the name of the XML node.
bool hasChild(const std::string &ch) const
Tests whether the current node has a child node with a particular name.
std::string id() const
Return the id attribute, if present.
const std::vector< XML_Node * > & children() const
Return an unchangeable reference to the vector of children of the current node.
XML_Node & child(const size_t n) const
Return a changeable reference to the n'th child of the current node.
CTML ("Cantera Markup Language") is the variant of XML that Cantera uses to store data.
Header file for a common definitions used in electrolytes thermodynamics.
#define AssertTrace(expr)
Assertion must be true or an error is thrown.
#define AssertThrowMsg(expr, procedure,...)
Assertion must be true or an error is thrown.
const size_t npos
index returned by functions to indicate "no position"
const double SmallNumber
smallest number to compare to zero.
std::vector< double > vector_fp
Turn on the use of stl vectors for the basic array type within cantera Vector of doubles.
const double GasConstant
Universal Gas Constant [J/kmol/K].
void writelog(const std::string &fmt, const Args &... args)
Write a formatted message to the screen.
void writelogf(const char *fmt, const Args &... args)
Write a formatted message to the screen.
void importPhase(XML_Node &phase, ThermoPhase *th)
Import a phase information into an empty ThermoPhase object.
Namespace for the Cantera kernel.
doublereal getFloat(const XML_Node &parent, const std::string &name, const std::string &type)
Get a floating-point value from a child element.
bool getOptionalFloat(const XML_Node &parent, const std::string &name, doublereal &fltRtn, const std::string &type)
Get an optional floating-point value from a child element.
bool caseInsensitiveEquals(const std::string &input, const std::string &test)
Case insensitive equality predicate.
const int PHSCALE_PITZER
Scale to be used for the output of single-ion activity coefficients is that used by Pitzer.
size_t getFloatArray(const XML_Node &node, vector_fp &v, const bool convert, const std::string &unitsString, const std::string &nodeName)
This function reads the current node or a child node of the current node with the default name,...
doublereal fpValueCheck(const std::string &val)
Translate a string into one doublereal value, with error checking.
const int PHSCALE_NBS
Scale to be used for evaluation of single-ion activity coefficients is that used by the NBS standard ...
Contains declarations for string manipulation functions within Cantera.
T value
The value of the cached property.
bool validate(double state1New)
Check whether the currently cached value is valid based on a single state variable.