Remove code deprecated in Cantera 2.4
This commit is contained in:
parent
0257c4868e
commit
6f45b241b5
61 changed files with 5 additions and 12304 deletions
|
|
@ -144,8 +144,7 @@ if localenv['sphinx_docs']:
|
||||||
'1D/@Domain1D': ['1D/AxiStagnFlow.m', '1D/AxisymmetricFlow.m',
|
'1D/@Domain1D': ['1D/AxiStagnFlow.m', '1D/AxisymmetricFlow.m',
|
||||||
'1D/Inlet.m', '1D/Outlet.m', '1D/OutletRes.m',
|
'1D/Inlet.m', '1D/Outlet.m', '1D/OutletRes.m',
|
||||||
'1D/Surface.m', '1D/SymmPlane.m'],
|
'1D/Surface.m', '1D/SymmPlane.m'],
|
||||||
'1D/@Stack': ['1D/FreeFlame.m', '1D/npflame_init.m',
|
'1D/@Stack': ['1D/FreeFlame.m', '1D/CounterFlowDiffusionFlame.m'],
|
||||||
'1D/CounterFlowDiffusionFlame.m'],
|
|
||||||
'@Interface': ['importEdge.m', 'importInterface.m'],
|
'@Interface': ['importEdge.m', 'importInterface.m'],
|
||||||
'@Data': ['gasconstant.m', 'oneatm.m'],
|
'@Data': ['gasconstant.m', 'oneatm.m'],
|
||||||
'@Utilities': ['adddir.m', 'ck2cti.m', 'cleanup.m', 'geterr.m',
|
'@Utilities': ['adddir.m', 'ck2cti.m', 'cleanup.m', 'geterr.m',
|
||||||
|
|
|
||||||
|
|
@ -80,9 +80,6 @@ Thermodynamic Properties
|
||||||
.. autoclass:: Shomate
|
.. autoclass:: Shomate
|
||||||
:no-undoc-members:
|
:no-undoc-members:
|
||||||
|
|
||||||
.. autoclass:: Adsorbate
|
|
||||||
:no-undoc-members:
|
|
||||||
|
|
||||||
.. autoclass:: const_cp
|
.. autoclass:: const_cp
|
||||||
:no-undoc-members:
|
:no-undoc-members:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -72,7 +72,6 @@ extern "C" {
|
||||||
CANTERA_CAPI double thermo_thermalExpansionCoeff(int n);
|
CANTERA_CAPI double thermo_thermalExpansionCoeff(int n);
|
||||||
CANTERA_CAPI double thermo_isothermalCompressibility(int n);
|
CANTERA_CAPI double thermo_isothermalCompressibility(int n);
|
||||||
CANTERA_CAPI int thermo_chemPotentials(int n, size_t lenm, double* murt);
|
CANTERA_CAPI int thermo_chemPotentials(int n, size_t lenm, double* murt);
|
||||||
CANTERA_CAPI int thermo_elementPotentials(int n, size_t lenm, double* lambda);
|
|
||||||
CANTERA_CAPI int thermo_getEnthalpies_RT(int n, size_t lenm, double* h_rt);
|
CANTERA_CAPI int thermo_getEnthalpies_RT(int n, size_t lenm, double* h_rt);
|
||||||
CANTERA_CAPI int thermo_getEntropies_R(int n, size_t lenm, double* s_r);
|
CANTERA_CAPI int thermo_getEntropies_R(int n, size_t lenm, double* s_r);
|
||||||
CANTERA_CAPI int thermo_getCp_R(int n, size_t lenm, double* cp_r);
|
CANTERA_CAPI int thermo_getCp_R(int n, size_t lenm, double* cp_r);
|
||||||
|
|
|
||||||
|
|
@ -124,11 +124,6 @@ public:
|
||||||
int equilibrate(thermo_t& s, const char* XY, vector_fp& elMoles,
|
int equilibrate(thermo_t& s, const char* XY, vector_fp& elMoles,
|
||||||
int loglevel = 0);
|
int loglevel = 0);
|
||||||
|
|
||||||
//! @deprecated To be removed after Cantera 2.4.
|
|
||||||
const vector_fp& elementPotentials() const {
|
|
||||||
return m_lambda;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Options controlling how the calculation is carried out.
|
* Options controlling how the calculation is carried out.
|
||||||
* @see EquilOptions
|
* @see EquilOptions
|
||||||
|
|
@ -267,10 +262,6 @@ protected:
|
||||||
//! Current value of the mole fractions in the single phase. length = #m_kk.
|
//! Current value of the mole fractions in the single phase. length = #m_kk.
|
||||||
vector_fp m_molefractions;
|
vector_fp m_molefractions;
|
||||||
|
|
||||||
//! Current value of the dimensional element potentials. length = #m_mm
|
|
||||||
//! @deprecated To be removed after Cantera 2.4.
|
|
||||||
vector_fp m_lambda;
|
|
||||||
|
|
||||||
//! Current value of the sum of the element abundances given the current
|
//! Current value of the sum of the element abundances given the current
|
||||||
//! element potentials.
|
//! element potentials.
|
||||||
doublereal m_elementTotalSum;
|
doublereal m_elementTotalSum;
|
||||||
|
|
|
||||||
|
|
@ -1,61 +0,0 @@
|
||||||
/**
|
|
||||||
* @file AqueousKinetics.h
|
|
||||||
* @ingroup chemkinetics
|
|
||||||
*/
|
|
||||||
|
|
||||||
// This file is part of Cantera. See License.txt in the top-level directory or
|
|
||||||
// at http://www.cantera.org/license.txt for license and copyright information.
|
|
||||||
|
|
||||||
#ifndef CT_AQUEOUSKINETICS_H
|
|
||||||
#define CT_AQUEOUSKINETICS_H
|
|
||||||
|
|
||||||
#include "BulkKinetics.h"
|
|
||||||
|
|
||||||
namespace Cantera
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Kinetics manager for elementary aqueous-phase chemistry. This kinetics
|
|
||||||
* manager implements standard mass-action reaction rate expressions for liquids
|
|
||||||
*
|
|
||||||
* @attention This class currently does not have any test cases or examples. Its
|
|
||||||
* implementation may be incomplete, and future changes to Cantera may
|
|
||||||
* unexpectedly cause this class to stop working. If you use this class,
|
|
||||||
* please consider contributing examples or test cases. In the absence of
|
|
||||||
* new tests or examples, this class may be deprecated and removed in a
|
|
||||||
* future version of Cantera. See
|
|
||||||
* https://github.com/Cantera/cantera/issues/267 for additional information.
|
|
||||||
*
|
|
||||||
* @deprecated To be removed after Cantera 2.4
|
|
||||||
*
|
|
||||||
* @ingroup kinetics
|
|
||||||
*/
|
|
||||||
class AqueousKinetics : public BulkKinetics
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
/// Constructor. Creates an empty reaction mechanism.
|
|
||||||
AqueousKinetics(thermo_t* thermo = 0);
|
|
||||||
|
|
||||||
virtual std::string kineticsType() const {
|
|
||||||
return "Aqueous";
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void getEquilibriumConstants(doublereal* kc);
|
|
||||||
virtual void getFwdRateConstants(doublereal* kfwd);
|
|
||||||
void updateROP();
|
|
||||||
|
|
||||||
//! Update temperature-dependent portions of reaction rates
|
|
||||||
void _update_rates_T();
|
|
||||||
|
|
||||||
//! Update properties that depend on concentrations.
|
|
||||||
void _update_rates_C();
|
|
||||||
|
|
||||||
//! Update the equilibrium constants in molar units.
|
|
||||||
void updateKc();
|
|
||||||
|
|
||||||
virtual bool addReaction(shared_ptr<Reaction> r);
|
|
||||||
virtual void modifyReaction(size_t i, shared_ptr<Reaction> rNew);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -466,46 +466,6 @@ private:
|
||||||
vector_fp m_ybar;
|
vector_fp m_ybar;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* A class for axisymmetric stagnation flows.
|
|
||||||
*
|
|
||||||
* @deprecated To be removed after Cantera 2.4. Use class StFlow with the
|
|
||||||
* StFlow::setAxisymmetricFlow() method instead.
|
|
||||||
*
|
|
||||||
* @ingroup onedim
|
|
||||||
*/
|
|
||||||
class AxiStagnFlow : public StFlow
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
AxiStagnFlow(IdealGasPhase* ph = 0, size_t nsp = 1, size_t points = 1) :
|
|
||||||
StFlow(ph, nsp, points) {
|
|
||||||
m_dovisc = true;
|
|
||||||
m_type = cAxisymmetricStagnationFlow;
|
|
||||||
warn_deprecated("Class AxiStagnFlow is deprecated",
|
|
||||||
"Use StFlow with setAxisymmetricFlow() instead. To be removed after Cantera 2.4.");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A class for freely-propagating premixed flames.
|
|
||||||
*
|
|
||||||
* @deprecated To be removed after Cantera 2.4. Use class StFlow with the
|
|
||||||
* StFlow::setFreeFlow() method instead.
|
|
||||||
*
|
|
||||||
* @ingroup onedim
|
|
||||||
*/
|
|
||||||
class FreeFlame : public StFlow
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
FreeFlame(IdealGasPhase* ph = 0, size_t nsp = 1, size_t points = 1) :
|
|
||||||
StFlow(ph, nsp, points) {
|
|
||||||
m_dovisc = false;
|
|
||||||
m_type = cFreeFlow;
|
|
||||||
warn_deprecated("Class FreeFlame is deprecated",
|
|
||||||
"Use StFlow with setFreeFlow() instead. To be removed after Cantera 2.4.");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -1,122 +0,0 @@
|
||||||
/**
|
|
||||||
* @file AdsorbateThermo.h
|
|
||||||
*
|
|
||||||
* Header for a single-species standard state object derived from \link
|
|
||||||
* Cantera::SpeciesThermoInterpType SpeciesThermoInterpType\endlink based on the
|
|
||||||
* expressions for the thermo properties of a species with several vibrational
|
|
||||||
* models.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// This file is part of Cantera. See License.txt in the top-level directory or
|
|
||||||
// at http://www.cantera.org/license.txt for license and copyright information.
|
|
||||||
|
|
||||||
#ifndef CT_ADSORBATE_H
|
|
||||||
#define CT_ADSORBATE_H
|
|
||||||
|
|
||||||
#include "SpeciesThermoInterpType.h"
|
|
||||||
|
|
||||||
namespace Cantera
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An adsorbed surface species.
|
|
||||||
*
|
|
||||||
* @attention This class currently does not have any test cases or examples. Its
|
|
||||||
* implementation may be incomplete, and future changes to Cantera may
|
|
||||||
* unexpectedly cause this class to stop working. If you use this class,
|
|
||||||
* please consider contributing examples or test cases. In the absence of
|
|
||||||
* new tests or examples, this class may be deprecated and removed in a
|
|
||||||
* future version of Cantera. See
|
|
||||||
* https://github.com/Cantera/cantera/issues/267 for additional information.
|
|
||||||
*
|
|
||||||
* @deprecated To be removed after Cantera 2.4
|
|
||||||
*
|
|
||||||
* This class is designed specifically for use by the class MultiSpeciesThermo.
|
|
||||||
* It implements a model for the thermodynamic properties of a molecule that can
|
|
||||||
* be modeled as a set of independent quantum harmonic oscillators.
|
|
||||||
*
|
|
||||||
* @ingroup spthermo
|
|
||||||
*/
|
|
||||||
class Adsorbate : public SpeciesThermoInterpType
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
//! Full Constructor
|
|
||||||
/*!
|
|
||||||
* @param tlow output - Minimum temperature
|
|
||||||
* @param thigh output - Maximum temperature
|
|
||||||
* @param pref output - reference pressure (Pa).
|
|
||||||
* @param coeffs Coefficients for the parameterization
|
|
||||||
*/
|
|
||||||
Adsorbate(double tlow, double thigh, double pref, const double* coeffs)
|
|
||||||
: SpeciesThermoInterpType(tlow, thigh, pref)
|
|
||||||
{
|
|
||||||
warn_deprecated("Class Adsorbate", "To be removed after Cantera 2.4");
|
|
||||||
m_freq.resize(int(coeffs[0]));
|
|
||||||
m_be = coeffs[1];
|
|
||||||
std::copy(coeffs+2, coeffs + 2 + m_freq.size(), m_freq.begin());
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual int reportType() const {
|
|
||||||
return ADSORBATE;
|
|
||||||
}
|
|
||||||
|
|
||||||
void updatePropertiesTemp(const doublereal temp,
|
|
||||||
doublereal* cp_R,
|
|
||||||
doublereal* h_RT,
|
|
||||||
doublereal* s_R) const {
|
|
||||||
*h_RT = _energy_RT(temp);
|
|
||||||
*cp_R = (temp**h_RT - (temp-0.01)*_energy_RT(temp-0.01))/0.01;
|
|
||||||
*s_R = *h_RT - _free_energy_RT(temp);
|
|
||||||
}
|
|
||||||
|
|
||||||
void reportParameters(size_t& n, int& type,
|
|
||||||
doublereal& tlow, doublereal& thigh,
|
|
||||||
doublereal& pref,
|
|
||||||
doublereal* const coeffs) const {
|
|
||||||
n = 0;
|
|
||||||
type = ADSORBATE;
|
|
||||||
tlow = m_lowT;
|
|
||||||
thigh = m_highT;
|
|
||||||
pref = m_Pref;
|
|
||||||
coeffs[0] = static_cast<double>(m_freq.size());
|
|
||||||
coeffs[1] = m_be;
|
|
||||||
for (size_t i = 2; i < m_freq.size()+2; i++) {
|
|
||||||
coeffs[i] = m_freq[i-2];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
//! array of vib frequencies
|
|
||||||
vector_fp m_freq;
|
|
||||||
doublereal m_be;
|
|
||||||
|
|
||||||
doublereal _energy_RT(double T) const {
|
|
||||||
doublereal x, hnu_kt, hnu, sum = 0.0;
|
|
||||||
doublereal kt = T*Boltzmann;
|
|
||||||
for (size_t i = 0; i < m_freq.size(); i++) {
|
|
||||||
hnu = Planck * m_freq[i];
|
|
||||||
hnu_kt = hnu/kt;
|
|
||||||
x = exp(-hnu_kt);
|
|
||||||
sum += hnu_kt * x/(1.0 - x);
|
|
||||||
}
|
|
||||||
return sum + m_be/(GasConstant*T);
|
|
||||||
}
|
|
||||||
|
|
||||||
doublereal _free_energy_RT(double T) const {
|
|
||||||
doublereal x, hnu_kt, sum = 0.0;
|
|
||||||
doublereal kt = T*Boltzmann;
|
|
||||||
for (size_t i = 0; i < m_freq.size(); i++) {
|
|
||||||
hnu_kt = Planck * m_freq[i] / kt;
|
|
||||||
x = exp(-hnu_kt);
|
|
||||||
sum += log(1.0 - x);
|
|
||||||
}
|
|
||||||
return sum + m_be/(GasConstant*T);
|
|
||||||
}
|
|
||||||
|
|
||||||
doublereal _entropy_R(double T) const {
|
|
||||||
return _energy_RT(T) - _free_energy_RT(T);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
@ -606,32 +606,6 @@ public:
|
||||||
//! Set the density of lattice sites [kmol/m^3]
|
//! Set the density of lattice sites [kmol/m^3]
|
||||||
void setSiteDensity(double sitedens);
|
void setSiteDensity(double sitedens);
|
||||||
|
|
||||||
//! Set the equation of state parameters from the argument list
|
|
||||||
/*!
|
|
||||||
* @deprecated To be removed after Cantera 2.4.
|
|
||||||
* @internal
|
|
||||||
* Set equation of state parameters.
|
|
||||||
*
|
|
||||||
* @param n number of parameters. Must be one
|
|
||||||
* @param c array of \a n coefficients
|
|
||||||
* c[0] = The bulk lattice density (kmol m-3)
|
|
||||||
*/
|
|
||||||
virtual void setParameters(int n, doublereal* const c);
|
|
||||||
|
|
||||||
//! Get the equation of state parameters in a vector
|
|
||||||
/*!
|
|
||||||
* @deprecated To be removed after Cantera 2.4.
|
|
||||||
* @internal
|
|
||||||
*
|
|
||||||
* @param n number of parameters
|
|
||||||
* @param c array of \a n coefficients
|
|
||||||
*
|
|
||||||
* For this phase:
|
|
||||||
* - n = 1
|
|
||||||
* - c[0] = molar density of phase [ kmol/m^3 ]
|
|
||||||
*/
|
|
||||||
virtual void getParameters(int& n, doublereal* const c) const;
|
|
||||||
|
|
||||||
//! Set equation of state parameter values from XML entries.
|
//! Set equation of state parameter values from XML entries.
|
||||||
/*!
|
/*!
|
||||||
* This method is called by function importPhase() when processing a phase
|
* This method is called by function importPhase() when processing a phase
|
||||||
|
|
|
||||||
|
|
@ -1,373 +0,0 @@
|
||||||
/**
|
|
||||||
* @file MetalSHEelectrons.h
|
|
||||||
* Header file for the MetalSHEElectrons class, which represents the
|
|
||||||
* electrons in a metal that are consistent with the
|
|
||||||
* SHE electrode (see \ref thermoprops and
|
|
||||||
* class \link Cantera::MetalSHEelectrons MetalSHEelectrons\endlink)
|
|
||||||
*/
|
|
||||||
|
|
||||||
// This file is part of Cantera. See License.txt in the top-level directory or
|
|
||||||
// at http://www.cantera.org/license.txt for license and copyright information.
|
|
||||||
|
|
||||||
#ifndef CT_METALSHEELECTRONS_H
|
|
||||||
#define CT_METALSHEELECTRONS_H
|
|
||||||
|
|
||||||
#include "SingleSpeciesTP.h"
|
|
||||||
|
|
||||||
namespace Cantera
|
|
||||||
{
|
|
||||||
|
|
||||||
//! Class MetalSHEelectrons represents electrons within a metal, adjacent to an
|
|
||||||
//! aqueous electrolyte, that are consistent with the SHE reference electrode.
|
|
||||||
/*!
|
|
||||||
*
|
|
||||||
* @attention This class currently does not have any test cases or examples. Its
|
|
||||||
* implementation may be incomplete, and future changes to Cantera may
|
|
||||||
* unexpectedly cause this class to stop working. If you use this class,
|
|
||||||
* please consider contributing examples or test cases. In the absence of
|
|
||||||
* new tests or examples, this class may be deprecated and removed in a
|
|
||||||
* future version of Cantera. See
|
|
||||||
* https://github.com/Cantera/cantera/issues/267 for additional information.
|
|
||||||
*
|
|
||||||
* @deprecated To be removed after Cantera 2.4
|
|
||||||
*
|
|
||||||
* The class is based on the electron having a chemical potential equal to one-
|
|
||||||
* half of the entropy of the H2 gas at the system pressure
|
|
||||||
*
|
|
||||||
* ## Specification of Species Standard State Properties
|
|
||||||
*
|
|
||||||
* This class inherits from SingleSpeciesTP. It is assumed that the reference
|
|
||||||
* state thermodynamics may be obtained by a pointer to a populated species
|
|
||||||
* thermodynamic property manager class (see ThermoPhase::m_spthermo). How to
|
|
||||||
* relate pressure changes to the reference state thermodynamics is resolved at
|
|
||||||
* this level.
|
|
||||||
*
|
|
||||||
* The enthalpy function is given by the following relation.
|
|
||||||
*
|
|
||||||
* \f[
|
|
||||||
* h^o_k(T,P) = h^{ref}_k(T)
|
|
||||||
* \f]
|
|
||||||
*
|
|
||||||
* The standard state constant-pressure heat capacity is independent of pressure:
|
|
||||||
*
|
|
||||||
* \f[
|
|
||||||
* Cp^o_k(T,P) = Cp^{ref}_k(T)
|
|
||||||
* \f]
|
|
||||||
*
|
|
||||||
* The standard state entropy depends in the following fashion on pressure:
|
|
||||||
*
|
|
||||||
* \f[
|
|
||||||
* S^o_k(T,P) = S^{ref}_k(T) - R \ln(\frac{P}{P_{ref}})
|
|
||||||
* \f]
|
|
||||||
*
|
|
||||||
* The standard state Gibbs free energy is obtained from the enthalpy and
|
|
||||||
* entropy functions:
|
|
||||||
*
|
|
||||||
* \f[
|
|
||||||
* \mu^o_k(T,P) = h^o_k(T,P) - S^o_k(T,P) T
|
|
||||||
* \f]
|
|
||||||
*
|
|
||||||
* \f[
|
|
||||||
* \mu^o_k(T,P) = \mu^{ref}_k(T) + R T \ln( \frac{P}{P_{ref}})
|
|
||||||
* \f]
|
|
||||||
*
|
|
||||||
* where
|
|
||||||
* \f[
|
|
||||||
* \mu^{ref}_k(T) = h^{ref}_k(T) - T S^{ref}_k(T)
|
|
||||||
* \f]
|
|
||||||
*
|
|
||||||
* The standard state internal energy is obtained from the enthalpy function also
|
|
||||||
*
|
|
||||||
* \f[
|
|
||||||
* u^o_k(T,P) = h^o_k(T) - R T
|
|
||||||
* \f]
|
|
||||||
*
|
|
||||||
* ## Specification of Solution Thermodynamic Properties
|
|
||||||
*
|
|
||||||
* All solution properties are obtained from the standard state species
|
|
||||||
* functions, since there is only one species in the phase.
|
|
||||||
*
|
|
||||||
* ## %Application within Kinetics Managers
|
|
||||||
*
|
|
||||||
* The standard concentration is equal to 1.0. This means that the kinetics
|
|
||||||
* operator works on an activities basis. Since this is a stoichiometric
|
|
||||||
* substance, this means that the concentration of this phase drops out of
|
|
||||||
* kinetics expressions since the activity is always equal to one.
|
|
||||||
*
|
|
||||||
* This is what is expected of electrons. The only effect that this class will
|
|
||||||
* have on reactions is in terms of the standard state chemical potential, which
|
|
||||||
* is equal to 1/2 of the H2 gas chemical potential, and the voltage assigned to
|
|
||||||
* the electron, which is the voltage of the metal.
|
|
||||||
*
|
|
||||||
* ## Instantiation of the Class
|
|
||||||
*
|
|
||||||
* The constructor for this phase is located in the default ThermoFactory for
|
|
||||||
* %Cantera. A new MetalSHEelectrons object may be created by the following code
|
|
||||||
* snippets, where the file metalSHEelectrons.xml exists in a local directory:
|
|
||||||
*
|
|
||||||
* @code
|
|
||||||
* MetalSHEelectrons *eMetal = new MetalSHEelectrons("metalSHEelectrons.xml", "");
|
|
||||||
* @endcode
|
|
||||||
*
|
|
||||||
* or by the following call to importPhase():
|
|
||||||
*
|
|
||||||
* @code
|
|
||||||
* XML_Node *xm = get_XML_NameID("phase", iFile + "#MetalSHEelectrons", 0);
|
|
||||||
* MetalSHEelectrons eMetal;
|
|
||||||
* importPhase(*xm, &eMetal);
|
|
||||||
* @endcode
|
|
||||||
*
|
|
||||||
* @code
|
|
||||||
* ThermoPhase *eMetal = newPhase("MetalSHEelectrons.xml", "MetalSHEelectrons");
|
|
||||||
* @endcode
|
|
||||||
*
|
|
||||||
* Additionally, this phase may be created without including an XML file with
|
|
||||||
* the special command, where the default file is embedded into this object.
|
|
||||||
*
|
|
||||||
* @code
|
|
||||||
* MetalSHEelectrons *eMetal = new MetalSHEelectrons("MetalSHEelectrons_default.xml", "");
|
|
||||||
* @endcode
|
|
||||||
*
|
|
||||||
* ## XML Example
|
|
||||||
*
|
|
||||||
* The phase model name for this is called MetalSHEelectrons. It must be
|
|
||||||
* supplied as the model attribute of the thermo XML element entry. Within the
|
|
||||||
* phase XML block, the density of the phase must be specified though it's not
|
|
||||||
* used. An example of an XML file this phase is given below.
|
|
||||||
*
|
|
||||||
* @code
|
|
||||||
* <?xml version="1.0"?>
|
|
||||||
* <ctml>
|
|
||||||
* <validate reactions="yes" species="yes"/>
|
|
||||||
*
|
|
||||||
* <phase dim="3" id="MetalSHEelectrons">
|
|
||||||
* <elementArray datasrc="elements.xml">
|
|
||||||
* E
|
|
||||||
* </elementArray>
|
|
||||||
* <speciesArray datasrc="#species_Metal_SHEelectrons"> she_electron </speciesArray>
|
|
||||||
* <thermo model="metalSHEelectrons">
|
|
||||||
* <density units="g/cm3">2.165</density>
|
|
||||||
* </thermo>
|
|
||||||
* <transport model="None"/>
|
|
||||||
* <kinetics model="none"/>
|
|
||||||
* </phase>
|
|
||||||
*
|
|
||||||
* <!-- species definitions -->
|
|
||||||
* <speciesData id="species_Metal_SHEelectrons">
|
|
||||||
* <species name="she_electron">
|
|
||||||
* <atomArray> E:1 </atomArray>
|
|
||||||
* <charge> -1 </charge>
|
|
||||||
* <thermo>
|
|
||||||
* <NASA Tmax="1000.0" Tmin="200.0" P0="100000.0">
|
|
||||||
* <floatArray name="coeffs" size="7">
|
|
||||||
* 1.172165560E+00, 3.990260375E-03, -9.739075500E-06, 1.007860470E-08,
|
|
||||||
* -3.688058805E-12, -4.589675865E+02, 3.415051190E-01
|
|
||||||
* </floatArray>
|
|
||||||
* </NASA>
|
|
||||||
* <NASA Tmax="6000.0" Tmin="1000.0" P0="100000.0">
|
|
||||||
* <floatArray name="coeffs" size="7">
|
|
||||||
* 1.466432895E+00, 4.133039835E-04, -7.320116750E-08, 7.705017950E-12,
|
|
||||||
* -3.444022160E-16, -4.065327985E+02, -5.121644350E-01
|
|
||||||
* </floatArray>
|
|
||||||
* </NASA>
|
|
||||||
* </thermo>
|
|
||||||
* <density units="g/cm3">2.165</density>
|
|
||||||
* </species>
|
|
||||||
* </speciesData>
|
|
||||||
* </ctml>
|
|
||||||
* @endcode
|
|
||||||
*
|
|
||||||
* The model attribute, "MetalSHEelectrons", on the thermo element identifies
|
|
||||||
* the phase as being a MetalSHEelectrons object.
|
|
||||||
*
|
|
||||||
* @ingroup thermoprops
|
|
||||||
*/
|
|
||||||
class MetalSHEelectrons : public SingleSpeciesTP
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
//! Default constructor for the MetalSHEelectrons class
|
|
||||||
MetalSHEelectrons();
|
|
||||||
|
|
||||||
//! Construct and initialize a MetalSHEelectrons ThermoPhase object
|
|
||||||
//! directly from an ASCII input file
|
|
||||||
/*!
|
|
||||||
* @param infile name of the input file
|
|
||||||
* @param id name of the phase id in the file.
|
|
||||||
* If this is blank, the first phase in the file is used.
|
|
||||||
*/
|
|
||||||
MetalSHEelectrons(const std::string& infile, const std::string& id = "");
|
|
||||||
|
|
||||||
//! Construct and initialize a MetalSHEelectrons ThermoPhase object
|
|
||||||
//! directly from an XML database
|
|
||||||
/*!
|
|
||||||
* @param phaseRef XML node pointing to a MetalSHEelectrons description
|
|
||||||
* @param id Id of the phase.
|
|
||||||
*/
|
|
||||||
MetalSHEelectrons(XML_Node& phaseRef, const std::string& id = "");
|
|
||||||
|
|
||||||
//! @name Mechanical Equation of State
|
|
||||||
//! @{
|
|
||||||
|
|
||||||
//! Report the Pressure. Units: Pa.
|
|
||||||
/*!
|
|
||||||
* For an incompressible substance, the density is independent of pressure.
|
|
||||||
* This method simply returns the stored pressure value.
|
|
||||||
*/
|
|
||||||
virtual doublereal pressure() const;
|
|
||||||
|
|
||||||
//! Set the pressure at constant temperature. Units: Pa.
|
|
||||||
/*!
|
|
||||||
* For an incompressible substance, the density is independent of pressure.
|
|
||||||
* Therefore, this method only stores the specified pressure value. It does
|
|
||||||
* not modify the density.
|
|
||||||
*
|
|
||||||
* @param p Pressure (units - Pa)
|
|
||||||
*/
|
|
||||||
virtual void setPressure(doublereal p);
|
|
||||||
|
|
||||||
virtual doublereal isothermalCompressibility() const;
|
|
||||||
virtual doublereal thermalExpansionCoeff() const;
|
|
||||||
|
|
||||||
//! @}
|
|
||||||
//! @name Activities, Standard States, and Activity Concentrations
|
|
||||||
//!
|
|
||||||
//! This section is largely handled by parent classes, since there
|
|
||||||
//! is only one species. Therefore, the activity is equal to one.
|
|
||||||
//! @{
|
|
||||||
|
|
||||||
//! This method returns an array of generalized concentrations
|
|
||||||
/*!
|
|
||||||
* \f$ C^a_k\f$ are defined such that \f$ a_k = C^a_k / C^0_k, \f$ where
|
|
||||||
* \f$ C^0_k \f$ is a standard concentration defined below and \f$ a_k \f$
|
|
||||||
* are activities used in the thermodynamic functions. These activity (or
|
|
||||||
* generalized) concentrations are used by kinetics manager classes to
|
|
||||||
* compute the forward and reverse rates of elementary reactions.
|
|
||||||
*
|
|
||||||
* For a stoichiometric substance, there is only one species, and the
|
|
||||||
* generalized concentration is 1.0.
|
|
||||||
*
|
|
||||||
* @param c Output array of generalized concentrations. The units depend
|
|
||||||
* upon the implementation of the reaction rate expressions within
|
|
||||||
* the phase.
|
|
||||||
*/
|
|
||||||
virtual void getActivityConcentrations(doublereal* c) const;
|
|
||||||
|
|
||||||
//! Return the standard concentration for the kth species
|
|
||||||
/*!
|
|
||||||
* The standard concentration \f$ C^0_k \f$ used to normalize the activity
|
|
||||||
* (i.e., generalized) concentration. This phase assumes that the kinetics
|
|
||||||
* operator works on an dimensionless basis. Thus, the standard
|
|
||||||
* concentration is equal to 1.0.
|
|
||||||
*
|
|
||||||
* @param k Optional parameter indicating the species. The default
|
|
||||||
* is to assume this refers to species 0.
|
|
||||||
* @return
|
|
||||||
* Returns The standard Concentration as 1.0
|
|
||||||
*/
|
|
||||||
virtual doublereal standardConcentration(size_t k=0) const;
|
|
||||||
|
|
||||||
//! Natural logarithm of the standard concentration of the kth species.
|
|
||||||
/*!
|
|
||||||
* @param k index of the species (defaults to zero)
|
|
||||||
*/
|
|
||||||
virtual doublereal logStandardConc(size_t k=0) const;
|
|
||||||
|
|
||||||
//! Get the array of chemical potentials at unit activity for the species at
|
|
||||||
//! their standard states at the current *T* and *P* of the solution.
|
|
||||||
/*!
|
|
||||||
* For a stoichiometric substance, there is no activity term in the chemical
|
|
||||||
* potential expression, and therefore the standard chemical potential and
|
|
||||||
* the chemical potential are both equal to the molar Gibbs function.
|
|
||||||
*
|
|
||||||
* These are the standard state chemical potentials \f$ \mu^0_k(T,P) \f$.
|
|
||||||
* The values are evaluated at the current temperature and pressure of the
|
|
||||||
* solution
|
|
||||||
*
|
|
||||||
* @param mu0 Output vector of chemical potentials.
|
|
||||||
* Length: m_kk.
|
|
||||||
*/
|
|
||||||
virtual void getStandardChemPotentials(doublereal* mu0) const;
|
|
||||||
|
|
||||||
//@}
|
|
||||||
/// @name Properties of the Standard State of the Species in the Solution
|
|
||||||
//@{
|
|
||||||
|
|
||||||
virtual void getEnthalpy_RT(doublereal* hrt) const;
|
|
||||||
virtual void getEntropy_R(doublereal* sr) const;
|
|
||||||
virtual void getGibbs_RT(doublereal* grt) const;
|
|
||||||
virtual void getCp_R(doublereal* cpr) const;
|
|
||||||
|
|
||||||
//! Returns the vector of nondimensional Internal Energies of the standard
|
|
||||||
//! state species at the current *T* and *P* of the solution
|
|
||||||
/*!
|
|
||||||
* For an incompressible, stoichiometric substance, the molar internal
|
|
||||||
* energy is independent of pressure. Since the thermodynamic properties are
|
|
||||||
* specified by giving the standard-state enthalpy, the term \f$ P_{ref}
|
|
||||||
* \hat v\f$ is subtracted from the specified reference molar enthalpy to
|
|
||||||
* compute the standard state molar internal energy.
|
|
||||||
*
|
|
||||||
* @param urt output vector of nondimensional standard state
|
|
||||||
* internal energies of the species. Length: m_kk.
|
|
||||||
*/
|
|
||||||
virtual void getIntEnergy_RT(doublereal* urt) const;
|
|
||||||
|
|
||||||
//@}
|
|
||||||
/// @name Thermodynamic Values for the Species Reference States
|
|
||||||
//@{
|
|
||||||
|
|
||||||
virtual void getIntEnergy_RT_ref(doublereal* urt) const;
|
|
||||||
// @}
|
|
||||||
|
|
||||||
virtual void initThermoXML(XML_Node& phaseNode, const std::string& id);
|
|
||||||
|
|
||||||
//! Make the default XML tree
|
|
||||||
/*!
|
|
||||||
* @returns a new XML tree containing the default info.
|
|
||||||
*/
|
|
||||||
static XML_Node* makeDefaultXMLTree();
|
|
||||||
|
|
||||||
//! Set the equation of state parameters
|
|
||||||
/*!
|
|
||||||
* @internal
|
|
||||||
*
|
|
||||||
* @param n number of parameters
|
|
||||||
* @param c array of \a n coefficients
|
|
||||||
* c[0] = density of phase [ kg/m3 ]
|
|
||||||
*/
|
|
||||||
virtual void setParameters(int n, doublereal* const c);
|
|
||||||
|
|
||||||
//! Get the equation of state parameters in a vector
|
|
||||||
/*!
|
|
||||||
* @internal
|
|
||||||
*
|
|
||||||
* @param n number of parameters
|
|
||||||
* @param c array of \a n coefficients
|
|
||||||
*
|
|
||||||
* For this phase:
|
|
||||||
* - n = 1
|
|
||||||
* - c[0] = density of phase [ kg/m3 ]
|
|
||||||
*/
|
|
||||||
virtual void getParameters(int& n, doublereal* const c) const;
|
|
||||||
|
|
||||||
//! Set equation of state parameter values from XML entries.
|
|
||||||
/*!
|
|
||||||
* For this phase, the density of the phase is specified in this block.
|
|
||||||
*
|
|
||||||
* @param eosdata An XML_Node object corresponding to
|
|
||||||
* the "thermo" entry for this phase in the input file.
|
|
||||||
*
|
|
||||||
* eosdata points to the thermo block, and looks like this:
|
|
||||||
*
|
|
||||||
* @code
|
|
||||||
* <phase id="stoichsolid" >
|
|
||||||
* <thermo model="StoichSubstance">
|
|
||||||
* <density units="g/cm3">3.52</density>
|
|
||||||
* </thermo>
|
|
||||||
* </phase>
|
|
||||||
* @endcode
|
|
||||||
*/
|
|
||||||
virtual void setParametersFromXML(const XML_Node& eosdata);
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,325 +0,0 @@
|
||||||
/**
|
|
||||||
* @file MineralEQ3.h
|
|
||||||
* Header file for the MineralEQ3 class, which represents a fixed-composition
|
|
||||||
* incompressible substance based on EQ3's parameterization (see \ref thermoprops and
|
|
||||||
* class \link Cantera::MineralEQ3 MineralEQ3\endlink)
|
|
||||||
*/
|
|
||||||
|
|
||||||
// This file is part of Cantera. See License.txt in the top-level directory or
|
|
||||||
// at http://www.cantera.org/license.txt for license and copyright information.
|
|
||||||
|
|
||||||
#ifndef CT_MINERALEQ3_H
|
|
||||||
#define CT_MINERALEQ3_H
|
|
||||||
|
|
||||||
#include "StoichSubstance.h"
|
|
||||||
|
|
||||||
namespace Cantera
|
|
||||||
{
|
|
||||||
|
|
||||||
//! Class MineralEQ3 represents a stoichiometric (fixed composition)
|
|
||||||
//! incompressible substance based on EQ3's parameterization
|
|
||||||
/*!
|
|
||||||
* @attention This class currently does not have any test cases or examples. Its
|
|
||||||
* implementation may be incomplete, and future changes to Cantera may
|
|
||||||
* unexpectedly cause this class to stop working. If you use this class,
|
|
||||||
* please consider contributing examples or test cases. In the absence of
|
|
||||||
* new tests or examples, this class may be deprecated and removed in a
|
|
||||||
* future version of Cantera. See
|
|
||||||
* https://github.com/Cantera/cantera/issues/267 for additional information.
|
|
||||||
*
|
|
||||||
* @deprecated To be removed after Cantera 2.4
|
|
||||||
*
|
|
||||||
* This class inherits from SingleSpeciesTP class. EQ's parameterization is
|
|
||||||
* mapped onto the Shomate polynomial class.
|
|
||||||
*
|
|
||||||
* ## Specification of Species Standard State Properties
|
|
||||||
*
|
|
||||||
* This class inherits from SingleSpeciesTP. It is assumed that the reference
|
|
||||||
* state thermodynamics may be obtained by a pointer to a populated species
|
|
||||||
* thermodynamic property manager class (see ThermoPhase::m_spthermo). How to
|
|
||||||
* relate pressure changes to the reference state thermodynamics is resolved at
|
|
||||||
* this level.
|
|
||||||
*
|
|
||||||
* For an incompressible, stoichiometric substance, the molar internal energy is
|
|
||||||
* independent of pressure. Since the thermodynamic properties are specified by
|
|
||||||
* giving the standard-state enthalpy, the term \f$ P_0 \hat v\f$ is subtracted
|
|
||||||
* from the specified molar enthalpy to compute the molar internal energy. The
|
|
||||||
* entropy is assumed to be independent of the pressure.
|
|
||||||
*
|
|
||||||
* The enthalpy function is given by the following relation.
|
|
||||||
*
|
|
||||||
* \f[
|
|
||||||
* h^o_k(T,P) =
|
|
||||||
* h^{ref}_k(T) + \tilde v \left( P - P_{ref} \right)
|
|
||||||
* \f]
|
|
||||||
*
|
|
||||||
* For an incompressible, stoichiometric substance, the molar internal energy is
|
|
||||||
* independent of pressure. Since the thermodynamic properties are specified by
|
|
||||||
* giving the standard-state enthalpy, the term \f$ P_{ref} \tilde v\f$ is
|
|
||||||
* subtracted from the specified reference molar enthalpy to compute the molar
|
|
||||||
* internal energy.
|
|
||||||
*
|
|
||||||
* \f[
|
|
||||||
* u^o_k(T,P) = h^{ref}_k(T) - P_{ref} \tilde v
|
|
||||||
* \f]
|
|
||||||
*
|
|
||||||
* The standard state heat capacity and entropy are independent of pressure. The
|
|
||||||
* standard state Gibbs free energy is obtained from the enthalpy and entropy
|
|
||||||
* functions.
|
|
||||||
*
|
|
||||||
* ## Specification of Solution Thermodynamic Properties
|
|
||||||
*
|
|
||||||
* All solution properties are obtained from the standard state species
|
|
||||||
* functions, since there is only one species in the phase.
|
|
||||||
*
|
|
||||||
* ## %Application within Kinetics Managers
|
|
||||||
*
|
|
||||||
* The standard concentration is equal to 1.0. This means that the kinetics
|
|
||||||
* operator works on an (activities basis). Since this is a stoichiometric
|
|
||||||
* substance, this means that the concentration of this phase drops out of
|
|
||||||
* kinetics expressions.
|
|
||||||
*
|
|
||||||
* An example of a reaction using this is a sticking coefficient reaction of a
|
|
||||||
* substance in an ideal gas phase on a surface with a bulk phase species in
|
|
||||||
* this phase. In this case, the rate of progress for this reaction,
|
|
||||||
* \f$ R_s \f$, may be expressed via the following equation:
|
|
||||||
* \f[
|
|
||||||
* R_s = k_s C_{gas}
|
|
||||||
* \f]
|
|
||||||
* where the units for \f$ R_s \f$ are kmol m-2 s-1. \f$ C_{gas} \f$ has units
|
|
||||||
* of kmol m-3. Therefore, the kinetic rate constant, \f$ k_s \f$, has units of
|
|
||||||
* m s-1. Nowhere does the concentration of the bulk phase appear in the rate
|
|
||||||
* constant expression, since it's a stoichiometric phase and the activity is
|
|
||||||
* always equal to 1.0.
|
|
||||||
*
|
|
||||||
* @ingroup thermoprops
|
|
||||||
*/
|
|
||||||
class MineralEQ3 : public StoichSubstance
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
//! Default constructor for the MineralEQ3 class
|
|
||||||
MineralEQ3() {
|
|
||||||
warn_deprecated("Class MineralEQ3", "To be removed after Cantera 2.4");
|
|
||||||
}
|
|
||||||
|
|
||||||
//! Construct and initialize a MineralEQ3 ThermoPhase object
|
|
||||||
//! directly from an ASCII input file
|
|
||||||
/*!
|
|
||||||
* @param infile name of the input file
|
|
||||||
* @param id name of the phase id in the file.
|
|
||||||
* If this is blank, the first phase in the file is used.
|
|
||||||
*/
|
|
||||||
MineralEQ3(const std::string& infile, const std::string& id = "");
|
|
||||||
|
|
||||||
//! Construct and initialize a MineralEQ3 ThermoPhase object
|
|
||||||
//! directly from an XML database
|
|
||||||
/*!
|
|
||||||
* @param phaseRef XML node pointing to a MineralEQ3 description
|
|
||||||
* @param id Id of the phase.
|
|
||||||
*/
|
|
||||||
MineralEQ3(XML_Node& phaseRef, const std::string& id = "");
|
|
||||||
|
|
||||||
virtual std::string type() const {
|
|
||||||
return "MineralEQ3";
|
|
||||||
}
|
|
||||||
|
|
||||||
//! @name Mechanical Equation of State
|
|
||||||
//! @{
|
|
||||||
|
|
||||||
//! Report the Pressure. Units: Pa.
|
|
||||||
/*!
|
|
||||||
* For an incompressible substance, the density is independent of pressure.
|
|
||||||
* This method simply returns the stored pressure value.
|
|
||||||
*/
|
|
||||||
virtual doublereal pressure() const;
|
|
||||||
|
|
||||||
//! Set the pressure at constant temperature. Units: Pa.
|
|
||||||
/*!
|
|
||||||
* For an incompressible substance, the density is independent of pressure.
|
|
||||||
* Therefore, this method only stores the specified pressure value. It does
|
|
||||||
* not modify the density.
|
|
||||||
*
|
|
||||||
* @param p Pressure (units - Pa)
|
|
||||||
*/
|
|
||||||
virtual void setPressure(doublereal p);
|
|
||||||
|
|
||||||
virtual doublereal isothermalCompressibility() const;
|
|
||||||
virtual doublereal thermalExpansionCoeff() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @}
|
|
||||||
* @name Activities, Standard States, and Activity Concentrations
|
|
||||||
*
|
|
||||||
* This section is largely handled by parent classes, since there is only
|
|
||||||
* one species. Therefore, the activity is equal to one.
|
|
||||||
* @{
|
|
||||||
*/
|
|
||||||
|
|
||||||
//! This method returns an array of generalized concentrations
|
|
||||||
/*!
|
|
||||||
* \f$ C^a_k\f$ are defined such that \f$ a_k = C^a_k / C^0_k, \f$ where
|
|
||||||
* \f$ C^0_k \f$ is a standard concentration defined below and \f$ a_k \f$
|
|
||||||
* are activities used in the thermodynamic functions. These activity (or
|
|
||||||
* generalized) concentrations are used by kinetics manager classes to
|
|
||||||
* compute the forward and reverse rates of elementary reactions.
|
|
||||||
*
|
|
||||||
* For a stoichiometric substance, there is only one species, and the
|
|
||||||
* generalized concentration is 1.0.
|
|
||||||
*
|
|
||||||
* @param c Output array of generalized concentrations. The units depend
|
|
||||||
* upon the implementation of the reaction rate expressions within
|
|
||||||
* the phase.
|
|
||||||
*/
|
|
||||||
virtual void getActivityConcentrations(doublereal* c) const;
|
|
||||||
|
|
||||||
//! Return the standard concentration for the kth species
|
|
||||||
/*!
|
|
||||||
* The standard concentration \f$ C^0_k \f$ used to normalize the activity
|
|
||||||
* (i.e., generalized) concentration. This phase assumes that the kinetics
|
|
||||||
* operator works on an dimensionless basis. Thus, the standard
|
|
||||||
* concentration is equal to 1.0.
|
|
||||||
*
|
|
||||||
* @param k Optional parameter indicating the species. The default
|
|
||||||
* is to assume this refers to species 0.
|
|
||||||
* @return
|
|
||||||
* Returns The standard Concentration as 1.0
|
|
||||||
*/
|
|
||||||
virtual doublereal standardConcentration(size_t k=0) const;
|
|
||||||
virtual doublereal logStandardConc(size_t k=0) const;
|
|
||||||
|
|
||||||
//! Get the array of chemical potentials at unit activity for the species at
|
|
||||||
//! their standard states at the current *T* and *P* of the solution.
|
|
||||||
/*!
|
|
||||||
* For a stoichiometric substance, there is no activity term in the chemical
|
|
||||||
* potential expression, and therefore the standard chemical potential and
|
|
||||||
* the chemical potential are both equal to the molar Gibbs function.
|
|
||||||
*
|
|
||||||
* These are the standard state chemical potentials \f$ \mu^0_k(T,P)
|
|
||||||
* \f$. The values are evaluated at the current
|
|
||||||
* temperature and pressure of the solution
|
|
||||||
*
|
|
||||||
* @param mu0 Output vector of chemical potentials.
|
|
||||||
* Length: m_kk.
|
|
||||||
*/
|
|
||||||
virtual void getStandardChemPotentials(doublereal* mu0) const;
|
|
||||||
|
|
||||||
//@}
|
|
||||||
/// @name Properties of the Standard State of the Species in the Solution
|
|
||||||
//@{
|
|
||||||
|
|
||||||
virtual void getEnthalpy_RT(doublereal* hrt) const;
|
|
||||||
virtual void getEntropy_R(doublereal* sr) const;
|
|
||||||
virtual void getGibbs_RT(doublereal* grt) const;
|
|
||||||
virtual void getCp_R(doublereal* cpr) const;
|
|
||||||
|
|
||||||
//! Returns the vector of nondimensional Internal Energies of the standard
|
|
||||||
//! state species at the current *T* and *P* of the solution
|
|
||||||
/*!
|
|
||||||
* For an incompressible, stoichiometric substance, the molar internal
|
|
||||||
* energy is independent of pressure. Since the thermodynamic properties are
|
|
||||||
* specified by giving the standard-state enthalpy, the term
|
|
||||||
* \f$ P_{ref} \hat v\f$ is subtracted from the specified reference molar
|
|
||||||
* enthalpy to compute the standard state molar internal energy.
|
|
||||||
*
|
|
||||||
* @param urt output vector of nondimensional standard state internal
|
|
||||||
* energies of the species. Length: m_kk.
|
|
||||||
*/
|
|
||||||
virtual void getIntEnergy_RT(doublereal* urt) const;
|
|
||||||
|
|
||||||
//@}
|
|
||||||
/// @name Thermodynamic Values for the Species Reference States
|
|
||||||
//@{
|
|
||||||
|
|
||||||
virtual void getIntEnergy_RT_ref(doublereal* urt) const;
|
|
||||||
//! @}
|
|
||||||
|
|
||||||
//! @copydoc ThermoPhase::initThermoXML
|
|
||||||
/*!
|
|
||||||
* This is the main routine for reading in activity coefficient parameters.
|
|
||||||
*/
|
|
||||||
virtual void initThermoXML(XML_Node& phaseNode, const std::string& id);
|
|
||||||
|
|
||||||
//! Set the equation of state parameters
|
|
||||||
/*!
|
|
||||||
* @internal
|
|
||||||
*
|
|
||||||
* @param n number of parameters
|
|
||||||
* @param c array of \a n coefficients
|
|
||||||
* c[0] = density of phase [ kg/m3 ]
|
|
||||||
*/
|
|
||||||
virtual void setParameters(int n, doublereal* const c);
|
|
||||||
|
|
||||||
//! Get the equation of state parameters in a vector
|
|
||||||
/*!
|
|
||||||
* @internal
|
|
||||||
*
|
|
||||||
* @param n number of parameters
|
|
||||||
* @param c array of \a n coefficients
|
|
||||||
*
|
|
||||||
* For this phase:
|
|
||||||
* - n = 1
|
|
||||||
* - c[0] = density of phase [ kg/m3 ]
|
|
||||||
*/
|
|
||||||
virtual void getParameters(int& n, doublereal* const c) const;
|
|
||||||
|
|
||||||
//! @copydoc ThermoPhase::setParametersFromXML
|
|
||||||
/*!
|
|
||||||
* For this phase, the density of the phase is specified in this block.
|
|
||||||
*/
|
|
||||||
virtual void setParametersFromXML(const XML_Node& eosdata);
|
|
||||||
doublereal LookupGe(const std::string& elemName);
|
|
||||||
void convertDGFormation();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
//! Value of the Absolute Gibbs Free Energy NIST scale at T_r and P_r
|
|
||||||
/*!
|
|
||||||
* This is the NIST scale value of Gibbs free energy at T_r = 298.15
|
|
||||||
* and P_r = 1 atm.
|
|
||||||
*
|
|
||||||
* J kmol-1
|
|
||||||
*/
|
|
||||||
doublereal m_Mu0_pr_tr;
|
|
||||||
|
|
||||||
//! Input value of S_j at Tr and Pr (cal gmol-1 K-1)
|
|
||||||
/*!
|
|
||||||
* Tr = 298.15 Pr = 1 atm
|
|
||||||
*/
|
|
||||||
doublereal m_Entrop_pr_tr;
|
|
||||||
|
|
||||||
//! Input Value of deltaG of Formation at Tr and Pr (cal gmol-1)
|
|
||||||
/*!
|
|
||||||
* Tr = 298.15 Pr = 1 atm
|
|
||||||
*
|
|
||||||
* This is the delta G for the formation reaction of the ion from elements
|
|
||||||
* in their stable state at Tr, Pr.
|
|
||||||
*/
|
|
||||||
doublereal m_deltaG_formation_pr_tr;
|
|
||||||
|
|
||||||
//! Input Value of deltaH of Formation at Tr and Pr (cal gmol-1)
|
|
||||||
/*!
|
|
||||||
* Tr = 298.15 Pr = 1 atm
|
|
||||||
*
|
|
||||||
* This is the delta H for the formation reaction of the ion from elements
|
|
||||||
* in their stable state at Tr, Pr.
|
|
||||||
*/
|
|
||||||
doublereal m_deltaH_formation_pr_tr;
|
|
||||||
|
|
||||||
//! Input Value of the molar volume at T_r and P_r
|
|
||||||
/*!
|
|
||||||
* cm^3 / gmol
|
|
||||||
*/
|
|
||||||
doublereal m_V0_pr_tr;
|
|
||||||
|
|
||||||
//! a coefficient (cal gmol-1 K-1)
|
|
||||||
doublereal m_a;
|
|
||||||
|
|
||||||
//! b coefficient (cal gmol-1 K-2) x 10^3
|
|
||||||
doublereal m_b;
|
|
||||||
|
|
||||||
//! c coefficient (cal K gmol-1 K) x 10^-5
|
|
||||||
doublereal m_c;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,469 +0,0 @@
|
||||||
/**
|
|
||||||
* @file MixedSolventElectrolyte.h (see \ref thermoprops and class \link
|
|
||||||
* Cantera::MixedSolventElectrolyte MixedSolventElectrolyte \endlink).
|
|
||||||
*/
|
|
||||||
|
|
||||||
// This file is part of Cantera. See License.txt in the top-level directory or
|
|
||||||
// at http://www.cantera.org/license.txt for license and copyright information.
|
|
||||||
|
|
||||||
#ifndef CT_MIXEDSOLVENTELECTROLYTEVPSSTP_H
|
|
||||||
#define CT_MIXEDSOLVENTELECTROLYTEVPSSTP_H
|
|
||||||
|
|
||||||
#include "MolarityIonicVPSSTP.h"
|
|
||||||
|
|
||||||
namespace Cantera
|
|
||||||
{
|
|
||||||
//! MixedSolventElectrolyte is a derived class of GibbsExcessVPSSTP that employs
|
|
||||||
//! the DH and local Margules approximations for the excess Gibbs free energy
|
|
||||||
/*!
|
|
||||||
* @attention This class currently does not have any test cases or examples. Its
|
|
||||||
* implementation may be incomplete, and future changes to Cantera may
|
|
||||||
* unexpectedly cause this class to stop working. If you use this class,
|
|
||||||
* please consider contributing examples or test cases. In the absence of
|
|
||||||
* new tests or examples, this class may be deprecated and removed in a
|
|
||||||
* future version of Cantera. See
|
|
||||||
* https://github.com/Cantera/cantera/issues/267 for additional information.
|
|
||||||
*
|
|
||||||
* MixedSolventElectrolyte derives from class GibbsExcessVPSSTP which is derived
|
|
||||||
* from VPStandardStateTP.
|
|
||||||
*
|
|
||||||
* The independent unknowns are pressure, temperature, and mass fraction.
|
|
||||||
*
|
|
||||||
* ## Specification of Species Standard State Properties
|
|
||||||
*
|
|
||||||
* All species are defined to have standard states that depend upon both the
|
|
||||||
* temperature and the pressure. The Margules approximation assumes symmetric
|
|
||||||
* standard states, where all of the standard state assume that the species are
|
|
||||||
* in pure component states at the temperature and pressure of the solution. I
|
|
||||||
* don't think it prevents, however, some species from being dilute in the
|
|
||||||
* solution.
|
|
||||||
*
|
|
||||||
* ## Specification of Solution Thermodynamic Properties
|
|
||||||
*
|
|
||||||
* The molar excess Gibbs free energy is given by the following formula which is
|
|
||||||
* a sum over interactions *i*. Each of the interactions are binary interactions
|
|
||||||
* involving two of the species in the phase, denoted, *Ai* and *Bi*. This is
|
|
||||||
* the generalization of the Margules formulation for a phase that has more than
|
|
||||||
* 2 species.
|
|
||||||
*
|
|
||||||
* \f[
|
|
||||||
* G^E = \sum_i \left( H_{Ei} - T S_{Ei} \right)
|
|
||||||
* \f]
|
|
||||||
* \f[
|
|
||||||
* H^E_i = n X_{Ai} X_{Bi} \left( h_{o,i} + h_{1,i} X_{Bi} \right)
|
|
||||||
* \f]
|
|
||||||
* \f[
|
|
||||||
* S^E_i = n X_{Ai} X_{Bi} \left( s_{o,i} + s_{1,i} X_{Bi} \right)
|
|
||||||
* \f]
|
|
||||||
*
|
|
||||||
* where n is the total moles in the solution.
|
|
||||||
*
|
|
||||||
* The activity of a species defined in the phase is given by an excess Gibbs
|
|
||||||
* free energy formulation.
|
|
||||||
*
|
|
||||||
* \f[
|
|
||||||
* a_k = \gamma_k X_k
|
|
||||||
* \f]
|
|
||||||
*
|
|
||||||
* where
|
|
||||||
*
|
|
||||||
* \f[
|
|
||||||
* R T \ln( \gamma_k )= \frac{d(n G^E)}{d(n_k)}\Bigg|_{n_i}
|
|
||||||
* \f]
|
|
||||||
*
|
|
||||||
* Taking the derivatives results in the following expression
|
|
||||||
*
|
|
||||||
* \f[
|
|
||||||
* R T \ln( \gamma_k )= \sum_i \left( \left( \delta_{Ai,k} X_{Bi} + \delta_{Bi,k} X_{Ai} - X_{Ai} X_{Bi} \right)
|
|
||||||
* \left( g^E_{o,i} + g^E_{1,i} X_{Bi} \right) +
|
|
||||||
* \left( \delta_{Bi,k} - X_{Bi} \right) X_{Ai} X_{Bi} g^E_{1,i} \right)
|
|
||||||
* \f]
|
|
||||||
* where \f$ g^E_{o,i} = h_{o,i} - T s_{o,i} \f$ and
|
|
||||||
* \f$ g^E_{1,i} = h_{1,i} - T s_{1,i} \f$ and where \f$ X_k \f$ is the mole
|
|
||||||
* fraction of species *k*.
|
|
||||||
*
|
|
||||||
* This object inherits from the class VPStandardStateTP. Therefore, the
|
|
||||||
* specification and calculation of all standard state and reference state
|
|
||||||
* values are handled at that level. Various functional forms for the standard
|
|
||||||
* state are permissible. The chemical potential for species *k* is equal to
|
|
||||||
*
|
|
||||||
* \f[
|
|
||||||
* \mu_k(T,P) = \mu^o_k(T, P) + R T \ln(\gamma_k X_k)
|
|
||||||
* \f]
|
|
||||||
*
|
|
||||||
* The partial molar entropy for species *k* is given by the following relation,
|
|
||||||
*
|
|
||||||
* \f[
|
|
||||||
* \tilde{s}_k(T,P) = s^o_k(T,P) - R \ln( \gamma_k X_k )
|
|
||||||
* - R T \frac{d \ln(\gamma_k) }{dT}
|
|
||||||
* \f]
|
|
||||||
*
|
|
||||||
* The partial molar enthalpy for species *k* is given by
|
|
||||||
*
|
|
||||||
* \f[
|
|
||||||
* \tilde{h}_k(T,P) = h^o_k(T,P) - R T^2 \frac{d \ln(\gamma_k)}{dT}
|
|
||||||
* \f]
|
|
||||||
*
|
|
||||||
* The partial molar volume for species *k* is
|
|
||||||
*
|
|
||||||
* \f[
|
|
||||||
* \tilde V_k(T,P) = V^o_k(T,P) + R T \frac{d \ln(\gamma_k) }{dP}
|
|
||||||
* \f]
|
|
||||||
*
|
|
||||||
* The partial molar Heat Capacity for species *k* is
|
|
||||||
*
|
|
||||||
* \f[
|
|
||||||
* \tilde{C}_{p,k}(T,P) = C^o_{p,k}(T,P) - 2 R T \frac{d \ln( \gamma_k )}{dT}
|
|
||||||
* - R T^2 \frac{d^2 \ln(\gamma_k) }{{dT}^2}
|
|
||||||
* \f]
|
|
||||||
*
|
|
||||||
* ## %Application within Kinetics Managers
|
|
||||||
*
|
|
||||||
* \f$ C^a_k\f$ are defined such that \f$ a_k = C^a_k / C^s_k, \f$ where
|
|
||||||
* \f$ C^s_k \f$ is a standard concentration defined below and \f$ a_k \f$ are
|
|
||||||
* activities used in the thermodynamic functions. These activity (or
|
|
||||||
* generalized) concentrations are used by kinetics manager classes to compute
|
|
||||||
* the forward and reverse rates of elementary reactions. The activity
|
|
||||||
* concentration, \f$ C^a_k \f$, is given by the following expression.
|
|
||||||
*
|
|
||||||
* \f[
|
|
||||||
* C^a_k = C^s_k X_k = \frac{P}{R T} X_k
|
|
||||||
* \f]
|
|
||||||
*
|
|
||||||
* The standard concentration for species *k* is independent of *k* and equal to
|
|
||||||
*
|
|
||||||
* \f[
|
|
||||||
* C^s_k = C^s = \frac{P}{R T}
|
|
||||||
* \f]
|
|
||||||
*
|
|
||||||
* For example, a bulk-phase binary gas reaction between species j and k,
|
|
||||||
* producing a new gas species l would have the following equation for its rate
|
|
||||||
* of progress variable, \f$ R^1 \f$, which has units of kmol m-3 s-1.
|
|
||||||
*
|
|
||||||
* \f[
|
|
||||||
* R^1 = k^1 C_j^a C_k^a = k^1 (C^s a_j) (C^s a_k)
|
|
||||||
* \f]
|
|
||||||
* where
|
|
||||||
* \f[
|
|
||||||
* C_j^a = C^s a_j \mbox{\quad and \quad} C_k^a = C^s a_k
|
|
||||||
* \f]
|
|
||||||
*
|
|
||||||
* \f$ C_j^a \f$ is the activity concentration of species j, and \f$ C_k^a \f$
|
|
||||||
* is the activity concentration of species k. \f$ C^s \f$ is the standard
|
|
||||||
* concentration. \f$ a_j \f$ is the activity of species j which is equal to the
|
|
||||||
* mole fraction of j.
|
|
||||||
*
|
|
||||||
* The reverse rate constant can then be obtained from the law of microscopic
|
|
||||||
* reversibility and the equilibrium expression for the system.
|
|
||||||
*
|
|
||||||
* \f[
|
|
||||||
* \frac{a_j a_k}{ a_l} = K_a^{o,1} = \exp(\frac{\mu^o_l - \mu^o_j - \mu^o_k}{R T} )
|
|
||||||
* \f]
|
|
||||||
*
|
|
||||||
* \f$ K_a^{o,1} \f$ is the dimensionless form of the equilibrium constant,
|
|
||||||
* associated with the pressure dependent standard states \f$ \mu^o_l(T,P) \f$
|
|
||||||
* and their associated activities, \f$ a_l \f$, repeated here:
|
|
||||||
*
|
|
||||||
* \f[
|
|
||||||
* \mu_l(T,P) = \mu^o_l(T, P) + R T \log(a_l)
|
|
||||||
* \f]
|
|
||||||
*
|
|
||||||
* We can switch over to expressing the equilibrium constant in terms of the
|
|
||||||
* reference state chemical potentials
|
|
||||||
*
|
|
||||||
* \f[
|
|
||||||
* K_a^{o,1} = \exp(\frac{\mu^{ref}_l - \mu^{ref}_j - \mu^{ref}_k}{R T} ) * \frac{P_{ref}}{P}
|
|
||||||
* \f]
|
|
||||||
*
|
|
||||||
* The concentration equilibrium constant, \f$ K_c \f$, may be obtained by
|
|
||||||
* changing over to activity concentrations. When this is done:
|
|
||||||
*
|
|
||||||
* \f[
|
|
||||||
* \frac{C^a_j C^a_k}{ C^a_l} = C^o K_a^{o,1} = K_c^1 =
|
|
||||||
* \exp(\frac{\mu^{ref}_l - \mu^{ref}_j - \mu^{ref}_k}{R T} ) * \frac{P_{ref}}{RT}
|
|
||||||
* \f]
|
|
||||||
*
|
|
||||||
* Kinetics managers will calculate the concentration equilibrium constant, \f$
|
|
||||||
* K_c \f$, using the second and third part of the above expression as a
|
|
||||||
* definition for the concentration equilibrium constant.
|
|
||||||
*
|
|
||||||
* For completeness, the pressure equilibrium constant may be obtained as well
|
|
||||||
*
|
|
||||||
* \f[
|
|
||||||
* \frac{P_j P_k}{ P_l P_{ref}} = K_p^1 = \exp(\frac{\mu^{ref}_l - \mu^{ref}_j - \mu^{ref}_k}{R T} )
|
|
||||||
* \f]
|
|
||||||
*
|
|
||||||
* \f$ K_p \f$ is the simplest form of the equilibrium constant for ideal gases.
|
|
||||||
* However, it isn't necessarily the simplest form of the equilibrium constant
|
|
||||||
* for other types of phases; \f$ K_c \f$ is used instead because it is
|
|
||||||
* completely general.
|
|
||||||
*
|
|
||||||
* The reverse rate of progress may be written down as
|
|
||||||
* \f[
|
|
||||||
* R^{-1} = k^{-1} C_l^a = k^{-1} (C^o a_l)
|
|
||||||
* \f]
|
|
||||||
*
|
|
||||||
* where we can use the concept of microscopic reversibility to write the
|
|
||||||
* reverse rate constant in terms of the forward reate constant and the
|
|
||||||
* concentration equilibrium constant, \f$ K_c \f$.
|
|
||||||
*
|
|
||||||
* \f[
|
|
||||||
* k^{-1} = k^1 K^1_c
|
|
||||||
* \f]
|
|
||||||
*
|
|
||||||
* \f$k^{-1} \f$ has units of s-1.
|
|
||||||
*
|
|
||||||
* @ingroup thermoprops
|
|
||||||
* @deprecated To be removed after Cantera 2.4.
|
|
||||||
*/
|
|
||||||
class MixedSolventElectrolyte : public MolarityIonicVPSSTP
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
MixedSolventElectrolyte();
|
|
||||||
|
|
||||||
//! Construct and initialize a MixedSolventElectrolyte ThermoPhase object
|
|
||||||
//! directly from an XML input file
|
|
||||||
/*!
|
|
||||||
* @param inputFile Name of the input file containing the phase XML data
|
|
||||||
* to set up the object
|
|
||||||
* @param id ID of the phase in the input file. Defaults to the
|
|
||||||
* empty string.
|
|
||||||
*/
|
|
||||||
MixedSolventElectrolyte(const std::string& inputFile,
|
|
||||||
const std::string& id = "");
|
|
||||||
|
|
||||||
//! Construct and initialize a MixedSolventElectrolyte ThermoPhase object
|
|
||||||
//! directly from an XML database
|
|
||||||
/*!
|
|
||||||
* @param phaseRef XML phase node containing the description of the phase
|
|
||||||
* @param id id attribute containing the name of the phase.
|
|
||||||
* (default is the empty string)
|
|
||||||
*/
|
|
||||||
MixedSolventElectrolyte(XML_Node& phaseRef, const std::string& id = "");
|
|
||||||
|
|
||||||
virtual std::string type() const {
|
|
||||||
return "MixedSolventElectrolyte";
|
|
||||||
}
|
|
||||||
|
|
||||||
//! @name Molar Thermodynamic Properties
|
|
||||||
//! @{
|
|
||||||
|
|
||||||
virtual doublereal enthalpy_mole() const;
|
|
||||||
virtual doublereal entropy_mole() const;
|
|
||||||
virtual doublereal cp_mole() const;
|
|
||||||
virtual doublereal cv_mole() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @}
|
|
||||||
* @name Activities, Standard States, and Activity Concentrations
|
|
||||||
*
|
|
||||||
* The activity \f$a_k\f$ of a species in solution is related to the
|
|
||||||
* chemical potential by \f[ \mu_k = \mu_k^0(T) + \hat R T \log a_k. \f] The
|
|
||||||
* quantity \f$\mu_k^0(T,P)\f$ is the chemical potential at unit activity,
|
|
||||||
* which depends only on temperature and pressure.
|
|
||||||
* @{
|
|
||||||
*/
|
|
||||||
|
|
||||||
virtual void getActivityCoefficients(doublereal* ac) const;
|
|
||||||
|
|
||||||
//@}
|
|
||||||
/// @name Partial Molar Properties of the Solution
|
|
||||||
//@{
|
|
||||||
|
|
||||||
virtual void getChemPotentials(doublereal* mu) const;
|
|
||||||
virtual void getPartialMolarEnthalpies(doublereal* hbar) const;
|
|
||||||
virtual void getPartialMolarEntropies(doublereal* sbar) const;
|
|
||||||
virtual void getPartialMolarCp(doublereal* cpbar) const;
|
|
||||||
virtual void getPartialMolarVolumes(doublereal* vbar) const;
|
|
||||||
|
|
||||||
//! Get the array of temperature second derivatives of the log activity
|
|
||||||
//! coefficients
|
|
||||||
/*!
|
|
||||||
* units = 1/Kelvin
|
|
||||||
*
|
|
||||||
* @param d2lnActCoeffdT2 Output vector of temperature 2nd derivatives of
|
|
||||||
* the log Activity Coefficients. length = m_kk
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
virtual void getd2lnActCoeffdT2(doublereal* d2lnActCoeffdT2) const;
|
|
||||||
|
|
||||||
//! Get the array of temperature derivatives of the log activity coefficients
|
|
||||||
/*!
|
|
||||||
* This is a virtual function, which first appears in GibbsExcessVPSSTP.
|
|
||||||
*
|
|
||||||
* units = 1/Kelvin
|
|
||||||
*
|
|
||||||
* @param dlnActCoeffdT Output vector of temperature derivatives of the
|
|
||||||
* log Activity Coefficients. length = m_kk
|
|
||||||
*/
|
|
||||||
virtual void getdlnActCoeffdT(doublereal* dlnActCoeffdT) const;
|
|
||||||
|
|
||||||
//! @}
|
|
||||||
//! @name Initialization
|
|
||||||
/// The following methods are used in the process of constructing the phase
|
|
||||||
/// and setting its parameters from a specification in an input file. They
|
|
||||||
/// are not normally used in application programs. To see how they are used,
|
|
||||||
/// see importPhase().
|
|
||||||
/// @{
|
|
||||||
|
|
||||||
virtual void initThermo();
|
|
||||||
virtual void initThermoXML(XML_Node& phaseNode, const std::string& id);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @}
|
|
||||||
* @name Derivatives of Thermodynamic Variables needed for Applications
|
|
||||||
* @{
|
|
||||||
*/
|
|
||||||
|
|
||||||
virtual void getdlnActCoeffds(const doublereal dTds, const doublereal* const dXds, doublereal* dlnActCoeffds) const;
|
|
||||||
virtual void getdlnActCoeffdlnX_diag(doublereal* dlnActCoeffdlnX_diag) const;
|
|
||||||
virtual void getdlnActCoeffdlnN_diag(doublereal* dlnActCoeffdlnN_diag) const;
|
|
||||||
virtual void getdlnActCoeffdlnN(const size_t ld, doublereal* const dlnActCoeffdlnN);
|
|
||||||
//@}
|
|
||||||
|
|
||||||
private:
|
|
||||||
//! Process an XML node called "binaryNeutralSpeciesParameters"
|
|
||||||
/*!
|
|
||||||
* This node contains all of the parameters necessary to describe the
|
|
||||||
* Margules model for a particular binary interaction. This function reads
|
|
||||||
* the XML file and writes the coefficients it finds to an internal data
|
|
||||||
* structures.
|
|
||||||
*
|
|
||||||
* @param xmlBinarySpecies Reference to the XML_Node named
|
|
||||||
* "binaryNeutralSpeciesParameters" containing the binary interaction
|
|
||||||
*/
|
|
||||||
void readXMLBinarySpecies(XML_Node& xmlBinarySpecies);
|
|
||||||
|
|
||||||
//! Resize internal arrays within the object that depend upon the number
|
|
||||||
//! of binary Margules interaction terms
|
|
||||||
/*!
|
|
||||||
* @param num Number of binary Margules interaction terms
|
|
||||||
*/
|
|
||||||
void resizeNumInteractions(const size_t num);
|
|
||||||
|
|
||||||
//! Initialize lengths of local variables after all species have been
|
|
||||||
//! identified.
|
|
||||||
void initLengths();
|
|
||||||
|
|
||||||
//! Update the activity coefficients
|
|
||||||
/*!
|
|
||||||
* This function will be called to update the internally stored natural
|
|
||||||
* logarithm of the activity coefficients
|
|
||||||
*/
|
|
||||||
void s_update_lnActCoeff() const;
|
|
||||||
|
|
||||||
//! Update the derivative of the log of the activity coefficients wrt T
|
|
||||||
/*!
|
|
||||||
* This function will be called to update the internally stored derivative
|
|
||||||
* of the natural logarithm of the activity coefficients wrt temperature.
|
|
||||||
*/
|
|
||||||
void s_update_dlnActCoeff_dT() const;
|
|
||||||
|
|
||||||
//! Update the derivative of the log of the activity coefficients
|
|
||||||
//! wrt log(mole fraction)
|
|
||||||
/*!
|
|
||||||
* This function will be called to update the internally stored derivative
|
|
||||||
* of the natural logarithm of the activity coefficients wrt logarithm of
|
|
||||||
* the mole fractions.
|
|
||||||
*/
|
|
||||||
void s_update_dlnActCoeff_dlnX_diag() const;
|
|
||||||
|
|
||||||
//! Update the derivative of the log of the activity coefficients
|
|
||||||
//! wrt log(moles) - diagonal only
|
|
||||||
/*!
|
|
||||||
* This function will be called to update the internally stored diagonal
|
|
||||||
* entries for the derivative of the natural logarithm of the activity
|
|
||||||
* coefficients wrt logarithm of the moles.
|
|
||||||
*/
|
|
||||||
void s_update_dlnActCoeff_dlnN_diag() const;
|
|
||||||
|
|
||||||
//! Update the derivative of the log of the activity coefficients wrt log(moles_m)
|
|
||||||
/*!
|
|
||||||
* This function will be called to update the internally stored derivative
|
|
||||||
* of the natural logarithm of the activity coefficients wrt logarithm of
|
|
||||||
* the mole number of species
|
|
||||||
*/
|
|
||||||
void s_update_dlnActCoeff_dlnN() const;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
//! number of binary interaction expressions
|
|
||||||
size_t numBinaryInteractions_;
|
|
||||||
|
|
||||||
//! Enthalpy term for the binary mole fraction interaction of the excess
|
|
||||||
//! Gibbs free energy expression
|
|
||||||
mutable vector_fp m_HE_b_ij;
|
|
||||||
|
|
||||||
//! Enthalpy term for the ternary mole fraction interaction of the excess
|
|
||||||
//! Gibbs free energy expression
|
|
||||||
mutable vector_fp m_HE_c_ij;
|
|
||||||
|
|
||||||
//! Enthalpy term for the quaternary mole fraction interaction of the excess
|
|
||||||
//! Gibbs free energy expression
|
|
||||||
mutable vector_fp m_HE_d_ij;
|
|
||||||
|
|
||||||
//! Entropy term for the binary mole fraction interaction of the excess
|
|
||||||
//! Gibbs free energy expression
|
|
||||||
mutable vector_fp m_SE_b_ij;
|
|
||||||
|
|
||||||
//! Entropy term for the ternary mole fraction interaction of the excess
|
|
||||||
//! Gibbs free energy expression
|
|
||||||
mutable vector_fp m_SE_c_ij;
|
|
||||||
|
|
||||||
//! Entropy term for the quaternary mole fraction interaction of the excess
|
|
||||||
//! Gibbs free energy expression
|
|
||||||
mutable vector_fp m_SE_d_ij;
|
|
||||||
|
|
||||||
//! Enthalpy term for the binary mole fraction interaction of the excess
|
|
||||||
//! Gibbs free energy expression
|
|
||||||
mutable vector_fp m_VHE_b_ij;
|
|
||||||
|
|
||||||
//! Enthalpy term for the ternary mole fraction interaction of the excess
|
|
||||||
//! Gibbs free energy expression
|
|
||||||
mutable vector_fp m_VHE_c_ij;
|
|
||||||
|
|
||||||
//! Enthalpy term for the quaternary mole fraction interaction of the excess
|
|
||||||
//! Gibbs free energy expression
|
|
||||||
mutable vector_fp m_VHE_d_ij;
|
|
||||||
|
|
||||||
//! Entropy term for the binary mole fraction interaction of the excess
|
|
||||||
//! Gibbs free energy expression
|
|
||||||
mutable vector_fp m_VSE_b_ij;
|
|
||||||
|
|
||||||
//! Entropy term for the ternary mole fraction interaction of the excess
|
|
||||||
//! Gibbs free energy expression
|
|
||||||
mutable vector_fp m_VSE_c_ij;
|
|
||||||
|
|
||||||
//! Entropy term for the quaternary mole fraction interaction of the excess
|
|
||||||
//! Gibbs free energy expression
|
|
||||||
mutable vector_fp m_VSE_d_ij;
|
|
||||||
|
|
||||||
//! vector of species indices representing species A in the interaction
|
|
||||||
/*!
|
|
||||||
* Each Margules excess Gibbs free energy term involves two species, A and
|
|
||||||
* B. This vector identifies species A.
|
|
||||||
*/
|
|
||||||
std::vector<size_t> m_pSpecies_A_ij;
|
|
||||||
|
|
||||||
//! vector of species indices representing species B in the interaction
|
|
||||||
/*!
|
|
||||||
* Each Margules excess Gibbs free energy term involves two species, A and
|
|
||||||
* B. This vector identifies species B.
|
|
||||||
*/
|
|
||||||
std::vector<size_t> m_pSpecies_B_ij;
|
|
||||||
|
|
||||||
//! form of the Margules interaction expression
|
|
||||||
/*!
|
|
||||||
* Currently there is only one form.
|
|
||||||
*/
|
|
||||||
int formMargules_;
|
|
||||||
|
|
||||||
//! form of the temperature dependence of the Margules interaction expression
|
|
||||||
/*!
|
|
||||||
* Currently there is only one form -> constant wrt temperature.
|
|
||||||
*/
|
|
||||||
int formTempModel_;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -218,23 +218,6 @@ public:
|
||||||
//! @name Utilities for Solvent ID and Molality
|
//! @name Utilities for Solvent ID and Molality
|
||||||
//! @{
|
//! @{
|
||||||
|
|
||||||
/**
|
|
||||||
* This routine sets the index number of the solvent for the phase.
|
|
||||||
*
|
|
||||||
* Note, having a solvent is a precursor to many things having to do with
|
|
||||||
* molality.
|
|
||||||
*
|
|
||||||
* @param k the solvent index number
|
|
||||||
* @deprecated The solvent is always the first species in the phase. To be
|
|
||||||
* removed after Cantera 2.4.
|
|
||||||
*/
|
|
||||||
void setSolvent(size_t k);
|
|
||||||
|
|
||||||
//! Returns the solvent index.
|
|
||||||
//! @deprecated The solvent is always the first species in the phase. To be
|
|
||||||
//! removed after Cantera 2.4.
|
|
||||||
size_t solventIndex() const;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the minimum mole fraction in the molality formulation. Note the
|
* Sets the minimum mole fraction in the molality formulation. Note the
|
||||||
* molality formulation is singular in the limit that the solvent mole
|
* molality formulation is singular in the limit that the solvent mole
|
||||||
|
|
|
||||||
|
|
@ -1,262 +0,0 @@
|
||||||
/**
|
|
||||||
* @file MolarityIonicVPSSTP.h (see \ref thermoprops and class \link
|
|
||||||
* Cantera::MolarityIonicVPSSTP MolarityIonicVPSSTP\endlink).
|
|
||||||
*
|
|
||||||
* Header file for a derived class of ThermoPhase that handles variable pressure
|
|
||||||
* standard state methods for calculating thermodynamic properties that are
|
|
||||||
* further based upon activities based on the molarity scale. In this class, we
|
|
||||||
* expect that there are ions, but they are treated on the molarity scale.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// This file is part of Cantera. See License.txt in the top-level directory or
|
|
||||||
// at http://www.cantera.org/license.txt for license and copyright information.
|
|
||||||
|
|
||||||
#ifndef CT_MOLARITYIONICVPSSTP_H
|
|
||||||
#define CT_MOLARITYIONICVPSSTP_H
|
|
||||||
|
|
||||||
#include "GibbsExcessVPSSTP.h"
|
|
||||||
|
|
||||||
namespace Cantera
|
|
||||||
{
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* MolarityIonicVPSSTP is a derived class of GibbsExcessVPSSTP that handles
|
|
||||||
* variable pressure standard state methods for calculating thermodynamic
|
|
||||||
* properties that are further based on expressing the Excess Gibbs free energy
|
|
||||||
* as a function of the mole fractions (or pseudo mole fractions) of the
|
|
||||||
* constituents. This category is the workhorse for describing ionic systems
|
|
||||||
* which are not on the molality scale.
|
|
||||||
*
|
|
||||||
* @attention This class currently does not have any test cases or examples. Its
|
|
||||||
* implementation may be incomplete, and future changes to Cantera may
|
|
||||||
* unexpectedly cause this class to stop working. If you use this class,
|
|
||||||
* please consider contributing examples or test cases. In the absence of
|
|
||||||
* new tests or examples, this class may be deprecated and removed in a
|
|
||||||
* future version of Cantera. See
|
|
||||||
* https://github.com/Cantera/cantera/issues/267 for additional information.
|
|
||||||
*
|
|
||||||
* @deprecated To be removed after Cantera 2.4
|
|
||||||
*
|
|
||||||
* This class adds additional functions onto the ThermoPhase interface that
|
|
||||||
* handles the calculation of the excess Gibbs free energy. The ThermoPhase
|
|
||||||
* class includes a member function, ThermoPhase::activityConvention() that
|
|
||||||
* indicates which convention the activities are based on. The default is to
|
|
||||||
* assume activities are based on the molar convention. That default is used
|
|
||||||
* here.
|
|
||||||
*
|
|
||||||
* All of the Excess Gibbs free energy formulations in this area employ
|
|
||||||
* symmetrical formulations.
|
|
||||||
*
|
|
||||||
* This layer will massage the mole fraction vector to implement cation and
|
|
||||||
* anion based mole numbers in an optional manner, such that it is expected that
|
|
||||||
* there exists a charge balance at all times. One of the ions must be a
|
|
||||||
* "special ion" in the sense that its' thermodynamic functions are set to zero,
|
|
||||||
* and the thermo functions of all other ions are based on a valuation relative
|
|
||||||
* to that special ion.
|
|
||||||
*/
|
|
||||||
class MolarityIonicVPSSTP : public GibbsExcessVPSSTP
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
MolarityIonicVPSSTP();
|
|
||||||
|
|
||||||
//! Construct and initialize a MolarityIonicVPSSTP ThermoPhase object
|
|
||||||
//! directly from an XML input file
|
|
||||||
/*!
|
|
||||||
* @param inputFile Name of the input file containing the phase XML data
|
|
||||||
* to set up the object
|
|
||||||
* @param id ID of the phase in the input file. Defaults to the
|
|
||||||
* empty string.
|
|
||||||
*/
|
|
||||||
MolarityIonicVPSSTP(const std::string& inputFile, const std::string& id = "");
|
|
||||||
|
|
||||||
//! Construct and initialize a MolarityIonicVPSSTP ThermoPhase object
|
|
||||||
//! directly from an XML database
|
|
||||||
/*!
|
|
||||||
* @param phaseRef XML phase node containing the description of the phase
|
|
||||||
* @param id id attribute containing the name of the phase.
|
|
||||||
* (default is the empty string)
|
|
||||||
*/
|
|
||||||
MolarityIonicVPSSTP(XML_Node& phaseRef, const std::string& id = "");
|
|
||||||
|
|
||||||
virtual std::string type() const {
|
|
||||||
return "MolarityIonic";
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @name Activities, Standard States, and Activity Concentrations
|
|
||||||
*
|
|
||||||
* The activity \f$a_k\f$ of a species in solution is
|
|
||||||
* related to the chemical potential by \f[ \mu_k = \mu_k^0(T)
|
|
||||||
* + \hat R T \log a_k. \f] The quantity \f$\mu_k^0(T,P)\f$ is
|
|
||||||
* the chemical potential at unit activity, which depends only
|
|
||||||
* on temperature and pressure.
|
|
||||||
* @{
|
|
||||||
*/
|
|
||||||
|
|
||||||
virtual void getLnActivityCoefficients(doublereal* lnac) const;
|
|
||||||
|
|
||||||
//@}
|
|
||||||
/// @name Partial Molar Properties of the Solution
|
|
||||||
//@{
|
|
||||||
|
|
||||||
virtual void getChemPotentials(doublereal* mu) const;
|
|
||||||
|
|
||||||
//! Returns an array of partial molar enthalpies for the species
|
|
||||||
//! in the mixture.
|
|
||||||
/*!
|
|
||||||
* Units (J/kmol)
|
|
||||||
*
|
|
||||||
* For this phase, the partial molar enthalpies are equal to the standard
|
|
||||||
* state enthalpies modified by the derivative of the molality-based
|
|
||||||
* activity coefficient wrt temperature
|
|
||||||
*
|
|
||||||
* \f[
|
|
||||||
* \bar h_k(T,P) = h^o_k(T,P) - R T^2 \frac{d \ln(\gamma_k)}{dT}
|
|
||||||
* \f]
|
|
||||||
*
|
|
||||||
* @param hbar Vector of returned partial molar enthalpies
|
|
||||||
* (length m_kk, units = J/kmol)
|
|
||||||
*/
|
|
||||||
virtual void getPartialMolarEnthalpies(doublereal* hbar) const;
|
|
||||||
|
|
||||||
//! Returns an array of partial molar entropies for the species in the
|
|
||||||
//! mixture.
|
|
||||||
/*!
|
|
||||||
* Units (J/kmol)
|
|
||||||
*
|
|
||||||
* For this phase, the partial molar enthalpies are equal to the standard
|
|
||||||
* state enthalpies modified by the derivative of the activity coefficient
|
|
||||||
* wrt temperature
|
|
||||||
*
|
|
||||||
* \f[
|
|
||||||
* \bar s_k(T,P) = s^o_k(T,P) - R T^2 \frac{d \ln(\gamma_k)}{dT}
|
|
||||||
* - R \ln( \gamma_k X_k)
|
|
||||||
* - R T \frac{d \ln(\gamma_k) }{dT}
|
|
||||||
* \f]
|
|
||||||
*
|
|
||||||
* @param sbar Vector of returned partial molar entropies
|
|
||||||
* (length m_kk, units = J/kmol/K)
|
|
||||||
*/
|
|
||||||
virtual void getPartialMolarEntropies(doublereal* sbar) const;
|
|
||||||
|
|
||||||
//! Returns an array of partial molar entropies for the species
|
|
||||||
//! in the mixture.
|
|
||||||
/*!
|
|
||||||
* Units (J/kmol)
|
|
||||||
*
|
|
||||||
* For this phase, the partial molar enthalpies are equal to the standard
|
|
||||||
* state enthalpies modified by the derivative of the activity coefficient
|
|
||||||
* wrt temperature
|
|
||||||
*
|
|
||||||
* \f[
|
|
||||||
* ???????????????
|
|
||||||
* \bar s_k(T,P) = s^o_k(T,P) - R T^2 \frac{d \ln(\gamma_k)}{dT}
|
|
||||||
* - R \ln( \gamma_k X_k)
|
|
||||||
* - R T \frac{d \ln(\gamma_k) }{dT}
|
|
||||||
* ???????????????
|
|
||||||
* \f]
|
|
||||||
*
|
|
||||||
* @param cpbar Vector of returned partial molar heat capacities
|
|
||||||
* (length m_kk, units = J/kmol/K)
|
|
||||||
*/
|
|
||||||
virtual void getPartialMolarCp(doublereal* cpbar) const;
|
|
||||||
|
|
||||||
virtual void getPartialMolarVolumes(doublereal* vbar) const;
|
|
||||||
|
|
||||||
//@}
|
|
||||||
|
|
||||||
//! Calculate pseudo binary mole fractions
|
|
||||||
virtual void calcPseudoBinaryMoleFractions() const;
|
|
||||||
|
|
||||||
/// @name Initialization
|
|
||||||
/// The following methods are used in the process of constructing
|
|
||||||
/// the phase and setting its parameters from a specification in an
|
|
||||||
/// input file. They are not normally used in application programs.
|
|
||||||
/// To see how they are used, see importPhase().
|
|
||||||
/// @{
|
|
||||||
|
|
||||||
virtual void initThermo();
|
|
||||||
virtual void initThermoXML(XML_Node& phaseNode, const std::string& id);
|
|
||||||
//! @}
|
|
||||||
|
|
||||||
virtual std::string report(bool show_thermo=true,
|
|
||||||
doublereal threshold=1e-14) const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
//! Initialize lengths of local variables after all species have been
|
|
||||||
//! identified.
|
|
||||||
void initLengths();
|
|
||||||
|
|
||||||
//! Process an XML node called "binaryNeutralSpeciesParameters"
|
|
||||||
/*!
|
|
||||||
* This node contains all of the parameters necessary to describe the
|
|
||||||
* Redlich-Kister model for a particular binary interaction. This function
|
|
||||||
* reads the XML file and writes the coefficients it finds to an internal
|
|
||||||
* data structures.
|
|
||||||
*
|
|
||||||
* @param xmlBinarySpecies Reference to the XML_Node named
|
|
||||||
* "binaryNeutralSpeciesParameters" containing the binary interaction
|
|
||||||
*/
|
|
||||||
void readXMLBinarySpecies(XML_Node& xmlBinarySpecies);
|
|
||||||
|
|
||||||
//! Update the activity coefficients
|
|
||||||
/*!
|
|
||||||
* This function will be called to update the internally stored natural
|
|
||||||
* logarithm of the activity coefficients
|
|
||||||
*/
|
|
||||||
void s_update_lnActCoeff() const;
|
|
||||||
|
|
||||||
//! Update the derivative of the log of the activity coefficients wrt T
|
|
||||||
/*!
|
|
||||||
* This function will be called to update the internally stored derivative
|
|
||||||
* of the natural logarithm of the activity coefficients wrt temperature.
|
|
||||||
*/
|
|
||||||
void s_update_dlnActCoeff_dT() const;
|
|
||||||
|
|
||||||
//! Internal routine that calculates the derivative of the activity
|
|
||||||
//! coefficients wrt the mole fractions.
|
|
||||||
/*!
|
|
||||||
* This routine calculates the the derivative of the activity coefficients
|
|
||||||
* wrt to mole fraction with all other mole fractions held constant. This is
|
|
||||||
* strictly not permitted. However, if the resulting matrix is multiplied by
|
|
||||||
* a permissible deltaX vector then everything is ok.
|
|
||||||
*
|
|
||||||
* This is the natural way to handle concentration derivatives in this
|
|
||||||
* routine.
|
|
||||||
*/
|
|
||||||
void s_update_dlnActCoeff_dX_() const;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
// Pseudobinary type
|
|
||||||
/*!
|
|
||||||
* - `PBTYPE_PASSTHROUGH` - All species are passthrough species
|
|
||||||
* - `PBTYPE_SINGLEANION` - there is only one anion in the mixture
|
|
||||||
* - `PBTYPE_SINGLECATION` - there is only one cation in the mixture
|
|
||||||
* - `PBTYPE_MULTICATIONANION` - Complex mixture
|
|
||||||
*/
|
|
||||||
int PBType_;
|
|
||||||
|
|
||||||
//! Number of pseudo binary species
|
|
||||||
size_t numPBSpecies_;
|
|
||||||
|
|
||||||
mutable vector_fp PBMoleFractions_;
|
|
||||||
|
|
||||||
//! Vector of cation indices in the mixture
|
|
||||||
std::vector<size_t> cationList_;
|
|
||||||
|
|
||||||
std::vector<size_t> anionList_;
|
|
||||||
|
|
||||||
std::vector<size_t> passThroughList_;
|
|
||||||
size_t neutralPBindexStart;
|
|
||||||
|
|
||||||
mutable vector_fp moleFractionsTmp_;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define PBTYPE_PASSTHROUGH 0
|
|
||||||
#define PBTYPE_SINGLEANION 1
|
|
||||||
#define PBTYPE_SINGLECATION 2
|
|
||||||
#define PBTYPE_MULTICATIONANION 3
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -72,20 +72,6 @@ public:
|
||||||
virtual void modifySpecies(size_t index,
|
virtual void modifySpecies(size_t index,
|
||||||
shared_ptr<SpeciesThermoInterpType> spec);
|
shared_ptr<SpeciesThermoInterpType> spec);
|
||||||
|
|
||||||
//! Like update(), but only updates the single species k.
|
|
||||||
/*!
|
|
||||||
* @param k species index
|
|
||||||
* @param T Temperature (Kelvin)
|
|
||||||
* @param cp_R Vector of Dimensionless heat capacities. (length m_kk).
|
|
||||||
* @param h_RT Vector of Dimensionless enthalpies. (length m_kk).
|
|
||||||
* @param s_R Vector of Dimensionless entropies. (length m_kk).
|
|
||||||
* @deprecated Use update_single() instead.
|
|
||||||
* To be removed after Cantera 2.4.
|
|
||||||
*/
|
|
||||||
virtual void update_one(size_t k, doublereal T, doublereal* cp_R,
|
|
||||||
doublereal* h_RT,
|
|
||||||
doublereal* s_R) const;
|
|
||||||
|
|
||||||
//! Like update_one, but without applying offsets to the output pointers
|
//! Like update_one, but without applying offsets to the output pointers
|
||||||
/*!
|
/*!
|
||||||
* @param k species index
|
* @param k species index
|
||||||
|
|
|
||||||
|
|
@ -406,15 +406,6 @@ public:
|
||||||
//! units = kg / kmol
|
//! units = kg / kmol
|
||||||
const vector_fp& molecularWeights() const;
|
const vector_fp& molecularWeights() const;
|
||||||
|
|
||||||
//! @deprecated To be removed after Cantera 2.4
|
|
||||||
//! @see SurfPhase::size
|
|
||||||
virtual double size(size_t k) const {
|
|
||||||
warn_deprecated("Phase::size", "Unused except for SurfPhase. "
|
|
||||||
"To be removed from class Phase after Cantera 2.4. "
|
|
||||||
"Cast object as SurfPhase to resolve this warning.");
|
|
||||||
return 1.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @name Composition
|
/// @name Composition
|
||||||
//@{
|
//@{
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,624 +0,0 @@
|
||||||
/**
|
|
||||||
* @file PhaseCombo_Interaction.h
|
|
||||||
* Header for intermediate ThermoPhase object for phases which
|
|
||||||
* employ the Margules Gibbs free energy formulation and eliminates the ideal mixing term.
|
|
||||||
* (see \ref thermoprops
|
|
||||||
* and class \link Cantera::PhaseCombo_Interaction PhaseCombo_Interaction\endlink).
|
|
||||||
*/
|
|
||||||
|
|
||||||
// This file is part of Cantera. See License.txt in the top-level directory or
|
|
||||||
// at http://www.cantera.org/license.txt for license and copyright information.
|
|
||||||
|
|
||||||
#ifndef CT_PHASECOMBO_INTERACTION_H
|
|
||||||
#define CT_PHASECOMBO_INTERACTION_H
|
|
||||||
|
|
||||||
#include "GibbsExcessVPSSTP.h"
|
|
||||||
|
|
||||||
namespace Cantera
|
|
||||||
{
|
|
||||||
|
|
||||||
//! PhaseCombo_Interaction is a derived class of GibbsExcessVPSSTP that employs
|
|
||||||
//! the Margules approximation for the excess Gibbs free energy while
|
|
||||||
//! eliminating the entropy of mixing term.
|
|
||||||
/*!
|
|
||||||
* @attention This class currently does not have any test cases or examples. Its
|
|
||||||
* implementation may be incomplete, and future changes to Cantera may
|
|
||||||
* unexpectedly cause this class to stop working. If you use this class,
|
|
||||||
* please consider contributing examples or test cases. In the absence of
|
|
||||||
* new tests or examples, this class may be deprecated and removed in a
|
|
||||||
* future version of Cantera. See
|
|
||||||
* https://github.com/Cantera/cantera/issues/267 for additional information.
|
|
||||||
*
|
|
||||||
* @deprecated To be removed after Cantera 2.4
|
|
||||||
*
|
|
||||||
* PhaseCombo_Interaction derives from class GibbsExcessVPSSTP which is derived
|
|
||||||
* from VPStandardStateTP, and overloads the virtual methods defined there with
|
|
||||||
* ones that use expressions appropriate for the Margules Excess Gibbs free
|
|
||||||
* energy approximation. The reader should refer to the MargulesVPSSTP class for
|
|
||||||
* information on that class. This class in addition adds a term to the activity
|
|
||||||
* coefficient that eliminates the ideal solution mixing term within the
|
|
||||||
* chemical potential. This is a very radical thing to do, but it is supported
|
|
||||||
* by experimental evidence under some conditions.
|
|
||||||
*
|
|
||||||
* The independent unknowns are pressure, temperature, and mass fraction.
|
|
||||||
*
|
|
||||||
* This class is introduced to represent specific conditions observed in thermal
|
|
||||||
* batteries. HOwever, it may be physically motivated to represent conditions
|
|
||||||
* where there may be a mixture of compounds that are not "mixed" at the
|
|
||||||
* molecular level. Therefore, there is no mixing term.
|
|
||||||
*
|
|
||||||
* The lack of a mixing term has profound effects. First, the mole fraction of a
|
|
||||||
* species can now be identically zero due to thermodynamic considerations. The
|
|
||||||
* phase behaves more like a series of phases. That's why we named it
|
|
||||||
* PhaseCombo.
|
|
||||||
*
|
|
||||||
* ## Specification of Species Standard State Properties
|
|
||||||
*
|
|
||||||
* All species are defined to have standard states that depend upon both the
|
|
||||||
* temperature and the pressure. The Margules approximation assumes symmetric
|
|
||||||
* standard states, where all of the standard state assume that the species are
|
|
||||||
* in pure component states at the temperature and pressure of the solution. I
|
|
||||||
* don't think it prevents, however, some species from being dilute in the
|
|
||||||
* solution.
|
|
||||||
*
|
|
||||||
* ## Specification of Solution Thermodynamic Properties
|
|
||||||
*
|
|
||||||
* The molar excess Gibbs free energy is given by the following formula which is
|
|
||||||
* a sum over interactions *i*. Each of the interactions are binary interactions
|
|
||||||
* involving two of the species in the phase, denoted, *Ai* and *Bi*. This is
|
|
||||||
* the generalization of the Margules formulation for a phase that has more than
|
|
||||||
* 2 species. The second term in the excess Gibbs free energy is a negation of
|
|
||||||
* the ideal solution's mixing term.
|
|
||||||
*
|
|
||||||
* \f[
|
|
||||||
* G^E = \sum_i \left( H_{Ei} - T S_{Ei} \right) - \sum_i \left( n_i R T \ln{X_i} \right)
|
|
||||||
* \f]
|
|
||||||
* \f[
|
|
||||||
* H^E_i = n X_{Ai} X_{Bi} \left( h_{o,i} + h_{1,i} X_{Bi} \right)
|
|
||||||
* \f]
|
|
||||||
* \f[
|
|
||||||
* S^E_i = n X_{Ai} X_{Bi} \left( s_{o,i} + s_{1,i} X_{Bi} \right)
|
|
||||||
* \f]
|
|
||||||
*
|
|
||||||
* where n is the total moles in the solution. The activity of a species defined
|
|
||||||
* in the phase is given by an excess Gibbs free energy formulation.
|
|
||||||
*
|
|
||||||
* \f[
|
|
||||||
* a_k = \gamma_k X_k
|
|
||||||
* \f]
|
|
||||||
*
|
|
||||||
* where
|
|
||||||
*
|
|
||||||
* \f[
|
|
||||||
* R T \ln( \gamma_k )= \frac{d(n G^E)}{d(n_k)}\Bigg|_{n_i}
|
|
||||||
* \f]
|
|
||||||
*
|
|
||||||
* Taking the derivatives results in the following expression
|
|
||||||
*
|
|
||||||
* \f[
|
|
||||||
* R T \ln( \gamma_k )= \sum_i \left( \left( \delta_{Ai,k} X_{Bi} + \delta_{Bi,k} X_{Ai} - X_{Ai} X_{Bi} \right)
|
|
||||||
* \left( g^E_{o,i} + g^E_{1,i} X_{Bi} \right) +
|
|
||||||
* \left( \delta_{Bi,k} - X_{Bi} \right) X_{Ai} X_{Bi} g^E_{1,i} \right) - RT \ln{X_k}
|
|
||||||
* \f]
|
|
||||||
*
|
|
||||||
* where \f$ g^E_{o,i} = h_{o,i} - T s_{o,i} \f$ and
|
|
||||||
* \f$ g^E_{1,i} = h_{1,i} - T s_{1,i} \f$ and where \f$ X_k \f$ is the mole
|
|
||||||
* fraction of species *k*.
|
|
||||||
*
|
|
||||||
* This object inherits from the class VPStandardStateTP. Therefore, the
|
|
||||||
* specification and calculation of all standard state and reference state
|
|
||||||
* values are handled at that level. Various functional forms for the standard
|
|
||||||
* state are permissible. The chemical potential for species *k* is equal to
|
|
||||||
*
|
|
||||||
* \f[
|
|
||||||
* \mu_k(T,P) = \mu^o_k(T, P) + R T \ln(\gamma_k X_k)
|
|
||||||
* \f]
|
|
||||||
*
|
|
||||||
* The partial molar entropy for species *k* is given by the following relation,
|
|
||||||
*
|
|
||||||
* \f[
|
|
||||||
* \tilde{s}_k(T,P) = s^o_k(T,P) - R \ln( \gamma_k X_k )
|
|
||||||
* - R T \frac{d \ln(\gamma_k) }{dT}
|
|
||||||
* \f]
|
|
||||||
*
|
|
||||||
* The partial molar enthalpy for species *k* is given by
|
|
||||||
*
|
|
||||||
* \f[
|
|
||||||
* \tilde{h}_k(T,P) = h^o_k(T,P) - R T^2 \frac{d \ln(\gamma_k)}{dT}
|
|
||||||
* \f]
|
|
||||||
*
|
|
||||||
* The partial molar volume for species *k* is
|
|
||||||
*
|
|
||||||
* \f[
|
|
||||||
* \tilde V_k(T,P) = V^o_k(T,P) + R T \frac{d \ln(\gamma_k) }{dP}
|
|
||||||
* \f]
|
|
||||||
*
|
|
||||||
* The partial molar Heat Capacity for species *k* is
|
|
||||||
*
|
|
||||||
* \f[
|
|
||||||
* \tilde{C}_{p,k}(T,P) = C^o_{p,k}(T,P) - 2 R T \frac{d \ln( \gamma_k )}{dT}
|
|
||||||
* - R T^2 \frac{d^2 \ln(\gamma_k) }{{dT}^2}
|
|
||||||
* \f]
|
|
||||||
*
|
|
||||||
* ## %Application within Kinetics Managers
|
|
||||||
*
|
|
||||||
* \f$ C^a_k\f$ are defined such that \f$ a_k = C^a_k / C^s_k, \f$ where
|
|
||||||
* \f$ C^s_k \f$ is a standard concentration defined below and \f$ a_k \f$ are
|
|
||||||
* activities used in the thermodynamic functions. These activity (or
|
|
||||||
* generalized) concentrations are used by kinetics manager classes to compute
|
|
||||||
* the forward and reverse rates of elementary reactions. The activity
|
|
||||||
* concentration,\f$ C^a_k \f$,is given by the following expression.
|
|
||||||
*
|
|
||||||
* \f[
|
|
||||||
* C^a_k = C^s_k X_k = \frac{P}{R T} X_k
|
|
||||||
* \f]
|
|
||||||
*
|
|
||||||
* The standard concentration for species *k* is independent of *k* and equal to
|
|
||||||
*
|
|
||||||
* \f[
|
|
||||||
* C^s_k = C^s = \frac{P}{R T}
|
|
||||||
* \f]
|
|
||||||
*
|
|
||||||
* For example, a bulk-phase binary gas reaction between species j and k,
|
|
||||||
* producing a new gas species l would have the following equation for its rate
|
|
||||||
* of progress variable, \f$ R^1 \f$, which has units of kmol m-3 s-1.
|
|
||||||
*
|
|
||||||
* \f[
|
|
||||||
* R^1 = k^1 C_j^a C_k^a = k^1 (C^s a_j) (C^s a_k)
|
|
||||||
* \f]
|
|
||||||
*
|
|
||||||
* where
|
|
||||||
*
|
|
||||||
* \f[
|
|
||||||
* C_j^a = C^s a_j \mbox{\quad and \quad} C_k^a = C^s a_k
|
|
||||||
* \f]
|
|
||||||
*
|
|
||||||
* \f$ C_j^a \f$ is the activity concentration of species j, and \f$ C_k^a \f$
|
|
||||||
* is the activity concentration of species k. \f$ C^s \f$ is the standard
|
|
||||||
* concentration. \f$ a_j \f$ is the activity of species j which is equal to the
|
|
||||||
* mole fraction of j.
|
|
||||||
*
|
|
||||||
* The reverse rate constant can then be obtained from the law of microscopic
|
|
||||||
* reversibility and the equilibrium expression for the system.
|
|
||||||
*
|
|
||||||
* \f[
|
|
||||||
* \frac{a_j a_k}{ a_l} = K_a^{o,1} = \exp(\frac{\mu^o_l - \mu^o_j - \mu^o_k}{R T} )
|
|
||||||
* \f]
|
|
||||||
*
|
|
||||||
* \f$ K_a^{o,1} \f$ is the dimensionless form of the equilibrium constant,
|
|
||||||
* associated with the pressure dependent standard states \f$ \mu^o_l(T,P) \f$
|
|
||||||
* and their associated activities, \f$ a_l \f$, repeated here:
|
|
||||||
*
|
|
||||||
* \f[
|
|
||||||
* \mu_l(T,P) = \mu^o_l(T, P) + R T \log(a_l)
|
|
||||||
* \f]
|
|
||||||
*
|
|
||||||
* We can switch over to expressing the equilibrium constant in terms of the
|
|
||||||
* reference state chemical potentials
|
|
||||||
*
|
|
||||||
* \f[
|
|
||||||
* K_a^{o,1} = \exp(\frac{\mu^{ref}_l - \mu^{ref}_j - \mu^{ref}_k}{R T} ) * \frac{P_{ref}}{P}
|
|
||||||
* \f]
|
|
||||||
*
|
|
||||||
* The concentration equilibrium constant, \f$ K_c \f$, may be obtained by
|
|
||||||
* changing over to activity concentrations. When this is done:
|
|
||||||
*
|
|
||||||
* \f[
|
|
||||||
* \frac{C^a_j C^a_k}{ C^a_l} = C^o K_a^{o,1} = K_c^1 =
|
|
||||||
* \exp(\frac{\mu^{ref}_l - \mu^{ref}_j - \mu^{ref}_k}{R T} ) * \frac{P_{ref}}{RT}
|
|
||||||
* \f]
|
|
||||||
*
|
|
||||||
* Kinetics managers will calculate the concentration equilibrium constant,
|
|
||||||
* \f$ K_c \f$, using the second and third part of the above expression as a
|
|
||||||
* definition for the concentration equilibrium constant.
|
|
||||||
*
|
|
||||||
* For completeness, the pressure equilibrium constant may be obtained as well
|
|
||||||
*
|
|
||||||
* \f[
|
|
||||||
* \frac{P_j P_k}{ P_l P_{ref}} = K_p^1 = \exp(\frac{\mu^{ref}_l - \mu^{ref}_j - \mu^{ref}_k}{R T} )
|
|
||||||
* \f]
|
|
||||||
*
|
|
||||||
* \f$ K_p \f$ is the simplest form of the equilibrium constant for ideal gases.
|
|
||||||
* However, it isn't necessarily the simplest form of the equilibrium constant
|
|
||||||
* for other types of phases; \f$ K_c \f$ is used instead because it is
|
|
||||||
* completely general.
|
|
||||||
*
|
|
||||||
* The reverse rate of progress may be written down as
|
|
||||||
* \f[
|
|
||||||
* R^{-1} = k^{-1} C_l^a = k^{-1} (C^o a_l)
|
|
||||||
* \f]
|
|
||||||
*
|
|
||||||
* where we can use the concept of microscopic reversibility to write the
|
|
||||||
* reverse rate constant in terms of the forward reate constant and the
|
|
||||||
* concentration equilibrium constant, \f$ K_c \f$.
|
|
||||||
*
|
|
||||||
* \f[
|
|
||||||
* k^{-1} = k^1 K^1_c
|
|
||||||
* \f]
|
|
||||||
*
|
|
||||||
* \f$k^{-1} \f$ has units of s-1.
|
|
||||||
*
|
|
||||||
* ## Instantiation of the Class
|
|
||||||
*
|
|
||||||
* The constructor for this phase is located in the default ThermoFactory for
|
|
||||||
* %Cantera. A new PhaseCombo_Interaction object may be created by the following
|
|
||||||
* code snippet:
|
|
||||||
*
|
|
||||||
* @code
|
|
||||||
* XML_Node *xc = get_XML_File("LiFeS_X_combo.xml");
|
|
||||||
* XML_Node * const xs = xc->findNameID("phase", "LiFeS_X");
|
|
||||||
* ThermoPhase *l_tp = newPhase(*xs);
|
|
||||||
* PhaseCombo_Interaction *LiFeS_X_solid = dynamic_cast <PhaseCombo_Interaction *>(l_tp);
|
|
||||||
* @endcode
|
|
||||||
*
|
|
||||||
* or by the following code
|
|
||||||
*
|
|
||||||
* @code
|
|
||||||
* std::string id = "LiFeS_X";
|
|
||||||
* Cantera::ThermoPhase *LiFeS_X_Phase = Cantera::newPhase("LiFeS_X_combo.xml", id);
|
|
||||||
* PhaseCombo_Interaction *LiFeS_X_solid = dynamic_cast <PhaseCombo_Interaction *>(l_tp);
|
|
||||||
* @endcode
|
|
||||||
*
|
|
||||||
* or by the following constructor:
|
|
||||||
*
|
|
||||||
* @code
|
|
||||||
* XML_Node *xc = get_XML_File("LiFeS_X_combo.xml");
|
|
||||||
* XML_Node * const xs = xc->findNameID("phase", "LiFeS_X");
|
|
||||||
* PhaseCombo_Interaction *LiFeS_X_solid = new PhaseCombo_Interaction(*xs);
|
|
||||||
* @endcode
|
|
||||||
*
|
|
||||||
* ## XML Example
|
|
||||||
*
|
|
||||||
* An example of an XML Element named phase setting up a PhaseCombo_Interaction
|
|
||||||
* object named LiFeS_X is given below.
|
|
||||||
*
|
|
||||||
* @code
|
|
||||||
* <phase dim="3" id="LiFeS_X">
|
|
||||||
* <elementArray datasrc="elements.xml">
|
|
||||||
* Li Fe S
|
|
||||||
* </elementArray>
|
|
||||||
* <speciesArray datasrc="#species_LiFeS">
|
|
||||||
* LiTFe1S2(S) Li2Fe1S2(S)
|
|
||||||
* </speciesArray>
|
|
||||||
* <thermo model="PhaseCombo_Interaction">
|
|
||||||
* <activityCoefficients model="Margules" TempModel="constant">
|
|
||||||
* <binaryNeutralSpeciesParameters speciesA="LiTFe1S2(S)" speciesB="Li2Fe1S2(S)">
|
|
||||||
* <excessEnthalpy model="poly_Xb" terms="2" units="kJ/mol">
|
|
||||||
* 84.67069219, -269.1959421
|
|
||||||
* </excessEnthalpy>
|
|
||||||
* <excessEntropy model="poly_Xb" terms="2" units="J/mol/K">
|
|
||||||
* 100.7511565, -361.4222659
|
|
||||||
* </excessEntropy>
|
|
||||||
* <excessVolume_Enthalpy model="poly_Xb" terms="2" units="ml/mol">
|
|
||||||
* 0, 0
|
|
||||||
* </excessVolume_Enthalpy>
|
|
||||||
* <excessVolume_Entropy model="poly_Xb" terms="2" units="ml/mol/K">
|
|
||||||
* 0, 0
|
|
||||||
* </excessVolume_Entropy>
|
|
||||||
* </binaryNeutralSpeciesParameters>
|
|
||||||
* </activityCoefficients>
|
|
||||||
* </thermo>
|
|
||||||
* <transport model="none"/>
|
|
||||||
* <kinetics model="none"/>
|
|
||||||
* </phase>
|
|
||||||
* @endcode
|
|
||||||
*
|
|
||||||
* The model attribute "PhaseCombo_Interaction" of the thermo XML element
|
|
||||||
* identifies the phase as being of the type handled by the
|
|
||||||
* PhaseCombo_Interaction object.
|
|
||||||
*
|
|
||||||
* @ingroup thermoprops
|
|
||||||
*/
|
|
||||||
class PhaseCombo_Interaction : public GibbsExcessVPSSTP
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
//! Constructor
|
|
||||||
PhaseCombo_Interaction();
|
|
||||||
|
|
||||||
//! Construct and initialize a PhaseCombo_Interaction ThermoPhase object
|
|
||||||
//! directly from an XML input file
|
|
||||||
/*!
|
|
||||||
* @param inputFile Name of the input file containing the phase XML data
|
|
||||||
* to set up the object
|
|
||||||
* @param id ID of the phase in the input file. Defaults to the
|
|
||||||
* empty string.
|
|
||||||
*/
|
|
||||||
PhaseCombo_Interaction(const std::string& inputFile, const std::string& id = "");
|
|
||||||
|
|
||||||
//! Construct and initialize a PhaseCombo_Interaction ThermoPhase object
|
|
||||||
//! directly from an XML database
|
|
||||||
/*!
|
|
||||||
* @param phaseRef XML phase node containing the description of the phase
|
|
||||||
* @param id id attribute containing the name of the phase.
|
|
||||||
* (default is the empty string)
|
|
||||||
*/
|
|
||||||
PhaseCombo_Interaction(XML_Node& phaseRef, const std::string& id = "");
|
|
||||||
|
|
||||||
//! @name Utilities
|
|
||||||
//! @{
|
|
||||||
|
|
||||||
virtual std::string type() const {
|
|
||||||
return "PhaseCombo_Interaction";
|
|
||||||
}
|
|
||||||
|
|
||||||
//! @}
|
|
||||||
//! @name Molar Thermodynamic Properties
|
|
||||||
//! @{
|
|
||||||
|
|
||||||
virtual doublereal enthalpy_mole() const;
|
|
||||||
virtual doublereal entropy_mole() const;
|
|
||||||
virtual doublereal cp_mole() const;
|
|
||||||
virtual doublereal cv_mole() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @}
|
|
||||||
* @name Activities, Standard States, and Activity Concentrations
|
|
||||||
*
|
|
||||||
* The activity \f$a_k\f$ of a species in solution is related to the
|
|
||||||
* chemical potential by \f[ \mu_k = \mu_k^0(T) + \hat R T \log a_k. \f] The
|
|
||||||
* quantity \f$\mu_k^0(T,P)\f$ is the chemical potential at unit activity,
|
|
||||||
* which depends only on temperature and pressure.
|
|
||||||
* @{
|
|
||||||
*/
|
|
||||||
|
|
||||||
virtual void getActivityCoefficients(doublereal* ac) const;
|
|
||||||
|
|
||||||
//@}
|
|
||||||
/// @name Partial Molar Properties of the Solution
|
|
||||||
//@{
|
|
||||||
|
|
||||||
virtual void getChemPotentials(doublereal* mu) const;
|
|
||||||
|
|
||||||
//! Returns an array of partial molar enthalpies for the species in the
|
|
||||||
//! mixture.
|
|
||||||
/*!
|
|
||||||
* Units (J/kmol)
|
|
||||||
*
|
|
||||||
* For this phase, the partial molar enthalpies are equal to the standard
|
|
||||||
* state enthalpies modified by the derivative of the molality-based
|
|
||||||
* activity coefficient wrt temperature
|
|
||||||
*
|
|
||||||
* \f[
|
|
||||||
* \bar h_k(T,P) = h^o_k(T,P) - R T^2 \frac{d \ln(\gamma_k)}{dT}
|
|
||||||
* \f]
|
|
||||||
*
|
|
||||||
* @param hbar Vector of returned partial molar enthalpies
|
|
||||||
* (length m_kk, units = J/kmol)
|
|
||||||
*/
|
|
||||||
virtual void getPartialMolarEnthalpies(doublereal* hbar) const;
|
|
||||||
|
|
||||||
//! Returns an array of partial molar entropies for the species in the
|
|
||||||
//! mixture.
|
|
||||||
/*!
|
|
||||||
* Units (J/kmol)
|
|
||||||
*
|
|
||||||
* For this phase, the partial molar enthalpies are equal to the standard
|
|
||||||
* state enthalpies modified by the derivative of the activity coefficient
|
|
||||||
* wrt temperature
|
|
||||||
*
|
|
||||||
* \f[
|
|
||||||
* \bar s_k(T,P) = s^o_k(T,P) - R T^2 \frac{d \ln(\gamma_k)}{dT}
|
|
||||||
* - R \ln( \gamma_k X_k)
|
|
||||||
* - R T \frac{d \ln(\gamma_k) }{dT}
|
|
||||||
* \f]
|
|
||||||
*
|
|
||||||
* @param sbar Vector of returned partial molar entropies
|
|
||||||
* (length m_kk, units = J/kmol/K)
|
|
||||||
*/
|
|
||||||
virtual void getPartialMolarEntropies(doublereal* sbar) const;
|
|
||||||
|
|
||||||
//! Returns an array of partial molar entropies for the species in the
|
|
||||||
//! mixture.
|
|
||||||
/*!
|
|
||||||
* Units (J/kmol)
|
|
||||||
*
|
|
||||||
* For this phase, the partial molar enthalpies are equal to the standard
|
|
||||||
* state enthalpies modified by the derivative of the activity coefficient
|
|
||||||
* wrt temperature
|
|
||||||
*
|
|
||||||
* \f[
|
|
||||||
* ???????????????
|
|
||||||
* \bar s_k(T,P) = s^o_k(T,P) - R T^2 \frac{d \ln(\gamma_k)}{dT}
|
|
||||||
* - R \ln( \gamma_k X_k)
|
|
||||||
* - R T \frac{d \ln(\gamma_k) }{dT}
|
|
||||||
* ???????????????
|
|
||||||
* \f]
|
|
||||||
*
|
|
||||||
* @param cpbar Vector of returned partial molar heat capacities
|
|
||||||
* (length m_kk, units = J/kmol/K)
|
|
||||||
*/
|
|
||||||
virtual void getPartialMolarCp(doublereal* cpbar) const;
|
|
||||||
|
|
||||||
//! Return an array of partial molar volumes for the species in the mixture.
|
|
||||||
//! Units: m^3/kmol.
|
|
||||||
/*!
|
|
||||||
* Frequently, for this class of thermodynamics representations, the excess
|
|
||||||
* Volume due to mixing is zero. Here, we set it as a default. It may be
|
|
||||||
* overridden in derived classes.
|
|
||||||
*
|
|
||||||
* @param vbar Output vector of species partial molar volumes.
|
|
||||||
* Length = m_kk. units are m^3/kmol.
|
|
||||||
*/
|
|
||||||
virtual void getPartialMolarVolumes(doublereal* vbar) const;
|
|
||||||
|
|
||||||
//! Get the array of temperature second derivatives of the log activity
|
|
||||||
//! coefficients
|
|
||||||
/*!
|
|
||||||
* units = 1/Kelvin
|
|
||||||
*
|
|
||||||
* @param d2lnActCoeffdT2 Output vector of temperature 2nd derivatives of
|
|
||||||
* the log Activity Coefficients. length = m_kk
|
|
||||||
*/
|
|
||||||
virtual void getd2lnActCoeffdT2(doublereal* d2lnActCoeffdT2) const;
|
|
||||||
|
|
||||||
virtual void getdlnActCoeffdT(doublereal* dlnActCoeffdT) const;
|
|
||||||
|
|
||||||
/// @}
|
|
||||||
/// @name Initialization
|
|
||||||
/// The following methods are used in the process of constructing
|
|
||||||
/// the phase and setting its parameters from a specification in an
|
|
||||||
/// input file. They are not normally used in application programs.
|
|
||||||
/// To see how they are used, see importPhase().
|
|
||||||
/// @{
|
|
||||||
|
|
||||||
virtual void initThermo();
|
|
||||||
virtual void initThermoXML(XML_Node& phaseNode, const std::string& id);
|
|
||||||
|
|
||||||
//! @}
|
|
||||||
//! @name Derivatives of Thermodynamic Variables needed for Applications
|
|
||||||
//! @{
|
|
||||||
|
|
||||||
virtual void getdlnActCoeffds(const doublereal dTds, const doublereal* const dXds, doublereal* dlnActCoeffds) const;
|
|
||||||
virtual void getdlnActCoeffdlnX_diag(doublereal* dlnActCoeffdlnX_diag) const;
|
|
||||||
virtual void getdlnActCoeffdlnN_diag(doublereal* dlnActCoeffdlnN_diag) const;
|
|
||||||
virtual void getdlnActCoeffdlnN(const size_t ld, doublereal* const dlnActCoeffdlnN);
|
|
||||||
|
|
||||||
//@}
|
|
||||||
|
|
||||||
private:
|
|
||||||
//! Process an XML node called "binaryNeutralSpeciesParameters"
|
|
||||||
/*!
|
|
||||||
* This node contains all of the parameters necessary to describe the
|
|
||||||
* Margules model for a particular binary interaction. This function reads
|
|
||||||
* the XML file and writes the coefficients it finds to an internal data
|
|
||||||
* structures.
|
|
||||||
*
|
|
||||||
* @param xmlBinarySpecies Reference to the XML_Node named
|
|
||||||
* "binaryNeutralSpeciesParameters" containing the binary interaction
|
|
||||||
*/
|
|
||||||
void readXMLBinarySpecies(XML_Node& xmlBinarySpecies);
|
|
||||||
|
|
||||||
//! Resize internal arrays within the object that depend upon the number of
|
|
||||||
//! binary Margules interaction terms
|
|
||||||
/*!
|
|
||||||
* @param num Number of binary Margules interaction terms
|
|
||||||
*/
|
|
||||||
void resizeNumInteractions(const size_t num);
|
|
||||||
|
|
||||||
//! Initialize lengths of local variables after all species have been
|
|
||||||
//! identified.
|
|
||||||
void initLengths();
|
|
||||||
|
|
||||||
//! Update the activity coefficients
|
|
||||||
/*!
|
|
||||||
* This function will be called to update the internally stored natural
|
|
||||||
* logarithm of the activity coefficients
|
|
||||||
*/
|
|
||||||
void s_update_lnActCoeff() const;
|
|
||||||
|
|
||||||
//! Update the derivative of the log of the activity coefficients wrt T
|
|
||||||
/*!
|
|
||||||
* This function will be called to update the internally stored derivative
|
|
||||||
* of the natural logarithm of the activity coefficients wrt temperature.
|
|
||||||
*/
|
|
||||||
void s_update_dlnActCoeff_dT() const;
|
|
||||||
|
|
||||||
//! Update the derivative of the log of the activity coefficients wrt
|
|
||||||
//! log(mole fraction)
|
|
||||||
/*!
|
|
||||||
* This function will be called to update the internally stored derivative
|
|
||||||
* of the natural logarithm of the activity coefficients wrt logarithm of
|
|
||||||
* the mole fractions.
|
|
||||||
*/
|
|
||||||
void s_update_dlnActCoeff_dlnX_diag() const;
|
|
||||||
|
|
||||||
//! Update the derivative of the log of the activity coefficients wrt
|
|
||||||
//! log(moles) - diagonal only
|
|
||||||
/*!
|
|
||||||
* This function will be called to update the internally stored diagonal
|
|
||||||
* entries for the derivative of the natural logarithm of the activity
|
|
||||||
* coefficients wrt logarithm of the moles.
|
|
||||||
*/
|
|
||||||
void s_update_dlnActCoeff_dlnN_diag() const;
|
|
||||||
|
|
||||||
//! Update the derivative of the log of the activity coefficients wrt
|
|
||||||
//! log(moles_m)
|
|
||||||
/*!
|
|
||||||
* This function will be called to update the internally stored derivative
|
|
||||||
* of the natural logarithm of the activity coefficients wrt logarithm of
|
|
||||||
* the mole number of species
|
|
||||||
*/
|
|
||||||
void s_update_dlnActCoeff_dlnN() const;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
//! number of binary interaction expressions
|
|
||||||
size_t numBinaryInteractions_;
|
|
||||||
|
|
||||||
//! Enthalpy term for the binary mole fraction interaction of the excess
|
|
||||||
//! Gibbs free energy expression
|
|
||||||
mutable vector_fp m_HE_b_ij;
|
|
||||||
|
|
||||||
//! Enthalpy term for the ternary mole fraction interaction of the excess
|
|
||||||
//! Gibbs free energy expression
|
|
||||||
mutable vector_fp m_HE_c_ij;
|
|
||||||
|
|
||||||
//! Enthalpy term for the quaternary mole fraction interaction of the excess
|
|
||||||
//! Gibbs free energy expression
|
|
||||||
mutable vector_fp m_HE_d_ij;
|
|
||||||
|
|
||||||
//! Entropy term for the binary mole fraction interaction of the excess
|
|
||||||
//! Gibbs free energy expression
|
|
||||||
mutable vector_fp m_SE_b_ij;
|
|
||||||
|
|
||||||
//! Entropy term for the ternary mole fraction interaction of the excess
|
|
||||||
//! Gibbs free energy expression
|
|
||||||
mutable vector_fp m_SE_c_ij;
|
|
||||||
|
|
||||||
//! Entropy term for the quaternary mole fraction interaction of the excess
|
|
||||||
//! Gibbs free energy expression
|
|
||||||
mutable vector_fp m_SE_d_ij;
|
|
||||||
|
|
||||||
//! Enthalpy term for the binary mole fraction interaction of the excess
|
|
||||||
//! Gibbs free energy expression
|
|
||||||
mutable vector_fp m_VHE_b_ij;
|
|
||||||
|
|
||||||
//! Enthalpy term for the ternary mole fraction interaction of the excess
|
|
||||||
//! Gibbs free energy expression
|
|
||||||
mutable vector_fp m_VHE_c_ij;
|
|
||||||
|
|
||||||
//! Enthalpy term for the quaternary mole fraction interaction of the excess
|
|
||||||
//! Gibbs free energy expression
|
|
||||||
mutable vector_fp m_VHE_d_ij;
|
|
||||||
|
|
||||||
//! Entropy term for the binary mole fraction interaction of the excess
|
|
||||||
//! Gibbs free energy expression
|
|
||||||
mutable vector_fp m_VSE_b_ij;
|
|
||||||
|
|
||||||
//! Entropy term for the ternary mole fraction interaction of the excess
|
|
||||||
//! Gibbs free energy expression
|
|
||||||
mutable vector_fp m_VSE_c_ij;
|
|
||||||
|
|
||||||
//! Entropy term for the quaternary mole fraction interaction of the excess
|
|
||||||
//! Gibbs free energy expression
|
|
||||||
mutable vector_fp m_VSE_d_ij;
|
|
||||||
|
|
||||||
//! vector of species indices representing species A in the interaction
|
|
||||||
/*!
|
|
||||||
* Each Margules excess Gibbs free energy term involves two species, A and
|
|
||||||
* B. This vector identifies species A.
|
|
||||||
*/
|
|
||||||
std::vector<size_t> m_pSpecies_A_ij;
|
|
||||||
|
|
||||||
//! vector of species indices representing species B in the interaction
|
|
||||||
/*!
|
|
||||||
* Each Margules excess Gibbs free energy term involves two species, A and
|
|
||||||
* B. This vector identifies species B.
|
|
||||||
*/
|
|
||||||
std::vector<size_t> m_pSpecies_B_ij;
|
|
||||||
|
|
||||||
//! form of the Margules interaction expression
|
|
||||||
/*!
|
|
||||||
* Currently there is only one form.
|
|
||||||
*/
|
|
||||||
int formMargules_;
|
|
||||||
|
|
||||||
//! form of the temperature dependence of the Margules interaction expression
|
|
||||||
/*!
|
|
||||||
* Currently there is only one form -> constant wrt temperature.
|
|
||||||
*/
|
|
||||||
int formTempModel_;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -1228,31 +1228,6 @@ public:
|
||||||
throw NotImplementedError("ThermoPhase::setToEquilState");
|
throw NotImplementedError("ThermoPhase::setToEquilState");
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Stores the element potentials in the ThermoPhase object
|
|
||||||
/*!
|
|
||||||
* Called by the ChemEquil equilibrium solver to transfer the element
|
|
||||||
* potentials to this object after every successful equilibration routine.
|
|
||||||
* The element potentials are stored in their dimensionless forms,
|
|
||||||
* calculated by dividing by RT.
|
|
||||||
*
|
|
||||||
* @param lambda Input vector containing the element potentials.
|
|
||||||
* Length = nElements. Units are Joules/kmol.
|
|
||||||
*/
|
|
||||||
void setElementPotentials(const vector_fp& lambda);
|
|
||||||
|
|
||||||
//! Returns the element potentials stored in the ThermoPhase object
|
|
||||||
/*!
|
|
||||||
* Returns the stored element potentials. The element potentials are
|
|
||||||
* retrieved from their stored dimensionless forms by multiplying by RT.
|
|
||||||
* @param lambda Output vector containing the element potentials.
|
|
||||||
* Length = nElements. Units are Joules/kmol.
|
|
||||||
* @return bool indicating whether there are any valid stored element
|
|
||||||
* potentials. The calling routine should check this
|
|
||||||
* bool. In the case that there aren't any, lambda is not
|
|
||||||
* touched.
|
|
||||||
*/
|
|
||||||
bool getElementPotentials(doublereal* lambda) const;
|
|
||||||
|
|
||||||
//! Indicates whether this phase type can be used with class MultiPhase for
|
//! Indicates whether this phase type can be used with class MultiPhase for
|
||||||
//! equilibrium calculations. Returns `false` for special phase types which
|
//! equilibrium calculations. Returns `false` for special phase types which
|
||||||
//! already represent multi-phase mixtures, namely PureFluidPhase.
|
//! already represent multi-phase mixtures, namely PureFluidPhase.
|
||||||
|
|
@ -1617,15 +1592,6 @@ protected:
|
||||||
//! Stored value of the electric potential for this phase. Units are Volts.
|
//! Stored value of the electric potential for this phase. Units are Volts.
|
||||||
doublereal m_phi;
|
doublereal m_phi;
|
||||||
|
|
||||||
//! Vector of element potentials. Length equal to number of elements.
|
|
||||||
//! @deprecated To be removed after Cantera 2.4.
|
|
||||||
vector_fp m_lambdaRRT;
|
|
||||||
|
|
||||||
//! Boolean indicating whether there is a valid set of saved element
|
|
||||||
//! potentials for this phase
|
|
||||||
//! @deprecated To be removed after Cantera 2.4.
|
|
||||||
bool m_hasElementPotentials;
|
|
||||||
|
|
||||||
//! Boolean indicating whether a charge neutrality condition is a necessity
|
//! Boolean indicating whether a charge neutrality condition is a necessity
|
||||||
/*!
|
/*!
|
||||||
* Note, the charge neutrality condition is not a necessity for ideal gas
|
* Note, the charge neutrality condition is not a necessity for ideal gas
|
||||||
|
|
|
||||||
|
|
@ -59,10 +59,6 @@
|
||||||
//! This is implemented in the class Nasa9PolyMultiTempRegion in Nasa9Poly1MultiTempRegion
|
//! This is implemented in the class Nasa9PolyMultiTempRegion in Nasa9Poly1MultiTempRegion
|
||||||
#define NASA9MULTITEMP 513
|
#define NASA9MULTITEMP 513
|
||||||
|
|
||||||
//! Surface Adsorbate Model for a species on a surface.
|
|
||||||
//! This is implemented in the class Adsorbate.
|
|
||||||
#define ADSORBATE 1024
|
|
||||||
|
|
||||||
//! Type of reference state thermo which is a wrapper around a pressure dependent
|
//! Type of reference state thermo which is a wrapper around a pressure dependent
|
||||||
//! standard state object. Basically, the reference state pressure isn't special.
|
//! standard state object. Basically, the reference state pressure isn't special.
|
||||||
//! A general object is called with the pressure set at the reference state.
|
//! A general object is called with the pressure set at the reference state.
|
||||||
|
|
|
||||||
|
|
@ -1,372 +0,0 @@
|
||||||
/**
|
|
||||||
* @file LTPspecies.h
|
|
||||||
* Header file defining class LTPspecies and its child classes
|
|
||||||
*/
|
|
||||||
|
|
||||||
// This file is part of Cantera. See License.txt in the top-level directory or
|
|
||||||
// at http://www.cantera.org/license.txt for license and copyright information.
|
|
||||||
|
|
||||||
#ifndef CT_LTPSPECIES_H
|
|
||||||
#define CT_LTPSPECIES_H
|
|
||||||
|
|
||||||
#include "TransportBase.h"
|
|
||||||
|
|
||||||
namespace Cantera
|
|
||||||
{
|
|
||||||
|
|
||||||
//! Enumeration of the types of transport properties that can be
|
|
||||||
//! handled by the variables in the various Transport classes.
|
|
||||||
/*!
|
|
||||||
* Not all of these are handled by each class and each class
|
|
||||||
* should handle exceptions where the transport property is not handled.
|
|
||||||
*
|
|
||||||
* Transport properties currently on the list
|
|
||||||
*
|
|
||||||
* 0 - viscosity
|
|
||||||
* 1 - Ionic conductivity
|
|
||||||
* 2 - Mobility Ratio
|
|
||||||
* 3 - Self Diffusion coefficient
|
|
||||||
* 4 - Thermal conductivity
|
|
||||||
* 5 - species diffusivity
|
|
||||||
* 6 - hydrodynamic radius
|
|
||||||
* 7 - electrical conductivity
|
|
||||||
*/
|
|
||||||
enum TransportPropertyType {
|
|
||||||
TP_UNKNOWN = -1,
|
|
||||||
TP_VISCOSITY = 0,
|
|
||||||
TP_IONCONDUCTIVITY,
|
|
||||||
TP_MOBILITYRATIO,
|
|
||||||
TP_SELFDIFFUSION,
|
|
||||||
TP_THERMALCOND,
|
|
||||||
TP_DIFFUSIVITY,
|
|
||||||
TP_HYDRORADIUS,
|
|
||||||
TP_ELECTCOND,
|
|
||||||
TP_DEFECTCONC,
|
|
||||||
TP_DEFECTDIFF
|
|
||||||
};
|
|
||||||
|
|
||||||
//! Temperature dependence type for standard state species properties
|
|
||||||
/*!
|
|
||||||
* Types of temperature dependencies:
|
|
||||||
* 0 - Independent of temperature
|
|
||||||
* 1 - extended arrhenius form
|
|
||||||
* 2 - polynomial in temperature form
|
|
||||||
* 3 - exponential temperature polynomial
|
|
||||||
*/
|
|
||||||
enum LTPTemperatureDependenceType {
|
|
||||||
LTP_TD_NOTSET=-1,
|
|
||||||
LTP_TD_CONSTANT,
|
|
||||||
LTP_TD_ARRHENIUS,
|
|
||||||
LTP_TD_POLY,
|
|
||||||
LTP_TD_EXPT
|
|
||||||
};
|
|
||||||
|
|
||||||
//! Class LTPspecies holds transport parameterizations for a specific liquid-
|
|
||||||
//! phase species.
|
|
||||||
/*!
|
|
||||||
* @deprecated To be removed after Cantera 2.4
|
|
||||||
*
|
|
||||||
* Subclasses handle different means of specifying transport properties like
|
|
||||||
* constant, %Arrhenius or polynomial temperature fits. In its current state,
|
|
||||||
* it is primarily suitable for specifying temperature dependence, but the
|
|
||||||
* adjustCoeffsForComposition() method can be implemented to adjust for the
|
|
||||||
* composition dependence.
|
|
||||||
*
|
|
||||||
* Mixing rules for computing mixture transport properties are handled
|
|
||||||
* separately in the LiquidTranInteraction subclasses.
|
|
||||||
*/
|
|
||||||
class LTPspecies
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
LTPspecies();
|
|
||||||
virtual ~LTPspecies() {}
|
|
||||||
|
|
||||||
//! Duplication routine
|
|
||||||
/*!
|
|
||||||
* (virtual from LTPspecies)
|
|
||||||
*
|
|
||||||
* @returns a copy of this routine as a pointer to LTPspecies
|
|
||||||
*/
|
|
||||||
virtual LTPspecies* duplMyselfAsLTPspecies() const;
|
|
||||||
|
|
||||||
//! Set the ThermoPhase object, which is used to find the temperature
|
|
||||||
void setThermo(thermo_t* thermo) {
|
|
||||||
m_thermo = thermo;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! Set the species name
|
|
||||||
void setName(const std::string& name) {
|
|
||||||
m_speciesName = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! TransportPropertyType containing the property id that this object is
|
|
||||||
//! creating a parameterization for (e.g., viscosity)
|
|
||||||
void setTransportPropertyType(TransportPropertyType tp_ind) {
|
|
||||||
m_property = tp_ind;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! Set up the species transport property from the XML node, `<propNode>`
|
|
||||||
//! that is a child of the `<transport>` node in the species block and
|
|
||||||
//! specifies a type of transport property (like viscosity)
|
|
||||||
virtual void setupFromXML(const XML_Node& propNode) {}
|
|
||||||
|
|
||||||
//! Returns the vector of standard state species transport property
|
|
||||||
/*!
|
|
||||||
* The standard state species transport property is returned. Any
|
|
||||||
* temperature and composition dependence will be adjusted internally
|
|
||||||
* according to the information provided by the subclass object.
|
|
||||||
*
|
|
||||||
* @returns a single double containing the property evaluation at the
|
|
||||||
* current ThermoPhase temperature.
|
|
||||||
*/
|
|
||||||
virtual doublereal getSpeciesTransProp();
|
|
||||||
|
|
||||||
//! Check to see if the property evaluation will be positive
|
|
||||||
virtual bool checkPositive() const;
|
|
||||||
|
|
||||||
//! Return the weight mixture
|
|
||||||
doublereal getMixWeight() const;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private:
|
|
||||||
//! Internal model to adjust species-specific properties for the composition.
|
|
||||||
/*!
|
|
||||||
* Currently just a place holder, but this method could take the composition
|
|
||||||
* from the thermo object and adjust coefficients according to some yet
|
|
||||||
* unspecified model.
|
|
||||||
*/
|
|
||||||
virtual void adjustCoeffsForComposition();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
//! Species Name for the property that is being described
|
|
||||||
std::string m_speciesName;
|
|
||||||
|
|
||||||
//! Model type for the temperature dependence
|
|
||||||
LTPTemperatureDependenceType m_model;
|
|
||||||
|
|
||||||
//! enum indicating which property this is (i.e viscosity)
|
|
||||||
TransportPropertyType m_property;
|
|
||||||
|
|
||||||
//! Model temperature-dependence ceofficients
|
|
||||||
vector_fp m_coeffs;
|
|
||||||
|
|
||||||
//! Pointer to a const thermo object to get current temperature
|
|
||||||
const thermo_t* m_thermo;
|
|
||||||
|
|
||||||
//! Weighting used for mixing.
|
|
||||||
/*!
|
|
||||||
* This weighting can be employed to allow salt transport properties to be
|
|
||||||
* represented by specific ions. For example, to have Li+ and Ca+ represent
|
|
||||||
* the mixing transport properties of LiCl and CaCl2, the weightings for Li+
|
|
||||||
* would be 2.0, for K+ would be 3.0 and for Cl- would be 0.0. The transport
|
|
||||||
* properties for Li+ would be those for LiCl and the transport properties
|
|
||||||
* for Ca+ would be those for CaCl2. The transport properties for Cl- should
|
|
||||||
* be something innoccuous like 1.0--note that 0.0 is not innocuous if there
|
|
||||||
* are logarithms involved.
|
|
||||||
*/
|
|
||||||
doublereal m_mixWeight;
|
|
||||||
};
|
|
||||||
|
|
||||||
//! Class LTPspecies_Const holds transport parameters for a specific liquid-
|
|
||||||
//! phase species (LTPspecies) when the transport property is just a constant
|
|
||||||
//! value.
|
|
||||||
/*!
|
|
||||||
* As an example of the input required for LTPspecies_Const consider the
|
|
||||||
* following XML fragment
|
|
||||||
*
|
|
||||||
* \verbatim
|
|
||||||
* <species>
|
|
||||||
* <!-- thermodynamic properties -->
|
|
||||||
* <transport>
|
|
||||||
* <hydrodynamicRadius model="Constant" units="A">
|
|
||||||
* 1.000
|
|
||||||
* </hydrodynamicRadius>
|
|
||||||
* <!-- other transport properties -->
|
|
||||||
* </transport>
|
|
||||||
* </species>
|
|
||||||
* \endverbatim
|
|
||||||
*/
|
|
||||||
class LTPspecies_Const : public LTPspecies
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
LTPspecies_Const();
|
|
||||||
|
|
||||||
virtual LTPspecies* duplMyselfAsLTPspecies() const;
|
|
||||||
virtual void setupFromXML(const XML_Node& propNode);
|
|
||||||
|
|
||||||
// Set the (constant) property value
|
|
||||||
void setCoeff(double C);
|
|
||||||
|
|
||||||
doublereal getSpeciesTransProp();
|
|
||||||
};
|
|
||||||
|
|
||||||
//! Class LTPspecies_Arrhenius holds transport parameters for a specific liquid-
|
|
||||||
//! phase species (LTPspecies) when the transport property is expressed in
|
|
||||||
//! Arrhenius form.
|
|
||||||
/*!
|
|
||||||
* Used for standard state species properties with equations of the form
|
|
||||||
* \f[
|
|
||||||
* x = A T^b \exp( - E / RT )
|
|
||||||
* \f]
|
|
||||||
* where A, b, and E are passed in the XML input file.
|
|
||||||
*
|
|
||||||
* As an example of the input required for LTPspecies_Arrhenius consider the
|
|
||||||
* following XML fragment
|
|
||||||
*
|
|
||||||
* \verbatim
|
|
||||||
* <species>
|
|
||||||
* <!-- thermodynamic properties -->
|
|
||||||
* <transport>
|
|
||||||
* <viscosity model="Arrhenius">
|
|
||||||
* <!-- Janz, JPCRD, 17, supplement 2, 1988 -->
|
|
||||||
* <A>6.578e-5</A>
|
|
||||||
* <b>0.0</b>
|
|
||||||
* <E units="J/kmol">23788.e3</E>
|
|
||||||
* </viscosity>
|
|
||||||
* <!-- other transport properties -->
|
|
||||||
* </transport>
|
|
||||||
* </species>
|
|
||||||
* \endverbatim
|
|
||||||
*/
|
|
||||||
class LTPspecies_Arrhenius : public LTPspecies
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
LTPspecies_Arrhenius();
|
|
||||||
virtual LTPspecies* duplMyselfAsLTPspecies() const;
|
|
||||||
virtual void setupFromXML(const XML_Node& propNode);
|
|
||||||
|
|
||||||
//! Return the standard state species value for this transport property
|
|
||||||
//! evaluated from the Arrhenius expression
|
|
||||||
/*!
|
|
||||||
* In general the Arrhenius expression is
|
|
||||||
*
|
|
||||||
* \f[
|
|
||||||
* \mu = A T^n \exp( - E / R T ).
|
|
||||||
* \f]
|
|
||||||
*
|
|
||||||
* Note that for viscosity, the convention is such that a positive
|
|
||||||
* activation energy corresponds to the typical case of a positive
|
|
||||||
* argument to the exponential so that the Arrhenius expression is
|
|
||||||
*
|
|
||||||
* \f[
|
|
||||||
* \mu = A T^n \exp( + E / R T ).
|
|
||||||
* \f]
|
|
||||||
*
|
|
||||||
* Any temperature and composition dependence will be adjusted internally
|
|
||||||
* according to the information provided.
|
|
||||||
*/
|
|
||||||
doublereal getSpeciesTransProp();
|
|
||||||
|
|
||||||
// Set the coefficients in the Arrhenius expression
|
|
||||||
void setCoeffs(double A, double n, double Tact);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
//! temperature from thermo object
|
|
||||||
doublereal m_temp;
|
|
||||||
|
|
||||||
//! logarithm of current temperature
|
|
||||||
doublereal m_logt;
|
|
||||||
|
|
||||||
//! most recent evaluation of transport property
|
|
||||||
doublereal m_prop;
|
|
||||||
|
|
||||||
//! logarithm of most recent evaluation of transport property
|
|
||||||
doublereal m_logProp;
|
|
||||||
};
|
|
||||||
|
|
||||||
//! Class LTPspecies_Poly holds transport parameters for a specific liquid-phase
|
|
||||||
//! species (LTPspecies) when the transport property is expressed as a
|
|
||||||
//! polynomial in temperature.
|
|
||||||
/*!
|
|
||||||
* Used for standard state species properties with equations of the form
|
|
||||||
* \f[
|
|
||||||
* x = f[0] + f[1] T + ... + f[N] T^N
|
|
||||||
* \f]
|
|
||||||
* where f[i] are elements of the float array passed in.
|
|
||||||
*
|
|
||||||
* As an example of the input required for LTPspecies_Poly consider the
|
|
||||||
* following XML fragment
|
|
||||||
*
|
|
||||||
* \verbatim
|
|
||||||
* <species>
|
|
||||||
* <!-- thermodynamic properties -->
|
|
||||||
* <transport>
|
|
||||||
* <thermalConductivity model="coeffs">
|
|
||||||
* <floatArray size="2"> 0.6, -15.0e-5 </floatArray>
|
|
||||||
* </thermalConductivity>
|
|
||||||
* <!-- other transport properties -->
|
|
||||||
* </transport>
|
|
||||||
* </species>
|
|
||||||
* \endverbatim
|
|
||||||
*/
|
|
||||||
class LTPspecies_Poly : public LTPspecies
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
LTPspecies_Poly();
|
|
||||||
|
|
||||||
virtual LTPspecies* duplMyselfAsLTPspecies() const;
|
|
||||||
virtual void setupFromXML(const XML_Node& propNode);
|
|
||||||
doublereal getSpeciesTransProp();
|
|
||||||
|
|
||||||
// Set the coefficients in the polynomial expression
|
|
||||||
void setCoeffs(size_t N, const double* coeffs);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
//! temperature from thermo object
|
|
||||||
doublereal m_temp;
|
|
||||||
|
|
||||||
//! most recent evaluation of transport property
|
|
||||||
doublereal m_prop;
|
|
||||||
};
|
|
||||||
|
|
||||||
//! Class LTPspecies_ExpT holds transport parameters for a specific liquid-
|
|
||||||
//! phase species (LTPspecies) when the transport property is expressed as an
|
|
||||||
//! exponential in temperature.
|
|
||||||
/*!
|
|
||||||
* Used for standard state species properties with equations of the form
|
|
||||||
*
|
|
||||||
* \f[
|
|
||||||
* x = f[0] \exp( f[1] T + ... + f[N] T^{N} )
|
|
||||||
* \f]
|
|
||||||
*
|
|
||||||
* where f[i] are elements of the float array passed in.
|
|
||||||
*
|
|
||||||
* As an example of the input required for LTPspecies_ExpT consider the
|
|
||||||
* following XML fragment
|
|
||||||
*
|
|
||||||
* \verbatim
|
|
||||||
* <species>
|
|
||||||
* <!-- thermodynamic properties -->
|
|
||||||
* <transport>
|
|
||||||
* <thermalConductivity model="expT">
|
|
||||||
* <floatArray size="2"> 0.6, -15.0e-5 </floatArray>
|
|
||||||
* </thermalConductivity>
|
|
||||||
* <!-- other transport properties -->
|
|
||||||
* </transport>
|
|
||||||
* </species>
|
|
||||||
* \endverbatim
|
|
||||||
*/
|
|
||||||
class LTPspecies_ExpT : public LTPspecies
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
LTPspecies_ExpT();
|
|
||||||
|
|
||||||
virtual LTPspecies* duplMyselfAsLTPspecies() const;
|
|
||||||
virtual void setupFromXML(const XML_Node& propNode);
|
|
||||||
|
|
||||||
// Set the coefficients in the polynomial expression
|
|
||||||
void setCoeffs(size_t N, const double* coeffs);
|
|
||||||
|
|
||||||
doublereal getSpeciesTransProp();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
//! temperature from thermo object
|
|
||||||
doublereal m_temp;
|
|
||||||
|
|
||||||
//! most recent evaluation of the transport property
|
|
||||||
doublereal m_prop;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,559 +0,0 @@
|
||||||
/**
|
|
||||||
* @file LiquidTranInteraction.h
|
|
||||||
* Header file defining the class LiquidTranInteraction and classes which
|
|
||||||
* derive from LiquidTranInteraction.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// This file is part of Cantera. See License.txt in the top-level directory or
|
|
||||||
// at http://www.cantera.org/license.txt for license and copyright information.
|
|
||||||
|
|
||||||
#ifndef CT_LIQUIDTRANINTERACTION_H
|
|
||||||
#define CT_LIQUIDTRANINTERACTION_H
|
|
||||||
|
|
||||||
#include "TransportParams.h"
|
|
||||||
#include "LiquidTransportData.h"
|
|
||||||
#include "cantera/base/xml.h"
|
|
||||||
|
|
||||||
namespace Cantera
|
|
||||||
{
|
|
||||||
//! Composition dependence type for liquid mixture transport properties
|
|
||||||
/*!
|
|
||||||
* @deprecated To be removed after Cantera 2.4
|
|
||||||
*
|
|
||||||
* Types of temperature dependencies:
|
|
||||||
* - 0 - Mixture calculations with this property are not allowed
|
|
||||||
* - 1 - Use solvent (species 0) properties
|
|
||||||
* - 2 - Properties weighted linearly by mole fractions
|
|
||||||
* - 3 - Properties weighted linearly by mass fractions
|
|
||||||
* - 4 - Properties weighted logarithmically by mole fractions (interaction energy weighting)
|
|
||||||
* - 5 - Interactions given pairwise between each possible species (i.e. D_ij)
|
|
||||||
*
|
|
||||||
* \verbatim
|
|
||||||
* <transport model="Liquid">
|
|
||||||
* <viscosity>
|
|
||||||
* <compositionDependence model="logMoleFractions">
|
|
||||||
* <interaction>
|
|
||||||
* <speciesA> LiCl(L) </speciesA>
|
|
||||||
* <speciesB> KCl(L) </speciesB>
|
|
||||||
* <Eij units="J/kmol"> -1.0 </Eij>
|
|
||||||
* <Sij units="J/kmol/K"> 1.0E-1 </Sij>
|
|
||||||
* -or- <Sij>
|
|
||||||
* <floatArray units="J/kmol/K"> 1.0E-1, 0.001 0.01 </floatArray>
|
|
||||||
* </Sij>
|
|
||||||
* -same form for Hij,Aij,Bij-
|
|
||||||
* </interaction>
|
|
||||||
* </compositionDependence>
|
|
||||||
* </viscosity>
|
|
||||||
* <speciesDiffusivity>
|
|
||||||
* <compositionDependence model="pairwiseInteraction">
|
|
||||||
* <interaction>
|
|
||||||
* <speciesA> Li+ </speciesA>
|
|
||||||
* <speciesB> K+ </speciesB>
|
|
||||||
* <Dij units="m2/s"> 1.5 </Dij>
|
|
||||||
* </interaction>
|
|
||||||
* <interaction>
|
|
||||||
* <speciesA> K+ </speciesA>
|
|
||||||
* <speciesB> Cl- </speciesB>
|
|
||||||
* <Dij units="m2/s"> 1.0 </Dij>
|
|
||||||
* </interaction>
|
|
||||||
* <interaction>
|
|
||||||
* <speciesA> Li+ </speciesA>
|
|
||||||
* <speciesB> Cl- </speciesB>
|
|
||||||
* <Dij units="m2/s"> 1.2 </Dij>
|
|
||||||
* </interaction>
|
|
||||||
* </compositionDependence>
|
|
||||||
* </speciesDiffusivity>
|
|
||||||
* <thermalConductivity>
|
|
||||||
* <compositionDependence model="massFractions"/>
|
|
||||||
* </thermalConductivity>
|
|
||||||
* <hydrodynamicRadius>
|
|
||||||
* <compositionDependence model="none"/>
|
|
||||||
* </hydrodynamicRadius>
|
|
||||||
* </transport>
|
|
||||||
* \endverbatim
|
|
||||||
*/
|
|
||||||
enum LiquidTranMixingModel {
|
|
||||||
LTI_MODEL_NOTSET=-1,
|
|
||||||
LTI_MODEL_SOLVENT,
|
|
||||||
LTI_MODEL_MOLEFRACS,
|
|
||||||
LTI_MODEL_MASSFRACS,
|
|
||||||
LTI_MODEL_LOG_MOLEFRACS,
|
|
||||||
LTI_MODEL_PAIRWISE_INTERACTION,
|
|
||||||
LTI_MODEL_STEFANMAXWELL_PPN,
|
|
||||||
LTI_MODEL_STOKES_EINSTEIN,
|
|
||||||
LTI_MODEL_MOLEFRACS_EXPT,
|
|
||||||
LTI_MODEL_NONE,
|
|
||||||
LTI_MODEL_MULTIPLE
|
|
||||||
};
|
|
||||||
|
|
||||||
//! Base class to handle transport property evaluation in a mixture.
|
|
||||||
/*!
|
|
||||||
* @deprecated To be removed after Cantera 2.4
|
|
||||||
*
|
|
||||||
* In a mixture, the mixture transport properties will generally depend on the
|
|
||||||
* contributions of each of the standard state species transport properties.
|
|
||||||
* Many composition dependencies are possible. This class,
|
|
||||||
* LiquidTranInteraction, is designed to be a base class for the implementation
|
|
||||||
* of various models for the mixing of standard state species transport
|
|
||||||
* properties.
|
|
||||||
*
|
|
||||||
* There are two very broad types of transport properties to consider. First,
|
|
||||||
* there are properties for which a mixture value can be obtained through some
|
|
||||||
* mixing rule. These are obtained using the method getMixTransProp().
|
|
||||||
* Viscosity is typical of this. Second, there are properties for which a matrix
|
|
||||||
* of properties may exist. This matrix of properties is obtained from the
|
|
||||||
* method getMatrixTransProp(). Diffusion coefficients are of this type.
|
|
||||||
* Subclasses should implement the appropriate one or both of these methods.
|
|
||||||
*/
|
|
||||||
class LiquidTranInteraction
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
//! Constructor
|
|
||||||
/**
|
|
||||||
* @param tp_ind Index indicating the transport property type (e.g., viscosity)
|
|
||||||
*/
|
|
||||||
LiquidTranInteraction(TransportPropertyType tp_ind = TP_UNKNOWN);
|
|
||||||
|
|
||||||
virtual ~LiquidTranInteraction();
|
|
||||||
|
|
||||||
//! initialize LiquidTranInteraction objects with thermo and XML node
|
|
||||||
/**
|
|
||||||
* @param compModelNode `<compositionDependence>` XML node
|
|
||||||
* @param thermo Pointer to thermo object
|
|
||||||
*/
|
|
||||||
virtual void init(const XML_Node& compModelNode = XML_Node(),
|
|
||||||
thermo_t* thermo = 0);
|
|
||||||
|
|
||||||
virtual void setParameters(LiquidTransportParams& trParam) {}
|
|
||||||
|
|
||||||
//! Return the mixture transport property value.
|
|
||||||
//! (Must be implemented in subclasses.)
|
|
||||||
virtual doublereal getMixTransProp(doublereal* speciesValues, doublereal* weightSpecies = 0) {
|
|
||||||
throw NotImplementedError("LiquidTranInteraction::getMixTransProp");
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual doublereal getMixTransProp(std::vector<LTPspecies*> LTPptrs) {
|
|
||||||
throw NotImplementedError("LiquidTranInteraction::getMixTransProp");
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void getMatrixTransProp(DenseMatrix& mat, doublereal* speciesValues = 0) {
|
|
||||||
throw NotImplementedError("LiquidTranInteraction::getMixTransProp");
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
//! Model for species interaction effects. Takes enum LiquidTranMixingModel
|
|
||||||
LiquidTranMixingModel m_model;
|
|
||||||
|
|
||||||
//! enum indicating what property this is (i.e viscosity)
|
|
||||||
TransportPropertyType m_property;
|
|
||||||
|
|
||||||
//! pointer to thermo object to get current temperature
|
|
||||||
thermo_t* m_thermo;
|
|
||||||
|
|
||||||
//! Matrix of interaction coefficients for polynomial in molefraction*weight
|
|
||||||
//! of speciesA (no temperature dependence, dimensionless)
|
|
||||||
std::vector<DenseMatrix*> m_Aij;
|
|
||||||
|
|
||||||
//! Matrix of interaction coefficients for polynomial in molefraction*weight
|
|
||||||
//! of speciesA (linear temperature dependence, units 1/K)
|
|
||||||
std::vector<DenseMatrix*> m_Bij;
|
|
||||||
|
|
||||||
//! Matrix of interactions (in energy units, 1/RT temperature dependence)
|
|
||||||
DenseMatrix m_Eij;
|
|
||||||
|
|
||||||
//! Matrix of interaction coefficients for polynomial in molefraction*weight
|
|
||||||
//! of speciesA (in energy units, 1/RT temperature dependence)
|
|
||||||
std::vector<DenseMatrix*> m_Hij;
|
|
||||||
|
|
||||||
//! Matrix of interaction coefficients for polynomial in molefraction*weight
|
|
||||||
//! of speciesA (in entropy units, divided by R)
|
|
||||||
std::vector<DenseMatrix*> m_Sij;
|
|
||||||
|
|
||||||
//! Matrix of interactions
|
|
||||||
DenseMatrix m_Dij;
|
|
||||||
};
|
|
||||||
|
|
||||||
class LTI_Solvent : public LiquidTranInteraction
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
LTI_Solvent(TransportPropertyType tp_ind = TP_UNKNOWN);
|
|
||||||
|
|
||||||
//! Return the mixture transport property value.
|
|
||||||
/**
|
|
||||||
* Takes the separate species transport properties as input (this method
|
|
||||||
* does not know what transport property it is at this point).
|
|
||||||
*/
|
|
||||||
doublereal getMixTransProp(doublereal* valueSpecies, doublereal* weightSpecies = 0);
|
|
||||||
doublereal getMixTransProp(std::vector<LTPspecies*> LTPptrs);
|
|
||||||
|
|
||||||
//! Return the matrix of binary interaction parameters.
|
|
||||||
/**
|
|
||||||
* Takes the proper mixing rule for the binary interaction parameters
|
|
||||||
* and calculates them: Not implemented for this mixing rule.
|
|
||||||
*/
|
|
||||||
void getMatrixTransProp(DenseMatrix& mat, doublereal* speciesValues = 0);
|
|
||||||
};
|
|
||||||
|
|
||||||
//! Simple mole fraction weighting of transport properties
|
|
||||||
/**
|
|
||||||
* This model weights the transport property by the mole fractions. The
|
|
||||||
* overall formula for the mixture viscosity is
|
|
||||||
*
|
|
||||||
* \f[
|
|
||||||
* \eta_{mix} = \sum_i X_i \eta_i + \sum_i \sum_j X_i X_j A_{i,j}
|
|
||||||
* \f]
|
|
||||||
*/
|
|
||||||
class LTI_MoleFracs : public LiquidTranInteraction
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
LTI_MoleFracs(TransportPropertyType tp_ind = TP_UNKNOWN) :
|
|
||||||
LiquidTranInteraction(tp_ind) {
|
|
||||||
m_model = LTI_MODEL_MOLEFRACS;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! Return the mixture transport property value.
|
|
||||||
/**
|
|
||||||
* Takes the separate species transport properties as input (this method
|
|
||||||
* does not know what transport property it is at this point.
|
|
||||||
*/
|
|
||||||
doublereal getMixTransProp(doublereal* valueSpecies, doublereal* weightSpecies = 0);
|
|
||||||
doublereal getMixTransProp(std::vector<LTPspecies*> LTPptrs);
|
|
||||||
|
|
||||||
//! Return the matrix of binary interaction parameters.
|
|
||||||
/**
|
|
||||||
* Takes the proper mixing rule for the binary interaction parameters
|
|
||||||
* and calculates them: Not Implemented for this Mixing rule;
|
|
||||||
*/
|
|
||||||
void getMatrixTransProp(DenseMatrix& mat, doublereal* speciesValues = 0) {
|
|
||||||
mat = (*m_Aij[0]);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
//! Simple mass fraction weighting of transport properties
|
|
||||||
/*!
|
|
||||||
* This model weights the transport property by the mass fractions. The
|
|
||||||
* overall formula for the mixture viscosity is
|
|
||||||
*
|
|
||||||
* \f[
|
|
||||||
* \eta_{mix} = \sum_i Y_i \eta_i
|
|
||||||
* + \sum_i \sum_j Y_i Y_j A_{i,j}
|
|
||||||
* \f].
|
|
||||||
*/
|
|
||||||
class LTI_MassFracs : public LiquidTranInteraction
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
LTI_MassFracs(TransportPropertyType tp_ind = TP_UNKNOWN) :
|
|
||||||
LiquidTranInteraction(tp_ind) {
|
|
||||||
m_model = LTI_MODEL_MASSFRACS;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! Return the mixture transport property value.
|
|
||||||
/**
|
|
||||||
* Takes the separate species transport properties as input (this method
|
|
||||||
* does not know what transport property it is at this point.
|
|
||||||
*/
|
|
||||||
doublereal getMixTransProp(doublereal* valueSpecies, doublereal* weightSpecies = 0);
|
|
||||||
doublereal getMixTransProp(std::vector<LTPspecies*> LTPptrs);
|
|
||||||
|
|
||||||
//! Return the matrix of binary interaction parameters.
|
|
||||||
/**
|
|
||||||
* Takes the proper mixing rule for the binary interaction parameters
|
|
||||||
* and calculates them: Not implemented for this mixing rule.
|
|
||||||
*/
|
|
||||||
void getMatrixTransProp(DenseMatrix& mat, doublereal* speciesValues = 0) {
|
|
||||||
mat = (*m_Aij[0]);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
//! Mixing rule using logarithms of the mole fractions
|
|
||||||
/**
|
|
||||||
* This model is based on the idea that liquid molecules are generally
|
|
||||||
* interacting with some energy and entropy of interaction. For transport
|
|
||||||
* properties that depend on these energies of interaction, the mixture
|
|
||||||
* transport property can be written in terms of its logarithm
|
|
||||||
*
|
|
||||||
* \f[ \ln \eta_{mix} = \sum_i X_i \ln \eta_i
|
|
||||||
* + \sum_i \sum_j X_i X_j ( S_{i,j} + E_{i,j} / T )
|
|
||||||
* \f].
|
|
||||||
*
|
|
||||||
* These additional interaction terms multiply the mixture property by
|
|
||||||
* \f[ \exp( \sum_{i} \sum_{j} X_i X_j ( S_{i,j} + E_{i,j} / T ) ) \f]
|
|
||||||
* so that the self-interaction terms \f$ S_{i,j} \f$ and
|
|
||||||
* \f$ E_{i,j} \f$ should be zero.
|
|
||||||
*
|
|
||||||
* Note that the energies and entropies of interaction should be
|
|
||||||
* a function of the composition themselves, but this is not yet
|
|
||||||
* implemented. (We might follow the input of Margules model
|
|
||||||
* thermodynamic data for the purpose of implementing this.)
|
|
||||||
*
|
|
||||||
* Sample input for this method is
|
|
||||||
* \verbatim
|
|
||||||
* <transport model="Liquid">
|
|
||||||
* <viscosity>
|
|
||||||
* <compositionDependence model="logMoleFractions">
|
|
||||||
* <interaction speciesA="Li+" speciesB="K+">
|
|
||||||
* <!--
|
|
||||||
* interactions are from speciesA = LiCl(L)
|
|
||||||
* and speciesB = KCl(L).
|
|
||||||
* -->
|
|
||||||
* <Eij units="J/kmol"> -1.0e3 </Eij>
|
|
||||||
* <Sij units="J/kmol/K"> 80.0e-5 </Sij>
|
|
||||||
* </interaction>
|
|
||||||
* </compositionDependence>
|
|
||||||
* </viscosity>
|
|
||||||
* </transport>
|
|
||||||
* \endverbatim
|
|
||||||
*/
|
|
||||||
class LTI_Log_MoleFracs : public LiquidTranInteraction
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
LTI_Log_MoleFracs(TransportPropertyType tp_ind = TP_UNKNOWN) :
|
|
||||||
LiquidTranInteraction(tp_ind) {
|
|
||||||
m_model = LTI_MODEL_LOG_MOLEFRACS;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! Return the mixture transport property value.
|
|
||||||
/**
|
|
||||||
* Takes the separate species transport properties as input (this method
|
|
||||||
* does not know what transport property it is at this point.
|
|
||||||
*/
|
|
||||||
doublereal getMixTransProp(doublereal* valueSpecies, doublereal* weightSpecies = 0);
|
|
||||||
doublereal getMixTransProp(std::vector<LTPspecies*> LTPptrs);
|
|
||||||
|
|
||||||
//! Return the matrix of binary interaction parameters.
|
|
||||||
/**
|
|
||||||
* Takes the proper mixing rule for the binary interaction parameters
|
|
||||||
* and calculates them: Not implemented for this mixing rule.
|
|
||||||
*/
|
|
||||||
void getMatrixTransProp(DenseMatrix& mat, doublereal* speciesValues = 0) {
|
|
||||||
mat = m_Eij;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
//! Transport properties that act like pairwise interactions
|
|
||||||
//! as in binary diffusion coefficients.
|
|
||||||
/**
|
|
||||||
* This class holds parameters for transport properties expressed as a matrix
|
|
||||||
* of pairwise interaction parameters. Input can be provided for constant or
|
|
||||||
* Arrhenius forms of the separate parameters.
|
|
||||||
*
|
|
||||||
* Sample input for this method is
|
|
||||||
* \verbatim
|
|
||||||
* <transport model="Liquid">
|
|
||||||
* <speciesDiffusivity>
|
|
||||||
* <compositionDependence model="pairwiseInteraction">
|
|
||||||
* <interaction speciesA="LiCl(L)" speciesB="KCl(L)">
|
|
||||||
* <Dij units="m/s"> 1.0e-8 </Dij>
|
|
||||||
* <Eij units="J/kmol"> 24.0e6 </Eij>
|
|
||||||
* </interaction>
|
|
||||||
* </compositionDependence>
|
|
||||||
* </speciesDiffusivity>
|
|
||||||
* </transport>
|
|
||||||
* \endverbatim
|
|
||||||
*/
|
|
||||||
class LTI_Pairwise_Interaction : public LiquidTranInteraction
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
LTI_Pairwise_Interaction(TransportPropertyType tp_ind = TP_UNKNOWN) :
|
|
||||||
LiquidTranInteraction(tp_ind) {
|
|
||||||
m_model = LTI_MODEL_PAIRWISE_INTERACTION;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setParameters(LiquidTransportParams& trParam);
|
|
||||||
|
|
||||||
//! Return the mixture transport property value.
|
|
||||||
/**
|
|
||||||
* Takes the separate species transport properties as input (this method
|
|
||||||
* does not know what transport property it is at this point.
|
|
||||||
*/
|
|
||||||
doublereal getMixTransProp(doublereal* valueSpecies, doublereal* weightSpecies = 0);
|
|
||||||
doublereal getMixTransProp(std::vector<LTPspecies*> LTPptrs);
|
|
||||||
|
|
||||||
//! Return the matrix of binary interaction parameters.
|
|
||||||
/**
|
|
||||||
* Takes the proper mixing rule for the binary interaction parameters
|
|
||||||
* and calculates them
|
|
||||||
*/
|
|
||||||
void getMatrixTransProp(DenseMatrix& mat, doublereal* speciesValues = 0);
|
|
||||||
protected:
|
|
||||||
|
|
||||||
std::vector<LTPspecies*> m_diagonals;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
//! Stefan Maxwell Diffusion Coefficients can be solved for given
|
|
||||||
//! ion conductivity, mobility ratios, and self diffusion coeffs.
|
|
||||||
//! This class is only valid for a common anion mixture of two
|
|
||||||
//! salts with cations of equal charge. Hence the name _PPN.
|
|
||||||
/**
|
|
||||||
* This class requres you specify
|
|
||||||
*
|
|
||||||
* 1 - ion conductivity
|
|
||||||
*
|
|
||||||
* 2 - mobility ratio of the two cations (set all other ratios to zero)
|
|
||||||
*
|
|
||||||
* 3 - Self diffusion coefficients of the cations (set others to zero)
|
|
||||||
* is used to calculate the "mutual diffusion coefficient". The
|
|
||||||
* approximation needed to do so requires the cations have equal charge.
|
|
||||||
*
|
|
||||||
* We than calculate the Stefan Maxwell Diffusion Coefficients by
|
|
||||||
* \f[
|
|
||||||
* \frac{1}{D_{12}} = (1-\epsilon X_A)(1+\epsilon X_B)
|
|
||||||
* \frac{\nu_- + \nu_+}{\nu_-\nu_+^2D}
|
|
||||||
* + \frac{z_-z_+ F^2}{\kappa V R T}
|
|
||||||
* \f]
|
|
||||||
* \f[
|
|
||||||
* \frac{1}{D_{12}} = -\epsilon X_B(1-\epsilon X_A)
|
|
||||||
* \frac{\nu_- + \nu_+}{\nu_-^2\nu_+D}
|
|
||||||
* - \frac{z_-z_+ F^2}{\kappa V R T}
|
|
||||||
* \f]
|
|
||||||
* \f[
|
|
||||||
* \frac{1}{D_{23}} = \epsilon X_A(1+\epsilon X_B)
|
|
||||||
* \frac{\nu_- + \nu_+}{\nu_-^2\nu_+D}
|
|
||||||
* - \frac{z_-z_+ F^2}{\kappa V R T}
|
|
||||||
* \f]
|
|
||||||
* where F is Faraday's constant, RT is the gas constant times the
|
|
||||||
* tempurature, and V is the molar volume (basis is moles of ions) that is
|
|
||||||
* calculated by the ThermoPhase member. X_A and X_B are the mole fractions
|
|
||||||
* of the salts composed of cation(1) and cation(2), respectively, that share
|
|
||||||
* a common anion(3). \f$\nu_{+,-}\f$ are the stoichiometric coefficients in
|
|
||||||
* the dissociation reaction of the salts to the ions with charges of
|
|
||||||
* \f$z_{+,-}\f$. Assuming that the cations have equal charge, the "mutual
|
|
||||||
* diffusion coefficient" is calculated using the cation self diffusion
|
|
||||||
* coefficients.
|
|
||||||
* \f[
|
|
||||||
* \frac{1}{\nu_-\nu_+D} = \left(1+\frac{\partial \gamma_B}{\partial N_B}
|
|
||||||
* \right)\frac{X_A}{D_2^*}+\left(1+\frac{\partial \gamma_A}{\partial N_A}
|
|
||||||
* \right)\frac{X_B}{D_1^*}
|
|
||||||
* \f]
|
|
||||||
* where the self diffusion coefficients, \f$D_i^*\f$, are temperature and
|
|
||||||
* composition parameterized inputs and the derivative of the activity
|
|
||||||
* coefficient, \f$\frac{\partial \gamma_B}{\partial N_B}\f$, is calculated
|
|
||||||
* by the ThermoPhase member using the excess enthalpy and entropy upon mixing.
|
|
||||||
*
|
|
||||||
* Finally, the deviation of the transferrence numbers from ideality,
|
|
||||||
* \f$\epsilon\f$, is calculated from the mobility ratio of the cations.
|
|
||||||
* \f[
|
|
||||||
* \epsilon = \frac{1-b_2/b_1}{X_A+X_Bb_2/b_1}
|
|
||||||
* \f]
|
|
||||||
* Where \f$b_i\f$ are the mobilities of the two cations. Everywhere,
|
|
||||||
* cation 1 corresponds with salt A and cation 2 with salt B.
|
|
||||||
*
|
|
||||||
* Sample input for this method is
|
|
||||||
* \verbatim
|
|
||||||
* <transport model="Liquid">
|
|
||||||
* <speciesDiffusivity>
|
|
||||||
* <compositionDependence model="stefanMaxwell_PPN">
|
|
||||||
* </compositionDependence>
|
|
||||||
* </speciesDiffusivity>
|
|
||||||
* </transport>
|
|
||||||
* \endverbatim
|
|
||||||
*/
|
|
||||||
class LTI_StefanMaxwell_PPN : public LiquidTranInteraction
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
LTI_StefanMaxwell_PPN(TransportPropertyType tp_ind = TP_UNKNOWN) :
|
|
||||||
LiquidTranInteraction(tp_ind) {
|
|
||||||
m_model = LTI_MODEL_STEFANMAXWELL_PPN;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setParameters(LiquidTransportParams& trParam);
|
|
||||||
|
|
||||||
//! Return the mixture transport property value.
|
|
||||||
/**
|
|
||||||
* Takes the separate species transport properties as input (this method
|
|
||||||
* does not know what transport property it is at this point.
|
|
||||||
*/
|
|
||||||
doublereal getMixTransProp(doublereal* valueSpecies, doublereal* weightSpecies = 0);
|
|
||||||
doublereal getMixTransProp(std::vector<LTPspecies*> LTPptrs);
|
|
||||||
|
|
||||||
//! Return the matrix of binary interaction parameters.
|
|
||||||
/**
|
|
||||||
* Takes the proper mixing rule for the binary interaction parameters
|
|
||||||
* and calculates them
|
|
||||||
*/
|
|
||||||
void getMatrixTransProp(DenseMatrix& mat, doublereal* speciesValues = 0);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
doublereal m_ionCondMix;
|
|
||||||
LiquidTranInteraction* m_ionCondMixModel;
|
|
||||||
std::vector<LTPspecies*> m_ionCondSpecies;
|
|
||||||
typedef std::vector<LTPspecies*> LTPvector;
|
|
||||||
DenseMatrix m_mobRatMix;
|
|
||||||
std::vector<LiquidTranInteraction*> m_mobRatMixModel;
|
|
||||||
std::vector<LTPvector> m_mobRatSpecies;
|
|
||||||
|
|
||||||
std::vector<LiquidTranInteraction*> m_selfDiffMixModel;
|
|
||||||
vector_fp m_selfDiffMix;
|
|
||||||
std::vector<LTPvector> m_selfDiffSpecies;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
class LTI_StokesEinstein : public LiquidTranInteraction
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
LTI_StokesEinstein(TransportPropertyType tp_ind = TP_UNKNOWN) :
|
|
||||||
LiquidTranInteraction(tp_ind) {
|
|
||||||
m_model = LTI_MODEL_STOKES_EINSTEIN;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setParameters(LiquidTransportParams& trParam);
|
|
||||||
|
|
||||||
//! Return the mixture transport property value.
|
|
||||||
/**
|
|
||||||
* Takes the separate species transport properties
|
|
||||||
* as input (this method does not know what
|
|
||||||
* transport property it is at this point.
|
|
||||||
*/
|
|
||||||
doublereal getMixTransProp(doublereal* valueSpecies, doublereal* weightSpecies = 0);
|
|
||||||
doublereal getMixTransProp(std::vector<LTPspecies*> LTPptrs);
|
|
||||||
|
|
||||||
//! Return the matrix of binary interaction parameters.
|
|
||||||
/**
|
|
||||||
* Takes the proper mixing rule for the binary interaction parameters
|
|
||||||
* and calculates them
|
|
||||||
*/
|
|
||||||
void getMatrixTransProp(DenseMatrix& mat, doublereal* speciesValues = 0);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
std::vector<LTPspecies*> m_viscosity;
|
|
||||||
std::vector<LTPspecies*> m_hydroRadius;
|
|
||||||
};
|
|
||||||
|
|
||||||
//! Simple mole fraction weighting of transport properties
|
|
||||||
/**
|
|
||||||
* This model weights the transport property by the mole fractions. The
|
|
||||||
* overall formula for the mixture viscosity is
|
|
||||||
*
|
|
||||||
* \f[ \eta_{mix} = \sum_i X_i \eta_i
|
|
||||||
* + \sum_i \sum_j X_i X_j A_{i,j} \f].
|
|
||||||
*/
|
|
||||||
class LTI_MoleFracs_ExpT : public LiquidTranInteraction
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
LTI_MoleFracs_ExpT(TransportPropertyType tp_ind = TP_UNKNOWN) :
|
|
||||||
LiquidTranInteraction(tp_ind) {
|
|
||||||
m_model = LTI_MODEL_MOLEFRACS_EXPT;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! Return the mixture transport property value.
|
|
||||||
/**
|
|
||||||
* Takes the separate species transport properties as input (this method
|
|
||||||
* does not know what transport property it is at this point.
|
|
||||||
*/
|
|
||||||
doublereal getMixTransProp(doublereal* valueSpecies, doublereal* weightSpecies = 0);
|
|
||||||
doublereal getMixTransProp(std::vector<LTPspecies*> LTPptrs);
|
|
||||||
|
|
||||||
//! Return the matrix of binary interaction parameters.
|
|
||||||
/**
|
|
||||||
* Takes the proper mixing rule for the binary interaction parameters
|
|
||||||
* and calculates them: Not Implemented for this mixing rule
|
|
||||||
*/
|
|
||||||
void getMatrixTransProp(DenseMatrix& mat, doublereal* speciesValues = 0) {
|
|
||||||
mat = (*m_Aij[0]);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,74 +0,0 @@
|
||||||
/**
|
|
||||||
* @file LiquidTransportData.h
|
|
||||||
* Header file defining class LiquidTransportData
|
|
||||||
*/
|
|
||||||
|
|
||||||
// This file is part of Cantera. See License.txt in the top-level directory or
|
|
||||||
// at http://www.cantera.org/license.txt for license and copyright information.
|
|
||||||
|
|
||||||
#ifndef CT_LIQUIDTRANSPORTDATA_H
|
|
||||||
#define CT_LIQUIDTRANSPORTDATA_H
|
|
||||||
|
|
||||||
#include "TransportBase.h"
|
|
||||||
#include "LTPspecies.h"
|
|
||||||
#include "TransportData.h"
|
|
||||||
|
|
||||||
namespace Cantera
|
|
||||||
{
|
|
||||||
|
|
||||||
//! Class LiquidTransportData holds transport parameters for a
|
|
||||||
//! specific liquid-phase species.
|
|
||||||
/*!
|
|
||||||
* @deprecated To be removed after Cantera 2.4
|
|
||||||
*
|
|
||||||
* A LiquidTransportData object is created for each species.
|
|
||||||
*
|
|
||||||
* This class is mainly used to collect transport properties from the parse
|
|
||||||
* phase in the TransportFactory and transfer them to the Transport class.
|
|
||||||
* Transport properties are expressed by subclasses of LTPspecies. One may
|
|
||||||
* need to be careful about deleting pointers to LTPspecies objects created in
|
|
||||||
* the TransportFactory.
|
|
||||||
*
|
|
||||||
* All of the pointers in this class are shallow pointers. Therefore, this
|
|
||||||
* is a passthrough class, which keeps track of pointer ownership by zeroing
|
|
||||||
* pointers as we go. Yes, Yes, yes, this is not good.
|
|
||||||
*/
|
|
||||||
class LiquidTransportData : public TransportData
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
LiquidTransportData();
|
|
||||||
LiquidTransportData(const LiquidTransportData& right);
|
|
||||||
LiquidTransportData& operator=(const LiquidTransportData& right);
|
|
||||||
~LiquidTransportData();
|
|
||||||
|
|
||||||
//! A LiquidTransportData object is instantiated for each species.
|
|
||||||
//! This is the species name for which this object is instantiated.
|
|
||||||
std::string speciesName;
|
|
||||||
|
|
||||||
//! Model type for the hydroradius
|
|
||||||
LTPspecies* hydroRadius;
|
|
||||||
|
|
||||||
//! Model type for the viscosity
|
|
||||||
LTPspecies* viscosity;
|
|
||||||
|
|
||||||
//! Model type for the ionic conductivity
|
|
||||||
LTPspecies* ionConductivity;
|
|
||||||
|
|
||||||
//! Model type for the mobility ratio
|
|
||||||
std::vector<LTPspecies*> mobilityRatio;
|
|
||||||
|
|
||||||
//! Model type for the self diffusion coefficients
|
|
||||||
std::vector<LTPspecies*> selfDiffusion;
|
|
||||||
|
|
||||||
//! Model type for the thermal conductivity
|
|
||||||
LTPspecies* thermalCond;
|
|
||||||
|
|
||||||
//! Model type for the electrical conductivity
|
|
||||||
LTPspecies* electCond;
|
|
||||||
|
|
||||||
//! Model type for the speciesDiffusivity
|
|
||||||
LTPspecies* speciesDiffusivity;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,143 +0,0 @@
|
||||||
/**
|
|
||||||
* @file LiquidTransportParams.h
|
|
||||||
* Header file defining class LiquidTransportParams
|
|
||||||
*/
|
|
||||||
|
|
||||||
// This file is part of Cantera. See License.txt in the top-level directory or
|
|
||||||
// at http://www.cantera.org/license.txt for license and copyright information.
|
|
||||||
|
|
||||||
#ifndef CT_LIQUIDTRANSPORTPARAMS_H
|
|
||||||
#define CT_LIQUIDTRANSPORTPARAMS_H
|
|
||||||
|
|
||||||
#include "TransportParams.h"
|
|
||||||
#include "LiquidTranInteraction.h"
|
|
||||||
|
|
||||||
namespace Cantera
|
|
||||||
{
|
|
||||||
|
|
||||||
//! Class LiquidTransportParams holds transport model parameters relevant to
|
|
||||||
//! transport in mixtures.
|
|
||||||
/*!
|
|
||||||
* @deprecated To be removed after Cantera 2.4
|
|
||||||
*
|
|
||||||
* This class is used by TransportFactory to initialize transport objects.
|
|
||||||
*/
|
|
||||||
class LiquidTransportParams : public TransportParams
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
LiquidTransportParams();
|
|
||||||
~LiquidTransportParams();
|
|
||||||
LiquidTransportParams(const LiquidTransportParams& right) = delete;
|
|
||||||
LiquidTransportParams& operator=(const LiquidTransportParams& right) = delete;
|
|
||||||
|
|
||||||
//! Species transport parameters
|
|
||||||
std::vector<LiquidTransportData> LTData;
|
|
||||||
|
|
||||||
//! Object that specifies the viscosity interaction for the mixture
|
|
||||||
LiquidTranInteraction* viscosity;
|
|
||||||
|
|
||||||
//! Object that specifies the ionic Conductivity of the mixture
|
|
||||||
LiquidTranInteraction* ionConductivity;
|
|
||||||
|
|
||||||
//! Vector of pointer to the LiquidTranInteraction object which handles the
|
|
||||||
//! calculation of the mobility ratios for the phase
|
|
||||||
/*!
|
|
||||||
* The mobility ratio is defined via the following quantity where i and j
|
|
||||||
* are species indices.
|
|
||||||
*
|
|
||||||
* mobRat(i,j) = mu_i / mu_j
|
|
||||||
*
|
|
||||||
* It is returned in fortran-ordering format. i.e. it is returned as
|
|
||||||
* mobRat[k], where
|
|
||||||
*
|
|
||||||
* k = j * nsp + i
|
|
||||||
*
|
|
||||||
* Length = nsp * nsp
|
|
||||||
*/
|
|
||||||
std::vector<LiquidTranInteraction*> mobilityRatio;
|
|
||||||
|
|
||||||
//! Vector of pointer to the LiquidTranInteraction object which handles the
|
|
||||||
//! calculation of each species' self diffusion coefficient for the phase
|
|
||||||
std::vector<LiquidTranInteraction*> selfDiffusion;
|
|
||||||
|
|
||||||
//! Pointer to the LiquidTranInteraction object which handles the
|
|
||||||
//! calculation of the mixture thermal conductivity for the phase
|
|
||||||
LiquidTranInteraction* thermalCond;
|
|
||||||
|
|
||||||
//! Pointer to the LiquidTranInteraction object which handles the
|
|
||||||
//! calculation of the species diffusivity for the phase
|
|
||||||
LiquidTranInteraction* speciesDiffusivity;
|
|
||||||
|
|
||||||
//! Pointer to the LiquidTranInteraction object which handles the
|
|
||||||
//! calculation of the electrical conductivity for the phase
|
|
||||||
LiquidTranInteraction* electCond;
|
|
||||||
|
|
||||||
//! Pointer to the LiquidTranInteraction object which handles the
|
|
||||||
//! calculation of the hydrodynamic radius for the phase
|
|
||||||
/*!
|
|
||||||
* @note I don't understand at the moment how one can define a
|
|
||||||
* hydrodynamic radius for the phase
|
|
||||||
*/
|
|
||||||
LiquidTranInteraction* hydroRadius;
|
|
||||||
|
|
||||||
//! Model for species interaction effects for viscosity
|
|
||||||
//! Takes enum LiquidTranMixingModel
|
|
||||||
LiquidTranMixingModel model_viscosity;
|
|
||||||
|
|
||||||
//! Model for species interaction effects for ionic conductivity
|
|
||||||
//! Takes enum LiquidTranMixingModel
|
|
||||||
LiquidTranMixingModel model_ionConductivity;
|
|
||||||
|
|
||||||
//! Model for species interaction effects for mobility ratio
|
|
||||||
//! Takes enum LiquidTranMixingModel
|
|
||||||
std::vector<LiquidTranMixingModel*> model_mobilityRatio;
|
|
||||||
|
|
||||||
//! Model for species interaction effects for mobility ratio
|
|
||||||
//! Takes enum LiquidTranMixingModel
|
|
||||||
std::vector<LiquidTranMixingModel*> model_selfDiffusion;
|
|
||||||
|
|
||||||
//! Interaction associated with linear weighting of
|
|
||||||
//! thermal conductivity.
|
|
||||||
/**
|
|
||||||
* This is used for either LTI_MODEL_MASSFRACS or LTI_MODEL_MOLEFRACS. The
|
|
||||||
* overall formula for the mixture viscosity is
|
|
||||||
*
|
|
||||||
* \f[ \eta_{mix} = \sum_i X_i \eta_i + \sum_i \sum_j X_i X_j A_{i,j} \f].
|
|
||||||
*/
|
|
||||||
DenseMatrix thermalCond_Aij;
|
|
||||||
|
|
||||||
//! Model for species interaction effects for mass diffusivity
|
|
||||||
//! Takes enum LiquidTranMixingModel
|
|
||||||
LiquidTranMixingModel model_speciesDiffusivity;
|
|
||||||
|
|
||||||
//! Interaction associated with linear weighting of
|
|
||||||
//! thermal conductivity.
|
|
||||||
/**
|
|
||||||
* This is used for either LTI_MODEL_PAIRWISE_INTERACTION or
|
|
||||||
* LTI_MODEL_STEFANMAXWELL_PPN. These provide species interaction
|
|
||||||
* coefficients associated with the Stefan-Maxwell formulation.
|
|
||||||
*/
|
|
||||||
DenseMatrix diff_Dij;
|
|
||||||
|
|
||||||
//! Model for species interaction effects for hydrodynamic radius
|
|
||||||
//! Takes enum LiquidTranMixingModel
|
|
||||||
LiquidTranMixingModel model_hydroradius;
|
|
||||||
|
|
||||||
//! Interaction associated with hydrodynamic radius.
|
|
||||||
/**
|
|
||||||
* Not yet implemented
|
|
||||||
*/
|
|
||||||
DenseMatrix radius_Aij;
|
|
||||||
|
|
||||||
//! Default composition dependence of the transport properties
|
|
||||||
/*!
|
|
||||||
* Permissible types of composition dependencies
|
|
||||||
* 0 - Solvent values (i.e., species 0) contributes only
|
|
||||||
* 1 - linear combination of mole fractions;
|
|
||||||
*/
|
|
||||||
LiquidTranMixingModel compositionDepTypeDefault_;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,694 +0,0 @@
|
||||||
/**
|
|
||||||
* @file SimpleTransport.h
|
|
||||||
* Header file for the class SimpleTransport which provides simple
|
|
||||||
* transport properties for liquids and solids
|
|
||||||
* (see \ref tranprops and \link Cantera::SimpleTransport SimpleTransport \endlink) .
|
|
||||||
*/
|
|
||||||
|
|
||||||
// This file is part of Cantera. See License.txt in the top-level directory or
|
|
||||||
// at http://www.cantera.org/license.txt for license and copyright information.
|
|
||||||
|
|
||||||
#ifndef CT_SIMPLETRAN_H
|
|
||||||
#define CT_SIMPLETRAN_H
|
|
||||||
|
|
||||||
#include "LiquidTransportParams.h"
|
|
||||||
|
|
||||||
namespace Cantera
|
|
||||||
{
|
|
||||||
//! Class SimpleTransport implements mixture-averaged transport properties for
|
|
||||||
//! liquid phases.
|
|
||||||
/*!
|
|
||||||
* @deprecated To be removed after Cantera 2.4
|
|
||||||
*
|
|
||||||
* The model is based on that described by Newman, Electrochemical Systems
|
|
||||||
*
|
|
||||||
* The velocity of species i may be described by the following equation p. 297
|
|
||||||
* (12.1)
|
|
||||||
*
|
|
||||||
* \f[
|
|
||||||
* c_i \nabla \mu_i = R T \sum_j \frac{c_i c_j}{c_T D_{ij}}
|
|
||||||
* (\mathbf{v}_j - \mathbf{v}_i)
|
|
||||||
* \f]
|
|
||||||
*
|
|
||||||
* This as written is degenerate by 1 dof.
|
|
||||||
*
|
|
||||||
* To fix this we must add in the definition of the mass averaged velocity of
|
|
||||||
* the solution. We will call the simple bold-faced \f$\mathbf{v} \f$ symbol the
|
|
||||||
* mass-averaged velocity. Then, the relation between \f$\mathbf{v}\f$ and the
|
|
||||||
* individual species velocities is \f$\mathbf{v}_i\f$
|
|
||||||
*
|
|
||||||
* \f[
|
|
||||||
* \rho_i \mathbf{v}_i = \rho_i \mathbf{v} + \mathbf{j}_i
|
|
||||||
* \f]
|
|
||||||
* where \f$\mathbf{j}_i\f$ are the diffusional fluxes of species i with respect
|
|
||||||
* to the mass averaged velocity and
|
|
||||||
*
|
|
||||||
* \f[
|
|
||||||
* \sum_i \mathbf{j}_i = 0
|
|
||||||
* \f]
|
|
||||||
*
|
|
||||||
* and
|
|
||||||
*
|
|
||||||
* \f[
|
|
||||||
* \sum_i \rho_i \mathbf{v}_i = \rho \mathbf{v}
|
|
||||||
* \f]
|
|
||||||
*
|
|
||||||
* Using these definitions, we can write
|
|
||||||
*
|
|
||||||
* \f[
|
|
||||||
* \mathbf{v}_i = \mathbf{v} + \frac{\mathbf{j}_i}{\rho_i}
|
|
||||||
* \f]
|
|
||||||
*
|
|
||||||
* \f[
|
|
||||||
* c_i \nabla \mu_i = R T \sum_j \frac{c_i c_j}{c_T D_{ij}}
|
|
||||||
* (\frac{\mathbf{j}_j}{\rho_j} - \frac{\mathbf{j}_i}{\rho_i})
|
|
||||||
* = R T \sum_j \frac{1}{D_{ij}}
|
|
||||||
* (\frac{x_i \mathbf{j}_j}{M_j} - \frac{x_j \mathbf{j}_i}{M_i})
|
|
||||||
* \f]
|
|
||||||
*
|
|
||||||
* The equations that we actually solve are
|
|
||||||
*
|
|
||||||
* \f[
|
|
||||||
* c_i \nabla \mu_i =
|
|
||||||
* = R T \sum_j \frac{1}{D_{ij}}
|
|
||||||
* (\frac{x_i \mathbf{j}_j}{M_j} - \frac{x_j \mathbf{j}_i}{M_i})
|
|
||||||
* \f]
|
|
||||||
* and we replace the 0th equation with the following:
|
|
||||||
*
|
|
||||||
* \f[
|
|
||||||
* \sum_i \mathbf{j}_i = 0
|
|
||||||
* \f]
|
|
||||||
*
|
|
||||||
* When there are charged species, we replace the RHS with the gradient of the
|
|
||||||
* electrochemical potential to obtain the modified equation
|
|
||||||
*
|
|
||||||
* \f[
|
|
||||||
* c_i \nabla \mu_i + c_i F z_i \nabla \Phi
|
|
||||||
* = R T \sum_j \frac{1}{D_{ij}}
|
|
||||||
* (\frac{x_i \mathbf{j}_j}{M_j} - \frac{x_j \mathbf{j}_i}{M_i})
|
|
||||||
* \f]
|
|
||||||
*
|
|
||||||
* With this formulation we may solve for the diffusion velocities, without
|
|
||||||
* having to worry about what the mass averaged velocity is.
|
|
||||||
*
|
|
||||||
* ## Viscosity Calculation
|
|
||||||
*
|
|
||||||
* The viscosity calculation may be broken down into two parts. In the first
|
|
||||||
* part, the viscosity of the pure species are calculated In the second part, a
|
|
||||||
* mixing rule is applied. There are two mixing rules. Solvent-only and mixture-
|
|
||||||
* averaged.
|
|
||||||
*
|
|
||||||
* For the solvent-only mixing rule, we use the pure species viscosity
|
|
||||||
* calculated for the solvent as the viscosity of the entire mixture. For the
|
|
||||||
* mixture averaged rule we do a mole fraction based average of the pure species
|
|
||||||
* viscosities:
|
|
||||||
*
|
|
||||||
* Solvent-only:
|
|
||||||
* \f[
|
|
||||||
* \mu = \mu_0
|
|
||||||
* \f]
|
|
||||||
* Mixture-average:
|
|
||||||
* \f[
|
|
||||||
* \mu = \sum_k {\mu_k X_k}
|
|
||||||
* \f]
|
|
||||||
*
|
|
||||||
* ## Calculate of the Binary Diffusion Coefficients
|
|
||||||
*
|
|
||||||
* The binary diffusion coefficients are obtained from the pure species
|
|
||||||
* diffusion coefficients using an additive process
|
|
||||||
*
|
|
||||||
* \f[
|
|
||||||
* D_{i,j} = \frac{1}{2} \left( D^0_i(T) + D^0_j(T) \right)
|
|
||||||
* \f]
|
|
||||||
*
|
|
||||||
* ## Electrical Mobilities
|
|
||||||
*
|
|
||||||
* The mobility \f$ \mu^e_k \f$ is calculated from the diffusion coefficient
|
|
||||||
* using the Einstein relation.
|
|
||||||
*
|
|
||||||
* \f[
|
|
||||||
* \mu^e_k = \frac{F D_k}{R T}
|
|
||||||
* \f]
|
|
||||||
*
|
|
||||||
* The diffusion coefficients, \f$ D_k \f$ , is calculated from a call to the
|
|
||||||
* mixture diffusion coefficient routine.
|
|
||||||
*
|
|
||||||
* ## Species Diffusive Fluxes
|
|
||||||
*
|
|
||||||
* The diffusive mass flux of species \e k is computed from the following
|
|
||||||
* formula
|
|
||||||
*
|
|
||||||
* Usually the specified solution average velocity is the mass averaged
|
|
||||||
* velocity. This is changed in some subclasses, however.
|
|
||||||
*
|
|
||||||
* \f[
|
|
||||||
* j_k = - c^T M_k D_k \nabla X_k - \rho Y_k V_c
|
|
||||||
* \f]
|
|
||||||
*
|
|
||||||
* where V_c is the correction velocity
|
|
||||||
*
|
|
||||||
* \f[
|
|
||||||
* \rho V_c = - \sum_j {c^T M_j D_j \nabla X_j}
|
|
||||||
* \f]
|
|
||||||
*
|
|
||||||
* In the above equation, \f$ D_k \f$ is the mixture diffusivity for species k
|
|
||||||
* calculated for the current conditions, which may depend on T, P, and X_k. \f$
|
|
||||||
* C^T \f$ is the total concentration of the phase.
|
|
||||||
*
|
|
||||||
* When this is electrical migration, the formulas above are enhanced to
|
|
||||||
*
|
|
||||||
* \f[
|
|
||||||
* j_k = - C^T M_k D_k \nabla X_k + F C^T M_k \frac{D_k}{ R T } X_k z_k \nabla V - \rho Y_k V_c
|
|
||||||
* \f]
|
|
||||||
*
|
|
||||||
* where V_c is the correction velocity
|
|
||||||
*
|
|
||||||
* \f[
|
|
||||||
* \rho V_c = - \sum_j {c^T M_j D_j \nabla X_j} + \sum_j F C^T M_j \frac{D_j}{ R T } X_j z_j \nabla V
|
|
||||||
* \f]
|
|
||||||
*
|
|
||||||
* ## Species Diffusional Velocities
|
|
||||||
*
|
|
||||||
* Species diffusional velocities are calculated from the species diffusional
|
|
||||||
* fluxes, within this object, using the following formula for the diffusional
|
|
||||||
* velocity of the kth species, \f$ V_k^d \f$
|
|
||||||
*
|
|
||||||
* \f[
|
|
||||||
* j_k = \rho Y_k V_k^d
|
|
||||||
* \f]
|
|
||||||
*
|
|
||||||
* TODO: This object has to be made compatible with different types of reference
|
|
||||||
* velocities. Right now, elements of the formulas are only compatible with the
|
|
||||||
* mass-averaged velocity.
|
|
||||||
*
|
|
||||||
* @ingroup tranprops
|
|
||||||
*/
|
|
||||||
class SimpleTransport : public Transport
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
//! Default constructor.
|
|
||||||
/*!
|
|
||||||
* This requires call to initLiquid(LiquidTransportParams& tr) after filling
|
|
||||||
* LiquidTransportParams to complete instantiation. The filling of
|
|
||||||
* LiquidTransportParams is currently carried out in the TransportFactory
|
|
||||||
* class, but might be moved at some point.
|
|
||||||
*
|
|
||||||
* @param thermo ThermoPhase object holding species information.
|
|
||||||
* @param ndim Number of spatial dimensions.
|
|
||||||
*/
|
|
||||||
SimpleTransport(thermo_t* thermo = 0, int ndim = 1);
|
|
||||||
|
|
||||||
virtual ~SimpleTransport();
|
|
||||||
|
|
||||||
//! Initialize the transport object
|
|
||||||
/*!
|
|
||||||
* Here we change all of the internal dimensions to be sufficient.
|
|
||||||
* We get the object ready to do property evaluations.
|
|
||||||
*
|
|
||||||
* @param tr Transport parameters for all of the species in the phase.
|
|
||||||
*/
|
|
||||||
virtual bool initLiquid(LiquidTransportParams& tr);
|
|
||||||
|
|
||||||
void setCompositionDependence(LiquidTranMixingModel model) {
|
|
||||||
compositionDepType_ = model;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual std::string transportType() const {
|
|
||||||
return "Simple";
|
|
||||||
}
|
|
||||||
|
|
||||||
//! Returns the mixture viscosity of the solution
|
|
||||||
/*!
|
|
||||||
* The viscosity is computed using the general mixture rules
|
|
||||||
* specified in the variable compositionDepType_.
|
|
||||||
*
|
|
||||||
* Solvent-only:
|
|
||||||
* \f[
|
|
||||||
* \mu = \mu_0
|
|
||||||
* \f]
|
|
||||||
* Mixture-average:
|
|
||||||
* \f[
|
|
||||||
* \mu = \sum_k {\mu_k X_k}
|
|
||||||
* \f]
|
|
||||||
*
|
|
||||||
* Here \f$ \mu_k \f$ is the viscosity of pure species \e k.
|
|
||||||
*
|
|
||||||
* units are Pa s or kg/m/s
|
|
||||||
*
|
|
||||||
* @see updateViscosity_T();
|
|
||||||
*/
|
|
||||||
virtual doublereal viscosity();
|
|
||||||
|
|
||||||
//! Returns the pure species viscosities
|
|
||||||
/*!
|
|
||||||
* The pure species viscosities are to be given in an Arrhenius form in
|
|
||||||
* accordance with activated-jump-process dominated transport.
|
|
||||||
*
|
|
||||||
* units are Pa s or kg/m/s
|
|
||||||
*
|
|
||||||
* @param visc Return the species viscosities as a vector of length m_nsp
|
|
||||||
*/
|
|
||||||
virtual void getSpeciesViscosities(doublereal* const visc);
|
|
||||||
|
|
||||||
//! Returns the binary diffusion coefficients
|
|
||||||
virtual void getBinaryDiffCoeffs(const size_t ld, doublereal* const d);
|
|
||||||
|
|
||||||
//! Get the Mixture diffusion coefficients
|
|
||||||
/*!
|
|
||||||
* @param d vector of mixture diffusion coefficients
|
|
||||||
* units = m2 s-1. length = number of species
|
|
||||||
*/
|
|
||||||
virtual void getMixDiffCoeffs(doublereal* const d);
|
|
||||||
|
|
||||||
//! Return the thermal diffusion coefficients
|
|
||||||
/*!
|
|
||||||
* These are all zero for this simple implementation
|
|
||||||
*
|
|
||||||
* @param dt thermal diffusion coefficients
|
|
||||||
*/
|
|
||||||
virtual void getThermalDiffCoeffs(doublereal* const dt);
|
|
||||||
|
|
||||||
//! Returns the mixture thermal conductivity of the solution
|
|
||||||
/*!
|
|
||||||
* The thermal is computed using the general mixture rules
|
|
||||||
* specified in the variable compositionDepType_.
|
|
||||||
*
|
|
||||||
* Controlling update boolean = m_condmix_ok
|
|
||||||
*
|
|
||||||
* Units are in W/m/K or equivalently kg m / s3 / K
|
|
||||||
*
|
|
||||||
* Solvent-only:
|
|
||||||
* \f[
|
|
||||||
* \lambda = \lambda_0
|
|
||||||
* \f]
|
|
||||||
* Mixture-average:
|
|
||||||
* \f[
|
|
||||||
* \lambda = \sum_k {\lambda_k X_k}
|
|
||||||
* \f]
|
|
||||||
*
|
|
||||||
* Here \f$ \lambda_k \f$ is the thermal conductivity of pure species \e k.
|
|
||||||
*
|
|
||||||
* @see updateCond_T();
|
|
||||||
*/
|
|
||||||
virtual doublereal thermalConductivity();
|
|
||||||
|
|
||||||
virtual void getMobilities(doublereal* const mobil_e);
|
|
||||||
|
|
||||||
virtual void getFluidMobilities(doublereal* const mobil_f);
|
|
||||||
|
|
||||||
//! Specify the value of the gradient of the voltage
|
|
||||||
/*!
|
|
||||||
* @param grad_V Gradient of the voltage (length num dimensions);
|
|
||||||
*/
|
|
||||||
virtual void set_Grad_V(const doublereal* const grad_V);
|
|
||||||
|
|
||||||
//! Specify the value of the gradient of the temperature
|
|
||||||
/*!
|
|
||||||
* @param grad_T Gradient of the temperature (length num dimensions);
|
|
||||||
*/
|
|
||||||
virtual void set_Grad_T(const doublereal* const grad_T);
|
|
||||||
|
|
||||||
//! Specify the value of the gradient of the MoleFractions
|
|
||||||
/*!
|
|
||||||
* @param grad_X Gradient of the mole fractions(length nsp * num dimensions);
|
|
||||||
*/
|
|
||||||
virtual void set_Grad_X(const doublereal* const grad_X);
|
|
||||||
|
|
||||||
//! Get the species diffusive velocities wrt to the averaged velocity,
|
|
||||||
//! given the gradients in mole fraction and temperature
|
|
||||||
/*!
|
|
||||||
* The average velocity can be computed on a mole-weighted
|
|
||||||
* or mass-weighted basis, or the diffusion velocities may
|
|
||||||
* be specified as relative to a specific species (i.e. a
|
|
||||||
* solvent) all according to the velocityBasis input parameter.
|
|
||||||
*
|
|
||||||
* Units for the returned velocities are m s-1.
|
|
||||||
*
|
|
||||||
* @param ndim Number of dimensions in the flux expressions
|
|
||||||
* @param grad_T Gradient of the temperature (length = ndim)
|
|
||||||
* @param ldx Leading dimension of the grad_X array (usually equal to
|
|
||||||
* m_nsp but not always)
|
|
||||||
* @param grad_X Gradients of the mole fraction. Flat vector with the m_nsp
|
|
||||||
* in the inner loop. length = ldx * ndim
|
|
||||||
* @param ldf Leading dimension of the fluxes array (usually equal to
|
|
||||||
* m_nsp but not always)
|
|
||||||
* @param Vdiff Output of the diffusive velocities. Flat vector with the
|
|
||||||
* m_nsp in the inner loop. length = ldx * ndim
|
|
||||||
*/
|
|
||||||
virtual void getSpeciesVdiff(size_t ndim,
|
|
||||||
const doublereal* grad_T,
|
|
||||||
int ldx,
|
|
||||||
const doublereal* grad_X,
|
|
||||||
int ldf,
|
|
||||||
doublereal* Vdiff);
|
|
||||||
|
|
||||||
//! Get the species diffusive velocities wrt to the averaged velocity, given
|
|
||||||
//! the gradients in mole fraction, temperature and electrostatic potential.
|
|
||||||
/*!
|
|
||||||
* The average velocity can be computed on a mole-weighted
|
|
||||||
* or mass-weighted basis, or the diffusion velocities may
|
|
||||||
* be specified as relative to a specific species (i.e. a
|
|
||||||
* solvent) all according to the velocityBasis input parameter.
|
|
||||||
*
|
|
||||||
* Units for the returned velocities are m s-1.
|
|
||||||
*
|
|
||||||
* @param ndim Number of dimensions in the flux expressions
|
|
||||||
* @param grad_T Gradient of the temperature (length = ndim)
|
|
||||||
* @param ldx Leading dimension of the grad_X array (usually equal
|
|
||||||
* to m_nsp but not always)
|
|
||||||
* @param grad_X Gradients of the mole fraction. Flat vector with the
|
|
||||||
* m_nsp in the inner loop. length = ldx * ndim
|
|
||||||
* @param ldf Leading dimension of the fluxes array (usually equal to
|
|
||||||
* m_nsp but not always)
|
|
||||||
* @param grad_Phi Gradients of the electrostatic potential (length =
|
|
||||||
* ndim)
|
|
||||||
* @param Vdiff Output of the species diffusion velocities. Flat vector
|
|
||||||
* with the m_nsp in the inner loop. length = ldx * ndim
|
|
||||||
*/
|
|
||||||
virtual void getSpeciesVdiffES(size_t ndim, const doublereal* grad_T,
|
|
||||||
int ldx, const doublereal* grad_X,
|
|
||||||
int ldf, const doublereal* grad_Phi,
|
|
||||||
doublereal* Vdiff);
|
|
||||||
|
|
||||||
//! Get the species diffusive mass fluxes wrt to the specified solution
|
|
||||||
//! averaged velocity, given the gradients in mole fraction and temperature
|
|
||||||
/*!
|
|
||||||
* units = kg/m2/s
|
|
||||||
*
|
|
||||||
* The diffusive mass flux of species \e k is computed from the following
|
|
||||||
* formula
|
|
||||||
*
|
|
||||||
* Usually the specified solution average velocity is the mass averaged
|
|
||||||
* velocity. This is changed in some subclasses, however.
|
|
||||||
*
|
|
||||||
* \f[
|
|
||||||
* j_k = - \rho M_k D_k \nabla X_k - Y_k V_c
|
|
||||||
* \f]
|
|
||||||
*
|
|
||||||
* where V_c is the correction velocity
|
|
||||||
*
|
|
||||||
* \f[
|
|
||||||
* V_c = - \sum_j {\rho M_j D_j \nabla X_j}
|
|
||||||
* \f]
|
|
||||||
*
|
|
||||||
* @param ndim The number of spatial dimensions (1, 2, or 3).
|
|
||||||
* @param grad_T The temperature gradient (ignored in this model).
|
|
||||||
* @param ldx Leading dimension of the grad_X array.
|
|
||||||
* @param grad_X Gradient of the mole fractions(length nsp * num dimensions);
|
|
||||||
* @param ldf Leading dimension of the fluxes array.
|
|
||||||
* @param fluxes Output fluxes of species.
|
|
||||||
*/
|
|
||||||
virtual void getSpeciesFluxes(size_t ndim, const doublereal* const grad_T,
|
|
||||||
size_t ldx, const doublereal* const grad_X,
|
|
||||||
size_t ldf, doublereal* const fluxes);
|
|
||||||
|
|
||||||
//! Return the species diffusive mass fluxes wrt to the mass averaged
|
|
||||||
//! velocity,
|
|
||||||
/*!
|
|
||||||
* units = kg/m2/s
|
|
||||||
*
|
|
||||||
* Internally, gradients in the in mole fraction, temperature
|
|
||||||
* and electrostatic potential contribute to the diffusive flux
|
|
||||||
*
|
|
||||||
* The diffusive mass flux of species \e k is computed from the following
|
|
||||||
* formula
|
|
||||||
*
|
|
||||||
* \f[
|
|
||||||
* j_k = - \rho M_k D_k \nabla X_k - Y_k V_c
|
|
||||||
* \f]
|
|
||||||
*
|
|
||||||
* where V_c is the correction velocity
|
|
||||||
*
|
|
||||||
* \f[
|
|
||||||
* V_c = - \sum_j {\rho M_j D_j \nabla X_j}
|
|
||||||
* \f]
|
|
||||||
*
|
|
||||||
* @param ldf stride of the fluxes array. Must be equal to or greater
|
|
||||||
* than the number of species.
|
|
||||||
* @param fluxes Vector of calculated fluxes
|
|
||||||
*/
|
|
||||||
virtual void getSpeciesFluxesExt(size_t ldf, doublereal* fluxes);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
//! Handles the effects of changes in the Temperature, internally within the
|
|
||||||
//! object.
|
|
||||||
/*!
|
|
||||||
* This is called whenever a transport property is requested. The first task
|
|
||||||
* is to check whether the temperature has changed since the last call to
|
|
||||||
* update_T(). If it hasn't then an immediate return is carried out.
|
|
||||||
*
|
|
||||||
* @returns true if the temperature has changed, and false otherwise
|
|
||||||
*/
|
|
||||||
virtual bool update_T();
|
|
||||||
|
|
||||||
//! Handles the effects of changes in the mixture concentration
|
|
||||||
/*!
|
|
||||||
* This is called for every interface call to check whether the
|
|
||||||
* concentrations have changed. Concentrations change whenever the pressure
|
|
||||||
* or the mole fraction has changed. If it has changed, the recalculations
|
|
||||||
* should be done.
|
|
||||||
*
|
|
||||||
* Note this should be a lightweight function since it's part of all of the
|
|
||||||
* interfaces.
|
|
||||||
*/
|
|
||||||
virtual bool update_C();
|
|
||||||
|
|
||||||
//! Update the temperature-dependent viscosity terms. Updates the array of
|
|
||||||
//! pure species viscosities, and the weighting functions in the viscosity
|
|
||||||
//! mixture rule.
|
|
||||||
/*!
|
|
||||||
* The flag m_visc_temp_ok is set to true.
|
|
||||||
*/
|
|
||||||
void updateViscosity_T();
|
|
||||||
|
|
||||||
//! Update the temperature-dependent parts of the mixture-averaged
|
|
||||||
//! thermal conductivity.
|
|
||||||
void updateCond_T();
|
|
||||||
|
|
||||||
//! Update the binary diffusion coefficients wrt T.
|
|
||||||
/*!
|
|
||||||
* These are evaluated from the polynomial fits at unit pressure (1 Pa).
|
|
||||||
*/
|
|
||||||
void updateDiff_T();
|
|
||||||
|
|
||||||
private:
|
|
||||||
//! Composition dependence of the transport properties
|
|
||||||
/*!
|
|
||||||
* The following coefficients are allowed to have simple composition
|
|
||||||
* dependencies:
|
|
||||||
* - mixture viscosity
|
|
||||||
* - mixture thermal conductivity
|
|
||||||
*
|
|
||||||
* Permissible types of composition dependencies
|
|
||||||
* 0 - Solvent values (i.e., species 0) contributes only
|
|
||||||
* 1 - linear combination of mole fractions;
|
|
||||||
*/
|
|
||||||
enum LiquidTranMixingModel compositionDepType_;
|
|
||||||
|
|
||||||
//! Boolean indicating whether to use the hydrodynamic radius formulation
|
|
||||||
/*!
|
|
||||||
* If true, then the diffusion coefficient is calculated from the
|
|
||||||
* hydrodynamic radius.
|
|
||||||
*/
|
|
||||||
bool useHydroRadius_;
|
|
||||||
|
|
||||||
//! Boolean indicating whether electro-migration term should be added
|
|
||||||
bool doMigration_;
|
|
||||||
|
|
||||||
//! Local Copy of the molecular weights of the species
|
|
||||||
/*!
|
|
||||||
* Length is Equal to the number of species in the mechanism.
|
|
||||||
*/
|
|
||||||
vector_fp m_mw;
|
|
||||||
|
|
||||||
//! Pure species viscosities in Arrhenius temperature-dependent form.
|
|
||||||
std::vector<LTPspecies*> m_coeffVisc_Ns;
|
|
||||||
|
|
||||||
//! Pure species thermal conductivities in Arrhenius temperature-dependent form.
|
|
||||||
std::vector<LTPspecies*> m_coeffLambda_Ns;
|
|
||||||
|
|
||||||
//! Pure species viscosities in Arrhenius temperature-dependent form.
|
|
||||||
std::vector<LTPspecies*> m_coeffDiff_Ns;
|
|
||||||
|
|
||||||
//! Hydrodynamic radius in LTPspecies form
|
|
||||||
std::vector<LTPspecies*> m_coeffHydroRadius_Ns;
|
|
||||||
|
|
||||||
//! Internal value of the gradient of the mole fraction vector
|
|
||||||
/*!
|
|
||||||
* Note, this is the only gradient value that can and perhaps should reflect
|
|
||||||
* the true state of the mole fractions in the application solution vector.
|
|
||||||
* In other words no cropping or massaging of the values to make sure they
|
|
||||||
* are above zero should occur. - developing ....
|
|
||||||
*
|
|
||||||
* m_nsp is the number of species in the fluid
|
|
||||||
* k is the species index
|
|
||||||
* n is the dimensional index (x, y, or z). It has a length equal to m_nDim
|
|
||||||
*
|
|
||||||
* m_Grad_X[n*m_nsp + k]
|
|
||||||
*/
|
|
||||||
vector_fp m_Grad_X;
|
|
||||||
|
|
||||||
//! Internal value of the gradient of the Temperature vector
|
|
||||||
/*!
|
|
||||||
* Generally, if a transport property needs this in its evaluation it
|
|
||||||
* will look to this place to get it.
|
|
||||||
*
|
|
||||||
* No internal property is precalculated based on gradients. Gradients
|
|
||||||
* are assumed to be freshly updated before every property call.
|
|
||||||
*/
|
|
||||||
vector_fp m_Grad_T;
|
|
||||||
|
|
||||||
//! Internal value of the gradient of the Pressure vector
|
|
||||||
/*!
|
|
||||||
* Generally, if a transport property needs this in its evaluation it
|
|
||||||
* will look to this place to get it.
|
|
||||||
*
|
|
||||||
* No internal property is precalculated based on gradients. Gradients
|
|
||||||
* are assumed to be freshly updated before every property call.
|
|
||||||
*/
|
|
||||||
vector_fp m_Grad_P;
|
|
||||||
|
|
||||||
//! Internal value of the gradient of the Electric Voltage
|
|
||||||
/*!
|
|
||||||
* Generally, if a transport property needs this in its evaluation it
|
|
||||||
* will look to this place to get it.
|
|
||||||
*
|
|
||||||
* No internal property is precalculated based on gradients. Gradients
|
|
||||||
* are assumed to be freshly updated before every property call.
|
|
||||||
*/
|
|
||||||
vector_fp m_Grad_V;
|
|
||||||
|
|
||||||
// property values
|
|
||||||
|
|
||||||
//! Vector of Species Diffusivities
|
|
||||||
/*!
|
|
||||||
* Depends on the temperature. We have set the pressure dependence to zero
|
|
||||||
* for this liquid phase constituitve model
|
|
||||||
*
|
|
||||||
* units m2/s
|
|
||||||
*/
|
|
||||||
vector_fp m_diffSpecies;
|
|
||||||
|
|
||||||
//! Species viscosities
|
|
||||||
/*!
|
|
||||||
* Viscosity of the species
|
|
||||||
* Length = number of species
|
|
||||||
*
|
|
||||||
* Depends on the temperature. We have set the pressure dependence to zero
|
|
||||||
* for this model
|
|
||||||
*
|
|
||||||
* controlling update boolean -> m_visc_temp_ok
|
|
||||||
*/
|
|
||||||
vector_fp m_viscSpecies;
|
|
||||||
|
|
||||||
//! Internal value of the species individual thermal conductivities
|
|
||||||
/*!
|
|
||||||
* Then a mixture rule is applied to get the solution conductivities
|
|
||||||
*
|
|
||||||
* Depends on the temperature and perhaps pressure, but
|
|
||||||
* not the species concentrations
|
|
||||||
*
|
|
||||||
* controlling update boolean -> m_cond_temp_ok
|
|
||||||
*/
|
|
||||||
vector_fp m_condSpecies;
|
|
||||||
|
|
||||||
//! State of the mole fraction vector.
|
|
||||||
int m_iStateMF;
|
|
||||||
|
|
||||||
//! Local copy of the mole fractions of the species in the phase
|
|
||||||
/*!
|
|
||||||
* The mole fractions here are assumed to be bounded by 0.0 and 1.0 and they
|
|
||||||
* are assumed to add up to one exactly. This mole fraction vector comes
|
|
||||||
* from the ThermoPhase object. Derivative quantities from this are referred
|
|
||||||
* to as bounded.
|
|
||||||
*
|
|
||||||
* Update info?
|
|
||||||
* length = m_nsp
|
|
||||||
*/
|
|
||||||
vector_fp m_molefracs;
|
|
||||||
|
|
||||||
//! Local copy of the concentrations of the species in the phase
|
|
||||||
/*!
|
|
||||||
* The concentrations are consistent with the m_molefracs vector which is
|
|
||||||
* bounded and sums to one.
|
|
||||||
*
|
|
||||||
* Update info?
|
|
||||||
* length = m_nsp
|
|
||||||
*/
|
|
||||||
vector_fp m_concentrations;
|
|
||||||
|
|
||||||
//! Local copy of the total concentration.
|
|
||||||
/*!
|
|
||||||
* This is consistent with the m_concentrations[] and m_molefracs[] vector.
|
|
||||||
*/
|
|
||||||
doublereal concTot_;
|
|
||||||
|
|
||||||
//! Mean molecular weight
|
|
||||||
doublereal meanMolecularWeight_;
|
|
||||||
|
|
||||||
//! Density
|
|
||||||
doublereal dens_;
|
|
||||||
|
|
||||||
//! Local copy of the charge of each species
|
|
||||||
/*!
|
|
||||||
* Contains the charge of each species (length m_nsp)
|
|
||||||
*/
|
|
||||||
vector_fp m_chargeSpecies;
|
|
||||||
|
|
||||||
//! Current Temperature -> locally stored
|
|
||||||
/*!
|
|
||||||
* This is used to test whether new temperature computations should be
|
|
||||||
* performed.
|
|
||||||
*/
|
|
||||||
doublereal m_temp;
|
|
||||||
|
|
||||||
//! Current value of the pressure
|
|
||||||
doublereal m_press;
|
|
||||||
|
|
||||||
//! Saved value of the mixture thermal conductivity
|
|
||||||
doublereal m_lambda;
|
|
||||||
|
|
||||||
//! Saved value of the mixture viscosity
|
|
||||||
doublereal m_viscmix;
|
|
||||||
|
|
||||||
//! work space
|
|
||||||
/*!
|
|
||||||
* Length is equal to m_nsp
|
|
||||||
*/
|
|
||||||
vector_fp m_spwork;
|
|
||||||
|
|
||||||
vector_fp m_fluxes;
|
|
||||||
|
|
||||||
//! Boolean indicating that the top-level mixture viscosity is current
|
|
||||||
/*!
|
|
||||||
* This is turned false for every change in T, P, or C.
|
|
||||||
*/
|
|
||||||
bool m_visc_mix_ok;
|
|
||||||
|
|
||||||
//! Boolean indicating that weight factors wrt viscosity is current
|
|
||||||
bool m_visc_temp_ok;
|
|
||||||
|
|
||||||
//! Boolean indicating that mixture diffusion coeffs are current
|
|
||||||
bool m_diff_mix_ok;
|
|
||||||
|
|
||||||
//! Boolean indicating that binary diffusion coeffs are current
|
|
||||||
bool m_diff_temp_ok;
|
|
||||||
|
|
||||||
//! Flag to indicate that the pure species conductivities
|
|
||||||
//! are current wrt the temperature
|
|
||||||
bool m_cond_temp_ok;
|
|
||||||
|
|
||||||
//! Boolean indicating that mixture conductivity is current
|
|
||||||
bool m_cond_mix_ok;
|
|
||||||
|
|
||||||
//! Number of dimensions
|
|
||||||
/*!
|
|
||||||
* Either 1, 2, or 3
|
|
||||||
*/
|
|
||||||
size_t m_nDim;
|
|
||||||
|
|
||||||
//! Temporary variable that stores the rho Vc value
|
|
||||||
double rhoVc[3];
|
|
||||||
};
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,188 +0,0 @@
|
||||||
/**
|
|
||||||
* @file SolidTransport.h
|
|
||||||
* Header file for defining the class SolidTransport, which handles transport
|
|
||||||
* of ions within solid phases
|
|
||||||
* (see \ref tranprops and \link Cantera::SolidTransport SolidTransport \endlink).
|
|
||||||
*/
|
|
||||||
|
|
||||||
// This file is part of Cantera. See License.txt in the top-level directory or
|
|
||||||
// at http://www.cantera.org/license.txt for license and copyright information.
|
|
||||||
|
|
||||||
#ifndef CT_SOLIDTRAN_H
|
|
||||||
#define CT_SOLIDTRAN_H
|
|
||||||
|
|
||||||
#include "LTPspecies.h"
|
|
||||||
#include "TransportBase.h"
|
|
||||||
|
|
||||||
namespace Cantera
|
|
||||||
{
|
|
||||||
//! Class SolidTransport implements transport properties for solids.
|
|
||||||
//! @ingroup tranprops
|
|
||||||
/*!
|
|
||||||
* @deprecated To be removed after Cantera 2.4
|
|
||||||
*
|
|
||||||
* @attention This class currently does not have any test cases or examples. Its
|
|
||||||
* implementation may be incomplete, and future changes to Cantera may
|
|
||||||
* unexpectedly cause this class to stop working. If you use this class,
|
|
||||||
* please consider contributing examples or test cases. In the absence of
|
|
||||||
* new tests or examples, this class may be deprecated and removed in a
|
|
||||||
* future version of Cantera. See
|
|
||||||
* https://github.com/Cantera/cantera/issues/267 for additional information.
|
|
||||||
*/
|
|
||||||
class SolidTransport : public Transport
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
SolidTransport();
|
|
||||||
|
|
||||||
virtual std::string transportType() const {
|
|
||||||
return "Solid";
|
|
||||||
}
|
|
||||||
|
|
||||||
//! Returns the ionic conductivity of the phase
|
|
||||||
/*!
|
|
||||||
* The thermo phase needs to be updated (temperature) prior to calling this.
|
|
||||||
* The ionConductivity calculation is handled by subclasses of LTPspecies as
|
|
||||||
* specified in the input file.
|
|
||||||
*/
|
|
||||||
virtual doublereal ionConductivity();
|
|
||||||
|
|
||||||
//! Returns the thermal conductivity of the phase
|
|
||||||
/*!
|
|
||||||
* The thermo phase needs to be updated (temperature) prior to calling this.
|
|
||||||
* The thermalConductivity calculation is handled by subclasses of
|
|
||||||
* LTPspecies as specified in the input file.
|
|
||||||
*
|
|
||||||
* There is also a legacy method to evaluate
|
|
||||||
* \f[
|
|
||||||
* \lambda = A T^n \exp(-E/RT)
|
|
||||||
* \f]
|
|
||||||
*/
|
|
||||||
virtual doublereal thermalConductivity();
|
|
||||||
|
|
||||||
//! Returns the electron conductivity of the phase
|
|
||||||
/*!
|
|
||||||
* The thermo phase needs to be updated (temperature) prior to calling
|
|
||||||
* this. The ionConductivity calculation is handled by subclasses of
|
|
||||||
* LTPspecies as specified in the input file.
|
|
||||||
*
|
|
||||||
* There is also a legacy multicomponent diffusion approach to electrical
|
|
||||||
* conductivity.
|
|
||||||
*/
|
|
||||||
virtual doublereal electricalConductivity();
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* The diffusivity of defects in the solid (m^2/s). The thermo phase needs
|
|
||||||
* to be updated (temperature) prior to calling this. The defectDiffusivity
|
|
||||||
* calculation is handled by subclasses of LTPspecies as specified in the
|
|
||||||
* input file.
|
|
||||||
*/
|
|
||||||
virtual doublereal defectDiffusivity();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The activity of defects in the solid. At some point this should be
|
|
||||||
* variable and the diffusion coefficient should depend on it.
|
|
||||||
*
|
|
||||||
* The thermo phase needs to be updated (temperature) prior to calling this.
|
|
||||||
* The defectActivity calculation is handled by subclasses of
|
|
||||||
* LTPspecies as specified in the input file.
|
|
||||||
*/
|
|
||||||
virtual doublereal defectActivity();
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The diffusion coefficients are computed from
|
|
||||||
*
|
|
||||||
* \f[
|
|
||||||
* D_k = A_k T^{n_k} \exp(-E_k/RT).
|
|
||||||
* \f]
|
|
||||||
*
|
|
||||||
* The diffusion coefficients are only non-zero for species for which
|
|
||||||
* parameters have been specified using method setParameters.
|
|
||||||
* @todo HEWSON WONDERS IF THE FOLLOWING ARE RELEVANT??
|
|
||||||
*/
|
|
||||||
virtual void getMixDiffCoeffs(doublereal* const d);
|
|
||||||
|
|
||||||
virtual void getMobilities(doublereal* const mobil);
|
|
||||||
|
|
||||||
virtual void setParameters(const int n, const int k, const doublereal* const p);
|
|
||||||
|
|
||||||
friend class TransportFactory;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
//! Initialize the transport object
|
|
||||||
/*!
|
|
||||||
* Here we change all of the internal dimensions to be sufficient. We get
|
|
||||||
* the object ready to do property evaluations. A lot of the input
|
|
||||||
* required to do property evaluations is contained in the
|
|
||||||
* SolidTransportParams class that is filled in TransportFactory.
|
|
||||||
*
|
|
||||||
* @param tr Transport parameters for all of the species in the phase.
|
|
||||||
*/
|
|
||||||
virtual bool initSolid(SolidTransportData& tr);
|
|
||||||
|
|
||||||
private:
|
|
||||||
//! Model type for the ionic conductivity
|
|
||||||
LTPspecies* m_ionConductivity;
|
|
||||||
|
|
||||||
//! Model type for the thermal conductivity
|
|
||||||
LTPspecies* m_thermalConductivity;
|
|
||||||
|
|
||||||
//! Model type for the electrical conductivity
|
|
||||||
LTPspecies* m_electConductivity;
|
|
||||||
|
|
||||||
//! Model type for the defectDiffusivity -- or more like a defect
|
|
||||||
//! diffusivity in the context of the solid phase.
|
|
||||||
LTPspecies* m_defectDiffusivity;
|
|
||||||
|
|
||||||
//! Model type for the defectActivity
|
|
||||||
LTPspecies* m_defectActivity;
|
|
||||||
|
|
||||||
//! number of mobile species
|
|
||||||
size_t m_nmobile;
|
|
||||||
|
|
||||||
//! Coefficient for the diffusivity of species within a solid
|
|
||||||
/*!
|
|
||||||
* This is with respect to the lattice
|
|
||||||
* units = m**2 / s
|
|
||||||
* vector of length m_nmobile
|
|
||||||
*/
|
|
||||||
vector_fp m_Adiff;
|
|
||||||
|
|
||||||
//! Temperature power coefficient for the diffusivity of species in a solid
|
|
||||||
/*!
|
|
||||||
* vector of length m_nmobile
|
|
||||||
*/
|
|
||||||
vector_fp m_Ndiff;
|
|
||||||
|
|
||||||
//! Arrhenius factor for the species diffusivities of a solid
|
|
||||||
/*!
|
|
||||||
* units = temperature
|
|
||||||
* vector of length m_nmobile
|
|
||||||
*/
|
|
||||||
vector_fp m_Ediff;
|
|
||||||
|
|
||||||
//! Index of mobile species to global species
|
|
||||||
/*!
|
|
||||||
* vector of length m_nmobile
|
|
||||||
*/
|
|
||||||
vector_int m_sp;
|
|
||||||
|
|
||||||
//! Coefficient for the thermal conductivity of a solid
|
|
||||||
/*!
|
|
||||||
* units = kg m / s3 /K = W/m/K
|
|
||||||
*/
|
|
||||||
doublereal m_Alam;
|
|
||||||
|
|
||||||
//! Temperature power coefficient for the thermal conductivity of a solid
|
|
||||||
doublereal m_Nlam;
|
|
||||||
|
|
||||||
//! Arrhenius factor for the thermal conductivity of a solid
|
|
||||||
/*!
|
|
||||||
* units = temperature
|
|
||||||
*/
|
|
||||||
doublereal m_Elam;
|
|
||||||
|
|
||||||
//! extra fp array of length nSpecies()
|
|
||||||
vector_fp m_work;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,68 +0,0 @@
|
||||||
/**
|
|
||||||
* @file SolidTransportData.h
|
|
||||||
* Header file defining class SolidTransportData
|
|
||||||
*/
|
|
||||||
|
|
||||||
// This file is part of Cantera. See License.txt in the top-level directory or
|
|
||||||
// at http://www.cantera.org/license.txt for license and copyright information.
|
|
||||||
|
|
||||||
#ifndef CT_SOLIDTRANSPORTDATA_H
|
|
||||||
#define CT_SOLIDTRANSPORTDATA_H
|
|
||||||
|
|
||||||
#include "cantera/transport/TransportParams.h"
|
|
||||||
#include "cantera/transport/LTPspecies.h"
|
|
||||||
|
|
||||||
namespace Cantera
|
|
||||||
{
|
|
||||||
|
|
||||||
//! Class SolidTransportData holds transport parameters for a specific solid-
|
|
||||||
//! phase species.
|
|
||||||
/*!
|
|
||||||
* @deprecated To be removed after Cantera 2.4
|
|
||||||
*
|
|
||||||
* A SolidTransportData object is created for a solid phase
|
|
||||||
* (not for each species as happens for the analogous LiquidTransportData).
|
|
||||||
*
|
|
||||||
* This class is mainly used to collect transport properties from the parse
|
|
||||||
* phase in the TranportFactory and transfer them to the Transport class.
|
|
||||||
* Transport properties are expressed by subclasses of LTPspecies. Note that we
|
|
||||||
* use the liquid phase species model for the solid phases. That is, for the
|
|
||||||
* time being at least, we ignore mixing models for solid phases and just
|
|
||||||
* specify a transport property at the level that we specify the transport
|
|
||||||
* property for a species in the liquid phase. One may need to be careful about
|
|
||||||
* deleting pointers to LTPspecies objects created in the TransportFactory.
|
|
||||||
*
|
|
||||||
* All of the pointers in this class are shallow pointers. Therefore, this is
|
|
||||||
* a passthrough class, which keeps track of pointer ownership by zeroing
|
|
||||||
* pointers as we go. Yes, Yes, yes, this is not good.
|
|
||||||
*/
|
|
||||||
class SolidTransportData : public TransportParams
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
SolidTransportData();
|
|
||||||
SolidTransportData(const SolidTransportData& right);
|
|
||||||
SolidTransportData& operator=(const SolidTransportData& right);
|
|
||||||
~SolidTransportData();
|
|
||||||
|
|
||||||
//! A SolidTransportData object is instantiated for each species.
|
|
||||||
//! This is the species name for which this object is instantiated.
|
|
||||||
std::string speciesName;
|
|
||||||
|
|
||||||
//! Model type for the ionic conductivity
|
|
||||||
LTPspecies* ionConductivity;
|
|
||||||
|
|
||||||
//! Model type for the thermal conductivity
|
|
||||||
LTPspecies* thermalConductivity;
|
|
||||||
|
|
||||||
//! Model type for the electrical conductivity
|
|
||||||
LTPspecies* electConductivity;
|
|
||||||
|
|
||||||
//! Model type for the defectDiffusivity -- or more like a defect diffusivity in the context of the solid phase.
|
|
||||||
LTPspecies* defectDiffusivity;
|
|
||||||
|
|
||||||
//! Model type for the defectActivity
|
|
||||||
LTPspecies* defectActivity;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,170 +0,0 @@
|
||||||
/**
|
|
||||||
* @file Tortuosity.h
|
|
||||||
* Class to compute the increase in diffusive path length in porous media
|
|
||||||
* assuming the Bruggeman exponent relation
|
|
||||||
*/
|
|
||||||
|
|
||||||
// This file is part of Cantera. See License.txt in the top-level directory or
|
|
||||||
// at http://www.cantera.org/license.txt for license and copyright information.
|
|
||||||
|
|
||||||
#ifndef CT_TORTUOSITY_H
|
|
||||||
#define CT_TORTUOSITY_H
|
|
||||||
|
|
||||||
namespace Cantera
|
|
||||||
{
|
|
||||||
|
|
||||||
//! Specific Class to handle tortuosity corrections for diffusive transport
|
|
||||||
//! in porous media using the Bruggeman exponent
|
|
||||||
/*!
|
|
||||||
* @attention This class currently does not have any test cases or examples. Its
|
|
||||||
* implementation may be incomplete, and future changes to Cantera may
|
|
||||||
* unexpectedly cause this class to stop working. If you use this class,
|
|
||||||
* please consider contributing examples or test cases. In the absence of
|
|
||||||
* new tests or examples, this class may be deprecated and removed in a
|
|
||||||
* future version of Cantera. See
|
|
||||||
* https://github.com/Cantera/cantera/issues/267 for additional information.
|
|
||||||
*
|
|
||||||
* @deprecated To be removed after Cantera 2.4
|
|
||||||
*
|
|
||||||
* Class to compute the increase in diffusive path length associated with
|
|
||||||
* tortuous path diffusion through, for example, porous media. This base class
|
|
||||||
* implementation relates tortuosity to volume fraction through a power-law
|
|
||||||
* relationship that goes back to Bruggeman. The exponent is referred to as the
|
|
||||||
* Bruggeman exponent.
|
|
||||||
*
|
|
||||||
* Note that the total diffusional flux is generally written as
|
|
||||||
*
|
|
||||||
* \f[
|
|
||||||
* \frac{ \phi C_T D_i \nabla X_i }{ \tau^2 }
|
|
||||||
* \f]
|
|
||||||
*
|
|
||||||
* where \f$ \phi \f$ is the volume fraction of the transported phase,
|
|
||||||
* \f$ \tau \f$ is referred to as the tortuosity. (Other variables are
|
|
||||||
* \f$ C_T \f$, the total concentration, \f$ D_i \f$, the diffusion coefficient,
|
|
||||||
* and \f$ X_i \f$, the mole fraction with Fickian transport assumed.)
|
|
||||||
*/
|
|
||||||
class Tortuosity
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
//! Default constructor uses Bruggeman exponent of 1.5
|
|
||||||
Tortuosity(double setPower = 1.5) : expBrug_(setPower) {
|
|
||||||
}
|
|
||||||
|
|
||||||
//! The tortuosity factor models the effective increase in the
|
|
||||||
//! diffusive transport length.
|
|
||||||
/**
|
|
||||||
* This method returns \f$ 1/\tau^2 \f$ in the description of the
|
|
||||||
* flux \f$ \phi C_T D_i \nabla X_i / \tau^2 \f$.
|
|
||||||
*/
|
|
||||||
virtual double tortuosityFactor(double porosity) {
|
|
||||||
return pow(porosity, expBrug_ - 1.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
//! The McMillan number is the ratio of the flux-like
|
|
||||||
//! variable to the value it would have without porous flow.
|
|
||||||
/**
|
|
||||||
* The McMillan number combines the effect of tortuosity and volume fraction
|
|
||||||
* of the transported phase. The net flux observed is then the product of
|
|
||||||
* the McMillan number and the non-porous transport rate. For a
|
|
||||||
* conductivity in a non-porous media, \f$ \kappa_0 \f$, the conductivity in
|
|
||||||
* the porous media would be \f$ \kappa = (\rm McMillan) \kappa_0 \f$.
|
|
||||||
*/
|
|
||||||
virtual double McMillan(double porosity) {
|
|
||||||
return pow(porosity, expBrug_);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
//! Bruggeman exponent: power to which the tortuosity depends on the volume
|
|
||||||
//! fraction
|
|
||||||
double expBrug_;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class implements transport coefficient corrections appropriate for
|
|
||||||
* porous media where percolation theory applies.
|
|
||||||
*
|
|
||||||
* @attention This class currently does not have any test cases or examples. Its
|
|
||||||
* implementation may be incomplete, and future changes to Cantera may
|
|
||||||
* unexpectedly cause this class to stop working. If you use this class,
|
|
||||||
* please consider contributing examples or test cases. In the absence of
|
|
||||||
* new tests or examples, this class may be deprecated and removed in a
|
|
||||||
* future version of Cantera. See
|
|
||||||
* https://github.com/Cantera/cantera/issues/267 for additional information.
|
|
||||||
*/
|
|
||||||
class TortuosityPercolation : public Tortuosity
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
//! Default constructor uses Bruggeman exponent of 1.5
|
|
||||||
TortuosityPercolation(double percolationThreshold = 0.4, double conductivityExponent = 2.0) : percolationThreshold_(percolationThreshold), conductivityExponent_(conductivityExponent) {
|
|
||||||
}
|
|
||||||
|
|
||||||
double tortuosityFactor(double porosity) {
|
|
||||||
return McMillan(porosity) / porosity;
|
|
||||||
}
|
|
||||||
|
|
||||||
double McMillan(double porosity) {
|
|
||||||
return pow((porosity - percolationThreshold_)
|
|
||||||
/ (1.0 - percolationThreshold_),
|
|
||||||
conductivityExponent_);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
//! Critical volume fraction / site density for percolation
|
|
||||||
double percolationThreshold_;
|
|
||||||
//! Conductivity exponent
|
|
||||||
/**
|
|
||||||
* The McMillan number (ratio of effective conductivity
|
|
||||||
* to non-porous conductivity) is
|
|
||||||
* \f[
|
|
||||||
* \kappa/\kappa_0 = ( \phi - \phi_c )^\mu
|
|
||||||
* \f]
|
|
||||||
* where \f$ \mu \f$ is the conductivity exponent (typical values range from
|
|
||||||
* 1.6 to 2.0) and \f$ \phi_c \f$ is the percolation threshold.
|
|
||||||
*/
|
|
||||||
double conductivityExponent_;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class implements transport coefficient corrections appropriate for
|
|
||||||
* porous media with a dispersed phase. This model goes back to Maxwell. The
|
|
||||||
* formula for the conductivity is expressed in terms of the volume fraction of
|
|
||||||
* the continuous phase, \f$ \phi \f$, and the relative conductivities of the
|
|
||||||
* dispersed and continuous phases, \f$ r = \kappa_d / \kappa_0 \f$. For dilute
|
|
||||||
* particle suspensions the effective conductivity is
|
|
||||||
* \f[
|
|
||||||
* \kappa / \kappa_0 = 1 + 3 ( 1 - \phi ) ( r - 1 ) / ( r + 2 ) + O(\phi^2)
|
|
||||||
* \f]
|
|
||||||
*
|
|
||||||
* @attention This class currently does not have any test cases or examples. Its
|
|
||||||
* implementation may be incomplete, and future changes to Cantera may
|
|
||||||
* unexpectedly cause this class to stop working. If you use this class,
|
|
||||||
* please consider contributing examples or test cases. In the absence of
|
|
||||||
* new tests or examples, this class may be deprecated and removed in a
|
|
||||||
* future version of Cantera. See
|
|
||||||
* https://github.com/Cantera/cantera/issues/267 for additional information.
|
|
||||||
*/
|
|
||||||
class TortuosityMaxwell : public Tortuosity
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
//! Default constructor uses Bruggeman exponent of 1.5
|
|
||||||
TortuosityMaxwell(double relativeConductivites = 0.0) : relativeConductivites_(relativeConductivites) {
|
|
||||||
}
|
|
||||||
|
|
||||||
double tortuosityFactor(double porosity) {
|
|
||||||
return McMillan(porosity) / porosity;
|
|
||||||
}
|
|
||||||
|
|
||||||
double McMillan(double porosity) {
|
|
||||||
return 1 + 3 * (1.0 - porosity) * (relativeConductivites_ - 1.0) / (relativeConductivites_ + 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
//! Relative conductivities of the dispersed and continuous phases,
|
|
||||||
//! `relativeConductivites_` \f$ = \kappa_d / \kappa_0 \f$.
|
|
||||||
double relativeConductivites_;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
@ -24,9 +24,6 @@
|
||||||
namespace Cantera
|
namespace Cantera
|
||||||
{
|
{
|
||||||
|
|
||||||
class LiquidTransportParams;
|
|
||||||
class SolidTransportData;
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \addtogroup tranprops
|
* \addtogroup tranprops
|
||||||
*/
|
*/
|
||||||
|
|
@ -270,47 +267,6 @@ public:
|
||||||
throw NotImplementedError("Transport::getSpeciesMobilityRatio");
|
throw NotImplementedError("Transport::getSpeciesMobilityRatio");
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Returns the self diffusion coefficients of the species in the phase
|
|
||||||
/*!
|
|
||||||
* The self diffusion coefficient is the diffusion coefficient of a tracer
|
|
||||||
* species at the current temperature and composition of the species.
|
|
||||||
* Therefore, the dilute limit of transport is assumed for the tracer
|
|
||||||
* species. The effective formula may be calculated from the Stefan-Maxwell
|
|
||||||
* formulation by adding another row for the tracer species, assigning all
|
|
||||||
* D's to be equal to the respective species D's, and then taking the limit
|
|
||||||
* as the tracer species mole fraction goes to zero. The corresponding flux
|
|
||||||
* equation for the tracer species k in units of kmol m-2 s-1 is.
|
|
||||||
*
|
|
||||||
* \f[
|
|
||||||
* J_k = - D^{sd}_k \frac{C_k}{R T} \nabla \mu_k
|
|
||||||
* \f]
|
|
||||||
*
|
|
||||||
* The derivative is taken at constant T and P.
|
|
||||||
*
|
|
||||||
* The self diffusion calculation is handled by subclasses of
|
|
||||||
* LiquidTranInteraction as specified in the input file. These in turn
|
|
||||||
* employ subclasses of LTPspecies to determine the individual species self
|
|
||||||
* diffusion coeffs.
|
|
||||||
*
|
|
||||||
* @param selfDiff Vector of self-diffusion coefficients. Length = number
|
|
||||||
* of species in phase. units = m**2 s-1.
|
|
||||||
*/
|
|
||||||
virtual void selfDiffusion(doublereal* const selfDiff) {
|
|
||||||
throw NotImplementedError("Transport::selfDiffusion");
|
|
||||||
}
|
|
||||||
|
|
||||||
//! Returns the pure species self diffusion in solution of each species
|
|
||||||
/*!
|
|
||||||
* The pure species molar volumes are evaluated using the appropriate
|
|
||||||
* subclasses of LTPspecies as specified in the input file.
|
|
||||||
*
|
|
||||||
* @param selfDiff array of length "number of species"
|
|
||||||
* to hold returned self diffusion coeffs.
|
|
||||||
*/
|
|
||||||
virtual void getSpeciesSelfDiffusion(double** selfDiff) {
|
|
||||||
throw NotImplementedError("Transport::getSpeciesSelfDiffusion");
|
|
||||||
}
|
|
||||||
|
|
||||||
//! Returns the mixture thermal conductivity in W/m/K.
|
//! Returns the mixture thermal conductivity in W/m/K.
|
||||||
/*!
|
/*!
|
||||||
* Units are in W / m K or equivalently kg m / s3 K
|
* Units are in W / m K or equivalently kg m / s3 K
|
||||||
|
|
@ -683,30 +639,6 @@ public:
|
||||||
*/
|
*/
|
||||||
virtual void init(thermo_t* thermo, int mode=0, int log_level=0) {}
|
virtual void init(thermo_t* thermo, int mode=0, int log_level=0) {}
|
||||||
|
|
||||||
//! Called by TransportFactory to set parameters.
|
|
||||||
/*!
|
|
||||||
* This is called by classes that use the liquid phase parameter list to
|
|
||||||
* initialize themselves.
|
|
||||||
*
|
|
||||||
* @param tr Reference to the parameter list that will be used to initialize
|
|
||||||
* the class
|
|
||||||
*/
|
|
||||||
virtual bool initLiquid(LiquidTransportParams& tr) {
|
|
||||||
throw NotImplementedError("Transport::initLiquid");
|
|
||||||
}
|
|
||||||
|
|
||||||
//! Called by TransportFactory to set parameters.
|
|
||||||
/*!
|
|
||||||
* This is called by classes that use the solid phase parameter list to
|
|
||||||
* initialize themselves.
|
|
||||||
*
|
|
||||||
* @param tr Reference to the parameter list that will be used to initialize
|
|
||||||
* the class
|
|
||||||
*/
|
|
||||||
virtual bool initSolid(SolidTransportData& tr) {
|
|
||||||
throw NotImplementedError("Transport::initSolid");
|
|
||||||
}
|
|
||||||
|
|
||||||
//! Specifies the ThermoPhase object.
|
//! Specifies the ThermoPhase object.
|
||||||
/*!
|
/*!
|
||||||
* We have relaxed this operation so that it will succeed when the
|
* We have relaxed this operation so that it will succeed when the
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,6 @@
|
||||||
// Cantera includes
|
// Cantera includes
|
||||||
#include "TransportBase.h"
|
#include "TransportBase.h"
|
||||||
#include "cantera/base/FactoryBase.h"
|
#include "cantera/base/FactoryBase.h"
|
||||||
#include "LiquidTransportParams.h"
|
|
||||||
|
|
||||||
namespace Cantera
|
namespace Cantera
|
||||||
{
|
{
|
||||||
|
|
@ -54,35 +53,6 @@ public:
|
||||||
//! Deletes the statically allocated factory instance.
|
//! Deletes the statically allocated factory instance.
|
||||||
virtual void deleteFactory();
|
virtual void deleteFactory();
|
||||||
|
|
||||||
//! Make one of several transport models, and return a base class pointer to it.
|
|
||||||
/*!
|
|
||||||
* This method operates at the level of a single transport property as a
|
|
||||||
* function of temperature and possibly composition. It's a factory for
|
|
||||||
* LTPspecies classes.
|
|
||||||
*
|
|
||||||
* @param trNode XML node
|
|
||||||
* @param name reference to the name
|
|
||||||
* @param tp_ind TransportPropertyType class
|
|
||||||
* @param thermo Pointer to the ThermoPhase class
|
|
||||||
*/
|
|
||||||
virtual LTPspecies* newLTP(const XML_Node& trNode, const std::string& name,
|
|
||||||
TransportPropertyType tp_ind, thermo_t* thermo);
|
|
||||||
|
|
||||||
//! Factory function for the construction of new LiquidTranInteraction
|
|
||||||
//! objects, which are transport models.
|
|
||||||
/*!
|
|
||||||
* This method operates at the level of a single mixture transport property.
|
|
||||||
* Individual species transport properties are addressed by the LTPspecies
|
|
||||||
* returned by newLTP.
|
|
||||||
*
|
|
||||||
* @param trNode XML_Node containing the information for the interaction
|
|
||||||
* @param tp_ind TransportPropertyType object
|
|
||||||
* @param trParam reference to the LiquidTransportParams object
|
|
||||||
*/
|
|
||||||
virtual LiquidTranInteraction* newLTI(const XML_Node& trNode,
|
|
||||||
TransportPropertyType tp_ind,
|
|
||||||
LiquidTransportParams& trParam);
|
|
||||||
|
|
||||||
//! Build a new transport manager using a transport manager
|
//! Build a new transport manager using a transport manager
|
||||||
//! that may not be the same as in the phase description
|
//! that may not be the same as in the phase description
|
||||||
//! and return a base class pointer to it
|
//! and return a base class pointer to it
|
||||||
|
|
@ -102,31 +72,7 @@ public:
|
||||||
*/
|
*/
|
||||||
virtual Transport* newTransport(thermo_t* thermo, int log_level=0);
|
virtual Transport* newTransport(thermo_t* thermo, int log_level=0);
|
||||||
|
|
||||||
//! Initialize an existing transport manager for liquid phase
|
|
||||||
/*!
|
|
||||||
* This routine sets up an existing liquid-phase transport manager. It is
|
|
||||||
* similar to initTransport except that it uses the LiquidTransportParams
|
|
||||||
* class and calls setupLiquidTransport().
|
|
||||||
*
|
|
||||||
* @param tr Pointer to the Transport manager
|
|
||||||
* @param thermo Pointer to the ThermoPhase object
|
|
||||||
* @param log_level Defaults to zero, no logging
|
|
||||||
*/
|
|
||||||
virtual void initLiquidTransport(Transport* tr, thermo_t* thermo, int log_level=0);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
//! Initialize an existing transport manager for solid phase
|
|
||||||
/*!
|
|
||||||
* This routine sets up an existing solid-phase transport manager. It is
|
|
||||||
* similar to initTransport except that it uses the SolidTransportData class
|
|
||||||
* and calls setupSolidTransport().
|
|
||||||
*
|
|
||||||
* @param tr Pointer to the Transport manager
|
|
||||||
* @param thermo Pointer to the ThermoPhase object
|
|
||||||
* @param log_level Defaults to zero, no logging
|
|
||||||
*/
|
|
||||||
virtual void initSolidTransport(Transport* tr, thermo_t* thermo, int log_level=0);
|
|
||||||
|
|
||||||
//! Static instance of the factor -> This is the only instance of this
|
//! Static instance of the factor -> This is the only instance of this
|
||||||
//! object allowed
|
//! object allowed
|
||||||
static TransportFactory* s_factory;
|
static TransportFactory* s_factory;
|
||||||
|
|
@ -143,94 +89,6 @@ private:
|
||||||
*/
|
*/
|
||||||
TransportFactory();
|
TransportFactory();
|
||||||
|
|
||||||
//! Read transport property data from a file for a list of species that
|
|
||||||
//! comprise the phase.
|
|
||||||
/*!
|
|
||||||
* Given a vector of pointers to species XML data bases and a list of
|
|
||||||
* species names, this method constructs the LiquidTransport Params object
|
|
||||||
* containing the transport data for these species.
|
|
||||||
*
|
|
||||||
* It is an error to not find a "transport" XML element within each of the
|
|
||||||
* species XML elements listed in the names vector.
|
|
||||||
*
|
|
||||||
* @param db Reference to a vector of XML_Node pointers containing the
|
|
||||||
* species XML nodes.
|
|
||||||
* @param log Reference to an XML log file. (currently unused)
|
|
||||||
* @param names Vector of names of species. On output, tr will contain
|
|
||||||
* transport data for each of of these names in the order
|
|
||||||
* determined by this vector.
|
|
||||||
* @param tr Reference to the LiquidTransportParams object that will
|
|
||||||
* contain the results.
|
|
||||||
*/
|
|
||||||
void getLiquidSpeciesTransportData(const std::vector<const XML_Node*> &db,
|
|
||||||
XML_Node& log, const std::vector<std::string>& names,
|
|
||||||
LiquidTransportParams& tr);
|
|
||||||
|
|
||||||
//! Read transport property data from a file for interactions between species.
|
|
||||||
/*!
|
|
||||||
* Given the XML_Node database for transport interactions defined within the
|
|
||||||
* current phase and a list of species names within the phase, this method
|
|
||||||
* returns an instance of TransportParams containing the transport data for
|
|
||||||
* these species read from the file.
|
|
||||||
*
|
|
||||||
* This routine reads interaction parameters between species within the phase.
|
|
||||||
*
|
|
||||||
* @param phaseTran_db Reference to the transport XML field for the phase
|
|
||||||
* @param log Reference to an XML log file. (currently unused)
|
|
||||||
* @param names Vector of names of species. On output, tr will
|
|
||||||
* contain transport data for each of of these names in
|
|
||||||
* the order determined by this vector.
|
|
||||||
* @param tr Reference to the LiquidTransportParams object that
|
|
||||||
* will contain the results.
|
|
||||||
*/
|
|
||||||
void getLiquidInteractionsTransportData(const XML_Node& phaseTran_db, XML_Node& log,
|
|
||||||
const std::vector<std::string>& names, LiquidTransportParams& tr);
|
|
||||||
|
|
||||||
//! Read transport property data from a file for a solid phase
|
|
||||||
/*!
|
|
||||||
* Given a phase XML data base, this method constructs the
|
|
||||||
* SolidTransportData object containing the transport data for the phase.
|
|
||||||
*
|
|
||||||
* @param transportNode Reference to XML_Node containing the phase.
|
|
||||||
* @param log Reference to an XML log file. (currently unused)
|
|
||||||
* @param phaseName name of the corresponding phase
|
|
||||||
* @param tr Reference to the SolidTransportData object that will
|
|
||||||
* contain the results.
|
|
||||||
*/
|
|
||||||
void getSolidTransportData(const XML_Node& transportNode,
|
|
||||||
XML_Node& log,
|
|
||||||
const std::string phaseName,
|
|
||||||
SolidTransportData& tr);
|
|
||||||
|
|
||||||
//! Prepare to build a new transport manager for liquids assuming that
|
|
||||||
//! viscosity transport data is provided in Arrhenius form.
|
|
||||||
/*!
|
|
||||||
* @param thermo Pointer to the ThermoPhase object
|
|
||||||
* @param log_level log level
|
|
||||||
* @param trParam LiquidTransportParams structure to be filled up with information
|
|
||||||
*/
|
|
||||||
void setupLiquidTransport(thermo_t* thermo, int log_level, LiquidTransportParams& trParam);
|
|
||||||
|
|
||||||
//! Prepare to build a new transport manager for solids
|
|
||||||
/*!
|
|
||||||
* @param thermo Pointer to the ThermoPhase object
|
|
||||||
* @param log_level log level
|
|
||||||
* @param trParam SolidTransportData structure to be filled up with information
|
|
||||||
*/
|
|
||||||
void setupSolidTransport(thermo_t* thermo, int log_level, SolidTransportData& trParam);
|
|
||||||
|
|
||||||
//! Mapping between between the string name
|
|
||||||
//! for a transport property and the integer name.
|
|
||||||
std::map<std::string, TransportPropertyType> m_tranPropMap;
|
|
||||||
|
|
||||||
//! Mapping between between the string name for a
|
|
||||||
//! species-specific transport property model and the integer name.
|
|
||||||
std::map<std::string, LTPTemperatureDependenceType> m_LTRmodelMap;
|
|
||||||
|
|
||||||
//! Mapping between between the string name for a
|
|
||||||
//! liquid mixture transport property model and the integer name.
|
|
||||||
std::map<std::string, LiquidTranMixingModel> m_LTImodelMap;
|
|
||||||
|
|
||||||
//! Models included in this map are initialized in CK compatibility mode
|
//! Models included in this map are initialized in CK compatibility mode
|
||||||
std::map<std::string, bool> m_CK_mode;
|
std::map<std::string, bool> m_CK_mode;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -8,8 +8,8 @@
|
||||||
#ifndef CT_WATERTRAN_H
|
#ifndef CT_WATERTRAN_H
|
||||||
#define CT_WATERTRAN_H
|
#define CT_WATERTRAN_H
|
||||||
|
|
||||||
#include "LiquidTransportParams.h"
|
|
||||||
#include "cantera/thermo/WaterPropsIAPWS.h"
|
#include "cantera/thermo/WaterPropsIAPWS.h"
|
||||||
|
#include "cantera/transport/TransportBase.h"
|
||||||
|
|
||||||
namespace Cantera
|
namespace Cantera
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -690,12 +690,6 @@ cdef extern from "cantera/oneD/StFlow.h":
|
||||||
void setFreeFlow()
|
void setFreeFlow()
|
||||||
void setAxisymmetricFlow()
|
void setAxisymmetricFlow()
|
||||||
|
|
||||||
cdef cppclass CxxFreeFlame "Cantera::FreeFlame":
|
|
||||||
CxxFreeFlame(CxxIdealGasPhase*, int, int)
|
|
||||||
|
|
||||||
cdef cppclass CxxAxiStagnFlow "Cantera::AxiStagnFlow":
|
|
||||||
CxxAxiStagnFlow(CxxIdealGasPhase*, int, int)
|
|
||||||
|
|
||||||
|
|
||||||
cdef extern from "cantera/oneD/IonFlow.h":
|
cdef extern from "cantera/oneD/IonFlow.h":
|
||||||
cdef cppclass CxxIonFlow "Cantera::IonFlow":
|
cdef cppclass CxxIonFlow "Cantera::IonFlow":
|
||||||
|
|
|
||||||
|
|
@ -887,41 +887,6 @@ class Shomate(thermo):
|
||||||
u["name"] = "coeffs"
|
u["name"] = "coeffs"
|
||||||
|
|
||||||
|
|
||||||
class Adsorbate(thermo):
|
|
||||||
"""Adsorbed species characterized by a binding energy and a set of
|
|
||||||
vibrational frequencies."""
|
|
||||||
|
|
||||||
def __init__(self, Trange = (0.0, 0.0),
|
|
||||||
binding_energy = 0.0,
|
|
||||||
frequencies = [], p0 = -1.0):
|
|
||||||
self._t = Trange
|
|
||||||
self._pref = p0
|
|
||||||
self._freqs = frequencies
|
|
||||||
self._be = binding_energy
|
|
||||||
|
|
||||||
|
|
||||||
def build(self, t):
|
|
||||||
n = t.addChild("adsorbate")
|
|
||||||
n['Tmin'] = repr(self._t[0])
|
|
||||||
n['Tmax'] = repr(self._t[1])
|
|
||||||
if self._pref <= 0.0:
|
|
||||||
n['P0'] = repr(_pref)
|
|
||||||
else:
|
|
||||||
n['P0'] = repr(self._pref)
|
|
||||||
|
|
||||||
energy_units = _uenergy+'/'+_umol
|
|
||||||
addFloat(n,'binding_energy',self._be, defunits = energy_units)
|
|
||||||
s = ""
|
|
||||||
nfreq = len(self._freqs)
|
|
||||||
for i in range(nfreq):
|
|
||||||
s += '%17.9E, ' % self._freqs[i]
|
|
||||||
s += '\n'
|
|
||||||
u = n.addChild("floatArray", s)
|
|
||||||
u["size"] = repr(nfreq)
|
|
||||||
u["name"] = "freqs"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class const_cp(thermo):
|
class const_cp(thermo):
|
||||||
"""Constant specific heat."""
|
"""Constant specific heat."""
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -533,34 +533,6 @@ cdef class IdealGasFlow(_FlowBase):
|
||||||
self.flow = new CxxStFlow(gas, thermo.n_species, 2)
|
self.flow = new CxxStFlow(gas, thermo.n_species, 2)
|
||||||
|
|
||||||
|
|
||||||
cdef class FreeFlow(IdealGasFlow):
|
|
||||||
"""
|
|
||||||
.. deprecated:: 2.4
|
|
||||||
To be removed after Cantera 2.4. Use class `IdealGasFlow` instead and
|
|
||||||
call the ``set_free_flow()`` method.
|
|
||||||
"""
|
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
warnings.warn("Class FreeFlow is deprecated and will be removed after"
|
|
||||||
" Cantera 2.4. Use class IdealGasFlow instead and call the"
|
|
||||||
" ``set_free_flow()`` method.")
|
|
||||||
super().__init__(*args, **kwargs)
|
|
||||||
self.set_free_flow()
|
|
||||||
|
|
||||||
|
|
||||||
cdef class AxisymmetricStagnationFlow(IdealGasFlow):
|
|
||||||
"""
|
|
||||||
.. deprecated:: 2.4
|
|
||||||
To be removed after Cantera 2.4. Use class `IdealGasFlow` instead and
|
|
||||||
call the ``set_axisymmetric_flow()`` method.
|
|
||||||
"""
|
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
warnings.warn("Class AxisymmetricStagnationFlow is deprecated and will"
|
|
||||||
" be removed after Cantera 2.4. Use class IdealGasFlow instead and"
|
|
||||||
" call the set_axisymmetric_flow() method.")
|
|
||||||
super().__init__(*args, **kwargs)
|
|
||||||
self.set_free_flow()
|
|
||||||
|
|
||||||
|
|
||||||
cdef class IonFlow(_FlowBase):
|
cdef class IonFlow(_FlowBase):
|
||||||
"""
|
"""
|
||||||
An ion flow domain.
|
An ion flow domain.
|
||||||
|
|
|
||||||
|
|
@ -1327,21 +1327,6 @@ cdef class ThermoPhase(_SolutionBase):
|
||||||
def __set__(self, double value):
|
def __set__(self, double value):
|
||||||
self.thermo.setElectricPotential(value)
|
self.thermo.setElectricPotential(value)
|
||||||
|
|
||||||
def element_potentials(self):
|
|
||||||
"""
|
|
||||||
Get the array of element potentials. The element potentials are only
|
|
||||||
defined for equilibrium states. This method first sets the composition
|
|
||||||
to a state of equilibrium at constant T and P, then computes the
|
|
||||||
element potentials for this equilibrium state.
|
|
||||||
|
|
||||||
.. deprecated:: 2.3
|
|
||||||
To be removed after Cantera 2.4.
|
|
||||||
"""
|
|
||||||
self.equilibrate('TP')
|
|
||||||
cdef np.ndarray[np.double_t, ndim=1] data = np.zeros(self.n_elements)
|
|
||||||
self.thermo.getElementPotentials(&data[0])
|
|
||||||
return data
|
|
||||||
|
|
||||||
|
|
||||||
cdef class InterfacePhase(ThermoPhase):
|
cdef class InterfacePhase(ThermoPhase):
|
||||||
""" A class representing a surface or edge phase"""
|
""" A class representing a surface or edge phase"""
|
||||||
|
|
|
||||||
|
|
@ -1,142 +0,0 @@
|
||||||
function flame = npflame_init(gas, left, flow, right, fuel, oxidizer, nuox)
|
|
||||||
% NPFLAME_INIT Create a non-premixed flame stack.
|
|
||||||
% flame = npflame_init(gas, left, flow, right, fuel, oxidizer, nuox)
|
|
||||||
%
|
|
||||||
% This function is deprecated in favor of :mat:func:`CounterFlowDiffusionFlame`
|
|
||||||
% and will be removed after Cantera 2.4.
|
|
||||||
%
|
|
||||||
% :param gas:
|
|
||||||
% Object representing the gas, instance of class
|
|
||||||
% :mat:func:`Solution`, and an ideal gas. This object will be used
|
|
||||||
% to compute all required thermodynamic, kinetic, and transport
|
|
||||||
% properties. The state of this object should be set
|
|
||||||
% to an estimate of the gas state emerging from the
|
|
||||||
% burner before calling StagnationFlame.
|
|
||||||
% :param left:
|
|
||||||
% Object representing the left inlet, which must be
|
|
||||||
% created using function :mat:func:`Inlet`.
|
|
||||||
% :param flow:
|
|
||||||
% Object representing the flow, created with
|
|
||||||
% function :mat:func:`AxisymmetricFlow`.
|
|
||||||
% :param right:
|
|
||||||
% Object representing the right inlet, which must be
|
|
||||||
% created using function :mat:func:`Inlet`.
|
|
||||||
% :param fuel:
|
|
||||||
% String representing the fuel species
|
|
||||||
% :param ox:
|
|
||||||
% String representing the oxidizer species
|
|
||||||
% :param nuox:
|
|
||||||
% Number of oxidizer molecules required to completely combust
|
|
||||||
% one fuel molecule.
|
|
||||||
% :return:
|
|
||||||
% Instance of :mat:func:`Stack` object representing the left
|
|
||||||
% inlet, flow, and right inlet.
|
|
||||||
%
|
|
||||||
|
|
||||||
warning('This function is deprecated and will be removed after Cantera 2.4. Use CounterFlowDiffusionFlame instead');
|
|
||||||
|
|
||||||
% Check input parameters
|
|
||||||
if nargin ~= 7
|
|
||||||
error('npflame_init expects seven input arguments.');
|
|
||||||
end
|
|
||||||
|
|
||||||
if ~isIdealGas(gas)
|
|
||||||
error('gas object must represent an ideal gas mixture.');
|
|
||||||
end
|
|
||||||
if ~isInlet(left)
|
|
||||||
error('left inlet object of wrong type.');
|
|
||||||
end
|
|
||||||
if ~isFlow(flow)
|
|
||||||
error('flow object of wrong type.');
|
|
||||||
end
|
|
||||||
if ~isInlet(right)
|
|
||||||
error('right inlet object of wrong type.');
|
|
||||||
end
|
|
||||||
|
|
||||||
% create the container object
|
|
||||||
flame = Stack([left flow right]);
|
|
||||||
|
|
||||||
% set default initial profiles.
|
|
||||||
rho0 = density(gas);
|
|
||||||
|
|
||||||
wt = molecularWeights(gas);
|
|
||||||
|
|
||||||
% find the fuel and oxidizer
|
|
||||||
ifuel = speciesIndex(gas, fuel);
|
|
||||||
ioxidizer = speciesIndex(gas, oxidizer);
|
|
||||||
|
|
||||||
s = nuox*wt(ioxidizer)/wt(ifuel);
|
|
||||||
y0f = massFraction(left, ifuel);
|
|
||||||
y0ox = massFraction(right, ioxidizer);
|
|
||||||
phi = s*y0f/y0ox;
|
|
||||||
zst = 1.0/(1.0 + phi);
|
|
||||||
|
|
||||||
% compute stoichiometric adiabatic flame temperature
|
|
||||||
nsp = nSpecies(gas);
|
|
||||||
tf = temperature(left);
|
|
||||||
tox = temperature(right);
|
|
||||||
|
|
||||||
yox = zeros(1, nsp);
|
|
||||||
yf = zeros(1, nsp);
|
|
||||||
ystoich = zeros(1, nsp);
|
|
||||||
for n = 1:nsp
|
|
||||||
yox(n) = massFraction(right, n);
|
|
||||||
yf(n) = massFraction(left, n);
|
|
||||||
ystoich(n) = zst*yf(n) + (1.0 - zst)*yox(n);
|
|
||||||
end
|
|
||||||
|
|
||||||
set(gas, 'T', temperature(left), 'P', pressure(gas), 'Y', ystoich);
|
|
||||||
equilibrate(gas, 'HP');
|
|
||||||
teq = temperature(gas);
|
|
||||||
yeq = massFractions(gas);
|
|
||||||
|
|
||||||
% estimated strain rate
|
|
||||||
zz = gridPoints(flow);
|
|
||||||
dz = zz(end) - zz(1);
|
|
||||||
vleft = massFlux(left)/rho0;
|
|
||||||
vright = massFlux(right)/rho0;
|
|
||||||
a = (abs(vleft) + abs(vright))/dz;
|
|
||||||
diff = mixDiffCoeffs(gas);
|
|
||||||
f = sqrt(a/(2.0*diff(ioxidizer)));
|
|
||||||
|
|
||||||
x0 = massFlux(left)*dz/(massFlux(left) + massFlux(right));
|
|
||||||
|
|
||||||
nz = nPoints(flow);
|
|
||||||
zm = zeros(1, nz);
|
|
||||||
u = zeros(1, nz);
|
|
||||||
v = zeros(1, nz);
|
|
||||||
y = zeros(nz, nsp);
|
|
||||||
t = zeros(1, nz);
|
|
||||||
for j = 1:nz
|
|
||||||
x = zz(j);
|
|
||||||
zeta = f*(x - x0);
|
|
||||||
zmix = 0.5*(1.0 - erf(zeta));
|
|
||||||
zm(j) = zmix;
|
|
||||||
u(j) = a*(x0 - zz(j));
|
|
||||||
v(j) = a;
|
|
||||||
if zmix > zst
|
|
||||||
for n = 1:nsp
|
|
||||||
y(j,n) = yeq(n) + (zmix - zst)*(yf(n) - yeq(n))/(1.0 - zst);
|
|
||||||
end
|
|
||||||
t(j) = teq + (tf - teq)*(zmix - zst)/(1.0 - zst);
|
|
||||||
else
|
|
||||||
for n = 1:nsp
|
|
||||||
y(j,n) = yox(n) + zmix*(yeq(n) - yox(n))/zst;
|
|
||||||
end
|
|
||||||
t(j) = tox + zmix*(teq - tox)/zst;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
zrel = zz/dz;
|
|
||||||
|
|
||||||
setProfile(flame, 2, {'u', 'V'}, [zrel; u; v]);
|
|
||||||
|
|
||||||
setProfile(flame, 2, 'T', [zrel; t] );
|
|
||||||
|
|
||||||
for n = 1:nsp
|
|
||||||
nm = speciesName(gas, n);
|
|
||||||
setProfile(flame, 2, nm, [zrel; transpose(y(:,n))])
|
|
||||||
end
|
|
||||||
|
|
||||||
% set minimal grid refinement criteria
|
|
||||||
setRefineCriteria(flame, 2, 10.0, 0.99, 0.99);
|
|
||||||
|
|
@ -501,19 +501,6 @@ extern "C" {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int thermo_elementPotentials(int n, size_t lenm, double* lambda)
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
ThermoPhase& thrm = ThermoCabinet::item(n);
|
|
||||||
thrm.checkElementArraySize(lenm);
|
|
||||||
thrm.equilibrate("TP", "element_potential");
|
|
||||||
thrm.getElementPotentials(lambda);
|
|
||||||
return 0;
|
|
||||||
} catch (...) {
|
|
||||||
return handleAllExceptions(-1, ERR);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int thermo_setPressure(int n, double p)
|
int thermo_setPressure(int n, double p)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
|
|
||||||
|
|
@ -72,7 +72,6 @@ void ChemEquil::initialize(thermo_t& s)
|
||||||
|
|
||||||
// allocate space in internal work arrays within the ChemEquil object
|
// allocate space in internal work arrays within the ChemEquil object
|
||||||
m_molefractions.resize(m_kk);
|
m_molefractions.resize(m_kk);
|
||||||
m_lambda.resize(m_mm, -100.0);
|
|
||||||
m_elementmolefracs.resize(m_mm);
|
m_elementmolefracs.resize(m_mm);
|
||||||
m_comp.resize(m_mm * m_kk);
|
m_comp.resize(m_mm * m_kk);
|
||||||
m_jwork1.resize(m_mm+2);
|
m_jwork1.resize(m_mm+2);
|
||||||
|
|
@ -577,9 +576,6 @@ int ChemEquil::equilibrate(thermo_t& s, const char* XYstr,
|
||||||
if (iter > 0 && passThis && fabs(deltax) < options.relTolerance
|
if (iter > 0 && passThis && fabs(deltax) < options.relTolerance
|
||||||
&& fabs(deltay) < options.relTolerance) {
|
&& fabs(deltay) < options.relTolerance) {
|
||||||
options.iterations = iter;
|
options.iterations = iter;
|
||||||
for (size_t m = 0; m < m_mm; m++) {
|
|
||||||
m_lambda[m] = x[m]* s.RT();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_eloc != npos) {
|
if (m_eloc != npos) {
|
||||||
adjustEloc(s, elMolesGoal);
|
adjustEloc(s, elMolesGoal);
|
||||||
|
|
|
||||||
|
|
@ -1,163 +0,0 @@
|
||||||
/**
|
|
||||||
* @file AqueousKinetics.cpp
|
|
||||||
*
|
|
||||||
* Homogeneous kinetics in an aqueous phase, either condensed or dilute in salts
|
|
||||||
*/
|
|
||||||
|
|
||||||
// This file is part of Cantera. See License.txt in the top-level directory or
|
|
||||||
// at http://www.cantera.org/license.txt for license and copyright information.
|
|
||||||
|
|
||||||
#include "cantera/kinetics/AqueousKinetics.h"
|
|
||||||
#include "cantera/kinetics/Reaction.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
namespace Cantera
|
|
||||||
{
|
|
||||||
|
|
||||||
AqueousKinetics::AqueousKinetics(thermo_t* thermo) :
|
|
||||||
BulkKinetics(thermo)
|
|
||||||
{
|
|
||||||
warn_deprecated("Class AqueousKinetics", "To be removed after Cantera 2.4");
|
|
||||||
}
|
|
||||||
|
|
||||||
void AqueousKinetics::_update_rates_T()
|
|
||||||
{
|
|
||||||
doublereal T = thermo().temperature();
|
|
||||||
m_rates.update(T, log(T), m_rfn.data());
|
|
||||||
|
|
||||||
m_temp = T;
|
|
||||||
updateKc();
|
|
||||||
m_ROP_ok = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AqueousKinetics::_update_rates_C()
|
|
||||||
{
|
|
||||||
thermo().getActivityConcentrations(m_conc.data());
|
|
||||||
m_ROP_ok = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AqueousKinetics::updateKc()
|
|
||||||
{
|
|
||||||
thermo().getStandardChemPotentials(m_grt.data());
|
|
||||||
fill(m_rkcn.begin(), m_rkcn.end(), 0.0);
|
|
||||||
for (size_t k = 0; k < thermo().nSpecies(); k++) {
|
|
||||||
doublereal logStandConc_k = thermo().logStandardConc(k);
|
|
||||||
m_grt[k] -= GasConstant * m_temp * logStandConc_k;
|
|
||||||
}
|
|
||||||
|
|
||||||
// compute Delta G^0 for all reversible reactions
|
|
||||||
getRevReactionDelta(m_grt.data(), m_rkcn.data());
|
|
||||||
|
|
||||||
doublereal rrt = 1.0 / thermo().RT();
|
|
||||||
for (size_t i = 0; i < m_revindex.size(); i++) {
|
|
||||||
size_t irxn = m_revindex[i];
|
|
||||||
m_rkcn[irxn] = exp(m_rkcn[irxn]*rrt);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i = 0; i != m_irrev.size(); ++i) {
|
|
||||||
m_rkcn[ m_irrev[i] ] = 0.0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void AqueousKinetics::getEquilibriumConstants(doublereal* kc)
|
|
||||||
{
|
|
||||||
_update_rates_T();
|
|
||||||
|
|
||||||
thermo().getStandardChemPotentials(m_grt.data());
|
|
||||||
fill(m_rkcn.begin(), m_rkcn.end(), 0.0);
|
|
||||||
for (size_t k = 0; k < thermo().nSpecies(); k++) {
|
|
||||||
doublereal logStandConc_k = thermo().logStandardConc(k);
|
|
||||||
m_grt[k] -= GasConstant * m_temp * logStandConc_k;
|
|
||||||
}
|
|
||||||
|
|
||||||
// compute Delta G^0 for all reactions
|
|
||||||
getReactionDelta(m_grt.data(), m_rkcn.data());
|
|
||||||
|
|
||||||
doublereal rrt = 1.0 / thermo().RT();
|
|
||||||
for (size_t i = 0; i < nReactions(); i++) {
|
|
||||||
kc[i] = exp(-m_rkcn[i]*rrt);
|
|
||||||
}
|
|
||||||
|
|
||||||
// force an update of T-dependent properties, so that m_rkcn will
|
|
||||||
// be updated before it is used next.
|
|
||||||
m_temp = 0.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AqueousKinetics::updateROP()
|
|
||||||
{
|
|
||||||
_update_rates_T();
|
|
||||||
_update_rates_C();
|
|
||||||
|
|
||||||
if (m_ROP_ok) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// copy rate coefficients into ropf
|
|
||||||
m_ropf = m_rfn;
|
|
||||||
|
|
||||||
// multiply by perturbation factor
|
|
||||||
multiply_each(m_ropf.begin(), m_ropf.end(), m_perturb.begin());
|
|
||||||
|
|
||||||
// copy the forward rates to the reverse rates
|
|
||||||
m_ropr = m_ropf;
|
|
||||||
|
|
||||||
// for reverse rates computed from thermochemistry, multiply the forward
|
|
||||||
// rates copied into m_ropr by the reciprocals of the equilibrium constants
|
|
||||||
multiply_each(m_ropr.begin(), m_ropr.end(), m_rkcn.begin());
|
|
||||||
|
|
||||||
// multiply ropf by concentration products
|
|
||||||
m_reactantStoich.multiply(m_conc.data(), m_ropf.data());
|
|
||||||
|
|
||||||
// for reversible reactions, multiply ropr by concentration products
|
|
||||||
m_revProductStoich.multiply(m_conc.data(), m_ropr.data());
|
|
||||||
|
|
||||||
for (size_t j = 0; j != nReactions(); ++j) {
|
|
||||||
m_ropnet[j] = m_ropf[j] - m_ropr[j];
|
|
||||||
}
|
|
||||||
|
|
||||||
m_ROP_ok = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AqueousKinetics::getFwdRateConstants(doublereal* kfwd)
|
|
||||||
{
|
|
||||||
_update_rates_T();
|
|
||||||
_update_rates_C();
|
|
||||||
|
|
||||||
// copy rate coefficients into ropf
|
|
||||||
m_ropf = m_rfn;
|
|
||||||
|
|
||||||
// multiply by perturbation factor
|
|
||||||
multiply_each(m_ropf.begin(), m_ropf.end(), m_perturb.begin());
|
|
||||||
|
|
||||||
for (size_t i = 0; i < nReactions(); i++) {
|
|
||||||
kfwd[i] = m_ropf[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AqueousKinetics::addReaction(shared_ptr<Reaction> r)
|
|
||||||
{
|
|
||||||
bool added = BulkKinetics::addReaction(r);
|
|
||||||
if (!added) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (r->reaction_type == ELEMENTARY_RXN) {
|
|
||||||
addElementaryReaction(dynamic_cast<ElementaryReaction&>(*r));
|
|
||||||
} else {
|
|
||||||
throw CanteraError("AqueousKinetics::addReaction",
|
|
||||||
"Invalid reaction type: {}", r->reaction_type);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AqueousKinetics::modifyReaction(size_t i, shared_ptr<Reaction> rNew)
|
|
||||||
{
|
|
||||||
BulkKinetics::modifyReaction(i, rNew);
|
|
||||||
modifyElementaryReaction(i, dynamic_cast<ElementaryReaction&>(*rNew));
|
|
||||||
|
|
||||||
// invalidate all cached data
|
|
||||||
m_ROP_ok = false;
|
|
||||||
m_temp += 0.1234;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -10,7 +10,6 @@
|
||||||
#include "cantera/kinetics/InterfaceKinetics.h"
|
#include "cantera/kinetics/InterfaceKinetics.h"
|
||||||
#include "cantera/kinetics/EdgeKinetics.h"
|
#include "cantera/kinetics/EdgeKinetics.h"
|
||||||
#include "cantera/kinetics/importKinetics.h"
|
#include "cantera/kinetics/importKinetics.h"
|
||||||
#include "cantera/kinetics/AqueousKinetics.h"
|
|
||||||
#include "cantera/base/xml.h"
|
#include "cantera/base/xml.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
@ -44,7 +43,6 @@ KineticsFactory::KineticsFactory() {
|
||||||
reg("gaskinetics", []() { return new GasKinetics(); });
|
reg("gaskinetics", []() { return new GasKinetics(); });
|
||||||
reg("interface", []() { return new InterfaceKinetics(); });
|
reg("interface", []() { return new InterfaceKinetics(); });
|
||||||
reg("edge", []() { return new EdgeKinetics(); });
|
reg("edge", []() { return new EdgeKinetics(); });
|
||||||
reg("aqueouskinetics", []() { return new AqueousKinetics(); });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Kinetics* KineticsFactory::newKinetics(const string& model)
|
Kinetics* KineticsFactory::newKinetics(const string& model)
|
||||||
|
|
|
||||||
|
|
@ -264,22 +264,6 @@ void LatticePhase::_updateThermo() const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LatticePhase::setParameters(int n, doublereal* const c)
|
|
||||||
{
|
|
||||||
warn_deprecated("LatticePhase::setParameters",
|
|
||||||
"To be removed after Cantera 2.4.");
|
|
||||||
m_site_density = c[0];
|
|
||||||
setMolarDensity(m_site_density);
|
|
||||||
}
|
|
||||||
|
|
||||||
void LatticePhase::getParameters(int& n, doublereal* const c) const
|
|
||||||
{
|
|
||||||
warn_deprecated("LatticePhase::getParameters",
|
|
||||||
"To be removed after Cantera 2.4.");
|
|
||||||
c[0] = molarDensity();
|
|
||||||
n = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void LatticePhase::setParametersFromXML(const XML_Node& eosdata)
|
void LatticePhase::setParametersFromXML(const XML_Node& eosdata)
|
||||||
{
|
{
|
||||||
eosdata._require("model", "Lattice");
|
eosdata._require("model", "Lattice");
|
||||||
|
|
|
||||||
|
|
@ -1,216 +0,0 @@
|
||||||
/**
|
|
||||||
* @file MetalSHEelectrons.cpp
|
|
||||||
* Definition file for the MetalSHEElectrons class, which represents the
|
|
||||||
* electrons in a metal that are consistent with the
|
|
||||||
* SHE electrode (see \ref thermoprops and
|
|
||||||
* class \link Cantera::MetalSHEelectrons MetalSHEelectrons\endlink)
|
|
||||||
*/
|
|
||||||
|
|
||||||
// This file is part of Cantera. See License.txt in the top-level directory or
|
|
||||||
// at http://www.cantera.org/license.txt for license and copyright information.
|
|
||||||
|
|
||||||
#include "cantera/base/ctml.h"
|
|
||||||
#include "cantera/thermo/MetalSHEelectrons.h"
|
|
||||||
#include "cantera/thermo/ThermoFactory.h"
|
|
||||||
|
|
||||||
namespace Cantera
|
|
||||||
{
|
|
||||||
|
|
||||||
// ---- Constructors -------
|
|
||||||
|
|
||||||
MetalSHEelectrons::MetalSHEelectrons()
|
|
||||||
{
|
|
||||||
warn_deprecated("Class MetalSHEelectrons", "To be removed after Cantera 2.4");
|
|
||||||
}
|
|
||||||
|
|
||||||
MetalSHEelectrons::MetalSHEelectrons(const std::string& infile, const std::string& id_)
|
|
||||||
{
|
|
||||||
warn_deprecated("Class MetalSHEelectrons", "To be removed after Cantera 2.4");
|
|
||||||
initThermoFile(infile, id_);
|
|
||||||
}
|
|
||||||
|
|
||||||
MetalSHEelectrons::MetalSHEelectrons(XML_Node& xmlphase, const std::string& id_)
|
|
||||||
{
|
|
||||||
warn_deprecated("Class MetalSHEelectrons", "To be removed after Cantera 2.4");
|
|
||||||
importPhase(xmlphase, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ----- Mechanical Equation of State ------
|
|
||||||
|
|
||||||
doublereal MetalSHEelectrons::pressure() const
|
|
||||||
{
|
|
||||||
return m_press;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MetalSHEelectrons::setPressure(doublereal p)
|
|
||||||
{
|
|
||||||
m_press = p;
|
|
||||||
}
|
|
||||||
|
|
||||||
doublereal MetalSHEelectrons::isothermalCompressibility() const
|
|
||||||
{
|
|
||||||
return 1.0/pressure();
|
|
||||||
}
|
|
||||||
|
|
||||||
doublereal MetalSHEelectrons::thermalExpansionCoeff() const
|
|
||||||
{
|
|
||||||
return 1.0/temperature();
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---- Chemical Potentials and Activities ----
|
|
||||||
|
|
||||||
void MetalSHEelectrons::getActivityConcentrations(doublereal* c) const
|
|
||||||
{
|
|
||||||
c[0] = 1.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
doublereal MetalSHEelectrons::standardConcentration(size_t k) const
|
|
||||||
{
|
|
||||||
return 1.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
doublereal MetalSHEelectrons::logStandardConc(size_t k) const
|
|
||||||
{
|
|
||||||
return 0.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Properties of the Standard State of the Species in the Solution
|
|
||||||
|
|
||||||
void MetalSHEelectrons::getStandardChemPotentials(doublereal* mu0) const
|
|
||||||
{
|
|
||||||
getGibbs_RT(mu0);
|
|
||||||
mu0[0] *= RT();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MetalSHEelectrons::getEnthalpy_RT(doublereal* hrt) const
|
|
||||||
{
|
|
||||||
getEnthalpy_RT_ref(hrt);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MetalSHEelectrons::getEntropy_R(doublereal* sr) const
|
|
||||||
{
|
|
||||||
getEntropy_R_ref(sr);
|
|
||||||
doublereal tmp = log(pressure() / m_p0);
|
|
||||||
sr[0] -= tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MetalSHEelectrons::getGibbs_RT(doublereal* grt) const
|
|
||||||
{
|
|
||||||
getGibbs_RT_ref(grt);
|
|
||||||
doublereal tmp = log(pressure() / m_p0);
|
|
||||||
grt[0] += tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MetalSHEelectrons::getCp_R(doublereal* cpr) const
|
|
||||||
{
|
|
||||||
_updateThermo();
|
|
||||||
cpr[0] = m_cp0_R;
|
|
||||||
}
|
|
||||||
void MetalSHEelectrons::getIntEnergy_RT(doublereal* urt) const
|
|
||||||
{
|
|
||||||
getEnthalpy_RT(urt);
|
|
||||||
urt[0] -= 1.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MetalSHEelectrons::getIntEnergy_RT_ref(doublereal* urt) const
|
|
||||||
{
|
|
||||||
_updateThermo();
|
|
||||||
urt[0] = m_h0_RT - m_p0 / molarDensity() / RT();
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---- Initialization and Internal functions
|
|
||||||
|
|
||||||
void MetalSHEelectrons::initThermoXML(XML_Node& phaseNode, const std::string& id_)
|
|
||||||
{
|
|
||||||
// Find the Thermo XML node
|
|
||||||
if (!phaseNode.hasChild("thermo")) {
|
|
||||||
throw CanteraError("MetalSHEelectrons::initThermoXML",
|
|
||||||
"no thermo XML node");
|
|
||||||
}
|
|
||||||
XML_Node& tnode = phaseNode.child("thermo");
|
|
||||||
doublereal dens = 2.65E3;
|
|
||||||
if (tnode.hasChild("density")) {
|
|
||||||
dens = getFloat(tnode, "density", "toSI");
|
|
||||||
}
|
|
||||||
setDensity(dens);
|
|
||||||
SingleSpeciesTP::initThermoXML(phaseNode, id_);
|
|
||||||
}
|
|
||||||
|
|
||||||
XML_Node* MetalSHEelectrons::makeDefaultXMLTree()
|
|
||||||
{
|
|
||||||
XML_Node* xtop = new XML_Node("ctml", 0);
|
|
||||||
XML_Node& xv = xtop->addChild("validate");
|
|
||||||
xv.addAttribute("reactions", "yes");
|
|
||||||
xv.addAttribute("species", "yes");
|
|
||||||
|
|
||||||
XML_Node& xp = xtop->addChild("phase");
|
|
||||||
xp.addAttribute("dim", "3");
|
|
||||||
xp.addAttribute("id", "MetalSHEelectrons");
|
|
||||||
XML_Node& xe = xp.addChild("elementArray", "E");
|
|
||||||
xe.addAttribute("datasrc", "elements.xml");
|
|
||||||
XML_Node& xs = xp.addChild("speciesArray", "she_electron");
|
|
||||||
xs.addAttribute("datasrc", "#species_Metal_SHEelectrons");
|
|
||||||
XML_Node& xt = xp.addChild("thermo");
|
|
||||||
xt.addAttribute("model", "metalSHEelectrons");
|
|
||||||
XML_Node& xtr = xp.addChild("transport");
|
|
||||||
xtr.addAttribute("model", "none");
|
|
||||||
XML_Node& xk = xp.addChild("kinetics");
|
|
||||||
xk.addAttribute("model", "none");
|
|
||||||
|
|
||||||
XML_Node& xsd = xtop->addChild("speciesData");
|
|
||||||
xsd.addAttribute("id", "species_Metal_SHEelectrons");
|
|
||||||
|
|
||||||
XML_Node& xsp = xsd.addChild("species");
|
|
||||||
xsp.addAttribute("name", "she_electron");
|
|
||||||
xsp.addChild("atomArray", "E:1");
|
|
||||||
xsp.addChild("charge", "-1");
|
|
||||||
XML_Node& xspt = xsp.addChild("thermo");
|
|
||||||
|
|
||||||
XML_Node& xN1 = xspt.addChild("NASA");
|
|
||||||
xN1.addAttribute("Tmax", "1000.");
|
|
||||||
xN1.addAttribute("Tmin", "200.");
|
|
||||||
xN1.addAttribute("P0", "100000.0");
|
|
||||||
XML_Node& xF1 = xsd.addChild("floatArray",
|
|
||||||
"1.172165560E+00, 3.990260375E-03, -9.739075500E-06, "
|
|
||||||
"1.007860470E-08, -3.688058805E-12, -4.589675865E+02, 3.415051190E-01");
|
|
||||||
xF1.addAttribute("name", "coeffs");
|
|
||||||
xF1.addAttribute("size", "7");
|
|
||||||
|
|
||||||
XML_Node& xN2 = xspt.addChild("NASA");
|
|
||||||
xN2.addAttribute("Tmax", "6000.");
|
|
||||||
xN2.addAttribute("Tmin", "1000.");
|
|
||||||
xN2.addAttribute("P0", "100000.0");
|
|
||||||
XML_Node& xF2 = xsd.addChild("floatArray",
|
|
||||||
"1.466432895E+00, 4.133039835E-04, -7.320116750E-08, 7.705017950E-12,"
|
|
||||||
"-3.444022160E-16, -4.065327985E+02, -5.121644350E-01");
|
|
||||||
xF2.addAttribute("name", "coeffs");
|
|
||||||
xF2.addAttribute("size", "7");
|
|
||||||
|
|
||||||
return xtop;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MetalSHEelectrons::setParameters(int n, doublereal* const c)
|
|
||||||
{
|
|
||||||
setDensity(c[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MetalSHEelectrons::getParameters(int& n, doublereal* const c) const
|
|
||||||
{
|
|
||||||
n = 1;
|
|
||||||
c[0] = density();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MetalSHEelectrons::setParametersFromXML(const XML_Node& eosdata)
|
|
||||||
{
|
|
||||||
if ( eosdata["model"] != "MetalSHEelectrons") {
|
|
||||||
throw CanteraError("MetalSHEelectrons::setParametersFromXML",
|
|
||||||
"thermo model attribute must be MetalSHEelectrons");
|
|
||||||
}
|
|
||||||
doublereal rho = 2.65E3;
|
|
||||||
if (eosdata.hasChild("density")) {
|
|
||||||
rho = getFloat(eosdata, "density", "toSI");
|
|
||||||
}
|
|
||||||
setDensity(rho);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,233 +0,0 @@
|
||||||
/**
|
|
||||||
* @file MineralEQ3.cpp
|
|
||||||
* Definition file for the MineralEQ3 class, which represents a fixed-composition
|
|
||||||
* incompressible substance (see \ref thermoprops and
|
|
||||||
* class \link Cantera::MineralEQ3 MineralEQ3\endlink)
|
|
||||||
*/
|
|
||||||
|
|
||||||
// This file is part of Cantera. See License.txt in the top-level directory or
|
|
||||||
// at http://www.cantera.org/license.txt for license and copyright information.
|
|
||||||
|
|
||||||
#include "cantera/base/ctml.h"
|
|
||||||
#include "cantera/thermo/MineralEQ3.h"
|
|
||||||
#include "cantera/thermo/ThermoFactory.h"
|
|
||||||
#include "cantera/base/stringUtils.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
namespace Cantera
|
|
||||||
{
|
|
||||||
|
|
||||||
// ---- Constructors -------
|
|
||||||
|
|
||||||
MineralEQ3::MineralEQ3(const std::string& infile, const std::string& id_)
|
|
||||||
{
|
|
||||||
warn_deprecated("Class MineralEQ3", "To be removed after Cantera 2.4");
|
|
||||||
initThermoFile(infile, id_);
|
|
||||||
}
|
|
||||||
|
|
||||||
MineralEQ3::MineralEQ3(XML_Node& xmlphase, const std::string& id_)
|
|
||||||
{
|
|
||||||
warn_deprecated("Class MineralEQ3", "To be removed after Cantera 2.4");
|
|
||||||
importPhase(xmlphase, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ----- Mechanical Equation of State ------
|
|
||||||
|
|
||||||
doublereal MineralEQ3::pressure() const
|
|
||||||
{
|
|
||||||
return m_press;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MineralEQ3::setPressure(doublereal p)
|
|
||||||
{
|
|
||||||
m_press = p;
|
|
||||||
}
|
|
||||||
|
|
||||||
doublereal MineralEQ3::isothermalCompressibility() const
|
|
||||||
{
|
|
||||||
return 0.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
doublereal MineralEQ3::thermalExpansionCoeff() const
|
|
||||||
{
|
|
||||||
return 0.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---- Chemical Potentials and Activities ----
|
|
||||||
|
|
||||||
void MineralEQ3::getActivityConcentrations(doublereal* c) const
|
|
||||||
{
|
|
||||||
c[0] = 1.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
doublereal MineralEQ3::standardConcentration(size_t k) const
|
|
||||||
{
|
|
||||||
return 1.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
doublereal MineralEQ3::logStandardConc(size_t k) const
|
|
||||||
{
|
|
||||||
return 0.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Properties of the Standard State of the Species in the Solution
|
|
||||||
|
|
||||||
void MineralEQ3::getStandardChemPotentials(doublereal* mu0) const
|
|
||||||
{
|
|
||||||
getGibbs_RT(mu0);
|
|
||||||
mu0[0] *= RT();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MineralEQ3::getEnthalpy_RT(doublereal* hrt) const
|
|
||||||
{
|
|
||||||
getEnthalpy_RT_ref(hrt);
|
|
||||||
doublereal presCorrect = (m_press - m_p0) / molarDensity();
|
|
||||||
hrt[0] += presCorrect / RT();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MineralEQ3::getEntropy_R(doublereal* sr) const
|
|
||||||
{
|
|
||||||
getEntropy_R_ref(sr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MineralEQ3::getGibbs_RT(doublereal* grt) const
|
|
||||||
{
|
|
||||||
getEnthalpy_RT(grt);
|
|
||||||
grt[0] -= m_s0_R;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MineralEQ3::getCp_R(doublereal* cpr) const
|
|
||||||
{
|
|
||||||
_updateThermo();
|
|
||||||
cpr[0] = m_cp0_R;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MineralEQ3::getIntEnergy_RT(doublereal* urt) const
|
|
||||||
{
|
|
||||||
_updateThermo();
|
|
||||||
urt[0] = m_h0_RT - m_p0 / molarDensity() / RT();
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---- Thermodynamic Values for the Species Reference States ----
|
|
||||||
|
|
||||||
void MineralEQ3::getIntEnergy_RT_ref(doublereal* urt) const
|
|
||||||
{
|
|
||||||
_updateThermo();
|
|
||||||
urt[0] = m_h0_RT - m_p0 / molarDensity() / RT();
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---- Initialization and Internal functions
|
|
||||||
|
|
||||||
void MineralEQ3::setParameters(int n, doublereal* const c)
|
|
||||||
{
|
|
||||||
setDensity(c[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MineralEQ3::getParameters(int& n, doublereal* const c) const
|
|
||||||
{
|
|
||||||
n = 1;
|
|
||||||
c[0] = density();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MineralEQ3::initThermoXML(XML_Node& phaseNode, const std::string& id_)
|
|
||||||
{
|
|
||||||
// Find the Thermo XML node
|
|
||||||
if (!phaseNode.hasChild("thermo")) {
|
|
||||||
throw CanteraError("HMWSoln::initThermoXML",
|
|
||||||
"no thermo XML node");
|
|
||||||
}
|
|
||||||
|
|
||||||
const XML_Node* xsp = speciesData()[0];
|
|
||||||
|
|
||||||
XML_Node* aStandardState = 0;
|
|
||||||
if (xsp->hasChild("standardState")) {
|
|
||||||
aStandardState = &xsp->child("standardState");
|
|
||||||
} else {
|
|
||||||
throw CanteraError("MineralEQ3::initThermoXML",
|
|
||||||
"no standard state mode");
|
|
||||||
}
|
|
||||||
doublereal volVal = 0.0;
|
|
||||||
if (aStandardState->attrib("model") != "constantVolume") {
|
|
||||||
throw CanteraError("MineralEQ3::initThermoXML",
|
|
||||||
"wrong standard state mode");
|
|
||||||
}
|
|
||||||
if (aStandardState->hasChild("V0_Pr_Tr")) {
|
|
||||||
XML_Node& aV = aStandardState->child("V0_Pr_Tr");
|
|
||||||
double Afactor = toSI("cm3/gmol");
|
|
||||||
if (aV.hasAttrib("units")) {
|
|
||||||
Afactor = toSI(aV.attrib("units"));
|
|
||||||
}
|
|
||||||
volVal = getFloat(*aStandardState, "V0_Pr_Tr");
|
|
||||||
m_V0_pr_tr= volVal;
|
|
||||||
volVal *= Afactor;
|
|
||||||
} else {
|
|
||||||
throw CanteraError("MineralEQ3::initThermoXML",
|
|
||||||
"wrong standard state mode");
|
|
||||||
}
|
|
||||||
setDensity(molecularWeight(0) / volVal);
|
|
||||||
|
|
||||||
const XML_Node& MinEQ3node = xsp->child("thermo").child("MinEQ3");
|
|
||||||
|
|
||||||
m_deltaG_formation_pr_tr =
|
|
||||||
getFloat(MinEQ3node, "DG0_f_Pr_Tr", "actEnergy") / actEnergyToSI("cal/gmol");
|
|
||||||
m_deltaH_formation_pr_tr =
|
|
||||||
getFloat(MinEQ3node, "DH0_f_Pr_Tr", "actEnergy") / actEnergyToSI("cal/gmol");
|
|
||||||
m_Entrop_pr_tr = getFloat(MinEQ3node, "S0_Pr_Tr", "toSI") / toSI("cal/gmol/K");
|
|
||||||
m_a = getFloat(MinEQ3node, "a", "toSI") / toSI("cal/gmol/K");
|
|
||||||
m_b = getFloat(MinEQ3node, "b", "toSI") / toSI("cal/gmol/K2");
|
|
||||||
m_c = getFloat(MinEQ3node, "c", "toSI") / toSI("cal-K/gmol");
|
|
||||||
|
|
||||||
convertDGFormation();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MineralEQ3::setParametersFromXML(const XML_Node& eosdata)
|
|
||||||
{
|
|
||||||
if (eosdata["model"] != "MineralEQ3") {
|
|
||||||
throw CanteraError("MineralEQ3::MineralEQ3",
|
|
||||||
"thermo model attribute must be MineralEQ3");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
doublereal MineralEQ3::LookupGe(const std::string& elemName)
|
|
||||||
{
|
|
||||||
size_t iE = elementIndex(elemName);
|
|
||||||
if (iE == npos) {
|
|
||||||
throw CanteraError("PDSS_HKFT::LookupGe", "element " + elemName + " not found");
|
|
||||||
}
|
|
||||||
doublereal geValue = entropyElement298(iE);
|
|
||||||
if (geValue == ENTROPY298_UNKNOWN) {
|
|
||||||
throw CanteraError("PDSS_HKFT::LookupGe",
|
|
||||||
"element " + elemName + " does not have a supplied entropy298");
|
|
||||||
}
|
|
||||||
geValue *= (-298.15);
|
|
||||||
return geValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MineralEQ3::convertDGFormation()
|
|
||||||
{
|
|
||||||
// Ok let's get the element compositions and conversion factors.
|
|
||||||
doublereal totalSum = 0.0;
|
|
||||||
for (size_t m = 0; m < nElements(); m++) {
|
|
||||||
double na = nAtoms(0, m);
|
|
||||||
if (na > 0.0) {
|
|
||||||
totalSum += na * LookupGe(elementName(m));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Ok, now do the calculation. Convert to joules kmol-1
|
|
||||||
doublereal dg = m_deltaG_formation_pr_tr * toSI("cal/gmol");
|
|
||||||
//! Store the result into an internal variable.
|
|
||||||
m_Mu0_pr_tr = dg + totalSum;
|
|
||||||
|
|
||||||
double Hcalc = m_Mu0_pr_tr + 298.15 * m_Entrop_pr_tr * toSI("cal/gmol");
|
|
||||||
double DHjmol = m_deltaH_formation_pr_tr * toSI("kal/gmol");
|
|
||||||
|
|
||||||
// If the discrepancy is greater than 100 cal gmol-1, print an error
|
|
||||||
if (fabs(Hcalc -DHjmol) > 100 * toSI("cal/gmol")) {
|
|
||||||
throw CanteraError("installMinEQ3asShomateThermoFromXML()",
|
|
||||||
"DHjmol is not consistent with G and S: {} vs {}",
|
|
||||||
Hcalc, DHjmol);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,587 +0,0 @@
|
||||||
/**
|
|
||||||
* @file MixedSolventElectrolyte.cpp see \ref thermoprops and class \link
|
|
||||||
* Cantera::MixedSolventElectrolyte MixedSolventElectrolyte \endlink).
|
|
||||||
*/
|
|
||||||
|
|
||||||
// This file is part of Cantera. See License.txt in the top-level directory or
|
|
||||||
// at http://www.cantera.org/license.txt for license and copyright information.
|
|
||||||
|
|
||||||
#include "cantera/thermo/MixedSolventElectrolyte.h"
|
|
||||||
#include "cantera/thermo/ThermoFactory.h"
|
|
||||||
#include "cantera/base/stringUtils.h"
|
|
||||||
#include "cantera/base/ctml.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
namespace Cantera
|
|
||||||
{
|
|
||||||
MixedSolventElectrolyte::MixedSolventElectrolyte() :
|
|
||||||
numBinaryInteractions_(0),
|
|
||||||
formMargules_(0),
|
|
||||||
formTempModel_(0)
|
|
||||||
{
|
|
||||||
warn_deprecated("class MixedSolventElectrolyte",
|
|
||||||
"To be removed after Cantera 2.4");
|
|
||||||
}
|
|
||||||
|
|
||||||
MixedSolventElectrolyte::MixedSolventElectrolyte(const std::string& inputFile,
|
|
||||||
const std::string& id_) :
|
|
||||||
numBinaryInteractions_(0),
|
|
||||||
formMargules_(0),
|
|
||||||
formTempModel_(0)
|
|
||||||
{
|
|
||||||
warn_deprecated("class MixedSolventElectrolyte",
|
|
||||||
"To be removed after Cantera 2.4");
|
|
||||||
initThermoFile(inputFile, id_);
|
|
||||||
}
|
|
||||||
|
|
||||||
MixedSolventElectrolyte::MixedSolventElectrolyte(XML_Node& phaseRoot,
|
|
||||||
const std::string& id_) :
|
|
||||||
numBinaryInteractions_(0),
|
|
||||||
formMargules_(0),
|
|
||||||
formTempModel_(0)
|
|
||||||
{
|
|
||||||
warn_deprecated("class MixedSolventElectrolyte",
|
|
||||||
"To be removed after Cantera 2.4");
|
|
||||||
importPhase(phaseRoot, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
// - Activities, Standard States, Activity Concentrations -----------
|
|
||||||
|
|
||||||
void MixedSolventElectrolyte::getActivityCoefficients(doublereal* ac) const
|
|
||||||
{
|
|
||||||
// Update the activity coefficients
|
|
||||||
s_update_lnActCoeff();
|
|
||||||
|
|
||||||
// take the exp of the internally stored coefficients.
|
|
||||||
for (size_t k = 0; k < m_kk; k++) {
|
|
||||||
ac[k] = exp(lnActCoeff_Scaled_[k]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------ Partial Molar Properties of the Solution ------------
|
|
||||||
|
|
||||||
void MixedSolventElectrolyte::getChemPotentials(doublereal* mu) const
|
|
||||||
{
|
|
||||||
// First get the standard chemical potentials in molar form. This requires
|
|
||||||
// updates of standard state as a function of T and P
|
|
||||||
getStandardChemPotentials(mu);
|
|
||||||
// Update the activity coefficients
|
|
||||||
s_update_lnActCoeff();
|
|
||||||
for (size_t k = 0; k < m_kk; k++) {
|
|
||||||
double xx = std::max(moleFractions_[k], SmallNumber);
|
|
||||||
mu[k] += RT() * (log(xx) + lnActCoeff_Scaled_[k]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
doublereal MixedSolventElectrolyte::enthalpy_mole() const
|
|
||||||
{
|
|
||||||
double h = 0;
|
|
||||||
vector_fp hbar(m_kk);
|
|
||||||
getPartialMolarEnthalpies(&hbar[0]);
|
|
||||||
for (size_t i = 0; i < m_kk; i++) {
|
|
||||||
h += moleFractions_[i]*hbar[i];
|
|
||||||
}
|
|
||||||
return h;
|
|
||||||
}
|
|
||||||
|
|
||||||
doublereal MixedSolventElectrolyte::entropy_mole() const
|
|
||||||
{
|
|
||||||
double s = 0;
|
|
||||||
vector_fp sbar(m_kk);
|
|
||||||
getPartialMolarEntropies(&sbar[0]);
|
|
||||||
for (size_t i = 0; i < m_kk; i++) {
|
|
||||||
s += moleFractions_[i]*sbar[i];
|
|
||||||
}
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
doublereal MixedSolventElectrolyte::cp_mole() const
|
|
||||||
{
|
|
||||||
double cp = 0;
|
|
||||||
vector_fp cpbar(m_kk);
|
|
||||||
getPartialMolarCp(&cpbar[0]);
|
|
||||||
for (size_t i = 0; i < m_kk; i++) {
|
|
||||||
cp += moleFractions_[i]*cpbar[i];
|
|
||||||
}
|
|
||||||
return cp;
|
|
||||||
}
|
|
||||||
|
|
||||||
doublereal MixedSolventElectrolyte::cv_mole() const
|
|
||||||
{
|
|
||||||
return cp_mole() - GasConstant;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MixedSolventElectrolyte::getPartialMolarEnthalpies(doublereal* hbar) const
|
|
||||||
{
|
|
||||||
// Get the nondimensional standard state enthalpies
|
|
||||||
getEnthalpy_RT(hbar);
|
|
||||||
// dimensionalize it.
|
|
||||||
for (size_t k = 0; k < m_kk; k++) {
|
|
||||||
hbar[k] *= RT();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update the activity coefficients, This also update the internally stored
|
|
||||||
// molalities.
|
|
||||||
s_update_lnActCoeff();
|
|
||||||
s_update_dlnActCoeff_dT();
|
|
||||||
for (size_t k = 0; k < m_kk; k++) {
|
|
||||||
hbar[k] -= RT() * temperature() * dlnActCoeffdT_Scaled_[k];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MixedSolventElectrolyte::getPartialMolarCp(doublereal* cpbar) const
|
|
||||||
{
|
|
||||||
getCp_R(cpbar);
|
|
||||||
double T = temperature();
|
|
||||||
|
|
||||||
// Update the activity coefficients, This also update the internally stored
|
|
||||||
// molalities.
|
|
||||||
s_update_lnActCoeff();
|
|
||||||
s_update_dlnActCoeff_dT();
|
|
||||||
|
|
||||||
for (size_t k = 0; k < m_kk; k++) {
|
|
||||||
cpbar[k] -= 2 * T * dlnActCoeffdT_Scaled_[k] + T * T * d2lnActCoeffdT2_Scaled_[k];
|
|
||||||
}
|
|
||||||
// dimensionalize it.
|
|
||||||
for (size_t k = 0; k < m_kk; k++) {
|
|
||||||
cpbar[k] *= GasConstant;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MixedSolventElectrolyte::getPartialMolarEntropies(doublereal* sbar) const
|
|
||||||
{
|
|
||||||
// Get the nondimensional standard state entropies
|
|
||||||
getEntropy_R(sbar);
|
|
||||||
double T = temperature();
|
|
||||||
|
|
||||||
// Update the activity coefficients, This also update the
|
|
||||||
// internally stored molalities.
|
|
||||||
s_update_lnActCoeff();
|
|
||||||
s_update_dlnActCoeff_dT();
|
|
||||||
|
|
||||||
for (size_t k = 0; k < m_kk; k++) {
|
|
||||||
double xx = std::max(moleFractions_[k], SmallNumber);
|
|
||||||
sbar[k] += - lnActCoeff_Scaled_[k] -log(xx) - T * dlnActCoeffdT_Scaled_[k];
|
|
||||||
}
|
|
||||||
// dimensionalize it.
|
|
||||||
for (size_t k = 0; k < m_kk; k++) {
|
|
||||||
sbar[k] *= GasConstant;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MixedSolventElectrolyte::getPartialMolarVolumes(doublereal* vbar) const
|
|
||||||
{
|
|
||||||
double T = temperature();
|
|
||||||
|
|
||||||
// Get the standard state values in m^3 kmol-1
|
|
||||||
getStandardVolumes(vbar);
|
|
||||||
|
|
||||||
for (size_t iK = 0; iK < m_kk; iK++) {
|
|
||||||
int delAK = 0;
|
|
||||||
int delBK = 0;
|
|
||||||
for (size_t i = 0; i < numBinaryInteractions_; i++) {
|
|
||||||
size_t iA = m_pSpecies_A_ij[i];
|
|
||||||
size_t iB = m_pSpecies_B_ij[i];
|
|
||||||
|
|
||||||
if (iA==iK) {
|
|
||||||
delAK = 1;
|
|
||||||
} else if (iB==iK) {
|
|
||||||
delBK = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
double XA = moleFractions_[iA];
|
|
||||||
double XB = moleFractions_[iB];
|
|
||||||
|
|
||||||
double g0 = (m_VHE_b_ij[i] - T * m_VSE_b_ij[i]);
|
|
||||||
double g1 = (m_VHE_c_ij[i] - T * m_VSE_c_ij[i]);
|
|
||||||
|
|
||||||
vbar[iK] += XA*XB*(g0+g1*XB)+((delAK-XA)*XB+XA*(delBK-XB))*(g0+g1*XB)+XA*XB*(delBK-XB)*g1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MixedSolventElectrolyte::initThermo()
|
|
||||||
{
|
|
||||||
initLengths();
|
|
||||||
MolarityIonicVPSSTP::initThermo();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MixedSolventElectrolyte::initLengths()
|
|
||||||
{
|
|
||||||
dlnActCoeffdlnN_.resize(m_kk, m_kk);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MixedSolventElectrolyte::initThermoXML(XML_Node& phaseNode, const std::string& id_)
|
|
||||||
{
|
|
||||||
if ((int) id_.size() > 0 && phaseNode.id() != id_) {
|
|
||||||
throw CanteraError("MixedSolventElectrolyte::initThermoXML",
|
|
||||||
"phasenode and Id are incompatible");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check on the thermo field. Must have:
|
|
||||||
// <thermo model="MixedSolventElectrolyte" />
|
|
||||||
if (!phaseNode.hasChild("thermo")) {
|
|
||||||
throw CanteraError("MixedSolventElectrolyte::initThermoXML",
|
|
||||||
"no thermo XML node");
|
|
||||||
}
|
|
||||||
XML_Node& thermoNode = phaseNode.child("thermo");
|
|
||||||
string mString = thermoNode["model"];
|
|
||||||
if (!caseInsensitiveEquals(thermoNode["model"], "mixedsolventelectrolyte")) {
|
|
||||||
throw CanteraError("MixedSolventElectrolyte::initThermoXML",
|
|
||||||
"Unknown thermo model: " + thermoNode["model"]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Go get all of the coefficients and factors in the activityCoefficients
|
|
||||||
// XML block
|
|
||||||
if (thermoNode.hasChild("activityCoefficients")) {
|
|
||||||
XML_Node& acNode = thermoNode.child("activityCoefficients");
|
|
||||||
if (!caseInsensitiveEquals(acNode["model"], "margules")) {
|
|
||||||
throw CanteraError("MixedSolventElectrolyte::initThermoXML",
|
|
||||||
"Unknown activity coefficient model: " + acNode["model"]);
|
|
||||||
}
|
|
||||||
for (size_t i = 0; i < acNode.nChildren(); i++) {
|
|
||||||
XML_Node& xmlACChild = acNode.child(i);
|
|
||||||
|
|
||||||
// Process a binary salt field, or any of the other XML fields that
|
|
||||||
// make up the Pitzer Database. Entries will be ignored if any of
|
|
||||||
// the species in the entry isn't in the solution.
|
|
||||||
if (caseInsensitiveEquals(xmlACChild.name(), "binaryneutralspeciesparameters")) {
|
|
||||||
readXMLBinarySpecies(xmlACChild);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Go down the chain
|
|
||||||
MolarityIonicVPSSTP::initThermoXML(phaseNode, id_);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MixedSolventElectrolyte::s_update_lnActCoeff() const
|
|
||||||
{
|
|
||||||
double T = temperature();
|
|
||||||
lnActCoeff_Scaled_.assign(m_kk, 0.0);
|
|
||||||
for (size_t iK = 0; iK < m_kk; iK++) {
|
|
||||||
for (size_t i = 0; i < numBinaryInteractions_; i++) {
|
|
||||||
size_t iA = m_pSpecies_A_ij[i];
|
|
||||||
size_t iB = m_pSpecies_B_ij[i];
|
|
||||||
int delAK = 0;
|
|
||||||
int delBK = 0;
|
|
||||||
if (iA==iK) {
|
|
||||||
delAK = 1;
|
|
||||||
} else if (iB==iK) {
|
|
||||||
delBK = 1;
|
|
||||||
}
|
|
||||||
double XA = moleFractions_[iA];
|
|
||||||
double XB = moleFractions_[iB];
|
|
||||||
double g0 = (m_HE_b_ij[i] - T * m_SE_b_ij[i]) / RT();
|
|
||||||
double g1 = (m_HE_c_ij[i] - T * m_SE_c_ij[i]) / RT();
|
|
||||||
lnActCoeff_Scaled_[iK] += (delAK * XB + XA * delBK - XA * XB) * (g0 + g1 * XB) + XA * XB * (delBK - XB) * g1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MixedSolventElectrolyte::s_update_dlnActCoeff_dT() const
|
|
||||||
{
|
|
||||||
doublereal T = temperature();
|
|
||||||
doublereal RTT = GasConstant*T*T;
|
|
||||||
dlnActCoeffdT_Scaled_.assign(m_kk, 0.0);
|
|
||||||
d2lnActCoeffdT2_Scaled_.assign(m_kk, 0.0);
|
|
||||||
for (size_t iK = 0; iK < m_kk; iK++) {
|
|
||||||
for (size_t i = 0; i < numBinaryInteractions_; i++) {
|
|
||||||
size_t iA = m_pSpecies_A_ij[i];
|
|
||||||
size_t iB = m_pSpecies_B_ij[i];
|
|
||||||
int delAK = 0;
|
|
||||||
int delBK = 0;
|
|
||||||
if (iA==iK) {
|
|
||||||
delAK = 1;
|
|
||||||
} else if (iB==iK) {
|
|
||||||
delBK = 1;
|
|
||||||
}
|
|
||||||
double XA = moleFractions_[iA];
|
|
||||||
double XB = moleFractions_[iB];
|
|
||||||
double g0 = -m_HE_b_ij[i] / RTT;
|
|
||||||
double g1 = -m_HE_c_ij[i] / RTT;
|
|
||||||
double temp = (delAK * XB + XA * delBK - XA * XB) * (g0 + g1 * XB) + XA * XB * (delBK - XB) * g1;
|
|
||||||
dlnActCoeffdT_Scaled_[iK] += temp;
|
|
||||||
d2lnActCoeffdT2_Scaled_[iK] -= 2.0 * temp / T;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MixedSolventElectrolyte::getdlnActCoeffdT(doublereal* dlnActCoeffdT) const
|
|
||||||
{
|
|
||||||
s_update_dlnActCoeff_dT();
|
|
||||||
for (size_t k = 0; k < m_kk; k++) {
|
|
||||||
dlnActCoeffdT[k] = dlnActCoeffdT_Scaled_[k];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MixedSolventElectrolyte::getd2lnActCoeffdT2(doublereal* d2lnActCoeffdT2) const
|
|
||||||
{
|
|
||||||
s_update_dlnActCoeff_dT();
|
|
||||||
for (size_t k = 0; k < m_kk; k++) {
|
|
||||||
d2lnActCoeffdT2[k] = d2lnActCoeffdT2_Scaled_[k];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MixedSolventElectrolyte::getdlnActCoeffds(const doublereal dTds, const doublereal* const dXds,
|
|
||||||
doublereal* dlnActCoeffds) const
|
|
||||||
{
|
|
||||||
double T = temperature();
|
|
||||||
s_update_dlnActCoeff_dT();
|
|
||||||
|
|
||||||
for (size_t iK = 0; iK < m_kk; iK++) {
|
|
||||||
dlnActCoeffds[iK] = 0.0;
|
|
||||||
for (size_t i = 0; i < numBinaryInteractions_; i++) {
|
|
||||||
size_t iA = m_pSpecies_A_ij[i];
|
|
||||||
size_t iB = m_pSpecies_B_ij[i];
|
|
||||||
int delAK = 0;
|
|
||||||
int delBK = 0;
|
|
||||||
|
|
||||||
if (iA==iK) {
|
|
||||||
delAK = 1;
|
|
||||||
} else if (iB==iK) {
|
|
||||||
delBK = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
double XA = moleFractions_[iA];
|
|
||||||
double XB = moleFractions_[iB];
|
|
||||||
double dXA = dXds[iA];
|
|
||||||
double dXB = dXds[iB];
|
|
||||||
double g0 = (m_HE_b_ij[i] - T * m_SE_b_ij[i]) / RT();
|
|
||||||
double g1 = (m_HE_c_ij[i] - T * m_SE_c_ij[i]) / RT();
|
|
||||||
dlnActCoeffds[iK] += ((delBK-XB)*dXA + (delAK-XA)*dXB)*(g0+2*g1*XB) + (delBK-XB)*2*g1*XA*dXB
|
|
||||||
+ dlnActCoeffdT_Scaled_[iK]*dTds;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MixedSolventElectrolyte::s_update_dlnActCoeff_dlnN_diag() const
|
|
||||||
{
|
|
||||||
double T = temperature();
|
|
||||||
dlnActCoeffdlnN_diag_.assign(m_kk, 0);
|
|
||||||
|
|
||||||
for (size_t iK = 0; iK < m_kk; iK++) {
|
|
||||||
double XK = moleFractions_[iK];
|
|
||||||
for (size_t i = 0; i < numBinaryInteractions_; i++) {
|
|
||||||
size_t iA = m_pSpecies_A_ij[i];
|
|
||||||
size_t iB = m_pSpecies_B_ij[i];
|
|
||||||
int delAK = 0;
|
|
||||||
int delBK = 0;
|
|
||||||
|
|
||||||
if (iA==iK) {
|
|
||||||
delAK = 1;
|
|
||||||
} else if (iB==iK) {
|
|
||||||
delBK = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
double XA = moleFractions_[iA];
|
|
||||||
double XB = moleFractions_[iB];
|
|
||||||
double g0 = (m_HE_b_ij[i] - T * m_SE_b_ij[i]) / RT();
|
|
||||||
double g1 = (m_HE_c_ij[i] - T * m_SE_c_ij[i]) / RT();
|
|
||||||
|
|
||||||
dlnActCoeffdlnN_diag_[iK] += 2*(delBK-XB)*(g0*(delAK-XA)+g1*(2*(delAK-XA)*XB+XA*(delBK-XB)));
|
|
||||||
}
|
|
||||||
dlnActCoeffdlnN_diag_[iK] = XK*dlnActCoeffdlnN_diag_[iK];//-XK;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MixedSolventElectrolyte::s_update_dlnActCoeff_dlnN() const
|
|
||||||
{
|
|
||||||
double T = temperature();
|
|
||||||
dlnActCoeffdlnN_.zero();
|
|
||||||
|
|
||||||
// Loop over the activity coefficient gamma_k
|
|
||||||
for (size_t iK = 0; iK < m_kk; iK++) {
|
|
||||||
for (size_t iM = 0; iM < m_kk; iM++) {
|
|
||||||
double XM = moleFractions_[iM];
|
|
||||||
for (size_t i = 0; i < numBinaryInteractions_; i++) {
|
|
||||||
size_t iA = m_pSpecies_A_ij[i];
|
|
||||||
size_t iB = m_pSpecies_B_ij[i];
|
|
||||||
double delAK = 0.0;
|
|
||||||
double delBK = 0.0;
|
|
||||||
double delAM = 0.0;
|
|
||||||
double delBM = 0.0;
|
|
||||||
if (iA==iK) {
|
|
||||||
delAK = 1.0;
|
|
||||||
} else if (iB==iK) {
|
|
||||||
delBK = 1.0;
|
|
||||||
}
|
|
||||||
if (iA==iM) {
|
|
||||||
delAM = 1.0;
|
|
||||||
} else if (iB==iM) {
|
|
||||||
delBM = 1.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
double XA = moleFractions_[iA];
|
|
||||||
double XB = moleFractions_[iB];
|
|
||||||
double g0 = (m_HE_b_ij[i] - T * m_SE_b_ij[i]) / RT();
|
|
||||||
double g1 = (m_HE_c_ij[i] - T * m_SE_c_ij[i]) / RT();
|
|
||||||
dlnActCoeffdlnN_(iK,iM) += g0*((delAM-XA)*(delBK-XB)+(delAK-XA)*(delBM-XB));
|
|
||||||
dlnActCoeffdlnN_(iK,iM) += 2*g1*((delAM-XA)*(delBK-XB)*XB+(delAK-XA)*(delBM-XB)*XB+(delBM-XB)*(delBK-XB)*XA);
|
|
||||||
}
|
|
||||||
dlnActCoeffdlnN_(iK,iM) = XM*dlnActCoeffdlnN_(iK,iM);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MixedSolventElectrolyte::s_update_dlnActCoeff_dlnX_diag() const
|
|
||||||
{
|
|
||||||
doublereal T = temperature();
|
|
||||||
dlnActCoeffdlnX_diag_.assign(m_kk, 0);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < numBinaryInteractions_; i++) {
|
|
||||||
size_t iA = m_pSpecies_A_ij[i];
|
|
||||||
size_t iB = m_pSpecies_B_ij[i];
|
|
||||||
double XA = moleFractions_[iA];
|
|
||||||
double XB = moleFractions_[iB];
|
|
||||||
double g0 = (m_HE_b_ij[i] - T * m_SE_b_ij[i]) / RT();
|
|
||||||
double g1 = (m_HE_c_ij[i] - T * m_SE_c_ij[i]) / RT();
|
|
||||||
dlnActCoeffdlnX_diag_[iA] += XA*XB*(2*g1*-2*g0-6*g1*XB);
|
|
||||||
dlnActCoeffdlnX_diag_[iB] += XA*XB*(2*g1*-2*g0-6*g1*XB);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MixedSolventElectrolyte::getdlnActCoeffdlnN_diag(doublereal* dlnActCoeffdlnN_diag) const
|
|
||||||
{
|
|
||||||
s_update_dlnActCoeff_dlnN_diag();
|
|
||||||
for (size_t k = 0; k < m_kk; k++) {
|
|
||||||
dlnActCoeffdlnN_diag[k] = dlnActCoeffdlnN_diag_[k];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MixedSolventElectrolyte::getdlnActCoeffdlnX_diag(doublereal* dlnActCoeffdlnX_diag) const
|
|
||||||
{
|
|
||||||
s_update_dlnActCoeff_dlnX_diag();
|
|
||||||
for (size_t k = 0; k < m_kk; k++) {
|
|
||||||
dlnActCoeffdlnX_diag[k] = dlnActCoeffdlnX_diag_[k];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MixedSolventElectrolyte::getdlnActCoeffdlnN(const size_t ld, doublereal* dlnActCoeffdlnN)
|
|
||||||
{
|
|
||||||
s_update_dlnActCoeff_dlnN();
|
|
||||||
double* data = & dlnActCoeffdlnN_(0,0);
|
|
||||||
for (size_t k = 0; k < m_kk; k++) {
|
|
||||||
for (size_t m = 0; m < m_kk; m++) {
|
|
||||||
dlnActCoeffdlnN[ld * k + m] = data[m_kk * k + m];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MixedSolventElectrolyte::resizeNumInteractions(const size_t num)
|
|
||||||
{
|
|
||||||
numBinaryInteractions_ = num;
|
|
||||||
m_HE_b_ij.resize(num, 0.0);
|
|
||||||
m_HE_c_ij.resize(num, 0.0);
|
|
||||||
m_HE_d_ij.resize(num, 0.0);
|
|
||||||
m_SE_b_ij.resize(num, 0.0);
|
|
||||||
m_SE_c_ij.resize(num, 0.0);
|
|
||||||
m_SE_d_ij.resize(num, 0.0);
|
|
||||||
m_VHE_b_ij.resize(num, 0.0);
|
|
||||||
m_VHE_c_ij.resize(num, 0.0);
|
|
||||||
m_VHE_d_ij.resize(num, 0.0);
|
|
||||||
m_VSE_b_ij.resize(num, 0.0);
|
|
||||||
m_VSE_c_ij.resize(num, 0.0);
|
|
||||||
m_VSE_d_ij.resize(num, 0.0);
|
|
||||||
m_pSpecies_A_ij.resize(num, npos);
|
|
||||||
m_pSpecies_B_ij.resize(num, npos);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MixedSolventElectrolyte::readXMLBinarySpecies(XML_Node& xmLBinarySpecies)
|
|
||||||
{
|
|
||||||
string xname = xmLBinarySpecies.name();
|
|
||||||
if (xname != "binaryNeutralSpeciesParameters") {
|
|
||||||
throw CanteraError("MixedSolventElectrolyte::readXMLBinarySpecies",
|
|
||||||
"Incorrect name for processing this routine: " + xname);
|
|
||||||
}
|
|
||||||
vector_fp vParams;
|
|
||||||
string iName = xmLBinarySpecies.attrib("speciesA");
|
|
||||||
if (iName == "") {
|
|
||||||
throw CanteraError("MixedSolventElectrolyte::readXMLBinarySpecies", "no speciesA attrib");
|
|
||||||
}
|
|
||||||
string jName = xmLBinarySpecies.attrib("speciesB");
|
|
||||||
if (jName == "") {
|
|
||||||
throw CanteraError("MixedSolventElectrolyte::readXMLBinarySpecies", "no speciesB attrib");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find the index of the species in the current phase. It's not an error to
|
|
||||||
// not find the species
|
|
||||||
size_t iSpecies = speciesIndex(iName);
|
|
||||||
if (iSpecies == npos) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
string ispName = speciesName(iSpecies);
|
|
||||||
if (charge(iSpecies) != 0) {
|
|
||||||
throw CanteraError("MixedSolventElectrolyte::readXMLBinarySpecies", "speciesA charge problem");
|
|
||||||
}
|
|
||||||
size_t jSpecies = speciesIndex(jName);
|
|
||||||
if (jSpecies == npos) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
string jspName = speciesName(jSpecies);
|
|
||||||
if (charge(jSpecies) != 0) {
|
|
||||||
throw CanteraError("MixedSolventElectrolyte::readXMLBinarySpecies", "speciesB charge problem");
|
|
||||||
}
|
|
||||||
|
|
||||||
resizeNumInteractions(numBinaryInteractions_ + 1);
|
|
||||||
size_t iSpot = numBinaryInteractions_ - 1;
|
|
||||||
m_pSpecies_A_ij[iSpot] = iSpecies;
|
|
||||||
m_pSpecies_B_ij[iSpot] = jSpecies;
|
|
||||||
|
|
||||||
for (size_t iChild = 0; iChild < xmLBinarySpecies.nChildren(); iChild++) {
|
|
||||||
XML_Node& xmlChild = xmLBinarySpecies.child(iChild);
|
|
||||||
string nodeName = toLowerCopy(xmlChild.name());
|
|
||||||
|
|
||||||
// Process the binary species interaction child elements
|
|
||||||
if (nodeName == "excessenthalpy") {
|
|
||||||
// Get the string containing all of the values
|
|
||||||
getFloatArray(xmlChild, vParams, true, "toSI", "excessEnthalpy");
|
|
||||||
if (vParams.size() != 2) {
|
|
||||||
throw CanteraError("MixedSolventElectrolyte::readXMLBinarySpecies::excessEnthalpy for " + ispName
|
|
||||||
+ "::" + jspName,
|
|
||||||
"wrong number of params found");
|
|
||||||
}
|
|
||||||
m_HE_b_ij[iSpot] = vParams[0];
|
|
||||||
m_HE_c_ij[iSpot] = vParams[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nodeName == "excessentropy") {
|
|
||||||
// Get the string containing all of the values
|
|
||||||
getFloatArray(xmlChild, vParams, true, "toSI", "excessEntropy");
|
|
||||||
if (vParams.size() != 2) {
|
|
||||||
throw CanteraError("MixedSolventElectrolyte::readXMLBinarySpecies::excessEntropy for " + ispName
|
|
||||||
+ "::" + jspName,
|
|
||||||
"wrong number of params found");
|
|
||||||
}
|
|
||||||
m_SE_b_ij[iSpot] = vParams[0];
|
|
||||||
m_SE_c_ij[iSpot] = vParams[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nodeName == "excessvolume_enthalpy") {
|
|
||||||
// Get the string containing all of the values
|
|
||||||
getFloatArray(xmlChild, vParams, true, "toSI", "excessVolume_Enthalpy");
|
|
||||||
if (vParams.size() != 2) {
|
|
||||||
throw CanteraError("MixedSolventElectrolyte::readXMLBinarySpecies::excessVolume_Enthalpy for " + ispName
|
|
||||||
+ "::" + jspName,
|
|
||||||
"wrong number of params found");
|
|
||||||
}
|
|
||||||
m_VHE_b_ij[iSpot] = vParams[0];
|
|
||||||
m_VHE_c_ij[iSpot] = vParams[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nodeName == "excessvolume_entropy") {
|
|
||||||
// Get the string containing all of the values
|
|
||||||
getFloatArray(xmlChild, vParams, true, "toSI", "excessVolume_Entropy");
|
|
||||||
if (vParams.size() != 2) {
|
|
||||||
throw CanteraError("MixedSolventElectrolyte::readXMLBinarySpecies::excessVolume_Entropy for " + ispName
|
|
||||||
+ "::" + jspName,
|
|
||||||
"wrong number of params found");
|
|
||||||
}
|
|
||||||
m_VSE_b_ij[iSpot] = vParams[0];
|
|
||||||
m_VSE_c_ij[iSpot] = vParams[1];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -50,19 +50,6 @@ int MolalityVPSSTP::pHScale() const
|
||||||
return m_pHScalingType;
|
return m_pHScalingType;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MolalityVPSSTP::setSolvent(size_t k)
|
|
||||||
{
|
|
||||||
warn_deprecated("MolalityVPSSTP::setSolvent", "Solvent is always the first"
|
|
||||||
" species. To be removed after Cantera 2.4.");
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t MolalityVPSSTP::solventIndex() const
|
|
||||||
{
|
|
||||||
warn_deprecated("MolalityVPSSTP::solventIndex", "Solvent is always the"
|
|
||||||
" first species. To be removed after Cantera 2.4.");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MolalityVPSSTP::setMoleFSolventMin(doublereal xmolSolventMIN)
|
void MolalityVPSSTP::setMoleFSolventMin(doublereal xmolSolventMIN)
|
||||||
{
|
{
|
||||||
if (xmolSolventMIN <= 0.0) {
|
if (xmolSolventMIN <= 0.0) {
|
||||||
|
|
|
||||||
|
|
@ -1,371 +0,0 @@
|
||||||
/**
|
|
||||||
* @file MolarityIonicVPSSTP.cpp
|
|
||||||
* Definitions for intermediate ThermoPhase object for phases which
|
|
||||||
* employ excess Gibbs free energy formulations
|
|
||||||
* (see \ref thermoprops
|
|
||||||
* and class \link Cantera::MolarityIonicVPSSTP MolarityIonicVPSSTP\endlink).
|
|
||||||
*
|
|
||||||
* Header file for a derived class of ThermoPhase that handles variable pressure
|
|
||||||
* standard state methods for calculating thermodynamic properties that are
|
|
||||||
* further based upon expressions for the excess Gibbs free energy expressed as
|
|
||||||
* a function of the mole fractions.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// This file is part of Cantera. See License.txt in the top-level directory or
|
|
||||||
// at http://www.cantera.org/license.txt for license and copyright information.
|
|
||||||
|
|
||||||
#include "cantera/thermo/MolarityIonicVPSSTP.h"
|
|
||||||
#include "cantera/thermo/ThermoFactory.h"
|
|
||||||
#include "cantera/base/stringUtils.h"
|
|
||||||
|
|
||||||
#include <cstdio>
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
namespace Cantera
|
|
||||||
{
|
|
||||||
|
|
||||||
MolarityIonicVPSSTP::MolarityIonicVPSSTP() :
|
|
||||||
PBType_(PBTYPE_PASSTHROUGH),
|
|
||||||
numPBSpecies_(m_kk),
|
|
||||||
neutralPBindexStart(0)
|
|
||||||
{
|
|
||||||
warn_deprecated("Class MolarityIonicVPSSTP", "To be removed after Cantera 2.4");
|
|
||||||
}
|
|
||||||
|
|
||||||
MolarityIonicVPSSTP::MolarityIonicVPSSTP(const std::string& inputFile,
|
|
||||||
const std::string& id_) :
|
|
||||||
PBType_(PBTYPE_PASSTHROUGH),
|
|
||||||
numPBSpecies_(m_kk),
|
|
||||||
neutralPBindexStart(0)
|
|
||||||
{
|
|
||||||
warn_deprecated("Class MolarityIonicVPSSTP", "To be removed after Cantera 2.4");
|
|
||||||
initThermoFile(inputFile, id_);
|
|
||||||
}
|
|
||||||
|
|
||||||
MolarityIonicVPSSTP::MolarityIonicVPSSTP(XML_Node& phaseRoot,
|
|
||||||
const std::string& id_) :
|
|
||||||
PBType_(PBTYPE_PASSTHROUGH),
|
|
||||||
numPBSpecies_(m_kk),
|
|
||||||
neutralPBindexStart(0)
|
|
||||||
{
|
|
||||||
warn_deprecated("Class MolarityIonicVPSSTP", "To be removed after Cantera 2.4");
|
|
||||||
importPhase(phaseRoot, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
// - Activities, Standard States, Activity Concentrations -----------
|
|
||||||
|
|
||||||
void MolarityIonicVPSSTP::getLnActivityCoefficients(doublereal* lnac) const
|
|
||||||
{
|
|
||||||
// Update the activity coefficients
|
|
||||||
s_update_lnActCoeff();
|
|
||||||
|
|
||||||
// take the exp of the internally stored coefficients.
|
|
||||||
for (size_t k = 0; k < m_kk; k++) {
|
|
||||||
lnac[k] = lnActCoeff_Scaled_[k];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MolarityIonicVPSSTP::getChemPotentials(doublereal* mu) const
|
|
||||||
{
|
|
||||||
// First get the standard chemical potentials in molar form. This requires
|
|
||||||
// updates of standard state as a function of T and P
|
|
||||||
getStandardChemPotentials(mu);
|
|
||||||
|
|
||||||
// Update the activity coefficients
|
|
||||||
s_update_lnActCoeff();
|
|
||||||
for (size_t k = 0; k < m_kk; k++) {
|
|
||||||
double xx = std::max(moleFractions_[k], SmallNumber);
|
|
||||||
mu[k] += RT() * (log(xx) + lnActCoeff_Scaled_[k]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MolarityIonicVPSSTP::getPartialMolarEnthalpies(doublereal* hbar) const
|
|
||||||
{
|
|
||||||
// Get the nondimensional standard state enthalpies
|
|
||||||
getEnthalpy_RT(hbar);
|
|
||||||
|
|
||||||
// dimensionalize it.
|
|
||||||
double T = temperature();
|
|
||||||
for (size_t k = 0; k < m_kk; k++) {
|
|
||||||
hbar[k] *= GasConstant * T;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update the activity coefficients, This also update the internally stored
|
|
||||||
// molalities.
|
|
||||||
s_update_lnActCoeff();
|
|
||||||
s_update_dlnActCoeff_dT();
|
|
||||||
for (size_t k = 0; k < m_kk; k++) {
|
|
||||||
hbar[k] -= GasConstant * T * T * dlnActCoeffdT_Scaled_[k];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MolarityIonicVPSSTP::getPartialMolarCp(doublereal* cpbar) const
|
|
||||||
{
|
|
||||||
// Get the nondimensional standard state entropies
|
|
||||||
getCp_R(cpbar);
|
|
||||||
double T = temperature();
|
|
||||||
|
|
||||||
// Update the activity coefficients, This also update the internally stored
|
|
||||||
// molalities.
|
|
||||||
s_update_lnActCoeff();
|
|
||||||
s_update_dlnActCoeff_dT();
|
|
||||||
|
|
||||||
for (size_t k = 0; k < m_kk; k++) {
|
|
||||||
cpbar[k] -= 2 * T * dlnActCoeffdT_Scaled_[k] + T * T * d2lnActCoeffdT2_Scaled_[k];
|
|
||||||
}
|
|
||||||
|
|
||||||
// dimensionalize it.
|
|
||||||
for (size_t k = 0; k < m_kk; k++) {
|
|
||||||
cpbar[k] *= GasConstant;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MolarityIonicVPSSTP::getPartialMolarEntropies(doublereal* sbar) const
|
|
||||||
{
|
|
||||||
// Get the nondimensional standard state entropies
|
|
||||||
getEntropy_R(sbar);
|
|
||||||
double T = temperature();
|
|
||||||
|
|
||||||
// Update the activity coefficients, This also update the internally stored
|
|
||||||
// molalities.
|
|
||||||
s_update_lnActCoeff();
|
|
||||||
s_update_dlnActCoeff_dT();
|
|
||||||
|
|
||||||
for (size_t k = 0; k < m_kk; k++) {
|
|
||||||
double xx = std::max(moleFractions_[k], SmallNumber);
|
|
||||||
sbar[k] += - lnActCoeff_Scaled_[k] -log(xx) - T * dlnActCoeffdT_Scaled_[k];
|
|
||||||
}
|
|
||||||
|
|
||||||
// dimensionalize it.
|
|
||||||
for (size_t k = 0; k < m_kk; k++) {
|
|
||||||
sbar[k] *= GasConstant;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MolarityIonicVPSSTP::getPartialMolarVolumes(doublereal* vbar) const
|
|
||||||
{
|
|
||||||
// Get the standard state values in m^3 kmol-1
|
|
||||||
getStandardVolumes(vbar);
|
|
||||||
for (size_t iK = 0; iK < m_kk; iK++) {
|
|
||||||
vbar[iK] += 0.0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MolarityIonicVPSSTP::calcPseudoBinaryMoleFractions() const
|
|
||||||
{
|
|
||||||
switch (PBType_) {
|
|
||||||
case PBTYPE_PASSTHROUGH:
|
|
||||||
for (size_t k = 0; k < m_kk; k++) {
|
|
||||||
PBMoleFractions_[k] = moleFractions_[k];
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case PBTYPE_SINGLEANION:
|
|
||||||
{
|
|
||||||
double sumCat = 0.0;
|
|
||||||
double sumAnion = 0.0;
|
|
||||||
for (size_t k = 0; k < m_kk; k++) {
|
|
||||||
moleFractionsTmp_[k] = moleFractions_[k];
|
|
||||||
}
|
|
||||||
size_t kMax = npos;
|
|
||||||
double sumMax = 0.0;
|
|
||||||
for (size_t k = 0; k < cationList_.size(); k++) {
|
|
||||||
size_t kCat = cationList_[k];
|
|
||||||
double chP = m_speciesCharge[kCat];
|
|
||||||
if (moleFractions_[kCat] > sumMax) {
|
|
||||||
kMax = k;
|
|
||||||
sumMax = moleFractions_[kCat];
|
|
||||||
}
|
|
||||||
sumCat += chP * moleFractions_[kCat];
|
|
||||||
}
|
|
||||||
size_t ka = anionList_[0];
|
|
||||||
sumAnion = moleFractions_[ka] * m_speciesCharge[ka];
|
|
||||||
double sum = sumCat - sumAnion;
|
|
||||||
if (fabs(sum) > 1.0E-16) {
|
|
||||||
moleFractionsTmp_[cationList_[kMax]] -= sum / m_speciesCharge[kMax];
|
|
||||||
sum = 0.0;
|
|
||||||
for (size_t k = 0; k < cationList_.size(); k++) {
|
|
||||||
sum += moleFractionsTmp_[k];
|
|
||||||
}
|
|
||||||
for (size_t k = 0; k < cationList_.size(); k++) {
|
|
||||||
moleFractionsTmp_[k]/= sum;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t k = 0; k < cationList_.size(); k++) {
|
|
||||||
PBMoleFractions_[k] = moleFractionsTmp_[cationList_[k]];
|
|
||||||
}
|
|
||||||
for (size_t k = 0; k < passThroughList_.size(); k++) {
|
|
||||||
PBMoleFractions_[neutralPBindexStart + k] = moleFractions_[passThroughList_[k]];
|
|
||||||
}
|
|
||||||
|
|
||||||
sum = std::max(0.0, PBMoleFractions_[0]);
|
|
||||||
for (size_t k = 1; k < numPBSpecies_; k++) {
|
|
||||||
sum += PBMoleFractions_[k];
|
|
||||||
}
|
|
||||||
for (size_t k = 0; k < numPBSpecies_; k++) {
|
|
||||||
PBMoleFractions_[k] /= sum;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case PBTYPE_SINGLECATION:
|
|
||||||
throw CanteraError("eosType", "Unknown type");
|
|
||||||
case PBTYPE_MULTICATIONANION:
|
|
||||||
throw CanteraError("eosType", "Unknown type");
|
|
||||||
default:
|
|
||||||
throw CanteraError("eosType", "Unknown type");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MolarityIonicVPSSTP::s_update_lnActCoeff() const
|
|
||||||
{
|
|
||||||
for (size_t k = 0; k < m_kk; k++) {
|
|
||||||
lnActCoeff_Scaled_[k] = 0.0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MolarityIonicVPSSTP::s_update_dlnActCoeff_dT() const
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void MolarityIonicVPSSTP::s_update_dlnActCoeff_dX_() const
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void MolarityIonicVPSSTP::initThermo()
|
|
||||||
{
|
|
||||||
GibbsExcessVPSSTP::initThermo();
|
|
||||||
initLengths();
|
|
||||||
|
|
||||||
// Go find the list of cations and anions
|
|
||||||
cationList_.clear();
|
|
||||||
anionList_.clear();
|
|
||||||
passThroughList_.clear();
|
|
||||||
for (size_t k = 0; k < m_kk; k++) {
|
|
||||||
double ch = m_speciesCharge[k];
|
|
||||||
if (ch > 0.0) {
|
|
||||||
cationList_.push_back(k);
|
|
||||||
} else if (ch < 0.0) {
|
|
||||||
anionList_.push_back(k);
|
|
||||||
} else {
|
|
||||||
passThroughList_.push_back(k);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
numPBSpecies_ = cationList_.size() + anionList_.size() - 1;
|
|
||||||
neutralPBindexStart = numPBSpecies_;
|
|
||||||
PBType_ = PBTYPE_MULTICATIONANION;
|
|
||||||
if (anionList_.size() == 1) {
|
|
||||||
PBType_ = PBTYPE_SINGLEANION;
|
|
||||||
} else if (cationList_.size() == 1) {
|
|
||||||
PBType_ = PBTYPE_SINGLECATION;
|
|
||||||
}
|
|
||||||
if (anionList_.size() == 0 && cationList_.size() == 0) {
|
|
||||||
PBType_ = PBTYPE_PASSTHROUGH;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MolarityIonicVPSSTP::initLengths()
|
|
||||||
{
|
|
||||||
moleFractionsTmp_.resize(m_kk);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MolarityIonicVPSSTP::initThermoXML(XML_Node& phaseNode, const std::string& id)
|
|
||||||
{
|
|
||||||
if ((int) id.size() > 0 && phaseNode.id() != id) {
|
|
||||||
throw CanteraError("MolarityIonicVPSSTP::initThermoXML",
|
|
||||||
"phasenode and Id are incompatible");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check on the thermo field. Must have one of:
|
|
||||||
// <thermo model="MolarityIonicVPSS" />
|
|
||||||
// <thermo model="MolarityIonicVPSSTP" />
|
|
||||||
if (!phaseNode.hasChild("thermo")) {
|
|
||||||
throw CanteraError("MolarityIonicVPSSTP::initThermoXML",
|
|
||||||
"no thermo XML node");
|
|
||||||
}
|
|
||||||
XML_Node& thermoNode = phaseNode.child("thermo");
|
|
||||||
if (!caseInsensitiveEquals(thermoNode["model"], "molarityionicvpss")
|
|
||||||
&& !caseInsensitiveEquals(thermoNode["model"], "molarityionicvpsstp")) {
|
|
||||||
throw CanteraError("MolarityIonicVPSSTP::initThermoXML",
|
|
||||||
"Unknown thermo model: " + thermoNode["model"]
|
|
||||||
+ " - This object only knows \"MolarityIonicVPSSTP\" ");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Go get all of the coefficients and factors in the activityCoefficients
|
|
||||||
// XML block
|
|
||||||
if (thermoNode.hasChild("activityCoefficients")) {
|
|
||||||
XML_Node& acNode = thermoNode.child("activityCoefficients");
|
|
||||||
for (size_t i = 0; i < acNode.nChildren(); i++) {
|
|
||||||
XML_Node& xmlACChild = acNode.child(i);
|
|
||||||
// Process a binary interaction
|
|
||||||
if (caseInsensitiveEquals(xmlACChild.name(), "binaryneutralspeciesparameters")) {
|
|
||||||
readXMLBinarySpecies(xmlACChild);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Go down the chain
|
|
||||||
GibbsExcessVPSSTP::initThermoXML(phaseNode, id);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MolarityIonicVPSSTP::readXMLBinarySpecies(XML_Node& xmLBinarySpecies)
|
|
||||||
{
|
|
||||||
std::string xname = xmLBinarySpecies.name();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string MolarityIonicVPSSTP::report(bool show_thermo, doublereal threshold) const
|
|
||||||
{
|
|
||||||
fmt::memory_buffer b;
|
|
||||||
try {
|
|
||||||
if (name() != "") {
|
|
||||||
format_to(b, "\n {}:\n", name());
|
|
||||||
}
|
|
||||||
format_to(b, "\n");
|
|
||||||
format_to(b, " temperature {:12.6g} K\n", temperature());
|
|
||||||
format_to(b, " pressure {:12.6g} Pa\n", pressure());
|
|
||||||
format_to(b, " density {:12.6g} kg/m^3\n", density());
|
|
||||||
format_to(b, " mean mol. weight {:12.6g} amu\n", meanMolecularWeight());
|
|
||||||
|
|
||||||
doublereal phi = electricPotential();
|
|
||||||
format_to(b, " potential {:12.6g} V\n", phi);
|
|
||||||
|
|
||||||
vector_fp x(m_kk);
|
|
||||||
vector_fp molal(m_kk);
|
|
||||||
vector_fp mu(m_kk);
|
|
||||||
vector_fp muss(m_kk);
|
|
||||||
vector_fp acMolal(m_kk);
|
|
||||||
vector_fp actMolal(m_kk);
|
|
||||||
getMoleFractions(&x[0]);
|
|
||||||
|
|
||||||
getChemPotentials(&mu[0]);
|
|
||||||
getStandardChemPotentials(&muss[0]);
|
|
||||||
getActivities(&actMolal[0]);
|
|
||||||
|
|
||||||
if (show_thermo) {
|
|
||||||
format_to(b, "\n");
|
|
||||||
format_to(b, " 1 kg 1 kmol\n");
|
|
||||||
format_to(b, " ----------- ------------\n");
|
|
||||||
format_to(b, " enthalpy {:12.6g} {:12.4g} J\n",
|
|
||||||
enthalpy_mass(), enthalpy_mole());
|
|
||||||
format_to(b, " internal energy {:12.6g} {:12.4g} J\n",
|
|
||||||
intEnergy_mass(), intEnergy_mole());
|
|
||||||
format_to(b, " entropy {:12.6g} {:12.4g} J/K\n",
|
|
||||||
entropy_mass(), entropy_mole());
|
|
||||||
format_to(b, " Gibbs function {:12.6g} {:12.4g} J\n",
|
|
||||||
gibbs_mass(), gibbs_mole());
|
|
||||||
format_to(b, " heat capacity c_p {:12.6g} {:12.4g} J/K\n",
|
|
||||||
cp_mass(), cp_mole());
|
|
||||||
try {
|
|
||||||
format_to(b, " heat capacity c_v {:12.6g} {:12.4g} J/K\n",
|
|
||||||
cv_mass(), cv_mole());
|
|
||||||
} catch (NotImplementedError&) {
|
|
||||||
format_to(b, " heat capacity c_v <not implemented>\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (CanteraError& e) {
|
|
||||||
return to_string(b) + e.what();
|
|
||||||
}
|
|
||||||
return to_string(b);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -78,17 +78,6 @@ void MultiSpeciesThermo::modifySpecies(size_t index,
|
||||||
m_sp[type][m_speciesLoc[index].second] = {index, spthermo};
|
m_sp[type][m_speciesLoc[index].second] = {index, spthermo};
|
||||||
}
|
}
|
||||||
|
|
||||||
void MultiSpeciesThermo::update_one(size_t k, doublereal t, doublereal* cp_R,
|
|
||||||
doublereal* h_RT, doublereal* s_R) const
|
|
||||||
{
|
|
||||||
warn_deprecated("MultiSpeciesThermo::update_one",
|
|
||||||
"Use update_single instead. To be removed after Cantera 2.4");
|
|
||||||
const SpeciesThermoInterpType* sp_ptr = provideSTIT(k);
|
|
||||||
if (sp_ptr) {
|
|
||||||
sp_ptr->updatePropertiesTemp(t, cp_R+k, h_RT+k, s_R+k);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MultiSpeciesThermo::update_single(size_t k, double t, double* cp_R,
|
void MultiSpeciesThermo::update_single(size_t k, double t, double* cp_R,
|
||||||
double* h_RT, double* s_R) const
|
double* h_RT, double* s_R) const
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1,620 +0,0 @@
|
||||||
/**
|
|
||||||
* @file PhaseCombo_Interaction.cpp
|
|
||||||
*/
|
|
||||||
|
|
||||||
// This file is part of Cantera. See License.txt in the top-level directory or
|
|
||||||
// at http://www.cantera.org/license.txt for license and copyright information.
|
|
||||||
|
|
||||||
#include "cantera/thermo/PhaseCombo_Interaction.h"
|
|
||||||
#include "cantera/thermo/ThermoFactory.h"
|
|
||||||
#include "cantera/base/stringUtils.h"
|
|
||||||
#include "cantera/base/ctml.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
namespace Cantera
|
|
||||||
{
|
|
||||||
PhaseCombo_Interaction::PhaseCombo_Interaction() :
|
|
||||||
numBinaryInteractions_(0),
|
|
||||||
formMargules_(0),
|
|
||||||
formTempModel_(0)
|
|
||||||
{
|
|
||||||
warn_deprecated("Class PhaseCombo_Interaction", "To be removed after Cantera 2.4");
|
|
||||||
}
|
|
||||||
|
|
||||||
PhaseCombo_Interaction::PhaseCombo_Interaction(const std::string& inputFile,
|
|
||||||
const std::string& id_) :
|
|
||||||
numBinaryInteractions_(0),
|
|
||||||
formMargules_(0),
|
|
||||||
formTempModel_(0)
|
|
||||||
{
|
|
||||||
warn_deprecated("Class PhaseCombo_Interaction", "To be removed after Cantera 2.4");
|
|
||||||
initThermoFile(inputFile, id_);
|
|
||||||
}
|
|
||||||
|
|
||||||
PhaseCombo_Interaction::PhaseCombo_Interaction(XML_Node& phaseRoot,
|
|
||||||
const std::string& id_) :
|
|
||||||
numBinaryInteractions_(0),
|
|
||||||
formMargules_(0),
|
|
||||||
formTempModel_(0)
|
|
||||||
{
|
|
||||||
warn_deprecated("Class PhaseCombo_Interaction", "To be removed after Cantera 2.4");
|
|
||||||
importPhase(phaseRoot, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
// - Activities, Standard States, Activity Concentrations -----------
|
|
||||||
|
|
||||||
void PhaseCombo_Interaction::getActivityCoefficients(doublereal* ac) const
|
|
||||||
{
|
|
||||||
// Update the activity coefficients
|
|
||||||
s_update_lnActCoeff();
|
|
||||||
|
|
||||||
// take the exp of the internally stored coefficients.
|
|
||||||
for (size_t k = 0; k < m_kk; k++) {
|
|
||||||
ac[k] = exp(lnActCoeff_Scaled_[k]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------ Partial Molar Properties of the Solution ------------
|
|
||||||
|
|
||||||
void PhaseCombo_Interaction::getChemPotentials(doublereal* mu) const
|
|
||||||
{
|
|
||||||
// First get the standard chemical potentials in molar form. This requires
|
|
||||||
// updates of standard state as a function of T and P
|
|
||||||
getStandardChemPotentials(mu);
|
|
||||||
// Update the activity coefficients
|
|
||||||
s_update_lnActCoeff();
|
|
||||||
|
|
||||||
for (size_t k = 0; k < m_kk; k++) {
|
|
||||||
double xx = std::max(moleFractions_[k], SmallNumber);
|
|
||||||
mu[k] += RT() * (log(xx) + lnActCoeff_Scaled_[k]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
doublereal PhaseCombo_Interaction::enthalpy_mole() const
|
|
||||||
{
|
|
||||||
double h = 0;
|
|
||||||
vector_fp hbar(m_kk);
|
|
||||||
getPartialMolarEnthalpies(&hbar[0]);
|
|
||||||
for (size_t i = 0; i < m_kk; i++) {
|
|
||||||
h += moleFractions_[i]*hbar[i];
|
|
||||||
}
|
|
||||||
return h;
|
|
||||||
}
|
|
||||||
|
|
||||||
doublereal PhaseCombo_Interaction::entropy_mole() const
|
|
||||||
{
|
|
||||||
double s = 0;
|
|
||||||
vector_fp sbar(m_kk);
|
|
||||||
getPartialMolarEntropies(&sbar[0]);
|
|
||||||
for (size_t i = 0; i < m_kk; i++) {
|
|
||||||
s += moleFractions_[i]*sbar[i];
|
|
||||||
}
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
doublereal PhaseCombo_Interaction::cp_mole() const
|
|
||||||
{
|
|
||||||
double cp = 0;
|
|
||||||
vector_fp cpbar(m_kk);
|
|
||||||
getPartialMolarCp(&cpbar[0]);
|
|
||||||
for (size_t i = 0; i < m_kk; i++) {
|
|
||||||
cp += moleFractions_[i]*cpbar[i];
|
|
||||||
}
|
|
||||||
return cp;
|
|
||||||
}
|
|
||||||
|
|
||||||
doublereal PhaseCombo_Interaction::cv_mole() const
|
|
||||||
{
|
|
||||||
return cp_mole() - GasConstant;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PhaseCombo_Interaction::getPartialMolarEnthalpies(doublereal* hbar) const
|
|
||||||
{
|
|
||||||
// Get the nondimensional standard state enthalpies
|
|
||||||
getEnthalpy_RT(hbar);
|
|
||||||
// dimensionalize it.
|
|
||||||
double T = temperature();
|
|
||||||
for (size_t k = 0; k < m_kk; k++) {
|
|
||||||
hbar[k] *= GasConstant * T;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update the activity coefficients, This also update the internally stored
|
|
||||||
// molalities.
|
|
||||||
s_update_lnActCoeff();
|
|
||||||
s_update_dlnActCoeff_dT();
|
|
||||||
for (size_t k = 0; k < m_kk; k++) {
|
|
||||||
hbar[k] -= GasConstant * T * T * dlnActCoeffdT_Scaled_[k];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void PhaseCombo_Interaction::getPartialMolarCp(doublereal* cpbar) const
|
|
||||||
{
|
|
||||||
// Get the nondimensional standard state entropies
|
|
||||||
getCp_R(cpbar);
|
|
||||||
double T = temperature();
|
|
||||||
|
|
||||||
// Update the activity coefficients, This also update the internally stored
|
|
||||||
// molalities.
|
|
||||||
s_update_lnActCoeff();
|
|
||||||
s_update_dlnActCoeff_dT();
|
|
||||||
|
|
||||||
for (size_t k = 0; k < m_kk; k++) {
|
|
||||||
cpbar[k] -= 2 * T * dlnActCoeffdT_Scaled_[k] + T * T * d2lnActCoeffdT2_Scaled_[k];
|
|
||||||
}
|
|
||||||
|
|
||||||
// dimensionalize it.
|
|
||||||
for (size_t k = 0; k < m_kk; k++) {
|
|
||||||
cpbar[k] *= GasConstant;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void PhaseCombo_Interaction::getPartialMolarEntropies(doublereal* sbar) const
|
|
||||||
{
|
|
||||||
// Get the nondimensional standard state entropies
|
|
||||||
getEntropy_R(sbar);
|
|
||||||
double T = temperature();
|
|
||||||
|
|
||||||
// Update the activity coefficients, This also update the internally stored
|
|
||||||
// molalities.
|
|
||||||
s_update_lnActCoeff();
|
|
||||||
s_update_dlnActCoeff_dT();
|
|
||||||
|
|
||||||
for (size_t k = 0; k < m_kk; k++) {
|
|
||||||
double xx = std::max(moleFractions_[k], SmallNumber);
|
|
||||||
sbar[k] += - lnActCoeff_Scaled_[k] - log(xx) - T * dlnActCoeffdT_Scaled_[k];
|
|
||||||
}
|
|
||||||
|
|
||||||
// dimensionalize it.
|
|
||||||
for (size_t k = 0; k < m_kk; k++) {
|
|
||||||
sbar[k] *= GasConstant;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void PhaseCombo_Interaction::getPartialMolarVolumes(doublereal* vbar) const
|
|
||||||
{
|
|
||||||
double T = temperature();
|
|
||||||
|
|
||||||
// Get the standard state values in m^3 kmol-1
|
|
||||||
getStandardVolumes(vbar);
|
|
||||||
|
|
||||||
for (size_t iK = 0; iK < m_kk; iK++) {
|
|
||||||
int delAK = 0;
|
|
||||||
int delBK = 0;
|
|
||||||
for (size_t i = 0; i < numBinaryInteractions_; i++) {
|
|
||||||
size_t iA = m_pSpecies_A_ij[i];
|
|
||||||
size_t iB = m_pSpecies_B_ij[i];
|
|
||||||
|
|
||||||
if (iA==iK) {
|
|
||||||
delAK = 1;
|
|
||||||
} else if (iB==iK) {
|
|
||||||
delBK = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
double XA = moleFractions_[iA];
|
|
||||||
double XB = moleFractions_[iB];
|
|
||||||
double g0 = (m_VHE_b_ij[i] - T * m_VSE_b_ij[i]);
|
|
||||||
double g1 = (m_VHE_c_ij[i] - T * m_VSE_c_ij[i]);
|
|
||||||
vbar[iK] += XA*XB*(g0+g1*XB)+((delAK-XA)*XB+XA*(delBK-XB))*(g0+g1*XB)+XA*XB*(delBK-XB)*g1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void PhaseCombo_Interaction::initThermo()
|
|
||||||
{
|
|
||||||
initLengths();
|
|
||||||
GibbsExcessVPSSTP::initThermo();
|
|
||||||
}
|
|
||||||
|
|
||||||
void PhaseCombo_Interaction::initLengths()
|
|
||||||
{
|
|
||||||
dlnActCoeffdlnN_.resize(m_kk, m_kk);
|
|
||||||
}
|
|
||||||
|
|
||||||
void PhaseCombo_Interaction::initThermoXML(XML_Node& phaseNode, const std::string& id)
|
|
||||||
{
|
|
||||||
if ((int) id.size() > 0 && phaseNode.id() != id) {
|
|
||||||
throw CanteraError("PhaseCombo_Interaction::initThermoXML",
|
|
||||||
"phasenode and Id are incompatible");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check on the thermo field. Must have:
|
|
||||||
// <thermo model="PhaseCombo_Interaction" />
|
|
||||||
if (!phaseNode.hasChild("thermo")) {
|
|
||||||
throw CanteraError("PhaseCombo_Interaction::initThermoXML",
|
|
||||||
"no thermo XML node");
|
|
||||||
}
|
|
||||||
XML_Node& thermoNode = phaseNode.child("thermo");
|
|
||||||
if (!caseInsensitiveEquals(thermoNode["model"], "phasecombo_interaction")) {
|
|
||||||
throw CanteraError("PhaseCombo_Interaction::initThermoXML",
|
|
||||||
"model name isn't PhaseCombo_Interaction: " + thermoNode["model"]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Go get all of the coefficients and factors in the activityCoefficients
|
|
||||||
// XML block
|
|
||||||
if (thermoNode.hasChild("activityCoefficients")) {
|
|
||||||
XML_Node& acNode = thermoNode.child("activityCoefficients");
|
|
||||||
if (!caseInsensitiveEquals(acNode["model"], "margules")) {
|
|
||||||
throw CanteraError("PhaseCombo_Interaction::initThermoXML",
|
|
||||||
"Unknown activity coefficient model: " + acNode["model"]);
|
|
||||||
}
|
|
||||||
for (size_t i = 0; i < acNode.nChildren(); i++) {
|
|
||||||
XML_Node& xmlACChild = acNode.child(i);
|
|
||||||
|
|
||||||
// Process a binary salt field, or any of the other XML fields that
|
|
||||||
// make up the Pitzer Database. Entries will be ignored if any of
|
|
||||||
// the species in the entry isn't in the solution.
|
|
||||||
if (caseInsensitiveEquals(xmlACChild.name(), "binaryneutralspeciesparameters")) {
|
|
||||||
readXMLBinarySpecies(xmlACChild);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Go down the chain
|
|
||||||
GibbsExcessVPSSTP::initThermoXML(phaseNode, id);
|
|
||||||
}
|
|
||||||
|
|
||||||
void PhaseCombo_Interaction::s_update_lnActCoeff() const
|
|
||||||
{
|
|
||||||
doublereal T = temperature();
|
|
||||||
lnActCoeff_Scaled_.assign(m_kk, 0.0);
|
|
||||||
|
|
||||||
for (size_t iK = 0; iK < m_kk; iK++) {
|
|
||||||
// We never sample the end of the mole fraction domains
|
|
||||||
double xx = std::max(moleFractions_[iK], SmallNumber);
|
|
||||||
|
|
||||||
// First wipe out the ideal solution mixing term
|
|
||||||
lnActCoeff_Scaled_[iK] = - log(xx);
|
|
||||||
|
|
||||||
// Then add in the Margules interaction terms. that's it!
|
|
||||||
for (size_t i = 0; i < numBinaryInteractions_; i++) {
|
|
||||||
size_t iA = m_pSpecies_A_ij[i];
|
|
||||||
size_t iB = m_pSpecies_B_ij[i];
|
|
||||||
int delAK = 0;
|
|
||||||
int delBK = 0;
|
|
||||||
if (iA==iK) {
|
|
||||||
delAK = 1;
|
|
||||||
} else if (iB==iK) {
|
|
||||||
delBK = 1;
|
|
||||||
}
|
|
||||||
double XA = moleFractions_[iA];
|
|
||||||
double XB = moleFractions_[iB];
|
|
||||||
double g0 = (m_HE_b_ij[i] - T * m_SE_b_ij[i]) / (GasConstant*T);
|
|
||||||
double g1 = (m_HE_c_ij[i] - T * m_SE_c_ij[i]) / (GasConstant*T);
|
|
||||||
lnActCoeff_Scaled_[iK] += (delAK * XB + XA * delBK - XA * XB) * (g0 + g1 * XB) + XA * XB * (delBK - XB) * g1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void PhaseCombo_Interaction::s_update_dlnActCoeff_dT() const
|
|
||||||
{
|
|
||||||
doublereal T = temperature();
|
|
||||||
dlnActCoeffdT_Scaled_.assign(m_kk, 0.0);
|
|
||||||
d2lnActCoeffdT2_Scaled_.assign(m_kk, 0.0);
|
|
||||||
for (size_t iK = 0; iK < m_kk; iK++) {
|
|
||||||
for (size_t i = 0; i < numBinaryInteractions_; i++) {
|
|
||||||
size_t iA = m_pSpecies_A_ij[i];
|
|
||||||
size_t iB = m_pSpecies_B_ij[i];
|
|
||||||
int delAK = 0;
|
|
||||||
int delBK = 0;
|
|
||||||
if (iA==iK) {
|
|
||||||
delAK = 1;
|
|
||||||
} else if (iB==iK) {
|
|
||||||
delBK = 1;
|
|
||||||
}
|
|
||||||
double XA = moleFractions_[iA];
|
|
||||||
double XB = moleFractions_[iB];
|
|
||||||
double g0 = -m_HE_b_ij[i] / (GasConstant*T*T);
|
|
||||||
double g1 = -m_HE_c_ij[i] / (GasConstant*T*T);
|
|
||||||
double temp = (delAK * XB + XA * delBK - XA * XB) * (g0 + g1 * XB) + XA * XB * (delBK - XB) * g1;
|
|
||||||
dlnActCoeffdT_Scaled_[iK] += temp;
|
|
||||||
d2lnActCoeffdT2_Scaled_[iK] -= 2.0 * temp / T;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void PhaseCombo_Interaction::getdlnActCoeffdT(doublereal* dlnActCoeffdT) const
|
|
||||||
{
|
|
||||||
s_update_dlnActCoeff_dT();
|
|
||||||
for (size_t k = 0; k < m_kk; k++) {
|
|
||||||
dlnActCoeffdT[k] = dlnActCoeffdT_Scaled_[k];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void PhaseCombo_Interaction::getd2lnActCoeffdT2(doublereal* d2lnActCoeffdT2) const
|
|
||||||
{
|
|
||||||
s_update_dlnActCoeff_dT();
|
|
||||||
for (size_t k = 0; k < m_kk; k++) {
|
|
||||||
d2lnActCoeffdT2[k] = d2lnActCoeffdT2_Scaled_[k];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void PhaseCombo_Interaction::getdlnActCoeffds(const doublereal dTds, const doublereal* const dXds,
|
|
||||||
doublereal* dlnActCoeffds) const
|
|
||||||
{
|
|
||||||
doublereal T = temperature();
|
|
||||||
s_update_dlnActCoeff_dT();
|
|
||||||
|
|
||||||
for (size_t iK = 0; iK < m_kk; iK++) {
|
|
||||||
// We never sample the end of the mole fraction domains
|
|
||||||
double xx = std::max(moleFractions_[iK], SmallNumber);
|
|
||||||
|
|
||||||
// First wipe out the ideal solution mixing term
|
|
||||||
if (xx > SmallNumber) {
|
|
||||||
dlnActCoeffds[iK] += - 1.0 / xx;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i = 0; i < numBinaryInteractions_; i++) {
|
|
||||||
size_t iA = m_pSpecies_A_ij[i];
|
|
||||||
size_t iB = m_pSpecies_B_ij[i];
|
|
||||||
int delAK = 0;
|
|
||||||
int delBK = 0;
|
|
||||||
|
|
||||||
if (iA==iK) {
|
|
||||||
delAK = 1;
|
|
||||||
} else if (iB==iK) {
|
|
||||||
delBK = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
double XA = moleFractions_[iA];
|
|
||||||
double XB = moleFractions_[iB];
|
|
||||||
double dXA = dXds[iA];
|
|
||||||
double dXB = dXds[iB];
|
|
||||||
double g0 = (m_HE_b_ij[i] - T * m_SE_b_ij[i]) / (GasConstant*T);
|
|
||||||
double g1 = (m_HE_c_ij[i] - T * m_SE_c_ij[i]) / (GasConstant*T);
|
|
||||||
dlnActCoeffds[iK] += ((delBK-XB)*dXA + (delAK-XA)*dXB)*(g0+2*g1*XB) + (delBK-XB)*2*g1*XA*dXB
|
|
||||||
+ dlnActCoeffdT_Scaled_[iK]*dTds;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void PhaseCombo_Interaction::s_update_dlnActCoeff_dlnN_diag() const
|
|
||||||
{
|
|
||||||
doublereal T = temperature();
|
|
||||||
dlnActCoeffdlnN_diag_.assign(m_kk, 0.0);
|
|
||||||
|
|
||||||
for (size_t iK = 0; iK < m_kk; iK++) {
|
|
||||||
double XK = moleFractions_[iK];
|
|
||||||
// We never sample the end of the mole fraction domains
|
|
||||||
double xx = std::max(moleFractions_[iK], SmallNumber);
|
|
||||||
|
|
||||||
// First wipe out the ideal solution mixing term
|
|
||||||
if (xx > SmallNumber) {
|
|
||||||
dlnActCoeffdlnN_diag_[iK] = - 1.0 + xx;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i = 0; i < numBinaryInteractions_; i++) {
|
|
||||||
size_t iA = m_pSpecies_A_ij[i];
|
|
||||||
size_t iB = m_pSpecies_B_ij[i];
|
|
||||||
int delAK = 0;
|
|
||||||
int delBK = 0;
|
|
||||||
|
|
||||||
if (iA==iK) {
|
|
||||||
delAK = 1;
|
|
||||||
} else if (iB==iK) {
|
|
||||||
delBK = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
double XA = moleFractions_[iA];
|
|
||||||
double XB = moleFractions_[iB];
|
|
||||||
double g0 = (m_HE_b_ij[i] - T * m_SE_b_ij[i]) / (GasConstant*T);
|
|
||||||
double g1 = (m_HE_c_ij[i] - T * m_SE_c_ij[i]) / (GasConstant*T);
|
|
||||||
dlnActCoeffdlnN_diag_[iK] += 2*(delBK-XB)*(g0*(delAK-XA)+g1*(2*(delAK-XA)*XB+XA*(delBK-XB)));
|
|
||||||
}
|
|
||||||
dlnActCoeffdlnN_diag_[iK] = XK*dlnActCoeffdlnN_diag_[iK];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void PhaseCombo_Interaction::s_update_dlnActCoeff_dlnN() const
|
|
||||||
{
|
|
||||||
double T = temperature();
|
|
||||||
dlnActCoeffdlnN_.zero();
|
|
||||||
|
|
||||||
// Loop over the activity coefficient gamma_k
|
|
||||||
for (size_t iK = 0; iK < m_kk; iK++) {
|
|
||||||
// We never sample the end of the mole fraction domains
|
|
||||||
double xx = std::max(moleFractions_[iK], SmallNumber);
|
|
||||||
for (size_t iM = 0; iM < m_kk; iM++) {
|
|
||||||
double XM = moleFractions_[iM];
|
|
||||||
if (xx > SmallNumber) {
|
|
||||||
double delKM = 0.0;
|
|
||||||
if (iK == iM) {
|
|
||||||
delKM = 1.0;
|
|
||||||
}
|
|
||||||
// this gets multiplied by XM at the bottom
|
|
||||||
dlnActCoeffdlnN_(iK,iM) += - delKM/XM + 1.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i = 0; i < numBinaryInteractions_; i++) {
|
|
||||||
size_t iA = m_pSpecies_A_ij[i];
|
|
||||||
size_t iB = m_pSpecies_B_ij[i];
|
|
||||||
double delAK = 0.0;
|
|
||||||
double delBK = 0.0;
|
|
||||||
double delAM = 0.0;
|
|
||||||
double delBM = 0.0;
|
|
||||||
if (iA==iK) {
|
|
||||||
delAK = 1.0;
|
|
||||||
} else if (iB==iK) {
|
|
||||||
delBK = 1.0;
|
|
||||||
}
|
|
||||||
if (iA==iM) {
|
|
||||||
delAM = 1.0;
|
|
||||||
} else if (iB==iM) {
|
|
||||||
delBM = 1.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
double XA = moleFractions_[iA];
|
|
||||||
double XB = moleFractions_[iB];
|
|
||||||
double g0 = (m_HE_b_ij[i] - T * m_SE_b_ij[i]) / (GasConstant*T);
|
|
||||||
double g1 = (m_HE_c_ij[i] - T * m_SE_c_ij[i]) / (GasConstant*T);
|
|
||||||
dlnActCoeffdlnN_(iK,iM) += g0*((delAM-XA)*(delBK-XB)+(delAK-XA)*(delBM-XB));
|
|
||||||
dlnActCoeffdlnN_(iK,iM) += 2*g1*((delAM-XA)*(delBK-XB)*XB+(delAK-XA)*(delBM-XB)*XB+(delBM-XB)*(delBK-XB)*XA);
|
|
||||||
}
|
|
||||||
dlnActCoeffdlnN_(iK,iM) = XM * dlnActCoeffdlnN_(iK,iM);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void PhaseCombo_Interaction::s_update_dlnActCoeff_dlnX_diag() const
|
|
||||||
{
|
|
||||||
doublereal T = temperature();
|
|
||||||
dlnActCoeffdlnX_diag_.assign(m_kk, 0.0);
|
|
||||||
for (size_t i = 0; i < numBinaryInteractions_; i++) {
|
|
||||||
size_t iA = m_pSpecies_A_ij[i];
|
|
||||||
size_t iB = m_pSpecies_B_ij[i];
|
|
||||||
|
|
||||||
double XA = moleFractions_[iA];
|
|
||||||
double XB = moleFractions_[iB];
|
|
||||||
|
|
||||||
double g0 = (m_HE_b_ij[i] - T * m_SE_b_ij[i]) / (GasConstant * T);
|
|
||||||
double g1 = (m_HE_c_ij[i] - T * m_SE_c_ij[i]) / (GasConstant * T);
|
|
||||||
|
|
||||||
dlnActCoeffdlnX_diag_[iA] += XA*XB*(2*g1*-2*g0-6*g1*XB);
|
|
||||||
dlnActCoeffdlnX_diag_[iB] += XA*XB*(2*g1*-2*g0-6*g1*XB);
|
|
||||||
}
|
|
||||||
throw CanteraError("PhaseCombo_Interaction::s_update_dlnActCoeff_dlnX_diag", "unimplemented");
|
|
||||||
}
|
|
||||||
|
|
||||||
void PhaseCombo_Interaction::getdlnActCoeffdlnN_diag(doublereal* dlnActCoeffdlnN_diag) const
|
|
||||||
{
|
|
||||||
s_update_dlnActCoeff_dlnN_diag();
|
|
||||||
for (size_t k = 0; k < m_kk; k++) {
|
|
||||||
dlnActCoeffdlnN_diag[k] = dlnActCoeffdlnN_diag_[k];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void PhaseCombo_Interaction::getdlnActCoeffdlnX_diag(doublereal* dlnActCoeffdlnX_diag) const
|
|
||||||
{
|
|
||||||
s_update_dlnActCoeff_dlnX_diag();
|
|
||||||
for (size_t k = 0; k < m_kk; k++) {
|
|
||||||
dlnActCoeffdlnX_diag[k] = dlnActCoeffdlnX_diag_[k];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void PhaseCombo_Interaction::getdlnActCoeffdlnN(const size_t ld, doublereal* dlnActCoeffdlnN)
|
|
||||||
{
|
|
||||||
s_update_dlnActCoeff_dlnN();
|
|
||||||
double* data = & dlnActCoeffdlnN_(0,0);
|
|
||||||
for (size_t k = 0; k < m_kk; k++) {
|
|
||||||
for (size_t m = 0; m < m_kk; m++) {
|
|
||||||
dlnActCoeffdlnN[ld * k + m] = data[m_kk * k + m];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void PhaseCombo_Interaction::resizeNumInteractions(const size_t num)
|
|
||||||
{
|
|
||||||
numBinaryInteractions_ = num;
|
|
||||||
m_HE_b_ij.resize(num, 0.0);
|
|
||||||
m_HE_c_ij.resize(num, 0.0);
|
|
||||||
m_HE_d_ij.resize(num, 0.0);
|
|
||||||
m_SE_b_ij.resize(num, 0.0);
|
|
||||||
m_SE_c_ij.resize(num, 0.0);
|
|
||||||
m_SE_d_ij.resize(num, 0.0);
|
|
||||||
m_VHE_b_ij.resize(num, 0.0);
|
|
||||||
m_VHE_c_ij.resize(num, 0.0);
|
|
||||||
m_VHE_d_ij.resize(num, 0.0);
|
|
||||||
m_VSE_b_ij.resize(num, 0.0);
|
|
||||||
m_VSE_c_ij.resize(num, 0.0);
|
|
||||||
m_VSE_d_ij.resize(num, 0.0);
|
|
||||||
m_pSpecies_A_ij.resize(num, npos);
|
|
||||||
m_pSpecies_B_ij.resize(num, npos);
|
|
||||||
}
|
|
||||||
|
|
||||||
void PhaseCombo_Interaction::readXMLBinarySpecies(XML_Node& xmLBinarySpecies)
|
|
||||||
{
|
|
||||||
string xname = xmLBinarySpecies.name();
|
|
||||||
if (xname != "binaryNeutralSpeciesParameters") {
|
|
||||||
throw CanteraError("PhaseCombo_Interaction::readXMLBinarySpecies",
|
|
||||||
"Incorrect name for processing this routine: " + xname);
|
|
||||||
}
|
|
||||||
vector_fp vParams;
|
|
||||||
string iName = xmLBinarySpecies.attrib("speciesA");
|
|
||||||
if (iName == "") {
|
|
||||||
throw CanteraError("PhaseCombo_Interaction::readXMLBinarySpecies", "no speciesA attrib");
|
|
||||||
}
|
|
||||||
string jName = xmLBinarySpecies.attrib("speciesB");
|
|
||||||
if (jName == "") {
|
|
||||||
throw CanteraError("PhaseCombo_Interaction::readXMLBinarySpecies", "no speciesB attrib");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find the index of the species in the current phase. It's not an error to
|
|
||||||
// not find the species
|
|
||||||
size_t iSpecies = speciesIndex(iName);
|
|
||||||
if (iSpecies == npos) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
string ispName = speciesName(iSpecies);
|
|
||||||
if (charge(iSpecies) != 0) {
|
|
||||||
throw CanteraError("PhaseCombo_Interaction::readXMLBinarySpecies", "speciesA charge problem");
|
|
||||||
}
|
|
||||||
size_t jSpecies = speciesIndex(jName);
|
|
||||||
if (jSpecies == npos) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
string jspName = speciesName(jSpecies);
|
|
||||||
if (charge(jSpecies) != 0) {
|
|
||||||
throw CanteraError("PhaseCombo_Interaction::readXMLBinarySpecies", "speciesB charge problem");
|
|
||||||
}
|
|
||||||
|
|
||||||
resizeNumInteractions(numBinaryInteractions_ + 1);
|
|
||||||
size_t iSpot = numBinaryInteractions_ - 1;
|
|
||||||
m_pSpecies_A_ij[iSpot] = iSpecies;
|
|
||||||
m_pSpecies_B_ij[iSpot] = jSpecies;
|
|
||||||
|
|
||||||
for (size_t iChild = 0; iChild < xmLBinarySpecies.nChildren(); iChild++) {
|
|
||||||
XML_Node& xmlChild = xmLBinarySpecies.child(iChild);
|
|
||||||
string nodeName = toLowerCopy(xmlChild.name());
|
|
||||||
|
|
||||||
// Process the binary species interaction child elements
|
|
||||||
if (nodeName == "excessenthalpy") {
|
|
||||||
// Get the string containing all of the values
|
|
||||||
getFloatArray(xmlChild, vParams, true, "toSI", "excessEnthalpy");
|
|
||||||
if (vParams.size() != 2) {
|
|
||||||
throw CanteraError("PhaseCombo_Interaction::readXMLBinarySpecies::excessEnthalpy for " + ispName
|
|
||||||
+ "::" + jspName,
|
|
||||||
"wrong number of params found");
|
|
||||||
}
|
|
||||||
m_HE_b_ij[iSpot] = vParams[0];
|
|
||||||
m_HE_c_ij[iSpot] = vParams[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nodeName == "excessentropy") {
|
|
||||||
// Get the string containing all of the values
|
|
||||||
getFloatArray(xmlChild, vParams, true, "toSI", "excessEntropy");
|
|
||||||
if (vParams.size() != 2) {
|
|
||||||
throw CanteraError("PhaseCombo_Interaction::readXMLBinarySpecies::excessEntropy for " + ispName
|
|
||||||
+ "::" + jspName,
|
|
||||||
"wrong number of params found");
|
|
||||||
}
|
|
||||||
m_SE_b_ij[iSpot] = vParams[0];
|
|
||||||
m_SE_c_ij[iSpot] = vParams[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nodeName == "excessvolume_enthalpy") {
|
|
||||||
// Get the string containing all of the values
|
|
||||||
getFloatArray(xmlChild, vParams, true, "toSI", "excessVolume_Enthalpy");
|
|
||||||
if (vParams.size() != 2) {
|
|
||||||
throw CanteraError("PhaseCombo_Interaction::readXMLBinarySpecies::excessVolume_Enthalpy for " + ispName
|
|
||||||
+ "::" + jspName,
|
|
||||||
"wrong number of params found");
|
|
||||||
}
|
|
||||||
m_VHE_b_ij[iSpot] = vParams[0];
|
|
||||||
m_VHE_c_ij[iSpot] = vParams[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nodeName == "excessvolume_entropy") {
|
|
||||||
// Get the string containing all of the values
|
|
||||||
getFloatArray(xmlChild, vParams, true, "toSI", "excessVolume_Entropy");
|
|
||||||
if (vParams.size() != 2) {
|
|
||||||
throw CanteraError("PhaseCombo_Interaction::readXMLBinarySpecies::excessVolume_Entropy for " + ispName
|
|
||||||
+ "::" + jspName,
|
|
||||||
"wrong number of params found");
|
|
||||||
}
|
|
||||||
m_VSE_b_ij[iSpot] = vParams[0];
|
|
||||||
m_VSE_c_ij[iSpot] = vParams[1];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -16,7 +16,6 @@
|
||||||
#include "cantera/thermo/NasaPoly2.h"
|
#include "cantera/thermo/NasaPoly2.h"
|
||||||
#include "cantera/thermo/ShomatePoly.h"
|
#include "cantera/thermo/ShomatePoly.h"
|
||||||
#include "cantera/thermo/ConstCpPoly.h"
|
#include "cantera/thermo/ConstCpPoly.h"
|
||||||
#include "cantera/thermo/AdsorbateThermo.h"
|
|
||||||
#include "cantera/thermo/speciesThermoTypes.h"
|
#include "cantera/thermo/speciesThermoTypes.h"
|
||||||
#include "cantera/thermo/VPStandardStateTP.h"
|
#include "cantera/thermo/VPStandardStateTP.h"
|
||||||
#include "cantera/base/ctml.h"
|
#include "cantera/base/ctml.h"
|
||||||
|
|
@ -44,8 +43,6 @@ SpeciesThermoInterpType* newSpeciesThermoInterpType(int type, double tlow,
|
||||||
return new ShomatePoly2(tlow, thigh, pref, coeffs);
|
return new ShomatePoly2(tlow, thigh, pref, coeffs);
|
||||||
case NASA2:
|
case NASA2:
|
||||||
return new NasaPoly2(tlow, thigh, pref, coeffs);
|
return new NasaPoly2(tlow, thigh, pref, coeffs);
|
||||||
case ADSORBATE:
|
|
||||||
return new Adsorbate(tlow, thigh, pref, coeffs);
|
|
||||||
default:
|
default:
|
||||||
throw CanteraError("newSpeciesThermoInterpType",
|
throw CanteraError("newSpeciesThermoInterpType",
|
||||||
"Unknown species thermo type: {}.", type);
|
"Unknown species thermo type: {}.", type);
|
||||||
|
|
@ -73,8 +70,6 @@ SpeciesThermoInterpType* newSpeciesThermoInterpType(const std::string& stype,
|
||||||
itype = NASA9MULTITEMP; // multi-region, 9-coefficient NASA polynomials
|
itype = NASA9MULTITEMP; // multi-region, 9-coefficient NASA polynomials
|
||||||
} else if (type == "mu0") {
|
} else if (type == "mu0") {
|
||||||
itype = MU0_INTERP;
|
itype = MU0_INTERP;
|
||||||
} else if (type == "adsorbate") {
|
|
||||||
itype = ADSORBATE;
|
|
||||||
} else {
|
} else {
|
||||||
throw CanteraError("newSpeciesThermoInterpType",
|
throw CanteraError("newSpeciesThermoInterpType",
|
||||||
"Unknown species thermo type: '" + stype + "'.");
|
"Unknown species thermo type: '" + stype + "'.");
|
||||||
|
|
@ -146,58 +141,6 @@ static SpeciesThermoInterpType* newNasaThermoFromXML(vector<XML_Node*> nodes)
|
||||||
return newSpeciesThermoInterpType(NASA, tmin, tmax, p0, &c[0]);
|
return newSpeciesThermoInterpType(NASA, tmin, tmax, p0, &c[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Create a Shomate polynomial from an XML node giving the 'EQ3' coefficients
|
|
||||||
/*!
|
|
||||||
* This is called if a 'MinEQ3' node is found in the XML input.
|
|
||||||
* @param MinEQ3node The XML_Node containing the MinEQ3 parameterization
|
|
||||||
*/
|
|
||||||
SpeciesThermoInterpType* newShomateForMineralEQ3(const XML_Node& MinEQ3node)
|
|
||||||
{
|
|
||||||
doublereal tmin0 = strSItoDbl(MinEQ3node["Tmin"]);
|
|
||||||
doublereal tmax0 = strSItoDbl(MinEQ3node["Tmax"]);
|
|
||||||
doublereal p0 = strSItoDbl(MinEQ3node["Pref"]);
|
|
||||||
|
|
||||||
doublereal deltaG_formation_pr_tr =
|
|
||||||
getFloat(MinEQ3node, "DG0_f_Pr_Tr", "actEnergy") / actEnergyToSI("cal/gmol");
|
|
||||||
doublereal deltaH_formation_pr_tr =
|
|
||||||
getFloat(MinEQ3node, "DH0_f_Pr_Tr", "actEnergy") / actEnergyToSI("cal/gmol");
|
|
||||||
doublereal Entrop_pr_tr = getFloat(MinEQ3node, "S0_Pr_Tr", "toSI") / toSI("cal/gmol/K");
|
|
||||||
doublereal a = getFloat(MinEQ3node, "a", "toSI") / toSI("cal/gmol/K");
|
|
||||||
doublereal b = getFloat(MinEQ3node, "b", "toSI") / toSI("cal/gmol/K2");
|
|
||||||
doublereal c = getFloat(MinEQ3node, "c", "toSI") / toSI("cal-K/gmol");
|
|
||||||
doublereal dg = deltaG_formation_pr_tr * toSI("cal/gmol");
|
|
||||||
doublereal DHjmol = deltaH_formation_pr_tr * toSI("cal/gmol");
|
|
||||||
doublereal fac = DHjmol - dg - 298.15 * Entrop_pr_tr * toSI("cal/gmol");
|
|
||||||
doublereal Mu0_tr_pr = fac + dg;
|
|
||||||
doublereal e = Entrop_pr_tr * toSI("cal/gmol");
|
|
||||||
doublereal Hcalc = Mu0_tr_pr + 298.15 * e;
|
|
||||||
|
|
||||||
// Now calculate the shomate polynomials
|
|
||||||
//
|
|
||||||
// Cp first
|
|
||||||
//
|
|
||||||
// Shomate: (Joules / gmol / K)
|
|
||||||
// Cp = As + Bs * t + Cs * t*t + Ds * t*t*t + Es / (t*t)
|
|
||||||
// where
|
|
||||||
// t = temperature(Kelvin) / 1000
|
|
||||||
double As = a * toSI("cal");
|
|
||||||
double Bs = b * toSI("cal") * 1000.;
|
|
||||||
double Cs = 0.0;
|
|
||||||
double Ds = 0.0;
|
|
||||||
double Es = c * toSI("cal") / (1.0E6);
|
|
||||||
|
|
||||||
double t = 298.15 / 1000.;
|
|
||||||
double H298smFs = As * t + Bs * t * t / 2.0 - Es / t;
|
|
||||||
double HcalcS = Hcalc / 1.0E6;
|
|
||||||
double Fs = HcalcS - H298smFs;
|
|
||||||
double S298smGs = As * log(t) + Bs * t - Es/(2.0*t*t);
|
|
||||||
double ScalcS = e / 1.0E3;
|
|
||||||
double Gs = ScalcS - S298smGs;
|
|
||||||
|
|
||||||
double c0[7] = {As, Bs, Cs, Ds, Es, Fs, Gs};
|
|
||||||
return newSpeciesThermoInterpType(SHOMATE1, tmin0, tmax0, p0, c0);
|
|
||||||
}
|
|
||||||
|
|
||||||
//! Create a Shomate polynomial thermodynamic property parameterization for a
|
//! Create a Shomate polynomial thermodynamic property parameterization for a
|
||||||
//! species
|
//! species
|
||||||
/*!
|
/*!
|
||||||
|
|
@ -341,41 +284,6 @@ static SpeciesThermoInterpType* newNasa9ThermoFromXML(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Create an Adsorbate polynomial thermodynamic property parameterization for a
|
|
||||||
//! species
|
|
||||||
/*!
|
|
||||||
* This is called if a 'Adsorbate' node is found in the XML input.
|
|
||||||
*
|
|
||||||
* @param f XML Node that contains the parameterization
|
|
||||||
*/
|
|
||||||
static SpeciesThermoInterpType* newAdsorbateThermoFromXML(const XML_Node& f)
|
|
||||||
{
|
|
||||||
vector_fp freqs;
|
|
||||||
doublereal pref = OneAtm;
|
|
||||||
double tmin = fpValue(f["Tmin"]);
|
|
||||||
double tmax = fpValue(f["Tmax"]);
|
|
||||||
if (f.hasAttrib("P0")) {
|
|
||||||
pref = fpValue(f["P0"]);
|
|
||||||
}
|
|
||||||
if (f.hasAttrib("Pref")) {
|
|
||||||
pref = fpValue(f["Pref"]);
|
|
||||||
}
|
|
||||||
if (tmax == 0.0) {
|
|
||||||
tmax = 1.0e30;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (f.hasChild("floatArray")) {
|
|
||||||
getFloatArray(f.child("floatArray"), freqs, false);
|
|
||||||
}
|
|
||||||
for (size_t n = 0; n < freqs.size(); n++) {
|
|
||||||
freqs[n] *= 3.0e10;
|
|
||||||
}
|
|
||||||
vector_fp coeffs(freqs.size() + 2);
|
|
||||||
coeffs[0] = static_cast<double>(freqs.size());
|
|
||||||
coeffs[1] = getFloat(f, "binding_energy", "toSI");
|
|
||||||
copy(freqs.begin(), freqs.end(), coeffs.begin() + 2);
|
|
||||||
return new Adsorbate(tmin, tmax, pref, &coeffs[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
SpeciesThermoInterpType* newSpeciesThermoInterpType(const XML_Node& thermo)
|
SpeciesThermoInterpType* newSpeciesThermoInterpType(const XML_Node& thermo)
|
||||||
{
|
{
|
||||||
|
|
@ -410,19 +318,12 @@ SpeciesThermoInterpType* newSpeciesThermoInterpType(const XML_Node& thermo)
|
||||||
}
|
}
|
||||||
if ((tp.size() > 2 && thermoType != "nasa9") ||
|
if ((tp.size() > 2 && thermoType != "nasa9") ||
|
||||||
(tp.size() > 1 && (thermoType == "const_cp" ||
|
(tp.size() > 1 && (thermoType == "const_cp" ||
|
||||||
thermoType == "mu0" ||
|
thermoType == "mu0"))) {
|
||||||
thermoType == "adsorbate"))) {
|
|
||||||
throw CanteraError("newSpeciesThermoInterpType",
|
throw CanteraError("newSpeciesThermoInterpType",
|
||||||
"Too many regions in thermo parameterization.");
|
"Too many regions in thermo parameterization.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (model == "mineraleq3") {
|
if (thermoType == "shomate") {
|
||||||
if (thermoType != "mineq3") {
|
|
||||||
throw CanteraError("newSpeciesThermoInterpType",
|
|
||||||
"confused: expected MinEQ3");
|
|
||||||
}
|
|
||||||
return newShomateForMineralEQ3(*tp[0]);
|
|
||||||
} else if (thermoType == "shomate") {
|
|
||||||
return newShomateThermoFromXML(tp);
|
return newShomateThermoFromXML(tp);
|
||||||
} else if (thermoType == "const_cp") {
|
} else if (thermoType == "const_cp") {
|
||||||
return newConstCpThermoFromXML(*tp[0]);
|
return newConstCpThermoFromXML(*tp[0]);
|
||||||
|
|
@ -432,8 +333,6 @@ SpeciesThermoInterpType* newSpeciesThermoInterpType(const XML_Node& thermo)
|
||||||
return newMu0ThermoFromXML(*tp[0]);
|
return newMu0ThermoFromXML(*tp[0]);
|
||||||
} else if (thermoType == "nasa9") {
|
} else if (thermoType == "nasa9") {
|
||||||
return newNasa9ThermoFromXML(tp);
|
return newNasa9ThermoFromXML(tp);
|
||||||
} else if (thermoType == "adsorbate") {
|
|
||||||
return newAdsorbateThermoFromXML(*tp[0]);
|
|
||||||
} else {
|
} else {
|
||||||
throw CanteraError("newSpeciesThermoInterpType",
|
throw CanteraError("newSpeciesThermoInterpType",
|
||||||
"Unknown species thermo model '" + thermoType + "'.");
|
"Unknown species thermo model '" + thermoType + "'.");
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,6 @@
|
||||||
#include "cantera/thermo/MargulesVPSSTP.h"
|
#include "cantera/thermo/MargulesVPSSTP.h"
|
||||||
#include "cantera/thermo/RedlichKisterVPSSTP.h"
|
#include "cantera/thermo/RedlichKisterVPSSTP.h"
|
||||||
#include "cantera/thermo/IonsFromNeutralVPSSTP.h"
|
#include "cantera/thermo/IonsFromNeutralVPSSTP.h"
|
||||||
#include "cantera/thermo/PhaseCombo_Interaction.h"
|
|
||||||
#include "cantera/thermo/PureFluidPhase.h"
|
#include "cantera/thermo/PureFluidPhase.h"
|
||||||
#include "cantera/thermo/RedlichKwongMFTP.h"
|
#include "cantera/thermo/RedlichKwongMFTP.h"
|
||||||
#include "cantera/thermo/ConstDensityThermo.h"
|
#include "cantera/thermo/ConstDensityThermo.h"
|
||||||
|
|
@ -29,15 +28,12 @@
|
||||||
#include "cantera/thermo/EdgePhase.h"
|
#include "cantera/thermo/EdgePhase.h"
|
||||||
#include "cantera/thermo/MetalPhase.h"
|
#include "cantera/thermo/MetalPhase.h"
|
||||||
#include "cantera/thermo/StoichSubstance.h"
|
#include "cantera/thermo/StoichSubstance.h"
|
||||||
#include "cantera/thermo/MineralEQ3.h"
|
|
||||||
#include "cantera/thermo/MetalSHEelectrons.h"
|
|
||||||
#include "cantera/thermo/FixedChemPotSSTP.h"
|
#include "cantera/thermo/FixedChemPotSSTP.h"
|
||||||
#include "cantera/thermo/LatticeSolidPhase.h"
|
#include "cantera/thermo/LatticeSolidPhase.h"
|
||||||
#include "cantera/thermo/LatticePhase.h"
|
#include "cantera/thermo/LatticePhase.h"
|
||||||
#include "cantera/thermo/HMWSoln.h"
|
#include "cantera/thermo/HMWSoln.h"
|
||||||
#include "cantera/thermo/DebyeHuckel.h"
|
#include "cantera/thermo/DebyeHuckel.h"
|
||||||
#include "cantera/thermo/IdealMolalSoln.h"
|
#include "cantera/thermo/IdealMolalSoln.h"
|
||||||
#include "cantera/thermo/MolarityIonicVPSSTP.h"
|
|
||||||
#include "cantera/thermo/IdealSolnGasVPSS.h"
|
#include "cantera/thermo/IdealSolnGasVPSS.h"
|
||||||
#include "cantera/thermo/WaterSSTP.h"
|
#include "cantera/thermo/WaterSSTP.h"
|
||||||
#include "cantera/base/stringUtils.h"
|
#include "cantera/base/stringUtils.h"
|
||||||
|
|
@ -67,13 +63,9 @@ ThermoFactory::ThermoFactory()
|
||||||
reg("IdealMolalSolution", []() { return new IdealMolalSoln(); });
|
reg("IdealMolalSolution", []() { return new IdealMolalSoln(); });
|
||||||
reg("IdealGasVPSS", []() { return new IdealSolnGasVPSS(); });
|
reg("IdealGasVPSS", []() { return new IdealSolnGasVPSS(); });
|
||||||
m_synonyms["IdealGasVPSS"] = "IdealSolnVPSS";
|
m_synonyms["IdealGasVPSS"] = "IdealSolnVPSS";
|
||||||
reg("MineralEQ3", []() { return new MineralEQ3(); });
|
|
||||||
reg("MetalSHEelectrons", []() { return new MetalSHEelectrons(); });
|
|
||||||
reg("Margules", []() { return new MargulesVPSSTP(); });
|
reg("Margules", []() { return new MargulesVPSSTP(); });
|
||||||
reg("PhaseCombo_Interaction", []() { return new PhaseCombo_Interaction(); });
|
|
||||||
reg("IonsFromNeutralMolecule", []() { return new IonsFromNeutralVPSSTP(); });
|
reg("IonsFromNeutralMolecule", []() { return new IonsFromNeutralVPSSTP(); });
|
||||||
reg("FixedChemPot", []() { return new FixedChemPotSSTP(); });
|
reg("FixedChemPot", []() { return new FixedChemPotSSTP(); });
|
||||||
reg("MolarityIonicVPSSTP", []() { return new MolarityIonicVPSSTP(); });
|
|
||||||
reg("Redlich-Kister", []() { return new RedlichKisterVPSSTP(); });
|
reg("Redlich-Kister", []() { return new RedlichKisterVPSSTP(); });
|
||||||
reg("RedlichKwong", []() { return new RedlichKwongMFTP(); });
|
reg("RedlichKwong", []() { return new RedlichKwongMFTP(); });
|
||||||
m_synonyms["RedlichKwongMFTP"] = "RedlichKwong";
|
m_synonyms["RedlichKwongMFTP"] = "RedlichKwong";
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,6 @@ namespace Cantera
|
||||||
ThermoPhase::ThermoPhase() :
|
ThermoPhase::ThermoPhase() :
|
||||||
m_speciesData(0),
|
m_speciesData(0),
|
||||||
m_phi(0.0),
|
m_phi(0.0),
|
||||||
m_hasElementPotentials(false),
|
|
||||||
m_chargeNeutralityNecessary(false),
|
m_chargeNeutralityNecessary(false),
|
||||||
m_ssConvention(cSS_CONVENTION_TEMPERATURE),
|
m_ssConvention(cSS_CONVENTION_TEMPERATURE),
|
||||||
m_tlast(0.0)
|
m_tlast(0.0)
|
||||||
|
|
@ -702,11 +701,6 @@ void ThermoPhase::equilibrate(const std::string& XY, const std::string& solver,
|
||||||
throw CanteraError("ThermoPhase::equilibrate",
|
throw CanteraError("ThermoPhase::equilibrate",
|
||||||
"ChemEquil solver failed. Return code: {}", ret);
|
"ChemEquil solver failed. Return code: {}", ret);
|
||||||
}
|
}
|
||||||
m_lambdaRRT.resize(nElements());
|
|
||||||
for (size_t m = 0; m < nElements(); m++) {
|
|
||||||
m_lambdaRRT[m] = E.elementPotentials()[m] / RT();
|
|
||||||
}
|
|
||||||
m_hasElementPotentials = true;
|
|
||||||
debuglog("ChemEquil solver succeeded\n", log_level);
|
debuglog("ChemEquil solver succeeded\n", log_level);
|
||||||
return;
|
return;
|
||||||
} catch (std::exception& err) {
|
} catch (std::exception& err) {
|
||||||
|
|
@ -735,31 +729,6 @@ void ThermoPhase::equilibrate(const std::string& XY, const std::string& solver,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ThermoPhase::setElementPotentials(const vector_fp& lambda)
|
|
||||||
{
|
|
||||||
warn_deprecated("ThermoPhase::setElementPotentials",
|
|
||||||
"To be removed after Cantera 2.4");
|
|
||||||
size_t mm = nElements();
|
|
||||||
if (lambda.size() < mm) {
|
|
||||||
throw CanteraError("setElementPotentials", "lambda too small");
|
|
||||||
}
|
|
||||||
if (!m_hasElementPotentials) {
|
|
||||||
m_lambdaRRT.resize(mm);
|
|
||||||
}
|
|
||||||
scale(lambda.begin(), lambda.end(), m_lambdaRRT.begin(), 1.0/RT());
|
|
||||||
m_hasElementPotentials = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ThermoPhase::getElementPotentials(doublereal* lambda) const
|
|
||||||
{
|
|
||||||
warn_deprecated("ThermoPhase::getElementPotentials",
|
|
||||||
"To be removed after Cantera 2.4");
|
|
||||||
if (m_hasElementPotentials) {
|
|
||||||
scale(m_lambdaRRT.begin(), m_lambdaRRT.end(), lambda, RT());
|
|
||||||
}
|
|
||||||
return m_hasElementPotentials;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ThermoPhase::getdlnActCoeffdlnN(const size_t ld, doublereal* const dlnActCoeffdlnN)
|
void ThermoPhase::getdlnActCoeffdlnN(const size_t ld, doublereal* const dlnActCoeffdlnN)
|
||||||
{
|
{
|
||||||
for (size_t m = 0; m < m_kk; m++) {
|
for (size_t m = 0; m < m_kk; m++) {
|
||||||
|
|
|
||||||
|
|
@ -1,246 +0,0 @@
|
||||||
/**
|
|
||||||
* @file LTPspecies.cpp
|
|
||||||
* Definitions for the LTPspecies objects and its children, which is the virtual base class
|
|
||||||
* for describing temperature dependence of submodels for transport parameters
|
|
||||||
* (see \ref tranprops and \link Cantera::LTPspecies LTPspecies \endlink) .
|
|
||||||
*/
|
|
||||||
|
|
||||||
// This file is part of Cantera. See License.txt in the top-level directory or
|
|
||||||
// at http://www.cantera.org/license.txt for license and copyright information.
|
|
||||||
|
|
||||||
#include "cantera/transport/LTPspecies.h"
|
|
||||||
#include "cantera/base/ctml.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
namespace Cantera
|
|
||||||
{
|
|
||||||
//! Exception thrown if an error is encountered while reading the transport database.
|
|
||||||
class LTPError : public CanteraError
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
//! Constructor is a wrapper around CanteraError
|
|
||||||
/*!
|
|
||||||
* @param msg Informative message
|
|
||||||
*/
|
|
||||||
explicit LTPError(const std::string& msg) :
|
|
||||||
CanteraError("LTPspecies", "error parsing transport data: " + msg + "\n") {
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
//! Parses the XML element called Arrhenius.
|
|
||||||
/*!
|
|
||||||
* The Arrhenius expression is
|
|
||||||
* \f[
|
|
||||||
* k = A T^(b) exp (-E_a / RT)
|
|
||||||
* \f]
|
|
||||||
*
|
|
||||||
* @param node XML_Node to be read
|
|
||||||
* @param A Output pre-exponential factor. The units are variable.
|
|
||||||
* @param b output temperature power
|
|
||||||
* @param E Output activation energy in units of Kelvin
|
|
||||||
*/
|
|
||||||
static void getArrhenius(const XML_Node& node,
|
|
||||||
doublereal& A, doublereal& b, doublereal& E)
|
|
||||||
{
|
|
||||||
// parse the children for the A, b, and E components.
|
|
||||||
A = getFloat(node, "A", "toSI");
|
|
||||||
b = getFloat(node, "b");
|
|
||||||
E = getFloat(node, "E", "actEnergy") / GasConstant;
|
|
||||||
}
|
|
||||||
|
|
||||||
LTPspecies::LTPspecies() :
|
|
||||||
m_speciesName("-"),
|
|
||||||
m_model(LTP_TD_NOTSET),
|
|
||||||
m_property(TP_UNKNOWN),
|
|
||||||
m_thermo(0),
|
|
||||||
m_mixWeight(1.0)
|
|
||||||
{
|
|
||||||
warn_deprecated("class LTPspecies", "To be removed after Cantera 2.4");
|
|
||||||
}
|
|
||||||
|
|
||||||
LTPspecies* LTPspecies::duplMyselfAsLTPspecies() const
|
|
||||||
{
|
|
||||||
return new LTPspecies(*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
doublereal LTPspecies::getSpeciesTransProp()
|
|
||||||
{
|
|
||||||
return 0.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool LTPspecies::checkPositive() const
|
|
||||||
{
|
|
||||||
return (m_coeffs[0] > 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
doublereal LTPspecies::getMixWeight() const
|
|
||||||
{
|
|
||||||
return m_mixWeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
void LTPspecies::adjustCoeffsForComposition()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
LTPspecies_Const::LTPspecies_Const()
|
|
||||||
{
|
|
||||||
m_model = LTP_TD_CONSTANT;
|
|
||||||
}
|
|
||||||
|
|
||||||
void LTPspecies_Const::setupFromXML(const XML_Node& propNode)
|
|
||||||
{
|
|
||||||
double A_k = getFloatCurrent(propNode, "toSI");
|
|
||||||
if (A_k > 0.0) {
|
|
||||||
setCoeff(A_k);
|
|
||||||
} else {
|
|
||||||
throw LTPError("negative or zero " + propNode.name());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void LTPspecies_Const::setCoeff(double C)
|
|
||||||
{
|
|
||||||
m_coeffs = {C};
|
|
||||||
}
|
|
||||||
|
|
||||||
LTPspecies* LTPspecies_Const::duplMyselfAsLTPspecies() const
|
|
||||||
{
|
|
||||||
return new LTPspecies_Const(*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
doublereal LTPspecies_Const::getSpeciesTransProp()
|
|
||||||
{
|
|
||||||
return m_coeffs[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
LTPspecies_Arrhenius::LTPspecies_Arrhenius()
|
|
||||||
{
|
|
||||||
m_model = LTP_TD_ARRHENIUS;
|
|
||||||
m_temp = 0.0;
|
|
||||||
m_prop = 0.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
LTPspecies* LTPspecies_Arrhenius::duplMyselfAsLTPspecies() const
|
|
||||||
{
|
|
||||||
return new LTPspecies_Arrhenius(*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void LTPspecies_Arrhenius::setupFromXML(const XML_Node& propNode)
|
|
||||||
{
|
|
||||||
doublereal A_k, n_k, Tact_k;
|
|
||||||
getArrhenius(propNode, A_k, n_k, Tact_k);
|
|
||||||
if (A_k <= 0.0) {
|
|
||||||
throw LTPError("negative or zero " + propNode.name());
|
|
||||||
}
|
|
||||||
setCoeffs(A_k, n_k, Tact_k);
|
|
||||||
}
|
|
||||||
|
|
||||||
void LTPspecies_Arrhenius::setCoeffs(double A, double n, double Tact)
|
|
||||||
{
|
|
||||||
m_coeffs = {A, n, Tact, log(A)};
|
|
||||||
}
|
|
||||||
|
|
||||||
doublereal LTPspecies_Arrhenius::getSpeciesTransProp()
|
|
||||||
{
|
|
||||||
doublereal t = m_thermo->temperature();
|
|
||||||
//m_coeffs[0] holds A
|
|
||||||
//m_coeffs[1] holds n
|
|
||||||
//m_coeffs[2] holds Tact
|
|
||||||
//m_coeffs[3] holds log(A)
|
|
||||||
if (t != m_temp) {
|
|
||||||
m_prop = 0;
|
|
||||||
m_logProp = 0;
|
|
||||||
m_temp = t;
|
|
||||||
m_logt = log(m_temp);
|
|
||||||
//For viscosity the sign convention on positive activation energy is swithced
|
|
||||||
if (m_property == TP_VISCOSITY) {
|
|
||||||
m_logProp = m_coeffs[3] + m_coeffs[1] * m_logt + m_coeffs[2] / m_temp;
|
|
||||||
} else {
|
|
||||||
m_logProp = m_coeffs[3] + m_coeffs[1] * m_logt - m_coeffs[2] / m_temp;
|
|
||||||
}
|
|
||||||
m_prop = exp(m_logProp);
|
|
||||||
}
|
|
||||||
return m_prop;
|
|
||||||
}
|
|
||||||
|
|
||||||
LTPspecies_Poly::LTPspecies_Poly() :
|
|
||||||
m_temp(-1.0),
|
|
||||||
m_prop(0.0)
|
|
||||||
{
|
|
||||||
m_model = LTP_TD_POLY;
|
|
||||||
}
|
|
||||||
|
|
||||||
LTPspecies* LTPspecies_Poly::duplMyselfAsLTPspecies() const
|
|
||||||
{
|
|
||||||
return new LTPspecies_Poly(*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void LTPspecies_Poly::setupFromXML(const XML_Node& propNode)
|
|
||||||
{
|
|
||||||
vector_fp coeffs;
|
|
||||||
getFloatArray(propNode, coeffs, "true", "toSI");
|
|
||||||
setCoeffs(coeffs.size(), coeffs.data());
|
|
||||||
}
|
|
||||||
|
|
||||||
void LTPspecies_Poly::setCoeffs(size_t N, const double* coeffs)
|
|
||||||
{
|
|
||||||
m_coeffs.assign(coeffs, coeffs+N);
|
|
||||||
}
|
|
||||||
|
|
||||||
doublereal LTPspecies_Poly::getSpeciesTransProp()
|
|
||||||
{
|
|
||||||
doublereal t = m_thermo->temperature();
|
|
||||||
if (t != m_temp) {
|
|
||||||
m_prop = 0.0;
|
|
||||||
m_temp = t;
|
|
||||||
double tempN = 1.0;
|
|
||||||
for (int i = 0; i < (int) m_coeffs.size() ; i++) {
|
|
||||||
m_prop += m_coeffs[i] * tempN;
|
|
||||||
tempN *= m_temp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return m_prop;
|
|
||||||
}
|
|
||||||
|
|
||||||
LTPspecies_ExpT::LTPspecies_ExpT() :
|
|
||||||
m_temp(-1.0),
|
|
||||||
m_prop(0.0)
|
|
||||||
{
|
|
||||||
m_model = LTP_TD_EXPT;
|
|
||||||
}
|
|
||||||
|
|
||||||
LTPspecies* LTPspecies_ExpT::duplMyselfAsLTPspecies() const
|
|
||||||
{
|
|
||||||
return new LTPspecies_ExpT(*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void LTPspecies_ExpT::setupFromXML(const XML_Node& propNode)
|
|
||||||
{
|
|
||||||
vector_fp coeffs;
|
|
||||||
getFloatArray(propNode, coeffs, "true", "toSI");
|
|
||||||
setCoeffs(coeffs.size(), coeffs.data());
|
|
||||||
}
|
|
||||||
|
|
||||||
void LTPspecies_ExpT::setCoeffs(size_t N, const double* coeffs)
|
|
||||||
{
|
|
||||||
m_coeffs.assign(coeffs, coeffs+N);
|
|
||||||
}
|
|
||||||
|
|
||||||
doublereal LTPspecies_ExpT::getSpeciesTransProp()
|
|
||||||
{
|
|
||||||
doublereal t = m_thermo->temperature();
|
|
||||||
if (t != m_temp) {
|
|
||||||
m_temp=t;
|
|
||||||
m_prop = m_coeffs[0];
|
|
||||||
doublereal tempN = 1.0;
|
|
||||||
doublereal tmp = 0.0;
|
|
||||||
for (int i = 1; i < (int) m_coeffs.size() ; i++) {
|
|
||||||
tempN *= m_temp;
|
|
||||||
tmp += m_coeffs[i] * tempN;
|
|
||||||
}
|
|
||||||
m_prop *= exp(tmp);
|
|
||||||
}
|
|
||||||
return m_prop;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,652 +0,0 @@
|
||||||
/**
|
|
||||||
* @file LiquidTranInteraction.cpp
|
|
||||||
* Source code for liquid mixture transport property evaluations.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// This file is part of Cantera. See License.txt in the top-level directory or
|
|
||||||
// at http://www.cantera.org/license.txt for license and copyright information.
|
|
||||||
|
|
||||||
#include "cantera/transport/LiquidTransportParams.h"
|
|
||||||
#include "cantera/thermo/IonsFromNeutralVPSSTP.h"
|
|
||||||
#include "cantera/thermo/MargulesVPSSTP.h"
|
|
||||||
#include "cantera/base/stringUtils.h"
|
|
||||||
#include "cantera/base/ctml.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
namespace Cantera
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Exception thrown if an error is encountered while reading the
|
|
||||||
* transport database.
|
|
||||||
*/
|
|
||||||
class LTPmodelError : public CanteraError
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
explicit LTPmodelError(const std::string& msg)
|
|
||||||
: CanteraError("LTPspecies",
|
|
||||||
"error parsing transport data: "
|
|
||||||
+ msg + "\n") {}
|
|
||||||
};
|
|
||||||
|
|
||||||
LiquidTranInteraction::LiquidTranInteraction(TransportPropertyType tp_ind) :
|
|
||||||
m_model(LTI_MODEL_NOTSET),
|
|
||||||
m_property(tp_ind)
|
|
||||||
{
|
|
||||||
warn_deprecated("Class LiquidTranInteraction", "To be removed after Cantera 2.4");
|
|
||||||
}
|
|
||||||
|
|
||||||
LiquidTranInteraction::~LiquidTranInteraction()
|
|
||||||
{
|
|
||||||
for (size_t k = 0; k < m_Aij.size(); k++) {
|
|
||||||
delete m_Aij[k];
|
|
||||||
}
|
|
||||||
for (size_t k = 0; k < m_Bij.size(); k++) {
|
|
||||||
delete m_Bij[k];
|
|
||||||
}
|
|
||||||
for (size_t k = 0; k < m_Hij.size(); k++) {
|
|
||||||
delete m_Hij[k];
|
|
||||||
}
|
|
||||||
for (size_t k = 0; k < m_Sij.size(); k++) {
|
|
||||||
delete m_Sij[k];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void LiquidTranInteraction::init(const XML_Node& compModelNode,
|
|
||||||
thermo_t* thermo)
|
|
||||||
{
|
|
||||||
m_thermo = thermo;
|
|
||||||
size_t nsp = thermo->nSpecies();
|
|
||||||
m_Dij.resize(nsp, nsp, 0.0);
|
|
||||||
m_Eij.resize(nsp, nsp, 0.0);
|
|
||||||
|
|
||||||
for (size_t iChild = 0; iChild < compModelNode.nChildren(); iChild++) {
|
|
||||||
XML_Node& xmlChild = compModelNode.child(iChild);
|
|
||||||
std::string nodeName = xmlChild.name();
|
|
||||||
if (!caseInsensitiveEquals(nodeName, "interaction")) {
|
|
||||||
throw CanteraError("TransportFactory::getLiquidInteractionsTransportData",
|
|
||||||
"expected <interaction> element and got <" + nodeName + ">");
|
|
||||||
}
|
|
||||||
string speciesA = xmlChild.attrib("speciesA");
|
|
||||||
string speciesB = xmlChild.attrib("speciesB");
|
|
||||||
size_t iSpecies = m_thermo->speciesIndex(speciesA);
|
|
||||||
if (iSpecies == npos) {
|
|
||||||
throw CanteraError("TransportFactory::getLiquidInteractionsTransportData",
|
|
||||||
"Unknown species " + speciesA);
|
|
||||||
}
|
|
||||||
size_t jSpecies = m_thermo->speciesIndex(speciesB);
|
|
||||||
if (jSpecies == npos) {
|
|
||||||
throw CanteraError("TransportFactory::getLiquidInteractionsTransportData",
|
|
||||||
"Unknown species " + speciesB);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (xmlChild.hasChild("Eij")) {
|
|
||||||
m_Eij(iSpecies,jSpecies) = getFloat(xmlChild, "Eij", "actEnergy");
|
|
||||||
m_Eij(iSpecies,jSpecies) /= GasConstant;
|
|
||||||
m_Eij(jSpecies,iSpecies) = m_Eij(iSpecies,jSpecies);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (xmlChild.hasChild("Aij")) {
|
|
||||||
vector_fp poly;
|
|
||||||
getFloatArray(xmlChild, poly, true, "toSI", "Aij");
|
|
||||||
while (m_Aij.size()<poly.size()) {
|
|
||||||
DenseMatrix* aTemp = new DenseMatrix();
|
|
||||||
aTemp->resize(nsp, nsp, 0.0);
|
|
||||||
m_Aij.push_back(aTemp);
|
|
||||||
}
|
|
||||||
for (int i = 0; i < (int)poly.size(); i++) {
|
|
||||||
(*m_Aij[i])(iSpecies,jSpecies) = poly[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (xmlChild.hasChild("Bij")) {
|
|
||||||
vector_fp poly;
|
|
||||||
getFloatArray(xmlChild, poly, true, "toSI", "Bij");
|
|
||||||
while (m_Bij.size() < poly.size()) {
|
|
||||||
DenseMatrix* bTemp = new DenseMatrix();
|
|
||||||
bTemp->resize(nsp, nsp, 0.0);
|
|
||||||
m_Bij.push_back(bTemp);
|
|
||||||
}
|
|
||||||
for (size_t i=0; i<poly.size(); i++) {
|
|
||||||
(*m_Bij[i])(iSpecies,jSpecies) = poly[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (xmlChild.hasChild("Hij")) {
|
|
||||||
vector_fp poly;
|
|
||||||
getFloatArray(xmlChild, poly, true, "actEnergy", "Hij");
|
|
||||||
while (m_Hij.size()<poly.size()) {
|
|
||||||
DenseMatrix* hTemp = new DenseMatrix();
|
|
||||||
hTemp->resize(nsp, nsp, 0.0);
|
|
||||||
m_Hij.push_back(hTemp);
|
|
||||||
}
|
|
||||||
for (size_t i=0; i<poly.size(); i++) {
|
|
||||||
(*m_Hij[i])(iSpecies,jSpecies) = poly[i];
|
|
||||||
(*m_Hij[i])(iSpecies,jSpecies) /= GasConstant;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (xmlChild.hasChild("Sij")) {
|
|
||||||
vector_fp poly;
|
|
||||||
getFloatArray(xmlChild, poly, true, "actEnergy", "Sij");
|
|
||||||
while (m_Sij.size()<poly.size()) {
|
|
||||||
DenseMatrix* sTemp = new DenseMatrix();
|
|
||||||
sTemp->resize(nsp, nsp, 0.0);
|
|
||||||
m_Sij.push_back(sTemp);
|
|
||||||
}
|
|
||||||
for (size_t i=0; i<poly.size(); i++) {
|
|
||||||
(*m_Sij[i])(iSpecies,jSpecies) = poly[i];
|
|
||||||
(*m_Sij[i])(iSpecies,jSpecies) /= GasConstant;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (xmlChild.hasChild("Dij")) {
|
|
||||||
m_Dij(iSpecies,jSpecies) = getFloat(xmlChild, "Dij", "toSI");
|
|
||||||
m_Dij(jSpecies,iSpecies) = m_Dij(iSpecies,jSpecies);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
LTI_Solvent::LTI_Solvent(TransportPropertyType tp_ind) :
|
|
||||||
LiquidTranInteraction(tp_ind)
|
|
||||||
{
|
|
||||||
m_model = LTI_MODEL_SOLVENT;
|
|
||||||
}
|
|
||||||
|
|
||||||
doublereal LTI_Solvent::getMixTransProp(doublereal* speciesValues, doublereal* speciesWeight)
|
|
||||||
{
|
|
||||||
size_t nsp = m_thermo->nSpecies();
|
|
||||||
doublereal temp = m_thermo->temperature();
|
|
||||||
vector_fp molefracs(nsp);
|
|
||||||
m_thermo->getMoleFractions(&molefracs[0]);
|
|
||||||
doublereal value = 0.0;
|
|
||||||
|
|
||||||
//if weightings are specified, use those
|
|
||||||
if (speciesWeight) {
|
|
||||||
for (size_t k = 0; k < nsp; k++) {
|
|
||||||
// should be: molefracs[k] = molefracs[k]*speciesWeight[k]; for consistency, but weight(solvent)=1?
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
throw CanteraError("LTI_Solvent::getMixTransProp","You should be specifying the speciesWeight");
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i = 0; i < nsp; i++) {
|
|
||||||
//presume that the weighting is set to 1.0 for solvent and 0.0 for everything else.
|
|
||||||
value += speciesValues[i] * speciesWeight[i];
|
|
||||||
if (i == 0) {
|
|
||||||
AssertTrace(speciesWeight[i] == 1.0);
|
|
||||||
} else {
|
|
||||||
AssertTrace(speciesWeight[i] == 0.0);
|
|
||||||
}
|
|
||||||
for (size_t j = 0; j < nsp; j++) {
|
|
||||||
for (size_t k = 0; k < m_Aij.size(); k++) {
|
|
||||||
value += molefracs[i]*molefracs[j]*(*m_Aij[k])(i,j)*pow(molefracs[i], (int) k);
|
|
||||||
}
|
|
||||||
for (size_t k = 0; k < m_Bij.size(); k++) {
|
|
||||||
value += molefracs[i]*molefracs[j]*(*m_Bij[k])(i,j)*temp*pow(molefracs[i], (int) k);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
doublereal LTI_Solvent::getMixTransProp(std::vector<LTPspecies*> LTPptrs)
|
|
||||||
{
|
|
||||||
size_t nsp = m_thermo->nSpecies();
|
|
||||||
doublereal temp = m_thermo->temperature();
|
|
||||||
vector_fp molefracs(nsp);
|
|
||||||
m_thermo->getMoleFractions(&molefracs[0]);
|
|
||||||
doublereal value = 0.0;
|
|
||||||
|
|
||||||
for (size_t k = 0; k < nsp; k++) {
|
|
||||||
// should be: molefracs[k] = molefracs[k]*LTPptrs[k]->getMixWeight(); for consistency, but weight(solvent)=1?
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i = 0; i < nsp; i++) {
|
|
||||||
//presume that the weighting is set to 1.0 for solvent and 0.0 for everything else.
|
|
||||||
value += LTPptrs[i]->getSpeciesTransProp() * LTPptrs[i]->getMixWeight();
|
|
||||||
for (size_t j = 0; j < nsp; j++) {
|
|
||||||
for (size_t k = 0; k < m_Aij.size(); k++) {
|
|
||||||
value += molefracs[i]*molefracs[j]*(*m_Aij[k])(i,j)*pow(molefracs[i], (int) k);
|
|
||||||
}
|
|
||||||
for (size_t k = 0; k < m_Bij.size(); k++) {
|
|
||||||
value += molefracs[i]*molefracs[j]*(*m_Bij[k])(i,j)*temp*pow(molefracs[i], (int) k);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
void LTI_Solvent::getMatrixTransProp(DenseMatrix& mat, doublereal* speciesValues)
|
|
||||||
{
|
|
||||||
mat = (*m_Aij[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
doublereal LTI_MoleFracs::getMixTransProp(doublereal* speciesValues, doublereal* speciesWeight)
|
|
||||||
{
|
|
||||||
size_t nsp = m_thermo->nSpecies();
|
|
||||||
doublereal temp = m_thermo->temperature();
|
|
||||||
vector_fp molefracs(nsp);
|
|
||||||
m_thermo->getMoleFractions(&molefracs[0]);
|
|
||||||
doublereal value = 0;
|
|
||||||
|
|
||||||
//if weightings are specified, use those
|
|
||||||
if (speciesWeight) {
|
|
||||||
for (size_t k = 0; k < nsp; k++) {
|
|
||||||
molefracs[k] = molefracs[k]*speciesWeight[k];
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
throw CanteraError("LTI_MoleFracs::getMixTransProp","You should be specifying the speciesWeight");
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i = 0; i < nsp; i++) {
|
|
||||||
value += speciesValues[i] * molefracs[i];
|
|
||||||
for (size_t j = 0; j < nsp; j++) {
|
|
||||||
for (size_t k = 0; k < m_Aij.size(); k++) {
|
|
||||||
value += molefracs[i]*molefracs[j]*(*m_Aij[k])(i,j)*pow(molefracs[i], (int) k);
|
|
||||||
}
|
|
||||||
for (size_t k = 0; k < m_Bij.size(); k++) {
|
|
||||||
value += molefracs[i]*molefracs[j]*(*m_Bij[k])(i,j)*temp*pow(molefracs[i], (int) k);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
doublereal LTI_MoleFracs::getMixTransProp(std::vector<LTPspecies*> LTPptrs)
|
|
||||||
{
|
|
||||||
size_t nsp = m_thermo->nSpecies();
|
|
||||||
doublereal temp = m_thermo->temperature();
|
|
||||||
vector_fp molefracs(nsp);
|
|
||||||
m_thermo->getMoleFractions(&molefracs[0]);
|
|
||||||
doublereal value = 0;
|
|
||||||
|
|
||||||
for (size_t k = 0; k < nsp; k++) {
|
|
||||||
molefracs[k] = molefracs[k]*LTPptrs[k]->getMixWeight();
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i = 0; i < nsp; i++) {
|
|
||||||
value += LTPptrs[i]->getSpeciesTransProp() * molefracs[i];
|
|
||||||
for (size_t j = 0; j < nsp; j++) {
|
|
||||||
for (size_t k = 0; k < m_Aij.size(); k++) {
|
|
||||||
value += molefracs[i]*molefracs[j]*(*m_Aij[k])(i,j)*pow(molefracs[i], (int) k);
|
|
||||||
}
|
|
||||||
for (size_t k = 0; k < m_Bij.size(); k++) {
|
|
||||||
value += molefracs[i]*molefracs[j]*(*m_Bij[k])(i,j)*temp*pow(molefracs[i], (int) k);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
doublereal LTI_MassFracs::getMixTransProp(doublereal* speciesValues, doublereal* speciesWeight)
|
|
||||||
{
|
|
||||||
size_t nsp = m_thermo->nSpecies();
|
|
||||||
doublereal temp = m_thermo->temperature();
|
|
||||||
vector_fp massfracs(nsp);
|
|
||||||
m_thermo->getMassFractions(&massfracs[0]);
|
|
||||||
doublereal value = 0;
|
|
||||||
|
|
||||||
//if weightings are specified, use those
|
|
||||||
if (speciesWeight) {
|
|
||||||
for (size_t k = 0; k < nsp; k++) {
|
|
||||||
massfracs[k] = massfracs[k]*speciesWeight[k];
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
throw CanteraError("LTI_MassFracs::getMixTransProp","You should be specifying the speciesWeight");
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i = 0; i < nsp; i++) {
|
|
||||||
value += speciesValues[i] * massfracs[i];
|
|
||||||
for (size_t j = 0; j < nsp; j++) {
|
|
||||||
for (size_t k = 0; k < m_Aij.size(); k++) {
|
|
||||||
value += massfracs[i]*massfracs[j]*(*m_Aij[k])(i,j)*pow(massfracs[i], (int) k);
|
|
||||||
}
|
|
||||||
for (size_t k = 0; k < m_Bij.size(); k++) {
|
|
||||||
value += massfracs[i]*massfracs[j]*(*m_Bij[k])(i,j)*temp*pow(massfracs[i], (int) k);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
doublereal LTI_MassFracs::getMixTransProp(std::vector<LTPspecies*> LTPptrs)
|
|
||||||
{
|
|
||||||
size_t nsp = m_thermo->nSpecies();
|
|
||||||
doublereal temp = m_thermo->temperature();
|
|
||||||
vector_fp massfracs(nsp);
|
|
||||||
m_thermo->getMassFractions(&massfracs[0]);
|
|
||||||
doublereal value = 0;
|
|
||||||
|
|
||||||
for (size_t k = 0; k < nsp; k++) {
|
|
||||||
massfracs[k] = massfracs[k]*LTPptrs[k]->getMixWeight();
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i = 0; i < nsp; i++) {
|
|
||||||
value += LTPptrs[i]->getSpeciesTransProp() * massfracs[i];
|
|
||||||
for (size_t j = 0; j < nsp; j++) {
|
|
||||||
for (size_t k = 0; k < m_Aij.size(); k++) {
|
|
||||||
value += massfracs[i]*massfracs[j]*(*m_Aij[k])(i,j)*pow(massfracs[i], (int) k);
|
|
||||||
}
|
|
||||||
for (size_t k = 0; k < m_Bij.size(); k++) {
|
|
||||||
value += massfracs[i]*massfracs[j]*(*m_Bij[k])(i,j)*temp*pow(massfracs[i], (int) k);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
doublereal LTI_Log_MoleFracs::getMixTransProp(doublereal* speciesValues, doublereal* speciesWeight)
|
|
||||||
{
|
|
||||||
size_t nsp = m_thermo->nSpecies();
|
|
||||||
doublereal temp = m_thermo->temperature();
|
|
||||||
vector_fp molefracs(nsp);
|
|
||||||
m_thermo->getMoleFractions(&molefracs[0]);
|
|
||||||
doublereal value = 0;
|
|
||||||
|
|
||||||
//if weightings are specified, use those
|
|
||||||
if (speciesWeight) {
|
|
||||||
for (size_t k = 0; k < nsp; k++) {
|
|
||||||
molefracs[k] = molefracs[k]*speciesWeight[k];
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
throw CanteraError("LTI_Log_MoleFracs::getMixTransProp","You probably should have a speciesWeight when you call getMixTransProp to convert ion mole fractions to molecular mole fractions");
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i = 0; i < nsp; i++) {
|
|
||||||
value += log(speciesValues[i]) * molefracs[i];
|
|
||||||
for (size_t j = 0; j < nsp; j++) {
|
|
||||||
for (size_t k = 0; k < m_Hij.size(); k++) {
|
|
||||||
value += molefracs[i]*molefracs[j]*(*m_Hij[k])(i,j)/temp*pow(molefracs[i], (int) k);
|
|
||||||
}
|
|
||||||
for (size_t k = 0; k < m_Sij.size(); k++) {
|
|
||||||
value -= molefracs[i]*molefracs[j]*(*m_Sij[k])(i,j)*pow(molefracs[i], (int) k);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return exp(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
doublereal LTI_Log_MoleFracs::getMixTransProp(std::vector<LTPspecies*> LTPptrs)
|
|
||||||
{
|
|
||||||
size_t nsp = m_thermo->nSpecies();
|
|
||||||
doublereal temp = m_thermo->temperature();
|
|
||||||
vector_fp molefracs(nsp);
|
|
||||||
m_thermo->getMoleFractions(&molefracs[0]);
|
|
||||||
doublereal value = 0;
|
|
||||||
|
|
||||||
//if weightings are specified, use those
|
|
||||||
for (size_t k = 0; k < nsp; k++) {
|
|
||||||
molefracs[k] = molefracs[k]*LTPptrs[k]->getMixWeight();
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i = 0; i < nsp; i++) {
|
|
||||||
value += log(LTPptrs[i]->getSpeciesTransProp()) * molefracs[i];
|
|
||||||
for (size_t j = 0; j < nsp; j++) {
|
|
||||||
for (size_t k = 0; k < m_Hij.size(); k++) {
|
|
||||||
value += molefracs[i]*molefracs[j]*(*m_Hij[k])(i,j)/temp*pow(molefracs[i], (int) k);
|
|
||||||
}
|
|
||||||
for (size_t k = 0; k < m_Sij.size(); k++) {
|
|
||||||
value -= molefracs[i]*molefracs[j]*(*m_Sij[k])(i,j)*pow(molefracs[i], (int) k);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return exp(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void LTI_Pairwise_Interaction::setParameters(LiquidTransportParams& trParam)
|
|
||||||
{
|
|
||||||
size_t nsp = m_thermo->nSpecies();
|
|
||||||
m_diagonals.resize(nsp, 0);
|
|
||||||
|
|
||||||
for (size_t k = 0; k < nsp; k++) {
|
|
||||||
LiquidTransportData& ltd = trParam.LTData[k];
|
|
||||||
if (ltd.speciesDiffusivity) {
|
|
||||||
m_diagonals[k] = ltd.speciesDiffusivity;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
doublereal LTI_Pairwise_Interaction::getMixTransProp(doublereal* speciesValues, doublereal* speciesWeight)
|
|
||||||
{
|
|
||||||
throw LTPmodelError("Calling LTI_Pairwise_Interaction::getMixTransProp does not make sense.");
|
|
||||||
}
|
|
||||||
|
|
||||||
doublereal LTI_Pairwise_Interaction::getMixTransProp(std::vector<LTPspecies*> LTPptrs)
|
|
||||||
{
|
|
||||||
throw LTPmodelError("Calling LTI_Pairwise_Interaction::getMixTransProp does not make sense.");
|
|
||||||
}
|
|
||||||
|
|
||||||
void LTI_Pairwise_Interaction::getMatrixTransProp(DenseMatrix& mat, doublereal* speciesValues)
|
|
||||||
{
|
|
||||||
size_t nsp = m_thermo->nSpecies();
|
|
||||||
doublereal temp = m_thermo->temperature();
|
|
||||||
vector_fp molefracs(nsp);
|
|
||||||
m_thermo->getMoleFractions(&molefracs[0]);
|
|
||||||
|
|
||||||
mat.resize(nsp, nsp, 0.0);
|
|
||||||
for (size_t i = 0; i < nsp; i++) {
|
|
||||||
for (size_t j = 0; j < i; j++) {
|
|
||||||
mat(i,j) = mat(j,i) = exp(m_Eij(i,j) / temp) / m_Dij(i,j);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i = 0; i < nsp; i++) {
|
|
||||||
if (mat(i,i) == 0.0 && m_diagonals[i]) {
|
|
||||||
mat(i,i) = 1.0 / m_diagonals[i]->getSpeciesTransProp();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void LTI_StefanMaxwell_PPN::setParameters(LiquidTransportParams& trParam)
|
|
||||||
{
|
|
||||||
size_t nsp = m_thermo->nSpecies();
|
|
||||||
m_ionCondMix = 0;
|
|
||||||
m_ionCondMixModel = trParam.ionConductivity;
|
|
||||||
m_ionCondSpecies.resize(nsp,0);
|
|
||||||
m_mobRatMix.resize(nsp,nsp,0.0);
|
|
||||||
m_mobRatMixModel.resize(nsp*nsp);
|
|
||||||
m_mobRatSpecies.resize(nsp*nsp);
|
|
||||||
m_selfDiffMix.resize(nsp,0.0);
|
|
||||||
m_selfDiffMixModel.resize(nsp);
|
|
||||||
m_selfDiffSpecies.resize(nsp);
|
|
||||||
|
|
||||||
for (size_t k = 0; k < nsp*nsp; k++) {
|
|
||||||
m_mobRatMixModel[k] = trParam.mobilityRatio[k];
|
|
||||||
m_mobRatSpecies[k].resize(nsp,0);
|
|
||||||
}
|
|
||||||
for (size_t k = 0; k < nsp; k++) {
|
|
||||||
m_selfDiffMixModel[k] = trParam.selfDiffusion[k];
|
|
||||||
m_selfDiffSpecies[k].resize(nsp,0);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t k = 0; k < nsp; k++) {
|
|
||||||
LiquidTransportData& ltd = trParam.LTData[k];
|
|
||||||
m_ionCondSpecies[k] = ltd.ionConductivity;
|
|
||||||
for (size_t j = 0; j < nsp*nsp; j++) {
|
|
||||||
m_mobRatSpecies[j][k] = ltd.mobilityRatio[j];
|
|
||||||
}
|
|
||||||
for (size_t j = 0; j < nsp; j++) {
|
|
||||||
m_selfDiffSpecies[j][k] = ltd.selfDiffusion[j];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
doublereal LTI_StefanMaxwell_PPN::getMixTransProp(doublereal* speciesValues, doublereal* speciesWeight)
|
|
||||||
{
|
|
||||||
throw LTPmodelError("Calling LTI_StefanMaxwell_PPN::getMixTransProp does not make sense.");
|
|
||||||
}
|
|
||||||
|
|
||||||
doublereal LTI_StefanMaxwell_PPN::getMixTransProp(std::vector<LTPspecies*> LTPptrs)
|
|
||||||
{
|
|
||||||
throw LTPmodelError("Calling LTI_StefanMaxwell_PPN::getMixTransProp does not make sense.");
|
|
||||||
}
|
|
||||||
|
|
||||||
void LTI_StefanMaxwell_PPN::getMatrixTransProp(DenseMatrix& mat, doublereal* speciesValues)
|
|
||||||
{
|
|
||||||
IonsFromNeutralVPSSTP* ions_thermo = dynamic_cast<IonsFromNeutralVPSSTP*>(m_thermo);
|
|
||||||
size_t nsp = m_thermo->nSpecies();
|
|
||||||
if (nsp != 3) {
|
|
||||||
throw CanteraError("LTI_StefanMaxwell_PPN::getMatrixTransProp","Function may only be called with a 3-ion system");
|
|
||||||
}
|
|
||||||
doublereal temp = m_thermo->temperature();
|
|
||||||
vector_fp molefracs(nsp);
|
|
||||||
m_thermo->getMoleFractions(&molefracs[0]);
|
|
||||||
vector_fp neut_molefracs;
|
|
||||||
ions_thermo->getNeutralMolecMoleFractions(neut_molefracs);
|
|
||||||
vector<size_t> cation;
|
|
||||||
vector<size_t> anion;
|
|
||||||
ions_thermo->getCationList(cation);
|
|
||||||
ions_thermo->getAnionList(anion);
|
|
||||||
|
|
||||||
// Reaction Coeffs and Charges
|
|
||||||
vector_fp viS(6);
|
|
||||||
vector_fp charges(3);
|
|
||||||
std::vector<size_t> neutMolIndex(3);
|
|
||||||
ions_thermo->getDissociationCoeffs(viS,charges,neutMolIndex);
|
|
||||||
|
|
||||||
if (anion.size() != 1) {
|
|
||||||
throw CanteraError("LTI_StefanMaxwell_PPN::getMatrixTransProp","Must have one anion only for StefanMaxwell_PPN");
|
|
||||||
}
|
|
||||||
if (cation.size() != 2) {
|
|
||||||
throw CanteraError("LTI_StefanMaxwell_PPN::getMatrixTransProp","Must have two cations of equal charge for StefanMaxwell_PPN");
|
|
||||||
}
|
|
||||||
if (charges[cation[0]] != charges[cation[1]]) {
|
|
||||||
throw CanteraError("LTI_StefanMaxwell_PPN::getMatrixTransProp","Cations must be of equal charge for StefanMaxwell_PPN");
|
|
||||||
}
|
|
||||||
|
|
||||||
m_ionCondMix = m_ionCondMixModel->getMixTransProp(m_ionCondSpecies);
|
|
||||||
MargulesVPSSTP* marg_thermo = dynamic_cast<MargulesVPSSTP*>(ions_thermo->getNeutralMoleculePhase().get());
|
|
||||||
doublereal vol = m_thermo->molarVolume();
|
|
||||||
|
|
||||||
size_t k = 0;
|
|
||||||
for (size_t j = 0; j < nsp; j++) {
|
|
||||||
for (size_t i = 0; i < nsp; i++) {
|
|
||||||
if (m_mobRatMixModel[k]) {
|
|
||||||
m_mobRatMix(i,j) = m_mobRatMixModel[k]->getMixTransProp(m_mobRatSpecies[k]);
|
|
||||||
if (m_mobRatMix(i,j) > 0.0) {
|
|
||||||
m_mobRatMix(j,i) = 1.0/m_mobRatMix(i,j);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
k++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (k = 0; k < nsp; k++) {
|
|
||||||
m_selfDiffMix[k] = m_selfDiffMixModel[k]->getMixTransProp(m_selfDiffSpecies[k]);
|
|
||||||
}
|
|
||||||
|
|
||||||
double vP = max(viS[cation[0]],viS[cation[1]]);
|
|
||||||
double vM = viS[anion[0]];
|
|
||||||
double zP = charges[cation[0]];
|
|
||||||
double zM = charges[anion[0]];
|
|
||||||
vector_fp dlnActCoeffdlnN_diag(neut_molefracs.size(),0.0);
|
|
||||||
marg_thermo->getdlnActCoeffdlnN_diag(&dlnActCoeffdlnN_diag[0]);
|
|
||||||
|
|
||||||
double xA = neut_molefracs[neutMolIndex[cation[0]]];
|
|
||||||
double xB = neut_molefracs[neutMolIndex[cation[1]]];
|
|
||||||
double eps = (1-m_mobRatMix(cation[1],cation[0]))/(xA+xB*m_mobRatMix(cation[1],cation[0]));
|
|
||||||
double inv_vP_vM_MutualDiff = (xA*(1-xB+dlnActCoeffdlnN_diag[neutMolIndex[cation[1]]])/m_selfDiffMix[cation[1]]+xB*(1-xA+dlnActCoeffdlnN_diag[neutMolIndex[cation[0]]])/m_selfDiffMix[cation[0]]);
|
|
||||||
|
|
||||||
mat.resize(nsp, nsp, 0.0);
|
|
||||||
mat(cation[0],cation[1]) = mat(cation[1],cation[0]) = (1+vM/vP)*(1+eps*xB)*(1-eps*xA)*inv_vP_vM_MutualDiff-zP*zP*Faraday*Faraday/GasConstant/temp/m_ionCondMix/vol;
|
|
||||||
mat(cation[0],anion[0]) = mat(anion[0],cation[0]) = (1+vP/vM)*(-eps*xB*(1-eps*xA)*inv_vP_vM_MutualDiff)-zP*zM*Faraday*Faraday/GasConstant/temp/m_ionCondMix/vol;
|
|
||||||
mat(cation[1],anion[0]) = mat(anion[0],cation[1]) = (1+vP/vM)*(eps*xA*(1+eps*xB)*inv_vP_vM_MutualDiff)-zP*zM*Faraday*Faraday/GasConstant/temp/m_ionCondMix/vol;
|
|
||||||
}
|
|
||||||
|
|
||||||
doublereal LTI_StokesEinstein::getMixTransProp(doublereal* speciesValues, doublereal* speciesWeight)
|
|
||||||
{
|
|
||||||
throw LTPmodelError("Calling LTI_StokesEinstein::getMixTransProp does not make sense.");
|
|
||||||
}
|
|
||||||
|
|
||||||
doublereal LTI_StokesEinstein::getMixTransProp(std::vector<LTPspecies*> LTPptrs)
|
|
||||||
{
|
|
||||||
throw LTPmodelError("Calling LTI_StokesEinstein::getMixTransProp does not make sense.");
|
|
||||||
}
|
|
||||||
|
|
||||||
void LTI_StokesEinstein::setParameters(LiquidTransportParams& trParam)
|
|
||||||
{
|
|
||||||
size_t nsp = m_thermo->nSpecies();
|
|
||||||
m_viscosity.resize(nsp, 0);
|
|
||||||
m_hydroRadius.resize(nsp, 0);
|
|
||||||
for (size_t k = 0; k < nsp; k++) {
|
|
||||||
LiquidTransportData& ltd = trParam.LTData[k];
|
|
||||||
m_viscosity[k] = ltd.viscosity;
|
|
||||||
m_hydroRadius[k] = ltd.hydroRadius;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void LTI_StokesEinstein::getMatrixTransProp(DenseMatrix& mat, doublereal* speciesValues)
|
|
||||||
{
|
|
||||||
size_t nsp = m_thermo->nSpecies();
|
|
||||||
doublereal temp = m_thermo->temperature();
|
|
||||||
vector_fp viscSpec(nsp);
|
|
||||||
vector_fp radiusSpec(nsp);
|
|
||||||
|
|
||||||
for (size_t k = 0; k < nsp; k++) {
|
|
||||||
viscSpec[k] = m_viscosity[k]->getSpeciesTransProp();
|
|
||||||
radiusSpec[k] = m_hydroRadius[k]->getSpeciesTransProp();
|
|
||||||
}
|
|
||||||
|
|
||||||
mat.resize(nsp,nsp, 0.0);
|
|
||||||
for (size_t i = 0; i < nsp; i++) {
|
|
||||||
for (size_t j = 0; j < nsp; j++) {
|
|
||||||
mat(i,j) = (6.0 * Pi * radiusSpec[i] * viscSpec[j]) / GasConstant / temp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
doublereal LTI_MoleFracs_ExpT::getMixTransProp(doublereal* speciesValues, doublereal* speciesWeight)
|
|
||||||
{
|
|
||||||
size_t nsp = m_thermo->nSpecies();
|
|
||||||
doublereal temp = m_thermo->temperature();
|
|
||||||
vector_fp molefracs(nsp);
|
|
||||||
m_thermo->getMoleFractions(&molefracs[0]);
|
|
||||||
doublereal value = 0;
|
|
||||||
|
|
||||||
//if weightings are specified, use those
|
|
||||||
if (speciesWeight) {
|
|
||||||
for (size_t k = 0; k < nsp; k++) {
|
|
||||||
molefracs[k] = molefracs[k]*speciesWeight[k];
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
throw CanteraError("LTI_MoleFracs_ExpT::getMixTransProp","You should be specifying the speciesWeight");
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i = 0; i < nsp; i++) {
|
|
||||||
value += speciesValues[i] * molefracs[i];
|
|
||||||
for (size_t j = 0; j < nsp; j++) {
|
|
||||||
for (size_t k = 0; k < m_Aij.size(); k++) {
|
|
||||||
value += molefracs[i]*molefracs[j]*(*m_Aij[k])(i,j)*pow(molefracs[i], (int) k)*exp((*m_Bij[k])(i,j)*temp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
doublereal LTI_MoleFracs_ExpT::getMixTransProp(std::vector<LTPspecies*> LTPptrs)
|
|
||||||
{
|
|
||||||
size_t nsp = m_thermo->nSpecies();
|
|
||||||
doublereal temp = m_thermo->temperature();
|
|
||||||
vector_fp molefracs(nsp);
|
|
||||||
m_thermo->getMoleFractions(&molefracs[0]);
|
|
||||||
doublereal value = 0;
|
|
||||||
|
|
||||||
for (size_t k = 0; k < nsp; k++) {
|
|
||||||
molefracs[k] = molefracs[k]*LTPptrs[k]->getMixWeight();
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i = 0; i < nsp; i++) {
|
|
||||||
value += LTPptrs[i]->getSpeciesTransProp() * molefracs[i];
|
|
||||||
for (size_t j = 0; j < nsp; j++) {
|
|
||||||
for (size_t k = 0; k < m_Aij.size(); k++) {
|
|
||||||
value += molefracs[i]*molefracs[j]*(*m_Aij[k])(i,j)*pow(molefracs[i], (int) k)*exp((*m_Bij[k])(i,j)*temp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
} //namespace Cantera
|
|
||||||
|
|
@ -1,974 +0,0 @@
|
||||||
/**
|
|
||||||
* @file LiquidTransport.cpp
|
|
||||||
* Mixture-averaged transport properties for ideal gas mixtures.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// This file is part of Cantera. See License.txt in the top-level directory or
|
|
||||||
// at http://www.cantera.org/license.txt for license and copyright information.
|
|
||||||
|
|
||||||
#include "cantera/transport/LiquidTransport.h"
|
|
||||||
#include "cantera/base/stringUtils.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
namespace Cantera
|
|
||||||
{
|
|
||||||
LiquidTransport::LiquidTransport(thermo_t* thermo, int ndim) :
|
|
||||||
Transport(thermo, ndim),
|
|
||||||
m_nsp2(0),
|
|
||||||
m_viscMixModel(0),
|
|
||||||
m_ionCondMixModel(0),
|
|
||||||
m_lambdaMixModel(0),
|
|
||||||
m_diffMixModel(0),
|
|
||||||
m_radiusMixModel(0),
|
|
||||||
m_iStateMF(-1),
|
|
||||||
concTot_(0.0),
|
|
||||||
concTot_tran_(0.0),
|
|
||||||
dens_(0.0),
|
|
||||||
m_temp(-1.0),
|
|
||||||
m_press(-1.0),
|
|
||||||
m_lambda(-1.0),
|
|
||||||
m_viscmix(-1.0),
|
|
||||||
m_ionCondmix(-1.0),
|
|
||||||
m_visc_mix_ok(false),
|
|
||||||
m_visc_temp_ok(false),
|
|
||||||
m_visc_conc_ok(false),
|
|
||||||
m_ionCond_mix_ok(false),
|
|
||||||
m_ionCond_temp_ok(false),
|
|
||||||
m_ionCond_conc_ok(false),
|
|
||||||
m_mobRat_mix_ok(false),
|
|
||||||
m_mobRat_temp_ok(false),
|
|
||||||
m_mobRat_conc_ok(false),
|
|
||||||
m_selfDiff_mix_ok(false),
|
|
||||||
m_selfDiff_temp_ok(false),
|
|
||||||
m_selfDiff_conc_ok(false),
|
|
||||||
m_radi_mix_ok(false),
|
|
||||||
m_radi_temp_ok(false),
|
|
||||||
m_radi_conc_ok(false),
|
|
||||||
m_diff_mix_ok(false),
|
|
||||||
m_diff_temp_ok(false),
|
|
||||||
m_lambda_temp_ok(false),
|
|
||||||
m_lambda_mix_ok(false),
|
|
||||||
m_mode(-1000),
|
|
||||||
m_debug(false)
|
|
||||||
{
|
|
||||||
warn_deprecated("Class LiquidTransport", "To be removed after Cantera 2.4");
|
|
||||||
}
|
|
||||||
|
|
||||||
LiquidTransport::~LiquidTransport()
|
|
||||||
{
|
|
||||||
//These are constructed in TransportFactory::newLTP
|
|
||||||
for (size_t k = 0; k < m_nsp; k++) {
|
|
||||||
delete m_viscTempDep_Ns[k];
|
|
||||||
delete m_ionCondTempDep_Ns[k];
|
|
||||||
for (size_t j = 0; j < m_nsp; j++) {
|
|
||||||
delete m_selfDiffTempDep_Ns[j][k];
|
|
||||||
}
|
|
||||||
for (size_t j=0; j < m_nsp2; j++) {
|
|
||||||
delete m_mobRatTempDep_Ns[j][k];
|
|
||||||
}
|
|
||||||
delete m_lambdaTempDep_Ns[k];
|
|
||||||
delete m_radiusTempDep_Ns[k];
|
|
||||||
delete m_diffTempDep_Ns[k];
|
|
||||||
//These are constructed in TransportFactory::newLTI
|
|
||||||
delete m_selfDiffMixModel[k];
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t k = 0; k < m_nsp2; k++) {
|
|
||||||
delete m_mobRatMixModel[k];
|
|
||||||
}
|
|
||||||
|
|
||||||
delete m_viscMixModel;
|
|
||||||
delete m_ionCondMixModel;
|
|
||||||
delete m_lambdaMixModel;
|
|
||||||
delete m_diffMixModel;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool LiquidTransport::initLiquid(LiquidTransportParams& tr)
|
|
||||||
{
|
|
||||||
// Transfer quantitities from the database to the Transport object
|
|
||||||
m_thermo = tr.thermo;
|
|
||||||
m_velocityBasis = tr.velocityBasis_;
|
|
||||||
m_nsp = m_thermo->nSpecies();
|
|
||||||
m_nsp2 = m_nsp*m_nsp;
|
|
||||||
|
|
||||||
// Resize the local storage according to the number of species
|
|
||||||
m_mw.resize(m_nsp, 0.0);
|
|
||||||
m_viscSpecies.resize(m_nsp, 0.0);
|
|
||||||
m_viscTempDep_Ns.resize(m_nsp, 0);
|
|
||||||
m_ionCondSpecies.resize(m_nsp, 0.0);
|
|
||||||
m_ionCondTempDep_Ns.resize(m_nsp, 0);
|
|
||||||
m_mobRatTempDep_Ns.resize(m_nsp2);
|
|
||||||
m_mobRatMixModel.resize(m_nsp2);
|
|
||||||
m_mobRatSpecies.resize(m_nsp2, m_nsp, 0.0);
|
|
||||||
m_mobRatMix.resize(m_nsp2,0.0);
|
|
||||||
m_selfDiffTempDep_Ns.resize(m_nsp);
|
|
||||||
m_selfDiffMixModel.resize(m_nsp);
|
|
||||||
m_selfDiffSpecies.resize(m_nsp, m_nsp, 0.0);
|
|
||||||
m_selfDiffMix.resize(m_nsp,0.0);
|
|
||||||
for (size_t k = 0; k < m_nsp; k++) {
|
|
||||||
m_selfDiffTempDep_Ns[k].resize(m_nsp, 0);
|
|
||||||
}
|
|
||||||
for (size_t k = 0; k < m_nsp2; k++) {
|
|
||||||
m_mobRatTempDep_Ns[k].resize(m_nsp, 0);
|
|
||||||
}
|
|
||||||
m_lambdaSpecies.resize(m_nsp, 0.0);
|
|
||||||
m_lambdaTempDep_Ns.resize(m_nsp, 0);
|
|
||||||
m_hydrodynamic_radius.resize(m_nsp, 0.0);
|
|
||||||
m_radiusTempDep_Ns.resize(m_nsp, 0);
|
|
||||||
|
|
||||||
// Make a local copy of the molecular weights
|
|
||||||
m_mw = m_thermo->molecularWeights();
|
|
||||||
|
|
||||||
// First populate mixing rules and indices (NOTE, we transfer pointers of
|
|
||||||
// manually allocated quantities. We zero out pointers so that we only have
|
|
||||||
// one copy of the pointer)
|
|
||||||
for (size_t k = 0; k < m_nsp; k++) {
|
|
||||||
m_selfDiffMixModel[k] = tr.selfDiffusion[k];
|
|
||||||
tr.selfDiffusion[k] = 0;
|
|
||||||
}
|
|
||||||
for (size_t k = 0; k < m_nsp2; k++) {
|
|
||||||
m_mobRatMixModel[k] = tr.mobilityRatio[k];
|
|
||||||
tr.mobilityRatio[k] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//for each species, assign viscosity model and coefficients
|
|
||||||
for (size_t k = 0; k < m_nsp; k++) {
|
|
||||||
LiquidTransportData& ltd = tr.LTData[k];
|
|
||||||
m_viscTempDep_Ns[k] = ltd.viscosity;
|
|
||||||
ltd.viscosity = 0;
|
|
||||||
m_ionCondTempDep_Ns[k] = ltd.ionConductivity;
|
|
||||||
ltd.ionConductivity = 0;
|
|
||||||
for (size_t j = 0; j < m_nsp2; j++) {
|
|
||||||
m_mobRatTempDep_Ns[j][k] = ltd.mobilityRatio[j];
|
|
||||||
ltd.mobilityRatio[j] = 0;
|
|
||||||
}
|
|
||||||
for (size_t j = 0; j < m_nsp; j++) {
|
|
||||||
m_selfDiffTempDep_Ns[j][k] = ltd.selfDiffusion[j];
|
|
||||||
ltd.selfDiffusion[j] = 0;
|
|
||||||
}
|
|
||||||
m_lambdaTempDep_Ns[k] = ltd.thermalCond;
|
|
||||||
ltd.thermalCond = 0;
|
|
||||||
m_radiusTempDep_Ns[k] = ltd.hydroRadius;
|
|
||||||
ltd.hydroRadius = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the input Species Diffusivities. Note that species diffusivities are
|
|
||||||
// not what is needed. Rather the Stefan Boltzmann interaction parameters
|
|
||||||
// are needed for the current model. This section may, therefore, be
|
|
||||||
// extraneous.
|
|
||||||
m_diffTempDep_Ns.resize(m_nsp, 0);
|
|
||||||
//for each species, assign viscosity model and coefficients
|
|
||||||
for (size_t k = 0; k < m_nsp; k++) {
|
|
||||||
LiquidTransportData& ltd = tr.LTData[k];
|
|
||||||
if (ltd.speciesDiffusivity != 0) {
|
|
||||||
cout << "Warning: diffusion coefficient data for "
|
|
||||||
<< m_thermo->speciesName(k)
|
|
||||||
<< endl
|
|
||||||
<< "in the input file is not used for LiquidTransport model."
|
|
||||||
<< endl
|
|
||||||
<< "LiquidTransport model uses Stefan-Maxwell interaction "
|
|
||||||
<< endl
|
|
||||||
<< "parameters defined in the <transport> input block."
|
|
||||||
<< endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Here we get interaction parameters from LiquidTransportParams that were
|
|
||||||
// filled in TransportFactory::getLiquidInteractionsTransportData
|
|
||||||
// Interaction models are provided here for viscosity, thermal conductivity,
|
|
||||||
// species diffusivity and hydrodynamics radius (perhaps not needed in the
|
|
||||||
// present class).
|
|
||||||
m_viscMixModel = tr.viscosity;
|
|
||||||
tr.viscosity = 0;
|
|
||||||
|
|
||||||
m_ionCondMixModel = tr.ionConductivity;
|
|
||||||
tr.ionConductivity = 0;
|
|
||||||
|
|
||||||
m_lambdaMixModel = tr.thermalCond;
|
|
||||||
tr.thermalCond = 0;
|
|
||||||
|
|
||||||
m_diffMixModel = tr.speciesDiffusivity;
|
|
||||||
tr.speciesDiffusivity = 0;
|
|
||||||
if (! m_diffMixModel) {
|
|
||||||
throw CanteraError("LiquidTransport::initLiquid()",
|
|
||||||
"A speciesDiffusivity model is required in the transport block for the phase, but none was provided");
|
|
||||||
}
|
|
||||||
|
|
||||||
m_bdiff.resize(m_nsp,m_nsp, 0.0);
|
|
||||||
|
|
||||||
// Don't really need to update this here. It is updated in updateDiff_T()
|
|
||||||
m_diffMixModel->getMatrixTransProp(m_bdiff);
|
|
||||||
|
|
||||||
m_mode = tr.mode_;
|
|
||||||
m_massfracs.resize(m_nsp, 0.0);
|
|
||||||
m_massfracs_tran.resize(m_nsp, 0.0);
|
|
||||||
m_molefracs.resize(m_nsp, 0.0);
|
|
||||||
m_molefracs_tran.resize(m_nsp, 0.0);
|
|
||||||
m_concentrations.resize(m_nsp, 0.0);
|
|
||||||
m_actCoeff.resize(m_nsp, 0.0);
|
|
||||||
m_chargeSpecies.resize(m_nsp, 0.0);
|
|
||||||
for (size_t i = 0; i < m_nsp; i++) {
|
|
||||||
m_chargeSpecies[i] = m_thermo->charge(i);
|
|
||||||
}
|
|
||||||
m_volume_spec.resize(m_nsp, 0.0);
|
|
||||||
m_Grad_lnAC.resize(m_nDim * m_nsp, 0.0);
|
|
||||||
m_spwork.resize(m_nsp, 0.0);
|
|
||||||
|
|
||||||
// resize the internal gradient variables
|
|
||||||
m_Grad_X.resize(m_nDim * m_nsp, 0.0);
|
|
||||||
m_Grad_T.resize(m_nDim, 0.0);
|
|
||||||
m_Grad_V.resize(m_nDim, 0.0);
|
|
||||||
m_Grad_mu.resize(m_nDim * m_nsp, 0.0);
|
|
||||||
m_flux.resize(m_nsp, m_nDim, 0.0);
|
|
||||||
m_Vdiff.resize(m_nsp, m_nDim, 0.0);
|
|
||||||
|
|
||||||
// set all flags to false
|
|
||||||
m_visc_mix_ok = false;
|
|
||||||
m_visc_temp_ok = false;
|
|
||||||
m_visc_conc_ok = false;
|
|
||||||
m_ionCond_mix_ok = false;
|
|
||||||
m_ionCond_temp_ok = false;
|
|
||||||
m_ionCond_conc_ok = false;
|
|
||||||
m_mobRat_mix_ok = false;
|
|
||||||
m_mobRat_temp_ok = false;
|
|
||||||
m_mobRat_conc_ok = false;
|
|
||||||
m_selfDiff_mix_ok = false;
|
|
||||||
m_selfDiff_temp_ok = false;
|
|
||||||
m_selfDiff_conc_ok = false;
|
|
||||||
m_radi_temp_ok = false;
|
|
||||||
m_radi_conc_ok = false;
|
|
||||||
m_lambda_temp_ok = false;
|
|
||||||
m_lambda_mix_ok = false;
|
|
||||||
m_diff_temp_ok = false;
|
|
||||||
m_diff_mix_ok = false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
doublereal LiquidTransport::viscosity()
|
|
||||||
{
|
|
||||||
update_T();
|
|
||||||
update_C();
|
|
||||||
if (m_visc_mix_ok) {
|
|
||||||
return m_viscmix;
|
|
||||||
}
|
|
||||||
////// LiquidTranInteraction method
|
|
||||||
m_viscmix = m_viscMixModel->getMixTransProp(m_viscTempDep_Ns);
|
|
||||||
return m_viscmix;
|
|
||||||
}
|
|
||||||
|
|
||||||
void LiquidTransport::getSpeciesViscosities(doublereal* const visc)
|
|
||||||
{
|
|
||||||
update_T();
|
|
||||||
if (!m_visc_temp_ok) {
|
|
||||||
updateViscosity_T();
|
|
||||||
}
|
|
||||||
copy(m_viscSpecies.begin(), m_viscSpecies.end(), visc);
|
|
||||||
}
|
|
||||||
|
|
||||||
doublereal LiquidTransport::ionConductivity()
|
|
||||||
{
|
|
||||||
update_T();
|
|
||||||
update_C();
|
|
||||||
if (m_ionCond_mix_ok) {
|
|
||||||
return m_ionCondmix;
|
|
||||||
}
|
|
||||||
////// LiquidTranInteraction method
|
|
||||||
m_ionCondmix = m_ionCondMixModel->getMixTransProp(m_ionCondTempDep_Ns);
|
|
||||||
return m_ionCondmix;
|
|
||||||
}
|
|
||||||
|
|
||||||
void LiquidTransport::getSpeciesIonConductivity(doublereal* ionCond)
|
|
||||||
{
|
|
||||||
update_T();
|
|
||||||
if (!m_ionCond_temp_ok) {
|
|
||||||
updateIonConductivity_T();
|
|
||||||
}
|
|
||||||
copy(m_ionCondSpecies.begin(), m_ionCondSpecies.end(), ionCond);
|
|
||||||
}
|
|
||||||
|
|
||||||
void LiquidTransport::mobilityRatio(doublereal* mobRat)
|
|
||||||
{
|
|
||||||
update_T();
|
|
||||||
update_C();
|
|
||||||
// LiquidTranInteraction method
|
|
||||||
if (!m_mobRat_mix_ok) {
|
|
||||||
for (size_t k = 0; k < m_nsp2; k++) {
|
|
||||||
if (m_mobRatMixModel[k]) {
|
|
||||||
m_mobRatMix[k] = m_mobRatMixModel[k]->getMixTransProp(m_mobRatTempDep_Ns[k]);
|
|
||||||
if (m_mobRatMix[k] > 0.0) {
|
|
||||||
m_mobRatMix[k / m_nsp + m_nsp * (k % m_nsp)] = 1.0 / m_mobRatMix[k]; // Also must be off diagonal: k%(1+n)!=0, but then m_mobRatMixModel[k] shouldn't be initialized anyway
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (size_t k = 0; k < m_nsp2; k++) {
|
|
||||||
mobRat[k] = m_mobRatMix[k];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void LiquidTransport::getSpeciesMobilityRatio(doublereal** mobRat)
|
|
||||||
{
|
|
||||||
update_T();
|
|
||||||
if (!m_mobRat_temp_ok) {
|
|
||||||
updateMobilityRatio_T();
|
|
||||||
}
|
|
||||||
for (size_t k = 0; k < m_nsp2; k++) {
|
|
||||||
for (size_t j = 0; j < m_nsp; j++) {
|
|
||||||
mobRat[k][j] = m_mobRatSpecies(k,j);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void LiquidTransport::selfDiffusion(doublereal* const selfDiff)
|
|
||||||
{
|
|
||||||
update_T();
|
|
||||||
update_C();
|
|
||||||
if (!m_selfDiff_mix_ok) {
|
|
||||||
for (size_t k = 0; k < m_nsp; k++) {
|
|
||||||
m_selfDiffMix[k] = m_selfDiffMixModel[k]->getMixTransProp(m_selfDiffTempDep_Ns[k]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (size_t k = 0; k < m_nsp; k++) {
|
|
||||||
selfDiff[k] = m_selfDiffMix[k];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void LiquidTransport::getSpeciesSelfDiffusion(doublereal** selfDiff)
|
|
||||||
{
|
|
||||||
update_T();
|
|
||||||
if (!m_selfDiff_temp_ok) {
|
|
||||||
updateSelfDiffusion_T();
|
|
||||||
}
|
|
||||||
for (size_t k=0; k<m_nsp; k++) {
|
|
||||||
for (size_t j=0; j < m_nsp; j++) {
|
|
||||||
selfDiff[k][j] = m_selfDiffSpecies(k,j);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void LiquidTransport::getSpeciesHydrodynamicRadius(doublereal* const radius)
|
|
||||||
{
|
|
||||||
update_T();
|
|
||||||
if (!m_radi_temp_ok) {
|
|
||||||
updateHydrodynamicRadius_T();
|
|
||||||
}
|
|
||||||
copy(m_hydrodynamic_radius.begin(), m_hydrodynamic_radius.end(), radius);
|
|
||||||
}
|
|
||||||
|
|
||||||
doublereal LiquidTransport::thermalConductivity()
|
|
||||||
{
|
|
||||||
update_T();
|
|
||||||
update_C();
|
|
||||||
if (!m_lambda_mix_ok) {
|
|
||||||
m_lambda = m_lambdaMixModel->getMixTransProp(m_lambdaTempDep_Ns);
|
|
||||||
m_cond_mix_ok = true;
|
|
||||||
}
|
|
||||||
return m_lambda;
|
|
||||||
}
|
|
||||||
|
|
||||||
void LiquidTransport::getThermalDiffCoeffs(doublereal* const dt)
|
|
||||||
{
|
|
||||||
for (size_t k = 0; k < m_nsp; k++) {
|
|
||||||
dt[k] = 0.0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void LiquidTransport::getBinaryDiffCoeffs(size_t ld, doublereal* d)
|
|
||||||
{
|
|
||||||
if (ld != m_nsp) {
|
|
||||||
throw CanteraError("LiquidTransport::getBinaryDiffCoeffs",
|
|
||||||
"First argument does not correspond to number of species in model.\nDiff Coeff matrix may be misdimensioned");
|
|
||||||
}
|
|
||||||
update_T();
|
|
||||||
// if necessary, evaluate the binary diffusion coefficients
|
|
||||||
// from the polynomial fits
|
|
||||||
if (!m_diff_temp_ok) {
|
|
||||||
updateDiff_T();
|
|
||||||
}
|
|
||||||
for (size_t i = 0; i < m_nsp; i++) {
|
|
||||||
for (size_t j = 0; j < m_nsp; j++) {
|
|
||||||
d[ld*j + i] = 1.0 / m_bdiff(i,j);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void LiquidTransport::getMobilities(doublereal* const mobil)
|
|
||||||
{
|
|
||||||
getMixDiffCoeffs(m_spwork.data());
|
|
||||||
doublereal c1 = ElectronCharge / (Boltzmann * m_temp);
|
|
||||||
for (size_t k = 0; k < m_nsp; k++) {
|
|
||||||
mobil[k] = c1 * m_spwork[k];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void LiquidTransport::getFluidMobilities(doublereal* const mobil_f)
|
|
||||||
{
|
|
||||||
getMixDiffCoeffs(m_spwork.data());
|
|
||||||
doublereal c1 = 1.0 / (GasConstant * m_temp);
|
|
||||||
for (size_t k = 0; k < m_nsp; k++) {
|
|
||||||
mobil_f[k] = c1 * m_spwork[k];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void LiquidTransport::set_Grad_T(const doublereal* grad_T)
|
|
||||||
{
|
|
||||||
for (size_t a = 0; a < m_nDim; a++) {
|
|
||||||
m_Grad_T[a] = grad_T[a];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void LiquidTransport::set_Grad_V(const doublereal* grad_V)
|
|
||||||
{
|
|
||||||
for (size_t a = 0; a < m_nDim; a++) {
|
|
||||||
m_Grad_V[a] = grad_V[a];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void LiquidTransport::set_Grad_X(const doublereal* grad_X)
|
|
||||||
{
|
|
||||||
size_t itop = m_nDim * m_nsp;
|
|
||||||
for (size_t i = 0; i < itop; i++) {
|
|
||||||
m_Grad_X[i] = grad_X[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
doublereal LiquidTransport::getElectricConduct()
|
|
||||||
{
|
|
||||||
vector_fp gradT(m_nDim,0.0);
|
|
||||||
vector_fp gradX(m_nDim * m_nsp, 0.0);
|
|
||||||
vector_fp gradV(m_nDim, 1.0);
|
|
||||||
|
|
||||||
set_Grad_T(&gradT[0]);
|
|
||||||
set_Grad_X(&gradX[0]);
|
|
||||||
set_Grad_V(&gradV[0]);
|
|
||||||
|
|
||||||
vector_fp fluxes(m_nsp * m_nDim);
|
|
||||||
doublereal current;
|
|
||||||
getSpeciesFluxesExt(m_nDim, &fluxes[0]);
|
|
||||||
|
|
||||||
//sum over species charges, fluxes, Faraday to get current
|
|
||||||
// Since we want the scalar conductivity, we need only consider one-dim
|
|
||||||
for (size_t i = 0; i < 1; i++) {
|
|
||||||
current = 0.0;
|
|
||||||
for (size_t k = 0; k < m_nsp; k++) {
|
|
||||||
current += m_chargeSpecies[k] * Faraday * fluxes[k] / m_mw[k];
|
|
||||||
}
|
|
||||||
//divide by unit potential gradient
|
|
||||||
current /= - gradV[i];
|
|
||||||
}
|
|
||||||
return current;
|
|
||||||
}
|
|
||||||
|
|
||||||
void LiquidTransport::getElectricCurrent(int ndim,
|
|
||||||
const doublereal* grad_T,
|
|
||||||
int ldx,
|
|
||||||
const doublereal* grad_X,
|
|
||||||
int ldf,
|
|
||||||
const doublereal* grad_V,
|
|
||||||
doublereal* current)
|
|
||||||
{
|
|
||||||
set_Grad_T(grad_T);
|
|
||||||
set_Grad_X(grad_X);
|
|
||||||
set_Grad_V(grad_V);
|
|
||||||
|
|
||||||
vector_fp fluxes(m_nsp * m_nDim);
|
|
||||||
getSpeciesFluxesExt(ldf, &fluxes[0]);
|
|
||||||
|
|
||||||
//sum over species charges, fluxes, Faraday to get current
|
|
||||||
for (size_t i = 0; i < m_nDim; i++) {
|
|
||||||
current[i] = 0.0;
|
|
||||||
for (size_t k = 0; k < m_nsp; k++) {
|
|
||||||
current[i] += m_chargeSpecies[k] * Faraday * fluxes[k] / m_mw[k];
|
|
||||||
}
|
|
||||||
//divide by unit potential gradient
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void LiquidTransport::getSpeciesVdiff(size_t ndim,
|
|
||||||
const doublereal* grad_T,
|
|
||||||
int ldx, const doublereal* grad_X,
|
|
||||||
int ldf, doublereal* Vdiff)
|
|
||||||
{
|
|
||||||
set_Grad_T(grad_T);
|
|
||||||
set_Grad_X(grad_X);
|
|
||||||
getSpeciesVdiffExt(ldf, Vdiff);
|
|
||||||
}
|
|
||||||
|
|
||||||
void LiquidTransport::getSpeciesVdiffES(size_t ndim,
|
|
||||||
const doublereal* grad_T,
|
|
||||||
int ldx,
|
|
||||||
const doublereal* grad_X,
|
|
||||||
int ldf,
|
|
||||||
const doublereal* grad_V,
|
|
||||||
doublereal* Vdiff)
|
|
||||||
{
|
|
||||||
set_Grad_T(grad_T);
|
|
||||||
set_Grad_X(grad_X);
|
|
||||||
set_Grad_V(grad_V);
|
|
||||||
getSpeciesVdiffExt(ldf, Vdiff);
|
|
||||||
}
|
|
||||||
|
|
||||||
void LiquidTransport::getSpeciesFluxes(size_t ndim,
|
|
||||||
const doublereal* const grad_T,
|
|
||||||
size_t ldx, const doublereal* const grad_X,
|
|
||||||
size_t ldf, doublereal* const fluxes)
|
|
||||||
{
|
|
||||||
set_Grad_T(grad_T);
|
|
||||||
set_Grad_X(grad_X);
|
|
||||||
getSpeciesFluxesExt(ldf, fluxes);
|
|
||||||
}
|
|
||||||
|
|
||||||
void LiquidTransport::getSpeciesFluxesES(size_t ndim,
|
|
||||||
const doublereal* grad_T,
|
|
||||||
size_t ldx,
|
|
||||||
const doublereal* grad_X,
|
|
||||||
size_t ldf,
|
|
||||||
const doublereal* grad_V,
|
|
||||||
doublereal* fluxes)
|
|
||||||
{
|
|
||||||
set_Grad_T(grad_T);
|
|
||||||
set_Grad_X(grad_X);
|
|
||||||
set_Grad_V(grad_V);
|
|
||||||
getSpeciesFluxesExt(ldf, fluxes);
|
|
||||||
}
|
|
||||||
|
|
||||||
void LiquidTransport::getSpeciesVdiffExt(size_t ldf, doublereal* Vdiff)
|
|
||||||
{
|
|
||||||
stefan_maxwell_solve();
|
|
||||||
for (size_t n = 0; n < m_nDim; n++) {
|
|
||||||
for (size_t k = 0; k < m_nsp; k++) {
|
|
||||||
Vdiff[n*ldf + k] = m_Vdiff(k,n);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void LiquidTransport::getSpeciesFluxesExt(size_t ldf, doublereal* fluxes)
|
|
||||||
{
|
|
||||||
stefan_maxwell_solve();
|
|
||||||
for (size_t n = 0; n < m_nDim; n++) {
|
|
||||||
for (size_t k = 0; k < m_nsp; k++) {
|
|
||||||
fluxes[n*ldf + k] = m_flux(k,n);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void LiquidTransport::getMixDiffCoeffs(doublereal* const d)
|
|
||||||
{
|
|
||||||
stefan_maxwell_solve();
|
|
||||||
for (size_t n = 0; n < m_nDim; n++) {
|
|
||||||
for (size_t k = 0; k < m_nsp; k++) {
|
|
||||||
if (m_Grad_X[n*m_nsp + k] != 0.0) {
|
|
||||||
d[n*m_nsp + k] = - m_Vdiff(k,n) * m_molefracs[k]
|
|
||||||
/ m_Grad_X[n*m_nsp + k];
|
|
||||||
} else {
|
|
||||||
//avoid divide by zero with nonsensical response
|
|
||||||
d[n*m_nsp + k] = - 1.0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool LiquidTransport::update_T()
|
|
||||||
{
|
|
||||||
// First make a decision about whether we need to recalculate
|
|
||||||
doublereal t = m_thermo->temperature();
|
|
||||||
if (t == m_temp) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Next do a reality check on temperature value
|
|
||||||
if (t < 0.0) {
|
|
||||||
throw CanteraError("LiquidTransport::update_T()",
|
|
||||||
"negative temperature {}", t);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Compute various direct functions of temperature
|
|
||||||
m_temp = t;
|
|
||||||
|
|
||||||
// temperature has changed so temp flags are flipped
|
|
||||||
m_visc_temp_ok = false;
|
|
||||||
m_ionCond_temp_ok = false;
|
|
||||||
m_mobRat_temp_ok = false;
|
|
||||||
m_selfDiff_temp_ok = false;
|
|
||||||
m_radi_temp_ok = false;
|
|
||||||
m_diff_temp_ok = false;
|
|
||||||
m_lambda_temp_ok = false;
|
|
||||||
|
|
||||||
// temperature has changed, so polynomial temperature
|
|
||||||
// interpolations will need to be reevaluated.
|
|
||||||
m_visc_conc_ok = false;
|
|
||||||
m_ionCond_conc_ok = false;
|
|
||||||
m_mobRat_conc_ok = false;
|
|
||||||
m_selfDiff_conc_ok = false;
|
|
||||||
|
|
||||||
// Mixture stuff needs to be evaluated
|
|
||||||
m_visc_mix_ok = false;
|
|
||||||
m_ionCond_mix_ok = false;
|
|
||||||
m_mobRat_mix_ok = false;
|
|
||||||
m_selfDiff_mix_ok = false;
|
|
||||||
m_diff_mix_ok = false;
|
|
||||||
m_lambda_mix_ok = false; //(don't need it because a lower lvl flag is set
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool LiquidTransport::update_C()
|
|
||||||
{
|
|
||||||
// If the pressure has changed then the concentrations have changed.
|
|
||||||
doublereal pres = m_thermo->pressure();
|
|
||||||
bool qReturn = true;
|
|
||||||
if (pres != m_press) {
|
|
||||||
qReturn = false;
|
|
||||||
m_press = pres;
|
|
||||||
}
|
|
||||||
int iStateNew = m_thermo->stateMFNumber();
|
|
||||||
if (iStateNew != m_iStateMF) {
|
|
||||||
qReturn = false;
|
|
||||||
m_thermo->getMassFractions(m_massfracs.data());
|
|
||||||
m_thermo->getMoleFractions(m_molefracs.data());
|
|
||||||
m_thermo->getConcentrations(m_concentrations.data());
|
|
||||||
concTot_ = 0.0;
|
|
||||||
concTot_tran_ = 0.0;
|
|
||||||
for (size_t k = 0; k < m_nsp; k++) {
|
|
||||||
m_molefracs[k] = std::max(0.0, m_molefracs[k]);
|
|
||||||
m_molefracs_tran[k] = std::max(Tiny, m_molefracs[k]);
|
|
||||||
m_massfracs_tran[k] = std::max(Tiny, m_massfracs[k]);
|
|
||||||
concTot_tran_ += m_molefracs_tran[k];
|
|
||||||
concTot_ += m_concentrations[k];
|
|
||||||
}
|
|
||||||
dens_ = m_thermo->density();
|
|
||||||
meanMolecularWeight_ = m_thermo->meanMolecularWeight();
|
|
||||||
concTot_tran_ *= concTot_;
|
|
||||||
}
|
|
||||||
if (qReturn) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// signal that concentration-dependent quantities will need to be recomputed
|
|
||||||
// before use, and update the local mole fractions.
|
|
||||||
m_visc_conc_ok = false;
|
|
||||||
m_ionCond_conc_ok = false;
|
|
||||||
m_mobRat_conc_ok = false;
|
|
||||||
m_selfDiff_conc_ok = false;
|
|
||||||
|
|
||||||
// Mixture stuff needs to be evaluated
|
|
||||||
m_visc_mix_ok = false;
|
|
||||||
m_ionCond_mix_ok = false;
|
|
||||||
m_mobRat_mix_ok = false;
|
|
||||||
m_selfDiff_mix_ok = false;
|
|
||||||
m_diff_mix_ok = false;
|
|
||||||
m_lambda_mix_ok = false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void LiquidTransport::updateCond_T()
|
|
||||||
{
|
|
||||||
for (size_t k = 0; k < m_nsp; k++) {
|
|
||||||
m_lambdaSpecies[k] = m_lambdaTempDep_Ns[k]->getSpeciesTransProp();
|
|
||||||
}
|
|
||||||
m_lambda_temp_ok = true;
|
|
||||||
m_lambda_mix_ok = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void LiquidTransport::updateDiff_T()
|
|
||||||
{
|
|
||||||
m_diffMixModel->getMatrixTransProp(m_bdiff);
|
|
||||||
m_diff_temp_ok = true;
|
|
||||||
m_diff_mix_ok = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void LiquidTransport::updateViscosities_C()
|
|
||||||
{
|
|
||||||
m_visc_conc_ok = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void LiquidTransport::updateViscosity_T()
|
|
||||||
{
|
|
||||||
for (size_t k = 0; k < m_nsp; k++) {
|
|
||||||
m_viscSpecies[k] = m_viscTempDep_Ns[k]->getSpeciesTransProp();
|
|
||||||
}
|
|
||||||
m_visc_temp_ok = true;
|
|
||||||
m_visc_mix_ok = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void LiquidTransport::updateIonConductivity_C()
|
|
||||||
{
|
|
||||||
m_ionCond_conc_ok = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void LiquidTransport::updateIonConductivity_T()
|
|
||||||
{
|
|
||||||
for (size_t k = 0; k < m_nsp; k++) {
|
|
||||||
m_ionCondSpecies[k] = m_ionCondTempDep_Ns[k]->getSpeciesTransProp();
|
|
||||||
}
|
|
||||||
m_ionCond_temp_ok = true;
|
|
||||||
m_ionCond_mix_ok = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void LiquidTransport::updateMobilityRatio_C()
|
|
||||||
{
|
|
||||||
m_mobRat_conc_ok = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void LiquidTransport::updateMobilityRatio_T()
|
|
||||||
{
|
|
||||||
for (size_t k = 0; k < m_nsp2; k++) {
|
|
||||||
for (size_t j = 0; j < m_nsp; j++) {
|
|
||||||
m_mobRatSpecies(k,j) = m_mobRatTempDep_Ns[k][j]->getSpeciesTransProp();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m_mobRat_temp_ok = true;
|
|
||||||
m_mobRat_mix_ok = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void LiquidTransport::updateSelfDiffusion_C()
|
|
||||||
{
|
|
||||||
m_selfDiff_conc_ok = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void LiquidTransport::updateSelfDiffusion_T()
|
|
||||||
{
|
|
||||||
for (size_t k = 0; k < m_nsp2; k++) {
|
|
||||||
for (size_t j = 0; j < m_nsp; j++) {
|
|
||||||
m_selfDiffSpecies(k,j) = m_selfDiffTempDep_Ns[k][j]->getSpeciesTransProp();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m_selfDiff_temp_ok = true;
|
|
||||||
m_selfDiff_mix_ok = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void LiquidTransport::updateHydrodynamicRadius_C()
|
|
||||||
{
|
|
||||||
m_radi_conc_ok = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void LiquidTransport::updateHydrodynamicRadius_T()
|
|
||||||
{
|
|
||||||
for (size_t k = 0; k < m_nsp; k++) {
|
|
||||||
m_hydrodynamic_radius[k] = m_radiusTempDep_Ns[k]->getSpeciesTransProp();
|
|
||||||
}
|
|
||||||
m_radi_temp_ok = true;
|
|
||||||
m_radi_mix_ok = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void LiquidTransport::update_Grad_lnAC()
|
|
||||||
{
|
|
||||||
for (size_t k = 0; k < m_nDim; k++) {
|
|
||||||
double grad_T = m_Grad_T[k];
|
|
||||||
size_t start = m_nsp*k;
|
|
||||||
m_thermo->getdlnActCoeffds(grad_T, &m_Grad_X[start], &m_Grad_lnAC[start]);
|
|
||||||
for (size_t i = 0; i < m_nsp; i++) {
|
|
||||||
if (m_molefracs[i] < 1.e-15) {
|
|
||||||
m_Grad_lnAC[start+i] = 0;
|
|
||||||
} else {
|
|
||||||
m_Grad_lnAC[start+i] += m_Grad_X[start+i]/m_molefracs[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void LiquidTransport::stefan_maxwell_solve()
|
|
||||||
{
|
|
||||||
m_B.resize(m_nsp, m_nDim, 0.0);
|
|
||||||
m_A.resize(m_nsp, m_nsp, 0.0);
|
|
||||||
|
|
||||||
//! grab a local copy of the molecular weights
|
|
||||||
const vector_fp& M = m_thermo->molecularWeights();
|
|
||||||
//! grad a local copy of the ion molar volume (inverse total ion concentration)
|
|
||||||
const doublereal vol = m_thermo->molarVolume();
|
|
||||||
|
|
||||||
//! Update the temperature, concentrations and diffusion coefficients in the
|
|
||||||
//! mixture.
|
|
||||||
update_T();
|
|
||||||
update_C();
|
|
||||||
if (!m_diff_temp_ok) {
|
|
||||||
updateDiff_T();
|
|
||||||
}
|
|
||||||
|
|
||||||
double T = m_thermo->temperature();
|
|
||||||
update_Grad_lnAC();
|
|
||||||
m_thermo->getActivityCoefficients(m_actCoeff.data());
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Calculate the electrochemical potential gradient. This is the
|
|
||||||
* driving force for relative diffusional transport.
|
|
||||||
*
|
|
||||||
* Here we calculate
|
|
||||||
*
|
|
||||||
* X_i * (grad (mu_i) + S_i grad T - M_i / dens * grad P
|
|
||||||
*
|
|
||||||
* This is Eqn. 13-1 p. 318 Newman. The original equation is from
|
|
||||||
* Hershfeld, Curtis, and Bird.
|
|
||||||
*
|
|
||||||
* S_i is the partial molar entropy of species i. This term will cancel
|
|
||||||
* out a lot of the grad T terms in grad (mu_i), therefore simplifying
|
|
||||||
* the expression.
|
|
||||||
*
|
|
||||||
* Ok I think there may be many ways to do this. One way is to do it via basis
|
|
||||||
* functions, at the nodes, as a function of the variables in the problem.
|
|
||||||
*
|
|
||||||
* For calculation of molality based thermo systems, we current get
|
|
||||||
* the molar based values. This may change.
|
|
||||||
*
|
|
||||||
* Note, we have broken the symmetry of the matrix here, due to
|
|
||||||
* considerations involving species concentrations going to zero.
|
|
||||||
*/
|
|
||||||
for (size_t a = 0; a < m_nDim; a++) {
|
|
||||||
for (size_t i = 0; i < m_nsp; i++) {
|
|
||||||
m_Grad_mu[a*m_nsp + i] =
|
|
||||||
m_chargeSpecies[i] * Faraday * m_Grad_V[a]
|
|
||||||
+ GasConstant * T * m_Grad_lnAC[a*m_nsp+i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_thermo->activityConvention() == cAC_CONVENTION_MOLALITY) {
|
|
||||||
int iSolvent = 0;
|
|
||||||
double mwSolvent = m_thermo->molecularWeight(iSolvent);
|
|
||||||
double mnaught = mwSolvent/ 1000.;
|
|
||||||
double lnmnaught = log(mnaught);
|
|
||||||
for (size_t a = 0; a < m_nDim; a++) {
|
|
||||||
for (size_t i = 1; i < m_nsp; i++) {
|
|
||||||
m_Grad_mu[a*m_nsp + i] -=
|
|
||||||
m_molefracs[i] * GasConstant * m_Grad_T[a] * lnmnaught;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Just for Note, m_A(i,j) refers to the ith row and jth column.
|
|
||||||
// They are still fortran ordered, so that i varies fastest.
|
|
||||||
double condSum1;
|
|
||||||
const doublereal invRT = 1.0 / (GasConstant * T);
|
|
||||||
switch (m_nDim) {
|
|
||||||
case 1: // 1-D approximation
|
|
||||||
m_B(0,0) = 0.0;
|
|
||||||
// equation for the reference velocity
|
|
||||||
for (size_t j = 0; j < m_nsp; j++) {
|
|
||||||
if (m_velocityBasis == VB_MOLEAVG) {
|
|
||||||
m_A(0,j) = m_molefracs_tran[j];
|
|
||||||
} else if (m_velocityBasis == VB_MASSAVG) {
|
|
||||||
m_A(0,j) = m_massfracs_tran[j];
|
|
||||||
} else if ((m_velocityBasis >= 0)
|
|
||||||
&& (m_velocityBasis < static_cast<int>(m_nsp))) {
|
|
||||||
// use species number m_velocityBasis as reference velocity
|
|
||||||
if (m_velocityBasis == static_cast<int>(j)) {
|
|
||||||
m_A(0,j) = 1.0;
|
|
||||||
} else {
|
|
||||||
m_A(0,j) = 0.0;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
throw CanteraError("LiquidTransport::stefan_maxwell_solve",
|
|
||||||
"Unknown reference velocity provided.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (size_t i = 1; i < m_nsp; i++) {
|
|
||||||
m_B(i,0) = m_Grad_mu[i] * invRT;
|
|
||||||
m_A(i,i) = 0.0;
|
|
||||||
for (size_t j = 0; j < m_nsp; j++) {
|
|
||||||
if (j != i) {
|
|
||||||
double tmp = m_molefracs_tran[j] * m_bdiff(i,j);
|
|
||||||
m_A(i,i) -= tmp;
|
|
||||||
m_A(i,j) = tmp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// invert and solve the system Ax = b. Answer is in m_B
|
|
||||||
solve(m_A, m_B);
|
|
||||||
condSum1 = 0;
|
|
||||||
for (size_t i = 0; i < m_nsp; i++) {
|
|
||||||
condSum1 -= Faraday*m_chargeSpecies[i]*m_B(i,0)*m_molefracs_tran[i]/vol;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 2: // 2-D approximation
|
|
||||||
m_B(0,0) = 0.0;
|
|
||||||
m_B(0,1) = 0.0;
|
|
||||||
//equation for the reference velocity
|
|
||||||
for (size_t j = 0; j < m_nsp; j++) {
|
|
||||||
if (m_velocityBasis == VB_MOLEAVG) {
|
|
||||||
m_A(0,j) = m_molefracs_tran[j];
|
|
||||||
} else if (m_velocityBasis == VB_MASSAVG) {
|
|
||||||
m_A(0,j) = m_massfracs_tran[j];
|
|
||||||
} else if ((m_velocityBasis >= 0)
|
|
||||||
&& (m_velocityBasis < static_cast<int>(m_nsp))) {
|
|
||||||
// use species number m_velocityBasis as reference velocity
|
|
||||||
if (m_velocityBasis == static_cast<int>(j)) {
|
|
||||||
m_A(0,j) = 1.0;
|
|
||||||
} else {
|
|
||||||
m_A(0,j) = 0.0;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
throw CanteraError("LiquidTransport::stefan_maxwell_solve",
|
|
||||||
"Unknown reference velocity provided.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (size_t i = 1; i < m_nsp; i++) {
|
|
||||||
m_B(i,0) = m_Grad_mu[i] * invRT;
|
|
||||||
m_B(i,1) = m_Grad_mu[m_nsp + i] * invRT;
|
|
||||||
m_A(i,i) = 0.0;
|
|
||||||
for (size_t j = 0; j < m_nsp; j++) {
|
|
||||||
if (j != i) {
|
|
||||||
double tmp = m_molefracs_tran[j] * m_bdiff(i,j);
|
|
||||||
m_A(i,i) -= tmp;
|
|
||||||
m_A(i,j) = tmp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// invert and solve the system Ax = b. Answer is in m_B
|
|
||||||
solve(m_A, m_B);
|
|
||||||
break;
|
|
||||||
case 3: // 3-D approximation
|
|
||||||
m_B(0,0) = 0.0;
|
|
||||||
m_B(0,1) = 0.0;
|
|
||||||
m_B(0,2) = 0.0;
|
|
||||||
// equation for the reference velocity
|
|
||||||
for (size_t j = 0; j < m_nsp; j++) {
|
|
||||||
if (m_velocityBasis == VB_MOLEAVG) {
|
|
||||||
m_A(0,j) = m_molefracs_tran[j];
|
|
||||||
} else if (m_velocityBasis == VB_MASSAVG) {
|
|
||||||
m_A(0,j) = m_massfracs_tran[j];
|
|
||||||
} else if ((m_velocityBasis >= 0)
|
|
||||||
&& (m_velocityBasis < static_cast<int>(m_nsp))) {
|
|
||||||
// use species number m_velocityBasis as reference velocity
|
|
||||||
if (m_velocityBasis == static_cast<int>(j)) {
|
|
||||||
m_A(0,j) = 1.0;
|
|
||||||
} else {
|
|
||||||
m_A(0,j) = 0.0;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
throw CanteraError("LiquidTransport::stefan_maxwell_solve",
|
|
||||||
"Unknown reference velocity provided.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (size_t i = 1; i < m_nsp; i++) {
|
|
||||||
m_B(i,0) = m_Grad_mu[i] * invRT;
|
|
||||||
m_B(i,1) = m_Grad_mu[m_nsp + i] * invRT;
|
|
||||||
m_B(i,2) = m_Grad_mu[2*m_nsp + i] * invRT;
|
|
||||||
m_A(i,i) = 0.0;
|
|
||||||
for (size_t j = 0; j < m_nsp; j++) {
|
|
||||||
if (j != i) {
|
|
||||||
double tmp = m_molefracs_tran[j] * m_bdiff(i,j);
|
|
||||||
m_A(i,i) -= tmp;
|
|
||||||
m_A(i,j) = tmp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// invert and solve the system Ax = b. Answer is in m_B
|
|
||||||
solve(m_A, m_B);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw CanteraError("routine", "not done");
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t a = 0; a < m_nDim; a++) {
|
|
||||||
for (size_t j = 0; j < m_nsp; j++) {
|
|
||||||
m_Vdiff(j,a) = m_B(j,a);
|
|
||||||
m_flux(j,a) = concTot_ * M[j] * m_molefracs_tran[j] * m_B(j,a);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,98 +0,0 @@
|
||||||
/**
|
|
||||||
* @file LiquidTransportData.cpp
|
|
||||||
* Source code for liquid transport property evaluations.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// This file is part of Cantera. See License.txt in the top-level directory or
|
|
||||||
// at http://www.cantera.org/license.txt for license and copyright information.
|
|
||||||
|
|
||||||
#include "cantera/transport/LiquidTransportData.h"
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
namespace Cantera
|
|
||||||
{
|
|
||||||
LiquidTransportData::LiquidTransportData() :
|
|
||||||
speciesName("-"),
|
|
||||||
hydroRadius(0),
|
|
||||||
viscosity(0),
|
|
||||||
ionConductivity(0),
|
|
||||||
thermalCond(0),
|
|
||||||
electCond(0),
|
|
||||||
speciesDiffusivity(0)
|
|
||||||
{
|
|
||||||
warn_deprecated("class LiquidTransportData", "To be removed after Cantera 2.4");
|
|
||||||
}
|
|
||||||
|
|
||||||
LiquidTransportData::LiquidTransportData(const LiquidTransportData& right) :
|
|
||||||
speciesName("-"),
|
|
||||||
hydroRadius(0),
|
|
||||||
viscosity(0),
|
|
||||||
ionConductivity(0),
|
|
||||||
thermalCond(0),
|
|
||||||
electCond(0),
|
|
||||||
speciesDiffusivity(0)
|
|
||||||
{
|
|
||||||
*this = right; //use assignment operator to do other work
|
|
||||||
}
|
|
||||||
|
|
||||||
LiquidTransportData& LiquidTransportData::operator=(const LiquidTransportData& right)
|
|
||||||
{
|
|
||||||
if (&right != this) {
|
|
||||||
// These are all shallow pointer copies - yes, yes, yes horrible crime.
|
|
||||||
speciesName = right.speciesName;
|
|
||||||
if (right.hydroRadius) {
|
|
||||||
hydroRadius = (right.hydroRadius)->duplMyselfAsLTPspecies();
|
|
||||||
}
|
|
||||||
if (right.viscosity) {
|
|
||||||
viscosity = (right.viscosity)->duplMyselfAsLTPspecies();
|
|
||||||
}
|
|
||||||
if (right.ionConductivity) {
|
|
||||||
ionConductivity = (right.ionConductivity)->duplMyselfAsLTPspecies();
|
|
||||||
}
|
|
||||||
|
|
||||||
mobilityRatio = right.mobilityRatio;
|
|
||||||
for (size_t k = 0; k < mobilityRatio.size(); k++) {
|
|
||||||
if (right.mobilityRatio[k]) {
|
|
||||||
mobilityRatio[k] = (right.mobilityRatio[k])->duplMyselfAsLTPspecies();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
selfDiffusion = right.selfDiffusion;
|
|
||||||
for (size_t k = 0; k < selfDiffusion.size(); k++) {
|
|
||||||
if (right.selfDiffusion[k]) {
|
|
||||||
selfDiffusion[k] = (right.selfDiffusion[k])->duplMyselfAsLTPspecies();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (right.thermalCond) {
|
|
||||||
thermalCond = (right.thermalCond)->duplMyselfAsLTPspecies();
|
|
||||||
}
|
|
||||||
if (right.electCond) {
|
|
||||||
electCond = (right.electCond)->duplMyselfAsLTPspecies();
|
|
||||||
}
|
|
||||||
if (right.speciesDiffusivity) {
|
|
||||||
speciesDiffusivity = (right.speciesDiffusivity)->duplMyselfAsLTPspecies();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
LiquidTransportData::~LiquidTransportData()
|
|
||||||
{
|
|
||||||
delete hydroRadius;
|
|
||||||
delete viscosity;
|
|
||||||
delete ionConductivity;
|
|
||||||
|
|
||||||
for (size_t k = 0; k < mobilityRatio.size(); k++) {
|
|
||||||
delete mobilityRatio[k];
|
|
||||||
}
|
|
||||||
for (size_t k = 0; k < selfDiffusion.size(); k++) {
|
|
||||||
delete selfDiffusion[k];
|
|
||||||
}
|
|
||||||
|
|
||||||
delete thermalCond;
|
|
||||||
delete electCond;
|
|
||||||
delete speciesDiffusivity;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,40 +0,0 @@
|
||||||
/**
|
|
||||||
* @file LiquidTransportParams.cpp
|
|
||||||
* Source code for liquid mixture transport property evaluations.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// This file is part of Cantera. See License.txt in the top-level directory or
|
|
||||||
// at http://www.cantera.org/license.txt for license and copyright information.
|
|
||||||
|
|
||||||
#include "cantera/transport/LiquidTransportParams.h"
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
namespace Cantera
|
|
||||||
{
|
|
||||||
|
|
||||||
LiquidTransportParams::LiquidTransportParams() :
|
|
||||||
viscosity(0),
|
|
||||||
ionConductivity(0),
|
|
||||||
thermalCond(0),
|
|
||||||
speciesDiffusivity(0),
|
|
||||||
electCond(0),
|
|
||||||
hydroRadius(0),
|
|
||||||
model_viscosity(LTI_MODEL_NOTSET),
|
|
||||||
model_speciesDiffusivity(LTI_MODEL_NOTSET),
|
|
||||||
model_hydroradius(LTI_MODEL_NOTSET),
|
|
||||||
compositionDepTypeDefault_(LTI_MODEL_NOTSET)
|
|
||||||
{
|
|
||||||
warn_deprecated("Class LiquidTransportParams", "To be removed after Cantera 2.4");
|
|
||||||
}
|
|
||||||
|
|
||||||
LiquidTransportParams::~LiquidTransportParams()
|
|
||||||
{
|
|
||||||
delete viscosity;
|
|
||||||
delete ionConductivity;
|
|
||||||
delete thermalCond;
|
|
||||||
delete speciesDiffusivity;
|
|
||||||
delete electCond;
|
|
||||||
delete hydroRadius;
|
|
||||||
}
|
|
||||||
|
|
||||||
} //namespace Cantera
|
|
||||||
|
|
@ -1,520 +0,0 @@
|
||||||
/**
|
|
||||||
* @file SimpleTransport.cpp
|
|
||||||
* Simple mostly constant transport properties
|
|
||||||
*/
|
|
||||||
|
|
||||||
// This file is part of Cantera. See License.txt in the top-level directory or
|
|
||||||
// at http://www.cantera.org/license.txt for license and copyright information.
|
|
||||||
|
|
||||||
#include "cantera/transport/SimpleTransport.h"
|
|
||||||
#include "cantera/base/stringUtils.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
namespace Cantera
|
|
||||||
{
|
|
||||||
SimpleTransport::SimpleTransport(thermo_t* thermo, int ndim) :
|
|
||||||
Transport(thermo, ndim),
|
|
||||||
compositionDepType_(LTI_MODEL_SOLVENT),
|
|
||||||
useHydroRadius_(false),
|
|
||||||
doMigration_(0),
|
|
||||||
m_iStateMF(-1),
|
|
||||||
concTot_(0.0),
|
|
||||||
meanMolecularWeight_(-1.0),
|
|
||||||
dens_(-1.0),
|
|
||||||
m_temp(-1.0),
|
|
||||||
m_press(-1.0),
|
|
||||||
m_lambda(-1.0),
|
|
||||||
m_viscmix(-1.0),
|
|
||||||
m_visc_mix_ok(false),
|
|
||||||
m_visc_temp_ok(false),
|
|
||||||
m_diff_mix_ok(false),
|
|
||||||
m_diff_temp_ok(false),
|
|
||||||
m_cond_temp_ok(false),
|
|
||||||
m_cond_mix_ok(false),
|
|
||||||
m_nDim(1)
|
|
||||||
{
|
|
||||||
warn_deprecated("Class SimpleTransport", "To be removed after Cantera 2.4");
|
|
||||||
}
|
|
||||||
|
|
||||||
SimpleTransport::~SimpleTransport()
|
|
||||||
{
|
|
||||||
for (size_t k = 0; k < m_coeffVisc_Ns.size() ; k++) {
|
|
||||||
delete m_coeffVisc_Ns[k];
|
|
||||||
}
|
|
||||||
for (size_t k = 0; k < m_coeffLambda_Ns.size(); k++) {
|
|
||||||
delete m_coeffLambda_Ns[k];
|
|
||||||
}
|
|
||||||
for (size_t k = 0; k < m_coeffDiff_Ns.size(); k++) {
|
|
||||||
delete m_coeffDiff_Ns[k];
|
|
||||||
}
|
|
||||||
for (size_t k = 0; k < m_coeffHydroRadius_Ns.size(); k++) {
|
|
||||||
delete m_coeffHydroRadius_Ns[k];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SimpleTransport::initLiquid(LiquidTransportParams& tr)
|
|
||||||
{
|
|
||||||
// constant substance attributes
|
|
||||||
m_thermo = tr.thermo;
|
|
||||||
m_nsp = m_thermo->nSpecies();
|
|
||||||
|
|
||||||
// Read the transport block in the phase XML Node
|
|
||||||
// It's not an error if this block doesn't exist. Just use the defaults
|
|
||||||
XML_Node& phaseNode = m_thermo->xml();
|
|
||||||
if (phaseNode.hasChild("transport")) {
|
|
||||||
XML_Node& transportNode = phaseNode.child("transport");
|
|
||||||
string transportModel = transportNode.attrib("model");
|
|
||||||
if (transportModel == "Simple") {
|
|
||||||
compositionDepType_ = tr.compositionDepTypeDefault_;
|
|
||||||
} else {
|
|
||||||
throw CanteraError("SimpleTransport::initLiquid()",
|
|
||||||
"transport model isn't the correct type: " + transportModel);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// make a local copy of the molecular weights
|
|
||||||
m_mw = m_thermo->molecularWeights();
|
|
||||||
|
|
||||||
// Get the input Viscosities
|
|
||||||
m_viscSpecies.resize(m_nsp);
|
|
||||||
m_coeffVisc_Ns.clear();
|
|
||||||
m_coeffVisc_Ns.resize(m_nsp);
|
|
||||||
for (size_t k = 0; k < m_nsp; k++) {
|
|
||||||
LiquidTransportData& ltd = tr.LTData[k];
|
|
||||||
m_coeffVisc_Ns[k] = ltd.viscosity;
|
|
||||||
ltd.viscosity = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the input thermal conductivities
|
|
||||||
m_condSpecies.resize(m_nsp);
|
|
||||||
m_coeffLambda_Ns.clear();
|
|
||||||
m_coeffLambda_Ns.resize(m_nsp);
|
|
||||||
for (size_t k = 0; k < m_nsp; k++) {
|
|
||||||
LiquidTransportData& ltd = tr.LTData[k];
|
|
||||||
m_coeffLambda_Ns[k] = ltd.thermalCond;
|
|
||||||
ltd.thermalCond = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the input species diffusivities
|
|
||||||
useHydroRadius_ = false;
|
|
||||||
m_diffSpecies.resize(m_nsp);
|
|
||||||
m_coeffDiff_Ns.clear();
|
|
||||||
m_coeffDiff_Ns.resize(m_nsp);
|
|
||||||
for (size_t k = 0; k < m_nsp; k++) {
|
|
||||||
string spName = m_thermo->speciesName(k);
|
|
||||||
LiquidTransportData& ltd = tr.LTData[k];
|
|
||||||
m_coeffDiff_Ns[k] = ltd.speciesDiffusivity;
|
|
||||||
ltd.speciesDiffusivity = 0;
|
|
||||||
if (!m_coeffDiff_Ns[k]) {
|
|
||||||
if (ltd.hydroRadius) {
|
|
||||||
m_coeffHydroRadius_Ns[k] = (ltd.hydroRadius)->duplMyselfAsLTPspecies();
|
|
||||||
}
|
|
||||||
if (!m_coeffHydroRadius_Ns[k]) {
|
|
||||||
throw CanteraError("SimpleTransport::initLiquid",
|
|
||||||
"Neither diffusivity nor hydroradius is set for species " + spName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m_molefracs.resize(m_nsp);
|
|
||||||
m_concentrations.resize(m_nsp);
|
|
||||||
m_chargeSpecies.resize(m_nsp);
|
|
||||||
for (size_t k = 0; k < m_nsp; k++) {
|
|
||||||
m_chargeSpecies[k] = m_thermo->charge(k);
|
|
||||||
}
|
|
||||||
m_spwork.resize(m_nsp);
|
|
||||||
|
|
||||||
// resize the internal gradient variables
|
|
||||||
m_Grad_X.resize(m_nDim * m_nsp, 0.0);
|
|
||||||
m_Grad_T.resize(m_nDim, 0.0);
|
|
||||||
m_Grad_P.resize(m_nDim, 0.0);
|
|
||||||
m_Grad_V.resize(m_nDim, 0.0);
|
|
||||||
|
|
||||||
// set all flags to false
|
|
||||||
m_visc_mix_ok = false;
|
|
||||||
m_visc_temp_ok = false;
|
|
||||||
m_cond_temp_ok = false;
|
|
||||||
m_cond_mix_ok = false;
|
|
||||||
m_diff_temp_ok = false;
|
|
||||||
m_diff_mix_ok = false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
doublereal SimpleTransport::viscosity()
|
|
||||||
{
|
|
||||||
update_T();
|
|
||||||
update_C();
|
|
||||||
|
|
||||||
if (m_visc_mix_ok) {
|
|
||||||
return m_viscmix;
|
|
||||||
}
|
|
||||||
|
|
||||||
// update m_viscSpecies[] if necessary
|
|
||||||
if (!m_visc_temp_ok) {
|
|
||||||
updateViscosity_T();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (compositionDepType_ == LTI_MODEL_SOLVENT) {
|
|
||||||
m_viscmix = m_viscSpecies[0];
|
|
||||||
} else if (compositionDepType_ == LTI_MODEL_MOLEFRACS) {
|
|
||||||
m_viscmix = 0.0;
|
|
||||||
for (size_t k = 0; k < m_nsp; k++) {
|
|
||||||
m_viscmix += m_viscSpecies[k] * m_molefracs[k];
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
throw CanteraError("SimpleTransport::viscosity()",
|
|
||||||
"Unknowns compositionDepType");
|
|
||||||
}
|
|
||||||
m_visc_mix_ok = true;
|
|
||||||
return m_viscmix;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SimpleTransport::getSpeciesViscosities(doublereal* const visc)
|
|
||||||
{
|
|
||||||
update_T();
|
|
||||||
if (!m_visc_temp_ok) {
|
|
||||||
updateViscosity_T();
|
|
||||||
}
|
|
||||||
copy(m_viscSpecies.begin(), m_viscSpecies.end(), visc);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SimpleTransport::getBinaryDiffCoeffs(size_t ld, doublereal* d)
|
|
||||||
{
|
|
||||||
update_T();
|
|
||||||
|
|
||||||
// if necessary, evaluate the species diffusion coefficients
|
|
||||||
// from the polynomial fits
|
|
||||||
if (!m_diff_temp_ok) {
|
|
||||||
updateDiff_T();
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i = 0; i < m_nsp; i++) {
|
|
||||||
for (size_t j = 0; j < m_nsp; j++) {
|
|
||||||
d[i*m_nsp+j] = 0.5 * (m_diffSpecies[i] + m_diffSpecies[j]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SimpleTransport::getMobilities(doublereal* const mobil)
|
|
||||||
{
|
|
||||||
getMixDiffCoeffs(m_spwork.data());
|
|
||||||
doublereal c1 = ElectronCharge / (Boltzmann * m_temp);
|
|
||||||
for (size_t k = 0; k < m_nsp; k++) {
|
|
||||||
mobil[k] = c1 * m_spwork[k];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SimpleTransport::getFluidMobilities(doublereal* const mobil_f)
|
|
||||||
{
|
|
||||||
getMixDiffCoeffs(m_spwork.data());
|
|
||||||
doublereal c1 = 1.0 / (GasConstant * m_temp);
|
|
||||||
for (size_t k = 0; k < m_nsp; k++) {
|
|
||||||
mobil_f[k] = c1 * m_spwork[k];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SimpleTransport::set_Grad_V(const doublereal* const grad_V)
|
|
||||||
{
|
|
||||||
doMigration_ = false;
|
|
||||||
for (size_t a = 0; a < m_nDim; a++) {
|
|
||||||
m_Grad_V[a] = grad_V[a];
|
|
||||||
if (fabs(grad_V[a]) > 1.0E-13) {
|
|
||||||
doMigration_ = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SimpleTransport::set_Grad_T(const doublereal* const grad_T)
|
|
||||||
{
|
|
||||||
for (size_t a = 0; a < m_nDim; a++) {
|
|
||||||
m_Grad_T[a] = grad_T[a];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SimpleTransport::set_Grad_X(const doublereal* const grad_X)
|
|
||||||
{
|
|
||||||
size_t itop = m_nDim * m_nsp;
|
|
||||||
for (size_t i = 0; i < itop; i++) {
|
|
||||||
m_Grad_X[i] = grad_X[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
doublereal SimpleTransport::thermalConductivity()
|
|
||||||
{
|
|
||||||
update_T();
|
|
||||||
update_C();
|
|
||||||
if (!m_cond_temp_ok) {
|
|
||||||
updateCond_T();
|
|
||||||
}
|
|
||||||
if (!m_cond_mix_ok) {
|
|
||||||
if (compositionDepType_ == LTI_MODEL_SOLVENT) {
|
|
||||||
m_lambda = m_condSpecies[0];
|
|
||||||
} else if (compositionDepType_ == LTI_MODEL_MOLEFRACS) {
|
|
||||||
m_lambda = 0.0;
|
|
||||||
for (size_t k = 0; k < m_nsp; k++) {
|
|
||||||
m_lambda += m_condSpecies[k] * m_molefracs[k];
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
throw CanteraError("SimpleTransport::thermalConductivity()",
|
|
||||||
"Unknown compositionDepType");
|
|
||||||
}
|
|
||||||
m_cond_mix_ok = true;
|
|
||||||
}
|
|
||||||
return m_lambda;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SimpleTransport::getThermalDiffCoeffs(doublereal* const dt)
|
|
||||||
{
|
|
||||||
for (size_t k = 0; k < m_nsp; k++) {
|
|
||||||
dt[k] = 0.0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SimpleTransport::getSpeciesVdiff(size_t ndim,
|
|
||||||
const doublereal* grad_T,
|
|
||||||
int ldx,
|
|
||||||
const doublereal* grad_X,
|
|
||||||
int ldf,
|
|
||||||
doublereal* Vdiff)
|
|
||||||
{
|
|
||||||
set_Grad_T(grad_T);
|
|
||||||
set_Grad_X(grad_X);
|
|
||||||
const doublereal* y = m_thermo->massFractions();
|
|
||||||
const doublereal rho = m_thermo->density();
|
|
||||||
getSpeciesFluxesExt(m_nsp, Vdiff);
|
|
||||||
for (size_t n = 0; n < m_nDim; n++) {
|
|
||||||
for (size_t k = 0; k < m_nsp; k++) {
|
|
||||||
if (y[k] > 1.0E-200) {
|
|
||||||
Vdiff[n * m_nsp + k] *= 1.0 / (rho * y[k]);
|
|
||||||
} else {
|
|
||||||
Vdiff[n * m_nsp + k] = 0.0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SimpleTransport::getSpeciesVdiffES(size_t ndim, const doublereal* grad_T,
|
|
||||||
int ldx, const doublereal* grad_X,
|
|
||||||
int ldf, const doublereal* grad_Phi,
|
|
||||||
doublereal* Vdiff)
|
|
||||||
{
|
|
||||||
set_Grad_T(grad_T);
|
|
||||||
set_Grad_X(grad_X);
|
|
||||||
set_Grad_V(grad_Phi);
|
|
||||||
const doublereal* y = m_thermo->massFractions();
|
|
||||||
const doublereal rho = m_thermo->density();
|
|
||||||
getSpeciesFluxesExt(m_nsp, Vdiff);
|
|
||||||
for (size_t n = 0; n < m_nDim; n++) {
|
|
||||||
for (size_t k = 0; k < m_nsp; k++) {
|
|
||||||
if (y[k] > 1.0E-200) {
|
|
||||||
Vdiff[n * m_nsp + k] *= 1.0 / (rho * y[k]);
|
|
||||||
} else {
|
|
||||||
Vdiff[n * m_nsp + k] = 0.0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SimpleTransport::getSpeciesFluxes(size_t ndim, const doublereal* const grad_T,
|
|
||||||
size_t ldx, const doublereal* const grad_X,
|
|
||||||
size_t ldf, doublereal* const fluxes)
|
|
||||||
{
|
|
||||||
set_Grad_T(grad_T);
|
|
||||||
set_Grad_X(grad_X);
|
|
||||||
getSpeciesFluxesExt(ldf, fluxes);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SimpleTransport::getSpeciesFluxesExt(size_t ldf, doublereal* fluxes)
|
|
||||||
{
|
|
||||||
AssertThrow(ldf >= m_nsp ,"SimpleTransport::getSpeciesFluxesExt: Stride must be greater than m_nsp");
|
|
||||||
update_T();
|
|
||||||
update_C();
|
|
||||||
|
|
||||||
getMixDiffCoeffs(m_spwork.data());
|
|
||||||
|
|
||||||
const vector_fp& mw = m_thermo->molecularWeights();
|
|
||||||
const doublereal* y = m_thermo->massFractions();
|
|
||||||
doublereal concTotal = m_thermo->molarDensity();
|
|
||||||
|
|
||||||
// Unroll wrt ndim
|
|
||||||
if (doMigration_) {
|
|
||||||
double FRT = ElectronCharge / (Boltzmann * m_temp);
|
|
||||||
for (size_t n = 0; n < m_nDim; n++) {
|
|
||||||
rhoVc[n] = 0.0;
|
|
||||||
for (size_t k = 0; k < m_nsp; k++) {
|
|
||||||
fluxes[n*ldf + k] = - concTotal * mw[k] * m_spwork[k] *
|
|
||||||
(m_Grad_X[n*m_nsp + k] + FRT * m_molefracs[k] * m_chargeSpecies[k] * m_Grad_V[n]);
|
|
||||||
rhoVc[n] += fluxes[n*ldf + k];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (size_t n = 0; n < m_nDim; n++) {
|
|
||||||
rhoVc[n] = 0.0;
|
|
||||||
for (size_t k = 0; k < m_nsp; k++) {
|
|
||||||
fluxes[n*ldf + k] = - concTotal * mw[k] * m_spwork[k] * m_Grad_X[n*m_nsp + k];
|
|
||||||
rhoVc[n] += fluxes[n*ldf + k];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_velocityBasis == VB_MASSAVG) {
|
|
||||||
for (size_t n = 0; n < m_nDim; n++) {
|
|
||||||
rhoVc[n] = 0.0;
|
|
||||||
for (size_t k = 0; k < m_nsp; k++) {
|
|
||||||
rhoVc[n] += fluxes[n*ldf + k];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (size_t n = 0; n < m_nDim; n++) {
|
|
||||||
for (size_t k = 0; k < m_nsp; k++) {
|
|
||||||
fluxes[n*ldf + k] -= y[k] * rhoVc[n];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (m_velocityBasis == VB_MOLEAVG) {
|
|
||||||
for (size_t n = 0; n < m_nDim; n++) {
|
|
||||||
rhoVc[n] = 0.0;
|
|
||||||
for (size_t k = 0; k < m_nsp; k++) {
|
|
||||||
rhoVc[n] += fluxes[n*ldf + k] / mw[k];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (size_t n = 0; n < m_nDim; n++) {
|
|
||||||
for (size_t k = 0; k < m_nsp; k++) {
|
|
||||||
fluxes[n*ldf + k] -= m_molefracs[k] * rhoVc[n] * mw[k];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (m_velocityBasis >= 0) {
|
|
||||||
for (size_t n = 0; n < m_nDim; n++) {
|
|
||||||
rhoVc[n] = - fluxes[n*ldf + m_velocityBasis] / mw[m_velocityBasis];
|
|
||||||
for (size_t k = 0; k < m_nsp; k++) {
|
|
||||||
rhoVc[n] += fluxes[n*ldf + k] / mw[k];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (size_t n = 0; n < m_nDim; n++) {
|
|
||||||
for (size_t k = 0; k < m_nsp; k++) {
|
|
||||||
fluxes[n*ldf + k] -= m_molefracs[k] * rhoVc[n] * mw[k];
|
|
||||||
}
|
|
||||||
fluxes[n*ldf + m_velocityBasis] = 0.0;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
throw CanteraError("SimpleTransport::getSpeciesFluxesExt()",
|
|
||||||
"unknown velocity basis");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SimpleTransport::getMixDiffCoeffs(doublereal* const d)
|
|
||||||
{
|
|
||||||
update_T();
|
|
||||||
update_C();
|
|
||||||
// update the binary diffusion coefficients if necessary
|
|
||||||
if (!m_diff_temp_ok) {
|
|
||||||
updateDiff_T();
|
|
||||||
}
|
|
||||||
for (size_t k = 0; k < m_nsp; k++) {
|
|
||||||
d[k] = m_diffSpecies[k];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SimpleTransport::update_C()
|
|
||||||
{
|
|
||||||
// If the pressure has changed then the concentrations have changed.
|
|
||||||
doublereal pres = m_thermo->pressure();
|
|
||||||
bool qReturn = true;
|
|
||||||
if (pres != m_press) {
|
|
||||||
qReturn = false;
|
|
||||||
m_press = pres;
|
|
||||||
}
|
|
||||||
int iStateNew = m_thermo->stateMFNumber();
|
|
||||||
if (iStateNew != m_iStateMF) {
|
|
||||||
qReturn = false;
|
|
||||||
m_thermo->getMoleFractions(m_molefracs.data());
|
|
||||||
m_thermo->getConcentrations(m_concentrations.data());
|
|
||||||
concTot_ = 0.0;
|
|
||||||
for (size_t k = 0; k < m_nsp; k++) {
|
|
||||||
m_molefracs[k] = std::max(0.0, m_molefracs[k]);
|
|
||||||
concTot_ += m_concentrations[k];
|
|
||||||
}
|
|
||||||
dens_ = m_thermo->density();
|
|
||||||
meanMolecularWeight_ = m_thermo->meanMolecularWeight();
|
|
||||||
}
|
|
||||||
if (qReturn) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mixture stuff needs to be evaluated
|
|
||||||
m_visc_mix_ok = false;
|
|
||||||
m_diff_mix_ok = false;
|
|
||||||
m_cond_mix_ok = false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SimpleTransport::updateCond_T()
|
|
||||||
{
|
|
||||||
if (compositionDepType_ == LTI_MODEL_SOLVENT) {
|
|
||||||
m_condSpecies[0] = m_coeffLambda_Ns[0]->getSpeciesTransProp();
|
|
||||||
} else {
|
|
||||||
for (size_t k = 0; k < m_nsp; k++) {
|
|
||||||
m_condSpecies[k] = m_coeffLambda_Ns[k]->getSpeciesTransProp();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m_cond_temp_ok = true;
|
|
||||||
m_cond_mix_ok = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SimpleTransport::updateDiff_T()
|
|
||||||
{
|
|
||||||
if (useHydroRadius_) {
|
|
||||||
double visc = viscosity();
|
|
||||||
double RT = GasConstant * m_temp;
|
|
||||||
for (size_t k = 0; k < m_nsp; k++) {
|
|
||||||
double rad = m_coeffHydroRadius_Ns[k]->getSpeciesTransProp();
|
|
||||||
m_diffSpecies[k] = RT / (6.0 * Pi * visc * rad);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (size_t k = 0; k < m_nsp; k++) {
|
|
||||||
m_diffSpecies[k] = m_coeffDiff_Ns[k]->getSpeciesTransProp();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m_diff_temp_ok = true;
|
|
||||||
m_diff_mix_ok = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SimpleTransport::updateViscosity_T()
|
|
||||||
{
|
|
||||||
if (compositionDepType_ == LTI_MODEL_SOLVENT) {
|
|
||||||
m_viscSpecies[0] = m_coeffVisc_Ns[0]->getSpeciesTransProp();
|
|
||||||
} else {
|
|
||||||
for (size_t k = 0; k < m_nsp; k++) {
|
|
||||||
m_viscSpecies[k] = m_coeffVisc_Ns[k]->getSpeciesTransProp();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m_visc_temp_ok = true;
|
|
||||||
m_visc_mix_ok = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SimpleTransport::update_T()
|
|
||||||
{
|
|
||||||
doublereal t = m_thermo->temperature();
|
|
||||||
if (t == m_temp) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (t < 0.0) {
|
|
||||||
throw CanteraError("SimpleTransport::update_T",
|
|
||||||
"negative temperature {}", t);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Compute various functions of temperature
|
|
||||||
m_temp = t;
|
|
||||||
|
|
||||||
// temperature has changed, so polynomial temperature interpolations will
|
|
||||||
// need to be reevaluated. Set all of these flags to false
|
|
||||||
m_visc_mix_ok = false;
|
|
||||||
m_visc_temp_ok = false;
|
|
||||||
m_cond_temp_ok = false;
|
|
||||||
m_cond_mix_ok = false;
|
|
||||||
m_diff_mix_ok = false;
|
|
||||||
m_diff_temp_ok = false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,132 +0,0 @@
|
||||||
/**
|
|
||||||
* @file SolidTransport.cpp
|
|
||||||
* Definition file for the class SolidTransport, which handles transport
|
|
||||||
* of ions within solid phases
|
|
||||||
* (see \ref tranprops and \link Cantera::SolidTransport SolidTransport \endlink).
|
|
||||||
*/
|
|
||||||
|
|
||||||
// This file is part of Cantera. See License.txt in the top-level directory or
|
|
||||||
// at http://www.cantera.org/license.txt for license and copyright information.
|
|
||||||
|
|
||||||
#include "cantera/transport/SolidTransport.h"
|
|
||||||
#include "cantera/transport/SolidTransportData.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
namespace Cantera
|
|
||||||
{
|
|
||||||
|
|
||||||
SolidTransport::SolidTransport() :
|
|
||||||
m_nmobile(0),
|
|
||||||
m_Alam(-1.0),
|
|
||||||
m_Nlam(0),
|
|
||||||
m_Elam(0)
|
|
||||||
{
|
|
||||||
warn_deprecated("Class SolidTransport", "To be removed after Cantera 2.4");
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SolidTransport::initSolid(SolidTransportData& tr)
|
|
||||||
{
|
|
||||||
m_thermo = tr.thermo;
|
|
||||||
tr.thermo = 0;
|
|
||||||
m_ionConductivity = tr.ionConductivity;
|
|
||||||
tr.ionConductivity = 0;
|
|
||||||
m_electConductivity = tr.electConductivity;
|
|
||||||
tr.electConductivity = 0;
|
|
||||||
m_thermalConductivity = tr.thermalConductivity;
|
|
||||||
tr.thermalConductivity = 0;
|
|
||||||
m_defectDiffusivity = tr.defectDiffusivity;
|
|
||||||
tr.defectDiffusivity = 0;
|
|
||||||
m_defectActivity = tr.defectActivity;
|
|
||||||
tr.defectActivity = 0;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SolidTransport::setParameters(const int n, const int k, const doublereal* const p)
|
|
||||||
{
|
|
||||||
switch (n) {
|
|
||||||
case 0:
|
|
||||||
// set the Arrhenius parameters for the diffusion coefficient
|
|
||||||
// of species k.
|
|
||||||
m_sp.push_back(k);
|
|
||||||
m_Adiff.push_back(p[0]);
|
|
||||||
m_Ndiff.push_back(p[1]);
|
|
||||||
m_Ediff.push_back(p[2]);
|
|
||||||
m_nmobile = m_sp.size();
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
// set the thermal conductivity Arrhenius parameters.
|
|
||||||
m_Alam = p[0];
|
|
||||||
m_Nlam = p[2];
|
|
||||||
m_Elam = p[2];
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
;
|
|
||||||
}
|
|
||||||
m_work.resize(m_thermo->nSpecies());
|
|
||||||
}
|
|
||||||
|
|
||||||
doublereal SolidTransport::ionConductivity()
|
|
||||||
{
|
|
||||||
// LTPspecies method
|
|
||||||
return m_ionConductivity->getSpeciesTransProp();
|
|
||||||
}
|
|
||||||
|
|
||||||
doublereal SolidTransport::electricalConductivity()
|
|
||||||
{
|
|
||||||
if (m_nmobile == 0) {
|
|
||||||
// LTPspecies method
|
|
||||||
return m_electConductivity->getSpeciesTransProp();
|
|
||||||
} else {
|
|
||||||
getMobilities(&m_work[0]);
|
|
||||||
doublereal sum = 0.0;
|
|
||||||
for (size_t k = 0; k < m_thermo->nSpecies(); k++) {
|
|
||||||
sum += m_thermo->charge(k) * m_thermo->moleFraction(k) * m_work[k];
|
|
||||||
}
|
|
||||||
return sum * m_thermo->molarDensity();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************** thermalConductivity ******************************/
|
|
||||||
|
|
||||||
doublereal SolidTransport::thermalConductivity()
|
|
||||||
{
|
|
||||||
if (m_Alam > 0.0) {
|
|
||||||
//legacy test case?
|
|
||||||
doublereal t = m_thermo->temperature();
|
|
||||||
return m_Alam * pow(t, m_Nlam) * exp(-m_Elam/t);
|
|
||||||
} else {
|
|
||||||
// LTPspecies method
|
|
||||||
return m_thermalConductivity->getSpeciesTransProp();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
doublereal SolidTransport::defectDiffusivity()
|
|
||||||
{
|
|
||||||
// LTPspecies method
|
|
||||||
return m_defectDiffusivity->getSpeciesTransProp();
|
|
||||||
}
|
|
||||||
|
|
||||||
doublereal SolidTransport::defectActivity()
|
|
||||||
{
|
|
||||||
// LTPspecies method
|
|
||||||
return m_defectActivity->getSpeciesTransProp();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SolidTransport::getMobilities(doublereal* const mobil)
|
|
||||||
{
|
|
||||||
getMixDiffCoeffs(mobil);
|
|
||||||
doublereal t = m_thermo->temperature();
|
|
||||||
doublereal c1 = ElectronCharge / (Boltzmann * t);
|
|
||||||
for (size_t k = 0; k < m_thermo->nSpecies(); k++) {
|
|
||||||
mobil[k] *= c1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SolidTransport::getMixDiffCoeffs(doublereal* const d)
|
|
||||||
{
|
|
||||||
for (size_t k = 0; k < m_thermo->nSpecies(); k++) {
|
|
||||||
d[k] = 0.0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,71 +0,0 @@
|
||||||
/**
|
|
||||||
* @file SolidTransportData.cpp
|
|
||||||
* Source code for solid transport property evaluations.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// This file is part of Cantera. See License.txt in the top-level directory or
|
|
||||||
// at http://www.cantera.org/license.txt for license and copyright information.
|
|
||||||
|
|
||||||
#include "cantera/transport/SolidTransportData.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
namespace Cantera
|
|
||||||
{
|
|
||||||
SolidTransportData::SolidTransportData() :
|
|
||||||
speciesName("-"),
|
|
||||||
ionConductivity(0),
|
|
||||||
thermalConductivity(0),
|
|
||||||
electConductivity(0),
|
|
||||||
defectDiffusivity(0),
|
|
||||||
defectActivity(0)
|
|
||||||
{
|
|
||||||
warn_deprecated("Class SolidTransportData", "To be removed after Cantera 2.4");
|
|
||||||
}
|
|
||||||
|
|
||||||
SolidTransportData::SolidTransportData(const SolidTransportData& right) :
|
|
||||||
speciesName("-"),
|
|
||||||
ionConductivity(0),
|
|
||||||
thermalConductivity(0),
|
|
||||||
electConductivity(0),
|
|
||||||
defectDiffusivity(0),
|
|
||||||
defectActivity(0)
|
|
||||||
{
|
|
||||||
*this = right; //use assignment operator to do other work
|
|
||||||
}
|
|
||||||
|
|
||||||
SolidTransportData& SolidTransportData::operator=(const SolidTransportData& right)
|
|
||||||
{
|
|
||||||
if (&right != this) {
|
|
||||||
// These are all shallow pointer copies - yes, yes, yes horrible crime.
|
|
||||||
speciesName = right.speciesName;
|
|
||||||
if (right.ionConductivity) {
|
|
||||||
ionConductivity = (right.ionConductivity)->duplMyselfAsLTPspecies();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (right.thermalConductivity) {
|
|
||||||
thermalConductivity = (right.thermalConductivity)->duplMyselfAsLTPspecies();
|
|
||||||
}
|
|
||||||
if (right.electConductivity) {
|
|
||||||
electConductivity = (right.electConductivity)->duplMyselfAsLTPspecies();
|
|
||||||
}
|
|
||||||
if (right.defectDiffusivity) {
|
|
||||||
defectDiffusivity = (right.defectDiffusivity)->duplMyselfAsLTPspecies();
|
|
||||||
}
|
|
||||||
if (right.defectActivity) {
|
|
||||||
defectActivity = (right.defectActivity)->duplMyselfAsLTPspecies();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
SolidTransportData::~SolidTransportData()
|
|
||||||
{
|
|
||||||
delete ionConductivity;
|
|
||||||
delete thermalConductivity;
|
|
||||||
delete electConductivity;
|
|
||||||
delete defectDiffusivity;
|
|
||||||
delete defectActivity;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -9,13 +9,9 @@
|
||||||
#include "cantera/transport/UnityLewisTransport.h"
|
#include "cantera/transport/UnityLewisTransport.h"
|
||||||
#include "cantera/transport/IonGasTransport.h"
|
#include "cantera/transport/IonGasTransport.h"
|
||||||
#include "cantera/transport/WaterTransport.h"
|
#include "cantera/transport/WaterTransport.h"
|
||||||
#include "cantera/transport/SolidTransport.h"
|
|
||||||
#include "cantera/transport/DustyGasTransport.h"
|
#include "cantera/transport/DustyGasTransport.h"
|
||||||
#include "cantera/transport/SimpleTransport.h"
|
|
||||||
#include "cantera/transport/LiquidTransport.h"
|
|
||||||
#include "cantera/transport/HighPressureGasTransport.h"
|
#include "cantera/transport/HighPressureGasTransport.h"
|
||||||
#include "cantera/transport/TransportFactory.h"
|
#include "cantera/transport/TransportFactory.h"
|
||||||
#include "cantera/transport/SolidTransportData.h"
|
|
||||||
#include "cantera/base/ctml.h"
|
#include "cantera/base/ctml.h"
|
||||||
#include "cantera/base/stringUtils.h"
|
#include "cantera/base/stringUtils.h"
|
||||||
#include "cantera/base/utilities.h"
|
#include "cantera/base/utilities.h"
|
||||||
|
|
@ -59,34 +55,6 @@ TransportFactory::TransportFactory()
|
||||||
reg("HighP", []() { return new HighPressureGasTransport(); });
|
reg("HighP", []() { return new HighPressureGasTransport(); });
|
||||||
m_CK_mode["CK_Mix"] = true;
|
m_CK_mode["CK_Mix"] = true;
|
||||||
m_CK_mode["CK_Multi"] = true;
|
m_CK_mode["CK_Multi"] = true;
|
||||||
|
|
||||||
m_tranPropMap["viscosity"] = TP_VISCOSITY;
|
|
||||||
m_tranPropMap["ionConductivity"] = TP_IONCONDUCTIVITY;
|
|
||||||
m_tranPropMap["mobilityRatio"] = TP_MOBILITYRATIO;
|
|
||||||
m_tranPropMap["selfDiffusion"] = TP_SELFDIFFUSION;
|
|
||||||
m_tranPropMap["thermalConductivity"] = TP_THERMALCOND;
|
|
||||||
m_tranPropMap["speciesDiffusivity"] = TP_DIFFUSIVITY;
|
|
||||||
m_tranPropMap["hydrodynamicRadius"] = TP_HYDRORADIUS;
|
|
||||||
m_tranPropMap["electricalConductivity"] = TP_ELECTCOND;
|
|
||||||
m_tranPropMap["defectDiffusivity"] = TP_DEFECTDIFF;
|
|
||||||
m_tranPropMap["defectActivity"] = TP_DEFECTCONC;
|
|
||||||
|
|
||||||
m_LTRmodelMap[""] = LTP_TD_CONSTANT;
|
|
||||||
m_LTRmodelMap["constant"] = LTP_TD_CONSTANT;
|
|
||||||
m_LTRmodelMap["arrhenius"] = LTP_TD_ARRHENIUS;
|
|
||||||
m_LTRmodelMap["coeffs"] = LTP_TD_POLY;
|
|
||||||
m_LTRmodelMap["exptemp"] = LTP_TD_EXPT;
|
|
||||||
|
|
||||||
m_LTImodelMap[""] = LTI_MODEL_NOTSET;
|
|
||||||
m_LTImodelMap["solvent"] = LTI_MODEL_SOLVENT;
|
|
||||||
m_LTImodelMap["moleFractions"] = LTI_MODEL_MOLEFRACS;
|
|
||||||
m_LTImodelMap["massFractions"] = LTI_MODEL_MASSFRACS;
|
|
||||||
m_LTImodelMap["logMoleFractions"] = LTI_MODEL_LOG_MOLEFRACS;
|
|
||||||
m_LTImodelMap["pairwiseInteraction"] = LTI_MODEL_PAIRWISE_INTERACTION;
|
|
||||||
m_LTImodelMap["stefanMaxwell_PPN"] = LTI_MODEL_STEFANMAXWELL_PPN;
|
|
||||||
m_LTImodelMap["moleFractionsExpT"] = LTI_MODEL_MOLEFRACS_EXPT;
|
|
||||||
m_LTImodelMap["none"] = LTI_MODEL_NONE;
|
|
||||||
m_LTImodelMap["multiple"] = LTI_MODEL_MULTIPLE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TransportFactory::deleteFactory()
|
void TransportFactory::deleteFactory()
|
||||||
|
|
@ -96,89 +64,6 @@ void TransportFactory::deleteFactory()
|
||||||
s_factory = 0;
|
s_factory = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
LTPspecies* TransportFactory::newLTP(const XML_Node& trNode, const std::string& name,
|
|
||||||
TransportPropertyType tp_ind, thermo_t* thermo)
|
|
||||||
{
|
|
||||||
std::string model = toLowerCopy(trNode["model"]);
|
|
||||||
LTPspecies* sp;
|
|
||||||
switch (m_LTRmodelMap[model]) {
|
|
||||||
case LTP_TD_CONSTANT:
|
|
||||||
sp = new LTPspecies_Const();
|
|
||||||
break;
|
|
||||||
case LTP_TD_ARRHENIUS:
|
|
||||||
sp = new LTPspecies_Arrhenius();
|
|
||||||
break;
|
|
||||||
case LTP_TD_POLY:
|
|
||||||
sp = new LTPspecies_Poly();
|
|
||||||
break;
|
|
||||||
case LTP_TD_EXPT:
|
|
||||||
sp = new LTPspecies_ExpT();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw CanteraError("TransportFactory::newLTP","unknown transport model: " + model);
|
|
||||||
}
|
|
||||||
sp->setName(name);
|
|
||||||
sp->setThermo(thermo);
|
|
||||||
sp->setTransportPropertyType(tp_ind);
|
|
||||||
sp->setupFromXML(trNode);
|
|
||||||
return sp;
|
|
||||||
}
|
|
||||||
|
|
||||||
LiquidTranInteraction* TransportFactory::newLTI(const XML_Node& trNode,
|
|
||||||
TransportPropertyType tp_ind,
|
|
||||||
LiquidTransportParams& trParam)
|
|
||||||
{
|
|
||||||
LiquidTranInteraction* lti = 0;
|
|
||||||
switch (m_LTImodelMap[trNode["model"]]) {
|
|
||||||
case LTI_MODEL_SOLVENT:
|
|
||||||
lti = new LTI_Solvent(tp_ind);
|
|
||||||
lti->init(trNode, trParam.thermo);
|
|
||||||
break;
|
|
||||||
case LTI_MODEL_MOLEFRACS:
|
|
||||||
lti = new LTI_MoleFracs(tp_ind);
|
|
||||||
lti->init(trNode, trParam.thermo);
|
|
||||||
break;
|
|
||||||
case LTI_MODEL_MASSFRACS:
|
|
||||||
lti = new LTI_MassFracs(tp_ind);
|
|
||||||
lti->init(trNode, trParam.thermo);
|
|
||||||
break;
|
|
||||||
case LTI_MODEL_LOG_MOLEFRACS:
|
|
||||||
lti = new LTI_Log_MoleFracs(tp_ind);
|
|
||||||
lti->init(trNode, trParam.thermo);
|
|
||||||
break;
|
|
||||||
case LTI_MODEL_PAIRWISE_INTERACTION:
|
|
||||||
lti = new LTI_Pairwise_Interaction(tp_ind);
|
|
||||||
lti->init(trNode, trParam.thermo);
|
|
||||||
lti->setParameters(trParam);
|
|
||||||
break;
|
|
||||||
case LTI_MODEL_STEFANMAXWELL_PPN:
|
|
||||||
lti = new LTI_StefanMaxwell_PPN(tp_ind);
|
|
||||||
lti->init(trNode, trParam.thermo);
|
|
||||||
lti->setParameters(trParam);
|
|
||||||
break;
|
|
||||||
case LTI_MODEL_STOKES_EINSTEIN:
|
|
||||||
lti = new LTI_StokesEinstein(tp_ind);
|
|
||||||
lti->init(trNode, trParam.thermo);
|
|
||||||
lti->setParameters(trParam);
|
|
||||||
break;
|
|
||||||
case LTI_MODEL_MOLEFRACS_EXPT:
|
|
||||||
lti = new LTI_MoleFracs_ExpT(tp_ind);
|
|
||||||
lti->init(trNode, trParam.thermo);
|
|
||||||
break;
|
|
||||||
case LTI_MODEL_NOTSET:
|
|
||||||
case LTI_MODEL_NONE:
|
|
||||||
case LTI_MODEL_MULTIPLE:
|
|
||||||
lti = new LiquidTranInteraction(tp_ind);
|
|
||||||
lti->init(trNode, trParam.thermo);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
// @TODO make sure we can throw an error here with existing datasets and tests before changing code
|
|
||||||
lti = new LiquidTranInteraction(tp_ind);
|
|
||||||
lti->init(trNode, trParam.thermo);
|
|
||||||
}
|
|
||||||
return lti;
|
|
||||||
}
|
|
||||||
|
|
||||||
Transport* TransportFactory::newTransport(const std::string& transportModel,
|
Transport* TransportFactory::newTransport(const std::string& transportModel,
|
||||||
thermo_t* phase, int log_level, int ndim)
|
thermo_t* phase, int log_level, int ndim)
|
||||||
{
|
{
|
||||||
|
|
@ -186,24 +71,12 @@ Transport* TransportFactory::newTransport(const std::string& transportModel,
|
||||||
Transport* tr = 0;
|
Transport* tr = 0;
|
||||||
phase->saveState(state);
|
phase->saveState(state);
|
||||||
|
|
||||||
if (transportModel == "Solid") {
|
if (transportModel == "DustyGas") {
|
||||||
tr = new SolidTransport;
|
|
||||||
initSolidTransport(tr, phase, log_level);
|
|
||||||
tr->setThermo(*phase);
|
|
||||||
} else if (transportModel == "DustyGas") {
|
|
||||||
tr = new DustyGasTransport;
|
tr = new DustyGasTransport;
|
||||||
Transport* gastr = new MultiTransport;
|
Transport* gastr = new MultiTransport;
|
||||||
gastr->init(phase, 0, log_level);
|
gastr->init(phase, 0, log_level);
|
||||||
DustyGasTransport* dtr = (DustyGasTransport*)tr;
|
DustyGasTransport* dtr = (DustyGasTransport*)tr;
|
||||||
dtr->initialize(phase, gastr);
|
dtr->initialize(phase, gastr);
|
||||||
} else if (transportModel == "Simple") {
|
|
||||||
tr = new SimpleTransport();
|
|
||||||
initLiquidTransport(tr, phase, log_level);
|
|
||||||
tr->setThermo(*phase);
|
|
||||||
} else if (transportModel == "Liquid") {
|
|
||||||
tr = new LiquidTransport(phase, ndim);
|
|
||||||
initLiquidTransport(tr, phase, log_level);
|
|
||||||
tr->setThermo(*phase);
|
|
||||||
} else {
|
} else {
|
||||||
tr = create(transportModel);
|
tr = create(transportModel);
|
||||||
int mode = m_CK_mode[transportModel] ? CK_Mode : 0;
|
int mode = m_CK_mode[transportModel] ? CK_Mode : 0;
|
||||||
|
|
@ -223,368 +96,6 @@ Transport* TransportFactory::newTransport(thermo_t* phase, int log_level)
|
||||||
return newTransport(transportModel, phase,log_level);
|
return newTransport(transportModel, phase,log_level);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TransportFactory::setupLiquidTransport(thermo_t* thermo, int log_level,
|
|
||||||
LiquidTransportParams& trParam)
|
|
||||||
{
|
|
||||||
const std::vector<const XML_Node*> & species_database = thermo->speciesData();
|
|
||||||
const XML_Node* phase_database = &thermo->xml();
|
|
||||||
|
|
||||||
// constant mixture attributes
|
|
||||||
trParam.thermo = thermo;
|
|
||||||
trParam.nsp_ = trParam.thermo->nSpecies();
|
|
||||||
size_t nsp = trParam.nsp_;
|
|
||||||
trParam.tmin = thermo->minTemp();
|
|
||||||
trParam.tmax = thermo->maxTemp();
|
|
||||||
trParam.log_level = log_level;
|
|
||||||
|
|
||||||
// Get the molecular weights and load them into trParam
|
|
||||||
trParam.mw = trParam.thermo->molecularWeights();
|
|
||||||
|
|
||||||
// Resize all other vectors in trParam
|
|
||||||
trParam.LTData.resize(nsp);
|
|
||||||
|
|
||||||
// Need to identify a method to obtain interaction matrices.
|
|
||||||
// This will fill LiquidTransportParams members visc_Eij, visc_Sij
|
|
||||||
trParam.thermalCond_Aij.resize(nsp,nsp);
|
|
||||||
trParam.diff_Dij.resize(nsp,nsp);
|
|
||||||
trParam.radius_Aij.resize(nsp,nsp);
|
|
||||||
|
|
||||||
XML_Node log;
|
|
||||||
// Note that getLiquidSpeciesTransportData just populates the pure species transport data.
|
|
||||||
getLiquidSpeciesTransportData(species_database, log, trParam.thermo->speciesNames(), trParam);
|
|
||||||
|
|
||||||
// getLiquidInteractionsTransportData() populates the species-species
|
|
||||||
// interaction models parameters like visc_Eij
|
|
||||||
if (phase_database->hasChild("transport")) {
|
|
||||||
XML_Node& transportNode = phase_database->child("transport");
|
|
||||||
getLiquidInteractionsTransportData(transportNode, log, trParam.thermo->speciesNames(), trParam);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void TransportFactory::setupSolidTransport(thermo_t* thermo, int log_level,
|
|
||||||
SolidTransportData& trParam)
|
|
||||||
{
|
|
||||||
const XML_Node* phase_database = &thermo->xml();
|
|
||||||
|
|
||||||
// constant mixture attributes
|
|
||||||
trParam.thermo = thermo;
|
|
||||||
trParam.nsp_ = trParam.thermo->nSpecies();
|
|
||||||
trParam.tmin = thermo->minTemp();
|
|
||||||
trParam.tmax = thermo->maxTemp();
|
|
||||||
trParam.log_level = log_level;
|
|
||||||
|
|
||||||
// Get the molecular weights and load them into trParam
|
|
||||||
trParam.mw = trParam.thermo->molecularWeights();
|
|
||||||
|
|
||||||
// getSolidTransportData() populates the phase transport models like
|
|
||||||
// electronic conductivity thermal conductivity, interstitial diffusion
|
|
||||||
if (phase_database->hasChild("transport")) {
|
|
||||||
XML_Node log;
|
|
||||||
XML_Node& transportNode = phase_database->child("transport");
|
|
||||||
getSolidTransportData(transportNode, log, thermo->name(), trParam);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void TransportFactory::initLiquidTransport(Transport* tran,
|
|
||||||
thermo_t* thermo,
|
|
||||||
int log_level)
|
|
||||||
{
|
|
||||||
LiquidTransportParams trParam;
|
|
||||||
setupLiquidTransport(thermo, log_level, trParam);
|
|
||||||
// do model-specific initialization
|
|
||||||
tran->initLiquid(trParam);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TransportFactory::initSolidTransport(Transport* tran,
|
|
||||||
thermo_t* thermo,
|
|
||||||
int log_level)
|
|
||||||
{
|
|
||||||
SolidTransportData trParam;
|
|
||||||
setupSolidTransport(thermo, log_level, trParam);
|
|
||||||
// do model-specific initialization
|
|
||||||
tran->initSolid(trParam);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TransportFactory::getLiquidSpeciesTransportData(const std::vector<const XML_Node*> &xspecies,
|
|
||||||
XML_Node& log,
|
|
||||||
const std::vector<std::string> &names,
|
|
||||||
LiquidTransportParams& trParam)
|
|
||||||
{
|
|
||||||
// Create a map of species names versus liquid transport data parameters
|
|
||||||
std::map<std::string, LiquidTransportData> datatable;
|
|
||||||
|
|
||||||
// Store the number of species in the phase
|
|
||||||
size_t nsp = trParam.nsp_;
|
|
||||||
|
|
||||||
// Store the number of off-diagonal symmetric interactions between species in the phase
|
|
||||||
size_t nBinInt = nsp*(nsp-1)/2;
|
|
||||||
|
|
||||||
// read all entries in database into 'datatable' and check for errors. Note
|
|
||||||
// that this procedure validates all entries, not only those for the species
|
|
||||||
// listed in 'names'.
|
|
||||||
for (size_t i = 0; i < nsp; i++) {
|
|
||||||
const XML_Node& sp = *xspecies[i];
|
|
||||||
string name = sp["name"];
|
|
||||||
|
|
||||||
// Species with no 'transport' child are skipped. However, if that
|
|
||||||
// species is in the list, it will throw an exception below.
|
|
||||||
if (sp.hasChild("transport")) {
|
|
||||||
XML_Node& trNode = sp.child("transport");
|
|
||||||
|
|
||||||
// Fill datatable with LiquidTransportData objects for error checking
|
|
||||||
// and then insertion into LiquidTransportData objects below.
|
|
||||||
LiquidTransportData data;
|
|
||||||
data.speciesName = name;
|
|
||||||
data.mobilityRatio.resize(nsp*nsp,0);
|
|
||||||
data.selfDiffusion.resize(nsp,0);
|
|
||||||
size_t num = trNode.nChildren();
|
|
||||||
for (size_t iChild = 0; iChild < num; iChild++) {
|
|
||||||
XML_Node& xmlChild = trNode.child(iChild);
|
|
||||||
std::string nodeName = xmlChild.name();
|
|
||||||
|
|
||||||
switch (m_tranPropMap[nodeName]) {
|
|
||||||
case TP_VISCOSITY:
|
|
||||||
data.viscosity = newLTP(xmlChild, name, m_tranPropMap[nodeName], trParam.thermo);
|
|
||||||
break;
|
|
||||||
case TP_IONCONDUCTIVITY:
|
|
||||||
data.ionConductivity = newLTP(xmlChild, name, m_tranPropMap[nodeName], trParam.thermo);
|
|
||||||
break;
|
|
||||||
case TP_MOBILITYRATIO: {
|
|
||||||
for (size_t iSpec = 0; iSpec< nBinInt; iSpec++) {
|
|
||||||
XML_Node& propSpecNode = xmlChild.child(iSpec);
|
|
||||||
std::string specName = propSpecNode.name();
|
|
||||||
size_t loc = specName.find(":");
|
|
||||||
std::string firstSpec = specName.substr(0,loc);
|
|
||||||
std::string secondSpec = specName.substr(loc+1);
|
|
||||||
size_t index = trParam.thermo->speciesIndex(firstSpec)+nsp*trParam.thermo->speciesIndex(secondSpec);
|
|
||||||
data.mobilityRatio[index] = newLTP(propSpecNode, name, m_tranPropMap[nodeName], trParam.thermo);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
break;
|
|
||||||
case TP_SELFDIFFUSION: {
|
|
||||||
for (size_t iSpec = 0; iSpec< nsp; iSpec++) {
|
|
||||||
XML_Node& propSpecNode = xmlChild.child(iSpec);
|
|
||||||
std::string specName = propSpecNode.name();
|
|
||||||
size_t index = trParam.thermo->speciesIndex(specName);
|
|
||||||
data.selfDiffusion[index] = newLTP(propSpecNode, name, m_tranPropMap[nodeName], trParam.thermo);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
break;
|
|
||||||
case TP_THERMALCOND:
|
|
||||||
data.thermalCond = newLTP(xmlChild,
|
|
||||||
name,
|
|
||||||
m_tranPropMap[nodeName],
|
|
||||||
trParam.thermo);
|
|
||||||
break;
|
|
||||||
case TP_DIFFUSIVITY:
|
|
||||||
data.speciesDiffusivity = newLTP(xmlChild,
|
|
||||||
name,
|
|
||||||
m_tranPropMap[nodeName],
|
|
||||||
trParam.thermo);
|
|
||||||
break;
|
|
||||||
case TP_HYDRORADIUS:
|
|
||||||
data.hydroRadius = newLTP(xmlChild,
|
|
||||||
name,
|
|
||||||
m_tranPropMap[nodeName],
|
|
||||||
trParam.thermo);
|
|
||||||
break;
|
|
||||||
case TP_ELECTCOND:
|
|
||||||
data.electCond = newLTP(xmlChild,
|
|
||||||
name,
|
|
||||||
m_tranPropMap[nodeName],
|
|
||||||
trParam.thermo);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw CanteraError("getLiquidSpeciesTransportData","unknown transport property: " + nodeName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
datatable[name] = data;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
trParam.LTData.clear();
|
|
||||||
for (size_t i = 0; i < trParam.nsp_; i++) {
|
|
||||||
// Check to see that we have a LiquidTransportData object for all of the
|
|
||||||
// species in the phase. If not, throw an error.
|
|
||||||
auto it = datatable.find(names[i]);
|
|
||||||
if (it == datatable.end()) {
|
|
||||||
throw TransportDBError(0,"No transport data found for species " + names[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now, transfer these objects into LTData in the correct phase index
|
|
||||||
// order by calling the default copy constructor for
|
|
||||||
// LiquidTransportData.
|
|
||||||
trParam.LTData.push_back(it->second);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Read transport property data from a file for interactions between species in
|
|
||||||
* a liquid. Given the name of a file containing transport property parameters
|
|
||||||
* and a list of species names, this method returns an instance of
|
|
||||||
* TransportParams containing the transport data for these species read from the
|
|
||||||
* file.
|
|
||||||
*/
|
|
||||||
void TransportFactory::getLiquidInteractionsTransportData(const XML_Node& transportNode,
|
|
||||||
XML_Node& log,
|
|
||||||
const std::vector<std::string> &names,
|
|
||||||
LiquidTransportParams& trParam)
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
size_t nsp = trParam.nsp_;
|
|
||||||
size_t nBinInt = nsp*(nsp-1)/2;
|
|
||||||
for (size_t iChild = 0; iChild < transportNode.nChildren(); iChild++) {
|
|
||||||
//tranTypeNode is a type of transport property like viscosity
|
|
||||||
XML_Node& tranTypeNode = transportNode.child(iChild);
|
|
||||||
std::string nodeName = tranTypeNode.name();
|
|
||||||
trParam.mobilityRatio.resize(nsp*nsp,0);
|
|
||||||
trParam.selfDiffusion.resize(nsp,0);
|
|
||||||
|
|
||||||
if (tranTypeNode.name() == "compositionDependence") {
|
|
||||||
std::string modelName = tranTypeNode.attrib("model");
|
|
||||||
auto it = m_LTImodelMap.find(modelName);
|
|
||||||
if (it == m_LTImodelMap.end()) {
|
|
||||||
throw CanteraError("TransportFactory::getLiquidInteractionsTransportData",
|
|
||||||
"Unknown compositionDependence string: " + modelName);
|
|
||||||
} else {
|
|
||||||
trParam.compositionDepTypeDefault_ = it->second;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (tranTypeNode.hasChild("compositionDependence")) {
|
|
||||||
//compDepNode contains the interaction model
|
|
||||||
XML_Node& compDepNode = tranTypeNode.child("compositionDependence");
|
|
||||||
switch (m_tranPropMap[nodeName]) {
|
|
||||||
break;
|
|
||||||
case TP_VISCOSITY:
|
|
||||||
trParam.viscosity = newLTI(compDepNode, m_tranPropMap[nodeName], trParam);
|
|
||||||
break;
|
|
||||||
case TP_IONCONDUCTIVITY:
|
|
||||||
trParam.ionConductivity = newLTI(compDepNode,
|
|
||||||
m_tranPropMap[nodeName],
|
|
||||||
trParam);
|
|
||||||
break;
|
|
||||||
case TP_MOBILITYRATIO: {
|
|
||||||
for (size_t iSpec = 0; iSpec< nBinInt; iSpec++) {
|
|
||||||
XML_Node& propSpecNode = compDepNode.child(iSpec);
|
|
||||||
string specName = propSpecNode.name();
|
|
||||||
size_t loc = specName.find(":");
|
|
||||||
string firstSpec = specName.substr(0,loc);
|
|
||||||
string secondSpec = specName.substr(loc+1);
|
|
||||||
size_t index = trParam.thermo->speciesIndex(firstSpec)+nsp*trParam.thermo->speciesIndex(secondSpec);
|
|
||||||
trParam.mobilityRatio[index] = newLTI(propSpecNode,
|
|
||||||
m_tranPropMap[nodeName],
|
|
||||||
trParam);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
break;
|
|
||||||
case TP_SELFDIFFUSION: {
|
|
||||||
for (size_t iSpec = 0; iSpec< nsp; iSpec++) {
|
|
||||||
XML_Node& propSpecNode = compDepNode.child(iSpec);
|
|
||||||
string specName = propSpecNode.name();
|
|
||||||
size_t index = trParam.thermo->speciesIndex(specName);
|
|
||||||
trParam.selfDiffusion[index] = newLTI(propSpecNode,
|
|
||||||
m_tranPropMap[nodeName],
|
|
||||||
trParam);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
break;
|
|
||||||
case TP_THERMALCOND:
|
|
||||||
trParam.thermalCond = newLTI(compDepNode,
|
|
||||||
m_tranPropMap[nodeName],
|
|
||||||
trParam);
|
|
||||||
break;
|
|
||||||
case TP_DIFFUSIVITY:
|
|
||||||
trParam.speciesDiffusivity = newLTI(compDepNode,
|
|
||||||
m_tranPropMap[nodeName],
|
|
||||||
trParam);
|
|
||||||
break;
|
|
||||||
case TP_HYDRORADIUS:
|
|
||||||
trParam.hydroRadius = newLTI(compDepNode,
|
|
||||||
m_tranPropMap[nodeName],
|
|
||||||
trParam);
|
|
||||||
break;
|
|
||||||
case TP_ELECTCOND:
|
|
||||||
trParam.electCond = newLTI(compDepNode,
|
|
||||||
m_tranPropMap[nodeName],
|
|
||||||
trParam);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw CanteraError("getLiquidInteractionsTransportData","unknown transport property: " + nodeName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* Allow a switch between mass-averaged, mole-averaged
|
|
||||||
* and solvent specified reference velocities.
|
|
||||||
* XML code within the transportProperty node
|
|
||||||
* (i.e. within <viscosity>) should read as follows
|
|
||||||
* <velocityBasis basis="mass"> <!-- mass averaged -->
|
|
||||||
* <velocityBasis basis="mole"> <!-- mole averaged -->
|
|
||||||
* <velocityBasis basis="H2O"> <!-- H2O solvent -->
|
|
||||||
*/
|
|
||||||
if (tranTypeNode.hasChild("velocityBasis")) {
|
|
||||||
std::string velocityBasis =
|
|
||||||
tranTypeNode.child("velocityBasis").attrib("basis");
|
|
||||||
if (velocityBasis == "mass") {
|
|
||||||
trParam.velocityBasis_ = VB_MASSAVG;
|
|
||||||
} else if (velocityBasis == "mole") {
|
|
||||||
trParam.velocityBasis_ = VB_MOLEAVG;
|
|
||||||
} else if (trParam.thermo->speciesIndex(velocityBasis) > 0) {
|
|
||||||
trParam.velocityBasis_ = static_cast<int>(trParam.thermo->speciesIndex(velocityBasis));
|
|
||||||
} else {
|
|
||||||
int linenum = __LINE__;
|
|
||||||
throw TransportDBError(linenum, "Unknown attribute \"" + velocityBasis + "\" for <velocityBasis> node. ");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (CanteraError& err) {
|
|
||||||
std::cout << err.what() << std::endl;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TransportFactory::getSolidTransportData(const XML_Node& transportNode,
|
|
||||||
XML_Node& log,
|
|
||||||
const std::string phaseName,
|
|
||||||
SolidTransportData& trParam)
|
|
||||||
{
|
|
||||||
for (size_t iChild = 0; iChild < transportNode.nChildren(); iChild++) {
|
|
||||||
//tranTypeNode is a type of transport property like viscosity
|
|
||||||
XML_Node& tranTypeNode = transportNode.child(iChild);
|
|
||||||
std::string nodeName = tranTypeNode.name();
|
|
||||||
|
|
||||||
//tranTypeNode contains the interaction model
|
|
||||||
switch (m_tranPropMap[nodeName]) {
|
|
||||||
case TP_IONCONDUCTIVITY:
|
|
||||||
trParam.ionConductivity = newLTP(tranTypeNode, phaseName,
|
|
||||||
m_tranPropMap[nodeName],
|
|
||||||
trParam.thermo);
|
|
||||||
break;
|
|
||||||
case TP_THERMALCOND:
|
|
||||||
trParam.thermalConductivity = newLTP(tranTypeNode, phaseName,
|
|
||||||
m_tranPropMap[nodeName],
|
|
||||||
trParam.thermo);
|
|
||||||
break;
|
|
||||||
case TP_DEFECTDIFF:
|
|
||||||
trParam.defectDiffusivity = newLTP(tranTypeNode, phaseName,
|
|
||||||
m_tranPropMap[nodeName],
|
|
||||||
trParam.thermo);
|
|
||||||
break;
|
|
||||||
case TP_DEFECTCONC:
|
|
||||||
trParam.defectActivity = newLTP(tranTypeNode, phaseName,
|
|
||||||
m_tranPropMap[nodeName],
|
|
||||||
trParam.thermo);
|
|
||||||
break;
|
|
||||||
case TP_ELECTCOND:
|
|
||||||
trParam.electConductivity = newLTP(tranTypeNode, phaseName,
|
|
||||||
m_tranPropMap[nodeName],
|
|
||||||
trParam.thermo);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw CanteraError("getSolidTransportData","unknown transport property: " + nodeName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Transport* newTransportMgr(const std::string& transportModel, thermo_t* thermo, int loglevel, int ndim)
|
Transport* newTransportMgr(const std::string& transportModel, thermo_t* thermo, int loglevel, int ndim)
|
||||||
{
|
{
|
||||||
TransportFactory* f = TransportFactory::factory();
|
TransportFactory* f = TransportFactory::factory();
|
||||||
|
|
|
||||||
|
|
@ -1,242 +0,0 @@
|
||||||
<?xml version="1.0"?>
|
|
||||||
<!--
|
|
||||||
NaCl modeling Based on the Silvester&Pitzer 1977 treatment:
|
|
||||||
|
|
||||||
(L. F. Silvester, K. S. Pitzer, "Thermodynamics of Electrolytes:
|
|
||||||
8. High-Temperature Properties, including Enthalpy and Heat
|
|
||||||
Capacity, with application to sodium chloride",
|
|
||||||
J. Phys. Chem., 81, 19 1822 - 1828 (1977)
|
|
||||||
-->
|
|
||||||
<ctml>
|
|
||||||
<phase id="NaCl_electrolyte" dim="3">
|
|
||||||
<speciesArray datasrc="#species_waterSolution">
|
|
||||||
H2O(L) Na+ Cl- H+ OH-
|
|
||||||
</speciesArray>
|
|
||||||
<state>
|
|
||||||
<temperature units="K"> 298.15 </temperature>
|
|
||||||
<pressure units="Pa"> 101325.0 </pressure>
|
|
||||||
<soluteMolalities>
|
|
||||||
Na+:6.0954
|
|
||||||
Cl-:6.0954
|
|
||||||
H+:2.1628E-9
|
|
||||||
OH-:1.3977E-6
|
|
||||||
</soluteMolalities>
|
|
||||||
</state>
|
|
||||||
|
|
||||||
<thermo model="HMW">
|
|
||||||
<standardConc model="solvent_volume" />
|
|
||||||
<activityCoefficients model="Pitzer" TempModel="complex1">
|
|
||||||
<!-- Pitzer Coefficients
|
|
||||||
These coefficients are from Pitzer's main
|
|
||||||
paper, in his book.
|
|
||||||
-->
|
|
||||||
<A_Debye model="water" />
|
|
||||||
<ionicRadius default="3.042843" units="Angstroms">
|
|
||||||
</ionicRadius>
|
|
||||||
<binarySaltParameters cation="Na+" anion="Cl-">
|
|
||||||
<beta0> 0.0765, 0.008946, -3.3158E-6,
|
|
||||||
-777.03, -4.4706
|
|
||||||
</beta0>
|
|
||||||
<beta1> 0.2664, 6.1608E-5, 1.0715E-6, 0.0, 0.0 </beta1>
|
|
||||||
<beta2> 0.0, 0.0, 0.0, 0.0, 0.0 </beta2>
|
|
||||||
<Cphi> 0.00127, -4.655E-5, 0.0,
|
|
||||||
33.317, 0.09421
|
|
||||||
</Cphi>
|
|
||||||
<Alpha1> 2.0 </Alpha1>
|
|
||||||
</binarySaltParameters>
|
|
||||||
|
|
||||||
<binarySaltParameters cation="H+" anion="Cl-">
|
|
||||||
<beta0> 0.1775, 0.0, 0.0, 0.0, 0.0 </beta0>
|
|
||||||
<beta1> 0.2945, 0.0, 0.0, 0.0, 0.0 </beta1>
|
|
||||||
<beta2> 0.0, 0.0, 0.0, 0.0, 0.0 </beta2>
|
|
||||||
<Cphi> 0.0008, 0.0, 0.0, 0.0, 0.0 </Cphi>
|
|
||||||
<Alpha1> 2.0 </Alpha1>
|
|
||||||
</binarySaltParameters>
|
|
||||||
|
|
||||||
<binarySaltParameters cation="Na+" anion="OH-">
|
|
||||||
<beta0> 0.0864, 0.0, 0.0, 0.0, 0.0 </beta0>
|
|
||||||
<beta1> 0.253, 0.0, 0.0, 0.0, 0.0 </beta1>
|
|
||||||
<beta2> 0.0, 0.0, 0.0, 0.0, 0.0 </beta2>
|
|
||||||
<Cphi> 0.0044, 0.0, 0.0, 0.0, 0.0 </Cphi>
|
|
||||||
<Alpha1> 2.0 </Alpha1>
|
|
||||||
</binarySaltParameters>
|
|
||||||
|
|
||||||
<thetaAnion anion1="Cl-" anion2="OH-">
|
|
||||||
<Theta> -0.05 </Theta>
|
|
||||||
</thetaAnion>
|
|
||||||
|
|
||||||
<psiCommonCation cation="Na+" anion1="Cl-" anion2="OH-">
|
|
||||||
<Theta> -0.05 </Theta>
|
|
||||||
<Psi> -0.006 </Psi>
|
|
||||||
</psiCommonCation>
|
|
||||||
|
|
||||||
<thetaCation cation1="Na+" cation2="H+">
|
|
||||||
<Theta> 0.036 </Theta>
|
|
||||||
</thetaCation>
|
|
||||||
|
|
||||||
<psiCommonAnion anion="Cl-" cation1="Na+" cation2="H+">
|
|
||||||
<Theta> 0.036 </Theta>
|
|
||||||
<Psi> -0.004 </Psi>
|
|
||||||
</psiCommonAnion>
|
|
||||||
|
|
||||||
</activityCoefficients>
|
|
||||||
<solvent> H2O(L) </solvent>
|
|
||||||
</thermo>
|
|
||||||
<elementArray datasrc="elements.xml"> O H C E Fe Si N Na Cl </elementArray>
|
|
||||||
<kinetics model="none" >
|
|
||||||
</kinetics>
|
|
||||||
<transport model="Simple">
|
|
||||||
<compositionDependence model="solvent"/>
|
|
||||||
<!--
|
|
||||||
<compositionDependence model="Mixture_Averaged"/>
|
|
||||||
-->
|
|
||||||
</transport>
|
|
||||||
</phase>
|
|
||||||
|
|
||||||
<speciesData id="species_waterSolution">
|
|
||||||
|
|
||||||
|
|
||||||
<species name="H2O(L)">
|
|
||||||
<!-- H2O(L) liquid standard state -> pure H2O
|
|
||||||
The origin of the NASA polynomial is a bit murky. It does
|
|
||||||
fit the vapor pressure curve at 298K adequately.
|
|
||||||
-->
|
|
||||||
<atomArray>H:2 O:1 </atomArray>
|
|
||||||
<thermo>
|
|
||||||
<NASA Tmax="600.0" Tmin="273.14999999999998" P0="100000.0">
|
|
||||||
<floatArray name="coeffs" size="7">
|
|
||||||
7.255750050E+01, -6.624454020E-01, 2.561987460E-03, -4.365919230E-06,
|
|
||||||
2.781789810E-09, -4.188654990E+04, -2.882801370E+02
|
|
||||||
</floatArray>
|
|
||||||
</NASA>
|
|
||||||
</thermo>
|
|
||||||
<standardState model="waterIAPWS">
|
|
||||||
<!--
|
|
||||||
Molar volume in m3 kmol-1.
|
|
||||||
(this is from Pitzer, Peiper, and Busey. However,
|
|
||||||
the result can be easily derived from ~ 1gm/cm**3)
|
|
||||||
<molarVolume> 0.018068 </molarVolume>
|
|
||||||
-->
|
|
||||||
</standardState>
|
|
||||||
<transport>
|
|
||||||
<viscosity model="Constant" units="centipoise"> 1.0E0 </viscosity>
|
|
||||||
<thermalConductivity model="Constant"> 0.58 </thermalConductivity>
|
|
||||||
<speciesDiffusivity model="Constant"> 1.0E-5 </speciesDiffusivity>
|
|
||||||
</transport>
|
|
||||||
</species>
|
|
||||||
|
|
||||||
<species name="Na+">
|
|
||||||
<!-- Na+ (aq) standard state based on the unity molality convention
|
|
||||||
xxx
|
|
||||||
-->
|
|
||||||
<atomArray> Na:1 E:-1 </atomArray>
|
|
||||||
<charge> +1 </charge>
|
|
||||||
<thermo model="HKFT">
|
|
||||||
<HKFT Pref="1 atm" Tmax=" 640." Tmin=" 273.15">
|
|
||||||
<!-- <DG0_f_Pr_Tr units="cal/gmol"> -62591. </DG0_f_Pr_Tr> -->
|
|
||||||
<DH0_f_Pr_Tr units="cal/gmol"> -57433. </DH0_f_Pr_Tr>
|
|
||||||
<S0_Pr_Tr units="cal/gmol/K"> 13.96 </S0_Pr_Tr>
|
|
||||||
</HKFT>
|
|
||||||
</thermo>
|
|
||||||
<standardState model="HKFT">
|
|
||||||
<a1 units="cal/gmol/bar"> 0.1839 </a1>
|
|
||||||
<a2 units="cal/gmol"> -228.5 </a2>
|
|
||||||
<a3 units="cal-K/gmol/bar"> 3.256 </a3>
|
|
||||||
<a4 units="cal-K/gmol"> -27260. </a4>
|
|
||||||
<c1 units="cal/gmol/K"> 18.18 </c1>
|
|
||||||
<c2 units="cal-K/gmol"> -29810. </c2>
|
|
||||||
<omega_Pr_Tr units="cal/gmol"> 33060. </omega_Pr_Tr>
|
|
||||||
</standardState>
|
|
||||||
<transport>
|
|
||||||
<speciesDiffusivity model="Constant"> 1.0E-5 </speciesDiffusivity>
|
|
||||||
</transport>
|
|
||||||
<source>
|
|
||||||
ref:G9
|
|
||||||
</source>
|
|
||||||
</species>
|
|
||||||
|
|
||||||
<species name="Cl-">
|
|
||||||
<atomArray> Cl:1 E:1 </atomArray>
|
|
||||||
<charge> -1 </charge>
|
|
||||||
<thermo model="HKFT">
|
|
||||||
<HKFT Pref="1 atm" Tmax=" 623.15" Tmin=" 298.00">
|
|
||||||
<DG0_f_Pr_Tr units="cal/gmol"> -31379. </DG0_f_Pr_Tr>
|
|
||||||
<!-- <DH0_f_Pr_Tr units="cal/gmol"> -39933. </DH0_f_Pr_Tr> -->
|
|
||||||
<S0_Pr_Tr units="cal/gmol/K"> 13.56 </S0_Pr_Tr>
|
|
||||||
</HKFT>
|
|
||||||
</thermo>
|
|
||||||
<standardState model="HKFT">
|
|
||||||
<a1 units="cal/gmol/bar"> 0.4032 </a1>
|
|
||||||
<a2 units="cal/gmol"> 480.1 </a2>
|
|
||||||
<a3 units="cal-K/gmol/bar"> 5.563 </a3>
|
|
||||||
<a4 units="cal-K/gmol"> -28470. </a4>
|
|
||||||
<c1 units="cal/gmol/K"> -4.4 </c1>
|
|
||||||
<c2 units="cal-K/gmol"> -57140. </c2>
|
|
||||||
<omega_Pr_Tr units="cal/gmol"> 145600. </omega_Pr_Tr>
|
|
||||||
</standardState>
|
|
||||||
<transport>
|
|
||||||
<speciesDiffusivity model="Constant"> 1.0E-5 </speciesDiffusivity>
|
|
||||||
</transport>
|
|
||||||
<source>
|
|
||||||
ref:G9
|
|
||||||
</source>
|
|
||||||
</species>
|
|
||||||
|
|
||||||
<species name="H+">
|
|
||||||
<atomArray> H:1 E:-1 </atomArray>
|
|
||||||
<charge> +1 </charge>
|
|
||||||
<thermo model="HKFT">
|
|
||||||
<HKFT Pref="1 atm" Tmax=" 623.15" Tmin=" 298.00">
|
|
||||||
<DG0_f_Pr_Tr units="cal/gmol"> 0.0 </DG0_f_Pr_Tr>
|
|
||||||
<DH0_f_Pr_Tr units="cal/gmol"> 0.0 </DH0_f_Pr_Tr>
|
|
||||||
<!-- <S0_Pr_Tr units="cal/gmol/K"> 0.0 </S0_Pr_Tr> -->
|
|
||||||
</HKFT>
|
|
||||||
</thermo>
|
|
||||||
<standardState model="HKFT">
|
|
||||||
<a1 units="cal/gmol/bar"> 0.0 </a1>
|
|
||||||
<a2 units="cal/gmol"> 0.0 </a2>
|
|
||||||
<a3 units="cal-K/gmol/bar"> 0.0 </a3>
|
|
||||||
<a4 units="cal-K/gmol"> 0.0 </a4>
|
|
||||||
<c1 units="cal/gmol/K"> 0.0 </c1>
|
|
||||||
<c2 units="cal-K/gmol"> 0.0 </c2>
|
|
||||||
<omega_Pr_Tr units="cal/gmol"> 0.0 </omega_Pr_Tr>
|
|
||||||
</standardState>
|
|
||||||
<transport>
|
|
||||||
<speciesDiffusivity model="Constant"> 1.0E-5 </speciesDiffusivity>
|
|
||||||
</transport>
|
|
||||||
<source>
|
|
||||||
ref:G9
|
|
||||||
</source>
|
|
||||||
</species>
|
|
||||||
|
|
||||||
|
|
||||||
<species name="OH-">
|
|
||||||
<atomArray> O:1 H:1 E:1 </atomArray>
|
|
||||||
<charge> -1 </charge>
|
|
||||||
<thermo model="HKFT">
|
|
||||||
<HKFT Pref="1 atm" Tmax=" 623.15" Tmin=" 298.00">
|
|
||||||
<DG0_f_Pr_Tr units="cal/gmol"> -37595. </DG0_f_Pr_Tr>
|
|
||||||
<DH0_f_Pr_Tr units="cal/gmol"> -54977. </DH0_f_Pr_Tr>
|
|
||||||
<S0_Pr_Tr units="cal/gmol/K"> -2.56 </S0_Pr_Tr>
|
|
||||||
</HKFT>
|
|
||||||
</thermo>
|
|
||||||
<standardState model="HKFT">
|
|
||||||
<a1 units="cal/gmol/bar"> 0.12527 </a1>
|
|
||||||
<a2 units="cal/gmol"> 7.38 </a2>
|
|
||||||
<a3 units="cal-K/gmol/bar"> 1.8423 </a3>
|
|
||||||
<a4 units="cal-K/gmol"> -27821 </a4>
|
|
||||||
<c1 units="cal/gmol/K"> 4.15 </c1>
|
|
||||||
<c2 units="cal-K/gmol"> -103460. </c2>
|
|
||||||
<omega_Pr_Tr units="cal/gmol"> 172460. </omega_Pr_Tr>
|
|
||||||
</standardState>
|
|
||||||
<transport>
|
|
||||||
<speciesDiffusivity model="Constant"> 1.0E-5 </speciesDiffusivity>
|
|
||||||
</transport>
|
|
||||||
<source>
|
|
||||||
ref:G9
|
|
||||||
</source>
|
|
||||||
</species>
|
|
||||||
|
|
||||||
</speciesData>
|
|
||||||
|
|
||||||
</ctml>
|
|
||||||
|
|
@ -3,7 +3,6 @@
|
||||||
#include "cantera/transport/TransportData.h"
|
#include "cantera/transport/TransportData.h"
|
||||||
#include "cantera/transport/MixTransport.h"
|
#include "cantera/transport/MixTransport.h"
|
||||||
#include "cantera/transport/MultiTransport.h"
|
#include "cantera/transport/MultiTransport.h"
|
||||||
#include "cantera/transport/SimpleTransport.h"
|
|
||||||
#include "cantera/transport/TransportFactory.h"
|
#include "cantera/transport/TransportFactory.h"
|
||||||
#include "cantera/thermo/ThermoFactory.h"
|
#include "cantera/thermo/ThermoFactory.h"
|
||||||
#include "cantera/thermo/IdealGasPhase.h"
|
#include "cantera/thermo/IdealGasPhase.h"
|
||||||
|
|
@ -167,103 +166,9 @@ TEST_F(TransportFromScratch, thermalConductivityMulti)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class SimpleTransportTest : public testing::Test
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
SimpleTransportTest()
|
|
||||||
: p(newPhase("HMW_NaCl_pdss.xml", "NaCl_electrolyte"))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void check_transport(SimpleTransport& tr) {
|
|
||||||
p->setState_TP(303.13, OneAtm);
|
|
||||||
size_t N = p->nSpecies();
|
|
||||||
EXPECT_NEAR(tr.viscosity(), 0.001, 1e-4);
|
|
||||||
EXPECT_NEAR(tr.thermalConductivity(), 0.58, 1e-3);
|
|
||||||
|
|
||||||
vector_fp spvisc(N), Dmix(N), mobilities(N), fluxes1(N), fluxes2(N);
|
|
||||||
vector_fp gradX(N, 0.0);
|
|
||||||
gradX[1] = 1.0;
|
|
||||||
double gradT = 0.0;
|
|
||||||
double gradV = 1.0;
|
|
||||||
|
|
||||||
vector_fp spvisc_ref = {0.001, 0, 0, 0, 0};
|
|
||||||
vector_fp Dmix_ref = {1e-05, 1e-05, 1e-05, 1e-05, 1e-05};
|
|
||||||
vector_fp mobilities_ref = {0.000382823, 0.000382823, 0.000382823,
|
|
||||||
0.000382823, 0.000382823};
|
|
||||||
vector_fp fluxes1_ref = {0.0102344, -0.0124461, 0.00221167,
|
|
||||||
2.22987e-14, 2.43291e-10};
|
|
||||||
vector_fp fluxes2_ref = {-0.0191255, -0.0505223, 0.0696478,
|
|
||||||
-7.85548e-13, 7.6615e-09};
|
|
||||||
|
|
||||||
tr.getSpeciesViscosities(spvisc.data());
|
|
||||||
tr.getMixDiffCoeffs(Dmix.data());
|
|
||||||
tr.getMobilities(mobilities.data());
|
|
||||||
tr.getSpeciesFluxes(1, &gradT, N, gradX.data(), N, fluxes1.data());
|
|
||||||
gradX[1] = 0.0;
|
|
||||||
tr.set_Grad_T(&gradT);
|
|
||||||
tr.set_Grad_V(&gradV);
|
|
||||||
tr.set_Grad_X(gradX.data());
|
|
||||||
tr.getSpeciesFluxesExt(N, fluxes2.data());
|
|
||||||
|
|
||||||
for (size_t k = 0; k < N; k++) {
|
|
||||||
EXPECT_NEAR(spvisc[k], spvisc_ref[k], 1e-5);
|
|
||||||
EXPECT_NEAR(Dmix[k], Dmix_ref[k], 1e-7);
|
|
||||||
EXPECT_NEAR(mobilities[k], mobilities_ref[k], 1e-9);
|
|
||||||
EXPECT_NEAR(fluxes1[k], fluxes1_ref[k], 1e-5*std::abs(fluxes1_ref[k]));
|
|
||||||
EXPECT_NEAR(fluxes2[k], fluxes2_ref[k], 1e-5*std::abs(fluxes2_ref[k]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
shared_ptr<ThermoPhase> p;
|
|
||||||
};
|
|
||||||
|
|
||||||
TEST_F(SimpleTransportTest, fromScratch)
|
|
||||||
{
|
|
||||||
SimpleTransport tr(p.get(), 3);
|
|
||||||
LiquidTransportParams params;
|
|
||||||
params.LTData.resize(p->nSpecies());
|
|
||||||
|
|
||||||
LTPspecies_Const* ltp = new LTPspecies_Const();
|
|
||||||
ltp->setName(p->speciesName(0));
|
|
||||||
ltp->setTransportPropertyType(TP_VISCOSITY);
|
|
||||||
ltp->setThermo(p.get());
|
|
||||||
ltp->setCoeff(1.0 * toSI("centipoise"));
|
|
||||||
params.LTData[0].viscosity = ltp;
|
|
||||||
|
|
||||||
ltp = new LTPspecies_Const();
|
|
||||||
ltp->setName(p->speciesName(0));
|
|
||||||
ltp->setTransportPropertyType(TP_THERMALCOND);
|
|
||||||
ltp->setThermo(p.get());
|
|
||||||
ltp->setCoeff(0.58);
|
|
||||||
params.LTData[0].thermalCond = ltp;
|
|
||||||
|
|
||||||
for (size_t k = 0; k < p->nSpecies(); k++) {
|
|
||||||
ltp = new LTPspecies_Const();
|
|
||||||
ltp->setName(p->speciesName(k));
|
|
||||||
ltp->setTransportPropertyType(TP_DIFFUSIVITY);
|
|
||||||
ltp->setThermo(p.get());
|
|
||||||
ltp->setCoeff(1e-5);
|
|
||||||
params.LTData[k].speciesDiffusivity = ltp;
|
|
||||||
}
|
|
||||||
|
|
||||||
params.thermo = p.get();
|
|
||||||
tr.initLiquid(params);
|
|
||||||
tr.setCompositionDependence(LTI_MODEL_SOLVENT);
|
|
||||||
check_transport(tr);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(SimpleTransportTest, fromXML)
|
|
||||||
{
|
|
||||||
shared_ptr<Transport> tr(newDefaultTransportMgr(p.get()));
|
|
||||||
check_transport(dynamic_cast<SimpleTransport&>(*tr.get()));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
printf("Running main() from transportFromScratch.cpp\n");
|
printf("Running main() from transportFromScratch.cpp\n");
|
||||||
// Cantera::make_deprecation_warnings_fatal();
|
|
||||||
testing::InitGoogleTest(&argc, argv);
|
testing::InitGoogleTest(&argc, argv);
|
||||||
int result = RUN_ALL_TESTS();
|
int result = RUN_ALL_TESTS();
|
||||||
appdelete();
|
appdelete();
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue