40 const char* cc = estString.c_str();
42 const char* ccl = lcs.c_str();
43 if (!strcmp(ccl,
"solvent")) {
45 }
else if (!strcmp(ccl,
"chargedspecies")) {
46 return cEST_chargedSpecies;
47 }
else if (!strcmp(ccl,
"weakacidassociated")) {
48 return cEST_weakAcidAssociated;
49 }
else if (!strcmp(ccl,
"strongacidassociated")) {
50 return cEST_strongAcidAssociated;
51 }
else if (!strcmp(ccl,
"polarneutral")) {
52 return cEST_polarNeutral;
53 }
else if (!strcmp(ccl,
"nonpolarneutral")) {
54 return cEST_nonpolarNeutral;
57 if ((retn = sscanf(cc,
"%d", &rval)) != 1) {
70 void HMWSoln::readXMLBinarySalt(
XML_Node& BinSalt)
72 string xname = BinSalt.
name();
73 if (xname !=
"binarySaltParameters") {
75 "Incorrect name for processing this routine: " + xname);
77 double* charge =
DATA_PTR(m_speciesCharge);
79 size_t nParamsFound, i;
81 string iName = BinSalt.
attrib(
"cation");
83 throw CanteraError(
"HMWSoln::readXMLBinarySalt",
"no cation attrib");
85 string jName = BinSalt.
attrib(
"anion");
87 throw CanteraError(
"HMWSoln::readXMLBinarySalt",
"no anion attrib");
93 size_t iSpecies = speciesIndex(iName);
94 if (iSpecies ==
npos) {
97 string ispName = speciesName(iSpecies);
98 if (charge[iSpecies] <= 0) {
99 throw CanteraError(
"HMWSoln::readXMLBinarySalt",
"cation charge problem");
101 size_t jSpecies = speciesIndex(jName);
102 if (jSpecies ==
npos) {
105 string jspName = speciesName(jSpecies);
106 if (charge[jSpecies] >= 0) {
107 throw CanteraError(
"HMWSoln::readXMLBinarySalt",
"anion charge problem");
110 size_t n = iSpecies * m_kk + jSpecies;
111 int counter = m_CounterIJ[n];
112 for (
size_t iChild = 0; iChild < BinSalt.
nChildren(); iChild++) {
114 stemp = xmlChild.
name();
119 if (nodeName ==
"beta0") {
124 nParamsFound = vParams.size();
125 if (m_formPitzerTemp == PITZER_TEMP_CONSTANT) {
126 if (nParamsFound != 1) {
127 throw CanteraError(
"HMWSoln::readXMLBinarySalt::beta0 for " + ispName
129 "wrong number of params found");
131 m_Beta0MX_ij[counter] = vParams[0];
132 m_Beta0MX_ij_coeff(0,counter) = m_Beta0MX_ij[counter];
133 }
else if (m_formPitzerTemp == PITZER_TEMP_LINEAR) {
134 if (nParamsFound != 2) {
135 throw CanteraError(
"HMWSoln::readXMLBinarySalt::beta0 for " + ispName
137 "wrong number of params found");
139 m_Beta0MX_ij_coeff(0,counter) = vParams[0];
140 m_Beta0MX_ij_coeff(1,counter) = vParams[1];
141 m_Beta0MX_ij[counter] = vParams[0];
142 }
else if (m_formPitzerTemp == PITZER_TEMP_COMPLEX1) {
143 if (nParamsFound != 5) {
144 throw CanteraError(
"HMWSoln::readXMLBinarySalt::beta0 for " + ispName
146 "wrong number of params found");
148 for (i = 0; i < nParamsFound; i++) {
149 m_Beta0MX_ij_coeff(i, counter) = vParams[i];
151 m_Beta0MX_ij[counter] = vParams[0];
154 if (nodeName ==
"beta1") {
160 nParamsFound = vParams.size();
161 if (m_formPitzerTemp == PITZER_TEMP_CONSTANT) {
162 if (nParamsFound != 1) {
163 throw CanteraError(
"HMWSoln::readXMLBinarySalt::beta1 for " + ispName
165 "wrong number of params found");
167 m_Beta1MX_ij[counter] = vParams[0];
168 m_Beta1MX_ij_coeff(0,counter) = m_Beta1MX_ij[counter];
169 }
else if (m_formPitzerTemp == PITZER_TEMP_LINEAR) {
170 if (nParamsFound != 2) {
171 throw CanteraError(
"HMWSoln::readXMLBinarySalt::beta1 for " + ispName
173 "wrong number of params found");
175 m_Beta1MX_ij_coeff(0,counter) = vParams[0];
176 m_Beta1MX_ij_coeff(1,counter) = vParams[1];
177 m_Beta1MX_ij[counter] = vParams[0];
178 }
else if (m_formPitzerTemp == PITZER_TEMP_COMPLEX1) {
179 if (nParamsFound != 5) {
180 throw CanteraError(
"HMWSoln::readXMLBinarySalt::beta1 for " + ispName
182 "wrong number of params found");
184 for (i = 0; i < nParamsFound; i++) {
185 m_Beta1MX_ij_coeff(i, counter) = vParams[i];
187 m_Beta1MX_ij[counter] = vParams[0];
190 if (nodeName ==
"beta2") {
192 nParamsFound = vParams.size();
193 if (m_formPitzerTemp == PITZER_TEMP_CONSTANT) {
194 if (nParamsFound != 1) {
195 throw CanteraError(
"HMWSoln::readXMLBinarySalt::beta2 for " + ispName
197 "wrong number of params found");
199 m_Beta2MX_ij[counter] = vParams[0];
200 m_Beta2MX_ij_coeff(0,counter) = m_Beta2MX_ij[counter];
201 }
else if (m_formPitzerTemp == PITZER_TEMP_LINEAR) {
202 if (nParamsFound != 2) {
203 throw CanteraError(
"HMWSoln::readXMLBinarySalt::beta2 for " + ispName
205 "wrong number of params found");
207 m_Beta2MX_ij_coeff(0,counter) = vParams[0];
208 m_Beta2MX_ij_coeff(1,counter) = vParams[1];
209 m_Beta2MX_ij[counter] = vParams[0];
210 }
else if (m_formPitzerTemp == PITZER_TEMP_COMPLEX1) {
211 if (nParamsFound != 5) {
212 throw CanteraError(
"HMWSoln::readXMLBinarySalt::beta2 for " + ispName
214 "wrong number of params found");
216 for (i = 0; i < nParamsFound; i++) {
217 m_Beta2MX_ij_coeff(i, counter) = vParams[i];
219 m_Beta2MX_ij[counter] = vParams[0];
223 if (nodeName ==
"cphi") {
228 nParamsFound = vParams.size();
229 if (m_formPitzerTemp == PITZER_TEMP_CONSTANT) {
230 if (nParamsFound != 1) {
231 throw CanteraError(
"HMWSoln::readXMLBinarySalt::Cphi for " + ispName
233 "wrong number of params found");
235 m_CphiMX_ij[counter] = vParams[0];
236 m_CphiMX_ij_coeff(0,counter) = m_CphiMX_ij[counter];
237 }
else if (m_formPitzerTemp == PITZER_TEMP_LINEAR) {
238 if (nParamsFound != 2) {
239 throw CanteraError(
"HMWSoln::readXMLBinarySalt::Cphi for " + ispName
241 "wrong number of params found");
243 m_CphiMX_ij_coeff(0,counter) = vParams[0];
244 m_CphiMX_ij_coeff(1,counter) = vParams[1];
245 m_CphiMX_ij[counter] = vParams[0];
246 }
else if (m_formPitzerTemp == PITZER_TEMP_COMPLEX1) {
247 if (nParamsFound != 5) {
248 throw CanteraError(
"HMWSoln::readXMLBinarySalt::Cphi for " + ispName
250 "wrong number of params found");
252 for (i = 0; i < nParamsFound; i++) {
253 m_CphiMX_ij_coeff(i, counter) = vParams[i];
255 m_CphiMX_ij[counter] = vParams[0];
259 if (nodeName ==
"alpha1") {
260 stemp = xmlChild.
value();
261 m_Alpha1MX_ij[counter] =
atofCheck(stemp.c_str());
264 if (nodeName ==
"alpha2") {
265 stemp = xmlChild.
value();
266 m_Alpha2MX_ij[counter] =
atofCheck(stemp.c_str());
278 string xname = BinSalt.
name();
280 size_t nParamsFound = 0;
281 if (xname !=
"thetaAnion") {
283 "Incorrect name for processing this routine: " + xname);
285 double* charge =
DATA_PTR(m_speciesCharge);
287 string ispName = BinSalt.
attrib(
"anion1");
289 throw CanteraError(
"HMWSoln::readXMLThetaAnion",
"no anion1 attrib");
291 string jspName = BinSalt.
attrib(
"anion2");
293 throw CanteraError(
"HMWSoln::readXMLThetaAnion",
"no anion2 attrib");
299 size_t iSpecies = speciesIndex(ispName);
300 if (iSpecies ==
npos) {
303 if (charge[iSpecies] >= 0) {
304 throw CanteraError(
"HMWSoln::readXMLThetaAnion",
"anion1 charge problem");
306 size_t jSpecies = speciesIndex(jspName);
307 if (jSpecies ==
npos) {
310 if (charge[jSpecies] >= 0) {
311 throw CanteraError(
"HMWSoln::readXMLThetaAnion",
"anion2 charge problem");
314 size_t n = iSpecies * m_kk + jSpecies;
315 int counter = m_CounterIJ[n];
316 for (
size_t i = 0; i < BinSalt.
nChildren(); i++) {
318 stemp = xmlChild.
name();
320 if (nodeName ==
"theta") {
322 nParamsFound = vParams.size();
323 if (m_formPitzerTemp == PITZER_TEMP_CONSTANT) {
324 if (nParamsFound != 1) {
325 throw CanteraError(
"HMWSoln::readXMLThetaAnion::Theta for " + ispName
327 "wrong number of params found");
329 m_Theta_ij_coeff(0,counter) = vParams[0];
330 m_Theta_ij[counter] = vParams[0];
331 }
else if (m_formPitzerTemp == PITZER_TEMP_LINEAR) {
332 if (nParamsFound != 2) {
333 throw CanteraError(
"HMWSoln::readXMLThetaAnion::Theta for " + ispName
335 "wrong number of params found");
337 m_Theta_ij_coeff(0,counter) = vParams[0];
338 m_Theta_ij_coeff(1,counter) = vParams[1];
339 m_Theta_ij[counter] = vParams[0];
340 }
else if (m_formPitzerTemp == PITZER_TEMP_COMPLEX1) {
341 if (nParamsFound == 1) {
342 vParams.resize(5, 0.0);
344 }
else if (nParamsFound != 5) {
345 throw CanteraError(
"HMWSoln::readXMLThetaAnion::Theta for " + ispName
347 "wrong number of params found");
349 for (
size_t j = 0; j < nParamsFound; j++) {
350 m_Theta_ij_coeff(j, counter) = vParams[j];
352 m_Theta_ij[counter] = vParams[0];
363 void HMWSoln::readXMLThetaCation(
XML_Node& BinSalt)
365 string xname = BinSalt.
name();
367 size_t nParamsFound = 0;
368 if (xname !=
"thetaCation") {
370 "Incorrect name for processing this routine: " + xname);
372 double* charge =
DATA_PTR(m_speciesCharge);
374 string ispName = BinSalt.
attrib(
"cation1");
376 throw CanteraError(
"HMWSoln::readXMLThetaCation",
"no cation1 attrib");
378 string jspName = BinSalt.
attrib(
"cation2");
380 throw CanteraError(
"HMWSoln::readXMLThetaCation",
"no cation2 attrib");
386 size_t iSpecies = speciesIndex(ispName);
387 if (iSpecies ==
npos) {
390 if (charge[iSpecies] <= 0) {
391 throw CanteraError(
"HMWSoln::readXMLThetaCation",
"cation1 charge problem");
393 size_t jSpecies = speciesIndex(jspName);
394 if (jSpecies ==
npos) {
397 if (charge[jSpecies] <= 0) {
398 throw CanteraError(
"HMWSoln::readXMLThetaCation",
"cation2 charge problem");
401 size_t n = iSpecies * m_kk + jSpecies;
402 int counter = m_CounterIJ[n];
403 for (
size_t i = 0; i < BinSalt.
nChildren(); i++) {
405 stemp = xmlChild.
name();
407 if (nodeName ==
"theta") {
409 nParamsFound = vParams.size();
410 if (m_formPitzerTemp == PITZER_TEMP_CONSTANT) {
411 if (nParamsFound != 1) {
412 throw CanteraError(
"HMWSoln::readXMLThetaCation::Theta for " + ispName
414 "wrong number of params found");
416 m_Theta_ij_coeff(0,counter) = vParams[0];
417 m_Theta_ij[counter] = vParams[0];
418 }
else if (m_formPitzerTemp == PITZER_TEMP_LINEAR) {
419 if (nParamsFound != 2) {
420 throw CanteraError(
"HMWSoln::readXMLThetaCation::Theta for " + ispName
422 "wrong number of params found");
424 m_Theta_ij_coeff(0,counter) = vParams[0];
425 m_Theta_ij_coeff(1,counter) = vParams[1];
426 m_Theta_ij[counter] = vParams[0];
427 }
else if (m_formPitzerTemp == PITZER_TEMP_COMPLEX1) {
428 if (nParamsFound == 1) {
429 vParams.resize(5, 0.0);
431 }
else if (nParamsFound != 5) {
432 throw CanteraError(
"HMWSoln::readXMLThetaCation::Theta for " + ispName
434 "wrong number of params found");
436 for (
size_t j = 0; j < nParamsFound; j++) {
437 m_Theta_ij_coeff(j, counter) = vParams[j];
439 m_Theta_ij[counter] = vParams[0];
450 void HMWSoln::readXMLPsiCommonCation(
XML_Node& BinSalt)
452 string xname = BinSalt.
name();
453 if (xname !=
"psiCommonCation") {
455 "Incorrect name for processing this routine: " + xname);
457 double* charge =
DATA_PTR(m_speciesCharge);
460 size_t nParamsFound = 0;
461 string kName = BinSalt.
attrib(
"cation");
463 throw CanteraError(
"HMWSoln::readXMLPsiCommonCation",
"no cation attrib");
465 string iName = BinSalt.
attrib(
"anion1");
467 throw CanteraError(
"HMWSoln::readXMLPsiCommonCation",
"no anion1 attrib");
469 string jName = BinSalt.
attrib(
"anion2");
471 throw CanteraError(
"HMWSoln::readXMLPsiCommonCation",
"no anion2 attrib");
477 size_t kSpecies = speciesIndex(kName);
478 if (kSpecies ==
npos) {
481 if (charge[kSpecies] <= 0) {
483 "cation charge problem");
485 size_t iSpecies = speciesIndex(iName);
486 if (iSpecies ==
npos) {
489 if (charge[iSpecies] >= 0) {
491 "anion1 charge problem");
493 size_t jSpecies = speciesIndex(jName);
494 if (jSpecies ==
npos) {
497 if (charge[jSpecies] >= 0) {
499 "anion2 charge problem");
502 size_t n = iSpecies * m_kk + jSpecies;
503 int counter = m_CounterIJ[n];
504 for (
size_t i = 0; i < BinSalt.
nChildren(); i++) {
506 stemp = xmlChild.
name();
508 if (nodeName ==
"theta") {
509 stemp = xmlChild.
value();
510 double old = m_Theta_ij[counter];
511 m_Theta_ij[counter] =
atofCheck(stemp.c_str());
513 if (old != m_Theta_ij[counter]) {
515 "conflicting values");
519 if (nodeName ==
"psi") {
521 nParamsFound = vParams.size();
522 n = iSpecies * m_kk *m_kk + jSpecies * m_kk + kSpecies ;
524 if (m_formPitzerTemp == PITZER_TEMP_CONSTANT) {
525 if (nParamsFound != 1) {
526 throw CanteraError(
"HMWSoln::readXMLPsiCommonCation::Psi for "
527 + kName +
"::" + iName +
"::" + jName,
528 "wrong number of params found");
530 m_Psi_ijk_coeff(0,n) = vParams[0];
531 m_Psi_ijk[n] = vParams[0];
532 }
else if (m_formPitzerTemp == PITZER_TEMP_LINEAR) {
533 if (nParamsFound != 2) {
534 throw CanteraError(
"HMWSoln::readXMLPsiCation::Psi for "
535 + kName +
"::" + iName +
"::" + jName,
536 "wrong number of params found");
538 m_Psi_ijk_coeff(0,n) = vParams[0];
539 m_Psi_ijk_coeff(1,n) = vParams[1];
540 m_Psi_ijk[n] = vParams[0];
541 }
else if (m_formPitzerTemp == PITZER_TEMP_COMPLEX1) {
542 if (nParamsFound == 1) {
543 vParams.resize(5, 0.0);
545 }
else if (nParamsFound != 5) {
546 throw CanteraError(
"HMWSoln::readXMLPsiCation::Psi for "
547 + kName +
"::" + iName +
"::" + jName,
548 "wrong number of params found");
550 for (
size_t j = 0; j < nParamsFound; j++) {
551 m_Psi_ijk_coeff(j, n) = vParams[j];
553 m_Psi_ijk[n] = vParams[0];
558 n = iSpecies * m_kk *m_kk + kSpecies * m_kk + jSpecies ;
559 for (
size_t j = 0; j < nParamsFound; j++) {
560 m_Psi_ijk_coeff(j, n) = vParams[j];
562 m_Psi_ijk[n] = vParams[0];
564 n = jSpecies * m_kk *m_kk + iSpecies * m_kk + kSpecies ;
565 for (
size_t j = 0; j < nParamsFound; j++) {
566 m_Psi_ijk_coeff(j, n) = vParams[j];
568 m_Psi_ijk[n] = vParams[0];
570 n = jSpecies * m_kk *m_kk + kSpecies * m_kk + iSpecies ;
571 for (
size_t j = 0; j < nParamsFound; j++) {
572 m_Psi_ijk_coeff(j, n) = vParams[j];
574 m_Psi_ijk[n] = vParams[0];
576 n = kSpecies * m_kk *m_kk + jSpecies * m_kk + iSpecies ;
577 for (
size_t j = 0; j < nParamsFound; j++) {
578 m_Psi_ijk_coeff(j, n) = vParams[j];
580 m_Psi_ijk[n] = vParams[0];
582 n = kSpecies * m_kk *m_kk + iSpecies * m_kk + jSpecies ;
583 for (
size_t j = 0; j < nParamsFound; j++) {
584 m_Psi_ijk_coeff(j, n) = vParams[j];
586 m_Psi_ijk[n] = vParams[0];
596 void HMWSoln::readXMLPsiCommonAnion(
XML_Node& BinSalt)
598 string xname = BinSalt.
name();
599 if (xname !=
"psiCommonAnion") {
601 "Incorrect name for processing this routine: " + xname);
603 double* charge =
DATA_PTR(m_speciesCharge);
606 size_t nParamsFound = 0;
607 string kName = BinSalt.
attrib(
"anion");
609 throw CanteraError(
"HMWSoln::readXMLPsiCommonAnion",
"no anion attrib");
611 string iName = BinSalt.
attrib(
"cation1");
613 throw CanteraError(
"HMWSoln::readXMLPsiCommonAnion",
"no cation1 attrib");
615 string jName = BinSalt.
attrib(
"cation2");
617 throw CanteraError(
"HMWSoln::readXMLPsiCommonAnion",
"no cation2 attrib");
623 size_t kSpecies = speciesIndex(kName);
624 if (kSpecies ==
npos) {
627 if (charge[kSpecies] >= 0) {
628 throw CanteraError(
"HMWSoln::readXMLPsiCommonAnion",
"anion charge problem");
630 size_t iSpecies = speciesIndex(iName);
631 if (iSpecies ==
npos) {
634 if (charge[iSpecies] <= 0) {
636 "cation1 charge problem");
638 size_t jSpecies = speciesIndex(jName);
639 if (jSpecies ==
npos) {
642 if (charge[jSpecies] <= 0) {
644 "cation2 charge problem");
647 size_t n = iSpecies * m_kk + jSpecies;
648 int counter = m_CounterIJ[n];
649 for (
size_t i = 0; i < BinSalt.
nChildren(); i++) {
651 stemp = xmlChild.
name();
653 if (nodeName ==
"theta") {
654 stemp = xmlChild.
value();
655 double old = m_Theta_ij[counter];
656 m_Theta_ij[counter] =
atofCheck(stemp.c_str());
658 if (old != m_Theta_ij[counter]) {
660 "conflicting values");
664 if (nodeName ==
"psi") {
667 nParamsFound = vParams.size();
668 n = iSpecies * m_kk *m_kk + jSpecies * m_kk + kSpecies ;
670 if (m_formPitzerTemp == PITZER_TEMP_CONSTANT) {
671 if (nParamsFound != 1) {
672 throw CanteraError(
"HMWSoln::readXMLPsiCommonAnion::Psi for "
673 + kName +
"::" + iName +
"::" + jName,
674 "wrong number of params found");
676 m_Psi_ijk_coeff(0,n) = vParams[0];
677 m_Psi_ijk[n] = vParams[0];
678 }
else if (m_formPitzerTemp == PITZER_TEMP_LINEAR) {
679 if (nParamsFound != 2) {
681 + kName +
"::" + iName +
"::" + jName,
682 "wrong number of params found");
684 m_Psi_ijk_coeff(0,n) = vParams[0];
685 m_Psi_ijk_coeff(1,n) = vParams[1];
686 m_Psi_ijk[n] = vParams[0];
687 }
else if (m_formPitzerTemp == PITZER_TEMP_COMPLEX1) {
688 if (nParamsFound == 1) {
689 vParams.resize(5, 0.0);
691 }
else if (nParamsFound != 5) {
693 + kName +
"::" + iName +
"::" + jName,
694 "wrong number of params found");
696 for (
size_t j = 0; j < nParamsFound; j++) {
697 m_Psi_ijk_coeff(j, n) = vParams[j];
699 m_Psi_ijk[n] = vParams[0];
704 n = iSpecies * m_kk *m_kk + kSpecies * m_kk + jSpecies ;
705 for (
size_t j = 0; j < nParamsFound; j++) {
706 m_Psi_ijk_coeff(j, n) = vParams[j];
708 m_Psi_ijk[n] = vParams[0];
710 n = jSpecies * m_kk *m_kk + iSpecies * m_kk + kSpecies ;
711 for (
size_t j = 0; j < nParamsFound; j++) {
712 m_Psi_ijk_coeff(j, n) = vParams[j];
714 m_Psi_ijk[n] = vParams[0];
716 n = jSpecies * m_kk *m_kk + kSpecies * m_kk + iSpecies ;
717 for (
size_t j = 0; j < nParamsFound; j++) {
718 m_Psi_ijk_coeff(j, n) = vParams[j];
720 m_Psi_ijk[n] = vParams[0];
722 n = kSpecies * m_kk *m_kk + jSpecies * m_kk + iSpecies ;
723 for (
size_t j = 0; j < nParamsFound; j++) {
724 m_Psi_ijk_coeff(j, n) = vParams[j];
726 m_Psi_ijk[n] = vParams[0];
728 n = kSpecies * m_kk *m_kk + iSpecies * m_kk + jSpecies ;
729 for (
size_t j = 0; j < nParamsFound; j++) {
730 m_Psi_ijk_coeff(j, n) = vParams[j];
732 m_Psi_ijk[n] = vParams[0];
746 void HMWSoln::readXMLLambdaNeutral(
XML_Node& BinSalt)
748 string xname = BinSalt.
name();
751 if (xname !=
"lambdaNeutral") {
753 "Incorrect name for processing this routine: " + xname);
755 double* charge =
DATA_PTR(m_speciesCharge);
757 string iName = BinSalt.
attrib(
"species1");
759 throw CanteraError(
"HMWSoln::readXMLLambdaNeutral",
"no species1 attrib");
761 string jName = BinSalt.
attrib(
"species2");
763 throw CanteraError(
"HMWSoln::readXMLLambdaNeutral",
"no species2 attrib");
769 size_t iSpecies = speciesIndex(iName);
770 if (iSpecies ==
npos) {
773 if (charge[iSpecies] != 0) {
775 "neutral charge problem");
777 size_t jSpecies = speciesIndex(jName);
778 if (jSpecies ==
npos) {
782 for (
size_t i = 0; i < BinSalt.
nChildren(); i++) {
784 stemp = xmlChild.
name();
786 if (nodeName ==
"lambda") {
787 size_t nCount = iSpecies*m_kk + jSpecies;
789 nParamsFound = vParams.size();
790 if (m_formPitzerTemp == PITZER_TEMP_CONSTANT) {
791 if (nParamsFound != 1) {
792 throw CanteraError(
"HMWSoln::readXMLLambdaNeutral::Lambda for " + iName
794 "wrong number of params found");
796 m_Lambda_nj_coeff(0,nCount) = vParams[0];
797 m_Lambda_nj(iSpecies,jSpecies) = vParams[0];
799 }
else if (m_formPitzerTemp == PITZER_TEMP_LINEAR) {
800 if (nParamsFound != 2) {
801 throw CanteraError(
"HMWSoln::readXMLLambdaNeutral::Lambda for " + iName
803 "wrong number of params found");
805 m_Lambda_nj_coeff(0,nCount) = vParams[0];
806 m_Lambda_nj_coeff(1,nCount) = vParams[1];
807 m_Lambda_nj(iSpecies, jSpecies) = vParams[0];
809 }
else if (m_formPitzerTemp == PITZER_TEMP_COMPLEX1) {
810 if (nParamsFound == 1) {
811 vParams.resize(5, 0.0);
813 }
else if (nParamsFound != 5) {
814 throw CanteraError(
"HMWSoln::readXMLLambdaNeutral::Lambda for " + iName
816 "wrong number of params found");
818 for (
size_t j = 0; j < nParamsFound; j++) {
819 m_Lambda_nj_coeff(j,nCount) = vParams[j];
821 m_Lambda_nj(iSpecies, jSpecies) = vParams[0];
832 void HMWSoln::readXMLMunnnNeutral(
XML_Node& BinSalt)
834 string xname = BinSalt.
name();
837 if (xname !=
"MunnnNeutral") {
839 "Incorrect name for processing this routine: " + xname);
841 double* charge =
DATA_PTR(m_speciesCharge);
843 string iName = BinSalt.
attrib(
"species1");
845 throw CanteraError(
"HMWSoln::readXMLMunnnNeutral",
"no species1 attrib");
852 size_t iSpecies = speciesIndex(iName);
853 if (iSpecies ==
npos) {
856 if (charge[iSpecies] != 0) {
858 "neutral charge problem");
861 for (
size_t i = 0; i < BinSalt.
nChildren(); i++) {
863 stemp = xmlChild.
name();
865 if (nodeName ==
"munnn") {
867 nParamsFound = vParams.size();
868 if (m_formPitzerTemp == PITZER_TEMP_CONSTANT) {
869 if (nParamsFound != 1) {
870 throw CanteraError(
"HMWSoln::readXMLMunnnNeutral::Munnn for " + iName,
871 "wrong number of params found");
873 m_Mu_nnn_coeff(0,iSpecies) = vParams[0];
874 m_Mu_nnn[iSpecies] = vParams[0];
876 }
else if (m_formPitzerTemp == PITZER_TEMP_LINEAR) {
877 if (nParamsFound != 2) {
878 throw CanteraError(
"HMWSoln::readXMLMunnnNeutral::Munnn for " + iName,
879 "wrong number of params found");
881 m_Mu_nnn_coeff(0, iSpecies) = vParams[0];
882 m_Mu_nnn_coeff(1, iSpecies) = vParams[1];
883 m_Mu_nnn[iSpecies] = vParams[0];
885 }
else if (m_formPitzerTemp == PITZER_TEMP_COMPLEX1) {
886 if (nParamsFound == 1) {
887 vParams.resize(5, 0.0);
889 }
else if (nParamsFound != 5) {
890 throw CanteraError(
"HMWSoln::readXMLMunnnNeutral::Munnn for " + iName,
891 "wrong number of params found");
893 for (
size_t j = 0; j < nParamsFound; j++) {
894 m_Mu_nnn_coeff(j, iSpecies) = vParams[j];
896 m_Mu_nnn[iSpecies] = vParams[0];
907 void HMWSoln::readXMLZetaCation(
const XML_Node& BinSalt)
909 string xname = BinSalt.
name();
910 if (xname !=
"zetaCation") {
912 "Incorrect name for processing this routine: " + xname);
914 double* charge =
DATA_PTR(m_speciesCharge);
917 size_t nParamsFound = 0;
919 string iName = BinSalt.
attrib(
"neutral");
921 throw CanteraError(
"HMWSoln::readXMLZetaCation",
"no neutral attrib");
924 string jName = BinSalt.
attrib(
"cation1");
926 throw CanteraError(
"HMWSoln::readXMLZetaCation",
"no cation1 attrib");
929 string kName = BinSalt.
attrib(
"anion1");
931 throw CanteraError(
"HMWSoln::readXMLZetaCation",
"no anion1 attrib");
937 size_t iSpecies = speciesIndex(iName);
938 if (iSpecies ==
npos) {
941 if (charge[iSpecies] != 0.0) {
942 throw CanteraError(
"HMWSoln::readXMLZetaCation",
"neutral charge problem");
945 size_t jSpecies = speciesIndex(jName);
946 if (jSpecies ==
npos) {
949 if (charge[jSpecies] <= 0.0) {
950 throw CanteraError(
"HMWSoln::readXLZetaCation",
"cation1 charge problem");
953 size_t kSpecies = speciesIndex(kName);
954 if (kSpecies ==
npos) {
957 if (charge[kSpecies] >= 0.0) {
958 throw CanteraError(
"HMWSoln::readXMLZetaCation",
"anion1 charge problem");
961 for (
size_t i = 0; i < BinSalt.
nChildren(); i++) {
963 stemp = xmlChild.
name();
965 if (nodeName ==
"zeta") {
967 nParamsFound = vParams.size();
968 size_t n = iSpecies * m_kk *m_kk + jSpecies * m_kk + kSpecies ;
970 if (m_formPitzerTemp == PITZER_TEMP_CONSTANT) {
971 if (nParamsFound != 1) {
972 throw CanteraError(
"HMWSoln::readXMLZetaCation::Zeta for "
973 + iName +
"::" + jName +
"::" + kName,
974 "wrong number of params found");
976 m_Psi_ijk_coeff(0,n) = vParams[0];
977 m_Psi_ijk[n] = vParams[0];
978 }
else if (m_formPitzerTemp == PITZER_TEMP_LINEAR) {
979 if (nParamsFound != 2) {
980 throw CanteraError(
"HMWSoln::readXMLZetaCation::Zeta for "
981 + iName +
"::" + jName +
"::" + kName,
982 "wrong number of params found");
984 m_Psi_ijk_coeff(0,n) = vParams[0];
985 m_Psi_ijk_coeff(1,n) = vParams[1];
986 m_Psi_ijk[n] = vParams[0];
987 }
else if (m_formPitzerTemp == PITZER_TEMP_COMPLEX1) {
988 if (nParamsFound == 1) {
989 vParams.resize(5, 0.0);
991 }
else if (nParamsFound != 5) {
992 throw CanteraError(
"HMWSoln::readXMLZetaCation::Zeta for "
993 + iName +
"::" + jName +
"::" + kName,
994 "wrong number of params found");
996 for (
size_t j = 0; j < nParamsFound; j++) {
997 m_Psi_ijk_coeff(j, n) = vParams[j];
999 m_Psi_ijk[n] = vParams[0];
1012 void HMWSoln::readXMLCroppingCoefficients(
const XML_Node& acNode)
1015 if (acNode.
hasChild(
"croppingCoefficients")) {
1017 if (cropNode.
hasChild(
"ln_gamma_k_min")) {
1021 if (cropNode.
hasChild(
"ln_gamma_k_max")) {
1026 if (cropNode.
hasChild(
"ln_gamma_o_min")) {
1031 if (cropNode.
hasChild(
"ln_gamma_o_max")) {
1044 void HMWSoln::initThermo()
1046 MolalityVPSSTP::initThermo();
1064 void HMWSoln::constructPhaseFile(std::string inputFile, std::string
id)
1067 if (inputFile.size() == 0) {
1069 "input file is null");
1072 std::ifstream fin(path.c_str());
1074 throw CanteraError(
"HMWSoln:constructPhaseFile",
"could not open "
1075 +path+
" for reading.");
1087 "ERROR: Can not find phase named " +
1088 id +
" in file named " + inputFile);
1090 fxml_phase->
copy(&phaseNode_XML);
1091 constructPhaseXML(*fxml_phase,
id);
1122 void HMWSoln::constructPhaseXML(
XML_Node& phaseNode, std::string
id)
1125 if (
id.size() > 0) {
1126 string idp = phaseNode.
id();
1129 "phasenode and Id are incompatible");
1136 if (!phaseNode.
hasChild(
"thermo")) {
1138 "no thermo XML node");
1145 if (thermoNode.
hasChild(
"standardConc")) {
1148 stemp = scNode.
attrib(
"model");
1150 if (formString !=
"") {
1151 if (formString ==
"unity") {
1153 printf(
"exit standardConc = unity not done\n");
1155 }
else if (formString ==
"molar_volume") {
1157 printf(
"exit standardConc = molar_volume not done\n");
1159 }
else if (formString ==
"solvent_volume") {
1163 "Unknown standardConc model: " + formString);
1171 string solventName =
"";
1172 if (thermoNode.
hasChild(
"solvent")) {
1174 vector<string> nameSolventa;
1176 int nsp =
static_cast<int>(nameSolventa.size());
1179 "badly formed solvent XML node");
1181 solventName = nameSolventa[0];
1188 if (thermoNode.
hasChild(
"activityCoefficients")) {
1189 XML_Node& scNode = thermoNode.
child(
"activityCoefficients");
1190 stemp = scNode.
attrib(
"model");
1192 if (formString !=
"") {
1193 if (formString ==
"pitzer" || formString ==
"default") {
1195 }
else if (formString ==
"base") {
1199 "Unknown Pitzer ActivityCoeff model: "
1208 stemp = scNode.
attrib(
"TempModel");
1210 if (formString !=
"") {
1211 if (formString ==
"constant" || formString ==
"default") {
1212 m_formPitzerTemp = PITZER_TEMP_CONSTANT;
1213 }
else if (formString ==
"linear") {
1214 m_formPitzerTemp = PITZER_TEMP_LINEAR;
1215 }
else if (formString ==
"complex" || formString ==
"complex1") {
1216 m_formPitzerTemp = PITZER_TEMP_COMPLEX1;
1219 "Unknown Pitzer ActivityCoeff Temp model: "
1229 stemp = scNode.
attrib(
"TempReference");
1231 if (formString !=
"") {
1232 m_TempPitzerRef =
atofCheck(formString.c_str());
1234 m_TempPitzerRef = 273.15 + 25;
1246 throw CanteraError(
"HMWSoln::constructPhaseXML",
"importPhase failed ");
1276 if (!phaseNode.
hasChild(
"thermo")) {
1278 "no thermo XML node");
1286 string solventName =
"";
1287 if (thermoNode.
hasChild(
"solvent")) {
1289 vector<string> nameSolventa;
1291 int nsp =
static_cast<int>(nameSolventa.size());
1294 "badly formed solvent XML node");
1296 solventName = nameSolventa[0];
1308 for (
size_t k = 0; k < m_kk; k++) {
1309 string sname = speciesName(k);
1310 if (solventName == sname) {
1314 "Solvent must be species 0 atm");
1320 if (m_indexSolvent ==
npos) {
1321 std::cout <<
"HMWSoln::initThermo: Solvent Name not found"
1324 "Solvent name not found");
1326 if (m_indexSolvent != 0) {
1328 "Solvent " + solventName +
1329 " should be first species");
1341 const vector<string>&sss = speciesNames();
1343 for (
size_t k = 0; k < m_kk; k++) {
1347 "Species Data Base " + sss[k] +
" not found");
1352 "Species " + sss[k] +
1353 " standardState XML block not found");
1355 string modelStringa = ss->
attrib(
"model");
1356 if (modelStringa ==
"") {
1358 "Species " + sss[k] +
1359 " standardState XML block model attribute not found");
1361 string modelString =
lowercase(modelStringa);
1363 if (modelString ==
"wateriapws" || modelString ==
"real_water" ||
1364 modelString ==
"waterpdss") {
1369 m_waterSS =
dynamic_cast<PDSS_Water*
>(providePDSS(0)) ;
1372 "Dynamic cast to PDSS_Water failed");
1379 m_waterSS->setState_TP(300.,
OneAtm);
1380 double dens = m_waterSS->density();
1381 double mw = m_waterSS->molecularWeight();
1382 m_speciesSize[0] = mw / dens;
1383 #ifdef DEBUG_HKM_NOT
1384 cout <<
"Solvent species " << sss[k] <<
" has volume " <<
1385 m_speciesSize[k] << endl;
1391 m_waterSS = providePDSS(0);
1392 m_waterSS->setState_TP(300.,
OneAtm);
1393 double dens = m_waterSS->density();
1394 double mw = m_waterSS->molecularWeight();
1395 m_speciesSize[0] = mw / dens;
1398 if (modelString !=
"constant_incompressible" && modelString !=
"hkft") {
1400 "Solute SS Model \"" + modelStringa +
1403 if (modelString ==
"constant_incompressible") {
1404 m_speciesSize[k] =
getFloat(*ss,
"molarVolume",
"toSI");
1405 #ifdef DEBUG_HKM_NOT
1406 cout <<
"species " << sss[k] <<
" has volume " <<
1407 m_speciesSize[k] << endl;
1418 m_waterProps =
new WaterProps(dynamic_cast<PDSS_Water*>(m_waterSS));
1427 for (
size_t k = 0; k < m_kk; k++) {
1428 m_speciesCharge_Stoich[k] = m_speciesCharge[k];
1436 if (thermoNode.
hasChild(
"activityCoefficients")) {
1437 XML_Node& acNode = thermoNode.
child(
"activityCoefficients");
1438 acNodePtr = &acNode;
1444 m_form_A_Debye = A_DEBYE_CONST;
1447 string atemp = ADebye.
attrib(stemp);
1449 if (stemp ==
"water") {
1450 m_form_A_Debye = A_DEBYE_WATER;
1453 if (m_form_A_Debye == A_DEBYE_CONST) {
1454 m_A_Debye =
getFloat(acNode,
"A_Debye");
1456 #ifdef DEBUG_HKM_NOT
1457 cout <<
"A_Debye = " << m_A_Debye << endl;
1464 if (acNode.
hasChild(
"maxIonicStrength")) {
1465 m_maxIionicStrength =
getFloat(acNode,
"maxIonicStrength");
1466 #ifdef DEBUG_HKM_NOT
1467 cout <<
"m_maxIionicStrength = "
1468 <<m_maxIionicStrength << endl;
1476 if (acNode.
hasChild(
"ionicRadius")) {
1480 double Afactor = 1.0;
1482 string Aunits = irNode.
attrib(
"units");
1483 Afactor =
toSI(Aunits);
1487 string ads = irNode.
attrib(
"default");
1489 for (
size_t k = 0; k < m_kk; k++) {
1490 m_Aionic[k] = ad * Afactor;
1501 std::vector<const XML_Node*> xspecies = speciesData();
1503 string kname, jname;
1504 size_t jj = xspecies.size();
1505 for (
size_t k = 0; k < m_kk; k++) {
1507 kname = speciesName(k);
1508 for (
size_t j = 0; j < jj; j++) {
1511 if (jname == kname) {
1517 const XML_Node& sp = *xspecies[jmap];
1530 if (acNodePtr->
hasChild(
"stoichIsMods")) {
1533 map<string, string> msIs;
1535 map<string,string>::const_iterator _b = msIs.begin();
1536 for (; _b != msIs.end(); ++_b) {
1537 size_t kk = speciesIndex(_b->first);
1539 double val =
fpValue(_b->second);
1540 m_speciesCharge_Stoich[kk] = val;
1552 for (
size_t i = 0; i < acNodePtr->
nChildren(); i++) {
1554 stemp = xmlACChild.
name();
1561 if (nodeName ==
"binarysaltparameters") {
1562 readXMLBinarySalt(xmlACChild);
1563 }
else if (nodeName ==
"thetaanion") {
1564 readXMLThetaAnion(xmlACChild);
1565 }
else if (nodeName ==
"thetacation") {
1566 readXMLThetaCation(xmlACChild);
1567 }
else if (nodeName ==
"psicommonanion") {
1568 readXMLPsiCommonAnion(xmlACChild);
1569 }
else if (nodeName ==
"psicommoncation") {
1570 readXMLPsiCommonCation(xmlACChild);
1571 }
else if (nodeName ==
"lambdaneutral") {
1572 readXMLLambdaNeutral(xmlACChild);
1573 }
else if (nodeName ==
"zetacation") {
1574 readXMLZetaCation(xmlACChild);
1580 readXMLCroppingCoefficients(acNode);
1591 for (
size_t k = 0; k < m_kk; k++) {
1592 if (fabs(m_speciesCharge[k]) > 0.0001) {
1593 m_electrolyteSpeciesType[k] = cEST_chargedSpecies;
1594 if (fabs(m_speciesCharge_Stoich[k] - m_speciesCharge[k])
1596 m_electrolyteSpeciesType[k] = cEST_weakAcidAssociated;
1598 }
else if (fabs(m_speciesCharge_Stoich[k]) > 0.0001) {
1599 m_electrolyteSpeciesType[k] = cEST_weakAcidAssociated;
1601 m_electrolyteSpeciesType[k] = cEST_nonpolarNeutral;
1604 m_electrolyteSpeciesType[m_indexSolvent] =
cEST_solvent;
1610 std::vector<const XML_Node*> xspecies = speciesData();
1613 for (
size_t k = 0; k < m_kk; k++) {
1614 kname = speciesName(k);
1615 spPtr = xspecies[k];
1617 if (spPtr->
hasChild(
"electrolyteSpeciesType")) {
1618 string est =
getChildValue(*spPtr,
"electrolyteSpeciesType");
1619 if ((m_electrolyteSpeciesType[k] =
interp_est(est)) == -1) {
1621 "Bad electrolyte type: " + est);
1630 if (acNodePtr->
hasChild(
"electrolyteSpeciesType")) {
1631 XML_Node& ESTNode = acNodePtr->
child(
"electrolyteSpeciesType");
1632 map<string, string> msEST;
1634 map<string,string>::const_iterator _b = msEST.begin();
1635 for (; _b != msEST.end(); ++_b) {
1636 size_t kk = speciesIndex(_b->first);
1638 string est = _b->second;
1639 if ((m_electrolyteSpeciesType[kk] =
interp_est(est)) == -1) {
1641 "Bad electrolyte type: " + est);
1648 IMS_typeCutoff_ = 2;
1649 if (IMS_typeCutoff_ == 2) {
1650 calcIMSCutoffParams_();
1652 calcMCCutoffParams_();
1653 setMoleFSolventMin(1.0E-5);
1655 MolalityVPSSTP::initThermoXML(phaseNode,
id);
1662 bool notDone =
true;
1666 size_t kMaxC =
npos;
1668 for (
size_t k = 0; k < m_kk; k++) {
1669 sum += mf[k] * m_speciesCharge[k];
1670 if (fabs(mf[k] * m_speciesCharge[k]) > MaxC) {
1674 size_t kHp = speciesIndex(
"H+");
1675 size_t kOHm = speciesIndex(
"OH-");
1678 if (fabs(sum) > 1.0E-30) {
1680 if (mf[kHp] > sum * 1.1) {
1694 if (mf[kOHm] > -sum * 1.1) {
1707 if (kMaxC !=
npos) {
1708 if (mf[kMaxC] > (1.1 * sum / m_speciesCharge[kMaxC])) {
1709 mf[kMaxC] -= sum / m_speciesCharge[kMaxC];
1710 mf[0] += sum / m_speciesCharge[kMaxC];
1740 void HMWSoln::calcIMSCutoffParams_()
1742 IMS_afCut_ = 1.0 / (std::exp(1.0) * IMS_gamma_k_min_);
1744 bool converged =
false;
1747 for (its = 0; its < 100 && !converged; its++) {
1749 IMS_afCut_ = 1.0 / (std::exp(1.0) * IMS_gamma_k_min_) -IMS_efCut_;
1750 IMS_bfCut_ = IMS_afCut_ / IMS_cCut_ + IMS_slopefCut_ - 1.0;
1751 IMS_dfCut_ = ((- IMS_afCut_/IMS_cCut_ + IMS_bfCut_ - IMS_bfCut_*IMS_X_o_cutoff_/IMS_cCut_)
1753 (IMS_X_o_cutoff_*IMS_X_o_cutoff_/IMS_cCut_ - 2.0 * IMS_X_o_cutoff_));
1754 double tmp = IMS_afCut_ + IMS_X_o_cutoff_*(IMS_bfCut_ + IMS_dfCut_ *IMS_X_o_cutoff_);
1755 double eterm = std::exp(-IMS_X_o_cutoff_/IMS_cCut_);
1756 IMS_efCut_ = - eterm * (tmp);
1757 if (fabs(IMS_efCut_ - oldV) < 1.0E-14) {
1763 " failed to converge on the f polynomial");
1766 double f_0 = IMS_afCut_ + IMS_efCut_;
1767 double f_prime_0 = 1.0 - IMS_afCut_ / IMS_cCut_ + IMS_bfCut_;
1769 for (its = 0; its < 100 && !converged; its++) {
1771 double lng_0 = -log(IMS_gamma_o_min_) - f_prime_0 / f_0;
1772 IMS_agCut_ = exp(lng_0) - IMS_egCut_;
1773 IMS_bgCut_ = IMS_agCut_ / IMS_cCut_ + IMS_slopegCut_ - 1.0;
1774 IMS_dgCut_ = ((- IMS_agCut_/IMS_cCut_ + IMS_bgCut_ - IMS_bgCut_*IMS_X_o_cutoff_/IMS_cCut_)
1776 (IMS_X_o_cutoff_*IMS_X_o_cutoff_/IMS_cCut_ - 2.0 * IMS_X_o_cutoff_));
1777 double tmp = IMS_agCut_ + IMS_X_o_cutoff_*(IMS_bgCut_ + IMS_dgCut_ *IMS_X_o_cutoff_);
1778 double eterm = std::exp(-IMS_X_o_cutoff_/IMS_cCut_);
1779 IMS_egCut_ = - eterm * (tmp);
1780 if (fabs(IMS_egCut_ - oldV) < 1.0E-14) {
1786 " failed to converge on the g polynomial");
1791 void HMWSoln::calcMCCutoffParams_()
1794 MC_X_o_cutoff_ = 0.6;
1795 MC_slopepCut_ = 0.02;
1799 MC_apCut_ = MC_X_o_min_;
1801 bool converged =
false;
1805 for (its = 0; its < 500 && !converged; its++) {
1807 MC_apCut_ = damp *(MC_X_o_min_ - MC_epCut_) + (1-damp) * MC_apCut_;
1808 double MC_bpCutNew = MC_apCut_ / MC_cpCut_ + MC_slopepCut_ - 1.0;
1809 MC_bpCut_ = damp * MC_bpCutNew + (1-damp) * MC_bpCut_;
1810 double MC_dpCutNew = ((- MC_apCut_/MC_cpCut_ + MC_bpCut_ - MC_bpCut_ * MC_X_o_cutoff_/MC_cpCut_)
1812 (MC_X_o_cutoff_ * MC_X_o_cutoff_/MC_cpCut_ - 2.0 * MC_X_o_cutoff_));
1813 MC_dpCut_ = damp * MC_dpCutNew + (1-damp) * MC_dpCut_;
1814 double tmp = MC_apCut_ + MC_X_o_cutoff_*(MC_bpCut_ + MC_dpCut_ * MC_X_o_cutoff_);
1815 double eterm = std::exp(- MC_X_o_cutoff_ / MC_cpCut_);
1816 MC_epCut_ = - eterm * (tmp);
1817 double diff = MC_epCut_ - oldV;
1818 if (fabs(diff) < 1.0E-14) {
1824 " failed to converge on the p polynomial");