Cantera  2.2.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
MolarityIonicVPSSTP.cpp
Go to the documentation of this file.
1 /**
2  * @file MolarityIonicVPSSTP.cpp
3  * Definitions for intermediate ThermoPhase object for phases which
4  * employ excess Gibbs free energy formulations
5  * (see \ref thermoprops
6  * and class \link Cantera::MolarityIonicVPSSTP MolarityIonicVPSSTP\endlink).
7  *
8  * Header file for a derived class of ThermoPhase that handles
9  * variable pressure standard state methods for calculating
10  * thermodynamic properties that are further based upon expressions
11  * for the excess Gibbs free energy expressed as a function of
12  * the mole fractions.
13  */
14 /*
15  * Copyright (2009) Sandia Corporation. Under the terms of
16  * Contract DE-AC04-94AL85000 with Sandia Corporation, the
17  * U.S. Government retains certain rights in this software.
18  */
22 
23 #include <cstdio>
24 
25 using namespace std;
26 
27 namespace Cantera
28 {
29 
30 MolarityIonicVPSSTP::MolarityIonicVPSSTP() :
31  PBType_(PBTYPE_PASSTHROUGH),
32  numPBSpecies_(m_kk),
33  indexSpecialSpecies_(npos),
34  neutralPBindexStart(0)
35 {
36 }
37 
38 MolarityIonicVPSSTP::MolarityIonicVPSSTP(const std::string& inputFile,
39  const std::string& id_) :
40  PBType_(PBTYPE_PASSTHROUGH),
41  numPBSpecies_(m_kk),
42  indexSpecialSpecies_(npos),
43  neutralPBindexStart(0)
44 {
45  initThermoFile(inputFile, id_);
46 }
47 
49  const std::string& id_) :
50  PBType_(PBTYPE_PASSTHROUGH),
51  numPBSpecies_(m_kk),
52  indexSpecialSpecies_(npos),
53  neutralPBindexStart(0)
54 {
55  importPhase(*findXMLPhase(&phaseRoot, id_), this);
56 }
57 
59  PBType_(PBTYPE_PASSTHROUGH),
60  numPBSpecies_(m_kk),
61  indexSpecialSpecies_(npos),
62  neutralPBindexStart(0)
63 {
64  *this = b;
65 }
66 
68 {
69  if (&b != this) {
71  }
72 
73  PBType_ = b.PBType_;
76  PBMoleFractions_ = b.PBMoleFractions_;
78  anionList_ = b.anionList_;
79  passThroughList_ = b.passThroughList_;
80  neutralPBindexStart = b.neutralPBindexStart;
81  moleFractionsTmp_ = b.moleFractionsTmp_;
82 
83  return *this;
84 }
85 
88 {
89  return new MolarityIonicVPSSTP(*this);
90 }
91 
92 /*
93  * - Activities, Standard States, Activity Concentrations -----------
94  */
95 
97 {
98  /*
99  * Update the activity coefficients
100  */
102 
103  /*
104  * take the exp of the internally stored coefficients.
105  */
106  for (size_t k = 0; k < m_kk; k++) {
107  lnac[k] = lnActCoeff_Scaled_[k];
108  }
109 }
110 
111 void MolarityIonicVPSSTP::getChemPotentials(doublereal* mu) const
112 {
113  /*
114  * First get the standard chemical potentials in
115  * molar form.
116  * -> this requires updates of standard state as a function
117  * of T and P
118  */
120  /*
121  * Update the activity coefficients
122  */
124  doublereal RT = GasConstant * temperature();
125  for (size_t k = 0; k < m_kk; k++) {
126  double xx = std::max(moleFractions_[k], SmallNumber);
127  mu[k] += RT * (log(xx) + lnActCoeff_Scaled_[k]);
128  }
129 }
130 
132 {
133  getChemPotentials(mu);
134  double ve = Faraday * electricPotential();
135  for (size_t k = 0; k < m_kk; k++) {
136  mu[k] += ve*charge(k);
137  }
138 }
139 
141 {
142  /*
143  * Get the nondimensional standard state enthalpies
144  */
145  getEnthalpy_RT(hbar);
146  /*
147  * dimensionalize it.
148  */
149  double T = temperature();
150  for (size_t k = 0; k < m_kk; k++) {
151  hbar[k] *= GasConstant * T;
152  }
153  /*
154  * Update the activity coefficients, This also update the
155  * internally stored molalities.
156  */
159  for (size_t k = 0; k < m_kk; k++) {
160  hbar[k] -= GasConstant * T * T * dlnActCoeffdT_Scaled_[k];
161  }
162 }
163 
164 void MolarityIonicVPSSTP::getPartialMolarCp(doublereal* cpbar) const
165 {
166  /*
167  * Get the nondimensional standard state entropies
168  */
169  getCp_R(cpbar);
170  double T = temperature();
171  /*
172  * Update the activity coefficients, This also update the
173  * internally stored molalities.
174  */
177 
178  for (size_t k = 0; k < m_kk; k++) {
179  cpbar[k] -= 2 * T * dlnActCoeffdT_Scaled_[k] + T * T * d2lnActCoeffdT2_Scaled_[k];
180  }
181  /*
182  * dimensionalize it.
183  */
184  for (size_t k = 0; k < m_kk; k++) {
185  cpbar[k] *= GasConstant;
186  }
187 }
188 
190 {
191  /*
192  * Get the nondimensional standard state entropies
193  */
194  getEntropy_R(sbar);
195  double T = temperature();
196  /*
197  * Update the activity coefficients, This also update the
198  * internally stored molalities.
199  */
202 
203  for (size_t k = 0; k < m_kk; k++) {
204  double xx = std::max(moleFractions_[k], SmallNumber);
205  sbar[k] += - lnActCoeff_Scaled_[k] -log(xx) - T * dlnActCoeffdT_Scaled_[k];
206  }
207  /*
208  * dimensionalize it.
209  */
210  for (size_t k = 0; k < m_kk; k++) {
211  sbar[k] *= GasConstant;
212  }
213 }
214 
216 {
217  /*
218  * Get the standard state values in m^3 kmol-1
219  */
220  getStandardVolumes(vbar);
221  for (size_t iK = 0; iK < m_kk; iK++) {
222  vbar[iK] += 0.0;
223  }
224 }
225 
227 {
228  switch (PBType_) {
229  case PBTYPE_PASSTHROUGH:
230  for (size_t k = 0; k < m_kk; k++) {
231  PBMoleFractions_[k] = moleFractions_[k];
232  }
233  break;
234  case PBTYPE_SINGLEANION:
235  {
236  double sumCat = 0.0;
237  double sumAnion = 0.0;
238  for (size_t k = 0; k < m_kk; k++) {
239  moleFractionsTmp_[k] = moleFractions_[k];
240  }
241  size_t kMax = npos;
242  double sumMax = 0.0;
243  for (size_t k = 0; k < cationList_.size(); k++) {
244  size_t kCat = cationList_[k];
245  double chP = m_speciesCharge[kCat];
246  if (moleFractions_[kCat] > sumMax) {
247  kMax = k;
248  sumMax = moleFractions_[kCat];
249  }
250  sumCat += chP * moleFractions_[kCat];
251  }
252  size_t ka = anionList_[0];
253  sumAnion = moleFractions_[ka] * m_speciesCharge[ka];
254  double sum = sumCat - sumAnion;
255  if (fabs(sum) > 1.0E-16) {
256  moleFractionsTmp_[cationList_[kMax]] -= sum / m_speciesCharge[kMax];
257  sum = 0.0;
258  for (size_t k = 0; k < cationList_.size(); k++) {
259  sum += moleFractionsTmp_[k];
260  }
261  for (size_t k = 0; k < cationList_.size(); k++) {
262  moleFractionsTmp_[k]/= sum;
263  }
264  }
265 
266  for (size_t k = 0; k < cationList_.size(); k++) {
267  PBMoleFractions_[k] = moleFractionsTmp_[cationList_[k]];
268  }
269  for (size_t k = 0; k < passThroughList_.size(); k++) {
270  PBMoleFractions_[neutralPBindexStart + k] = moleFractions_[passThroughList_[k]];
271  }
272 
273  sum = std::max(0.0, PBMoleFractions_[0]);
274  for (size_t k = 1; k < numPBSpecies_; k++) {
275  sum += PBMoleFractions_[k];
276 
277  }
278  for (size_t k = 0; k < numPBSpecies_; k++) {
279  PBMoleFractions_[k] /= sum;
280  }
281 
282  break;
283  }
284  case PBTYPE_SINGLECATION:
285  throw CanteraError("eosType", "Unknown type");
286 
287  break;
288 
289  case PBTYPE_MULTICATIONANION:
290  throw CanteraError("eosType", "Unknown type");
291 
292  break;
293  default:
294  throw CanteraError("eosType", "Unknown type");
295  break;
296 
297  }
298 }
299 
301 {
302  for (size_t k = 0; k < m_kk; k++) {
303  lnActCoeff_Scaled_[k] = 0.0;
304  }
305 }
306 
308 {
309 }
310 
312 {
313 }
314 
316 {
318  initLengths();
319  /*
320  * Go find the list of cations and anions
321  */
322  cationList_.clear();
323  anionList_.clear();
324  passThroughList_.clear();
325  for (size_t k = 0; k < m_kk; k++) {
326  double ch = m_speciesCharge[k];
327  if (ch > 0.0) {
328  cationList_.push_back(k);
329  } else if (ch < 0.0) {
330  anionList_.push_back(k);
331  } else {
332  passThroughList_.push_back(k);
333  }
334  }
335  numPBSpecies_ = cationList_.size() + anionList_.size() - 1;
336  neutralPBindexStart = numPBSpecies_;
337  PBType_ = PBTYPE_MULTICATIONANION;
338  if (anionList_.size() == 1) {
339  PBType_ = PBTYPE_SINGLEANION;
340  } else if (cationList_.size() == 1) {
341  PBType_ = PBTYPE_SINGLECATION;
342  }
343  if (anionList_.size() == 0 && cationList_.size() == 0) {
344  PBType_ = PBTYPE_PASSTHROUGH;
345  }
346 }
347 
349 {
350  moleFractionsTmp_.resize(m_kk);
351 }
352 
353 void MolarityIonicVPSSTP::initThermoXML(XML_Node& phaseNode, const std::string& id)
354 {
355  if ((int) id.size() > 0 && phaseNode.id() != id) {
356  throw CanteraError("MolarityIonicVPSSTP::initThermoXML",
357  "phasenode and Id are incompatible");
358  }
359 
360  /*
361  * Check on the thermo field. Must have one of:
362  * <thermo model="MolarityIonicVPSS" />
363  * <thermo model="MolarityIonicVPSSTP" />
364  */
365  if (!phaseNode.hasChild("thermo")) {
366  throw CanteraError("MolarityIonicVPSSTP::initThermoXML",
367  "no thermo XML node");
368  }
369  XML_Node& thermoNode = phaseNode.child("thermo");
370  std::string mStringa = thermoNode.attrib("model");
371  std::string mString = lowercase(mStringa);
372  if (mString != "molarityionicvpss" && mString != "molarityionicvpsstp") {
373  throw CanteraError("MolarityIonicVPSSTP::initThermoXML",
374  "Unknown thermo model: " + mStringa + " - This object only knows \"MolarityIonicVPSSTP\" ");
375  }
376 
377  /*
378  * Go get all of the coefficients and factors in the
379  * activityCoefficients XML block
380  */
381  if (thermoNode.hasChild("activityCoefficients")) {
382  XML_Node& acNode = thermoNode.child("activityCoefficients");
383  for (size_t i = 0; i < acNode.nChildren(); i++) {
384  XML_Node& xmlACChild = acNode.child(i);
385  /*
386  * Process a binary interaction
387  */
388  if (lowercase(xmlACChild.name()) == "binaryneutralspeciesparameters") {
389  readXMLBinarySpecies(xmlACChild);
390  }
391  }
392  }
393 
394 
395  /*
396  * Go down the chain
397  */
398  GibbsExcessVPSSTP::initThermoXML(phaseNode, id);
399 }
400 
402 {
403  std::string xname = xmLBinarySpecies.name();
404 }
405 
406 std::string MolarityIonicVPSSTP::report(bool show_thermo, doublereal threshold) const
407 {
408  char p[800];
409  string s = "";
410  try {
411  if (name() != "") {
412  sprintf(p, " \n %s:\n", name().c_str());
413  s += p;
414  }
415  sprintf(p, " \n temperature %12.6g K\n", temperature());
416  s += p;
417  sprintf(p, " pressure %12.6g Pa\n", pressure());
418  s += p;
419  sprintf(p, " density %12.6g kg/m^3\n", density());
420  s += p;
421  sprintf(p, " mean mol. weight %12.6g amu\n", meanMolecularWeight());
422  s += p;
423 
424  doublereal phi = electricPotential();
425  sprintf(p, " potential %12.6g V\n", phi);
426  s += p;
427 
428  vector_fp x(m_kk);
429  vector_fp molal(m_kk);
430  vector_fp mu(m_kk);
431  vector_fp muss(m_kk);
432  vector_fp acMolal(m_kk);
433  vector_fp actMolal(m_kk);
434  getMoleFractions(&x[0]);
435 
436  getChemPotentials(&mu[0]);
437  getStandardChemPotentials(&muss[0]);
438  getActivities(&actMolal[0]);
439 
440 
441  if (show_thermo) {
442  sprintf(p, " \n");
443  s += p;
444  sprintf(p, " 1 kg 1 kmol\n");
445  s += p;
446  sprintf(p, " ----------- ------------\n");
447  s += p;
448  sprintf(p, " enthalpy %12.6g %12.4g J\n",
450  s += p;
451  sprintf(p, " internal energy %12.6g %12.4g J\n",
453  s += p;
454  sprintf(p, " entropy %12.6g %12.4g J/K\n",
456  s += p;
457  sprintf(p, " Gibbs function %12.6g %12.4g J\n",
458  gibbs_mass(), gibbs_mole());
459  s += p;
460  sprintf(p, " heat capacity c_p %12.6g %12.4g J/K\n",
461  cp_mass(), cp_mole());
462  s += p;
463  try {
464  sprintf(p, " heat capacity c_v %12.6g %12.4g J/K\n",
465  cv_mass(), cv_mole());
466  s += p;
467  } catch (CanteraError& e) {
468  e.save();
469  sprintf(p, " heat capacity c_v <not implemented> \n");
470  s += p;
471  }
472  }
473 
474  } catch (CanteraError& e) {
475  e.save();
476  }
477  return s;
478 }
479 
480 }
virtual doublereal density() const
Density (kg/m^3).
Definition: Phase.h:608
doublereal electricPotential() const
Returns the electric potential of this phase (V).
Definition: ThermoPhase.h:352
virtual doublereal gibbs_mole() const
Molar Gibbs function. Units: J/kmol.
Definition: ThermoPhase.h:242
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
std::string attrib(const std::string &attr) const
Function returns the value of an attribute.
Definition: xml.cpp:527
GibbsExcessVPSSTP & operator=(const GibbsExcessVPSSTP &b)
Assignment operator.
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...
virtual void calcPseudoBinaryMoleFractions() const
Calculate pseudo binary mole fractions.
const size_t npos
index returned by functions to indicate "no position"
Definition: ct_defs.h:165
virtual void getActivities(doublereal *ac) const
Get the array of non-dimensional activities (molality based for this class and classes that derive fr...
vector_fp m_speciesCharge
Vector of species charges. length m_kk.
Definition: Phase.h:858
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 std::string report(bool show_thermo=true, doublereal threshold=1e-14) const
returns a summary of the state of the phase as a string
virtual void getPartialMolarCp(doublereal *cpbar) const
Returns an array of partial molar entropies for the species in the mixture.
virtual void getLnActivityCoefficients(doublereal *lnac) const
Get the array of non-dimensional molar-based ln activity coefficients at the current solution tempera...
void readXMLBinarySpecies(XML_Node &xmlBinarySpecies)
Process an XML node called "binaryNeutralSpeciesParameters".
Class XML_Node is a tree-based representation of the contents of an XML file.
Definition: xml.h:100
doublereal size(size_t k) const
This routine returns the size of species k.
Definition: Phase.h:411
std::vector< size_t > cationList_
Vector of cation indices in the mixture.
std::string lowercase(const std::string &s)
Cast a copy of a string to lower case.
Definition: stringUtils.cpp:73
std::vector< doublereal > d2lnActCoeffdT2_Scaled_
Storage for the current derivative values of the gradients with respect to temperature of the log of ...
void getMoleFractions(doublereal *const x) const
Get the species mole fraction vector.
Definition: Phase.cpp:556
std::string name() const
Return the name of the phase.
Definition: Phase.cpp:157
Header for intermediate ThermoPhase object for phases which employ Gibbs excess free energy based for...
MolarityIonicVPSSTP & operator=(const MolarityIonicVPSSTP &b)
Assignment operator.
virtual doublereal entropy_mole() const
Molar entropy. Units: J/kmol/K.
Definition: ThermoPhase.h:237
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
doublereal intEnergy_mass() const
Specific internal energy.
Definition: ThermoPhase.h:899
Base class for a phase with thermodynamic properties.
Definition: ThermoPhase.h:97
bool importPhase(XML_Node &phase, ThermoPhase *th, SpeciesThermoFactory *spfactory)
Import a phase information into an empty ThermoPhase object.
virtual doublereal intEnergy_mole() const
Molar internal energy. Units: J/kmol.
Definition: ThermoPhase.h:232
virtual doublereal enthalpy_mole() const
Molar enthalpy. Units: J/kmol.
Definition: ThermoPhase.h:227
void initThermoXML(XML_Node &phaseNode, const std::string &id)
Import and initialize a ThermoPhase object.
doublereal gibbs_mass() const
Specific Gibbs function.
Definition: ThermoPhase.h:913
virtual void getChemPotentials(doublereal *mu) const
Get the species chemical potentials. Units: J/kmol.
void s_update_dlnActCoeff_dT() const
Update the derivative of the log of the activity coefficients wrt T.
doublereal entropy_mass() const
Specific entropy.
Definition: ThermoPhase.h:906
doublereal pressure() const
Returns the current pressure of the phase.
std::string name() const
Returns the name of the XML node.
Definition: xml.h:394
doublereal cp_mass() const
Specific heat at constant pressure.
Definition: ThermoPhase.h:920
std::string id() const
Return the string id for the phase.
Definition: Phase.cpp:147
Base class for exceptions thrown by Cantera classes.
Definition: ctexceptions.h:99
doublereal cv_mass() const
Specific heat at constant volume.
Definition: ThermoPhase.h:927
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 getPartialMolarVolumes(doublereal *vbar) const
Return an array of partial molar volumes for the species in the mixture.
void getElectrochemPotentials(doublereal *mu) const
Get the species electrochemical potentials.
void initLengths()
Initialize lengths of local variables after all species have been identified.
virtual doublereal cv_mole() const
Molar heat capacity at constant volume. Units: J/kmol/K.
Definition: ThermoPhase.h:252
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
std::string id() const
Return the id attribute, if present.
Definition: xml.cpp:448
const doublereal SmallNumber
smallest number to compare to zero.
Definition: ct_defs.h:126
std::vector< doublereal > lnActCoeff_Scaled_
Storage for the current values of the activity coefficients of the species.
std::vector< double > vector_fp
Turn on the use of stl vectors for the basic array type within cantera Vector of doubles.
Definition: ct_defs.h:157
virtual void getPartialMolarEntropies(doublereal *sbar) const
Returns an array of partial molar entropies for the species in the mixture.
doublereal enthalpy_mass() const
Specific enthalpy.
Definition: ThermoPhase.h:892
std::vector< doublereal > moleFractions_
Storage for the current values of the mole fractions of the species.
virtual void getEnthalpy_RT(doublereal *hrt) const
Get the nondimensional Enthalpy functions for the species at their standard states at the current T a...
doublereal meanMolecularWeight() const
The mean molecular weight. Units: (kg/kmol)
Definition: Phase.h:669
const doublereal GasConstant
Universal Gas Constant. [J/kmol/K].
Definition: ct_defs.h:64
virtual void initThermoXML(XML_Node &phaseNode, const std::string &id)
Initialize a ThermoPhase object, potentially reading activity coefficient information from an XML dat...
Contains declarations for string manipulation functions within Cantera.
virtual void getPartialMolarEnthalpies(doublereal *hbar) const
Returns an array of partial molar enthalpies for the species in the mixture.
size_t numPBSpecies_
Number of pseudo binary species.
virtual ThermoPhase * duplMyselfAsThermoPhase() const
Duplication routine for objects which inherit from ThermoPhase.
virtual doublereal cp_mole() const
Molar heat capacity at constant pressure. Units: J/kmol/K.
Definition: ThermoPhase.h:247
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)
virtual void getStandardChemPotentials(doublereal *mu) const
Get the array of chemical potentials at unit activity.
size_t nChildren(bool discardComments=false) const
Return the number of children.
Definition: xml.cpp:583
void s_update_dlnActCoeff_dX_() const
Internal routine that calculates the derivative of the activity coefficients wrt the mole fractions...
size_t indexSpecialSpecies_
index of special species
std::vector< doublereal > dlnActCoeffdT_Scaled_
Storage for the current derivative values of the gradients with respect to temperature of the log of ...
void s_update_lnActCoeff() const
Update the activity coefficients.
doublereal charge(size_t k) const
Dimensionless electrical charge of a single molecule of species k The charge is normalized by the the...
Definition: Phase.h:578
void save()
Function to put this error onto Cantera's error stack.