29 if (ba::iequals(estString,
"solvent")) {
31 }
else if (ba::iequals(estString,
"chargedspecies")) {
32 return cEST_chargedSpecies;
33 }
else if (ba::iequals(estString,
"weakacidassociated")) {
34 return cEST_weakAcidAssociated;
35 }
else if (ba::iequals(estString,
"strongacidassociated")) {
36 return cEST_strongAcidAssociated;
37 }
else if (ba::iequals(estString,
"polarneutral")) {
38 return cEST_polarNeutral;
39 }
else if (ba::iequals(estString,
"nonpolarneutral")) {
40 return cEST_nonpolarNeutral;
43 if ((retn = sscanf(estString.c_str(),
"%d", &rval)) != 1) {
49 void HMWSoln::readXMLBinarySalt(
XML_Node& BinSalt)
51 string xname = BinSalt.
name();
52 if (xname !=
"binarySaltParameters") {
54 "Incorrect name for processing this routine: " + xname);
58 string iName = BinSalt.
attrib(
"cation");
60 throw CanteraError(
"HMWSoln::readXMLBinarySalt",
"no cation attrib");
62 string jName = BinSalt.
attrib(
"anion");
64 throw CanteraError(
"HMWSoln::readXMLBinarySalt",
"no anion attrib");
69 size_t iSpecies = speciesIndex(iName);
70 if (iSpecies ==
npos) {
73 string ispName = speciesName(iSpecies);
74 if (charge(iSpecies) <= 0) {
75 throw CanteraError(
"HMWSoln::readXMLBinarySalt",
"cation charge problem");
77 size_t jSpecies = speciesIndex(jName);
78 if (jSpecies ==
npos) {
81 string jspName = speciesName(jSpecies);
82 if (charge(jSpecies) >= 0) {
83 throw CanteraError(
"HMWSoln::readXMLBinarySalt",
"anion charge problem");
86 size_t n = iSpecies * m_kk + jSpecies;
87 int counter = m_CounterIJ[n];
88 for (
size_t iChild = 0; iChild < BinSalt.
nChildren(); iChild++) {
90 string nodeName = xmlChild.
name();
93 if (ba::iequals(nodeName,
"beta0")) {
96 size_t nParamsFound = vParams.size();
97 if (m_formPitzerTemp == PITZER_TEMP_CONSTANT) {
98 if (nParamsFound != 1) {
99 throw CanteraError(
"HMWSoln::readXMLBinarySalt::beta0 for " + ispName
101 "wrong number of params found");
103 m_Beta0MX_ij[counter] = vParams[0];
104 m_Beta0MX_ij_coeff(0,counter) = m_Beta0MX_ij[counter];
105 }
else if (m_formPitzerTemp == PITZER_TEMP_LINEAR) {
106 if (nParamsFound != 2) {
107 throw CanteraError(
"HMWSoln::readXMLBinarySalt::beta0 for " + ispName
109 "wrong number of params found");
111 m_Beta0MX_ij_coeff(0,counter) = vParams[0];
112 m_Beta0MX_ij_coeff(1,counter) = vParams[1];
113 m_Beta0MX_ij[counter] = vParams[0];
114 }
else if (m_formPitzerTemp == PITZER_TEMP_COMPLEX1) {
115 if (nParamsFound != 5) {
116 throw CanteraError(
"HMWSoln::readXMLBinarySalt::beta0 for " + ispName
118 "wrong number of params found");
120 for (
size_t i = 0; i < nParamsFound; i++) {
121 m_Beta0MX_ij_coeff(i, counter) = vParams[i];
123 m_Beta0MX_ij[counter] = vParams[0];
126 if (ba::iequals(nodeName,
"beta1")) {
129 size_t nParamsFound = vParams.size();
130 if (m_formPitzerTemp == PITZER_TEMP_CONSTANT) {
131 if (nParamsFound != 1) {
132 throw CanteraError(
"HMWSoln::readXMLBinarySalt::beta1 for " + ispName
134 "wrong number of params found");
136 m_Beta1MX_ij[counter] = vParams[0];
137 m_Beta1MX_ij_coeff(0,counter) = m_Beta1MX_ij[counter];
138 }
else if (m_formPitzerTemp == PITZER_TEMP_LINEAR) {
139 if (nParamsFound != 2) {
140 throw CanteraError(
"HMWSoln::readXMLBinarySalt::beta1 for " + ispName
142 "wrong number of params found");
144 m_Beta1MX_ij_coeff(0,counter) = vParams[0];
145 m_Beta1MX_ij_coeff(1,counter) = vParams[1];
146 m_Beta1MX_ij[counter] = vParams[0];
147 }
else if (m_formPitzerTemp == PITZER_TEMP_COMPLEX1) {
148 if (nParamsFound != 5) {
149 throw CanteraError(
"HMWSoln::readXMLBinarySalt::beta1 for " + ispName
151 "wrong number of params found");
153 for (
size_t i = 0; i < nParamsFound; i++) {
154 m_Beta1MX_ij_coeff(i, counter) = vParams[i];
156 m_Beta1MX_ij[counter] = vParams[0];
159 if (ba::iequals(nodeName,
"beta2")) {
161 size_t nParamsFound = vParams.size();
162 if (m_formPitzerTemp == PITZER_TEMP_CONSTANT) {
163 if (nParamsFound != 1) {
164 throw CanteraError(
"HMWSoln::readXMLBinarySalt::beta2 for " + ispName
166 "wrong number of params found");
168 m_Beta2MX_ij[counter] = vParams[0];
169 m_Beta2MX_ij_coeff(0,counter) = m_Beta2MX_ij[counter];
170 }
else if (m_formPitzerTemp == PITZER_TEMP_LINEAR) {
171 if (nParamsFound != 2) {
172 throw CanteraError(
"HMWSoln::readXMLBinarySalt::beta2 for " + ispName
174 "wrong number of params found");
176 m_Beta2MX_ij_coeff(0,counter) = vParams[0];
177 m_Beta2MX_ij_coeff(1,counter) = vParams[1];
178 m_Beta2MX_ij[counter] = vParams[0];
179 }
else if (m_formPitzerTemp == PITZER_TEMP_COMPLEX1) {
180 if (nParamsFound != 5) {
181 throw CanteraError(
"HMWSoln::readXMLBinarySalt::beta2 for " + ispName
183 "wrong number of params found");
185 for (
size_t i = 0; i < nParamsFound; i++) {
186 m_Beta2MX_ij_coeff(i, counter) = vParams[i];
188 m_Beta2MX_ij[counter] = vParams[0];
191 if (ba::iequals(nodeName,
"cphi")) {
194 size_t nParamsFound = vParams.size();
195 if (m_formPitzerTemp == PITZER_TEMP_CONSTANT) {
196 if (nParamsFound != 1) {
197 throw CanteraError(
"HMWSoln::readXMLBinarySalt::Cphi for " + ispName
199 "wrong number of params found");
201 m_CphiMX_ij[counter] = vParams[0];
202 m_CphiMX_ij_coeff(0,counter) = m_CphiMX_ij[counter];
203 }
else if (m_formPitzerTemp == PITZER_TEMP_LINEAR) {
204 if (nParamsFound != 2) {
205 throw CanteraError(
"HMWSoln::readXMLBinarySalt::Cphi for " + ispName
207 "wrong number of params found");
209 m_CphiMX_ij_coeff(0,counter) = vParams[0];
210 m_CphiMX_ij_coeff(1,counter) = vParams[1];
211 m_CphiMX_ij[counter] = vParams[0];
212 }
else if (m_formPitzerTemp == PITZER_TEMP_COMPLEX1) {
213 if (nParamsFound != 5) {
214 throw CanteraError(
"HMWSoln::readXMLBinarySalt::Cphi for " + ispName
216 "wrong number of params found");
218 for (
size_t i = 0; i < nParamsFound; i++) {
219 m_CphiMX_ij_coeff(i, counter) = vParams[i];
221 m_CphiMX_ij[counter] = vParams[0];
225 if (ba::iequals(nodeName,
"alpha1")) {
229 if (ba::iequals(nodeName,
"alpha2")) {
237 string xname = BinSalt.
name();
239 if (xname !=
"thetaAnion") {
241 "Incorrect name for processing this routine: " + xname);
243 string ispName = BinSalt.
attrib(
"anion1");
245 throw CanteraError(
"HMWSoln::readXMLThetaAnion",
"no anion1 attrib");
247 string jspName = BinSalt.
attrib(
"anion2");
249 throw CanteraError(
"HMWSoln::readXMLThetaAnion",
"no anion2 attrib");
254 size_t iSpecies = speciesIndex(ispName);
255 if (iSpecies ==
npos) {
258 if (charge(iSpecies) >= 0) {
259 throw CanteraError(
"HMWSoln::readXMLThetaAnion",
"anion1 charge problem");
261 size_t jSpecies = speciesIndex(jspName);
262 if (jSpecies ==
npos) {
265 if (charge(jSpecies) >= 0) {
266 throw CanteraError(
"HMWSoln::readXMLThetaAnion",
"anion2 charge problem");
269 size_t n = iSpecies * m_kk + jSpecies;
270 int counter = m_CounterIJ[n];
271 for (
size_t i = 0; i < BinSalt.
nChildren(); i++) {
273 if (ba::iequals(xmlChild.
name(),
"theta")) {
275 size_t nParamsFound = vParams.size();
276 if (m_formPitzerTemp == PITZER_TEMP_CONSTANT) {
277 if (nParamsFound != 1) {
278 throw CanteraError(
"HMWSoln::readXMLThetaAnion::Theta for " + ispName
280 "wrong number of params found");
282 m_Theta_ij_coeff(0,counter) = vParams[0];
283 m_Theta_ij[counter] = vParams[0];
284 }
else if (m_formPitzerTemp == PITZER_TEMP_LINEAR) {
285 if (nParamsFound != 2) {
286 throw CanteraError(
"HMWSoln::readXMLThetaAnion::Theta for " + ispName
288 "wrong number of params found");
290 m_Theta_ij_coeff(0,counter) = vParams[0];
291 m_Theta_ij_coeff(1,counter) = vParams[1];
292 m_Theta_ij[counter] = vParams[0];
293 }
else if (m_formPitzerTemp == PITZER_TEMP_COMPLEX1) {
294 if (nParamsFound == 1) {
295 vParams.resize(5, 0.0);
297 }
else if (nParamsFound != 5) {
298 throw CanteraError(
"HMWSoln::readXMLThetaAnion::Theta for " + ispName
300 "wrong number of params found");
302 for (
size_t j = 0; j < nParamsFound; j++) {
303 m_Theta_ij_coeff(j, counter) = vParams[j];
305 m_Theta_ij[counter] = vParams[0];
311 void HMWSoln::readXMLThetaCation(
XML_Node& BinSalt)
313 string xname = BinSalt.
name();
315 if (xname !=
"thetaCation") {
317 "Incorrect name for processing this routine: " + xname);
319 string ispName = BinSalt.
attrib(
"cation1");
321 throw CanteraError(
"HMWSoln::readXMLThetaCation",
"no cation1 attrib");
323 string jspName = BinSalt.
attrib(
"cation2");
325 throw CanteraError(
"HMWSoln::readXMLThetaCation",
"no cation2 attrib");
330 size_t iSpecies = speciesIndex(ispName);
331 if (iSpecies ==
npos) {
334 if (charge(iSpecies) <= 0) {
335 throw CanteraError(
"HMWSoln::readXMLThetaCation",
"cation1 charge problem");
337 size_t jSpecies = speciesIndex(jspName);
338 if (jSpecies ==
npos) {
341 if (charge(jSpecies) <= 0) {
342 throw CanteraError(
"HMWSoln::readXMLThetaCation",
"cation2 charge problem");
345 size_t n = iSpecies * m_kk + jSpecies;
346 int counter = m_CounterIJ[n];
347 for (
size_t i = 0; i < BinSalt.
nChildren(); i++) {
349 if (ba::iequals(xmlChild.
name(),
"theta")) {
351 size_t nParamsFound = vParams.size();
352 if (m_formPitzerTemp == PITZER_TEMP_CONSTANT) {
353 if (nParamsFound != 1) {
354 throw CanteraError(
"HMWSoln::readXMLThetaCation::Theta for " + ispName
356 "wrong number of params found");
358 m_Theta_ij_coeff(0,counter) = vParams[0];
359 m_Theta_ij[counter] = vParams[0];
360 }
else if (m_formPitzerTemp == PITZER_TEMP_LINEAR) {
361 if (nParamsFound != 2) {
362 throw CanteraError(
"HMWSoln::readXMLThetaCation::Theta for " + ispName
364 "wrong number of params found");
366 m_Theta_ij_coeff(0,counter) = vParams[0];
367 m_Theta_ij_coeff(1,counter) = vParams[1];
368 m_Theta_ij[counter] = vParams[0];
369 }
else if (m_formPitzerTemp == PITZER_TEMP_COMPLEX1) {
370 if (nParamsFound == 1) {
371 vParams.resize(5, 0.0);
373 }
else if (nParamsFound != 5) {
374 throw CanteraError(
"HMWSoln::readXMLThetaCation::Theta for " + ispName
376 "wrong number of params found");
378 for (
size_t j = 0; j < nParamsFound; j++) {
379 m_Theta_ij_coeff(j, counter) = vParams[j];
381 m_Theta_ij[counter] = vParams[0];
387 void HMWSoln::readXMLPsiCommonCation(
XML_Node& BinSalt)
389 string xname = BinSalt.
name();
390 if (xname !=
"psiCommonCation") {
392 "Incorrect name for processing this routine: " + xname);
395 string kName = BinSalt.
attrib(
"cation");
397 throw CanteraError(
"HMWSoln::readXMLPsiCommonCation",
"no cation attrib");
399 string iName = BinSalt.
attrib(
"anion1");
401 throw CanteraError(
"HMWSoln::readXMLPsiCommonCation",
"no anion1 attrib");
403 string jName = BinSalt.
attrib(
"anion2");
405 throw CanteraError(
"HMWSoln::readXMLPsiCommonCation",
"no anion2 attrib");
410 size_t kSpecies = speciesIndex(kName);
411 if (kSpecies ==
npos) {
414 if (charge(kSpecies) <= 0) {
416 "cation charge problem");
418 size_t iSpecies = speciesIndex(iName);
419 if (iSpecies ==
npos) {
422 if (charge(iSpecies) >= 0) {
424 "anion1 charge problem");
426 size_t jSpecies = speciesIndex(jName);
427 if (jSpecies ==
npos) {
430 if (charge(jSpecies) >= 0) {
432 "anion2 charge problem");
435 size_t n = iSpecies * m_kk + jSpecies;
436 int counter = m_CounterIJ[n];
437 for (
size_t i = 0; i < BinSalt.
nChildren(); i++) {
439 if (ba::iequals(xmlChild.
name(),
"theta")) {
440 double old = m_Theta_ij[counter];
442 if (old != 0.0 && old != m_Theta_ij[counter]) {
444 "conflicting values");
447 if (ba::iequals(xmlChild.
name(),
"psi")) {
449 size_t nParamsFound = vParams.size();
450 n = iSpecies * m_kk *m_kk + jSpecies * m_kk + kSpecies;
452 if (m_formPitzerTemp == PITZER_TEMP_CONSTANT) {
453 if (nParamsFound != 1) {
454 throw CanteraError(
"HMWSoln::readXMLPsiCommonCation::Psi for " 455 + kName +
"::" + iName +
"::" + jName,
456 "wrong number of params found");
458 m_Psi_ijk_coeff(0,n) = vParams[0];
459 m_Psi_ijk[n] = vParams[0];
460 }
else if (m_formPitzerTemp == PITZER_TEMP_LINEAR) {
461 if (nParamsFound != 2) {
462 throw CanteraError(
"HMWSoln::readXMLPsiCation::Psi for " 463 + kName +
"::" + iName +
"::" + jName,
464 "wrong number of params found");
466 m_Psi_ijk_coeff(0,n) = vParams[0];
467 m_Psi_ijk_coeff(1,n) = vParams[1];
468 m_Psi_ijk[n] = vParams[0];
469 }
else if (m_formPitzerTemp == PITZER_TEMP_COMPLEX1) {
470 if (nParamsFound == 1) {
471 vParams.resize(5, 0.0);
473 }
else if (nParamsFound != 5) {
474 throw CanteraError(
"HMWSoln::readXMLPsiCation::Psi for " 475 + kName +
"::" + iName +
"::" + jName,
476 "wrong number of params found");
478 for (
size_t j = 0; j < nParamsFound; j++) {
479 m_Psi_ijk_coeff(j, n) = vParams[j];
481 m_Psi_ijk[n] = vParams[0];
485 n = iSpecies * m_kk *m_kk + kSpecies * m_kk + jSpecies;
486 for (
size_t j = 0; j < nParamsFound; j++) {
487 m_Psi_ijk_coeff(j, n) = vParams[j];
489 m_Psi_ijk[n] = vParams[0];
491 n = jSpecies * m_kk *m_kk + iSpecies * m_kk + kSpecies;
492 for (
size_t j = 0; j < nParamsFound; j++) {
493 m_Psi_ijk_coeff(j, n) = vParams[j];
495 m_Psi_ijk[n] = vParams[0];
497 n = jSpecies * m_kk *m_kk + kSpecies * m_kk + iSpecies;
498 for (
size_t j = 0; j < nParamsFound; j++) {
499 m_Psi_ijk_coeff(j, n) = vParams[j];
501 m_Psi_ijk[n] = vParams[0];
503 n = kSpecies * m_kk *m_kk + jSpecies * m_kk + iSpecies;
504 for (
size_t j = 0; j < nParamsFound; j++) {
505 m_Psi_ijk_coeff(j, n) = vParams[j];
507 m_Psi_ijk[n] = vParams[0];
509 n = kSpecies * m_kk *m_kk + iSpecies * m_kk + jSpecies;
510 for (
size_t j = 0; j < nParamsFound; j++) {
511 m_Psi_ijk_coeff(j, n) = vParams[j];
513 m_Psi_ijk[n] = vParams[0];
518 void HMWSoln::readXMLPsiCommonAnion(
XML_Node& BinSalt)
520 string xname = BinSalt.
name();
521 if (xname !=
"psiCommonAnion") {
523 "Incorrect name for processing this routine: " + xname);
526 string kName = BinSalt.
attrib(
"anion");
528 throw CanteraError(
"HMWSoln::readXMLPsiCommonAnion",
"no anion attrib");
530 string iName = BinSalt.
attrib(
"cation1");
532 throw CanteraError(
"HMWSoln::readXMLPsiCommonAnion",
"no cation1 attrib");
534 string jName = BinSalt.
attrib(
"cation2");
536 throw CanteraError(
"HMWSoln::readXMLPsiCommonAnion",
"no cation2 attrib");
541 size_t kSpecies = speciesIndex(kName);
542 if (kSpecies ==
npos) {
545 if (charge(kSpecies) >= 0) {
546 throw CanteraError(
"HMWSoln::readXMLPsiCommonAnion",
"anion charge problem");
548 size_t iSpecies = speciesIndex(iName);
549 if (iSpecies ==
npos) {
552 if (charge(iSpecies) <= 0) {
554 "cation1 charge problem");
556 size_t jSpecies = speciesIndex(jName);
557 if (jSpecies ==
npos) {
560 if (charge(jSpecies) <= 0) {
562 "cation2 charge problem");
565 size_t n = iSpecies * m_kk + jSpecies;
566 int counter = m_CounterIJ[n];
567 for (
size_t i = 0; i < BinSalt.
nChildren(); i++) {
569 if (ba::iequals(xmlChild.
name(),
"theta")) {
570 double old = m_Theta_ij[counter];
572 if (old != 0.0 && old != m_Theta_ij[counter]) {
574 "conflicting values");
577 if (ba::iequals(xmlChild.
name(),
"psi")) {
579 size_t nParamsFound = vParams.size();
580 n = iSpecies * m_kk *m_kk + jSpecies * m_kk + kSpecies;
582 if (m_formPitzerTemp == PITZER_TEMP_CONSTANT) {
583 if (nParamsFound != 1) {
584 throw CanteraError(
"HMWSoln::readXMLPsiCommonAnion::Psi for " 585 + kName +
"::" + iName +
"::" + jName,
586 "wrong number of params found");
588 m_Psi_ijk_coeff(0,n) = vParams[0];
589 m_Psi_ijk[n] = vParams[0];
590 }
else if (m_formPitzerTemp == PITZER_TEMP_LINEAR) {
591 if (nParamsFound != 2) {
593 + kName +
"::" + iName +
"::" + jName,
594 "wrong number of params found");
596 m_Psi_ijk_coeff(0,n) = vParams[0];
597 m_Psi_ijk_coeff(1,n) = vParams[1];
598 m_Psi_ijk[n] = vParams[0];
599 }
else if (m_formPitzerTemp == PITZER_TEMP_COMPLEX1) {
600 if (nParamsFound == 1) {
601 vParams.resize(5, 0.0);
603 }
else if (nParamsFound != 5) {
605 + kName +
"::" + iName +
"::" + jName,
606 "wrong number of params found");
608 for (
size_t j = 0; j < nParamsFound; j++) {
609 m_Psi_ijk_coeff(j, n) = vParams[j];
611 m_Psi_ijk[n] = vParams[0];
615 n = iSpecies * m_kk *m_kk + kSpecies * m_kk + jSpecies;
616 for (
size_t j = 0; j < nParamsFound; j++) {
617 m_Psi_ijk_coeff(j, n) = vParams[j];
619 m_Psi_ijk[n] = vParams[0];
621 n = jSpecies * m_kk *m_kk + iSpecies * m_kk + kSpecies;
622 for (
size_t j = 0; j < nParamsFound; j++) {
623 m_Psi_ijk_coeff(j, n) = vParams[j];
625 m_Psi_ijk[n] = vParams[0];
627 n = jSpecies * m_kk *m_kk + kSpecies * m_kk + iSpecies;
628 for (
size_t j = 0; j < nParamsFound; j++) {
629 m_Psi_ijk_coeff(j, n) = vParams[j];
631 m_Psi_ijk[n] = vParams[0];
633 n = kSpecies * m_kk *m_kk + jSpecies * m_kk + iSpecies;
634 for (
size_t j = 0; j < nParamsFound; j++) {
635 m_Psi_ijk_coeff(j, n) = vParams[j];
637 m_Psi_ijk[n] = vParams[0];
639 n = kSpecies * m_kk *m_kk + iSpecies * m_kk + jSpecies;
640 for (
size_t j = 0; j < nParamsFound; j++) {
641 m_Psi_ijk_coeff(j, n) = vParams[j];
643 m_Psi_ijk[n] = vParams[0];
648 void HMWSoln::readXMLLambdaNeutral(
XML_Node& BinSalt)
650 string xname = BinSalt.
name();
652 if (xname !=
"lambdaNeutral") {
654 "Incorrect name for processing this routine: " + xname);
657 string iName = BinSalt.
attrib(
"species1");
659 throw CanteraError(
"HMWSoln::readXMLLambdaNeutral",
"no species1 attrib");
661 string jName = BinSalt.
attrib(
"species2");
663 throw CanteraError(
"HMWSoln::readXMLLambdaNeutral",
"no species2 attrib");
668 size_t iSpecies = speciesIndex(iName);
669 if (iSpecies ==
npos) {
672 if (charge(iSpecies) != 0) {
674 "neutral charge problem");
676 size_t jSpecies = speciesIndex(jName);
677 if (jSpecies ==
npos) {
681 for (
size_t i = 0; i < BinSalt.
nChildren(); i++) {
683 if (ba::iequals(xmlChild.
name(),
"lambda")) {
684 size_t nCount = iSpecies*m_kk + jSpecies;
686 size_t nParamsFound = vParams.size();
687 if (m_formPitzerTemp == PITZER_TEMP_CONSTANT) {
688 if (nParamsFound != 1) {
689 throw CanteraError(
"HMWSoln::readXMLLambdaNeutral::Lambda for " + iName
691 "wrong number of params found");
693 m_Lambda_nj_coeff(0,nCount) = vParams[0];
694 m_Lambda_nj(iSpecies,jSpecies) = vParams[0];
695 }
else if (m_formPitzerTemp == PITZER_TEMP_LINEAR) {
696 if (nParamsFound != 2) {
697 throw CanteraError(
"HMWSoln::readXMLLambdaNeutral::Lambda for " + iName
699 "wrong number of params found");
701 m_Lambda_nj_coeff(0,nCount) = vParams[0];
702 m_Lambda_nj_coeff(1,nCount) = vParams[1];
703 m_Lambda_nj(iSpecies, jSpecies) = vParams[0];
704 }
else if (m_formPitzerTemp == PITZER_TEMP_COMPLEX1) {
705 if (nParamsFound == 1) {
706 vParams.resize(5, 0.0);
708 }
else if (nParamsFound != 5) {
709 throw CanteraError(
"HMWSoln::readXMLLambdaNeutral::Lambda for " + iName
711 "wrong number of params found");
713 for (
size_t j = 0; j < nParamsFound; j++) {
714 m_Lambda_nj_coeff(j,nCount) = vParams[j];
716 m_Lambda_nj(iSpecies, jSpecies) = vParams[0];
722 void HMWSoln::readXMLMunnnNeutral(
XML_Node& BinSalt)
724 string xname = BinSalt.
name();
726 if (xname !=
"MunnnNeutral") {
728 "Incorrect name for processing this routine: " + xname);
730 string iName = BinSalt.
attrib(
"species1");
732 throw CanteraError(
"HMWSoln::readXMLMunnnNeutral",
"no species1 attrib");
737 size_t iSpecies = speciesIndex(iName);
738 if (iSpecies ==
npos) {
741 if (charge(iSpecies) != 0) {
743 "neutral charge problem");
746 for (
size_t i = 0; i < BinSalt.
nChildren(); i++) {
748 if (ba::iequals(xmlChild.
name(),
"Munnn")) {
750 size_t nParamsFound = vParams.size();
751 if (m_formPitzerTemp == PITZER_TEMP_CONSTANT) {
752 if (nParamsFound != 1) {
753 throw CanteraError(
"HMWSoln::readXMLMunnnNeutral::Munnn for " + iName,
754 "wrong number of params found");
756 m_Mu_nnn_coeff(0,iSpecies) = vParams[0];
757 m_Mu_nnn[iSpecies] = vParams[0];
758 }
else if (m_formPitzerTemp == PITZER_TEMP_LINEAR) {
759 if (nParamsFound != 2) {
760 throw CanteraError(
"HMWSoln::readXMLMunnnNeutral::Munnn for " + iName,
761 "wrong number of params found");
763 m_Mu_nnn_coeff(0, iSpecies) = vParams[0];
764 m_Mu_nnn_coeff(1, iSpecies) = vParams[1];
765 m_Mu_nnn[iSpecies] = vParams[0];
766 }
else if (m_formPitzerTemp == PITZER_TEMP_COMPLEX1) {
767 if (nParamsFound == 1) {
768 vParams.resize(5, 0.0);
770 }
else if (nParamsFound != 5) {
771 throw CanteraError(
"HMWSoln::readXMLMunnnNeutral::Munnn for " + iName,
772 "wrong number of params found");
774 for (
size_t j = 0; j < nParamsFound; j++) {
775 m_Mu_nnn_coeff(j, iSpecies) = vParams[j];
777 m_Mu_nnn[iSpecies] = vParams[0];
783 void HMWSoln::readXMLZetaCation(
const XML_Node& BinSalt)
785 string xname = BinSalt.
name();
786 if (xname !=
"zetaCation") {
788 "Incorrect name for processing this routine: " + xname);
792 string iName = BinSalt.
attrib(
"neutral");
794 throw CanteraError(
"HMWSoln::readXMLZetaCation",
"no neutral attrib");
797 string jName = BinSalt.
attrib(
"cation1");
799 throw CanteraError(
"HMWSoln::readXMLZetaCation",
"no cation1 attrib");
802 string kName = BinSalt.
attrib(
"anion1");
804 throw CanteraError(
"HMWSoln::readXMLZetaCation",
"no anion1 attrib");
809 size_t iSpecies = speciesIndex(iName);
810 if (iSpecies ==
npos) {
813 if (charge(iSpecies) != 0.0) {
814 throw CanteraError(
"HMWSoln::readXMLZetaCation",
"neutral charge problem");
817 size_t jSpecies = speciesIndex(jName);
818 if (jSpecies ==
npos) {
821 if (charge(jSpecies) <= 0.0) {
822 throw CanteraError(
"HMWSoln::readXLZetaCation",
"cation1 charge problem");
825 size_t kSpecies = speciesIndex(kName);
826 if (kSpecies ==
npos) {
829 if (charge(kSpecies) >= 0.0) {
830 throw CanteraError(
"HMWSoln::readXMLZetaCation",
"anion1 charge problem");
833 for (
size_t i = 0; i < BinSalt.
nChildren(); i++) {
835 if (ba::iequals(xmlChild.
name(),
"zeta")) {
837 size_t nParamsFound = vParams.size();
838 size_t n = iSpecies * m_kk *m_kk + jSpecies * m_kk + kSpecies;
840 if (m_formPitzerTemp == PITZER_TEMP_CONSTANT) {
841 if (nParamsFound != 1) {
842 throw CanteraError(
"HMWSoln::readXMLZetaCation::Zeta for " 843 + iName +
"::" + jName +
"::" + kName,
844 "wrong number of params found");
846 m_Psi_ijk_coeff(0,n) = vParams[0];
847 m_Psi_ijk[n] = vParams[0];
848 }
else if (m_formPitzerTemp == PITZER_TEMP_LINEAR) {
849 if (nParamsFound != 2) {
850 throw CanteraError(
"HMWSoln::readXMLZetaCation::Zeta for " 851 + iName +
"::" + jName +
"::" + kName,
852 "wrong number of params found");
854 m_Psi_ijk_coeff(0,n) = vParams[0];
855 m_Psi_ijk_coeff(1,n) = vParams[1];
856 m_Psi_ijk[n] = vParams[0];
857 }
else if (m_formPitzerTemp == PITZER_TEMP_COMPLEX1) {
858 if (nParamsFound == 1) {
859 vParams.resize(5, 0.0);
861 }
else if (nParamsFound != 5) {
862 throw CanteraError(
"HMWSoln::readXMLZetaCation::Zeta for " 863 + iName +
"::" + jName +
"::" + kName,
864 "wrong number of params found");
866 for (
size_t j = 0; j < nParamsFound; j++) {
867 m_Psi_ijk_coeff(j, n) = vParams[j];
869 m_Psi_ijk[n] = vParams[0];
876 void HMWSoln::readXMLCroppingCoefficients(
const XML_Node& acNode)
878 if (acNode.
hasChild(
"croppingCoefficients")) {
880 if (cropNode.
hasChild(
"ln_gamma_k_min")) {
884 if (cropNode.
hasChild(
"ln_gamma_k_max")) {
889 if (cropNode.
hasChild(
"ln_gamma_o_min")) {
894 if (cropNode.
hasChild(
"ln_gamma_o_max")) {
901 void HMWSoln::initThermo()
903 MolalityVPSSTP::initThermo();
904 for (
int i = 0; i < 17; i++) {
911 void HMWSoln::constructPhaseFile(std::string inputFile, std::string id_)
914 "Use initThermoFile instead. To be removed after Cantera 2.3.");
916 initThermoFile(inputFile, id_);
919 void HMWSoln::constructPhaseXML(
XML_Node& phaseNode, std::string id_)
922 "Use importPhase instead. To be removed after Cantera 2.3.");
926 void HMWSoln::initThermoXML(
XML_Node& phaseNode,
const std::string& id_)
928 if (id_.size() > 0) {
929 string idp = phaseNode.
id();
932 "phasenode and Id are incompatible");
937 if (!phaseNode.
hasChild(
"thermo")) {
939 "no thermo XML node");
944 if (thermoNode.
hasChild(
"standardConc")) {
947 string formString = scNode.
attrib(
"model");
948 if (formString !=
"") {
949 if (ba::iequals(formString,
"unity")) {
952 "standardConc = unity not done");
953 }
else if (ba::iequals(formString,
"molar_volume")) {
956 "standardConc = molar_volume not done");
957 }
else if (ba::iequals(formString,
"solvent_volume")) {
961 "Unknown standardConc model: " + formString);
968 if (thermoNode.
hasChild(
"activityCoefficients")) {
970 string formString = scNode.
attrib(
"model");
971 if (formString !=
"") {
972 if (ba::iequals(formString,
"pitzer") || ba::iequals(formString,
"default")) {
974 }
else if (ba::iequals(formString,
"base")) {
978 "Unknown Pitzer ActivityCoeff model: " 985 formString = scNode.
attrib(
"TempModel");
986 if (formString !=
"") {
987 if (ba::iequals(formString,
"constant") || ba::iequals(formString,
"default")) {
988 m_formPitzerTemp = PITZER_TEMP_CONSTANT;
989 }
else if (ba::iequals(formString,
"linear")) {
990 m_formPitzerTemp = PITZER_TEMP_LINEAR;
991 }
else if (ba::iequals(formString,
"complex") || ba::iequals(formString,
"complex1")) {
992 m_formPitzerTemp = PITZER_TEMP_COMPLEX1;
995 "Unknown Pitzer ActivityCoeff Temp model: " 1003 formString = scNode.
attrib(
"TempReference");
1004 if (formString !=
"") {
1007 m_TempPitzerRef = 273.15 + 25;
1013 string solventName =
"";
1014 if (thermoNode.
hasChild(
"solvent")) {
1016 vector<string> nameSolventa;
1018 if (nameSolventa.size() != 1) {
1020 "badly formed solvent XML node");
1022 solventName = nameSolventa[0];
1030 for (
size_t k = 0; k < m_kk; k++) {
1031 string sname = speciesName(k);
1032 if (solventName == sname) {
1036 "Solvent must be species 0 atm");
1042 if (m_indexSolvent ==
npos) {
1043 std::cout <<
"HMWSoln::initThermo: Solvent Name not found" 1046 "Solvent name not found");
1048 if (m_indexSolvent != 0) {
1050 "Solvent " + solventName +
1051 " should be first species");
1061 const vector<string>&sss = speciesNames();
1063 for (
size_t k = 0; k < m_kk; k++) {
1067 "Species Data Base " + sss[k] +
" not found");
1072 "Species " + sss[k] +
1073 " standardState XML block not found");
1075 string modelString = ba::to_lower_copy(ss->
attrib(
"model"));
1076 if (modelString ==
"") {
1078 "Species " + sss[k] +
1079 " standardState XML block model attribute not found");
1082 if (modelString ==
"wateriapws" || modelString ==
"real_water" ||
1083 modelString ==
"waterpdss") {
1087 m_waterSS =
dynamic_cast<PDSS_Water*
>(providePDSS(0));
1090 "Dynamic cast to PDSS_Water failed");
1096 m_waterSS->setState_TP(300.,
OneAtm);
1097 double dens = m_waterSS->density();
1098 double mw = m_waterSS->molecularWeight();
1099 m_speciesSize[0] = mw / dens;
1101 m_waterSS = providePDSS(0);
1102 m_waterSS->setState_TP(300.,
OneAtm);
1103 double dens = m_waterSS->density();
1104 double mw = m_waterSS->molecularWeight();
1105 m_speciesSize[0] = mw / dens;
1108 if (modelString !=
"constant_incompressible" && modelString !=
"hkft") {
1110 "Solute SS Model \"" + modelString +
1113 if (modelString ==
"constant_incompressible") {
1114 m_speciesSize[k] =
getFloat(*ss,
"molarVolume",
"toSI");
1122 m_waterProps.reset(
new WaterProps(&dynamic_cast<PDSS_Water&>(*m_waterSS)));
1127 for (
size_t k = 0; k < m_kk; k++) {
1128 m_speciesCharge_Stoich[k] = charge(k);
1134 if (thermoNode.
hasChild(
"activityCoefficients")) {
1135 XML_Node& acNode = thermoNode.
child(
"activityCoefficients");
1136 acNodePtr = &acNode;
1141 m_form_A_Debye = A_DEBYE_CONST;
1142 string stemp =
"model";
1144 if (ba::iequals(ADebye.
attrib(
"model"),
"water")) {
1145 m_form_A_Debye = A_DEBYE_WATER;
1148 if (m_form_A_Debye == A_DEBYE_CONST) {
1149 m_A_Debye =
getFloat(acNode,
"A_Debye");
1154 if (acNode.
hasChild(
"maxIonicStrength")) {
1155 m_maxIionicStrength =
getFloat(acNode,
"maxIonicStrength");
1159 if (acNode.
hasChild(
"ionicRadius")) {
1161 double Afactor = 1.0;
1163 string Aunits = irNode.
attrib(
"units");
1164 Afactor =
toSI(Aunits);
1168 string ads = irNode.
attrib(
"default");
1170 for (
size_t k = 0; k < m_kk; k++) {
1171 m_Aionic[k] = ad * Afactor;
1178 std::vector<const XML_Node*> xspecies = speciesData();
1179 for (
size_t k = 0; k < m_kk; k++) {
1181 string kname = speciesName(k);
1182 for (
size_t j = 0; j < xspecies.size(); j++) {
1184 string jname = sp[
"name"];
1185 if (jname == kname) {
1191 const XML_Node& sp = *xspecies[jmap];
1197 if (acNodePtr && acNodePtr->
hasChild(
"stoichIsMods")) {
1199 map<string, string> msIs;
1201 for (
const auto& b : msIs) {
1202 size_t kk = speciesIndex(b.first);
1204 double val =
fpValue(b.second);
1205 m_speciesCharge_Stoich[kk] = val;
1212 for (
size_t i = 0; i < acNodePtr->
nChildren(); i++) {
1214 string nodeName = xmlACChild.
name();
1219 if (ba::iequals(nodeName,
"binarysaltparameters")) {
1220 readXMLBinarySalt(xmlACChild);
1221 }
else if (ba::iequals(nodeName,
"thetaanion")) {
1222 readXMLThetaAnion(xmlACChild);
1223 }
else if (ba::iequals(nodeName,
"thetacation")) {
1224 readXMLThetaCation(xmlACChild);
1225 }
else if (ba::iequals(nodeName,
"psicommonanion")) {
1226 readXMLPsiCommonAnion(xmlACChild);
1227 }
else if (ba::iequals(nodeName,
"psicommoncation")) {
1228 readXMLPsiCommonCation(xmlACChild);
1229 }
else if (ba::iequals(nodeName,
"lambdaneutral")) {
1230 readXMLLambdaNeutral(xmlACChild);
1231 }
else if (ba::iequals(nodeName,
"zetacation")) {
1232 readXMLZetaCation(xmlACChild);
1238 readXMLCroppingCoefficients(acNode);
1245 for (
size_t k = 0; k < m_kk; k++) {
1246 if (fabs(charge(k)) > 0.0001) {
1247 m_electrolyteSpeciesType[k] = cEST_chargedSpecies;
1248 if (fabs(m_speciesCharge_Stoich[k] - charge(k)) > 0.0001) {
1249 m_electrolyteSpeciesType[k] = cEST_weakAcidAssociated;
1251 }
else if (fabs(m_speciesCharge_Stoich[k]) > 0.0001) {
1252 m_electrolyteSpeciesType[k] = cEST_weakAcidAssociated;
1254 m_electrolyteSpeciesType[k] = cEST_nonpolarNeutral;
1257 m_electrolyteSpeciesType[m_indexSolvent] =
cEST_solvent;
1261 std::vector<const XML_Node*> xspecies = speciesData();
1262 for (
size_t k = 0; k < m_kk; k++) {
1263 const XML_Node* spPtr = xspecies[k];
1264 if (spPtr && spPtr->
hasChild(
"electrolyteSpeciesType")) {
1265 string est =
getChildValue(*spPtr,
"electrolyteSpeciesType");
1266 if ((m_electrolyteSpeciesType[k] =
interp_est(est)) == -1) {
1268 "Bad electrolyte type: " + est);
1274 if (acNodePtr && acNodePtr->
hasChild(
"electrolyteSpeciesType")) {
1275 XML_Node& ESTNode = acNodePtr->
child(
"electrolyteSpeciesType");
1276 map<string, string> msEST;
1278 for (
const auto& b : msEST) {
1279 size_t kk = speciesIndex(b.first);
1281 string est = b.second;
1282 if ((m_electrolyteSpeciesType[kk] =
interp_est(est)) == -1) {
1284 "Bad electrolyte type: " + est);
1290 IMS_typeCutoff_ = 2;
1291 if (IMS_typeCutoff_ == 2) {
1292 calcIMSCutoffParams_();
1294 calcMCCutoffParams_();
1295 setMoleFSolventMin(1.0E-5);
1297 MolalityVPSSTP::initThermoXML(phaseNode, id_);
1302 getMoleFractions(mf.data());
1303 bool notDone =
true;
1307 size_t kMaxC =
npos;
1309 for (
size_t k = 0; k < m_kk; k++) {
1310 sum += mf[k] * charge(k);
1311 if (fabs(mf[k] * charge(k)) > MaxC) {
1315 size_t kHp = speciesIndex(
"H+");
1316 size_t kOHm = speciesIndex(
"OH-");
1318 if (fabs(sum) > 1.0E-30) {
1320 if (mf[kHp] > sum * 1.1) {
1334 if (mf[kOHm] > -sum * 1.1) {
1346 if (notDone && kMaxC !=
npos) {
1347 if (mf[kMaxC] > (1.1 * sum / charge(kMaxC))) {
1348 mf[kMaxC] -= sum / charge(kMaxC);
1349 mf[0] += sum / charge(kMaxC);
1357 setMoleFractions(mf.data());
1364 void HMWSoln::calcIMSCutoffParams_()
1366 IMS_afCut_ = 1.0 / (std::exp(1.0) * IMS_gamma_k_min_);
1368 bool converged =
false;
1370 for (
int its = 0; its < 100 && !converged; its++) {
1372 IMS_afCut_ = 1.0 / (std::exp(1.0) * IMS_gamma_k_min_) -IMS_efCut_;
1373 IMS_bfCut_ = IMS_afCut_ / IMS_cCut_ + IMS_slopefCut_ - 1.0;
1374 IMS_dfCut_ = ((- IMS_afCut_/IMS_cCut_ + IMS_bfCut_ - IMS_bfCut_*IMS_X_o_cutoff_/IMS_cCut_)
1376 (IMS_X_o_cutoff_*IMS_X_o_cutoff_/IMS_cCut_ - 2.0 * IMS_X_o_cutoff_));
1377 double tmp = IMS_afCut_ + IMS_X_o_cutoff_*(IMS_bfCut_ + IMS_dfCut_ *IMS_X_o_cutoff_);
1378 double eterm = std::exp(-IMS_X_o_cutoff_/IMS_cCut_);
1379 IMS_efCut_ = - eterm * tmp;
1380 if (fabs(IMS_efCut_ - oldV) < 1.0E-14) {
1386 " failed to converge on the f polynomial");
1389 double f_0 = IMS_afCut_ + IMS_efCut_;
1390 double f_prime_0 = 1.0 - IMS_afCut_ / IMS_cCut_ + IMS_bfCut_;
1392 for (
int its = 0; its < 100 && !converged; its++) {
1394 double lng_0 = -log(IMS_gamma_o_min_) - f_prime_0 / f_0;
1395 IMS_agCut_ = exp(lng_0) - IMS_egCut_;
1396 IMS_bgCut_ = IMS_agCut_ / IMS_cCut_ + IMS_slopegCut_ - 1.0;
1397 IMS_dgCut_ = ((- IMS_agCut_/IMS_cCut_ + IMS_bgCut_ - IMS_bgCut_*IMS_X_o_cutoff_/IMS_cCut_)
1399 (IMS_X_o_cutoff_*IMS_X_o_cutoff_/IMS_cCut_ - 2.0 * IMS_X_o_cutoff_));
1400 double tmp = IMS_agCut_ + IMS_X_o_cutoff_*(IMS_bgCut_ + IMS_dgCut_ *IMS_X_o_cutoff_);
1401 double eterm = std::exp(-IMS_X_o_cutoff_/IMS_cCut_);
1402 IMS_egCut_ = - eterm * tmp;
1403 if (fabs(IMS_egCut_ - oldV) < 1.0E-14) {
1409 " failed to converge on the g polynomial");
1413 void HMWSoln::calcMCCutoffParams_()
1416 MC_X_o_cutoff_ = 0.6;
1417 MC_slopepCut_ = 0.02;
1421 MC_apCut_ = MC_X_o_min_;
1423 bool converged =
false;
1426 for (
int its = 0; its < 500 && !converged; its++) {
1428 MC_apCut_ = damp *(MC_X_o_min_ - MC_epCut_) + (1-damp) * MC_apCut_;
1429 double MC_bpCutNew = MC_apCut_ / MC_cpCut_ + MC_slopepCut_ - 1.0;
1430 MC_bpCut_ = damp * MC_bpCutNew + (1-damp) * MC_bpCut_;
1431 double MC_dpCutNew = ((- MC_apCut_/MC_cpCut_ + MC_bpCut_ - MC_bpCut_ * MC_X_o_cutoff_/MC_cpCut_)
1433 (MC_X_o_cutoff_ * MC_X_o_cutoff_/MC_cpCut_ - 2.0 * MC_X_o_cutoff_));
1434 MC_dpCut_ = damp * MC_dpCutNew + (1-damp) * MC_dpCut_;
1435 double tmp = MC_apCut_ + MC_X_o_cutoff_*(MC_bpCut_ + MC_dpCut_ * MC_X_o_cutoff_);
1436 double eterm = std::exp(- MC_X_o_cutoff_ / MC_cpCut_);
1437 MC_epCut_ = - eterm * tmp;
1438 double diff = MC_epCut_ - oldV;
1439 if (fabs(diff) < 1.0E-14) {
1445 " failed to converge on the p polynomial");
void getMap(const XML_Node &node, std::map< std::string, std::string > &m)
This routine is used to interpret the value portions of XML elements that contain colon separated pai...
const int cEST_solvent
Electrolyte species type.
doublereal fpValue(const std::string &val)
Translate a string into one doublereal value.
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...
CTML ("Cantera Markup Language") is the variant of XML that Cantera uses to store data...
std::string name() const
Returns the name of the XML node.
std::string getChildValue(const XML_Node &parent, const std::string &nameString)
This function reads a child node with the name, nameString, and returns its XML value as the return s...
static int interp_est(const std::string &estString)
Utility function to assign an integer value from a string for the ElectrolyteSpeciesType field...
const XML_Node * findByName(const std::string &nm, int depth=100000) const
This routine carries out a recursive search for an XML node based on the name of the node...
const doublereal OneAtm
One atmosphere [Pa].
doublereal toSI(const std::string &unit)
Return the conversion factor to convert unit std::string 'unit' to SI units.
const size_t npos
index returned by functions to indicate "no position"
Header file for a common definitions used in electrolytes thermodynamics.
Headers for the factory class that can create known ThermoPhase objects (see Thermodynamic Properties...
Class XML_Node is a tree-based representation of the contents of an XML file.
Implementation of a pressure dependent standard state virtual function for a Pure Water Phase (see Sp...
void warn_deprecated(const std::string &method, const std::string &extra)
Print a warning indicating that method is deprecated.
bool hasAttrib(const std::string &a) const
Tests whether the current node has an attribute with a particular name.
Headers for the HMWSoln ThermoPhase object, which models concentrated electrolyte solutions (see Ther...
The WaterProps class is used to house several approximation routines for properties of water...
#define PITZERFORM_BASE
Major Parameters: The form of the Pitzer expression refers to the form of the Gibbs free energy expre...
Class for the liquid water pressure dependent standard state.
Base class for exceptions thrown by Cantera classes.
std::string value() const
Return the value of an XML node as a string.
void importPhase(XML_Node &phase, ThermoPhase *th)
Import a phase information into an empty ThermoPhase object.
bool hasChild(const std::string &ch) const
Tests whether the current node has a child node with a particular name.
XML_Node & child(const size_t n) const
Return a changeable reference to the n'th child of the current node.
XML_Node & root() const
Return the root of the current XML_Node tree.
std::string attrib(const std::string &attr) const
Function returns the value of an attribute.
std::vector< double > vector_fp
Turn on the use of stl vectors for the basic array type within cantera Vector of doubles.
void getStringArray(const XML_Node &node, std::vector< std::string > &v)
This function interprets the value portion of an XML element as a string.
std::string id() const
Return the id attribute, if present.
Contains declarations for string manipulation functions within Cantera.
doublereal getFloat(const XML_Node &parent, const std::string &name, const std::string &type)
Get a floating-point value from a child element.
XML_Node * findByAttr(const std::string &attr, const std::string &val, int depth=100000) const
This routine carries out a recursive search for an XML node based on an attribute of each XML node...
Namespace for the Cantera kernel.
doublereal fpValueCheck(const std::string &val)
Translate a string into one doublereal value, with error checking.
size_t nChildren(bool discardComments=false) const
Return the number of children.
XML_Node * get_XML_NameID(const std::string &nameTarget, const std::string &file_ID, XML_Node *root)
This routine will locate an XML node in either the input XML tree or in another input file specified ...
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.