Cantera  2.5.1
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 https://cantera.org/license.txt for license and copyright information.
17 
20 #include "cantera/base/ctml.h"
22 
23 #include <iostream>
24 
25 namespace Cantera
26 {
27 
29  m_formGC(2),
30  IMS_typeCutoff_(0),
31  IMS_X_o_cutoff_(0.20),
32  IMS_gamma_o_min_(0.00001),
33  IMS_gamma_k_min_(10.0),
34  IMS_slopefCut_(0.6),
35  IMS_slopegCut_(0.0),
36  IMS_cCut_(.05),
37  IMS_dfCut_(0.0),
38  IMS_efCut_(0.0),
39  IMS_afCut_(0.0),
40  IMS_bfCut_(0.0),
41  IMS_dgCut_(0.0),
42  IMS_egCut_(0.0),
43  IMS_agCut_(0.0),
44  IMS_bgCut_(0.0)
45 {
46 }
47 
48 IdealMolalSoln::IdealMolalSoln(const std::string& inputFile,
49  const std::string& id_) :
51  m_formGC(2),
52  IMS_typeCutoff_(0),
53  IMS_X_o_cutoff_(0.2),
54  IMS_gamma_o_min_(0.00001),
55  IMS_gamma_k_min_(10.0),
56  IMS_slopefCut_(0.6),
57  IMS_slopegCut_(0.0),
58  IMS_cCut_(.05),
59  IMS_dfCut_(0.0),
60  IMS_efCut_(0.0),
61  IMS_afCut_(0.0),
62  IMS_bfCut_(0.0),
63  IMS_dgCut_(0.0),
64  IMS_egCut_(0.0),
65  IMS_agCut_(0.0),
66  IMS_bgCut_(0.0)
67 {
68  initThermoFile(inputFile, id_);
69 }
70 
71 IdealMolalSoln::IdealMolalSoln(XML_Node& root, const std::string& id_) :
73  m_formGC(2),
74  IMS_typeCutoff_(0),
75  IMS_X_o_cutoff_(0.2),
76  IMS_gamma_o_min_(0.00001),
77  IMS_gamma_k_min_(10.0),
78  IMS_slopefCut_(0.6),
79  IMS_slopegCut_(0.0),
80  IMS_cCut_(.05),
81  IMS_dfCut_(0.0),
82  IMS_efCut_(0.0),
83  IMS_afCut_(0.0),
84  IMS_bfCut_(0.0),
85  IMS_dgCut_(0.0),
86  IMS_egCut_(0.0),
87  IMS_agCut_(0.0),
88  IMS_bgCut_(0.0)
89 {
90  importPhase(root, this);
91 }
92 
94 {
96  return mean_X(m_tmpV);
97 }
98 
100 {
102  return mean_X(m_tmpV);
103 }
104 
106 {
108  return mean_X(m_tmpV);
109 }
110 
111 doublereal IdealMolalSoln::gibbs_mole() const
112 {
113  getChemPotentials(m_tmpV.data());
114  return mean_X(m_tmpV);
115 }
116 
117 doublereal IdealMolalSoln::cp_mole() const
118 {
119  getPartialMolarCp(m_tmpV.data());
120  return mean_X(m_tmpV);
121 }
122 
123 // ------- Mechanical Equation of State Properties ------------------------
124 
126 {
128  doublereal dd = meanMolecularWeight() / mean_X(m_tmpV);
130 }
131 
133 {
134  return 0.0;
135 }
136 
138 {
139  return 0.0;
140 }
141 
142 void IdealMolalSoln::setDensity(const doublereal rho)
143 {
144  warn_deprecated("IdealMolalSoln::setDensity",
145  "Overloaded function to be removed after Cantera 2.5. "
146  "Error will be thrown by Phase::setDensity instead");
147  if (rho != density()) {
148  throw CanteraError("IdealMolalSoln::setDensity",
149  "Density is not an independent variable");
150  }
151 }
152 
153 void IdealMolalSoln::setMolarDensity(const doublereal conc)
154 {
155  warn_deprecated("IdealMolalSoln::setMolarDensity",
156  "Overloaded function to be removed after Cantera 2.5. "
157  "Error will be thrown by Phase::setMolarDensity instead");
158  if (conc != Phase::molarDensity()) {
159  throw CanteraError("IdealMolalSoln::setMolarDensity",
160  "molarDensity/density is not an independent variable");
161  }
162 }
163 
164 // ------- Activities and Activity Concentrations
165 
167 {
168  if (m_formGC == 0) {
169  return Units(1.0); // dimensionless
170  } else {
171  // kmol/m^3 for bulk phases
172  return Units(1.0, 0, -static_cast<double>(nDim()), 0, 0, 0, 1);
173  }
174 }
175 
177 {
178  if (m_formGC != 1) {
179  double c_solvent = standardConcentration();
180  getActivities(c);
181  for (size_t k = 0; k < m_kk; k++) {
182  c[k] *= c_solvent;
183  }
184  } else {
185  getActivities(c);
186  for (size_t k = 0; k < m_kk; k++) {
187  double c0 = standardConcentration(k);
188  c[k] *= c0;
189  }
190  }
191 }
192 
193 doublereal IdealMolalSoln::standardConcentration(size_t k) const
194 {
195  switch (m_formGC) {
196  case 0:
197  return 1.0;
198  case 1:
199  return 1.0 / m_speciesMolarVolume[k];
200  case 2:
201  return 1.0 / m_speciesMolarVolume[0];
202  default:
203  throw CanteraError("IdealMolalSoln::standardConcentration",
204  "m_formGC is set to an incorrect value. \
205  Allowed values are 0, 1, and 2");
206  }
207 }
208 
209 void IdealMolalSoln::getActivities(doublereal* ac) const
210 {
212 
213  // Update the molality array, m_molalities(). This requires an update due to
214  // mole fractions
215  if (IMS_typeCutoff_ == 0) {
216  calcMolalities();
217  for (size_t k = 0; k < m_kk; k++) {
218  ac[k] = m_molalities[k];
219  }
220  double xmolSolvent = moleFraction(0);
221  // Limit the activity coefficient to be finite as the solvent mole
222  // fraction goes to zero.
223  xmolSolvent = std::max(m_xmolSolventMIN, xmolSolvent);
224  ac[0] = exp((xmolSolvent - 1.0)/xmolSolvent);
225  } else {
226 
228 
229  // Now calculate the array of activities.
230  for (size_t k = 1; k < m_kk; k++) {
231  ac[k] = m_molalities[k] * exp(IMS_lnActCoeffMolal_[k]);
232  }
233  double xmolSolvent = moleFraction(0);
234  ac[0] = exp(IMS_lnActCoeffMolal_[0]) * xmolSolvent;
235  }
236 }
237 
238 void IdealMolalSoln::getMolalityActivityCoefficients(doublereal* acMolality) const
239 {
240  if (IMS_typeCutoff_ == 0) {
241  for (size_t k = 0; k < m_kk; k++) {
242  acMolality[k] = 1.0;
243  }
244  double xmolSolvent = moleFraction(0);
245  // Limit the activity coefficient to be finite as the solvent mole
246  // fraction goes to zero.
247  xmolSolvent = std::max(m_xmolSolventMIN, xmolSolvent);
248  acMolality[0] = exp((xmolSolvent - 1.0)/xmolSolvent) / xmolSolvent;
249  } else {
251  std::copy(IMS_lnActCoeffMolal_.begin(), IMS_lnActCoeffMolal_.end(), acMolality);
252  for (size_t k = 0; k < m_kk; k++) {
253  acMolality[k] = exp(acMolality[k]);
254  }
255  }
256 }
257 
258 // ------ Partial Molar Properties of the Solution -----------------
259 
260 void IdealMolalSoln::getChemPotentials(doublereal* mu) const
261 {
262  // First get the standard chemical potentials. This requires updates of
263  // standard state as a function of T and P These are defined at unit
264  // molality.
266 
267  // Update the molality array, m_molalities(). This requires an update due to
268  // mole fractions
269  calcMolalities();
270 
271  // get the solvent mole fraction
272  double xmolSolvent = moleFraction(0);
273 
274  if (IMS_typeCutoff_ == 0 || xmolSolvent > 3.* IMS_X_o_cutoff_/2.0) {
275  for (size_t k = 1; k < m_kk; k++) {
276  double xx = std::max(m_molalities[k], SmallNumber);
277  mu[k] += RT() * log(xx);
278  }
279 
280  // Do the solvent
281  // -> see my notes
282  double xx = std::max(xmolSolvent, SmallNumber);
283  mu[0] += (RT() * (xmolSolvent - 1.0) / xx);
284  } else {
285  // Update the activity coefficients. This also updates the internal
286  // molality array.
288 
289  for (size_t k = 1; k < m_kk; k++) {
290  double xx = std::max(m_molalities[k], SmallNumber);
291  mu[k] += RT() * (log(xx) + IMS_lnActCoeffMolal_[k]);
292  }
293  double xx = std::max(xmolSolvent, SmallNumber);
294  mu[0] += RT() * (log(xx) + IMS_lnActCoeffMolal_[0]);
295  }
296 }
297 
298 void IdealMolalSoln::getPartialMolarEnthalpies(doublereal* hbar) const
299 {
300  getEnthalpy_RT(hbar);
301  for (size_t k = 0; k < m_kk; k++) {
302  hbar[k] *= RT();
303  }
304 }
305 
306 void IdealMolalSoln::getPartialMolarEntropies(doublereal* sbar) const
307 {
308  getEntropy_R(sbar);
309  calcMolalities();
310  if (IMS_typeCutoff_ == 0) {
311  for (size_t k = 1; k < m_kk; k++) {
312  doublereal mm = std::max(SmallNumber, m_molalities[k]);
313  sbar[k] -= GasConstant * log(mm);
314  }
315  double xmolSolvent = moleFraction(0);
316  sbar[0] -= (GasConstant * (xmolSolvent - 1.0) / xmolSolvent);
317  } else {
318  // Update the activity coefficients, This also update the internally
319  // stored molalities.
321 
322  // First we will add in the obvious dependence on the T term out front
323  // of the log activity term
324  doublereal mm;
325  for (size_t k = 1; k < m_kk; k++) {
326  mm = std::max(SmallNumber, m_molalities[k]);
327  sbar[k] -= GasConstant * (log(mm) + IMS_lnActCoeffMolal_[k]);
328  }
329  double xmolSolvent = moleFraction(0);
330  mm = std::max(SmallNumber, xmolSolvent);
331  sbar[0] -= GasConstant *(log(mm) + IMS_lnActCoeffMolal_[0]);
332  }
333 }
334 
335 void IdealMolalSoln::getPartialMolarVolumes(doublereal* vbar) const
336 {
337  getStandardVolumes(vbar);
338 }
339 
340 void IdealMolalSoln::getPartialMolarCp(doublereal* cpbar) const
341 {
342  // Get the nondimensional Gibbs standard state of the species at the T and P
343  // of the solution.
344  getCp_R(cpbar);
345  for (size_t k = 0; k < m_kk; k++) {
346  cpbar[k] *= GasConstant;
347  }
348 }
349 
350 // -------------- Utilities -------------------------------
351 
352 bool IdealMolalSoln::addSpecies(shared_ptr<Species> spec)
353 {
354  bool added = MolalityVPSSTP::addSpecies(spec);
355  if (added) {
356  m_speciesMolarVolume.push_back(0.0);
357  m_tmpV.push_back(0.0);
358  IMS_lnActCoeffMolal_.push_back(0.0);
359  }
360  return added;
361 }
362 
363 void IdealMolalSoln::initThermoXML(XML_Node& phaseNode, const std::string& id_)
364 {
365  MolalityVPSSTP::initThermoXML(phaseNode, id_);
366 
367  if (id_.size() > 0 && phaseNode.id() != id_) {
368  throw CanteraError("IdealMolalSoln::initThermoXML",
369  "phasenode and Id are incompatible");
370  }
371 
372  // Find the Thermo XML node
373  if (!phaseNode.hasChild("thermo")) {
374  throw CanteraError("IdealMolalSoln::initThermoXML",
375  "no thermo XML node");
376  }
377  XML_Node& thermoNode = phaseNode.child("thermo");
378 
379  // Possible change the form of the standard concentrations
380  if (thermoNode.hasChild("standardConc")) {
381  XML_Node& scNode = thermoNode.child("standardConc");
382  setStandardConcentrationModel(scNode["model"]);
383  }
384 
385  if (thermoNode.hasChild("activityCoefficients")) {
386  XML_Node& acNode = thermoNode.child("activityCoefficients");
387  std::string modelString = acNode.attrib("model");
388  if (modelString != "IdealMolalSoln") {
389  throw CanteraError("IdealMolalSoln::initThermoXML",
390  "unknown ActivityCoefficient model: " + modelString);
391  }
392  if (acNode.hasChild("idealMolalSolnCutoff")) {
393  XML_Node& ccNode = acNode.child("idealMolalSolnCutoff");
394  modelString = ccNode.attrib("model");
395  if (modelString != "") {
396  setCutoffModel(modelString);
397  if (ccNode.hasChild("gamma_o_limit")) {
398  IMS_gamma_o_min_ = getFloat(ccNode, "gamma_o_limit");
399  }
400  if (ccNode.hasChild("gamma_k_limit")) {
401  IMS_gamma_k_min_ = getFloat(ccNode, "gamma_k_limit");
402  }
403  if (ccNode.hasChild("X_o_cutoff")) {
404  IMS_X_o_cutoff_ = getFloat(ccNode, "X_o_cutoff");
405  }
406  if (ccNode.hasChild("c_0_param")) {
407  IMS_cCut_ = getFloat(ccNode, "c_0_param");
408  }
409  if (ccNode.hasChild("slope_f_limit")) {
410  IMS_slopefCut_ = getFloat(ccNode, "slope_f_limit");
411  }
412  if (ccNode.hasChild("slope_g_limit")) {
413  IMS_slopegCut_ = getFloat(ccNode, "slope_g_limit");
414  }
415  }
416  } else {
417  setCutoffModel("none");
418  }
419  }
420 }
421 
423 {
425 
426  if (m_input.hasKey("standard-concentration-basis")) {
427  setStandardConcentrationModel(m_input["standard-concentration-basis"].asString());
428  }
429  if (m_input.hasKey("cutoff")) {
430  auto& cutoff = m_input["cutoff"].as<AnyMap>();
431  setCutoffModel(cutoff.getString("model", "none"));
432  if (cutoff.hasKey("gamma_o")) {
433  IMS_gamma_o_min_ = cutoff["gamma_o"].asDouble();
434  }
435  if (cutoff.hasKey("gamma_k")) {
436  IMS_gamma_k_min_ = cutoff["gamma_k"].asDouble();
437  }
438  if (cutoff.hasKey("X_o")) {
439  IMS_X_o_cutoff_ = cutoff["X_o"].asDouble();
440  }
441  if (cutoff.hasKey("c_0")) {
442  IMS_cCut_ = cutoff["c_0"].asDouble();
443  }
444  if (cutoff.hasKey("slope_f")) {
445  IMS_slopefCut_ = cutoff["slope_f"].asDouble();
446  }
447  if (cutoff.hasKey("slope_g")) {
448  IMS_slopegCut_ = cutoff["slope_g"].asDouble();
449  }
450  }
451 
452  for (size_t k = 0; k < nSpecies(); k++) {
453  m_speciesMolarVolume[k] = providePDSS(k)->molarVolume();
454  }
455  if (IMS_typeCutoff_ == 2) {
457  }
458  setMoleFSolventMin(1.0E-5);
459 }
460 
461 void IdealMolalSoln::setStandardConcentrationModel(const std::string& model)
462 {
463  if (caseInsensitiveEquals(model, "unity")) {
464  m_formGC = 0;
465  } else if (caseInsensitiveEquals(model, "species-molar-volume")
466  || caseInsensitiveEquals(model, "molar_volume")) {
467  m_formGC = 1;
468  } else if (caseInsensitiveEquals(model, "solvent-molar-volume")
469  || caseInsensitiveEquals(model, "solvent_volume")) {
470  m_formGC = 2;
471  } else {
472  throw CanteraError("IdealMolalSoln::setStandardConcentrationModel",
473  "Unknown standard concentration model '{}'", model);
474  }
475 }
476 
477 void IdealMolalSoln::setCutoffModel(const std::string& model)
478 {
479  if (caseInsensitiveEquals(model, "none")) {
480  IMS_typeCutoff_ = 0;
481  } else if (caseInsensitiveEquals(model, "poly")) {
482  IMS_typeCutoff_ = 1;
483  } else if (caseInsensitiveEquals(model, "polyexp")) {
484  IMS_typeCutoff_ = 2;
485  } else {
486  throw CanteraError("IdealMolalSoln::setCutoffModel",
487  "Unknown cutoff model '{}'", model);
488  }
489 }
490 
491 // ------------ Private and Restricted Functions ------------------
492 
494 {
495  // Calculate the molalities. Currently, the molalities may not be current
496  // with respect to the contents of the State objects' data.
497  calcMolalities();
498 
499  double xmolSolvent = moleFraction(0);
500  double xx = std::max(m_xmolSolventMIN, xmolSolvent);
501 
502  if (IMS_typeCutoff_ == 0) {
503  for (size_t k = 1; k < m_kk; k++) {
504  IMS_lnActCoeffMolal_[k]= 0.0;
505  }
506  IMS_lnActCoeffMolal_[0] = - log(xx) + (xx - 1.0)/xx;
507  return;
508  } else if (IMS_typeCutoff_ == 1) {
509  if (xmolSolvent > 3.0 * IMS_X_o_cutoff_/2.0) {
510  for (size_t k = 1; k < m_kk; k++) {
511  IMS_lnActCoeffMolal_[k]= 0.0;
512  }
513  IMS_lnActCoeffMolal_[0] = - log(xx) + (xx - 1.0)/xx;
514  return;
515  } else if (xmolSolvent < IMS_X_o_cutoff_/2.0) {
516  double tmp = log(xx * IMS_gamma_k_min_);
517  for (size_t k = 1; k < m_kk; k++) {
518  IMS_lnActCoeffMolal_[k]= tmp;
519  }
521  return;
522  } else {
523  // If we are in the middle region, calculate the connecting polynomials
524  double xminus = xmolSolvent - IMS_X_o_cutoff_/2.0;
525  double xminus2 = xminus * xminus;
526  double xminus3 = xminus2 * xminus;
527  double x_o_cut2 = IMS_X_o_cutoff_ * IMS_X_o_cutoff_;
528  double x_o_cut3 = x_o_cut2 * IMS_X_o_cutoff_;
529 
530  double h2 = 3.5 * xminus2 / IMS_X_o_cutoff_ - 2.0 * xminus3 / x_o_cut2;
531  double h2_prime = 7.0 * xminus / IMS_X_o_cutoff_ - 6.0 * xminus2 / x_o_cut2;
532 
533  double h1 = (1.0 - 3.0 * xminus2 / x_o_cut2 + 2.0 * xminus3/ x_o_cut3);
534  double h1_prime = (- 6.0 * xminus / x_o_cut2 + 6.0 * xminus2/ x_o_cut3);
535 
536  double h1_g = h1 / IMS_gamma_o_min_;
537  double h1_g_prime = h1_prime / IMS_gamma_o_min_;
538 
539  double alpha = 1.0 / (exp(1.0) * IMS_gamma_k_min_);
540  double h1_f = h1 * alpha;
541  double h1_f_prime = h1_prime * alpha;
542 
543  double f = h2 + h1_f;
544  double f_prime = h2_prime + h1_f_prime;
545 
546  double g = h2 + h1_g;
547  double g_prime = h2_prime + h1_g_prime;
548 
549  double tmp = (xmolSolvent/ g * g_prime + (1.0-xmolSolvent) / f * f_prime);
550  double lngammak = -1.0 - log(f) + tmp * xmolSolvent;
551  double lngammao =-log(g) - tmp * (1.0-xmolSolvent);
552 
553  tmp = log(xmolSolvent) + lngammak;
554  for (size_t k = 1; k < m_kk; k++) {
555  IMS_lnActCoeffMolal_[k]= tmp;
556  }
557  IMS_lnActCoeffMolal_[0] = lngammao;
558  }
559  } else if (IMS_typeCutoff_ == 2) {
560  // Exponentials - trial 2
561  if (xmolSolvent > IMS_X_o_cutoff_) {
562  for (size_t k = 1; k < m_kk; k++) {
563  IMS_lnActCoeffMolal_[k]= 0.0;
564  }
565  IMS_lnActCoeffMolal_[0] = - log(xx) + (xx - 1.0)/xx;
566  return;
567  } else {
568  double xoverc = xmolSolvent/IMS_cCut_;
569  double eterm = std::exp(-xoverc);
570 
571  double fptmp = IMS_bfCut_ - IMS_afCut_ / IMS_cCut_ - IMS_bfCut_*xoverc
572  + 2.0*IMS_dfCut_*xmolSolvent - IMS_dfCut_*xmolSolvent*xoverc;
573  double f_prime = 1.0 + eterm*fptmp;
574  double f = xmolSolvent + IMS_efCut_ + eterm * (IMS_afCut_ + xmolSolvent * (IMS_bfCut_ + IMS_dfCut_*xmolSolvent));
575 
576  double gptmp = IMS_bgCut_ - IMS_agCut_ / IMS_cCut_ - IMS_bgCut_*xoverc
577  + 2.0*IMS_dgCut_*xmolSolvent - IMS_dgCut_*xmolSolvent*xoverc;
578  double g_prime = 1.0 + eterm*gptmp;
579  double g = xmolSolvent + IMS_egCut_ + eterm * (IMS_agCut_ + xmolSolvent * (IMS_bgCut_ + IMS_dgCut_*xmolSolvent));
580 
581  double tmp = (xmolSolvent / g * g_prime + (1.0 - xmolSolvent) / f * f_prime);
582  double lngammak = -1.0 - log(f) + tmp * xmolSolvent;
583  double lngammao =-log(g) - tmp * (1.0-xmolSolvent);
584 
585  tmp = log(xx) + lngammak;
586  for (size_t k = 1; k < m_kk; k++) {
587  IMS_lnActCoeffMolal_[k]= tmp;
588  }
589  IMS_lnActCoeffMolal_[0] = lngammao;
590  }
591  }
592 }
593 
595 {
596  IMS_afCut_ = 1.0 / (std::exp(1.0) * IMS_gamma_k_min_);
597  IMS_efCut_ = 0.0;
598  bool converged = false;
599  for (int its = 0; its < 100 && !converged; its++) {
600  double oldV = IMS_efCut_;
601  IMS_afCut_ = 1.0 / (std::exp(1.0) * IMS_gamma_k_min_) - IMS_efCut_;
602  IMS_bfCut_ = IMS_afCut_ / IMS_cCut_ + IMS_slopefCut_ - 1.0;
603  IMS_dfCut_ = ((- IMS_afCut_/IMS_cCut_ + IMS_bfCut_ - IMS_bfCut_*IMS_X_o_cutoff_/IMS_cCut_)
604  /
605  (IMS_X_o_cutoff_*IMS_X_o_cutoff_/IMS_cCut_ - 2.0 * IMS_X_o_cutoff_));
606  double tmp = IMS_afCut_ + IMS_X_o_cutoff_*(IMS_bfCut_ + IMS_dfCut_ * IMS_X_o_cutoff_);
607  double eterm = std::exp(-IMS_X_o_cutoff_/IMS_cCut_);
608  IMS_efCut_ = - eterm * (tmp);
609  if (fabs(IMS_efCut_ - oldV) < 1.0E-14) {
610  converged = true;
611  }
612  }
613  if (!converged) {
614  throw CanteraError("IdealMolalSoln::calcCutoffParams_",
615  "failed to converge on the f polynomial");
616  }
617  converged = false;
618  double f_0 = IMS_afCut_ + IMS_efCut_;
619  double f_prime_0 = 1.0 - IMS_afCut_ / IMS_cCut_ + IMS_bfCut_;
620  IMS_egCut_ = 0.0;
621  for (int its = 0; its < 100 && !converged; its++) {
622  double oldV = IMS_egCut_;
623  double lng_0 = -log(IMS_gamma_o_min_) - f_prime_0 / f_0;
624  IMS_agCut_ = exp(lng_0) - IMS_egCut_;
625  IMS_bgCut_ = IMS_agCut_ / IMS_cCut_ + IMS_slopegCut_ - 1.0;
626  IMS_dgCut_ = ((- IMS_agCut_/IMS_cCut_ + IMS_bgCut_ - IMS_bgCut_*IMS_X_o_cutoff_/IMS_cCut_)
627  /
628  (IMS_X_o_cutoff_*IMS_X_o_cutoff_/IMS_cCut_ - 2.0 * IMS_X_o_cutoff_));
629  double tmp = IMS_agCut_ + IMS_X_o_cutoff_*(IMS_bgCut_ + IMS_dgCut_ *IMS_X_o_cutoff_);
630  double eterm = std::exp(-IMS_X_o_cutoff_/IMS_cCut_);
631  IMS_egCut_ = - eterm * (tmp);
632  if (fabs(IMS_egCut_ - oldV) < 1.0E-14) {
633  converged = true;
634  }
635  }
636  if (!converged) {
637  throw CanteraError("IdealMolalSoln::calcCutoffParams_",
638  "failed to converge on the g polynomial");
639  }
640 }
641 
642 }
ThermoPhase object for the ideal molal equation of state (see Thermodynamic Properties and class Idea...
Headers for the factory class that can create known ThermoPhase objects (see Thermodynamic Properties...
A map of string keys to values whose type can vary at runtime.
Definition: AnyMap.h:360
bool hasKey(const std::string &key) const
Returns true if the map contains an item named key.
Definition: AnyMap.cpp:984
Base class for exceptions thrown by Cantera classes.
Definition: ctexceptions.h:61
void calcIMSCutoffParams_()
Calculate parameters for cutoff treatments of activity coefficients.
void setCutoffModel(const std::string &model)
Set cutoff model. Must be one of 'none', 'poly', or 'polyExp'.
doublereal IMS_slopegCut_
Parameter in the polyExp cutoff treatment.
int IMS_typeCutoff_
Cutoff type.
virtual doublereal cp_mole() const
Molar heat capacity of the solution at constant pressure. Units: J/kmol/K.
virtual void getMolalityActivityCoefficients(doublereal *acMolality) const
virtual void getPartialMolarEnthalpies(doublereal *hbar) const
Returns an array of partial molar enthalpies for the species in the mixture.
virtual void getPartialMolarEntropies(doublereal *sbar) const
Returns an array of partial molar entropies of the species in the solution.
doublereal IMS_slopefCut_
Parameter in the polyExp cutoff treatment.
virtual doublereal enthalpy_mole() const
Molar enthalpy of the solution. Units: J/kmol.
doublereal IMS_X_o_cutoff_
value of the solute mole fraction that centers the cutoff polynomials for the cutoff =1 process;
virtual void getPartialMolarVolumes(doublereal *vbar) const
virtual void getActivityConcentrations(doublereal *c) const
This method returns an array of generalized concentrations.
virtual doublereal thermalExpansionCoeff() const
The thermal expansion coefficient. Units: 1/K.
virtual void getPartialMolarCp(doublereal *cpbar) const
Partial molar heat capacity of the solution:. UnitsL J/kmol/K.
IdealMolalSoln()
Constructor.
virtual void setDensity(const doublereal rho)
Overridden setDensity() function is necessary because the density is not an independent variable.
vector_fp m_speciesMolarVolume
Species molar volume .
virtual doublereal entropy_mole() const
Molar entropy of the solution. Units: J/kmol/K.
doublereal IMS_gamma_o_min_
gamma_o value for the cutoff process at the zero solvent point
int m_formGC
The standard concentrations can have one of three different forms: 0 = 'unity', 1 = 'molar_volume',...
virtual doublereal gibbs_mole() const
Molar Gibbs function for the solution: Units J/kmol.
vector_fp IMS_lnActCoeffMolal_
Logarithm of the molal activity coefficients.
virtual Units standardConcentrationUnits() const
Returns the units of the "standard concentration" for this phase.
doublereal IMS_gamma_k_min_
gamma_k minimum for the cutoff process at the zero solvent point
void setStandardConcentrationModel(const std::string &model)
Set the standard concentration model.
virtual void getChemPotentials(doublereal *mu) const
Get the species chemical potentials: Units: J/kmol.
virtual void setMolarDensity(const doublereal rho)
Overridden setMolarDensity() function is necessary because the density is not an independent variable...
virtual void initThermoXML(XML_Node &phaseNode, const std::string &id="")
Import and initialize a ThermoPhase object using an XML tree.
void s_updateIMS_lnMolalityActCoeff() const
This function will be called to update the internally stored natural logarithm of the molality activi...
virtual void getActivities(doublereal *ac) const
vector_fp m_tmpV
vector of size m_kk, used as a temporary holding area.
virtual doublereal intEnergy_mole() const
Molar internal energy of the solution: Units: J/kmol.
void calcDensity()
Calculate the density of the mixture using the partial molar volumes and mole fractions as input.
virtual doublereal isothermalCompressibility() const
The isothermal compressibility. Units: 1/Pa.
virtual doublereal standardConcentration(size_t k=0) const
Return the standard concentration for the kth species.
void setMoleFSolventMin(doublereal xmolSolventMIN)
Sets the minimum mole fraction in the molality formulation.
void calcMolalities() const
Calculates the molality of all species and stores the result internally.
vector_fp m_molalities
Current value of the molalities of the species in the phase.
virtual doublereal molarVolume() const
Return the molar volume at standard state.
Definition: PDSS.cpp:72
double molarDensity() const
Molar density (kmol/m^3).
Definition: Phase.cpp:700
void assignDensity(const double density_)
Set the internally stored constant density (kg/m^3) of the phase.
Definition: Phase.cpp:727
doublereal mean_X(const doublereal *const Q) const
Evaluate the mole-fraction-weighted mean of an array Q.
Definition: Phase.cpp:746
size_t nSpecies() const
Returns the number of species in the phase.
Definition: Phase.h:285
size_t m_kk
Number of species in the phase.
Definition: Phase.h:942
size_t nDim() const
Returns the number of spatial dimensions (1, 2, or 3)
Definition: Phase.h:651
doublereal meanMolecularWeight() const
The mean molecular weight. Units: (kg/kmol)
Definition: Phase.h:748
double moleFraction(size_t k) const
Return the mole fraction of a single species.
Definition: Phase.cpp:577
virtual double density() const
Density (kg/m^3).
Definition: Phase.h:685
doublereal RT() const
Return the Gas Constant multiplied by the current temperature.
Definition: ThermoPhase.h:776
virtual void initThermoFile(const std::string &inputFile, const std::string &id)
virtual void initThermoXML(XML_Node &phaseNode, const std::string &id)
Import and initialize a ThermoPhase object using an XML tree.
AnyMap m_input
Data supplied via setParameters.
Definition: ThermoPhase.h:1874
A representation of the units associated with a dimensional quantity.
Definition: Units.h:30
virtual bool addSpecies(shared_ptr< Species > spec)
Add a Species to this Phase.
Definition: Phase.cpp:833
virtual void _updateStandardStateThermo() const
Updates the standard state thermodynamic functions at the current T and P of the solution.
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 getCp_R(doublereal *cpr) const
Get the nondimensional Heat Capacities at constant pressure for the species standard states at the cu...
virtual void getEntropy_R(doublereal *sr) const
Get the array of nondimensional Entropy functions for the standard state species at the current T and...
virtual void getStandardChemPotentials(doublereal *mu) const
Get the array of chemical potentials at unit activity for the species at their standard states at the...
virtual void getEnthalpy_RT(doublereal *hrt) const
Get the nondimensional Enthalpy functions for the species at their standard states at the current T a...
Class XML_Node is a tree-based representation of the contents of an XML file.
Definition: xml.h:104
std::string attrib(const std::string &attr) const
Function returns the value of an attribute.
Definition: xml.cpp:492
bool hasChild(const std::string &ch) const
Tests whether the current node has a child node with a particular name.
Definition: xml.cpp:528
std::string id() const
Return the id attribute, if present.
Definition: xml.cpp:538
XML_Node & child(const size_t n) const
Return a changeable reference to the n'th child of the current node.
Definition: xml.cpp:546
CTML ("Cantera Markup Language") is the variant of XML that Cantera uses to store data.
void warn_deprecated(const std::string &method, const std::string &extra)
Print a warning indicating that method is deprecated.
Definition: global.cpp:54
const double SmallNumber
smallest number to compare to zero.
Definition: ct_defs.h:149
const double GasConstant
Universal Gas Constant [J/kmol/K].
Definition: ct_defs.h:109
void importPhase(XML_Node &phase, ThermoPhase *th)
Import a phase information into an empty ThermoPhase object.
Namespace for the Cantera kernel.
Definition: AnyMap.cpp:264
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:164
bool caseInsensitiveEquals(const std::string &input, const std::string &test)
Case insensitive equality predicate.
Contains declarations for string manipulation functions within Cantera.