Cantera  2.3.0
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 // This file is part of Cantera. See License.txt in the top-level directory or
9 // at http://www.cantera.org/license.txt for license and copyright information.
10 
13 #include "cantera/base/xml.h"
14 
15 #include <cassert>
16 
17 namespace Cantera
18 {
19 
20 MaskellSolidSolnPhase::MaskellSolidSolnPhase() :
21  m_Pcurrent(OneAtm),
22  m_h0_RT(2),
23  m_cp0_R(2),
24  m_g0_RT(2),
25  m_s0_R(2),
26  h_mixing(0.0),
27  product_species_index(0),
28  reactant_species_index(1)
29 {
30 }
31 
32 MaskellSolidSolnPhase::MaskellSolidSolnPhase(const MaskellSolidSolnPhase& b) :
33  m_Pcurrent(OneAtm),
34  m_h0_RT(2),
35  m_cp0_R(2),
36  m_g0_RT(2),
37  m_s0_R(2),
38  h_mixing(0.0),
39  product_species_index(0),
40  reactant_species_index(1)
41 {
42  *this = b;
43 }
44 
45 MaskellSolidSolnPhase&
46 MaskellSolidSolnPhase::operator=(const MaskellSolidSolnPhase& b)
47 {
48  if (this != &b) {
49  VPStandardStateTP::operator=(b);
50  }
51  return *this;
52 }
53 
55 {
56  return new MaskellSolidSolnPhase(*this);
57 }
58 
60 {
62  for (size_t sp = 0; sp < m_kk; ++sp) {
63  c[sp] *= moleFraction(sp);
64  }
65 }
66 
67 // Molar Thermodynamic Properties of the Solution
68 
70 {
71  _updateThermo();
72  const doublereal h0 = RT() * mean_X(m_h0_RT);
73  const doublereal r = moleFraction(product_species_index);
74  const doublereal fmval = fm(r);
75  return h0 + r * fmval * h_mixing;
76 }
77 
78 doublereal xlogx(doublereal x)
79 {
80  return x * std::log(x);
81 }
82 
84 {
85  _updateThermo();
86  const doublereal s0 = GasConstant * mean_X(m_s0_R);
87  const doublereal r = moleFraction(product_species_index);
88  const doublereal fmval = fm(r);
89  const doublereal rfm = r * fmval;
90  return s0 + GasConstant * (xlogx(1-rfm) - xlogx(rfm) - xlogx(1-r-rfm) - xlogx((1-fmval)*r) - xlogx(1-r) - xlogx(r));
91 }
92 
93 // Mechanical Equation of State
94 
95 void MaskellSolidSolnPhase::setDensity(const doublereal rho)
96 {
97  // Unless the input density is exactly equal to the density calculated and
98  // stored in the State object, we throw an exception. This is because the
99  // density is NOT an independent variable.
100  double dens = density();
101  if (rho != dens) {
102  throw CanteraError("MaskellSolidSolnPhase::setDensity",
103  "Density is not an independent variable");
104  }
105 }
106 
108 {
109  const vector_fp& vbar = getStandardVolumes();
110 
111  vector_fp moleFracs(m_kk);
112  Phase::getMoleFractions(&moleFracs[0]);
113  doublereal vtotal = 0.0;
114  for (size_t i = 0; i < m_kk; i++) {
115  vtotal += vbar[i] * moleFracs[i];
116  }
118 }
119 
121 {
122  m_Pcurrent = p;
123 }
124 
126 {
127  throw CanteraError("MaskellSolidSolnPhase::setMolarDensity",
128  "Density is not an independent variable");
129 }
130 
131 // Chemical Potentials and Activities
132 
134 {
135  _updateThermo();
136  static const int cacheId = m_cache.getId();
137  CachedArray cached = m_cache.getArray(cacheId);
138  if (!cached.validate(temperature(), pressure(), stateMFNumber())) {
139  cached.value.resize(2);
140 
141  const doublereal r = moleFraction(product_species_index);
142  const doublereal pval = p(r);
143  const doublereal rfm = r * fm(r);
144  const doublereal A = (std::pow(1 - rfm, pval) * std::pow(rfm, pval) * std::pow(r - rfm, 1 - pval)) /
145  (std::pow(1 - r - rfm, 1 + pval) * (1 - r));
146  const doublereal B = pval * h_mixing / RT();
147  cached.value[product_species_index] = A * std::exp(B);
148  cached.value[reactant_species_index] = 1 / (A * r * (1-r) ) * std::exp(-B);
149  }
150  std::copy(cached.value.begin(), cached.value.end(), ac);
151 }
152 
154 {
155  _updateThermo();
156  const doublereal r = moleFraction(product_species_index);
157  const doublereal pval = p(r);
158  const doublereal rfm = r * fm(r);
159  const doublereal DgbarDr = pval * h_mixing +
160  RT() *
161  std::log( (std::pow(1 - rfm, pval) * std::pow(rfm, pval) * std::pow(r - rfm, 1 - pval) * r) /
162  (std::pow(1 - r - rfm, 1 + pval) * (1 - r)) );
164  mu[reactant_species_index] = RT() * m_g0_RT[reactant_species_index] - DgbarDr;
165 }
166 
168 {
169  getChemPotentials(mu);
170  for (size_t sp=0; sp < m_kk; ++sp) {
171  mu[sp] *= 1.0 / RT();
172  }
173 }
174 
175 // Partial Molar Properties
176 
178 {
179  throw CanteraError("MaskellSolidSolnPhase::getPartialMolarEnthalpies()", "Not yet implemented.");
180 }
181 
183 {
184  throw CanteraError("MaskellSolidSolnPhase::getPartialMolarEntropies()", "Not yet implemented.");
185 }
186 
187 void MaskellSolidSolnPhase::getPartialMolarCp(doublereal* cpbar) const
188 {
189  throw CanteraError("MaskellSolidSolnPhase::getPartialMolarCp()", "Not yet implemented.");
190 }
191 
193 {
194  getStandardVolumes(vbar);
195 }
196 
197 void MaskellSolidSolnPhase::getPureGibbs(doublereal* gpure) const
198 {
199  _updateThermo();
200  for (size_t sp=0; sp < m_kk; ++sp) {
201  gpure[sp] = RT() * m_g0_RT[sp];
202  }
203 }
204 
206 {
207  // What is the difference between this and getPureGibbs? IdealSolidSolnPhase
208  // gives the same for both
209  getPureGibbs(mu);
210 }
211 
212 // Utility Functions
213 
214 void MaskellSolidSolnPhase::initThermoXML(XML_Node& phaseNode, const std::string& id_)
215 {
216  if (id_.size() > 0 && phaseNode.id() != id_) {
217  throw CanteraError("MaskellSolidSolnPhase::initThermoXML",
218  "phasenode and Id are incompatible");
219  }
220 
221  // Check on the thermo field. Must have:
222  // <thermo model="MaskellSolidSolution" />
223  if (phaseNode.hasChild("thermo")) {
224  XML_Node& thNode = phaseNode.child("thermo");
225  if (!ba::iequals(thNode["model"], "maskellsolidsolnphase")) {
226  throw CanteraError("MaskellSolidSolnPhase::initThermoXML",
227  "Unknown thermo model: " + thNode["model"]);
228  }
229 
230  // Parse the enthalpy of mixing constant
231  if (thNode.hasChild("h_mix")) {
232  set_h_mix(fpValue(thNode.child("h_mix").value()));
233  } else {
234  throw CanteraError("MaskellSolidSolnPhase::initThermoXML",
235  "Mixing enthalpy parameter not specified.");
236  }
237 
238  if (thNode.hasChild("product_species")) {
239  std::string product_species_name = thNode.child("product_species").value();
240  product_species_index = static_cast<int>(speciesIndex(product_species_name));
241  if (product_species_index == -1) {
242  throw CanteraError("MaskellSolidSolnPhase::initThermoXML",
243  "Species " + product_species_name + " not found.");
244  }
245  if (product_species_index == 0) {
246  reactant_species_index = 1;
247  } else {
248  reactant_species_index = 0;
249  }
250  }
251  } else {
252  throw CanteraError("MaskellSolidSolnPhase::initThermoXML",
253  "Unspecified thermo model");
254  }
255 
256  // Confirm that the phase only contains 2 species
257  if (m_kk != 2) {
258  throw CanteraError("MaskellSolidSolnPhase::initThermoXML",
259  "MaskellSolidSolution model requires exactly 2 species.");
260  }
261 
262  // Call the base initThermo, which handles setting the initial state.
263  VPStandardStateTP::initThermoXML(phaseNode, id_);
264 }
265 
267 {
268  assert(m_kk == 2);
269  static const int cacheId = m_cache.getId();
270  CachedScalar cached = m_cache.getScalar(cacheId);
271 
272  // Update the thermodynamic functions of the reference state.
273  doublereal tnow = temperature();
274  if (!cached.validate(tnow)) {
275  m_spthermo->update(tnow, m_cp0_R.data(), m_h0_RT.data(), m_s0_R.data());
276  for (size_t k = 0; k < m_kk; k++) {
277  m_g0_RT[k] = m_h0_RT[k] - m_s0_R[k];
278  }
279  }
280 }
281 
282 doublereal MaskellSolidSolnPhase::s() const
283 {
284  return 1 + std::exp(h_mixing / RT());
285 }
286 
287 doublereal MaskellSolidSolnPhase::fm(const doublereal r) const
288 {
289  return (1 - std::sqrt(1 - 4*r*(1-r)/s())) / (2*r);
290 }
291 
292 doublereal MaskellSolidSolnPhase::p(const doublereal r) const
293 {
294  const doublereal sval = s();
295  return (1 - 2*r) / std::sqrt(sval*sval - 4 * sval * r + 4 * sval * r * r);
296 }
297 
298 } // end namespace Cantera
virtual void getActivityCoefficients(doublereal *ac) const
Get the array of non-dimensional molar-based activity coefficients at the current solution temperatur...
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.
int getId()
Get a unique id for a cached value.
Definition: ValueCache.cpp:21
virtual void getChemPotentials(doublereal *mu) const
Get the species chemical potentials. Units: J/kmol.
vector_fp m_h0_RT
Vector containing the species reference enthalpies at T = m_tlast.
virtual void setMolarDensity(const doublereal rho)
Overridden setMolarDensity() function is necessary because the density is not an independent variable...
const doublereal OneAtm
One atmosphere [Pa].
Definition: ct_defs.h:69
doublereal temperature() const
Temperature (K).
Definition: Phase.h:601
size_t speciesIndex(const std::string &name) const
Returns the index of a species named &#39;name&#39; within the Phase object.
Definition: Phase.cpp:251
virtual void update(doublereal T, doublereal *cp_R, doublereal *h_RT, doublereal *s_R) const
Compute the reference-state properties for all species.
doublereal moleFraction(size_t k) const
Return the mole fraction of a single species.
Definition: Phase.cpp:547
Class XML_Node is a tree-based representation of the contents of an XML file.
Definition: xml.h:97
virtual doublereal density() const
Density (kg/m^3).
Definition: Phase.h:607
virtual doublereal entropy_mole() const
Molar entropy. Units: J/kmol/K.
virtual void getPartialMolarEntropies(doublereal *sbar) const
Returns an array of partial molar entropies of the species in the solution.
doublereal h_mixing
Value of the enthalpy change on mixing due to protons changing from type B to type A configurations...
doublereal mean_X(const doublereal *const Q) const
Evaluate the mole-fraction-weighted mean of an array Q.
Definition: Phase.cpp:690
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
Header file for a solid solution model following Maskell, Shaw, and Tye.
virtual void initThermoXML(XML_Node &phaseNode, const std::string &id)
Import and initialize a ThermoPhase object using an XML tree.
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...
int product_species_index
Index of the species whose mole fraction defines the extent of reduction r.
virtual void getPartialMolarEnthalpies(doublereal *hbar) const
Returns an array of partial molar enthalpies for the species in the mixture.
CachedScalar getScalar(int id)
Get a reference to a CachedValue object representing a scalar (doublereal) with the given id...
Definition: ValueCache.h:165
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.
virtual void getStandardChemPotentials(doublereal *mu) const
Get the array of chemical potentials at unit activity for the species at their standard states at the...
ValueCache m_cache
Cached for saved calculations within each ThermoPhase.
Definition: Phase.h:761
Base class for exceptions thrown by Cantera classes.
Definition: ctexceptions.h:65
int stateMFNumber() const
Return the State Mole Fraction Number.
Definition: Phase.h:747
std::string value() const
Return the value of an XML node as a string.
Definition: xml.cpp:449
virtual void setDensity(const doublereal rho)
Overridden setDensity() function is necessary because the density is not an independent variable...
virtual void getPartialMolarCp(doublereal *cpbar) const
Return an array of partial molar heat capacities for the species in the mixture.
void getMoleFractions(doublereal *const x) const
Get the species mole fraction vector.
Definition: Phase.cpp:542
virtual doublereal pressure() const
Pressure.
bool hasChild(const std::string &ch) const
Tests whether the current node has a child node with a particular name.
Definition: xml.cpp:536
MultiSpeciesThermo * m_spthermo
Pointer to the calculation manager for species reference-state thermodynamic properties.
Definition: ThermoPhase.h:1693
vector_fp m_s0_R
Vector containing the species reference entropies at T = m_tlast.
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 getChemPotentials_RT(doublereal *mu) const
Get the array of non-dimensional species chemical potentials.
doublereal m_Pcurrent
m_Pcurrent = The current pressure.
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
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.
bool validate(double state1New)
Check whether the currently cached value is valid based on a single state variable.
Definition: ValueCache.h:44
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 doublereal enthalpy_mole() const
Molar enthalpy. Units: J/kmol.
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.
CachedArray getArray(int id)
Get a reference to a CachedValue object representing an array (vector_fp) with the given id...
Definition: ValueCache.h:171
virtual void getActivityConcentrations(doublereal *c) const
This method returns an array of generalized concentrations.
size_t m_kk
Number of species in the phase.
Definition: Phase.h:784
Class MaskellSolidSolnPhase represents a condensed phase non-ideal solution with 2 species following ...
virtual void getPartialMolarVolumes(doublereal *vbar) const
Return an array of partial molar volumes for the species in the mixture.
T value
The value of the cached property.
Definition: ValueCache.h:118
virtual void setPressure(doublereal p)
Set the pressure at constant temperature.
Namespace for the Cantera kernel.
Definition: application.cpp:29
virtual ThermoPhase * duplMyselfAsThermoPhase() const
Duplication routine for objects which inherit from ThermoPhase.
vector_fp m_g0_RT
Vector containing the species reference Gibbs functions at T = m_tlast.
virtual void getStandardVolumes(doublereal *vol) const
Get the molar volumes of the species standard states at the current T and P of the solution...
virtual void setDensity(const doublereal density_)
Set the internally stored density (kg/m^3) of the phase.
Definition: Phase.h:622