Cantera  2.1.2
RedlichKisterVPSSTP.cpp
Go to the documentation of this file.
1 /**
2  * @file RedlichKisterVPSSTP.cpp
3  * Definitions for ThermoPhase object for phases which
4  * employ excess gibbs free energy formulations related to RedlichKister
5  * expansions (see \ref thermoprops
6  * and class \link Cantera::RedlichKisterVPSSTP RedlichKisterVPSSTP\endlink).
7  *
8  */
9 /*
10  * Copyright (2009) Sandia Corporation. Under the terms of
11  * Contract DE-AC04-94AL85000 with Sandia Corporation, the
12  * U.S. Government retains certain rights in this software.
13  */
14 
18 
19 #include <iomanip>
20 #include <fstream>
21 
22 using namespace std;
23 
24 namespace Cantera
25 {
26 RedlichKisterVPSSTP::RedlichKisterVPSSTP() :
28  numBinaryInteractions_(0),
29  m_pSpecies_A_ij(0),
30  m_pSpecies_B_ij(0),
31  m_N_ij(0),
32  m_HE_m_ij(0),
33  m_SE_m_ij(0),
34  formRedlichKister_(0),
35  formTempModel_(0),
36  dlnActCoeff_dX_()
37 {
38 }
39 
40 RedlichKisterVPSSTP::RedlichKisterVPSSTP(const std::string& inputFile,
41  const std::string& id_) :
43  numBinaryInteractions_(0),
44  m_pSpecies_A_ij(0),
45  m_pSpecies_B_ij(0),
46  m_N_ij(0),
47  m_HE_m_ij(0),
48  m_SE_m_ij(0),
49  formRedlichKister_(0),
50  formTempModel_(0),
51  dlnActCoeff_dX_()
52 {
53  initThermoFile(inputFile, id_);
54 }
55 
57  const std::string& id_) :
59  numBinaryInteractions_(0),
60  m_pSpecies_A_ij(0),
61  m_pSpecies_B_ij(0),
62  m_N_ij(0),
63  m_HE_m_ij(0),
64  m_SE_m_ij(0),
65  formRedlichKister_(0),
66  formTempModel_(0),
67  dlnActCoeff_dX_()
68 {
69  importPhase(*findXMLPhase(&phaseRoot, id_), this);
70 }
71 
74  numBinaryInteractions_(0),
75  m_pSpecies_A_ij(0),
76  m_pSpecies_B_ij(0),
77  m_N_ij(0),
78  m_HE_m_ij(0),
79  m_SE_m_ij(0),
80  formRedlichKister_(0),
81  formTempModel_(0),
82  dlnActCoeff_dX_()
83 {
84  initThermoFile("LiKCl_liquid.xml", "");
86 
87  m_HE_m_ij.resize(0);
88  m_SE_m_ij.resize(0);
89 
90  vector_fp he(2);
91  he[0] = 0.0;
92  he[1] = 0.0;
93  vector_fp se(2);
94  se[0] = 0.0;
95  se[1] = 0.0;
96 
97  m_HE_m_ij.push_back(he);
98  m_SE_m_ij.push_back(se);
99  m_N_ij.push_back(1);
100  m_pSpecies_A_ij.resize(1);
101  m_pSpecies_B_ij.resize(1);
102 
103  size_t iLiLi = speciesIndex("LiLi");
104  if (iLiLi == npos) {
105  throw CanteraError("RedlichKisterVPSSTP test1 constructor",
106  "Unable to find LiLi");
107  }
108  m_pSpecies_A_ij[0] = iLiLi;
109 
110 
111  size_t iVLi = speciesIndex("VLi");
112  if (iVLi == npos) {
113  throw CanteraError("RedlichKisterVPSSTP test1 constructor",
114  "Unable to find VLi");
115  }
116  m_pSpecies_B_ij[0] = iVLi;
117 }
118 
121  numBinaryInteractions_(0),
122  m_pSpecies_A_ij(0),
123  m_pSpecies_B_ij(0),
124  m_N_ij(0),
125  m_HE_m_ij(0),
126  m_SE_m_ij(0),
127  formRedlichKister_(0),
128  formTempModel_(0),
129  dlnActCoeff_dX_()
130 {
132 }
133 
136 {
137  if (&b == this) {
138  return *this;
139  }
140 
142 
146  m_N_ij = b.m_N_ij;
147  m_HE_m_ij = b.m_HE_m_ij;
148  m_SE_m_ij = b.m_SE_m_ij;
152 
153  return *this;
154 }
155 
158 {
159  return new RedlichKisterVPSSTP(*this);
160 }
161 
163 {
164  return 0;
165 }
166 
167 /*
168  * - Activities, Standard States, Activity Concentrations -----------
169  */
170 
172 {
173  /*
174  * Update the activity coefficients
175  */
177 
178  /*
179  * take the exp of the internally stored coefficients.
180  */
181  for (size_t k = 0; k < m_kk; k++) {
182  lnac[k] = lnActCoeff_Scaled_[k];
183  }
184 }
185 
186 /*
187  * ------------ Partial Molar Properties of the Solution ------------
188  */
189 
191 {
192  getChemPotentials(mu);
193  double ve = Faraday * electricPotential();
194  for (size_t k = 0; k < m_kk; k++) {
195  mu[k] += ve*charge(k);
196  }
197 }
198 
199 void RedlichKisterVPSSTP::getChemPotentials(doublereal* mu) const
200 {
201  doublereal xx;
202  /*
203  * First get the standard chemical potentials in
204  * molar form.
205  * -> this requires updates of standard state as a function
206  * of T and P
207  */
209  /*
210  * Update the activity coefficients
211  */
213  /*
214  *
215  */
216  doublereal RT = GasConstant * temperature();
217  for (size_t k = 0; k < m_kk; k++) {
218  xx = std::max(moleFractions_[k], SmallNumber);
219  mu[k] += RT * (log(xx) + lnActCoeff_Scaled_[k]);
220  }
221 }
222 
224 {
225  size_t kk = nSpecies();
226  double h = 0;
227  vector_fp hbar(kk);
228  getPartialMolarEnthalpies(&hbar[0]);
229  for (size_t i = 0; i < kk; i++) {
230  h += moleFractions_[i]*hbar[i];
231  }
232  return h;
233 }
234 
236 {
237  size_t kk = nSpecies();
238  double s = 0;
239  vector_fp sbar(kk);
240  getPartialMolarEntropies(&sbar[0]);
241  for (size_t i = 0; i < kk; i++) {
242  s += moleFractions_[i]*sbar[i];
243  }
244  return s;
245 }
246 
248 {
249  size_t kk = nSpecies();
250  double cp = 0;
251  vector_fp cpbar(kk);
252  getPartialMolarCp(&cpbar[0]);
253  for (size_t i = 0; i < kk; i++) {
254  cp += moleFractions_[i]*cpbar[i];
255  }
256  return cp;
257 }
258 
260 {
261  return cp_mole() - GasConstant;
262 }
263 
265 {
266  /*
267  * Get the nondimensional standard state enthalpies
268  */
269  getEnthalpy_RT(hbar);
270  /*
271  * dimensionalize it.
272  */
273  double T = temperature();
274  double RT = GasConstant * T;
275  for (size_t k = 0; k < m_kk; k++) {
276  hbar[k] *= RT;
277  }
278  /*
279  * Update the activity coefficients, This also update the
280  * internally stored molalities.
281  */
284  double RTT = RT * T;
285  for (size_t k = 0; k < m_kk; k++) {
286  hbar[k] -= RTT * dlnActCoeffdT_Scaled_[k];
287  }
288 }
289 
290 void RedlichKisterVPSSTP::getPartialMolarCp(doublereal* cpbar) const
291 {
292  /*
293  * Get the nondimensional standard state entropies
294  */
295  getCp_R(cpbar);
296  double T = temperature();
297  /*
298  * Update the activity coefficients, This also update the
299  * internally stored molalities.
300  */
303 
304  for (size_t k = 0; k < m_kk; k++) {
305  cpbar[k] -= 2 * T * dlnActCoeffdT_Scaled_[k] + T * T * d2lnActCoeffdT2_Scaled_[k];
306  }
307  /*
308  * dimensionalize it.
309  */
310  for (size_t k = 0; k < m_kk; k++) {
311  cpbar[k] *= GasConstant;
312  }
313 }
314 
316 {
317  double xx;
318  /*
319  * Get the nondimensional standard state entropies
320  */
321  getEntropy_R(sbar);
322  double T = temperature();
323  /*
324  * Update the activity coefficients, This also update the
325  * internally stored molalities.
326  */
329 
330  for (size_t k = 0; k < m_kk; k++) {
331  xx = std::max(moleFractions_[k], SmallNumber);
332  sbar[k] += - lnActCoeff_Scaled_[k] -log(xx) - T * dlnActCoeffdT_Scaled_[k];
333  }
334  /*
335  * dimensionalize it.
336  */
337  for (size_t k = 0; k < m_kk; k++) {
338  sbar[k] *= GasConstant;
339  }
340 }
341 
342 void RedlichKisterVPSSTP::getPartialMolarVolumes(doublereal* vbar) const
343 {
344  /*
345  * Get the standard state values in m^3 kmol-1
346  */
347  getStandardVolumes(vbar);
348  for (size_t iK = 0; iK < m_kk; iK++) {
349 
350  vbar[iK] += 0.0;
351  }
352 }
353 
354 doublereal RedlichKisterVPSSTP::err(const std::string& msg) const
355 {
356  throw CanteraError("RedlichKisterVPSSTP","Base class method "
357  +msg+" called. Equation of state type: "+int2str(eosType()));
358  return 0;
359 }
360 
362 {
363  initLengths();
365 }
366 
368 {
369  m_kk = nSpecies();
371 }
372 
373 void RedlichKisterVPSSTP::initThermoXML(XML_Node& phaseNode, const std::string& id_)
374 {
375  std::string subname = "RedlichKisterVPSSTP::initThermoXML";
376  std::string stemp;
377  if ((int) id_.size() > 0) {
378  string idp = phaseNode.id();
379  if (idp != id_) {
380  throw CanteraError(subname,
381  "phasenode and Id are incompatible");
382  }
383  }
384 
385  /*
386  * Check on the thermo field. Must have:
387  * <thermo model="Redlich-Kister" />
388  */
389  if (!phaseNode.hasChild("thermo")) {
390  throw CanteraError(subname, "no thermo XML node");
391  }
392  XML_Node& thermoNode = phaseNode.child("thermo");
393  std::string mStringa = thermoNode.attrib("model");
394  std::string mString = lowercase(mStringa);
395  if (mString != "redlich-kister") {
396  throw CanteraError(subname.c_str(),
397  "Unknown thermo model: " + mStringa + " - This object only knows \"Redlich-Kister\" ");
398  }
399 
400  /*
401  * Go get all of the coefficients and factors in the
402  * activityCoefficients XML block
403  */
404  XML_Node* acNodePtr = 0;
405  if (thermoNode.hasChild("activityCoefficients")) {
406  XML_Node& acNode = thermoNode.child("activityCoefficients");
407  acNodePtr = &acNode;
408  mStringa = acNode.attrib("model");
409  mString = lowercase(mStringa);
410  if (mString != "redlich-kister") {
411  throw CanteraError(subname.c_str(),
412  "Unknown activity coefficient model: " + mStringa);
413  }
414  size_t n = acNodePtr->nChildren();
415  for (size_t i = 0; i < n; i++) {
416  XML_Node& xmlACChild = acNodePtr->child(i);
417  stemp = xmlACChild.name();
418  std::string nodeName = lowercase(stemp);
419  /*
420  * Process a binary salt field, or any of the other XML fields
421  * that make up the Pitzer Database. Entries will be ignored
422  * if any of the species in the entry isn't in the solution.
423  */
424  if (nodeName == "binaryneutralspeciesparameters") {
425  readXMLBinarySpecies(xmlACChild);
426  }
427  }
428  }
429  /*
430  * Go down the chain
431  */
432  GibbsExcessVPSSTP::initThermoXML(phaseNode, id_);
433 }
434 
436 {
437  doublereal XA, XB;
438  doublereal T = temperature();
439  doublereal RT = GasConstant * T;
440 
441  lnActCoeff_Scaled_.assign(m_kk, 0.0);
442 
443  /*
444  * Scaling: I moved the division of RT higher so that we are always dealing with G/RT dimensionless terms
445  * within the routine. There is a severe problem with roundoff error in these calculations. The
446  * dimensionless terms help.
447  */
448 
449  for (size_t i = 0; i < numBinaryInteractions_; i++) {
450  size_t iA = m_pSpecies_A_ij[i];
451  size_t iB = m_pSpecies_B_ij[i];
452  XA = moleFractions_[iA];
453  XB = moleFractions_[iB];
454  doublereal deltaX = XA - XB;
455  size_t N = m_N_ij[i];
456  vector_fp& he_vec = m_HE_m_ij[i];
457  vector_fp& se_vec = m_SE_m_ij[i];
458  doublereal poly = 1.0;
459  doublereal polyMm1 = 1.0;
460  doublereal sum = 0.0;
461  doublereal sumMm1 = 0.0;
462  doublereal sum2 = 0.0;
463  for (size_t m = 0; m < N; m++) {
464  doublereal A_ge = (he_vec[m] - T * se_vec[m]) / RT;
465  sum += A_ge * poly;
466  sum2 += A_ge * (m + 1) * poly;
467  poly *= deltaX;
468  if (m >= 1) {
469  sumMm1 += (A_ge * polyMm1 * m);
470  polyMm1 *= deltaX;
471  }
472  }
473  doublereal oneMXA = 1.0 - XA;
474  doublereal oneMXB = 1.0 - XB;
475  for (size_t k = 0; k < m_kk; k++) {
476  if (iA == k) {
477  lnActCoeff_Scaled_[k] += (oneMXA * XB * sum) + (XA * XB * sumMm1 * (oneMXA + XB));
478  } else if (iB == k) {
479  lnActCoeff_Scaled_[k] += (oneMXB * XA * sum) + (XA * XB * sumMm1 * (-oneMXB - XA));
480  } else {
481  lnActCoeff_Scaled_[k] += -(XA * XB * sum2);
482  }
483  }
484  // Debug against formula in literature
485 #ifdef DEBUG_MODE_NOT
486  double lnA = 0.0;
487  double lnB = 0.0;
488  double polyk = 1.0;
489  double fac = 2.0 * XA - 1.0;
490  for (int m = 0; m < N; m++) {
491  doublereal A_ge = (he_vec[m] - T * se_vec[m]) / RT;
492  lnA += A_ge * oneMXA * oneMXA * polyk * (1.0 + 2.0 * XA * m / fac);
493  lnB += A_ge * XA * XA * polyk * (1.0 - 2.0 * oneMXA * m / fac);
494  polyk *= fac;
495  }
496  // This gives the same result as above
497  // printf("RT lnActCoeff_Scaled_[iA] = %15.8E , lnA = %15.8E\n", lnActCoeff_Scaled_[iA], lnA);
498  // printf("RT lnActCoeff_Scaled_[iB] = %15.8E , lnB = %15.8E\n", lnActCoeff_Scaled_[iB], lnB);
499 
500 #endif
501 
502  }
503 
504 }
505 
507 {
508  doublereal XA, XB;
509  // doublereal T = temperature();
510 
511  dlnActCoeffdT_Scaled_.assign(m_kk, 0.0);
512  d2lnActCoeffdT2_Scaled_.assign(m_kk, 0.0);
513 
514  for (size_t i = 0; i < numBinaryInteractions_; i++) {
515  size_t iA = m_pSpecies_A_ij[i];
516  size_t iB = m_pSpecies_B_ij[i];
517  XA = moleFractions_[iA];
518  XB = moleFractions_[iB];
519  doublereal deltaX = XA - XB;
520  size_t N = m_N_ij[i];
521  doublereal poly = 1.0;
522  doublereal sum = 0.0;
523 
524  vector_fp& se_vec = m_SE_m_ij[i];
525  doublereal sumMm1 = 0.0;
526  doublereal polyMm1 = 1.0;
527  doublereal sum2 = 0.0;
528  for (size_t m = 0; m < N; m++) {
529  doublereal A_ge = - se_vec[m];
530  sum += A_ge * poly;
531  sum2 += A_ge * (m + 1) * poly;
532  poly *= deltaX;
533  if (m >= 1) {
534  sumMm1 += (A_ge * polyMm1 * m);
535  polyMm1 *= deltaX;
536  }
537  }
538  doublereal oneMXA = 1.0 - XA;
539  doublereal oneMXB = 1.0 - XB;
540  for (size_t k = 0; k < m_kk; k++) {
541  if (iA == k) {
542  dlnActCoeffdT_Scaled_[k] += (oneMXA * XB * sum) + (XA * XB * sumMm1 * (oneMXA + XB));
543  } else if (iB == k) {
544  dlnActCoeffdT_Scaled_[k] += (oneMXB * XA * sum) + (XA * XB * sumMm1 * (-oneMXB - XA));
545  } else {
546  dlnActCoeffdT_Scaled_[k] += -(XA * XB * sum2);
547  }
548  }
549  }
550 }
551 
552 void RedlichKisterVPSSTP::getdlnActCoeffdT(doublereal* dlnActCoeffdT) const
553 {
555  for (size_t k = 0; k < m_kk; k++) {
556  dlnActCoeffdT[k] = dlnActCoeffdT_Scaled_[k];
557  }
558 }
559 
560 void RedlichKisterVPSSTP::getd2lnActCoeffdT2(doublereal* d2lnActCoeffdT2) const
561 {
563  for (size_t k = 0; k < m_kk; k++) {
564  d2lnActCoeffdT2[k] = d2lnActCoeffdT2_Scaled_[k];
565  }
566 }
567 
569 {
570  doublereal XA, XB;
571  doublereal T = temperature();
572 
574 
575  for (size_t i = 0; i < numBinaryInteractions_; i++) {
576  size_t iA = m_pSpecies_A_ij[i];
577  size_t iB = m_pSpecies_B_ij[i];
578  XA = moleFractions_[iA];
579  XB = moleFractions_[iB];
580  doublereal deltaX = XA - XB;
581  size_t N = m_N_ij[i];
582  doublereal poly = 1.0;
583  doublereal sum = 0.0;
584  vector_fp& he_vec = m_HE_m_ij[i];
585  vector_fp& se_vec = m_SE_m_ij[i];
586  doublereal sumMm1 = 0.0;
587  doublereal polyMm1 = 1.0;
588  doublereal polyMm2 = 1.0;
589  doublereal sum2 = 0.0;
590  doublereal sum2Mm1 = 0.0;
591  doublereal sumMm2 = 0.0;
592  for (size_t m = 0; m < N; m++) {
593  doublereal A_ge = he_vec[m] - T * se_vec[m];
594  sum += A_ge * poly;
595  sum2 += A_ge * (m + 1) * poly;
596  poly *= deltaX;
597  if (m >= 1) {
598  sumMm1 += (A_ge * polyMm1 * m);
599  sum2Mm1 += (A_ge * polyMm1 * m * (1.0 + m));
600  polyMm1 *= deltaX;
601  }
602  if (m >= 2) {
603  sumMm2 += (A_ge * polyMm2 * m * (m - 1.0));
604  polyMm2 *= deltaX;
605  }
606  }
607 
608  for (size_t k = 0; k < m_kk; k++) {
609  if (iA == k) {
610 
611  dlnActCoeff_dX_(k, iA) += (- XB * sum + (1.0 - XA) * XB * sumMm1
612  + XB * sumMm1 * (1.0 - 2.0 * XA + XB)
613  + XA * XB * sumMm2 * (1.0 - XA + XB));
614 
615  dlnActCoeff_dX_(k, iB) += ((1.0 - XA) * sum - (1.0 - XA) * XB * sumMm1
616  + XA * sumMm1 * (1.0 + 2.0 * XB - XA)
617  - XA * XB * sumMm2 * (1.0 - XA + XB));
618 
619  } else if (iB == k) {
620 
621  dlnActCoeff_dX_(k, iA) += ((1.0 - XB) * sum + (1.0 - XA) * XB * sumMm1
622  + XB * sumMm1 * (1.0 - 2.0 * XA + XB)
623  + XA * XB * sumMm2 * (1.0 - XA + XB));
624 
625  dlnActCoeff_dX_(k, iB) += (- XA * sum - (1.0 - XB) * XA * sumMm1
626  + XA * sumMm1 * (XB - XA - (1.0 - XB))
627  - XA * XB * sumMm2 * (-XA - (1.0 - XB)));
628  } else {
629 
630  dlnActCoeff_dX_(k, iA) += (- XB * sum2 - XA * XB * sum2Mm1);
631 
632  dlnActCoeff_dX_(k, iB) += (- XA * sum2 + XA * XB * sum2Mm1);
633 
634  }
635  }
636  }
637 }
638 
639 void RedlichKisterVPSSTP::getdlnActCoeffds(const doublereal dTds, const doublereal* const dXds,
640  doublereal* dlnActCoeffds) const
641 {
644  for (size_t k = 0; k < m_kk; k++) {
645  dlnActCoeffds[k] = dlnActCoeffdT_Scaled_[k] * dTds;
646  for (size_t l = 0; l < m_kk; l++) {
647  dlnActCoeffds[k] += dlnActCoeff_dX_(k, l) * dXds[l];
648  }
649  }
650 }
651 
652 void RedlichKisterVPSSTP::getdlnActCoeffdlnN_diag(doublereal* dlnActCoeffdlnN_diag) const
653 {
655  for (size_t l = 0; l < m_kk; l++) {
656  dlnActCoeffdlnN_diag[l] = dlnActCoeff_dX_(l, l);
657  for (size_t k = 0; k < m_kk; k++) {
658  dlnActCoeffdlnN_diag[k] -= dlnActCoeff_dX_(l, k) * moleFractions_[k];
659  }
660  }
661 }
662 
663 void RedlichKisterVPSSTP::getdlnActCoeffdlnX_diag(doublereal* dlnActCoeffdlnX_diag) const
664 {
666  for (size_t k = 0; k < m_kk; k++) {
667  dlnActCoeffdlnX_diag[k] = dlnActCoeffdlnX_diag_[k];
668  }
669 }
670 
671 void RedlichKisterVPSSTP::getdlnActCoeffdlnN(const size_t ld, doublereal* dlnActCoeffdlnN)
672 {
674  double* data = & dlnActCoeffdlnN_(0,0);
675  for (size_t k = 0; k < m_kk; k++) {
676  for (size_t m = 0; m < m_kk; m++) {
677  dlnActCoeffdlnN[ld * k + m] = data[m_kk * k + m];
678  }
679  }
680 }
681 
683 {
685  m_pSpecies_A_ij.resize(num, npos);
686  m_pSpecies_B_ij.resize(num, npos);
687  m_N_ij.resize(num, npos);
688  m_HE_m_ij.resize(num);
689  m_SE_m_ij.resize(num);
690  dlnActCoeff_dX_.resize(num, num, 0.0);
691 }
692 
694 {
695  std::string xname = xmLBinarySpecies.name();
696  if (xname != "binaryNeutralSpeciesParameters") {
697  throw CanteraError("RedlichKisterVPSSTP::readXMLBinarySpecies",
698  "Incorrect name for processing this routine: " + xname);
699  }
700  std::string stemp;
701  size_t Npoly = 0;
702  vector_fp hParams, sParams, vParams;
703  std::string iName = xmLBinarySpecies.attrib("speciesA");
704  if (iName == "") {
705  throw CanteraError("RedlichKisterVPSSTP::readXMLBinarySpecies", "no speciesA attrib");
706  }
707  std::string jName = xmLBinarySpecies.attrib("speciesB");
708  if (jName == "") {
709  throw CanteraError("RedlichKisterVPSSTP::readXMLBinarySpecies", "no speciesB attrib");
710  }
711  /*
712  * Find the index of the species in the current phase. It's not
713  * an error to not find the species. This means that the interaction doesn't occur for the current
714  * implementation of the phase.
715  */
716  size_t iSpecies = speciesIndex(iName);
717  if (iSpecies == npos) {
718  return;
719  }
720  string ispName = speciesName(iSpecies);
721  if (charge(iSpecies) != 0) {
722  throw CanteraError("RedlichKisterVPSSTP::readXMLBinarySpecies", "speciesA charge problem");
723  }
724  size_t jSpecies = speciesIndex(jName);
725  if (jSpecies == npos) {
726  return;
727  }
728  std::string jspName = speciesName(jSpecies);
729  if (charge(jSpecies) != 0) {
730  throw CanteraError("RedlichKisterVPSSTP::readXMLBinarySpecies", "speciesB charge problem");
731  }
732  /*
733  * Ok we have found a valid interaction
734  */
736  size_t iSpot = numBinaryInteractions_ - 1;
739  m_pSpecies_A_ij[iSpot] = iSpecies;
740  m_pSpecies_B_ij[iSpot] = jSpecies;
741 
742  size_t num = xmLBinarySpecies.nChildren();
743  for (size_t iChild = 0; iChild < num; iChild++) {
744  XML_Node& xmlChild = xmLBinarySpecies.child(iChild);
745  stemp = xmlChild.name();
746  string nodeName = lowercase(stemp);
747  /*
748  * Process the binary species interaction child elements
749  */
750  if (nodeName == "excessenthalpy") {
751  /*
752  * Get the string containing all of the values
753  */
754  ctml::getFloatArray(xmlChild, hParams, true, "toSI", "excessEnthalpy");
755  size_t nParamsFound = hParams.size();
756  if (nParamsFound > Npoly) {
757  Npoly = nParamsFound;
758  }
759 
760  }
761 
762  if (nodeName == "excessentropy") {
763  /*
764  * Get the string containing all of the values
765  */
766  ctml::getFloatArray(xmlChild, sParams, true, "toSI", "excessEntropy");
767  size_t nParamsFound = sParams.size();
768  if (nParamsFound > Npoly) {
769  Npoly = nParamsFound;
770  }
771  }
772  }
773  hParams.resize(Npoly, 0.0);
774  sParams.resize(Npoly, 0.0);
775  m_HE_m_ij.push_back(hParams);
776  m_SE_m_ij.push_back(sParams);
777  m_N_ij.push_back(Npoly);
779 }
780 
781 #ifdef DEBUG_MODE
782 void RedlichKisterVPSSTP::Vint(double& VintOut, double& voltsOut)
783 {
784  int iA, iB, m;
785  doublereal XA, XB;
786  doublereal T = temperature();
787  doublereal RT = GasConstant * T;
788  double Volts = 0.0;
789 
790  lnActCoeff_Scaled_.assign(m_kk, 0.0);
791 
792  for (int i = 0; i < numBinaryInteractions_; i++) {
793  iA = m_pSpecies_A_ij[i];
794  iB = m_pSpecies_B_ij[i];
795  XA = moleFractions_[iA];
796  XB = moleFractions_[iB];
797  if (XA <= 1.0E-14) {
798  XA = 1.0E-14;
799  }
800  if (XA >= (1.0 - 1.0E-14)) {
801  XA = 1.0 - 1.0E-14;
802  }
803 
804  int N = m_N_ij[i];
805  vector_fp& he_vec = m_HE_m_ij[i];
806  vector_fp& se_vec = m_SE_m_ij[i];
807  double fac = 2.0 * XA - 1.0;
808  if (fabs(fac) < 1.0E-13) {
809  fac = 1.0E-13;
810  }
811  double polykp1 = fac;
812  double poly1mk = fac;
813 
814  for (m = 0; m < N; m++) {
815  doublereal A_ge = he_vec[m] - T * se_vec[m];
816  Volts += A_ge * (polykp1 - (2.0 * XA * m * (1.0-XA)) / poly1mk);
817  polykp1 *= fac;
818  poly1mk /= fac;
819  }
820  }
821  Volts /= Faraday;
822 
823  double termp = RT * log((1.0 - XA)/XA) / Faraday;
824 
825  VintOut = Volts;
826  voltsOut = Volts + termp;
827 }
828 #endif
829 }
virtual void getdlnActCoeffds(const doublereal dTds, const doublereal *const dXds, doublereal *dlnActCoeffds) const
Get the change in activity coefficients w.r.t.
std::string int2str(const int n, const std::string &fmt)
Convert an int to a string using a format converter.
Definition: stringUtils.cpp:40
virtual doublereal cv_mole() const
Molar heat capacity at constant volume. Units: J/kmol/K.
virtual void getdlnActCoeffdT(doublereal *dlnActCoeffdT) const
Get the array of temperature derivatives of the log activity coefficients.
doublereal electricPotential() const
Returns the electric potential of this phase (V).
Definition: ThermoPhase.h:391
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
std::string attrib(const std::string &attr) const
Function returns the value of an attribute.
Definition: xml.cpp:534
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
RedlichKisterVPSSTP is a derived class of GibbsExcessVPSSTP that employs the Redlich-Kister approxima...
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...
RedlichKisterVPSSTP & operator=(const RedlichKisterVPSSTP &b)
Assignment operator.
const size_t npos
index returned by functions to indicate "no position"
Definition: ct_defs.h:173
size_t numBinaryInteractions_
number of binary interaction expressions
virtual int eosType() const
Equation of state type flag.
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...
std::vector< vector_fp > m_HE_m_ij
Enthalpy term for the binary mole fraction interaction of the excess gibbs free energy expression...
int formRedlichKister_
form of the RedlichKister interaction expression
virtual void getPartialMolarEntropies(doublereal *sbar) const
Returns an array of partial molar entropies for the species in the mixture.
Class XML_Node is a tree-based representation of the contents of an XML file.
Definition: xml.h:100
std::string lowercase(const std::string &s)
Cast a copy of a string to lower case.
Definition: stringUtils.cpp:58
int formTempModel_
form of the temperature dependence of the Redlich-Kister interaction expression
std::vector< doublereal > d2lnActCoeffdT2_Scaled_
Storage for the current derivative values of the gradients with respect to temperature of the log of ...
Array2D dlnActCoeff_dX_
Two dimensional array of derivatives of activity coefficients wrt mole fractions. ...
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 doublereal cp_mole() const
Molar heat capacity at constant pressure. Units: J/kmol/K.
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.
void s_update_lnActCoeff() const
Update the activity coefficients.
virtual void getPartialMolarCp(doublereal *cpbar) const
Returns an array of partial molar entropies for the species in the mixture.
std::string name() const
Returns the name of the XML node.
Definition: xml.h:390
virtual void getdlnActCoeffdlnX_diag(doublereal *dlnActCoeffdlnX_diag) const
Get the array of log concentration-like derivatives of the log activity coefficients - diagonal compo...
virtual ThermoPhase * duplMyselfAsThermoPhase() const
Duplication routine for objects which inherit from ThermoPhase.
std::vector< size_t > m_pSpecies_B_ij
vector of species indices representing species B in the interaction
Base class for exceptions thrown by Cantera classes.
Definition: ctexceptions.h:68
doublereal err(const std::string &msg) const
Error function.
virtual void getdlnActCoeffdlnN_diag(doublereal *dlnActCoeffdlnN_diag) const
Get the array of derivatives of the log activity coefficients wrt mole numbers - diagonal only...
void readXMLBinarySpecies(XML_Node &xmlBinarySpecies)
Process an XML node called "binaryNeutralSpeciesParameters".
bool hasChild(const std::string &ch) const
Tests whether the current node has a child node with a particular name.
Definition: xml.cpp:574
void s_update_dlnActCoeff_dT() const
Update the derivative of the log of the activity coefficients wrt T.
virtual doublereal enthalpy_mole() const
Molar enthalpy. Units: J/kmol.
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
void initLengths()
Initialize lengths of local variables after all species have been identified.
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 getLnActivityCoefficients(doublereal *lnac) const
Get the array of non-dimensional molar-based ln activity coefficients at the current solution tempera...
void s_update_dlnActCoeff_dX_() const
Internal routine that calculates the derivative of the activity coefficients wrt the mole fractions...
std::vector< doublereal > moleFractions_
Storage for the current values of the mole fractions of the species.
virtual void getChemPotentials(doublereal *mu) const
Get the species chemical potentials. Units: J/kmol.
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.
void initThermoXML(XML_Node &phaseNode, const std::string &id)
Import and initialize a ThermoPhase object.
virtual void getPartialMolarEnthalpies(doublereal *hbar) const
Returns an array of partial molar enthalpies for the species in the mixture.
void getElectrochemPotentials(doublereal *mu) const
Get the species electrochemical potentials.
virtual void getdlnActCoeffdlnN(const size_t ld, doublereal *const dlnActCoeffdlnN)
Get the array of derivatives of the ln activity coefficients with respect to the ln species mole numb...
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 Vint(double &VintOut, double &voltsOut)
Utility routine that calculates a literature expression.
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.
Header for intermediate ThermoPhase object for phases which employ gibbs excess free energy based for...
virtual void getd2lnActCoeffdT2(doublereal *d2lnActCoeffdT2) const
Get the array of temperature second derivatives of the log activity coefficients. ...
std::string speciesName(size_t k) const
Name of the species with index k.
Definition: Phase.cpp:246
void resizeNumInteractions(const size_t num)
Resize internal arrays within the object that depend upon the number of binary Redlich-Kister interac...
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 doublereal entropy_mole() const
Molar entropy. Units: J/kmol.
std::vector< size_t > m_N_ij
Vector of the length of the polynomial for the interaction.
std::vector< vector_fp > m_SE_m_ij
Entropy term for the binary mole fraction interaction of the excess gibbs free energy expression...
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