Cantera  2.1.2
PhaseCombo_Interaction.cpp
Go to the documentation of this file.
1 /**
2  * @file
3  */
4 /*
5  * Copyright (2009) Sandia Corporation. Under the terms of
6  * Contract DE-AC04-94AL85000 with Sandia Corporation, the
7  * U.S. Government retains certain rights in this software.
8  */
9 
13 
14 #include <iomanip>
15 #include <fstream>
16 
17 using namespace std;
18 
19 namespace Cantera
20 {
21 PhaseCombo_Interaction::PhaseCombo_Interaction() :
23  numBinaryInteractions_(0),
24  formMargules_(0),
25  formTempModel_(0)
26 {
27 }
28 
30  const std::string& id_) :
32  numBinaryInteractions_(0),
33  formMargules_(0),
34  formTempModel_(0)
35 {
36  initThermoFile(inputFile, id_);
37 }
38 
40  const std::string& id_) :
42  numBinaryInteractions_(0),
43  formMargules_(0),
44  formTempModel_(0)
45 {
46  importPhase(*findXMLPhase(&phaseRoot, id_), this);
47 }
48 
51 {
53 }
54 
57 {
58  if (&b == this) {
59  return *this;
60  }
61 
63 
65  m_HE_b_ij = b.m_HE_b_ij;
66  m_HE_c_ij = b.m_HE_c_ij;
67  m_HE_d_ij = b.m_HE_d_ij;
68  m_SE_b_ij = b.m_SE_b_ij;
69  m_SE_c_ij = b.m_SE_c_ij;
70  m_SE_d_ij = b.m_SE_d_ij;
81 
82  return *this;
83 }
84 
87 {
88  return new PhaseCombo_Interaction(*this);
89 }
90 
93  numBinaryInteractions_(0),
94  formMargules_(0),
95  formTempModel_(0)
96 {
97 
98 
99  initThermoFile("PhaseCombo_Interaction.xml", "");
100 
101 
103 
104  m_HE_b_ij.resize(1);
105  m_HE_c_ij.resize(1);
106  m_HE_d_ij.resize(1);
107 
108  m_SE_b_ij.resize(1);
109  m_SE_c_ij.resize(1);
110  m_SE_d_ij.resize(1);
111 
112  m_VHE_b_ij.resize(1);
113  m_VHE_c_ij.resize(1);
114  m_VHE_d_ij.resize(1);
115 
116  m_VSE_b_ij.resize(1);
117  m_VSE_c_ij.resize(1);
118  m_VSE_d_ij.resize(1);
119 
120  m_pSpecies_A_ij.resize(1);
121  m_pSpecies_B_ij.resize(1);
122 
123 
124 
125  m_HE_b_ij[0] = -17570E3;
126  m_HE_c_ij[0] = -377.0E3;
127  m_HE_d_ij[0] = 0.0;
128 
129  m_SE_b_ij[0] = -7.627E3;
130  m_SE_c_ij[0] = 4.958E3;
131  m_SE_d_ij[0] = 0.0;
132 
133 
134  size_t iLiT = speciesIndex("LiTFe1S2(S)");
135  if (iLiT == npos) {
136  throw CanteraError("PhaseCombo_Interaction test1 constructor",
137  "Unable to find LiTFe1S2(S)");
138  }
139  m_pSpecies_A_ij[0] = iLiT;
140 
141 
142  size_t iLi2 = speciesIndex("Li2Fe1S2(S)");
143  if (iLi2 == npos) {
144  throw CanteraError("PhaseCombo_Interaction test1 constructor",
145  "Unable to find Li2Fe1S2(S)");
146  }
147  m_pSpecies_B_ij[0] = iLi2;
148  throw CanteraError("", "unimplemented");
149 }
150 
151 /*
152  * -------------- Utilities -------------------------------
153  */
154 
156 {
157  return cPhaseCombo_Interaction;
158 }
159 
160 /*
161  * - Activities, Standard States, Activity Concentrations -----------
162  */
163 
165 {
166  /*
167  * Update the activity coefficients
168  */
170 
171  /*
172  * take the exp of the internally stored coefficients.
173  */
174  for (size_t k = 0; k < m_kk; k++) {
175  ac[k] = exp(lnActCoeff_Scaled_[k]);
176  }
177 }
178 
179 /*
180  * ------------ Partial Molar Properties of the Solution ------------
181  */
182 
184 {
185  getChemPotentials(mu);
186  double ve = Faraday * electricPotential();
187  for (size_t k = 0; k < m_kk; k++) {
188  mu[k] += ve*charge(k);
189  }
190 }
191 
193 {
194  doublereal xx;
195  /*
196  * First get the standard chemical potentials in
197  * molar form.
198  * -> this requires updates of standard state as a function
199  * of T and P
200  */
202  /*
203  * Update the activity coefficients
204  */
206  /*
207  *
208  */
209  doublereal RT = GasConstant * temperature();
210  for (size_t k = 0; k < m_kk; k++) {
211  xx = std::max(moleFractions_[k], SmallNumber);
212  mu[k] += RT * (log(xx) + lnActCoeff_Scaled_[k]);
213  }
214 }
215 
217 {
218  size_t kk = nSpecies();
219  double h = 0;
220  vector_fp hbar(kk);
221  getPartialMolarEnthalpies(&hbar[0]);
222  for (size_t i = 0; i < kk; i++) {
223  h += moleFractions_[i]*hbar[i];
224  }
225  return h;
226 }
227 
229 {
230  size_t kk = nSpecies();
231  double s = 0;
232  vector_fp sbar(kk);
233  getPartialMolarEntropies(&sbar[0]);
234  for (size_t i = 0; i < kk; i++) {
235  s += moleFractions_[i]*sbar[i];
236  }
237  return s;
238 }
239 
241 {
242  size_t kk = nSpecies();
243  double cp = 0;
244  vector_fp cpbar(kk);
245  getPartialMolarCp(&cpbar[0]);
246  for (size_t i = 0; i < kk; i++) {
247  cp += moleFractions_[i]*cpbar[i];
248  }
249  return cp;
250 }
251 
253 {
254  return cp_mole() - GasConstant;
255 }
256 
258 {
259  /*
260  * Get the nondimensional standard state enthalpies
261  */
262  getEnthalpy_RT(hbar);
263  /*
264  * dimensionalize it.
265  */
266  double T = temperature();
267  double RT = GasConstant * T;
268  for (size_t k = 0; k < m_kk; k++) {
269  hbar[k] *= RT;
270  }
271  /*
272  * Update the activity coefficients, This also update the
273  * internally stored molalities.
274  */
277  double RTT = RT * T;
278  for (size_t k = 0; k < m_kk; k++) {
279  hbar[k] -= RTT * dlnActCoeffdT_Scaled_[k];
280  }
281 }
282 
283 void PhaseCombo_Interaction::getPartialMolarCp(doublereal* cpbar) const
284 {
285  /*
286  * Get the nondimensional standard state entropies
287  */
288  getCp_R(cpbar);
289  double T = temperature();
290  /*
291  * Update the activity coefficients, This also update the
292  * internally stored molalities.
293  */
296 
297  for (size_t k = 0; k < m_kk; k++) {
298  cpbar[k] -= 2 * T * dlnActCoeffdT_Scaled_[k] + T * T * d2lnActCoeffdT2_Scaled_[k];
299  }
300  /*
301  * dimensionalize it.
302  */
303  for (size_t k = 0; k < m_kk; k++) {
304  cpbar[k] *= GasConstant;
305  }
306 }
307 
309 {
310  double xx;
311  /*
312  * Get the nondimensional standard state entropies
313  */
314  getEntropy_R(sbar);
315  double T = temperature();
316  /*
317  * Update the activity coefficients, This also update the
318  * internally stored molalities.
319  */
322 
323  for (size_t k = 0; k < m_kk; k++) {
324  xx = std::max(moleFractions_[k], SmallNumber);
325  sbar[k] += - lnActCoeff_Scaled_[k] - log(xx) - T * dlnActCoeffdT_Scaled_[k];
326  }
327  /*
328  * dimensionalize it.
329  */
330  for (size_t k = 0; k < m_kk; k++) {
331  sbar[k] *= GasConstant;
332  }
333 }
334 
335 void PhaseCombo_Interaction::getPartialMolarVolumes(doublereal* vbar) const
336 {
337  int delAK, delBK;
338  double XA, XB, g0, g1;
339  double T = temperature();
340 
341  /*
342  * Get the standard state values in m^3 kmol-1
343  */
344  getStandardVolumes(vbar);
345 
346  for (size_t iK = 0; iK < m_kk; iK++) {
347  delAK = 0;
348  delBK = 0;
349  for (size_t i = 0; i < numBinaryInteractions_; i++) {
350 
351  size_t iA = m_pSpecies_A_ij[i];
352  size_t iB = m_pSpecies_B_ij[i];
353 
354  if (iA==iK) {
355  delAK = 1;
356  } else if (iB==iK) {
357  delBK = 1;
358  }
359 
360  XA = moleFractions_[iA];
361  XB = moleFractions_[iB];
362 
363  g0 = (m_VHE_b_ij[i] - T * m_VSE_b_ij[i]);
364  g1 = (m_VHE_c_ij[i] - T * m_VSE_c_ij[i]);
365 
366  vbar[iK] += XA*XB*(g0+g1*XB)+((delAK-XA)*XB+XA*(delBK-XB))*(g0+g1*XB)+XA*XB*(delBK-XB)*g1;
367  }
368  }
369 }
370 
371 doublereal PhaseCombo_Interaction::err(const std::string& msg) const
372 {
373  throw CanteraError("PhaseCombo_Interaction","Base class method "
374  +msg+" called. Equation of state type: "+int2str(eosType()));
375  return 0;
376 }
377 
379 {
380  initLengths();
382 }
383 
385 {
386  m_kk = nSpecies();
388 }
389 
390 void PhaseCombo_Interaction::initThermoXML(XML_Node& phaseNode, const std::string& id)
391 {
392  string subname = "PhaseCombo_Interaction::initThermoXML";
393  string stemp;
394  if ((int) id.size() > 0) {
395  string idp = phaseNode.id();
396  if (idp != id) {
397  throw CanteraError(subname,
398  "phasenode and Id are incompatible");
399  }
400  }
401 
402  /*
403  * Check on the thermo field. Must have:
404  * <thermo model="PhaseCombo_Interaction" />
405  */
406  if (!phaseNode.hasChild("thermo")) {
407  throw CanteraError(subname,
408  "no thermo XML node");
409  }
410  XML_Node& thermoNode = phaseNode.child("thermo");
411  stemp = thermoNode.attrib("model");
412  string formString = lowercase(stemp);
413  if (formString != "phasecombo_interaction") {
414  throw CanteraError(subname,
415  "model name isn't PhaseCombo_Interaction: " + formString);
416  }
417 
418  /*
419  * Go get all of the coefficients and factors in the
420  * activityCoefficients XML block
421  */
422  XML_Node* acNodePtr = 0;
423  if (thermoNode.hasChild("activityCoefficients")) {
424  XML_Node& acNode = thermoNode.child("activityCoefficients");
425  acNodePtr = &acNode;
426  string mStringa = acNode.attrib("model");
427  string mString = lowercase(mStringa);
428  if (mString != "margules") {
429  throw CanteraError(subname.c_str(),
430  "Unknown activity coefficient model: " + mStringa);
431  }
432  size_t n = acNodePtr->nChildren();
433  for (size_t i = 0; i < n; i++) {
434  XML_Node& xmlACChild = acNodePtr->child(i);
435  stemp = xmlACChild.name();
436  string nodeName = lowercase(stemp);
437  /*
438  * Process a binary salt field, or any of the other XML fields
439  * that make up the Pitzer Database. Entries will be ignored
440  * if any of the species in the entry isn't in the solution.
441  */
442  if (nodeName == "binaryneutralspeciesparameters") {
443  readXMLBinarySpecies(xmlACChild);
444 
445  }
446  }
447  }
448 
449  /*
450  * Go down the chain
451  */
452  GibbsExcessVPSSTP::initThermoXML(phaseNode, id);
453 
454 
455 }
456 
458 {
459  int delAK, delBK;
460  doublereal XA, XB, g0 , g1;
461  doublereal xx;
462  doublereal T = temperature();
463  doublereal RT = GasConstant*T;
464  lnActCoeff_Scaled_.assign(m_kk, 0.0);
465 
466  for (size_t iK = 0; iK < m_kk; iK++) {
467  /*
468  * We never sample the end of the mole fraction domains
469  */
470  xx = std::max(moleFractions_[iK], SmallNumber);
471  /*
472  * First wipe out the ideal solution mixing term
473  */
474  lnActCoeff_Scaled_[iK] = - log(xx);
475 
476  /*
477  * Then add in the Margules interaction terms. that's it!
478  */
479  for (size_t i = 0; i < numBinaryInteractions_; i++) {
480  size_t iA = m_pSpecies_A_ij[i];
481  size_t iB = m_pSpecies_B_ij[i];
482  delAK = 0;
483  delBK = 0;
484  if (iA==iK) {
485  delAK = 1;
486  } else if (iB==iK) {
487  delBK = 1;
488  }
489  XA = moleFractions_[iA];
490  XB = moleFractions_[iB];
491  g0 = (m_HE_b_ij[i] - T * m_SE_b_ij[i]) / RT;
492  g1 = (m_HE_c_ij[i] - T * m_SE_c_ij[i]) / RT;
493  lnActCoeff_Scaled_[iK] += (delAK * XB + XA * delBK - XA * XB) * (g0 + g1 * XB) + XA * XB * (delBK - XB) * g1;
494  }
495  }
496 }
497 
499 {
500  int delAK, delBK;
501  doublereal XA, XB, g0, g1;
502  doublereal T = temperature();
503  doublereal RTT = GasConstant*T*T;
504  dlnActCoeffdT_Scaled_.assign(m_kk, 0.0);
505  d2lnActCoeffdT2_Scaled_.assign(m_kk, 0.0);
506  for (size_t iK = 0; iK < m_kk; iK++) {
507  for (size_t i = 0; i < numBinaryInteractions_; i++) {
508  size_t iA = m_pSpecies_A_ij[i];
509  size_t iB = m_pSpecies_B_ij[i];
510  delAK = 0;
511  delBK = 0;
512  if (iA==iK) {
513  delAK = 1;
514  } else if (iB==iK) {
515  delBK = 1;
516  }
517  XA = moleFractions_[iA];
518  XB = moleFractions_[iB];
519  g0 = -m_HE_b_ij[i] / RTT;
520  g1 = -m_HE_c_ij[i] / RTT;
521  double temp = (delAK * XB + XA * delBK - XA * XB) * (g0 + g1 * XB) + XA * XB * (delBK - XB) * g1;
522  dlnActCoeffdT_Scaled_[iK] += temp;
523  d2lnActCoeffdT2_Scaled_[iK] -= 2.0 * temp / T;
524  }
525  }
526 }
527 
528 void PhaseCombo_Interaction::getdlnActCoeffdT(doublereal* dlnActCoeffdT) const
529 {
531  for (size_t k = 0; k < m_kk; k++) {
532  dlnActCoeffdT[k] = dlnActCoeffdT_Scaled_[k];
533  }
534 }
535 
536 void PhaseCombo_Interaction::getd2lnActCoeffdT2(doublereal* d2lnActCoeffdT2) const
537 {
539  for (size_t k = 0; k < m_kk; k++) {
540  d2lnActCoeffdT2[k] = d2lnActCoeffdT2_Scaled_[k];
541  }
542 }
543 
544 void PhaseCombo_Interaction::getdlnActCoeffds(const doublereal dTds, const doublereal* const dXds,
545  doublereal* dlnActCoeffds) const
546 {
547  int delAK, delBK;
548  doublereal XA, XB, g0 , g1, dXA, dXB;
549  doublereal T = temperature();
550  doublereal RT = GasConstant*T;
551  doublereal xx;
552 
553  //fvo_zero_dbl_1(dlnActCoeff, m_kk);
555 
556  for (size_t iK = 0; iK < m_kk; iK++) {
557  /*
558  * We never sample the end of the mole fraction domains
559  */
560  xx = std::max(moleFractions_[iK], SmallNumber);
561  /*
562  * First wipe out the ideal solution mixing term
563  */
564  if (xx > SmallNumber) {
565  dlnActCoeffds[iK] += - 1.0 / xx;
566  }
567 
568  for (size_t i = 0; i < numBinaryInteractions_; i++) {
569  size_t iA = m_pSpecies_A_ij[i];
570  size_t iB = m_pSpecies_B_ij[i];
571 
572  delAK = 0;
573  delBK = 0;
574 
575  if (iA==iK) {
576  delAK = 1;
577  } else if (iB==iK) {
578  delBK = 1;
579  }
580 
581  XA = moleFractions_[iA];
582  XB = moleFractions_[iB];
583 
584  dXA = dXds[iA];
585  dXB = dXds[iB];
586 
587  g0 = (m_HE_b_ij[i] - T * m_SE_b_ij[i]) / RT;
588  g1 = (m_HE_c_ij[i] - T * m_SE_c_ij[i]) / RT;
589 
590  dlnActCoeffds[iK] += ((delBK-XB)*dXA + (delAK-XA)*dXB)*(g0+2*g1*XB) + (delBK-XB)*2*g1*XA*dXB
591  + dlnActCoeffdT_Scaled_[iK]*dTds;
592  }
593  }
594 }
595 
597 {
598  int delAK, delBK;
599  doublereal XA, XB, XK, g0 , g1;
600  doublereal T = temperature();
601  doublereal RT = GasConstant*T;
602  doublereal xx;
603 
604  dlnActCoeffdlnN_diag_.assign(m_kk, 0.0);
605 
606  for (size_t iK = 0; iK < m_kk; iK++) {
607 
608  XK = moleFractions_[iK];
609  /*
610  * We never sample the end of the mole fraction domains
611  */
612  xx = std::max(moleFractions_[iK], SmallNumber);
613  /*
614  * First wipe out the ideal solution mixing term
615  */
616  // lnActCoeff_Scaled_[iK] = - log(xx);
617  if (xx > SmallNumber) {
618  dlnActCoeffdlnN_diag_[iK] = - 1.0 + xx;
619  }
620 
621  for (size_t i = 0; i < numBinaryInteractions_; i++) {
622  size_t iA = m_pSpecies_A_ij[i];
623  size_t iB = m_pSpecies_B_ij[i];
624 
625  delAK = 0;
626  delBK = 0;
627 
628  if (iA==iK) {
629  delAK = 1;
630  } else if (iB==iK) {
631  delBK = 1;
632  }
633 
634  XA = moleFractions_[iA];
635  XB = moleFractions_[iB];
636 
637  g0 = (m_HE_b_ij[i] - T * m_SE_b_ij[i]) / RT;
638  g1 = (m_HE_c_ij[i] - T * m_SE_c_ij[i]) / RT;
639 
640  dlnActCoeffdlnN_diag_[iK] += 2*(delBK-XB)*(g0*(delAK-XA)+g1*(2*(delAK-XA)*XB+XA*(delBK-XB)));
641  }
643  }
644 
645 }
646 
648 {
649  doublereal delAK, delBK;
650  double XA, XB, g0, g1, XM;
651  double xx , delKM;
652  double T = temperature();
653  double RT = GasConstant*T;
654 
655  doublereal delAM, delBM;
656 
658 
659  /*
660  * Loop over the activity coefficient gamma_k
661  */
662  for (size_t iK = 0; iK < m_kk; iK++) {
663  /*
664  * We never sample the end of the mole fraction domains
665  */
666  xx = std::max(moleFractions_[iK], SmallNumber);
667 
668  for (size_t iM = 0; iM < m_kk; iM++) {
669  XM = moleFractions_[iM];
670 
671  if (xx > SmallNumber) {
672  delKM = 0.0;
673  if (iK == iM) {
674  delKM = 1.0;
675  }
676  // this gets multiplied by XM at the bottom
677  dlnActCoeffdlnN_(iK,iM) += - delKM/XM + 1.0;
678  }
679 
680  for (size_t i = 0; i < numBinaryInteractions_; i++) {
681  size_t iA = m_pSpecies_A_ij[i];
682  size_t iB = m_pSpecies_B_ij[i];
683 
684  delAK = 0.0;
685  delBK = 0.0;
686  delAM = 0.0;
687  delBM = 0.0;
688  if (iA==iK) {
689  delAK = 1.0;
690  } else if (iB==iK) {
691  delBK = 1.0;
692  }
693  if (iA==iM) {
694  delAM = 1.0;
695  } else if (iB==iM) {
696  delBM = 1.0;
697  }
698 
699  XA = moleFractions_[iA];
700  XB = moleFractions_[iB];
701 
702  g0 = (m_HE_b_ij[i] - T * m_SE_b_ij[i]) / RT;
703  g1 = (m_HE_c_ij[i] - T * m_SE_c_ij[i]) / RT;
704 
705  dlnActCoeffdlnN_(iK,iM) += g0*((delAM-XA)*(delBK-XB)+(delAK-XA)*(delBM-XB));
706  dlnActCoeffdlnN_(iK,iM) += 2*g1*((delAM-XA)*(delBK-XB)*XB+(delAK-XA)*(delBM-XB)*XB+(delBM-XB)*(delBK-XB)*XA);
707 
708  }
709  dlnActCoeffdlnN_(iK,iM) = XM * dlnActCoeffdlnN_(iK,iM);
710  }
711  }
712 }
713 
715 {
716  doublereal XA, XB, g0 , g1;
717  doublereal T = temperature();
718 
719  dlnActCoeffdlnX_diag_.assign(m_kk, 0.0);
720  doublereal RT = GasConstant * T;
721 
722  for (size_t i = 0; i < numBinaryInteractions_; i++) {
723  size_t iA = m_pSpecies_A_ij[i];
724  size_t iB = m_pSpecies_B_ij[i];
725 
726  XA = moleFractions_[iA];
727  XB = moleFractions_[iB];
728 
729  g0 = (m_HE_b_ij[i] - T * m_SE_b_ij[i]) / RT;
730  g1 = (m_HE_c_ij[i] - T * m_SE_c_ij[i]) / RT;
731 
732  dlnActCoeffdlnX_diag_[iA] += XA*XB*(2*g1*-2*g0-6*g1*XB);
733  dlnActCoeffdlnX_diag_[iB] += XA*XB*(2*g1*-2*g0-6*g1*XB);
734  }
735  throw CanteraError("", "unimplemented");
736 }
737 
738 void PhaseCombo_Interaction::getdlnActCoeffdlnN_diag(doublereal* dlnActCoeffdlnN_diag) const
739 {
741  for (size_t k = 0; k < m_kk; k++) {
742  dlnActCoeffdlnN_diag[k] = dlnActCoeffdlnN_diag_[k];
743  }
744 }
745 
746 void PhaseCombo_Interaction::getdlnActCoeffdlnX_diag(doublereal* dlnActCoeffdlnX_diag) const
747 {
749  for (size_t k = 0; k < m_kk; k++) {
750  dlnActCoeffdlnX_diag[k] = dlnActCoeffdlnX_diag_[k];
751  }
752 }
753 
754 void PhaseCombo_Interaction::getdlnActCoeffdlnN(const size_t ld, doublereal* dlnActCoeffdlnN)
755 {
757  double* data = & dlnActCoeffdlnN_(0,0);
758  for (size_t k = 0; k < m_kk; k++) {
759  for (size_t m = 0; m < m_kk; m++) {
760  dlnActCoeffdlnN[ld * k + m] = data[m_kk * k + m];
761  }
762  }
763 }
764 
766 {
768  m_HE_b_ij.resize(num, 0.0);
769  m_HE_c_ij.resize(num, 0.0);
770  m_HE_d_ij.resize(num, 0.0);
771  m_SE_b_ij.resize(num, 0.0);
772  m_SE_c_ij.resize(num, 0.0);
773  m_SE_d_ij.resize(num, 0.0);
774  m_VHE_b_ij.resize(num, 0.0);
775  m_VHE_c_ij.resize(num, 0.0);
776  m_VHE_d_ij.resize(num, 0.0);
777  m_VSE_b_ij.resize(num, 0.0);
778  m_VSE_c_ij.resize(num, 0.0);
779  m_VSE_d_ij.resize(num, 0.0);
780 
781  m_pSpecies_A_ij.resize(num, npos);
782  m_pSpecies_B_ij.resize(num, npos);
783 }
784 
786 {
787  string xname = xmLBinarySpecies.name();
788  if (xname != "binaryNeutralSpeciesParameters") {
789  throw CanteraError("PhaseCombo_Interaction::readXMLBinarySpecies",
790  "Incorrect name for processing this routine: " + xname);
791  }
792  string stemp;
793  size_t nParamsFound;
794  vector_fp vParams;
795  string iName = xmLBinarySpecies.attrib("speciesA");
796  if (iName == "") {
797  throw CanteraError("PhaseCombo_Interaction::readXMLBinarySpecies", "no speciesA attrib");
798  }
799  string jName = xmLBinarySpecies.attrib("speciesB");
800  if (jName == "") {
801  throw CanteraError("PhaseCombo_Interaction::readXMLBinarySpecies", "no speciesB attrib");
802  }
803  /*
804  * Find the index of the species in the current phase. It's not
805  * an error to not find the species
806  */
807  size_t iSpecies = speciesIndex(iName);
808  if (iSpecies == npos) {
809  return;
810  }
811  string ispName = speciesName(iSpecies);
812  if (charge(iSpecies) != 0) {
813  throw CanteraError("PhaseCombo_Interaction::readXMLBinarySpecies", "speciesA charge problem");
814  }
815  size_t jSpecies = speciesIndex(jName);
816  if (jSpecies == npos) {
817  return;
818  }
819  string jspName = speciesName(jSpecies);
820  if (charge(jSpecies) != 0) {
821  throw CanteraError("PhaseCombo_Interaction::readXMLBinarySpecies", "speciesB charge problem");
822  }
823 
825  size_t iSpot = numBinaryInteractions_ - 1;
826  m_pSpecies_A_ij[iSpot] = iSpecies;
827  m_pSpecies_B_ij[iSpot] = jSpecies;
828 
829  size_t num = xmLBinarySpecies.nChildren();
830  for (size_t iChild = 0; iChild < num; iChild++) {
831  XML_Node& xmlChild = xmLBinarySpecies.child(iChild);
832  stemp = xmlChild.name();
833  string nodeName = lowercase(stemp);
834  /*
835  * Process the binary species interaction child elements
836  */
837  if (nodeName == "excessenthalpy") {
838  /*
839  * Get the string containing all of the values
840  */
841  ctml::getFloatArray(xmlChild, vParams, true, "toSI", "excessEnthalpy");
842  nParamsFound = vParams.size();
843 
844  if (nParamsFound != 2) {
845  throw CanteraError("PhaseCombo_Interaction::readXMLBinarySpecies::excessEnthalpy for " + ispName
846  + "::" + jspName,
847  "wrong number of params found");
848  }
849  m_HE_b_ij[iSpot] = vParams[0];
850  m_HE_c_ij[iSpot] = vParams[1];
851  }
852 
853  if (nodeName == "excessentropy") {
854  /*
855  * Get the string containing all of the values
856  */
857  ctml::getFloatArray(xmlChild, vParams, true, "toSI", "excessEntropy");
858  nParamsFound = vParams.size();
859 
860  if (nParamsFound != 2) {
861  throw CanteraError("PhaseCombo_Interaction::readXMLBinarySpecies::excessEntropy for " + ispName
862  + "::" + jspName,
863  "wrong number of params found");
864  }
865  m_SE_b_ij[iSpot] = vParams[0];
866  m_SE_c_ij[iSpot] = vParams[1];
867  }
868 
869  if (nodeName == "excessvolume_enthalpy") {
870  /*
871  * Get the string containing all of the values
872  */
873  ctml::getFloatArray(xmlChild, vParams, true, "toSI", "excessVolume_Enthalpy");
874  nParamsFound = vParams.size();
875 
876  if (nParamsFound != 2) {
877  throw CanteraError("PhaseCombo_Interaction::readXMLBinarySpecies::excessVolume_Enthalpy for " + ispName
878  + "::" + jspName,
879  "wrong number of params found");
880  }
881  m_VHE_b_ij[iSpot] = vParams[0];
882  m_VHE_c_ij[iSpot] = vParams[1];
883  }
884 
885  if (nodeName == "excessvolume_entropy") {
886  /*
887  * Get the string containing all of the values
888  */
889  ctml::getFloatArray(xmlChild, vParams, true, "toSI", "excessVolume_Entropy");
890  nParamsFound = vParams.size();
891 
892  if (nParamsFound != 2) {
893  throw CanteraError("PhaseCombo_Interaction::readXMLBinarySpecies::excessVolume_Entropy for " + ispName
894  + "::" + jspName,
895  "wrong number of params found");
896  }
897  m_VSE_b_ij[iSpot] = vParams[0];
898  m_VSE_c_ij[iSpot] = vParams[1];
899  }
900  }
901 }
902 
903 }
vector_fp m_VSE_b_ij
Entropy term for the binary mole fraction interaction of the excess gibbs free energy expression...
std::string int2str(const int n, const std::string &fmt)
Convert an int to a string using a format converter.
Definition: stringUtils.cpp:40
doublereal err(const std::string &msg) const
Error function.
PhaseCombo_Interaction & operator=(const PhaseCombo_Interaction &b)
Assignment operator.
doublereal electricPotential() const
Returns the electric potential of this phase (V).
Definition: ThermoPhase.h:391
virtual void getPartialMolarCp(doublereal *cpbar) const
Returns an array of partial molar entropies for the species in the mixture.
int formTempModel_
form of the temperature dependence of the Margules interaction expression
XML_Node * findXMLPhase(XML_Node *root, const std::string &idtarget)
Search an XML_Node tree for a named phase XML_Node.
Definition: xml.cpp:1104
virtual void getdlnActCoeffdT(doublereal *dlnActCoeffdT) const
Get the array of temperature derivatives of the log activity coefficients.
std::string attrib(const std::string &attr) const
Function returns the value of an attribute.
Definition: xml.cpp:534
vector_fp m_VHE_c_ij
Enthalpy term for the ternary mole fraction interaction of the excess gibbs free energy expression...
GibbsExcessVPSSTP & operator=(const GibbsExcessVPSSTP &b)
Assignment operator.
void resize(size_t n, size_t m, doublereal v=0.0)
Resize the array, and fill the new entries with 'v'.
Definition: Array.h:128
virtual void getdlnActCoeffdlnN(const size_t ld, doublereal *const dlnActCoeffdlnN)
Get the array of derivatives of the log activity coefficients with respect to the ln species mole num...
Header for intermediate ThermoPhase object for phases which employ the Margules gibbs free energy for...
virtual void getStandardVolumes(doublereal *vol) const
Get the molar volumes of each species in their standard states at the current T and P of the solution...
const size_t npos
index returned by functions to indicate "no position"
Definition: ct_defs.h:173
void initLengths()
Initialize lengths of local variables after all species have been identified.
void s_update_dlnActCoeff_dT() const
Update the derivative of the log of the activity coefficients wrt T.
virtual void getCp_R(doublereal *cpr) const
Get the nondimensional Heat Capacities at constant pressure for the standard state of the species at ...
Headers for the factory class that can create known ThermoPhase objects (see Thermodynamic Properties...
virtual doublereal cv_mole() const
Molar heat capacity at constant volume. Units: J/kmol/K.
virtual void getdlnActCoeffds(const doublereal dTds, const doublereal *const dXds, doublereal *dlnActCoeffds) const
Get the change in activity coefficients w.r.t.
virtual void getActivityCoefficients(doublereal *ac) const
Get the array of non-dimensional molar-based activity coefficients at the current solution temperatur...
Class XML_Node is a tree-based representation of the contents of an XML file.
Definition: xml.h:100
doublereal size(size_t k) const
This routine returns the size of species k.
Definition: Phase.h:398
vector_fp m_HE_d_ij
Enthalpy term for the quaternary mole fraction interaction of the excess gibbs free energy expression...
void initThermoXML(XML_Node &phaseNode, const std::string &id)
Import and initialize a ThermoPhase object.
int formMargules_
form of the Margules interaction expression
virtual void getdlnActCoeffdlnX_diag(doublereal *dlnActCoeffdlnX_diag) const
Get the array of log concentration-like derivatives of the log activity coefficients - diagonal compo...
std::string lowercase(const std::string &s)
Cast a copy of a string to lower case.
Definition: stringUtils.cpp:58
std::vector< doublereal > d2lnActCoeffdT2_Scaled_
Storage for the current derivative values of the gradients with respect to temperature of the log of ...
void resizeNumInteractions(const size_t num)
Resize internal arrays within the object that depend upon the number of binary Margules interaction t...
std::vector< doublereal > dlnActCoeffdlnN_diag_
Storage for the current derivative values of the gradients with respect to logarithm of the mole frac...
void s_update_dlnActCoeff_dlnN() const
Update the derivative of the log of the activity coefficients wrt log(moles_m)
XML_Node & child(const size_t n) const
Return a changeable reference to the n'th child of the current node.
Definition: xml.cpp:584
std::vector< size_t > m_pSpecies_A_ij
vector of species indices representing species A in the interaction
Base class for a phase with thermodynamic properties.
Definition: ThermoPhase.h:101
virtual ThermoPhase * duplMyselfAsThermoPhase() const
Duplication routine for objects which inherit from ThermoPhase.
void readXMLBinarySpecies(XML_Node &xmlBinarySpecies)
Process an XML node called "binaryNeutralSpeciesParameters".
size_t speciesIndex(const std::string &name) const
Returns the index of a species named 'name' within the Phase object.
Definition: Phase.cpp:229
bool importPhase(XML_Node &phase, ThermoPhase *th, SpeciesThermoFactory *spfactory)
Import a phase information into an empty thermophase object.
virtual void getChemPotentials(doublereal *mu) const
Get the species chemical potentials. Units: J/kmol.
vector_fp m_VSE_d_ij
Entropy term for the quaternary mole fraction interaction of the excess gibbs free energy expression...
void getElectrochemPotentials(doublereal *mu) const
Get the species electrochemical potentials.
vector_fp m_VHE_d_ij
Enthalpy term for the quaternary mole fraction interaction of the excess gibbs free energy expression...
void s_update_dlnActCoeff_dlnX_diag() const
Update the derivative of the log of the activity coefficients wrt log(mole fraction) ...
std::string name() const
Returns the name of the XML node.
Definition: xml.h:390
virtual doublereal cp_mole() const
Molar heat capacity at constant pressure. Units: J/kmol/K.
virtual void getPartialMolarEnthalpies(doublereal *hbar) const
Returns an array of partial molar enthalpies for the species in the mixture.
vector_fp m_HE_b_ij
Enthalpy term for the binary mole fraction interaction of the excess gibbs free energy expression...
Base class for exceptions thrown by Cantera classes.
Definition: ctexceptions.h:68
std::vector< size_t > m_pSpecies_B_ij
vector of species indices representing species B in the interaction
vector_fp m_VSE_c_ij
Entropy term for the ternary mole fraction interaction of the excess gibbs free energy expression...
size_t numBinaryInteractions_
number of binary interaction expressions
vector_fp m_SE_c_ij
Entropy term for the ternary mole fraction interaction of the excess gibbs free energy expression...
void s_update_lnActCoeff() const
Update the activity coefficients.
bool hasChild(const std::string &ch) const
Tests whether the current node has a child node with a particular name.
Definition: xml.cpp:574
size_t nSpecies() const
Returns the number of species in the phase.
Definition: Phase.h:252
std::vector< doublereal > dlnActCoeffdlnX_diag_
Storage for the current derivative values of the gradients with respect to logarithm of the mole frac...
virtual void getEntropy_R(doublereal *sr) const
Get the array of nondimensional Enthalpy functions for the standard state species at the current T an...
doublereal temperature() const
Temperature (K).
Definition: Phase.h:528
std::string id() const
Return the id attribute, if present.
Definition: xml.cpp:467
const doublereal SmallNumber
smallest number to compare to zero.
Definition: ct_defs.h:139
std::vector< doublereal > lnActCoeff_Scaled_
Storage for the current values of the activity coefficients of the species.
std::vector< double > vector_fp
Turn on the use of stl vectors for the basic array type within cantera Vector of doubles.
Definition: ct_defs.h:165
virtual void getdlnActCoeffdlnN_diag(doublereal *dlnActCoeffdlnN_diag) const
Get the array of derivatives of the log activity coefficients wrt mole numbers - diagonal only...
std::vector< doublereal > moleFractions_
Storage for the current values of the mole fractions of the species.
PhaseCombo_Interaction is a derived class of GibbsExcessVPSSTP that employs the Margules approximatio...
virtual void getEnthalpy_RT(doublereal *hrt) const
Get the nondimensional Enthalpy functions for the species at their standard states at the current T a...
const doublereal GasConstant
Universal Gas Constant. [J/kmol/K].
Definition: ct_defs.h:66
virtual void initThermoXML(XML_Node &phaseNode, const std::string &id)
Initialize a ThermoPhase object, potentially reading activity coefficient information from an XML dat...
Contains declarations for string manipulation functions within Cantera.
vector_fp m_SE_d_ij
Entropy term for the quaternary mole fraction interaction of the excess gibbs free energy expression...
virtual doublereal entropy_mole() const
Molar entropy. Units: J/kmol.
virtual int eosType() const
Equation of state type flag.
vector_fp m_SE_b_ij
Entropy term for the binary mole fraction interaction of the excess gibbs free energy expression...
size_t m_kk
Number of species in the phase.
Definition: Phase.h:716
Array2D dlnActCoeffdlnN_
Storage for the current derivative values of the gradients with respect to logarithm of the species m...
void zero()
Set all of the entries to zero.
Definition: Array.h:256
virtual void initThermoFile(const std::string &inputFile, const std::string &id)
virtual void getStandardChemPotentials(doublereal *mu) const
Get the array of chemical potentials at unit activity.
vector_fp m_HE_c_ij
Enthalpy term for the ternary mole fraction interaction of the excess gibbs free energy expression...
vector_fp m_VHE_b_ij
Enthalpy term for the binary mole fraction interaction of the excess gibbs free energy expression...
virtual void getd2lnActCoeffdT2(doublereal *d2lnActCoeffdT2) const
Get the array of temperature second derivatives of the log activity coefficients. ...
void s_update_dlnActCoeff_dlnN_diag() const
Update the derivative of the log of the activity coefficients wrt log(moles) - diagonal only...
std::string speciesName(size_t k) const
Name of the species with index k.
Definition: Phase.cpp:246
size_t getFloatArray(const Cantera::XML_Node &node, std::vector< doublereal > &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...
Definition: ctml.cpp:419
size_t nChildren(bool discardComments=false) const
Return the number of children.
Definition: xml.cpp:594
std::vector< doublereal > dlnActCoeffdT_Scaled_
Storage for the current derivative values of the gradients with respect to temperature of the log of ...
virtual void getPartialMolarEntropies(doublereal *sbar) const
Returns an array of partial molar entropies for the species in the mixture.
doublereal charge(size_t k) const
Dimensionless electrical charge of a single molecule of species k The charge is normalized by the the...
Definition: Phase.h:504
virtual doublereal enthalpy_mole() const
Molar enthalpy. Units: J/kmol.