22 #include "cantera/thermo/mix_defs.h"
34 static const double xxSmall = 1.0E-150;
40 IonsFromNeutralVPSSTP::IonsFromNeutralVPSSTP() :
42 ionSolnType_(cIonSolnType_SINGLEANION),
43 numNeutralMoleculeSpecies_(0),
44 indexSpecialSpecies_(
npos),
45 indexSecondSpecialSpecies_(
npos),
48 numPassThroughSpecies_(0),
49 neutralMoleculePhase_(0),
50 IOwnNThermoPhase_(true),
52 muNeutralMolecule_(0),
53 lnActCoeff_NeutralMolecule_(0)
86 ionSolnType_(cIonSolnType_SINGLEANION),
87 numNeutralMoleculeSpecies_(0),
88 indexSpecialSpecies_(
npos),
89 indexSecondSpecialSpecies_(
npos),
92 numPassThroughSpecies_(0),
93 neutralMoleculePhase_(neutralPhase),
94 IOwnNThermoPhase_(true),
96 muNeutralMolecule_(0),
97 lnActCoeff_NeutralMolecule_(0)
108 ionSolnType_(cIonSolnType_SINGLEANION),
109 numNeutralMoleculeSpecies_(0),
110 indexSpecialSpecies_(
npos),
111 indexSecondSpecialSpecies_(
npos),
112 numCationSpecies_(0),
114 numPassThroughSpecies_(0),
115 neutralMoleculePhase_(neutralPhase),
116 IOwnNThermoPhase_(true),
117 moleFractionsTmp_(0),
118 muNeutralMolecule_(0),
120 lnActCoeff_NeutralMolecule_(0)
138 ionSolnType_(cIonSolnType_SINGLEANION),
139 numNeutralMoleculeSpecies_(0),
140 indexSpecialSpecies_(
npos),
141 indexSecondSpecialSpecies_(
npos),
142 numCationSpecies_(0),
144 numPassThroughSpecies_(0),
145 neutralMoleculePhase_(0),
146 IOwnNThermoPhase_(true),
147 moleFractionsTmp_(0),
148 muNeutralMolecule_(0),
150 lnActCoeff_NeutralMolecule_(0)
258 return cIonsFromNeutral;
286 double uu = hh - pres * molarV;
334 vector_fp& charges, std::vector<size_t>& neutMolIndex)
const
362 for (
size_t k = 0; k <
m_kk; k++) {
384 doublereal xx, fact2;
401 case cIonSolnType_PASSTHROUGH:
404 case cIonSolnType_SINGLEANION:
408 fact2 = 2.0 * RT_ * log(2.0);
423 mu[icat] = RT_ * log(xx);
434 case cIonSolnType_SINGLECATION:
437 case cIonSolnType_MULTICATIONANION:
472 for (
size_t k = 0; k <
m_kk; k++) {
482 for (
size_t k = 0; k <
m_kk; k++) {
516 for (
size_t k = 0; k <
m_kk; k++) {
523 for (
size_t k = 0; k <
m_kk; k++) {
553 for (
size_t k = 0; k <
m_kk; k++) {
582 for (
size_t k = 0; k <
m_kk; k++) {
592 for (
size_t k = 0; k <
m_kk; k++) {
593 for (
size_t m = 0; m <
m_kk; m++) {
594 dlnActCoeffdlnN[ld * k + m] = data[m_kk * k + m];
651 for (
size_t k = 0; k <
m_kk; k++) {
659 for (
size_t k = 0; k <
m_kk; k++) {
668 doublereal sum = 0.0;
669 for (
size_t k = 0; k <
m_kk; k++) {
672 for (
size_t k = 0; k <
m_kk; k++) {
696 doublereal sum = 0.0;
704 for (
int k = 0; k <
m_kk; k++) {
707 if (fabs(sum) > 1.0E-11) {
708 throw CanteraError(
"IonsFromNeutralVPSSTP::calcNeutralMoleculeMoleFractions",
709 "molefracts don't sum to one: " +
fp2str(sum));
717 case cIonSolnType_PASSTHROUGH:
718 for (
size_t k = 0; k <
m_kk; k++) {
723 case cIonSolnType_SINGLEANION:
747 for (
size_t k = 0; k <
m_kk; k++) {
751 for (
size_t k = 0; k <
m_kk; k++) {
756 for (
size_t k = 0; k <
m_kk; k++) {
764 throw CanteraError(
"",
"neutral molecule calc error - anion");
782 case cIonSolnType_SINGLECATION:
788 case cIonSolnType_MULTICATIONANION:
820 doublereal sumy, sumdy;
834 case cIonSolnType_PASSTHROUGH:
835 for (
size_t k = 0; k <
m_kk; k++) {
840 case cIonSolnType_SINGLEANION:
848 dy[jNeut] += dx[icat] / fmij;
857 dy[jNeut] += dx[icat] / fmij;
860 #ifdef DEBUG_MODE_NOT
862 for (
size_t k = 0; k <
m_kk; k++) {
866 for (
size_t k = 0; k <
m_kk; k++) {
871 for (
size_t k = 0; k <
m_kk; k++) {
879 throw CanteraError(
"",
"neutral molecule calc error - anion");
893 dy[k] = dy[k]/sumy - y[k]*sumdy/sumy/sumy;
898 case cIonSolnType_SINGLECATION:
904 case cIonSolnType_MULTICATIONANION:
961 throw CanteraError(
"IonsFromNeutralVPSSTP",
"Base class method "
982 if (inputFile.size() == 0) {
984 "input file is null");
987 std::ifstream fin(path.c_str());
989 throw CanteraError(
"MargulesVPSSTP:constructPhaseFile",
"could not open "
990 +path+
" for reading.");
1001 throw CanteraError(
"MargulesVPSSTP:constructPhaseFile",
1002 "ERROR: Can not find phase named " +
1003 id +
" in file named " + inputFile);
1005 fxml_phase->
copy(&phaseNode_XML);
1040 if (
id.
size() > 0) {
1041 string idp = phaseNode.
id();
1043 throw CanteraError(
"IonsFromNeutralVPSSTP::constructPhaseXML",
1044 "phasenode and Id are incompatible");
1051 if (!phaseNode.
hasChild(
"thermo")) {
1052 throw CanteraError(
"IonsFromNeutralVPSSTP::constructPhaseXML",
1053 "no thermo XML node");
1062 stemp = thermoNode.
attrib(
"model");
1064 if (formString !=
"ionsfromneutralmolecule") {
1065 throw CanteraError(
"IonsFromNeutralVPSSTP::constructPhaseXML",
1066 "model name isn't IonsFromNeutralMolecule: " + formString);
1072 if (!thermoNode.
hasChild(
"neutralMoleculePhase")) {
1073 throw CanteraError(
"IonsFromNeutralVPSSTP::constructPhaseXML",
1074 "no neutralMoleculePhase XML node");
1076 XML_Node& neutralMoleculeNode = thermoNode.
child(
"neutralMoleculePhase");
1078 string nsource = neutralMoleculeNode[
"datasrc"];
1081 throw CanteraError(
"IonsFromNeutralVPSSTP::constructPhaseXML",
1099 throw CanteraError(
"IonsFromNeutralVPSSTP::constructPhaseXML",
1100 "importPhase failed ");
1159 const std::vector<double>& elemVectorN,
1160 const size_t nElementsN,
1161 const std::vector<std::string>& elnamesVI ,
1162 const std::vector<double>& elemVectorI,
1163 const size_t nElementsI)
1165 double fMax = 1.0E100;
1166 for (
size_t mi = 0; mi < nElementsI; mi++) {
1167 if (elnamesVI[mi] !=
"E") {
1168 if (elemVectorI[mi] > 1.0E-13) {
1169 double eiNum = elemVectorI[mi];
1170 for (
size_t mn = 0; mn < nElementsN; mn++) {
1171 if (elnamesVI[mi] == elnamesVN[mn]) {
1172 if (elemVectorN[mn] <= 1.0E-13) {
1175 fMax =
std::min(fMax, elemVectorN[mn]/eiNum);
1211 for (k = 0; k <
m_kk; k++) {
1220 for (k = 0; k <
m_kk; k++) {
1229 for (k = 0; k <
m_kk; k++) {
1238 for (k = 0; k <
m_kk; k++) {
1241 throw CanteraError(
"initThermoXML",
"Dynamic cast failed");
1254 std::vector<double> elemVectorN(nElementsN);
1255 std::vector<double> elemVectorN_orig(nElementsN);
1258 const std::vector<std::string>& elnamesVI =
elementNames();
1259 std::vector<double> elemVectorI(nElementsI);
1261 vector<doublereal> fm_tmp(m_kk);
1262 for (
size_t k = 0; k <
m_kk; k++) {
1269 for (
size_t m = 0; m < nElementsN; m++) {
1272 elemVectorN_orig = elemVectorN;
1273 fm_tmp.assign(m_kk, 0.0);
1275 for (
size_t m = 0; m < nElementsI; m++) {
1278 double fac =
factorOverlap(elnamesVN, elemVectorN, nElementsN,
1279 elnamesVI ,elemVectorI, nElementsI);
1281 for (
size_t m = 0; m < nElementsN; m++) {
1282 std::string mName = elnamesVN[m];
1283 for (
size_t mi = 0; mi < nElementsI; mi++) {
1284 std::string eName = elnamesVI[mi];
1285 if (mName == eName) {
1286 elemVectorN[m] -= fac * elemVectorI[mi];
1295 for (k = 0; k <
m_kk; k++) {
1296 for (
size_t m = 0; m < nElementsI; m++) {
1297 elemVectorI[m] =
nAtoms(k, m);
1299 double fac =
factorOverlap(elnamesVN, elemVectorN, nElementsN,
1300 elnamesVI ,elemVectorI, nElementsI);
1302 for (
size_t m = 0; m < nElementsN; m++) {
1303 std::string mName = elnamesVN[m];
1304 for (
size_t mi = 0; mi < nElementsI; mi++) {
1305 std::string eName = elnamesVI[mi];
1306 if (mName == eName) {
1307 elemVectorN[m] -= fac * elemVectorI[mi];
1312 bool notTaken =
true;
1313 for (
size_t iNeut = 0; iNeut < jNeut; iNeut++) {
1321 throw CanteraError(
"IonsFromNeutralVPSSTP::initThermoXML",
1322 "Simple formula matrix generation failed, one cation is shared between two salts");
1329 for (
size_t m = 0; m < nElementsN; m++) {
1330 if (fabs(elemVectorN[m]) > 1.0E-13) {
1331 throw CanteraError(
"IonsFromNeutralVPSSTP::initThermoXML",
1332 "Simple formula matrix generation failed");
1365 case cIonSolnType_PASSTHROUGH:
1367 case cIonSolnType_SINGLEANION:
1391 case cIonSolnType_SINGLECATION:
1392 throw CanteraError(
"IonsFromNeutralVPSSTP::s_update_lnActCoeff",
"Unimplemented type");
1394 case cIonSolnType_MULTICATIONANION:
1395 throw CanteraError(
"IonsFromNeutralVPSSTP::s_update_lnActCoeff",
"Unimplemented type");
1398 throw CanteraError(
"IonsFromNeutralVPSSTP::s_update_lnActCoeff",
"Unimplemented type");
1415 doublereal* dlnActCoeffds)
const
1424 for (
size_t k = 0; k <
m_kk; k++) {
1430 size_t numNeutMolSpec = geThermo->
nSpecies();
1431 vector_fp dlnActCoeff_NeutralMolecule(numNeutMolSpec);
1432 vector_fp dX_NeutralMolecule(numNeutMolSpec);
1442 case cIonSolnType_PASSTHROUGH:
1444 case cIonSolnType_SINGLEANION:
1452 dlnActCoeffds[icat] = dlnActCoeff_NeutralMolecule[jNeut]/fmij;
1458 dlnActCoeffds[icat]= 0.0;
1464 dlnActCoeffds[icat] = dlnActCoeff_NeutralMolecule[jNeut];
1468 case cIonSolnType_SINGLECATION:
1469 throw CanteraError(
"IonsFromNeutralVPSSTP::s_update_lnActCoeffds",
"Unimplemented type");
1471 case cIonSolnType_MULTICATIONANION:
1472 throw CanteraError(
"IonsFromNeutralVPSSTP::s_update_lnActCoeffds",
"Unimplemented type");
1475 throw CanteraError(
"IonsFromNeutralVPSSTP::s_update_lnActCoeffds",
"Unimplemented type");
1502 case cIonSolnType_PASSTHROUGH:
1504 case cIonSolnType_SINGLEANION:
1528 case cIonSolnType_SINGLECATION:
1529 throw CanteraError(
"IonsFromNeutralVPSSTP::s_update_lnActCoeffdT",
"Unimplemented type");
1531 case cIonSolnType_MULTICATIONANION:
1532 throw CanteraError(
"IonsFromNeutralVPSSTP::s_update_lnActCoeffdT",
"Unimplemented type");
1535 throw CanteraError(
"IonsFromNeutralVPSSTP::s_update_lnActCoeffdT",
"Unimplemented type");
1561 case cIonSolnType_PASSTHROUGH:
1563 case cIonSolnType_SINGLEANION:
1587 case cIonSolnType_SINGLECATION:
1588 throw CanteraError(
"IonsFromNeutralVPSSTP::s_update_lnActCoeff_dlnX_diag()",
"Unimplemented type");
1590 case cIonSolnType_MULTICATIONANION:
1591 throw CanteraError(
"IonsFromNeutralVPSSTP::s_update_lnActCoeff_dlnX_diag()",
"Unimplemented type");
1594 throw CanteraError(
"IonsFromNeutralVPSSTP::s_update_lnActCoeff_dlnX_diag()",
"Unimplemented type");
1620 case cIonSolnType_PASSTHROUGH:
1622 case cIonSolnType_SINGLEANION:
1646 case cIonSolnType_SINGLECATION:
1647 throw CanteraError(
"IonsFromNeutralVPSSTP::s_update_lnActCoeff_dlnN_diag()",
"Unimplemented type");
1649 case cIonSolnType_MULTICATIONANION:
1650 throw CanteraError(
"IonsFromNeutralVPSSTP::s_update_lnActCoeff_dlnN_diag()",
"Unimplemented type");
1653 throw CanteraError(
"IonsFromNeutralVPSSTP::s_update_lnActCoeff_dlnN_diag()",
"Unimplemented type");
1668 size_t kcat, kNeut, mcat, mNeut;
1669 doublereal fmij, mfmij;
1676 throw CanteraError(
"IonsFromNeutralVPSSTP::s_update_dlnActCoeff_dlnN()",
"dynamic cast failed");
1678 size_t nsp_ge = geThermo->
nSpecies();
1682 case cIonSolnType_PASSTHROUGH:
1684 case cIonSolnType_SINGLEANION:
1712 for (
size_t k = 0; k <
m_kk; k++) {
1723 for (
size_t m = 0; m <
m_kk; m++) {
1740 case cIonSolnType_SINGLECATION:
1741 throw CanteraError(
"IonsFromNeutralVPSSTP::s_update_lnActCoeff_dlnN",
"Unimplemented type");
1743 case cIonSolnType_MULTICATIONANION:
1744 throw CanteraError(
"IonsFromNeutralVPSSTP::s_update_lnActCoeff_dlnN",
"Unimplemented type");
1747 throw CanteraError(
"IonsFromNeutralVPSSTP::s_update_lnActCoeff_dlnN",
"Unimplemented type");