Cantera  4.0.0a1
Loading...
Searching...
No Matches
BinarySolutionTabulatedThermo.h
Go to the documentation of this file.
1/**
2 * @file BinarySolutionTabulatedThermo.h
3 * Header file for an binary solution model with tabulated standard state
4 * thermodynamic data (see @ref thermoprops and class
5 * @link Cantera::BinarySolutionTabulatedThermo BinarySolutionTabulatedThermo@endlink).
6 */
7
8// This file is part of Cantera. See License.txt in the top-level directory or
9// at https://cantera.org/license.txt for license and copyright information.
10
11#ifndef CT_BINARYSOLUTIONTABULATEDTHERMO_H
12#define CT_BINARYSOLUTIONTABULATEDTHERMO_H
13
14#include "IdealSolidSolnPhase.h"
16
17namespace Cantera
18{
19
20//! Overloads the virtual methods of class IdealSolidSolnPhase to implement
21//! tabulated standard state thermodynamics for one species in a binary
22//! solution.
23/**
24 *
25 * BinarySolutionTabulatedThermo is derived from IdealSolidSolnPhase, but
26 * overwrites the standard state thermodynamic data using tabulated data,
27 * as provided by the user in the input file. This ends up being useful for
28 * certain non-ideal / non-dilute species where the interaction potentials, as
29 * a function of composition / solute mole fraction, are not easily represented
30 * by any closed-form equation of state.
31 *
32 * A good example of this type of phase is intercalation-based lithium storage
33 * materials used for lithium-ion battery electrodes. Measuring the open
34 * circuit voltage @f$ E_eq @f$, relative to a reference electrode, as a
35 * function of lithium mole fraction and as a function of temperature, provides
36 * a means to evaluate the gibbs free energy of reaction:
37 *
38 * @f[
39 * \Delta g_{\rm rxn} = -\frac{E_eq}{nF}
40 * @f]
41 *
42 * where @f$ n @f$ is the charge number transferred to the phase, via the
43 * reaction, and @f$ F @f$ is Faraday's constant. The gibbs energy of
44 * reaction, in turn, can be separated into enthalpy and entropy of reaction
45 * components:
46 *
47 * @f[
48 * \Delta g_{\rm rxn} = \Delta h_{\rm rxn} - T\Delta s_{\rm rxn}
49 * @f]
50 * @f[
51 * \frac{d\Delta g_{\rm rxn}}{dT} = - \Delta s_{\rm rxn}
52 * @f]
53 *
54 * For the tabulated binary phase, the user identifies a 'tabulated' species,
55 * while the other is considered the 'reference' species. The reference
56 * species (typically a vacancy) is assigned standard state thermo variables
57 * @f$ h^{\rm o} = 0 @f$ and @f$ s^{\rm o} = 0 @f$, and all excess
58 * thermodynamics are absorbed into the standard state of the tabulated
59 * species. Standard state thermo variables for species in any other phases
60 * are calculated according to the rules specified in that phase definition.
61 * The standard state thermo variables are calculated according to the
62 * reaction energy terms:
63 *
64 * @f[
65 * \Delta h_{\rm rxn} = \sum_k \nu_k h^{\rm o}_k
66 * @f]
67 * @f[
68 * \Delta s_{\rm rxn} = \sum_k \nu_k s^{\rm o}_k + RT\ln\left(\prod_k\left(\frac{c_k}{c^{\rm o}_k} \right)^{\nu_k}\right)
69 * @f]
70 *
71 * The present model is intended for modeling non-ideal, tabulated
72 * thermodynamics for binary solutions where the tabulated species is
73 * incorporated via an electrochemical reaction, such that the open circuit
74 * voltage can be measured, relative to a counter electrode species with
75 * standard state thermo properties @f$ h^{\rm o} = 0 @f$.
76 * It is possible that this can be generalized such that this assumption about
77 * the counter-electrode is not required. At present, this is left as future
78 * work.
79 *
80 * The user therefore provides a table of three equally-sized vectors of
81 * tabulated data:
82 *
83 * - @f$ x_{\rm tab} @f$ = array of mole fractions for the tabulated species
84 * at which measurements were conducted and thermo
85 * data are provided.
86 * - @f$ h_{\rm tab} @f$ = @f$ F\left(-E_{\rm eq}\left(x,T^{\rm o} \right) + T^{\rm o} \frac{dE_{\rm eq}\left(x,T^{\rm o} \right)}{dT}\right) @f$
87 * - @f$ s_{\rm tab} @f$ = @f$ F \left(\frac{dE_{\rm eq}\left(x,T^{\rm o} \right)}{dT} + s_{\rm counter}^{\rm o} \right) @f$
88 *
89 * where @f$ E_{\rm eq}\left(x,T^{\rm o} \right) @f$ and @f$ \frac{dE_{\rm eq}\left(x,T^{\rm o} \right)}{dT} @f$
90 * are the experimentally-measured open circuit voltage and derivative in
91 * open circuit voltage with respect to temperature, respectively, both
92 * measured as a mole fraction of @f$ x @f$ for the tabulated species and at a
93 * temperature of @f$ T^{\rm o} @f$. The arrays @f$ h_{\rm tab} @f$ and
94 * @f$ s_{\rm tab} @f$ must be the same length as the @f$ x_{\rm tab} @f$ array.
95 *
96 * Note that @f$ s_{\rm tab} @f$ is the *non-configurational* (excess) entropy
97 * derived from electrochemical measurements. It is a experimentally determined
98 * function of composition and does not include any logarithmic mixing terms.
99 *
100 * From these tabulated inputs, the standard state thermodynamic properties
101 * for the tabulated species (subscript @f$ k @f$, tab) are calculated as:
102 *
103 * @f[
104 * h^{\rm o}_{k,\,{\rm tab}} = h_{\rm tab}
105 * @f]
106 * @f[
107 * s^{\rm o}_{k,\,{\rm tab}} = s_{\rm tab} + R\ln\frac{x_{k,\,{\rm tab}}}{1-x_{k,\,{\rm tab}}} + \frac{R}{F} \ln\left(\frac{c^{\rm o}_{k,\,{\rm ref}}}{c^{\rm o}_{k,\,{\rm tab}}}\right)
108 * @f]
109 *
110 * The mole fraction-dependent term in @f$ s^{\rm o} @f$ encodes the vacancy-reference
111 * activity convention: it ensures that the electrode reaction driving force
112 * @f$ \Delta g_{\rm rxn} = \mu_{\rm tab} - \mu_{\rm ref} = h_{\rm tab} - T s_{\rm tab} @f$
113 * is independent of the vacancy (reference species) mole fraction. Because
114 * this term makes @f$ s^{\rm o}_{k,\,{\rm tab}} @f$ composition-dependent, the
115 * standard-state entropy of the tabulated species diverges at both composition
116 * limits (@f$ x_{\rm tab} \to 0 @f$ and @f$ x_{\rm tab} \to 1 @f$), and the
117 * mixture entropy returned by entropy_mole() diverges as @f$ x_{\rm tab} \to 1
118 * @f$ (equivalently, @f$ x_{\rm ref} \to 0 @f$). These behaviors are
119 * expected consequences of the activity convention and do not affect the
120 * accuracy of electrode reaction thermodynamics, which is the primary
121 * intended use of this class.
122 *
123 * The correction term @f$ (R/F)\ln(c^{\rm o}_{k,\,{\rm ref}} / c^{\rm o}_{k,\,{\rm tab}}) @f$
124 * accounts for differing standard concentration choices between the tabulated phase
125 * and the counter electrode phase.
126 *
127 * Now, whenever the composition has changed, the lookup/interpolation of the
128 * tabulated thermo data is performed to update the standard state
129 * thermodynamic data for the tabulated species.
130 *
131 * Furthermore, there is an optional feature to include non-ideal effects regarding
132 * partial molar volumes of the species, @f$ \bar V_k @f$. Being derived from
133 * IdealSolidSolnPhase, the default assumption in BinarySolutionTabulatedThermo
134 * is that the species comprising the binary solution have constant partial molar
135 * volumes equal to their pure species molar volumes. However, this assumption only
136 * holds true if there is no or only weak interactions between the two species in the
137 * binary mixture. In non-ideal solid materials, for example intercalation-based
138 * lithium storage materials, the partial molar volumes of the species typically show a
139 * strong non-linear dependency on the composition of the mixture. These dependencies
140 * can most often only be determined experimentally, for example via X-ray diffraction
141 * (XRD) measurements of the unit cell volume. Therefore, the user can provide an optional fourth vector of
142 * tabulated molar volume data with the same size as the other tabulated data:
143 *
144 * - @f$ V_{\mathrm{m,tab}} @f$ = array of the molar volume of the binary solution phase at
145 * the tabulated mole fractions.
146 *
147 * The partial molar volumes @f$ \bar V_1 @f$ of the tabulated species and
148 * @f$ \bar V_2 @f$ of the 'reference' species, respectively, can then be derived from
149 * the provided molar volume:
150 *
151 * @f[
152 * \bar V_1 = V_{\mathrm{m,tab}} + \left(1-x_{\mathrm {tab}}\right) \cdot
153 * \frac{\mathrm{d}V_{\mathrm{m,tab}}}{\mathrm{d}x_{\mathrm {tab}}} \\
154 * \bar V_2 = V_{\mathrm{m,tab}} - x_{\mathrm {tab}} \cdot
155 * \frac{\mathrm{d}V_{\mathrm{m,tab}}}{\mathrm{d}x_{\mathrm {tab}}}
156 * @f]
157 *
158 * The derivation is implemented using forward differences at the boundaries of the
159 * input vector and a central differencing scheme at interior points. As the
160 * derivative is determined numerically, the input data should be relatively smooth
161 * (recommended is one data point for every mole fraction per cent). The calculated
162 * partial molar volumes are accessible to the user via getPartialMolarVolumes().
163 *
164 * The calculation of the mass density incorporates the non-ideal behavior by using
165 * the provided molar volume in the equation:
166 *
167 * @f[
168 * \rho = \frac{\sum_k{x_k W_k}}{V_\mathrm{m}}
169 * @f]
170 *
171 * where @f$ x_k @f$ are the mole fractions, @f$ W_k @f$ are the molecular weights, and
172 * @f$ V_\mathrm{m} @f$ is the molar volume interpolated from @f$ V_{\mathrm{m,tab}} @f$.
173 *
174 * If the optional fourth input vector is not specified, the molar volume is calculated
175 * by using the pure species molar volumes, as in IdealSolidSolnPhase. Regardless if the
176 * molarVolume key is provided or not, the equation-of-state field in the pure species
177 * entries has to be defined.
178 *
179 * @ingroup thermoprops
180 */
182{
183public:
184 //! Construct and initialize an BinarySolutionTabulatedThermo ThermoPhase object
185 //! directly from an input file
186 /*!
187 * This constructor will also fully initialize the object.
188 *
189 * @param infile File name for the input file containing information
190 * for this phase. If not specified, an empty phase will be created.
191 * @param id The name of this phase. This is used to look up
192 * the phase in the input file.
193 */
194 explicit BinarySolutionTabulatedThermo(const string& infile="", const string& id="");
195
196 string type() const override {
197 return "binary-solution-tabulated";
198 }
199
200 bool addSpecies(shared_ptr<Species> spec) override;
201 void initThermo() override;
202 bool ready() const override;
203 void getParameters(AnyMap& phaseNode) const override;
204
205 /**
206 * returns an array of partial molar volumes of the species
207 * in the solution. Units: m^3 kmol-1.
208 *
209 * The partial molar volumes are derived as shown in the equations in the detailed
210 * description section.
211 *
212 * @param vbar Output vector of partial molar volumes. Length: m_kk.
213 */
214 void getPartialMolarVolumes(span<double> vbar) const override;
215
216 /**
217 * Overloads the calcDensity() method of IdealSolidSoln to also consider non-ideal
218 * behavior.
219 *
220 * The formula for this is
221 *
222 * @f[
223 * \rho = \frac{\sum_k{X_k W_k}}{V_\mathrm{m}}
224 * @f]
225 *
226 * where @f$ X_k @f$ are the mole fractions, @f$ W_k @f$ are the molecular weights, and
227 * @f$ V_\mathrm{m} @f$ is the molar volume interpolated from @f$ V_{\mathrm{m,tab}} @f$.
228 */
229 void calcDensity() override;
230
231protected:
232 //! If the compositions have changed, update the tabulated thermo lookup
233 void compositionChanged() override;
234
235 //! Species thermodynamics linear interpolation function
236 /*!
237 * Tabulated values are only interpolated within the limits of the provided mole
238 * fraction. If these limits are exceeded, the values are capped at the lower or
239 * the upper limit.
240 *
241 * @param x Current mole fraction at which to interpolate.
242 * @param inputData Input vector of the data to be interpolated.
243 * @returns Linear interpolation of tabulated data at the current
244 * mole fraction x.
245 */
246 double interpolate(const double x, span<const double> inputData) const;
247
248 //! Numerical derivative of the molar volume table
249 /*!
250 * Tabulated values are only interpolated within the limits of the provided mole
251 * fraction. If these limits are exceeded, the values are capped at the lower or
252 * the upper limit.
253 *
254 * @param inputData Input vector of tabulated data to be derived.
255 * @param derivedData Output vector of tabulated data that is numerically
256 * derived with respect to the mole fraction.
257 */
258 void diff(span<const double> inputData, span<double> derivedData) const;
259
260 //! Current tabulated species index
261 size_t m_kk_tab = npos;
262
263 //! Tabulated contribution to h0[m_kk_tab] at the current composition
264 mutable double m_h0_tab;
265
266 //! Tabulated contribution to s0[m_kk_tab] at the current composition
267 mutable double m_s0_tab;
268
269 //! Vector for storing tabulated thermo
270 vector<double> m_molefrac_tab;
271 vector<double> m_enthalpy_tab;
272 vector<double> m_entropy_tab;
273 vector<double> m_molar_volume_tab;
274 vector<double> m_derived_molar_volume_tab;
275
276private:
277 void _updateThermo() const override;
278};
279}
280
281#endif
Header file for an ideal solid solution model with incompressible thermodynamics (see Thermodynamic P...
A map of string keys to values whose type can vary at runtime.
Definition AnyMap.h:431
Overloads the virtual methods of class IdealSolidSolnPhase to implement tabulated standard state ther...
vector< double > m_molefrac_tab
Vector for storing tabulated thermo.
double m_s0_tab
Tabulated contribution to s0[m_kk_tab] at the current composition.
void getParameters(AnyMap &phaseNode) const override
Store the parameters of a ThermoPhase object such that an identical one could be reconstructed using ...
string type() const override
String indicating the thermodynamic model implemented.
void initThermo() override
Initialize the ThermoPhase object after all species have been set up.
double interpolate(const double x, span< const double > inputData) const
Species thermodynamics linear interpolation function.
size_t m_kk_tab
Current tabulated species index.
void calcDensity() override
Overloads the calcDensity() method of IdealSolidSoln to also consider non-ideal behavior.
void getPartialMolarVolumes(span< double > vbar) const override
returns an array of partial molar volumes of the species in the solution.
double m_h0_tab
Tabulated contribution to h0[m_kk_tab] at the current composition.
void compositionChanged() override
If the compositions have changed, update the tabulated thermo lookup.
bool ready() const override
Returns a bool indicating whether the object is ready for use.
bool addSpecies(shared_ptr< Species > spec) override
Add a Species to this Phase.
void _updateThermo() const override
This function gets called for every call to functions in this class.
void diff(span< const double > inputData, span< double > derivedData) const
Numerical derivative of the molar volume table.
Class IdealSolidSolnPhase represents a condensed phase ideal solution compound.
Namespace for the Cantera kernel.
Definition AnyMap.cpp:595
const size_t npos
index returned by functions to indicate "no position"
Definition ct_defs.h:183
Various templated functions that carry out common vector and polynomial operations (see Templated Arr...