Cantera  2.3.0
IdealMolalSoln.cpp
Go to the documentation of this file.
1 /**
2  * @file IdealMolalSoln.cpp
3  * ThermoPhase object for the ideal molal equation of
4  * state (see \ref thermoprops
5  * and class \link Cantera::IdealMolalSoln IdealMolalSoln\endlink).
6  *
7  * Definition file for a derived class of ThermoPhase that handles variable
8  * pressure standard state methods for calculating thermodynamic properties that
9  * are further based upon activities on the molality scale. The Ideal molal
10  * solution assumes that all molality-based activity coefficients are equal to
11  * one. This turns out, actually, to be highly nonlinear when the solvent
12  * densities get low.
13  */
14 
15 // This file is part of Cantera. See License.txt in the top-level directory or
16 // at http://www.cantera.org/license.txt for license and copyright information.
17 
20 #include "cantera/base/ctml.h"
21 #include <iostream>
22 
23 namespace Cantera
24 {
25 
27  m_formGC(2),
28  IMS_typeCutoff_(0),
29  IMS_X_o_cutoff_(0.20),
30  IMS_gamma_o_min_(0.00001),
31  IMS_gamma_k_min_(10.0),
32  IMS_slopefCut_(0.6),
33  IMS_slopegCut_(0.0),
34  IMS_cCut_(.05),
35  IMS_dfCut_(0.0),
36  IMS_efCut_(0.0),
37  IMS_afCut_(0.0),
38  IMS_bfCut_(0.0),
39  IMS_dgCut_(0.0),
40  IMS_egCut_(0.0),
41  IMS_agCut_(0.0),
42  IMS_bgCut_(0.0)
43 {
44 }
45 
48 {
49  // Use the assignment operator to do the brunt of the work for the copy
50  // constructor.
51  *this = b;
52 }
53 
54 IdealMolalSoln& IdealMolalSoln::operator=(const IdealMolalSoln& b)
55 {
56  if (&b != this) {
57  MolalityVPSSTP::operator=(b);
58  m_speciesMolarVolume = b.m_speciesMolarVolume;
59  m_formGC = b.m_formGC;
60  IMS_typeCutoff_ = b.IMS_typeCutoff_;
61  IMS_X_o_cutoff_ = b.IMS_X_o_cutoff_;
62  IMS_gamma_o_min_ = b.IMS_gamma_o_min_;
63  IMS_gamma_k_min_ = b.IMS_gamma_k_min_;
64  IMS_cCut_ = b.IMS_cCut_;
65  IMS_slopefCut_ = b.IMS_slopefCut_;
66  IMS_dfCut_ = b.IMS_dfCut_;
67  IMS_efCut_ = b.IMS_efCut_;
68  IMS_afCut_ = b.IMS_afCut_;
69  IMS_bfCut_ = b.IMS_bfCut_;
70  IMS_slopegCut_ = b.IMS_slopegCut_;
71  IMS_dgCut_ = b.IMS_dgCut_;
72  IMS_egCut_ = b.IMS_egCut_;
73  IMS_agCut_ = b.IMS_agCut_;
74  IMS_bgCut_ = b.IMS_bgCut_;
75  m_tmpV = b.m_tmpV;
76  IMS_lnActCoeffMolal_ = b.IMS_lnActCoeffMolal_;
77  }
78  return *this;
79 }
80 
81 IdealMolalSoln::IdealMolalSoln(const std::string& inputFile,
82  const std::string& id_) :
84  m_formGC(2),
85  IMS_typeCutoff_(0),
86  IMS_X_o_cutoff_(0.2),
87  IMS_gamma_o_min_(0.00001),
88  IMS_gamma_k_min_(10.0),
89  IMS_slopefCut_(0.6),
90  IMS_slopegCut_(0.0),
91  IMS_cCut_(.05),
92  IMS_dfCut_(0.0),
93  IMS_efCut_(0.0),
94  IMS_afCut_(0.0),
95  IMS_bfCut_(0.0),
96  IMS_dgCut_(0.0),
97  IMS_egCut_(0.0),
98  IMS_agCut_(0.0),
99  IMS_bgCut_(0.0)
100 {
101  initThermoFile(inputFile, id_);
102 }
103 
104 IdealMolalSoln::IdealMolalSoln(XML_Node& root, const std::string& id_) :
105  MolalityVPSSTP(),
106  m_formGC(2),
107  IMS_typeCutoff_(0),
108  IMS_X_o_cutoff_(0.2),
109  IMS_gamma_o_min_(0.00001),
110  IMS_gamma_k_min_(10.0),
111  IMS_slopefCut_(0.6),
112  IMS_slopegCut_(0.0),
113  IMS_cCut_(.05),
114  IMS_dfCut_(0.0),
115  IMS_efCut_(0.0),
116  IMS_afCut_(0.0),
117  IMS_bfCut_(0.0),
118  IMS_dgCut_(0.0),
119  IMS_egCut_(0.0),
120  IMS_agCut_(0.0),
121  IMS_bgCut_(0.0)
122 {
123  importPhase(root, this);
124 }
125 
127 {
128  return new IdealMolalSoln(*this);
129 }
130 
132 {
134  return mean_X(m_tmpV);
135 }
136 
138 {
140  return mean_X(m_tmpV);
141 }
142 
144 {
146  return mean_X(m_tmpV);
147 }
148 
149 doublereal IdealMolalSoln::gibbs_mole() const
150 {
151  getChemPotentials(m_tmpV.data());
152  return mean_X(m_tmpV);
153 }
154 
155 doublereal IdealMolalSoln::cp_mole() const
156 {
157  getPartialMolarCp(m_tmpV.data());
158  return mean_X(m_tmpV);
159 }
160 
161 // ------- Mechanical Equation of State Properties ------------------------
162 
164 {
166  doublereal dd = meanMolecularWeight() / mean_X(m_tmpV);
167  Phase::setDensity(dd);
168 }
169 
171 {
172  return 0.0;
173 }
174 
176 {
177  return 0.0;
178 }
179 
180 void IdealMolalSoln::setDensity(const doublereal rho)
181 {
182  if (rho != density()) {
183  throw CanteraError("Idea;MolalSoln::setDensity",
184  "Density is not an independent variable");
185  }
186 }
187 
188 void IdealMolalSoln::setMolarDensity(const doublereal conc)
189 {
190  if (conc != Phase::molarDensity()) {
191  throw CanteraError("IdealMolalSoln::setMolarDensity",
192  "molarDensity/denisty is not an independent variable");
193  }
194 }
195 
196 // ------- Activities and Activity Concentrations
197 
199 {
200  if (m_formGC != 1) {
201  double c_solvent = standardConcentration();
202  getActivities(c);
203  for (size_t k = 0; k < m_kk; k++) {
204  c[k] *= c_solvent;
205  }
206  } else {
207  getActivities(c);
208  for (size_t k = 0; k < m_kk; k++) {
209  double c0 = standardConcentration(k);
210  c[k] *= c0;
211  }
212  }
213 }
214 
215 doublereal IdealMolalSoln::standardConcentration(size_t k) const
216 {
217  double c0 = 1.0;
218  switch (m_formGC) {
219  case 0:
220  break;
221  case 1:
222  return c0 = 1.0 /m_speciesMolarVolume[m_indexSolvent];
223  break;
224  case 2:
226  break;
227  }
228  return c0;
229 }
230 
231 void IdealMolalSoln::getActivities(doublereal* ac) const
232 {
234 
235  // Update the molality array, m_molalities(). This requires an update due to
236  // mole fractions
237  if (IMS_typeCutoff_ == 0) {
238  calcMolalities();
239  for (size_t k = 0; k < m_kk; k++) {
240  ac[k] = m_molalities[k];
241  }
242  double xmolSolvent = moleFraction(m_indexSolvent);
243  // Limit the activity coefficient to be finite as the solvent mole
244  // fraction goes to zero.
245  xmolSolvent = std::max(m_xmolSolventMIN, xmolSolvent);
246  ac[m_indexSolvent] =
247  exp((xmolSolvent - 1.0)/xmolSolvent);
248  } else {
249 
251 
252  // Now calculate the array of activities.
253  for (size_t k = 1; k < m_kk; k++) {
254  ac[k] = m_molalities[k] * exp(IMS_lnActCoeffMolal_[k]);
255  }
256  double xmolSolvent = moleFraction(m_indexSolvent);
257  ac[m_indexSolvent] =
258  exp(IMS_lnActCoeffMolal_[m_indexSolvent]) * xmolSolvent;
259  }
260 }
261 
262 void IdealMolalSoln::getMolalityActivityCoefficients(doublereal* acMolality) const
263 {
264  if (IMS_typeCutoff_ == 0) {
265  for (size_t k = 0; k < m_kk; k++) {
266  acMolality[k] = 1.0;
267  }
268  double xmolSolvent = moleFraction(m_indexSolvent);
269  // Limit the activity coefficient to be finite as the solvent mole
270  // fraction goes to zero.
271  xmolSolvent = std::max(m_xmolSolventMIN, xmolSolvent);
272  acMolality[m_indexSolvent] =
273  exp((xmolSolvent - 1.0)/xmolSolvent) / xmolSolvent;
274  } else {
276  std::copy(IMS_lnActCoeffMolal_.begin(), IMS_lnActCoeffMolal_.end(), acMolality);
277  for (size_t k = 0; k < m_kk; k++) {
278  acMolality[k] = exp(acMolality[k]);
279  }
280  }
281 }
282 
283 // ------ Partial Molar Properties of the Solution -----------------
284 
285 void IdealMolalSoln::getChemPotentials(doublereal* mu) const
286 {
287  // Assertion is made for speed
288  AssertThrow(m_indexSolvent == 0, "solvent not the first species");
289 
290  // First get the standard chemical potentials. This requires updates of
291  // standard state as a function of T and P These are defined at unit
292  // molality.
294 
295  // Update the molality array, m_molalities(). This requires an update due to
296  // mole fractions
297  calcMolalities();
298 
299  // get the solvent mole fraction
300  double xmolSolvent = moleFraction(m_indexSolvent);
301 
302  if (IMS_typeCutoff_ == 0 || xmolSolvent > 3.* IMS_X_o_cutoff_/2.0) {
303  for (size_t k = 1; k < m_kk; k++) {
304  double xx = std::max(m_molalities[k], SmallNumber);
305  mu[k] += RT() * log(xx);
306  }
307 
308  // Do the solvent
309  // -> see my notes
310  double xx = std::max(xmolSolvent, SmallNumber);
311  mu[m_indexSolvent] +=
312  (RT() * (xmolSolvent - 1.0) / xx);
313  } else {
314  // Update the activity coefficients. This also updates the internal
315  // molality array.
317 
318  for (size_t k = 1; k < m_kk; k++) {
319  double xx = std::max(m_molalities[k], SmallNumber);
320  mu[k] += RT() * (log(xx) + IMS_lnActCoeffMolal_[k]);
321  }
322  double xx = std::max(xmolSolvent, SmallNumber);
323  mu[m_indexSolvent] +=
324  RT() * (log(xx) + IMS_lnActCoeffMolal_[m_indexSolvent]);
325  }
326 }
327 
328 void IdealMolalSoln::getPartialMolarEnthalpies(doublereal* hbar) const
329 {
330  getEnthalpy_RT(hbar);
331  for (size_t k = 0; k < m_kk; k++) {
332  hbar[k] *= RT();
333  }
334 }
335 
336 void IdealMolalSoln::getPartialMolarEntropies(doublereal* sbar) const
337 {
338  getEntropy_R(sbar);
339  calcMolalities();
340  if (IMS_typeCutoff_ == 0) {
341  for (size_t k = 0; k < m_kk; k++) {
342  if (k != m_indexSolvent) {
343  doublereal mm = std::max(SmallNumber, m_molalities[k]);
344  sbar[k] -= GasConstant * log(mm);
345  }
346  }
347  double xmolSolvent = moleFraction(m_indexSolvent);
348  sbar[m_indexSolvent] -= (GasConstant * (xmolSolvent - 1.0) / xmolSolvent);
349  } else {
350  // Update the activity coefficients, This also update the internally
351  // stored molalities.
353 
354  // First we will add in the obvious dependence on the T term out front
355  // of the log activity term
356  doublereal mm;
357  for (size_t k = 0; k < m_kk; k++) {
358  if (k != m_indexSolvent) {
359  mm = std::max(SmallNumber, m_molalities[k]);
360  sbar[k] -= GasConstant * (log(mm) + IMS_lnActCoeffMolal_[k]);
361  }
362  }
363  double xmolSolvent = moleFraction(m_indexSolvent);
364  mm = std::max(SmallNumber, xmolSolvent);
366  }
367 }
368 
369 void IdealMolalSoln::getPartialMolarVolumes(doublereal* vbar) const
370 {
371  getStandardVolumes(vbar);
372 }
373 
374 void IdealMolalSoln::getPartialMolarCp(doublereal* cpbar) const
375 {
376  // Get the nondimensional Gibbs standard state of the species at the T and P
377  // of the solution.
378  getCp_R(cpbar);
379  for (size_t k = 0; k < m_kk; k++) {
380  cpbar[k] *= GasConstant;
381  }
382 }
383 
384 // -------------- Utilities -------------------------------
385 
386 bool IdealMolalSoln::addSpecies(shared_ptr<Species> spec)
387 {
388  bool added = MolalityVPSSTP::addSpecies(spec);
389  if (added) {
390  m_speciesMolarVolume.push_back(0.0);
391  m_tmpV.push_back(0.0);
392  IMS_lnActCoeffMolal_.push_back(0.0);
393  }
394  return added;
395 }
396 
397 void IdealMolalSoln::initThermoXML(XML_Node& phaseNode, const std::string& id_)
398 {
399  // Initialize the whole thermo object, using a virtual function.
400  initThermo();
401 
402  if (id_.size() > 0 && phaseNode.id() != id_) {
403  throw CanteraError("IdealMolalSoln::initThermo",
404  "phasenode and Id are incompatible");
405  }
406 
407  // Find the Thermo XML node
408  if (!phaseNode.hasChild("thermo")) {
409  throw CanteraError("IdealMolalSoln::initThermo",
410  "no thermo XML node");
411  }
412  XML_Node& thermoNode = phaseNode.child("thermo");
413 
414  // Possible change the form of the standard concentrations
415  if (thermoNode.hasChild("standardConc")) {
416  XML_Node& scNode = thermoNode.child("standardConc");
417  m_formGC = 2;
418  std::string formString = scNode.attrib("model");
419  if (formString != "") {
420  if (formString == "unity") {
421  m_formGC = 0;
422  } else if (formString == "molar_volume") {
423  m_formGC = 1;
424  } else if (formString == "solvent_volume") {
425  m_formGC = 2;
426  } else {
427  throw CanteraError("IdealMolalSoln::initThermo",
428  "Unknown standardConc model: " + formString);
429  }
430  }
431  }
432 
433  // Get the Name of the Solvent:
434  // <solvent> solventName </solvent>
435  std::string solventName = "";
436  if (thermoNode.hasChild("solvent")) {
437  std::vector<std::string> nameSolventa;
438  getStringArray(thermoNode.child("solvent"), nameSolventa);
439  if (nameSolventa.size() != 1) {
440  throw CanteraError("IdealMolalSoln::initThermoXML",
441  "badly formed solvent XML node");
442  }
443  solventName = nameSolventa[0];
444  }
445 
446  if (thermoNode.hasChild("activityCoefficients")) {
447  XML_Node& acNode = thermoNode.child("activityCoefficients");
448  std::string modelString = acNode.attrib("model");
449  IMS_typeCutoff_ = 0;
450  if (modelString != "IdealMolalSoln") {
451  throw CanteraError("IdealMolalSoln::initThermoXML",
452  "unknown ActivityCoefficient model: " + modelString);
453  }
454  if (acNode.hasChild("idealMolalSolnCutoff")) {
455  XML_Node& ccNode = acNode.child("idealMolalSolnCutoff");
456  modelString = ccNode.attrib("model");
457  if (modelString != "") {
458  if (modelString == "polyExp") {
459  IMS_typeCutoff_ = 2;
460  } else if (modelString == "poly") {
461  IMS_typeCutoff_ = 1;
462  } else {
463  throw CanteraError("IdealMolalSoln::initThermoXML",
464  "Unknown idealMolalSolnCutoff form: " + modelString);
465  }
466 
467  if (ccNode.hasChild("gamma_o_limit")) {
468  IMS_gamma_o_min_ = getFloat(ccNode, "gamma_o_limit");
469  }
470  if (ccNode.hasChild("gamma_k_limit")) {
471  IMS_gamma_k_min_ = getFloat(ccNode, "gamma_k_limit");
472  }
473  if (ccNode.hasChild("X_o_cutoff")) {
474  IMS_X_o_cutoff_ = getFloat(ccNode, "X_o_cutoff");
475  }
476  if (ccNode.hasChild("c_0_param")) {
477  IMS_cCut_ = getFloat(ccNode, "c_0_param");
478  }
479  if (ccNode.hasChild("slope_f_limit")) {
480  IMS_slopefCut_ = getFloat(ccNode, "slope_f_limit");
481  }
482  if (ccNode.hasChild("slope_g_limit")) {
483  IMS_slopegCut_ = getFloat(ccNode, "slope_g_limit");
484  }
485  }
486  }
487  }
488 
489  // Reconcile the solvent name and index.
490  for (size_t k = 0; k < m_kk; k++) {
491  if (solventName == speciesName(k)) {
492  m_indexSolvent = k;
493  break;
494  }
495  }
496  if (m_indexSolvent == npos) {
497  std::cout << "IdealMolalSoln::initThermo: Solvent Name not found"
498  << std::endl;
499  throw CanteraError("IdealMolalSoln::initThermo",
500  "Solvent name not found");
501  }
502  if (m_indexSolvent != 0) {
503  throw CanteraError("IdealMolalSoln::initThermo",
504  "Solvent " + solventName +
505  " should be first species");
506  }
507 
508  // Now go get the molar volumes
509  XML_Node& speciesList = phaseNode.child("speciesArray");
510  XML_Node* speciesDB =
511  get_XML_NameID("speciesData", speciesList["datasrc"],
512  &phaseNode.root());
513  const std::vector<std::string> &sss = speciesNames();
514 
515  for (size_t k = 0; k < m_kk; k++) {
516  XML_Node* s = speciesDB->findByAttr("name", sss[k]);
517  XML_Node* ss = s->findByName("standardState");
518  m_speciesMolarVolume[k] = getFloat(*ss, "molarVolume", "toSI");
519  }
520 
521  IMS_typeCutoff_ = 2;
522  if (IMS_typeCutoff_ == 2) {
524  }
525 
526  MolalityVPSSTP::initThermoXML(phaseNode, id_);
527  setMoleFSolventMin(1.0E-5);
528 
529  // Set the state
530  if (phaseNode.hasChild("state")) {
531  XML_Node& stateNode = phaseNode.child("state");
532  setStateFromXML(stateNode);
533  }
534 }
535 
536 // ------------ Private and Restricted Functions ------------------
537 
539 {
540  // Calculate the molalities. Currently, the molalities may not be current
541  // with respect to the contents of the State objects' data.
542  calcMolalities();
543 
544  double xmolSolvent = moleFraction(m_indexSolvent);
545  double xx = std::max(m_xmolSolventMIN, xmolSolvent);
546 
547  if (IMS_typeCutoff_ == 0) {
548  for (size_t k = 1; k < m_kk; k++) {
549  IMS_lnActCoeffMolal_[k]= 0.0;
550  }
551  IMS_lnActCoeffMolal_[m_indexSolvent] = - log(xx) + (xx - 1.0)/xx;
552  return;
553  } else if (IMS_typeCutoff_ == 1) {
554  if (xmolSolvent > 3.0 * IMS_X_o_cutoff_/2.0) {
555  for (size_t k = 1; k < m_kk; k++) {
556  IMS_lnActCoeffMolal_[k]= 0.0;
557  }
558  IMS_lnActCoeffMolal_[m_indexSolvent] = - log(xx) + (xx - 1.0)/xx;
559  return;
560  } else if (xmolSolvent < IMS_X_o_cutoff_/2.0) {
561  double tmp = log(xx * IMS_gamma_k_min_);
562  for (size_t k = 1; k < m_kk; k++) {
563  IMS_lnActCoeffMolal_[k]= tmp;
564  }
566  return;
567  } else {
568  // If we are in the middle region, calculate the connecting polynomials
569  double xminus = xmolSolvent - IMS_X_o_cutoff_/2.0;
570  double xminus2 = xminus * xminus;
571  double xminus3 = xminus2 * xminus;
572  double x_o_cut2 = IMS_X_o_cutoff_ * IMS_X_o_cutoff_;
573  double x_o_cut3 = x_o_cut2 * IMS_X_o_cutoff_;
574 
575  double h2 = 3.5 * xminus2 / IMS_X_o_cutoff_ - 2.0 * xminus3 / x_o_cut2;
576  double h2_prime = 7.0 * xminus / IMS_X_o_cutoff_ - 6.0 * xminus2 / x_o_cut2;
577 
578  double h1 = (1.0 - 3.0 * xminus2 / x_o_cut2 + 2.0 * xminus3/ x_o_cut3);
579  double h1_prime = (- 6.0 * xminus / x_o_cut2 + 6.0 * xminus2/ x_o_cut3);
580 
581  double h1_g = h1 / IMS_gamma_o_min_;
582  double h1_g_prime = h1_prime / IMS_gamma_o_min_;
583 
584  double alpha = 1.0 / (exp(1.0) * IMS_gamma_k_min_);
585  double h1_f = h1 * alpha;
586  double h1_f_prime = h1_prime * alpha;
587 
588  double f = h2 + h1_f;
589  double f_prime = h2_prime + h1_f_prime;
590 
591  double g = h2 + h1_g;
592  double g_prime = h2_prime + h1_g_prime;
593 
594  double tmp = (xmolSolvent/ g * g_prime + (1.0-xmolSolvent) / f * f_prime);
595  double lngammak = -1.0 - log(f) + tmp * xmolSolvent;
596  double lngammao =-log(g) - tmp * (1.0-xmolSolvent);
597 
598  tmp = log(xmolSolvent) + lngammak;
599  for (size_t k = 1; k < m_kk; k++) {
600  IMS_lnActCoeffMolal_[k]= tmp;
601  }
603  }
604  } else if (IMS_typeCutoff_ == 2) {
605  // Exponentials - trial 2
606  if (xmolSolvent > IMS_X_o_cutoff_) {
607  for (size_t k = 1; k < m_kk; k++) {
608  IMS_lnActCoeffMolal_[k]= 0.0;
609  }
610  IMS_lnActCoeffMolal_[m_indexSolvent] = - log(xx) + (xx - 1.0)/xx;
611  return;
612  } else {
613  double xoverc = xmolSolvent/IMS_cCut_;
614  double eterm = std::exp(-xoverc);
615 
616  double fptmp = IMS_bfCut_ - IMS_afCut_ / IMS_cCut_ - IMS_bfCut_*xoverc
617  + 2.0*IMS_dfCut_*xmolSolvent - IMS_dfCut_*xmolSolvent*xoverc;
618  double f_prime = 1.0 + eterm*fptmp;
619  double f = xmolSolvent + IMS_efCut_ + eterm * (IMS_afCut_ + xmolSolvent * (IMS_bfCut_ + IMS_dfCut_*xmolSolvent));
620 
621  double gptmp = IMS_bgCut_ - IMS_agCut_ / IMS_cCut_ - IMS_bgCut_*xoverc
622  + 2.0*IMS_dgCut_*xmolSolvent - IMS_dgCut_*xmolSolvent*xoverc;
623  double g_prime = 1.0 + eterm*gptmp;
624  double g = xmolSolvent + IMS_egCut_ + eterm * (IMS_agCut_ + xmolSolvent * (IMS_bgCut_ + IMS_dgCut_*xmolSolvent));
625 
626  double tmp = (xmolSolvent / g * g_prime + (1.0 - xmolSolvent) / f * f_prime);
627  double lngammak = -1.0 - log(f) + tmp * xmolSolvent;
628  double lngammao =-log(g) - tmp * (1.0-xmolSolvent);
629 
630  tmp = log(xx) + lngammak;
631  for (size_t k = 1; k < m_kk; k++) {
632  IMS_lnActCoeffMolal_[k]= tmp;
633  }
635  }
636  }
637 }
638 
640 {
641  IMS_afCut_ = 1.0 / (std::exp(1.0) * IMS_gamma_k_min_);
642  IMS_efCut_ = 0.0;
643  bool converged = false;
644  for (int its = 0; its < 100 && !converged; its++) {
645  double oldV = IMS_efCut_;
646  IMS_afCut_ = 1.0 / (std::exp(1.0) * IMS_gamma_k_min_) - IMS_efCut_;
647  IMS_bfCut_ = IMS_afCut_ / IMS_cCut_ + IMS_slopefCut_ - 1.0;
648  IMS_dfCut_ = ((- IMS_afCut_/IMS_cCut_ + IMS_bfCut_ - IMS_bfCut_*IMS_X_o_cutoff_/IMS_cCut_)
649  /
650  (IMS_X_o_cutoff_*IMS_X_o_cutoff_/IMS_cCut_ - 2.0 * IMS_X_o_cutoff_));
651  double tmp = IMS_afCut_ + IMS_X_o_cutoff_*(IMS_bfCut_ + IMS_dfCut_ * IMS_X_o_cutoff_);
652  double eterm = std::exp(-IMS_X_o_cutoff_/IMS_cCut_);
653  IMS_efCut_ = - eterm * (tmp);
654  if (fabs(IMS_efCut_ - oldV) < 1.0E-14) {
655  converged = true;
656  }
657  }
658  if (!converged) {
659  throw CanteraError(" IdealMolalSoln::calcCutoffParams_()",
660  " failed to converge on the f polynomial");
661  }
662  converged = false;
663  double f_0 = IMS_afCut_ + IMS_efCut_;
664  double f_prime_0 = 1.0 - IMS_afCut_ / IMS_cCut_ + IMS_bfCut_;
665  IMS_egCut_ = 0.0;
666  for (int its = 0; its < 100 && !converged; its++) {
667  double oldV = IMS_egCut_;
668  double lng_0 = -log(IMS_gamma_o_min_) - f_prime_0 / f_0;
669  IMS_agCut_ = exp(lng_0) - IMS_egCut_;
670  IMS_bgCut_ = IMS_agCut_ / IMS_cCut_ + IMS_slopegCut_ - 1.0;
671  IMS_dgCut_ = ((- IMS_agCut_/IMS_cCut_ + IMS_bgCut_ - IMS_bgCut_*IMS_X_o_cutoff_/IMS_cCut_)
672  /
673  (IMS_X_o_cutoff_*IMS_X_o_cutoff_/IMS_cCut_ - 2.0 * IMS_X_o_cutoff_));
674  double tmp = IMS_agCut_ + IMS_X_o_cutoff_*(IMS_bgCut_ + IMS_dgCut_ *IMS_X_o_cutoff_);
675  double eterm = std::exp(-IMS_X_o_cutoff_/IMS_cCut_);
676  IMS_egCut_ = - eterm * (tmp);
677  if (fabs(IMS_egCut_ - oldV) < 1.0E-14) {
678  converged = true;
679  }
680  }
681  if (!converged) {
682  throw CanteraError(" IdealMolalSoln::calcCutoffParams_()",
683  " failed to converge on the g polynomial");
684  }
685 }
686 
687 }
virtual ThermoPhase * duplMyselfAsThermoPhase() const
Duplication routine for objects which inherit from ThermoPhase.
ThermoPhase object for the ideal molal equation of state (see Thermodynamic Properties and class Idea...
virtual doublereal intEnergy_mole() const
Molar internal energy of the solution: Units: J/kmol.
virtual doublereal standardConcentration(size_t k=0) const
Return the standard concentration for the kth species.
virtual void getPartialMolarVolumes(doublereal *vbar) const
CTML ("Cantera Markup Language") is the variant of XML that Cantera uses to store data...
const XML_Node * findByName(const std::string &nm, int depth=100000) const
This routine carries out a recursive search for an XML node based on the name of the node...
Definition: xml.cpp:695
doublereal IMS_slopefCut_
Parameter in the polyExp cutoff treatment.
doublereal IMS_slopegCut_
Parameter in the polyExp cutoff treatment.
virtual void getPartialMolarEntropies(doublereal *sbar) const
Returns an array of partial molar entropies of the species in the solution.
doublereal moleFraction(size_t k) const
Return the mole fraction of a single species.
Definition: Phase.cpp:547
IdealMolalSoln()
Constructor.
const size_t npos
index returned by functions to indicate "no position"
Definition: ct_defs.h:165
Headers for the factory class that can create known ThermoPhase objects (see Thermodynamic Properties...
virtual void getActivities(doublereal *ac) const
vector_fp m_tmpV
vector of size m_kk, used as a temporary holding area.
Class XML_Node is a tree-based representation of the contents of an XML file.
Definition: xml.h:97
virtual void getCp_R(doublereal *cpr) const
Get the nondimensional Heat Capacities at constant pressure for the species standard states at the cu...
virtual void getMolalityActivityCoefficients(doublereal *acMolality) const
virtual doublereal density() const
Density (kg/m^3).
Definition: Phase.h:607
virtual void getPartialMolarCp(doublereal *cpbar) const
Partial molar heat capacity of the solution:. UnitsL J/kmol/K.
doublereal IMS_gamma_k_min_
gamma_k minimum for the cutoff process at the zero solvent point
virtual void setDensity(const doublereal rho)
Overridden setDensity() function is necessary because the density is not an independent variable...
virtual bool addSpecies(shared_ptr< Species > spec)
virtual void setMolarDensity(const doublereal rho)
Overridden setMolarDensity() function is necessary because the density is not an independent variable...
virtual doublereal cp_mole() const
Molar heat capacity of the solution at constant pressure. Units: J/kmol/K.
doublereal IMS_gamma_o_min_
gamma_o value for the cutoff process at the zero solvent point
const std::vector< std::string > & speciesNames() const
Return a const reference to the vector of species names.
Definition: Phase.cpp:273
doublereal mean_X(const doublereal *const Q) const
Evaluate the mole-fraction-weighted mean of an array Q.
Definition: Phase.cpp:690
vector_fp m_speciesMolarVolume
Species molar volume .
doublereal RT() const
Return the Gas Constant multiplied by the current temperature.
Definition: ThermoPhase.h:809
Base class for a phase with thermodynamic properties.
Definition: ThermoPhase.h:93
virtual void getActivityConcentrations(doublereal *c) const
This method returns an array of generalized concentrations.
doublereal molarDensity() const
Molar density (kmol/m^3).
Definition: Phase.cpp:666
virtual doublereal entropy_mole() const
Molar entropy of the solution. Units: J/kmol/K.
virtual void initThermoXML(XML_Node &phaseNode, const std::string &id="")
Import and initialize a ThermoPhase object using an XML tree.
std::string speciesName(size_t k) const
Name of the species with index k.
Definition: Phase.cpp:267
virtual doublereal thermalExpansionCoeff() const
The thermal expansion coefficient. Units: 1/K.
virtual void _updateStandardStateThermo() const
Updates the standard state thermodynamic functions at the current T and P of the solution.
#define AssertThrow(expr, procedure)
Assertion must be true or an error is thrown.
Definition: ctexceptions.h:253
virtual void getStandardChemPotentials(doublereal *mu) const
Get the array of chemical potentials at unit activity for the species at their standard states at the...
Base class for exceptions thrown by Cantera classes.
Definition: ctexceptions.h:65
virtual doublereal enthalpy_mole() const
Molar enthalpy of the solution. Units: J/kmol.
virtual bool addSpecies(shared_ptr< Species > spec)
int IMS_typeCutoff_
Cutoff type.
virtual void setStateFromXML(const XML_Node &state)
Set equation of state parameter values from XML entries.
void importPhase(XML_Node &phase, ThermoPhase *th)
Import a phase information into an empty ThermoPhase object.
void s_updateIMS_lnMolalityActCoeff() const
This function will be called to update the internally stored natural logarithm of the molality activi...
bool hasChild(const std::string &ch) const
Tests whether the current node has a child node with a particular name.
Definition: xml.cpp:536
XML_Node & child(const size_t n) const
Return a changeable reference to the n&#39;th child of the current node.
Definition: xml.cpp:546
XML_Node & root() const
Return the root of the current XML_Node tree.
Definition: xml.cpp:1025
vector_fp m_molalities
Current value of the molalities of the species in the phase.
int m_formGC
The standard concentrations can have three different forms depending on the value of the member attri...
const doublereal SmallNumber
smallest number to compare to zero.
Definition: ct_defs.h:126
std::string attrib(const std::string &attr) const
Function returns the value of an attribute.
Definition: xml.cpp:500
virtual doublereal isothermalCompressibility() const
The isothermal compressibility. Units: 1/Pa.
doublereal meanMolecularWeight() const
The mean molecular weight. Units: (kg/kmol)
Definition: Phase.h:661
void getStringArray(const XML_Node &node, std::vector< std::string > &v)
This function interprets the value portion of an XML element as a string.
Definition: ctml.cpp:470
virtual void getChemPotentials(doublereal *mu) const
Get the species chemical potentials: Units: J/kmol.
virtual void getPartialMolarEnthalpies(doublereal *hbar) const
Returns an array of partial molar enthalpies for the species in the mixture.
std::string id() const
Return the id attribute, if present.
Definition: xml.cpp:428
void calcDensity()
Calculate the density of the mixture using the partial molar volumes and mole fractions as input...
const doublereal GasConstant
Universal Gas Constant. [J/kmol/K].
Definition: ct_defs.h:64
virtual void initThermoXML(XML_Node &phaseNode, const std::string &id)
Import and initialize a ThermoPhase object using an XML tree.
doublereal getFloat(const XML_Node &parent, const std::string &name, const std::string &type)
Get a floating-point value from a child element.
Definition: ctml.cpp:178
size_t m_kk
Number of species in the phase.
Definition: Phase.h:784
virtual void getEntropy_R(doublereal *sr) const
Get the array of nondimensional Entropy functions for the standard state species at the current T and...
XML_Node * findByAttr(const std::string &attr, const std::string &val, int depth=100000) const
This routine carries out a recursive search for an XML node based on an attribute of each XML node...
Definition: xml.cpp:661
virtual void initThermoFile(const std::string &inputFile, const std::string &id)
This phase is based upon the mixing-rule assumption that all molality-based activity coefficients are...
void calcMolalities() const
Calculates the molality of all species and stores the result internally.
Namespace for the Cantera kernel.
Definition: application.cpp:29
size_t m_indexSolvent
Index of the solvent.
virtual doublereal gibbs_mole() const
Molar Gibbs function for the solution: Units J/kmol.
void calcIMSCutoffParams_()
Calculate parameters for cutoff treatments of activity coefficients.
doublereal IMS_X_o_cutoff_
value of the solute mole fraction that centers the cutoff polynomials for the cutoff =1 process; ...
virtual void getEnthalpy_RT(doublereal *hrt) const
Get the nondimensional Enthalpy functions for the species at their standard states at the current T a...
XML_Node * get_XML_NameID(const std::string &nameTarget, const std::string &file_ID, XML_Node *root)
This routine will locate an XML node in either the input XML tree or in another input file specified ...
Definition: global.cpp:252
virtual void getStandardVolumes(doublereal *vol) const
Get the molar volumes of the species standard states at the current T and P of the solution...
virtual void setDensity(const doublereal density_)
Set the internally stored density (kg/m^3) of the phase.
Definition: Phase.h:622
void setMoleFSolventMin(doublereal xmolSolventMIN)
Sets the minimum mole fraction in the molality formulation.
vector_fp IMS_lnActCoeffMolal_
Logarithm of the molal activity coefficients.