Cantera  2.2.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
MaskellSolidSolnPhase.cpp
Go to the documentation of this file.
1 /**
2  * @file MaskellSolidSolnPhase.cpp Implementation file for an ideal solid
3  * solution model with incompressible thermodynamics (see \ref
4  * thermoprops and \link Cantera::MaskellSolidSolnPhase
5  * MaskellSolidSolnPhase\endlink).
6  */
7 /*
8  * Copyright 2006 Sandia Corporation. Under the terms of Contract
9  * DE-AC04-94AL85000, with Sandia Corporation, the U.S. Government
10  * retains certain rights in this software.
11  */
12 
15 #include "cantera/base/xml.h"
16 
17 #include <cassert>
18 
19 namespace Cantera
20 {
21 
22 MaskellSolidSolnPhase::MaskellSolidSolnPhase() :
23  m_Pcurrent(OneAtm),
24  m_h0_RT(2),
25  m_cp0_R(2),
26  m_g0_RT(2),
27  m_s0_R(2),
28  h_mixing(0.0),
29  product_species_index(0),
30  reactant_species_index(1)
31 {
32 }
33 
34 MaskellSolidSolnPhase::MaskellSolidSolnPhase(const MaskellSolidSolnPhase& b) :
35  m_Pcurrent(OneAtm),
36  m_h0_RT(2),
37  m_cp0_R(2),
38  m_g0_RT(2),
39  m_s0_R(2),
40  h_mixing(0.0),
41  product_species_index(0),
42  reactant_species_index(1)
43 {
44  *this = b;
45 }
46 
49 {
50  if (this != &b) {
52  }
53  return *this;
54 }
55 
57 {
58  return new MaskellSolidSolnPhase(*this);
59 }
60 
62 {
64  for (size_t sp = 0; sp < m_kk; ++sp) {
65  c[sp] *= moleFraction(sp);
66  }
67 }
68 
69 /********************************************************************
70  * Molar Thermodynamic Properties of the Solution
71  ********************************************************************/
73 {
74  _updateThermo();
75  const doublereal h0 = GasConstant * temperature() * mean_X(m_h0_RT);
76  const doublereal r = moleFraction(product_species_index);
77  const doublereal fmval = fm(r);
78  return h0 + r * fmval * h_mixing;
79 }
80 
81 doublereal xlogx(doublereal x)
82 {
83  return x * std::log(x);
84 }
85 
87 {
88  _updateThermo();
89  const doublereal s0 = GasConstant * mean_X(m_s0_R);
90  const doublereal r = moleFraction(product_species_index);
91  const doublereal fmval = fm(r);
92  const doublereal rfm = r * fmval;
93  return s0 + GasConstant * (xlogx(1-rfm) - xlogx(rfm) - xlogx(1-r-rfm) - xlogx((1-fmval)*r) - xlogx(1-r) - xlogx(r));
94 }
95 
96 /********************************************************************
97  * Mechanical Equation of State
98  ********************************************************************/
99 
100 void MaskellSolidSolnPhase::setDensity(const doublereal rho)
101 {
102  /*
103  * Unless the input density is exactly equal to the density
104  * calculated and stored in the State object, we throw an
105  * exception. This is because the density is NOT an
106  * independent variable.
107  */
108  double dens = density();
109  if (rho != dens) {
110  throw CanteraError("MaskellSolidSolnPhase::setDensity",
111  "Density is not an independent variable");
112  }
113 }
114 
116 {
117  const vector_fp& vbar = getStandardVolumes();
118 
119  vector_fp moleFracs(m_kk);
120  Phase::getMoleFractions(&moleFracs[0]);
121  doublereal vtotal = 0.0;
122  for (size_t i = 0; i < m_kk; i++) {
123  vtotal += vbar[i] * moleFracs[i];
124  }
126 }
127 
129 {
130  m_Pcurrent = p;
131 }
132 
134 {
135  throw CanteraError("MaskellSolidSolnPhase::setMolarDensity",
136  "Density is not an independent variable");
137 }
138 
139 /********************************************************************
140  * Chemical Potentials and Activities
141  ********************************************************************/
142 
144 {
145  _updateThermo();
146  static const int cacheId = m_cache.getId();
147  CachedArray cached = m_cache.getArray(cacheId);
148  if (!cached.validate(temperature(), pressure(), stateMFNumber())) {
149  cached.value.resize(2);
150 
151  const doublereal r = moleFraction(product_species_index);
152  const doublereal pval = p(r);
153  const doublereal rfm = r * fm(r);
154  const doublereal A = (std::pow(1 - rfm, pval) * std::pow(rfm, pval) * std::pow(r - rfm, 1 - pval)) /
155  (std::pow(1 - r - rfm, 1 + pval) * (1 - r));
156  const doublereal B = pval * h_mixing / (GasConstant * temperature());
157  cached.value[product_species_index] = A * std::exp(B);
158  cached.value[reactant_species_index] = 1 / (A * r * (1-r) ) * std::exp(-B);
159  }
160  std::copy(cached.value.begin(), cached.value.end(), ac);
161 }
162 
164 {
165  _updateThermo();
166  const doublereal r = moleFraction(product_species_index);
167  const doublereal pval = p(r);
168  const doublereal rfm = r * fm(r);
169  const doublereal RT = GasConstant * temperature();
170  const doublereal DgbarDr = pval * h_mixing +
172  std::log( (std::pow(1 - rfm, pval) * std::pow(rfm, pval) * std::pow(r - rfm, 1 - pval) * r) /
173  (std::pow(1 - r - rfm, 1 + pval) * (1 - r)) );
175  mu[reactant_species_index] = RT * m_g0_RT[reactant_species_index] - DgbarDr;
176 }
177 
179 {
180  const doublereal invRT = 1.0 / (GasConstant * temperature());
181  getChemPotentials(mu);
182  for (size_t sp=0; sp < m_kk; ++sp) {
183  mu[sp] *= invRT;
184  }
185 }
186 
187 /********************************************************************
188  * Partial Molar Properties
189  ********************************************************************/
190 
192 {
193  throw CanteraError("MaskellSolidSolnPhase::getPartialMolarEnthalpies()", "Not yet implemented.");
194 }
195 
197 {
198  throw CanteraError("MaskellSolidSolnPhase::getPartialMolarEntropies()", "Not yet implemented.");
199 }
200 
201 void MaskellSolidSolnPhase::getPartialMolarCp(doublereal* cpbar) const
202 {
203  throw CanteraError("MaskellSolidSolnPhase::getPartialMolarCp()", "Not yet implemented.");
204 }
205 
207 {
208  getStandardVolumes(vbar);
209 }
210 
211 void MaskellSolidSolnPhase::getPureGibbs(doublereal* gpure) const
212 {
213  _updateThermo();
214  const doublereal RT = GasConstant * temperature();
215  for (size_t sp=0; sp < m_kk; ++sp) {
216  gpure[sp] = RT * m_g0_RT[sp];
217  }
218 }
219 
221 {
222  // What is the difference between this and getPureGibbs? IdealSolidSolnPhase gives the same for both
223  getPureGibbs(mu);
224 }
225 
226 /*********************************************************************
227  * Utility Functions
228  *********************************************************************/
229 void MaskellSolidSolnPhase::initThermoXML(XML_Node& phaseNode, const std::string& id_)
230 {
231  if (id_.size() > 0 && phaseNode.id() != id_) {
232  throw CanteraError("MaskellSolidSolnPhase::initThermoXML",
233  "phasenode and Id are incompatible");
234  }
235 
236  /*
237  * Check on the thermo field. Must have:
238  * <thermo model="MaskellSolidSolution" />
239  */
240  if (phaseNode.hasChild("thermo")) {
241  XML_Node& thNode = phaseNode.child("thermo");
242  std::string mString = thNode.attrib("model");
243  if (lowercase(mString) != "maskellsolidsolnphase") {
244  throw CanteraError("MaskellSolidSolnPhase::initThermoXML",
245  "Unknown thermo model: " + mString);
246  }
247 
248  /*
249  * Parse the enthalpy of mixing constant
250  */
251  if (thNode.hasChild("h_mix")) {
252  set_h_mix(fpValue(thNode.child("h_mix").value()));
253  } else {
254  throw CanteraError("MaskellSolidSolnPhase::initThermoXML",
255  "Mixing enthalpy parameter not specified.");
256  }
257 
258  if (thNode.hasChild("product_species")) {
259  std::string product_species_name = thNode.child("product_species").value();
260  product_species_index = static_cast<int>(speciesIndex(product_species_name));
261  if (product_species_index == -1) {
262  throw CanteraError("MaskellSolidSolnPhase::initThermoXML",
263  "Species " + product_species_name + " not found.");
264  }
265  if (product_species_index == 0) {
266  reactant_species_index = 1;
267  } else {
268  reactant_species_index = 0;
269  }
270  }
271  } else {
272  throw CanteraError("MaskellSolidSolnPhase::initThermoXML",
273  "Unspecified thermo model");
274  }
275 
276 
277  // Confirm that the phase only contains 2 species
278  if (m_kk != 2) {
279  throw CanteraError("MaskellSolidSolnPhase::initThermoXML",
280  "MaskellSolidSolution model requires exactly 2 species.");
281  }
282 
283  /*
284  * Call the base initThermo, which handles setting the initial
285  * state.
286  */
287  VPStandardStateTP::initThermoXML(phaseNode, id_);
288 }
289 
291 {
292  assert(m_kk == 2);
293  static const int cacheId = m_cache.getId();
294  CachedScalar cached = m_cache.getScalar(cacheId);
295  /*
296  * Update the thermodynamic functions of the reference state.
297  */
298  doublereal tnow = temperature();
299  if (!cached.validate(tnow)) {
301  DATA_PTR(m_s0_R));
302  for (size_t k = 0; k < m_kk; k++) {
303  m_g0_RT[k] = m_h0_RT[k] - m_s0_R[k];
304  }
305  }
306 }
307 
308 doublereal MaskellSolidSolnPhase::s() const
309 {
310  return 1 + std::exp(h_mixing / (GasConstant * temperature()));
311 }
312 
313 doublereal MaskellSolidSolnPhase::fm(const doublereal r) const
314 {
315  return (1 - std::sqrt(1 - 4*r*(1-r)/s())) / (2*r);
316 }
317 
318 doublereal MaskellSolidSolnPhase::p(const doublereal r) const
319 {
320  const doublereal sval = s();
321  return (1 - 2*r) / std::sqrt(sval*sval - 4 * sval * r + 4 * sval * r * r);
322 }
323 
324 } // end namespace Cantera
doublereal fpValue(const std::string &val)
Translate a string into one doublereal value.
vector_fp m_cp0_R
Vector containing the species reference constant pressure heat capacities at T = m_tlast.
virtual doublereal entropy_mole() const
Molar entropy of the solution.
void _updateThermo() const
Function to call through to m_spthermo->update and fill m_h0_RT, m_cp0_R, m_g0_RT, m_s0_R.
virtual doublereal density() const
Density (kg/m^3).
Definition: Phase.h:608
int getId()
Get a unique id for a cached value.
Definition: ValueCache.cpp:18
vector_fp m_h0_RT
Vector containing the species reference enthalpies at T = m_tlast.
virtual void setMolarDensity(const doublereal rho)
Overwritten setMolarDensity() function is necessary because the density is not an independent variabl...
const doublereal OneAtm
One atmosphere [Pa].
Definition: ct_defs.h:69
MaskellSolidSolnPhase & operator=(const MaskellSolidSolnPhase &)
Assignment operator.
std::string attrib(const std::string &attr) const
Function returns the value of an attribute.
Definition: xml.cpp:527
virtual doublereal pressure() const
Pressure.
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...
Class XML_Node is a tree-based representation of the contents of an XML file.
Definition: xml.h:100
int stateMFNumber() const
Return the State Mole Fraction Number.
Definition: Phase.h:823
std::string lowercase(const std::string &s)
Cast a copy of a string to lower case.
Definition: stringUtils.cpp:73
void getMoleFractions(doublereal *const x) const
Get the species mole fraction vector.
Definition: Phase.cpp:556
virtual void getStandardChemPotentials(doublereal *mu) const
Get the array of chemical potentials at unit activity for the species at their standard states at the...
doublereal h_mixing
Value of the enthalpy change on mixing due to protons changing from type B to type A configurations...
virtual void getPartialMolarVolumes(doublereal *vbar) const
returns an array of partial molar volumes of the species in the solution.
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
VPStandardStateTP & operator=(const VPStandardStateTP &b)
Assignment operator.
Base class for a phase with thermodynamic properties.
Definition: ThermoPhase.h:97
Header file for a solid solution model following Maskell, Shaw, and Tye.
virtual void getPartialMolarEnthalpies(doublereal *hbar) const
Returns an array of partial molar enthalpies for the species in the mixture.
doublereal mean_X(const doublereal *const Q) const
Evaluate the mole-fraction-weighted mean of an array Q.
Definition: Phase.cpp:687
virtual void initThermoXML(XML_Node &phaseNode, const std::string &id)
virtual void getActivityCoefficients(doublereal *ac) const
Get the array of species activity coefficients.
size_t speciesIndex(const std::string &name) const
Returns the index of a species named 'name' within the Phase object.
Definition: Phase.cpp:257
virtual ThermoPhase * duplMyselfAsThermoPhase() const
virtual void getChemPotentials(doublereal *mu) const
Get the species chemical potentials.
int product_species_index
Index of the species whose mole fraction defines the extent of reduction r.
virtual doublereal enthalpy_mole() const
Molar enthalpy of the solution.
CachedScalar getScalar(int id)
Get a reference to a CachedValue object representing a scalar (doublereal) with the given id...
Definition: ValueCache.h:162
virtual void calcDensity()
Calculate the density of the mixture using the partial molar volumes and mole fractions as input...
Classes providing support for XML data files.
ValueCache m_cache
Cached for saved calculations within each ThermoPhase.
Definition: Phase.h:833
Base class for exceptions thrown by Cantera classes.
Definition: ctexceptions.h:99
virtual void setDensity(const doublereal rho)
Overwritten setDensity() function is necessary because the density is not an independent variable...
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 getActivityConcentrations(doublereal *c) const
This method returns the array of generalized concentrations.
virtual void getPartialMolarEntropies(doublereal *sbar) const
Returns an array of partial molar entropies of the species in the solution.
vector_fp m_s0_R
Vector containing the species reference entropies at T = m_tlast.
virtual void getPureGibbs(doublereal *gpure) const
Get the Gibbs functions for the standard state of the species at the current T and P of the solution...
std::string value() const
Return the value of an XML node as a string.
Definition: xml.cpp:469
doublereal m_Pcurrent
m_Pcurrent = The current pressure Since the density isn't a function of pressure, but only of the mol...
doublereal moleFraction(size_t k) const
Return the mole fraction of a single species.
Definition: Phase.cpp:561
doublereal temperature() const
Temperature (K).
Definition: Phase.h:602
std::string id() const
Return the id attribute, if present.
Definition: xml.cpp:448
virtual void getPartialMolarCp(doublereal *cpbar) const
Returns an array of partial molar Heat Capacities at constant pressure of the species in the solution...
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
bool validate(double state1New)
Check whether the currently cached value is valid based on a single state variable.
Definition: ValueCache.h:41
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.
#define DATA_PTR(vec)
Creates a pointer to the start of the raw data for a vector.
Definition: ct_defs.h:36
CachedArray getArray(int id)
Get a reference to a CachedValue object representing an array (vector_fp) with the given id...
Definition: ValueCache.h:168
size_t m_kk
Number of species in the phase.
Definition: Phase.h:843
Class MaskellSolidSolnPhase represents a condensed phase non-ideal solution with 2 species following ...
virtual void update(doublereal T, doublereal *cp_R, doublereal *h_RT, doublereal *s_R) const =0
Compute the reference-state properties for all species.
virtual void getChemPotentials_RT(doublereal *mu) const
Get the array of non-dimensional species solution chemical potentials at the current T and P...
T value
The value of the cached property.
Definition: ValueCache.h:115
virtual void setPressure(doublereal p)
Set the pressure at constant temperature.
SpeciesThermo * m_spthermo
Pointer to the calculation manager for species reference-state thermodynamic properties.
Definition: ThermoPhase.h:1607
vector_fp m_g0_RT
Vector containing the species reference Gibbs functions at T = m_tlast.
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