Cantera  2.4.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(-1),
28  reactant_species_index(-1)
29 {
30 }
31 
33 {
35  for (size_t sp = 0; sp < m_kk; ++sp) {
36  c[sp] *= moleFraction(sp);
37  }
38 }
39 
40 // Molar Thermodynamic Properties of the Solution
41 
43 {
44  _updateThermo();
45  const doublereal h0 = RT() * mean_X(m_h0_RT);
46  const doublereal r = moleFraction(product_species_index);
47  const doublereal fmval = fm(r);
48  return h0 + r * fmval * h_mixing;
49 }
50 
51 doublereal xlogx(doublereal x)
52 {
53  return x * std::log(x);
54 }
55 
57 {
58  _updateThermo();
59  const doublereal s0 = GasConstant * mean_X(m_s0_R);
60  const doublereal r = moleFraction(product_species_index);
61  const doublereal fmval = fm(r);
62  const doublereal rfm = r * fmval;
63  return s0 + GasConstant * (xlogx(1-rfm) - xlogx(rfm) - xlogx(1-r-rfm) - xlogx((1-fmval)*r) - xlogx(1-r) - xlogx(r));
64 }
65 
66 // Mechanical Equation of State
67 
68 void MaskellSolidSolnPhase::setDensity(const doublereal rho)
69 {
70  // Unless the input density is exactly equal to the density calculated and
71  // stored in the State object, we throw an exception. This is because the
72  // density is NOT an independent variable.
73  double dens = density();
74  if (rho != dens) {
75  throw CanteraError("MaskellSolidSolnPhase::setDensity",
76  "Density is not an independent variable");
77  }
78 }
79 
81 {
82  const vector_fp& vbar = getStandardVolumes();
83 
84  vector_fp moleFracs(m_kk);
85  Phase::getMoleFractions(&moleFracs[0]);
86  doublereal vtotal = 0.0;
87  for (size_t i = 0; i < m_kk; i++) {
88  vtotal += vbar[i] * moleFracs[i];
89  }
91 }
92 
94 {
95  m_Pcurrent = p;
96 }
97 
99 {
100  throw CanteraError("MaskellSolidSolnPhase::setMolarDensity",
101  "Density is not an independent variable");
102 }
103 
104 // Chemical Potentials and Activities
105 
107 {
108  _updateThermo();
109  static const int cacheId = m_cache.getId();
110  CachedArray cached = m_cache.getArray(cacheId);
111  if (!cached.validate(temperature(), pressure(), stateMFNumber())) {
112  cached.value.resize(2);
113 
114  const doublereal r = moleFraction(product_species_index);
115  const doublereal pval = p(r);
116  const doublereal rfm = r * fm(r);
117  const doublereal A = (std::pow(1 - rfm, pval) * std::pow(rfm, pval) * std::pow(r - rfm, 1 - pval)) /
118  (std::pow(1 - r - rfm, 1 + pval) * (1 - r));
119  const doublereal B = pval * h_mixing / RT();
120  cached.value[product_species_index] = A * std::exp(B);
121  cached.value[reactant_species_index] = 1 / (A * r * (1-r) ) * std::exp(-B);
122  }
123  std::copy(cached.value.begin(), cached.value.end(), ac);
124 }
125 
127 {
128  _updateThermo();
129  const doublereal r = moleFraction(product_species_index);
130  const doublereal pval = p(r);
131  const doublereal rfm = r * fm(r);
132  const doublereal DgbarDr = pval * h_mixing +
133  RT() *
134  std::log( (std::pow(1 - rfm, pval) * std::pow(rfm, pval) * std::pow(r - rfm, 1 - pval) * r) /
135  (std::pow(1 - r - rfm, 1 + pval) * (1 - r)) );
137  mu[reactant_species_index] = RT() * m_g0_RT[reactant_species_index] - DgbarDr;
138 }
139 
141 {
142  getChemPotentials(mu);
143  for (size_t sp=0; sp < m_kk; ++sp) {
144  mu[sp] *= 1.0 / RT();
145  }
146 }
147 
148 // Partial Molar Properties
149 
151 {
152  throw CanteraError("MaskellSolidSolnPhase::getPartialMolarEnthalpies()", "Not yet implemented.");
153 }
154 
156 {
157  throw CanteraError("MaskellSolidSolnPhase::getPartialMolarEntropies()", "Not yet implemented.");
158 }
159 
160 void MaskellSolidSolnPhase::getPartialMolarCp(doublereal* cpbar) const
161 {
162  throw CanteraError("MaskellSolidSolnPhase::getPartialMolarCp()", "Not yet implemented.");
163 }
164 
166 {
167  getStandardVolumes(vbar);
168 }
169 
170 void MaskellSolidSolnPhase::getPureGibbs(doublereal* gpure) const
171 {
172  _updateThermo();
173  for (size_t sp=0; sp < m_kk; ++sp) {
174  gpure[sp] = RT() * m_g0_RT[sp];
175  }
176 }
177 
179 {
180  // What is the difference between this and getPureGibbs? IdealSolidSolnPhase
181  // gives the same for both
182  getPureGibbs(mu);
183 }
184 
185 // Utility Functions
186 
187 void MaskellSolidSolnPhase::initThermoXML(XML_Node& phaseNode, const std::string& id_)
188 {
189  if (id_.size() > 0 && phaseNode.id() != id_) {
190  throw CanteraError("MaskellSolidSolnPhase::initThermoXML",
191  "phasenode and Id are incompatible");
192  }
193 
194  // Check on the thermo field. Must have:
195  // <thermo model="MaskellSolidSolution" />
196  if (phaseNode.hasChild("thermo")) {
197  XML_Node& thNode = phaseNode.child("thermo");
198  if (!caseInsensitiveEquals(thNode["model"], "maskellsolidsolnphase")) {
199  throw CanteraError("MaskellSolidSolnPhase::initThermoXML",
200  "Unknown thermo model: " + thNode["model"]);
201  }
202 
203  // Parse the enthalpy of mixing constant
204  if (thNode.hasChild("h_mix")) {
205  set_h_mix(fpValue(thNode.child("h_mix").value()));
206  } else {
207  throw CanteraError("MaskellSolidSolnPhase::initThermoXML",
208  "Mixing enthalpy parameter not specified.");
209  }
210 
211  if (thNode.hasChild("product_species")) {
212  setProductSpecies(thNode.child("product_species").value());
213  } else {
214  setProductSpecies(speciesName(0)); // default
215  }
216  } else {
217  throw CanteraError("MaskellSolidSolnPhase::initThermoXML",
218  "Unspecified thermo model");
219  }
220 
221  // Confirm that the phase only contains 2 species
222  if (m_kk != 2) {
223  throw CanteraError("MaskellSolidSolnPhase::initThermoXML",
224  "MaskellSolidSolution model requires exactly 2 species.");
225  }
226 
227  // Call the base initThermo, which handles setting the initial state.
228  VPStandardStateTP::initThermoXML(phaseNode, id_);
229 }
230 
231 void MaskellSolidSolnPhase::setProductSpecies(const std::string& name)
232 {
233  product_species_index = static_cast<int>(speciesIndex(name));
234  if (product_species_index == -1) {
235  throw CanteraError("MaskellSolidSolnPhase::setProductSpecies",
236  "Species '{}' not found", name);
237  }
238  reactant_species_index = (product_species_index == 0) ? 1 : 0;
239 }
240 
242 {
243  assert(m_kk == 2);
244  static const int cacheId = m_cache.getId();
245  CachedScalar cached = m_cache.getScalar(cacheId);
246 
247  // Update the thermodynamic functions of the reference state.
248  doublereal tnow = temperature();
249  if (!cached.validate(tnow)) {
250  m_spthermo.update(tnow, m_cp0_R.data(), m_h0_RT.data(), m_s0_R.data());
251  for (size_t k = 0; k < m_kk; k++) {
252  m_g0_RT[k] = m_h0_RT[k] - m_s0_R[k];
253  }
254  }
255 }
256 
257 doublereal MaskellSolidSolnPhase::s() const
258 {
259  return 1 + std::exp(h_mixing / RT());
260 }
261 
262 doublereal MaskellSolidSolnPhase::fm(const doublereal r) const
263 {
264  return (1 - std::sqrt(1 - 4*r*(1-r)/s())) / (2*r);
265 }
266 
267 doublereal MaskellSolidSolnPhase::p(const doublereal r) const
268 {
269  const doublereal sval = s();
270  return (1 - 2*r) / std::sqrt(sval*sval - 4 * sval * r + 4 * sval * r * r);
271 }
272 
273 } // 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.
MultiSpeciesThermo m_spthermo
Pointer to the calculation manager for species reference-state thermodynamic properties.
Definition: ThermoPhase.h:1607
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
void setProductSpecies(const std::string &name)
Set the product Species. Must be called after species have been added.
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:175
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:471
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:614
doublereal RT() const
Return the Gas Constant multiplied by the current temperature.
Definition: ThermoPhase.h:748
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
std::string speciesName(size_t k) const
Name of the species with index k.
Definition: Phase.cpp:191
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:765
bool caseInsensitiveEquals(const std::string &input, const std::string &test)
Case insensitive equality predicate.
Base class for exceptions thrown by Cantera classes.
Definition: ctexceptions.h:65
int stateMFNumber() const
Return the State Mole Fraction Number.
Definition: Phase.h:751
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:466
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
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.
virtual void initThermoXML(XML_Node &phaseNode, const std::string &id)
Import and initialize a ThermoPhase object using an XML tree.
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.
std::string name() const
Return the name of the phase.
Definition: Phase.cpp:78
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:788
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: AnyMap.cpp:8
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