Cantera  2.3.0
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 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 
20 
21 #include <cstdio>
22 
23 using namespace std;
24 
25 namespace Cantera
26 {
27 
28 MolarityIonicVPSSTP::MolarityIonicVPSSTP() :
29  PBType_(PBTYPE_PASSTHROUGH),
30  numPBSpecies_(m_kk),
31  indexSpecialSpecies_(npos),
32  neutralPBindexStart(0)
33 {
34 }
35 
36 MolarityIonicVPSSTP::MolarityIonicVPSSTP(const std::string& inputFile,
37  const std::string& id_) :
38  PBType_(PBTYPE_PASSTHROUGH),
39  numPBSpecies_(m_kk),
40  indexSpecialSpecies_(npos),
41  neutralPBindexStart(0)
42 {
43  initThermoFile(inputFile, id_);
44 }
45 
46 MolarityIonicVPSSTP::MolarityIonicVPSSTP(XML_Node& phaseRoot,
47  const std::string& id_) :
48  PBType_(PBTYPE_PASSTHROUGH),
49  numPBSpecies_(m_kk),
50  indexSpecialSpecies_(npos),
51  neutralPBindexStart(0)
52 {
53  importPhase(phaseRoot, this);
54 }
55 
56 MolarityIonicVPSSTP::MolarityIonicVPSSTP(const MolarityIonicVPSSTP& b) :
57  PBType_(PBTYPE_PASSTHROUGH),
58  numPBSpecies_(m_kk),
59  indexSpecialSpecies_(npos),
60  neutralPBindexStart(0)
61 {
62  *this = b;
63 }
64 
65 MolarityIonicVPSSTP& MolarityIonicVPSSTP::operator=(const MolarityIonicVPSSTP& b)
66 {
67  if (&b != this) {
68  GibbsExcessVPSSTP::operator=(b);
69  }
70 
71  PBType_ = b.PBType_;
72  numPBSpecies_ = b.numPBSpecies_;
73  indexSpecialSpecies_ = b.indexSpecialSpecies_;
74  PBMoleFractions_ = b.PBMoleFractions_;
75  cationList_ = b.cationList_;
76  anionList_ = b.anionList_;
77  passThroughList_ = b.passThroughList_;
78  neutralPBindexStart = b.neutralPBindexStart;
79  moleFractionsTmp_ = b.moleFractionsTmp_;
80 
81  return *this;
82 }
83 
85 {
86  return new MolarityIonicVPSSTP(*this);
87 }
88 
89 // - Activities, Standard States, Activity Concentrations -----------
90 
92 {
93  // Update the activity coefficients
95 
96  // take the exp of the internally stored coefficients.
97  for (size_t k = 0; k < m_kk; k++) {
98  lnac[k] = lnActCoeff_Scaled_[k];
99  }
100 }
101 
102 void MolarityIonicVPSSTP::getChemPotentials(doublereal* mu) const
103 {
104  // First get the standard chemical potentials in molar form. This requires
105  // updates of standard state as a function of T and P
107 
108  // Update the activity coefficients
110  for (size_t k = 0; k < m_kk; k++) {
111  double xx = std::max(moleFractions_[k], SmallNumber);
112  mu[k] += RT() * (log(xx) + lnActCoeff_Scaled_[k]);
113  }
114 }
115 
117 {
118  // Get the nondimensional standard state enthalpies
119  getEnthalpy_RT(hbar);
120 
121  // dimensionalize it.
122  double T = temperature();
123  for (size_t k = 0; k < m_kk; k++) {
124  hbar[k] *= GasConstant * T;
125  }
126 
127  // Update the activity coefficients, This also update the internally stored
128  // molalities.
131  for (size_t k = 0; k < m_kk; k++) {
132  hbar[k] -= GasConstant * T * T * dlnActCoeffdT_Scaled_[k];
133  }
134 }
135 
136 void MolarityIonicVPSSTP::getPartialMolarCp(doublereal* cpbar) const
137 {
138  // Get the nondimensional standard state entropies
139  getCp_R(cpbar);
140  double T = temperature();
141 
142  // Update the activity coefficients, This also update the internally stored
143  // molalities.
146 
147  for (size_t k = 0; k < m_kk; k++) {
148  cpbar[k] -= 2 * T * dlnActCoeffdT_Scaled_[k] + T * T * d2lnActCoeffdT2_Scaled_[k];
149  }
150 
151  // dimensionalize it.
152  for (size_t k = 0; k < m_kk; k++) {
153  cpbar[k] *= GasConstant;
154  }
155 }
156 
158 {
159  // Get the nondimensional standard state entropies
160  getEntropy_R(sbar);
161  double T = temperature();
162 
163  // Update the activity coefficients, This also update the internally stored
164  // molalities.
167 
168  for (size_t k = 0; k < m_kk; k++) {
169  double xx = std::max(moleFractions_[k], SmallNumber);
170  sbar[k] += - lnActCoeff_Scaled_[k] -log(xx) - T * dlnActCoeffdT_Scaled_[k];
171  }
172 
173  // dimensionalize it.
174  for (size_t k = 0; k < m_kk; k++) {
175  sbar[k] *= GasConstant;
176  }
177 }
178 
180 {
181  // Get the standard state values in m^3 kmol-1
182  getStandardVolumes(vbar);
183  for (size_t iK = 0; iK < m_kk; iK++) {
184  vbar[iK] += 0.0;
185  }
186 }
187 
189 {
190  switch (PBType_) {
191  case PBTYPE_PASSTHROUGH:
192  for (size_t k = 0; k < m_kk; k++) {
193  PBMoleFractions_[k] = moleFractions_[k];
194  }
195  break;
196  case PBTYPE_SINGLEANION:
197  {
198  double sumCat = 0.0;
199  double sumAnion = 0.0;
200  for (size_t k = 0; k < m_kk; k++) {
201  moleFractionsTmp_[k] = moleFractions_[k];
202  }
203  size_t kMax = npos;
204  double sumMax = 0.0;
205  for (size_t k = 0; k < cationList_.size(); k++) {
206  size_t kCat = cationList_[k];
207  double chP = m_speciesCharge[kCat];
208  if (moleFractions_[kCat] > sumMax) {
209  kMax = k;
210  sumMax = moleFractions_[kCat];
211  }
212  sumCat += chP * moleFractions_[kCat];
213  }
214  size_t ka = anionList_[0];
215  sumAnion = moleFractions_[ka] * m_speciesCharge[ka];
216  double sum = sumCat - sumAnion;
217  if (fabs(sum) > 1.0E-16) {
218  moleFractionsTmp_[cationList_[kMax]] -= sum / m_speciesCharge[kMax];
219  sum = 0.0;
220  for (size_t k = 0; k < cationList_.size(); k++) {
221  sum += moleFractionsTmp_[k];
222  }
223  for (size_t k = 0; k < cationList_.size(); k++) {
224  moleFractionsTmp_[k]/= sum;
225  }
226  }
227 
228  for (size_t k = 0; k < cationList_.size(); k++) {
229  PBMoleFractions_[k] = moleFractionsTmp_[cationList_[k]];
230  }
231  for (size_t k = 0; k < passThroughList_.size(); k++) {
232  PBMoleFractions_[neutralPBindexStart + k] = moleFractions_[passThroughList_[k]];
233  }
234 
235  sum = std::max(0.0, PBMoleFractions_[0]);
236  for (size_t k = 1; k < numPBSpecies_; k++) {
237  sum += PBMoleFractions_[k];
238  }
239  for (size_t k = 0; k < numPBSpecies_; k++) {
240  PBMoleFractions_[k] /= sum;
241  }
242  break;
243  }
244  case PBTYPE_SINGLECATION:
245  throw CanteraError("eosType", "Unknown type");
246  case PBTYPE_MULTICATIONANION:
247  throw CanteraError("eosType", "Unknown type");
248  default:
249  throw CanteraError("eosType", "Unknown type");
250  }
251 }
252 
254 {
255  for (size_t k = 0; k < m_kk; k++) {
256  lnActCoeff_Scaled_[k] = 0.0;
257  }
258 }
259 
261 {
262 }
263 
265 {
266 }
267 
269 {
271  initLengths();
272 
273  // Go find the list of cations and anions
274  cationList_.clear();
275  anionList_.clear();
276  passThroughList_.clear();
277  for (size_t k = 0; k < m_kk; k++) {
278  double ch = m_speciesCharge[k];
279  if (ch > 0.0) {
280  cationList_.push_back(k);
281  } else if (ch < 0.0) {
282  anionList_.push_back(k);
283  } else {
284  passThroughList_.push_back(k);
285  }
286  }
287  numPBSpecies_ = cationList_.size() + anionList_.size() - 1;
288  neutralPBindexStart = numPBSpecies_;
289  PBType_ = PBTYPE_MULTICATIONANION;
290  if (anionList_.size() == 1) {
291  PBType_ = PBTYPE_SINGLEANION;
292  } else if (cationList_.size() == 1) {
293  PBType_ = PBTYPE_SINGLECATION;
294  }
295  if (anionList_.size() == 0 && cationList_.size() == 0) {
296  PBType_ = PBTYPE_PASSTHROUGH;
297  }
298 }
299 
301 {
302  moleFractionsTmp_.resize(m_kk);
303 }
304 
305 void MolarityIonicVPSSTP::initThermoXML(XML_Node& phaseNode, const std::string& id)
306 {
307  if ((int) id.size() > 0 && phaseNode.id() != id) {
308  throw CanteraError("MolarityIonicVPSSTP::initThermoXML",
309  "phasenode and Id are incompatible");
310  }
311 
312  // Check on the thermo field. Must have one of:
313  // <thermo model="MolarityIonicVPSS" />
314  // <thermo model="MolarityIonicVPSSTP" />
315  if (!phaseNode.hasChild("thermo")) {
316  throw CanteraError("MolarityIonicVPSSTP::initThermoXML",
317  "no thermo XML node");
318  }
319  XML_Node& thermoNode = phaseNode.child("thermo");
320  if (!ba::iequals(thermoNode["model"], "molarityionicvpss")
321  && !ba::iequals(thermoNode["model"], "molarityionicvpsstp")) {
322  throw CanteraError("MolarityIonicVPSSTP::initThermoXML",
323  "Unknown thermo model: " + thermoNode["model"]
324  + " - This object only knows \"MolarityIonicVPSSTP\" ");
325  }
326 
327  // Go get all of the coefficients and factors in the activityCoefficients
328  // XML block
329  if (thermoNode.hasChild("activityCoefficients")) {
330  XML_Node& acNode = thermoNode.child("activityCoefficients");
331  for (size_t i = 0; i < acNode.nChildren(); i++) {
332  XML_Node& xmlACChild = acNode.child(i);
333  // Process a binary interaction
334  if (ba::iequals(xmlACChild.name(), "binaryneutralspeciesparameters")) {
335  readXMLBinarySpecies(xmlACChild);
336  }
337  }
338  }
339 
340  // Go down the chain
341  GibbsExcessVPSSTP::initThermoXML(phaseNode, id);
342 }
343 
345 {
346  std::string xname = xmLBinarySpecies.name();
347 }
348 
349 std::string MolarityIonicVPSSTP::report(bool show_thermo, doublereal threshold) const
350 {
351  fmt::MemoryWriter b;
352  try {
353  if (name() != "") {
354  b.write("\n {}:\n", name());
355  }
356  b.write("\n");
357  b.write(" temperature {:12.6g} K\n", temperature());
358  b.write(" pressure {:12.6g} Pa\n", pressure());
359  b.write(" density {:12.6g} kg/m^3\n", density());
360  b.write(" mean mol. weight {:12.6g} amu\n", meanMolecularWeight());
361 
362  doublereal phi = electricPotential();
363  b.write(" potential {:12.6g} V\n", phi);
364 
365  vector_fp x(m_kk);
366  vector_fp molal(m_kk);
367  vector_fp mu(m_kk);
368  vector_fp muss(m_kk);
369  vector_fp acMolal(m_kk);
370  vector_fp actMolal(m_kk);
371  getMoleFractions(&x[0]);
372 
373  getChemPotentials(&mu[0]);
374  getStandardChemPotentials(&muss[0]);
375  getActivities(&actMolal[0]);
376 
377  if (show_thermo) {
378  b.write("\n");
379  b.write(" 1 kg 1 kmol\n");
380  b.write(" ----------- ------------\n");
381  b.write(" enthalpy {:12.6g} {:12.4g} J\n",
383  b.write(" internal energy {:12.6g} {:12.4g} J\n",
385  b.write(" entropy {:12.6g} {:12.4g} J/K\n",
387  b.write(" Gibbs function {:12.6g} {:12.4g} J\n",
388  gibbs_mass(), gibbs_mole());
389  b.write(" heat capacity c_p {:12.6g} {:12.4g} J/K\n",
390  cp_mass(), cp_mole());
391  try {
392  b.write(" heat capacity c_v {:12.6g} {:12.4g} J/K\n",
393  cv_mass(), cv_mole());
394  } catch (NotImplementedError&) {
395  b.write(" heat capacity c_v <not implemented>\n");
396  }
397  }
398  } catch (CanteraError& e) {
399  return b.str() + e.what();
400  }
401  return b.str();
402 }
403 
404 }
virtual void getPartialMolarVolumes(doublereal *vbar) const
Return an array of partial molar volumes for the species in the mixture.
std::string name() const
Returns the name of the XML node.
Definition: xml.h:370
virtual void calcPseudoBinaryMoleFractions() const
Calculate pseudo binary mole fractions.
doublereal temperature() const
Temperature (K).
Definition: Phase.h:601
virtual doublereal cv_mole() const
Molar heat capacity at constant volume. Units: J/kmol/K.
Definition: ThermoPhase.h:263
An error indicating that an unimplemented function has been called.
Definition: ctexceptions.h:193
doublereal cp_mass() const
Specific heat at constant pressure. Units: J/kg/K.
Definition: ThermoPhase.h:784
const size_t npos
index returned by functions to indicate "no position"
Definition: ct_defs.h:165
void s_update_dlnActCoeff_dT() const
Update the derivative of the log of the activity coefficients wrt T.
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...
void readXMLBinarySpecies(XML_Node &xmlBinarySpecies)
Process an XML node called "binaryNeutralSpeciesParameters".
const char * what() const
Get a description of the error.
Class XML_Node is a tree-based representation of the contents of an XML file.
Definition: xml.h:97
virtual void getCp_R(doublereal *cpr) const
Get the nondimensional Heat Capacities at constant pressure for the species standard states at the cu...
STL namespace.
virtual doublereal density() const
Density (kg/m^3).
Definition: Phase.h:607
doublereal enthalpy_mass() const
Specific enthalpy. Units: J/kg.
Definition: ThermoPhase.h:764
std::vector< size_t > cationList_
Vector of cation indices in the mixture.
virtual doublereal enthalpy_mole() const
Molar enthalpy. Units: J/kmol.
Definition: ThermoPhase.h:238
(see Thermodynamic Properties and class MolarityIonicVPSSTP).
void s_update_lnActCoeff() const
Update the activity coefficients.
doublereal RT() const
Return the Gas Constant multiplied by the current temperature.
Definition: ThermoPhase.h:809
virtual void getPartialMolarEntropies(doublereal *sbar) const
Returns an array of partial molar entropies for the species in the mixture.
Base class for a phase with thermodynamic properties.
Definition: ThermoPhase.h:93
virtual void getChemPotentials(doublereal *mu) const
Get the species chemical potentials. Units: J/kmol.
virtual doublereal intEnergy_mole() const
Molar internal energy. Units: J/kmol.
Definition: ThermoPhase.h:243
virtual doublereal gibbs_mole() const
Molar Gibbs function. Units: J/kmol.
Definition: ThermoPhase.h:253
virtual void initThermoXML(XML_Node &phaseNode, const std::string &id)
Import and initialize a ThermoPhase object using an XML tree.
vector_fp d2lnActCoeffdT2_Scaled_
Storage for the current derivative values of the gradients with respect to temperature of the log of ...
doublereal electricPotential() const
Returns the electric potential of this phase (V).
Definition: ThermoPhase.h:335
doublereal entropy_mass() const
Specific entropy. Units: J/kg/K.
Definition: ThermoPhase.h:774
virtual void getStandardChemPotentials(doublereal *mu) const
Get the array of chemical potentials at unit activity for the species at their standard states at the...
Base class for exceptions thrown by Cantera classes.
Definition: ctexceptions.h:65
virtual doublereal cp_mole() const
Molar heat capacity at constant pressure. Units: J/kmol/K.
Definition: ThermoPhase.h:258
void getMoleFractions(doublereal *const x) const
Get the species mole fraction vector.
Definition: Phase.cpp:542
void importPhase(XML_Node &phase, ThermoPhase *th)
Import a phase information into an empty ThermoPhase object.
vector_fp lnActCoeff_Scaled_
Storage for the current values of the activity coefficients of the species.
virtual doublereal pressure() const
Returns the current pressure of the phase.
virtual ThermoPhase * duplMyselfAsThermoPhase() const
Duplication routine for objects which inherit from ThermoPhase.
void initLengths()
Initialize lengths of local variables after all species have been identified.
virtual void getActivities(doublereal *ac) const
Get the array of non-dimensional activities (molality based for this class and classes that derive fr...
void s_update_dlnActCoeff_dX_() const
Internal routine that calculates the derivative of the activity coefficients wrt the mole fractions...
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
virtual void getLnActivityCoefficients(doublereal *lnac) const
Get the array of non-dimensional molar-based ln activity coefficients at the current solution tempera...
doublereal cv_mass() const
Specific heat at constant volume. Units: J/kg/K.
Definition: ThermoPhase.h:789
virtual void getPartialMolarCp(doublereal *cpbar) const
Returns an array of partial molar entropies for the species in the mixture.
std::string id() const
Return the string id for the phase.
Definition: Phase.cpp:141
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
doublereal meanMolecularWeight() const
The mean molecular weight. Units: (kg/kmol)
Definition: Phase.h:661
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
doublereal gibbs_mass() const
Specific Gibbs function. Units: J/kg.
Definition: ThermoPhase.h:779
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
std::string name() const
Return the name of the phase.
Definition: Phase.cpp:151
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.
doublereal size(size_t k) const
This routine returns the size of species k.
Definition: Phase.h:414
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.
vector_fp moleFractions_
Storage for the current values of the mole fractions of the species.
size_t m_kk
Number of species in the phase.
Definition: Phase.h:784
virtual void getEntropy_R(doublereal *sr) const
Get the array of nondimensional Entropy functions for the standard state species at the current T and...
virtual void initThermoFile(const std::string &inputFile, const std::string &id)
Namespace for the Cantera kernel.
Definition: application.cpp:29
doublereal intEnergy_mass() const
Specific internal energy. Units: J/kg.
Definition: ThermoPhase.h:769
virtual doublereal entropy_mole() const
Molar entropy. Units: J/kmol/K.
Definition: ThermoPhase.h:248
size_t nChildren(bool discardComments=false) const
Return the number of children.
Definition: xml.cpp:556
virtual void getEnthalpy_RT(doublereal *hrt) const
Get the nondimensional Enthalpy functions for the species at their standard states at the current T a...
size_t indexSpecialSpecies_
index of special species
virtual void getStandardVolumes(doublereal *vol) const
Get the molar volumes of the species standard states at the current T and P of the solution...
vector_fp dlnActCoeffdT_Scaled_
Storage for the current derivative values of the gradients with respect to temperature of the log of ...