Cantera  2.2.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
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
8  * variable pressure standard state methods for calculating
9  * thermodynamic properties that are further based upon
10  * activities on the molality scale. The Ideal molal
11  * solution assumes that all molality-based activity
12  * coefficients are equal to one. This turns out, actually, to be
13  * highly nonlinear when the solvent densities get low.
14  */
15 /*
16  * Copyright (2006) Sandia Corporation. Under the terms of
17  * Contract DE-AC04-94AL85000 with Sandia Corporation, the
18  * U.S. Government retains certain rights in this software.
19  */
22 #include "cantera/base/ctml.h"
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 
50 {
51  /*
52  * Use the assignment operator to do the brunt
53  * of the work for the copy constructor.
54  */
55  *this = b;
56 }
57 
59 {
60  if (&b != this) {
63  m_formGC = b.m_formGC;
68  IMS_cCut_ = b.IMS_cCut_;
70  IMS_dfCut_ = b.IMS_dfCut_;
71  IMS_efCut_ = b.IMS_efCut_;
72  IMS_afCut_ = b.IMS_afCut_;
73  IMS_bfCut_ = b.IMS_bfCut_;
75  IMS_dgCut_ = b.IMS_dgCut_;
76  IMS_egCut_ = b.IMS_egCut_;
77  IMS_agCut_ = b.IMS_agCut_;
78  IMS_bgCut_ = b.IMS_bgCut_;
79  m_pp = b.m_pp;
80  m_tmpV = b.m_tmpV;
82  }
83  return *this;
84 }
85 
86 IdealMolalSoln::IdealMolalSoln(const std::string& inputFile,
87  const std::string& id_) :
89  m_formGC(2),
90  IMS_typeCutoff_(0),
91  IMS_X_o_cutoff_(0.2),
92  IMS_gamma_o_min_(0.00001),
93  IMS_gamma_k_min_(10.0),
94  IMS_slopefCut_(0.6),
95  IMS_slopegCut_(0.0),
96  IMS_cCut_(.05),
97  IMS_dfCut_(0.0),
98  IMS_efCut_(0.0),
99  IMS_afCut_(0.0),
100  IMS_bfCut_(0.0),
101  IMS_dgCut_(0.0),
102  IMS_egCut_(0.0),
103  IMS_agCut_(0.0),
104  IMS_bgCut_(0.0)
105 {
106  initThermoFile(inputFile, id_);
107 }
108 
109 IdealMolalSoln::IdealMolalSoln(XML_Node& root, const std::string& id_) :
110  MolalityVPSSTP(),
111  m_formGC(2),
112  IMS_typeCutoff_(0),
113  IMS_X_o_cutoff_(0.2),
114  IMS_gamma_o_min_(0.00001),
115  IMS_gamma_k_min_(10.0),
116  IMS_slopefCut_(0.6),
117  IMS_slopegCut_(0.0),
118  IMS_cCut_(.05),
119  IMS_dfCut_(0.0),
120  IMS_efCut_(0.0),
121  IMS_afCut_(0.0),
122  IMS_bfCut_(0.0),
123  IMS_dgCut_(0.0),
124  IMS_egCut_(0.0),
125  IMS_agCut_(0.0),
126  IMS_bgCut_(0.0)
127 {
128  importPhase(*findXMLPhase(&root, id_), this);
129 }
130 
132 {
133  return new IdealMolalSoln(*this);
134 }
135 
137 {
140  return mean_X(m_tmpV);
141 }
142 
144 {
146  return mean_X(m_tmpV);
147 }
148 
150 {
152  return mean_X(m_tmpV);
153 }
154 
155 doublereal IdealMolalSoln::gibbs_mole() const
156 {
158  return mean_X(m_tmpV);
159 }
160 
161 doublereal IdealMolalSoln::cp_mole() const
162 {
164  return mean_X(m_tmpV);
165 }
166 
167 doublereal IdealMolalSoln::cv_mole() const
168 {
169  throw NotImplementedError("IdealMolalSoln::cv_mole");
170 }
171 
172 //
173 // ------- Mechanical Equation of State Properties ------------------------
174 //
175 
176 void IdealMolalSoln::setPressure(doublereal p)
177 {
178  setState_TP(temperature(), p);
179 }
180 
182 {
183  double* vbar = &m_pp[0];
185  double* x = &m_tmpV[0];
186  getMoleFractions(x);
187  doublereal vtotal = 0.0;
188  for (size_t i = 0; i < m_kk; i++) {
189  vtotal += vbar[i] * x[i];
190  }
191  doublereal dd = meanMolecularWeight() / vtotal;
192  Phase::setDensity(dd);
193 }
194 
196 {
197  return 0.0;
198 }
199 
201 {
202  return 0.0;
203 }
204 
205 void IdealMolalSoln::setDensity(const doublereal rho)
206 {
207  if (rho != density()) {
208  throw CanteraError("Idea;MolalSoln::setDensity",
209  "Density is not an independent variable");
210  }
211 }
212 
213 void IdealMolalSoln::setMolarDensity(const doublereal conc)
214 {
215  if (conc != Phase::molarDensity()) {
216  throw CanteraError("IdealMolalSoln::setMolarDensity",
217  "molarDensity/denisty is not an independent variable");
218  }
219 }
220 
221 void IdealMolalSoln::setState_TP(doublereal temp, doublereal pres)
222 {
223  Phase::setTemperature(temp);
224  m_Pcurrent = pres;
226  calcDensity();
227 }
228 
229 //
230 // ------- Activities and Activity Concentrations
231 //
232 
234 {
235  if (m_formGC != 1) {
236  double c_solvent = standardConcentration();
237  getActivities(c);
238  for (size_t k = 0; k < m_kk; k++) {
239  c[k] *= c_solvent;
240  }
241  } else {
242  getActivities(c);
243  for (size_t k = 0; k < m_kk; k++) {
244  double c0 = standardConcentration(k);
245  c[k] *= c0;
246  }
247  }
248 }
249 
250 doublereal IdealMolalSoln::standardConcentration(size_t k) const
251 {
252  double c0 = 1.0;
253  switch (m_formGC) {
254  case 0:
255  break;
256  case 1:
257  return c0 = 1.0 /m_speciesMolarVolume[m_indexSolvent];
258  break;
259  case 2:
261  break;
262  }
263  return c0;
264 }
265 
266 void IdealMolalSoln::getUnitsStandardConc(double* uA, int k, int sizeUA) const
267 {
268  warn_deprecated("IdealMolalSoln::getUnitsStandardConc",
269  "To be removed after Cantera 2.2.");
270 
271  int eos = eosType();
272  if (eos == 0) {
273  for (int i = 0; i < sizeUA; i++) {
274  uA[i] = 0.0;
275  }
276  } else {
277  for (int i = 0; i < sizeUA; i++) {
278  if (i == 0) {
279  uA[0] = 1.0;
280  }
281  if (i == 1) {
282  uA[1] = -int(nDim());
283  }
284  if (i == 2) {
285  uA[2] = 0.0;
286  }
287  if (i == 3) {
288  uA[3] = 0.0;
289  }
290  if (i == 4) {
291  uA[4] = 0.0;
292  }
293  if (i == 5) {
294  uA[5] = 0.0;
295  }
296  }
297  }
298 }
299 
300 void IdealMolalSoln::getActivities(doublereal* ac) const
301 {
303  /*
304  * Update the molality array, m_molalities()
305  * This requires an update due to mole fractions
306  */
307  if (IMS_typeCutoff_ == 0) {
308  calcMolalities();
309  for (size_t k = 0; k < m_kk; k++) {
310  ac[k] = m_molalities[k];
311  }
312  double xmolSolvent = moleFraction(m_indexSolvent);
313  // Limit the activity coefficient to be finite as the solvent mole
314  // fraction goes to zero.
315  xmolSolvent = std::max(m_xmolSolventMIN, xmolSolvent);
316  ac[m_indexSolvent] =
317  exp((xmolSolvent - 1.0)/xmolSolvent);
318  } else {
319 
321  /*
322  * Now calculate the array of activities.
323  */
324  for (size_t k = 1; k < m_kk; k++) {
325  ac[k] = m_molalities[k] * exp(IMS_lnActCoeffMolal_[k]);
326  }
327  double xmolSolvent = moleFraction(m_indexSolvent);
328  ac[m_indexSolvent] =
329  exp(IMS_lnActCoeffMolal_[m_indexSolvent]) * xmolSolvent;
330 
331  }
332 }
333 
334 void IdealMolalSoln::getMolalityActivityCoefficients(doublereal* acMolality) const
335 {
336  if (IMS_typeCutoff_ == 0) {
337  for (size_t k = 0; k < m_kk; k++) {
338  acMolality[k] = 1.0;
339  }
340  double xmolSolvent = moleFraction(m_indexSolvent);
341  // Limit the activity coefficient to be finite as the solvent mole
342  // fraction goes to zero.
343  xmolSolvent = std::max(m_xmolSolventMIN, xmolSolvent);
344  acMolality[m_indexSolvent] =
345  exp((xmolSolvent - 1.0)/xmolSolvent) / xmolSolvent;
346  } else {
348  std::copy(IMS_lnActCoeffMolal_.begin(), IMS_lnActCoeffMolal_.end(), acMolality);
349  for (size_t k = 0; k < m_kk; k++) {
350  acMolality[k] = exp(acMolality[k]);
351  }
352  }
353 }
354 
355 //
356 // ------ Partial Molar Properties of the Solution -----------------
357 //
358 
359 void IdealMolalSoln::getChemPotentials(doublereal* mu) const
360 {
361  // Assertion is made for speed
362  AssertThrow(m_indexSolvent == 0, "solvent not the first species");
363 
364  /*
365  * First get the standard chemical potentials
366  * -> this requires updates of standard state as a function
367  * of T and P
368  * These are defined at unit molality.
369  */
371  /*
372  * Update the molality array, m_molalities()
373  * This requires an update due to mole fractions
374  */
375  calcMolalities();
376  /*
377  * get the solvent mole fraction
378  */
379  double xmolSolvent = moleFraction(m_indexSolvent);
380  doublereal RT = GasConstant * temperature();
381 
382  if (IMS_typeCutoff_ == 0 || xmolSolvent > 3.* IMS_X_o_cutoff_/2.0) {
383 
384  for (size_t k = 1; k < m_kk; k++) {
385  double xx = std::max(m_molalities[k], SmallNumber);
386  mu[k] += RT * log(xx);
387  }
388  /*
389  * Do the solvent
390  * -> see my notes
391  */
392 
393  double xx = std::max(xmolSolvent, SmallNumber);
394  mu[m_indexSolvent] +=
395  (RT * (xmolSolvent - 1.0) / xx);
396  } else {
397  /*
398  * Update the activity coefficients
399  * This also updates the internal molality array.
400  */
402 
403 
404  for (size_t k = 1; k < m_kk; k++) {
405  double xx = std::max(m_molalities[k], SmallNumber);
406  mu[k] += RT * (log(xx) + IMS_lnActCoeffMolal_[k]);
407  }
408  double xx = std::max(xmolSolvent, SmallNumber);
409  mu[m_indexSolvent] +=
410  RT * (log(xx) + IMS_lnActCoeffMolal_[m_indexSolvent]);
411  }
412 
413 }
414 
415 void IdealMolalSoln::getPartialMolarEnthalpies(doublereal* hbar) const
416 {
417  getEnthalpy_RT(hbar);
418  doublereal RT = _RT();
419  for (size_t k = 0; k < m_kk; k++) {
420  hbar[k] *= RT;
421  }
422 }
423 
424 void IdealMolalSoln::getPartialMolarEntropies(doublereal* sbar) const
425 {
426  getEntropy_R(sbar);
427  calcMolalities();
428  if (IMS_typeCutoff_ == 0) {
429  for (size_t k = 0; k < m_kk; k++) {
430  if (k != m_indexSolvent) {
431  doublereal mm = std::max(SmallNumber, m_molalities[k]);
432  sbar[k] -= GasConstant * log(mm);
433  }
434  }
435  double xmolSolvent = moleFraction(m_indexSolvent);
436  sbar[m_indexSolvent] -= (GasConstant * (xmolSolvent - 1.0) / xmolSolvent);
437  } else {
438  /*
439  * Update the activity coefficients, This also update the
440  * internally stored molalities.
441  */
443  /*
444  * First we will add in the obvious dependence on the T
445  * term out front of the log activity term
446  */
447  doublereal mm;
448  for (size_t k = 0; k < m_kk; k++) {
449  if (k != m_indexSolvent) {
450  mm = std::max(SmallNumber, m_molalities[k]);
451  sbar[k] -= GasConstant * (log(mm) + IMS_lnActCoeffMolal_[k]);
452  }
453  }
454  double xmolSolvent = moleFraction(m_indexSolvent);
455  mm = std::max(SmallNumber, xmolSolvent);
457 
458  }
459 }
460 
461 void IdealMolalSoln::getPartialMolarVolumes(doublereal* vbar) const
462 {
463  getStandardVolumes(vbar);
464 }
465 
466 void IdealMolalSoln::getPartialMolarCp(doublereal* cpbar) const
467 {
468  /*
469  * Get the nondimensional Gibbs standard state of the
470  * species at the T and P of the solution.
471  */
472  getCp_R(cpbar);
473 
474  for (size_t k = 0; k < m_kk; k++) {
475  cpbar[k] *= GasConstant;
476  }
477 }
478 
479 /*
480  * -------------- Utilities -------------------------------
481  */
482 
484 {
485  initLengths();
487 }
488 
489 void IdealMolalSoln::initThermoXML(XML_Node& phaseNode, const std::string& id_)
490 {
491  /*
492  * Find the Thermo XML node
493  */
494  if (!phaseNode.hasChild("thermo")) {
495  throw CanteraError("IdealMolalSoln::initThermoXML",
496  "no thermo XML node");
497  }
498 
499  /*
500  * Initialize the whole thermo object, using a virtual function.
501  */
502  initThermo();
503 
504  if (id_.size() > 0) {
505  if (phaseNode.id() != id_) {
506  throw CanteraError("IdealMolalSoln::initThermo",
507  "phasenode and Id are incompatible");
508  }
509  }
510 
511  /*
512  * Find the Thermo XML node
513  */
514  if (!phaseNode.hasChild("thermo")) {
515  throw CanteraError("IdealMolalSoln::initThermo",
516  "no thermo XML node");
517  }
518  XML_Node& thermoNode = phaseNode.child("thermo");
519 
520  /*
521  * Possible change the form of the standard concentrations
522  */
523  if (thermoNode.hasChild("standardConc")) {
524  XML_Node& scNode = thermoNode.child("standardConc");
525  m_formGC = 2;
526  std::string formString = scNode.attrib("model");
527  if (formString != "") {
528  if (formString == "unity") {
529  m_formGC = 0;
530  } else if (formString == "molar_volume") {
531  m_formGC = 1;
532  } else if (formString == "solvent_volume") {
533  m_formGC = 2;
534  } else {
535  throw CanteraError("IdealMolalSoln::initThermo",
536  "Unknown standardConc model: " + formString);
537  }
538  }
539  }
540 
541  /*
542  * Get the Name of the Solvent:
543  * <solvent> solventName </solvent>
544  */
545  std::string solventName = "";
546  if (thermoNode.hasChild("solvent")) {
547  std::vector<std::string> nameSolventa;
548  getStringArray(thermoNode.child("solvent"), nameSolventa);
549  if (nameSolventa.size() != 1) {
550  throw CanteraError("IdealMolalSoln::initThermoXML",
551  "badly formed solvent XML node");
552  }
553  solventName = nameSolventa[0];
554  }
555 
556  if (thermoNode.hasChild("activityCoefficients")) {
557  XML_Node& acNode = thermoNode.child("activityCoefficients");
558  std::string modelString = acNode.attrib("model");
559  IMS_typeCutoff_ = 0;
560  if (modelString != "IdealMolalSoln") {
561  throw CanteraError("IdealMolalSoln::initThermoXML",
562  "unknown ActivityCoefficient model: " + modelString);
563  }
564  if (acNode.hasChild("idealMolalSolnCutoff")) {
565  XML_Node& ccNode = acNode.child("idealMolalSolnCutoff");
566  modelString = ccNode.attrib("model");
567  if (modelString != "") {
568  if (modelString == "polyExp") {
569  IMS_typeCutoff_ = 2;
570  } else if (modelString == "poly") {
571  IMS_typeCutoff_ = 1;
572  } else {
573  throw CanteraError("IdealMolalSoln::initThermoXML",
574  "Unknown idealMolalSolnCutoff form: " + modelString);
575  }
576 
577  if (ccNode.hasChild("gamma_o_limit")) {
578  IMS_gamma_o_min_ = getFloat(ccNode, "gamma_o_limit");
579  }
580  if (ccNode.hasChild("gamma_k_limit")) {
581  IMS_gamma_k_min_ = getFloat(ccNode, "gamma_k_limit");
582  }
583  if (ccNode.hasChild("X_o_cutoff")) {
584  IMS_X_o_cutoff_ = getFloat(ccNode, "X_o_cutoff");
585  }
586  if (ccNode.hasChild("c_0_param")) {
587  IMS_cCut_ = getFloat(ccNode, "c_0_param");
588  }
589  if (ccNode.hasChild("slope_f_limit")) {
590  IMS_slopefCut_ = getFloat(ccNode, "slope_f_limit");
591  }
592  if (ccNode.hasChild("slope_g_limit")) {
593  IMS_slopegCut_ = getFloat(ccNode, "slope_g_limit");
594  }
595 
596  }
597  }
598  }
599 
600 
601  /*
602  * Reconcile the solvent name and index.
603  */
604  for (size_t k = 0; k < m_kk; k++) {
605  if (solventName == speciesName(k)) {
606  m_indexSolvent = k;
607  break;
608  }
609  }
610  if (m_indexSolvent == npos) {
611  std::cout << "IdealMolalSoln::initThermo: Solvent Name not found"
612  << std::endl;
613  throw CanteraError("IdealMolalSoln::initThermo",
614  "Solvent name not found");
615  }
616  if (m_indexSolvent != 0) {
617  throw CanteraError("IdealMolalSoln::initThermo",
618  "Solvent " + solventName +
619  " should be first species");
620  }
621 
622 
623  /*
624  * Now go get the molar volumes
625  */
626  XML_Node& speciesList = phaseNode.child("speciesArray");
627  XML_Node* speciesDB =
628  get_XML_NameID("speciesData", speciesList["datasrc"],
629  &phaseNode.root());
630  const std::vector<std::string> &sss = speciesNames();
631 
632  for (size_t k = 0; k < m_kk; k++) {
633  XML_Node* s = speciesDB->findByAttr("name", sss[k]);
634  XML_Node* ss = s->findByName("standardState");
635  m_speciesMolarVolume[k] = getFloat(*ss, "molarVolume", "toSI");
636  }
637 
638  IMS_typeCutoff_ = 2;
639  if (IMS_typeCutoff_ == 2) {
641  }
642 
643  MolalityVPSSTP::initThermoXML(phaseNode, id_);
644 
645 
646  setMoleFSolventMin(1.0E-5);
647  /*
648  * Set the state
649  */
650  if (phaseNode.hasChild("state")) {
651  XML_Node& stateNode = phaseNode.child("state");
652  setStateFromXML(stateNode);
653  }
654 
655 }
656 
657 /*
658  * ------------ Private and Restricted Functions ------------------
659  */
660 
662 {
663  /*
664  * Calculate the molalities. Currently, the molalities
665  * may not be current with respect to the contents of the
666  * State objects' data.
667  */
668  calcMolalities();
669 
670  double xmolSolvent = moleFraction(m_indexSolvent);
671  double xx = std::max(m_xmolSolventMIN, xmolSolvent);
672 
673  if (IMS_typeCutoff_ == 0) {
674  for (size_t k = 1; k < m_kk; k++) {
675  IMS_lnActCoeffMolal_[k]= 0.0;
676  }
677  IMS_lnActCoeffMolal_[m_indexSolvent] = - log(xx) + (xx - 1.0)/xx;
678  return;
679  } else if (IMS_typeCutoff_ == 1) {
680  if (xmolSolvent > 3.0 * IMS_X_o_cutoff_/2.0) {
681  for (size_t k = 1; k < m_kk; k++) {
682  IMS_lnActCoeffMolal_[k]= 0.0;
683  }
684  IMS_lnActCoeffMolal_[m_indexSolvent] = - log(xx) + (xx - 1.0)/xx;
685  return;
686  } else if (xmolSolvent < IMS_X_o_cutoff_/2.0) {
687  double tmp = log(xx * IMS_gamma_k_min_);
688  for (size_t k = 1; k < m_kk; k++) {
689  IMS_lnActCoeffMolal_[k]= tmp;
690  }
692  return;
693  } else {
694 
695  /*
696  * If we are in the middle region, calculate the connecting polynomials
697  */
698  double xminus = xmolSolvent - IMS_X_o_cutoff_/2.0;
699  double xminus2 = xminus * xminus;
700  double xminus3 = xminus2 * xminus;
701  double x_o_cut2 = IMS_X_o_cutoff_ * IMS_X_o_cutoff_;
702  double x_o_cut3 = x_o_cut2 * IMS_X_o_cutoff_;
703 
704  double h2 = 3.5 * xminus2 / IMS_X_o_cutoff_ - 2.0 * xminus3 / x_o_cut2;
705  double h2_prime = 7.0 * xminus / IMS_X_o_cutoff_ - 6.0 * xminus2 / x_o_cut2;
706 
707  double h1 = (1.0 - 3.0 * xminus2 / x_o_cut2 + 2.0 * xminus3/ x_o_cut3);
708  double h1_prime = (- 6.0 * xminus / x_o_cut2 + 6.0 * xminus2/ x_o_cut3);
709 
710  double h1_g = h1 / IMS_gamma_o_min_;
711  double h1_g_prime = h1_prime / IMS_gamma_o_min_;
712 
713  double alpha = 1.0 / (exp(1.0) * IMS_gamma_k_min_);
714  double h1_f = h1 * alpha;
715  double h1_f_prime = h1_prime * alpha;
716 
717  double f = h2 + h1_f;
718  double f_prime = h2_prime + h1_f_prime;
719 
720  double g = h2 + h1_g;
721  double g_prime = h2_prime + h1_g_prime;
722 
723  double tmp = (xmolSolvent/ g * g_prime + (1.0-xmolSolvent) / f * f_prime);
724  double lngammak = -1.0 - log(f) + tmp * xmolSolvent;
725  double lngammao =-log(g) - tmp * (1.0-xmolSolvent);
726 
727  tmp = log(xmolSolvent) + lngammak;
728  for (size_t k = 1; k < m_kk; k++) {
729  IMS_lnActCoeffMolal_[k]= tmp;
730  }
732  }
733  }
734 
735  // Exponentials - trial 2
736  else if (IMS_typeCutoff_ == 2) {
737  if (xmolSolvent > IMS_X_o_cutoff_) {
738  for (size_t k = 1; k < m_kk; k++) {
739  IMS_lnActCoeffMolal_[k]= 0.0;
740  }
741  IMS_lnActCoeffMolal_[m_indexSolvent] = - log(xx) + (xx - 1.0)/xx;
742  return;
743  } else {
744 
745  double xoverc = xmolSolvent/IMS_cCut_;
746  double eterm = std::exp(-xoverc);
747 
748  double fptmp = IMS_bfCut_ - IMS_afCut_ / IMS_cCut_ - IMS_bfCut_*xoverc
749  + 2.0*IMS_dfCut_*xmolSolvent - IMS_dfCut_*xmolSolvent*xoverc;
750  double f_prime = 1.0 + eterm*fptmp;
751  double f = xmolSolvent + IMS_efCut_ + eterm * (IMS_afCut_ + xmolSolvent * (IMS_bfCut_ + IMS_dfCut_*xmolSolvent));
752 
753  double gptmp = IMS_bgCut_ - IMS_agCut_ / IMS_cCut_ - IMS_bgCut_*xoverc
754  + 2.0*IMS_dgCut_*xmolSolvent - IMS_dgCut_*xmolSolvent*xoverc;
755  double g_prime = 1.0 + eterm*gptmp;
756  double g = xmolSolvent + IMS_egCut_ + eterm * (IMS_agCut_ + xmolSolvent * (IMS_bgCut_ + IMS_dgCut_*xmolSolvent));
757 
758  double tmp = (xmolSolvent / g * g_prime + (1.0 - xmolSolvent) / f * f_prime);
759  double lngammak = -1.0 - log(f) + tmp * xmolSolvent;
760  double lngammao =-log(g) - tmp * (1.0-xmolSolvent);
761 
762  tmp = log(xx) + lngammak;
763  for (size_t k = 1; k < m_kk; k++) {
764  IMS_lnActCoeffMolal_[k]= tmp;
765  }
767  }
768  }
769 }
770 
772 {
773  /*
774  * Obtain the limits of the temperature from the species
775  * thermo handler's limits.
776  */
777  m_pp.resize(m_kk);
778  m_speciesMolarVolume.resize(m_kk);
779  m_tmpV.resize(m_kk);
780  IMS_lnActCoeffMolal_.resize(m_kk);
781 }
782 
784 {
785  IMS_afCut_ = 1.0 / (std::exp(1.0) * IMS_gamma_k_min_);
786  IMS_efCut_ = 0.0;
787  bool converged = false;
788  for (int its = 0; its < 100 && !converged; its++) {
789  double oldV = IMS_efCut_;
790  IMS_afCut_ = 1.0 / (std::exp(1.0) * IMS_gamma_k_min_) - IMS_efCut_;
791  IMS_bfCut_ = IMS_afCut_ / IMS_cCut_ + IMS_slopefCut_ - 1.0;
792  IMS_dfCut_ = ((- IMS_afCut_/IMS_cCut_ + IMS_bfCut_ - IMS_bfCut_*IMS_X_o_cutoff_/IMS_cCut_)
793  /
794  (IMS_X_o_cutoff_*IMS_X_o_cutoff_/IMS_cCut_ - 2.0 * IMS_X_o_cutoff_));
795  double tmp = IMS_afCut_ + IMS_X_o_cutoff_*(IMS_bfCut_ + IMS_dfCut_ * IMS_X_o_cutoff_);
796  double eterm = std::exp(-IMS_X_o_cutoff_/IMS_cCut_);
797  IMS_efCut_ = - eterm * (tmp);
798  if (fabs(IMS_efCut_ - oldV) < 1.0E-14) {
799  converged = true;
800  }
801  }
802  if (!converged) {
803  throw CanteraError(" IdealMolalSoln::calcCutoffParams_()",
804  " failed to converge on the f polynomial");
805  }
806  converged = false;
807  double f_0 = IMS_afCut_ + IMS_efCut_;
808  double f_prime_0 = 1.0 - IMS_afCut_ / IMS_cCut_ + IMS_bfCut_;
809  IMS_egCut_ = 0.0;
810  for (int its = 0; its < 100 && !converged; its++) {
811  double oldV = IMS_egCut_;
812  double lng_0 = -log(IMS_gamma_o_min_) - f_prime_0 / f_0;
813  IMS_agCut_ = exp(lng_0) - IMS_egCut_;
814  IMS_bgCut_ = IMS_agCut_ / IMS_cCut_ + IMS_slopegCut_ - 1.0;
815  IMS_dgCut_ = ((- IMS_agCut_/IMS_cCut_ + IMS_bgCut_ - IMS_bgCut_*IMS_X_o_cutoff_/IMS_cCut_)
816  /
817  (IMS_X_o_cutoff_*IMS_X_o_cutoff_/IMS_cCut_ - 2.0 * IMS_X_o_cutoff_));
818  double tmp = IMS_agCut_ + IMS_X_o_cutoff_*(IMS_bgCut_ + IMS_dgCut_ *IMS_X_o_cutoff_);
819  double eterm = std::exp(-IMS_X_o_cutoff_/IMS_cCut_);
820  IMS_egCut_ = - eterm * (tmp);
821  if (fabs(IMS_egCut_ - oldV) < 1.0E-14) {
822  converged = true;
823  }
824  }
825  if (!converged) {
826  throw CanteraError(" IdealMolalSoln::calcCutoffParams_()",
827  " failed to converge on the g polynomial");
828  }
829 }
830 
831 }
IdealMolalSoln & operator=(const IdealMolalSoln &)
Assignment operator.
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:704
ThermoPhase object for the ideal molal equation of state (see Thermodynamic Properties and class Idea...
virtual doublereal density() const
Density (kg/m^3).
Definition: Phase.h:608
virtual void setPressure(doublereal p)
Set the pressure at constant temperature.
CTML ("Cantera Markup Language") is the variant of XML that Cantera uses to store data...
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
virtual void setState_TP(doublereal t, doublereal p)
Set the temperature (K) and pressure (Pa)
std::string attrib(const std::string &attr) const
Function returns the value of an attribute.
Definition: xml.cpp:527
An error indicating that an unimplemented function has been called.
Definition: ctexceptions.h:213
doublereal IMS_slopefCut_
Parameter in the polyExp cutoff treatment.
doublereal IMS_slopegCut_
Parameter in the polyExp cutoff treatment.
doublereal _RT() const
Return the Gas Constant multiplied by the current temperature.
Definition: ThermoPhase.h:936
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...
IdealMolalSoln()
Constructor.
const size_t npos
index returned by functions to indicate "no position"
Definition: ct_defs.h:165
virtual void getPartialMolarVolumes(doublereal *vbar) const
virtual void getCp_R(doublereal *cpr) const
Get the nondimensional Heat Capacities at constant pressure for the standard state of the species at ...
Headers for the factory class that can create known ThermoPhase objects (see Thermodynamic Properties...
virtual doublereal enthalpy_mole() const
Molar enthalpy of the solution. Units: J/kmol.
virtual void getActivityConcentrations(doublereal *c) const
vector_fp m_tmpV
vector of size m_kk, used as a temporary holding area.
virtual doublereal standardConcentration(size_t k=0) const
The standard concentration used to normalize the generalized concentration.
Class XML_Node is a tree-based representation of the contents of an XML file.
Definition: xml.h:100
virtual void updateStandardStateThermo() const
Updates the standard state thermodynamic functions at the current T and P of the solution.
void warn_deprecated(const std::string &method, const std::string &extra)
Print a warning indicating that method is deprecated.
Definition: global.cpp:78
ThermoPhase * duplMyselfAsThermoPhase() const
Duplication function.
doublereal IMS_gamma_k_min_
gamma_k minimum for the cutoff process at the zero solvent point
void setDensity(const doublereal rho)
Overwritten setDensity() function is necessary because the density is not an independent variable...
doublereal molarDensity() const
Molar density (kmol/m^3).
Definition: Phase.cpp:663
void initLengths()
This internal function adjusts the lengths of arrays.
void getMoleFractions(doublereal *const x) const
Get the species mole fraction vector.
Definition: Phase.cpp:556
void setMolarDensity(const doublereal rho)
Overwritten setMolarDensity() function is necessary because the density is not an independent variabl...
doublereal IMS_gamma_o_min_
gamma_o value for the cutoff process at the zero solvent point
vector_fp m_pp
Temporary array used in equilibrium calculations.
vector_fp m_speciesMolarVolume
Species molar volume .
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 getPartialMolarEnthalpies(doublereal *hbar) const
Returns an array of partial molar enthalpies for the species in the mixture.
virtual doublereal gibbs_mole() const
Molar Gibbs function for the solution: Units J/kmol.
Base class for a phase with thermodynamic properties.
Definition: ThermoPhase.h:97
virtual void getChemPotentials(doublereal *mu) const
Get the species chemical potentials: Units: J/kmol.
doublereal mean_X(const doublereal *const Q) const
Evaluate the mole-fraction-weighted mean of an array Q.
Definition: Phase.cpp:687
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:742
virtual void getActivities(doublereal *ac) const
bool importPhase(XML_Node &phase, ThermoPhase *th, SpeciesThermoFactory *spfactory)
Import a phase information into an empty ThermoPhase object.
virtual doublereal isothermalCompressibility() const
The isothermal compressibility. Units: 1/Pa.
virtual void getUnitsStandardConc(double *uA, int k=0, int sizeUA=6) const
virtual doublereal cv_mole() const
Molar heat capacity of the solution at constant volume. Units: J/kmol/K.
void s_updateIMS_lnMolalityActCoeff() const
This function will be called to update the internally stored natural logarithm of the molality activi...
virtual void initThermoXML(XML_Node &phaseNode, const std::string &id="")
Import and initialize an IdealMolalSoln phase specification in an XML tree into the current object...
virtual doublereal entropy_mole() const
Molar entropy of the solution. Units: J/kmol/K.
MolalityVPSSTP & operator=(const MolalityVPSSTP &b)
Assignment operator.
virtual void getPartialMolarEntropies(doublereal *sbar) const
Returns an array of partial molar entropies of the species in the solution. Units: J/kmol...
virtual doublereal cp_mole() const
Molar heat capacity of the solution at constant pressure. Units: J/kmol/K.
#define AssertThrow(expr, procedure)
Assertion must be true or an error is thrown.
Definition: ctexceptions.h:283
Base class for exceptions thrown by Cantera classes.
Definition: ctexceptions.h:99
virtual doublereal intEnergy_mole() const
Molar internal energy of the solution: Units: J/kmol.
bool hasChild(const std::string &ch) const
Tests whether the current node has a child node with a particular name.
Definition: xml.cpp:563
virtual void getPartialMolarCp(doublereal *cpbar) const
Partial molar heat capacity of the solution:. UnitsL J/kmol/K.
int IMS_typeCutoff_
Cutoff type.
virtual void setStateFromXML(const XML_Node &state)
Set equation of state parameter values from XML entries.
const std::vector< std::string > & speciesNames() const
Return a const reference to the vector of species names.
Definition: Phase.cpp:278
doublereal moleFraction(size_t k) const
Return the mole fraction of a single species.
Definition: Phase.cpp:561
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
size_t nDim() const
Returns the number of spatial dimensions (1, 2, or 3)
Definition: Phase.h:586
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...
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
virtual void initThermo()
Initialization routine for an IdealMolalSoln phase.
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:503
virtual int eosType() const
Equation of state type flag.
Definition: ThermoPhase.h:142
virtual void setTemperature(const doublereal temp)
Set the internally stored temperature of the phase (K).
Definition: Phase.h:638
virtual void getEnthalpy_RT(doublereal *hrt) const
Get the nondimensional Enthalpy functions for the species at their standard states at the current T a...
virtual void getMolalityActivityCoefficients(doublereal *acMolality) const
doublereal meanMolecularWeight() const
The mean molecular weight. Units: (kg/kmol)
Definition: Phase.h:669
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
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:194
#define DATA_PTR(vec)
Creates a pointer to the start of the raw data for a vector.
Definition: ct_defs.h:36
void initThermoXML(XML_Node &phaseNode, const std::string &id)
Import and initialize a ThermoPhase object.
size_t m_kk
Number of species in the phase.
Definition: Phase.h:843
virtual void initThermoFile(const std::string &inputFile, const std::string &id)
doublereal m_Pcurrent
Current value of the pressure - state variable.
This phase is based upon the mixing-rule assumption that all molality-based activity coefficients are...
virtual void getStandardChemPotentials(doublereal *mu) const
Get the array of chemical potentials at unit activity.
XML_Node & root() const
Return the root of the current XML_Node tree.
Definition: xml.cpp:1095
size_t m_indexSolvent
Index of the solvent.
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; ...
void calcMolalities() const
Calculates the molality of all species and stores the result internally.
std::string speciesName(size_t k) const
Name of the species with index k.
Definition: Phase.cpp:272
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 setDensity(const doublereal density_)
Set the internally stored density (kg/m^3) of the phase Note the density of a phase is an independent...
Definition: Phase.h:623
void setMoleFSolventMin(doublereal xmolSolventMIN)
Sets the minimum mole fraction in the molality formulation.
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.
vector_fp IMS_lnActCoeffMolal_
Logarithm of the molal activity coefficients.