Cantera  2.3.0
IonsFromNeutralVPSSTP.cpp
Go to the documentation of this file.
1 /**
2  * @file IonsFromNeutralVPSSTP.cpp
3  * Definitions for the object which treats ionic liquids as made of ions as species
4  * even though the thermodynamics is obtained from the neutral molecule representation.
5  * (see \ref thermoprops
6  * and class \link Cantera::IonsFromNeutralVPSSTP IonsFromNeutralVPSSTP\endlink).
7  *
8  * Header file for a derived class of ThermoPhase that handles variable pressure
9  * standard state methods for calculating thermodynamic properties that are
10  * further based upon expressions for the excess Gibbs free energy expressed as
11  * a function of the mole fractions.
12  */
13 
14 // This file is part of Cantera. See License.txt in the top-level directory or
15 // at http://www.cantera.org/license.txt for license and copyright information.
16 
21 
22 #include <fstream>
23 
24 using namespace std;
25 
26 namespace Cantera
27 {
28 
29 IonsFromNeutralVPSSTP::IonsFromNeutralVPSSTP() :
30  ionSolnType_(cIonSolnType_SINGLEANION),
31  numNeutralMoleculeSpecies_(0),
32  indexSpecialSpecies_(npos),
33  indexSecondSpecialSpecies_(npos),
34  neutralMoleculePhase_(0),
35  geThermo(0),
36  IOwnNThermoPhase_(true)
37 {
38 }
39 
40 IonsFromNeutralVPSSTP::IonsFromNeutralVPSSTP(const std::string& inputFile,
41  const std::string& id_,
42  ThermoPhase* neutralPhase) :
43  ionSolnType_(cIonSolnType_SINGLEANION),
44  numNeutralMoleculeSpecies_(0),
45  indexSpecialSpecies_(npos),
46  indexSecondSpecialSpecies_(npos),
47  neutralMoleculePhase_(neutralPhase),
48  IOwnNThermoPhase_(true)
49 {
50  if (neutralPhase) {
51  IOwnNThermoPhase_ = false;
52  }
53  constructPhaseFile(inputFile, id_);
54 }
55 
57  const std::string& id_, ThermoPhase* neutralPhase) :
58  ionSolnType_(cIonSolnType_SINGLEANION),
59  numNeutralMoleculeSpecies_(0),
60  indexSpecialSpecies_(npos),
61  indexSecondSpecialSpecies_(npos),
62  neutralMoleculePhase_(neutralPhase),
63  IOwnNThermoPhase_(true)
64 {
65  if (neutralPhase) {
66  IOwnNThermoPhase_ = false;
67  }
68  constructPhaseXML(phaseRoot, id_);
69 }
70 
72  ionSolnType_(cIonSolnType_SINGLEANION),
73  numNeutralMoleculeSpecies_(0),
74  indexSpecialSpecies_(npos),
75  indexSecondSpecialSpecies_(npos),
76  neutralMoleculePhase_(0),
77  geThermo(0),
78  IOwnNThermoPhase_(true)
79 {
80  IonsFromNeutralVPSSTP::operator=(b);
81 }
82 
83 IonsFromNeutralVPSSTP&
84 IonsFromNeutralVPSSTP::operator=(const IonsFromNeutralVPSSTP& b)
85 {
86  if (&b == this) {
87  return *this;
88  }
89 
90  // If we own the underlying neutral molecule phase, then we do a deep copy.
91  // If not, we do a shallow copy. We get a valid pointer for
92  // neutralMoleculePhase_ first, because we need it to assign the pointers
93  // within the PDSS_IonsFromNeutral object. which is done in the
94  // GibbsExcessVPSSTP::operator=(b) step.
95  if (IOwnNThermoPhase_) {
96  if (b.neutralMoleculePhase_) {
97  delete neutralMoleculePhase_;
98  neutralMoleculePhase_ = (b.neutralMoleculePhase_)->duplMyselfAsThermoPhase();
99  } else {
101  }
102  } else {
103  neutralMoleculePhase_ = b.neutralMoleculePhase_;
104  }
105  geThermo = dynamic_cast<GibbsExcessVPSSTP*>(neutralMoleculePhase_);
106 
107  GibbsExcessVPSSTP::operator=(b);
108 
109  ionSolnType_ = b.ionSolnType_;
110  numNeutralMoleculeSpecies_ = b.numNeutralMoleculeSpecies_;
111  indexSpecialSpecies_ = b.indexSpecialSpecies_;
112  indexSecondSpecialSpecies_ = b.indexSecondSpecialSpecies_;
113  fm_neutralMolec_ions_ = b.fm_neutralMolec_ions_;
114  fm_invert_ionForNeutral = b.fm_invert_ionForNeutral;
115  NeutralMolecMoleFractions_ = b.NeutralMolecMoleFractions_;
116  cationList_ = b.cationList_;
117  anionList_ = b.anionList_;
118  passThroughList_ = b.passThroughList_;
119  y_ = b.y_;
120  dlnActCoeff_NeutralMolecule_ = b.dlnActCoeff_NeutralMolecule_;
121  dX_NeutralMolecule_ = b.dX_NeutralMolecule_;
122  m_work = b.m_work;
123  IOwnNThermoPhase_ = b.IOwnNThermoPhase_;
124  moleFractionsTmp_ = b.moleFractionsTmp_;
125  muNeutralMolecule_ = b.muNeutralMolecule_;
126  lnActCoeff_NeutralMolecule_ = b.lnActCoeff_NeutralMolecule_;
127  dlnActCoeffdT_NeutralMolecule_ = b.dlnActCoeffdT_NeutralMolecule_;
128  dlnActCoeffdlnX_diag_NeutralMolecule_ = b.dlnActCoeffdlnX_diag_NeutralMolecule_;
129  dlnActCoeffdlnN_diag_NeutralMolecule_ = b.dlnActCoeffdlnN_diag_NeutralMolecule_;
130  dlnActCoeffdlnN_NeutralMolecule_ = b.dlnActCoeffdlnN_NeutralMolecule_;
131 
132  return *this;
133 }
134 
135 IonsFromNeutralVPSSTP::~IonsFromNeutralVPSSTP()
136 {
137  if (IOwnNThermoPhase_) {
138  delete neutralMoleculePhase_;
140  }
141 }
142 
144 {
145  return new IonsFromNeutralVPSSTP(*this);
146 }
147 
148 void IonsFromNeutralVPSSTP::constructPhaseFile(std::string inputFile, std::string id_)
149 {
150  warn_deprecated("IonsFromNeutralVPSSTP::constructPhaseFile",
151  "Use initThermoFile instead. To be removed after Cantera 2.3.");
152  initThermoFile(inputFile, id_);
153 }
154 
155 void IonsFromNeutralVPSSTP::constructPhaseXML(XML_Node& phaseNode, std::string id_)
156 {
157  warn_deprecated("IonsFromNeutralVPSSTP::constructPhaseXML",
158  "Use importPhase instead. To be removed after Cantera 2.3.");
159  importPhase(phaseNode, this);
160 }
161 
162 // -------------- Utilities -------------------------------
163 
165 {
166  warn_deprecated("IonsFromNeutralVPSSTP::eosType",
167  "To be removed after Cantera 2.3.");
168  return cIonsFromNeutral;
169 }
170 
171 // ------------ Molar Thermodynamic Properties ----------------------
172 
174 {
175  getPartialMolarEnthalpies(m_work.data());
176  return mean_X(m_work);
177 }
178 
180 {
181  getPartialMolarEntropies(m_work.data());
182  return mean_X(m_work);
183 }
184 
186 {
187  getChemPotentials(m_work.data());
188  return mean_X(m_work);
189 }
190 
192 {
193  getPartialMolarCp(m_work.data());
194  return mean_X(m_work);
195 }
196 
198 {
199  // Need to revisit this, as it is wrong
200  getPartialMolarCp(m_work.data());
201  return mean_X(m_work);
202 }
203 
204 // -- Activities, Standard States, Activity Concentrations -----------
205 
207  vector_fp& charges, std::vector<size_t>& neutMolIndex) const
208 {
209  coeffs = fm_neutralMolec_ions_;
210  charges = m_speciesCharge;
211  neutMolIndex = fm_invert_ionForNeutral;
212 }
213 
215 {
216  // Update the activity coefficients
218 
219  // take the exp of the internally stored coefficients.
220  for (size_t k = 0; k < m_kk; k++) {
221  ac[k] = exp(lnActCoeff_Scaled_[k]);
222  }
223 }
224 
225 // --------- Partial Molar Properties of the Solution -------------
226 
228 {
229  size_t icat, jNeut;
230  doublereal xx, fact2;
231 
232  // Get the standard chemical potentials of netural molecules
234 
235  switch (ionSolnType_) {
236  case cIonSolnType_PASSTHROUGH:
238  break;
239  case cIonSolnType_SINGLEANION:
241  fact2 = 2.0 * RT() * log(2.0);
242 
243  // Do the cation list
244  for (size_t k = 0; k < cationList_.size(); k++) {
245  // Get the id for the next cation
246  icat = cationList_[k];
247  jNeut = fm_invert_ionForNeutral[icat];
248  xx = std::max(SmallNumber, moleFractions_[icat]);
249  mu[icat] = muNeutralMolecule_[jNeut] + fact2 + RT() * (lnActCoeff_NeutralMolecule_[jNeut] + log(xx));
250  }
251 
252  // Do the anion list
253  icat = anionList_[0];
254  jNeut = fm_invert_ionForNeutral[icat];
255  xx = std::max(SmallNumber, moleFractions_[icat]);
256  mu[icat] = RT() * log(xx);
257 
258  // Do the list of neutral molecules
259  for (size_t k = 0; k < passThroughList_.size(); k++) {
260  icat = passThroughList_[k];
261  jNeut = fm_invert_ionForNeutral[icat];
262  xx = std::max(SmallNumber, moleFractions_[icat]);
263  mu[icat] = muNeutralMolecule_[jNeut] + RT() * (lnActCoeff_NeutralMolecule_[jNeut] + log(xx));
264  }
265  break;
266 
267  case cIonSolnType_SINGLECATION:
268  throw CanteraError("eosType", "Unknown type");
269  break;
270  case cIonSolnType_MULTICATIONANION:
271  throw CanteraError("eosType", "Unknown type");
272  break;
273  default:
274  throw CanteraError("eosType", "Unknown type");
275  break;
276  }
277 }
278 
280 {
281  // Get the nondimensional standard state enthalpies
282  getEnthalpy_RT(hbar);
283 
284  // dimensionalize it.
285  for (size_t k = 0; k < m_kk; k++) {
286  hbar[k] *= RT();
287  }
288 
289  // Update the activity coefficients, This also update the internally stored
290  // molalities.
293  for (size_t k = 0; k < m_kk; k++) {
294  hbar[k] -= RT() * temperature() * dlnActCoeffdT_Scaled_[k];
295  }
296 }
297 
299 {
300  // Get the nondimensional standard state entropies
301  getEntropy_R(sbar);
302 
303  // Update the activity coefficients, This also update the internally stored
304  // molalities.
307 
308  for (size_t k = 0; k < m_kk; k++) {
309  double xx = std::max(moleFractions_[k], SmallNumber);
310  sbar[k] += - lnActCoeff_Scaled_[k] -log(xx) - temperature() * dlnActCoeffdT_Scaled_[k];
311  }
312 
313  // dimensionalize it.
314  for (size_t k = 0; k < m_kk; k++) {
315  sbar[k] *= GasConstant;
316  }
317 }
318 
319 void IonsFromNeutralVPSSTP::getdlnActCoeffdlnX_diag(doublereal* dlnActCoeffdlnX_diag) const
320 {
323 
324  for (size_t k = 0; k < m_kk; k++) {
325  dlnActCoeffdlnX_diag[k] = dlnActCoeffdlnX_diag_[k];
326  }
327 }
328 
329 void IonsFromNeutralVPSSTP::getdlnActCoeffdlnN_diag(doublereal* dlnActCoeffdlnN_diag) const
330 {
333 
334  for (size_t k = 0; k < m_kk; k++) {
335  dlnActCoeffdlnN_diag[k] = dlnActCoeffdlnN_diag_[k];
336  }
337 }
338 
339 void IonsFromNeutralVPSSTP::getdlnActCoeffdlnN(const size_t ld, doublereal* dlnActCoeffdlnN)
340 {
343  double* data = & dlnActCoeffdlnN_(0,0);
344  for (size_t k = 0; k < m_kk; k++) {
345  for (size_t m = 0; m < m_kk; m++) {
346  dlnActCoeffdlnN[ld * k + m] = data[m_kk * k + m];
347  }
348  }
349 }
350 
352 {
353  // This is a two phase process. First, we calculate the standard states
354  // within the neutral molecule phase.
356 
357  // Calculate the partial molar volumes, and then the density of the fluid
359 }
360 
361 void IonsFromNeutralVPSSTP::calcIonMoleFractions(doublereal* const mf) const
362 {
363  // Download the neutral mole fraction vector into the vector,
364  // NeutralMolecMoleFractions_[]
366 
367  // Zero the mole fractions
368  for (size_t k = 0; k < m_kk; k++) {
369  mf[k] = 0.0;
370  }
371 
372  // Use the formula matrix to calculate the relative mole numbers.
373  for (size_t jNeut = 0; jNeut < numNeutralMoleculeSpecies_; jNeut++) {
374  for (size_t k = 0; k < m_kk; k++) {
375  double fmij = fm_neutralMolec_ions_[k + jNeut * m_kk];
376  mf[k] += fmij * NeutralMolecMoleFractions_[jNeut];
377  }
378  }
379 
380  // Normalize the new mole fractions
381  doublereal sum = 0.0;
382  for (size_t k = 0; k < m_kk; k++) {
383  sum += mf[k];
384  }
385  for (size_t k = 0; k < m_kk; k++) {
386  mf[k] /= sum;
387  }
388 }
389 
391 {
392  size_t icat, jNeut;
393  doublereal fmij;
394  doublereal sum = 0.0;
395 
396  // Zero the vector we are trying to find.
397  for (size_t k = 0; k < numNeutralMoleculeSpecies_; k++) {
399  }
400  sum = -1.0;
401  for (size_t k = 0; k < m_kk; k++) {
402  sum += moleFractions_[k];
403  }
404  if (fabs(sum) > 1.0E-11) {
405  throw CanteraError("IonsFromNeutralVPSSTP::calcNeutralMoleculeMoleFractions",
406  "molefracts don't sum to one: {}", sum);
407  }
408 
409  switch (ionSolnType_) {
410  case cIonSolnType_PASSTHROUGH:
411  for (size_t k = 0; k < m_kk; k++) {
413  }
414  break;
415 
416  case cIonSolnType_SINGLEANION:
417  for (size_t k = 0; k < numNeutralMoleculeSpecies_; k++) {
419  }
420 
421  for (size_t k = 0; k < cationList_.size(); k++) {
422  // Get the id for the next cation
423  icat = cationList_[k];
424  jNeut = fm_invert_ionForNeutral[icat];
425  if (jNeut != npos) {
426  fmij = fm_neutralMolec_ions_[icat + jNeut * m_kk];
427  AssertTrace(fmij != 0.0);
428  NeutralMolecMoleFractions_[jNeut] += moleFractions_[icat] / fmij;
429  }
430  }
431 
432  for (size_t k = 0; k < passThroughList_.size(); k++) {
433  icat = passThroughList_[k];
434  jNeut = fm_invert_ionForNeutral[icat];
435  fmij = fm_neutralMolec_ions_[ icat + jNeut * m_kk];
436  NeutralMolecMoleFractions_[jNeut] += moleFractions_[icat] / fmij;
437  }
438 
439  for (size_t k = 0; k < m_kk; k++) {
441  }
442  for (jNeut = 0; jNeut < numNeutralMoleculeSpecies_; jNeut++) {
443  for (size_t k = 0; k < m_kk; k++) {
444  fmij = fm_neutralMolec_ions_[k + jNeut * m_kk];
445  moleFractionsTmp_[k] -= fmij * NeutralMolecMoleFractions_[jNeut];
446  }
447  }
448  for (size_t k = 0; k < m_kk; k++) {
449  if (fabs(moleFractionsTmp_[k]) > 1.0E-13) {
450  // Check to see if we have in fact found the inverse.
451  if (anionList_[0] != k) {
452  throw CanteraError("IonsFromNeutralVPSSTP::calcNeutralMoleculeMoleFractions",
453  "neutral molecule calc error");
454  } else {
455  // For the single anion case, we will allow some slippage
456  if (fabs(moleFractionsTmp_[k]) > 1.0E-5) {
457  throw CanteraError("IonsFromNeutralVPSSTP::calcNeutralMoleculeMoleFractions",
458  "neutral molecule calc error - anion");
459  }
460  }
461  }
462  }
463 
464  // Normalize the Neutral Molecule mole fractions
465  sum = 0.0;
466  for (size_t k = 0; k < numNeutralMoleculeSpecies_; k++) {
467  sum += NeutralMolecMoleFractions_[k];
468  }
469  for (size_t k = 0; k < numNeutralMoleculeSpecies_; k++) {
470  NeutralMolecMoleFractions_[k] /= sum;
471  }
472  break;
473 
474  case cIonSolnType_SINGLECATION:
475  throw CanteraError("IonsFromNeutralVPSSTP::calcNeutralMoleculeMoleFractions", "Unknown type");
476  break;
477  case cIonSolnType_MULTICATIONANION:
478  throw CanteraError("IonsFromNeutralVPSSTP::calcNeutralMoleculeMoleFractions", "Unknown type");
479  break;
480  default:
481  throw CanteraError("IonsFromNeutralVPSSTP::calcNeutralMoleculeMoleFractions", "Unknown type");
482  break;
483  }
484 }
485 
486 void IonsFromNeutralVPSSTP::getNeutralMoleculeMoleGrads(const doublereal* const dx, doublereal* const dy) const
487 {
488  doublereal sumy, sumdy;
489 
490  // check sum dx = 0
491  // Zero the vector we are trying to find.
492  for (size_t k = 0; k < numNeutralMoleculeSpecies_; k++) {
493  y_[k] = 0.0;
494  dy[k] = 0.0;
495  }
496 
497  switch (ionSolnType_) {
498 
499  case cIonSolnType_PASSTHROUGH:
500  for (size_t k = 0; k < m_kk; k++) {
501  dy[k] = dx[k];
502  }
503  break;
504 
505  case cIonSolnType_SINGLEANION:
506  for (size_t k = 0; k < cationList_.size(); k++) {
507  // Get the id for the next cation
508  size_t icat = cationList_[k];
509  size_t jNeut = fm_invert_ionForNeutral[icat];
510  if (jNeut != npos) {
511  double fmij = fm_neutralMolec_ions_[icat + jNeut * m_kk];
512  AssertTrace(fmij != 0.0);
513  const doublereal temp = 1.0/fmij;
514  dy[jNeut] += dx[icat] * temp;
515  y_[jNeut] += moleFractions_[icat] * temp;
516  }
517  }
518 
519  for (size_t k = 0; k < passThroughList_.size(); k++) {
520  size_t icat = passThroughList_[k];
521  size_t jNeut = fm_invert_ionForNeutral[icat];
522  double fmij = fm_neutralMolec_ions_[ icat + jNeut * m_kk];
523  const doublereal temp = 1.0/fmij;
524  dy[jNeut] += dx[icat] * temp;
525  y_[jNeut] += moleFractions_[icat] * temp;
526  }
527  // Normalize the Neutral Molecule mole fractions
528  sumy = 0.0;
529  sumdy = 0.0;
530  for (size_t k = 0; k < numNeutralMoleculeSpecies_; k++) {
531  sumy += y_[k];
532  sumdy += dy[k];
533  }
534  sumy = 1.0 / sumy;
535  for (size_t k = 0; k < numNeutralMoleculeSpecies_; k++) {
536  dy[k] = dy[k] * sumy - y_[k]*sumdy*sumy*sumy;
537  }
538 
539  break;
540 
541  case cIonSolnType_SINGLECATION:
542  throw CanteraError("IonsFromNeutralVPSSTP::getNeutralMoleculeMoleGrads",
543  "Unknown type");
544  break;
545  case cIonSolnType_MULTICATIONANION:
546  throw CanteraError("IonsFromNeutralVPSSTP::getNeutralMoleculeMoleGrads",
547  "Unknown type");
548  break;
549  default:
550  throw CanteraError("IonsFromNeutralVPSSTP::getNeutralMoleculeMoleGrads",
551  "Unknown type");
552  break;
553  }
554 }
555 
557 {
561 }
562 
563 // ------------ Partial Molar Properties of the Solution ------------
564 
566 {
567  initLengths();
569  geThermo = dynamic_cast<GibbsExcessVPSSTP*>(neutralMoleculePhase_);
570 }
571 
573 {
575  moleFractions_.resize(m_kk);
579  cationList_.resize(m_kk);
580  anionList_.resize(m_kk);
581  passThroughList_.resize(m_kk);
582  moleFractionsTmp_.resize(m_kk);
589  y_.resize(numNeutralMoleculeSpecies_, 0.0);
590  dlnActCoeff_NeutralMolecule_.resize(numNeutralMoleculeSpecies_, 0.0);
591  dX_NeutralMolecule_.resize(numNeutralMoleculeSpecies_, 0.0);
592  m_work.resize(m_kk);
593 }
594 
595 //! Return the factor overlap
596 /*!
597  * @param elnamesVN
598  * @param elemVectorN
599  * @param nElementsN
600  * @param elnamesVI
601  * @param elemVectorI
602  * @param nElementsI
603  */
604 static double factorOverlap(const std::vector<std::string>& elnamesVN ,
605  const vector_fp& elemVectorN,
606  const size_t nElementsN,
607  const std::vector<std::string>& elnamesVI ,
608  const vector_fp& elemVectorI,
609  const size_t nElementsI)
610 {
611  double fMax = 1.0E100;
612  for (size_t mi = 0; mi < nElementsI; mi++) {
613  if (elnamesVI[mi] != "E" && elemVectorI[mi] > 1.0E-13) {
614  double eiNum = elemVectorI[mi];
615  for (size_t mn = 0; mn < nElementsN; mn++) {
616  if (elnamesVI[mi] == elnamesVN[mn]) {
617  if (elemVectorN[mn] <= 1.0E-13) {
618  return 0.0;
619  }
620  fMax = std::min(fMax, elemVectorN[mn]/eiNum);
621  }
622  }
623  }
624  }
625  return fMax;
626 }
627 void IonsFromNeutralVPSSTP::initThermoXML(XML_Node& phaseNode, const std::string& id_)
628 {
629  if (id_.size() > 0 && phaseNode.id() != id_) {
630  throw CanteraError("IonsFromNeutralVPSSTP::initThermoXML",
631  "phasenode and Id are incompatible");
632  }
633 
634  // Find the Thermo XML node
635  if (!phaseNode.hasChild("thermo")) {
636  throw CanteraError("IonsFromNeutralVPSSTP::initThermoXML",
637  "no thermo XML node");
638  }
639  XML_Node& thermoNode = phaseNode.child("thermo");
640 
641  // Make sure that the thermo model is IonsFromNeutralMolecule
642  if (!ba::iequals(thermoNode["model"], "ionsfromneutralmolecule")) {
643  throw CanteraError("IonsFromNeutralVPSSTP::initThermoXML",
644  "model name isn't IonsFromNeutralMolecule: "
645  + thermoNode["model"]);
646  }
647 
648  // Find the Neutral Molecule Phase
649  if (!thermoNode.hasChild("neutralMoleculePhase")) {
650  throw CanteraError("IonsFromNeutralVPSSTP::initThermoXML",
651  "no neutralMoleculePhase XML node");
652  }
653  XML_Node& neutralMoleculeNode = thermoNode.child("neutralMoleculePhase");
654 
655  XML_Node* neut_ptr = get_XML_Node(neutralMoleculeNode["datasrc"], 0);
656  if (!neut_ptr) {
657  throw CanteraError("IonsFromNeutralVPSSTP::initThermoXML",
658  "neut_ptr = 0");
659  }
660 
661  // Create the neutralMolecule ThermoPhase if we haven't already
662  if (!neutralMoleculePhase_) {
663  neutralMoleculePhase_ = newPhase(*neut_ptr);
664  }
665 
666  cationList_.clear();
667  for (size_t k = 0; k < m_kk; k++) {
668  if (charge(k) > 0) {
669  cationList_.push_back(k);
670  }
671  }
672 
673  anionList_.clear();
674  for (size_t k = 0; k < m_kk; k++) {
675  if (charge(k) < 0) {
676  anionList_.push_back(k);
677  }
678  }
679 
680  passThroughList_.clear();
681  for (size_t k = 0; k < m_kk; k++) {
682  if (charge(k) == 0) {
683  passThroughList_.push_back(k);
684  }
685  }
686 
688  for (size_t k = 0; k < m_kk; k++) {
689  PDSS_IonsFromNeutral* speciesSS =
690  dynamic_cast<PDSS_IonsFromNeutral*>(providePDSS(k));
691  if (!speciesSS) {
692  throw CanteraError("initThermoXML", "Dynamic cast failed");
693  }
694  if (speciesSS->specialSpecies_ == 1) {
696  }
697  if (speciesSS->specialSpecies_ == 2) {
699  }
700  }
701 
702  size_t nElementsN = neutralMoleculePhase_->nElements();
703  const std::vector<std::string>& elnamesVN = neutralMoleculePhase_->elementNames();
704  vector_fp elemVectorN(nElementsN);
705  vector_fp elemVectorN_orig(nElementsN);
706 
707  size_t nElementsI = nElements();
708  const std::vector<std::string>& elnamesVI = elementNames();
709  vector_fp elemVectorI(nElementsI);
710 
711  vector_fp fm_tmp(m_kk);
712  for (size_t k = 0; k < m_kk; k++) {
714  }
715  for (size_t jNeut = 0; jNeut < numNeutralMoleculeSpecies_; jNeut++) {
716  for (size_t m = 0; m < nElementsN; m++) {
717  elemVectorN[m] = neutralMoleculePhase_->nAtoms(jNeut, m);
718  }
719  elemVectorN_orig = elemVectorN;
720  fm_tmp.assign(m_kk, 0.0);
721 
722  for (size_t m = 0; m < nElementsI; m++) {
723  elemVectorI[m] = nAtoms(indexSpecialSpecies_, m);
724  }
725  double fac = factorOverlap(elnamesVN, elemVectorN, nElementsN,
726  elnamesVI ,elemVectorI, nElementsI);
727  if (fac > 0.0) {
728  for (size_t m = 0; m < nElementsN; m++) {
729  std::string mName = elnamesVN[m];
730  for (size_t mi = 0; mi < nElementsI; mi++) {
731  std::string eName = elnamesVI[mi];
732  if (mName == eName) {
733  elemVectorN[m] -= fac * elemVectorI[mi];
734  }
735 
736  }
737  }
738  }
740 
741  for (size_t k = 0; k < m_kk; k++) {
742  for (size_t m = 0; m < nElementsI; m++) {
743  elemVectorI[m] = nAtoms(k, m);
744  }
745  fac = factorOverlap(elnamesVN, elemVectorN, nElementsN,
746  elnamesVI ,elemVectorI, nElementsI);
747  if (fac > 0.0) {
748  for (size_t m = 0; m < nElementsN; m++) {
749  std::string mName = elnamesVN[m];
750  for (size_t mi = 0; mi < nElementsI; mi++) {
751  std::string eName = elnamesVI[mi];
752  if (mName == eName) {
753  elemVectorN[m] -= fac * elemVectorI[mi];
754  }
755  }
756  }
757  bool notTaken = true;
758  for (size_t iNeut = 0; iNeut < jNeut; iNeut++) {
759  if (fm_invert_ionForNeutral[k] == iNeut) {
760  notTaken = false;
761  }
762  }
763  if (notTaken) {
764  fm_invert_ionForNeutral[k] = jNeut;
765  } else {
766  throw CanteraError("IonsFromNeutralVPSSTP::initThermoXML",
767  "Simple formula matrix generation failed, one cation is shared between two salts");
768  }
769  }
770  fm_neutralMolec_ions_[k + jNeut * m_kk] += fac;
771  }
772 
773  // Ok check the work
774  for (size_t m = 0; m < nElementsN; m++) {
775  if (fabs(elemVectorN[m]) > 1.0E-13) {
776  throw CanteraError("IonsFromNeutralVPSSTP::initThermoXML",
777  "Simple formula matrix generation failed");
778  }
779  }
780  }
781  // This includes the setStateFromXML calls
782  GibbsExcessVPSSTP::initThermoXML(phaseNode, id_);
783 }
784 
786 {
787  size_t icat, jNeut;
788  // Get the activity coefficiens of the neutral molecules
790 
791  switch (ionSolnType_) {
792  case cIonSolnType_PASSTHROUGH:
793  break;
794  case cIonSolnType_SINGLEANION:
795  // Do the cation list
796  for (size_t k = 0; k < cationList_.size(); k++) {
797  // Get the id for the next cation
798  icat = cationList_[k];
799  jNeut = fm_invert_ionForNeutral[icat];
800  double fmij = fm_neutralMolec_ions_[icat + jNeut * m_kk];
801  lnActCoeff_Scaled_[icat] = lnActCoeff_NeutralMolecule_[jNeut] / fmij;
802  }
803 
804  // Do the anion list
805  icat = anionList_[0];
806  jNeut = fm_invert_ionForNeutral[icat];
807  lnActCoeff_Scaled_[icat]= 0.0;
808 
809  // Do the list of neutral molecules
810  for (size_t k = 0; k < passThroughList_.size(); k++) {
811  icat = passThroughList_[k];
812  jNeut = fm_invert_ionForNeutral[icat];
814  }
815  break;
816 
817  case cIonSolnType_SINGLECATION:
818  throw CanteraError("IonsFromNeutralVPSSTP::s_update_lnActCoeff", "Unimplemented type");
819  break;
820  case cIonSolnType_MULTICATIONANION:
821  throw CanteraError("IonsFromNeutralVPSSTP::s_update_lnActCoeff", "Unimplemented type");
822  break;
823  default:
824  throw CanteraError("IonsFromNeutralVPSSTP::s_update_lnActCoeff", "Unimplemented type");
825  break;
826  }
827 }
828 
829 void IonsFromNeutralVPSSTP::getdlnActCoeffds(const doublereal dTds, const doublereal* const dXds,
830  doublereal* dlnActCoeffds) const
831 {
832  size_t icat, jNeut;
833  // Get the activity coefficients of the neutral molecules
834  if (!geThermo) {
835  for (size_t k = 0; k < m_kk; k++) {
836  dlnActCoeffds[k] = dXds[k] / moleFractions_[k];
837  }
838  return;
839  }
840 
841  getNeutralMoleculeMoleGrads(dXds, dX_NeutralMolecule_.data());
842 
843  // All mole fractions returned to normal
844  geThermo->getdlnActCoeffds(dTds, dX_NeutralMolecule_.data(), dlnActCoeff_NeutralMolecule_.data());
845 
846  switch (ionSolnType_) {
847  case cIonSolnType_PASSTHROUGH:
848  break;
849  case cIonSolnType_SINGLEANION:
850  // Do the cation list
851  for (size_t k = 0; k < cationList_.size(); k++) {
852  // Get the id for the next cation
853  icat = cationList_[k];
854  jNeut = fm_invert_ionForNeutral[icat];
855  double fmij = fm_neutralMolec_ions_[icat + jNeut * m_kk];
856  dlnActCoeffds[icat] = dlnActCoeff_NeutralMolecule_[jNeut]/fmij;
857  }
858 
859  // Do the anion list
860  icat = anionList_[0];
861  jNeut = fm_invert_ionForNeutral[icat];
862  dlnActCoeffds[icat]= 0.0;
863 
864  // Do the list of neutral molecules
865  for (size_t k = 0; k < passThroughList_.size(); k++) {
866  icat = passThroughList_[k];
867  jNeut = fm_invert_ionForNeutral[icat];
868  dlnActCoeffds[icat] = dlnActCoeff_NeutralMolecule_[jNeut];
869  }
870  break;
871 
872  case cIonSolnType_SINGLECATION:
873  throw CanteraError("IonsFromNeutralVPSSTP::s_update_lnActCoeffds", "Unimplemented type");
874  break;
875  case cIonSolnType_MULTICATIONANION:
876  throw CanteraError("IonsFromNeutralVPSSTP::s_update_lnActCoeffds", "Unimplemented type");
877  break;
878  default:
879  throw CanteraError("IonsFromNeutralVPSSTP::s_update_lnActCoeffds", "Unimplemented type");
880  break;
881  }
882 }
883 
885 {
886  size_t icat, jNeut;
887 
888  // Get the activity coefficients of the neutral molecules
889  if (!geThermo) {
890  dlnActCoeffdT_Scaled_.assign(m_kk, 0.0);
891  return;
892  }
893 
895 
896  switch (ionSolnType_) {
897  case cIonSolnType_PASSTHROUGH:
898  break;
899  case cIonSolnType_SINGLEANION:
900  // Do the cation list
901  for (size_t k = 0; k < cationList_.size(); k++) {
902  //! Get the id for the next cation
903  icat = cationList_[k];
904  jNeut = fm_invert_ionForNeutral[icat];
905  double fmij = fm_neutralMolec_ions_[icat + jNeut * m_kk];
907  }
908 
909  // Do the anion list
910  icat = anionList_[0];
911  jNeut = fm_invert_ionForNeutral[icat];
912  dlnActCoeffdT_Scaled_[icat]= 0.0;
913 
914  // Do the list of neutral molecules
915  for (size_t k = 0; k < passThroughList_.size(); k++) {
916  icat = passThroughList_[k];
917  jNeut = fm_invert_ionForNeutral[icat];
919  }
920  break;
921 
922  case cIonSolnType_SINGLECATION:
923  throw CanteraError("IonsFromNeutralVPSSTP::s_update_lnActCoeffdT", "Unimplemented type");
924  break;
925  case cIonSolnType_MULTICATIONANION:
926  throw CanteraError("IonsFromNeutralVPSSTP::s_update_lnActCoeffdT", "Unimplemented type");
927  break;
928  default:
929  throw CanteraError("IonsFromNeutralVPSSTP::s_update_lnActCoeffdT", "Unimplemented type");
930  break;
931  }
932 }
933 
935 {
936  size_t icat, jNeut;
937 
938  // Get the activity coefficients of the neutral molecules
939  if (!geThermo) {
940  dlnActCoeffdlnX_diag_.assign(m_kk, 0.0);
941  return;
942  }
943 
945 
946  switch (ionSolnType_) {
947  case cIonSolnType_PASSTHROUGH:
948  break;
949  case cIonSolnType_SINGLEANION:
950  // Do the cation list
951  for (size_t k = 0; k < cationList_.size(); k++) {
952  // Get the id for the next cation
953  icat = cationList_[k];
954  jNeut = fm_invert_ionForNeutral[icat];
955  double fmij = fm_neutralMolec_ions_[icat + jNeut * m_kk];
957  }
958 
959  // Do the anion list
960  icat = anionList_[0];
961  jNeut = fm_invert_ionForNeutral[icat];
962  dlnActCoeffdlnX_diag_[icat]= 0.0;
963 
964  // Do the list of neutral molecules
965  for (size_t k = 0; k < passThroughList_.size(); k++) {
966  icat = passThroughList_[k];
967  jNeut = fm_invert_ionForNeutral[icat];
969  }
970  break;
971 
972  case cIonSolnType_SINGLECATION:
973  throw CanteraError("IonsFromNeutralVPSSTP::s_update_lnActCoeff_dlnX_diag()", "Unimplemented type");
974  break;
975  case cIonSolnType_MULTICATIONANION:
976  throw CanteraError("IonsFromNeutralVPSSTP::s_update_lnActCoeff_dlnX_diag()", "Unimplemented type");
977  break;
978  default:
979  throw CanteraError("IonsFromNeutralVPSSTP::s_update_lnActCoeff_dlnX_diag()", "Unimplemented type");
980  break;
981  }
982 }
983 
985 {
986  size_t icat, jNeut;
987 
988  // Get the activity coefficients of the neutral molecules
989  if (!geThermo) {
990  dlnActCoeffdlnN_diag_.assign(m_kk, 0.0);
991  return;
992  }
993 
995 
996  switch (ionSolnType_) {
997  case cIonSolnType_PASSTHROUGH:
998  break;
999  case cIonSolnType_SINGLEANION:
1000  // Do the cation list
1001  for (size_t k = 0; k < cationList_.size(); k++) {
1002  // Get the id for the next cation
1003  icat = cationList_[k];
1004  jNeut = fm_invert_ionForNeutral[icat];
1005  double fmij = fm_neutralMolec_ions_[icat + jNeut * m_kk];
1007  }
1008 
1009  // Do the anion list
1010  icat = anionList_[0];
1011  jNeut = fm_invert_ionForNeutral[icat];
1012  dlnActCoeffdlnN_diag_[icat]= 0.0;
1013 
1014  // Do the list of neutral molecules
1015  for (size_t k = 0; k < passThroughList_.size(); k++) {
1016  icat = passThroughList_[k];
1017  jNeut = fm_invert_ionForNeutral[icat];
1019  }
1020  break;
1021 
1022  case cIonSolnType_SINGLECATION:
1023  throw CanteraError("IonsFromNeutralVPSSTP::s_update_lnActCoeff_dlnN_diag()", "Unimplemented type");
1024  break;
1025  case cIonSolnType_MULTICATIONANION:
1026  throw CanteraError("IonsFromNeutralVPSSTP::s_update_lnActCoeff_dlnN_diag()", "Unimplemented type");
1027  break;
1028  default:
1029  throw CanteraError("IonsFromNeutralVPSSTP::s_update_lnActCoeff_dlnN_diag()", "Unimplemented type");
1030  break;
1031  }
1032 }
1033 
1035 {
1036  size_t kcat = 0, kNeut = 0, mcat = 0, mNeut = 0;
1037  doublereal fmij = 0.0;
1039  // Get the activity coefficients of the neutral molecules
1040  if (!geThermo) {
1041  throw CanteraError("IonsFromNeutralVPSSTP::s_update_dlnActCoeff_dlnN()", "dynamic cast failed");
1042  }
1043  size_t nsp_ge = geThermo->nSpecies();
1044  geThermo->getdlnActCoeffdlnN(nsp_ge, &dlnActCoeffdlnN_NeutralMolecule_(0,0));
1045 
1046  switch (ionSolnType_) {
1047  case cIonSolnType_PASSTHROUGH:
1048  break;
1049  case cIonSolnType_SINGLEANION:
1050  // Do the cation list
1051  for (size_t k = 0; k < cationList_.size(); k++) {
1052  for (size_t m = 0; m < cationList_.size(); m++) {
1053  kcat = cationList_[k];
1054 
1055  kNeut = fm_invert_ionForNeutral[kcat];
1056  fmij = fm_neutralMolec_ions_[kcat + kNeut * m_kk];
1058 
1059  mcat = cationList_[m];
1060  mNeut = fm_invert_ionForNeutral[mcat];
1061  double mfmij = fm_neutralMolec_ions_[mcat + mNeut * m_kk];
1062 
1063  dlnActCoeffdlnN_(kcat,mcat) = dlnActCoeffdlnN_NeutralMolecule_(kNeut,mNeut) * mfmij / fmij;
1064 
1065  }
1066  for (size_t m = 0; m < passThroughList_.size(); m++) {
1067  mcat = passThroughList_[m];
1068  mNeut = fm_invert_ionForNeutral[mcat];
1069  dlnActCoeffdlnN_(kcat, mcat) = dlnActCoeffdlnN_NeutralMolecule_(kNeut, mNeut) / fmij;
1070  }
1071  }
1072 
1073  // Do the anion list -> anion activity coefficient is one
1074  kcat = anionList_[0];
1075  kNeut = fm_invert_ionForNeutral[kcat];
1076  for (size_t k = 0; k < m_kk; k++) {
1077  dlnActCoeffdlnN_(kcat, k) = 0.0;
1078  dlnActCoeffdlnN_(k, kcat) = 0.0;
1079  }
1080 
1081  // Do the list of neutral molecules
1082  for (size_t k = 0; k < passThroughList_.size(); k++) {
1083  kcat = passThroughList_[k];
1084  kNeut = fm_invert_ionForNeutral[kcat];
1086 
1087  for (size_t m = 0; m < m_kk; m++) {
1088  mcat = passThroughList_[m];
1089  mNeut = fm_invert_ionForNeutral[mcat];
1090  dlnActCoeffdlnN_(kcat, mcat) = dlnActCoeffdlnN_NeutralMolecule_(kNeut, mNeut);
1091  }
1092 
1093  for (size_t m = 0; m < cationList_.size(); m++) {
1094  mcat = cationList_[m];
1095  mNeut = fm_invert_ionForNeutral[mcat];
1096  dlnActCoeffdlnN_(kcat, mcat) = dlnActCoeffdlnN_NeutralMolecule_(kNeut,mNeut);
1097  }
1098  }
1099  break;
1100 
1101  case cIonSolnType_SINGLECATION:
1102  throw CanteraError("IonsFromNeutralVPSSTP::s_update_lnActCoeff_dlnN", "Unimplemented type");
1103  break;
1104  case cIonSolnType_MULTICATIONANION:
1105  throw CanteraError("IonsFromNeutralVPSSTP::s_update_lnActCoeff_dlnN", "Unimplemented type");
1106  break;
1107  default:
1108  throw CanteraError("IonsFromNeutralVPSSTP::s_update_lnActCoeff_dlnN", "Unimplemented type");
1109  break;
1110  }
1111 }
1112 
1113 }
virtual void getdlnActCoeffdlnN(const size_t ld, doublereal *const dlnActCoeffdlnN)
Get the array of derivatives of the log activity coefficients with respect to the log of the species ...
XML_Node * get_XML_Node(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:214
virtual void getLnActivityCoefficients(doublereal *lnac) const
Get the array of non-dimensional molar-based ln activity coefficients at the current solution tempera...
vector_fp muNeutralMolecule_
Storage vector for the neutral molecule chemical potentials.
ThermoPhase * newPhase(XML_Node &xmlphase)
Create a new ThermoPhase object and initializes it according to the XML tree.
size_t nElements() const
Number of elements.
Definition: Phase.cpp:161
vector_fp NeutralMolecMoleFractions_
Mole fractions using the Neutral Molecule Mole fraction basis.
Derived class for pressure dependent standard states of an ideal gas species.
vector_fp dlnActCoeffdlnX_diag_
Storage for the current derivative values of the gradients with respect to logarithm of the mole frac...
doublereal temperature() const
Temperature (K).
Definition: Phase.h:601
void resize(size_t n, size_t m, doublereal v=0.0)
Resize the array, and fill the new entries with &#39;v&#39;.
Definition: Array.h:112
Header for intermediate ThermoPhase object for phases which consist of ions whose thermodynamics is c...
const size_t npos
index returned by functions to indicate "no position"
Definition: ct_defs.h:165
virtual void getChemPotentials(doublereal *mu) const
Get the species chemical potentials. Units: J/kmol.
Definition: ThermoPhase.h:494
vector_fp m_speciesCharge
Vector of species charges. length m_kk.
Definition: Phase.h:800
Headers for the factory class that can create known ThermoPhase objects (see Thermodynamic Properties...
size_t indexSpecialSpecies_
Index of special species.
Class XML_Node is a tree-based representation of the contents of an XML file.
Definition: xml.h:97
void warn_deprecated(const std::string &method, const std::string &extra)
Print a warning indicating that method is deprecated.
Definition: global.cpp:54
size_t nSpecies() const
Returns the number of species in the phase.
Definition: Phase.h:262
STL namespace.
virtual doublereal density() const
Density (kg/m^3).
Definition: Phase.h:607
void constructPhaseFile(std::string inputFile, std::string id)
The following methods are used in the process of constructing the phase and setting its parameters fr...
virtual void compositionChanged()
Apply changes to the state which are needed after the composition changes.
bool IOwnNThermoPhase_
If true then we own the underlying neutral Molecule Phase.
void constructPhaseXML(XML_Node &phaseNode, std::string id)
Import and initialize an IonsFromNeutralVPSSTP phase specification in an XML tree into the current ob...
doublereal mean_X(const doublereal *const Q) const
Evaluate the mole-fraction-weighted mean of an array Q.
Definition: Phase.cpp:690
vector_fp lnActCoeff_NeutralMolecule_
Storage vector for the neutral molecule ln activity coefficients.
vector_fp dlnActCoeffdT_NeutralMolecule_
Storage vector for the neutral molecule d ln activity coefficients dT.
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
void s_update_dlnActCoeff_dlnX_diag() const
Update the derivative of the log of the activity coefficients wrt log(mole fraction) ...
vector_fp dlnActCoeffdlnN_diag_NeutralMolecule_
Storage vector for the neutral molecule d ln activity coefficients dlnN.
virtual void calcNeutralMoleculeMoleFractions() const
Calculate neutral molecule mole fractions.
vector_fp dlnActCoeffdlnN_diag_
Storage for the current derivative values of the gradients with respect to logarithm of the mole frac...
virtual void getChemPotentials(doublereal *mu) const
Get the species chemical potentials. Units: J/kmol.
virtual void getdlnActCoeffds(const doublereal dTds, const doublereal *const dXds, doublereal *dlnActCoeffds) const
Get the change in activity coefficients wrt changes in state (temp, mole fraction, etc) along a line in parameter space or along a line in physical space.
void s_update_dlnActCoeffdT() const
Update the temperature derivative of the ln activity coefficients.
IonSolnType_enumType ionSolnType_
Ion solution type.
virtual void getdlnActCoeffdlnN_diag(doublereal *dlnActCoeffdlnN_diag) const
Get the array of log species mole number derivatives of the log activity coefficients.
virtual void getdlnActCoeffdlnN(const size_t ld, doublereal *const dlnActCoeffdlnN)
Get the array of derivatives of the log activity coefficients with respect to the log of the species ...
virtual void compositionChanged()
Apply changes to the state which are needed after the composition changes.
void s_update_lnActCoeff() const
Update the activity coefficients.
Array2D dlnActCoeffdlnN_NeutralMolecule_
Storage vector for the neutral molecule d ln activity coefficients dlnN.
virtual doublereal gibbs_mole() const
Molar Gibbs function. Units: J/kmol.
void initLengths()
Initialize lengths of local variables after all species have been identified.
Base class for exceptions thrown by Cantera classes.
Definition: ctexceptions.h:65
virtual void calcDensity()
Calculate the density of the mixture using the partial molar volumes and mole fractions as input...
virtual void setMoleFractions(const doublereal *const x)
Set the mole fractions to the specified values.
Definition: Phase.cpp:327
virtual void getPartialMolarEntropies(doublereal *sbar) const
Returns an array of partial molar entropies for the species in the mixture.
void getMoleFractions(doublereal *const x) const
Get the species mole fraction vector.
Definition: Phase.cpp:542
void s_update_dlnActCoeff_dlnN() const
Update the derivative of the log of the activity coefficients wrt log(number of moles) - diagonal com...
std::vector< size_t > anionList_
List of the species in this ThermoPhase which are anion species.
void importPhase(XML_Node &phase, ThermoPhase *th)
Import a phase information into an empty ThermoPhase object.
virtual doublereal entropy_mole() const
Molar entropy. Units: J/kmol/K.
vector_fp lnActCoeff_Scaled_
Storage for the current values of the activity coefficients of the species.
virtual void setState_TP(doublereal t, doublereal p)
Set the temperature (K) and pressure (Pa)
virtual doublereal pressure() const
Returns the current pressure of the phase.
std::vector< size_t > passThroughList_
List of the species in this ThermoPhase which are passed through to the neutralMoleculePhase ThermoPh...
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
#define AssertTrace(expr)
Assertion must be true or an error is thrown.
Definition: ctexceptions.h:239
virtual doublereal cv_mole() const
Molar heat capacity at constant volume. Units: J/kmol/K.
virtual int eosType() const
Equation of state type flag.
virtual void calcIonMoleFractions(doublereal *const mf) const
Calculate ion mole fractions from neutral molecule mole fractions.
virtual void getdlnActCoeffdlnX_diag(doublereal *dlnActCoeffdlnX_diag) const
Get the array of ln mole fraction derivatives of the log activity coefficients - diagonal component o...
const doublereal SmallNumber
smallest number to compare to zero.
Definition: ct_defs.h:126
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
virtual void getdlnActCoeffdlnN_diag(doublereal *dlnActCoeffdlnN_diag) const
Get the array of log species mole number derivatives of the log activity coefficients.
std::vector< size_t > fm_invert_ionForNeutral
Mapping between ion species and neutral molecule for quick invert.
virtual doublereal enthalpy_mole() const
Return the Molar enthalpy. Units: J/kmol.
std::string id() const
Return the id attribute, if present.
Definition: xml.cpp:428
const doublereal GasConstant
Universal Gas Constant. [J/kmol/K].
Definition: ct_defs.h:64
virtual void getPartialMolarEnthalpies(doublereal *hbar) const
Returns an array of partial molar enthalpies for the species in the mixture.
virtual void initThermoXML(XML_Node &phaseNode, const std::string &id)
Import and initialize a ThermoPhase object using an XML tree.
Contains declarations for string manipulation functions within Cantera.
virtual void getStandardChemPotentials(doublereal *mu) const
Get the array of chemical potentials at unit activity for the species at their standard states at the...
Definition: ThermoPhase.h:579
std::vector< size_t > cationList_
List of the species in this ThermoPhase which are cation species.
vector_fp moleFractions_
Storage for the current values of the mole fractions of the species.
virtual void getActivityCoefficients(doublereal *ac) const
Get the array of non-dimensional molar-based activity coefficients at the current solution temperatur...
virtual void initThermoXML(XML_Node &phaseNode, const std::string &id)
Import and initialize a ThermoPhase object using an XML tree.
vector_fp fm_neutralMolec_ions_
Formula Matrix for composition of neutral molecules in terms of the molecules in this ThermoPhase...
size_t m_kk
Number of species in the phase.
Definition: Phase.h:784
Array2D dlnActCoeffdlnN_
Storage for the current derivative values of the gradients with respect to logarithm of the species m...
virtual void getEntropy_R(doublereal *sr) const
Get the array of nondimensional Entropy functions for the standard state species at the current T and...
void zero()
Set all of the entries to zero.
Definition: Array.h:220
virtual void initThermoFile(const std::string &inputFile, const std::string &id)
virtual ThermoPhase * duplMyselfAsThermoPhase() const
Duplication routine for objects which inherit from ThermoPhase.
void getDissociationCoeffs(vector_fp &fm_neutralMolec_ions, vector_fp &charges, std::vector< size_t > &neutMolIndex) const
Get the Salt Dissociation Coefficients.
virtual void getPartialMolarCp(doublereal *cpbar) const
Return an array of partial molar heat capacities for the species in the mixture.
Definition: ThermoPhase.h:551
Namespace for the Cantera kernel.
Definition: application.cpp:29
static double factorOverlap(const std::vector< std::string > &elnamesVN, const vector_fp &elemVectorN, const size_t nElementsN, const std::vector< std::string > &elnamesVI, const vector_fp &elemVectorI, const size_t nElementsI)
Return the factor overlap.
size_t indexSecondSpecialSpecies_
Index of special species.
Declarations for the class PDSS_IonsFromNeutral ( which handles calculations for a single ion in a fl...
doublereal nAtoms(size_t k, size_t m) const
Number of atoms of element m in species k.
Definition: Phase.cpp:237
size_t numNeutralMoleculeSpecies_
Number of neutral molecule species.
ThermoPhase * neutralMoleculePhase_
This is a pointer to the neutral Molecule Phase.
virtual void getdlnActCoeffdlnX_diag(doublereal *dlnActCoeffdlnX_diag) const
Get the array of ln mole fraction derivatives of the log activity coefficients - diagonal component o...
Definition: ThermoPhase.h:1606
virtual doublereal cp_mole() const
Molar heat capacity at constant pressure. Units: J/kmol/K.
virtual void getdlnActCoeffds(const doublereal dTds, const doublereal *const dXds, doublereal *dlnActCoeffds) const
Get the change in activity coefficients wrt changes in state (temp, mole fraction, etc) along a line in parameter space or along a line in physical space.
Definition: ThermoPhase.h:1586
const std::vector< std::string > & elementNames() const
Return a read-only reference to the vector of element names.
Definition: Phase.cpp:196
vector_fp moleFractionsTmp_
Temporary mole fraction vector.
void getNeutralMoleculeMoleGrads(const doublereal *const dx, doublereal *const dy) const
Calculate neutral molecule mole fractions.
virtual void getEnthalpy_RT(doublereal *hrt) const
Get the nondimensional Enthalpy functions for the species at their standard states at the current T a...
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:577
int specialSpecies_
True if this species is the special species.
virtual void getdlnActCoeffdT(doublereal *dlnActCoeffdT) const
Get the array of temperature derivatives of the log activity coefficients.
virtual void setDensity(const doublereal density_)
Set the internally stored density (kg/m^3) of the phase.
Definition: Phase.h:622
vector_fp dlnActCoeffdT_Scaled_
Storage for the current derivative values of the gradients with respect to temperature of the log of ...
void s_update_dlnActCoeff_dlnN_diag() const
Update the derivative of the log of the activity coefficients wrt log(number of moles) - diagonal com...
vector_fp dlnActCoeffdlnX_diag_NeutralMolecule_
Storage vector for the neutral molecule d ln activity coefficients dX - diagonal component.