Cantera  2.2.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
MargulesVPSSTP.cpp
Go to the documentation of this file.
1 /**
2  * @file MargulesVPSSTP.cpp
3  * Definitions for ThermoPhase object for phases which
4  * employ excess Gibbs free energy formulations related to Margules
5  * expansions (see \ref thermoprops
6  * and class \link Cantera::MargulesVPSSTP MargulesVPSSTP\endlink).
7  */
8 /*
9  * Copyright (2009) Sandia Corporation. Under the terms of
10  * Contract DE-AC04-94AL85000 with Sandia Corporation, the
11  * U.S. Government retains certain rights in this software.
12  */
16 #include "cantera/base/ctml.h"
17 
18 using namespace std;
19 
20 namespace Cantera
21 {
22 MargulesVPSSTP::MargulesVPSSTP() :
23  numBinaryInteractions_(0),
24  formMargules_(0),
25  formTempModel_(0)
26 {
27 }
28 
29 MargulesVPSSTP::MargulesVPSSTP(const std::string& inputFile, const std::string& id_) :
30  numBinaryInteractions_(0),
31  formMargules_(0),
32  formTempModel_(0)
33 {
34  initThermoFile(inputFile, id_);
35 }
36 
37 MargulesVPSSTP::MargulesVPSSTP(XML_Node& phaseRoot, const std::string& id_) :
38  numBinaryInteractions_(0),
39  formMargules_(0),
40  formTempModel_(0)
41 {
42  importPhase(*findXMLPhase(&phaseRoot, id_), this);
43 }
44 
46 {
48 }
49 
51 {
52  if (&b == this) {
53  return *this;
54  }
55 
57 
59  m_HE_b_ij = b.m_HE_b_ij;
60  m_HE_c_ij = b.m_HE_c_ij;
61  m_HE_d_ij = b.m_HE_d_ij;
62  m_SE_b_ij = b.m_SE_b_ij;
63  m_SE_c_ij = b.m_SE_c_ij;
64  m_SE_d_ij = b.m_SE_d_ij;
75 
76  return *this;
77 }
78 
81 {
82  return new MargulesVPSSTP(*this);
83 }
84 
87  numBinaryInteractions_(0),
88  formMargules_(0),
89  formTempModel_(0)
90 {
91  warn_deprecated("MargulesVPSSTP::MargulesVPSSTP(int testProb)",
92  "To be removed after Cantera 2.2");
93 
94  initThermoFile("LiKCl_liquid.xml", "");
95 
96 
98 
99  m_HE_b_ij.resize(1);
100  m_HE_c_ij.resize(1);
101  m_HE_d_ij.resize(1);
102 
103  m_SE_b_ij.resize(1);
104  m_SE_c_ij.resize(1);
105  m_SE_d_ij.resize(1);
106 
107  m_VHE_b_ij.resize(1);
108  m_VHE_c_ij.resize(1);
109  m_VHE_d_ij.resize(1);
110 
111  m_VSE_b_ij.resize(1);
112  m_VSE_c_ij.resize(1);
113  m_VSE_d_ij.resize(1);
114 
115  m_pSpecies_A_ij.resize(1);
116  m_pSpecies_B_ij.resize(1);
117 
118 
119 
120  m_HE_b_ij[0] = -17570E3;
121  m_HE_c_ij[0] = -377.0E3;
122  m_HE_d_ij[0] = 0.0;
123 
124  m_SE_b_ij[0] = -7.627E3;
125  m_SE_c_ij[0] = 4.958E3;
126  m_SE_d_ij[0] = 0.0;
127 
128 
129  size_t iLiCl = speciesIndex("LiCl(L)");
130  if (iLiCl == npos) {
131  throw CanteraError("MargulesVPSSTP test1 constructor",
132  "Unable to find LiCl(L)");
133  }
134  m_pSpecies_B_ij[0] = iLiCl;
135 
136 
137  size_t iKCl = speciesIndex("KCl(L)");
138  if (iKCl == npos) {
139  throw CanteraError("MargulesVPSSTP test1 constructor",
140  "Unable to find KCl(L)");
141  }
142  m_pSpecies_A_ij[0] = iKCl;
143 }
144 
145 /*
146  * - Activities, Standard States, Activity Concentrations -----------
147  */
148 
149 void MargulesVPSSTP::getLnActivityCoefficients(doublereal* lnac) const
150 {
151  /*
152  * Update the activity coefficients
153  */
155 
156  /*
157  * take the exp of the internally stored coefficients.
158  */
159  for (size_t k = 0; k < m_kk; k++) {
160  lnac[k] = lnActCoeff_Scaled_[k];
161  }
162 }
163 
164 /*
165  * ------------ Partial Molar Properties of the Solution ------------
166  */
167 
169 {
170  getChemPotentials(mu);
171  double ve = Faraday * electricPotential();
172  for (size_t k = 0; k < m_kk; k++) {
173  mu[k] += ve*charge(k);
174  }
175 }
176 
177 void MargulesVPSSTP::getChemPotentials(doublereal* mu) const
178 {
179  /*
180  * First get the standard chemical potentials in
181  * molar form.
182  * -> this requires updates of standard state as a function
183  * of T and P
184  */
186  /*
187  * Update the activity coefficients
188  */
190  doublereal RT = GasConstant * temperature();
191  for (size_t k = 0; k < m_kk; k++) {
192  double xx = std::max(moleFractions_[k], SmallNumber);
193  mu[k] += RT * (log(xx) + lnActCoeff_Scaled_[k]);
194  }
195 }
196 
198 {
199  size_t kk = nSpecies();
200  double h = 0;
201  vector_fp hbar(kk);
202  getPartialMolarEnthalpies(&hbar[0]);
203  for (size_t i = 0; i < kk; i++) {
204  h += moleFractions_[i]*hbar[i];
205  }
206  return h;
207 }
208 
210 {
211  size_t kk = nSpecies();
212  double s = 0;
213  vector_fp sbar(kk);
214  getPartialMolarEntropies(&sbar[0]);
215  for (size_t i = 0; i < kk; i++) {
216  s += moleFractions_[i]*sbar[i];
217  }
218  return s;
219 }
220 
221 doublereal MargulesVPSSTP::cp_mole() const
222 {
223  size_t kk = nSpecies();
224  double cp = 0;
225  vector_fp cpbar(kk);
226  getPartialMolarCp(&cpbar[0]);
227  for (size_t i = 0; i < kk; i++) {
228  cp += moleFractions_[i]*cpbar[i];
229  }
230  return cp;
231 }
232 
233 doublereal MargulesVPSSTP::cv_mole() const
234 {
235  return cp_mole() - GasConstant;
236 }
237 
238 void MargulesVPSSTP::getPartialMolarEnthalpies(doublereal* hbar) const
239 {
240  /*
241  * Get the nondimensional standard state enthalpies
242  */
243  getEnthalpy_RT(hbar);
244  /*
245  * dimensionalize it.
246  */
247  double T = temperature();
248  double RT = GasConstant * T;
249  for (size_t k = 0; k < m_kk; k++) {
250  hbar[k] *= RT;
251  }
252  /*
253  * Update the activity coefficients, This also update the
254  * internally stored molalities.
255  */
258  double RTT = RT * T;
259  for (size_t k = 0; k < m_kk; k++) {
260  hbar[k] -= RTT * dlnActCoeffdT_Scaled_[k];
261  }
262 }
263 
264 void MargulesVPSSTP::getPartialMolarCp(doublereal* cpbar) const
265 {
266  /*
267  * Get the nondimensional standard state entropies
268  */
269  getCp_R(cpbar);
270  double T = temperature();
271  /*
272  * Update the activity coefficients, This also update the
273  * internally stored molalities.
274  */
277 
278  for (size_t k = 0; k < m_kk; k++) {
279  cpbar[k] -= 2 * T * dlnActCoeffdT_Scaled_[k] + T * T * d2lnActCoeffdT2_Scaled_[k];
280  }
281  /*
282  * dimensionalize it.
283  */
284  for (size_t k = 0; k < m_kk; k++) {
285  cpbar[k] *= GasConstant;
286  }
287 }
288 
289 void MargulesVPSSTP::getPartialMolarEntropies(doublereal* sbar) const
290 {
291  /*
292  * Get the nondimensional standard state entropies
293  */
294  getEntropy_R(sbar);
295  double T = temperature();
296  /*
297  * Update the activity coefficients, This also update the
298  * internally stored molalities.
299  */
302 
303  for (size_t k = 0; k < m_kk; k++) {
304  double xx = std::max(moleFractions_[k], SmallNumber);
305  sbar[k] += - lnActCoeff_Scaled_[k] -log(xx) - T * dlnActCoeffdT_Scaled_[k];
306  }
307  /*
308  * dimensionalize it.
309  */
310  for (size_t k = 0; k < m_kk; k++) {
311  sbar[k] *= GasConstant;
312  }
313 }
314 
315 void MargulesVPSSTP::getPartialMolarVolumes(doublereal* vbar) const
316 {
317  double T = temperature();
318 
319  /*
320  * Get the standard state values in m^3 kmol-1
321  */
322  getStandardVolumes(vbar);
323 
324  for (size_t i = 0; i < numBinaryInteractions_; i++) {
325  size_t iA = m_pSpecies_A_ij[i];
326  size_t iB = m_pSpecies_B_ij[i];
327  double XA = moleFractions_[iA];
328  double XB = moleFractions_[iB];
329  double g0 = (m_VHE_b_ij[i] - T * m_VSE_b_ij[i]);
330  double g1 = (m_VHE_c_ij[i] - T * m_VSE_c_ij[i]);
331  const doublereal temp1 = g0 + g1 * XB;
332  const doublereal all = -1.0*XA*XB*temp1 - XA*XB*XB*g1;
333 
334  for (size_t iK = 0; iK < m_kk; iK++) {
335  vbar[iK] += all;
336  }
337  vbar[iA] += XB * temp1;
338  vbar[iB] += XA * temp1 + XA*XB*g1;
339  }
340 }
341 
343 {
344  initLengths();
346 }
347 
349 {
351 }
352 
353 void MargulesVPSSTP::initThermoXML(XML_Node& phaseNode, const std::string& id_)
354 {
355  if ((int) id_.size() > 0) {
356  string idp = phaseNode.id();
357  if (idp != id_) {
358  throw CanteraError("MargulesVPSSTP::initThermoXML", "phasenode and Id are incompatible");
359  }
360  }
361 
362  /*
363  * Find the Thermo XML node
364  */
365  if (!phaseNode.hasChild("thermo")) {
366  throw CanteraError("MargulesVPSSTP::initThermoXML",
367  "no thermo XML node");
368  }
369  XML_Node& thermoNode = phaseNode.child("thermo");
370 
371  /*
372  * Make sure that the thermo model is Margules
373  */
374  string formString = lowercase(thermoNode.attrib("model"));
375  if (formString != "margules") {
376  throw CanteraError("MargulesVPSSTP::initThermoXML",
377  "model name isn't Margules: " + formString);
378 
379  }
380 
381  /*
382  * Go get all of the coefficients and factors in the
383  * activityCoefficients XML block
384  */
385  if (thermoNode.hasChild("activityCoefficients")) {
386  XML_Node& acNode = thermoNode.child("activityCoefficients");
387  string mStringa = acNode.attrib("model");
388  if (lowercase(mStringa) != "margules") {
389  throw CanteraError("MargulesVPSSTP::initThermoXML",
390  "Unknown activity coefficient model: " + mStringa);
391  }
392  for (size_t i = 0; i < acNode.nChildren(); i++) {
393  XML_Node& xmlACChild = acNode.child(i);
394  /*
395  * Process a binary salt field, or any of the other XML fields
396  * that make up the Pitzer Database. Entries will be ignored
397  * if any of the species in the entry isn't in the solution.
398  */
399  if (lowercase(xmlACChild.name()) == "binaryneutralspeciesparameters") {
400  readXMLBinarySpecies(xmlACChild);
401  }
402  }
403  }
404 
405  /*
406  * Go down the chain
407  */
408  GibbsExcessVPSSTP::initThermoXML(phaseNode, id_);
409 }
410 
412 {
413  double T = temperature();
414  double invRT = 1.0 / (GasConstant*T);
415  lnActCoeff_Scaled_.assign(m_kk, 0.0);
416  for (size_t i = 0; i < numBinaryInteractions_; i++) {
417  size_t iA = m_pSpecies_A_ij[i];
418  size_t iB = m_pSpecies_B_ij[i];
419  double g0 = (m_HE_b_ij[i] - T * m_SE_b_ij[i]) * invRT;
420  double g1 = (m_HE_c_ij[i] - T * m_SE_c_ij[i]) * invRT;
421  double XA = moleFractions_[iA];
422  double XB = moleFractions_[iB];
423  const doublereal XAXB = XA * XB;
424  const doublereal g0g1XB = (g0 + g1 * XB);
425  const doublereal all = -1.0 * XAXB * g0g1XB - XAXB * XB * g1;
426  for (size_t iK = 0; iK < m_kk; iK++) {
427  lnActCoeff_Scaled_[iK] += all;
428  }
429  lnActCoeff_Scaled_[iA] += XB * g0g1XB;
430  lnActCoeff_Scaled_[iB] += XA * g0g1XB + XAXB * g1;
431  }
432 }
433 
435 {
436  doublereal invT = 1.0 / temperature();
437  doublereal invRTT = 1.0 / (GasConstant)*invT*invT;
438  dlnActCoeffdT_Scaled_.assign(m_kk, 0.0);
439  d2lnActCoeffdT2_Scaled_.assign(m_kk, 0.0);
440  for (size_t i = 0; i < numBinaryInteractions_; i++) {
441  size_t iA = m_pSpecies_A_ij[i];
442  size_t iB = m_pSpecies_B_ij[i];
443  double XA = moleFractions_[iA];
444  double XB = moleFractions_[iB];
445  double g0 = -m_HE_b_ij[i] * invRTT;
446  double g1 = -m_HE_c_ij[i] * invRTT;
447  const doublereal XAXB = XA * XB;
448  const doublereal g0g1XB = (g0 + g1 * XB);
449  const doublereal all = -1.0 * XAXB * g0g1XB - XAXB * XB * g1;
450  const doublereal mult = 2.0 * invT;
451  const doublereal dT2all = mult * all;
452  for (size_t iK = 0; iK < m_kk; iK++) {
453  dlnActCoeffdT_Scaled_[iK] += all;
454  d2lnActCoeffdT2_Scaled_[iK] -= dT2all;
455  }
456  dlnActCoeffdT_Scaled_[iA] += XB * g0g1XB;
457  dlnActCoeffdT_Scaled_[iB] += XA * g0g1XB + XAXB * g1;
458  d2lnActCoeffdT2_Scaled_[iA] -= mult * XB * g0g1XB;
459  d2lnActCoeffdT2_Scaled_[iB] -= mult * (XA * g0g1XB + XAXB * g1);
460  }
461 }
462 
463 void MargulesVPSSTP::getdlnActCoeffdT(doublereal* dlnActCoeffdT) const
464 {
466  for (size_t k = 0; k < m_kk; k++) {
467  dlnActCoeffdT[k] = dlnActCoeffdT_Scaled_[k];
468  }
469 }
470 
471 void MargulesVPSSTP::getd2lnActCoeffdT2(doublereal* d2lnActCoeffdT2) const
472 {
474  for (size_t k = 0; k < m_kk; k++) {
475  d2lnActCoeffdT2[k] = d2lnActCoeffdT2_Scaled_[k];
476  }
477 }
478 
479 void MargulesVPSSTP::getdlnActCoeffds(const doublereal dTds, const doublereal* const dXds,
480  doublereal* dlnActCoeffds) const
481 {
482  double T = temperature();
483  double RT = GasConstant*T;
485  for (size_t iK = 0; iK < m_kk; iK++) {
486  dlnActCoeffds[iK] = 0.0;
487  }
488 
489  for (size_t i = 0; i < numBinaryInteractions_; i++) {
490  size_t iA = m_pSpecies_A_ij[i];
491  size_t iB = m_pSpecies_B_ij[i];
492  double XA = moleFractions_[iA];
493  double XB = moleFractions_[iB];
494  double dXA = dXds[iA];
495  double dXB = dXds[iB];
496  double g0 = (m_HE_b_ij[i] - T * m_SE_b_ij[i]) / RT;
497  double g1 = (m_HE_c_ij[i] - T * m_SE_c_ij[i]) / RT;
498  const doublereal g02g1XB = g0 + 2*g1*XB;
499  const doublereal g2XAdXB = 2*g1*XA*dXB;
500  const doublereal all = (-XB * dXA - XA *dXB) * g02g1XB - XB *g2XAdXB;
501  for (size_t iK = 0; iK < m_kk; iK++) {
502  dlnActCoeffds[iK] += all + dlnActCoeffdT_Scaled_[iK]*dTds;
503  }
504  dlnActCoeffds[iA] += dXB * g02g1XB;
505  dlnActCoeffds[iB] += dXA * g02g1XB + g2XAdXB;
506  }
507 }
508 
510 {
511  double T = temperature();
512  double RT = GasConstant*T;
513 
514  dlnActCoeffdlnN_diag_.assign(m_kk, 0.0);
515 
516  for (size_t iK = 0; iK < m_kk; iK++) {
517  double XK = moleFractions_[iK];
518 
519  for (size_t i = 0; i < numBinaryInteractions_; i++) {
520  size_t iA = m_pSpecies_A_ij[i];
521  size_t iB = m_pSpecies_B_ij[i];
522  size_t delAK = 0;
523  size_t delBK = 0;
524 
525  if (iA==iK) {
526  delAK = 1;
527  } else if (iB==iK) {
528  delBK = 1;
529  }
530 
531  double XA = moleFractions_[iA];
532  double XB = moleFractions_[iB];
533 
534  double g0 = (m_HE_b_ij[i] - T * m_SE_b_ij[i]) / RT;
535  double g1 = (m_HE_c_ij[i] - T * m_SE_c_ij[i]) / RT;
536 
537  dlnActCoeffdlnN_diag_[iK] += 2*(delBK-XB)*(g0*(delAK-XA)+g1*(2*(delAK-XA)*XB+XA*(delBK-XB)));
538  }
540  }
541 }
542 
544 {
545  double T = temperature();
546  double RT = GasConstant*T;
548 
549  /*
550  * Loop over the activity coefficient gamma_k
551  */
552  for (size_t iK = 0; iK < m_kk; iK++) {
553  for (size_t iM = 0; iM < m_kk; iM++) {
554  double XM = moleFractions_[iM];
555  for (size_t i = 0; i < numBinaryInteractions_; i++) {
556 
557  size_t iA = m_pSpecies_A_ij[i];
558  size_t iB = m_pSpecies_B_ij[i];
559 
560  double delAK = 0.0;
561  double delBK = 0.0;
562  double delAM = 0.0;
563  double delBM = 0.0;
564  if (iA==iK) {
565  delAK = 1.0;
566  } else if (iB==iK) {
567  delBK = 1.0;
568  }
569  if (iA==iM) {
570  delAM = 1.0;
571  } else if (iB==iM) {
572  delBM = 1.0;
573  }
574 
575  double XA = moleFractions_[iA];
576  double XB = moleFractions_[iB];
577 
578  double g0 = (m_HE_b_ij[i] - T * m_SE_b_ij[i]) / RT;
579  double g1 = (m_HE_c_ij[i] - T * m_SE_c_ij[i]) / RT;
580 
581  dlnActCoeffdlnN_(iK,iM) += g0*((delAM-XA)*(delBK-XB)+(delAK-XA)*(delBM-XB));
582  dlnActCoeffdlnN_(iK,iM) += 2*g1*((delAM-XA)*(delBK-XB)*XB+(delAK-XA)*(delBM-XB)*XB+(delBM-XB)*(delBK-XB)*XA);
583  }
584  dlnActCoeffdlnN_(iK,iM) = XM*dlnActCoeffdlnN_(iK,iM);
585  }
586  }
587 }
588 
590 {
591  doublereal T = temperature();
592  dlnActCoeffdlnX_diag_.assign(m_kk, 0.0);
593  doublereal RT = GasConstant * T;
594 
595  for (size_t i = 0; i < numBinaryInteractions_; i++) {
596  size_t iA = m_pSpecies_A_ij[i];
597  size_t iB = m_pSpecies_B_ij[i];
598 
599  doublereal XA = moleFractions_[iA];
600  doublereal XB = moleFractions_[iB];
601 
602  doublereal g0 = (m_HE_b_ij[i] - T * m_SE_b_ij[i]) / RT;
603  doublereal g1 = (m_HE_c_ij[i] - T * m_SE_c_ij[i]) / RT;
604 
605  dlnActCoeffdlnX_diag_[iA] += XA*XB*(2*g1*-2*g0-6*g1*XB);
606  dlnActCoeffdlnX_diag_[iB] += XA*XB*(2*g1*-2*g0-6*g1*XB);
607  }
608 }
609 
610 void MargulesVPSSTP::getdlnActCoeffdlnN_diag(doublereal* dlnActCoeffdlnN_diag) const
611 {
613  for (size_t k = 0; k < m_kk; k++) {
614  dlnActCoeffdlnN_diag[k] = dlnActCoeffdlnN_diag_[k];
615  }
616 }
617 
618 void MargulesVPSSTP::getdlnActCoeffdlnX_diag(doublereal* dlnActCoeffdlnX_diag) const
619 {
621  for (size_t k = 0; k < m_kk; k++) {
622  dlnActCoeffdlnX_diag[k] = dlnActCoeffdlnX_diag_[k];
623  }
624 }
625 
626 void MargulesVPSSTP::getdlnActCoeffdlnN(const size_t ld, doublereal* dlnActCoeffdlnN)
627 {
629  double* data = & dlnActCoeffdlnN_(0,0);
630  for (size_t k = 0; k < m_kk; k++) {
631  for (size_t m = 0; m < m_kk; m++) {
632  dlnActCoeffdlnN[ld * k + m] = data[m_kk * k + m];
633  }
634  }
635 }
636 
638 {
640  m_HE_b_ij.resize(num, 0.0);
641  m_HE_c_ij.resize(num, 0.0);
642  m_HE_d_ij.resize(num, 0.0);
643  m_SE_b_ij.resize(num, 0.0);
644  m_SE_c_ij.resize(num, 0.0);
645  m_SE_d_ij.resize(num, 0.0);
646  m_VHE_b_ij.resize(num, 0.0);
647  m_VHE_c_ij.resize(num, 0.0);
648  m_VHE_d_ij.resize(num, 0.0);
649  m_VSE_b_ij.resize(num, 0.0);
650  m_VSE_c_ij.resize(num, 0.0);
651  m_VSE_d_ij.resize(num, 0.0);
652 
653  m_pSpecies_A_ij.resize(num, npos);
654  m_pSpecies_B_ij.resize(num, npos);
655 }
656 
658 {
659  string xname = xmLBinarySpecies.name();
660  if (xname != "binaryNeutralSpeciesParameters") {
661  throw CanteraError("MargulesVPSSTP::readXMLBinarySpecies",
662  "Incorrect name for processing this routine: " + xname);
663  }
664  vector_fp vParams;
665  string aName = xmLBinarySpecies.attrib("speciesA");
666  if (aName == "") {
667  throw CanteraError("MargulesVPSSTP::readXMLBinarySpecies", "no speciesA attrib");
668  }
669  string bName = xmLBinarySpecies.attrib("speciesB");
670  if (bName == "") {
671  throw CanteraError("MargulesVPSSTP::readXMLBinarySpecies", "no speciesB attrib");
672  }
673  /*
674  * Find the index of the species in the current phase. It's not
675  * an error to not find the species. What this means is that the A-B interaction referred to in this
676  * block will be ignored.
677  */
678  size_t aSpecies = speciesIndex(aName);
679  if (aSpecies == npos) {
680  return;
681  }
682  string aspName = speciesName(aSpecies);
683  //
684  // @TODO Figure out what the original reason is for putting an error condition for charged species
685  // Seems OK to me.
686  //
687  if (charge(aSpecies) != 0.0) {
688  throw CanteraError("MargulesVPSSTP::readXMLBinarySpecies", "speciesA has a charge: " + fp2str(charge(aSpecies)));
689  }
690  size_t bSpecies = speciesIndex(bName);
691  if (bSpecies == npos) {
692  return;
693  }
694  string bspName = speciesName(bSpecies);
695  if (charge(bSpecies) != 0.0) {
696  throw CanteraError("MargulesVPSSTP::readXMLBinarySpecies", "speciesB has a charge: " + fp2str(charge(bSpecies)));
697  }
698 
700  size_t iSpot = numBinaryInteractions_ - 1;
701  m_pSpecies_A_ij[iSpot] = aSpecies;
702  m_pSpecies_B_ij[iSpot] = bSpecies;
703 
704  for (size_t iChild = 0; iChild < xmLBinarySpecies.nChildren(); iChild++) {
705  XML_Node& xmlChild = xmLBinarySpecies.child(iChild);
706  string nodeName = lowercase(xmlChild.name());
707  /*
708  * Process the binary species interaction parameters.
709  * They are in subblocks labeled:
710  * excessEnthalpy
711  * excessEntropy
712  * excessVolume_Enthalpy
713  * excessVolume_Entropy
714  * Other blocks are currently ignored.
715  * @TODO determine a policy about ignoring blocks that should or shouldn't be there.
716  */
717  if (nodeName == "excessenthalpy") {
718  /*
719  * Get the string containing all of the values
720  */
721  getFloatArray(xmlChild, vParams, true, "toSI", "excessEnthalpy");
722  if (vParams.size() != 2) {
723  throw CanteraError("MargulesVPSSTP::readXMLBinarySpecies::excessEnthalpy for " + aspName
724  + "::" + bspName,
725  "wrong number of params found. Need 2");
726  }
727  m_HE_b_ij[iSpot] = vParams[0];
728  m_HE_c_ij[iSpot] = vParams[1];
729  }
730 
731  if (nodeName == "excessentropy") {
732  /*
733  * Get the string containing all of the values
734  */
735  getFloatArray(xmlChild, vParams, true, "toSI", "excessEntropy");
736  if (vParams.size() != 2) {
737  throw CanteraError("MargulesVPSSTP::readXMLBinarySpecies::excessEntropy for " + aspName
738  + "::" + bspName,
739  "wrong number of params found. Need 2");
740  }
741  m_SE_b_ij[iSpot] = vParams[0];
742  m_SE_c_ij[iSpot] = vParams[1];
743  }
744 
745  if (nodeName == "excessvolume_enthalpy") {
746  /*
747  * Get the string containing all of the values
748  */
749  getFloatArray(xmlChild, vParams, true, "toSI", "excessVolume_Enthalpy");
750  if (vParams.size() != 2) {
751  throw CanteraError("MargulesVPSSTP::readXMLBinarySpecies::excessVolume_Enthalpy for " + aspName
752  + "::" + bspName,
753  "wrong number of params found. Need 2");
754  }
755  m_VHE_b_ij[iSpot] = vParams[0];
756  m_VHE_c_ij[iSpot] = vParams[1];
757  }
758 
759  if (nodeName == "excessvolume_entropy") {
760  /*
761  * Get the string containing all of the values
762  */
763  getFloatArray(xmlChild, vParams, true, "toSI", "excessVolume_Entropy");
764  if (vParams.size() != 2) {
765  throw CanteraError("MargulesVPSSTP::readXMLBinarySpecies::excessVolume_Entropy for " + aspName
766  + "::" + bspName,
767  "wrong number of params found. Need 2");
768  }
769  m_VSE_b_ij[iSpot] = vParams[0];
770  m_VSE_c_ij[iSpot] = vParams[1];
771  }
772  }
773 }
774 
775 }
int formMargules_
form of the Margules interaction expression
vector_fp m_VSE_c_ij
Entropy term for the ternary mole fraction interaction of the excess Gibbs free energy expression...
void readXMLBinarySpecies(XML_Node &xmlBinarySpecies)
Process an XML node called "binaryNeutralSpeciesParameters".
doublereal electricPotential() const
Returns the electric potential of this phase (V).
Definition: ThermoPhase.h:352
vector_fp m_VSE_d_ij
Entropy term for the quaternary mole fraction interaction of the excess Gibbs free energy expression...
CTML ("Cantera Markup Language") is the variant of XML that Cantera uses to store data...
vector_fp m_HE_b_ij
Enthalpy term for the binary mole fraction interaction of the excess Gibbs free energy 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:1108
vector_fp m_VHE_d_ij
Enthalpy term for the quaternary mole fraction interaction of the excess Gibbs free energy expression...
Header for intermediate ThermoPhase object for phases which employ Gibbs excess free energy based for...
std::string attrib(const std::string &attr) const
Function returns the value of an attribute.
Definition: xml.cpp:527
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:121
virtual doublereal entropy_mole() const
Molar entropy. Units: J/kmol.
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...
void initThermoXML(XML_Node &phaseNode, const std::string &id)
Import and initialize a ThermoPhase object.
const size_t npos
index returned by functions to indicate "no position"
Definition: ct_defs.h:165
std::vector< size_t > m_pSpecies_A_ij
vector of species indices representing species A in the interaction
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...
vector_fp m_HE_d_ij
Enthalpy term for the quaternary mole fraction interaction of the excess Gibbs free energy expression...
Class XML_Node is a tree-based representation of the contents of an XML file.
Definition: xml.h:100
void warn_deprecated(const std::string &method, const std::string &extra)
Print a warning indicating that method is deprecated.
Definition: global.cpp:78
virtual void getd2lnActCoeffdT2(doublereal *d2lnActCoeffdT2) const
Get the array of temperature second derivatives of the log activity coefficients. ...
size_t numBinaryInteractions_
number of binary interaction expressions
std::string lowercase(const std::string &s)
Cast a copy of a string to lower case.
Definition: stringUtils.cpp:73
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...
std::vector< doublereal > d2lnActCoeffdT2_Scaled_
Storage for the current derivative values of the gradients with respect to temperature of the log of ...
virtual void getdlnActCoeffdT(doublereal *dlnActCoeffdT) const
Get the array of temperature derivatives of the log activity coefficients.
std::vector< doublereal > dlnActCoeffdlnN_diag_
Storage for the current derivative values of the gradients with respect to logarithm of the mole frac...
void resizeNumInteractions(const size_t num)
Resize internal arrays within the object that depend upon the number of binary Margules interaction t...
void initLengths()
Initialize lengths of local variables after all species have been identified.
virtual void getPartialMolarCp(doublereal *cpbar) const
Returns an array of partial molar entropies for the species in the mixture.
XML_Node & child(const size_t n) const
Return a changeable reference to the n'th child of the current node.
Definition: xml.cpp:573
virtual void getdlnActCoeffds(const doublereal dTds, const doublereal *const dXds, doublereal *dlnActCoeffds) const
Get the change in activity coefficients w.r.t.
Base class for a phase with thermodynamic properties.
Definition: ThermoPhase.h:97
vector_fp m_SE_d_ij
Entropy term for the quaternary mole fraction interaction of the excess Gibbs free energy expression...
size_t speciesIndex(const std::string &name) const
Returns the index of a species named 'name' within the Phase object.
Definition: Phase.cpp:257
bool importPhase(XML_Node &phase, ThermoPhase *th, SpeciesThermoFactory *spfactory)
Import a phase information into an empty ThermoPhase object.
virtual ThermoPhase * duplMyselfAsThermoPhase() const
Duplication routine for objects which inherit from ThermoPhase.
vector_fp m_SE_b_ij
Entropy term for the binary mole fraction interaction of the excess Gibbs free energy expression...
void s_update_dlnActCoeff_dlnN() const
Update the derivative of the log of the activity coefficients wrt log(moles_m)
void getElectrochemPotentials(doublereal *mu) const
Get the species electrochemical potentials.
std::string fp2str(const double x, const std::string &fmt)
Convert a double into a c++ string.
Definition: stringUtils.cpp:28
virtual doublereal enthalpy_mole() const
Molar enthalpy. Units: J/kmol.
std::string name() const
Returns the name of the XML node.
Definition: xml.h:394
Base class for exceptions thrown by Cantera classes.
Definition: ctexceptions.h:99
virtual void getPartialMolarEntropies(doublereal *sbar) const
Returns an array of partial molar entropies for the species in the mixture.
virtual void getPartialMolarEnthalpies(doublereal *hbar) const
Returns an array of partial molar enthalpies for the species in the mixture.
bool hasChild(const std::string &ch) const
Tests whether the current node has a child node with a particular name.
Definition: xml.cpp:563
vector_fp m_VHE_b_ij
Enthalpy term for the binary mole fraction interaction of the excess Gibbs free energy expression...
void s_update_dlnActCoeff_dlnN_diag() const
Update the derivative of the log of the activity coefficients wrt log(moles) - diagonal only...
virtual void getChemPotentials(doublereal *mu) const
Get the species chemical potentials. Units: J/kmol.
virtual void getLnActivityCoefficients(doublereal *lnac) const
Get the array of non-dimensional molar-based ln activity coefficients at the current solution tempera...
vector_fp m_VSE_b_ij
Entropy term for the binary mole fraction interaction of the excess Gibbs free energy expression...
size_t nSpecies() const
Returns the number of species in the phase.
Definition: Phase.h:265
std::vector< doublereal > dlnActCoeffdlnX_diag_
Storage for the current derivative values of the gradients with respect to logarithm of the mole frac...
std::vector< size_t > m_pSpecies_B_ij
vector of species indices representing species B in the interaction
virtual void getdlnActCoeffdlnX_diag(doublereal *dlnActCoeffdlnX_diag) const
Get the array of log concentration-like derivatives of the log activity coefficients - diagonal compo...
MargulesVPSSTP & operator=(const MargulesVPSSTP &b)
Assignment operator.
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:602
vector_fp m_VHE_c_ij
Enthalpy term for the ternary mole fraction interaction of the excess Gibbs free energy expression...
std::string id() const
Return the id attribute, if present.
Definition: xml.cpp:448
const doublereal SmallNumber
smallest number to compare to zero.
Definition: ct_defs.h:126
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:157
MargulesVPSSTP()
Constructor.
size_t getFloatArray(const 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:323
std::vector< doublereal > moleFractions_
Storage for the current values of the mole fractions of the species.
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:64
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 s_update_lnActCoeff() const
Update the activity coefficients.
vector_fp m_SE_c_ij
Entropy term for the ternary mole fraction interaction of the excess Gibbs free energy expression...
virtual void getPartialMolarVolumes(doublereal *vbar) const
Return an array of partial molar volumes for the species in the mixture.
MargulesVPSSTP is a derived class of GibbsExcessVPSSTP that employs the Margules approximation for th...
vector_fp m_HE_c_ij
Enthalpy term for the ternary mole fraction interaction of the excess Gibbs free energy expression...
int formTempModel_
form of the temperature dependence of the Margules interaction expression
virtual doublereal cp_mole() const
Molar heat capacity at constant pressure. Units: J/kmol/K.
size_t m_kk
Number of species in the phase.
Definition: Phase.h:843
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:251
virtual void initThermoFile(const std::string &inputFile, const std::string &id)
void s_update_dlnActCoeff_dT() const
Update the derivative of the log of the activity coefficients wrt T.
virtual void getStandardChemPotentials(doublereal *mu) const
Get the array of chemical potentials at unit activity.
void s_update_dlnActCoeff_dlnX_diag() const
Update the derivative of the log of the activity coefficients wrt log(mole fraction) ...
virtual doublereal cv_mole() const
Molar heat capacity at constant volume. Units: J/kmol/K.
std::string speciesName(size_t k) const
Name of the species with index k.
Definition: Phase.cpp:272
size_t nChildren(bool discardComments=false) const
Return the number of children.
Definition: xml.cpp:583
std::vector< doublereal > dlnActCoeffdT_Scaled_
Storage for the current derivative values of the gradients with respect to temperature of the log of ...
virtual void getdlnActCoeffdlnN_diag(doublereal *dlnActCoeffdlnN_diag) const
Get the array of derivatives of the log activity coefficients wrt mole numbers - diagonal only...
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:578